[Lldb-commits] [lldb] r178608 - <rdar://problem/13506727>

Greg Clayton gclayton at apple.com
Tue Apr 2 19:00:15 PDT 2013


Author: gclayton
Date: Tue Apr  2 21:00:15 2013
New Revision: 178608

URL: http://llvm.org/viewvc/llvm-project?rev=178608&view=rev
Log:
<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.


Modified:
    lldb/trunk/include/lldb/Breakpoint/BreakpointResolverName.h
    lldb/trunk/include/lldb/Core/Module.h
    lldb/trunk/include/lldb/Symbol/SymbolContext.h
    lldb/trunk/include/lldb/Symbol/Symtab.h
    lldb/trunk/include/lldb/Target/CPPLanguageRuntime.h
    lldb/trunk/source/Breakpoint/BreakpointResolverName.cpp
    lldb/trunk/source/Core/Module.cpp
    lldb/trunk/source/Core/ModuleList.cpp
    lldb/trunk/source/Expression/ClangExpressionDeclMap.cpp
    lldb/trunk/source/Interpreter/CommandObjectRegexCommand.cpp
    lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
    lldb/trunk/source/Symbol/SymbolContext.cpp
    lldb/trunk/source/Symbol/Symtab.cpp
    lldb/trunk/source/Target/CPPLanguageRuntime.cpp

Modified: lldb/trunk/include/lldb/Breakpoint/BreakpointResolverName.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Breakpoint/BreakpointResolverName.h?rev=178608&r1=178607&r2=178608&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Breakpoint/BreakpointResolverName.h (original)
+++ lldb/trunk/include/lldb/Breakpoint/BreakpointResolverName.h Tue Apr  2 21:00:15 2013
@@ -86,13 +86,33 @@ public:
     }
 
 protected:
-    std::vector<ConstString> m_func_names;
-    uint32_t m_func_name_type_mask;  // See FunctionNameType
-    ConstString m_class_name;  // FIXME: Not used yet.  The idea would be to stop on methods of this class.
+    struct LookupInfo
+    {
+        ConstString name;
+        ConstString lookup_name;
+        uint32_t name_type_mask; // See FunctionNameType
+        bool match_name_after_lookup;
+        
+        LookupInfo () :
+            name(),
+            lookup_name(),
+            name_type_mask (0),
+            match_name_after_lookup (false)
+        {
+        }
+        
+        void
+        Prune (SymbolContextList &sc_list,
+               size_t start_idx) const;
+    };
+    std::vector<LookupInfo> m_lookups;
+    ConstString m_class_name;
     RegularExpression m_regex;
     Breakpoint::MatchType m_match_type;
     bool m_skip_prologue;
 
+    void
+    AddNameLookup (const ConstString &name, uint32_t name_type_mask);
 private:
     DISALLOW_COPY_AND_ASSIGN(BreakpointResolverName);
 };

Modified: lldb/trunk/include/lldb/Core/Module.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/Module.h?rev=178608&r1=178607&r2=178608&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Core/Module.h (original)
+++ lldb/trunk/include/lldb/Core/Module.h Tue Apr  2 21:00:15 2013
@@ -882,6 +882,56 @@ public:
     bool
     RemapSourceFile (const char *path, std::string &new_path) const;
     
+    
+    //------------------------------------------------------------------
+    /// Prepare to do a function name lookup.
+    ///
+    /// Looking up functions by name can be a tricky thing. LLDB requires
+    /// that accelerator tables contain full names for functions as well
+    /// as function basenames which include functions, class methods and
+    /// class functions. When the user requests that an action use a
+    /// function by name, we are sometimes asked to automatically figure
+    /// out what a name could possibly map to. A user might request a
+    /// breakpoint be set on "count". If no options are supplied to limit
+    /// the scope of where to search for count, we will by default match
+    /// any function names named "count", all class and instance methods
+    /// named "count" (no matter what the namespace or contained context)
+    /// and any selectors named "count". If a user specifies "a::b" we
+    /// will search for the basename "b", and then prune the results that
+    /// don't match "a::b" (note that "c::a::b" and "d::e::a::b" will
+    /// match a query of "a::b".
+    ///
+    /// @param[in] name
+    ///     The user supplied name to use in the lookup
+    ///
+    /// @param[in] name_type_mask
+    ///     The mask of bits from lldb::FunctionNameType enumerations
+    ///     that tell us what kind of name we are looking for.
+    ///
+    /// @param[out] lookup_name
+    ///     The actual name that will be used when calling
+    ///     SymbolVendor::FindFunctions() or Symtab::FindFunctionSymbols()
+    ///
+    /// @param[out] lookup_name_type_mask
+    ///     The actual name mask that should be used in the calls to
+    ///     SymbolVendor::FindFunctions() or Symtab::FindFunctionSymbols()
+    ///
+    /// @param[out] match_name_after_lookup
+    ///     A boolean that indicates if we need to iterate through any
+    ///     match results obtained from SymbolVendor::FindFunctions() or
+    ///     Symtab::FindFunctionSymbols() to see if the name contains
+    ///     \a name. For example if \a name is "a::b", this function will
+    ///     return a \a lookup_name of "b", with \a match_name_after_lookup
+    ///     set to true to indicate any matches will need to be checked
+    ///     to make sure they contain \a name.
+    //------------------------------------------------------------------
+    static void
+    PrepareForFunctionNameLookup (const ConstString &name,
+                                  uint32_t name_type_mask,
+                                  ConstString &lookup_name,
+                                  uint32_t &lookup_name_type_mask,
+                                  bool &match_name_after_lookup);
+
 protected:
     //------------------------------------------------------------------
     // Member Variables

