Skip to content

Commit b035580

Browse files
authored
[ItaniumMangle] Make sure class types are added to the dictionary of substitution candidates when compiling for older ABIs (#138947)
`mangleCXXRecordDecl` should add class types to the substitution dictionary unless it is called by `mangleCXXCtorVTable` (see #109970 for why that is needed). This fixes a mis-compile caused by #132401, which started calling `mangleCXXRecordDecl` in `CXXNameMangler::mangleType(const MemberPointerType *T)`. rdar://149307496
1 parent a4b2f4a commit b035580

File tree

3 files changed

+37
-4
lines changed

3 files changed

+37
-4
lines changed

clang/lib/AST/ItaniumMangle.cpp

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -455,7 +455,8 @@ class CXXNameMangler {
455455
void mangleSeqID(unsigned SeqID);
456456
void mangleName(GlobalDecl GD);
457457
void mangleType(QualType T);
458-
void mangleCXXRecordDecl(const CXXRecordDecl *Record);
458+
void mangleCXXRecordDecl(const CXXRecordDecl *Record,
459+
bool SuppressSubstitution = false);
459460
void mangleLambdaSig(const CXXRecordDecl *Lambda);
460461
void mangleModuleNamePrefix(StringRef Name, bool IsPartition = false);
461462
void mangleVendorQualifier(StringRef Name);
@@ -3103,11 +3104,12 @@ void CXXNameMangler::mangleType(QualType T) {
31033104
addSubstitution(T);
31043105
}
31053106

3106-
void CXXNameMangler::mangleCXXRecordDecl(const CXXRecordDecl *Record) {
3107+
void CXXNameMangler::mangleCXXRecordDecl(const CXXRecordDecl *Record,
3108+
bool SuppressSubstitution) {
31073109
if (mangleSubstitution(Record))
31083110
return;
31093111
mangleName(Record);
3110-
if (isCompatibleWith(LangOptions::ClangABI::Ver19))
3112+
if (SuppressSubstitution)
31113113
return;
31123114
addSubstitution(Record);
31133115
}
@@ -7557,7 +7559,12 @@ void ItaniumMangleContextImpl::mangleCXXCtorVTable(const CXXRecordDecl *RD,
75577559
// <special-name> ::= TC <type> <offset number> _ <base type>
75587560
CXXNameMangler Mangler(*this, Out);
75597561
Mangler.getStream() << "_ZTC";
7560-
Mangler.mangleCXXRecordDecl(RD);
7562+
// Older versions of clang did not add the record as a substitution candidate
7563+
// here.
7564+
bool SuppressSubstitution =
7565+
getASTContext().getLangOpts().getClangABICompat() <=
7566+
LangOptions::ClangABI::Ver19;
7567+
Mangler.mangleCXXRecordDecl(RD, SuppressSubstitution);
75617568
Mangler.getStream() << Offset;
75627569
Mangler.getStream() << '_';
75637570
Mangler.mangleCXXRecordDecl(Type);

clang/test/CodeGenCXX/clang-abi-compat.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,3 +160,15 @@ template <typename T> void test10(typename T::Y::a, typename T::Y::b, float*, fl
160160
// PRE15: @_Z6test10I1XEvNT_1Y1aENS1_1Y1bEPfS4_
161161
// V15: @_Z6test10I1XEvNT_1Y1aENS2_1bEPfS5_
162162
template void test10<X>(int, int, float*, float*);
163+
164+
namespace test_substitution {
165+
struct S { int f(void *, void *); };
166+
167+
typedef int (S::*s_func)(void *, void *);
168+
169+
// clang used to incorrectly emit 'S0_' for the second 'void *' parameter type
170+
// when targeting older ABIs because of a bug in the mangler.
171+
172+
// CHECK-LABEL: define dso_local void @_ZN17test_substitution4foo1EMNS_1SEFiPvS1_E(
173+
void foo1(s_func s) {}
174+
}

clang/test/CodeGenCXX/mangle-itanium-ptrauth.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,19 @@
11
// RUN: %clang_cc1 -std=c++11 -fptrauth-intrinsics -fptrauth-calls -emit-llvm -o - -triple=arm64-apple-ios %s | FileCheck %s
22
// RUN: %clang_cc1 -std=c++11 -fptrauth-intrinsics -fptrauth-calls -emit-llvm -o - -triple=aarch64-linux-gnu %s | FileCheck %s
3+
// RUN: %clang_cc1 -std=c++11 -fptrauth-intrinsics -fptrauth-calls -emit-llvm -o - -triple=arm64-apple-ios -fclang-abi-compat=4 %s | FileCheck %s
4+
5+
// clang previously emitted an incorrect discriminator for the member function
6+
// pointer because of a bug in the mangler.
7+
8+
// 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
9+
namespace test_substitution {
10+
struct S { int f(void *, void *); };
11+
12+
typedef int (S::*s_func)(void *, void *);
13+
14+
s_func funcs[] = { (s_func)(&S::f) };
15+
}
16+
317

418
// CHECK: define {{.*}}void @_Z3fooPU9__ptrauthILj3ELb1ELj234EEPi(
519
void foo(int * __ptrauth(3, 1, 234) *) {}

0 commit comments

Comments
 (0)