Author: Richard Smith Date: 2020-11-24T16:25:18-08:00 New Revision: c2cb61bed3652126278b4a738e367f524e040ccc
URL: https://github.com/llvm/llvm-project/commit/c2cb61bed3652126278b4a738e367f524e040ccc DIFF: https://github.com/llvm/llvm-project/commit/c2cb61bed3652126278b4a738e367f524e040ccc.diff LOG: Fix mangling of substitutions for template-prefixes. Previously we only considered using a substitution for a template-name after already having mangled its prefix, so we'd produce nonsense manglings like NS3_S4_IiEE where we should simply produce NS4_IiEE. This is not ABI-compatible with previous Clang versions, and the old behavior is restored by -fclang-abi-compat=11.0 or earlier. Added: Modified: clang/include/clang/Basic/LangOptions.h clang/lib/AST/ItaniumMangle.cpp clang/test/CodeGenCXX/clang-abi-compat.cpp clang/test/CodeGenCXX/mangle-template.cpp Removed: ################################################################################ diff --git a/clang/include/clang/Basic/LangOptions.h b/clang/include/clang/Basic/LangOptions.h index d54bfcd7245b..203c45fdd9a7 100644 --- a/clang/include/clang/Basic/LangOptions.h +++ b/clang/include/clang/Basic/LangOptions.h @@ -155,7 +155,8 @@ class LangOptions : public LangOptionsBase { /// Attempt to be ABI-compatible with code generated by Clang 11.0.x /// (git 2e10b7a39b93). This causes clang to pass unions with a 256-bit - /// vector member on the stack instead of using registers. + /// vector member on the stack instead of using registers, and to not + /// properly mangle substitutions for template names in some cases. Ver11, /// Conform to the underlying platform's C and C++ ABIs as closely diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp index 2b6fda4d9dcc..172b94f26018 100644 --- a/clang/lib/AST/ItaniumMangle.cpp +++ b/clang/lib/AST/ItaniumMangle.cpp @@ -479,8 +479,6 @@ class CXXNameMangler { const AbiTagList *AdditionalAbiTags); void mangleUnscopedTemplateName(GlobalDecl GD, const AbiTagList *AdditionalAbiTags); - void mangleUnscopedTemplateName(TemplateName, - const AbiTagList *AdditionalAbiTags); void mangleSourceName(const IdentifierInfo *II); void mangleRegCallName(const IdentifierInfo *II); void mangleDeviceStubName(const IdentifierInfo *II); @@ -994,29 +992,6 @@ void CXXNameMangler::mangleUnscopedTemplateName( addSubstitution(ND); } -void CXXNameMangler::mangleUnscopedTemplateName( - TemplateName Template, const AbiTagList *AdditionalAbiTags) { - // <unscoped-template-name> ::= <unscoped-name> - // ::= <substitution> - if (TemplateDecl *TD = Template.getAsTemplateDecl()) - return mangleUnscopedTemplateName(TD, AdditionalAbiTags); - - if (mangleSubstitution(Template)) - return; - - assert(!AdditionalAbiTags && - "dependent template name cannot have abi tags"); - - DependentTemplateName *Dependent = Template.getAsDependentTemplateName(); - assert(Dependent && "Not a dependent template name?"); - if (const IdentifierInfo *Id = Dependent->getIdentifier()) - mangleSourceName(Id); - else - mangleOperatorName(Dependent->getOperator(), UnknownArity); - - addSubstitution(Template); -} - void CXXNameMangler::mangleFloat(const llvm::APFloat &f) { // ABI: // Floating-point literals are encoded using a fixed-length @@ -1944,21 +1919,28 @@ void CXXNameMangler::mangleTemplatePrefix(TemplateName Template) { if (TemplateDecl *TD = Template.getAsTemplateDecl()) return mangleTemplatePrefix(TD); - if (QualifiedTemplateName *Qualified = Template.getAsQualifiedTemplateName()) - manglePrefix(Qualified->getQualifier()); + DependentTemplateName *Dependent = Template.getAsDependentTemplateName(); + assert(Dependent && "unexpected template name kind"); - if (OverloadedTemplateStorage *Overloaded - = Template.getAsOverloadedTemplate()) { - mangleUnqualifiedName(GlobalDecl(), (*Overloaded->begin())->getDeclName(), - UnknownArity, nullptr); + // Clang 11 and before mangled the substitution for a dependent template name + // after already having emitted (a substitution for) the prefix. + bool Clang11Compat = getASTContext().getLangOpts().getClangABICompat() <= + LangOptions::ClangABI::Ver11; + if (!Clang11Compat && mangleSubstitution(Template)) return; - } - DependentTemplateName *Dependent = Template.getAsDependentTemplateName(); - assert(Dependent && "Unknown template name kind?"); if (NestedNameSpecifier *Qualifier = Dependent->getQualifier()) manglePrefix(Qualifier); - mangleUnscopedTemplateName(Template, /* AdditionalAbiTags */ nullptr); + + if (Clang11Compat && mangleSubstitution(Template)) + return; + + if (const IdentifierInfo *Id = Dependent->getIdentifier()) + mangleSourceName(Id); + else + mangleOperatorName(Dependent->getOperator(), UnknownArity); + + addSubstitution(Template); } void CXXNameMangler::mangleTemplatePrefix(GlobalDecl GD, diff --git a/clang/test/CodeGenCXX/clang-abi-compat.cpp b/clang/test/CodeGenCXX/clang-abi-compat.cpp index 409c72108f64..7943cad004e1 100644 --- a/clang/test/CodeGenCXX/clang-abi-compat.cpp +++ b/clang/test/CodeGenCXX/clang-abi-compat.cpp @@ -1,9 +1,10 @@ -// RUN: %clang_cc1 -std=c++17 -triple x86_64-linux-gnu -fclang-abi-compat=3.0 %s -emit-llvm -o - | FileCheck --check-prefix=PRE39 --check-prefix=PRE5 %s -// RUN: %clang_cc1 -std=c++17 -triple x86_64-linux-gnu -fclang-abi-compat=3.8 %s -emit-llvm -o - | FileCheck --check-prefix=PRE39 --check-prefix=PRE5 %s -// RUN: %clang_cc1 -std=c++17 -triple x86_64-linux-gnu -fclang-abi-compat=3.9 %s -emit-llvm -o - | FileCheck --check-prefix=V39 --check-prefix=PRE5 %s -// RUN: %clang_cc1 -std=c++17 -triple x86_64-linux-gnu -fclang-abi-compat=4.0 %s -emit-llvm -o - | FileCheck --check-prefix=V39 --check-prefix=PRE5 %s -// RUN: %clang_cc1 -std=c++17 -triple x86_64-linux-gnu -fclang-abi-compat=5 %s -emit-llvm -o - | FileCheck --check-prefix=V39 --check-prefix=V5 %s -// RUN: %clang_cc1 -std=c++17 -triple x86_64-linux-gnu -fclang-abi-compat=latest %s -emit-llvm -o - | FileCheck --check-prefix=V39 --check-prefix=V5 %s +// RUN: %clang_cc1 -std=c++17 -triple x86_64-linux-gnu -fclang-abi-compat=3.0 %s -emit-llvm -o - | FileCheck --check-prefixes=PRE39,PRE5,PRE12 %s +// RUN: %clang_cc1 -std=c++17 -triple x86_64-linux-gnu -fclang-abi-compat=3.8 %s -emit-llvm -o - | FileCheck --check-prefixes=PRE39,PRE5,PRE12 %s +// RUN: %clang_cc1 -std=c++17 -triple x86_64-linux-gnu -fclang-abi-compat=3.9 %s -emit-llvm -o - | FileCheck --check-prefixes=V39,PRE5,PRE12 %s +// RUN: %clang_cc1 -std=c++17 -triple x86_64-linux-gnu -fclang-abi-compat=4.0 %s -emit-llvm -o - | FileCheck --check-prefixes=V39,PRE5,PRE12 %s +// RUN: %clang_cc1 -std=c++17 -triple x86_64-linux-gnu -fclang-abi-compat=5 %s -emit-llvm -o - | FileCheck --check-prefixes=V39,V5,PRE12 %s +// RUN: %clang_cc1 -std=c++17 -triple x86_64-linux-gnu -fclang-abi-compat=11 %s -emit-llvm -o - | FileCheck --check-prefixes=V11,V5,PRE12 %s +// RUN: %clang_cc1 -std=c++17 -triple x86_64-linux-gnu -fclang-abi-compat=latest %s -emit-llvm -o - | FileCheck --check-prefixes=V39,V5,V12 %s typedef __attribute__((vector_size(8))) long long v1xi64; void clang39(v1xi64) {} @@ -17,3 +18,12 @@ struct A { void clang5(A) {} // PRE5: @_Z6clang51A() // V5: @_Z6clang51A(%{{.*}}* + +namespace mangle_template_prefix { + // PRE12: @_ZN22mangle_template_prefix1fINS_1TEEEvNT_1UIiE1VIiEENS4_S5_IfEE( + // V12: @_ZN22mangle_template_prefix1fINS_1TEEEvNT_1UIiE1VIiEENS5_IfEE( + template<typename T> void f(typename T::template U<int>::template V<int>, typename T::template U<int>::template V<float>); + struct T { template<typename I> struct U { template<typename J> using V = int; }; }; + void g() { f<T>(1, 2); } +} + diff --git a/clang/test/CodeGenCXX/mangle-template.cpp b/clang/test/CodeGenCXX/mangle-template.cpp index 23134693de5c..45868f51f5e8 100644 --- a/clang/test/CodeGenCXX/mangle-template.cpp +++ b/clang/test/CodeGenCXX/mangle-template.cpp @@ -212,3 +212,12 @@ __make_integer_seq<std::integer_sequence, int, N> make() {} template __make_integer_seq<std::integer_sequence, int, 5> make<5>(); // CHECK: define weak_odr {{.*}} @_ZN6test154makeILi5EEE18__make_integer_seqISt16integer_sequenceiXT_EEv( } + +namespace test16 { + // Ensure we properly form substitutions for template names in prefixes. + // CHECK: @_ZN6test161fINS_1TEEEvNT_1UIiE1VIiEENS5_IfEE + template<typename T> void f(typename T::template U<int>::template V<int>, typename T::template U<int>::template V<float>); + struct T { template<typename I> struct U { template<typename J> using V = int; }; }; + void g() { f<T>(1, 2); } +} + _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits