This revision was automatically updated to reflect the committed changes.
labath marked 2 inline comments as done.
Closed by commit rL331447: lldb-test symbols: Add ability to do name-based 
lookup (authored by labath, committed by ).
Herald added a subscriber: llvm-commits.

Changed prior to commit:
  https://reviews.llvm.org/D46318?vs=144904&id=144993#toc

Repository:
  rL LLVM

https://reviews.llvm.org/D46318

Files:
  lldb/trunk/include/lldb/Symbol/VariableList.h
  lldb/trunk/lit/CMakeLists.txt
  lldb/trunk/lit/SymbolFile/DWARF/find-basic-function.cpp
  lldb/trunk/lit/SymbolFile/DWARF/find-basic-namespace.cpp
  lldb/trunk/lit/SymbolFile/DWARF/find-basic-type.cpp
  lldb/trunk/lit/SymbolFile/DWARF/find-basic-variable.cpp
  lldb/trunk/lit/SymbolFile/DWARF/find-type-in-function.cpp
  lldb/trunk/lit/SymbolFile/DWARF/lit.local.cfg
  lldb/trunk/lit/lit.cfg
  lldb/trunk/lit/lit.site.cfg.in
  lldb/trunk/tools/lldb-test/lldb-test.cpp

Index: lldb/trunk/tools/lldb-test/lldb-test.cpp
===================================================================
--- lldb/trunk/tools/lldb-test/lldb-test.cpp
+++ lldb/trunk/tools/lldb-test/lldb-test.cpp
@@ -20,6 +20,10 @@
 #include "lldb/Interpreter/CommandReturnObject.h"
 #include "lldb/Symbol/ClangASTContext.h"
 #include "lldb/Symbol/ClangASTImporter.h"
+#include "lldb/Symbol/SymbolVendor.h"
+#include "lldb/Symbol/TypeList.h"
+#include "lldb/Symbol/VariableList.h"
+#include "lldb/Utility/CleanUp.h"
 #include "lldb/Utility/DataExtractor.h"
 #include "lldb/Utility/StreamString.h"
 
@@ -29,6 +33,7 @@
 #include "llvm/Support/Path.h"
 #include "llvm/Support/PrettyStackTrace.h"
 #include "llvm/Support/Signals.h"
+#include "llvm/Support/WithColor.h"
 #include <thread>
 
 using namespace lldb;
@@ -57,7 +62,7 @@
 static llvm::StringRef plural(uintmax_t value) { return value == 1 ? "" : "s"; }
 static void dumpState(const BreakpointList &List, LinePrinter &P);
 static std::string substitute(StringRef Cmd);
-static void evaluateBreakpoints(Debugger &Dbg);
+static int evaluateBreakpoints(Debugger &Dbg);
 } // namespace breakpoint
 
 namespace module {
@@ -69,12 +74,68 @@
 } // namespace module
 
 namespace symbols {
-cl::list<std::string> InputFilenames(cl::Positional, cl::desc("<input files>"),
-                                     cl::OneOrMore, cl::sub(SymbolsSubcommand));
+static cl::list<std::string> InputFilenames(cl::Positional,
+                                            cl::desc("<input files>"),
+                                            cl::OneOrMore,
+                                            cl::sub(SymbolsSubcommand));
+enum class FindType {
+  None,
+  Function,
+  Namespace,
+  Type,
+  Variable,
+};
+static cl::opt<FindType> Find(
+    "find", cl::desc("Choose search type:"),
+    cl::values(
+        clEnumValN(FindType::None, "none",
+                   "No search, just dump the module."),
+        clEnumValN(FindType::Function, "function", "Find functions."),
+        clEnumValN(FindType::Namespace, "namespace", "Find namespaces."),
+        clEnumValN(FindType::Type, "type", "Find types."),
+        clEnumValN(FindType::Variable, "variable", "Find global variables.")),
+    cl::sub(SymbolsSubcommand));
+
+static cl::opt<std::string> Name("name", cl::desc("Name to find."),
+                                 cl::sub(SymbolsSubcommand));
+static cl::opt<bool>
+    Regex("regex",
+          cl::desc("Search using regular expressions (avaliable for variables "
+                   "and functions only)."),
+          cl::sub(SymbolsSubcommand));
+static cl::opt<std::string>
+    Context("context",
+            cl::desc("Restrict search to the context of the given variable."),
+            cl::value_desc("variable"), cl::sub(SymbolsSubcommand));
+
+static cl::list<FunctionNameType> FunctionNameFlags(
+    "function-flags", cl::desc("Function search flags:"),
+    cl::values(clEnumValN(eFunctionNameTypeAuto, "auto",
+                          "Automatically deduce flags based on name."),
+               clEnumValN(eFunctionNameTypeFull, "full", "Full function name."),
+               clEnumValN(eFunctionNameTypeBase, "base", "Base name."),
+               clEnumValN(eFunctionNameTypeMethod, "method", "Method name."),
+               clEnumValN(eFunctionNameTypeSelector, "selector",
+                          "Selector name.")),
+    cl::sub(SymbolsSubcommand));
+static FunctionNameType getFunctionNameFlags() {
+  FunctionNameType Result = FunctionNameType(0);
+  for (FunctionNameType Flag : FunctionNameFlags)
+    Result = FunctionNameType(Result | Flag);
+  return Result;
 }
-} // namespace opts
 
