Author: Harald van Dijk Date: 2022-05-02T18:07:47+01:00 New Revision: fed7be096f8ed5d70029acd712ac19ffc61e04e5
URL: https://github.com/llvm/llvm-project/commit/fed7be096f8ed5d70029acd712ac19ffc61e04e5 DIFF: https://github.com/llvm/llvm-project/commit/fed7be096f8ed5d70029acd712ac19ffc61e04e5.diff LOG: Mark identifier prefixes as substitutable 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. Reviewed By: erichkeane Differential Revision: https://reviews.llvm.org/D122663 Added: Modified: clang/docs/ReleaseNotes.rst clang/include/clang/Basic/LangOptions.h clang/lib/AST/ItaniumMangle.cpp clang/lib/Frontend/CompilerInvocation.cpp clang/test/CodeGenCXX/clang-abi-compat.cpp clang/test/CodeGenCXX/mangle.cpp Removed: ################################################################################ diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 839a7035a94fd..855d1a6c41468 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -265,6 +265,10 @@ C++ Language Changes in Clang ``std::move_if_noexcept``, ``std::addressof``, and ``std::as_const``. These are now treated as compiler builtins and implemented directly, rather than instantiating the definition from the standard library. +- Fixed mangling of nested dependent names such as ``T::a::b``, where ``T`` is a + template parameter, to conform to the Itanium C++ ABI and be compatible with + GCC. This breaks binary compatibility with code compiled with earlier versions + of clang; use the ``-fclang-abi-compat=14`` option to get the old mangling. C++20 Feature Support ^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/include/clang/Basic/LangOptions.h b/clang/include/clang/Basic/LangOptions.h index eb4c7c4c7d93e..83b8c062aa65c 100644 --- a/clang/include/clang/Basic/LangOptions.h +++ b/clang/include/clang/Basic/LangOptions.h @@ -218,6 +218,10 @@ class LangOptions : public LangOptionsBase { /// This causes clang to not pack non-POD members of packed structs. Ver13, + /// Attempt to be ABI-compatible with code generated by Clang 14.0.x. + /// This causes clang to mangle dependent nested names incorrectly. + Ver14, + /// Conform to the underlying platform's C and C++ ABIs as closely /// as we can. Latest diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp index 75f072168858b..f72789da526c1 100644 --- a/clang/lib/AST/ItaniumMangle.cpp +++ b/clang/lib/AST/ItaniumMangle.cpp @@ -443,6 +443,7 @@ class CXXNameMangler { private: bool mangleSubstitution(const NamedDecl *ND); + bool mangleSubstitution(NestedNameSpecifier *NNS); bool mangleSubstitution(QualType T); bool mangleSubstitution(TemplateName Template); bool mangleSubstitution(uintptr_t Ptr); @@ -456,6 +457,11 @@ class CXXNameMangler { addSubstitution(reinterpret_cast<uintptr_t>(ND)); } + void addSubstitution(NestedNameSpecifier *NNS) { + NNS = Context.getASTContext().getCanonicalNestedNameSpecifier(NNS); + + addSubstitution(reinterpret_cast<uintptr_t>(NNS)); + } void addSubstitution(QualType T); void addSubstitution(TemplateName Template); void addSubstitution(uintptr_t Ptr); @@ -2036,12 +2042,21 @@ void CXXNameMangler::manglePrefix(NestedNameSpecifier *qualifier) { return; case NestedNameSpecifier::Identifier: + // Clang 14 and before did not consider this substitutable. + bool Clang14Compat = getASTContext().getLangOpts().getClangABICompat() <= + LangOptions::ClangABI::Ver14; + if (!Clang14Compat && mangleSubstitution(qualifier)) + return; + // Member expressions can have these without prefixes, but that // should end up in mangleUnresolvedPrefix instead. assert(qualifier->getPrefix()); manglePrefix(qualifier->getPrefix()); mangleSourceName(qualifier->getAsIdentifier()); + + if (!Clang14Compat) + addSubstitution(qualifier); return; } @@ -6009,6 +6024,14 @@ bool CXXNameMangler::mangleSubstitution(const NamedDecl *ND) { return mangleSubstitution(reinterpret_cast<uintptr_t>(ND)); } +bool CXXNameMangler::mangleSubstitution(NestedNameSpecifier *NNS) { + assert(NNS->getKind() == NestedNameSpecifier::Identifier && + "mangleSubstitution(NestedNameSpecifier *) is only used for " + "identifier nested name specifiers."); + NNS = Context.getASTContext().getCanonicalNestedNameSpecifier(NNS); + return mangleSubstitution(reinterpret_cast<uintptr_t>(NNS)); +} + /// Determine whether the given type has any qualifiers that are relevant for /// substitutions. static bool hasMangledSubstitutionQualifiers(QualType T) { diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index b35e3f4fd78a4..847766a58c021 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -3518,6 +3518,8 @@ void CompilerInvocation::GenerateLangArgs(const LangOptions &Opts, GenerateArg(Args, OPT_fclang_abi_compat_EQ, "12.0", SA); else if (Opts.getClangABICompat() == LangOptions::ClangABI::Ver13) GenerateArg(Args, OPT_fclang_abi_compat_EQ, "13.0", SA); + else if (Opts.getClangABICompat() == LangOptions::ClangABI::Ver14) + GenerateArg(Args, OPT_fclang_abi_compat_EQ, "14.0", SA); if (Opts.getSignReturnAddressScope() == LangOptions::SignReturnAddressScopeKind::All) @@ -4026,6 +4028,8 @@ bool CompilerInvocation::ParseLangArgs(LangOptions &Opts, ArgList &Args, Opts.setClangABICompat(LangOptions::ClangABI::Ver12); else if (Major <= 13) Opts.setClangABICompat(LangOptions::ClangABI::Ver13); + else if (Major <= 14) + Opts.setClangABICompat(LangOptions::ClangABI::Ver14); } else if (Ver != "latest") { Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << A->getValue(); diff --git a/clang/test/CodeGenCXX/clang-abi-compat.cpp b/clang/test/CodeGenCXX/clang-abi-compat.cpp index d18b1bfc760e2..9a8df9138ab07 100644 --- a/clang/test/CodeGenCXX/clang-abi-compat.cpp +++ b/clang/test/CodeGenCXX/clang-abi-compat.cpp @@ -1,25 +1,27 @@ // RUN: %clang_cc1 -no-opaque-pointers -std=c++98 -triple x86_64-linux-gnu -fenable-matrix -fclang-abi-compat=3.0 %s -emit-llvm -o - -Wno-c++11-extensions \ -// RUN: | FileCheck --check-prefixes=CHECK,PRE39,PRE5,PRE12 %s +// RUN: | FileCheck --check-prefixes=CHECK,PRE39,PRE5,PRE12,PRE15 %s // RUN: %clang_cc1 -no-opaque-pointers -std=c++17 -triple x86_64-linux-gnu -fenable-matrix -fclang-abi-compat=3.0 %s -emit-llvm -o - \ -// RUN: | FileCheck --check-prefixes=CHECK,PRE39,PRE5,PRE12 %s +// RUN: | FileCheck --check-prefixes=CHECK,PRE39,PRE5,PRE12,PRE15 %s // RUN: %clang_cc1 -no-opaque-pointers -std=c++17 -triple x86_64-linux-gnu -fenable-matrix -fclang-abi-compat=3.8 %s -emit-llvm -o - \ -// RUN: | FileCheck --check-prefixes=CHECK,PRE39,PRE5,PRE12 %s +// RUN: | FileCheck --check-prefixes=CHECK,PRE39,PRE5,PRE12,PRE15 %s // RUN: %clang_cc1 -no-opaque-pointers -std=c++17 -triple x86_64-linux-gnu -fenable-matrix -fclang-abi-compat=3.9 %s -emit-llvm -o - \ -// RUN: | FileCheck --check-prefixes=CHECK,V39,PRE5,PRE12 %s +// RUN: | FileCheck --check-prefixes=CHECK,V39,PRE5,PRE12,PRE15 %s // RUN: %clang_cc1 -no-opaque-pointers -std=c++17 -triple x86_64-linux-gnu -fenable-matrix -fclang-abi-compat=4.0 %s -emit-llvm -o - \ -// RUN: | FileCheck --check-prefixes=CHECK,V39,PRE5,PRE12 %s +// RUN: | FileCheck --check-prefixes=CHECK,V39,PRE5,PRE12,PRE15 %s // RUN: %clang_cc1 -no-opaque-pointers -std=c++17 -triple x86_64-linux-gnu -fenable-matrix -fclang-abi-compat=5 %s -emit-llvm -o - \ -// RUN: | FileCheck --check-prefixes=CHECK,V39,V5,PRE12,PRE12-CXX17 %s +// RUN: | FileCheck --check-prefixes=CHECK,V39,V5,PRE12,PRE12-CXX17,PRE15 %s // RUN: %clang_cc1 -no-opaque-pointers -std=c++17 -triple x86_64-linux-gnu -fenable-matrix -fclang-abi-compat=11 %s -emit-llvm -o - \ -// RUN: | FileCheck --check-prefixes=CHECK,V39,V5,PRE12,PRE12-CXX17 %s +// RUN: | FileCheck --check-prefixes=CHECK,V39,V5,PRE12,PRE12-CXX17,PRE15 %s // RUN: %clang_cc1 -no-opaque-pointers -std=c++20 -triple x86_64-linux-gnu -fenable-matrix -fclang-abi-compat=11 %s -emit-llvm -o - \ -// RUN: | FileCheck --check-prefixes=CHECK,V39,V5,PRE12,PRE12-CXX17,PRE12-CXX20,PRE13-CXX20 %s +// RUN: | FileCheck --check-prefixes=CHECK,V39,V5,PRE12,PRE12-CXX17,PRE12-CXX20,PRE13-CXX20,PRE15 %s // RUN: %clang_cc1 -no-opaque-pointers -std=c++20 -triple x86_64-linux-gnu -fenable-matrix -fclang-abi-compat=12 %s -emit-llvm -o - \ -// RUN: | FileCheck --check-prefixes=CHECK,V39,V5,V12,V12-CXX17,V12-CXX20,PRE13-CXX20 %s +// RUN: | FileCheck --check-prefixes=CHECK,V39,V5,V12,V12-CXX17,V12-CXX20,PRE13-CXX20,PRE15 %s +// RUN: %clang_cc1 -no-opaque-pointers -std=c++20 -triple x86_64-linux-gnu -fenable-matrix -fclang-abi-compat=14 %s -emit-llvm -o - \ +// RUN: | FileCheck --check-prefixes=CHECK,V39,V5,V12,V12-CXX17,V12-CXX20,V13-CXX20,PRE15 %s // RUN: %clang_cc1 -no-opaque-pointers -std=c++98 -triple x86_64-linux-gnu -fenable-matrix -fclang-abi-compat=latest %s -emit-llvm -o - -Wno-c++11-extensions \ -// RUN: | FileCheck --check-prefixes=CHECK,V39,V5,V12 %s +// RUN: | FileCheck --check-prefixes=CHECK,V39,V5,V12,V15 %s // RUN: %clang_cc1 -no-opaque-pointers -std=c++20 -triple x86_64-linux-gnu -fenable-matrix -fclang-abi-compat=latest %s -emit-llvm -o - \ -// RUN: | FileCheck --check-prefixes=CHECK,V39,V5,V12,V12-CXX17,V12-CXX20,V13-CXX20 %s +// RUN: | FileCheck --check-prefixes=CHECK,V39,V5,V12,V12-CXX17,V12-CXX20,V13-CXX20,V15 %s typedef __attribute__((vector_size(8))) long long v1xi64; void clang39(v1xi64) {} @@ -147,3 +149,14 @@ int observe_lambdas(T, U, V, W) { return 0; } inline auto inline_var_lambda = observe_lambdas([]{}, []{}, (int*)0, (int*)0); int use_inline_var_lambda() { return inline_var_lambda; } #endif + +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*) {} +// PRE15: @_Z6test10I1XEvNT_1Y1aENS1_1Y1bEPfS4_ +// V15: @_Z6test10I1XEvNT_1Y1aENS2_1bEPfS5_ +template void test10<X>(int, int, float*, float*); diff --git a/clang/test/CodeGenCXX/mangle.cpp b/clang/test/CodeGenCXX/mangle.cpp index f6b5297cda25a..eb87118c56e62 100644 --- a/clang/test/CodeGenCXX/mangle.cpp +++ b/clang/test/CodeGenCXX/mangle.cpp @@ -1155,3 +1155,15 @@ namespace test60 { // CHECK-LABEL: @_ZN6test601fIiEEvDTplL_ZNS_1aEEcvT__EE template void f<int>(int); } + +namespace test61 { + struct X { + struct Y { + using a = int; + using b = int; + }; + }; + template <typename T> void f(typename T::Y::a, typename T::Y::b) {} + // CHECK-LABEL: @_ZN6test611fINS_1XEEEvNT_1Y1aENS3_1bE + template void f<X>(int, int); +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits