Michael137 created this revision.
Michael137 added reviewers: labath, aprantl.
Herald added a project: All.
Michael137 requested review of this revision.
Herald added a project: LLDB.
Herald added a subscriber: lldb-commits.

This patch adds a way to extract the return type out
of the `CPlusPlusNameParser`. This will be useful
for cases where we want a function's basename *and* the
return type but not the function arguments; this is
currently not possible (the parser either gives us the
full name or just the basename). Since the parser knows
how to handle return types already we should just expose
this to users that need it.

**Testing**

- Added unit-tests


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D136935

Files:
  lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
  lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h
  lldb/source/Plugins/Language/CPlusPlus/CPlusPlusNameParser.cpp
  lldb/source/Plugins/Language/CPlusPlus/CPlusPlusNameParser.h
  lldb/unittests/Language/CPlusPlus/CPlusPlusLanguageTest.cpp

Index: lldb/unittests/Language/CPlusPlus/CPlusPlusLanguageTest.cpp
===================================================================
--- lldb/unittests/Language/CPlusPlus/CPlusPlusLanguageTest.cpp
+++ lldb/unittests/Language/CPlusPlus/CPlusPlusLanguageTest.cpp
@@ -17,130 +17,136 @@
 TEST(CPlusPlusLanguage, MethodNameParsing) {
   struct TestCase {
     std::string input;
-    std::string context, basename, arguments, qualifiers, scope_qualified_name;
+    std::string return_type, context, basename, arguments, qualifiers,
+        scope_qualified_name;
   };
 
   TestCase test_cases[] = {
-      {"main(int, char *[]) ", "", "main", "(int, char *[])", "", "main"},
-      {"foo::bar(baz) const", "foo", "bar", "(baz)", "const", "foo::bar"},
-      {"foo::~bar(baz)", "foo", "~bar", "(baz)", "", "foo::~bar"},
-      {"a::b::c::d(e,f)", "a::b::c", "d", "(e,f)", "", "a::b::c::d"},
-      {"void f(int)", "", "f", "(int)", "", "f"},
+      {"main(int, char *[]) ", "", "", "main", "(int, char *[])", "", "main"},
+      {"foo::bar(baz) const", "", "foo", "bar", "(baz)", "const", "foo::bar"},
+      {"foo::~bar(baz)", "", "foo", "~bar", "(baz)", "", "foo::~bar"},
+      {"a::b::c::d(e,f)", "", "a::b::c", "d", "(e,f)", "", "a::b::c::d"},
+      {"void f(int)", "void", "", "f", "(int)", "", "f"},
 
       // Operators
       {"std::basic_ostream<char, std::char_traits<char> >& "
        "std::operator<<<std::char_traits<char> >"
+       "std::basic_ostream<char, std::char_traits<char> >&",
        "(std::basic_ostream<char, std::char_traits<char> >&, char const*)",
        "std", "operator<<<std::char_traits<char> >",
        "(std::basic_ostream<char, std::char_traits<char> >&, char const*)", "",
        "std::operator<<<std::char_traits<char> >"},
       {"operator delete[](void*, clang::ASTContext const&, unsigned long)", "",
-       "operator delete[]", "(void*, clang::ASTContext const&, unsigned long)",
-       "", "operator delete[]"},
-      {"llvm::Optional<clang::PostInitializer>::operator bool() const",
+       "", "operator delete[]",
+       "(void*, clang::ASTContext const&, unsigned long)", "",
+       "operator delete[]"},
+      {"llvm::Optional<clang::PostInitializer>::operator bool() const", "",
        "llvm::Optional<clang::PostInitializer>", "operator bool", "()", "const",
        "llvm::Optional<clang::PostInitializer>::operator bool"},
-      {"(anonymous namespace)::FactManager::operator[](unsigned short)",
+      {"(anonymous namespace)::FactManager::operator[](unsigned short)", "",
        "(anonymous namespace)::FactManager", "operator[]", "(unsigned short)",
        "", "(anonymous namespace)::FactManager::operator[]"},
       {"const int& std::map<int, pair<short, int>>::operator[](short) const",
-       "std::map<int, pair<short, int>>", "operator[]", "(short)", "const",
-       "std::map<int, pair<short, int>>::operator[]"},
-      {"CompareInsn::operator()(llvm::StringRef, InsnMatchEntry const&)",
+       "const int&", "std::map<int, pair<short, int>>", "operator[]", "(short)",
+       "const", "std::map<int, pair<short, int>>::operator[]"},
+      {"CompareInsn::operator()(llvm::StringRef, InsnMatchEntry const&)", "",
        "CompareInsn", "operator()", "(llvm::StringRef, InsnMatchEntry const&)",
        "", "CompareInsn::operator()"},
-      {"llvm::Optional<llvm::MCFixupKind>::operator*() const &",
+      {"llvm::Optional<llvm::MCFixupKind>::operator*() const &", "",
        "llvm::Optional<llvm::MCFixupKind>", "operator*", "()", "const &",
        "llvm::Optional<llvm::MCFixupKind>::operator*"},
       {"auto std::__1::ranges::__begin::__fn::operator()[abi:v160000]<char "
        "const, 18ul>(char const (&) [18ul]) const",
-       "std::__1::ranges::__begin::__fn",
+       "auto", "std::__1::ranges::__begin::__fn",
        "operator()[abi:v160000]<char const, 18ul>", "(char const (&) [18ul])",
        "const",
        "std::__1::ranges::__begin::__fn::operator()[abi:v160000]<char const, "
        "18ul>"},
       // Internal classes
-      {"operator<<(Cls, Cls)::Subclass::function()",
+      {"operator<<(Cls, Cls)::Subclass::function()", "",
        "operator<<(Cls, Cls)::Subclass", "function", "()", "",
        "operator<<(Cls, Cls)::Subclass::function"},
-      {"SAEC::checkFunction(context&) const::CallBack::CallBack(int)",
+      {"SAEC::checkFunction(context&) const::CallBack::CallBack(int)", "",
        "SAEC::checkFunction(context&) const::CallBack", "CallBack", "(int)", "",
        "SAEC::checkFunction(context&) const::CallBack::CallBack"},
       // Anonymous namespace
-      {"XX::(anonymous namespace)::anon_class::anon_func() const",
+      {"XX::(anonymous namespace)::anon_class::anon_func() const", "",
        "XX::(anonymous namespace)::anon_class", "anon_func", "()", "const",
        "XX::(anonymous namespace)::anon_class::anon_func"},
 
       // Lambda
       {"main::{lambda()#1}::operator()() const::{lambda()#1}::operator()() "
        "const",
-       "main::{lambda()#1}::operator()() const::{lambda()#1}", "operator()",
+       "", "main::{lambda()#1}::operator()() const::{lambda()#1}", "operator()",
        "()", "const",
        "main::{lambda()#1}::operator()() const::{lambda()#1}::operator()"},
 
       // Function pointers
-      {"string (*f(vector<int>&&))(float)", "", "f", "(vector<int>&&)", "",
-       "f"},
-      {"void (*&std::_Any_data::_M_access<void (*)()>())()", "std::_Any_data",
-       "_M_access<void (*)()>", "()", "",
+      {"string (*f(vector<int>&&))(float)", "string", "", "f",
+       "(vector<int>&&)", "", "f"},
+      {"void (*&std::_Any_data::_M_access<void (*)()>())()", "void",
+       "std::_Any_data", "_M_access<void (*)()>", "()", "",
        "std::_Any_data::_M_access<void (*)()>"},
-      {"void (*(*(*(*(*(*(*(* const&func1(int))())())())())())())())()", "",
-       "func1", "(int)", "", "func1"},
+      {"void (*(*(*(*(*(*(*(* const&func1(int))())())())())())())())()", "void",
+       "", "func1", "(int)", "", "func1"},
 
       // Decltype
       {"decltype(nullptr)&& std::forward<decltype(nullptr)>"
        "(std::remove_reference<decltype(nullptr)>::type&)",
-       "std", "forward<decltype(nullptr)>",
+       "decltype(nullptr)&&", "std", "forward<decltype(nullptr)>",
        "(std::remove_reference<decltype(nullptr)>::type&)", "",
        "std::forward<decltype(nullptr)>"},
 
       // Templates
       {"void llvm::PM<llvm::Module, llvm::AM<llvm::Module>>::"
        "addPass<llvm::VP>(llvm::VP)",
-       "llvm::PM<llvm::Module, llvm::AM<llvm::Module>>", "addPass<llvm::VP>",
-       "(llvm::VP)", "",
+       "void", "llvm::PM<llvm::Module, llvm::AM<llvm::Module>>",
+       "addPass<llvm::VP>", "(llvm::VP)", "",
        "llvm::PM<llvm::Module, llvm::AM<llvm::Module>>::"
        "addPass<llvm::VP>"},
       {"void std::vector<Class, std::allocator<Class> >"
        "::_M_emplace_back_aux<Class const&>(Class const&)",
-       "std::vector<Class, std::allocator<Class> >",
+       "void", "std::vector<Class, std::allocator<Class> >",
        "_M_emplace_back_aux<Class const&>", "(Class const&)", "",
        "std::vector<Class, std::allocator<Class> >::"
        "_M_emplace_back_aux<Class const&>"},
       {"unsigned long llvm::countTrailingOnes<unsigned int>"
        "(unsigned int, llvm::ZeroBehavior)",
-       "llvm", "countTrailingOnes<unsigned int>",
+       "unsigned long", "llvm", "countTrailingOnes<unsigned int>",
        "(unsigned int, llvm::ZeroBehavior)", "",
        "llvm::countTrailingOnes<unsigned int>"},
       {"std::enable_if<(10u)<(64), bool>::type llvm::isUInt<10u>(unsigned "
        "long)",
-       "llvm", "isUInt<10u>", "(unsigned long)", "", "llvm::isUInt<10u>"},
-      {"f<A<operator<(X,Y)::Subclass>, sizeof(B)<sizeof(C)>()", "",
+       "std::enable_if<(10u)<(64), bool>::type", "llvm", "isUInt<10u>",
+       "(unsigned long)", "", "llvm::isUInt<10u>"},
+      {"f<A<operator<(X,Y)::Subclass>, sizeof(B)<sizeof(C)>()", "", "",
        "f<A<operator<(X,Y)::Subclass>, sizeof(B)<sizeof(C)>", "()", "",
        "f<A<operator<(X,Y)::Subclass>, sizeof(B)<sizeof(C)>"},
-      {"llvm::Optional<llvm::MCFixupKind>::operator*() const volatile &&",
+      {"llvm::Optional<llvm::MCFixupKind>::operator*() const volatile &&", "",
        "llvm::Optional<llvm::MCFixupKind>", "operator*", "()",
        "const volatile &&", "llvm::Optional<llvm::MCFixupKind>::operator*"},
-      {"void foo<Dummy<char [10]>>()", "", "foo<Dummy<char [10]>>", "()", "",
-       "foo<Dummy<char [10]>>"},
-      {"void foo<Bar<Bar<int>[10]>>()", "", "foo<Bar<Bar<int>[10]>>", "()", "",
-       "foo<Bar<Bar<int>[10]>>"},
-      {"void foo<Bar[10]>()", "", "foo<Bar[10]>", "()", "",
+      {"void foo<Dummy<char [10]>>()", "void", "", "foo<Dummy<char [10]>>",
+       "()", "", "foo<Dummy<char [10]>>"},
+      {"void foo<Bar<Bar<int>[10]>>()", "void", "", "foo<Bar<Bar<int>[10]>>",
+       "()", "", "foo<Bar<Bar<int>[10]>>"},
+      {"void foo<Bar[10]>()", "void", "", "foo<Bar[10]>", "()", "",
        "foo<Bar[10]>"},
-      {"void foo<Bar[]>()", "", "foo<Bar[]>", "()", "",
-       "foo<Bar[]>"},
+      {"void foo<Bar[]>()", "void", "", "foo<Bar[]>", "()", "", "foo<Bar[]>"},
 
       // auto return type
-      {"auto std::test_return_auto<int>() const", "std",
+      {"auto std::test_return_auto<int>() const", "auto", "std",
        "test_return_auto<int>", "()", "const", "std::test_return_auto<int>"},
-      {"decltype(auto) std::test_return_auto<int>(int) const", "std",
-       "test_return_auto<int>", "(int)", "const", "std::test_return_auto<int>"},
+      {"decltype(auto) std::test_return_auto<int>(int) const", "decltype(auto)",
+       "std", "test_return_auto<int>", "(int)", "const",
+       "std::test_return_auto<int>"},
 
       // abi_tag on class method
       {"v1::v2::Dummy[abi:c1][abi:c2]<v1::v2::Dummy[abi:c1][abi:c2]<int>> "
        "v1::v2::Dummy[abi:c1][abi:c2]<v1::v2::Dummy[abi:c1][abi:c2]<int>>"
        "::method2<v1::v2::Dummy[abi:c1][abi:c2]<v1::v2::Dummy[abi:c1][abi:c2]<"
        "int>>>(int, v1::v2::Dummy<int>) const &&",
+       // Return type
+       "v1::v2::Dummy[abi:c1][abi:c2]<v1::v2::Dummy[abi:c1][abi:c2]<int>>",
        // Context
        "v1::v2::Dummy[abi:c1][abi:c2]<v1::v2::Dummy[abi:c1][abi:c2]<int>>",
        // Basename
@@ -158,6 +164,8 @@
        "v1::v2::with_tag_in_ns[abi:f1][abi:f2]<v1::v2::Dummy[abi:c1][abi:c2]"
        "<v1::v2::Dummy[abi:c1][abi:c2]<int>>>(int, v1::v2::Dummy<int>) const "
        "&&",
+       // Return type
+       "v1::v2::Dummy[abi:c1][abi:c2]<v1::v2::Dummy[abi:c1][abi:c2]<int>>",
        // Context
        "v1::v2",
        // Basename
@@ -173,6 +181,8 @@
       {"auto ns::with_tag_in_ns[abi:special tag,0.0][abi:special "
        "tag,1.0]<Dummy<int>>"
        "(float) const &&",
+       // Return type
+       "auto",
        // Context
        "ns",
        // Basename
@@ -184,15 +194,15 @@
        "tag,1.0]<Dummy<int>>"},
 
       // abi_tag on operator overloads
-      {"std::__1::error_code::operator bool[abi:v160000]() const",
+      {"std::__1::error_code::operator bool[abi:v160000]() const", "",
        "std::__1::error_code", "operator bool[abi:v160000]", "()", "const",
        "std::__1::error_code::operator bool[abi:v160000]"},
 
-      {"auto ns::foo::operator[][abi:v160000](size_t) const", "ns::foo",
+      {"auto ns::foo::operator[][abi:v160000](size_t) const", "auto", "ns::foo",
        "operator[][abi:v160000]", "(size_t)", "const",
        "ns::foo::operator[][abi:v160000]"},
 
-      {"auto Foo[abi:abc]<int>::operator<<<Foo[abi:abc]<int>>(int) &",
+      {"auto Foo[abi:abc]<int>::operator<<<Foo[abi:abc]<int>>(int) &", "auto",
        "Foo[abi:abc]<int>", "operator<<<Foo[abi:abc]<int>>", "(int)", "&",
        "Foo[abi:abc]<int>::operator<<<Foo[abi:abc]<int>>"}};
 
@@ -200,6 +210,7 @@
     CPlusPlusLanguage::MethodName method(ConstString(test.input));
     EXPECT_TRUE(method.IsValid()) << test.input;
     if (method.IsValid()) {
+      EXPECT_EQ(test.return_type, method.GetReturnType().str());
       EXPECT_EQ(test.context, method.GetContext().str());
       EXPECT_EQ(test.basename, method.GetBasename().str());
       EXPECT_EQ(test.arguments, method.GetArguments().str());
Index: lldb/source/Plugins/Language/CPlusPlus/CPlusPlusNameParser.h
===================================================================
--- lldb/source/Plugins/Language/CPlusPlus/CPlusPlusNameParser.h
+++ lldb/source/Plugins/Language/CPlusPlus/CPlusPlusNameParser.h
@@ -33,6 +33,7 @@
     ParsedName name;
     llvm::StringRef arguments;
     llvm::StringRef qualifiers;
+    llvm::StringRef return_type;
   };
 
   // Treats given text as a function definition and parses it.
Index: lldb/source/Plugins/Language/CPlusPlus/CPlusPlusNameParser.cpp
===================================================================
--- lldb/source/Plugins/Language/CPlusPlus/CPlusPlusNameParser.cpp
+++ lldb/source/Plugins/Language/CPlusPlus/CPlusPlusNameParser.cpp
@@ -105,10 +105,16 @@
 Optional<ParsedFunction>
 CPlusPlusNameParser::ParseFunctionImpl(bool expect_return_type) {
   Bookmark start_position = SetBookmark();
+
+  ParsedFunction result;
   if (expect_return_type) {
+    size_t return_start = GetCurrentPosition();
     // Consume return type if it's expected.
     if (!ConsumeToken(tok::kw_auto) && !ConsumeTypename())
       return None;
+
+    size_t return_end = GetCurrentPosition();
+    result.return_type = GetTextForRange(Range(return_start, return_end));
   }
 
   auto maybe_name = ParseFullNameImpl();
@@ -125,7 +131,6 @@
   SkipFunctionQualifiers();
   size_t end_position = GetCurrentPosition();
 
-  ParsedFunction result;
   result.name.basename = GetTextForRange(maybe_name.value().basename_range);
   result.name.context = GetTextForRange(maybe_name.value().context_range);
   result.arguments = GetTextForRange(Range(argument_start, qualifiers_start));
Index: lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h
===================================================================
--- lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h
+++ lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h
@@ -55,7 +55,9 @@
     llvm::StringRef GetArguments();
 
     llvm::StringRef GetQualifiers();
-    
+
+    llvm::StringRef GetReturnType();
+
     bool ContainsPath(llvm::StringRef path);
 
   private:
@@ -78,12 +80,13 @@
     bool TrySimplifiedParse();
 
     ConstString m_full; // Full name:
-                        // "lldb::SBTarget::GetBreakpointAtIndex(unsigned int)
-                        // const"
-    llvm::StringRef m_basename;   // Basename:     "GetBreakpointAtIndex"
-    llvm::StringRef m_context;    // Decl context: "lldb::SBTarget"
-    llvm::StringRef m_arguments;  // Arguments:    "(unsigned int)"
-    llvm::StringRef m_qualifiers; // Qualifiers:   "const"
+                        // "size_t lldb::SBTarget::GetBreakpointAtIndex(unsigned
+                        // int) const"
+    llvm::StringRef m_basename;    // Basename:     "GetBreakpointAtIndex"
+    llvm::StringRef m_context;     // Decl context: "lldb::SBTarget"
+    llvm::StringRef m_arguments;   // Arguments:    "(unsigned int)"
+    llvm::StringRef m_qualifiers;  // Qualifiers:   "const"
+    llvm::StringRef m_return_type; // Return type:   "size_t"
     bool m_parsed = false;
     bool m_parse_error = false;
   };
Index: lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
===================================================================
--- lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
+++ lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
@@ -109,6 +109,7 @@
   m_context = llvm::StringRef();
   m_arguments = llvm::StringRef();
   m_qualifiers = llvm::StringRef();
+  m_return_type = llvm::StringRef();
   m_parsed = false;
   m_parse_error = false;
 }
@@ -206,6 +207,7 @@
       m_basename = llvm::StringRef();
       m_arguments = llvm::StringRef();
       m_qualifiers = llvm::StringRef();
+      m_return_type = llvm::StringRef();
       return false;
     }
   }
@@ -223,6 +225,7 @@
         m_context = function.value().name.context;
         m_arguments = function.value().arguments;
         m_qualifiers = function.value().qualifiers;
+        m_return_type = function.value().return_type;
         m_parse_error = false;
       } else {
         m_parse_error = true;
@@ -256,6 +259,12 @@
   return m_qualifiers;
 }
 
+llvm::StringRef CPlusPlusLanguage::MethodName::GetReturnType() {
+  if (!m_parsed)
+    Parse();
+  return m_return_type;
+}
+
 std::string CPlusPlusLanguage::MethodName::GetScopeQualifiedName() {
   if (!m_parsed)
     Parse();
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
  • [Lldb-commits] [PATCH] D1369... Michael Buch via Phabricator via lldb-commits

Reply via email to