-static llvm::ManagedStatic<SystemLifetimeManager> DebuggerLifetime;
+static Expected<CompilerDeclContext> getDeclContext(SymbolVendor &Vendor);
+
+static Error findFunctions(lldb_private::Module &Module);
+static Error findNamespaces(lldb_private::Module &Module);
+static Error findTypes(lldb_private::Module &Module);
+static Error findVariables(lldb_private::Module &Module);
+static Error dumpModule(lldb_private::Module &Module);
+
+static int dumpSymbols(Debugger &Dbg);
+}
+} // namespace opts
 
 void opts::breakpoint::dumpState(const BreakpointList &List, LinePrinter &P) {
   P.formatLine("{0} breakpoint{1}", List.GetSize(), plural(List.GetSize()));
@@ -130,7 +191,7 @@
   return std::move(OS.str());
 }
 
-void opts::breakpoint::evaluateBreakpoints(Debugger &Dbg) {
+int opts::breakpoint::evaluateBreakpoints(Debugger &Dbg) {
   TargetSP Target;
   Status ST =
       Dbg.GetTargetList().CreateTarget(Dbg, breakpoint::Target, /*triple*/ "",
@@ -151,6 +212,7 @@
 
   LinePrinter P(4, outs());
   StringRef Rest = (*MB)->getBuffer();
+  int HadErrors = 0;
   while (!Rest.empty()) {
     StringRef Line;
     std::tie(Line, Rest) = Rest.split('\n');
@@ -167,31 +229,198 @@
     if (!Dbg.GetCommandInterpreter().HandleCommand(
             Command.c_str(), /*add_to_history*/ eLazyBoolNo, Result)) {
       P.formatLine("Failed: {0}", Result.GetErrorData());
+      HadErrors = 1;
       continue;
     }
 
     dumpState(Target->GetBreakpointList(/*internal*/ false), P);
   }
+  return HadErrors;
+}
+
+Expected<CompilerDeclContext>
+opts::symbols::getDeclContext(SymbolVendor &Vendor) {
+  if (Context.empty())
+    return CompilerDeclContext();
+  VariableList List;
+  Vendor.FindGlobalVariables(ConstString(Context), nullptr, false, UINT32_MAX,
+                             List);
+  if (List.Empty()) {
+    return make_error<StringError>("Context search didn't find a match.",
+                                   inconvertibleErrorCode());
+  }
+  if (List.GetSize() > 1) {
+    return make_error<StringError>("Context search found multiple matches.",
+                                   inconvertibleErrorCode());
+  }
+  return List.GetVariableAtIndex(0)->GetDeclContext();
+}
+
+Error opts::symbols::findFunctions(lldb_private::Module &Module) {
+  SymbolVendor &Vendor = *Module.GetSymbolVendor();
+  SymbolContextList List;
+  if (Regex) {
+    RegularExpression RE(Name);
+    assert(RE.IsValid());
+    Vendor.FindFunctions(RE, true, false, List);
+  } else {
+    Expected<CompilerDeclContext> ContextOr = getDeclContext(Vendor);
+    if (!ContextOr)
+      return ContextOr.takeError();
+    CompilerDeclContext *ContextPtr =
+        ContextOr->IsValid() ? &*ContextOr : nullptr;
+
+    Vendor.FindFunctions(ConstString(Name), ContextPtr, getFunctionNameFlags(),
+                          true, false, List);
+  }
+  outs() << formatv("Found {0} functions:\n", List.GetSize());
+  StreamString Stream;
+  List.Dump(&Stream, nullptr);
+  outs() << Stream.GetData() << "\n";
+  return Error::success();
+}
+
+Error opts::symbols::findNamespaces(lldb_private::Module &Module) {
+  SymbolVendor &Vendor = *Module.GetSymbolVendor();
+  Expected<CompilerDeclContext> ContextOr = getDeclContext(Vendor);
+  if (!ContextOr)
+    return ContextOr.takeError();
+  CompilerDeclContext *ContextPtr =
+      ContextOr->IsValid() ? &*ContextOr : nullptr;
+
+  SymbolContext SC;
+  CompilerDeclContext Result =
+      Vendor.FindNamespace(SC, ConstString(Name), ContextPtr);
+  if (Result)
+    outs() << "Found namespace: "
+           << Result.GetScopeQualifiedName().GetStringRef() << "\n";
+  else
+    outs() << "Namespace not found.\n";
+  return Error::success();
+}
+
+Error opts::symbols::findTypes(lldb_private::Module &Module) {
+  SymbolVendor &Vendor = *Module.GetSymbolVendor();
+  Expected<CompilerDeclContext> ContextOr = getDeclContext(Vendor);
+  if (!ContextOr)
+    return ContextOr.takeError();
+  CompilerDeclContext *ContextPtr =
+      ContextOr->IsValid() ? &*ContextOr : nullptr;
+
+  SymbolContext SC;
+  DenseSet<SymbolFile *> SearchedFiles;
+  TypeMap Map;
+  Vendor.FindTypes(SC, ConstString(Name), ContextPtr, true, UINT32_MAX,
+                    SearchedFiles, Map);
+
+  outs() << formatv("Found {0} types:\n", Map.GetSize());
+  StreamString Stream;
+  Map.Dump(&Stream, false);
+  outs() << Stream.GetData() << "\n";
+  return Error::success();
+}
+
+Error opts::symbols::findVariables(lldb_private::Module &Module) {
+  SymbolVendor &Vendor = *Module.GetSymbolVendor();
+  VariableList List;
+  if (Regex) {
+    RegularExpression RE(Name);
+    assert(RE.IsValid());
+    Vendor.FindGlobalVariables(RE, false, UINT32_MAX, List);
+  } else {
+    Expected<CompilerDeclContext> ContextOr = getDeclContext(Vendor);
+    if (!ContextOr)
+      return ContextOr.takeError();
+    CompilerDeclContext *ContextPtr =
+        ContextOr->IsValid() ? &*ContextOr : nullptr;
+
+    Vendor.FindGlobalVariables(ConstString(Name), ContextPtr, false, UINT32_MAX,
+                               List);
+  }
+  outs() << formatv("Found {0} variables:\n", List.GetSize());
+  StreamString Stream;
+  List.Dump(&Stream, false);
+  outs() << Stream.GetData() << "\n";
+  return Error::success();
 }
 
-static void dumpSymbols(Debugger &Dbg) {
-  for (const auto &File : opts::symbols::InputFilenames) {
+Error opts::symbols::dumpModule(lldb_private::Module &Module) {
+  StreamString Stream;
+  Module.ParseAllDebugSymbols();
+  Module.Dump(&Stream);
+  outs() << Stream.GetData() << "\n";
+  return Error::success();
+}
+
+int opts::symbols::dumpSymbols(Debugger &Dbg) {
+  if (Find != FindType::None && Regex && !Context.empty()) {
+    WithColor::error()
+        << "Cannot search using both regular expressions and context.\n";
+    return 1;
+  }
+  if ((Find == FindType::Type || Find == FindType::Namespace) && Regex) {
+    WithColor::error() << "Cannot search for types and namespaces using "
+                          "regular expressions.\n";
+    return 1;
+  }
+  if (Find == FindType::Function && Regex && getFunctionNameFlags() != 0) {
+    WithColor::error() << "Cannot search for types using both regular "
+                          "expressions and function-flags.\n";
+    return 1;
+  }
+  if (Regex && !RegularExpression(Name).IsValid()) {
+    WithColor::error() << "`" << Name
+                       << "` is not a valid regular expression.\n";
+    return 1;
+  }
+
+  Error (*Action)(lldb_private::Module &);
+  switch (Find) {
+  case FindType::Function:
+    Action = findFunctions;
+    break;
+  case FindType::Namespace:
+    Action = findNamespaces;
+    break;
+  case FindType::Type:
+    Action = findTypes;
+    break;
+  case FindType::Variable:
+    Action = findVariables;
+    break;
+  case FindType::None:
+    Action = dumpModule;
+    break;
+  }
+
+  int HadErrors = 0;
+  for (const auto &File : InputFilenames) {
+    outs() << "Module: " << File << "\n";
     ModuleSpec Spec{FileSpec(File, false)};
     Spec.GetSymbolFileSpec().SetFile(File, false);
 
     auto ModulePtr = std::make_shared<lldb_private::Module>(Spec);
+    SymbolVendor *Vendor = ModulePtr->GetSymbolVendor();
+    if (!Vendor) {
+      WithColor::error() << "Module has no symbol vendor.\n";
+      HadErrors = 1;
+      continue;
+    }
+    
+    if (Error E = Action(*ModulePtr)) {
+      WithColor::error() << toString(std::move(E)) << "\n";
+      HadErrors = 1;
+    }
 
-    StreamString Stream;
-    ModulePtr->ParseAllDebugSymbols();
-    ModulePtr->Dump(&Stream);
-    llvm::outs() << Stream.GetData() << "\n";
-    llvm::outs().flush();
+    outs().flush();
   }
+  return HadErrors;
 }
 
-static void dumpModules(Debugger &Dbg) {
+static int dumpModules(Debugger &Dbg) {
   LinePrinter Printer(4, llvm::outs());
 
+  int HadErrors = 0;
   for (const auto &File : opts::module::InputFilenames) {
     ModuleSpec Spec{FileSpec(File, false)};
 
@@ -202,6 +431,7 @@
     SectionList *Sections = ModulePtr->GetSectionList();
     if (!Sections) {
       llvm::errs() << "Could not load sections for module " << File << "\n";
+      HadErrors = 1;
       continue;
     }
 
@@ -226,6 +456,7 @@
       Printer.NewLine();
     }
   }
+  return HadErrors;
 }
 
 int main(int argc, const char *argv[]) {
@@ -236,18 +467,20 @@
 
   cl::ParseCommandLineOptions(argc, argv, "LLDB Testing Utility\n");
 
-  DebuggerLifetime->Initialize(llvm::make_unique<SystemInitializerTest>(),
-                               nullptr);
+  SystemLifetimeManager DebuggerLifetime;
+  DebuggerLifetime.Initialize(llvm::make_unique<SystemInitializerTest>(),
+                              nullptr);
+  CleanUp TerminateDebugger([&] { DebuggerLifetime.Terminate(); });
 
   auto Dbg = lldb_private::Debugger::CreateInstance();
 
   if (opts::BreakpointSubcommand)
-    opts::breakpoint::evaluateBreakpoints(*Dbg);
+    return opts::breakpoint::evaluateBreakpoints(*Dbg);
   if (opts::ModuleSubcommand)
-    dumpModules(*Dbg);
-  else if (opts::SymbolsSubcommand)
-    dumpSymbols(*Dbg);
+    return dumpModules(*Dbg);
+  if (opts::SymbolsSubcommand)
+    return opts::symbols::dumpSymbols(*Dbg);
 
-  DebuggerLifetime->Terminate();
-  return 0;
+  WithColor::error() << "No command specified.\n";
+  return 1;
 }
Index: lldb/trunk/lit/lit.site.cfg.in
===================================================================
--- lldb/trunk/lit/lit.site.cfg.in
+++ lldb/trunk/lit/lit.site.cfg.in
@@ -13,6 +13,7 @@
 config.cc = "@LLDB_TEST_C_COMPILER@"
 config.cxx = "@LLDB_TEST_CXX_COMPILER@"
 config.have_zlib = @LLVM_ENABLE_ZLIB@
+config.have_lld = @LLDB_HAVE_LLD@
 
 # Support substitution of the tools and libs dirs with user parameters. This is
 # used when we can't determine the tool dir at configuration time.
Index: lldb/trunk/lit/CMakeLists.txt
===================================================================
--- lldb/trunk/lit/CMakeLists.txt
+++ lldb/trunk/lit/CMakeLists.txt
@@ -18,6 +18,24 @@
 string(REPLACE ${CMAKE_CFG_INTDIR} ${LLVM_BUILD_MODE} LLDB_LIBS_DIR ${LLVM_LIBRARY_OUTPUT_INTDIR})
 string(REPLACE ${CMAKE_CFG_INTDIR} ${LLVM_BUILD_MODE} LLDB_TOOLS_DIR ${LLVM_RUNTIME_OUTPUT_INTDIR})
 
+set(LLDB_TEST_DEPS
+  LLDBUnitTests
+  dsymutil
+  lldb
+  lldb-test
+  llvm-config
+  llvm-mc
+  llvm-objcopy
+  )
+
+if(TARGET lld)
+  list(APPEND LLDB_TEST_DEPS lld)
+  set(LLDB_HAVE_LLD 1)
+else()
+  set(LLDB_HAVE_LLD 0)
+endif()
+
+
 if(BUILD_SHARED_LIBS)
   set(ENABLE_SHARED 1)
 else()
@@ -36,16 +54,6 @@
   ${CMAKE_CURRENT_BINARY_DIR}/Unit/lit.site.cfg
   )
 
-set(LLDB_TEST_DEPS
-  LLDBUnitTests
-  dsymutil
-  lldb
-  lldb-test
-  llvm-config
-  llvm-mc
-  llvm-objcopy
-  )
-
 if(NOT LLDB_BUILT_STANDALONE)
   list(APPEND LLDB_TEST_DEPS FileCheck not yaml2obj)
 endif()
Index: lldb/trunk/lit/lit.cfg
===================================================================
--- lldb/trunk/lit/lit.cfg
+++ lldb/trunk/lit/lit.cfg
@@ -132,6 +132,8 @@
     config.available_features.add("compiler-msvc")
 
 config.available_features.add(binary_feature(config.have_zlib, "zlib", "no"))
+if config.have_lld:
+  config.available_features.add("lld")
 
 # llvm-config knows whether it is compiled with asserts (and)
 # whether we are operating in release/debug mode.
Index: lldb/trunk/lit/SymbolFile/DWARF/find-basic-namespace.cpp
===================================================================
--- lldb/trunk/lit/SymbolFile/DWARF/find-basic-namespace.cpp
+++ lldb/trunk/lit/SymbolFile/DWARF/find-basic-namespace.cpp
@@ -0,0 +1,29 @@
+// REQUIRES: lld
+
+// RUN: clang %s -g -c -o %t.o --target=x86_64-pc-linux
+// RUN: ld.lld %t.o -o %t
+// RUN: lldb-test symbols --name=foo --find=namespace %t | \
+// RUN:   FileCheck --check-prefix=FOO %s
+// RUN: lldb-test symbols --name=foo --find=namespace --context=context %t | \
+// RUN:   FileCheck --check-prefix=CONTEXT %s
+// RUN: lldb-test symbols --name=not_there --find=namespace %t | \
+// RUN:   FileCheck --check-prefix=EMPTY %s
+
+// FOO: Found namespace: foo
+
+// CONTEXT: Found namespace: bar::foo
+
+// EMPTY: Namespace not found.
+
+namespace foo {
+int X;
+}
+
+namespace bar {
+int context;
+namespace foo {
+int X;
+}
+} // namespace bar
+
+extern "C" void _start() {}
Index: lldb/trunk/lit/SymbolFile/DWARF/find-type-in-function.cpp
===================================================================
--- lldb/trunk/lit/SymbolFile/DWARF/find-type-in-function.cpp
+++ lldb/trunk/lit/SymbolFile/DWARF/find-type-in-function.cpp
@@ -0,0 +1,24 @@
+// REQUIRES: lld
+
+// XFAIL: *
+
+// RUN: clang %s -g -c -o %t.o --target=x86_64-pc-linux
+// RUN: ld.lld %t.o -o %t
+// RUN: lldb-test symbols --name=foo --find=type %t | \
+// RUN:   FileCheck --check-prefix=NAME %s
+
+// Lookup for "foo" should find either both "struct foo" types or just the
+// global one. Right now, it finds the definition inside bar(), which is
+// definitely wrong.
+
+// NAME: Found 2 types:
+struct foo {};
+// NAME-DAG: name = "foo", {{.*}} decl = find-type-in-function.cpp:[[@LINE-1]]
+
+void bar() {
+  struct foo {};
+// NAME-DAG: name = "foo", {{.*}} decl = find-type-in-function.cpp:[[@LINE-1]]
+  foo a;
+}
+
+extern "C" void _start(foo) {}
Index: lldb/trunk/lit/SymbolFile/DWARF/find-basic-variable.cpp
===================================================================
--- lldb/trunk/lit/SymbolFile/DWARF/find-basic-variable.cpp
+++ lldb/trunk/lit/SymbolFile/DWARF/find-basic-variable.cpp
@@ -0,0 +1,55 @@
+// REQUIRES: lld
+
+// RUN: clang %s -g -c -o %t.o --target=x86_64-pc-linux
+// RUN: ld.lld %t.o -o %t
+// RUN: lldb-test symbols --name=foo --find=variable --context=context %t | \
+// RUN:   FileCheck --check-prefix=CONTEXT %s
+// RUN: lldb-test symbols --name=foo --find=variable %t | \
+// RUN:   FileCheck --check-prefix=NAME %s
+// RUN: lldb-test symbols --regex --name=foo --find=variable %t | \
+// RUN:   FileCheck --check-prefix=REGEX %s
+// RUN: lldb-test symbols --name=not_there --find=variable %t | \
+// RUN:   FileCheck --check-prefix=EMPTY %s
+
+// EMPTY: Found 0 variables:
+// NAME: Found 4 variables:
+// CONTEXT: Found 1 variables:
+// REGEX: Found 5 variables:
+int foo;
+// NAME-DAG: name = "foo", type = {{.*}} (int), {{.*}} decl = find-basic-variable.cpp:[[@LINE-1]]
+// REGEX-DAG: name = "foo", type = {{.*}} (int), {{.*}} decl = find-basic-variable.cpp:[[@LINE-2]]
+namespace bar {
+int context;
+long foo;
+// NAME-DAG: name = "foo", type = {{.*}} (long int), {{.*}} decl = find-basic-variable.cpp:[[@LINE-1]]
+// CONTEXT-DAG: name = "foo", type = {{.*}} (long int), {{.*}} decl = find-basic-variable.cpp:[[@LINE-2]]
+// REGEX-DAG: name = "foo", type = {{.*}} (long int), {{.*}} decl = find-basic-variable.cpp:[[@LINE-3]]
+namespace baz {
+static short foo;
+// NAME-DAG: name = "foo", type = {{.*}} (short), {{.*}} decl = find-basic-variable.cpp:[[@LINE-1]]
+// REGEX-DAG: name = "foo", type = {{.*}} (short), {{.*}} decl = find-basic-variable.cpp:[[@LINE-2]]
+}
+}
+
+struct sbar {
+  static int foo;
+// NAME-DAG: name = "foo", type = {{.*}} (int), {{.*}} decl = find-basic-variable.cpp:[[@LINE-1]]
+// REGEX-DAG: name = "foo", type = {{.*}} (int), {{.*}} decl = find-basic-variable.cpp:[[@LINE-2]]
+};
+int sbar::foo;
+
+int foobar;
+// REGEX-DAG: name = "foobar", type = {{.*}} (int), {{.*}} decl = find-basic-variable.cpp:[[@LINE-1]]
+
+int fbar() {
+  static int foo;
+  return foo + bar::baz::foo;
+}
+
+int Foo;
+
+struct ssbar {
+  int foo;
+};
+
+extern "C" void _start(sbar, ssbar) {}
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
@@ -0,0 +1,67 @@
+// REQUIRES: lld
+
+// RUN: clang %s -g -c -o %t.o --target=x86_64-pc-linux
+// 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=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"
+// BASE-DAG: name = "bar::foo()", mangled = "_ZN3bar3fooEv"
+// BASE-DAG: name = "bar::baz::foo()", mangled = "_ZN3bar3baz3fooEv"
+
+// METHOD: Found 3 functions:
+// METHOD-DAG: name = "sbar::foo()", mangled = "_ZN4sbar3fooEv"
+// METHOD-DAG: name = "sbar::foo(int)", mangled = "_ZN4sbar3fooEi"
+// METHOD-DAG: name = "ffbar()::sbar::foo()", mangled = "_ZZ5ffbarvEN4sbar3fooEv"
+
+// FULL: Found 2 functions:
+// FULL-DAG: name = "foo()", mangled = "_Z3foov"
+// FULL-DAG: name = "foo(int)", mangled = "_Z3fooi"
+
+// CONTEXT: Found 1 functions:
+// CONTEXT-DAG: name = "bar::foo()", mangled = "_ZN3bar3fooEv"
+
+// EMPTY: Found 0 functions:
+
+void foo() {}
+void foo(int) {}
+
+namespace bar {
+int context;
+void foo() {}
+namespace baz {
+void foo() {}
+} // namespace baz
+} // namespace bar
+
+struct foo {};
+void fbar(struct foo) {}
+
+void Foo() {}
+
+struct sbar {
+  void foo();
+  static void foo(int);
+};
+void sbar::foo() {}
+void sbar::foo(int) {}
+
+void ffbar() {
+  struct sbar {
+    void foo() {}
+  };
+  sbar a;
+  a.foo();
+}
+
+extern "C" void _start() {}
Index: lldb/trunk/lit/SymbolFile/DWARF/lit.local.cfg
===================================================================
--- lldb/trunk/lit/SymbolFile/DWARF/lit.local.cfg
+++ lldb/trunk/lit/SymbolFile/DWARF/lit.local.cfg
@@ -0,0 +1 @@
+config.suffixes = ['.cpp']
Index: lldb/trunk/lit/SymbolFile/DWARF/find-basic-type.cpp
===================================================================
--- lldb/trunk/lit/SymbolFile/DWARF/find-basic-type.cpp
+++ lldb/trunk/lit/SymbolFile/DWARF/find-basic-type.cpp
@@ -0,0 +1,38 @@
+// REQUIRES: lld
+
+// RUN: clang %s -g -c -o %t.o --target=x86_64-pc-linux
+// RUN: ld.lld %t.o -o %t
+// RUN: lldb-test symbols --name=foo --find=type %t | \
+// RUN:   FileCheck --check-prefix=NAME %s
+// RUN: lldb-test symbols --name=foo --context=context --find=type %t | \
+// RUN:   FileCheck --check-prefix=CONTEXT %s
+// RUN: lldb-test symbols --name=not_there --find=type %t | \
+// RUN:   FileCheck --check-prefix=EMPTY %s
+
+// EMPTY: Found 0 types:
+// NAME: Found 4 types:
+// CONTEXT: Found 1 types:
+struct foo { };
+// NAME-DAG: name = "foo", {{.*}} decl = find-basic-type.cpp:[[@LINE-1]]
+
+namespace bar {
+int context;
+struct foo {};
+// NAME-DAG: name = "foo", {{.*}} decl = find-basic-type.cpp:[[@LINE-1]]
+// CONTEXT-DAG: name = "foo", {{.*}} decl = find-basic-type.cpp:[[@LINE-2]]
+namespace baz {
+struct foo {};
+// NAME-DAG: name = "foo", {{.*}} decl = find-basic-type.cpp:[[@LINE-1]]
+}
+}
+
+struct sbar {
+  struct foo {};
+// NAME-DAG: name = "foo", {{.*}} decl = find-basic-type.cpp:[[@LINE-1]]
+};
+
+struct foobar {};
+
+struct Foo {};
+
+extern "C" void _start(foo, bar::foo, bar::baz::foo, sbar::foo, foobar, Foo) {}
Index: lldb/trunk/include/lldb/Symbol/VariableList.h
===================================================================
--- lldb/trunk/include/lldb/Symbol/VariableList.h
+++ lldb/trunk/include/lldb/Symbol/VariableList.h
@@ -66,6 +66,7 @@
   size_t MemorySize() const;
 
   size_t GetSize() const;
+  bool Empty() const { return m_variables.empty(); }
 
 protected:
   typedef std::vector<lldb::VariableSP> collection;
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to