116 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			116 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			C++
		
	
	
	
| //===------------------ ItaniumDemangleTest.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 "llvm/Demangle/ItaniumDemangle.h"
 | |
| #include "llvm/Support/Allocator.h"
 | |
| #include "gmock/gmock.h"
 | |
| #include "gtest/gtest.h"
 | |
| #include <cstdlib>
 | |
| #include <vector>
 | |
| 
 | |
| using namespace llvm;
 | |
| using namespace llvm::itanium_demangle;
 | |
| 
 | |
| namespace {
 | |
| class TestAllocator {
 | |
|   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(Node *) * sz, alignof(Node *));
 | |
|   }
 | |
| };
 | |
| } // namespace
 | |
| 
 | |
| namespace NodeMatcher {
 | |
| // Make sure the node matchers provide constructor parameters. This is a
 | |
| // compilation test.
 | |
| template <typename NT> struct Ctor {
 | |
|   template <typename... Args> void operator()(Args &&...args) {
 | |
|     auto _ = NT(std::forward<Args>(args)...);
 | |
|   }
 | |
| };
 | |
| 
 | |
| template <typename NT> void Visit(const NT *Node) { Node->match(Ctor<NT>{}); }
 | |
| #define NOMATCHER(X)                                                           \
 | |
|   template <> void Visit<itanium_demangle::X>(const itanium_demangle::X *) {}
 | |
| // Some nodes have no match member.
 | |
| NOMATCHER(ForwardTemplateReference)
 | |
| #undef NOMATCHER
 | |
| 
 | |
| void Visitor() {
 | |
| #define NODE(X) Visit(static_cast<const itanium_demangle::X *>(nullptr));
 | |
| #include "llvm/Demangle/ItaniumNodes.def"
 | |
| }
 | |
| } // namespace NodeMatcher
 | |
| 
 | |
| // Verify Operator table is ordered
 | |
| TEST(ItaniumDemangle, OperatorOrdering) {
 | |
|   struct TestParser : AbstractManglingParser<TestParser, TestAllocator> {};
 | |
|   for (const auto *Op = &TestParser::Ops[0];
 | |
|        Op != &TestParser::Ops[TestParser::NumOps - 1]; Op++)
 | |
|     ASSERT_LT(Op[0], Op[1]);
 | |
| }
 | |
| 
 | |
| TEST(ItaniumDemangle, MethodOverride) {
 | |
|   struct TestParser : AbstractManglingParser<TestParser, TestAllocator> {
 | |
|     std::vector<char> Types;
 | |
| 
 | |
|     TestParser(const char *Str)
 | |
|         : AbstractManglingParser(Str, Str + strlen(Str)) {}
 | |
| 
 | |
|     Node *parseType() {
 | |
|       Types.push_back(*First);
 | |
|       return AbstractManglingParser<TestParser, TestAllocator>::parseType();
 | |
|     }
 | |
|   };
 | |
| 
 | |
|   TestParser Parser("_Z1fIiEjl");
 | |
|   ASSERT_NE(nullptr, Parser.parse());
 | |
|   EXPECT_THAT(Parser.Types, testing::ElementsAre('i', 'j', 'l'));
 | |
| }
 | |
| 
 | |
| static std::string toString(OutputBuffer &OB) {
 | |
|   StringView SV = OB;
 | |
|   return {SV.begin(), SV.end()};
 | |
| }
 | |
| 
 | |
| TEST(ItaniumDemangle, HalfType) {
 | |
|   struct TestParser : AbstractManglingParser<TestParser, TestAllocator> {
 | |
|     std::vector<std::string> Types;
 | |
| 
 | |
|     TestParser(const char *Str)
 | |
|         : AbstractManglingParser(Str, Str + strlen(Str)) {}
 | |
| 
 | |
|     Node *parseType() {
 | |
|       OutputBuffer OB;
 | |
|       Node *N = AbstractManglingParser<TestParser, TestAllocator>::parseType();
 | |
|       N->printLeft(OB);
 | |
|       StringView Name = N->getBaseName();
 | |
|       if (!Name.empty())
 | |
|         Types.push_back(std::string(Name.begin(), Name.end()));
 | |
|       else
 | |
|         Types.push_back(toString(OB));
 | |
|       std::free(OB.getBuffer());
 | |
|       return N;
 | |
|     }
 | |
|   };
 | |
| 
 | |
|   // void f(A<_Float16>, _Float16);
 | |
|   TestParser Parser("_Z1f1AIDF16_EDF16_");
 | |
|   ASSERT_NE(nullptr, Parser.parse());
 | |
|   EXPECT_THAT(Parser.Types, testing::ElementsAre("_Float16", "A", "_Float16"));
 | |
| }
 |