Modified: lldb/trunk/include/lldb/Symbol/SymbolContext.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Symbol/SymbolContext.h?rev=178608&r1=178607&r2=178608&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Symbol/SymbolContext.h (original)
+++ lldb/trunk/include/lldb/Symbol/SymbolContext.h Tue Apr  2 21:00:15 2013
@@ -461,6 +461,19 @@ public:
     bool
     GetContextAtIndex(size_t idx, SymbolContext& sc) const;
 
+    //------------------------------------------------------------------
+    /// Get accessor for the last symbol context in the list.
+    ///
+    /// @param[out] sc
+    ///     A reference to the symbol context to fill in.
+    ///
+    /// @return
+    ///     Returns \b true if \a sc was filled in, \b false if the
+    ///     list is empty.
+    //------------------------------------------------------------------
+    bool
+    GetLastContext(SymbolContext& sc) const;
+
     bool
     RemoveContextAtIndex (size_t idx);
     //------------------------------------------------------------------

Modified: lldb/trunk/include/lldb/Symbol/Symtab.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Symbol/Symtab.h?rev=178608&r1=178607&r2=178608&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Symbol/Symtab.h (original)
+++ lldb/trunk/include/lldb/Symbol/Symtab.h Tue Apr  2 21:00:15 2013
@@ -107,6 +107,8 @@ protected:
     collection          m_symbols;
     std::vector<uint32_t> m_addr_indexes;
     UniqueCStringMap<uint32_t> m_name_to_index;
+    UniqueCStringMap<uint32_t> m_basename_to_index;
+    UniqueCStringMap<uint32_t> m_method_to_index;
     UniqueCStringMap<uint32_t> m_selector_to_index;
     mutable Mutex       m_mutex; // Provide thread safety for this symbol table
     bool                m_addr_indexes_computed:1,

Modified: lldb/trunk/include/lldb/Target/CPPLanguageRuntime.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/CPPLanguageRuntime.h?rev=178608&r1=178607&r2=178608&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Target/CPPLanguageRuntime.h (original)
+++ lldb/trunk/include/lldb/Target/CPPLanguageRuntime.h Tue Apr  2 21:00:15 2013
@@ -25,6 +25,93 @@ class CPPLanguageRuntime :
     public LanguageRuntime
 {
 public:
+    
+    class MethodName
+    {
+    public:
+        enum Type
+        {
+            eTypeInvalid,
+            eTypeUnknownMethod,
+            eTypeClassMethod,
+            eTypeInstanceMethod
+        };
+        
+        MethodName () :
+            m_full(),
+            m_basename(),
+            m_context(),
+            m_arguments(),
+            m_qualifiers(),
+            m_type (eTypeInvalid),
+            m_parsed (false),
+            m_parse_error (false)
+        {
+        }
+
+        MethodName (const ConstString &s) :
+            m_full(s),
+            m_basename(),
+            m_context(),
+            m_arguments(),
+            m_qualifiers(),
+            m_type (eTypeInvalid),
+            m_parsed (false),
+            m_parse_error (false)
+        {
+        }
+
+        void
+        Clear();
+        
+        bool
+        IsValid () const
+        {
+            if (m_parse_error)
+                return false;
+            if (m_type == eTypeInvalid)
+                return false;
+            return (bool)m_full;
+        }
+
+        Type
+        GetType () const
+        {
+            return m_type;
+        }
+        
+        const ConstString &
+        GetFullName () const
+        {
+            return m_full;
+        }
+        
+        const ConstString &
+        GetBasename ();
+
+        llvm::StringRef
+        GetContext ();
+        
+        llvm::StringRef
+        GetArguments ();
+        
+        llvm::StringRef
+        GetQualifiers ();
+
+    protected:
+        void
+        Parse();
+
+        ConstString     m_full;         // Full name:    "lldb::SBTarget::GetBreakpointAtIndex(unsigned int) const"
+        ConstString     m_basename;     // Basename:     "GetBreakpointAtIndex"
+        llvm::StringRef m_context;      // Decl context: "lldb::SBTarget"
+        llvm::StringRef m_arguments;    // Arguments:    "(unsigned int)"
+        llvm::StringRef m_qualifiers;   // Qualifiers:   "const"
+        Type m_type;
+        bool m_parsed;
+        bool m_parse_error;
+    };
+
     virtual
     ~CPPLanguageRuntime();
     

Modified: lldb/trunk/source/Breakpoint/BreakpointResolverName.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Breakpoint/BreakpointResolverName.cpp?rev=178608&r1=178607&r2=178608&view=diff
==============================================================================
--- lldb/trunk/source/Breakpoint/BreakpointResolverName.cpp (original)
+++ lldb/trunk/source/Breakpoint/BreakpointResolverName.cpp Tue Apr  2 21:00:15 2013
@@ -27,16 +27,12 @@
 using namespace lldb;
 using namespace lldb_private;
 
-BreakpointResolverName::BreakpointResolverName
-(
-    Breakpoint *bkpt,
-    const char *func_name,
-    uint32_t func_name_type_mask,
-    Breakpoint::MatchType type,
-    bool skip_prologue
-) :
+BreakpointResolverName::BreakpointResolverName (Breakpoint *bkpt,
+                                                const char *name_cstr,
+                                                uint32_t name_type_mask,
+                                                Breakpoint::MatchType type,
+                                                bool skip_prologue) :
     BreakpointResolver (bkpt, BreakpointResolver::NameResolver),
-    m_func_name_type_mask (func_name_type_mask),
     m_class_name (),
     m_regex (),
     m_match_type (type),
@@ -45,22 +41,17 @@ BreakpointResolverName::BreakpointResolv
     
     if (m_match_type == Breakpoint::Regexp)
     {
-        if (!m_regex.Compile (func_name))
+        if (!m_regex.Compile (name_cstr))
         {
             Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS));
 
             if (log)
-                log->Warning ("function name regexp: \"%s\" did not compile.", func_name);
+                log->Warning ("function name regexp: \"%s\" did not compile.", name_cstr);
         }
     }
     else
     {
-        const bool append = true;
-        ObjCLanguageRuntime::MethodName objc_name(func_name, false);
-        if (objc_name.IsValid(false))
-            objc_name.GetFullNames(m_func_names, append);
-        else
-            m_func_names.push_back(ConstString(func_name));
+        AddNameLookup (ConstString(name_cstr), name_type_mask);
     }
 }
 
