The Itanium C++ ABI says prefixes are substitutable. For most prefixes we already handle this: the manglePrefix(const DeclContext *, bool) and manglePrefix(QualType) overloads explicitly handles substitutions or defer to functions that handle substitutions on their behalf. The manglePrefix(NestedNameSpecifier *) overload, however, is different and handles some cases implicitly, but not all. The Identifier case was not handled; this change adds handling for it, as well as a test case.
Details
Diff Detail
- Repository
- rG LLVM Github Monorepo
Unit Tests
Event Timeline
Question: does this need to be covered by -fclang-abi-compat= when the prior mangling resulted in names that even llvm-cxxfilt agreed made no sense? (If it is needed, it should be an easy change.)
ping. Apologies, I don't know who to add as a reviewer, there is no one specifically listed as code owner and it does not seem to be handled by anyone in particular. @urnathan, @erichkeane, you two appear to be the most recent people who pushed commits specifically for mangling issues, would either of you be able to review this?
@rjmccall is the expert on the Itanium ABI.
Code wise, I have no real comments, though he might. As far as:
Question: does this need to be covered by -fclang-abi-compat= when the prior mangling resulted in names that even llvm-cxxfilt agreed made no sense? (If it is needed, it should be an easy change.)
I believe the answer here is 'yes'. We also likely need release notes.
Thanks for the feedback. -fclang-abi-compat= support added. Other mangling bugfixes appear to not have made it into release notes so I did not add it for this one either, but if that is something that's wanted I can add it; I'll wait for some more comments on that.
Our most recent direction is to document any non-NFC patches in the release notes if at all sensible, so I think this meets those requirements.
Thanks, I'm not finding documentation of any change in policy even after specifically looking for it, so I have opened https://github.com/llvm/llvm-project/issues/54965 for that. However, I have no issue with the policy and will add a release note for this.
LGTM! I would like @rjmccall to take a pass if he ends up having time in the next day or two (perhaps tack on an extra day or two because of Easter), else I'll be willing to approve later in the week.
clang/lib/AST/ItaniumMangle.cpp | ||
---|---|---|
6031 | This seems a little error-prone to me: calling this on a type NNS would do the wrong thing (those are supposed to share a substitution number with the type, rather than have a substitution of their own). We could handle the various cases here and dispatch to the right forms of mangleSubstitution depending on the kind of NNS, but that code would all be unreachable / untested. So maybe we should just make this assert that NNS->getKind() == NestedNameSpecifier::Identifier. (And optionally we could give this a more specific name, eg mangleSubstitutionForIdentifierNNS?) | |
clang/test/CodeGenCXX/clang-abi-compat.cpp | ||
160 | I think this test does not capture an important property for which we should have test coverage: that we used to not register a substitution for T::Y (not only that we used to not *use* a substitution for it). For example, this test would capture that: struct X { struct Y { using a = int; using b = int; }; }; template <typename T> void test10(typename T::Y::a, typename T::Y::b, float*, float*) {} template void test10<X>(int, int, float*, float*); ... where the numbering of float* depends on how many substitutions we created for the earlier types. (Put another way, this test covers only one of the two if (!Clang14Compat) tests in ItaniumMangle.cpp, and we should cover both.) |
clang/lib/AST/ItaniumMangle.cpp | ||
---|---|---|
6031 | I have added the assert that you suggested. I would actually have preferred for this function to be used for other NNS substitutions as well to better align with how the spec says substitutions should be handled (it's a rule of <prefix>, not any component within) but that seemed like an unnecessarily more invasive change. If you are okay with it I would like to keep the function named just mangleSubstitution to keep that open as option for a possible future clean-up. | |
clang/test/CodeGenCXX/clang-abi-compat.cpp | ||
160 | I get where you're coming from. My thinking was the other way around, if we add the first if (!Clang14Compat && ...) by itself that will have no effect and cannot be tested for, then if we add the second if (!Clang14Compat) that does have impact and needs testing. You're looking at it the other way around, if we add the second if (!Clang14Compat) first, we fix one bug, and if we then add the first if (!Clang14Compat && ...) we fix another. Happy to extend the test like you suggested. |
clang/docs/ReleaseNotes.rst | ||
---|---|---|
240 | This is incorrect rst syntax. |
Ping me EOW if @rsmith doesn't respond in the meantime. It is also not clear to me whether you were able to capture/fix the issue he had with the clang-abi-compat.cpp test.
Will do, sure. For the record, for that test I applied @rsmith's suggestion verbatim so it *should* address his concern, but I will wait for him to confirm.
I DID see that and am REASONABLY sure you do, but sometimes folks will ask for test coverage because they suspect the resulting behavior will demonstrate some sort of problem with the current patch. I DID run this through the demangler and found that the PRE15 case looks odd?
void test10<X>(X::Y::a, X::Y::b, float*, X::Y)
vs
void test10<X>(X::Y::a, X::Y::b, float*, float*)
Or is that exactly the bug being caught here? That is, is the float* substitution not being properly registered/emitted and being confused with X::Y?
PS:, and as an unrelated-lament... A while back I wrote a test regarding mangling where I ALSO had it run us through llvm-cxxfilt so that we had an output of every mangled string that showed the demangled version. I wish we'd done that from the beginning to make it much less confusing what is going on in these.
[was out last week] It seems the demangler already gets this right, probably because it just looks like a regular nested name
Yes, that is exactly it. That is what @rsmith was getting at with his comment about regarding this as two separate bugs (he can correct me if I am misstating things), one that we do not add the substitution and as such use wrong numbers for subsequent substitutions, the other that we do not use the substitution. The other is what I had covered in my initial test, his addition covers that first bug where we wrongly used S4 when we should be using S5.
PS:, and as an unrelated-lament... A while back I wrote a test regarding mangling where I ALSO had it run us through llvm-cxxfilt so that we had an output of every mangled string that showed the demangled version. I wish we'd done that from the beginning to make it much less confusing what is going on in these.
llvm-cxxfilt has no option to be compatible with earlier incorrect mangling though, so it would not help with this particular test. But it could help with other tests, agreed.
llvm-cxxfilt has no option to be compatible with earlier incorrect mangling though, so it would not help with this particular test. But it could help with other tests, agreed.
This actually wouldn't be necessary in this case: cxxfilt is already 'right', this is just for humans to be able to see "we changed this from mangling as <obviously wrong> to <looks right>".
That's a good point. We do have tests in clang that use llvm-cxxfilt already (the PPC intrinsic tests) so there should be no problem with it as a dependency; I think once this is in I might submit that as a follow-up change for review unless someone else beats me to it.
Any amount of test cleanup in that direction would be greatly appreciated! Even as NFC.
The test I did it for was CodeGenCXX/mangle-nttp-anon-union.cpp as an example of what I'm talking about.
clang/lib/AST/ItaniumMangle.cpp | ||
---|---|---|
6031 | One could name it mangleSubstitutionForIdentifierNNS now and rename it in the future, if your unification dream comes true? That names it for what it does now. Just a thought, not a requirement. |
clang/lib/AST/ItaniumMangle.cpp | ||
---|---|---|
6031 | Sorry, that comment came after I pushed it already. I have some more things to look into when I have some more time (including @erichkeane's comment about the test), will see if it makes sense to include with that, or perhaps to just make that NFC change to allow it to be used more generally. |
clang/lib/AST/ItaniumMangle.cpp | ||
---|---|---|
6031 | no worries, I failed to notice it'd already landed |
This is incorrect rst syntax.