Index: lldb/trunk/lit/SymbolFile/DWARF/find-basic-function.cpp
===================================================================
--- lldb/trunk/lit/SymbolFile/DWARF/find-basic-function.cpp
+++ lldb/trunk/lit/SymbolFile/DWARF/find-basic-function.cpp
@@ -29,6 +29,22 @@
 // RUN: lldb-test symbols --name=not_there --find=function %t | \
 // RUN:   FileCheck --check-prefix=EMPTY %s
 
+// RUN: clang %s -g -c -emit-llvm -o - --target=x86_64-pc-linux | \
+// RUN:   llc -accel-tables=Dwarf -filetype=obj -o %t.o
+// RUN: ld.lld %t.o -o %t
+// RUN: lldb-test symbols --name=foo --find=function --function-flags=base %t | \
+// RUN:   FileCheck --check-prefix=BASE %s
+// RUN: lldb-test symbols --name=foo --find=function --function-flags=method %t | \
+// RUN:   FileCheck --check-prefix=METHOD %s
+// RUN: lldb-test symbols --name=foo --find=function --function-flags=full %t | \
+// RUN:   FileCheck --check-prefix=FULL %s
+// RUN: lldb-test symbols --name=_Z3fooi --find=function --function-flags=full %t | \
+// RUN:   FileCheck --check-prefix=FULL-MANGLED %s
+// RUN: lldb-test symbols --name=foo --context=context --find=function --function-flags=base %t | \
+// RUN:   FileCheck --check-prefix=CONTEXT %s
+// RUN: lldb-test symbols --name=not_there --find=function %t | \
+// RUN:   FileCheck --check-prefix=EMPTY %s
+
 // BASE: Found 4 functions:
 // BASE-DAG: name = "foo()", mangled = "_Z3foov"
 // BASE-DAG: name = "foo(int)", mangled = "_Z3fooi"
Index: lldb/trunk/source/Plugins/SymbolFile/DWARF/AppleDWARFIndex.cpp
===================================================================
--- lldb/trunk/source/Plugins/SymbolFile/DWARF/AppleDWARFIndex.cpp
+++ lldb/trunk/source/Plugins/SymbolFile/DWARF/AppleDWARFIndex.cpp
@@ -13,7 +13,6 @@
 #include "Plugins/SymbolFile/DWARF/DWARFUnit.h"
 #include "Plugins/SymbolFile/DWARF/LogChannelDWARF.h"
 
-#include "Plugins/Language/ObjC/ObjCLanguage.h"
 #include "lldb/Core/Module.h"
 #include "lldb/Symbol/Function.h"
 
@@ -135,74 +134,15 @@
     m_apple_namespaces_up->FindByName(name.GetStringRef(), offsets);
 }
 
-static bool KeepFunctionDIE(DWARFDIE die, uint32_t name_type_mask) {
-  bool looking_for_methods = name_type_mask & eFunctionNameTypeMethod;
-  bool looking_for_functions = name_type_mask & eFunctionNameTypeBase;
-  if (looking_for_methods && looking_for_functions)
-    return true;
-  return looking_for_methods == die.IsMethod();
-}
-
 void AppleDWARFIndex::GetFunctions(ConstString name, DWARFDebugInfo &info,
                                    const CompilerDeclContext &parent_decl_ctx,
                                    uint32_t name_type_mask,
                                    std::vector<DWARFDIE> &dies) {
-  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 dies that we find by exact match.
-    DIEArray offsets;
-    m_apple_names_up->FindByName(name.GetStringRef(), offsets);
-    for (const DIERef &die_ref: offsets) {
-      DWARFDIE die = info.GetDIE(die_ref);
-      if (!die) {
-        ReportInvalidDIEOffset(die_ref.die_offset, name.GetStringRef());
-        continue;
-      }
-      if (SymbolFileDWARF::DIEInDeclContext(&parent_decl_ctx, die))
-        dies.push_back(die);
-    }
-  }
-  if (name_type_mask & eFunctionNameTypeSelector &&
-      !parent_decl_ctx.IsValid()) {
-    DIEArray offsets;
-    m_apple_names_up->FindByName(name.GetStringRef(), 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 (const DIERef &die_ref: offsets) {
-      DWARFDIE die = info.GetDIE(die_ref);
-      if (!die) {
-        ReportInvalidDIEOffset(die_ref.die_offset, name.GetStringRef());
-        continue;
-      }
-      const char *die_name = die.GetName();
-      if (ObjCLanguage::IsPossibleObjCMethodName(die_name))
-        dies.push_back(die);
-    }
-  }
-  if (((name_type_mask & eFunctionNameTypeMethod) &&
-       !parent_decl_ctx.IsValid()) ||
-      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.
-
-    DIEArray offsets;
-    m_apple_names_up->FindByName(name.GetStringRef(), offsets);
-
-    for (const DIERef &die_ref: offsets) {
-      DWARFDIE die = info.GetDIE(die_ref);
-      if (!die) {
-        ReportInvalidDIEOffset(die_ref.die_offset, name.GetStringRef());
-        continue;
-      }
-      if (SymbolFileDWARF::DIEInDeclContext(&parent_decl_ctx, die) &&
-          KeepFunctionDIE(die, name_type_mask))
-        dies.push_back(die);
-    }
+  DIEArray offsets;
+  m_apple_names_up->FindByName(name.GetStringRef(), offsets);
+  for (const DIERef &die_ref : offsets) {
+    ProcessFunctionDIE(name.GetStringRef(), die_ref, info, parent_decl_ctx,
+                       name_type_mask, dies);
   }
 }
 
Index: lldb/trunk/source/Plugins/SymbolFile/DWARF/DIERef.h
===================================================================
--- lldb/trunk/source/Plugins/SymbolFile/DWARF/DIERef.h
+++ lldb/trunk/source/Plugins/SymbolFile/DWARF/DIERef.h
@@ -45,6 +45,10 @@
 
   bool operator<(const DIERef &ref) { return die_offset < ref.die_offset; }
 
+  explicit operator bool() const {
+    return cu_offset != DW_INVALID_OFFSET || die_offset != DW_INVALID_OFFSET;
+  }
+
   dw_offset_t cu_offset = DW_INVALID_OFFSET;
   dw_offset_t die_offset = DW_INVALID_OFFSET;
 };