@@ -70,18 +61,12 @@ BreakpointResolverName::BreakpointResolv
                                                 uint32_t name_type_mask,
                                                 bool skip_prologue) :
     BreakpointResolver (bkpt, BreakpointResolver::NameResolver),
-    m_func_name_type_mask (name_type_mask),
     m_match_type (Breakpoint::Exact),
     m_skip_prologue (skip_prologue)
 {
-    const bool append = true;
     for (size_t i = 0; i < num_names; i++)
     {
-        ObjCLanguageRuntime::MethodName objc_name(names[i], false);
-        if (objc_name.IsValid(false))
-            objc_name.GetFullNames(m_func_names, append);
-        else
-            m_func_names.push_back (ConstString (names[i]));
+        AddNameLookup (ConstString (names[i]), name_type_mask);
     }
 }
 
@@ -90,28 +75,18 @@ BreakpointResolverName::BreakpointResolv
                                                 uint32_t name_type_mask,
                                                 bool skip_prologue) :
     BreakpointResolver (bkpt, BreakpointResolver::NameResolver),
-    m_func_name_type_mask (name_type_mask),
     m_match_type (Breakpoint::Exact),
     m_skip_prologue (skip_prologue)
 {
-    size_t num_names = names.size();
-    const bool append = true;    
-    for (size_t i = 0; i < num_names; i++)
+    for (const std::string& name : names)
     {
-        ObjCLanguageRuntime::MethodName objc_name(names[i].c_str(), false);
-        if (objc_name.IsValid(false))
-            objc_name.GetFullNames(m_func_names, append);
-        else
-            m_func_names.push_back (ConstString (names[i].c_str()));
+        AddNameLookup (ConstString (name.c_str(), name.size()), name_type_mask);
     }
 }
 
-BreakpointResolverName::BreakpointResolverName
-(
-    Breakpoint *bkpt,
-    RegularExpression &func_regex,
-    bool skip_prologue
-) :
+BreakpointResolverName::BreakpointResolverName (Breakpoint *bkpt,
+                                                RegularExpression &func_regex,
+                                                bool skip_prologue) :
     BreakpointResolver (bkpt, BreakpointResolver::NameResolver),
     m_class_name (NULL),
     m_regex (func_regex),
@@ -134,13 +109,71 @@ BreakpointResolverName::BreakpointResolv
     m_match_type (type),
     m_skip_prologue (skip_prologue)
 {
-    m_func_names.push_back(ConstString(method));
+    LookupInfo lookup;
+    lookup.name.SetCString(method);
+    lookup.lookup_name = lookup.name;
+    lookup.name_type_mask = eFunctionNameTypeMethod;
+    lookup.match_name_after_lookup = false;
+    m_lookups.push_back (lookup);
 }
 
 BreakpointResolverName::~BreakpointResolverName ()
 {
 }
 
+void
+BreakpointResolverName::AddNameLookup (const ConstString &name, uint32_t name_type_mask)
+{
+    ObjCLanguageRuntime::MethodName objc_method(name.GetCString(), false);
+    if (objc_method.IsValid(false))
+    {
+        std::vector<ConstString> objc_names;
+        objc_method.GetFullNames(objc_names, true);
+        for (ConstString objc_name : objc_names)
+        {
+            LookupInfo lookup;
+            lookup.name = name;
+            lookup.lookup_name = objc_name;
+            lookup.name_type_mask = eFunctionNameTypeFull;
+            lookup.match_name_after_lookup = false;
+            m_lookups.push_back (lookup);
+        }
+    }
+    else
+    {
+        LookupInfo lookup;
+        lookup.name = name;
+        Module::PrepareForFunctionNameLookup(lookup.name, name_type_mask, lookup.lookup_name, lookup.name_type_mask, lookup.match_name_after_lookup);
+        m_lookups.push_back (lookup);
+    }
+}
+
+
+void
+BreakpointResolverName::LookupInfo::Prune (SymbolContextList &sc_list, size_t start_idx) const
+{
+    if (match_name_after_lookup && name)
+    {
+        SymbolContext sc;
+        size_t i = start_idx;
+        while (i < sc_list.GetSize())
+        {
+            if (!sc_list.GetContextAtIndex(i, sc))
+                break;
+            ConstString full_name (sc.GetFunctionName());
+            if (full_name && ::strstr(full_name.GetCString(), name.GetCString()) == NULL)
+            {
+                sc_list.RemoveContextAtIndex(i);
+            }
+            else
+            {
+                ++i;
+            }
+        }
+    }
+}
+
+
 // FIXME: Right now we look at the module level, and call the module's "FindFunctions".
 // Greg says he will add function tables, maybe at the CompileUnit level to accelerate function
 // lookup.  At that point, we should switch the depth to CompileUnit, and look in these tables.
@@ -159,7 +192,6 @@ BreakpointResolverName::SearchCallback
     
     uint32_t i;
     bool new_location;
