[clang] c2cb61b - Fix mangling of substitutions for template-prefixes.
Richard Smith via cfe-commits
cfe-commits at lists.llvm.org
Tue Nov 24 16:25:36 PST 2020
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); }
+}
+
More information about the cfe-commits
mailing list