<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.

llvm-svn: 178608
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
index 3c0624d..35cd129 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
@@ -3322,6 +3322,9 @@
                         "SymbolFileDWARF::FindFunctions (name = '%s')",
                         name.AsCString());
 
+    // eFunctionNameTypeAuto should be pre-resolved by a call to Module::PrepareForFunctionNameLookup()
+    assert ((name_type_mask & eFunctionNameTypeAuto) == 0);
+
     Log *log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_LOOKUPS));
     
     if (log)
@@ -3347,59 +3350,16 @@
     // Remember how many sc_list are in the list before we search in case
     // we are appending the results to a variable list.
 
-    const uint32_t original_size = sc_list.GetSize();
-
     const char *name_cstr = name.GetCString();
-    uint32_t effective_name_type_mask = eFunctionNameTypeNone;
-    const char *base_name_start = name_cstr;
-    const char *base_name_end = name_cstr + strlen(name_cstr);
-    
-    if (name_type_mask & eFunctionNameTypeAuto)
-    {
-        if (CPPLanguageRuntime::IsCPPMangledName (name_cstr))
-            effective_name_type_mask = eFunctionNameTypeFull;
-        else if (ObjCLanguageRuntime::IsPossibleObjCMethodName (name_cstr))
-            effective_name_type_mask = eFunctionNameTypeFull;
-        else
-        {
-            if (ObjCLanguageRuntime::IsPossibleObjCSelector(name_cstr))
-                effective_name_type_mask |= eFunctionNameTypeSelector;
-                
-            if (CPPLanguageRuntime::IsPossibleCPPCall(name_cstr, base_name_start, base_name_end))
-                effective_name_type_mask |= (eFunctionNameTypeMethod | eFunctionNameTypeBase);
-        }
-    }
-    else
-    {
-        effective_name_type_mask = name_type_mask;
-        if (effective_name_type_mask & eFunctionNameTypeMethod || name_type_mask & eFunctionNameTypeBase)
-        {
-            // If they've asked for a CPP method or function name and it can't be that, we don't
-            // even need to search for CPP methods or names.
-            if (!CPPLanguageRuntime::IsPossibleCPPCall(name_cstr, base_name_start, base_name_end))
-            {
-                effective_name_type_mask &= ~(eFunctionNameTypeMethod | eFunctionNameTypeBase);
-                if (effective_name_type_mask == eFunctionNameTypeNone)
-                    return 0;
-            }
-        }
-        
-        if (effective_name_type_mask & eFunctionNameTypeSelector)
-        {
-            if (!ObjCLanguageRuntime::IsPossibleObjCSelector(name_cstr))
-            {
-                effective_name_type_mask &= ~(eFunctionNameTypeSelector);
-                if (effective_name_type_mask == eFunctionNameTypeNone)
-                    return 0;
-            }
-        }
-    }
-    
+
+    const uint32_t original_size = sc_list.GetSize();
+   
     DWARFDebugInfo* info = DebugInfo();
     if (info == NULL)
         return 0;
 
     DWARFCompileUnit *dwarf_cu = NULL;
+    std::set<const DWARFDebugInfoEntry *> resolved_dies;
     if (m_using_apple_tables)
     {
         if (m_apple_names_ap.get())
@@ -3409,7 +3369,7 @@
 
             uint32_t num_matches = 0;
                 
-            if (effective_name_type_mask & eFunctionNameTypeFull)
+            if (name_type_mask & eFunctionNameTypeFull)
             {
                 // If they asked for the full name, match what they typed.  At some point we may
                 // want to canonicalize this (strip double spaces, etc.  For now, we just add all the
@@ -3427,7 +3387,11 @@
                         if (!include_inlines && die->Tag() == DW_TAG_inlined_subroutine)
                             continue;
                         
-                        ResolveFunction (dwarf_cu, die, sc_list);
+                        if (resolved_dies.find(die) == resolved_dies.end())
+                        {
+                            if (ResolveFunction (dwarf_cu, die, sc_list))
+                                resolved_dies.insert(die);
+                        }
                     }
                     else
                     {
@@ -3436,87 +3400,116 @@
                     }                                    
                 }
             }