-    SymbolContext sc;
     Address break_addr;
     assert (m_breakpoint != NULL);
     
@@ -182,22 +214,29 @@ BreakpointResolverName::SearchCallback
         case Breakpoint::Exact:
             if (context.module_sp)
             {
-                size_t num_names = m_func_names.size();
-                for (int j = 0; j < num_names; j++)
+                for (const LookupInfo &lookup : m_lookups)
                 {
-                    size_t num_functions = context.module_sp->FindFunctions (m_func_names[j],
-                                                                             NULL,
-                                                                             m_func_name_type_mask,
-                                                                             include_symbols,
-                                                                             include_inlines,
-                                                                             append,
-                                                                             func_list);
+                    const size_t start_func_idx = func_list.GetSize();
+                    context.module_sp->FindFunctions (lookup.lookup_name,
+                                                      NULL,
+                                                      lookup.name_type_mask,
+                                                      include_symbols,
+                                                      include_inlines,
+                                                      append,
+                                                      func_list);
+                    const size_t end_func_idx = func_list.GetSize();
+
+                    if (start_func_idx < end_func_idx)
+                        lookup.Prune (func_list, start_func_idx);
                     // If the search filter specifies a Compilation Unit, then we don't need to bother to look in plain
                     // symbols, since all the ones from a set compilation unit will have been found above already.
-                    
-                    if (num_functions == 0 && !filter_by_cu)
+                    else if (!filter_by_cu)
                     {
-                        context.module_sp->FindFunctionSymbols (m_func_names[j], m_func_name_type_mask, sym_list);
+                        const size_t start_symbol_idx = sym_list.GetSize();
+                        context.module_sp->FindFunctionSymbols (lookup.lookup_name, lookup.name_type_mask, sym_list);
+                        const size_t end_symbol_idx = sym_list.GetSize();
+                        if (start_symbol_idx < end_symbol_idx)
+                            lookup.Prune (func_list, start_symbol_idx);
                     }
                 }
             }
@@ -239,6 +278,7 @@ BreakpointResolverName::SearchCallback
     }
 
     // Remove any duplicates between the funcion list and the symbol list
+    SymbolContext sc;
     if (func_list.GetSize())
     {
         for (i = 0; i < func_list.GetSize(); i++)
@@ -356,17 +396,17 @@ BreakpointResolverName::GetDescription (
         s->Printf("regex = '%s'", m_regex.GetText());
     else
     {
-        size_t num_names = m_func_names.size();
+        size_t num_names = m_lookups.size();
         if (num_names == 1)
-            s->Printf("name = '%s'", m_func_names[0].AsCString());
+            s->Printf("name = '%s'", m_lookups[0].name.GetCString());
         else
         {
             s->Printf("names = {");
             for (size_t i = 0; i < num_names - 1; i++)
             {
-                s->Printf ("'%s', ", m_func_names[i].AsCString());
+                s->Printf ("'%s', ", m_lookups[i].name.GetCString());
             }
-            s->Printf ("'%s'}", m_func_names[num_names - 1].AsCString());
+            s->Printf ("'%s'}", m_lookups[num_names - 1].name.GetCString());
         }
     }
 }

Modified: lldb/trunk/source/Core/Module.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/Module.cpp?rev=178608&r1=178607&r2=178608&view=diff
==============================================================================
--- lldb/trunk/source/Core/Module.cpp (original)
+++ lldb/trunk/source/Core/Module.cpp Tue Apr  2 21:00:15 2013
@@ -29,6 +29,8 @@
 #include "lldb/Symbol/ObjectFile.h"
 #include "lldb/Symbol/SymbolContext.h"
 #include "lldb/Symbol/SymbolVendor.h"
+#include "lldb/Target/CPPLanguageRuntime.h"
+#include "lldb/Target/ObjCLanguageRuntime.h"
 #include "lldb/Target/Process.h"
 #include "lldb/Target/Target.h"
 
@@ -589,42 +591,83 @@ Module::FindFunctions (const ConstString
     if (!append)
         sc_list.Clear();
 
-    const size_t start_size = sc_list.GetSize();
+    const size_t old_size = sc_list.GetSize();
 
     // Find all the functions (not symbols, but debug information functions...
     SymbolVendor *symbols = GetSymbolVendor ();
-    if (symbols)
-        symbols->FindFunctions(name, namespace_decl, name_type_mask, include_inlines, append, sc_list);
-
-    // Now check our symbol table for symbols that are code symbols if requested
-    if (include_symbols)
+    
+    if (name_type_mask & eFunctionNameTypeAuto)
     {
-        ObjectFile *objfile = GetObjectFile();
-        if (objfile)
+        ConstString lookup_name;
+        uint32_t lookup_name_type_mask = 0;
+        bool match_name_after_lookup = false;
+        Module::PrepareForFunctionNameLookup (name,
+                                              name_type_mask,
+                                              lookup_name,
+                                              lookup_name_type_mask,
+                                              match_name_after_lookup);
+        
+        if (symbols)
+            symbols->FindFunctions(lookup_name,
+                                   namespace_decl,
+                                   lookup_name_type_mask,
+                                   include_inlines,
+                                   append,
+                                   sc_list);
+        
+        // Now check our symbol table for symbols that are code symbols if requested
+        if (include_symbols)
         {
-            Symtab *symtab = objfile->GetSymtab();
-            if (symtab)
+            ObjectFile *objfile = GetObjectFile();
+            if (objfile)
             {
-                std::vector<uint32_t> symbol_indexes;
-                symtab->FindAllSymbolsWithNameAndType (name, eSymbolTypeAny, Symtab::eDebugAny, Symtab::eVisibilityAny, symbol_indexes);
-                const size_t num_matches = symbol_indexes.size();
-                if (num_matches)
+                Symtab *symtab = objfile->GetSymtab();
+                if (symtab)
+                    symtab->FindFunctionSymbols(lookup_name, lookup_name_type_mask, sc_list);
+            }
+        }
+
+        if (match_name_after_lookup)
+        {
+            SymbolContext sc;
+            size_t i = old_size;
+            while (i<sc_list.GetSize())
+            {
+                if (sc_list.GetContextAtIndex(i, sc))
                 {
-                    const bool merge_symbol_into_function = true;
-                    SymbolContext sc(this);
-                    for (size_t i=0; i<num_matches; i++)
+                    const char *func_name = sc.GetFunctionName().GetCString();
+                    if (func_name && strstr (func_name, name.GetCString()) == NULL)
                     {
-                        sc.symbol = symtab->SymbolAtIndex(symbol_indexes[i]);
-                        SymbolType sym_type = sc.symbol->GetType();
-                        if (sc.symbol && (sym_type == eSymbolTypeCode ||
-                                          sym_type == eSymbolTypeResolver))
-                            sc_list.AppendIfUnique (sc, merge_symbol_into_function);
+                        // Remove the current context
+                        sc_list.RemoveContextAtIndex(i);
+                        // Don't increment i and continue in the loop
+                        continue;
                     }
                 }
+                ++i;
             }
         }
+        
     }
-    return sc_list.GetSize() - start_size;
+    else
+    {
+        if (symbols)
+            symbols->FindFunctions(name, namespace_decl, name_type_mask, include_inlines, append, sc_list);
+
+        // Now check our symbol table for symbols that are code symbols if requested
+        if (include_symbols)
+        {
+            ObjectFile *objfile = GetObjectFile();
+            if (objfile)
+            {
+                Symtab *symtab = objfile->GetSymtab();
+                if (symtab)
+                    symtab->FindFunctionSymbols(name, name_type_mask, sc_list);
+            }
+        }
+    }
+
+    return sc_list.GetSize() - old_size;
 }
 
 size_t
@@ -1347,3 +1390,78 @@ Module::GetVersion (uint32_t *versions,
     }
     return 0;
 }
