-
Notifications
You must be signed in to change notification settings - Fork 13.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[ItaniumDemangle] Unconditionally parse substitution template arguments #131970
base: main
Are you sure you want to change the base?
[ItaniumDemangle] Unconditionally parse substitution template arguments #131970
Conversation
With the current mangled name parser, when we try to parse a type name inside the template argument of an operator, we end up not parsing any template arguments of substitutions, which ends up causing things to fail in certain cases. This is compliant with the Itanium ABI documentation as far as I can tell. I tried to look through the git history to find out why the limitation on parsing template arguments for substitutions inside of operators existed, but I only ended up at the import commit, so I suspect the original motivation is lost to time. A regression test from LLVM has been added.
@llvm/pr-subscribers-libcxxabi Author: Aiden Grossman (boomanaiden154) ChangesWith the current mangled name parser, when we try to parse a type name inside the template argument of an operator, we end up not parsing any template arguments of substitutions, which ends up causing things to fail in certain cases. This is compliant with the Itanium ABI documentation as far as I can tell. I tried to look through the git history to find out why the limitation on parsing template arguments for substitutions inside of operators existed, but I only ended up at the import commit, so I suspect the original motivation is lost to time. A regression test from LLVM has been added. Full diff: https://github.com/llvm/llvm-project/pull/131970.diff 3 Files Affected:
diff --git a/libcxxabi/src/demangle/ItaniumDemangle.h b/libcxxabi/src/demangle/ItaniumDemangle.h
index 3df41b5f4d7d0..45ec8d41fee41 100644
--- a/libcxxabi/src/demangle/ItaniumDemangle.h
+++ b/libcxxabi/src/demangle/ItaniumDemangle.h
@@ -4626,10 +4626,10 @@ Node *AbstractManglingParser<Derived, Alloc>::parseType() {
// <template-template-param> ::= <template-param>
// ::= <substitution>
//
- // If this is followed by some <template-args>, and we're permitted to
- // parse them, take the second production.
+ // If this is followed by some <template-args>, take the second
+ // production.
- if (look() == 'I' && (!IsSubst || TryToParseTemplateArgs)) {
+ if (look() == 'I') {
if (!IsSubst)
Subs.push_back(Result);
Node *TA = getDerived().parseTemplateArgs();
diff --git a/libcxxabi/test/test_demangle.pass.cpp b/libcxxabi/test/test_demangle.pass.cpp
index e9c74f70a094b..fad6c101f742d 100644
--- a/libcxxabi/test/test_demangle.pass.cpp
+++ b/libcxxabi/test/test_demangle.pass.cpp
@@ -30247,6 +30247,7 @@ const char* cases[][2] = {
{"_Z1fDSDRm", "f(_Sat unsigned long _Fract)"},
{"_Z11bfloat16addDF16bDF16b", "bfloat16add(std::bfloat16_t, std::bfloat16_t)"},
+ {"_ZNK4llvm11SmallStringILj16EEcvNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEv", "llvm::SmallString<16u>::operator std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>() const"},
// clang-format on
};
diff --git a/llvm/include/llvm/Demangle/ItaniumDemangle.h b/llvm/include/llvm/Demangle/ItaniumDemangle.h
index b0363c1a7a786..15400694b3c70 100644
--- a/llvm/include/llvm/Demangle/ItaniumDemangle.h
+++ b/llvm/include/llvm/Demangle/ItaniumDemangle.h
@@ -4626,10 +4626,10 @@ Node *AbstractManglingParser<Derived, Alloc>::parseType() {
// <template-template-param> ::= <template-param>
// ::= <substitution>
//
- // If this is followed by some <template-args>, and we're permitted to
- // parse them, take the second production.
+ // If this is followed by some <template-args>, take the second
+ // production.
- if (look() == 'I' && (!IsSubst || TryToParseTemplateArgs)) {
+ if (look() == 'I') {
if (!IsSubst)
Subs.push_back(Result);
Node *TA = getDerived().parseTemplateArgs();
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks like we might be able to make additional simplifications to the code since I think all meaningful references to TryToParseTemplateArgs
are being removed in this patch?
There are still a couple there, and those ones do impact demangling (I ran the tests with them disabled and got failures). |
I think the point here is to handle a mangling collision between: template<typename T> struct X {};
struct C {
operator X<int>();
} c;
X<int> x = c; and: struct X {};
struct C {
template<typename T = int>
operator X() {}
} c;
X x = c; where in both cases the conversion function mangles as I think that's why Can you check that these all still demangle with this patch applied:
|
I tried removing it, but ended up getting test failures, specifically with
It is able to still demangle all those cases. Interestingly the
|
It would be good for someone to figure out and ideally write down (perhaps in a comment) how the existing code is handling these problems when demangling conversion functions. I don't have a lot of confidence that what we're currently doing is correct (and it's clearly not correct for the example in the new test case), but it's going to be hard to confidently approve this change without that understanding (Chesterton's fence). |
Yeah, makes sense. I will go through it more thoroughly when I have time and document what I find. |
With the current mangled name parser, when we try to parse a type name inside the template argument of an operator, we end up not parsing any template arguments of substitutions, which ends up causing things to fail in certain cases. This is compliant with the Itanium ABI documentation as far as I can tell.
I tried to look through the git history to find out why the limitation on parsing template arguments for substitutions inside of operators existed, but I only ended up at the import commit, so I suspect the original motivation is lost to time.
A regression test from LLVM has been added.