Skip to content

Commit 90e8889

Browse files
authored
[lldb] Fix CxxMethodName Parser on return type (#169652)
The simplified parser incorrectly assumes if there is a context, there is no return type. Fixed the case where functions have both a context and a return type. For example, `int foo::bar::func()` `Type<int> foo::bar::func()` Also fixed the case where there is no space between the context and return. `std::vector<int>foo::bar()`
1 parent 7f1423e commit 90e8889

File tree

2 files changed

+29
-10
lines changed

2 files changed

+29
-10
lines changed

lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,20 @@ static bool IsTrivialBasename(const llvm::StringRef &basename) {
208208
return idx == basename.size();
209209
}
210210

211+
/// A context is trivial if an only if it matches this pattern.
212+
/// "^\s*([A-Za-z_:]*)\s*$". for example function `foo::bar::func()`
213+
/// has a trivial context but. but `foo<int>::bar::func()` doesn't.
214+
static bool IsTrivialContext(llvm::StringRef context) {
215+
// remove trailing or leading whitespace.
216+
context = context.trim();
217+
218+
const auto iter = context.find_if_not([](char current) {
219+
return std::isalnum(static_cast<unsigned char>(current)) ||
220+
current == '_' || current == ':';
221+
});
222+
return iter == llvm::StringRef::npos;
223+
}
224+
211225
/// Writes out the function name in 'full_name' to 'out_stream'
212226
/// but replaces each argument type with the variable name
213227
/// and the corresponding pretty-printed value
@@ -481,18 +495,17 @@ bool CPlusPlusLanguage::CxxMethodName::TrySimplifiedParse() {
481495
m_basename = full.substr(basename_begin, basename_end - basename_begin);
482496
}
483497

484-
if (IsTrivialBasename(m_basename)) {
498+
if (IsTrivialBasename(m_basename) && IsTrivialContext(m_context)) {
485499
return true;
486-
} else {
487-
// The C++ basename doesn't match our regular expressions so this can't
488-
// be a valid C++ method, clear everything out and indicate an error
489-
m_context = llvm::StringRef();
490-
m_basename = llvm::StringRef();
491-
m_arguments = llvm::StringRef();
492-
m_qualifiers = llvm::StringRef();
493-
m_return_type = llvm::StringRef();
494-
return false;
495500
}
501+
// The C++ basename doesn't match our regular expressions so this can't
502+
// be a valid C++ method, clear everything out and indicate an error
503+
m_context = llvm::StringRef();
504+
m_basename = llvm::StringRef();
505+
m_arguments = llvm::StringRef();
506+
m_qualifiers = llvm::StringRef();
507+
m_return_type = llvm::StringRef();
508+
return false;
496509
}
497510
return false;
498511
}

lldb/unittests/Language/CPlusPlus/CPlusPlusLanguageTest.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,10 @@ TEST(CPlusPlusLanguage, MethodNameParsing) {
3030
{"foo::~bar(baz)", "", "foo", "~bar", "(baz)", "", "foo::~bar"},
3131
{"a::b::c::d(e,f)", "", "a::b::c", "d", "(e,f)", "", "a::b::c::d"},
3232
{"void f(int)", "void", "", "f", "(int)", "", "f"},
33+
{"std::vector<int>foo::bar()", "std::vector<int>", "foo", "bar", "()", "",
34+
"foo::bar"},
35+
{"int foo::bar::func01(int a, double b)", "int", "foo::bar", "func01",
36+
"(int a, double b)", "", "foo::bar::func01"},
3337

3438
// Operators
3539
{"std::basic_ostream<char, std::char_traits<char> >& "
@@ -101,6 +105,8 @@ TEST(CPlusPlusLanguage, MethodNameParsing) {
101105
"std::forward<decltype(nullptr)>"},
102106

103107
// Templates
108+
{"vector<int > foo::bar::func(int)", "vector<int >", "foo::bar", "func",
109+
"(int)", "", "foo::bar::func"},
104110
{"void llvm::PM<llvm::Module, llvm::AM<llvm::Module>>::"
105111
"addPass<llvm::VP>(llvm::VP)",
106112
"void", "llvm::PM<llvm::Module, llvm::AM<llvm::Module>>",

0 commit comments

Comments
 (0)