+
+void
+Module::PrepareForFunctionNameLookup (const ConstString &name,
+                                      uint32_t name_type_mask,
+                                      ConstString &lookup_name,
+                                      uint32_t &lookup_name_type_mask,
+                                      bool &match_name_after_lookup)
+{
+    const char *name_cstr = name.GetCString();
+    lookup_name_type_mask = eFunctionNameTypeNone;
+    match_name_after_lookup = false;
+    const char *base_name_start = NULL;
+    const char *base_name_end = NULL;
+    
+    if (name_type_mask & eFunctionNameTypeAuto)
+    {
+        if (CPPLanguageRuntime::IsCPPMangledName (name_cstr))
+            lookup_name_type_mask = eFunctionNameTypeFull;
+        else if (ObjCLanguageRuntime::IsPossibleObjCMethodName (name_cstr))
+            lookup_name_type_mask = eFunctionNameTypeFull;
+        else
+        {
+            if (ObjCLanguageRuntime::IsPossibleObjCSelector(name_cstr))
+                lookup_name_type_mask |= eFunctionNameTypeSelector;
+            
+            if (CPPLanguageRuntime::IsPossibleCPPCall(name_cstr, base_name_start, base_name_end))
+                lookup_name_type_mask |= (eFunctionNameTypeMethod | eFunctionNameTypeBase);
+        }
+    }
+    else
+    {
+        lookup_name_type_mask = name_type_mask;
+        if (lookup_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))
+            {
+                lookup_name_type_mask &= ~(eFunctionNameTypeMethod | eFunctionNameTypeBase);
+                if (lookup_name_type_mask == eFunctionNameTypeNone)
+                    return;
+            }
+        }
+        
+        if (lookup_name_type_mask & eFunctionNameTypeSelector)
+        {
+            if (!ObjCLanguageRuntime::IsPossibleObjCSelector(name_cstr))
+            {
+                lookup_name_type_mask &= ~(eFunctionNameTypeSelector);
+                if (lookup_name_type_mask == eFunctionNameTypeNone)
+                    return;
+            }
+        }
+    }
+    
+    if (base_name_start &&
+        base_name_end &&
+        base_name_start != name_cstr &&
+        base_name_start < base_name_end)
+    {
+        // The name supplied was a partial C++ path like "a::count". In this case we want to do a
+        // lookup on the basename "count" and then make sure any matching results contain "a::count"
+        // so that it would match "b::a::count" and "a::count". This is why we set "match_name_after_lookup"
+        // to true
+        lookup_name.SetCStringWithLength(base_name_start, base_name_end - base_name_start);
+        match_name_after_lookup = true;
+    }
+    else
+    {
+        // The name is already correct, just use the exact name as supplied, and we won't need
+        // to check if any matches contain "name"
+        lookup_name = name;
+        match_name_after_lookup = false;
+    }
+}
\ No newline at end of file

