xref: /llvm-project/lldb/unittests/Language/CPlusPlus/CPlusPlusLanguageTest.cpp (revision 699a748893d6b96a21d235aa109a6465e8af9f83)
1 //===-- CPlusPlusLanguageTest.cpp -------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 #include "gtest/gtest.h"
10 
11 #include "Plugins/Language/CPlusPlus/CPlusPlusLanguage.h"
12 
13 using namespace lldb_private;
14 
15 TEST(CPlusPlusLanguage, MethodNameParsing) {
16   struct TestCase {
17     std::string input;
18     std::string context, basename, arguments, qualifiers, scope_qualified_name;
19   };
20 
21   TestCase test_cases[] = {
22       {"main(int, char *[]) ", "", "main", "(int, char *[])", "", "main"},
23       {"foo::bar(baz) const", "foo", "bar", "(baz)", "const", "foo::bar"},
24       {"foo::~bar(baz)", "foo", "~bar", "(baz)", "", "foo::~bar"},
25       {"a::b::c::d(e,f)", "a::b::c", "d", "(e,f)", "", "a::b::c::d"},
26       {"void f(int)", "", "f", "(int)", "", "f"},
27 
28       // Operators
29       {"std::basic_ostream<char, std::char_traits<char> >& "
30        "std::operator<<<std::char_traits<char> >"
31        "(std::basic_ostream<char, std::char_traits<char> >&, char const*)",
32        "std", "operator<<<std::char_traits<char> >",
33        "(std::basic_ostream<char, std::char_traits<char> >&, char const*)", "",
34        "std::operator<<<std::char_traits<char> >"},
35       {"operator delete[](void*, clang::ASTContext const&, unsigned long)", "",
36        "operator delete[]", "(void*, clang::ASTContext const&, unsigned long)",
37        "", "operator delete[]"},
38       {"llvm::Optional<clang::PostInitializer>::operator bool() const",
39        "llvm::Optional<clang::PostInitializer>", "operator bool", "()", "const",
40        "llvm::Optional<clang::PostInitializer>::operator bool"},
41       {"(anonymous namespace)::FactManager::operator[](unsigned short)",
42        "(anonymous namespace)::FactManager", "operator[]", "(unsigned short)",
43        "", "(anonymous namespace)::FactManager::operator[]"},
44       {"const int& std::map<int, pair<short, int>>::operator[](short) const",
45        "std::map<int, pair<short, int>>", "operator[]", "(short)", "const",
46        "std::map<int, pair<short, int>>::operator[]"},
47       {"CompareInsn::operator()(llvm::StringRef, InsnMatchEntry const&)",
48        "CompareInsn", "operator()", "(llvm::StringRef, InsnMatchEntry const&)",
49        "", "CompareInsn::operator()"},
50       {"llvm::Optional<llvm::MCFixupKind>::operator*() const &",
51        "llvm::Optional<llvm::MCFixupKind>", "operator*", "()", "const &",
52        "llvm::Optional<llvm::MCFixupKind>::operator*"},
53       // Internal classes
54       {"operator<<(Cls, Cls)::Subclass::function()",
55        "operator<<(Cls, Cls)::Subclass", "function", "()", "",
56        "operator<<(Cls, Cls)::Subclass::function"},
57       {"SAEC::checkFunction(context&) const::CallBack::CallBack(int)",
58        "SAEC::checkFunction(context&) const::CallBack", "CallBack", "(int)", "",
59        "SAEC::checkFunction(context&) const::CallBack::CallBack"},
60       // Anonymous namespace
61       {"XX::(anonymous namespace)::anon_class::anon_func() const",
62        "XX::(anonymous namespace)::anon_class", "anon_func", "()", "const",
63        "XX::(anonymous namespace)::anon_class::anon_func"},
64 
65       // Function pointers
66       {"string (*f(vector<int>&&))(float)", "", "f", "(vector<int>&&)", "",
67        "f"},
68       {"void (*&std::_Any_data::_M_access<void (*)()>())()", "std::_Any_data",
69        "_M_access<void (*)()>", "()", "",
70        "std::_Any_data::_M_access<void (*)()>"},
71       {"void (*(*(*(*(*(*(*(* const&func1(int))())())())())())())())()", "",
72        "func1", "(int)", "", "func1"},
73 
74       // Templates
75       {"void llvm::PM<llvm::Module, llvm::AM<llvm::Module>>::"
76        "addPass<llvm::VP>(llvm::VP)",
77        "llvm::PM<llvm::Module, llvm::AM<llvm::Module>>", "addPass<llvm::VP>",
78        "(llvm::VP)", "",
79        "llvm::PM<llvm::Module, llvm::AM<llvm::Module>>::"
80        "addPass<llvm::VP>"},
81       {"void std::vector<Class, std::allocator<Class> >"
82        "::_M_emplace_back_aux<Class const&>(Class const&)",
83        "std::vector<Class, std::allocator<Class> >",
84        "_M_emplace_back_aux<Class const&>", "(Class const&)", "",
85        "std::vector<Class, std::allocator<Class> >::"
86        "_M_emplace_back_aux<Class const&>"},
87       {"unsigned long llvm::countTrailingOnes<unsigned int>"
88        "(unsigned int, llvm::ZeroBehavior)",
89        "llvm", "countTrailingOnes<unsigned int>",
90        "(unsigned int, llvm::ZeroBehavior)", "",
91        "llvm::countTrailingOnes<unsigned int>"},
92       {"std::enable_if<(10u)<(64), bool>::type llvm::isUInt<10u>(unsigned "
93        "long)",
94        "llvm", "isUInt<10u>", "(unsigned long)", "", "llvm::isUInt<10u>"},
95       {"f<A<operator<(X,Y)::Subclass>, sizeof(B)<sizeof(C)>()", "",
96        "f<A<operator<(X,Y)::Subclass>, sizeof(B)<sizeof(C)>", "()", "",
97        "f<A<operator<(X,Y)::Subclass>, sizeof(B)<sizeof(C)>"}};
98 
99   for (const auto &test : test_cases) {
100     CPlusPlusLanguage::MethodName method(ConstString(test.input));
101     EXPECT_TRUE(method.IsValid()) << test.input;
102     if (method.IsValid()) {
103       EXPECT_EQ(test.context, method.GetContext().str());
104       EXPECT_EQ(test.basename, method.GetBasename().str());
105       EXPECT_EQ(test.arguments, method.GetArguments().str());
106       EXPECT_EQ(test.qualifiers, method.GetQualifiers().str());
107       EXPECT_EQ(test.scope_qualified_name, method.GetScopeQualifiedName());
108     }
109   }
110 }
111 
112 TEST(CPlusPlusLanguage, ExtractContextAndIdentifier) {
113   struct TestCase {
114     std::string input;
115     std::string context, basename;
116   };
117 
118   TestCase test_cases[] = {
119       {"main", "", "main"},
120       {"foo01::bar", "foo01", "bar"},
121       {"foo::~bar", "foo", "~bar"},
122       {"std::vector<int>::push_back", "std::vector<int>", "push_back"},
123       {"operator<<(Cls, Cls)::Subclass::function",
124        "operator<<(Cls, Cls)::Subclass", "function"},
125       {"std::vector<Class, std::allocator<Class>>"
126        "::_M_emplace_back_aux<Class const&>",
127        "std::vector<Class, std::allocator<Class>>",
128        "_M_emplace_back_aux<Class const&>"}};
129 
130   llvm::StringRef context, basename;
131   for (const auto &test : test_cases) {
132     EXPECT_TRUE(CPlusPlusLanguage::ExtractContextAndIdentifier(
133         test.input.c_str(), context, basename));
134     EXPECT_EQ(test.context, context.str());
135     EXPECT_EQ(test.basename, basename.str());
136   }
137 
138   EXPECT_FALSE(CPlusPlusLanguage::ExtractContextAndIdentifier("void", context,
139                                                               basename));
140   EXPECT_FALSE(
141       CPlusPlusLanguage::ExtractContextAndIdentifier("321", context, basename));
142   EXPECT_FALSE(
143       CPlusPlusLanguage::ExtractContextAndIdentifier("", context, basename));
144 }
145