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 "Plugins/Language/CPlusPlus/CPlusPlusLanguage.h" 10 #include "gmock/gmock.h" 11 #include "gtest/gtest.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 // Lambda 66 {"main::{lambda()#1}::operator()() const::{lambda()#1}::operator()() const", 67 "main::{lambda()#1}::operator()() const::{lambda()#1}", "operator()", "()", "const", 68 "main::{lambda()#1}::operator()() const::{lambda()#1}::operator()"}, 69 70 // Function pointers 71 {"string (*f(vector<int>&&))(float)", "", "f", "(vector<int>&&)", "", 72 "f"}, 73 {"void (*&std::_Any_data::_M_access<void (*)()>())()", "std::_Any_data", 74 "_M_access<void (*)()>", "()", "", 75 "std::_Any_data::_M_access<void (*)()>"}, 76 {"void (*(*(*(*(*(*(*(* const&func1(int))())())())())())())())()", "", 77 "func1", "(int)", "", "func1"}, 78 79 // Decltype 80 {"decltype(nullptr)&& std::forward<decltype(nullptr)>" 81 "(std::remove_reference<decltype(nullptr)>::type&)", 82 "std", "forward<decltype(nullptr)>", 83 "(std::remove_reference<decltype(nullptr)>::type&)", "", 84 "std::forward<decltype(nullptr)>"}, 85 86 // Templates 87 {"void llvm::PM<llvm::Module, llvm::AM<llvm::Module>>::" 88 "addPass<llvm::VP>(llvm::VP)", 89 "llvm::PM<llvm::Module, llvm::AM<llvm::Module>>", "addPass<llvm::VP>", 90 "(llvm::VP)", "", 91 "llvm::PM<llvm::Module, llvm::AM<llvm::Module>>::" 92 "addPass<llvm::VP>"}, 93 {"void std::vector<Class, std::allocator<Class> >" 94 "::_M_emplace_back_aux<Class const&>(Class const&)", 95 "std::vector<Class, std::allocator<Class> >", 96 "_M_emplace_back_aux<Class const&>", "(Class const&)", "", 97 "std::vector<Class, std::allocator<Class> >::" 98 "_M_emplace_back_aux<Class const&>"}, 99 {"unsigned long llvm::countTrailingOnes<unsigned int>" 100 "(unsigned int, llvm::ZeroBehavior)", 101 "llvm", "countTrailingOnes<unsigned int>", 102 "(unsigned int, llvm::ZeroBehavior)", "", 103 "llvm::countTrailingOnes<unsigned int>"}, 104 {"std::enable_if<(10u)<(64), bool>::type llvm::isUInt<10u>(unsigned " 105 "long)", 106 "llvm", "isUInt<10u>", "(unsigned long)", "", "llvm::isUInt<10u>"}, 107 {"f<A<operator<(X,Y)::Subclass>, sizeof(B)<sizeof(C)>()", "", 108 "f<A<operator<(X,Y)::Subclass>, sizeof(B)<sizeof(C)>", "()", "", 109 "f<A<operator<(X,Y)::Subclass>, sizeof(B)<sizeof(C)>"}}; 110 111 for (const auto &test : test_cases) { 112 CPlusPlusLanguage::MethodName method(ConstString(test.input)); 113 EXPECT_TRUE(method.IsValid()) << test.input; 114 if (method.IsValid()) { 115 EXPECT_EQ(test.context, method.GetContext().str()); 116 EXPECT_EQ(test.basename, method.GetBasename().str()); 117 EXPECT_EQ(test.arguments, method.GetArguments().str()); 118 EXPECT_EQ(test.qualifiers, method.GetQualifiers().str()); 119 EXPECT_EQ(test.scope_qualified_name, method.GetScopeQualifiedName()); 120 } 121 } 122 } 123 124 TEST(CPlusPlusLanguage, ExtractContextAndIdentifier) { 125 struct TestCase { 126 std::string input; 127 std::string context, basename; 128 }; 129 130 TestCase test_cases[] = { 131 {"main", "", "main"}, 132 {"main ", "", "main"}, 133 {"foo01::bar", "foo01", "bar"}, 134 {"foo::~bar", "foo", "~bar"}, 135 {"std::vector<int>::push_back", "std::vector<int>", "push_back"}, 136 {"operator<<(Cls, Cls)::Subclass::function", 137 "operator<<(Cls, Cls)::Subclass", "function"}, 138 {"std::vector<Class, std::allocator<Class>>" 139 "::_M_emplace_back_aux<Class const&>", 140 "std::vector<Class, std::allocator<Class>>", 141 "_M_emplace_back_aux<Class const&>"}}; 142 143 llvm::StringRef context, basename; 144 for (const auto &test : test_cases) { 145 EXPECT_TRUE(CPlusPlusLanguage::ExtractContextAndIdentifier( 146 test.input.c_str(), context, basename)); 147 EXPECT_EQ(test.context, context.str()); 148 EXPECT_EQ(test.basename, basename.str()); 149 } 150 151 EXPECT_FALSE(CPlusPlusLanguage::ExtractContextAndIdentifier("void", context, 152 basename)); 153 EXPECT_FALSE( 154 CPlusPlusLanguage::ExtractContextAndIdentifier("321", context, basename)); 155 EXPECT_FALSE( 156 CPlusPlusLanguage::ExtractContextAndIdentifier("", context, basename)); 157 EXPECT_FALSE(CPlusPlusLanguage::ExtractContextAndIdentifier( 158 "selector:", context, basename)); 159 EXPECT_FALSE(CPlusPlusLanguage::ExtractContextAndIdentifier( 160 "selector:otherField:", context, basename)); 161 EXPECT_FALSE(CPlusPlusLanguage::ExtractContextAndIdentifier( 162 "abc::", context, basename)); 163 EXPECT_FALSE(CPlusPlusLanguage::ExtractContextAndIdentifier( 164 "f<A<B><C>>", context, basename)); 165 } 166 167 static std::set<std::string> FindAlternate(llvm::StringRef Name) { 168 std::set<ConstString> Results; 169 uint32_t Count = CPlusPlusLanguage::FindAlternateFunctionManglings( 170 ConstString(Name), Results); 171 EXPECT_EQ(Count, Results.size()); 172 std::set<std::string> Strings; 173 for (ConstString Str : Results) 174 Strings.insert(Str.GetStringRef()); 175 return Strings; 176 } 177 178 TEST(CPlusPlusLanguage, FindAlternateFunctionManglings) { 179 using namespace testing; 180 181 EXPECT_THAT(FindAlternate("_ZN1A1fEv"), 182 UnorderedElementsAre("_ZNK1A1fEv", "_ZLN1A1fEv")); 183 EXPECT_THAT(FindAlternate("_ZN1A1fEa"), Contains("_ZN1A1fEc")); 184 EXPECT_THAT(FindAlternate("_ZN1A1fEx"), Contains("_ZN1A1fEl")); 185 EXPECT_THAT(FindAlternate("_ZN1A1fEy"), Contains("_ZN1A1fEm")); 186 EXPECT_THAT(FindAlternate("_ZN1A1fEai"), Contains("_ZN1A1fEci")); 187 } 188