Initial check in
Bug: 137197907
diff --git a/src/llvm-project/llvm/unittests/Demangle/CMakeLists.txt b/src/llvm-project/llvm/unittests/Demangle/CMakeLists.txt
new file mode 100644
index 0000000..954f3d0
--- /dev/null
+++ b/src/llvm-project/llvm/unittests/Demangle/CMakeLists.txt
@@ -0,0 +1,9 @@
+set(LLVM_LINK_COMPONENTS
+ Demangle
+ Support
+)
+
+add_llvm_unittest(DemangleTests
+ ItaniumDemangleTest.cpp
+ PartialDemangleTest.cpp
+)
diff --git a/src/llvm-project/llvm/unittests/Demangle/ItaniumDemangleTest.cpp b/src/llvm-project/llvm/unittests/Demangle/ItaniumDemangleTest.cpp
new file mode 100644
index 0000000..abb690c
--- /dev/null
+++ b/src/llvm-project/llvm/unittests/Demangle/ItaniumDemangleTest.cpp
@@ -0,0 +1,54 @@
+//===------------------ ItaniumDemangleTest.cpp ---------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#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
+
+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'));
+}
diff --git a/src/llvm-project/llvm/unittests/Demangle/PartialDemangleTest.cpp b/src/llvm-project/llvm/unittests/Demangle/PartialDemangleTest.cpp
new file mode 100644
index 0000000..8bb4a3a
--- /dev/null
+++ b/src/llvm-project/llvm/unittests/Demangle/PartialDemangleTest.cpp
@@ -0,0 +1,194 @@
+//===----------------------- PartialDemangleTest.cpp ----------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <cstdlib>
+#include "llvm/Demangle/Demangle.h"
+#include "gtest/gtest.h"
+
+struct ChoppedName {
+ const char *Mangled;
+ const char *ContextName, *BaseName, *ReturnType, *Params;
+};
+
+static ChoppedName NamesToTest[] = {
+ {"_Z1fv", "", "f", "", "()"},
+ {"_ZN1a1b1cIiiiEEvm", "a::b", "c", "void", "(unsigned long)"},
+ {"_ZZ5OuterIiEivEN5Inner12inner_memberEv",
+ "int Outer<int>()::Inner", "inner_member", "", "()"},
+ {"_Z1fIiEPFvvEv", "", "f", "void (*)()", "()"},
+ {"_ZN1S1fIiEEvv", "S", "f", "void", "()"},
+
+ // Call operator for a lambda in f().
+ {"_ZZ1fvENK3$_0clEi", "f()::$_0", "operator()", "", "(int)"},
+
+ // A call operator for a lambda in a lambda in f().
+ {"_ZZZ1fvENK3$_0clEvENKUlvE_clEv",
+ "f()::$_0::operator()() const::'lambda'()", "operator()", "", "()"},
+
+ {"_ZZN1S1fEiiEd0_NKUlvE_clEv",
+ "S::f(int, int)::'lambda'()", "operator()", "", "()"},
+
+ {"_ZN1Scv7MuncherIJDpPT_EEIJFivEA_iEEEv",
+ "S", "operator Muncher<int (*)(), int (*) []>", "", "()"},
+
+ // Attributes.
+ {"_ZN5test4IdE1fEUa9enable_ifIXeqfL0p_Li1EEXeqfL0p0_Li2EEEi",
+ "test4<double>", "f", "", "(int)"},
+ {"_ZN1SC2B8ctor_tagEv", "S", "S", "", "()"},
+ {"_ZN1S1fB4MERPIiEEvv", "S", "f", "void", "()"},
+
+ {"_ZNSsC1EmcRKSaIcE",
+ "std::basic_string<char, std::char_traits<char>, std::allocator<char> >",
+ "basic_string", "", "(unsigned long, char, std::allocator<char> const&)"},
+ {"_ZNSsixEm", "std::string", "operator[]", "", "(unsigned long)"},
+ {"_ZSt17__throw_bad_allocv", "std", "__throw_bad_alloc", "", "()"},
+
+ {"_ZN1AI1BEC2Ev", "A<B>", "A", "", "()"},
+ {"_ZN1AI1BED2Ev", "A<B>", "~A", "", "()"},
+ {"_ZN1AI1BECI24BaseEi", "A<B>", "A", "", "(int)"},
+ {"_ZNKR1AI1BE1fIiEEiv", "A<B>", "f", "int", "()"},
+
+ {"_ZN1SIJicfEE3mfnIJjcdEEEvicfDpT_", "S<int, char, float>",
+ "mfn", "void", "(int, char, float, unsigned int, char, double)"},
+};
+
+TEST(PartialDemanglerTest, TestNameChopping) {
+ size_t Size = 1;
+ char *Buf = static_cast<char *>(std::malloc(Size));
+
+ llvm::ItaniumPartialDemangler D;
+
+ for (ChoppedName &N : NamesToTest) {
+ EXPECT_FALSE(D.partialDemangle(N.Mangled));
+ EXPECT_TRUE(D.isFunction());
+ EXPECT_FALSE(D.isData());
+ EXPECT_FALSE(D.isSpecialName());
+
+ Buf = D.getFunctionDeclContextName(Buf, &Size);
+ EXPECT_STREQ(Buf, N.ContextName);
+
+ Buf = D.getFunctionBaseName(Buf, &Size);
+ EXPECT_STREQ(Buf, N.BaseName);
+
+ Buf = D.getFunctionReturnType(Buf, &Size);
+ EXPECT_STREQ(Buf, N.ReturnType);
+
+ Buf = D.getFunctionParameters(Buf, &Size);
+ EXPECT_STREQ(Buf, N.Params);
+ }
+
+ std::free(Buf);
+}
+
+TEST(PartialDemanglerTest, TestNameMeta) {
+ llvm::ItaniumPartialDemangler Demangler;
+
+ EXPECT_FALSE(Demangler.partialDemangle("_ZNK1f1gEv"));
+ EXPECT_TRUE(Demangler.isFunction());
+ EXPECT_TRUE(Demangler.hasFunctionQualifiers());
+ EXPECT_FALSE(Demangler.isSpecialName());
+ EXPECT_FALSE(Demangler.isData());
+
+ EXPECT_FALSE(Demangler.partialDemangle("_Z1fv"));
+ EXPECT_FALSE(Demangler.hasFunctionQualifiers());
+
+ EXPECT_FALSE(Demangler.partialDemangle("_ZTV1S"));
+ EXPECT_TRUE(Demangler.isSpecialName());
+ EXPECT_FALSE(Demangler.isData());
+ EXPECT_FALSE(Demangler.isFunction());
+
+ EXPECT_FALSE(Demangler.partialDemangle("_ZN1aDC1a1b1cEE"));
+ EXPECT_FALSE(Demangler.isFunction());
+ EXPECT_FALSE(Demangler.isSpecialName());
+ EXPECT_TRUE(Demangler.isData());
+}
+
+TEST(PartialDemanglerTest, TestCtorOrDtor) {
+ static const char *Pos[] = {
+ "_ZN1AC1Ev", // A::A()
+ "_ZN1AC1IiEET_", // A::A<int>(int)
+ "_ZN1AD2Ev", // A::~A()
+ "_ZN1BIiEC1IcEET_", // B<int>::B<char>(char)
+ "_ZN1AC1B1TEv", // A::A[abi:T]()
+ "_ZNSt1AD2Ev", // std::A::~A()
+ "_ZN2ns1AD1Ev", // ns::A::~A()
+ };
+ static const char *Neg[] = {
+ "_Z1fv",
+ "_ZN1A1gIiEEvT_", // void A::g<int>(int)
+ };
+
+ llvm::ItaniumPartialDemangler D;
+ for (const char *N : Pos) {
+ EXPECT_FALSE(D.partialDemangle(N));
+ EXPECT_TRUE(D.isCtorOrDtor());
+ }
+ for (const char *N : Neg) {
+ EXPECT_FALSE(D.partialDemangle(N));
+ EXPECT_FALSE(D.isCtorOrDtor());
+ }
+}
+
+TEST(PartialDemanglerTest, TestMisc) {
+ llvm::ItaniumPartialDemangler D1, D2;
+
+ EXPECT_FALSE(D1.partialDemangle("_Z1fv"));
+ EXPECT_FALSE(D2.partialDemangle("_Z1g"));
+ std::swap(D1, D2);
+ EXPECT_FALSE(D1.isFunction());
+ EXPECT_TRUE(D2.isFunction());
+
+ EXPECT_TRUE(D1.partialDemangle("Not a mangled name!"));
+}
+
+TEST(PartialDemanglerTest, TestPrintCases) {
+ llvm::ItaniumPartialDemangler D;
+
+ const size_t OriginalSize = 4;
+ char *Buf = static_cast<char *>(std::malloc(OriginalSize));
+ const char *OriginalBuf = Buf;
+
+ // Default success case: Result fits into the given buffer.
+ // Res points to Buf. N returns string size including null termination.
+ {
+ EXPECT_FALSE(D.partialDemangle("_ZN1a1bEv"));
+
+ size_t N = OriginalSize;
+ char *Res = D.getFunctionDeclContextName(Buf, &N);
+ EXPECT_STREQ("a", Res);
+ EXPECT_EQ(OriginalBuf, Res);
+ EXPECT_EQ(strlen(Res) + 1, N);
+ }
+
+ // Realloc success case: Result does not fit into the given buffer.
+ // Res points to the new or extended buffer. N returns string size
+ // including null termination. Buf was extended or freed.
+ {
+ EXPECT_FALSE(D.partialDemangle("_ZN1a1b1cIiiiEEvm"));
+
+ size_t N = OriginalSize;
+ char *Res = D.finishDemangle(Buf, &N);
+ EXPECT_STREQ("void a::b::c<int, int, int>(unsigned long)", Res);
+ EXPECT_EQ(strlen(Res) + 1, N);
+ Buf = Res;
+ }
+
+ // Failure case: a::c is not a function.
+ // Res is nullptr. N remains unchanged.
+ {
+ EXPECT_FALSE(D.partialDemangle("_ZN1a1cE"));
+
+ size_t N = OriginalSize;
+ char *Res = D.getFunctionName(Buf, &N);
+ EXPECT_EQ(nullptr, Res);
+ EXPECT_EQ(OriginalSize, N);
+ }
+
+ std::free(Buf);
+}