xref: /llvm-project/llvm/unittests/Demangle/ItaniumDemangleTest.cpp (revision 7c59e8001a3b66be545a890a26ad8a24a6c9fe4b)
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 
17 using namespace llvm;
18 using namespace llvm::itanium_demangle;
19 
20 namespace {
21 class TestAllocator {
22   BumpPtrAllocator Alloc;
23 
24 public:
reset()25   void reset() { Alloc.Reset(); }
26 
makeNode(Args &&...args)27   template <typename T, typename... Args> T *makeNode(Args &&... args) {
28     return new (Alloc.Allocate(sizeof(T), alignof(T)))
29         T(std::forward<Args>(args)...);
30   }
31 
allocateNodeArray(size_t sz)32   void *allocateNodeArray(size_t sz) {
33     return Alloc.Allocate(sizeof(Node *) * sz, alignof(Node *));
34   }
35 };
36 } // namespace
37 
38 namespace NodeMatcher {
39 // Make sure the node matchers provide constructor parameters. This is a
40 // compilation test.
41 template <typename NT> struct Ctor {
operator ()NodeMatcher::Ctor42   template <typename... Args> void operator()(Args &&...args) {
43     auto _ = NT(std::forward<Args>(args)...);
44   }
45 };
46 
Visit(const NT * Node)47 template <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.
NOMATCHER(ForwardTemplateReference)51 NOMATCHER(ForwardTemplateReference)
52 #undef NOMATCHER
53 
54 void 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
TEST(ItaniumDemangle,OperatorOrdering)61 TEST(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 
TEST(ItaniumDemangle,MethodOverride)68 TEST(ItaniumDemangle, MethodOverride) {
69   struct TestParser : AbstractManglingParser<TestParser, TestAllocator> {
70     std::vector<char> Types;
71 
72     TestParser(const char *Str)
73         : AbstractManglingParser(Str, Str + strlen(Str)) {}
74 
75     Node *parseType() {
76       Types.push_back(*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 
toString(OutputBuffer & OB)86 static std::string toString(OutputBuffer &OB) {
87   std::string_view SV = OB;
88   return {SV.begin(), SV.end()};
89 }
90 
TEST(ItaniumDemangle,HalfType)91 TEST(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(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(std::string(Name.begin(), Name.end()));
105       else
106         Types.push_back(toString(OB));
107       std::free(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