219 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8 9#include <cstdlib>10#include "llvm/Demangle/Demangle.h"11#include "gtest/gtest.h"12 13struct ChoppedName {14 const char *Mangled;15 const char *ContextName, *BaseName, *ReturnType, *Params;16};17 18static 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 85TEST(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 113TEST(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 136TEST(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 162TEST(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 174TEST(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 size195 // 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