Modified: lldb/trunk/source/Core/ModuleList.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/ModuleList.cpp?rev=178608&r1=178607&r2=178608&view=diff
==============================================================================
--- lldb/trunk/source/Core/ModuleList.cpp (original)
+++ lldb/trunk/source/Core/ModuleList.cpp Tue Apr  2 21:00:15 2013
@@ -337,14 +337,64 @@ ModuleList::FindFunctions (const ConstSt
     if (!append)
         sc_list.Clear();
     
-    Mutex::Locker locker(m_modules_mutex);
-    collection::const_iterator pos, end = m_modules.end();
-    for (pos = m_modules.begin(); pos != end; ++pos)
+    const size_t old_size = sc_list.GetSize();
+    
+    if (name_type_mask & eFunctionNameTypeAuto)
     {
-        (*pos)->FindFunctions (name, NULL, name_type_mask, include_symbols, include_inlines, true, sc_list);
+        ConstString lookup_name;
+        uint32_t lookup_name_type_mask = 0;
+        bool match_name_after_lookup = false;
+        Module::PrepareForFunctionNameLookup (name, name_type_mask,
+                                              lookup_name,
+                                              lookup_name_type_mask,
+                                              match_name_after_lookup);
+    
+        Mutex::Locker locker(m_modules_mutex);
+        collection::const_iterator pos, end = m_modules.end();
+        for (pos = m_modules.begin(); pos != end; ++pos)
+        {
+            (*pos)->FindFunctions (lookup_name,
+                                   NULL,
+                                   lookup_name_type_mask,
+                                   include_symbols,
+                                   include_inlines,
+                                   true,
+                                   sc_list);
+        }
+        
+        if (match_name_after_lookup)
+        {
+            SymbolContext sc;
+            size_t i = old_size;
+            while (i<sc_list.GetSize())
+            {
+                if (sc_list.GetContextAtIndex(i, sc))
+                {
+                    const char *func_name = sc.GetFunctionName().GetCString();
+                    if (func_name && strstr (func_name, name.GetCString()) == NULL)
+                    {
+                        // Remove the current context
+                        sc_list.RemoveContextAtIndex(i);
+                        // Don't increment i and continue in the loop
+                        continue;
+                    }
+                }
+                ++i;
+            }
+        }
+
     }
+    else
+    {
     
-    return sc_list.GetSize();
+        Mutex::Locker locker(m_modules_mutex);
+        collection::const_iterator pos, end = m_modules.end();
+        for (pos = m_modules.begin(); pos != end; ++pos)
+        {
+            (*pos)->FindFunctions (name, NULL, name_type_mask, include_symbols, include_inlines, true, sc_list);
+        }
+    }
+    return sc_list.GetSize() - old_size;
 }
 
 size_t

Modified: lldb/trunk/source/Expression/ClangExpressionDeclMap.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Expression/ClangExpressionDeclMap.cpp?rev=178608&r1=178607&r2=178608&view=diff
==============================================================================
--- lldb/trunk/source/Expression/ClangExpressionDeclMap.cpp (original)
+++ lldb/trunk/source/Expression/ClangExpressionDeclMap.cpp Tue Apr  2 21:00:15 2013
@@ -3116,7 +3116,7 @@ ClangExpressionDeclMap::FindExternalVisi
                 //   instance methods for eFunctionNameTypeBase.
                 
                 target->GetImages().FindFunctions(name,
-                                                  eFunctionNameTypeBase,
+                                                  eFunctionNameTypeFull,
                                                   include_symbols,
                                                   include_inlines,
                                                   append, 

Modified: lldb/trunk/source/Interpreter/CommandObjectRegexCommand.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Interpreter/CommandObjectRegexCommand.cpp?rev=178608&r1=178607&r2=178608&view=diff
==============================================================================
--- lldb/trunk/source/Interpreter/CommandObjectRegexCommand.cpp (original)
+++ lldb/trunk/source/Interpreter/CommandObjectRegexCommand.cpp Tue Apr  2 21:00:15 2013
@@ -35,8 +35,8 @@ CommandObjectRegexCommand::CommandObject
 ) :
     CommandObjectRaw (interpreter, name, help, syntax),
     m_max_matches (max_matches),
-    m_entries (),
-    m_completion_type_mask (completion_type_mask)
+    m_completion_type_mask (completion_type_mask),
+    m_entries ()
 {
 }
 

Modified: lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp?rev=178608&r1=178607&r2=178608&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp (original)
+++ lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp Tue Apr  2 21:00:15 2013
@@ -3322,6 +3322,9 @@ SymbolFileDWARF::FindFunctions (const Co
                         "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 @@ SymbolFileDWARF::FindFunctions (const Co
     // 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 @@ SymbolFileDWARF::FindFunctions (const Co
 
             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 @@ SymbolFileDWARF::FindFunctions (const Co
                         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 @@ SymbolFileDWARF::FindFunctions (const Co
                     }                                    
                 }
             }
-            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++)
+                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.
+                
+                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))
                         {
-                            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 (resolved_dies.find(die) == resolved_dies.end())
                             {
-                                if (!include_inlines && die->Tag() == DW_TAG_inlined_subroutine)
-                                    continue;
-                                
-                                ResolveFunction (dwarf_cu, die, sc_list);
+                                if (ResolveFunction (dwarf_cu, die, sc_list))
+                                    resolved_dies.insert(die);
                             }
                         }
-                        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();
+                    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);
                 
