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.
This commit is contained in:
Richard Smith 2020-11-24 15:20:06 -08:00
parent 1bc85cbbb8
commit c2cb61bed3
4 changed files with 46 additions and 44 deletions

View File

@ -155,7 +155,8 @@ public:
/// 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

View File

@ -479,8 +479,6 @@ private:
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());
if (OverloadedTemplateStorage *Overloaded
= Template.getAsOverloadedTemplate()) {
mangleUnqualifiedName(GlobalDecl(), (*Overloaded->begin())->getDeclName(),
UnknownArity, nullptr);
return;
}
DependentTemplateName *Dependent = Template.getAsDependentTemplateName();
assert(Dependent && "Unknown template name kind?");
assert(Dependent && "unexpected template name kind");
// 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;
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,

View File

@ -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); }
}

View File

@ -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); }
}