[clang] [ItaniumMangle] Make sure class types are added to the dictionary of substitution candidates when compiling for older ABIs (PR #138947)
Akira Hatanaka via cfe-commits
cfe-commits at lists.llvm.org
Wed May 7 17:14:16 PDT 2025
https://github.com/ahatanak updated https://github.com/llvm/llvm-project/pull/138947
>From ece5ba2ee3adac03f058d5cc450ecf2ad70a5a70 Mon Sep 17 00:00:00 2001
From: Akira Hatanaka <ahatanak at gmail.com>
Date: Wed, 7 May 2025 12:00:08 -0700
Subject: [PATCH 1/2] [ItaniumMangle] Make sure class types are added to the
dictionary of substitution candidates when compiling for older ABIs
https://github.com/llvm/llvm-project/pull/132401 made changes to
the function that mangles member pointer types, which caused
substitutions to be mangled incorrectly.
Make sure addSubstitution is called in mangleCXXRecordDecl unless
vtables are being mangled (see https://github.com/llvm/llvm-project/pull/109970
for why that is needed).
rdar://149307496
---
clang/lib/AST/ItaniumMangle.cpp | 19 ++++++++++++-------
.../CodeGenCXX/mangle-itanium-ptrauth.cpp | 14 ++++++++++++++
clang/test/CodeGenCXX/mangle.cpp | 19 ++++++++++++++++---
3 files changed, 42 insertions(+), 10 deletions(-)
diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp
index 33a8728728574..f5a1c4332ef80 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 IsManglingVTable = false);
void mangleLambdaSig(const CXXRecordDecl *Lambda);
void mangleModuleNamePrefix(StringRef Name, bool IsPartition = false);
void mangleVendorQualifier(StringRef Name);
@@ -3102,11 +3103,15 @@ void CXXNameMangler::mangleType(QualType T) {
addSubstitution(T);
}
-void CXXNameMangler::mangleCXXRecordDecl(const CXXRecordDecl *Record) {
+void CXXNameMangler::mangleCXXRecordDecl(const CXXRecordDecl *Record,
+ bool IsManglingVTable) {
if (mangleSubstitution(Record))
return;
mangleName(Record);
- if (isCompatibleWith(LangOptions::ClangABI::Ver19))
+ // If we are mangling vtables, return early without adding the record to the
+ // dictionary of substitution candidates to maintain compatibility with older
+ // ABIs.
+ if (IsManglingVTable && isCompatibleWith(LangOptions::ClangABI::Ver19))
return;
addSubstitution(Record);
}
@@ -7501,7 +7506,7 @@ void ItaniumMangleContextImpl::mangleCXXVTable(const CXXRecordDecl *RD,
// <special-name> ::= TV <type> # virtual table
CXXNameMangler Mangler(*this, Out);
Mangler.getStream() << "_ZTV";
- Mangler.mangleCXXRecordDecl(RD);
+ Mangler.mangleCXXRecordDecl(RD, /*IsManglingVTable=*/true);
}
void ItaniumMangleContextImpl::mangleCXXVTT(const CXXRecordDecl *RD,
@@ -7509,7 +7514,7 @@ void ItaniumMangleContextImpl::mangleCXXVTT(const CXXRecordDecl *RD,
// <special-name> ::= TT <type> # VTT structure
CXXNameMangler Mangler(*this, Out);
Mangler.getStream() << "_ZTT";
- Mangler.mangleCXXRecordDecl(RD);
+ Mangler.mangleCXXRecordDecl(RD, /*IsManglingVTable=*/true);
}
void ItaniumMangleContextImpl::mangleCXXCtorVTable(const CXXRecordDecl *RD,
@@ -7519,10 +7524,10 @@ void ItaniumMangleContextImpl::mangleCXXCtorVTable(const CXXRecordDecl *RD,
// <special-name> ::= TC <type> <offset number> _ <base type>
CXXNameMangler Mangler(*this, Out);
Mangler.getStream() << "_ZTC";
- Mangler.mangleCXXRecordDecl(RD);
+ Mangler.mangleCXXRecordDecl(RD, /*IsManglingVTable=*/true);
Mangler.getStream() << Offset;
Mangler.getStream() << '_';
- Mangler.mangleCXXRecordDecl(Type);
+ Mangler.mangleCXXRecordDecl(Type, /*IsManglingVTable=*/true);
}
void ItaniumMangleContextImpl::mangleCXXRTTI(QualType Ty, raw_ostream &Out) {
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) *) {}
diff --git a/clang/test/CodeGenCXX/mangle.cpp b/clang/test/CodeGenCXX/mangle.cpp
index f4dc17bc4561e..bf9a4f6187778 100644
--- a/clang/test/CodeGenCXX/mangle.cpp
+++ b/clang/test/CodeGenCXX/mangle.cpp
@@ -1,4 +1,5 @@
-// RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-apple-darwin9 -fblocks -std=c++11 | FileCheck %s
+// RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-apple-darwin9 -fblocks -std=c++11 | FileCheck --check-prefixes=CHECK,CHECK-ABI-LATEST %s
+// RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-apple-darwin9 -fblocks -std=c++11 -fclang-abi-compat=4 | FileCheck %s
struct X { };
struct Y { };
@@ -1176,7 +1177,7 @@ namespace test56 {
namespace test57 {
struct X { template <int N> int f(); } x;
template<int N> void f(decltype(x.f<0>() + N)) {}
- // CHECK-LABEL: @_ZN6test571fILi0EEEvDTplcldtL_ZNS_1xEE1fILi0EEET_E
+ // CHECK-ABI-LATEST: @_ZN6test571fILi0EEEvDTplcldtL_ZNS_1xEE1fILi0EEET_E
template void f<0>(int);
}
@@ -1217,7 +1218,7 @@ namespace test61 {
};
};
template <typename T> void f(typename T::Y::a, typename T::Y::b) {}
- // CHECK-LABEL: @_ZN6test611fINS_1XEEEvNT_1Y1aENS3_1bE
+ // CHECK-ABI-LATEST-LABEL: @_ZN6test611fINS_1XEEEvNT_1Y1aENS3_1bE
template void f<X>(int, int);
}
@@ -1247,3 +1248,15 @@ namespace test63 {
// CHECK-LABEL: @_ZN6test6312_GLOBAL__N_11fIiEEvNS0_4_AndINS0_17integral_constantIivEENS0_7_OrImplIXsr17integral_constantIT_iEE5valueEEEEE
void g() { f<int>({}); }
} // namespace test63
+
+namespace test_substitution {
+struct S { int f(void *, void *); };
+
+typedef int (S::*s_func)(void *, void *);
+
+// clang previously emitted 'S0_' for the second 'void *' parameter type because
+// of a bug in the mangler.
+
+// CHECK-LABEL: define void @_ZN17test_substitution4foo1EMNS_1SEFiPvS1_E(
+void foo1(s_func s) {}
+}
>From 1856a6071d2cd64caca725d803151b5f43b8e8b1 Mon Sep 17 00:00:00 2001
From: Akira Hatanaka <ahatanak at gmail.com>
Date: Wed, 7 May 2025 17:08:57 -0700
Subject: [PATCH 2/2] Move test to clang-abi-compat.cpp
---
clang/test/CodeGenCXX/clang-abi-compat.cpp | 12 ++++++++++++
clang/test/CodeGenCXX/mangle.cpp | 19 +++----------------
2 files changed, 15 insertions(+), 16 deletions(-)
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 <typename T> void test10(typename T::Y::a, typename T::Y::b, float*, fl
// PRE15: @_Z6test10I1XEvNT_1Y1aENS1_1Y1bEPfS4_
// V15: @_Z6test10I1XEvNT_1Y1aENS2_1bEPfS5_
template void test10<X>(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.cpp b/clang/test/CodeGenCXX/mangle.cpp
index bf9a4f6187778..f4dc17bc4561e 100644
--- a/clang/test/CodeGenCXX/mangle.cpp
+++ b/clang/test/CodeGenCXX/mangle.cpp
@@ -1,5 +1,4 @@
-// RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-apple-darwin9 -fblocks -std=c++11 | FileCheck --check-prefixes=CHECK,CHECK-ABI-LATEST %s
-// RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-apple-darwin9 -fblocks -std=c++11 -fclang-abi-compat=4 | FileCheck %s
+// RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-apple-darwin9 -fblocks -std=c++11 | FileCheck %s
struct X { };
struct Y { };
@@ -1177,7 +1176,7 @@ namespace test56 {
namespace test57 {
struct X { template <int N> int f(); } x;
template<int N> void f(decltype(x.f<0>() + N)) {}
- // CHECK-ABI-LATEST: @_ZN6test571fILi0EEEvDTplcldtL_ZNS_1xEE1fILi0EEET_E
+ // CHECK-LABEL: @_ZN6test571fILi0EEEvDTplcldtL_ZNS_1xEE1fILi0EEET_E
template void f<0>(int);
}
@@ -1218,7 +1217,7 @@ namespace test61 {
};
};
template <typename T> void f(typename T::Y::a, typename T::Y::b) {}
- // CHECK-ABI-LATEST-LABEL: @_ZN6test611fINS_1XEEEvNT_1Y1aENS3_1bE
+ // CHECK-LABEL: @_ZN6test611fINS_1XEEEvNT_1Y1aENS3_1bE
template void f<X>(int, int);
}
@@ -1248,15 +1247,3 @@ namespace test63 {
// CHECK-LABEL: @_ZN6test6312_GLOBAL__N_11fIiEEvNS0_4_AndINS0_17integral_constantIivEENS0_7_OrImplIXsr17integral_constantIT_iEE5valueEEEEE
void g() { f<int>({}); }
} // namespace test63
-
-namespace test_substitution {
-struct S { int f(void *, void *); };
-
-typedef int (S::*s_func)(void *, void *);
-
-// clang previously emitted 'S0_' for the second 'void *' parameter type because
-// of a bug in the mangler.
-
-// CHECK-LABEL: define void @_ZN17test_substitution4foo1EMNS_1SEFiPvS1_E(
-void foo1(s_func s) {}
-}
More information about the cfe-commits
mailing list