[lldb] Filter DIEs based on qualified name where possible

Context:
When setting a breakpoint by name, we invoke Module::FindFunctions to
find the function(s) in question. However, we use a Module::LookupInfo
to first process the user-provided name and figure out exactly what
we're looking for. When we actually perform the function lookup, we
search for the basename. After performing the search, we then filter out
the results using Module::LookupInfo::Prune. For example, given
a::b::foo we would first search for all instances of foo and then filter
out the results to just names that have a::b::foo in them. As one can
imagine, this involves a lot of debug info processing that we do not
necessarily need to be doing. Instead of doing one large post-processing
step after finding each instance of `foo`, we can filter them as we go
to save time.

Some numbers:
Debugging LLDB and placing a breakpoint on
llvm::itanium_demangle::StringView::begin without this change takes
approximately 70 seconds and resolves 31,920 DIEs. With this change,
placing the breakpoint takes around 30 seconds and resolves 8 DIEs.

Differential Revision: https://reviews.llvm.org/D129682

GitOrigin-RevId: befa77e59a7760d8c4fdd177b234e4a59500f61c
diff --git a/include/lldb/Core/Module.h b/include/lldb/Core/Module.h
index 117b14c..e877a14 100644
--- a/include/lldb/Core/Module.h
+++ b/include/lldb/Core/Module.h
@@ -85,6 +85,7 @@
 class Module : public std::enable_shared_from_this<Module>,
                public SymbolContextScope {
 public:
+  class LookupInfo;
   // Static functions that can track the lifetime of module objects. This is
   // handy because we might have Module objects that are in shared pointers
   // that aren't in the global module list (from ModuleList). If this is the
@@ -294,6 +295,23 @@
   ///     matches.
   void FindCompileUnits(const FileSpec &path, SymbolContextList &sc_list);
 
+  /// Find functions by lookup info.
+  ///
+  /// If the function is an inlined function, it will have a block,
+  /// representing the inlined function, and the function will be the
+  /// containing function.  If it is not inlined, then the block will be NULL.
+  ///
+  /// \param[in] lookup_info
+  ///     The lookup info of the function we are looking for.
+  ///
+  /// \param[out] sc_list
+  ///     A symbol context list that gets filled in with all of the
+  ///     matches.
+  void FindFunctions(const LookupInfo &lookup_info,
+                     const CompilerDeclContext &parent_decl_ctx,
+                     const ModuleFunctionSearchOptions &options,
+                     SymbolContextList &sc_list);
+
   /// Find functions by name.
   ///
   /// If the function is an inlined function, it will have a block,
@@ -931,6 +949,12 @@
       m_name_type_mask = mask;
     }
 
+    lldb::LanguageType GetLanguageType() const { return m_language; }
+
+    bool NameMatchesLookupInfo(
+        ConstString function_name,
+        lldb::LanguageType language_type = lldb::eLanguageTypeUnknown) const;
+
     void Prune(SymbolContextList &sc_list, size_t start_idx) const;
 
   protected:
diff --git a/include/lldb/Symbol/SymbolFile.h b/include/lldb/Symbol/SymbolFile.h
index ed0de1b..6d34e4c 100644
--- a/include/lldb/Symbol/SymbolFile.h
+++ b/include/lldb/Symbol/SymbolFile.h
@@ -9,6 +9,7 @@
 #ifndef LLDB_SYMBOL_SYMBOLFILE_H
 #define LLDB_SYMBOL_SYMBOLFILE_H
 
+#include "lldb/Core/Module.h"
 #include "lldb/Core/ModuleList.h"
 #include "lldb/Core/PluginInterface.h"
 #include "lldb/Core/SourceLocationSpec.h"
@@ -234,9 +235,8 @@
   virtual void FindGlobalVariables(const RegularExpression &regex,
                                    uint32_t max_matches,
                                    VariableList &variables);
-  virtual void FindFunctions(ConstString name,
+  virtual void FindFunctions(const Module::LookupInfo &lookup_info,
                              const CompilerDeclContext &parent_decl_ctx,
-                             lldb::FunctionNameType name_type_mask,
                              bool include_inlines, SymbolContextList &sc_list);
   virtual void FindFunctions(const RegularExpression &regex,
                              bool include_inlines, SymbolContextList &sc_list);
diff --git a/include/lldb/Symbol/SymbolFileOnDemand.h b/include/lldb/Symbol/SymbolFileOnDemand.h
index e47872c..653a004 100644
--- a/include/lldb/Symbol/SymbolFileOnDemand.h
+++ b/include/lldb/Symbol/SymbolFileOnDemand.h
@@ -135,9 +135,8 @@
                            uint32_t max_matches,
                            lldb_private::VariableList &variables) override;
 