Index: lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFIndex.h
===================================================================
--- lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFIndex.h
+++ lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFIndex.h
@@ -11,6 +11,7 @@
 #define LLDB_DWARFINDEX_H
 
 #include "Plugins/SymbolFile/DWARF/DIERef.h"
+#include "Plugins/SymbolFile/DWARF/DWARFDIE.h"
 #include "Plugins/SymbolFile/DWARF/DWARFFormValue.h"
 
 class DWARFDebugInfo;
@@ -53,6 +54,15 @@
 
 protected:
   Module &m_module;
+
+  /// Helper function implementing common logic for processing function dies. If
+  /// the function given by "ref" matches search criteria given by
+  /// "parent_decl_ctx" and "name_type_mask", it is inserted into the "dies"
+  /// vector.
+  void ProcessFunctionDIE(llvm::StringRef name, DIERef ref,
+                          DWARFDebugInfo &info,
+                          const CompilerDeclContext &parent_decl_ctx,
+                          uint32_t name_type_mask, std::vector<DWARFDIE> &dies);
 };
 } // namespace lldb_private
 
Index: lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFIndex.cpp
===================================================================
--- lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFIndex.cpp
+++ lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFIndex.cpp
@@ -11,7 +11,58 @@
 #include "Plugins/SymbolFile/DWARF/DWARFDIE.h"
 #include "Plugins/SymbolFile/DWARF/DWARFDebugInfo.h"
 
+#include "Plugins/Language/ObjC/ObjCLanguage.h"
+
 using namespace lldb_private;
 using namespace lldb;
 
 DWARFIndex::~DWARFIndex() = default;
