Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 80f9f56

Browse files
committedMay 15, 2025
fixup! just sync test-case file into LLVM; don't move tests
1 parent 96232c3 commit 80f9f56

File tree

6 files changed

+30543
-244
lines changed

6 files changed

+30543
-244
lines changed
 

‎libcxxabi/src/demangle/README.txt

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,9 +52,10 @@ shared demangler library.
5252
Testing
5353
-------
5454

55-
The main ItaniumDemangle test-suite lives in llvm/unittests/Demangle/.
56-
The libcxxabi/test/{unit,}test_demangle.cpp suite tests basic functionality
57-
of __cxa_demangle.
55+
The tests are split up between libcxxabi/test/{unit,}test_demangle.cpp, and
56+
llvm/unittests/Demangle. The llvm directory should only get tests for stuff not
57+
included in the core library. In the future though, we should probably move all
58+
the tests to LLVM.
5859

5960
It is also a really good idea to run libFuzzer after non-trivial changes, see
6061
libcxxabi/fuzz/cxa_demangle_fuzzer.cpp and https://llvm.org/docs/LibFuzzer.html.

‎libcxxabi/src/demangle/cp-to-llvm.sh

Lines changed: 34 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,30 +7,52 @@ set -e
77

88
cd $(dirname $0)
99
HDRS="ItaniumDemangle.h ItaniumNodes.def StringViewExtras.h Utility.h"
10+
TEST_HDRS="DemangleTestCases.inc"
1011
LLVM_DEMANGLE_DIR=$1
12+
LLVM_TESTING_DIR=
1113

1214
if [[ -z "$LLVM_DEMANGLE_DIR" ]]; then
1315
LLVM_DEMANGLE_DIR="../../../llvm/include/llvm/Demangle"
16+
LLVM_TESTING_DIR=$LLVM_DEMANGLE_DIR/../Testing/Demangle
1417
fi
1518

1619
if [[ ! -d "$LLVM_DEMANGLE_DIR" ]]; then
1720
echo "No such directory: $LLVM_DEMANGLE_DIR" >&2
1821
exit 1
1922
fi
2023

21-
read -p "This will overwrite the copies of $HDRS in $LLVM_DEMANGLE_DIR; are you sure? [y/N]" -n 1 -r ANSWER
24+
if [[ ! -d "$LLVM_TESTING_DIR" ]]; then
25+
LLVM_TESTING_DIR="../../../llvm/include/llvm/Testing/Demangle"
26+
fi
27+
28+
if [[ ! -d "$LLVM_TESTING_DIR" ]]; then
29+
echo "No such directory: $LLVM_TESTING_DIR" >&2
30+
exit 1
31+
fi
32+
33+
read -p "This will overwrite the copies of $HDRS in $LLVM_DEMANGLE_DIR and $TEST_HDRS in $LLVM_TESTING_DIR; are you sure? [y/N]" -n 1 -r ANSWER
2234
echo
2335

24-
if [[ $ANSWER =~ ^[Yy]$ ]]; then
25-
cp -f README.txt $LLVM_DEMANGLE_DIR
26-
chmod -w $LLVM_DEMANGLE_DIR/README.txt
27-
for I in $HDRS ; do
28-
rm -f $LLVM_DEMANGLE_DIR/$I
29-
dash=$(echo "$I---------------------------" | cut -c -27 |\
30-
sed 's|[^-]*||')
31-
sed -e '1s|^//=*-* .*\..* -*.*=*// *$|//===--- '"$I $dash"'-*- mode:c++;eval:(read-only-mode) -*-===//|' \
32-
-e '2s|^// *$|// Do not edit! See README.txt.|' \
33-
$I >$LLVM_DEMANGLE_DIR/$I
34-
chmod -w $LLVM_DEMANGLE_DIR/$I
36+
copy_files() {
37+
local src=$1
38+
local dst=$2
39+
local hdrs=$3
40+
41+
cp -f README.txt $dst
42+
chmod -w $dst/README.txt
43+
44+
for I in $hdrs ; do
45+
rm -f $dst/$I
46+
dash=$(echo "$I---------------------------" | cut -c -27 |\
47+
sed 's|[^-]*||')
48+
sed -e '1s|^//=*-* .*\..* -*.*=*// *$|//===--- '"$I $dash"'-*- mode:c++;eval:(read-only-mode) -*-===//|' \
49+
-e '2s|^// *$|// Do not edit! See README.txt.|' \
50+
$src/$I >$dst/$I
51+
chmod -w $dst/$I
3552
done
53+
}
54+
55+
if [[ $ANSWER =~ ^[Yy]$ ]]; then
56+
copy_files . $LLVM_DEMANGLE_DIR $HDRS
57+
copy_files ../../test $LLVM_TESTING_DIR $TEST_HDRS
3658
fi

‎libcxxabi/test/DemangleTestCases.inc

Lines changed: 30219 additions & 0 deletions
Large diffs are not rendered by default.

‎libcxxabi/test/test_demangle.pass.cpp

Lines changed: 225 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,15 @@
66
//
77
//===----------------------------------------------------------------------===//
88

