1 //===----------------------- PartialDemangleTest.cpp ----------------------===// 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 #include <cstdlib> 10 #include "llvm/Demangle/Demangle.h" 11 #include "gtest/gtest.h" 12 13 struct ChoppedName { 14 const char *Mangled; 15 const char *ContextName, *BaseName, *ReturnType, *Params; 16 }; 17 18 static ChoppedName NamesToTest[] = { 19 {"_Z1fv", "", "f", "", "()"}, 20 {"_ZN1a1b1cIiiiEEvm", "a::b", "c", "void", "(unsigned long)"}, 21 {"_ZZ5OuterIiEivEN5Inner12inner_memberEv", "int Outer<int>()::Inner", 22 "inner_member", "", "()"}, 23 {"_Z1fIiEPFvvEv", "", "f", "void (*)()", "()"}, 24 {"_ZN1S1fIiEEvv", "S", "f", "void", "()"}, 25 26 // Call operator for a lambda in f(). 27 {"_ZZ1fvENK3$_0clEi", "f()::$_0", "operator()", "", "(int)"}, 28 29 // A call operator for a lambda in a lambda in f(). 30 {"_ZZZ1fvENK3$_0clEvENKUlvE_clEv", 31 "f()::$_0::operator()() const::'lambda'()", "operator()", "", "()"}, 32 33 {"_ZZN1S1fEiiEd0_NKUlvE_clEv", "S::f(int, int)::'lambda'()", "operator()", 34 "", "()"}, 35 36 {"_ZN1Scv7MuncherIJDpPT_EEIJFivEA_iEEEv", "S", 37 "operator Muncher<int (*)(), int (*) []>", "", "()"}, 38 39 // Attributes. 40 {"_ZN5test4IdE1fEUa9enable_ifIXeqfL0p_Li1EEXeqfL0p0_Li2EEEi", 41 "test4<double>", "f", "", "(int)"}, 42 {"_ZN1SC2B8ctor_tagEv", "S", "S", "", "()"}, 43 {"_ZN1S1fB4MERPIiEEvv", "S", "f", "void", "()"}, 44 45 {"_ZNSsC1EmcRKSaIcE", 46 "std::basic_string<char, std::char_traits<char>, std::allocator<char>>", 47 "basic_string", "", "(unsigned long, char, std::allocator<char> const&)"}, 48 {"_ZNSsixEm", "std::string", "operator[]", "", "(unsigned long)"}, 49 {"_ZSt17__throw_bad_allocv", "std", "__throw_bad_alloc", "", "()"}, 50 51 {"_ZN1AI1BEC2Ev", "A<B>", "A", "", "()"}, 52 {"_ZN1AI1BED2Ev", "A<B>", "~A", "", "()"}, 53 {"_ZN1AI1BECI24BaseEi", "A<B>", "A", "", "(int)"}, 54 {"_ZNKR1AI1BE1fIiEEiv", "A<B>", "f", "int", "()"}, 55 56 {"_ZN1SIJicfEE3mfnIJjcdEEEvicfDpT_", "S<int, char, float>", "mfn", "void", 57 "(int, char, float, unsigned int, char, double)"}, 58 59 {"_Z1fDAs", "", "f", "", "(short _Accum)"}, 60 {"_Z1fDAt", "", "f", "", "(unsigned short _Accum)"}, 61 {"_Z1fDAi", "", "f", "", "(_Accum)"}, 62 {"_Z1fDAj", "", "f", "", "(unsigned _Accum)"}, 63 {"_Z1fDAl", "", "f", "", "(long _Accum)"}, 64 {"_Z1fDAm", "", "f", "", "(unsigned long _Accum)"}, 65 {"_Z1fDRs", "", "f", "", "(short _Fract)"}, 66 {"_Z1fDRt", "", "f", "", "(unsigned short _Fract)"}, 67 {"_Z1fDRi", "", "f", "", "(_Fract)"}, 68 {"_Z1fDRj", "", "f", "", "(unsigned _Fract)"}, 69 {"_Z1fDRl", "", "f", "", "(long _Fract)"}, 70 {"_Z1fDRm", "", "f", "", "(unsigned long _Fract)"}, 71 {"_Z1fDSDAs", "", "f", "", "(_Sat short _Accum)"}, 72 {"_Z1fDSDAt", "", "f", "", "(_Sat unsigned short _Accum)"}, 73 {"_Z1fDSDAi", "", "f", "", "(_Sat _Accum)"}, 74 {"_Z1fDSDAj", "", "f", "", "(_Sat unsigned _Accum)"}, 75 {"_Z1fDSDAl", "", "f", "", "(_Sat long _Accum)"}, 76 {"_Z1fDSDAm", "", "f", "", "(_Sat unsigned long _Accum)"}, 77 {"_Z1fDSDRs", "", "f", "", "(_Sat short _Fract)"}, 78 {"_Z1fDSDRt", "", "f", "", "(_Sat unsigned short _Fract)"}, 79 {"_Z1fDSDRi", "", "f", "", "(_Sat _Fract)"}, 80 {"_Z1fDSDRj", "", "f", "", "(_Sat unsigned _Fract)"}, 81 {"_Z1fDSDRl", "", "f", "", "(_Sat long _Fract)"}, 82 {"_Z1fDSDRm", "", "f", "", "(_Sat unsigned long _Fract)"}, 83 }; 84 85 TEST(PartialDemanglerTest, TestNameChopping) { 86 size_t Size = 1; 87 char *Buf = static_cast<char *>(std::malloc(Size)); 88 89 llvm::ItaniumPartialDemangler D; 90 91 for (ChoppedName &N : NamesToTest) { 92 EXPECT_FALSE(D.partialDemangle(N.Mangled)); 93 EXPECT_TRUE(D.isFunction()); 94 EXPECT_FALSE(D.isData()); 95 EXPECT_FALSE(D.isSpecialName()); 96 97 Buf = D.getFunctionDeclContextName(Buf, &Size); 98 EXPECT_STREQ(Buf, N.ContextName); 99 100 Buf = D.getFunctionBaseName(Buf, &Size); 101 EXPECT_STREQ(Buf, N.BaseName); 102 103 Buf = D.getFunctionReturnType(Buf, &Size); 104 EXPECT_STREQ(Buf, N.ReturnType); 105 106 Buf = D.getFunctionParameters(Buf, &Size); 107 EXPECT_STREQ(Buf, N.Params); 108 } 109 110 std::free(Buf); 111 } 112 113 TEST(PartialDemanglerTest, TestNameMeta) { 114 llvm::ItaniumPartialDemangler Demangler; 115 116 EXPECT_FALSE(Demangler.partialDemangle("_ZNK1f1gEv")); 117 EXPECT_TRUE(Demangler.isFunction()); 118 EXPECT_TRUE(Demangler.hasFunctionQualifiers()); 119 EXPECT_FALSE(Demangler.isSpecialName()); 120 EXPECT_FALSE(Demangler.isData()); 121 122 EXPECT_FALSE(Demangler.partialDemangle("_Z1fv")); 123 EXPECT_FALSE(Demangler.hasFunctionQualifiers()); 124 125 EXPECT_FALSE(Demangler.partialDemangle("_ZTV1S")); 126 EXPECT_TRUE(Demangler.isSpecialName()); 127 EXPECT_FALSE(Demangler.isData()); 128 EXPECT_FALSE(Demangler.isFunction()); 129 130 EXPECT_FALSE(Demangler.partialDemangle("_ZN1aDC1a1b1cEE")); 131 EXPECT_FALSE(Demangler.isFunction()); 132 EXPECT_FALSE(Demangler.isSpecialName()); 133 EXPECT_TRUE(Demangler.isData()); 134 } 135 136 TEST(PartialDemanglerTest, TestCtorOrDtor) { 137 static const char *Pos[] = { 138 "_ZN1AC1Ev", // A::A() 139 "_ZN1AC1IiEET_", // A::A<int>(int) 140 "_ZN1AD2Ev", // A::~A() 141 "_ZN1BIiEC1IcEET_", // B<int>::B<char>(char) 142 "_ZN1AC1B1TEv", // A::A[abi:T]() 143 "_ZNSt1AD2Ev", // std::A::~A() 144 "_ZN2ns1AD1Ev", // ns::A::~A() 145 }; 146 static const char *Neg[] = { 147 "_Z1fv", 148 "_ZN1A1gIiEEvT_", // void A::g<int>(int) 149 }; 150 151 llvm::ItaniumPartialDemangler D; 152 for (const char *N : Pos) { 153 EXPECT_FALSE(D.partialDemangle(N)); 154 EXPECT_TRUE(D.isCtorOrDtor()); 155 } 156 for (const char *N : Neg) { 157 EXPECT_FALSE(D.partialDemangle(N)); 158 EXPECT_FALSE(D.isCtorOrDtor()); 159 } 160 } 161 162 TEST(PartialDemanglerTest, TestMisc) { 163 llvm::ItaniumPartialDemangler D1, D2; 164 165 EXPECT_FALSE(D1.partialDemangle("_Z1fv")); 166 EXPECT_FALSE(D2.partialDemangle("_Z1g")); 167 std::swap(D1, D2); 168 EXPECT_FALSE(D1.isFunction()); 169 EXPECT_TRUE(D2.isFunction()); 170 171 EXPECT_TRUE(D1.partialDemangle("Not a mangled name!")); 172 } 173 174 TEST(PartialDemanglerTest, TestPrintCases) { 175 llvm::ItaniumPartialDemangler D; 176 177 const size_t OriginalSize = 4; 178 char *Buf = static_cast<char *>(std::malloc(OriginalSize)); 179 const char *OriginalBuf = Buf; 180 181 // Default success case: Result fits into the given buffer. 182 // Res points to Buf. N returns string size including null termination. 183 { 184 EXPECT_FALSE(D.partialDemangle("_ZN1a1bEv")); 185 186 size_t N = OriginalSize; 187 char *Res = D.getFunctionDeclContextName(Buf, &N); 188 EXPECT_STREQ("a", Res); 189 EXPECT_EQ(OriginalBuf, Res); 190 EXPECT_EQ(strlen(Res) + 1, N); 191 } 192 193 // Realloc success case: Result does not fit into the given buffer. 194 // Res points to the new or extended buffer. N returns string size 195 // including null termination. Buf was extended or freed. 196 { 197 EXPECT_FALSE(D.partialDemangle("_ZN1a1b1cIiiiEEvm")); 198 199 size_t N = OriginalSize; 200 char *Res = D.finishDemangle(Buf, &N); 201 EXPECT_STREQ("void a::b::c<int, int, int>(unsigned long)", Res); 202 EXPECT_EQ(strlen(Res) + 1, N); 203 Buf = Res; 204 } 205 206 // Failure case: a::c is not a function. 207 // Res is nullptr. N remains unchanged. 208 { 209 EXPECT_FALSE(D.partialDemangle("_ZN1a1cE")); 210 211 size_t N = OriginalSize; 212 char *Res = D.getFunctionName(Buf, &N); 213 EXPECT_EQ(nullptr, Res); 214 EXPECT_EQ(OriginalSize, N); 215 } 216 217 std::free(Buf); 218 } 219