//===------------------ 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 #include #include using namespace llvm; using namespace llvm::itanium_demangle; namespace { class TestAllocator { BumpPtrAllocator Alloc; public: void reset() { Alloc.Reset(); } template T *makeNode(Args &&... args) { return new (Alloc.Allocate(sizeof(T), alignof(T))) T(std::forward(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 struct Ctor { template void operator()(Args &&...args) { auto _ = NT(std::forward(args)...); } }; template void Visit(const NT *Node) { Node->match(Ctor{}); } #define NOMATCHER(X) \ template <> void Visit(const itanium_demangle::X *) {} // Some nodes have no match member. NOMATCHER(ForwardTemplateReference) #undef NOMATCHER void Visitor() { #define NODE(X) Visit(static_cast(nullptr)); #include "llvm/Demangle/ItaniumNodes.def" } } // namespace NodeMatcher // Verify Operator table is ordered TEST(ItaniumDemangle, OperatorOrdering) { struct TestParser : AbstractManglingParser {}; 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 { std::vector Types; TestParser(const char *Str) : AbstractManglingParser(Str, Str + strlen(Str)) {} Node *parseType() { Types.push_back(*First); return AbstractManglingParser::parseType(); } }; TestParser Parser("_Z1fIiEjl"); ASSERT_NE(nullptr, Parser.parse()); EXPECT_THAT(Parser.Types, testing::ElementsAre('i', 'j', 'l')); } static std::string toString(OutputBuffer &OB) { std::string_view SV = OB; return {SV.begin(), SV.end()}; } TEST(ItaniumDemangle, HalfType) { struct TestParser : AbstractManglingParser { std::vector Types; TestParser(const char *Str) : AbstractManglingParser(Str, Str + strlen(Str)) {} Node *parseType() { OutputBuffer OB; Node *N = AbstractManglingParser::parseType(); N->printLeft(OB); std::string_view 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")); }