9-
// Tests for ItaniumDemangle live in llvm/unittests/Demangle
9+
// This test is too big for most embedded devices.
10+
// XFAIL: LIBCXX-PICOLIBC-FIXME
1011

1112
// This test exercises support for char array initializer lists added in
1213
// dd8b266ef.
1314
// UNSUPPORTED: using-built-library-before-llvm-20
1415

16+
// XFAIL: win32-broken-printf-a-precision
17+
1518
#include "support/timer.h"
1619
#include <algorithm>
1720
#include <cassert>
@@ -21,27 +24,137 @@
2124
#include <cxxabi.h>
2225
#include <string>
2326

27+
// Is long double fp80? (Only x87 extended double has 64-bit mantissa)
28+
#define LDBL_FP80 (__LDBL_MANT_DIG__ == 64)
29+
// Is long double fp128?
30+
#define LDBL_FP128 (__LDBL_MANT_DIG__ == 113)
31+
32+
const char* cases[][2] = {
33+
#include "DemangleTestCases.inc"
34+
};
35+
36+
const unsigned N = sizeof(cases) / sizeof(cases[0]);
37+
38+
struct FPLiteralCase {
39+
const char* mangled;
40+
// There are four possible demanglings of a given float.
41+
std::string expecting[4];
42+
} fp_literal_cases[] = {
43+
// clang-format off
44+
{"_ZN5test01gIfEEvRAszplcvT__ELf40a00000E_c",
45+
{
46+
"void test0::g<float>(char (&) [sizeof ((float)() + 0x1.4p+2f)])",
47+
"void test0::g<float>(char (&) [sizeof ((float)() + 0x2.8p+1f)])",
48+
"void test0::g<float>(char (&) [sizeof ((float)() + 0x5p+0f)])",
49+
"void test0::g<float>(char (&) [sizeof ((float)() + 0xap-1f)])",
50+
}},
51+
{"_ZN5test01hIfEEvRAszplcvT__ELd4014000000000000E_c",
52+
{
53+
"void test0::h<float>(char (&) [sizeof ((float)() + 0x1.4p+2)])",
54+
"void test0::h<float>(char (&) [sizeof ((float)() + 0x2.8p+1)])",
55+
"void test0::h<float>(char (&) [sizeof ((float)() + 0x5p+0)])",
56+
"void test0::h<float>(char (&) [sizeof ((float)() + 0xap-1)])",
57+
}},
58+
#if LDBL_FP80
59+
{"_ZN5test01hIfEEvRAcvjplstT_Le4001a000000000000000E_c",
60+
{
61+
"void test0::h<float>(char (&) [(unsigned int)(sizeof (float) + 0x1.4p+2L)])",
62+
"void test0::h<float>(char (&) [(unsigned int)(sizeof (float) + 0x2.8p+1L)])",
63+
"void test0::h<float>(char (&) [(unsigned int)(sizeof (float) + 0x5p+0L)])",
64+
"void test0::h<float>(char (&) [(unsigned int)(sizeof (float) + 0xap-1L)])",
65+
}},
66+
#endif
67+
#if LDBL_FP128
68+
// A 32-character FP literal of long double type
69+
{"3FooILeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeEE",
70+
{"Foo<-0x1.eeeeeeeeeeeeeeeeeeeeeeeeeeeep+12015L>"}},
71+
#endif
72+
// clang-format on
73+
};
74+
const unsigned NF = sizeof(fp_literal_cases) / sizeof(fp_literal_cases[0]);
75+
const unsigned NEF = sizeof(fp_literal_cases[0].expecting) / sizeof(fp_literal_cases[0].expecting[0]);
76+
77+
const char* invalid_cases[] = {
78+
// clang-format off
79+
"_ZIPPreEncode",
80+
"Agentt",
81+
"NSoERj5E=Y1[uM:ga",
82+
"Aon_PmKVPDk7?fg4XP5smMUL6;<WsI_mgbf23cCgsHbT<l8EE\0uVRkNOoXDrgdA4[8IU>Vl<>IL8ayHpiVDDDXTY;^o9;i",
83+
"_ZNSt16allocator_traitsISaIN4llvm3sys2fs18directory_iteratorEEE9constructIS3_IS3_EEEDTcl12_S_constructfp_fp0_spcl7forwardIT0_Efp1_EEERS4_PT_DpOS7_",
84+
"3FooILdaaaaaaaaaaAAAAaaEE",
85+
"3FooILdaaaaaaaaaaaaaaEE",
86+
#if !LDBL_FP80
87+
"_ZN5test01hIfEEvRAcvjplstT_Le4001a000000000000000E_c",
88+
#endif
89+
// The following test cases were found by libFuzzer+ASAN
90+
"\x44\x74\x70\x74\x71\x75\x34\x43\x41\x72\x4D\x6E\x65\x34\x9F\xC1\x43\x41\x72\x4D\x6E\x77\x38\x9A\x8E\x44\x6F\x64\x6C\x53\xF9\x5F\x70\x74\x70\x69\x45\x34\xD3\x73\x9E\x2A\x37",
91+
"\x4D\x41\x72\x63\x4E\x39\x44\x76\x72\x4D\x34\x44\x53\x4B\x6F\x44\x54\x6E\x61\x37\x47\x77\x78\x38\x43\x27\x41\x5F\x73\x70\x69\x45*",
92+
"\x41\x64\x6E\x32*",
93+
"\x43\x46\x41\x67\x73*",
94+
"\x72\x3A\x4E\x53\x64\x45\x39\x4F\x52\x4E\x1F\x43\x34\x64\x54\x5F\x49\x31\x41\x63\x6C\x37\x2A\x4D\x41\x67\x73\x76\x43\x54\x35\x5F\x49\x4B\x4C\x55\x6C\x73\x4C\x38\x64\x43\x41\x47\x4C\x5A\x28\x4F\x41\x6E\x77\x5F\x53\x6F\x70\x69\x45\x5F\x63\x47\x61\x4C\x31\x4F\x4C\x33\x3E\x41\x4C\x4B\x4C\x55\x6C\x73\x4C\x38\x64\x43\x66\x41\x47\x4C\x5A\x28\x4F\x41\x6E\x77\x5F\x53\x6F\x70\x69\x45\x5F\x37\x41*",
95+
"\x2D\x5F\x63\x47\x4F\x63\xD3",
96+
"\x44\x74\x70\x74\x71\x75\x32\x43\x41\x38\x65\x6E\x9B\x72\x4D\xC1\x43\x41\x72\x4D\x6E\x77\x38\x9A\x8E\x44\x6F\x64\xC3\x53\xF9\x5F\x70\x74\x70\x69\x45\x38\xD3\x73\x9E\x2A\x37",
97+
"\x4C\x5A\x4C\x55\x6C\x4D\x41\x5F\x41\x67\x74\x71\x75\x34\x4D\x41\x64\x73\x4C\x44\x76\x72\x4D\x34\x44\x4B\x44\x54\x6E\x61\x37\x47\x77\x78\x38\x43\x27\x41\x5F\x73\x70\x69\x45\x6D\x73\x72\x53\x41\x6F\x41\x7B",
98+
"\x44\x74\x70\x74\x71\x75\x32\x43\x41\x38\x65\x6E\x9B\x72\x4D\xC1\x43\x41\x72\x4D\x6E\x77\x38\x9A\x8E\x44\x6F\x64\x2C\x53\xF9\x5F\x70\x74\x70\x69\x45\xB4\xD3\x73\x9F\x2A\x37",
99+
"\x4C\x5A\x4C\x55\x6C\x69\x4D\x73\x72\x53\x6F\x7A\x41\x5F\x41\x67\x74\x71\x75\x32\x4D\x41\x64\x73\x39\x28\x76\x72\x4D\x34\x44\x4B\x45\x54\x6E\x61\x37\x47\x77\x78\x38\x43\x27\x41\x5F\x73\x70\x69\x45\x6F\x45\x49\x6D\x1A\x4C\x53\x38\x6A\x7A\x5A",
100+
"\x44\x74\x63*",
101+
"\x44\x74\x71\x75\x35\x2A\xDF\x74\x44\x61\x73\x63\x35\x2A\x3B\x41\x72\x4D\x6E\x65\x34\x9F\xC1\x63\x41\x72\x4D\x6E\x77\x38\x9A\x8E\x44\x6F\x64\x6C\x53\xF9\x5F\x70\x74\x70\x69\x45\x33\x44\x76\x35",
102+
"\x44\x74\x70\x74\x71\x75\x32\x43\x41\x38\x65\x6E\x9B\x72\x4D\xC1\x43\x41\x72\x4D\x6E\x77\x38\x9A\x8E\x44\x6F\x64\x6C\x53\xF9\x5F\x70\x74\x70\x69\x45\x38\xD3\x73\x9E\x2A\x37",
103+
"\x46\x44\x74\x70\x74\x71\x75\x32\x43\x41\x72\x4D\x6E\x65\x34\x9F\xC1\x43\x41\x72\x4D\x6E\x77\x38\x9A\x8E\x44\x6F\x64\x6C\x53\xF9\x5F\x70\x74\x70\x69\x45\x34\xD3\x73\x9E\x2A\x37\x72\x33\x8E\x3A\x29\x8E\x44\x35",
104+
"_ZcvCiIJEEDvT__FFFFT_vT_v",
105+
"Z1JIJ1_T_EE3o00EUlT_E0",
106+
"___Z2i_D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D",
107+
"ZcvSdIZcvSdIZcvSdIZcvSdIZcvSdIZcvSdIDv_ZcvSdIZcvSdIZcvSdIZcvSdIZcvSdIZcvSdIDv_ZcvSdIZcvSdIZcvSdIZcvSdIZcvSdIZcvSdIDv_Dv_Dv_Dv_Dv_dZcvSdIZcvSdIZcvSdIZcvSdIZcvSdIZcvSdIDv_ZcvSdIZcvSdIZcvSdIZcvSdIZcvSdIZcvSdIDv_ZcvSdIZcvSdIZcvSdIZcvSdIZcvSdIZcvSdIDv_Dv_Dv_Dv_Dv_d",
108+
"Z1 Z1 IJEEAcvZcvT_EcvT_T_",
109+
"T_IZaaIJEEAnaaaT_T__",
110+
"PT_IJPNT_IJEET_T_T_T_)J)JKE",
111+
"1 IJEVNT_T_T_EE",
112+
"AT__ZSiIJEEAnwscT_T__",
113+
"FSiIJEENT_IoE ",
114+
"ZTVSiIZTVSiIZTVSiIZTVSiINIJEET_T_T_T_T_ ",
115+
"Ana_T_E_T_IJEffffffffffffffersfffffrsrsffffffbgE",
116+
117+
"_ZN3TPLS_E",
118+
"_ZN3CLSIiEIiEE",
119+
"_ZN3CLSDtLi0EEE",
120+
"_ZN3CLSIiEEvNS_T_Ev",
121+
122+
"_ZN1fIiEEvNTUt_E",
123+
"_ZNDTUt_Ev",
124+
125+
"_Z1fIXfLpt1x1yEEvv",
126+
"_Z1fIXfLdt1x1yEEvv",
127+
128+
"_ZN1fIXawLi0EEEEvv",
129+
130+
"_ZNWUt_3FOOEv",
131+
"_ZWDC3FOOEv",
132+
"_ZGI3Foo",
133+
"_ZGIW3Foov",
134+
"W1x",
135+
// clang-format on
136+
};
137+
138+
const unsigned NI = sizeof(invalid_cases) / sizeof(invalid_cases[0]);
139+
24140
void test() {
25141
std::size_t len = 0;
26142
char *buf = nullptr;
27143
bool failed = false;
28-
const char* mangled = "_ZN5test71XIiEC1IdEEPT_PNS_5int_cIXplL_ZNS_4metaIiE5valueEEsrNS6_IS3_EE5valueEE4typeE";
29-
const char* expected =
30-
"test7::X<int>::X<double>(double*, test7::int_c<test7::meta<int>::value + test7::meta<double>::value>::type*)";
31-
32-
int status;
33-
char* demang = __cxxabiv1::__cxa_demangle(mangled, buf, &len, &status);
34-
if (!demang || std::strcmp(demang, expected) != 0 || status != 0) {
35-
std::fprintf(stderr,
36-
"ERROR demangling %s\n"
37-
"expected: %s\n"
38-
"got: %d, %s\n",
39-
mangled, expected, status, demang ? demang : "(null)");
40-
failed = true;
144+
for (unsigned i = 0; i < N; ++i) {
145+
int status;
146+
char* demang = __cxxabiv1::__cxa_demangle(cases[i][0], buf, &len, &status);
147+
if (!demang || std::strcmp(demang, cases[i][1]) != 0) {
148+
std::fprintf(stderr,
149+
"ERROR demangling %s\n"
150+
"expected: %s\n"
151+
"got: %d, %s\n",
152+
cases[i][0], cases[i][1], status, demang ? demang : "(null)");
153+
failed = true;
154+
}
155+
if (demang)
156+
buf = demang;
41157
}
42-
if (demang)
43-
buf = demang;
44-
45158
free(buf);
46159
assert(!failed && "demangle failed");
47160
}
@@ -50,48 +163,114 @@ void test_invalid_cases() {
50163
std::size_t len = 0;
51164
char *buf = nullptr;
52165
bool passed = false;
53-
const char* invalid =
54-
"Aon_PmKVPDk7?fg4XP5smMUL6;<WsI_mgbf23cCgsHbT<l8EE\0uVRkNOoXDrgdA4[8IU>Vl<>IL8ayHpiVDDDXTY;^o9;i";
55-
56-
int status;
57-
char* demang = __cxxabiv1::__cxa_demangle(invalid, buf, &len, &status);
58-
if (status != -2) {
59-
std::printf("%s should be invalid but is not\n", invalid);
60-
std::printf("Got: %d, %s\n", status, demang ? demang : "(null)");
61-
passed = true;
166+
for (unsigned i = 0; i < NI; ++i) {
167+
int status;
168+
char* demang = __cxxabiv1::__cxa_demangle(invalid_cases[i], buf, &len, &status);
169+
if (status != -2) {
170+
std::printf("%s should be invalid but is not\n", invalid_cases[i]);
171+
std::printf("Got: %d, %s\n", status, demang ? demang : "(null)");
172+
passed = true;
173+
}
174+
if (demang)
175+
buf = demang;
62176
}
63-
if (demang)
64-
buf = demang;
65-
66177
free(buf);
67178
assert(!passed && "demangle did not fail");
68179
}
69180

70-
void test_invalid_args() {
71-
std::size_t len = 16;
72-
char buf[16];
73-
{
74-
// NULL mangled name should fail.
181+
const char* const xfail_cases[] = {
182+
// Sentinel value
183+
nullptr,
184+
};
185+
186+
void test_xfail_cases() {
187+
std::size_t len = 0;
188+
char* buf = nullptr;
189+
for (const char* c_str : xfail_cases) {
190+
if (!c_str)
191+
break;
75192
int status;
76-
char* demang = __cxxabiv1::__cxa_demangle(nullptr, buf, &len, &status);
77-
assert(status == -3);
78-
assert(!demang);
193+
char* demang = __cxxabiv1::__cxa_demangle(c_str, buf, &len, &status);
194+
if (status != -2) {
195+
std::printf("%s was documented as xfail but passed\n", c_str);
196+
std::printf("Got status = %d\n", status);
197+
assert(status == -2);
198+
} else {
199+
buf = demang;
200+
}
79201
}
202+
free(buf);
203+
}
80204

81-
{
82-
// Buffer without specifying length should fail.
205+
void testFPLiterals() {
206+
std::size_t len = 0;
207+
char* buf = nullptr;
208+
for (unsigned i = 0; i < NF; ++i) {
209+
FPLiteralCase* fpCase = fp_literal_cases + i;
83210
int status;
84-
char* demang = __cxxabiv1::__cxa_demangle("_Z1fv", buf, nullptr, &status);
85-
assert(status == -3);
86-
assert(!demang);
211+
char* demang = __cxxabiv1::__cxa_demangle(fpCase->mangled, buf, &len, &status);
212+
if (demang == 0) {
213+
std::printf("%s -> %s\n", fpCase->mangled, fpCase->expecting[0].c_str());
214+
std::printf("Got instead: NULL, %d\n", status);
215+
assert(false);
216+
continue;
217+
}
218+
std::string* e_beg = fpCase->expecting;
219+
std::string* e_end = fpCase->expecting + NEF;
220+
if (std::find(e_beg, e_end, demang) == e_end) {
221+
std::printf("%s -> %s\n", fpCase->mangled, fpCase->expecting[0].c_str());
222+
std::printf("Got instead: %s\n", demang);
223+
assert(false);
224+
continue;
225+
}
226+
buf = demang;
87227
}
228+
free(buf);
88229
}
89230

90231
int main(int, char**) {
91-
timer t;
92-
test();
93-
test_invalid_cases();
94-
test_invalid_args();
232+
std::printf("Testing %d symbols.\n", N);
233+
{
234+
timer t;
235+
test();
236+
test_invalid_cases();
237+
test_xfail_cases();
238+
testFPLiterals();
239+
}
240+
#if 0
241+
std::string input;
242+
while (std::cin)
243+
{
244+
std::getline(std::cin, input);
245+
if (std::cin.fail())
246+
break;
247+
std::size_t len = 0;
248+
int status;
249+
len = 0;
250+
char* demang = abi::__cxa_demangle(input.c_str(), 0, &len, &status);
251+
switch (status)
252+
{
253+
case -3:
254+
std::cout << "Invalid arguments\n";
255+
break;
256+
case -2:
257+
std::cout << "Invalid mangled name\n";
258+
break;
259+
case -1:
260+
std::cout << "memory allocation failure\n";
261+
break;
262+
case 0:
263+
std::cout << "len = " << len << '\n';
264+
std::cout << demang << '\n';
265+
std::free(demang);
266+
break;
267+
case 1:
268+
std::cout << "not implemented\n";
269+
break;
270+
}
271+
std::cout << '\n';
272+
}
273+
#endif
95274

96275
return 0;
97276
}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
Itanium Name Demangler Library
2+
==============================
3+
4+
Introduction
5+
------------
6+
7+
This directory contains the generic itanium name demangler
8+
library. The main purpose of the library is to demangle C++ symbols,
9+
i.e. convert the string "_Z1fv" into "f()". You can also use the CRTP
10+
base ManglingParser to perform some simple analysis on the mangled
11+
name, or (in LLVM) use the opaque ItaniumPartialDemangler to query the
12+
demangled AST.
13+
14+
Why are there multiple copies of the this library in the source tree?
15+
---------------------------------------------------------------------
16+
17+
The canonical sources are in libcxxabi/src/demangle and some of the
18+
files are copied to llvm/include/llvm/Demangle. The simple reason for
19+
this comes from before the monorepo, and both [sub]projects need to
20+
demangle symbols, but neither can depend on each other.
21+
22+
* libcxxabi needs the demangler to implement __cxa_demangle, which is
23+
part of the itanium ABI spec.
24+
25+
* LLVM needs a copy for a bunch of places, and cannot rely on the
26+
system's __cxa_demangle because it a) might not be available (i.e.,
27+
on Windows), and b) may not be up-to-date on the latest language
28+
features.
29+
30+
The copy of the demangler in LLVM has some extra stuff that aren't
31+
needed in libcxxabi (ie, the MSVC demangler, ItaniumPartialDemangler),
32+
which depend on the shared generic components. Despite these
33+
differences, we want to keep the "core" generic demangling library
34+
identical between both copies to simplify development and testing.
35+
36+
If you're working on the generic library, then do the work first in
37+
libcxxabi, then run libcxxabi/src/demangle/cp-to-llvm.sh. This
38+
script takes as an optional argument the path to llvm, and copies the
39+
changes you made to libcxxabi over. Note that this script just
40+
blindly overwrites all changes to the generic library in llvm, so be
41+
careful.
42+
43+
Because the core demangler needs to work in libcxxabi, everything
44+
needs to be declared in an anonymous namespace (see
45+
DEMANGLE_NAMESPACE_BEGIN), and you can't introduce any code that
46+
depends on the libcxx dylib.
47+
48+
FIXME: Now that LLVM is a monorepo, it should be possible to
49+
de-duplicate this code, and have both LLVM and libcxxabi depend on a
50+
shared demangler library.
51+
52+
Testing
53+
-------
54+
55+
The tests are split up between libcxxabi/test/{unit,}test_demangle.cpp, and
56+
llvm/unittests/Demangle. The llvm directory should only get tests for stuff not
57+
included in the core library. In the future though, we should probably move all
58+
the tests to LLVM.
59+
60+
It is also a really good idea to run libFuzzer after non-trivial changes, see
61+
libcxxabi/fuzz/cxa_demangle_fuzzer.cpp and https://llvm.org/docs/LibFuzzer.html.

‎llvm/unittests/Demangle/ItaniumDemangleTest.cpp

Lines changed: 0 additions & 183 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
//===----------------------------------------------------------------------===//
88

99
#include "llvm/Demangle/ItaniumDemangle.h"
10-
#include "llvm/ADT/STLExtras.h"
1110
#include "llvm/Support/Allocator.h"
1211
#include "gmock/gmock.h"
1312
#include "gtest/gtest.h"
@@ -115,185 +114,3 @@ TEST(ItaniumDemangle, HalfType) {
115114
ASSERT_NE(nullptr, Parser.parse());
116115
EXPECT_THAT(Parser.Types, testing::ElementsAre("_Float16", "A", "_Float16"));
117116
}
118-
119-
struct DemangleTestCase {
120-
const char *mangled;
121-
const char *expected;
122-
};
123-
124-
struct DemangleTestFixture : public ::testing::TestWithParam<DemangleTestCase> {
125-
};
126-
127-
DemangleTestCase g_demangle_test_cases[] = {
128-
#include "llvm/Testing/Demangle/DemangleTestCases.inc"
129-
};
130-
131-
TEST_P(DemangleTestFixture, Demangle_Valid) {
132-
auto [mangled, expected] = GetParam();
133-
134-
llvm::itanium_demangle::ManglingParser<TestAllocator> Parser(
135-
mangled, mangled + ::strlen(mangled));
136-
137-
const auto *Root = Parser.parse();
138-
139-
ASSERT_NE(nullptr, Root);
140-
141-
OutputBuffer OB;
142-
Root->print(OB);
143-
auto demangled = std::string_view(OB);
144-
145-
EXPECT_EQ(demangled, std::string_view(expected));
146-
std::free(OB.getBuffer());
147-
}
148-
149-
INSTANTIATE_TEST_SUITE_P(DemangleValidTests, DemangleTestFixture,
150-
::testing::ValuesIn(g_demangle_test_cases));
151-
152-
// Is long double fp80? (Only x87 extended double has 64-bit mantissa)
153-
#define LDBL_FP80 (__LDBL_MANT_DIG__ == 64)
154-
// Is long double fp128?
155-
#define LDBL_FP128 (__LDBL_MANT_DIG__ == 113)
156-
157-
struct DemangleInvalidTestFixture
158-
: public ::testing::TestWithParam<const char *> {};
159-
160-
const char *g_demangle_invalid_test_cases[] = {
161-
// clang-format off
162-
"_ZIPPreEncode",
163-
"Agentt",
164-
"NSoERj5E=Y1[uM:ga",
165-
"Aon_PmKVPDk7?fg4XP5smMUL6;<WsI_mgbf23cCgsHbT<l8EE\0uVRkNOoXDrgdA4[8IU>Vl<>IL8ayHpiVDDDXTY;^o9;i",
166-
"_ZNSt16allocator_traitsISaIN4llvm3sys2fs18directory_iteratorEEE9constructIS3_IS3_EEEDTcl12_S_constructfp_fp0_spcl7forwardIT0_Efp1_EEERS4_PT_DpOS7_",
167-
"3FooILdaaaaaaaaaaAAAAaaEE",
168-
"3FooILdaaaaaaaaaaaaaaEE",
169-
#if !LDBL_FP80
170-
"_ZN5test01hIfEEvRAcvjplstT_Le4001a000000000000000E_c",
171-
#endif
172-
// The following test cases were found by libFuzzer+ASAN
173-
"\x44\x74\x70\x74\x71\x75\x34\x43\x41\x72\x4D\x6E\x65\x34\x9F\xC1\x43\x41\x72\x4D\x6E\x77\x38\x9A\x8E\x44\x6F\x64\x6C\x53\xF9\x5F\x70\x74\x70\x69\x45\x34\xD3\x73\x9E\x2A\x37",
174-
"\x4D\x41\x72\x63\x4E\x39\x44\x76\x72\x4D\x34\x44\x53\x4B\x6F\x44\x54\x6E\x61\x37\x47\x77\x78\x38\x43\x27\x41\x5F\x73\x70\x69\x45*",
175-
"\x41\x64\x6E\x32*",
176-
"\x43\x46\x41\x67\x73*",
177-
"\x72\x3A\x4E\x53\x64\x45\x39\x4F\x52\x4E\x1F\x43\x34\x64\x54\x5F\x49\x31\x41\x63\x6C\x37\x2A\x4D\x41\x67\x73\x76\x43\x54\x35\x5F\x49\x4B\x4C\x55\x6C\x73\x4C\x38\x64\x43\x41\x47\x4C\x5A\x28\x4F\x41\x6E\x77\x5F\x53\x6F\x70\x69\x45\x5F\x63\x47\x61\x4C\x31\x4F\x4C\x33\x3E\x41\x4C\x4B\x4C\x55\x6C\x73\x4C\x38\x64\x43\x66\x41\x47\x4C\x5A\x28\x4F\x41\x6E\x77\x5F\x53\x6F\x70\x69\x45\x5F\x37\x41*",
178-
"\x2D\x5F\x63\x47\x4F\x63\xD3",
179-
"\x44\x74\x70\x74\x71\x75\x32\x43\x41\x38\x65\x6E\x9B\x72\x4D\xC1\x43\x41\x72\x4D\x6E\x77\x38\x9A\x8E\x44\x6F\x64\xC3\x53\xF9\x5F\x70\x74\x70\x69\x45\x38\xD3\x73\x9E\x2A\x37",
180-
"\x4C\x5A\x4C\x55\x6C\x4D\x41\x5F\x41\x67\x74\x71\x75\x34\x4D\x41\x64\x73\x4C\x44\x76\x72\x4D\x34\x44\x4B\x44\x54\x6E\x61\x37\x47\x77\x78\x38\x43\x27\x41\x5F\x73\x70\x69\x45\x6D\x73\x72\x53\x41\x6F\x41\x7B",
181-
"\x44\x74\x70\x74\x71\x75\x32\x43\x41\x38\x65\x6E\x9B\x72\x4D\xC1\x43\x41\x72\x4D\x6E\x77\x38\x9A\x8E\x44\x6F\x64\x2C\x53\xF9\x5F\x70\x74\x70\x69\x45\xB4\xD3\x73\x9F\x2A\x37",
182-
"\x4C\x5A\x4C\x55\x6C\x69\x4D\x73\x72\x53\x6F\x7A\x41\x5F\x41\x67\x74\x71\x75\x32\x4D\x41\x64\x73\x39\x28\x76\x72\x4D\x34\x44\x4B\x45\x54\x6E\x61\x37\x47\x77\x78\x38\x43\x27\x41\x5F\x73\x70\x69\x45\x6F\x45\x49\x6D\x1A\x4C\x53\x38\x6A\x7A\x5A",
183-
"\x44\x74\x63*",
184-
"\x44\x74\x71\x75\x35\x2A\xDF\x74\x44\x61\x73\x63\x35\x2A\x3B\x41\x72\x4D\x6E\x65\x34\x9F\xC1\x63\x41\x72\x4D\x6E\x77\x38\x9A\x8E\x44\x6F\x64\x6C\x53\xF9\x5F\x70\x74\x70\x69\x45\x33\x44\x76\x35",
185-
"\x44\x74\x70\x74\x71\x75\x32\x43\x41\x38\x65\x6E\x9B\x72\x4D\xC1\x43\x41\x72\x4D\x6E\x77\x38\x9A\x8E\x44\x6F\x64\x6C\x53\xF9\x5F\x70\x74\x70\x69\x45\x38\xD3\x73\x9E\x2A\x37",
186-
"\x46\x44\x74\x70\x74\x71\x75\x32\x43\x41\x72\x4D\x6E\x65\x34\x9F\xC1\x43\x41\x72\x4D\x6E\x77\x38\x9A\x8E\x44\x6F\x64\x6C\x53\xF9\x5F\x70\x74\x70\x69\x45\x34\xD3\x73\x9E\x2A\x37\x72\x33\x8E\x3A\x29\x8E\x44\x35",
187-
"_ZcvCiIJEEDvT__FFFFT_vT_v",
188-
"Z1JIJ1_T_EE3o00EUlT_E0",
189-
"___Z2i_D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D",
190-
"ZcvSdIZcvSdIZcvSdIZcvSdIZcvSdIZcvSdIDv_ZcvSdIZcvSdIZcvSdIZcvSdIZcvSdIZcvSdIDv_ZcvSdIZcvSdIZcvSdIZcvSdIZcvSdIZcvSdIDv_Dv_Dv_Dv_Dv_dZcvSdIZcvSdIZcvSdIZcvSdIZcvSdIZcvSdIDv_ZcvSdIZcvSdIZcvSdIZcvSdIZcvSdIZcvSdIDv_ZcvSdIZcvSdIZcvSdIZcvSdIZcvSdIZcvSdIDv_Dv_Dv_Dv_Dv_d",
191-
"Z1 Z1 IJEEAcvZcvT_EcvT_T_",
192-
"T_IZaaIJEEAnaaaT_T__",
193-
"PT_IJPNT_IJEET_T_T_T_)J)JKE",
194-
"1 IJEVNT_T_T_EE",
195-
"AT__ZSiIJEEAnwscT_T__",
196-
"FSiIJEENT_IoE ",
197-
"ZTVSiIZTVSiIZTVSiIZTVSiINIJEET_T_T_T_T_ ",
198-
"Ana_T_E_T_IJEffffffffffffffersfffffrsrsffffffbgE",
199-
200-
"_ZN3TPLS_E",
201-
"_ZN3CLSIiEIiEE",
202-
"_ZN3CLSDtLi0EEE",
203-
"_ZN3CLSIiEEvNS_T_Ev",
204-
205-
"_ZN1fIiEEvNTUt_E",
206-
"_ZNDTUt_Ev",
207-
208-
"_Z1fIXfLpt1x1yEEvv",
209-
"_Z1fIXfLdt1x1yEEvv",
210-
211-
"_ZN1fIXawLi0EEEEvv",
212-
213-
"_ZNWUt_3FOOEv",
214-
"_ZWDC3FOOEv",
215-
"_ZGI3Foo",
216-
"_ZGIW3Foov",
217-
"W1x",
218-
// clang-format on
219-
};
220-
221-
TEST_P(DemangleInvalidTestFixture, Demangle_Invalid) {
222-
const char *mangled = GetParam();
223-
224-
llvm::itanium_demangle::ManglingParser<TestAllocator> Parser(
225-
mangled, mangled + ::strlen(mangled));
226-
227-
const auto *Root = Parser.parse();
228-
229-
EXPECT_EQ(nullptr, Root) << "Unexpectedly succeeded demangling: " << mangled;
230-
}
231-
232-
INSTANTIATE_TEST_SUITE_P(DemangleInvalidTests, DemangleInvalidTestFixture,
233-
::testing::ValuesIn(g_demangle_invalid_test_cases));
234-
235-
struct FPLiteralCase {
236-
const char *mangled;
237-
// There are multiple possible demanglings of a given float.
238-
std::string expecting[5];
239-
};
240-
241-
struct DemangleFPLiteralTestFixture
242-
: public ::testing::TestWithParam<FPLiteralCase> {};
243-
244-
FPLiteralCase g_fp_literal_cases[] = {
245-
// clang-format off
246-
{"_ZN5test01gIfEEvRAszplcvT__ELf40a00000E_c",
247-
{
248-
"void test0::g<float>(char (&) [sizeof ((float)() + 0x1.4000000000000p+2f)])",
249-
"void test0::g<float>(char (&) [sizeof ((float)() + 0x1.4p+2f)])",
250-
"void test0::g<float>(char (&) [sizeof ((float)() + 0x2.8p+1f)])",
251-
"void test0::g<float>(char (&) [sizeof ((float)() + 0x5p+0f)])",
252-
"void test0::g<float>(char (&) [sizeof ((float)() + 0xap-1f)])",
253-
}},
254-
{"_ZN5test01hIfEEvRAszplcvT__ELd4014000000000000E_c",
255-
{
256-
"void test0::h<float>(char (&) [sizeof ((float)() + 0x1.4000000000000p+2)])",
257-
"void test0::h<float>(char (&) [sizeof ((float)() + 0x1.4p+2)])",
258-
"void test0::h<float>(char (&) [sizeof ((float)() + 0x2.8p+1)])",
259-
"void test0::h<float>(char (&) [sizeof ((float)() + 0x5p+0)])",
260-
"void test0::h<float>(char (&) [sizeof ((float)() + 0xap-1)])",
261-
}},
262-
#if LDBL_FP80
263-
{"_ZN5test01hIfEEvRAcvjplstT_Le4001a000000000000000E_c",
264-
{
265-
"void test0::h<float>(char (&) [(unsigned int)(sizeof (float) + 0x1.4000000000000p+2L)])",
266-
"void test0::h<float>(char (&) [(unsigned int)(sizeof (float) + 0x1.4p+2L)])",
267-
"void test0::h<float>(char (&) [(unsigned int)(sizeof (float) + 0x2.8p+1L)])",
268-
"void test0::h<float>(char (&) [(unsigned int)(sizeof (float) + 0x5p+0L)])",
269-
"void test0::h<float>(char (&) [(unsigned int)(sizeof (float) + 0xap-1L)])",
270-
}},
271-
#endif
272-
#if LDBL_FP128
273-
// A 32-character FP literal of long double type
274-
{"3FooILeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeEE",
275-
{"Foo<-0x1.eeeeeeeeeeeeeeeeeeeeeeeeeeeep+12015L>"}},
276-
#endif
277-
// clang-format on
278-
};
279-
280-
TEST_P(DemangleFPLiteralTestFixture, Demangle_FPLiteral) {
281-
auto [mangled, expected] = GetParam();
282-
283-
llvm::itanium_demangle::ManglingParser<TestAllocator> Parser(
284-
mangled, mangled + ::strlen(mangled));
285-
286-
const auto *Root = Parser.parse();
287-
288-
ASSERT_NE(nullptr, Root);
289-
290-
OutputBuffer OB;
291-
Root->print(OB);
292-
auto demangled = std::string_view(OB);
293-
294-
EXPECT_THAT(expected, testing::Contains(demangled));
295-
std::free(OB.getBuffer());
296-
}
297-
298-
INSTANTIATE_TEST_SUITE_P(DemangleFPLiteralTests, DemangleFPLiteralTestFixture,
299-
::testing::ValuesIn(g_fp_literal_cases));

0 commit comments

Comments
 (0)
Please sign in to comment.