From f8d897f5f3a89a5664e95a45948f9725101aa36f Mon Sep 17 00:00:00 2001 From: Viktoriia Bakalova Date: Fri, 27 Sep 2024 11:33:17 +0000 Subject: [PATCH 1/5] [clang][ItaniumMangle] Mangle friend function templates with a constraint that depends on a template parameter from an enclosing template as members of the enclosing class. Such function templates should be considered member-like constrained friends per [temp.friend]p9 and https://github.com/itanium-cxx-abi/cxx-abi/issues/24#issuecomment-934977198). --- clang/lib/AST/ItaniumMangle.cpp | 8 ++++++++ clang/test/CodeGenCXX/mangle-concept.cpp | 6 +++--- libcxxabi/test/test_demangle.pass.cpp | 6 +++--- 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp index b6e1da0c3192da..172561f73b9a74 100644 --- a/clang/lib/AST/ItaniumMangle.cpp +++ b/clang/lib/AST/ItaniumMangle.cpp @@ -2270,6 +2270,14 @@ void CXXNameMangler::mangleTemplatePrefix(GlobalDecl GD, mangleTemplateParameter(TTP->getDepth(), TTP->getIndex()); } else { const DeclContext *DC = Context.getEffectiveDeclContext(ND); + if (const auto *FD = dyn_cast(GD.getDecl())) { + // Member-like constrained friends are mangled as if they were members of + // the enclosing class. + if (FD->getTemplatedDecl()->isMemberLikeConstrainedFriend() && + getASTContext().getLangOpts().getClangABICompat() > + LangOptions::ClangABI::Ver17) + DC = GD.getDecl()->getLexicalDeclContext()->getRedeclContext(); + } manglePrefix(DC, NoFunction); if (isa(ND) || isa(ND)) mangleUnqualifiedName(GD, DC, nullptr); diff --git a/clang/test/CodeGenCXX/mangle-concept.cpp b/clang/test/CodeGenCXX/mangle-concept.cpp index 91dc1b0e688e0d..6053511c00a7b5 100644 --- a/clang/test/CodeGenCXX/mangle-concept.cpp +++ b/clang/test/CodeGenCXX/mangle-concept.cpp @@ -58,19 +58,19 @@ namespace test2 { // CHECK: call {{.*}}@_ZN5test21AIiEF1fEzQ4TrueIT_E( // CLANG17: call {{.*}}@_ZN5test21fEz( f(ai); - // CHECK: call {{.*}}@_ZN5test2F1gIvEEvzQaa4TrueIT_E4TrueITL0__E( + // CHECK: call {{.*}}@_ZN5test21AIiEF1gIvEEvzQaa4TrueIT_E4TrueITL0__E( // CLANG17: call {{.*}}@_ZN5test21gIvEEvz( g(ai); // CHECK: call {{.*}}@_ZN5test21hIvEEvzQ4TrueITL0__E( // CLANG17: call {{.*}}@_ZN5test21hIvEEvz( h(ai); - // CHECK: call {{.*}}@_ZN5test2F1iIvQaa4TrueIT_E4TrueITL0__EEEvz( + // CHECK: call {{.*}}@_ZN5test21AIiEF1iIvQaa4TrueIT_E4TrueITL0__EEEvz( // CLANG17: call {{.*}}@_ZN5test21iIvEEvz( i(ai); // CHECK: call {{.*}}@_ZN5test21jIvQ4TrueITL0__EEEvz( // CLANG17: call {{.*}}@_ZN5test21jIvEEvz( j(ai); - // CHECK: call {{.*}}@_ZN5test2F1kITk4TruevQ4TrueIT_EEEvz( + // CHECK: call {{.*}}@_ZN5test21AIiEF1kITk4TruevQ4TrueIT_EEEvz( // CLANG17: call {{.*}}@_ZN5test21kIvEEvz( k(ai); // CHECK: call {{.*}}@_ZN5test21lITk4TruevEEvz( diff --git a/libcxxabi/test/test_demangle.pass.cpp b/libcxxabi/test/test_demangle.pass.cpp index 17786a3a486fcd..efe482aad1b76c 100644 --- a/libcxxabi/test/test_demangle.pass.cpp +++ b/libcxxabi/test/test_demangle.pass.cpp @@ -30128,11 +30128,11 @@ const char* cases[][2] = // C++20 concepts, see https://github.com/itanium-cxx-abi/cxx-abi/issues/24. {"_Z2f0IiE1SIX1CIT_EEEv", "S> f0()"}, {"_ZN5test21AIiEF1fEzQ4TrueIT_E", "test2::A::friend f(...) requires True"}, - {"_ZN5test2F1gIvEEvzQaa4TrueIT_E4TrueITL0__E", "void test2::friend g(...) requires True && True"}, + {"_ZN5test21AIiEF1gIvEEvzQaa4TrueIT_E4TrueITL0__E", "void test2::A::friend g(...) requires True && True"}, {"_ZN5test21hIvEEvzQ4TrueITL0__E", "void test2::h(...) requires True"}, - {"_ZN5test2F1iIvQaa4TrueIT_E4TrueITL0__EEEvz", "void test2::friend i(...)"}, + {"_ZN5test21AIiEF1iIvQaa4TrueIT_E4TrueITL0__EEEvz", "void test2::A::friend i(...)"}, {"_ZN5test21jIvQ4TrueITL0__EEEvz", "void test2::j(...)"}, - {"_ZN5test2F1kITk4TruevQ4TrueIT_EEEvz", "void test2::friend k(...)"}, + {"_ZN5test21AIiEF1kITk4TruevQ4TrueIT_EEEvz", "void test2::A::friend k(...)"}, {"_ZN5test21lITk4TruevEEvz", "void test2::l(...)"}, {"_ZN5test31dITnDaLi0EEEvv", "void test3::d<0>()"}, {"_ZN5test31eITnDcLi0EEEvv", "void test3::e<0>()"}, From 7f61556ecdef242043e24a7f514fe8f80d559200 Mon Sep 17 00:00:00 2001 From: Viktoriia Bakalova Date: Fri, 27 Sep 2024 11:42:04 +0000 Subject: [PATCH 2/5] fixup! [clang][ItaniumMangle] Mangle friend function templates with a constraint that depends on a template parameter from an enclosing template as members of the enclosing class. --- clang/lib/AST/ItaniumMangle.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp index 172561f73b9a74..0e5963b91f3253 100644 --- a/clang/lib/AST/ItaniumMangle.cpp +++ b/clang/lib/AST/ItaniumMangle.cpp @@ -2276,7 +2276,7 @@ void CXXNameMangler::mangleTemplatePrefix(GlobalDecl GD, if (FD->getTemplatedDecl()->isMemberLikeConstrainedFriend() && getASTContext().getLangOpts().getClangABICompat() > LangOptions::ClangABI::Ver17) - DC = GD.getDecl()->getLexicalDeclContext()->getRedeclContext(); + DC = GD.getDecl()->getLexicalDeclContext()->getRedeclContext(); } manglePrefix(DC, NoFunction); if (isa(ND) || isa(ND)) From cfc150dab0f515141e7e8fe0a8dae6a1e1586cbb Mon Sep 17 00:00:00 2001 From: Viktoriia Bakalova Date: Fri, 27 Sep 2024 15:23:10 +0000 Subject: [PATCH 3/5] fixup! fixup! [clang][ItaniumMangle] Mangle friend function templates with a constraint that depends on a template parameter from an enclosing template as members of the enclosing class. --- clang/docs/ReleaseNotes.rst | 1 + clang/lib/AST/ItaniumMangle.cpp | 17 +++++++++-------- clang/test/CodeGenCXX/mangle-concept.cpp | 23 +++++++++++++++++++++++ libcxxabi/test/test_demangle.pass.cpp | 4 ++++ 4 files changed, 37 insertions(+), 8 deletions(-) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 14907e7db18de3..ae7f0bf062ae4a 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -426,6 +426,7 @@ Bug Fixes to C++ Support - Fixed an assertion failure in debug mode, and potential crashes in release mode, when diagnosing a failed cast caused indirectly by a failed implicit conversion to the type of the constructor parameter. - Fixed an assertion failure by adjusting integral to boolean vector conversions (#GH108326) +- Fixed mangling of friend function templates with a constraint that depends on a template parameter from an enclosing template. (#GH110247) Bug Fixes to AST Handling ^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp index 0e5963b91f3253..31a766d8bb0597 100644 --- a/clang/lib/AST/ItaniumMangle.cpp +++ b/clang/lib/AST/ItaniumMangle.cpp @@ -704,6 +704,15 @@ ItaniumMangleContextImpl::getEffectiveDeclContext(const Decl *D) { return D->getLexicalDeclContext()->getRedeclContext(); } + if (const auto *FTD = dyn_cast(D)) { + // Member-like constrained friends are mangled as if they were members of + // the enclosing class. + if (FTD->getTemplatedDecl()->isMemberLikeConstrainedFriend() && + getASTContext().getLangOpts().getClangABICompat() > + LangOptions::ClangABI::Ver17) + return D->getLexicalDeclContext()->getRedeclContext(); + } + return DC->getRedeclContext(); } @@ -2270,14 +2279,6 @@ void CXXNameMangler::mangleTemplatePrefix(GlobalDecl GD, mangleTemplateParameter(TTP->getDepth(), TTP->getIndex()); } else { const DeclContext *DC = Context.getEffectiveDeclContext(ND); - if (const auto *FD = dyn_cast(GD.getDecl())) { - // Member-like constrained friends are mangled as if they were members of - // the enclosing class. - if (FD->getTemplatedDecl()->isMemberLikeConstrainedFriend() && - getASTContext().getLangOpts().getClangABICompat() > - LangOptions::ClangABI::Ver17) - DC = GD.getDecl()->getLexicalDeclContext()->getRedeclContext(); - } manglePrefix(DC, NoFunction); if (isa(ND) || isa(ND)) mangleUnqualifiedName(GD, DC, nullptr); diff --git a/clang/test/CodeGenCXX/mangle-concept.cpp b/clang/test/CodeGenCXX/mangle-concept.cpp index 6053511c00a7b5..966117544bfec1 100644 --- a/clang/test/CodeGenCXX/mangle-concept.cpp +++ b/clang/test/CodeGenCXX/mangle-concept.cpp @@ -52,6 +52,7 @@ namespace test2 { }; A ai; + A aj; // CHECK-LABEL: define {{.*}}@{{.*}}test2{{.*}}use void use() { @@ -76,6 +77,28 @@ namespace test2 { // CHECK: call {{.*}}@_ZN5test21lITk4TruevEEvz( // CLANG17: call {{.*}}@_ZN5test21lIvEEvz( l(ai); + + // CHECK: call {{.*}}@_ZN5test21AIbEF1fEzQ4TrueIT_E( + // CLANG17: call {{.*}}@_ZN5test21fEz( + f(aj); + // CHECK: call {{.*}}@_ZN5test21AIbEF1gIvEEvzQaa4TrueIT_E4TrueITL0__E( + // CLANG17: call {{.*}}@_ZN5test21gIvEEvz( + g(aj); + // CHECK: call {{.*}}@_ZN5test21hIvEEvzQ4TrueITL0__E( + // CLANG17: call {{.*}}@_ZN5test21hIvEEvz( + h(aj); + // CHECK: call {{.*}}@_ZN5test21AIbEF1iIvQaa4TrueIT_E4TrueITL0__EEEvz( + // CLANG17: call {{.*}}@_ZN5test21iIvEEvz( + i(aj); + // CHECK: call {{.*}}@_ZN5test21jIvQ4TrueITL0__EEEvz( + // CLANG17: call {{.*}}@_ZN5test21jIvEEvz( + j(aj); + // CHECK: call {{.*}}@_ZN5test21AIbEF1kITk4TruevQ4TrueIT_EEEvz( + // CLANG17: call {{.*}}@_ZN5test21kIvEEvz( + k(aj); + // CHECK: call {{.*}}@_ZN5test21lITk4TruevEEvz( + // CLANG17: call {{.*}}@_ZN5test21lIvEEvz( + l(aj); } } diff --git a/libcxxabi/test/test_demangle.pass.cpp b/libcxxabi/test/test_demangle.pass.cpp index efe482aad1b76c..eb32b4679aff0c 100644 --- a/libcxxabi/test/test_demangle.pass.cpp +++ b/libcxxabi/test/test_demangle.pass.cpp @@ -30128,11 +30128,15 @@ const char* cases[][2] = // C++20 concepts, see https://github.com/itanium-cxx-abi/cxx-abi/issues/24. {"_Z2f0IiE1SIX1CIT_EEEv", "S> f0()"}, {"_ZN5test21AIiEF1fEzQ4TrueIT_E", "test2::A::friend f(...) requires True"}, + {"_ZN5test21AIbEF1fEzQ4TrueIT_E", "test2::A::friend f(...) requires True"}, {"_ZN5test21AIiEF1gIvEEvzQaa4TrueIT_E4TrueITL0__E", "void test2::A::friend g(...) requires True && True"}, + {"_ZN5test21AIbEF1gIvEEvzQaa4TrueIT_E4TrueITL0__E", "void test2::A::friend g(...) requires True && True"}, {"_ZN5test21hIvEEvzQ4TrueITL0__E", "void test2::h(...) requires True"}, {"_ZN5test21AIiEF1iIvQaa4TrueIT_E4TrueITL0__EEEvz", "void test2::A::friend i(...)"}, + {"_ZN5test21AIbEF1iIvQaa4TrueIT_E4TrueITL0__EEEvz", "void test2::A::friend i(...)"}, {"_ZN5test21jIvQ4TrueITL0__EEEvz", "void test2::j(...)"}, {"_ZN5test21AIiEF1kITk4TruevQ4TrueIT_EEEvz", "void test2::A::friend k(...)"}, + {"_ZN5test21AIbEF1kITk4TruevQ4TrueIT_EEEvz", "void test2::A::friend k(...)"}, {"_ZN5test21lITk4TruevEEvz", "void test2::l(...)"}, {"_ZN5test31dITnDaLi0EEEvv", "void test3::d<0>()"}, {"_ZN5test31eITnDcLi0EEEvv", "void test3::e<0>()"}, From 782cd5c382d779c8ef1d800b1ef394aa623ab4ff Mon Sep 17 00:00:00 2001 From: Viktoriia Bakalova Date: Fri, 27 Sep 2024 15:23:46 +0000 Subject: [PATCH 4/5] fixup! fixup! [clang][ItaniumMangle] Mangle friend function templates with a constraint that depends on a template parameter from an enclosing template as members of the enclosing class. --- clang/docs/ReleaseNotes.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index ae7f0bf062ae4a..9d0de8a6bb8c6a 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -426,7 +426,7 @@ Bug Fixes to C++ Support - Fixed an assertion failure in debug mode, and potential crashes in release mode, when diagnosing a failed cast caused indirectly by a failed implicit conversion to the type of the constructor parameter. - Fixed an assertion failure by adjusting integral to boolean vector conversions (#GH108326) -- Fixed mangling of friend function templates with a constraint that depends on a template parameter from an enclosing template. (#GH110247) +- Mangle friend function templates with a constraint that depends on a template parameter from an enclosing template as members of the enclosing class. (#GH110247) Bug Fixes to AST Handling ^^^^^^^^^^^^^^^^^^^^^^^^^ From 24b15f74847cbb71e455ccebb43334d12c3bfe1a Mon Sep 17 00:00:00 2001 From: Viktoriia Bakalova Date: Mon, 30 Sep 2024 07:24:57 +0000 Subject: [PATCH 5/5] fixup! fixup! fixup! [clang][ItaniumMangle] Mangle friend function templates with a constraint that depends on a template parameter from an enclosing template as members of the enclosing class. --- clang/lib/AST/ItaniumMangle.cpp | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp index 31a766d8bb0597..bd5abb5e42ee87 100644 --- a/clang/lib/AST/ItaniumMangle.cpp +++ b/clang/lib/AST/ItaniumMangle.cpp @@ -693,7 +693,7 @@ ItaniumMangleContextImpl::getEffectiveDeclContext(const Decl *D) { if (VD->isExternC()) return getASTContext().getTranslationUnitDecl(); - if (const auto *FD = dyn_cast(D)) { + if (const auto *FD = D->getAsFunction()) { if (FD->isExternC()) return getASTContext().getTranslationUnitDecl(); // Member-like constrained friends are mangled as if they were members of @@ -704,15 +704,6 @@ ItaniumMangleContextImpl::getEffectiveDeclContext(const Decl *D) { return D->getLexicalDeclContext()->getRedeclContext(); } - if (const auto *FTD = dyn_cast(D)) { - // Member-like constrained friends are mangled as if they were members of - // the enclosing class. - if (FTD->getTemplatedDecl()->isMemberLikeConstrainedFriend() && - getASTContext().getLangOpts().getClangABICompat() > - LangOptions::ClangABI::Ver17) - return D->getLexicalDeclContext()->getRedeclContext(); - } - return DC->getRedeclContext(); }