-  void FindFunctions(lldb_private::ConstString name,
+  void FindFunctions(const lldb_private::Module::LookupInfo &lookup_info,
                      const lldb_private::CompilerDeclContext &parent_decl_ctx,
-                     lldb::FunctionNameType name_type_mask,
                      bool include_inlines,
                      lldb_private::SymbolContextList &sc_list) override;
 
diff --git a/source/Breakpoint/BreakpointResolverName.cpp b/source/Breakpoint/BreakpointResolverName.cpp
index 24e36f3..dbaeec9 100644
--- a/source/Breakpoint/BreakpointResolverName.cpp
+++ b/source/Breakpoint/BreakpointResolverName.cpp
@@ -274,9 +274,8 @@
     if (context.module_sp) {
       for (const auto &lookup : m_lookups) {
         const size_t start_func_idx = func_list.GetSize();
-        context.module_sp->FindFunctions(
-            lookup.GetLookupName(), CompilerDeclContext(),
-            lookup.GetNameTypeMask(), function_options, func_list);
+        context.module_sp->FindFunctions(lookup, CompilerDeclContext(),
+                                         function_options, func_list);
 
         const size_t end_func_idx = func_list.GetSize();
 
diff --git a/source/Core/Module.cpp b/source/Core/Module.cpp
index 0d4466a..0704e0e 100644
--- a/source/Core/Module.cpp
+++ b/source/Core/Module.cpp
@@ -727,6 +727,41 @@
   }
 }
 
+bool Module::LookupInfo::NameMatchesLookupInfo(
+    ConstString function_name, LanguageType language_type) const {
+  // We always keep unnamed symbols
+  if (!function_name)
+    return true;
+
+  // If we match exactly, we can return early
+  if (m_name == function_name)
+    return true;
+
+  // If function_name is mangled, we'll need to demangle it.
+  // In the pathologial case where the function name "looks" mangled but is
+  // actually demangled (e.g. a method named _Zonk), this operation should be
+  // relatively inexpensive since no demangling is actually occuring. See
+  // Mangled::SetValue for more context.
+  const bool function_name_may_be_mangled =
+      Mangled::GetManglingScheme(function_name.GetStringRef()) !=
+      Mangled::eManglingSchemeNone;
+  ConstString demangled_function_name = function_name;
+  if (function_name_may_be_mangled) {
+    Mangled mangled_function_name(function_name);
+    demangled_function_name = mangled_function_name.GetDemangledName();
+  }
+
+  // If the symbol has a language, then let the language make the match.
+  // Otherwise just check that the demangled function name contains the
+  // demangled user-provided name.
+  if (Language *language = Language::FindPlugin(language_type))
+    return language->DemangledNameContainsPath(m_name.GetStringRef(),
+                                               demangled_function_name);
+
+  llvm::StringRef function_name_ref = demangled_function_name.GetStringRef();
+  return function_name_ref.contains(m_name.GetStringRef());
+}
+
 void Module::LookupInfo::Prune(SymbolContextList &sc_list,
                                size_t start_idx) const {
   if (m_match_name_after_lookup && m_name) {
@@ -736,20 +771,8 @@
       if (!sc_list.GetContextAtIndex(i, sc))
         break;
       
-      llvm::StringRef user_name = m_name.GetStringRef();
-      bool keep_it = true;
-      Language *language = Language::FindPlugin(sc.GetLanguage());
-      // If the symbol has a language, then let the language make the match.
-      // Otherwise just check that the demangled name contains the user name.
-      if (language)
-        keep_it = language->DemangledNameContainsPath(m_name.GetStringRef(),
-                sc.GetFunctionName());
-      else {
-        llvm::StringRef full_name = sc.GetFunctionName().GetStringRef();
-        // We always keep unnamed symbols:
-        if (!full_name.empty())
-          keep_it = full_name.contains(user_name);
-      }
+      bool keep_it =
+          NameMatchesLookupInfo(sc.GetFunctionName(), sc.GetLanguage());
       if (keep_it)
         ++i;
       else
@@ -798,51 +821,37 @@
   }
 }
 
+void Module::FindFunctions(const Module::LookupInfo &lookup_info,
+                           const CompilerDeclContext &parent_decl_ctx,
+                           const ModuleFunctionSearchOptions &options,
+                           SymbolContextList &sc_list) {
+  // Find all the functions (not symbols, but debug information functions...
+  if (SymbolFile *symbols = GetSymbolFile()) {
+    symbols->FindFunctions(lookup_info, parent_decl_ctx,
+                           options.include_inlines, sc_list);
+    // Now check our symbol table for symbols that are code symbols if
+    // requested
+    if (options.include_symbols) {
+      if (Symtab *symtab = symbols->GetSymtab()) {
+        symtab->FindFunctionSymbols(lookup_info.GetLookupName(),
+                                    lookup_info.GetNameTypeMask(), sc_list);
+      }
+    }
+  }
+}
+
 void Module::FindFunctions(ConstString name,
                            const CompilerDeclContext &parent_decl_ctx,
                            FunctionNameType name_type_mask,
                            const ModuleFunctionSearchOptions &options,
                            SymbolContextList &sc_list) {
   const size_t old_size = sc_list.GetSize();
-
-  // Find all the functions (not symbols, but debug information functions...
-  SymbolFile *symbols = GetSymbolFile();
-
+  LookupInfo lookup_info(name, name_type_mask, eLanguageTypeUnknown);
+  FindFunctions(lookup_info, parent_decl_ctx, options, sc_list);
   if (name_type_mask & eFunctionNameTypeAuto) {
-    LookupInfo lookup_info(name, name_type_mask, eLanguageTypeUnknown);
-
-    if (symbols) {
-      symbols->FindFunctions(lookup_info.GetLookupName(), parent_decl_ctx,
-                             lookup_info.GetNameTypeMask(),
-                             options.include_inlines, sc_list);
-
-      // Now check our symbol table for symbols that are code symbols if
-      // requested
-      if (options.include_symbols) {
-        Symtab *symtab = symbols->GetSymtab();
-        if (symtab)
-          symtab->FindFunctionSymbols(lookup_info.GetLookupName(),
-                                      lookup_info.GetNameTypeMask(), sc_list);
-      }
-    }
-
     const size_t new_size = sc_list.GetSize();
-
     if (old_size < new_size)
       lookup_info.Prune(sc_list, old_size);
-  } else {
-    if (symbols) {
-      symbols->FindFunctions(name, parent_decl_ctx, name_type_mask,
-                             options.include_inlines, sc_list);
-
-      // Now check our symbol table for symbols that are code symbols if
-      // requested
-      if (options.include_symbols) {
-        Symtab *symtab = symbols->GetSymtab();
-        if (symtab)
-          symtab->FindFunctionSymbols(name, name_type_mask, sc_list);
-      }
-    }
   }
 }
 
diff --git a/source/Core/ModuleList.cpp b/source/Core/ModuleList.cpp
index 1692a37..baf44d2 100644
--- a/source/Core/ModuleList.cpp
+++ b/source/Core/ModuleList.cpp
@@ -425,9 +425,8 @@
 
     std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);
     for (const ModuleSP &module_sp : m_modules) {
-      module_sp->FindFunctions(lookup_info.GetLookupName(),
-                               CompilerDeclContext(),
-                               lookup_info.GetNameTypeMask(), options, sc_list);
+      module_sp->FindFunctions(lookup_info, CompilerDeclContext(), options,
+                               sc_list);
     }
 
     const size_t new_size = sc_list.GetSize();
