diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp index 33a8728728574..9e491b8d13a80 100644 --- a/clang/lib/AST/ItaniumMangle.cpp +++ b/clang/lib/AST/ItaniumMangle.cpp @@ -455,7 +455,8 @@ class CXXNameMangler { void mangleSeqID(unsigned SeqID); void mangleName(GlobalDecl GD); void mangleType(QualType T); - void mangleCXXRecordDecl(const CXXRecordDecl *Record); + void mangleCXXRecordDecl(const CXXRecordDecl *Record, + bool SuppressSubstitution = false); void mangleLambdaSig(const CXXRecordDecl *Lambda); void mangleModuleNamePrefix(StringRef Name, bool IsPartition = false); void mangleVendorQualifier(StringRef Name); @@ -3102,11 +3103,12 @@ void CXXNameMangler::mangleType(QualType T) { addSubstitution(T); } -void CXXNameMangler::mangleCXXRecordDecl(const CXXRecordDecl *Record) { +void CXXNameMangler::mangleCXXRecordDecl(const CXXRecordDecl *Record, + bool SuppressSubstitution) { if (mangleSubstitution(Record)) return; mangleName(Record); - if (isCompatibleWith(LangOptions::ClangABI::Ver19)) + if (SuppressSubstitution) return; addSubstitution(Record); } @@ -7519,7 +7521,12 @@ void ItaniumMangleContextImpl::mangleCXXCtorVTable(const CXXRecordDecl *RD, // ::= TC _ CXXNameMangler Mangler(*this, Out); Mangler.getStream() << "_ZTC"; - Mangler.mangleCXXRecordDecl(RD); + // Older versions of clang did not add the record as a substitution candidate + // here. + bool SuppressSubstitution = + getASTContext().getLangOpts().getClangABICompat() <= + LangOptions::ClangABI::Ver19; + Mangler.mangleCXXRecordDecl(RD, SuppressSubstitution); Mangler.getStream() << Offset; Mangler.getStream() << '_'; Mangler.mangleCXXRecordDecl(Type); diff --git a/clang/test/CodeGenCXX/clang-abi-compat.cpp b/clang/test/CodeGenCXX/clang-abi-compat.cpp index 4d518116f0a70..e23b6f5d59d49 100644 --- a/clang/test/CodeGenCXX/clang-abi-compat.cpp +++ b/clang/test/CodeGenCXX/clang-abi-compat.cpp @@ -160,3 +160,15 @@ template void test10(typename T::Y::a, typename T::Y::b, float*, fl // PRE15: @_Z6test10I1XEvNT_1Y1aENS1_1Y1bEPfS4_ // V15: @_Z6test10I1XEvNT_1Y1aENS2_1bEPfS5_ template void test10(int, int, float*, float*); + +namespace test_substitution { +struct S { int f(void *, void *); }; + +typedef int (S::*s_func)(void *, void *); + +// clang used to incorrectly emit 'S0_' for the second 'void *' parameter type +// when targeting older ABIs because of a bug in the mangler. + +// CHECK-LABEL: define dso_local void @_ZN17test_substitution4foo1EMNS_1SEFiPvS1_E( +void foo1(s_func s) {} +} diff --git a/clang/test/CodeGenCXX/mangle-itanium-ptrauth.cpp b/clang/test/CodeGenCXX/mangle-itanium-ptrauth.cpp index 88d80423c3764..155b766803a0a 100644 --- a/clang/test/CodeGenCXX/mangle-itanium-ptrauth.cpp +++ b/clang/test/CodeGenCXX/mangle-itanium-ptrauth.cpp @@ -1,5 +1,19 @@ // RUN: %clang_cc1 -std=c++11 -fptrauth-intrinsics -fptrauth-calls -emit-llvm -o - -triple=arm64-apple-ios %s | FileCheck %s // RUN: %clang_cc1 -std=c++11 -fptrauth-intrinsics -fptrauth-calls -emit-llvm -o - -triple=aarch64-linux-gnu %s | FileCheck %s +// RUN: %clang_cc1 -std=c++11 -fptrauth-intrinsics -fptrauth-calls -emit-llvm -o - -triple=arm64-apple-ios -fclang-abi-compat=4 %s | FileCheck %s + +// clang previously emitted an incorrect discriminator for the member function +// pointer because of a bug in the mangler. + +// CHECK: @_ZN17test_substitution5funcsE = global [1 x { i64, i64 }] [{ i64, i64 } { i64 ptrtoint (ptr ptrauth (ptr @_ZN17test_substitution1S1fEPvS1_, i32 0, i64 48995) to i64), i64 0 }], align 8 +namespace test_substitution { +struct S { int f(void *, void *); }; + +typedef int (S::*s_func)(void *, void *); + +s_func funcs[] = { (s_func)(&S::f) }; +} + // CHECK: define {{.*}}void @_Z3fooPU9__ptrauthILj3ELb1ELj234EEPi( void foo(int * __ptrauth(3, 1, 234) *) {}