From 81eed943a36c6fc7fec245e32105a24790652133 Mon Sep 17 00:00:00 2001 From: Greg Clayton Date: Wed, 5 Nov 2014 23:56:37 +0000 Subject: [PATCH] Fixed the C++ method name class to be a bit more picky about what it identifies as a C++ method. This was done by using regular expressions on any basename we find to ensure it is valid. This fixed setting breakpoints by name with values like '[J]com.robovm.debug.server.apps.SleepLoop.startingUp()V'. This was previously triggering the C++ method name class to identify the string as C++ with a basename of '[J]com.robovm.debug.server.apps.SleepLoop.startingUp' which was obviously incorrect. The changes also fixed errors in templated function names like "void foo(...)" where "void foo" was being identified incorrectly as the basename. We also handle more C++ operators correctly now. llvm-svn: 221416 --- lldb/include/lldb/Target/CPPLanguageRuntime.h | 4 ++- lldb/source/Target/CPPLanguageRuntime.cpp | 49 +++++++++++++++++++++++++-- 2 files changed, 50 insertions(+), 3 deletions(-) diff --git a/lldb/include/lldb/Target/CPPLanguageRuntime.h b/lldb/include/lldb/Target/CPPLanguageRuntime.h index 8be9f09..43df9e6 100644 --- a/lldb/include/lldb/Target/CPPLanguageRuntime.h +++ b/lldb/include/lldb/Target/CPPLanguageRuntime.h @@ -65,8 +65,10 @@ public: Clear(); bool - IsValid () const + IsValid () { + if (!m_parsed) + Parse(); if (m_parse_error) return false; if (m_type == eTypeInvalid) diff --git a/lldb/source/Target/CPPLanguageRuntime.cpp b/lldb/source/Target/CPPLanguageRuntime.cpp index 082a485..f048c67 100644 --- a/lldb/source/Target/CPPLanguageRuntime.cpp +++ b/lldb/source/Target/CPPLanguageRuntime.cpp @@ -271,6 +271,7 @@ ReverseFindMatchingChars (const llvm::StringRef &s, return false; } + void CPPLanguageRuntime::MethodName::Parse() { @@ -295,6 +296,7 @@ CPPLanguageRuntime::MethodName::Parse() if (arg_start > 0) { size_t basename_end = arg_start; + size_t context_start = 0; size_t context_end = llvm::StringRef::npos; if (basename_end > 0 && full[basename_end-1] == '>') { @@ -303,16 +305,35 @@ CPPLanguageRuntime::MethodName::Parse() size_t template_start, template_end; llvm::StringRef lt_gt("<>", 2); if (ReverseFindMatchingChars (full, lt_gt, template_start, template_end, basename_end)) + { context_end = full.rfind(':', template_start); + if (context_end == llvm::StringRef::npos) + { + // Check for templated functions that include return type like: + // 'void foo()' + context_end = full.rfind(' ', template_start); + if (context_end != llvm::StringRef::npos) + { + context_start = context_end; + } + } + } + else + { + context_end = full.rfind(':', basename_end); + } } - if (context_end == llvm::StringRef::npos) + else if (context_end == llvm::StringRef::npos) + { context_end = full.rfind(':', basename_end); + } if (context_end == llvm::StringRef::npos) m_basename = full.substr(0, basename_end); else { - m_context = full.substr(0, context_end - 1); + if (context_start < context_end) + m_context = full.substr(context_start, context_end - 1); const size_t basename_begin = context_end + 1; m_basename = full.substr(basename_begin, basename_end - basename_begin); } @@ -332,6 +353,30 @@ CPPLanguageRuntime::MethodName::Parse() // printf (" arguments = '%s'\n", m_arguments.str().c_str()); // if (!m_qualifiers.empty()) // printf ("qualifiers = '%s'\n", m_qualifiers.str().c_str()); + + // Make sure we have a valid C++ basename with optional template args + static RegularExpression g_identifier_regex("^~?([A-Za-z_][A-Za-z_0-9]*)(<.*>)?$"); + std::string basename_str(m_basename.str()); + bool basename_is_valid = g_identifier_regex.Execute (basename_str.c_str(), NULL); + if (!basename_is_valid) + { + // Check for C++ operators + if (m_basename.startswith("operator")) + { + static RegularExpression g_operator_regex("^(operator)( ?)([A-Za-z_][A-Za-z_0-9]*|\\(\\)|\\[\\]|[\\^<>=!\\/*+-]+)(<.*>)?(\\[\\])?$"); + basename_is_valid = g_operator_regex.Execute(basename_str.c_str(), NULL); + } + } + if (!basename_is_valid) + { + // The C++ basename doesn't match our regular expressions so this can't + // be a valid C++ method, clear everything out and indicate an error + m_context = llvm::StringRef(); + m_basename = llvm::StringRef(); + m_arguments = llvm::StringRef(); + m_qualifiers = llvm::StringRef(); + m_parse_error = true; + } } else { -- 2.7.4