[Lldb-commits] [lldb] r341782 - [PDB] Restore AST from PDB symbols

Aleksandr Urakov via lldb-commits lldb-commits at lists.llvm.org
Mon Sep 10 01:08:43 PDT 2018


Author: aleksandr.urakov
Date: Mon Sep 10 01:08:43 2018
New Revision: 341782

URL: http://llvm.org/viewvc/llvm-project?rev=341782&view=rev
Log:
[PDB] Restore AST from PDB symbols

Summary:
This patch adds an implementation of retrieving of declarations and declaration
contexts based on PDB symbols.

PDB has different type symbols for const-qualified types, and this
implementation ensures that only one declaration was created for both const
and non-const types, but creates different compiler types for them.

The implementation also processes the case when there are two symbols
corresponding to a variable. It's possible e.g. for class static variables,
they has one global symbol and one symbol belonging to a class.

PDB has no info about namespaces, so this implementation parses the full symbol
name and tries to figure out if the symbol belongs to namespace or not,
and then creates nested namespaces if necessary.

Reviewers: asmith, zturner, labath

Reviewed By: asmith

Subscribers: aleksandr.urakov, teemperor, lldb-commits, stella.stamenova

Tags: #lldb

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

Added:
    lldb/trunk/lit/SymbolFile/PDB/Inputs/AstRestoreTest.cpp
    lldb/trunk/lit/SymbolFile/PDB/ast-restore.test
Modified:
    lldb/trunk/include/lldb/Symbol/ClangASTContext.h
    lldb/trunk/lit/SymbolFile/PDB/class-layout.test
    lldb/trunk/lit/SymbolFile/PDB/func-symbols.test
    lldb/trunk/lit/SymbolFile/PDB/pointers.test
    lldb/trunk/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp
    lldb/trunk/source/Plugins/SymbolFile/PDB/PDBASTParser.h
    lldb/trunk/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp
    lldb/trunk/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h
    lldb/trunk/source/Symbol/ClangASTContext.cpp
    lldb/trunk/tools/lldb-test/lldb-test.cpp

Modified: lldb/trunk/include/lldb/Symbol/ClangASTContext.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Symbol/ClangASTContext.h?rev=341782&r1=341781&r2=341782&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Symbol/ClangASTContext.h (original)
+++ lldb/trunk/include/lldb/Symbol/ClangASTContext.h Mon Sep 10 01:08:43 2018
@@ -214,19 +214,24 @@ public:
   static CompilerType GetTypeForDecl(clang::ObjCInterfaceDecl *objc_decl);
 
   template <typename RecordDeclType>