-            else
-            {                
-                if (effective_name_type_mask & eFunctionNameTypeSelector)
-                {
-                    if (namespace_decl && *namespace_decl)
-                        return 0; // no selectors in namespaces
-                        
-                    num_matches = m_apple_names_ap->FindByName (name_cstr, die_offsets);
-                    // Now make sure these are actually ObjC methods.  In this case we can simply look up the name,
-                    // and if it is an ObjC method name, we're good.
+
+            if (name_type_mask & eFunctionNameTypeSelector)
+            {
+                if (namespace_decl && *namespace_decl)
+                    return 0; // no selectors in namespaces
                     
-                    for (uint32_t i = 0; i < num_matches; i++)
-                    {
-                        const dw_offset_t die_offset = die_offsets[i];
-                        const DWARFDebugInfoEntry* die = info->GetDIEPtrWithCompileUnitHint (die_offset, &dwarf_cu);
-                        if (die)
-                        {
-                            const char *die_name = die->GetName(this, dwarf_cu);
-                            if (ObjCLanguageRuntime::IsPossibleObjCMethodName(die_name))
-                            {
-                                if (!include_inlines && die->Tag() == DW_TAG_inlined_subroutine)
-                                    continue;
-                                
-                                ResolveFunction (dwarf_cu, die, sc_list);
-                            }
-                        }
-                        else
-                        {
-                            GetObjectFile()->GetModule()->ReportError ("the DWARF debug information has been modified (.apple_names accelerator table had bad die 0x%8.8x for '%s')",
-                                                                       die_offset, name_cstr);
-                        }                                    
-                    }
-                    die_offsets.clear();
-                }
+                num_matches = m_apple_names_ap->FindByName (name_cstr, die_offsets);
+                // Now make sure these are actually ObjC methods.  In this case we can simply look up the name,
+                // and if it is an ObjC method name, we're good.
                 
-                if (effective_name_type_mask & eFunctionNameTypeMethod
-                    || effective_name_type_mask & eFunctionNameTypeBase)
+                for (uint32_t i = 0; i < num_matches; i++)
                 {
-                    if ((effective_name_type_mask & eFunctionNameTypeMethod) &&
-                        (namespace_decl && *namespace_decl))
-                        return 0; // no methods in namespaces
-                    
-                    // The apple_names table stores just the "base name" of C++ methods in the table.  So we have to 
-                    // extract the base name, look that up, and if there is any other information in the name we were
-                    // passed in we have to post-filter based on that.
-                    
-                    // FIXME: Arrange the logic above so that we don't calculate the base name twice:
-                    std::string base_name(base_name_start, base_name_end - base_name_start);
-                    num_matches = m_apple_names_ap->FindByName (base_name.c_str(), die_offsets);
-                    
-                    for (uint32_t i = 0; i < num_matches; i++)
+                    const dw_offset_t die_offset = die_offsets[i];
+                    const DWARFDebugInfoEntry* die = info->GetDIEPtrWithCompileUnitHint (die_offset, &dwarf_cu);
+                    if (die)
                     {
-                        const dw_offset_t die_offset = die_offsets[i];
-                        const DWARFDebugInfoEntry* die = info->GetDIEPtrWithCompileUnitHint (die_offset, &dwarf_cu);
-                        if (die)
+                        const char *die_name = die->GetName(this, dwarf_cu);
+                        if (ObjCLanguageRuntime::IsPossibleObjCMethodName(die_name))
                         {
                             if (!include_inlines && die->Tag() == DW_TAG_inlined_subroutine)
                                 continue;
                             
-                            if (namespace_decl && !DIEIsInNamespace (namespace_decl, dwarf_cu, die))
-                                continue;
-                            
-                            if (!FunctionDieMatchesPartialName(die,
-                                                               dwarf_cu, 
-                                                               effective_name_type_mask,
-                                                               name_cstr, 
-                                                               base_name_start, 
-                                                               base_name_end))
-                                continue;
-                            
-                            // If we get to here, the die is good, and we should add it:
-                            ResolveFunction (dwarf_cu, die, sc_list);
+                            if (resolved_dies.find(die) == resolved_dies.end())
+                            {
+                                if (ResolveFunction (dwarf_cu, die, sc_list))
+                                    resolved_dies.insert(die);
+                            }
                         }
-                        else
-                        {
-                            GetObjectFile()->GetModule()->ReportErrorIfModifyDetected ("the DWARF debug information has been modified (.apple_names accelerator table had bad die 0x%8.8x for '%s')",
-                                                                                       die_offset, name_cstr);
-                        }                                    
                     }
-                    die_offsets.clear();
+                    else
+                    {
+                        GetObjectFile()->GetModule()->ReportError ("the DWARF debug information has been modified (.apple_names accelerator table had bad die 0x%8.8x for '%s')",
+                                                                   die_offset, name_cstr);
+                    }                                    
                 }
+                die_offsets.clear();
+            }
+            
+            if (((name_type_mask & eFunctionNameTypeMethod) && !namespace_decl) || name_type_mask & eFunctionNameTypeBase)
+            {
+                // The apple_names table stores just the "base name" of C++ methods in the table.  So we have to
+                // extract the base name, look that up, and if there is any other information in the name we were
+                // passed in we have to post-filter based on that.
+                
+                // FIXME: Arrange the logic above so that we don't calculate the base name twice:
+                num_matches = m_apple_names_ap->FindByName (name_cstr, die_offsets);
+                
+                for (uint32_t i = 0; i < num_matches; i++)
+                {
+                    const dw_offset_t die_offset = die_offsets[i];
+                    const DWARFDebugInfoEntry* die = info->GetDIEPtrWithCompileUnitHint (die_offset, &dwarf_cu);
+                    if (die)
+                    {
+                        if (!include_inlines && die->Tag() == DW_TAG_inlined_subroutine)
+                            continue;
+                        
+                        if (namespace_decl && !DIEIsInNamespace (namespace_decl, dwarf_cu, die))
+                            continue;
+
+                        // If we get to here, the die is good, and we should add it:
+                        if (resolved_dies.find(die) == resolved_dies.end())
+                        if (ResolveFunction (dwarf_cu, die, sc_list))
+                        {
+                            bool keep_die = true;
+                            if ((name_type_mask & (eFunctionNameTypeBase|eFunctionNameTypeMethod)) != (eFunctionNameTypeBase|eFunctionNameTypeMethod))
+                            {
+                                // We are looking for either basenames or methods, so we need to
+                                // trim out the ones we won't want by looking at the type
+                                SymbolContext sc;
+                                if (sc_list.GetLastContext(sc))
+                                {
+                                    if (sc.block)
+                                    {
+                                        // We have an inlined function
+                                    }
+                                    else if (sc.function)
+                                    {
+                                        Type *type = sc.function->GetType();
+                                        
+                                        clang::DeclContext* decl_ctx = GetClangDeclContextContainingTypeUID (type->GetID());
+                                        if (decl_ctx->isRecord())
+                                        {
+                                            if (name_type_mask & eFunctionNameTypeBase)
+                                            {
+                                                sc_list.RemoveContextAtIndex(sc_list.GetSize()-1);
+                                                keep_die = false;
+                                            }
+                                        }
+                                        else
+                                        {
+                                            if (name_type_mask & eFunctionNameTypeMethod)
+                                            {
+                                                sc_list.RemoveContextAtIndex(sc_list.GetSize()-1);
+                                                keep_die = false;
+                                            }
+                                        }
+                                    }
+                                }
+                            }
+                            if (keep_die)
+                                resolved_dies.insert(die);
+                        }
+                    }
+                    else
+                    {
+                        GetObjectFile()->GetModule()->ReportErrorIfModifyDetected ("the DWARF debug information has been modified (.apple_names accelerator table had bad die 0x%8.8x for '%s')",
+                                                                                   die_offset, name_cstr);
+                    }                                    
+                }
+                die_offsets.clear();
             }
         }
     }
