1//===------------------ ItaniumDemangleTest.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 "llvm/Demangle/ItaniumDemangle.h"
10#include "llvm/Support/Allocator.h"
11#include "gmock/gmock.h"
12#include "gtest/gtest.h"
13#include <cstdlib>
14#include <string_view>
15#include <vector>
16
17using namespace llvm;
18using namespace llvm::itanium_demangle;
19
20namespace {
21class TestAllocator {
22 BumpPtrAllocator Alloc;
23
24public:
25 void reset() { Alloc.Reset(); }
26
27 template <typename T, typename... Args> T *makeNode(Args &&... args) {
28 return new (Alloc.Allocate(Size: sizeof(T), Alignment: alignof(T)))
29 T(std::forward<Args>(args)...);
30 }
31
32 void *allocateNodeArray(size_t sz) {
33 return Alloc.Allocate(Size: sizeof(Node *) * sz, Alignment: alignof(Node *));
34 }
35};
36} // namespace
37
38namespace NodeMatcher {
39// Make sure the node matchers provide constructor parameters. This is a
40// compilation test.
41template <typename NT> struct Ctor {
42 template <typename... Args> void operator()(Args &&...args) {
43 auto _ = NT(std::forward<Args>(args)...);
44 }
45};
46
47template <typename NT> void Visit(const NT *Node) { Node->match(Ctor<NT>{}); }
48#define NOMATCHER(X) \
49 template <> void Visit<itanium_demangle::X>(const itanium_demangle::X *) {}
50// Some nodes have no match member.
51NOMATCHER(ForwardTemplateReference)
52#undef NOMATCHER
53
54void Visitor() {
55#define NODE(X) Visit(static_cast<const itanium_demangle::X *>(nullptr));
56#include "llvm/Demangle/ItaniumNodes.def"
57}
58} // namespace NodeMatcher
59
60// Verify Operator table is ordered
61TEST(ItaniumDemangle, OperatorOrdering) {
62 struct TestParser : AbstractManglingParser<TestParser, TestAllocator> {};
63 for (const auto *Op = &TestParser::Ops[0];
64 Op != &TestParser::Ops[TestParser::NumOps - 1]; Op++)
65 ASSERT_LT(Op[0], Op[1]);
66}
67
68TEST(ItaniumDemangle, MethodOverride) {
69 struct TestParser : AbstractManglingParser<TestParser, TestAllocator> {
70 std::vector<char> Types;
71
72 TestParser(const char *Str)
73 : AbstractManglingParser(Str, Str + strlen(s: Str)) {}
74
75 Node *parseType() {
76 Types.push_back(x: *First);
77 return AbstractManglingParser<TestParser, TestAllocator>::parseType();
78 }
79 };
80
81 TestParser Parser("_Z1fIiEjl");
82 ASSERT_NE(nullptr, Parser.parse());
83 EXPECT_THAT(Parser.Types, testing::ElementsAre('i', 'j', 'l'));
84}
85
86static std::string toString(OutputBuffer &OB) {
87 std::string_view SV = OB;
88 return {SV.begin(), SV.end()};
89}
90
91TEST(ItaniumDemangle, HalfType) {
92 struct TestParser : AbstractManglingParser<TestParser, TestAllocator> {
93 std::vector<std::string> Types;
94
95 TestParser(const char *Str)
96 : AbstractManglingParser(Str, Str + strlen(s: Str)) {}
97
98 Node *parseType() {
99 OutputBuffer OB;
100 Node *N = AbstractManglingParser<TestParser, TestAllocator>::parseType();
101 N->printLeft(OB);
102 std::string_view Name = N->getBaseName();
103 if (!Name.empty())
104 Types.push_back(x: std::string(Name.begin(), Name.end()));
105 else
106 Types.push_back(x: toString(OB));
107 std::free(ptr: OB.getBuffer());
108 return N;
109 }
110 };
111
112 // void f(A<_Float16>, _Float16);
113 TestParser Parser("_Z1f1AIDF16_EDF16_");
114 ASSERT_NE(nullptr, Parser.parse());
115 EXPECT_THAT(Parser.Types, testing::ElementsAre("_Float16", "A", "_Float16"));
116}
117

source code of llvm/unittests/Demangle/ItaniumDemangleTest.cpp