diff options
Diffstat (limited to 'contrib/llvm/tools/lldb/source/Target/CPPLanguageRuntime.cpp')
-rw-r--r-- | contrib/llvm/tools/lldb/source/Target/CPPLanguageRuntime.cpp | 78 |
1 files changed, 56 insertions, 22 deletions
diff --git a/contrib/llvm/tools/lldb/source/Target/CPPLanguageRuntime.cpp b/contrib/llvm/tools/lldb/source/Target/CPPLanguageRuntime.cpp index f5b7f7fc41a6..f048c6706a9b 100644 --- a/contrib/llvm/tools/lldb/source/Target/CPPLanguageRuntime.cpp +++ b/contrib/llvm/tools/lldb/source/Target/CPPLanguageRuntime.cpp @@ -11,6 +11,8 @@ #include <string.h> +#include "llvm/ADT/StringRef.h" + #include "lldb/Core/PluginManager.h" #include "lldb/Core/UniqueCStringMap.h" #include "lldb/Target/ExecutionContext.h" @@ -190,30 +192,17 @@ CPPLanguageRuntime::IsCPPMangledName (const char *name) } bool -CPPLanguageRuntime::StripNamespacesFromVariableName (const char *name, const char *&base_name_start, const char *&base_name_end) +CPPLanguageRuntime::ExtractContextAndIdentifier (const char *name, llvm::StringRef &context, llvm::StringRef &identifier) { - if (base_name_end == NULL) - base_name_end = name + strlen (name); - - const char *last_colon = strrchr (name, ':'); - - if (last_colon == NULL) - { - base_name_start = name; - return true; - } - - // Can't have a C++ name that begins with a single ':', nor contains an internal single ':' - if (last_colon == name) - return false; - else if (last_colon[-1] != ':') - return false; - else + static RegularExpression g_basename_regex("^(([A-Za-z_][A-Za-z_0-9]*::)*)([A-Za-z_][A-Za-z_0-9]*)$"); + RegularExpression::Match match(4); + if (g_basename_regex.Execute (name, &match)) { - // FIXME: should check if there is - base_name_start = last_colon + 1; + match.GetMatchAtIndex(name, 1, context); + match.GetMatchAtIndex(name, 3, identifier); return true; } + return false; } uint32_t @@ -282,6 +271,7 @@ ReverseFindMatchingChars (const llvm::StringRef &s, return false; } + void CPPLanguageRuntime::MethodName::Parse() { @@ -306,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] == '>') { @@ -314,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<Int>()' + 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); } @@ -343,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 { |