xref: /llvm-project/lldb/unittests/Language/CPlusPlus/CPlusPlusLanguageTest.cpp (revision 89cd0e8c267f57004a734c94ff15c6bd0facf646)
180814287SRaphael Isemann //===-- CPlusPlusLanguageTest.cpp -----------------------------------------===//
29361c439SPavel Labath //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
69361c439SPavel Labath //
79361c439SPavel Labath //===----------------------------------------------------------------------===//
89361c439SPavel Labath #include "Plugins/Language/CPlusPlus/CPlusPlusLanguage.h"
94a585a3eSAdrian Prantl #include "Plugins/Language/CPlusPlus/CPlusPlusNameParser.h"
10a65f6aafSAlex Langford #include "TestingSupport/SubsystemRAII.h"
11a65f6aafSAlex Langford #include "lldb/lldb-enumerations.h"
124865ff1eSPavel Labath #include "gmock/gmock.h"
134865ff1eSPavel Labath #include "gtest/gtest.h"
14f190ce62SKazu Hirata #include <optional>
159361c439SPavel Labath 
169361c439SPavel Labath using namespace lldb_private;
179361c439SPavel Labath 
TEST(CPlusPlusLanguage,MethodNameParsing)18a633ee6eSEugene Zemtsov TEST(CPlusPlusLanguage, MethodNameParsing) {
199361c439SPavel Labath   struct TestCase {
209361c439SPavel Labath     std::string input;
2176f34ed2SMichael Buch     std::string return_type, context, basename, arguments, qualifiers,
2276f34ed2SMichael Buch         scope_qualified_name;
239361c439SPavel Labath   };
249361c439SPavel Labath 
25b9c1b51eSKate Stone   TestCase test_cases[] = {
2676f34ed2SMichael Buch       {"main(int, char *[]) ", "", "", "main", "(int, char *[])", "", "main"},
2776f34ed2SMichael Buch       {"foo::bar(baz) const", "", "foo", "bar", "(baz)", "const", "foo::bar"},
2876f34ed2SMichael Buch       {"foo::~bar(baz)", "", "foo", "~bar", "(baz)", "", "foo::~bar"},
2976f34ed2SMichael Buch       {"a::b::c::d(e,f)", "", "a::b::c", "d", "(e,f)", "", "a::b::c::d"},
3076f34ed2SMichael Buch       {"void f(int)", "void", "", "f", "(int)", "", "f"},
31a633ee6eSEugene Zemtsov 
32a633ee6eSEugene Zemtsov       // Operators
339361c439SPavel Labath       {"std::basic_ostream<char, std::char_traits<char> >& "
3476f34ed2SMichael Buch        "std::operator<<<std::char_traits<char> >(std::basic_ostream<char, "
3576f34ed2SMichael Buch        "std::char_traits<char> >&, char const*)",
3676f34ed2SMichael Buch        "std::basic_ostream<char, std::char_traits<char> >&", "std",
3776f34ed2SMichael Buch        "operator<<<std::char_traits<char> >",
389361c439SPavel Labath        "(std::basic_ostream<char, std::char_traits<char> >&, char const*)", "",
39a633ee6eSEugene Zemtsov        "std::operator<<<std::char_traits<char> >"},
40a633ee6eSEugene Zemtsov       {"operator delete[](void*, clang::ASTContext const&, unsigned long)", "",
4176f34ed2SMichael Buch        "", "operator delete[]",
4276f34ed2SMichael Buch        "(void*, clang::ASTContext const&, unsigned long)", "",
4376f34ed2SMichael Buch        "operator delete[]"},
442fe83274SKazu Hirata       {"std::optional<clang::PostInitializer>::operator bool() const", "",
452fe83274SKazu Hirata        "std::optional<clang::PostInitializer>", "operator bool", "()", "const",
462fe83274SKazu Hirata        "std::optional<clang::PostInitializer>::operator bool"},
4776f34ed2SMichael Buch       {"(anonymous namespace)::FactManager::operator[](unsigned short)", "",
48a633ee6eSEugene Zemtsov        "(anonymous namespace)::FactManager", "operator[]", "(unsigned short)",
49a633ee6eSEugene Zemtsov        "", "(anonymous namespace)::FactManager::operator[]"},
50a633ee6eSEugene Zemtsov       {"const int& std::map<int, pair<short, int>>::operator[](short) const",
5176f34ed2SMichael Buch        "const int&", "std::map<int, pair<short, int>>", "operator[]", "(short)",
5276f34ed2SMichael Buch        "const", "std::map<int, pair<short, int>>::operator[]"},
5376f34ed2SMichael Buch       {"CompareInsn::operator()(llvm::StringRef, InsnMatchEntry const&)", "",
54a633ee6eSEugene Zemtsov        "CompareInsn", "operator()", "(llvm::StringRef, InsnMatchEntry const&)",
55a633ee6eSEugene Zemtsov        "", "CompareInsn::operator()"},
562fe83274SKazu Hirata       {"std::optional<llvm::MCFixupKind>::operator*() const &", "",
572fe83274SKazu Hirata        "std::optional<llvm::MCFixupKind>", "operator*", "()", "const &",
582fe83274SKazu Hirata        "std::optional<llvm::MCFixupKind>::operator*"},
5938389f31SMichael Buch       {"auto std::__1::ranges::__begin::__fn::operator()[abi:v160000]<char "
6038389f31SMichael Buch        "const, 18ul>(char const (&) [18ul]) const",
6176f34ed2SMichael Buch        "auto", "std::__1::ranges::__begin::__fn",
6238389f31SMichael Buch        "operator()[abi:v160000]<char const, 18ul>", "(char const (&) [18ul])",
6338389f31SMichael Buch        "const",
6438389f31SMichael Buch        "std::__1::ranges::__begin::__fn::operator()[abi:v160000]<char const, "
6538389f31SMichael Buch        "18ul>"},
66a633ee6eSEugene Zemtsov       // Internal classes
6776f34ed2SMichael Buch       {"operator<<(Cls, Cls)::Subclass::function()", "",
68a633ee6eSEugene Zemtsov        "operator<<(Cls, Cls)::Subclass", "function", "()", "",
69a633ee6eSEugene Zemtsov        "operator<<(Cls, Cls)::Subclass::function"},
7076f34ed2SMichael Buch       {"SAEC::checkFunction(context&) const::CallBack::CallBack(int)", "",
71a633ee6eSEugene Zemtsov        "SAEC::checkFunction(context&) const::CallBack", "CallBack", "(int)", "",
72a633ee6eSEugene Zemtsov        "SAEC::checkFunction(context&) const::CallBack::CallBack"},
73a633ee6eSEugene Zemtsov       // Anonymous namespace
7476f34ed2SMichael Buch       {"XX::(anonymous namespace)::anon_class::anon_func() const", "",
75a633ee6eSEugene Zemtsov        "XX::(anonymous namespace)::anon_class", "anon_func", "()", "const",
76a633ee6eSEugene Zemtsov        "XX::(anonymous namespace)::anon_class::anon_func"},
77a633ee6eSEugene Zemtsov 
78055e65f0SJim Ingham       // Lambda
79a4561d93SMichael Buch       {"main::{lambda()#1}::operator()() const::{lambda()#1}::operator()() "
80a4561d93SMichael Buch        "const",
8176f34ed2SMichael Buch        "", "main::{lambda()#1}::operator()() const::{lambda()#1}", "operator()",
82a4561d93SMichael Buch        "()", "const",
83055e65f0SJim Ingham        "main::{lambda()#1}::operator()() const::{lambda()#1}::operator()"},
84055e65f0SJim Ingham 
85a633ee6eSEugene Zemtsov       // Function pointers
862fe83274SKazu Hirata       {"string (*f(vector<int>&&))(float)", "", "", "f", "(vector<int>&&)", "",
872fe83274SKazu Hirata        "f"},
8876f34ed2SMichael Buch       {"void (*&std::_Any_data::_M_access<void (*)()>())()", "",
8976f34ed2SMichael Buch        "std::_Any_data", "_M_access<void (*)()>", "()", "",
90a633ee6eSEugene Zemtsov        "std::_Any_data::_M_access<void (*)()>"},
912fe83274SKazu Hirata       {"void (*(*(*(*(*(*(*(* const&func1(int))())())())())())())())()", "", "",
922fe83274SKazu Hirata        "func1", "(int)", "", "func1"},
93a633ee6eSEugene Zemtsov 
94a633ee6eSEugene Zemtsov       // Decltype
95a633ee6eSEugene Zemtsov       {"decltype(nullptr)&& std::forward<decltype(nullptr)>"
96a633ee6eSEugene Zemtsov        "(std::remove_reference<decltype(nullptr)>::type&)",
9776f34ed2SMichael Buch        "decltype(nullptr)&&", "std", "forward<decltype(nullptr)>",
98a633ee6eSEugene Zemtsov        "(std::remove_reference<decltype(nullptr)>::type&)", "",
99a633ee6eSEugene Zemtsov        "std::forward<decltype(nullptr)>"},
100a633ee6eSEugene Zemtsov 
101a633ee6eSEugene Zemtsov       // Templates
102a633ee6eSEugene Zemtsov       {"void llvm::PM<llvm::Module, llvm::AM<llvm::Module>>::"
103a633ee6eSEugene Zemtsov        "addPass<llvm::VP>(llvm::VP)",
10476f34ed2SMichael Buch        "void", "llvm::PM<llvm::Module, llvm::AM<llvm::Module>>",
10576f34ed2SMichael Buch        "addPass<llvm::VP>", "(llvm::VP)", "",
106a633ee6eSEugene Zemtsov        "llvm::PM<llvm::Module, llvm::AM<llvm::Module>>::"
107a633ee6eSEugene Zemtsov        "addPass<llvm::VP>"},
108a633ee6eSEugene Zemtsov       {"void std::vector<Class, std::allocator<Class> >"
109a633ee6eSEugene Zemtsov        "::_M_emplace_back_aux<Class const&>(Class const&)",
11076f34ed2SMichael Buch        "void", "std::vector<Class, std::allocator<Class> >",
111a633ee6eSEugene Zemtsov        "_M_emplace_back_aux<Class const&>", "(Class const&)", "",
112a633ee6eSEugene Zemtsov        "std::vector<Class, std::allocator<Class> >::"
113a633ee6eSEugene Zemtsov        "_M_emplace_back_aux<Class const&>"},
114a633ee6eSEugene Zemtsov       {"unsigned long llvm::countTrailingOnes<unsigned int>"
115a633ee6eSEugene Zemtsov        "(unsigned int, llvm::ZeroBehavior)",
11676f34ed2SMichael Buch        "unsigned long", "llvm", "countTrailingOnes<unsigned int>",
117a633ee6eSEugene Zemtsov        "(unsigned int, llvm::ZeroBehavior)", "",
118a633ee6eSEugene Zemtsov        "llvm::countTrailingOnes<unsigned int>"},
119a633ee6eSEugene Zemtsov       {"std::enable_if<(10u)<(64), bool>::type llvm::isUInt<10u>(unsigned "
120a633ee6eSEugene Zemtsov        "long)",
12176f34ed2SMichael Buch        "std::enable_if<(10u)<(64), bool>::type", "llvm", "isUInt<10u>",
12276f34ed2SMichael Buch        "(unsigned long)", "", "llvm::isUInt<10u>"},
12376f34ed2SMichael Buch       {"f<A<operator<(X,Y)::Subclass>, sizeof(B)<sizeof(C)>()", "", "",
124a633ee6eSEugene Zemtsov        "f<A<operator<(X,Y)::Subclass>, sizeof(B)<sizeof(C)>", "()", "",
125af4cdfe1SMichael Buch        "f<A<operator<(X,Y)::Subclass>, sizeof(B)<sizeof(C)>"},
1262fe83274SKazu Hirata       {"std::optional<llvm::MCFixupKind>::operator*() const volatile &&", "",
1272fe83274SKazu Hirata        "std::optional<llvm::MCFixupKind>", "operator*", "()",
1282fe83274SKazu Hirata        "const volatile &&", "std::optional<llvm::MCFixupKind>::operator*"},
12976f34ed2SMichael Buch       {"void foo<Dummy<char [10]>>()", "void", "", "foo<Dummy<char [10]>>",
13076f34ed2SMichael Buch        "()", "", "foo<Dummy<char [10]>>"},
13176f34ed2SMichael Buch       {"void foo<Bar<Bar<int>[10]>>()", "void", "", "foo<Bar<Bar<int>[10]>>",
13276f34ed2SMichael Buch        "()", "", "foo<Bar<Bar<int>[10]>>"},
13376f34ed2SMichael Buch       {"void foo<Bar[10]>()", "void", "", "foo<Bar[10]>", "()", "",
13446d84286SMichael Buch        "foo<Bar[10]>"},
13576f34ed2SMichael Buch       {"void foo<Bar[]>()", "void", "", "foo<Bar[]>", "()", "", "foo<Bar[]>"},
136a4561d93SMichael Buch 
137a4561d93SMichael Buch       // auto return type
13876f34ed2SMichael Buch       {"auto std::test_return_auto<int>() const", "auto", "std",
139a4561d93SMichael Buch        "test_return_auto<int>", "()", "const", "std::test_return_auto<int>"},
14076f34ed2SMichael Buch       {"decltype(auto) std::test_return_auto<int>(int) const", "decltype(auto)",
14176f34ed2SMichael Buch        "std", "test_return_auto<int>", "(int)", "const",
14276f34ed2SMichael Buch        "std::test_return_auto<int>"},
1433cc98845SMichael Buch 
1443cc98845SMichael Buch       // abi_tag on class method
1453cc98845SMichael Buch       {"v1::v2::Dummy[abi:c1][abi:c2]<v1::v2::Dummy[abi:c1][abi:c2]<int>> "
1463cc98845SMichael Buch        "v1::v2::Dummy[abi:c1][abi:c2]<v1::v2::Dummy[abi:c1][abi:c2]<int>>"
1473cc98845SMichael Buch        "::method2<v1::v2::Dummy[abi:c1][abi:c2]<v1::v2::Dummy[abi:c1][abi:c2]<"
1483cc98845SMichael Buch        "int>>>(int, v1::v2::Dummy<int>) const &&",
14976f34ed2SMichael Buch        // Return type
15076f34ed2SMichael Buch        "v1::v2::Dummy[abi:c1][abi:c2]<v1::v2::Dummy[abi:c1][abi:c2]<int>>",
1513cc98845SMichael Buch        // Context
1523cc98845SMichael Buch        "v1::v2::Dummy[abi:c1][abi:c2]<v1::v2::Dummy[abi:c1][abi:c2]<int>>",
1533cc98845SMichael Buch        // Basename
1543cc98845SMichael Buch        "method2<v1::v2::Dummy[abi:c1][abi:c2]<v1::v2::Dummy[abi:c1][abi:c2]<"
1553cc98845SMichael Buch        "int>>>",
1563cc98845SMichael Buch        // Args, qualifiers
1573cc98845SMichael Buch        "(int, v1::v2::Dummy<int>)", "const &&",
1583cc98845SMichael Buch        // Full scope-qualified name without args
1593cc98845SMichael Buch        "v1::v2::Dummy[abi:c1][abi:c2]<v1::v2::Dummy[abi:c1][abi:c2]<int>>"
1603cc98845SMichael Buch        "::method2<v1::v2::Dummy[abi:c1][abi:c2]<v1::v2::Dummy[abi:c1][abi:c2]<"
1613cc98845SMichael Buch        "int>>>"},
1623cc98845SMichael Buch 
1633cc98845SMichael Buch       // abi_tag on free function and template argument
1643cc98845SMichael Buch       {"v1::v2::Dummy[abi:c1][abi:c2]<v1::v2::Dummy[abi:c1][abi:c2]<int>> "
1653cc98845SMichael Buch        "v1::v2::with_tag_in_ns[abi:f1][abi:f2]<v1::v2::Dummy[abi:c1][abi:c2]"
1663cc98845SMichael Buch        "<v1::v2::Dummy[abi:c1][abi:c2]<int>>>(int, v1::v2::Dummy<int>) const "
1673cc98845SMichael Buch        "&&",
16876f34ed2SMichael Buch        // Return type
16976f34ed2SMichael Buch        "v1::v2::Dummy[abi:c1][abi:c2]<v1::v2::Dummy[abi:c1][abi:c2]<int>>",
1703cc98845SMichael Buch        // Context
1713cc98845SMichael Buch        "v1::v2",
1723cc98845SMichael Buch        // Basename
1733cc98845SMichael Buch        "with_tag_in_ns[abi:f1][abi:f2]<v1::v2::Dummy[abi:c1][abi:c2]<v1::v2::"
1743cc98845SMichael Buch        "Dummy[abi:c1][abi:c2]<int>>>",
1753cc98845SMichael Buch        // Args, qualifiers
1763cc98845SMichael Buch        "(int, v1::v2::Dummy<int>)", "const &&",
1773cc98845SMichael Buch        // Full scope-qualified name without args
1783cc98845SMichael Buch        "v1::v2::with_tag_in_ns[abi:f1][abi:f2]<v1::v2::Dummy[abi:c1][abi:c2]<"
1793cc98845SMichael Buch        "v1::v2::Dummy[abi:c1][abi:c2]<int>>>"},
1803cc98845SMichael Buch 
1813cc98845SMichael Buch       // abi_tag with special characters
1823cc98845SMichael Buch       {"auto ns::with_tag_in_ns[abi:special tag,0.0][abi:special "
1833cc98845SMichael Buch        "tag,1.0]<Dummy<int>>"
1843cc98845SMichael Buch        "(float) const &&",
18576f34ed2SMichael Buch        // Return type
18676f34ed2SMichael Buch        "auto",
1873cc98845SMichael Buch        // Context
1883cc98845SMichael Buch        "ns",
1893cc98845SMichael Buch        // Basename
1903cc98845SMichael Buch        "with_tag_in_ns[abi:special tag,0.0][abi:special tag,1.0]<Dummy<int>>",
1913cc98845SMichael Buch        // Args, qualifiers
1923cc98845SMichael Buch        "(float)", "const &&",
1933cc98845SMichael Buch        // Full scope-qualified name without args
1943cc98845SMichael Buch        "ns::with_tag_in_ns[abi:special tag,0.0][abi:special "
1953cc98845SMichael Buch        "tag,1.0]<Dummy<int>>"},
1963cc98845SMichael Buch 
1973cc98845SMichael Buch       // abi_tag on operator overloads
19876f34ed2SMichael Buch       {"std::__1::error_code::operator bool[abi:v160000]() const", "",
1993cc98845SMichael Buch        "std::__1::error_code", "operator bool[abi:v160000]", "()", "const",
2003cc98845SMichael Buch        "std::__1::error_code::operator bool[abi:v160000]"},
2013cc98845SMichael Buch 
20276f34ed2SMichael Buch       {"auto ns::foo::operator[][abi:v160000](size_t) const", "auto", "ns::foo",
2033cc98845SMichael Buch        "operator[][abi:v160000]", "(size_t)", "const",
2043cc98845SMichael Buch        "ns::foo::operator[][abi:v160000]"},
2053cc98845SMichael Buch 
20676f34ed2SMichael Buch       {"auto Foo[abi:abc]<int>::operator<<<Foo[abi:abc]<int>>(int) &", "auto",
2073cc98845SMichael Buch        "Foo[abi:abc]<int>", "operator<<<Foo[abi:abc]<int>>", "(int)", "&",
208*89cd0e8cSMichael Buch        "Foo[abi:abc]<int>::operator<<<Foo[abi:abc]<int>>"},
209*89cd0e8cSMichael Buch 
210*89cd0e8cSMichael Buch       {"auto A::operator<=>[abi:tag]<A::B>()", "auto", "A",
211*89cd0e8cSMichael Buch        "operator<=>[abi:tag]<A::B>", "()", "",
212*89cd0e8cSMichael Buch        "A::operator<=>[abi:tag]<A::B>"}};
2139361c439SPavel Labath 
214b9c1b51eSKate Stone   for (const auto &test : test_cases) {
2159361c439SPavel Labath     CPlusPlusLanguage::MethodName method(ConstString(test.input));
216a633ee6eSEugene Zemtsov     EXPECT_TRUE(method.IsValid()) << test.input;
217a633ee6eSEugene Zemtsov     if (method.IsValid()) {
21876f34ed2SMichael Buch       EXPECT_EQ(test.return_type, method.GetReturnType().str());
219a633ee6eSEugene Zemtsov       EXPECT_EQ(test.context, method.GetContext().str());
220a633ee6eSEugene Zemtsov       EXPECT_EQ(test.basename, method.GetBasename().str());
221a633ee6eSEugene Zemtsov       EXPECT_EQ(test.arguments, method.GetArguments().str());
222a633ee6eSEugene Zemtsov       EXPECT_EQ(test.qualifiers, method.GetQualifiers().str());
2239361c439SPavel Labath       EXPECT_EQ(test.scope_qualified_name, method.GetScopeQualifiedName());
2249361c439SPavel Labath     }
2259361c439SPavel Labath   }
226a633ee6eSEugene Zemtsov }
227a633ee6eSEugene Zemtsov 
TEST(CPlusPlusLanguage,InvalidMethodNameParsing)2283cc98845SMichael Buch TEST(CPlusPlusLanguage, InvalidMethodNameParsing) {
2293cc98845SMichael Buch   // Tests that we correctly reject malformed function names
2303cc98845SMichael Buch 
2313cc98845SMichael Buch   std::string test_cases[] = {
2323cc98845SMichael Buch       "int Foo::operator[]<[10>()",
2333cc98845SMichael Buch       "Foo::operator bool[10]()",
2343cc98845SMichael Buch       "auto A::operator<<<(int)",
2353cc98845SMichael Buch       "auto A::operator>>>(int)",
2363cc98845SMichael Buch       "auto A::operator<<<Type[abi:tag]<>(int)",
2373cc98845SMichael Buch       "auto A::operator<<<Type[abi:tag]<Type<int>>(int)",
2383cc98845SMichael Buch       "auto A::foo[(int)",
2393cc98845SMichael Buch       "auto A::foo[](int)",
2403cc98845SMichael Buch       "auto A::foo[bar](int)",
2413cc98845SMichael Buch       "auto A::foo[abi](int)",
2423cc98845SMichael Buch       "auto A::foo[abi:(int)",
2433cc98845SMichael Buch   };
2443cc98845SMichael Buch 
2453cc98845SMichael Buch   for (const auto &name : test_cases) {
2463cc98845SMichael Buch     CPlusPlusLanguage::MethodName method{ConstString(name)};
2473cc98845SMichael Buch     EXPECT_FALSE(method.IsValid()) << name;
2483cc98845SMichael Buch   }
2493cc98845SMichael Buch }
2503cc98845SMichael Buch 
TEST(CPlusPlusLanguage,ContainsPath)2513339000eSJim Ingham TEST(CPlusPlusLanguage, ContainsPath) {
2523339000eSJim Ingham   CPlusPlusLanguage::MethodName
2533339000eSJim Ingham       reference_1(ConstString("int foo::bar::func01(int a, double b)"));
2543339000eSJim Ingham   CPlusPlusLanguage::MethodName
2553339000eSJim Ingham       reference_2(ConstString("int foofoo::bar::func01(std::string a, int b)"));
2563339000eSJim Ingham   CPlusPlusLanguage::MethodName reference_3(ConstString("int func01()"));
2573339000eSJim Ingham   CPlusPlusLanguage::MethodName
2583339000eSJim Ingham       reference_4(ConstString("bar::baz::operator bool()"));
259d4a55ad3SMichael Buch   CPlusPlusLanguage::MethodName reference_5(
260d4a55ad3SMichael Buch       ConstString("bar::baz::operator bool<int, Type<double>>()"));
261d4a55ad3SMichael Buch   CPlusPlusLanguage::MethodName reference_6(ConstString(
262d4a55ad3SMichael Buch       "bar::baz::operator<<<Type<double>, Type<std::vector<double>>>()"));
2633339000eSJim Ingham 
264d4a55ad3SMichael Buch   EXPECT_TRUE(reference_1.ContainsPath(""));
2653339000eSJim Ingham   EXPECT_TRUE(reference_1.ContainsPath("func01"));
2663339000eSJim Ingham   EXPECT_TRUE(reference_1.ContainsPath("bar::func01"));
2673339000eSJim Ingham   EXPECT_TRUE(reference_1.ContainsPath("foo::bar::func01"));
2683339000eSJim Ingham   EXPECT_FALSE(reference_1.ContainsPath("func"));
2693339000eSJim Ingham   EXPECT_FALSE(reference_1.ContainsPath("baz::func01"));
2703339000eSJim Ingham   EXPECT_FALSE(reference_1.ContainsPath("::bar::func01"));
2713339000eSJim Ingham   EXPECT_FALSE(reference_1.ContainsPath("::foo::baz::func01"));
2723339000eSJim Ingham   EXPECT_FALSE(reference_1.ContainsPath("foo::bar::baz::func01"));
2733339000eSJim Ingham 
274d4a55ad3SMichael Buch   EXPECT_TRUE(reference_2.ContainsPath(""));
2753339000eSJim Ingham   EXPECT_TRUE(reference_2.ContainsPath("foofoo::bar::func01"));
2763339000eSJim Ingham   EXPECT_FALSE(reference_2.ContainsPath("foo::bar::func01"));
2773339000eSJim Ingham 
278d4a55ad3SMichael Buch   EXPECT_TRUE(reference_3.ContainsPath(""));
2793339000eSJim Ingham   EXPECT_TRUE(reference_3.ContainsPath("func01"));
2803339000eSJim Ingham   EXPECT_FALSE(reference_3.ContainsPath("func"));
2813339000eSJim Ingham   EXPECT_FALSE(reference_3.ContainsPath("bar::func01"));
2823339000eSJim Ingham 
283d4a55ad3SMichael Buch   EXPECT_TRUE(reference_4.ContainsPath(""));
284d4a55ad3SMichael Buch   EXPECT_TRUE(reference_4.ContainsPath("operator"));
2853339000eSJim Ingham   EXPECT_TRUE(reference_4.ContainsPath("operator bool"));
2863339000eSJim Ingham   EXPECT_TRUE(reference_4.ContainsPath("baz::operator bool"));
2873339000eSJim Ingham   EXPECT_TRUE(reference_4.ContainsPath("bar::baz::operator bool"));
2883339000eSJim Ingham   EXPECT_FALSE(reference_4.ContainsPath("az::operator bool"));
289d4a55ad3SMichael Buch 
290d4a55ad3SMichael Buch   EXPECT_TRUE(reference_5.ContainsPath(""));
291d4a55ad3SMichael Buch   EXPECT_TRUE(reference_5.ContainsPath("operator"));
292d4a55ad3SMichael Buch   EXPECT_TRUE(reference_5.ContainsPath("operator bool"));
293d4a55ad3SMichael Buch   EXPECT_TRUE(reference_5.ContainsPath("operator bool<int, Type<double>>"));
294d4a55ad3SMichael Buch   EXPECT_FALSE(reference_5.ContainsPath("operator bool<int, double>"));
295d4a55ad3SMichael Buch   EXPECT_FALSE(reference_5.ContainsPath("operator bool<int, Type<int>>"));
296d4a55ad3SMichael Buch 
297d4a55ad3SMichael Buch   EXPECT_TRUE(reference_6.ContainsPath(""));
298d4a55ad3SMichael Buch   EXPECT_TRUE(reference_6.ContainsPath("operator"));
299d4a55ad3SMichael Buch   EXPECT_TRUE(reference_6.ContainsPath("operator<<"));
300d4a55ad3SMichael Buch   EXPECT_TRUE(reference_6.ContainsPath(
301d4a55ad3SMichael Buch       "bar::baz::operator<<<Type<double>, Type<std::vector<double>>>()"));
302d4a55ad3SMichael Buch   EXPECT_FALSE(reference_6.ContainsPath("operator<<<Type<double>>"));
3033339000eSJim Ingham }
3043339000eSJim Ingham 
TEST(CPlusPlusLanguage,ExtractContextAndIdentifier)305a633ee6eSEugene Zemtsov TEST(CPlusPlusLanguage, ExtractContextAndIdentifier) {
306a633ee6eSEugene Zemtsov   struct TestCase {
307a633ee6eSEugene Zemtsov     std::string input;
308a633ee6eSEugene Zemtsov     std::string context, basename;
309a633ee6eSEugene Zemtsov   };
310a633ee6eSEugene Zemtsov 
311a633ee6eSEugene Zemtsov   TestCase test_cases[] = {
312a633ee6eSEugene Zemtsov       {"main", "", "main"},
31357537102SEugene Zemtsov       {"main     ", "", "main"},
314a633ee6eSEugene Zemtsov       {"foo01::bar", "foo01", "bar"},
315a633ee6eSEugene Zemtsov       {"foo::~bar", "foo", "~bar"},
316a633ee6eSEugene Zemtsov       {"std::vector<int>::push_back", "std::vector<int>", "push_back"},
317a633ee6eSEugene Zemtsov       {"operator<<(Cls, Cls)::Subclass::function",
318a633ee6eSEugene Zemtsov        "operator<<(Cls, Cls)::Subclass", "function"},
319a633ee6eSEugene Zemtsov       {"std::vector<Class, std::allocator<Class>>"
320a633ee6eSEugene Zemtsov        "::_M_emplace_back_aux<Class const&>",
321a633ee6eSEugene Zemtsov        "std::vector<Class, std::allocator<Class>>",
322c1e530eeSAleksandr Urakov        "_M_emplace_back_aux<Class const&>"},
323c1e530eeSAleksandr Urakov       {"`anonymous namespace'::foo", "`anonymous namespace'", "foo"},
3248016d61eSshafik       {"`operator<<A>'::`2'::B<0>::operator>", "`operator<<A>'::`2'::B<0>",
325c1e530eeSAleksandr Urakov        "operator>"},
326c1e530eeSAleksandr Urakov       {"`anonymous namespace'::S::<<::__l2::Foo",
3278016d61eSshafik        "`anonymous namespace'::S::<<::__l2", "Foo"},
3288016d61eSshafik       // These cases are idiosyncratic in how clang generates debug info for
3298016d61eSshafik       // names when we have template parameters. They are not valid C++ names
3308016d61eSshafik       // but if we fix this we need to support them for older compilers.
3318016d61eSshafik       {"A::operator><A::B>", "A", "operator><A::B>"},
3328016d61eSshafik       {"operator><A::B>", "", "operator><A::B>"},
3338016d61eSshafik       {"A::operator<<A::B>", "A", "operator<<A::B>"},
3348016d61eSshafik       {"operator<<A::B>", "", "operator<<A::B>"},
3358016d61eSshafik       {"A::operator<<<A::B>", "A", "operator<<<A::B>"},
3368016d61eSshafik       {"operator<<<A::B>", "", "operator<<<A::B>"},
3378016d61eSshafik   };
338a633ee6eSEugene Zemtsov 
339a633ee6eSEugene Zemtsov   llvm::StringRef context, basename;
340a633ee6eSEugene Zemtsov   for (const auto &test : test_cases) {
341a633ee6eSEugene Zemtsov     EXPECT_TRUE(CPlusPlusLanguage::ExtractContextAndIdentifier(
342a633ee6eSEugene Zemtsov         test.input.c_str(), context, basename));
343a633ee6eSEugene Zemtsov     EXPECT_EQ(test.context, context.str());
344a633ee6eSEugene Zemtsov     EXPECT_EQ(test.basename, basename.str());
345a633ee6eSEugene Zemtsov   }
346a633ee6eSEugene Zemtsov 
347a633ee6eSEugene Zemtsov   EXPECT_FALSE(CPlusPlusLanguage::ExtractContextAndIdentifier("void", context,
348a633ee6eSEugene Zemtsov                                                               basename));
349a633ee6eSEugene Zemtsov   EXPECT_FALSE(
350a633ee6eSEugene Zemtsov       CPlusPlusLanguage::ExtractContextAndIdentifier("321", context, basename));
351a633ee6eSEugene Zemtsov   EXPECT_FALSE(
352a633ee6eSEugene Zemtsov       CPlusPlusLanguage::ExtractContextAndIdentifier("", context, basename));
353a633ee6eSEugene Zemtsov   EXPECT_FALSE(CPlusPlusLanguage::ExtractContextAndIdentifier(
354a633ee6eSEugene Zemtsov       "selector:", context, basename));
35557537102SEugene Zemtsov   EXPECT_FALSE(CPlusPlusLanguage::ExtractContextAndIdentifier(
35657537102SEugene Zemtsov       "selector:otherField:", context, basename));
35757537102SEugene Zemtsov   EXPECT_FALSE(CPlusPlusLanguage::ExtractContextAndIdentifier(
35857537102SEugene Zemtsov       "abc::", context, basename));
3599e916e5eSEugene Zemtsov   EXPECT_FALSE(CPlusPlusLanguage::ExtractContextAndIdentifier(
3609e916e5eSEugene Zemtsov       "f<A<B><C>>", context, basename));
3618016d61eSshafik 
362*89cd0e8cSMichael Buch   EXPECT_TRUE(CPlusPlusLanguage::ExtractContextAndIdentifier(
3638016d61eSshafik       "A::operator<=><A::B>", context, basename));
364*89cd0e8cSMichael Buch   EXPECT_TRUE(CPlusPlusLanguage::ExtractContextAndIdentifier(
3658016d61eSshafik       "operator<=><A::B>", context, basename));
366a633ee6eSEugene Zemtsov }
3674865ff1eSPavel Labath 
GenerateAlternate(llvm::StringRef Name)368a65f6aafSAlex Langford static std::vector<std::string> GenerateAlternate(llvm::StringRef Name) {
369a65f6aafSAlex Langford   std::vector<std::string> Strings;
370a65f6aafSAlex Langford   if (Language *CPlusPlusLang =
371a65f6aafSAlex Langford           Language::FindPlugin(lldb::eLanguageTypeC_plus_plus)) {
372a65f6aafSAlex Langford     std::vector<ConstString> Results =
373a65f6aafSAlex Langford         CPlusPlusLang->GenerateAlternateFunctionManglings(ConstString(Name));
3744865ff1eSPavel Labath     for (ConstString Str : Results)
375a65f6aafSAlex Langford       Strings.push_back(std::string(Str.GetStringRef()));
376a65f6aafSAlex Langford   }
3774865ff1eSPavel Labath   return Strings;
3784865ff1eSPavel Labath }
3794865ff1eSPavel Labath 
TEST(CPlusPlusLanguage,GenerateAlternateFunctionManglings)380a65f6aafSAlex Langford TEST(CPlusPlusLanguage, GenerateAlternateFunctionManglings) {
3814865ff1eSPavel Labath   using namespace testing;
3824865ff1eSPavel Labath 
383a65f6aafSAlex Langford   SubsystemRAII<CPlusPlusLanguage> lang;
384a65f6aafSAlex Langford 
385a65f6aafSAlex Langford   EXPECT_THAT(GenerateAlternate("_ZN1A1fEv"),
3864865ff1eSPavel Labath               UnorderedElementsAre("_ZNK1A1fEv", "_ZLN1A1fEv"));
387a65f6aafSAlex Langford   EXPECT_THAT(GenerateAlternate("_ZN1A1fEa"), Contains("_ZN1A1fEc"));
388a65f6aafSAlex Langford   EXPECT_THAT(GenerateAlternate("_ZN1A1fEx"), Contains("_ZN1A1fEl"));
389a65f6aafSAlex Langford   EXPECT_THAT(GenerateAlternate("_ZN1A1fEy"), Contains("_ZN1A1fEm"));
390a65f6aafSAlex Langford   EXPECT_THAT(GenerateAlternate("_ZN1A1fEai"), Contains("_ZN1A1fEci"));
391a65f6aafSAlex Langford   EXPECT_THAT(GenerateAlternate("_ZN1AC1Ev"), Contains("_ZN1AC2Ev"));
392a65f6aafSAlex Langford   EXPECT_THAT(GenerateAlternate("_ZN1AD1Ev"), Contains("_ZN1AD2Ev"));
393a65f6aafSAlex Langford   EXPECT_THAT(GenerateAlternate("_bogus"), IsEmpty());
3944865ff1eSPavel Labath }
3954a585a3eSAdrian Prantl 
TEST(CPlusPlusLanguage,CPlusPlusNameParser)3964a585a3eSAdrian Prantl TEST(CPlusPlusLanguage, CPlusPlusNameParser) {
3974a585a3eSAdrian Prantl   // Don't crash.
3984a585a3eSAdrian Prantl   CPlusPlusNameParser((const char *)nullptr);
3994a585a3eSAdrian Prantl }
400