@@ -3530,14 +3523,12 @@
         if (name_type_mask & eFunctionNameTypeFull)
             FindFunctions (name, m_function_fullname_index, sc_list);
 
-        std::string base_name(base_name_start, base_name_end - base_name_start);
-        ConstString base_name_const(base_name.c_str());
         DIEArray die_offsets;
         DWARFCompileUnit *dwarf_cu = NULL;
         
-        if (effective_name_type_mask & eFunctionNameTypeBase)
+        if (name_type_mask & eFunctionNameTypeBase)
         {
-            uint32_t num_base = m_function_basename_index.Find(base_name_const, die_offsets);
+            uint32_t num_base = m_function_basename_index.Find(name, die_offsets);
             for (uint32_t i = 0; i < num_base; i++)
             {
                 const DWARFDebugInfoEntry* die = info->GetDIEPtrWithCompileUnitHint (die_offsets[i], &dwarf_cu);
@@ -3549,27 +3540,23 @@
                     if (namespace_decl && !DIEIsInNamespace (namespace_decl, dwarf_cu, die))
                         continue;
                     
-                    if (!FunctionDieMatchesPartialName(die, 
-                                                       dwarf_cu, 
-                                                       eFunctionNameTypeBase, 
-                                                       name_cstr, 
-                                                       base_name_start, 
-                                                       base_name_end))
-                        continue;
-                    
                     // If we get to here, the die is good, and we should add it:
-                    ResolveFunction (dwarf_cu, die, sc_list);
+                    if (resolved_dies.find(die) == resolved_dies.end())
+                    {
+                        if (ResolveFunction (dwarf_cu, die, sc_list))
+                            resolved_dies.insert(die);
+                    }
                 }
             }
             die_offsets.clear();
         }
         
