forked from OSchip/llvm-project
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"));
|
|
}
|