-  CompilerType GetTypeForIdentifier(const ConstString &type_name) {
+  CompilerType
+  GetTypeForIdentifier(const ConstString &type_name,
+                       clang::DeclContext *decl_context = nullptr) {
     CompilerType compiler_type;
 
     if (type_name.GetLength()) {
       clang::ASTContext *ast = getASTContext();
       if (ast) {
+        if (!decl_context)
+          decl_context = ast->getTranslationUnitDecl();
+
         clang::IdentifierInfo &myIdent =
             ast->Idents.get(type_name.GetCString());
         clang::DeclarationName myName =
             ast->DeclarationNames.getIdentifier(&myIdent);
 
         clang::DeclContext::lookup_result result =
-            ast->getTranslationUnitDecl()->lookup(myName);
+            decl_context->lookup(myName);
 
         if (!result.empty()) {
           clang::NamedDecl *named_decl = result[0];
@@ -881,7 +886,7 @@ public:
   //----------------------------------------------------------------------
   // Modifying Enumeration types
   //----------------------------------------------------------------------
-  bool AddEnumerationValueToEnumerationType(
+  clang::EnumConstantDecl *AddEnumerationValueToEnumerationType(
       lldb::opaque_compiler_type_t type,
       const CompilerType &enumerator_qual_type, const Declaration &decl,
       const char *name, int64_t enum_value, uint32_t enum_value_bit_size);
@@ -937,6 +942,8 @@ public:
 
   static clang::TagDecl *GetAsTagDecl(const CompilerType &type);
 
+  static clang::TypedefNameDecl *GetAsTypedefDecl(const CompilerType &type);
+
   clang::CXXRecordDecl *GetAsCXXRecordDecl(lldb::opaque_compiler_type_t type);
 
   static clang::ObjCInterfaceDecl *

Added: lldb/trunk/lit/SymbolFile/PDB/Inputs/AstRestoreTest.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/lit/SymbolFile/PDB/Inputs/AstRestoreTest.cpp?rev=341782&view=auto
==============================================================================
--- lldb/trunk/lit/SymbolFile/PDB/Inputs/AstRestoreTest.cpp (added)
+++ lldb/trunk/lit/SymbolFile/PDB/Inputs/AstRestoreTest.cpp Mon Sep 10 01:08:43 2018
@@ -0,0 +1,47 @@
+namespace N0 {
+namespace N1 {
+
+namespace {
+enum Enum { Enum_0 = 1, Enum_1 = 2, Enum_2 = 4, Enum_3 = 8 };
+}
+
+Enum Global = Enum_3;
+
+struct Base {
+  Enum m_e = Enum_1;
+};
+
+class Class : public Base {
+public:
+  Class(Enum e) : m_ce(e) {}
+
+  static int StaticFunc(const Class &c) {
+    return c.PrivateFunc(c.m_inner) + Global + ClassStatic;
+  }
+
+  const Enum m_ce;
+
+  static int ClassStatic;
+
+private:
+  struct Inner {
+    char x;
+    short y;
+    int z;
+  };
+
+  int PrivateFunc(const Inner &i) const { return i.z; }
+
+  Inner m_inner{};
+};
+int Class::ClassStatic = 7;
+
+void foo() { Class::StaticFunc(Class(Enum_0)); }
+
+} // namespace N1
+} // namespace N0
+
+int main() {
+  N0::N1::foo();
+  return 0;
+}

Added: lldb/trunk/lit/SymbolFile/PDB/ast-restore.test
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/lit/SymbolFile/PDB/ast-restore.test?rev=341782&view=auto
==============================================================================
--- lldb/trunk/lit/SymbolFile/PDB/ast-restore.test (added)
+++ lldb/trunk/lit/SymbolFile/PDB/ast-restore.test Mon Sep 10 01:08:43 2018
@@ -0,0 +1,77 @@
+REQUIRES: windows
+RUN: cl /Zi /GS- /c %S/Inputs/AstRestoreTest.cpp /Fo%t.obj
+RUN: link /debug:full /nodefaultlib /entry:main %t.obj /out:%t.exe
+RUN: lldb-test symbols -dump-ast %t.exe | FileCheck --check-prefix=ENUM %s
+RUN: lldb-test symbols -dump-ast %t.exe | FileCheck --check-prefix=GLOBAL %s
+RUN: lldb-test symbols -dump-ast %t.exe | FileCheck --check-prefix=BASE %s
+RUN: lldb-test symbols -dump-ast %t.exe | FileCheck --check-prefix=CLASS %s
+RUN: lldb-test symbols -dump-ast %t.exe | FileCheck --check-prefix=INNER %s
+RUN: lldb-test symbols -dump-ast %t.exe | FileCheck --check-prefix=FOO %s
+RUN: lldb-test symbols -dump-ast %t.exe | FileCheck --check-prefix=MAIN %s
+
+ENUM: Module: {{.*}}
+ENUM: namespace N0 {
+ENUM:     namespace N1 {
+ENUM:         namespace  {
+ENUM:             enum Enum {
+ENUM:                 Enum_0,
+ENUM:                 Enum_1,
+ENUM:                 Enum_2,
+ENUM:                 Enum_3
+ENUM:             };
+ENUM:         }
+ENUM:     }
+ENUM: }
+
+GLOBAL: Module: {{.*}}
+GLOBAL: namespace N0 {
+GLOBAL:     namespace N1 {
+GLOBAL:         N0::N1::(anonymous namespace)::Enum Global;
+GLOBAL:     }
+GLOBAL: }
+
+BASE: Module: {{.*}}
+BASE: namespace N0 {
+BASE:     namespace N1 {
+BASE:         struct Base {
+BASE:             N0::N1::(anonymous namespace)::Enum m_e;
+BASE:         };
+BASE:     }
+BASE: }
+
+CLASS: Module: {{.*}}
+CLASS: namespace N0 {
+CLASS:     namespace N1 {
+CLASS:         class Class : public N0::N1::Base {
+CLASS-DAG:             const N0::N1::(anonymous namespace)::Enum m_ce;
+CLASS-DAG:             static int ClassStatic;
+CLASS-DAG:             N0::N1::Class::Inner m_inner;
+CLASS-DAG:             {{(inline )?}}Class(N0::N1::(anonymous namespace)::Enum);
+CLASS-DAG:             static {{(inline )?}}int StaticFunc(const N0::N1::Class &);
+CLASS-DAG:             {{(inline )?}}int PrivateFunc(const N0::N1::Class::Inner &);
+CLASS:         };
+CLASS:     }
+CLASS: }
+
+INNER: Module: {{.*}}
+INNER: namespace N0 {
+INNER:     namespace N1 {
+INNER:         class Class : public N0::N1::Base {
+INNER:             struct Inner {
+INNER:                 signed char x;
+INNER:                 short y;
+INNER:                 int z;
+INNER:             };
+INNER:         };
+INNER:     }
+INNER: }
+
+FOO: Module: {{.*}}
+FOO: namespace N0 {
+FOO:     namespace N1 {
+FOO:         void foo();
+FOO:     }
+FOO: }
+
+MAIN: Module: {{.*}}
+MAIN: int main();

Modified: lldb/trunk/lit/SymbolFile/PDB/class-layout.test
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/lit/SymbolFile/PDB/class-layout.test?rev=341782&r1=341781&r2=341782&view=diff
==============================================================================
--- lldb/trunk/lit/SymbolFile/PDB/class-layout.test (original)
+++ lldb/trunk/lit/SymbolFile/PDB/class-layout.test Mon Sep 10 01:08:43 2018
@@ -61,30 +61,30 @@ UNNAMED-STRUCT-SAME: struct UnnamedStruc
 UNNAMED-STRUCT:   int a;
 UNNAMED-STRUCT:}
 
-BASE:  name = "MemberTest::Base", size = 4,  decl = ClassLayoutTest.cpp:59
-BASE-SAME: class MemberTest::Base {
+BASE:  name = "Base", size = 4,  decl = ClassLayoutTest.cpp:59
+BASE-SAME: class Base {
 BASE:    int a;
-BASE:    void {{.*}}Base();
-BASE:    {{.*}}~Base();
-BASE:    int {{.*}}Get();
+BASE:    Base();
+BASE:    ~Base();
+BASE:    int Get();
 BASE:}
 
-FRIEND:  name = "MemberTest::Friend", size = 1, decl = ClassLayoutTest.cpp:70
-FRIEND-SAME: class MemberTest::Friend {
+FRIEND:  name = "Friend", size = 1, decl = ClassLayoutTest.cpp:70
+FRIEND-SAME: class Friend {
 FRIEND:    int f();
 FRIEND: }
 
-CLASS:  name = "MemberTest::Class", size = 88, decl = ClassLayoutTest.cpp:74
-CLASS-SAME: class MemberTest::Class : public MemberTest::Base {
+CLASS:  name = "Class", size = 88, decl = ClassLayoutTest.cpp:74
+CLASS-SAME: class Class : public MemberTest::Base {
 CLASS:    static int m_static;
 CLASS:    int m_public;
 CLASS:    Struct m_struct;
 CLASS:    Union m_union;
 CLASS:    int m_private;
 CLASS:    int m_protected;
-CLASS:    void Class();
-CLASS:    void Class(int);
-CLASS:    ~MemberTest::Class();
+CLASS:    Class();
+CLASS:    Class(int);
+CLASS:    ~Class();
 CLASS:    static int {{.*}}StaticMemberFunc(int, ...);
 CLASS:    int Get();
 CLASS:    int f(MemberTest::Friend);

Modified: lldb/trunk/lit/SymbolFile/PDB/func-symbols.test
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/lit/SymbolFile/PDB/func-symbols.test?rev=341782&r1=341781&r2=341782&view=diff
==============================================================================
--- lldb/trunk/lit/SymbolFile/PDB/func-symbols.test (original)
+++ lldb/trunk/lit/SymbolFile/PDB/func-symbols.test Mon Sep 10 01:08:43 2018
@@ -14,11 +14,11 @@ CHECK-ONE-DAG: [[TY0:.*]]:   Type{[[UID0
 CHECK-ONE-DAG: [[TY1:.*]]:   Type{[[UID1:.*]]} , name = "Func_arg_void", decl = FuncSymbolsTestMain.cpp:4, compiler_type = {{.*}} void (void)
 CHECK-ONE-DAG: [[TY2:.*]]:   Type{[[UID2:.*]]} , name = "Func_arg_none", decl = FuncSymbolsTestMain.cpp:5, compiler_type = {{.*}} void (void)
 CHECK-ONE-DAG: [[TY3:.*]]:   Type{[[UID3:.*]]} , name = "Func_varargs", decl = FuncSymbolsTestMain.cpp:6, compiler_type = {{.*}} void (...)
-CHECK-ONE-DAG: [[TY4:.*]]:   Type{[[UID4:.*]]} , name = "NS::Func", decl = FuncSymbolsTestMain.cpp:28, compiler_type = {{.*}} void (signed char, int)
+CHECK-ONE-DAG: [[TY4:.*]]:   Type{[[UID4:.*]]} , name = "Func", decl = FuncSymbolsTestMain.cpp:28, compiler_type = {{.*}} void (signed char, int)
 CHECK-ONE-DAG: [[TY5:.*]]:   Type{[[UID5:.*]]} , name = "main", decl = FuncSymbolsTestMain.cpp:44, compiler_type = {{.*}} int (void)
-CHECK-ONE-DAG: [[TY6:.*]]:   Type{[[UID6:.*]]} , name = "`anonymous namespace'::Func", decl = FuncSymbolsTestMain.cpp:24, compiler_type = {{.*}} void (int, const long, volatile _Bool, ...)
+CHECK-ONE-DAG: [[TY6:.*]]:   Type{[[UID6:.*]]} , name = "Func", decl = FuncSymbolsTestMain.cpp:24, compiler_type = {{.*}} void (int, const long, volatile _Bool, ...)
 CHECK-ONE-DAG: [[TY7:.*]]:   Type{[[UID7:.*]]} , name = "StaticFunction", decl = FuncSymbolsTestMain.cpp:35, compiler_type = {{.*}} long (int)
-CHECK-ONE-DAG: [[TY8:.*]]:   Type{[[UID8:.*]]} , name = "MemberTest::A::Func", decl = FuncSymbolsTestMain.cpp:12, compiler_type = {{.*}} int (int, ...)
+CHECK-ONE-DAG: [[TY8:.*]]:   Type{[[UID8:.*]]} , name = "Func", decl = FuncSymbolsTestMain.cpp:12, compiler_type = {{.*}} int (int, ...)
 CHECK-ONE-DAG: [[TY9:.*]]:   Type{[[UID9:.*]]} , name = "TemplateFunc<1,int>", decl = FuncSymbolsTestMain.cpp:18, compiler_type = {{.*}} void (int)
 CHECK-ONE-DAG: [[TY10:.*]]:   Type{[[UID10:.*]]} , name = "TemplateFunc<1,int,int,int>", decl = FuncSymbolsTestMain.cpp:18, compiler_type = {{.*}} void (int, int, int)
 CHECK-ONE-DAG: [[TY11:.*]]:   Type{[[UID11:.*]]} , name = "InlinedFunction", decl = FuncSymbolsTestMain.cpp:40, compiler_type = {{.*}} void (long)
@@ -39,7 +39,7 @@ CHECK-ONE-DAG: Function{[[UID11]]}, mang
 
 ; We expect new types observed in another compile unit
 CHECK-TWO-DAG: [[TY30:.*]]:   Type{[[UID30:.*]]} , name = "FunctionCall", decl = FuncSymbols.cpp:13, compiler_type = {{.*}} void (void)
-CHECK-TWO-DAG: [[TY31:.*]]:   Type{[[UID31:.*]]} , name = "`anonymous namespace'::StaticFunction", decl = FuncSymbols.cpp:4, compiler_type = {{.*}} long (int)
+CHECK-TWO-DAG: [[TY31:.*]]:   Type{[[UID31:.*]]} , name = "StaticFunction", decl = FuncSymbols.cpp:4, compiler_type = {{.*}} long (int)
 CHECK-TWO-DAG: [[TY32:.*]]:   Type{[[UID32:.*]]} , name = "InlinedFunction", decl = FuncSymbols.cpp:10, compiler_type = {{.*}} int (long)
 
 CHECK-TWO: {{.*}}:   CompileUnit{{.*}}, language = "c++", file = '{{.*}}\FuncSymbols.cpp'

Modified: lldb/trunk/lit/SymbolFile/PDB/pointers.test
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/lit/SymbolFile/PDB/pointers.test?rev=341782&r1=341781&r2=341782&view=diff
==============================================================================
--- lldb/trunk/lit/SymbolFile/PDB/pointers.test (original)
+++ lldb/trunk/lit/SymbolFile/PDB/pointers.test Mon Sep 10 01:08:43 2018
@@ -10,11 +10,11 @@ RUN: lldb-test symbols %T/PointerTypeTes
 CHECK: Module [[MOD:.*]]
 CHECK: {{^[0-9A-F]+}}:   CompileUnit{{[{]0x[0-9a-f]+[}]}}, language = "c++", file = '{{.*}}\PointerTypeTest.cpp'
 
-MAIN-ST-F:  name = "main::ST::f"
+MAIN-ST-F:  name = "f"
 MAIN-ST-F-SAME: decl = PointerTypeTest.cpp:8
 MAIN-ST-F-SAME: compiler_type = {{.*}} int (int)
 
-MAIN-ST:  name = "main::ST", size = 4, decl = PointerTypeTest.cpp:6, compiler_type = {{.*}} struct main::ST {
+MAIN-ST:  name = "ST", size = 4, decl = PointerTypeTest.cpp:6, compiler_type = {{.*}} struct ST {
 MAIN-ST-NEXT: int a;
 MAIN-ST-NEXT: int {{.*}}f(int);
 MAIN-ST-NEXT:}
@@ -26,13 +26,13 @@ MAIN-SAME:    (int (*)[2][4]), scope = l
 MAIN:     Variable{{.*}}, name = "p_int"
 MAIN-SAME:    (int *), scope = local
 MAIN:     Variable{{.*}}, name = "p_member_field"
-MAIN-SAME:    (int main::ST::*), scope = local
+MAIN-SAME:    (int ST::*), scope = local
 MAIN:     Variable{{.*}}, name = "p_member_method"
-MAIN-SAME:    (int (main::ST::*)(int)), scope = local
+MAIN-SAME:    (int (ST::*)(int)), scope = local
 
 F:   Function{[[FID2:.*]]}, demangled = {{.*}}f(int)
 F-NEXT:  Block{[[FID2]]}
 F:     Variable{{.*}}, name = "this"
-F-SAME:    (main::ST *), scope = parameter, location = {{.*}}, artificial
+F-SAME:    (ST *), scope = parameter, location = {{.*}}, artificial
 F:     Variable{{.*}}, name = "x"
 F-SAME:    (int), scope = parameter, decl = PointerTypeTest.cpp:8

Modified: lldb/trunk/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp?rev=341782&r1=341781&r2=341782&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp (original)
+++ lldb/trunk/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp Mon Sep 10 01:08:43 2018
@@ -21,6 +21,7 @@
 #include "lldb/Symbol/ClangUtil.h"
 #include "lldb/Symbol/Declaration.h"
 #include "lldb/Symbol/SymbolFile.h"
+#include "lldb/Symbol/TypeMap.h"
 #include "lldb/Symbol/TypeSystem.h"
 
 #include "llvm/DebugInfo/PDB/IPDBLineNumber.h"
@@ -244,8 +245,8 @@ AccessType GetAccessibilityForUdt(const
   return GetDefaultAccessibilityForUdtKind(parent_udt->getUdtKind());
 }
 
-clang::MSInheritanceAttr::Spelling GetMSInheritance(
-    const PDBSymbolTypeUDT &udt) {
+clang::MSInheritanceAttr::Spelling
+GetMSInheritance(const PDBSymbolTypeUDT &udt) {
   int base_count = 0;
   bool has_virtual = false;
 
@@ -263,6 +264,46 @@ clang::MSInheritanceAttr::Spelling GetMS
     return clang::MSInheritanceAttr::Keyword_multiple_inheritance;
   return clang::MSInheritanceAttr::Keyword_single_inheritance;
 }
+
+std::unique_ptr<llvm::pdb::PDBSymbol>
+GetClassOrFunctionParent(const llvm::pdb::PDBSymbol &symbol) {
+  const IPDBSession &session = symbol.getSession();
+  const IPDBRawSymbol &raw = symbol.getRawSymbol();
+
+  auto class_parent_id = raw.getClassParentId();
+  if (auto class_parent = session.getSymbolById(class_parent_id))
+    return class_parent;
+
+  auto lexical_parent_id = raw.getLexicalParentId();
+  auto lexical_parent = session.getSymbolById(lexical_parent_id);
+  if (!lexical_parent)
+    return nullptr;
+
+  auto lexical_parent_tag = lexical_parent->getSymTag();
+  if (lexical_parent_tag == PDB_SymType::Function)
+    return lexical_parent;
+  if (lexical_parent_tag == PDB_SymType::Exe)
+    return nullptr;
+
+  return GetClassOrFunctionParent(*lexical_parent);
+}
+
+clang::NamedDecl *
+GetDeclFromContextByName(const clang::ASTContext &ast,
+                         const clang::DeclContext &decl_context,
+                         llvm::StringRef name) {
+  clang::IdentifierInfo &ident = ast.Idents.get(name);
+  clang::DeclarationName decl_name = ast.DeclarationNames.getIdentifier(&ident);
+  clang::DeclContext::lookup_result result = decl_context.lookup(decl_name);
+  if (result.empty())
+    return nullptr;
+
+  return result[0];
+}
+
+bool IsAnonymousNamespaceName(const std::string &name) {
+  return name == "`anonymous namespace'" | name == "`anonymous-namespace'";
+}
 } // namespace
 
 PDBASTParser::PDBASTParser(lldb_private::ClangASTContext &ast) : m_ast(ast) {}
@@ -272,13 +313,7 @@ PDBASTParser::~PDBASTParser() {}
 // DebugInfoASTParser interface
 
 lldb::TypeSP PDBASTParser::CreateLLDBTypeFromPDBType(const PDBSymbol &type) {
-  // PDB doesn't maintain enough information to robustly rebuild the entire
-  // tree, and this is most problematic when it comes to figure out the right
-  // DeclContext to put a type in.  So for now, everything goes in the
-  // translation unit decl as a fully qualified type.
-  clang::DeclContext *tu_decl_ctx = m_ast.GetTranslationUnitDecl();
   Declaration decl;
-
   switch (type.getSymTag()) {
   case PDB_SymType::BaseClass: {
     auto symbol_file = m_ast.GetSymbolFile();
@@ -304,21 +339,66 @@ lldb::TypeSP PDBASTParser::CreateLLDBTyp
       return nullptr;
 
     // Ignore unnamed-tag UDTs.
-    if (udt->getName().empty())
+    auto name = PDBNameDropScope(udt->getName());
+    if (name.empty())
       return nullptr;
 
-    auto access = GetAccessibilityForUdt(*udt);
+    auto decl_context = GetDeclContextContainingSymbol(type);
 
-    auto tag_type_kind = TranslateUdtKind(udt->getUdtKind());
+    // Check if such an UDT already exists in the current context.
+    // This may occur with const or volatile types. There are separate type
+    // symbols in PDB for types with const or volatile modifiers, but we need
+    // to create only one declaration for them all.
+    Type::ResolveStateTag type_resolve_state_tag;
+    CompilerType clang_type = m_ast.GetTypeForIdentifier<clang::CXXRecordDecl>(
+        ConstString(name), decl_context);
+    if (!clang_type.IsValid()) {
+      auto access = GetAccessibilityForUdt(*udt);
+
+      auto tag_type_kind = TranslateUdtKind(udt->getUdtKind());
+
+      ClangASTMetadata metadata;
+      metadata.SetUserID(type.getSymIndexId());
+      metadata.SetIsDynamicCXXType(false);
+
+      clang_type = m_ast.CreateRecordType(
+          decl_context, access, name.c_str(), tag_type_kind,
+          lldb::eLanguageTypeC_plus_plus, &metadata);
+      assert(clang_type.IsValid());
+
+      auto record_decl =
+          m_ast.GetAsCXXRecordDecl(clang_type.GetOpaqueQualType());
+      assert(record_decl);
+      m_uid_to_decl[type.getSymIndexId()] = record_decl;
+
+      auto inheritance_attr = clang::MSInheritanceAttr::CreateImplicit(
+          *m_ast.getASTContext(), GetMSInheritance(*udt));
+      record_decl->addAttr(inheritance_attr);
+
+      ClangASTContext::StartTagDeclarationDefinition(clang_type);
+
+      auto children = udt->findAllChildren();
+      if (!children || children->getChildCount() == 0) {
+        // PDB does not have symbol of forwarder. We assume we get an udt w/o
+        // any fields. Just complete it at this point.
+        ClangASTContext::CompleteTagDeclarationDefinition(clang_type);
+
+        ClangASTContext::SetHasExternalStorage(clang_type.GetOpaqueQualType(),
+                                               false);
 
-    ClangASTMetadata metadata;
-    metadata.SetUserID(type.getSymIndexId());
-    metadata.SetIsDynamicCXXType(false);
-
-    CompilerType clang_type = m_ast.CreateRecordType(
-        tu_decl_ctx, access, udt->getName().c_str(), tag_type_kind,
-        lldb::eLanguageTypeC_plus_plus, &metadata);
-    assert(clang_type.IsValid());
+        type_resolve_state_tag = Type::eResolveStateFull;
+      } else {
+        // Add the type to the forward declarations. It will help us to avoid
+        // an endless recursion in CompleteTypeFromUdt function.
+        m_forward_decl_to_uid[record_decl] = type.getSymIndexId();
+
+        ClangASTContext::SetHasExternalStorage(clang_type.GetOpaqueQualType(),
+                                               true);
+
+        type_resolve_state_tag = Type::eResolveStateForward;
+      }
+    } else
+      type_resolve_state_tag = Type::eResolveStateForward;
 
     if (udt->isConstType())
       clang_type = clang_type.AddConstModifier();
@@ -326,83 +406,73 @@ lldb::TypeSP PDBASTParser::CreateLLDBTyp
     if (udt->isVolatileType())
       clang_type = clang_type.AddVolatileModifier();
 
-    clang::CXXRecordDecl *record_decl =
-      m_ast.GetAsCXXRecordDecl(clang_type.GetOpaqueQualType());
-    assert(record_decl);
-    auto inheritance_attr = clang::MSInheritanceAttr::CreateImplicit(
-        *m_ast.getASTContext(), GetMSInheritance(*udt));
-    record_decl->addAttr(inheritance_attr);
-
-    ClangASTContext::StartTagDeclarationDefinition(clang_type);
-
-    Type::ResolveStateTag type_resolve_state_tag;
-    auto children = udt->findAllChildren();
-    if (!children || children->getChildCount() == 0) {
-      // PDB does not have symbol of forwarder. We assume we get an udt w/o any
-      // fields. Just complete it at this point.
-      ClangASTContext::CompleteTagDeclarationDefinition(clang_type);
-
-      m_ast.SetHasExternalStorage(clang_type.GetOpaqueQualType(), false);
-
-      type_resolve_state_tag = Type::eResolveStateFull;
-    } else {
-      // Add the type to the forward declarations. It will help us to avoid
-      // an endless recursion in CompleteTypeFromUdt function.
-      auto clang_type_removed_fast_quals =
-          ClangUtil::RemoveFastQualifiers(clang_type).GetOpaqueQualType();
-      m_forward_decl_clang_type_to_uid[clang_type_removed_fast_quals] =
-          type.getSymIndexId();
-
-      m_ast.SetHasExternalStorage(clang_type.GetOpaqueQualType(), true);
-
-      type_resolve_state_tag = Type::eResolveStateForward;
-    }
-
     GetDeclarationForSymbol(type, decl);
     return std::make_shared<lldb_private::Type>(
-        type.getSymIndexId(), m_ast.GetSymbolFile(),
-        ConstString(udt->getName()), udt->getLength(), nullptr,
-        LLDB_INVALID_UID, lldb_private::Type::eEncodingIsUID, decl, clang_type,
+        type.getSymIndexId(), m_ast.GetSymbolFile(), ConstString(name),
+        udt->getLength(), nullptr, LLDB_INVALID_UID,
+        lldb_private::Type::eEncodingIsUID, decl, clang_type,
         type_resolve_state_tag);
   } break;
   case PDB_SymType::Enum: {
     auto enum_type = llvm::dyn_cast<PDBSymbolTypeEnum>(&type);
     assert(enum_type);
-    auto underlying_type_up = enum_type->getUnderlyingType();
-    if (!underlying_type_up)
-      return nullptr;
-    lldb::Encoding encoding =
-        TranslateBuiltinEncoding(underlying_type_up->getBuiltinType());
-    // FIXME: Type of underlying builtin is always `Int`. We correct it with
-    // the very first enumerator's encoding if any.
-    auto first_child = enum_type->findOneChild<PDBSymbolData>();
-    if (first_child) {
-      encoding = TranslateEnumEncoding(first_child->getValue().Type);
-    }
-    std::string name = enum_type->getName();
+
+    std::string name = PDBNameDropScope(enum_type->getName());
+    auto decl_context = GetDeclContextContainingSymbol(type);
     uint64_t bytes = enum_type->getLength();
-    CompilerType builtin_type;
-    if (bytes > 0)
-      builtin_type = GetBuiltinTypeForPDBEncodingAndBitSize(
-          m_ast, *underlying_type_up, encoding, bytes * 8);
-    else
-      builtin_type = m_ast.GetBasicType(eBasicTypeInt);
-    // FIXME: PDB does not have information about scoped enumeration (Enum
-    // Class). Set it false for now.
-    bool isScoped = false;
-
-    CompilerType ast_enum = m_ast.CreateEnumerationType(
-        name.c_str(), tu_decl_ctx, decl, builtin_type, isScoped);
-    auto enum_values = enum_type->findAllChildren<PDBSymbolData>();
-    if (enum_values) {
-      while (auto enum_value = enum_values->getNext()) {
-        if (enum_value->getDataKind() != PDB_DataKind::Constant)
-          continue;
-        AddEnumValue(ast_enum, *enum_value);
+
+    // Check if such an enum already exists in the current context
+    CompilerType ast_enum = m_ast.GetTypeForIdentifier<clang::EnumDecl>(
+        ConstString(name), decl_context);
+    if (!ast_enum.IsValid()) {
+      auto underlying_type_up = enum_type->getUnderlyingType();
+      if (!underlying_type_up)
+        return nullptr;
+
+      lldb::Encoding encoding =
+          TranslateBuiltinEncoding(underlying_type_up->getBuiltinType());
+      // FIXME: Type of underlying builtin is always `Int`. We correct it with
+      // the very first enumerator's encoding if any.
+      auto first_child = enum_type->findOneChild<PDBSymbolData>();
+      if (first_child)
+        encoding = TranslateEnumEncoding(first_child->getValue().Type);
+
+      CompilerType builtin_type;
+      if (bytes > 0)
+        builtin_type = GetBuiltinTypeForPDBEncodingAndBitSize(
+            m_ast, *underlying_type_up, encoding, bytes * 8);
+      else
+        builtin_type = m_ast.GetBasicType(eBasicTypeInt);
+
+      // FIXME: PDB does not have information about scoped enumeration (Enum
+      // Class). Set it false for now.
+      bool isScoped = false;
+
+      ast_enum = m_ast.CreateEnumerationType(name.c_str(), decl_context, decl,
+                                             builtin_type, isScoped);
+
+      auto enum_decl = ClangASTContext::GetAsEnumDecl(ast_enum);
+      assert(enum_decl);
+      m_uid_to_decl[type.getSymIndexId()] = enum_decl;
+
+      auto enum_values = enum_type->findAllChildren<PDBSymbolData>();
+      if (enum_values) {
+        while (auto enum_value = enum_values->getNext()) {
+          if (enum_value->getDataKind() != PDB_DataKind::Constant)
+            continue;
+          AddEnumValue(ast_enum, *enum_value);
+        }
       }
+
+      if (ClangASTContext::StartTagDeclarationDefinition(ast_enum))
+        ClangASTContext::CompleteTagDeclarationDefinition(ast_enum);
     }
-    if (ClangASTContext::StartTagDeclarationDefinition(ast_enum))
-      ClangASTContext::CompleteTagDeclarationDefinition(ast_enum);
+
+    if (enum_type->isConstType())
+      ast_enum = ast_enum.AddConstModifier();
+
+    if (enum_type->isVolatileType())
+      ast_enum = ast_enum.AddVolatileModifier();
 
     GetDeclarationForSymbol(type, decl);
     return std::make_shared<lldb_private::Type>(
@@ -413,23 +483,42 @@ lldb::TypeSP PDBASTParser::CreateLLDBTyp
   case PDB_SymType::Typedef: {
     auto type_def = llvm::dyn_cast<PDBSymbolTypeTypedef>(&type);
     assert(type_def);
+
     lldb_private::Type *target_type =
         m_ast.GetSymbolFile()->ResolveTypeUID(type_def->getTypeId());
     if (!target_type)
       return nullptr;
-    std::string name = type_def->getName();
-    uint64_t bytes = type_def->getLength();
-    CompilerType target_ast_type = target_type->GetFullCompilerType();
-    CompilerDeclContext target_decl_ctx =
-        m_ast.GetSymbolFile()->GetDeclContextForUID(target_type->GetID());
+
+    std::string name = PDBNameDropScope(type_def->getName());
+    auto decl_ctx = GetDeclContextContainingSymbol(type);
+
+    // Check if such a typedef already exists in the current context
     CompilerType ast_typedef =
-        m_ast.CreateTypedefType(target_ast_type, name.c_str(), target_decl_ctx);
-    if (!ast_typedef)
-      return nullptr;
+        m_ast.GetTypeForIdentifier<clang::TypedefNameDecl>(ConstString(name),
+                                                           decl_ctx);
+    if (!ast_typedef.IsValid()) {
+      CompilerType target_ast_type = target_type->GetFullCompilerType();
+
+      ast_typedef = m_ast.CreateTypedefType(
+          target_ast_type, name.c_str(), CompilerDeclContext(&m_ast, decl_ctx));
+      if (!ast_typedef)
+        return nullptr;
 
+      auto typedef_decl = ClangASTContext::GetAsTypedefDecl(ast_typedef);
+      assert(typedef_decl);
+      m_uid_to_decl[type.getSymIndexId()] = typedef_decl;
+    }
+
+    if (type_def->isConstType())
+      ast_typedef = ast_typedef.AddConstModifier();
+
+    if (type_def->isVolatileType())
+      ast_typedef = ast_typedef.AddVolatileModifier();
+
+    GetDeclarationForSymbol(type, decl);
     return std::make_shared<lldb_private::Type>(
         type_def->getSymIndexId(), m_ast.GetSymbolFile(), ConstString(name),
-        bytes, nullptr, target_type->GetID(),
+        type_def->getLength(), nullptr, target_type->GetID(),
         lldb_private::Type::eEncodingIsTypedefUID, decl, ast_typedef,
         lldb_private::Type::eResolveStateFull);
   } break;
@@ -446,7 +535,7 @@ lldb::TypeSP PDBASTParser::CreateLLDBTyp
         return nullptr;
       func_sig = sig.release();
       // Function type is named.
-      name = pdb_func->getName();
+      name = PDBNameDropScope(pdb_func->getName());
     } else if (auto pdb_func_sig =
                    llvm::dyn_cast<PDBSymbolTypeFunctionSig>(&type)) {
       func_sig = const_cast<PDBSymbolTypeFunctionSig *>(pdb_func_sig);
@@ -623,11 +712,10 @@ bool PDBASTParser::CompleteTypeFromPDB(
 
   // Remove the type from the forward declarations to avoid
   // an endless recursion for types like a linked list.
-  CompilerType compiler_type_no_qualifiers =
-      ClangUtil::RemoveFastQualifiers(compiler_type);
-  auto uid_it = m_forward_decl_clang_type_to_uid.find(
-      compiler_type_no_qualifiers.GetOpaqueQualType());
-  if (uid_it == m_forward_decl_clang_type_to_uid.end())
+  clang::CXXRecordDecl *record_decl =
+      m_ast.GetAsCXXRecordDecl(compiler_type.GetOpaqueQualType());
+  auto uid_it = m_forward_decl_to_uid.find(record_decl);
+  if (uid_it == m_forward_decl_to_uid.end())
     return true;
 
   auto symbol_file = static_cast<SymbolFilePDB *>(m_ast.GetSymbolFile());
@@ -639,7 +727,7 @@ bool PDBASTParser::CompleteTypeFromPDB(
   if (!symbol)
     return false;
 
-  m_forward_decl_clang_type_to_uid.erase(uid_it);
+  m_forward_decl_to_uid.erase(uid_it);
 
   ClangASTContext::SetHasExternalStorage(compiler_type.GetOpaqueQualType(),
                                          false);
@@ -657,11 +745,265 @@ bool PDBASTParser::CompleteTypeFromPDB(
   }
 }
 
+clang::Decl *
+PDBASTParser::GetDeclForSymbol(const llvm::pdb::PDBSymbol &symbol) {
+  auto it = m_uid_to_decl.find(symbol.getSymIndexId());
+  if (it != m_uid_to_decl.end())
+    return it->second;
+
+  auto symbol_file = static_cast<SymbolFilePDB *>(m_ast.GetSymbolFile());
+  if (!symbol_file)
+    return nullptr;
+
+  // First of all, check if the symbol is a member of a class. Resolve the full
+  // class type and return the declaration from the cache if so.
+  auto tag = symbol.getSymTag();
+  if (tag == PDB_SymType::Data || tag == PDB_SymType::Function) {
+    const IPDBSession &session = symbol.getSession();
+    const IPDBRawSymbol &raw = symbol.getRawSymbol();
+
+    auto class_parent_id = raw.getClassParentId();
+    if (session.getSymbolById(class_parent_id)) {
+      auto class_parent_type = symbol_file->ResolveTypeUID(class_parent_id);
+      if (!class_parent_type)
+        return nullptr;
+
+      class_parent_type->GetFullCompilerType();
+
+      return m_uid_to_decl.lookup(symbol.getSymIndexId());
+    }
+  }
+
+  // If we are here, then the symbol is not belonging to a class and is not
+  // contained in the cache. So create a declaration for it.
+  switch (symbol.getSymTag()) {
+  case PDB_SymType::Data: {
+    auto data = llvm::dyn_cast<PDBSymbolData>(&symbol);
+    assert(data);
+
+    auto decl_context = GetDeclContextContainingSymbol(symbol);
+    assert(decl_context);
+
+    // May be the current context is a class really, but we haven't found
+    // any class parent. This happens e.g. in the case of class static
+    // variables - they has two symbols, one is a child of the class when
+    // another is a child of the exe. So always complete the parent and use
+    // an existing declaration if possible.
+    if (auto parent_decl = llvm::dyn_cast_or_null<clang::TagDecl>(decl_context))
+      m_ast.GetCompleteDecl(parent_decl);
+
+    auto name = PDBNameDropScope(data->getName());
+
+    // Check if the current context already contains the symbol with the name.
+    clang::Decl *decl =
+        GetDeclFromContextByName(*m_ast.getASTContext(), *decl_context, name);
+    if (!decl) {
+      auto type = symbol_file->ResolveTypeUID(data->getTypeId());
+      if (!type)
+        return nullptr;
+
+      decl = m_ast.CreateVariableDeclaration(
+          decl_context, name.c_str(),
+          ClangUtil::GetQualType(type->GetLayoutCompilerType()));
+    }
+
+    m_uid_to_decl[data->getSymIndexId()] = decl;
+
+    return decl;
+  }
+  case PDB_SymType::Function: {
+    auto func = llvm::dyn_cast<PDBSymbolFunc>(&symbol);
+    assert(func);
+
+    auto decl_context = GetDeclContextContainingSymbol(symbol);
+    assert(decl_context);
+
+    auto name = PDBNameDropScope(func->getName());
+
+    auto type = symbol_file->ResolveTypeUID(func->getSymIndexId());
+    if (!type)
+      return nullptr;
+
+    auto storage = func->isStatic() ? clang::StorageClass::SC_Static
+                                    : clang::StorageClass::SC_None;
+
+    auto decl = m_ast.CreateFunctionDeclaration(
+        decl_context, name.c_str(), type->GetForwardCompilerType(), storage,
+        func->hasInlineAttribute());
+
+    m_uid_to_decl[func->getSymIndexId()] = decl;
+
+    return decl;
+  }
+  default: {
+    // It's not a variable and not a function, check if it's a type
+    auto type = symbol_file->ResolveTypeUID(symbol.getSymIndexId());
+    if (!type)
+      return nullptr;
+
+    return m_uid_to_decl.lookup(symbol.getSymIndexId());
+  }
+  }
+}
+
+clang::DeclContext *
+PDBASTParser::GetDeclContextForSymbol(const llvm::pdb::PDBSymbol &symbol) {
+  if (symbol.getSymTag() == PDB_SymType::Function) {
+    clang::DeclContext *result =
+        llvm::dyn_cast_or_null<clang::FunctionDecl>(GetDeclForSymbol(symbol));
+
+    if (result)
+      m_decl_context_to_uid[result] = symbol.getSymIndexId();
+
+    return result;
+  }
+
+  auto symbol_file = static_cast<SymbolFilePDB *>(m_ast.GetSymbolFile());
+  if (!symbol_file)
+    return nullptr;
+
+  auto type = symbol_file->ResolveTypeUID(symbol.getSymIndexId());
+  if (!type)
+    return nullptr;
+
+  clang::DeclContext *result =
+      m_ast.GetDeclContextForType(type->GetForwardCompilerType());
+
+  if (result)
+    m_decl_context_to_uid[result] = symbol.getSymIndexId();
+
+  return result;
+}
+
+clang::DeclContext *PDBASTParser::GetDeclContextContainingSymbol(
+    const llvm::pdb::PDBSymbol &symbol) {
+  auto parent = GetClassOrFunctionParent(symbol);
+  while (parent) {
+    if (auto parent_context = GetDeclContextForSymbol(*parent))
+      return parent_context;
+
+    parent = GetClassOrFunctionParent(*parent);
+  }
+
+  // We can't find any class or function parent of the symbol. So analyze
+  // the full symbol name. The symbol may be belonging to a namespace
+  // or function (or even to a class if it's e.g. a static variable symbol).
+  // We do not use CPlusPlusNameParser because it fails on things like
+  // `anonymous namespace'.
+
+  // TODO: Make clang to emit full names for variables in namespaces
+  // (as MSVC does)
+
+  auto context = symbol.getRawSymbol().getName();
+  auto context_size = context.rfind("::");
+  if (context_size == std::string::npos)
+    context_size = 0;
+  context = context.substr(0, context_size);
+
+  // Check if there is a symbol with the name of the context.
+
+  auto symbol_file = static_cast<SymbolFilePDB *>(m_ast.GetSymbolFile());
+  if (!symbol_file)
+    return m_ast.GetTranslationUnitDecl();
+
+  auto global = symbol_file->GetPDBSession().getGlobalScope();
+  if (!global)
+    return m_ast.GetTranslationUnitDecl();
+
+  TypeMap types;
+  if (auto children_enum =
+          global->findChildren(PDB_SymType::None, context, NS_CaseSensitive))
+    while (auto child = children_enum->getNext())
+      if (auto child_context = GetDeclContextForSymbol(*child))
+        return child_context;
+
+  // Split context and retrieve nested namespaces
+  auto curr_context = m_ast.GetTranslationUnitDecl();
+  auto from = 0;
+  while (from < context_size) {
+    auto to = context.find("::", from);
+    if (to == std::string::npos)
+      to = context_size;
+
+    auto namespace_name = context.substr(from, to - from);
+    auto namespace_name_c_str = IsAnonymousNamespaceName(namespace_name)
+                                    ? nullptr
+                                    : namespace_name.c_str();
+    auto namespace_decl =
+        m_ast.GetUniqueNamespaceDeclaration(namespace_name_c_str, curr_context);
+
+    m_parent_to_namespaces[curr_context].insert(namespace_decl);
+
+    curr_context = namespace_decl;
+    from = to + 2;
+  }
+
+  return curr_context;
+}
+
+void PDBASTParser::ParseDeclsForDeclContext(
+    const clang::DeclContext *decl_context) {
+  auto symbol_file = static_cast<SymbolFilePDB *>(m_ast.GetSymbolFile());
+  if (!symbol_file)
+    return;
+
+  IPDBSession &session = symbol_file->GetPDBSession();
+  auto symbol_up =
+      session.getSymbolById(m_decl_context_to_uid.lookup(decl_context));
+  auto global_up = session.getGlobalScope();
+
+  PDBSymbol *symbol;
+  if (symbol_up)
+    symbol = symbol_up.get();
+  else if (global_up)
+    symbol = global_up.get();
+  else
+    return;
+
+  if (auto children = symbol->findAllChildren())
+    while (auto child = children->getNext())
+      GetDeclForSymbol(*child);
+}
+
+clang::NamespaceDecl *
+PDBASTParser::FindNamespaceDecl(const clang::DeclContext *parent,
+                                llvm::StringRef name) {
+  if (!parent)
+    parent = m_ast.GetTranslationUnitDecl();
+
+  auto it = m_parent_to_namespaces.find(parent);
+  if (it == m_parent_to_namespaces.end())
+    return nullptr;
+
+  for (auto namespace_decl : it->second)
+    if (namespace_decl->getName().equals(name))
+      return namespace_decl;
+
+  for (auto namespace_decl : it->second)
+    if (namespace_decl->isAnonymousNamespace())
+      return FindNamespaceDecl(namespace_decl, name);
+
+  return nullptr;
+}
+
+std::string PDBASTParser::PDBNameDropScope(const std::string &name) {
+  // Not all PDB names can be parsed with CPlusPlusNameParser.
+  // E.g. it fails on names containing `anonymous namespace'.
+  // So we simply drop everything before '::'
+
+  auto offset = name.rfind("::");
+  if (offset == std::string::npos)
+    return name;
+  assert(offset + 2 <= name.size());
+
+  return name.substr(offset + 2);
+}
+
 bool PDBASTParser::AddEnumValue(CompilerType enum_type,
-                                const PDBSymbolData &enum_value) const {
+                                const PDBSymbolData &enum_value) {
   Declaration decl;
   Variant v = enum_value.getValue();
-  std::string name = enum_value.getName();
+  std::string name = PDBNameDropScope(enum_value.getName());
   int64_t raw_value;
   switch (v.Type) {
   case PDB_VariantType::Int8:
@@ -695,9 +1037,15 @@ bool PDBASTParser::AddEnumValue(Compiler
       m_ast.GetEnumerationIntegerType(enum_type.GetOpaqueQualType());
   uint32_t byte_size = m_ast.getASTContext()->getTypeSize(
       ClangUtil::GetQualType(underlying_type));
-  return m_ast.AddEnumerationValueToEnumerationType(
+  auto enum_constant_decl = m_ast.AddEnumerationValueToEnumerationType(
       enum_type.GetOpaqueQualType(), underlying_type, decl, name.c_str(),
       raw_value, byte_size * 8);
+  if (!enum_constant_decl)
+    return false;
+
+  m_uid_to_decl[enum_value.getSymIndexId()] = enum_constant_decl;
+
+  return true;
 }
 
 bool PDBASTParser::CompleteTypeFromUDT(
@@ -744,10 +1092,10 @@ void PDBASTParser::AddRecordMembers(
     lldb_private::SymbolFile &symbol_file,
     lldb_private::CompilerType &record_type,
     PDBDataSymbolEnumerator &members_enum,
-    lldb_private::ClangASTImporter::LayoutInfo &layout_info) const {
+    lldb_private::ClangASTImporter::LayoutInfo &layout_info) {
   while (auto member = members_enum.getNext()) {
     if (member->isCompilerGenerated())
-        continue;
+      continue;
 
     auto member_name = member->getName();
 
@@ -781,6 +1129,8 @@ void PDBASTParser::AddRecordMembers(
       if (!decl)
         continue;
 
+      m_uid_to_decl[member->getSymIndexId()] = decl;
+
       auto offset = member->getOffset() * 8;
       if (location_type == PDB_LocType::BitField)
         offset += member->getBitPosition();
@@ -789,10 +1139,16 @@ void PDBASTParser::AddRecordMembers(
 
       break;
     }
-    case PDB_DataKind::StaticMember:
-      ClangASTContext::AddVariableToRecordType(record_type, member_name.c_str(),
-                                               member_comp_type, access);
+    case PDB_DataKind::StaticMember: {
+      auto decl = ClangASTContext::AddVariableToRecordType(
+          record_type, member_name.c_str(), member_comp_type, access);
+      if (!decl)
+        continue;
+
+      m_uid_to_decl[member->getSymIndexId()] = decl;
+
       break;
+    }
     default:
       llvm_unreachable("unsupported PDB data kind");
     }
@@ -829,12 +1185,12 @@ void PDBASTParser::AddRecordBases(
         base_comp_type.GetOpaqueQualType(), access, is_virtual,
         record_kind == clang::TTK_Class);
     if (!base_class_spec)
-        continue;
+      continue;
 
     base_classes.push_back(base_class_spec);
 
     if (is_virtual)
-        continue;
+      continue;
 
     auto decl = m_ast.GetAsCXXRecordDecl(base_comp_type.GetOpaqueQualType());
     if (!decl)
@@ -852,15 +1208,16 @@ void PDBASTParser::AddRecordBases(
   }
 }
 
-void PDBASTParser::AddRecordMethods(
-    lldb_private::SymbolFile &symbol_file,
-    lldb_private::CompilerType &record_type,
-    PDBFuncSymbolEnumerator &methods_enum) const {
+void PDBASTParser::AddRecordMethods(lldb_private::SymbolFile &symbol_file,
+                                    lldb_private::CompilerType &record_type,
+                                    PDBFuncSymbolEnumerator &methods_enum) {
   while (auto method = methods_enum.getNext()) {
+    auto name = PDBNameDropScope(method->getName().c_str());
+
     auto method_type = symbol_file.ResolveTypeUID(method->getSymIndexId());
     // MSVC specific __vecDelDtor.
     if (!method_type)
-      break;
+      continue;
 
     auto method_comp_type = method_type->GetFullCompilerType();
     if (!method_comp_type.GetCompleteType()) {
@@ -873,13 +1230,17 @@ void PDBASTParser::AddRecordMethods(
     }
 
     // TODO: get mangled name for the method.
-    m_ast.AddMethodToCXXRecordType(
-        record_type.GetOpaqueQualType(), method->getName().c_str(),
+    auto decl = m_ast.AddMethodToCXXRecordType(
+        record_type.GetOpaqueQualType(), name.c_str(),
         /*mangled_name*/ nullptr, method_comp_type,
         TranslateMemberAccess(method->getAccess()), method->isVirtual(),
         method->isStatic(), method->hasInlineAttribute(),
         /*is_explicit*/ false, // FIXME: Need this field in CodeView.
         /*is_attr_used*/ false,
         /*is_artificial*/ method->isCompilerGenerated());
+    if (!decl)
+      continue;
+
+    m_uid_to_decl[method->getSymIndexId()] = decl;
   }
 }

Modified: lldb/trunk/source/Plugins/SymbolFile/PDB/PDBASTParser.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/PDB/PDBASTParser.h?rev=341782&r1=341781&r2=341782&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/SymbolFile/PDB/PDBASTParser.h (original)
+++ lldb/trunk/source/Plugins/SymbolFile/PDB/PDBASTParser.h Mon Sep 10 01:08:43 2018
@@ -14,6 +14,8 @@
 
 #include "lldb/Symbol/ClangASTImporter.h"
 
+class SymbolFilePDB;
+
 namespace clang {
 class CharUnits;
 class CXXRecordDecl;
@@ -47,13 +49,32 @@ public:
   lldb::TypeSP CreateLLDBTypeFromPDBType(const llvm::pdb::PDBSymbol &type);
   bool CompleteTypeFromPDB(lldb_private::CompilerType &compiler_type);
 
+  clang::Decl *GetDeclForSymbol(const llvm::pdb::PDBSymbol &symbol);
+
+  clang::DeclContext *
+  GetDeclContextForSymbol(const llvm::pdb::PDBSymbol &symbol);
+  clang::DeclContext *
+  GetDeclContextContainingSymbol(const llvm::pdb::PDBSymbol &symbol);
+
+  void ParseDeclsForDeclContext(const clang::DeclContext *decl_context);
+
+  clang::NamespaceDecl *FindNamespaceDecl(const clang::DeclContext *parent,
+                                          llvm::StringRef name);
+
   lldb_private::ClangASTImporter &GetClangASTImporter() {
     return m_ast_importer;
   }
 
+  static std::string PDBNameDropScope(const std::string &name);
+
 private:
-  typedef llvm::DenseMap<lldb::opaque_compiler_type_t, lldb::user_id_t>
-      ClangTypeToUidMap;
+  typedef llvm::DenseMap<clang::CXXRecordDecl *, lldb::user_id_t>
+      CXXRecordDeclToUidMap;
+  typedef llvm::DenseMap<lldb::user_id_t, clang::Decl *> UidToDeclMap;
+  typedef llvm::DenseMap<clang::DeclContext *, std::set<clang::NamespaceDecl *>>
+      ParentToNamespacesMap;
+  typedef llvm::DenseMap<clang::DeclContext *, lldb::user_id_t>
+      DeclContextToUidMap;
   typedef llvm::pdb::ConcreteSymbolEnumerator<llvm::pdb::PDBSymbolData>
       PDBDataSymbolEnumerator;
   typedef llvm::pdb::ConcreteSymbolEnumerator<llvm::pdb::PDBSymbolTypeBaseClass>
@@ -62,29 +83,31 @@ private:
       PDBFuncSymbolEnumerator;
 
   bool AddEnumValue(lldb_private::CompilerType enum_type,
-                    const llvm::pdb::PDBSymbolData &data) const;
+                    const llvm::pdb::PDBSymbolData &data);
   bool CompleteTypeFromUDT(lldb_private::SymbolFile &symbol_file,
                            lldb_private::CompilerType &compiler_type,
                            llvm::pdb::PDBSymbolTypeUDT &udt);
-  void AddRecordMembers(
-      lldb_private::SymbolFile &symbol_file,
-      lldb_private::CompilerType &record_type,
-      PDBDataSymbolEnumerator &members_enum,
-      lldb_private::ClangASTImporter::LayoutInfo &layout_info) const;
-  void AddRecordBases(
-      lldb_private::SymbolFile &symbol_file,
-      lldb_private::CompilerType &record_type,
-      int record_kind,
-      PDBBaseClassSymbolEnumerator &bases_enum,
-      lldb_private::ClangASTImporter::LayoutInfo &layout_info) const;
-  void AddRecordMethods(
-      lldb_private::SymbolFile &symbol_file,
-      lldb_private::CompilerType &record_type,
-      PDBFuncSymbolEnumerator &methods_enum) const;
+  void
+  AddRecordMembers(lldb_private::SymbolFile &symbol_file,
+                   lldb_private::CompilerType &record_type,
+                   PDBDataSymbolEnumerator &members_enum,
+                   lldb_private::ClangASTImporter::LayoutInfo &layout_info);
+  void
+  AddRecordBases(lldb_private::SymbolFile &symbol_file,
+                 lldb_private::CompilerType &record_type, int record_kind,
+                 PDBBaseClassSymbolEnumerator &bases_enum,
+                 lldb_private::ClangASTImporter::LayoutInfo &layout_info) const;
+  void AddRecordMethods(lldb_private::SymbolFile &symbol_file,
+                        lldb_private::CompilerType &record_type,
+                        PDBFuncSymbolEnumerator &methods_enum);
 
   lldb_private::ClangASTContext &m_ast;
   lldb_private::ClangASTImporter m_ast_importer;
-  ClangTypeToUidMap m_forward_decl_clang_type_to_uid;
+
+  CXXRecordDeclToUidMap m_forward_decl_to_uid;
+  UidToDeclMap m_uid_to_decl;
+  ParentToNamespacesMap m_parent_to_namespaces;
+  DeclContextToUidMap m_decl_context_to_uid;
 };
 
 #endif // LLDB_PLUGINS_SYMBOLFILE_PDB_PDBASTPARSER_H

Modified: lldb/trunk/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp?rev=341782&r1=341781&r2=341782&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp (original)
+++ lldb/trunk/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp Mon Sep 10 01:08:43 2018
@@ -551,8 +551,7 @@ lldb_private::Type *SymbolFilePDB::Resol
       llvm::dyn_cast_or_null<ClangASTContext>(type_system);
   if (!clang_type_system)
     return nullptr;
-  PDBASTParser *pdb =
-      llvm::dyn_cast<PDBASTParser>(clang_type_system->GetPDBParser());
+  PDBASTParser *pdb = clang_type_system->GetPDBParser();
   if (!pdb)
     return nullptr;
 
@@ -579,8 +578,7 @@ bool SymbolFilePDB::CompleteType(lldb_pr
   if (!clang_ast_ctx)
     return false;
 
-  PDBASTParser *pdb =
-      llvm::dyn_cast<PDBASTParser>(clang_ast_ctx->GetPDBParser());
+  PDBASTParser *pdb = clang_ast_ctx->GetPDBParser();
   if (!pdb)
     return false;
 
@@ -588,24 +586,83 @@ bool SymbolFilePDB::CompleteType(lldb_pr
 }
 
 lldb_private::CompilerDecl SymbolFilePDB::GetDeclForUID(lldb::user_id_t uid) {
-  return lldb_private::CompilerDecl();
+  ClangASTContext *clang_ast_ctx = llvm::dyn_cast_or_null<ClangASTContext>(
+      GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus));
+  if (!clang_ast_ctx)
+    return CompilerDecl();
+
+  PDBASTParser *pdb = clang_ast_ctx->GetPDBParser();
+  if (!pdb)
+    return CompilerDecl();
+
+  auto symbol = m_session_up->getSymbolById(uid);
+  if (!symbol)
+    return CompilerDecl();
+
+  auto decl = pdb->GetDeclForSymbol(*symbol);
+  if (!decl)
+    return CompilerDecl();
+
+  return CompilerDecl(clang_ast_ctx, decl);
 }
 
 lldb_private::CompilerDeclContext
 SymbolFilePDB::GetDeclContextForUID(lldb::user_id_t uid) {
-  // PDB always uses the translation unit decl context for everything.  We can
-  // improve this later but it's not easy because PDB doesn't provide a high
-  // enough level of type fidelity in this area.
-  return *m_tu_decl_ctx_up;
+  ClangASTContext *clang_ast_ctx = llvm::dyn_cast_or_null<ClangASTContext>(
+      GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus));
+  if (!clang_ast_ctx)
+    return CompilerDeclContext();
+
+  PDBASTParser *pdb = clang_ast_ctx->GetPDBParser();
+  if (!pdb)
+    return CompilerDeclContext();
+
+  auto symbol = m_session_up->getSymbolById(uid);
+  if (!symbol)
+    return CompilerDeclContext();
+
+  auto decl_context = pdb->GetDeclContextForSymbol(*symbol);
+  if (!decl_context)
+    return GetDeclContextContainingUID(uid);
+
+  return CompilerDeclContext(clang_ast_ctx, decl_context);
 }
 
 lldb_private::CompilerDeclContext
 SymbolFilePDB::GetDeclContextContainingUID(lldb::user_id_t uid) {
-  return *m_tu_decl_ctx_up;
+  ClangASTContext *clang_ast_ctx = llvm::dyn_cast_or_null<ClangASTContext>(
+      GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus));
+  if (!clang_ast_ctx)
+    return CompilerDeclContext();
+
+  PDBASTParser *pdb = clang_ast_ctx->GetPDBParser();
+  if (!pdb)
+    return CompilerDeclContext();
+
+  auto symbol = m_session_up->getSymbolById(uid);
+  if (!symbol)
+    return CompilerDeclContext();
+
+  auto decl_context = pdb->GetDeclContextContainingSymbol(*symbol);
+  assert(decl_context);
+
+  return CompilerDeclContext(clang_ast_ctx, decl_context);
 }
 
 void SymbolFilePDB::ParseDeclsForContext(
-    lldb_private::CompilerDeclContext decl_ctx) {}
+    lldb_private::CompilerDeclContext decl_ctx) {
+  ClangASTContext *clang_ast_ctx = llvm::dyn_cast_or_null<ClangASTContext>(
+      GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus));
+  if (!clang_ast_ctx)
+    return;
+
+  PDBASTParser *pdb = clang_ast_ctx->GetPDBParser();
+  if (!pdb)
+    return;
+
+  pdb->ParseDeclsForDeclContext(
+      static_cast<clang::DeclContext *>(decl_ctx.GetOpaqueDeclContext()));
+}
 
 uint32_t
 SymbolFilePDB::ResolveSymbolContext(const lldb_private::Address &so_addr,
@@ -876,7 +933,7 @@ VariableSP SymbolFilePDB::ParseVariableF
   if (scope == eValueTypeVariableLocal) {
     if (sc.function) {
       context_scope = sc.function->GetBlock(true).FindBlockByID(
-          pdb_data.getClassParentId());
+          pdb_data.getLexicalParentId());
       if (context_scope == nullptr)
         context_scope = sc.function;
     }
@@ -973,14 +1030,14 @@ uint32_t SymbolFilePDB::FindGlobalVariab
     const lldb_private::ConstString &name,
     const lldb_private::CompilerDeclContext *parent_decl_ctx,
     uint32_t max_matches, lldb_private::VariableList &variables) {
+  if (!parent_decl_ctx)
+    parent_decl_ctx = m_tu_decl_ctx_up.get();
   if (!DeclContextMatchesThisSymbolFile(parent_decl_ctx))
     return 0;
   if (name.IsEmpty())
     return 0;
 
-  auto results =
-      m_global_scope_up->findChildren(PDB_SymType::Data, name.GetStringRef(),
-                                      PDB_NameSearchFlags::NS_CaseSensitive);
+  auto results = m_global_scope_up->findAllChildren<PDBSymbolData>();
   if (!results)
     return 0;
 
@@ -1000,6 +1057,15 @@ uint32_t SymbolFilePDB::FindGlobalVariab
     if (sc.comp_unit == nullptr)
       continue;
 
+    if (!name.GetStringRef().equals(
+            PDBASTParser::PDBNameDropScope(pdb_data->getName())))
+      continue;
+
+    auto actual_parent_decl_ctx =
+        GetDeclContextContainingUID(result->getSymIndexId());
+    if (actual_parent_decl_ctx != *parent_decl_ctx)
+      continue;
+
     ParseVariables(sc, *pdb_data, &variables);
     matches = variables.GetSize() - old_size;
   }
@@ -1275,7 +1341,7 @@ uint32_t SymbolFilePDB::FindTypes(
   std::string name_str = name.AsCString();
 
   // There is an assumption 'name' is not a regex
-  FindTypesByName(name_str, max_matches, types);
+  FindTypesByName(name_str, parent_decl_ctx, max_matches, types);
 
   return types.GetSize();
 }
@@ -1335,14 +1401,16 @@ void SymbolFilePDB::FindTypesByRegex(
   }
 }
 
-void SymbolFilePDB::FindTypesByName(const std::string &name,
-                                    uint32_t max_matches,
-                                    lldb_private::TypeMap &types) {
+void SymbolFilePDB::FindTypesByName(
+    const std::string &name,
+    const lldb_private::CompilerDeclContext *parent_decl_ctx,
+    uint32_t max_matches, lldb_private::TypeMap &types) {
+  if (!parent_decl_ctx)
+    parent_decl_ctx = m_tu_decl_ctx_up.get();
   std::unique_ptr<IPDBEnumSymbols> results;
   if (name.empty())
     return;
-  results = m_global_scope_up->findChildren(PDB_SymType::None, name,
-                                            PDB_NameSearchFlags::NS_Default);
+  results = m_global_scope_up->findAllChildren(PDB_SymType::None);
   if (!results)
     return;
 
@@ -1351,6 +1419,11 @@ void SymbolFilePDB::FindTypesByName(cons
   while (auto result = results->getNext()) {
     if (max_matches > 0 && matches >= max_matches)
       break;
+
+    if (PDBASTParser::PDBNameDropScope(result->getRawSymbol().getName()) !=
+        name)
+      continue;
+
     switch (result->getSymTag()) {
     case PDB_SymType::Enum:
     case PDB_SymType::UDT:
@@ -1367,6 +1440,11 @@ void SymbolFilePDB::FindTypesByName(cons
     if (!ResolveTypeUID(result->getSymIndexId()))
       continue;
 
+    auto actual_parent_decl_ctx =
+        GetDeclContextContainingUID(result->getSymIndexId());
+    if (actual_parent_decl_ctx != *parent_decl_ctx)
+      continue;
+
     auto iter = m_types.find(result->getSymIndexId());
     if (iter == m_types.end())
       continue;
@@ -1477,7 +1555,27 @@ lldb_private::CompilerDeclContext Symbol
     const lldb_private::SymbolContext &sc,
     const lldb_private::ConstString &name,
     const lldb_private::CompilerDeclContext *parent_decl_ctx) {
-  return lldb_private::CompilerDeclContext();
+  auto type_system = GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus);
+  auto clang_type_system = llvm::dyn_cast_or_null<ClangASTContext>(type_system);
+  if (!clang_type_system)
+    return CompilerDeclContext();
+
+  PDBASTParser *pdb = clang_type_system->GetPDBParser();
+  if (!pdb)
+    return CompilerDeclContext();
+
+  clang::DeclContext *decl_context = nullptr;
+  if (parent_decl_ctx)
+    decl_context = static_cast<clang::DeclContext *>(
+        parent_decl_ctx->GetOpaqueDeclContext());
+
+  auto namespace_decl =
+      pdb->FindNamespaceDecl(decl_context, name.GetStringRef());
+  if (!namespace_decl)
+    return CompilerDeclContext();
+
+  return CompilerDeclContext(type_system,
+                             static_cast<clang::DeclContext *>(namespace_decl));
 }
 
 lldb_private::ConstString SymbolFilePDB::GetPluginName() {

Modified: lldb/trunk/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h?rev=341782&r1=341781&r2=341782&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h (original)
+++ lldb/trunk/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h Mon Sep 10 01:08:43 2018
@@ -179,8 +179,9 @@ private:
       const llvm::pdb::PDBSymbolCompiland &pdb_compiland,
       llvm::DenseMap<uint32_t, uint32_t> &index_map) const;
 
-  void FindTypesByName(const std::string &name, uint32_t max_matches,
-                       lldb_private::TypeMap &types);
+  void FindTypesByName(const std::string &name,
+                       const lldb_private::CompilerDeclContext *parent_decl_ctx,
+                       uint32_t max_matches, lldb_private::TypeMap &types);
 
   std::string GetMangledForPDBData(const llvm::pdb::PDBSymbolData &pdb_data);
 

Modified: lldb/trunk/source/Symbol/ClangASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Symbol/ClangASTContext.cpp?rev=341782&r1=341781&r2=341782&view=diff
==============================================================================
--- lldb/trunk/source/Symbol/ClangASTContext.cpp (original)
+++ lldb/trunk/source/Symbol/ClangASTContext.cpp Mon Sep 10 01:08:43 2018
@@ -2212,6 +2212,9 @@ ClangASTContext::CreateEnumerationType(c
       false);    // IsFixed
 
   if (enum_decl) {
+    if (decl_ctx)
+      decl_ctx->addDecl(enum_decl);
+
     // TODO: check if we should be setting the promotion type too?
     enum_decl->setIntegerType(ClangUtil::GetQualType(integer_clang_type));
 
@@ -4739,6 +4742,8 @@ CompilerType ClangASTContext::CreateType
 
     decl->setAccess(clang::AS_public); // TODO respect proper access specifier
 
+    decl_ctx->addDecl(decl);
+
     // Get a uniqued clang::QualType for the typedef decl type
     return CompilerType(clang_ast, clang_ast->getTypedefType(decl));
   }
@@ -7746,6 +7751,15 @@ clang::TagDecl *ClangASTContext::GetAsTa
     return qual_type->getAsTagDecl();
 }
 
+clang::TypedefNameDecl *
+ClangASTContext::GetAsTypedefDecl(const CompilerType &type) {
+  const clang::TypedefType *typedef_type =
+      llvm::dyn_cast<clang::TypedefType>(ClangUtil::GetQualType(type));
+  if (typedef_type)
+    return typedef_type->getDecl();
+  return nullptr;
+}
+
 clang::CXXRecordDecl *
 ClangASTContext::GetAsCXXRecordDecl(lldb::opaque_compiler_type_t type) {
   return GetCanonicalQualType(type)->getAsCXXRecordDecl();
@@ -8831,7 +8845,7 @@ bool ClangASTContext::CompleteTagDeclara
   return false;
 }
 
-bool ClangASTContext::AddEnumerationValueToEnumerationType(
+clang::EnumConstantDecl *ClangASTContext::AddEnumerationValueToEnumerationType(
     lldb::opaque_compiler_type_t type,
     const CompilerType &enumerator_clang_type, const Declaration &decl,
     const char *name, int64_t enum_value, uint32_t enum_value_bit_size) {
@@ -8863,12 +8877,12 @@ bool ClangASTContext::AddEnumerationValu
           VerifyDecl(enumerator_decl);
 #endif
 
-          return true;
+          return enumerator_decl;
         }
       }
     }
   }
-  return false;
+  return nullptr;
 }
 
 CompilerType

Modified: lldb/trunk/tools/lldb-test/lldb-test.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/lldb-test/lldb-test.cpp?rev=341782&r1=341781&r2=341782&view=diff
==============================================================================
--- lldb/trunk/tools/lldb-test/lldb-test.cpp (original)
+++ lldb/trunk/tools/lldb-test/lldb-test.cpp Mon Sep 10 01:08:43 2018
@@ -148,6 +148,10 @@ static FunctionNameType getFunctionNameF
   return Result;
 }
 
+static cl::opt<bool> DumpAST("dump-ast",
+                             cl::desc("Dump AST restored from symbols."),
+                             cl::sub(SymbolsSubcommand));
+
 static cl::opt<bool> Verify("verify", cl::desc("Verify symbol information."),
                             cl::sub(SymbolsSubcommand));
 
@@ -165,6 +169,7 @@ static Error findNamespaces(lldb_private
 static Error findTypes(lldb_private::Module &Module);
 static Error findVariables(lldb_private::Module &Module);
 static Error dumpModule(lldb_private::Module &Module);
+static Error dumpAST(lldb_private::Module &Module);
 static Error verify(lldb_private::Module &Module);
 
 static Expected<Error (*)(lldb_private::Module &)> getAction();
@@ -509,6 +514,34 @@ Error opts::symbols::dumpModule(lldb_pri
   return Error::success();
 }
 
+Error opts::symbols::dumpAST(lldb_private::Module &Module) {
+  SymbolVendor &plugin = *Module.GetSymbolVendor();
+
+  auto symfile = plugin.GetSymbolFile();
+  if (!symfile)
+    return make_string_error("Module has no symbol file.");
+
+  auto clang_ast_ctx = llvm::dyn_cast_or_null<ClangASTContext>(
+      symfile->GetTypeSystemForLanguage(eLanguageTypeC_plus_plus));
+  if (!clang_ast_ctx)
+    return make_string_error("Can't retrieve Clang AST context.");
+
+  auto ast_ctx = clang_ast_ctx->getASTContext();
+  if (!ast_ctx)
+    return make_string_error("Can't retrieve AST context.");
+
+  auto tu = ast_ctx->getTranslationUnitDecl();
+  if (!tu)
+    return make_string_error("Can't retrieve translation unit declaration.");
+
+  symfile->ParseDeclsForContext(CompilerDeclContext(
+      clang_ast_ctx, static_cast<clang::DeclContext *>(tu)));
+
+  tu->print(outs());
+
+  return Error::success();
+}
+
 Error opts::symbols::verify(lldb_private::Module &Module) {
   SymbolVendor &plugin = *Module.GetSymbolVendor();
 
@@ -562,6 +595,10 @@ Error opts::symbols::verify(lldb_private
 }
 
 Expected<Error (*)(lldb_private::Module &)> opts::symbols::getAction() {
+  if (Verify && DumpAST)
+    return make_string_error(
+        "Cannot both verify symbol information and dump AST.");
+
   if (Verify) {
     if (Find != FindType::None)
       return make_string_error(
@@ -574,6 +611,18 @@ Expected<Error (*)(lldb_private::Module
     return verify;
   }
 
+  if (DumpAST) {
+    if (Find != FindType::None)
+      return make_string_error(
+          "Cannot both search and dump AST.");
+    if (Regex || !Context.empty() || !Name.empty() || !File.empty() ||
+        Line != 0)
+      return make_string_error(
+          "-regex, -context, -name, -file and -line options are not "
+          "applicable for dumping AST.");
+    return dumpAST;
+  }
+
   if (Regex && !Context.empty())
     return make_string_error(
         "Cannot search using both regular expressions and context.");
@@ -632,6 +681,8 @@ Expected<Error (*)(lldb_private::Module
                                "using line numbers.");
     return findVariables;
   }
+
+  llvm_unreachable("Unsupported symbol action.");
 }
 
 int opts::symbols::dumpSymbols(Debugger &Dbg) {




More information about the lldb-commits mailing list