<rdar://problem/13506727> 

Symbol table function names should support lookups like symbols with debug info. 

To fix this I:
- Gutted the way FindFunctions is used, there used to be way too much smarts only in the DWARF plug-in
- Made it more efficient by chopping the name up once and using simpler queries so that SymbolFile and Symtab plug-ins don't need to do as much
- Filter the results at a higher level
- Make the lldb_private::Symtab able to chop up C++ mangled names and make as much sense out of them as possible and also be able to search by basename, fullname, method name, and selector name.



git-svn-id: https://llvm.org/svn/llvm-project/lldb/trunk@178608 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/source/Target/CPPLanguageRuntime.cpp b/source/Target/CPPLanguageRuntime.cpp
index 6b36d14..b020e0a 100644
--- a/source/Target/CPPLanguageRuntime.cpp
+++ b/source/Target/CPPLanguageRuntime.cpp
@@ -190,65 +190,65 @@
 bool
 CPPLanguageRuntime::StripNamespacesFromVariableName (const char *name, const char *&base_name_start, const char *&base_name_end)
 {
-  if (base_name_end == NULL)
-    base_name_end = name + strlen (name);
+    if (base_name_end == NULL)
+        base_name_end = name + strlen (name);
     
-  const char *last_colon = NULL;
-  for (const char *ptr = base_name_end; ptr != name; ptr--)
+    const char *last_colon = NULL;
+    for (const char *ptr = base_name_end; ptr != name; ptr--)
     {
-      if (*ptr == ':')
+        if (*ptr == ':')
         {
-          last_colon = ptr;
-          break;
+            last_colon = ptr;
+            break;
         }
     }
-
-  if (last_colon == NULL)
+    
+    if (last_colon == NULL)
     {
-      base_name_start = name;
-      return true;
+        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
+    
+    // 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
     {
-      // FIXME: should check if there is
-      base_name_start = last_colon + 1;
-      return true;
+        // FIXME: should check if there is
+        base_name_start = last_colon + 1;
+        return true;
     }
 }
 bool
 CPPLanguageRuntime::IsPossibleCPPCall (const char *name, const char *&base_name_start, const char *&base_name_end)
 {
     if (!name)
-      return false;
+        return false;
     // For now, I really can't handle taking template names apart, so if you
     // have < or > I'll say "could be CPP but leave the base_name empty which
     // means I couldn't figure out what to use for that.
     // FIXME: Do I need to do more sanity checking here?
-
+    
     if (strchr(name, '>') != NULL || strchr (name, '>') != NULL)
-      return true;
-
+        return true;
+    
     size_t name_len = strlen (name);
-
+    
     if (name[name_len - 1] == ')')
     {
         // We've got arguments.
         base_name_end = strchr (name, '(');
         if (base_name_end == NULL)
-          return false;
-
+            return false;
+        
         // FIXME: should check that this parenthesis isn't a template specialized
         // on a function type or something gross like that...
     }
     else
         base_name_end = name + strlen (name);
-
+    
     return StripNamespacesFromVariableName (name, base_name_start, base_name_end);
 }
 
@@ -267,3 +267,156 @@
     
     return count;
 }
+
+void
+CPPLanguageRuntime::MethodName::Clear()
+{
+    m_full.Clear();
+    m_basename.Clear();
+    m_context = llvm::StringRef();
+    m_arguments = llvm::StringRef();
+    m_qualifiers = llvm::StringRef();
+    m_type = eTypeInvalid;
+    m_parsed = false;
+    m_parse_error = false;
+}
+
+bool
+ReverseFindMatchingChars (const llvm::StringRef &s,
+                          const llvm::StringRef &left_right_chars,
+                          size_t &left_pos,
+                          size_t &right_pos,
+                          size_t pos = llvm::StringRef::npos)
+{
+    assert (left_right_chars.size() == 2);
+    left_pos = llvm::StringRef::npos;
+    const char left_char = left_right_chars[0];
+    const char right_char = left_right_chars[1];
+    pos = s.find_last_of(left_right_chars, pos);
+    if (pos == llvm::StringRef::npos || s[pos] == left_char)
+        return false;
+    right_pos = pos;
+    uint32_t depth = 1;
+    while (pos > 0 && depth > 0)
+    {
+        pos = s.find_last_of(left_right_chars, pos);
+        if (pos == llvm::StringRef::npos)
+            return false;
+        if (s[pos] == left_char)
+        {
+            if (--depth == 0)
+            {
+                left_pos = pos;
+                return left_pos < right_pos;
+            }            
+        }
+        else if (s[pos] == right_char)
+        {
+            ++depth;
+        }
+    }
+    return false;
+}
+
+void
+CPPLanguageRuntime::MethodName::Parse()
+{
+    if (!m_parsed && m_full)
+    {
+//        ConstString mangled;
+//        m_full.GetMangledCounterpart(mangled);
+//        printf ("\n   parsing = '%s'\n", m_full.GetCString());
+//        if (mangled)
+//            printf ("   mangled = '%s'\n", mangled.GetCString());
+        m_parse_error = false;
+        m_parsed = true;
+        llvm::StringRef full (m_full.GetCString());
+        
+        size_t arg_start, arg_end;
+        llvm::StringRef parens("()", 2);
+        if (ReverseFindMatchingChars (full, parens, arg_start, arg_end))
+        {
+            m_arguments = full.substr(arg_start, arg_end - arg_start + 1);
+            if (arg_end + 1 < full.size())
+                m_qualifiers = full.substr(arg_end + 1);
+            if (arg_start > 0)
+            {
+                size_t basename_end = arg_start;
+                size_t context_end = llvm::StringRef::npos;
+                if (basename_end > 0 && full[basename_end-1] == '>')
+                {
+                    // TODO: handle template junk...
+                    // Templated function
+                    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)
+                    context_end = full.rfind(':', basename_end);
+
+                if (context_end == llvm::StringRef::npos)
+                    m_basename.SetString(full.substr(0, basename_end));
+                else
+                {
+                    m_context = full.substr(0, context_end - 1);
+                    const size_t basename_begin = context_end + 1;
+                    m_basename.SetString(full.substr(basename_begin, basename_end - basename_begin));
+                }
+                m_type = eTypeUnknownMethod;
+            }
+            else
+            {
+                m_parse_error = true;
+                return;
+            }
+        
+//            if (!m_context.empty())
+//                printf ("   context = '%s'\n", m_context.str().c_str());
+//            if (m_basename)
+//                printf ("  basename = '%s'\n", m_basename.GetCString());
+//            if (!m_arguments.empty())
+//                printf (" arguments = '%s'\n", m_arguments.str().c_str());
+//            if (!m_qualifiers.empty())
+//                printf ("qualifiers = '%s'\n", m_qualifiers.str().c_str());
+        }
+        else
+        {
+            m_parse_error = true;
+//            printf ("error: didn't find matching parens for arguments\n");
+        }
+    }
+}
+
+const ConstString &
+CPPLanguageRuntime::MethodName::GetBasename ()
+{
+    if (!m_parsed)
+        Parse();
+    return m_basename;
+}
+
+llvm::StringRef
+CPPLanguageRuntime::MethodName::GetContext ()
+{
+    if (!m_parsed)
+        Parse();
+    return m_context;
+}
+
+llvm::StringRef
+CPPLanguageRuntime::MethodName::GetArguments ()
+{
+    if (!m_parsed)
+        Parse();
+    return m_arguments;
+}
+
+llvm::StringRef
+CPPLanguageRuntime::MethodName::GetQualifiers ()
+{
+    if (!m_parsed)
+        Parse();
+    return m_qualifiers;
+}
+