1 | //===----------------------------------------------------------------------===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | |
9 | // This test is too big for most embedded devices. |
10 | // XFAIL: LIBCXX-PICOLIBC-FIXME |
11 | |
12 | // This test exercises support for char array initializer lists added in |
13 | // dd8b266ef. |
14 | // UNSUPPORTED: using-built-library-before-llvm-20 |
15 | |
16 | // XFAIL: win32-broken-printf-a-precision |
17 | |
18 | #include "support/timer.h" |
19 | #include <algorithm> |
20 | #include <cassert> |
21 | #include <cstdio> |
22 | #include <cstdlib> |
23 | #include <cstring> |
24 | #include <cxxabi.h> |
25 | #include <string> |
26 | |
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 | {.mangled: "_ZN5test01gIfEEvRAszplcvT__ELf40a00000E_c" , |
45 | .expecting: { |
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 | {.mangled: "_ZN5test01hIfEEvRAszplcvT__ELd4014000000000000E_c" , |
52 | .expecting: { |
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 | {.mangled: "_ZN5test01hIfEEvRAcvjplstT_Le4001a000000000000000E_c" , |
60 | .expecting: { |
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 | |
140 | void test() { |
141 | std::size_t len = 0; |
142 | char *buf = nullptr; |
143 | bool failed = false; |
144 | for (unsigned i = 0; i < N; ++i) { |
145 | int status; |
146 | char* demang = __cxxabiv1::__cxa_demangle(mangled_name: cases[i][0], output_buffer: buf, length: &len, status: &status); |
147 | if (!demang || std::strcmp(s1: demang, s2: cases[i][1]) != 0) { |
148 | std::fprintf(stderr, |
149 | format: "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; |
157 | } |
158 | free(ptr: buf); |
159 | assert(!failed && "demangle failed" ); |
160 | } |
161 | |
162 | void test_invalid_cases() { |
163 | std::size_t len = 0; |
164 | char *buf = nullptr; |
165 | bool passed = false; |
166 | for (unsigned i = 0; i < NI; ++i) { |
167 | int status; |
168 | char* demang = __cxxabiv1::__cxa_demangle(mangled_name: invalid_cases[i], output_buffer: buf, length: &len, status: &status); |
169 | if (status != -2) { |
170 | std::printf(format: "%s should be invalid but is not\n" , invalid_cases[i]); |
171 | std::printf(format: "Got: %d, %s\n" , status, demang ? demang : "(null)" ); |
172 | passed = true; |
173 | } |
174 | if (demang) |
175 | buf = demang; |
176 | } |
177 | free(ptr: buf); |
178 | assert(!passed && "demangle did not fail" ); |
179 | } |
180 | |
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; |
192 | int status; |
193 | char* demang = __cxxabiv1::__cxa_demangle(mangled_name: c_str, output_buffer: buf, length: &len, status: &status); |
194 | if (status != -2) { |
195 | std::printf(format: "%s was documented as xfail but passed\n" , c_str); |
196 | std::printf(format: "Got status = %d\n" , status); |
197 | assert(status == -2); |
198 | } else { |
199 | buf = demang; |
200 | } |
201 | } |
202 | free(ptr: buf); |
203 | } |
204 | |
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; |
210 | int status; |
211 | char* demang = __cxxabiv1::__cxa_demangle(mangled_name: fpCase->mangled, output_buffer: buf, length: &len, status: &status); |
212 | if (demang == 0) { |
213 | std::printf(format: "%s -> %s\n" , fpCase->mangled, fpCase->expecting[0].c_str()); |
214 | std::printf(format: "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(first: e_beg, last: e_end, val: demang) == e_end) { |
221 | std::printf(format: "%s -> %s\n" , fpCase->mangled, fpCase->expecting[0].c_str()); |
222 | std::printf(format: "Got instead: %s\n" , demang); |
223 | assert(false); |
224 | continue; |
225 | } |
226 | buf = demang; |
227 | } |
228 | free(ptr: buf); |
229 | } |
230 | |
231 | int main(int, char**) { |
232 | std::printf(format: "Testing %d symbols.\n" , N); |
233 | { |
234 | timer t; |
235 | test(); |
236 | test_invalid_cases(); |
237 | test_xfail_cases(); |
238 | testFPLiterals(); |
239 | } |
240 | |
241 | return 0; |
242 | } |
243 | |