-                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)
+                        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))
                         {
-                            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);
+                            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();
+                    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 @@ SymbolFileDWARF::FindFunctions (const Co
         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 @@ SymbolFileDWARF::FindFunctions (const Co
                     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 @@ SymbolFileDWARF::FindFunctions (const Co
                         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);
         }

Modified: lldb/trunk/source/Symbol/SymbolContext.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Symbol/SymbolContext.cpp?rev=178608&r1=178607&r2=178608&view=diff
==============================================================================
--- lldb/trunk/source/Symbol/SymbolContext.cpp (original)
+++ lldb/trunk/source/Symbol/SymbolContext.cpp Tue Apr  2 21:00:15 2013
@@ -1056,6 +1056,17 @@ SymbolContextList::GetContextAtIndex(siz
 }
 
 bool
+SymbolContextList::GetLastContext(SymbolContext& sc) const
+{
+    if (!m_symbol_contexts.empty())
+    {
+        sc = m_symbol_contexts.back();
+        return true;
+    }
+    return false;
+}
+
+bool
 SymbolContextList::RemoveContextAtIndex (size_t idx)
 {
     if (idx < m_symbol_contexts.size())

Modified: lldb/trunk/source/Symbol/Symtab.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Symbol/Symtab.cpp?rev=178608&r1=178607&r2=178608&view=diff
==============================================================================
--- lldb/trunk/source/Symbol/Symtab.cpp (original)
+++ lldb/trunk/source/Symbol/Symtab.cpp Tue Apr  2 21:00:15 2013
@@ -16,6 +16,7 @@
 #include "lldb/Symbol/ObjectFile.h"
 #include "lldb/Symbol/SymbolContext.h"
 #include "lldb/Symbol/Symtab.h"
+#include "lldb/Target/CPPLanguageRuntime.h"
 #include "lldb/Target/ObjCLanguageRuntime.h"
 
 using namespace lldb;
@@ -263,9 +264,9 @@ Symtab::InitNameIndexes()
         m_name_indexes_computed = true;
         Timer scoped_timer (__PRETTY_FUNCTION__, "%s", __PRETTY_FUNCTION__);
         // Create the name index vector to be able to quickly search by name
-        const size_t count = m_symbols.size();
+        const size_t num_symbols = m_symbols.size();
 #if 1
-        m_name_to_index.Reserve (count);
+        m_name_to_index.Reserve (num_symbols);
 #else
         // TODO: benchmark this to see if we save any memory. Otherwise we
         // will always keep the memory reserved in the vector unless we pull
@@ -288,7 +289,12 @@ Symtab::InitNameIndexes()
 
         NameToIndexMap::Entry entry;
 
-        for (entry.value = 0; entry.value < count; ++entry.value)
+        // The "const char *" in "class_contexts" must come from a ConstString::GetCString()
+        std::set<const char *> class_contexts;
+        UniqueCStringMap<uint32_t> mangled_name_to_index;
+        std::vector<const char *> symbol_contexts(num_symbols, NULL);
+
+        for (entry.value = 0; entry.value<num_symbols; ++entry.value)
         {
             const Symbol *symbol = &m_symbols[entry.value];
 
@@ -303,8 +309,66 @@ Symtab::InitNameIndexes()
             const Mangled &mangled = symbol->GetMangled();
             entry.cstring = mangled.GetMangledName().GetCString();
             if (entry.cstring && entry.cstring[0])
+            {
                 m_name_to_index.Append (entry);
-
+                
+                const SymbolType symbol_type = symbol->GetType();
+                if (symbol_type == eSymbolTypeCode || symbol_type == eSymbolTypeResolver)
+                {
+                    if (entry.cstring[0] == '_' && entry.cstring[1] == 'Z' &&
+                        (entry.cstring[2] != 'T' && // avoid virtual table, VTT structure, typeinfo structure, and typeinfo name
+                         entry.cstring[2] != 'G' && // avoid guard variables
+                         entry.cstring[2] != 'Z'))  // named local entities (if we eventually handle eSymbolTypeData, we will want this back)
+                    {
+                        CPPLanguageRuntime::MethodName cxx_method (mangled.GetDemangledName());
+                        entry.cstring = cxx_method.GetBasename ().GetCString();
+                        if (entry.cstring && entry.cstring[0])
+                        {
+                            // ConstString objects permanently store the string in the pool so calling
+                            // GetCString() on the value gets us a const char * that will never go away
+                            const char *const_context = ConstString(cxx_method.GetContext()).GetCString();
+
+                            if (entry.cstring[0] == '~' || !cxx_method.GetQualifiers().empty())
+                            {
+                                // The first character of the demangled basename is '~' which
+                                // means we have a class destructor. We can use this information
+                                // to help us know what is a class and what isn't.
+                                if (class_contexts.find(const_context) == class_contexts.end())
+                                    class_contexts.insert(const_context);
+                                m_method_to_index.Append (entry);
+                            }
+                            else
+                            {
+                                if (const_context && const_context[0])
+                                {
+                                    if (class_contexts.find(const_context) != class_contexts.end())
+                                    {
+                                        // The current decl context is in our "class_contexts" which means
+                                        // this is a method on a class
+                                        m_method_to_index.Append (entry);
+                                    }
+                                    else
+                                    {
+                                        // We don't know if this is a function basename or a method,
+                                        // so put it into a temporary collection so once we are done
+                                        // we can look in class_contexts to see if each entry is a class
+                                        // or just a function and will put any remaining items into
+                                        // m_method_to_index or m_basename_to_index as needed
+                                        mangled_name_to_index.Append (entry);
+                                        symbol_contexts[entry.value] = const_context;
+                                    }
+                                }
+                                else
+                                {
+                                    // No context for this function so this has to be a basename
+                                    m_basename_to_index.Append(entry);
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+            
             entry.cstring = mangled.GetDemangledName().GetCString();
             if (entry.cstring && entry.cstring[0])
                 m_name_to_index.Append (entry);
@@ -326,15 +390,64 @@ Symtab::InitNameIndexes()
             }
                                                         
         }
+        
+        size_t count;
+        if (!mangled_name_to_index.IsEmpty())
+        {
+            count = mangled_name_to_index.GetSize();
+            for (size_t i=0; i<count; ++i)
+            {
+                if (mangled_name_to_index.GetValueAtIndex(i, entry.value))
+                {
+                    entry.cstring = mangled_name_to_index.GetCStringAtIndex(i);
+                    if (symbol_contexts[entry.value] && class_contexts.find(symbol_contexts[entry.value]) != class_contexts.end())
+                    {
+                        m_method_to_index.Append (entry);
+                    }
+                    else
+                    {
+                        // If we got here, we have something that had a context (was inside a namespace or class)
+                        // yet we don't know if the entry
+                        m_method_to_index.Append (entry);
+                        m_basename_to_index.Append (entry);
+                    }
+                }
+            }
+        }
         m_name_to_index.Sort();
         m_name_to_index.SizeToFit();
         m_selector_to_index.Sort();
         m_selector_to_index.SizeToFit();
+        m_basename_to_index.Sort();
+        m_basename_to_index.SizeToFit();
+        m_method_to_index.Sort();
+        m_method_to_index.SizeToFit();
+    
+//        static StreamFile a ("/tmp/a.txt");
+//
+//        count = m_basename_to_index.GetSize();
+//        if (count)
+//        {
+//            for (size_t i=0; i<count; ++i)
+//            {
+//                if (m_basename_to_index.GetValueAtIndex(i, entry.value))
+//                    a.Printf ("%s BASENAME\n", m_symbols[entry.value].GetMangled().GetName().GetCString());
+//            }
+//        }
+//        count = m_method_to_index.GetSize();
+//        if (count)
+//        {
+//            for (size_t i=0; i<count; ++i)
+//            {
+//                if (m_method_to_index.GetValueAtIndex(i, entry.value))
+//                    a.Printf ("%s METHOD\n", m_symbols[entry.value].GetMangled().GetName().GetCString());
+//            }
+//        }
     }
 }
 
 void
-Symtab::AppendSymbolNamesToMap (const IndexCollection &indexes, 
+Symtab::AppendSymbolNamesToMap (const IndexCollection &indexes,
                                 bool add_demangled,
                                 bool add_mangled,
                                 NameToIndexMap &name_to_index_map) const
@@ -1009,6 +1122,7 @@ Symtab::SymbolIndicesToSymbolContextList
     // No need to protect this call using m_mutex all other method calls are
     // already thread safe.
     
+    const bool merge_symbol_into_function = true;
     size_t num_indices = symbol_indexes.size();
     if (num_indices > 0)
     {
@@ -1018,7 +1132,7 @@ Symtab::SymbolIndicesToSymbolContextList
         {
             sc.symbol = SymbolAtIndex (symbol_indexes[i]);
             if (sc.symbol)
-                sc_list.Append (sc);
+                sc_list.AppendIfUnique(sc, merge_symbol_into_function);
         }
     }
 }
@@ -1031,11 +1145,53 @@ Symtab::FindFunctionSymbols (const Const
 {
     size_t count = 0;
     std::vector<uint32_t> symbol_indexes;
-    if (name_type_mask & (eFunctionNameTypeBase | eFunctionNameTypeFull | eFunctionNameTypeAuto))
+    
+    const char *name_cstr = name.GetCString();
+    
+    // eFunctionNameTypeAuto should be pre-resolved by a call to Module::PrepareForFunctionNameLookup()
+    assert ((name_type_mask & eFunctionNameTypeAuto) == 0);
+
+    if (name_type_mask & (eFunctionNameTypeBase | eFunctionNameTypeFull))
     {
         FindAllSymbolsWithNameAndType (name, eSymbolTypeCode, symbol_indexes);
     }
     
+    if (name_type_mask & eFunctionNameTypeBase)
+    {
+        // From mangled names we can't tell what is a basename and what
+        // is a method name, so we just treat them the same
+        if (!m_name_indexes_computed)
+            InitNameIndexes();
+
+        if (!m_basename_to_index.IsEmpty())
+        {
+            const UniqueCStringMap<uint32_t>::Entry *match;
+            for (match = m_basename_to_index.FindFirstValueForName(name_cstr);
+                 match != NULL;
+                 match = m_basename_to_index.FindNextValueForName(match))
+            {
+                symbol_indexes.push_back(match->value);
+            }
+        }
+    }
+    
+    if (name_type_mask & eFunctionNameTypeMethod)
+    {
+        if (!m_name_indexes_computed)
+            InitNameIndexes();
+        
+        if (!m_method_to_index.IsEmpty())
+        {
+            const UniqueCStringMap<uint32_t>::Entry *match;
+            for (match = m_method_to_index.FindFirstValueForName(name_cstr);
+                 match != NULL;
+                 match = m_method_to_index.FindNextValueForName(match))
+            {
+                symbol_indexes.push_back(match->value);
+            }
+        }
+    }
+
     if (name_type_mask & eFunctionNameTypeSelector)
     {
         if (!m_name_indexes_computed)
@@ -1044,7 +1200,7 @@ Symtab::FindFunctionSymbols (const Const
         if (!m_selector_to_index.IsEmpty())
         {
             const UniqueCStringMap<uint32_t>::Entry *match;
-            for (match = m_selector_to_index.FindFirstValueForName(name.AsCString());
+            for (match = m_selector_to_index.FindFirstValueForName(name_cstr);
                  match != NULL;
                  match = m_selector_to_index.FindNextValueForName(match))
             {

Modified: lldb/trunk/source/Target/CPPLanguageRuntime.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/CPPLanguageRuntime.cpp?rev=178608&r1=178607&r2=178608&view=diff
==============================================================================
--- lldb/trunk/source/Target/CPPLanguageRuntime.cpp (original)
+++ lldb/trunk/source/Target/CPPLanguageRuntime.cpp Tue Apr  2 21:00:15 2013
@@ -190,65 +190,65 @@ CPPLanguageRuntime::IsCPPMangledName (co
 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 @@ CPPLanguageRuntime::FindEquivalentNames(
     
     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;
+}
+





More information about the lldb-commits mailing list