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", 22 "int Outer<int>()::Inner", "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", 34 "S::f(int, int)::'lambda'()", "operator()", "", "()"}, 35 36 {"_ZN1Scv7MuncherIJDpPT_EEIJFivEA_iEEEv", 37 "S", "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>", 57 "mfn", "void", "(int, char, float, unsigned int, char, double)"}, 58 }; 59 60 TEST(PartialDemanglerTest, TestNameChopping) { 61 size_t Size = 1; 62 char *Buf = static_cast<char *>(std::malloc(Size)); 63 64 llvm::ItaniumPartialDemangler D; 65 66 for (ChoppedName &N : NamesToTest) { 67 EXPECT_FALSE(D.partialDemangle(N.Mangled)); 68 EXPECT_TRUE(D.isFunction()); 69 EXPECT_FALSE(D.isData()); 70 EXPECT_FALSE(D.isSpecialName()); 71 72 Buf = D.getFunctionDeclContextName(Buf, &Size); 73 EXPECT_STREQ(Buf, N.ContextName); 74 75 Buf = D.getFunctionBaseName(Buf, &Size); 76 EXPECT_STREQ(Buf, N.BaseName); 77 78 Buf = D.getFunctionReturnType(Buf, &Size); 79 EXPECT_STREQ(Buf, N.ReturnType); 80 81 Buf = D.getFunctionParameters(Buf, &Size); 82 EXPECT_STREQ(Buf, N.Params); 83 } 84 85 std::free(Buf); 86 } 87 88 TEST(PartialDemanglerTest, TestNameMeta) { 89 llvm::ItaniumPartialDemangler Demangler; 90 91 EXPECT_FALSE(Demangler.partialDemangle("_ZNK1f1gEv")); 92 EXPECT_TRUE(Demangler.isFunction()); 93 EXPECT_TRUE(Demangler.hasFunctionQualifiers()); 94 EXPECT_FALSE(Demangler.isSpecialName()); 95 EXPECT_FALSE(Demangler.isData()); 96 97 EXPECT_FALSE(Demangler.partialDemangle("_Z1fv")); 98 EXPECT_FALSE(Demangler.hasFunctionQualifiers()); 99 100 EXPECT_FALSE(Demangler.partialDemangle("_ZTV1S")); 101 EXPECT_TRUE(Demangler.isSpecialName()); 102 EXPECT_FALSE(Demangler.isData()); 103 EXPECT_FALSE(Demangler.isFunction()); 104 105 EXPECT_FALSE(Demangler.partialDemangle("_ZN1aDC1a1b1cEE")); 106 EXPECT_FALSE(Demangler.isFunction()); 107 EXPECT_FALSE(Demangler.isSpecialName()); 108 EXPECT_TRUE(Demangler.isData()); 109 } 110 111 TEST(PartialDemanglerTest, TestCtorOrDtor) { 112 static const char *Pos[] = { 113 "_ZN1AC1Ev", // A::A() 114 "_ZN1AC1IiEET_", // A::A<int>(int) 115 "_ZN1AD2Ev", // A::~A() 116 "_ZN1BIiEC1IcEET_", // B<int>::B<char>(char) 117 "_ZN1AC1B1TEv", // A::A[abi:T]() 118 "_ZNSt1AD2Ev", // std::A::~A() 119 "_ZN2ns1AD1Ev", // ns::A::~A() 120 }; 121 static const char *Neg[] = { 122 "_Z1fv", 123 "_ZN1A1gIiEEvT_", // void A::g<int>(int) 124 }; 125 126 llvm::ItaniumPartialDemangler D; 127 for (const char *N : Pos) { 128 EXPECT_FALSE(D.partialDemangle(N)); 129 EXPECT_TRUE(D.isCtorOrDtor()); 130 } 131 for (const char *N : Neg) { 132 EXPECT_FALSE(D.partialDemangle(N)); 133 EXPECT_FALSE(D.isCtorOrDtor()); 134 } 135 } 136 137 TEST(PartialDemanglerTest, TestMisc) { 138 llvm::ItaniumPartialDemangler D1, D2; 139 140 EXPECT_FALSE(D1.partialDemangle("_Z1fv")); 141 EXPECT_FALSE(D2.partialDemangle("_Z1g")); 142 std::swap(D1, D2); 143 EXPECT_FALSE(D1.isFunction()); 144 EXPECT_TRUE(D2.isFunction()); 145 146 EXPECT_TRUE(D1.partialDemangle("Not a mangled name!")); 147 } 148 149 TEST(PartialDemanglerTest, TestPrintCases) { 150 llvm::ItaniumPartialDemangler D; 151 152 const size_t OriginalSize = 4; 153 char *Buf = static_cast<char *>(std::malloc(OriginalSize)); 154 const char *OriginalBuf = Buf; 155 156 // Default success case: Result fits into the given buffer. 157 // Res points to Buf. N returns string size including null termination. 158 { 159 EXPECT_FALSE(D.partialDemangle("_ZN1a1bEv")); 160 161 size_t N = OriginalSize; 162 char *Res = D.getFunctionDeclContextName(Buf, &N); 163 EXPECT_STREQ("a", Res); 164 EXPECT_EQ(OriginalBuf, Res); 165 EXPECT_EQ(strlen(Res) + 1, N); 166 } 167 168 // Realloc success case: Result does not fit into the given buffer. 169 // Res points to the new or extended buffer. N returns string size 170 // including null termination. Buf was extended or freed. 171 { 172 EXPECT_FALSE(D.partialDemangle("_ZN1a1b1cIiiiEEvm")); 173 174 size_t N = OriginalSize; 175 char *Res = D.finishDemangle(Buf, &N); 176 EXPECT_STREQ("void a::b::c<int, int, int>(unsigned long)", Res); 177 EXPECT_EQ(strlen(Res) + 1, N); 178 Buf = Res; 179 } 180 181 // Failure case: a::c is not a function. 182 // Res is nullptr. N remains unchanged. 183 { 184 EXPECT_FALSE(D.partialDemangle("_ZN1a1cE")); 185 186 size_t N = OriginalSize; 187 char *Res = D.getFunctionName(Buf, &N); 188 EXPECT_EQ(nullptr, Res); 189 EXPECT_EQ(OriginalSize, N); 190 } 191 192 std::free(Buf); 193 } 194