
This patch turns the `libcxxabi/test/test_demangle.pass.cpp` into gtest unit-tests in `llvm/unittests/Demangle`. The main motivation for this is https://github.com/llvm/llvm-project/pull/137793, where we want to re-use the test-cases from the ItaniumDemangler to test our OutputBuffer implementation. `libcxxabi/test/test_demangle.pass.cpp` now only tests the `__cxa_demangle` API surface, not the underlying ItaniumDemangle implementation.
243 lines
9.2 KiB
C++
243 lines
9.2 KiB
C++
//===----------------------------------------------------------------------===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// This test is too big for most embedded devices.
|
|
// XFAIL: LIBCXX-PICOLIBC-FIXME
|
|
|
|
// This test exercises support for char array initializer lists added in
|
|
// dd8b266ef.
|
|
// UNSUPPORTED: using-built-library-before-llvm-20
|
|
|
|
// XFAIL: win32-broken-printf-a-precision
|
|
|
|
#include "support/timer.h"
|
|
#include <algorithm>
|
|
#include <cassert>
|
|
#include <cstdio>
|
|
#include <cstdlib>
|
|
#include <cstring>
|
|
#include <cxxabi.h>
|
|
#include <string>
|
|
|
|
// Is long double fp80? (Only x87 extended double has 64-bit mantissa)
|
|
#define LDBL_FP80 (__LDBL_MANT_DIG__ == 64)
|
|
// Is long double fp128?
|
|
#define LDBL_FP128 (__LDBL_MANT_DIG__ == 113)
|
|
|
|
const char* cases[][2] = {
|
|
#include "DemangleTestCases.inc"
|
|
};
|
|
|
|
const unsigned N = sizeof(cases) / sizeof(cases[0]);
|
|
|
|
struct FPLiteralCase {
|
|
const char* mangled;
|
|
// There are four possible demanglings of a given float.
|
|
std::string expecting[4];
|
|
} fp_literal_cases[] = {
|
|
// clang-format off
|
|
{"_ZN5test01gIfEEvRAszplcvT__ELf40a00000E_c",
|
|
{
|
|
"void test0::g<float>(char (&) [sizeof ((float)() + 0x1.4p+2f)])",
|
|
"void test0::g<float>(char (&) [sizeof ((float)() + 0x2.8p+1f)])",
|
|
"void test0::g<float>(char (&) [sizeof ((float)() + 0x5p+0f)])",
|
|
"void test0::g<float>(char (&) [sizeof ((float)() + 0xap-1f)])",
|
|
}},
|
|
{"_ZN5test01hIfEEvRAszplcvT__ELd4014000000000000E_c",
|
|
{
|
|
"void test0::h<float>(char (&) [sizeof ((float)() + 0x1.4p+2)])",
|
|
"void test0::h<float>(char (&) [sizeof ((float)() + 0x2.8p+1)])",
|
|
"void test0::h<float>(char (&) [sizeof ((float)() + 0x5p+0)])",
|
|
"void test0::h<float>(char (&) [sizeof ((float)() + 0xap-1)])",
|
|
}},
|
|
#if LDBL_FP80
|
|
{"_ZN5test01hIfEEvRAcvjplstT_Le4001a000000000000000E_c",
|
|
{
|
|
"void test0::h<float>(char (&) [(unsigned int)(sizeof (float) + 0x1.4p+2L)])",
|
|
"void test0::h<float>(char (&) [(unsigned int)(sizeof (float) + 0x2.8p+1L)])",
|
|
"void test0::h<float>(char (&) [(unsigned int)(sizeof (float) + 0x5p+0L)])",
|
|
"void test0::h<float>(char (&) [(unsigned int)(sizeof (float) + 0xap-1L)])",
|
|
}},
|
|
#endif
|
|
#if LDBL_FP128
|
|
// A 32-character FP literal of long double type
|
|
{"3FooILeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeEE",
|
|
{"Foo<-0x1.eeeeeeeeeeeeeeeeeeeeeeeeeeeep+12015L>"}},
|
|
#endif
|
|
// clang-format on
|
|
};
|
|
const unsigned NF = sizeof(fp_literal_cases) / sizeof(fp_literal_cases[0]);
|
|
const unsigned NEF = sizeof(fp_literal_cases[0].expecting) / sizeof(fp_literal_cases[0].expecting[0]);
|
|
|
|
const char* invalid_cases[] = {
|
|
// clang-format off
|
|
"_ZIPPreEncode",
|
|
"Agentt",
|
|
"NSoERj5E=Y1[uM:ga",
|
|
"Aon_PmKVPDk7?fg4XP5smMUL6;<WsI_mgbf23cCgsHbT<l8EE\0uVRkNOoXDrgdA4[8IU>Vl<>IL8ayHpiVDDDXTY;^o9;i",
|
|
"_ZNSt16allocator_traitsISaIN4llvm3sys2fs18directory_iteratorEEE9constructIS3_IS3_EEEDTcl12_S_constructfp_fp0_spcl7forwardIT0_Efp1_EEERS4_PT_DpOS7_",
|
|
"3FooILdaaaaaaaaaaAAAAaaEE",
|
|
"3FooILdaaaaaaaaaaaaaaEE",
|
|
#if !LDBL_FP80
|
|
"_ZN5test01hIfEEvRAcvjplstT_Le4001a000000000000000E_c",
|
|
#endif
|
|
// The following test cases were found by libFuzzer+ASAN
|
|
"\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",
|
|
"\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*",
|
|
"\x41\x64\x6E\x32*",
|
|
"\x43\x46\x41\x67\x73*",
|
|
"\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*",
|
|
"\x2D\x5F\x63\x47\x4F\x63\xD3",
|
|
"\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",
|
|
"\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",
|
|
"\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",
|
|
"\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",
|
|
"\x44\x74\x63*",
|
|
"\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",
|
|
"\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",
|
|
"\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",
|
|
"_ZcvCiIJEEDvT__FFFFT_vT_v",
|
|
"Z1JIJ1_T_EE3o00EUlT_E0",
|
|
"___Z2i_D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D",
|
|
"ZcvSdIZcvSdIZcvSdIZcvSdIZcvSdIZcvSdIDv_ZcvSdIZcvSdIZcvSdIZcvSdIZcvSdIZcvSdIDv_ZcvSdIZcvSdIZcvSdIZcvSdIZcvSdIZcvSdIDv_Dv_Dv_Dv_Dv_dZcvSdIZcvSdIZcvSdIZcvSdIZcvSdIZcvSdIDv_ZcvSdIZcvSdIZcvSdIZcvSdIZcvSdIZcvSdIDv_ZcvSdIZcvSdIZcvSdIZcvSdIZcvSdIZcvSdIDv_Dv_Dv_Dv_Dv_d",
|
|
"Z1 Z1 IJEEAcvZcvT_EcvT_T_",
|
|
"T_IZaaIJEEAnaaaT_T__",
|
|
"PT_IJPNT_IJEET_T_T_T_)J)JKE",
|
|
"1 IJEVNT_T_T_EE",
|
|
"AT__ZSiIJEEAnwscT_T__",
|
|
"FSiIJEENT_IoE ",
|
|
"ZTVSiIZTVSiIZTVSiIZTVSiINIJEET_T_T_T_T_ ",
|
|
"Ana_T_E_T_IJEffffffffffffffersfffffrsrsffffffbgE",
|
|
|
|
"_ZN3TPLS_E",
|
|
"_ZN3CLSIiEIiEE",
|
|
"_ZN3CLSDtLi0EEE",
|
|
"_ZN3CLSIiEEvNS_T_Ev",
|
|
|
|
"_ZN1fIiEEvNTUt_E",
|
|
"_ZNDTUt_Ev",
|
|
|
|
"_Z1fIXfLpt1x1yEEvv",
|
|
"_Z1fIXfLdt1x1yEEvv",
|
|
|
|
"_ZN1fIXawLi0EEEEvv",
|
|
|
|
"_ZNWUt_3FOOEv",
|
|
"_ZWDC3FOOEv",
|
|
"_ZGI3Foo",
|
|
"_ZGIW3Foov",
|
|
"W1x",
|
|
// clang-format on
|
|
};
|
|
|
|
const unsigned NI = sizeof(invalid_cases) / sizeof(invalid_cases[0]);
|
|
|
|
void test() {
|
|
std::size_t len = 0;
|
|
char *buf = nullptr;
|
|
bool failed = false;
|
|
for (unsigned i = 0; i < N; ++i) {
|
|
int status;
|
|
char* demang = __cxxabiv1::__cxa_demangle(cases[i][0], buf, &len, &status);
|
|
if (!demang || std::strcmp(demang, cases[i][1]) != 0) {
|
|
std::fprintf(stderr,
|
|
"ERROR demangling %s\n"
|
|
"expected: %s\n"
|
|
"got: %d, %s\n",
|
|
cases[i][0], cases[i][1], status, demang ? demang : "(null)");
|
|
failed = true;
|
|
}
|
|
if (demang)
|
|
buf = demang;
|
|
}
|
|
free(buf);
|
|
assert(!failed && "demangle failed");
|
|
}
|
|
|
|
void test_invalid_cases() {
|
|
std::size_t len = 0;
|
|
char *buf = nullptr;
|
|
bool passed = false;
|
|
for (unsigned i = 0; i < NI; ++i) {
|
|
int status;
|
|
char* demang = __cxxabiv1::__cxa_demangle(invalid_cases[i], buf, &len, &status);
|
|
if (status != -2) {
|
|
std::printf("%s should be invalid but is not\n", invalid_cases[i]);
|
|
std::printf("Got: %d, %s\n", status, demang ? demang : "(null)");
|
|
passed = true;
|
|
}
|
|
if (demang)
|
|
buf = demang;
|
|
}
|
|
free(buf);
|
|
assert(!passed && "demangle did not fail");
|
|
}
|
|
|
|
const char* const xfail_cases[] = {
|
|
// Sentinel value
|
|
nullptr,
|
|
};
|
|
|
|
void test_xfail_cases() {
|
|
std::size_t len = 0;
|
|
char* buf = nullptr;
|
|
for (const char* c_str : xfail_cases) {
|
|
if (!c_str)
|
|
break;
|
|
int status;
|
|
char* demang = __cxxabiv1::__cxa_demangle(c_str, buf, &len, &status);
|
|
if (status != -2) {
|
|
std::printf("%s was documented as xfail but passed\n", c_str);
|
|
std::printf("Got status = %d\n", status);
|
|
assert(status == -2);
|
|
} else {
|
|
buf = demang;
|
|
}
|
|
}
|
|
free(buf);
|
|
}
|
|
|
|
void testFPLiterals() {
|
|
std::size_t len = 0;
|
|
char* buf = nullptr;
|
|
for (unsigned i = 0; i < NF; ++i) {
|
|
FPLiteralCase* fpCase = fp_literal_cases + i;
|
|
int status;
|
|
char* demang = __cxxabiv1::__cxa_demangle(fpCase->mangled, buf, &len, &status);
|
|
if (demang == 0) {
|
|
std::printf("%s -> %s\n", fpCase->mangled, fpCase->expecting[0].c_str());
|
|
std::printf("Got instead: NULL, %d\n", status);
|
|
assert(false);
|
|
continue;
|
|
}
|
|
std::string* e_beg = fpCase->expecting;
|
|
std::string* e_end = fpCase->expecting + NEF;
|
|
if (std::find(e_beg, e_end, demang) == e_end) {
|
|
std::printf("%s -> %s\n", fpCase->mangled, fpCase->expecting[0].c_str());
|
|
std::printf("Got instead: %s\n", demang);
|
|
assert(false);
|
|
continue;
|
|
}
|
|
buf = demang;
|
|
}
|
|
free(buf);
|
|
}
|
|
|
|
int main(int, char**) {
|
|
std::printf("Testing %d symbols.\n", N);
|
|
{
|
|
timer t;
|
|
test();
|
|
test_invalid_cases();
|
|
test_xfail_cases();
|
|
testFPLiterals();
|
|
}
|
|
|
|
return 0;
|
|
}
|