-        if (effective_name_type_mask & eFunctionNameTypeMethod)
+        if (name_type_mask & eFunctionNameTypeMethod)
         {
             if (namespace_decl && *namespace_decl)
                 return 0; // no methods in namespaces
 
-            uint32_t num_base = m_function_method_index.Find(base_name_const, die_offsets);
+            uint32_t num_base = m_function_method_index.Find(name, die_offsets);
             {
                 for (uint32_t i = 0; i < num_base; i++)
                 {
@@ -3579,23 +3566,19 @@
                         if (!include_inlines && die->Tag() == DW_TAG_inlined_subroutine)
                             continue;
                         
-                        if (!FunctionDieMatchesPartialName(die,
-                                                           dwarf_cu, 
-                                                           eFunctionNameTypeMethod, 
-                                                           name_cstr, 
-                                                           base_name_start, 
-                                                           base_name_end))
-                            continue;
-                        
                         // If we get to here, the die is good, and we should add it:
-                        ResolveFunction (dwarf_cu, die, sc_list);
+                        if (resolved_dies.find(die) == resolved_dies.end())
+                        {
+                            if (ResolveFunction (dwarf_cu, die, sc_list))
+                                resolved_dies.insert(die);
+                        }
                     }
                 }
             }
             die_offsets.clear();
         }
 
-        if ((effective_name_type_mask & eFunctionNameTypeSelector) && (!namespace_decl || !*namespace_decl))
+        if ((name_type_mask & eFunctionNameTypeSelector) && (!namespace_decl || !*namespace_decl))
         {
             FindFunctions (name, m_function_selector_index, sc_list);
         }