diff --git a/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp b/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp
index b5615c3..2782472 100644
--- a/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp
+++ b/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp
@@ -421,12 +421,13 @@
 }
 
 void SymbolFileBreakpad::FindFunctions(
-    ConstString name, const CompilerDeclContext &parent_decl_ctx,
-    FunctionNameType name_type_mask, bool include_inlines,
+    const Module::LookupInfo &lookup_info,
+    const CompilerDeclContext &parent_decl_ctx, bool include_inlines,
     SymbolContextList &sc_list) {
   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
   // TODO: Implement this with supported FunctionNameType.
 
+  ConstString name = lookup_info.GetLookupName();
   for (uint32_t i = 0; i < GetNumCompileUnits(); ++i) {
     CompUnitSP cu_sp = GetCompileUnitAtIndex(i);
     FunctionSP func_sp = GetOrCreateFunction(*cu_sp);
diff --git a/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.h b/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.h
index 639d2e2..7c1f6fa 100644
--- a/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.h
+++ b/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.h
@@ -110,9 +110,8 @@
   void GetTypes(SymbolContextScope *sc_scope, lldb::TypeClass type_mask,
                 TypeList &type_list) override {}
 
-  void FindFunctions(ConstString name,
+  void FindFunctions(const Module::LookupInfo &lookup_info,
                      const CompilerDeclContext &parent_decl_ctx,
-                     lldb::FunctionNameType name_type_mask,
                      bool include_inlines, SymbolContextList &sc_list) override;
 
   void FindFunctions(const RegularExpression &regex, bool include_inlines,
diff --git a/source/Plugins/SymbolFile/DWARF/AppleDWARFIndex.cpp b/source/Plugins/SymbolFile/DWARF/AppleDWARFIndex.cpp
index 4877169..f6a49ba 100644
--- a/source/Plugins/SymbolFile/DWARF/AppleDWARFIndex.cpp
+++ b/source/Plugins/SymbolFile/DWARF/AppleDWARFIndex.cpp
@@ -180,12 +180,13 @@
 }
 
 void AppleDWARFIndex::GetFunctions(
-    ConstString name, SymbolFileDWARF &dwarf,
-    const CompilerDeclContext &parent_decl_ctx, uint32_t name_type_mask,
+    const Module::LookupInfo &lookup_info, SymbolFileDWARF &dwarf,
+    const CompilerDeclContext &parent_decl_ctx,
     llvm::function_ref<bool(DWARFDIE die)> callback) {
+  ConstString name = lookup_info.GetLookupName();
   m_apple_names_up->FindByName(name.GetStringRef(), [&](DIERef die_ref) {
-    return ProcessFunctionDIE(name.GetStringRef(), die_ref, dwarf,
-                              parent_decl_ctx, name_type_mask, callback);
+    return ProcessFunctionDIE(lookup_info, die_ref, dwarf, parent_decl_ctx,
+                              callback);
   });
 }
 
diff --git a/source/Plugins/SymbolFile/DWARF/AppleDWARFIndex.h b/source/Plugins/SymbolFile/DWARF/AppleDWARFIndex.h
index ef3cb5d..3a5b8ee 100644
--- a/source/Plugins/SymbolFile/DWARF/AppleDWARFIndex.h
+++ b/source/Plugins/SymbolFile/DWARF/AppleDWARFIndex.h
@@ -52,9 +52,9 @@
                 llvm::function_ref<bool(DWARFDIE die)> callback) override;
   void GetNamespaces(ConstString name,
                      llvm::function_ref<bool(DWARFDIE die)> callback) override;
-  void GetFunctions(ConstString name, SymbolFileDWARF &dwarf,
+  void GetFunctions(const Module::LookupInfo &lookup_info,
+                    SymbolFileDWARF &dwarf,
                     const CompilerDeclContext &parent_decl_ctx,
-                    uint32_t name_type_mask,
                     llvm::function_ref<bool(DWARFDIE die)> callback) override;
   void GetFunctions(const RegularExpression &regex,
                     llvm::function_ref<bool(DWARFDIE die)> callback) override;
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFASTParser.h b/source/Plugins/SymbolFile/DWARF/DWARFASTParser.h
index 97b0ea1..a6dba10 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFASTParser.h
+++ b/source/Plugins/SymbolFile/DWARF/DWARFASTParser.h
@@ -31,6 +31,9 @@
                                           const DWARFDIE &die,
                                           bool *type_is_new_ptr) = 0;
 
+  virtual lldb_private::ConstString
+  ConstructDemangledNameFromDWARF(const DWARFDIE &die) = 0;
+
   virtual lldb_private::Function *
   ParseFunctionFromDWARF(lldb_private::CompileUnit &comp_unit,
                          const DWARFDIE &die,
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
index b6407af..9e37bef 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
+++ b/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
@@ -2280,6 +2280,39 @@
   return enumerators_added;
 }
 
+ConstString
+DWARFASTParserClang::ConstructDemangledNameFromDWARF(const DWARFDIE &die) {
+  bool is_static = false;
+  bool is_variadic = false;
+  bool has_template_params = false;
+  unsigned type_quals = 0;
+  std::vector<CompilerType> param_types;
+  std::vector<clang::ParmVarDecl *> param_decls;
+  StreamString sstr;
+
+  DWARFDeclContext decl_ctx = SymbolFileDWARF::GetDWARFDeclContext(die);
+  sstr << decl_ctx.GetQualifiedName();
+
+  clang::DeclContext *containing_decl_ctx =
+      GetClangDeclContextContainingDIE(die, nullptr);
+  ParseChildParameters(containing_decl_ctx, die, true, is_static, is_variadic,
+                       has_template_params, param_types, param_decls,
+                       type_quals);
+  sstr << "(";
+  for (size_t i = 0; i < param_types.size(); i++) {
+    if (i > 0)
+      sstr << ", ";
+    sstr << param_types[i].GetTypeName();
+  }
+  if (is_variadic)
+    sstr << ", ...";
+  sstr << ")";
+  if (type_quals & clang::Qualifiers::Const)
+    sstr << " const";
+
+  return ConstString(sstr.GetString());
+}
+
 Function *
 DWARFASTParserClang::ParseFunctionFromDWARF(CompileUnit &comp_unit,
                                             const DWARFDIE &die,
@@ -2317,35 +2350,7 @@
       // If the mangled name is not present in the DWARF, generate the
       // demangled name using the decl context. We skip if the function is
       // "main" as its name is never mangled.
-      bool is_static = false;
-      bool is_variadic = false;
-      bool has_template_params = false;
-      unsigned type_quals = 0;
-      std::vector<CompilerType> param_types;
-      std::vector<clang::ParmVarDecl *> param_decls;
-      StreamString sstr;
-
-      DWARFDeclContext decl_ctx = SymbolFileDWARF::GetDWARFDeclContext(die);
-      sstr << decl_ctx.GetQualifiedName();
-
-      clang::DeclContext *containing_decl_ctx =
-          GetClangDeclContextContainingDIE(die, nullptr);
-      ParseChildParameters(containing_decl_ctx, die, true, is_static,
-                           is_variadic, has_template_params, param_types,
-                           param_decls, type_quals);
-      sstr << "(";
-      for (size_t i = 0; i < param_types.size(); i++) {
-        if (i > 0)
-          sstr << ", ";
-        sstr << param_types[i].GetTypeName();
-      }
-      if (is_variadic)
-        sstr << ", ...";
-      sstr << ")";
-      if (type_quals & clang::Qualifiers::Const)
-        sstr << " const";
-
-      func_name.SetValue(ConstString(sstr.GetString()), false);
+      func_name.SetValue(ConstructDemangledNameFromDWARF(die), false);
     } else
       func_name.SetValue(ConstString(name), false);
 
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h b/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h
index 2bc166c..7356653 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h
+++ b/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h
@@ -45,6 +45,9 @@
                                   const DWARFDIE &die,
                                   bool *type_is_new_ptr) override;
 
+  lldb_private::ConstString
+  ConstructDemangledNameFromDWARF(const DWARFDIE &die) override;
+
   lldb_private::Function *
   ParseFunctionFromDWARF(lldb_private::CompileUnit &comp_unit,
                          const DWARFDIE &die,
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp
index c989536..600a2ea 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp
@@ -18,6 +18,7 @@
 #include "lldb/Expression/DWARFExpression.h"
 #include "lldb/Symbol/ObjectFile.h"
 #include "lldb/Utility/Stream.h"
+#include "lldb/Utility/StreamString.h"
 
 #include "DWARFCompileUnit.h"
 #include "DWARFDebugAbbrev.h"
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFIndex.cpp b/source/Plugins/SymbolFile/DWARF/DWARFIndex.cpp
index 5131584..71df9e0 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFIndex.cpp
+++ b/source/Plugins/SymbolFile/DWARF/DWARFIndex.cpp
@@ -11,7 +11,9 @@
 #include "Plugins/SymbolFile/DWARF/DWARFDIE.h"
 #include "Plugins/SymbolFile/DWARF/SymbolFileDWARF.h"
 
+#include "lldb/Core/Mangled.h"
 #include "lldb/Core/Module.h"
+#include "lldb/Target/Language.h"
 
 using namespace lldb_private;
 using namespace lldb;
@@ -19,15 +21,33 @@
 DWARFIndex::~DWARFIndex() = default;
 
 bool DWARFIndex::ProcessFunctionDIE(
-    llvm::StringRef name, DIERef ref, SymbolFileDWARF &dwarf,
-    const CompilerDeclContext &parent_decl_ctx, uint32_t name_type_mask,
+    const Module::LookupInfo &lookup_info, DIERef ref, SymbolFileDWARF &dwarf,
+    const CompilerDeclContext &parent_decl_ctx,
     llvm::function_ref<bool(DWARFDIE die)> callback) {
+  llvm::StringRef name = lookup_info.GetLookupName().GetStringRef();
+  FunctionNameType name_type_mask = lookup_info.GetNameTypeMask();
   DWARFDIE die = dwarf.GetDIE(ref);
   if (!die) {
     ReportInvalidDIERef(ref, name);
     return true;
   }
 
+  if (!(name_type_mask & eFunctionNameTypeFull)) {
+    ConstString name_to_match_against;
+    if (const char *mangled_die_name = die.GetMangledName()) {
+      name_to_match_against = ConstString(mangled_die_name);
+    } else {
+      SymbolFileDWARF *symbols = die.GetDWARF();
+      if (ConstString demangled_die_name =
+              symbols->ConstructFunctionDemangledName(die))
+        name_to_match_against = demangled_die_name;
+    }
+
+    if (!lookup_info.NameMatchesLookupInfo(name_to_match_against,
+                                           lookup_info.GetLanguageType()))
+      return true;
+  }
+
   // Exit early if we're searching exclusively for methods or selectors and
   // we have a context specified (no methods in namespaces).
   uint32_t looking_for_nonmethods =
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFIndex.h b/source/Plugins/SymbolFile/DWARF/DWARFIndex.h
index c4995e7..c820793 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFIndex.h
+++ b/source/Plugins/SymbolFile/DWARF/DWARFIndex.h
@@ -13,6 +13,7 @@
 #include "Plugins/SymbolFile/DWARF/DWARFDIE.h"
 #include "Plugins/SymbolFile/DWARF/DWARFFormValue.h"
 
+#include "lldb/Core/Module.h"
 #include "lldb/Target/Statistics.h"
 
 class DWARFDeclContext;
@@ -54,9 +55,8 @@
   GetNamespaces(ConstString name,
                 llvm::function_ref<bool(DWARFDIE die)> callback) = 0;
   virtual void
-  GetFunctions(ConstString name, SymbolFileDWARF &dwarf,
+  GetFunctions(const Module::LookupInfo &lookup_info, SymbolFileDWARF &dwarf,
                const CompilerDeclContext &parent_decl_ctx,
-               uint32_t name_type_mask,
                llvm::function_ref<bool(DWARFDIE die)> callback) = 0;
   virtual void
   GetFunctions(const RegularExpression &regex,
@@ -74,10 +74,9 @@
   /// the function given by "ref" matches search criteria given by
   /// "parent_decl_ctx" and "name_type_mask", it is inserted into the "dies"
   /// vector.
-  bool ProcessFunctionDIE(llvm::StringRef name, DIERef ref,
+  bool ProcessFunctionDIE(const Module::LookupInfo &lookup_info, DIERef ref,
                           SymbolFileDWARF &dwarf,
                           const CompilerDeclContext &parent_decl_ctx,
-                          uint32_t name_type_mask,
                           llvm::function_ref<bool(DWARFDIE die)> callback);
 
   class DIERefCallbackImpl {
diff --git a/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.cpp b/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.cpp
index ad22078..a8e9b41 100644
--- a/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.cpp
+++ b/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.cpp
@@ -238,10 +238,10 @@
 }
 
 void DebugNamesDWARFIndex::GetFunctions(
-    ConstString name, SymbolFileDWARF &dwarf,
-    const CompilerDeclContext &parent_decl_ctx, uint32_t name_type_mask,
+    const Module::LookupInfo &lookup_info, SymbolFileDWARF &dwarf,
+    const CompilerDeclContext &parent_decl_ctx,
     llvm::function_ref<bool(DWARFDIE die)> callback) {
-
+  ConstString name = lookup_info.GetLookupName();
   std::set<DWARFDebugInfoEntry *> seen;
   for (const DebugNames::Entry &entry :
        m_debug_names_up->equal_range(name.GetStringRef())) {
@@ -250,8 +250,8 @@
       continue;
 
     if (llvm::Optional<DIERef> ref = ToDIERef(entry)) {
-      if (!ProcessFunctionDIE(name.GetStringRef(), *ref, dwarf, parent_decl_ctx,
-                              name_type_mask, [&](DWARFDIE die) {
+      if (!ProcessFunctionDIE(lookup_info, *ref, dwarf, parent_decl_ctx,
+                              [&](DWARFDIE die) {
                                 if (!seen.insert(die.GetDIE()).second)
                                   return true;
                                 return callback(die);
@@ -260,8 +260,7 @@
     }
   }
 
-  m_fallback.GetFunctions(name, dwarf, parent_decl_ctx, name_type_mask,
-                          callback);
+  m_fallback.GetFunctions(lookup_info, dwarf, parent_decl_ctx, callback);
 }
 
 void DebugNamesDWARFIndex::GetFunctions(
diff --git a/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.h b/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.h
index c451ccd..a0880c6 100644
--- a/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.h
+++ b/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.h
@@ -46,9 +46,9 @@
                 llvm::function_ref<bool(DWARFDIE die)> callback) override;
   void GetNamespaces(ConstString name,
                      llvm::function_ref<bool(DWARFDIE die)> callback) override;
-  void GetFunctions(ConstString name, SymbolFileDWARF &dwarf,
+  void GetFunctions(const Module::LookupInfo &lookup_info,
+                    SymbolFileDWARF &dwarf,
                     const CompilerDeclContext &parent_decl_ctx,
-                    uint32_t name_type_mask,
                     llvm::function_ref<bool(DWARFDIE die)> callback) override;
   void GetFunctions(const RegularExpression &regex,
                     llvm::function_ref<bool(DWARFDIE die)> callback) override;
diff --git a/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp b/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp
index b743c84..86e5653 100644
--- a/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp
+++ b/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp
@@ -411,10 +411,12 @@
 }
 
 void ManualDWARFIndex::GetFunctions(
-    ConstString name, SymbolFileDWARF &dwarf,
-    const CompilerDeclContext &parent_decl_ctx, uint32_t name_type_mask,
+    const Module::LookupInfo &lookup_info, SymbolFileDWARF &dwarf,
+    const CompilerDeclContext &parent_decl_ctx,
     llvm::function_ref<bool(DWARFDIE die)> callback) {
   Index();
+  ConstString name = lookup_info.GetLookupName();
+  FunctionNameType name_type_mask = lookup_info.GetNameTypeMask();
 
   if (name_type_mask & eFunctionNameTypeFull) {
     if (!m_set.function_fullnames.Find(
diff --git a/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.h b/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.h
index 5c5e43d..d95cf50 100644
--- a/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.h
+++ b/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.h
@@ -46,9 +46,9 @@
                 llvm::function_ref<bool(DWARFDIE die)> callback) override;
   void GetNamespaces(ConstString name,
                      llvm::function_ref<bool(DWARFDIE die)> callback) override;
-  void GetFunctions(ConstString name, SymbolFileDWARF &dwarf,
+  void GetFunctions(const Module::LookupInfo &lookup_info,
+                    SymbolFileDWARF &dwarf,
                     const CompilerDeclContext &parent_decl_ctx,
-                    uint32_t name_type_mask,
                     llvm::function_ref<bool(DWARFDIE die)> callback) override;
   void GetFunctions(const RegularExpression &regex,
                     llvm::function_ref<bool(DWARFDIE die)> callback) override;
diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
index 9d68cb1..af74a7b 100644
--- a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
+++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
@@ -862,6 +862,27 @@
   return dwarf_ast->ParseFunctionFromDWARF(comp_unit, die, func_range);
 }
 
+ConstString
+SymbolFileDWARF::ConstructFunctionDemangledName(const DWARFDIE &die) {
+  ASSERT_MODULE_LOCK(this);
+  if (!die.IsValid()) {
+    return ConstString();
+  }
+
+  auto type_system_or_err = GetTypeSystemForLanguage(GetLanguage(*die.GetCU()));
+  if (auto err = type_system_or_err.takeError()) {
+    LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), std::move(err),
+                   "Unable to construct demangled name for function");
+    return ConstString();
+  }
+
+  DWARFASTParser *dwarf_ast = type_system_or_err->GetDWARFParser();
+  if (!dwarf_ast)
+    return ConstString();
+
+  return dwarf_ast->ConstructDemangledNameFromDWARF(die);
+}
+
 lldb::addr_t SymbolFileDWARF::FixupAddress(lldb::addr_t file_addr) {
   SymbolFileDWARFDebugMap *debug_map_symfile = GetDebugMapSymfile();
   if (debug_map_symfile)
@@ -2310,12 +2331,13 @@
   return false;
 }
 
-void SymbolFileDWARF::FindFunctions(ConstString name,
+void SymbolFileDWARF::FindFunctions(const Module::LookupInfo &lookup_info,
                                     const CompilerDeclContext &parent_decl_ctx,
-                                    FunctionNameType name_type_mask,
                                     bool include_inlines,
                                     SymbolContextList &sc_list) {
   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
+  ConstString name = lookup_info.GetLookupName();
+  FunctionNameType name_type_mask = lookup_info.GetNameTypeMask();
   LLDB_SCOPED_TIMERF("SymbolFileDWARF::FindFunctions (name = '%s')",
                      name.AsCString());
 
@@ -2347,12 +2369,11 @@
 
   llvm::DenseSet<const DWARFDebugInfoEntry *> resolved_dies;
 
-  m_index->GetFunctions(name, *this, parent_decl_ctx, name_type_mask,
-                        [&](DWARFDIE die) {
-                          if (resolved_dies.insert(die.GetDIE()).second)
-                            ResolveFunction(die, include_inlines, sc_list);
-                          return true;
-                        });
+  m_index->GetFunctions(lookup_info, *this, parent_decl_ctx, [&](DWARFDIE die) {
+    if (resolved_dies.insert(die.GetDIE()).second)
+      ResolveFunction(die, include_inlines, sc_list);
+    return true;
+  });
 
   // Return the number of variable that were appended to the list
   const uint32_t num_matches = sc_list.GetSize() - original_size;
diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
index cfd18f0..235fa7c 100644
--- a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
+++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
@@ -178,9 +178,8 @@
                            uint32_t max_matches,
                            lldb_private::VariableList &variables) override;
 
-  void FindFunctions(lldb_private::ConstString name,
+  void FindFunctions(const lldb_private::Module::LookupInfo &lookup_info,
                      const lldb_private::CompilerDeclContext &parent_decl_ctx,
-                     lldb::FunctionNameType name_type_mask,
                      bool include_inlines,
                      lldb_private::SymbolContextList &sc_list) override;
 
@@ -329,6 +328,8 @@
     return m_parse_time;
   }
 
+  lldb_private::ConstString ConstructFunctionDemangledName(const DWARFDIE &die);
+
 protected:
   typedef llvm::DenseMap<const DWARFDebugInfoEntry *, lldb_private::Type *>
       DIEToTypePtr;
diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp
index 7637726..7bc6aae 100644
--- a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp
+++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp
@@ -1004,17 +1004,17 @@
 }
 
 void SymbolFileDWARFDebugMap::FindFunctions(
-    ConstString name, const CompilerDeclContext &parent_decl_ctx,
-    FunctionNameType name_type_mask, bool include_inlines,
+    const Module::LookupInfo &lookup_info,
+    const CompilerDeclContext &parent_decl_ctx, bool include_inlines,
     SymbolContextList &sc_list) {
   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
   LLDB_SCOPED_TIMERF("SymbolFileDWARFDebugMap::FindFunctions (name = %s)",
-                     name.GetCString());
+                     lookup_info.GetLookupName().GetCString());
 
   ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool {
     uint32_t sc_idx = sc_list.GetSize();
-    oso_dwarf->FindFunctions(name, parent_decl_ctx, name_type_mask,
-                             include_inlines, sc_list);
+    oso_dwarf->FindFunctions(lookup_info, parent_decl_ctx, include_inlines,
+                             sc_list);
     if (!sc_list.IsEmpty()) {
       RemoveFunctionsWithModuleNotEqualTo(m_objfile_sp->GetModule(), sc_list,
                                           sc_idx);
diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h
index 52c4d77..10a188f 100644
--- a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h
+++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h
@@ -109,9 +109,8 @@
   void FindGlobalVariables(const lldb_private::RegularExpression &regex,
                            uint32_t max_matches,
                            lldb_private::VariableList &variables) override;
-  void FindFunctions(lldb_private::ConstString name,
+  void FindFunctions(const lldb_private::Module::LookupInfo &lookup_info,
                      const lldb_private::CompilerDeclContext &parent_decl_ctx,
-                     lldb::FunctionNameType name_type_mask,
                      bool include_inlines,
                      lldb_private::SymbolContextList &sc_list) override;
   void FindFunctions(const lldb_private::RegularExpression &regex,
diff --git a/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp b/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
index fbaea33..3325af6 100644
--- a/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
+++ b/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
@@ -1563,10 +1563,12 @@
 }
 
 void SymbolFileNativePDB::FindFunctions(
-    ConstString name, const CompilerDeclContext &parent_decl_ctx,
-    FunctionNameType name_type_mask, bool include_inlines,
+    const Module::LookupInfo &lookup_info,
+    const CompilerDeclContext &parent_decl_ctx, bool include_inlines,
     SymbolContextList &sc_list) {
   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
+  ConstString name = lookup_info.GetLookupName();
+  FunctionNameType name_type_mask = lookup_info.GetNameTypeMask();
   // For now we only support lookup by method name or full name.
   if (!(name_type_mask & eFunctionNameTypeFull ||
         name_type_mask & eFunctionNameTypeMethod))
diff --git a/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h b/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h
index 187791b..4bb37d9 100644
--- a/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h
+++ b/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h
@@ -130,9 +130,8 @@
   void GetTypes(SymbolContextScope *sc_scope, lldb::TypeClass type_mask,
                 TypeList &type_list) override;
 
-  void FindFunctions(ConstString name,
+  void FindFunctions(const Module::LookupInfo &lookup_info,
                      const CompilerDeclContext &parent_decl_ctx,
-                     lldb::FunctionNameType name_type_mask,
                      bool include_inlines, SymbolContextList &sc_list) override;
 
   void FindFunctions(const RegularExpression &regex, bool include_inlines,
diff --git a/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp b/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp
index baa4853..da97507 100644
--- a/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp
+++ b/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp
@@ -1305,11 +1305,13 @@
 }
 
 void SymbolFilePDB::FindFunctions(
-    lldb_private::ConstString name,
+    const lldb_private::Module::LookupInfo &lookup_info,
     const lldb_private::CompilerDeclContext &parent_decl_ctx,
-    FunctionNameType name_type_mask, bool include_inlines,
+    bool include_inlines,
     lldb_private::SymbolContextList &sc_list) {
   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
+  ConstString name = lookup_info.GetLookupName();
+  FunctionNameType name_type_mask = lookup_info.GetNameTypeMask();
   lldbassert((name_type_mask & eFunctionNameTypeAuto) == 0);
 
   if (name_type_mask == eFunctionNameTypeNone)
diff --git a/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h b/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h
index 5d4b51b..1292bbe 100644
--- a/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h
+++ b/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h
@@ -119,9 +119,8 @@
                            uint32_t max_matches,
                            lldb_private::VariableList &variables) override;
 
-  void FindFunctions(lldb_private::ConstString name,
+  void FindFunctions(const lldb_private::Module::LookupInfo &lookup_info,
                      const lldb_private::CompilerDeclContext &parent_decl_ctx,
-                     lldb::FunctionNameType name_type_mask,
                      bool include_inlines,
                      lldb_private::SymbolContextList &sc_list) override;
 
diff --git a/source/Symbol/SymbolFile.cpp b/source/Symbol/SymbolFile.cpp
index e69150e..362f6ba 100644
--- a/source/Symbol/SymbolFile.cpp
+++ b/source/Symbol/SymbolFile.cpp
@@ -120,9 +120,8 @@
                                      uint32_t max_matches,
                                      VariableList &variables) {}
 
-void SymbolFile::FindFunctions(ConstString name,
+void SymbolFile::FindFunctions(const Module::LookupInfo &lookup_info,
                                const CompilerDeclContext &parent_decl_ctx,
-                               lldb::FunctionNameType name_type_mask,
                                bool include_inlines,
                                SymbolContextList &sc_list) {}
 
diff --git a/source/Symbol/SymbolFileOnDemand.cpp b/source/Symbol/SymbolFileOnDemand.cpp
index b97bc54..b4c9ed0 100644
--- a/source/Symbol/SymbolFileOnDemand.cpp
+++ b/source/Symbol/SymbolFileOnDemand.cpp
@@ -375,9 +375,11 @@
 }
 
 void SymbolFileOnDemand::FindFunctions(
-    ConstString name, const CompilerDeclContext &parent_decl_ctx,
-    FunctionNameType name_type_mask, bool include_inlines,
+    const Module::LookupInfo &lookup_info,
+    const CompilerDeclContext &parent_decl_ctx, bool include_inlines,
     SymbolContextList &sc_list) {
+  ConstString name = lookup_info.GetLookupName();
+  FunctionNameType name_type_mask = lookup_info.GetNameTypeMask();
   if (!m_debug_info_enabled) {
     Log *log = GetLog();
 
@@ -402,7 +404,7 @@
     // allow the FindFucntions to go through.
     SetLoadDebugInfoEnabled();
   }
-  return m_sym_file_impl->FindFunctions(name, parent_decl_ctx, name_type_mask,
+  return m_sym_file_impl->FindFunctions(lookup_info, parent_decl_ctx,
                                         include_inlines, sc_list);
 }
 
diff --git a/tools/lldb-test/lldb-test.cpp b/tools/lldb-test/lldb-test.cpp
index c0dd95d..5c7b128 100644
--- a/tools/lldb-test/lldb-test.cpp
+++ b/tools/lldb-test/lldb-test.cpp
@@ -505,8 +505,9 @@
         ContextOr->IsValid() ? *ContextOr : CompilerDeclContext();
 
     List.Clear();
-    Symfile.FindFunctions(ConstString(Name), ContextPtr, getFunctionNameFlags(),
-                         true, List);
+    Module::LookupInfo lookup_info(ConstString(Name), getFunctionNameFlags(),
+                                   eLanguageTypeUnknown);
+    Symfile.FindFunctions(lookup_info, ContextPtr, true, List);
   }
   outs() << formatv("Found {0} functions:\n", List.GetSize());
   StreamString Stream;