+
+void DWARFIndex::ProcessFunctionDIE(llvm::StringRef name, DIERef ref,
+                                    DWARFDebugInfo &info,
+                                    const CompilerDeclContext &parent_decl_ctx,
+                                    uint32_t name_type_mask,
+                                    std::vector<DWARFDIE> &dies) {
+  DWARFDIE die = info.GetDIE(ref);
+  if (!die) {
+    ReportInvalidDIEOffset(ref.die_offset, name);
+    return;
+  }
+
+  // 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 =
+      name_type_mask & ~(eFunctionNameTypeMethod | eFunctionNameTypeSelector);
+  if (!looking_for_nonmethods && parent_decl_ctx.IsValid())
+    return;
+
+  // Otherwise, we need to also check that the context matches. If it does not
+  // match, we do nothing.
+  if (!SymbolFileDWARF::DIEInDeclContext(&parent_decl_ctx, die))
+    return;
+
+  // In case of a full match, we just insert everything we find.
+  if (name_type_mask & eFunctionNameTypeFull) {
+    dies.push_back(die);
+    return;
+  }
+
+  // If looking for ObjC selectors, we need to also check if the name is a
+  // possible selector.
+  if (name_type_mask & eFunctionNameTypeSelector &&
+      ObjCLanguage::IsPossibleObjCMethodName(die.GetName())) {
+    dies.push_back(die);
+    return;
+  }
+
+  bool looking_for_methods = name_type_mask & lldb::eFunctionNameTypeMethod;
+  bool looking_for_functions = name_type_mask & lldb::eFunctionNameTypeBase;
+  if (looking_for_methods || looking_for_functions) {
+    // If we're looking for either methods or functions, we definitely want this
+    // die. Otherwise, only keep it if the die type matches what we are
+    // searching for.
+    if ((looking_for_methods && looking_for_functions) ||
+        looking_for_methods == die.IsMethod())
+      dies.push_back(die);
+  }
+}
Index: lldb/trunk/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.h
===================================================================
--- lldb/trunk/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.h
+++ lldb/trunk/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.h
@@ -38,7 +38,7 @@
   void GetFunctions(ConstString name, DWARFDebugInfo &info,
                     const CompilerDeclContext &parent_decl_ctx,
                     uint32_t name_type_mask,
-                    std::vector<DWARFDIE> &dies) override {}
+                    std::vector<DWARFDIE> &dies) override;
   void GetFunctions(const RegularExpression &regex,
                     DIEArray &offsets) override {}
 
@@ -64,9 +64,11 @@
   std::unique_ptr<DebugNames> m_debug_names_up;
   ManualDWARFIndex m_fallback;
 
-  void Append(const DebugNames::Entry &entry, DIEArray &offsets);
-  void MaybeLogLookupError(llvm::Error error, const DebugNames::NameIndex &ni,
-                           llvm::StringRef name);
+  static DIERef ToDIERef(const DebugNames::Entry &entry);
+  static void Append(const DebugNames::Entry &entry, DIEArray &offsets);
+  static void MaybeLogLookupError(llvm::Error error,
+                                  const DebugNames::NameIndex &ni,
+                                  llvm::StringRef name);
 
   static llvm::DenseSet<dw_offset_t> GetUnits(const DebugNames &debug_names);
 };
Index: lldb/trunk/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.cpp
===================================================================
--- lldb/trunk/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.cpp
+++ lldb/trunk/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.cpp
@@ -8,6 +8,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.h"
+#include "Plugins/SymbolFile/DWARF/DWARFDebugInfo.h"
 #include "lldb/Utility/RegularExpression.h"
 #include "lldb/Utility/Stream.h"
 
@@ -44,12 +45,18 @@
   return result;
 }
 
-void DebugNamesDWARFIndex::Append(const DebugNames::Entry &entry,
-                                  DIEArray &offsets) {
+DIERef DebugNamesDWARFIndex::ToDIERef(const DebugNames::Entry &entry) {
   llvm::Optional<uint64_t> cu_offset = entry.getCUOffset();
   llvm::Optional<uint64_t> die_offset = entry.getDIESectionOffset();
   if (cu_offset && die_offset)
-    offsets.emplace_back(*cu_offset, *die_offset);
+    return DIERef(*cu_offset, *die_offset);
+  return DIERef();
+}
+
+void DebugNamesDWARFIndex::Append(const DebugNames::Entry &entry,
+                                  DIEArray &offsets) {
+  if (DIERef ref = ToDIERef(entry))
+    offsets.push_back(ref);
 }
 
 void DebugNamesDWARFIndex::MaybeLogLookupError(llvm::Error error,
@@ -118,6 +125,25 @@
   }
 }
 
+void DebugNamesDWARFIndex::GetFunctions(
+    ConstString name, DWARFDebugInfo &info,
+    const CompilerDeclContext &parent_decl_ctx, uint32_t name_type_mask,
+    std::vector<DWARFDIE> &dies) {
+
+  m_fallback.GetFunctions(name, info, parent_decl_ctx, name_type_mask, dies);
+
+  for (const DebugNames::Entry &entry :
+       m_debug_names_up->equal_range(name.GetStringRef())) {
+    Tag tag = entry.tag();
+    if (tag != DW_TAG_subprogram && tag != DW_TAG_inlined_subroutine)
+      continue;
+
+    if (DIERef ref = ToDIERef(entry))
+      ProcessFunctionDIE(name.GetStringRef(), ref, info, parent_decl_ctx,
+                         name_type_mask, dies);
+  }
+}
+
 void DebugNamesDWARFIndex::Dump(Stream &s) {
   m_fallback.Dump(s);