Currently `OutputBuffer::GtIsGt` is used to tell us if we're inside
template arguments and have printed a '(' without a closing ')'. If so,
we don't need to quote '<' when printing it as part of a binary
expression inside a template argument. Otherwise we need to. E.g.,
```
foo<a<(b < c)>> // Quotes around binary expression needed.
```
LLDB's `TrackingOutputBuffer` has heuristics that rely on checking
whether we are inside template arguments, regardless of the current
parentheses depth. We've been using `isGtInsideTemplateArgs` for this,
but that isn't correct. Resulting in us incorrectly tracking the
basename of function like:
```
void func<(foo::Enum)1>()
```
Here `GtIsGt > 0` despite us being inside template arguments (because we
incremented it when seeing '(').
This patch adds a `isInsideTemplateArgs` API which LLDB will use to more
accurately track parts of the demangled name.
To make sure this API doesn't go untested in the actual libcxxabi
test-suite, I changed the existing `GtIsGt` logic to use it. Also
renamed the various variables/APIs involved to make it (in my opinion)
more straightforward to understand what's going on. But happy to rename
it back if people disagree.
Also adjusted LLDB to use the newly introduced API (and added a
unit-test that would previously fail).
913 lines
35 KiB
C++
913 lines
35 KiB
C++
//===-- MangledTest.cpp ---------------------------------------------------===//
|
|
//
|
|
// 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
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "Plugins/Language/CPlusPlus/CPlusPlusLanguage.h"
|
|
#include "Plugins/ObjectFile/ELF/ObjectFileELF.h"
|
|
#include "Plugins/SymbolFile/Symtab/SymbolFileSymtab.h"
|
|
#include "TestingSupport/SubsystemRAII.h"
|
|
#include "TestingSupport/TestUtilities.h"
|
|
|
|
#include "lldb/Core/DemangledNameInfo.h"
|
|
#include "lldb/Core/Mangled.h"
|
|
#include "lldb/Core/Module.h"
|
|
#include "lldb/Core/ModuleSpec.h"
|
|
#include "lldb/Host/FileSystem.h"
|
|
#include "lldb/Host/HostInfo.h"
|
|
#include "lldb/Symbol/SymbolContext.h"
|
|
|
|
#include "llvm/Support/Error.h"
|
|
#include "llvm/Support/FileUtilities.h"
|
|
#include "llvm/Support/Path.h"
|
|
#include "llvm/Support/Program.h"
|
|
#include "llvm/Testing/Support/Error.h"
|
|
|
|
#include "gtest/gtest.h"
|
|
|
|
#include <cstdlib>
|
|
#include <memory>
|
|
|
|
using namespace lldb;
|
|
using namespace lldb_private;
|
|
|
|
/// Custom deleter to use with unique_ptr.
|
|
///
|
|
/// Usage:
|
|
/// \code{.cpp}
|
|
///
|
|
/// auto OB =
|
|
/// std::unique_ptr<TrackingOutputBuffer, TrackingOutputBufferDeleter>(
|
|
/// new TrackingOutputBuffer());
|
|
///
|
|
/// \endcode
|
|
struct TrackingOutputBufferDeleter {
|
|
void operator()(TrackingOutputBuffer *TOB) {
|
|
if (!TOB)
|
|
return;
|
|
std::free(TOB->getBuffer());
|
|
delete TOB;
|
|
}
|
|
};
|
|
|
|
TEST(MangledTest, ResultForValidName) {
|
|
ConstString MangledName("_ZN1a1b1cIiiiEEvm");
|
|
Mangled TheMangled(MangledName);
|
|
ConstString TheDemangled = TheMangled.GetDemangledName();
|
|
|
|
ConstString ExpectedResult("void a::b::c<int, int, int>(unsigned long)");
|
|
EXPECT_STREQ(ExpectedResult.GetCString(), TheDemangled.GetCString());
|
|
}
|
|
|
|
TEST(MangledTest, ResultForBlockInvocation) {
|
|
ConstString MangledName("___Z1fU13block_pointerFviE_block_invoke");
|
|
Mangled TheMangled(MangledName);
|
|
ConstString TheDemangled = TheMangled.GetDemangledName();
|
|
|
|
ConstString ExpectedResult(
|
|
"invocation function for block in f(void (int) block_pointer)");
|
|
EXPECT_STREQ(ExpectedResult.GetCString(), TheDemangled.GetCString());
|
|
}
|
|
|
|
TEST(MangledTest, EmptyForInvalidName) {
|
|
ConstString MangledName("_ZN1a1b1cmxktpEEvm");
|
|
Mangled TheMangled(MangledName);
|
|
ConstString TheDemangled = TheMangled.GetDemangledName();
|
|
|
|
EXPECT_STREQ("", TheDemangled.GetCString());
|
|
}
|
|
|
|
TEST(MangledTest, ResultForValidRustV0Name) {
|
|
ConstString mangled_name("_RNvC1a4main");
|
|
Mangled the_mangled(mangled_name);
|
|
ConstString the_demangled = the_mangled.GetDemangledName();
|
|
|
|
ConstString expected_result("a::main");
|
|
EXPECT_STREQ(expected_result.GetCString(), the_demangled.GetCString());
|
|
}
|
|
|
|
TEST(MangledTest, EmptyForInvalidRustV0Name) {
|
|
ConstString mangled_name("_RRR");
|
|
Mangled the_mangled(mangled_name);
|
|
ConstString the_demangled = the_mangled.GetDemangledName();
|
|
|
|
EXPECT_STREQ("", the_demangled.GetCString());
|
|
}
|
|
|
|
TEST(MangledTest, ResultForValidDLangName) {
|
|
ConstString mangled_name("_Dmain");
|
|
Mangled the_mangled(mangled_name);
|
|
ConstString the_demangled = the_mangled.GetDemangledName();
|
|
|
|
ConstString expected_result("D main");
|
|
EXPECT_STREQ(expected_result.GetCString(), the_demangled.GetCString());
|
|
}
|
|
|
|
TEST(MangledTest, SameForInvalidDLangPrefixedName) {
|
|
ConstString mangled_name("_DDD");
|
|
Mangled the_mangled(mangled_name);
|
|
ConstString the_demangled = the_mangled.GetDemangledName();
|
|
|
|
EXPECT_STREQ("_DDD", the_demangled.GetCString());
|
|
}
|
|
|
|
TEST(MangledTest, RecognizeSwiftMangledNames) {
|
|
llvm::StringRef valid_swift_mangled_names[] = {
|
|
"_TtC4main7MyClass", // Mangled objc class name
|
|
"_TtP4main3Foo_", // Mangld objc protocol name
|
|
"$s4main3BarCACycfC", // Mangled name
|
|
"_$s4main3BarCACycfC", // Mangled name with leading underscore
|
|
"$S4main3BarCACycfC", // Older swift mangled name
|
|
"_$S4main3BarCACycfC", // Older swift mangled name
|
|
// with leading underscore
|
|
// Mangled swift filename
|
|
"@__swiftmacro_4main16FunVariableNames9OptionSetfMm_.swift",
|
|
};
|
|
|
|
for (llvm::StringRef mangled : valid_swift_mangled_names)
|
|
EXPECT_EQ(Mangled::GetManglingScheme(mangled),
|
|
Mangled::eManglingSchemeSwift);
|
|
}
|
|
|
|
TEST(MangledTest, BoolConversionOperator) {
|
|
{
|
|
ConstString MangledName("_ZN1a1b1cIiiiEEvm");
|
|
Mangled TheMangled(MangledName);
|
|
EXPECT_EQ(true, bool(TheMangled));
|
|
EXPECT_EQ(false, !TheMangled);
|
|
}
|
|
{
|
|
ConstString UnmangledName("puts");
|
|
Mangled TheMangled(UnmangledName);
|
|
EXPECT_EQ(true, bool(TheMangled));
|
|
EXPECT_EQ(false, !TheMangled);
|
|
}
|
|
{
|
|
Mangled TheMangled{};
|
|
EXPECT_EQ(false, bool(TheMangled));
|
|
EXPECT_EQ(true, !TheMangled);
|
|
}
|
|
}
|
|
|
|
TEST(MangledTest, NameIndexes_FindFunctionSymbols) {
|
|
SubsystemRAII<FileSystem, HostInfo, ObjectFileELF, SymbolFileSymtab>
|
|
subsystems;
|
|
|
|
auto ExpectedFile = TestFile::fromYaml(R"(
|
|
--- !ELF
|
|
FileHeader:
|
|
Class: ELFCLASS64
|
|
Data: ELFDATA2LSB
|
|
Type: ET_EXEC
|
|
Machine: EM_X86_64
|
|
Sections:
|
|
- Name: .text
|
|
Type: SHT_PROGBITS
|
|
Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
|
|
AddressAlign: 0x0000000000000010
|
|
Size: 0x20
|
|
- Name: .anothertext
|
|
Type: SHT_PROGBITS
|
|
Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
|
|
Address: 0x0000000000000010
|
|
AddressAlign: 0x0000000000000010
|
|
Size: 0x40
|
|
- Name: .data
|
|
Type: SHT_PROGBITS
|
|
Flags: [ SHF_WRITE, SHF_ALLOC ]
|
|
Address: 0x00000000000000A8
|
|
AddressAlign: 0x0000000000000004
|
|
Content: '01000000'
|
|
Symbols:
|
|
- Name: somedata
|
|
Type: STT_OBJECT
|
|
Section: .anothertext
|
|
Value: 0x0000000000000045
|
|
Binding: STB_GLOBAL
|
|
- Name: main
|
|
Type: STT_FUNC
|
|
Section: .anothertext
|
|
Value: 0x0000000000000010
|
|
Size: 0x000000000000003F
|
|
Binding: STB_GLOBAL
|
|
- Name: _Z3foov
|
|
Type: STT_FUNC
|
|
Section: .text
|
|
Size: 0x000000000000000D
|
|
Binding: STB_GLOBAL
|
|
- Name: puts@GLIBC_2.5
|
|
Type: STT_FUNC
|
|
Section: .text
|
|
Size: 0x000000000000000D
|
|
Binding: STB_GLOBAL
|
|
- Name: puts@GLIBC_2.6
|
|
Type: STT_FUNC
|
|
Section: .text
|
|
Size: 0x000000000000000D
|
|
Binding: STB_GLOBAL
|
|
- Name: _Z5annotv@VERSION3
|
|
Type: STT_FUNC
|
|
Section: .text
|
|
Size: 0x000000000000000D
|
|
Binding: STB_GLOBAL
|
|
- Name: _ZN1AC2Ev
|
|
Type: STT_FUNC
|
|
Section: .text
|
|
Size: 0x000000000000000D
|
|
Binding: STB_GLOBAL
|
|
- Name: _ZN1AD2Ev
|
|
Type: STT_FUNC
|
|
Section: .text
|
|
Size: 0x000000000000000D
|
|
Binding: STB_GLOBAL
|
|
- Name: _ZN1A3barEv
|
|
Type: STT_FUNC
|
|
Section: .text
|
|
Size: 0x000000000000000D
|
|
Binding: STB_GLOBAL
|
|
- Name: _ZGVZN4llvm4dbgsEvE7thestrm
|
|
Type: STT_FUNC
|
|
Section: .text
|
|
Size: 0x000000000000000D
|
|
Binding: STB_GLOBAL
|
|
- Name: _ZZN4llvm4dbgsEvE7thestrm
|
|
Type: STT_FUNC
|
|
Section: .text
|
|
Size: 0x000000000000000D
|
|
Binding: STB_GLOBAL
|
|
- Name: _ZTVN5clang4DeclE
|
|
Type: STT_FUNC
|
|
Section: .text
|
|
Size: 0x000000000000000D
|
|
Binding: STB_GLOBAL
|
|
- Name: -[ObjCfoo]
|
|
Type: STT_FUNC
|
|
Section: .text
|
|
Size: 0x000000000000000D
|
|
Binding: STB_GLOBAL
|
|
- Name: +[B ObjCbar(WithCategory)]
|
|
Type: STT_FUNC
|
|
Section: .text
|
|
Size: 0x000000000000000D
|
|
Binding: STB_GLOBAL
|
|
- Name: _Z12undemangableEvx42
|
|
Type: STT_FUNC
|
|
Section: .text
|
|
Size: 0x000000000000000D
|
|
Binding: STB_GLOBAL
|
|
...
|
|
)");
|
|
ASSERT_THAT_EXPECTED(ExpectedFile, llvm::Succeeded());
|
|
|
|
auto M = std::make_shared<Module>(ExpectedFile->moduleSpec());
|
|
|
|
auto Count = [M](const char *Name, FunctionNameType Type) -> int {
|
|
SymbolContextList SymList;
|
|
M->FindFunctionSymbols(ConstString(Name), Type, SymList);
|
|
return SymList.GetSize();
|
|
};
|
|
|
|
// Unmangled
|
|
EXPECT_EQ(1, Count("main", eFunctionNameTypeFull));
|
|
EXPECT_EQ(1, Count("main", eFunctionNameTypeBase));
|
|
EXPECT_EQ(0, Count("main", eFunctionNameTypeMethod));
|
|
|
|
// Itanium mangled
|
|
EXPECT_EQ(1, Count("_Z3foov", eFunctionNameTypeFull));
|
|
EXPECT_EQ(1, Count("_Z3foov", eFunctionNameTypeBase));
|
|
EXPECT_EQ(1, Count("foo", eFunctionNameTypeBase));
|
|
EXPECT_EQ(0, Count("foo", eFunctionNameTypeMethod));
|
|
|
|
// Unmangled with linker annotation
|
|
EXPECT_EQ(1, Count("puts@GLIBC_2.5", eFunctionNameTypeFull));
|
|
EXPECT_EQ(1, Count("puts@GLIBC_2.6", eFunctionNameTypeFull));
|
|
EXPECT_EQ(2, Count("puts", eFunctionNameTypeFull));
|
|
EXPECT_EQ(2, Count("puts", eFunctionNameTypeBase));
|
|
EXPECT_EQ(0, Count("puts", eFunctionNameTypeMethod));
|
|
|
|
// Itanium mangled with linker annotation
|
|
EXPECT_EQ(1, Count("_Z5annotv@VERSION3", eFunctionNameTypeFull));
|
|
EXPECT_EQ(1, Count("_Z5annotv", eFunctionNameTypeFull));
|
|
EXPECT_EQ(1, Count("_Z5annotv", eFunctionNameTypeBase));
|
|
EXPECT_EQ(0, Count("annot", eFunctionNameTypeBase));
|
|
EXPECT_EQ(0, Count("annot", eFunctionNameTypeMethod));
|
|
|
|
// Itanium mangled ctor A::A()
|
|
EXPECT_EQ(1, Count("_ZN1AC2Ev", eFunctionNameTypeFull));
|
|
EXPECT_EQ(1, Count("_ZN1AC2Ev", eFunctionNameTypeBase));
|
|
EXPECT_EQ(1, Count("A", eFunctionNameTypeMethod));
|
|
EXPECT_EQ(0, Count("A", eFunctionNameTypeBase));
|
|
|
|
// Itanium mangled dtor A::~A()
|
|
EXPECT_EQ(1, Count("_ZN1AD2Ev", eFunctionNameTypeFull));
|
|
EXPECT_EQ(1, Count("_ZN1AD2Ev", eFunctionNameTypeBase));
|
|
EXPECT_EQ(1, Count("~A", eFunctionNameTypeMethod));
|
|
EXPECT_EQ(0, Count("~A", eFunctionNameTypeBase));
|
|
|
|
// Itanium mangled method A::bar()
|
|
EXPECT_EQ(1, Count("_ZN1A3barEv", eFunctionNameTypeFull));
|
|
EXPECT_EQ(1, Count("_ZN1A3barEv", eFunctionNameTypeBase));
|
|
EXPECT_EQ(1, Count("bar", eFunctionNameTypeMethod));
|
|
EXPECT_EQ(0, Count("bar", eFunctionNameTypeBase));
|
|
|
|
// Itanium mangled names that are explicitly excluded from parsing
|
|
EXPECT_EQ(1, Count("_ZGVZN4llvm4dbgsEvE7thestrm", eFunctionNameTypeFull));
|
|
EXPECT_EQ(1, Count("_ZGVZN4llvm4dbgsEvE7thestrm", eFunctionNameTypeBase));
|
|
EXPECT_EQ(0, Count("dbgs", eFunctionNameTypeMethod));
|
|
EXPECT_EQ(0, Count("dbgs", eFunctionNameTypeBase));
|
|
EXPECT_EQ(1, Count("_ZZN4llvm4dbgsEvE7thestrm", eFunctionNameTypeFull));
|
|
EXPECT_EQ(1, Count("_ZZN4llvm4dbgsEvE7thestrm", eFunctionNameTypeBase));
|
|
EXPECT_EQ(0, Count("dbgs", eFunctionNameTypeMethod));
|
|
EXPECT_EQ(0, Count("dbgs", eFunctionNameTypeBase));
|
|
EXPECT_EQ(1, Count("_ZTVN5clang4DeclE", eFunctionNameTypeFull));
|
|
EXPECT_EQ(1, Count("_ZTVN5clang4DeclE", eFunctionNameTypeBase));
|
|
EXPECT_EQ(0, Count("Decl", eFunctionNameTypeMethod));
|
|
EXPECT_EQ(0, Count("Decl", eFunctionNameTypeBase));
|
|
|
|
// ObjC mangled static
|
|
EXPECT_EQ(1, Count("-[ObjCfoo]", eFunctionNameTypeFull));
|
|
EXPECT_EQ(1, Count("-[ObjCfoo]", eFunctionNameTypeBase));
|
|
EXPECT_EQ(0, Count("ObjCfoo", eFunctionNameTypeMethod));
|
|
|
|
// ObjC mangled method with category
|
|
EXPECT_EQ(1, Count("+[B ObjCbar(WithCategory)]", eFunctionNameTypeFull));
|
|
EXPECT_EQ(1, Count("+[B ObjCbar(WithCategory)]", eFunctionNameTypeBase));
|
|
EXPECT_EQ(0, Count("ObjCbar", eFunctionNameTypeMethod));
|
|
|
|
// Invalid things: unable to decode but still possible to find by full name
|
|
EXPECT_EQ(1, Count("_Z12undemangableEvx42", eFunctionNameTypeFull));
|
|
EXPECT_EQ(1, Count("_Z12undemangableEvx42", eFunctionNameTypeBase));
|
|
EXPECT_EQ(0, Count("_Z12undemangableEvx42", eFunctionNameTypeMethod));
|
|
EXPECT_EQ(0, Count("undemangable", eFunctionNameTypeBase));
|
|
EXPECT_EQ(0, Count("undemangable", eFunctionNameTypeMethod));
|
|
}
|
|
|
|
static bool NameInfoEquals(const DemangledNameInfo &lhs,
|
|
const DemangledNameInfo &rhs) {
|
|
return std::tie(lhs.BasenameRange, lhs.ArgumentsRange, lhs.ScopeRange,
|
|
lhs.QualifiersRange) ==
|
|
std::tie(rhs.BasenameRange, rhs.ArgumentsRange, rhs.ScopeRange,
|
|
rhs.QualifiersRange);
|
|
}
|
|
|
|
TEST(MangledTest, DemangledNameInfo_SetMangledResets) {
|
|
Mangled mangled;
|
|
EXPECT_EQ(mangled.GetDemangledInfo(), std::nullopt);
|
|
|
|
mangled.SetMangledName(ConstString("_Z3foov"));
|
|
ASSERT_TRUE(mangled);
|
|
|
|
auto info1 = mangled.GetDemangledInfo();
|
|
EXPECT_NE(info1, std::nullopt);
|
|
EXPECT_TRUE(info1->hasBasename());
|
|
|
|
mangled.SetMangledName(ConstString("_Z4funcv"));
|
|
|
|
// Should have re-calculated demangled-info since mangled name changed.
|
|
auto info2 = mangled.GetDemangledInfo();
|
|
ASSERT_NE(info2, std::nullopt);
|
|
EXPECT_TRUE(info2->hasBasename());
|
|
|
|
EXPECT_FALSE(NameInfoEquals(info1.value(), info2.value()));
|
|
EXPECT_EQ(mangled.GetDemangledName(), "func()");
|
|
}
|
|
|
|
TEST(MangledTest, DemangledNameInfo_SetDemangledResets) {
|
|
Mangled mangled("_Z3foov");
|
|
ASSERT_TRUE(mangled);
|
|
|
|
mangled.SetDemangledName(ConstString(""));
|
|
|
|
// Mangled name hasn't changed, so GetDemangledInfo causes re-demangling
|
|
// of previously set mangled name.
|
|
EXPECT_NE(mangled.GetDemangledInfo(), std::nullopt);
|
|
EXPECT_EQ(mangled.GetDemangledName(), "foo()");
|
|
}
|
|
|
|
TEST(MangledTest, DemangledNameInfo_Clear) {
|
|
Mangled mangled("_Z3foov");
|
|
ASSERT_TRUE(mangled);
|
|
EXPECT_NE(mangled.GetDemangledInfo(), std::nullopt);
|
|
|
|
mangled.Clear();
|
|
|
|
EXPECT_EQ(mangled.GetDemangledInfo(), std::nullopt);
|
|
}
|
|
|
|
TEST(MangledTest, DemangledNameInfo_SetValue) {
|
|
Mangled mangled("_Z4funcv");
|
|
ASSERT_TRUE(mangled);
|
|
|
|
auto demangled_func = mangled.GetDemangledInfo();
|
|
|
|
// SetValue(mangled) resets demangled-info
|
|
mangled.SetValue(ConstString("_Z3foov"));
|
|
auto demangled_foo = mangled.GetDemangledInfo();
|
|
EXPECT_NE(demangled_foo, std::nullopt);
|
|
EXPECT_FALSE(NameInfoEquals(demangled_foo.value(), demangled_func.value()));
|
|
|
|
// SetValue(demangled) resets demangled-info
|
|
mangled.SetValue(ConstString("_Z4funcv"));
|
|
EXPECT_TRUE(NameInfoEquals(mangled.GetDemangledInfo().value(),
|
|
demangled_func.value()));
|
|
|
|
// SetValue(empty) resets demangled-info
|
|
mangled.SetValue(ConstString());
|
|
EXPECT_EQ(mangled.GetDemangledInfo(), std::nullopt);
|
|
|
|
// Demangling invalid mangled name will set demangled-info
|
|
// (without a valid basename).
|
|
mangled.SetValue(ConstString("_Zinvalid"));
|
|
ASSERT_NE(mangled.GetDemangledInfo(), std::nullopt);
|
|
EXPECT_FALSE(mangled.GetDemangledInfo()->hasBasename());
|
|
}
|
|
|
|
struct DemanglingPartsTestCase {
|
|
const char *mangled;
|
|
DemangledNameInfo expected_info;
|
|
std::string_view basename;
|
|
std::string_view scope;
|
|
std::string_view qualifiers;
|
|
bool valid_basename = true;
|
|
};
|
|
|
|
DemanglingPartsTestCase g_demangling_parts_test_cases[] = {
|
|
// clang-format off
|
|
{ "_ZNVKO3BarIN2ns3QuxIiEEE1CIPFi3FooIS_IiES6_EEE6methodIS6_EENS5_IT_SC_E5InnerIiEESD_SD_",
|
|
{
|
|
/*.BasenameRange=*/{92, 98}, /*.TemplateArgumentsRange=*/{98, 108}, /*.ScopeRange=*/{36, 92},
|
|
/*.ArgumentsRange=*/{108, 158}, /*.QualifiersRange=*/{158, 176}, /*.NameQualifiersRange=*/{0, 0},
|
|
/*.PrefixRange=*/{0, 0}, /*.SuffixRange=*/{0, 0}
|
|
},
|
|
/*.basename=*/"method",
|
|
/*.scope=*/"Bar<ns::Qux<int>>::C<int (*)(Foo<Bar<int>, Bar<int>>)>::",
|
|
/*.qualifiers=*/" const volatile &&"
|
|
},
|
|
{ "_Z7getFuncIfEPFiiiET_",
|
|
{
|
|
/*.BasenameRange=*/{6, 13}, /*.TemplateArgumentsRange=*/{13, 20}, /*.ScopeRange=*/{6, 6},
|
|
/*.ArgumentsRange=*/{20, 27}, /*.QualifiersRange=*/{38, 38}, /*.NameQualifiersRange=*/{0, 0},
|
|
/*.PrefixRange=*/{0, 0}, /*.SuffixRange=*/{0, 0}
|
|
},
|
|
/*.basename=*/"getFunc",
|
|
/*.scope=*/"",
|
|
/*.qualifiers=*/""
|
|
},
|
|
{ "_ZN1f1b1c1gEv",
|
|
{
|
|
/*.BasenameRange=*/{9, 10}, /*.TemplateArgumentsRange=*/{0, 0}, /*.ScopeRange=*/{0, 9},
|
|
/*.ArgumentsRange=*/{10, 12}, /*.QualifiersRange=*/{12, 12}, /*.NameQualifiersRange=*/{0, 0},
|
|
/*.PrefixRange=*/{0, 0}, /*.SuffixRange=*/{0, 0}
|
|
},
|
|
/*.basename=*/"g",
|
|
/*.scope=*/"f::b::c::",
|
|
/*.qualifiers=*/""
|
|
},
|
|
{ "_ZN5test73fD1IiEEDTcmtlNS_1DEL_ZNS_1bEEEcvT__EES2_",
|
|
{
|
|
/*.BasenameRange=*/{45, 48}, /*.TemplateArgumentsRange=*/{48, 53}, /*.ScopeRange=*/{38, 45},
|
|
/*.ArgumentsRange=*/{53, 58}, /*.QualifiersRange=*/{58, 58}, /*.NameQualifiersRange=*/{0, 0},
|
|
/*.PrefixRange=*/{0, 0}, /*.SuffixRange=*/{0, 0}
|
|
},
|
|
/*.basename=*/"fD1",
|
|
/*.scope=*/"test7::",
|
|
/*.qualifiers=*/""
|
|
},
|
|
{ "_ZN5test73fD1IiEEDTcmtlNS_1DEL_ZNS_1bINDT1cE1dEEEEEcvT__EES2_",
|
|
{
|
|
/*.BasenameRange=*/{61, 64}, /*.TemplateArgumentsRange=*/{64, 69},/*.ScopeRange=*/{54, 61},
|
|
/*.ArgumentsRange=*/{69, 79}, /*.QualifiersRange=*/{79, 79}, /*.NameQualifiersRange=*/{0, 0},
|
|
/*.PrefixRange=*/{0, 0}, /*.SuffixRange=*/{0, 0}
|
|
},
|
|
/*.basename=*/"fD1",
|
|
/*.scope=*/"test7::",
|
|
/*.qualifiers=*/""
|
|
},
|
|
{ "_ZN5test7INDT1cE1dINDT1cE1dEEEE3fD1INDT1cE1dINDT1cE1dEEEEEDTcmtlNS_1DEL_ZNS_1bINDT1cE1dEEEEEcvT__EES2_",
|
|
{
|
|
/*.BasenameRange=*/{120, 123}, /*.TemplateArgumentsRange=*/{123, 155}, /*.ScopeRange=*/{81, 120},
|
|
/*.ArgumentsRange=*/{155, 168}, /*.QualifiersRange=*/{168, 168}, /*.NameQualifiersRange=*/{0, 0},
|
|
/*.PrefixRange=*/{0, 0}, /*.SuffixRange=*/{0, 0}
|
|
},
|
|
/*.basename=*/"fD1",
|
|
/*.scope=*/"test7<decltype(c)::d<decltype(c)::d>>::",
|
|
/*.qualifiers=*/""
|
|
},
|
|
{ "_ZN8nlohmann16json_abi_v3_11_310basic_jsonINSt3__13mapENS2_6vectorENS2_12basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEEbxydS8_NS0_14adl_serializerENS4_IhNS8_IhEEEEvE5parseIRA29_KcEESE_OT_NS2_8functionIFbiNS0_6detail13parse_event_tERSE_EEEbb",
|
|
{
|
|
/*.BasenameRange=*/{687, 692}, /*.TemplateArgumentsRange=*/{692, 713}, /*.ScopeRange=*/{343, 687},
|
|
/*.ArgumentsRange=*/{713, 1174}, /*.QualifiersRange=*/{1174, 1174}, /*.NameQualifiersRange=*/{0, 0},
|
|
/*.PrefixRange=*/{0, 0}, /*.SuffixRange=*/{0, 0}
|
|
},
|
|
/*.basename=*/"parse",
|
|
/*.scope=*/"nlohmann::json_abi_v3_11_3::basic_json<std::__1::map, std::__1::vector, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>, bool, long long, unsigned long long, double, std::__1::allocator, nlohmann::json_abi_v3_11_3::adl_serializer, std::__1::vector<unsigned char, std::__1::allocator<unsigned char>>, void>::",
|
|
/*.qualifiers=*/""
|
|
},
|
|
{ "_ZN8nlohmann16json_abi_v3_11_310basic_jsonINSt3__13mapENS2_6vectorENS2_12basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEEbxydS8_NS0_14adl_serializerENS4_IhNS8_IhEEEEvEC1EDn",
|
|
{
|
|
/*.BasenameRange=*/{344, 354}, /*.TemplateArgumentsRange=*/{0, 0}, /*.ScopeRange=*/{0, 344},
|
|
/*.ArgumentsRange=*/{354, 370}, /*.QualifiersRange=*/{370, 370}, /*.NameQualifiersRange=*/{0, 0},
|
|
/*.PrefixRange=*/{0, 0}, /*.SuffixRange=*/{0, 0}
|
|
},
|
|
/*.basename=*/"basic_json",
|
|
/*.scope=*/"nlohmann::json_abi_v3_11_3::basic_json<std::__1::map, std::__1::vector, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>, bool, long long, unsigned long long, double, std::__1::allocator, nlohmann::json_abi_v3_11_3::adl_serializer, std::__1::vector<unsigned char, std::__1::allocator<unsigned char>>, void>::",
|
|
/*.qualifiers=*/""
|
|
},
|
|
{ "_Z3fppIiEPFPFvvEiEf",
|
|
{
|
|
/*.BasenameRange=*/{10, 13}, /*.TemplateArgumentsRange=*/{13, 18}, /*.ScopeRange=*/{10, 10},
|
|
/*.ArgumentsRange=*/{18, 25}, /*.QualifiersRange=*/{34,34}, /*.NameQualifiersRange=*/{0, 0},
|
|
/*.PrefixRange=*/{0, 0}, /*.SuffixRange=*/{0, 0}
|
|
},
|
|
/*.basename=*/"fpp",
|
|
/*.scope=*/"",
|
|
/*.qualifiers=*/""
|
|
},
|
|
{ "_Z3fppIiEPFPFvvEN2ns3FooIiEEEf",
|
|
{
|
|
/*.BasenameRange=*/{10, 13}, /*.TemplateArgumentsRange=*/{13, 18}, /*.ScopeRange=*/{10, 10},
|
|
/*.ArgumentsRange=*/{18, 25}, /*.QualifiersRange=*/{43, 43}, /*.NameQualifiersRange=*/{0, 0},
|
|
/*.PrefixRange=*/{0, 0}, /*.SuffixRange=*/{0, 0}
|
|
},
|
|
/*.basename=*/"fpp",
|
|
/*.scope=*/"",
|
|
/*.qualifiers=*/""
|
|
},
|
|
{ "_Z3fppIiEPFPFvPFN2ns3FooIiEENS2_3BarIfE3QuxEEEPFS2_S2_EEf",
|
|
{
|
|
/*.BasenameRange=*/{10, 13}, /*.TemplateArgumentsRange=*/{13, 18}, /*.ScopeRange=*/{10, 10},
|
|
/*.ArgumentsRange=*/{18, 25}, /*.QualifiersRange=*/{108, 108}, /*.NameQualifiersRange=*/{0, 0},
|
|
/*.PrefixRange=*/{0, 0}, /*.SuffixRange=*/{0, 0}
|
|
},
|
|
/*.basename=*/"fpp",
|
|
/*.scope=*/"",
|
|
/*.qualifiers=*/""
|
|
},
|
|
{ "_ZN2ns8HasFuncsINS_3FooINS1_IiE3BarIfE3QuxEEEE3fppIiEEPFPFvvEiEf",
|
|
{
|
|
/*.BasenameRange=*/{64, 67}, /*.TemplateArgumentsRange=*/{67, 72}, /*.ScopeRange=*/{10, 64},
|
|
/*.ArgumentsRange=*/{72, 79}, /*.QualifiersRange=*/{88, 88}, /*.NameQualifiersRange=*/{0, 0},
|
|
/*.PrefixRange=*/{0, 0}, /*.SuffixRange=*/{0, 0}
|
|
},
|
|
/*.basename=*/"fpp",
|
|
/*.scope=*/"ns::HasFuncs<ns::Foo<ns::Foo<int>::Bar<float>::Qux>>::",
|
|
/*.qualifiers=*/""
|
|
},
|
|
{ "_ZN2ns8HasFuncsINS_3FooINS1_IiE3BarIfE3QuxEEEE3fppIiEEPFPFvvES2_Ef",
|
|
{
|
|
/*.BasenameRange=*/{64, 67}, /*.TemplateArgumentsRange=*/{67, 72}, /*.ScopeRange=*/{10, 64},
|
|
/*.ArgumentsRange=*/{72, 79}, /*.QualifiersRange=*/{97, 97}, /*.NameQualifiersRange=*/{0, 0},
|
|
/*.PrefixRange=*/{0, 0}, /*.SuffixRange=*/{0, 0}
|
|
},
|
|
/*.basename=*/"fpp",
|
|
/*.scope=*/"ns::HasFuncs<ns::Foo<ns::Foo<int>::Bar<float>::Qux>>::",
|
|
/*.qualifiers=*/"",
|
|
},
|
|
{ "_ZN2ns8HasFuncsINS_3FooINS1_IiE3BarIfE3QuxEEEE3fppIiEEPFPFvPFS2_S5_EEPFS2_S2_EEf",
|
|
{
|
|
/*.BasenameRange=*/{64, 67}, /*.TemplateArgumentsRange=*/{67, 72}, /*.ScopeRange=*/{10, 64},
|
|
/*.ArgumentsRange=*/{72, 79}, /*.QualifiersRange=*/{162, 162}, /*.NameQualifiersRange=*/{0, 0},
|
|
/*.PrefixRange=*/{0, 0}, /*.SuffixRange=*/{0, 0}
|
|
},
|
|
/*.basename=*/"fpp",
|
|
/*.scope=*/"ns::HasFuncs<ns::Foo<ns::Foo<int>::Bar<float>::Qux>>::",
|
|
/*.qualifiers=*/"",
|
|
},
|
|
{ "_ZNKO2ns3ns23Bar3fooIiEEPFPFNS0_3FooIiEEiENS3_IfEEEi",
|
|
{
|
|
/*.BasenameRange=*/{37, 40}, /*.TemplateArgumentsRange=*/{40, 45}, /*.ScopeRange=*/{23, 37},
|
|
/*.ArgumentsRange=*/{45, 50}, /*.QualifiersRange=*/{78, 87}, /*.NameQualifiersRange=*/{0, 0},
|
|
/*.PrefixRange=*/{0, 0}, /*.SuffixRange=*/{0, 0}
|
|
},
|
|
/*.basename=*/"foo",
|
|
/*.scope=*/"ns::ns2::Bar::",
|
|
/*.qualifiers=*/" const &&",
|
|
},
|
|
{ "_ZTV11ImageLoader",
|
|
{
|
|
/*.BasenameRange=*/{0, 0}, /*.TemplateArgumentsRange=*/{0, 0}, /*.ScopeRange=*/{0, 0},
|
|
/*.ArgumentsRange=*/{0, 0}, /*.QualifiersRange=*/{0, 0}, /*.NameQualifiersRange=*/{0, 0},
|
|
/*.PrefixRange=*/{0, 0}, /*.SuffixRange=*/{0, 0}
|
|
},
|
|
/*.basename=*/"",
|
|
/*.scope=*/"",
|
|
/*.qualifiers=*/"",
|
|
/*.valid_basename=*/false
|
|
},
|
|
{ "___ZNK5dyld313MachOAnalyzer18forEachInitializerER11DiagnosticsRKNS0_15VMAddrConverterEU13block_pointerFvjEPKv_block_invoke.204",
|
|
{
|
|
/*.BasenameRange=*/{55, 73}, /*.TemplateArgumentsRange=*/{0, 0}, /*.ScopeRange=*/{33, 55},
|
|
/*.ArgumentsRange=*/{73, 181}, /*.QualifiersRange=*/{181, 187}, /*.NameQualifiersRange=*/{0, 0},
|
|
/*.PrefixRange=*/{0, 0}, /*.SuffixRange=*/{0, 0}
|
|
},
|
|
/*.basename=*/"forEachInitializer",
|
|
/*.scope=*/"dyld3::MachOAnalyzer::",
|
|
/*.qualifiers=*/" const",
|
|
},
|
|
{ "_ZZN5dyld45startEPNS_10KernelArgsEPvS2_ENK3$_1clEv",
|
|
{
|
|
/*.BasenameRange=*/{53, 63}, /*.TemplateArgumentsRange=*/{0, 0}, /*.ScopeRange=*/{0, 53},
|
|
/*.ArgumentsRange=*/{63, 65}, /*.QualifiersRange=*/{65, 71}, /*.NameQualifiersRange=*/{0, 0},
|
|
/*.PrefixRange=*/{0, 0}, /*.SuffixRange=*/{0, 0}
|
|
},
|
|
/*.basename=*/"operator()",
|
|
/*.scope=*/"dyld4::start(dyld4::KernelArgs*, void*, void*)::$_1::",
|
|
/*.qualifiers=*/" const",
|
|
},
|
|
{ "_ZZNK5dyld46Loader38runInitializersBottomUpPlusUpwardLinksERNS_12RuntimeStateEENK3$_0clEv",
|
|
{
|
|
/*.BasenameRange=*/{88, 98}, /*.TemplateArgumentsRange=*/{0, 0}, /*.ScopeRange=*/{0, 88},
|
|
/*.ArgumentsRange=*/{98, 100}, /*.QualifiersRange=*/{100, 106}, /*.NameQualifiersRange=*/{0, 0},
|
|
/*.PrefixRange=*/{0, 0}, /*.SuffixRange=*/{0, 0}
|
|
},
|
|
/*.basename=*/"operator()",
|
|
/*.scope=*/"dyld4::Loader::runInitializersBottomUpPlusUpwardLinks(dyld4::RuntimeState&) const::$_0::",
|
|
/*.qualifiers=*/" const",
|
|
},
|
|
{ "_ZZNK5dyld46Loader38runInitializersBottomUpPlusUpwardLinksERNS_12RuntimeStateEENK3$_0clEv.cold",
|
|
{
|
|
/*.BasenameRange=*/{88, 98}, /*.TemplateArgumentsRange=*/{0, 0}, /*.ScopeRange=*/{0, 88},
|
|
/*.ArgumentsRange=*/{98, 100}, /*.QualifiersRange=*/{100, 106}, /*.NameQualifiersRange=*/{0, 0},
|
|
/*.PrefixRange=*/{0, 0}, /*.SuffixRange=*/{0, 0}
|
|
},
|
|
/*.basename=*/"operator()",
|
|
/*.scope=*/"dyld4::Loader::runInitializersBottomUpPlusUpwardLinks(dyld4::RuntimeState&) const::$_0::",
|
|
/*.qualifiers=*/" const",
|
|
},
|
|
{"_Z4funcILN3foo4EnumE1EEvv",
|
|
{
|
|
/*.BasenameRange=*/{5, 9}, /*.TemplateArgumentsRange=*/{9, 23}, /*.ScopeRange=*/{5, 5},
|
|
/*.ArgumentsRange=*/{23, 25}, /*.QualifiersRange=*/{25, 25}, /*.NameQualifiersRange=*/{0, 0},
|
|
/*.PrefixRange=*/{0, 0}, /*.SuffixRange=*/{0, 0}
|
|
},
|
|
/*.basename=*/"func",
|
|
/*.scope=*/"",
|
|
/*.qualifiers=*/"",
|
|
}
|
|
// clang-format on
|
|
};
|
|
|
|
struct DemanglingPartsTestFixture
|
|
: public ::testing::TestWithParam<DemanglingPartsTestCase> {};
|
|
|
|
namespace {
|
|
class TestAllocator {
|
|
llvm::BumpPtrAllocator Alloc;
|
|
|
|
public:
|
|
void reset() { Alloc.Reset(); }
|
|
|
|
template <typename T, typename... Args> T *makeNode(Args &&...args) {
|
|
return new (Alloc.Allocate(sizeof(T), alignof(T)))
|
|
T(std::forward<Args>(args)...);
|
|
}
|
|
|
|
void *allocateNodeArray(size_t sz) {
|
|
return Alloc.Allocate(sizeof(llvm::itanium_demangle::Node *) * sz,
|
|
alignof(llvm::itanium_demangle::Node *));
|
|
}
|
|
};
|
|
} // namespace
|
|
|
|
TEST_P(DemanglingPartsTestFixture, DemanglingParts) {
|
|
const auto &[mangled, info, basename, scope, qualifiers, valid_basename] =
|
|
GetParam();
|
|
|
|
llvm::itanium_demangle::ManglingParser<TestAllocator> Parser(
|
|
mangled, mangled + ::strlen(mangled));
|
|
|
|
const auto *Root = Parser.parse();
|
|
|
|
ASSERT_NE(nullptr, Root);
|
|
|
|
auto OB = std::unique_ptr<TrackingOutputBuffer, TrackingOutputBufferDeleter>(
|
|
new TrackingOutputBuffer());
|
|
Root->print(*OB);
|
|
auto demangled = std::string_view(*OB);
|
|
|
|
ASSERT_EQ(OB->NameInfo.hasBasename(), valid_basename);
|
|
EXPECT_EQ(OB->NameInfo.BasenameRange, info.BasenameRange);
|
|
EXPECT_EQ(OB->NameInfo.TemplateArgumentsRange, info.TemplateArgumentsRange);
|
|
EXPECT_EQ(OB->NameInfo.ScopeRange, info.ScopeRange);
|
|
EXPECT_EQ(OB->NameInfo.ArgumentsRange, info.ArgumentsRange);
|
|
EXPECT_EQ(OB->NameInfo.QualifiersRange, info.QualifiersRange);
|
|
EXPECT_EQ(OB->NameInfo.NameQualifiersRange, info.NameQualifiersRange);
|
|
|
|
auto get_part = [&](const std::pair<size_t, size_t> &loc) {
|
|
return demangled.substr(loc.first, loc.second - loc.first);
|
|
};
|
|
|
|
EXPECT_EQ(get_part(OB->NameInfo.BasenameRange), basename);
|
|
EXPECT_EQ(get_part(OB->NameInfo.ScopeRange), scope);
|
|
EXPECT_EQ(get_part(OB->NameInfo.QualifiersRange), qualifiers);
|
|
}
|
|
|
|
INSTANTIATE_TEST_SUITE_P(DemanglingPartsTests, DemanglingPartsTestFixture,
|
|
::testing::ValuesIn(g_demangling_parts_test_cases));
|
|
|
|
struct DemangledNameInfoTestCase {
|
|
DemangledNameInfo expected_info;
|
|
bool valid_basename;
|
|
bool valid_template;
|
|
bool valid_scope;
|
|
bool valid_arguments;
|
|
bool valid_qualifiers;
|
|
bool valid_name_qualifiers;
|
|
bool valid_prefix;
|
|
bool valid_suffix;
|
|
};
|
|
|
|
DemangledNameInfoTestCase g_demangled_name_info_test_cases[] = {
|
|
// clang-format off
|
|
{
|
|
{
|
|
/*.BasenameRange=*/{0, 10}, /*.TemplateArgumentsRange=*/{1, 0}, /*.ScopeRange=*/{1, 0},
|
|
/*.ArgumentsRange=*/{1, 0}, /*.QualifiersRange=*/{1, 0}, /*.NameQualifiersRange=*/{1, 0},
|
|
/*.PrefixRange=*/{1, 0}, /*.SuffixRange=*/{1, 0}
|
|
},
|
|
/*valid_basename=*/true, /*valid_template=*/false, /*valid_scope=*/false,
|
|
/*valid_arguments=*/false, /*valid_qualifiers=*/false, /*valid_name_qualifiers=*/false,
|
|
/*valid_prefix=*/false, /*valid_suffix=*/false,
|
|
},
|
|
{
|
|
{
|
|
/*.BasenameRange=*/{1, 0}, /*.TemplateArgumentsRange=*/{0, 10}, /*.ScopeRange=*/{1, 0},
|
|
/*.ArgumentsRange=*/{1, 0}, /*.QualifiersRange=*/{1, 0}, /*.NameQualifiersRange=*/{1, 0},
|
|
/*.PrefixRange=*/{1, 0}, /*.SuffixRange=*/{1, 0}
|
|
},
|
|
/*valid_basename=*/false, /*valid_name_qualifiers=*/true, /*valid_scope=*/false,
|
|
/*valid_arguments=*/false, /*valid_qualifiers=*/false, /*valid_name_qualifiers=*/false,
|
|
/*valid_prefix=*/false, /*valid_suffix=*/false,
|
|
},
|
|
{
|
|
{
|
|
/*.BasenameRange=*/{1, 0}, /*.TemplateArgumentsRange=*/{1, 0}, /*.ScopeRange=*/{0, 10},
|
|
/*.ArgumentsRange=*/{1, 0}, /*.QualifiersRange=*/{1, 0}, /*.NameQualifiersRange=*/{1, 0},
|
|
/*.PrefixRange=*/{1, 0}, /*.SuffixRange=*/{1, 0}
|
|
},
|
|
/*valid_basename=*/false, /*valid_template=*/false, /*valid_scope=*/true,
|
|
/*valid_arguments=*/false, /*valid_qualifiers=*/false, /*valid_name_qualifiers=*/false,
|
|
/*valid_prefix=*/false, /*valid_suffix=*/false,
|
|
},
|
|
{
|
|
{
|
|
/*.BasenameRange=*/{1, 0}, /*.TemplateArgumentsRange=*/{1, 0}, /*.ScopeRange=*/{1, 0},
|
|
/*.ArgumentsRange=*/{0, 10}, /*.QualifiersRange=*/{1, 0}, /*.NameQualifiersRange=*/{1, 0},
|
|
/*.PrefixRange=*/{1, 0}, /*.SuffixRange=*/{1, 0}
|
|
},
|
|
/*valid_basename=*/false, /*valid_template=*/false, /*valid_scope=*/false,
|
|
/*valid_arguments=*/true, /*valid_qualifiers=*/false, /*valid_name_qualifiers=*/false,
|
|
/*valid_prefix=*/false, /*valid_suffix=*/false,
|
|
},
|
|
{
|
|
{
|
|
/*.BasenameRange=*/{1, 0}, /*.TemplateArgumentsRange=*/{1, 0}, /*.ScopeRange=*/{1, 0},
|
|
/*.ArgumentsRange=*/{1, 0}, /*.QualifiersRange=*/{0, 10}, /*.NameQualifiersRange=*/{1, 0},
|
|
/*.PrefixRange=*/{1, 0}, /*.SuffixRange=*/{1, 0}
|
|
},
|
|
/*valid_basename=*/false, /*valid_template=*/false, /*valid_scope=*/false,
|
|
/*valid_arguments=*/false, /*valid_qualifiers=*/true, /*valid_name_qualifiers=*/false,
|
|
/*valid_prefix=*/false, /*valid_suffix=*/false,
|
|
},
|
|
{
|
|
{
|
|
/*.BasenameRange=*/{1, 0}, /*.TemplateArgumentsRange=*/{1, 0}, /*.ScopeRange=*/{1, 0},
|
|
/*.ArgumentsRange=*/{1, 0}, /*.QualifiersRange=*/{1, 0}, /*.NameQualifiersRange=*/{0, 10},
|
|
/*.PrefixRange=*/{1, 0}, /*.SuffixRange=*/{1, 0}
|
|
},
|
|
/*valid_basename=*/false, /*valid_template=*/false, /*valid_scope=*/false,
|
|
/*valid_arguments=*/false, /*valid_qualifiers=*/false, /*valid_name_qualifiers=*/true,
|
|
/*valid_prefix=*/false, /*valid_suffix=*/false,
|
|
},
|
|
{
|
|
{
|
|
/*.BasenameRange=*/{1, 0}, /*.TemplateArgumentsRange=*/{1, 0}, /*.ScopeRange=*/{1, 0},
|
|
/*.ArgumentsRange=*/{1, 0}, /*.QualifiersRange=*/{1, 0}, /*.NameQualifiersRange=*/{1, 0},
|
|
/*.PrefixRange=*/{0, 10}, /*.SuffixRange=*/{1, 0}
|
|
},
|
|
/*valid_basename=*/false, /*valid_template=*/false, /*valid_scope=*/false,
|
|
/*valid_arguments=*/false, /*valid_qualifiers=*/false, /*valid_name_qualifiers=*/false,
|
|
/*valid_prefix=*/true, /*valid_suffix=*/false,
|
|
},
|
|
{
|
|
{
|
|
/*.BasenameRange=*/{1, 0}, /*.TemplateArgumentsRange=*/{1, 0}, /*.ScopeRange=*/{1, 0},
|
|
/*.ArgumentsRange=*/{1, 0}, /*.QualifiersRange=*/{1, 0}, /*.NameQualifiersRange=*/{1, 0},
|
|
/*.PrefixRange=*/{1, 0}, /*.SuffixRange=*/{0, 10}
|
|
},
|
|
/*valid_basename=*/false, /*valid_template=*/false, /*valid_scope=*/false,
|
|
/*valid_arguments=*/false, /*valid_qualifiers=*/false, /*valid_name_qualifiers=*/false,
|
|
/*valid_prefix=*/false, /*valid_suffix=*/true,
|
|
},
|
|
// clang-format on
|
|
};
|
|
|
|
struct DemangledNameInfoTestFixture
|
|
: public ::testing::TestWithParam<DemangledNameInfoTestCase> {};
|
|
|
|
TEST_P(DemangledNameInfoTestFixture, DemangledNameInfoRanges) {
|
|
const auto &[info, valid_basename, valid_template_arguments, valid_scope,
|
|
valid_arguments, valid_qualifiers, valid_name_qualifiers,
|
|
valid_prefix, valid_suffix] = GetParam();
|
|
|
|
ASSERT_EQ(info.hasBasename(), valid_basename);
|
|
ASSERT_EQ(info.hasTemplateArguments(), valid_template_arguments);
|
|
ASSERT_EQ(info.hasScope(), valid_scope);
|
|
ASSERT_EQ(info.hasArguments(), valid_arguments);
|
|
ASSERT_EQ(info.hasQualifiers(), valid_qualifiers);
|
|
ASSERT_EQ(info.hasNameQualifiers(), valid_name_qualifiers);
|
|
ASSERT_EQ(info.hasPrefix(), valid_prefix);
|
|
ASSERT_EQ(info.hasSuffix(), valid_suffix);
|
|
}
|
|
|
|
INSTANTIATE_TEST_SUITE_P(DemangledNameInfoRangesTests,
|
|
DemangledNameInfoTestFixture,
|
|
::testing::ValuesIn(g_demangled_name_info_test_cases));
|
|
|
|
struct DemanglingInfoCorrectnessTestCase {
|
|
const char *mangled;
|
|
const char *demangled;
|
|
};
|
|
|
|
DemanglingInfoCorrectnessTestCase g_demangling_correctness_test_cases[] = {
|
|
#include "llvm/Testing/Demangle/DemangleTestCases.inc"
|
|
};
|
|
|
|
struct DemanglingInfoCorrectnessTestFixutre
|
|
: public ::testing::TestWithParam<DemanglingInfoCorrectnessTestCase> {};
|
|
|
|
TEST_P(DemanglingInfoCorrectnessTestFixutre, Correctness) {
|
|
auto [mangled, demangled] = GetParam();
|
|
|
|
llvm::itanium_demangle::ManglingParser<TestAllocator> Parser(
|
|
mangled, mangled + ::strlen(mangled));
|
|
|
|
const auto *Root = Parser.parse();
|
|
|
|
ASSERT_NE(nullptr, Root);
|
|
|
|
auto OB = std::unique_ptr<TrackingOutputBuffer, TrackingOutputBufferDeleter>(
|
|
new TrackingOutputBuffer());
|
|
Root->print(*OB);
|
|
|
|
// Filter out cases which would never show up in frames. We only care about
|
|
// function names.
|
|
if (Root->getKind() !=
|
|
llvm::itanium_demangle::Node::Kind::KFunctionEncoding &&
|
|
Root->getKind() != llvm::itanium_demangle::Node::Kind::KDotSuffix)
|
|
return;
|
|
|
|
ASSERT_TRUE(OB->NameInfo.hasBasename());
|
|
|
|
auto tracked_name = llvm::StringRef(*OB);
|
|
|
|
std::string reconstructed_name;
|
|
|
|
auto return_left =
|
|
CPlusPlusLanguage::GetDemangledReturnTypeLHS(tracked_name, OB->NameInfo);
|
|
EXPECT_THAT_EXPECTED(return_left, llvm::Succeeded());
|
|
reconstructed_name += *return_left;
|
|
|
|
auto scope = CPlusPlusLanguage::GetDemangledScope(tracked_name, OB->NameInfo);
|
|
EXPECT_THAT_EXPECTED(scope, llvm::Succeeded());
|
|
reconstructed_name += *scope;
|
|
|
|
auto basename =
|
|
CPlusPlusLanguage::GetDemangledBasename(tracked_name, OB->NameInfo);
|
|
reconstructed_name += basename;
|
|
|
|
auto template_args = CPlusPlusLanguage::GetDemangledTemplateArguments(
|
|
tracked_name, OB->NameInfo);
|
|
EXPECT_THAT_EXPECTED(template_args, llvm::Succeeded());
|
|
reconstructed_name += *template_args;
|
|
|
|
auto args = CPlusPlusLanguage::GetDemangledFunctionArguments(tracked_name,
|
|
OB->NameInfo);
|
|
EXPECT_THAT_EXPECTED(args, llvm::Succeeded());
|
|
reconstructed_name += *args;
|
|
|
|
auto return_right =
|
|
CPlusPlusLanguage::GetDemangledReturnTypeRHS(tracked_name, OB->NameInfo);
|
|
EXPECT_THAT_EXPECTED(return_right, llvm::Succeeded());
|
|
reconstructed_name += *return_right;
|
|
|
|
auto qualifiers = CPlusPlusLanguage::GetDemangledFunctionQualifiers(
|
|
tracked_name, OB->NameInfo);
|
|
EXPECT_THAT_EXPECTED(qualifiers, llvm::Succeeded());
|
|
reconstructed_name += *qualifiers;
|
|
|
|
auto suffix =
|
|
CPlusPlusLanguage::GetDemangledFunctionSuffix(tracked_name, OB->NameInfo);
|
|
EXPECT_THAT_EXPECTED(suffix, llvm::Succeeded());
|
|
reconstructed_name += *suffix;
|
|
|
|
EXPECT_EQ(reconstructed_name, demangled);
|
|
}
|
|
|
|
INSTANTIATE_TEST_SUITE_P(
|
|
DemanglingInfoCorrectnessTests, DemanglingInfoCorrectnessTestFixutre,
|
|
::testing::ValuesIn(g_demangling_correctness_test_cases));
|