aleksandr.urakov updated this revision to Diff 163708.
aleksandr.urakov added a comment.

Added the dumping AST ability to `lldb-test`; adding a corresponding test for 
the patch.


https://reviews.llvm.org/D51162

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

Index: tools/lldb-test/lldb-test.cpp
===================================================================
--- tools/lldb-test/lldb-test.cpp
+++ tools/lldb-test/lldb-test.cpp
@@ -148,6 +148,10 @@
   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 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 @@
   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 @@
 }
 
 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 @@
     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 @@
                                "using line numbers.");
     return findVariables;
   }
+
+  llvm_unreachable("Unsupported symbol action.");
 }
 
 int opts::symbols::dumpSymbols(Debugger &Dbg) {
Index: source/Symbol/ClangASTContext.cpp
===================================================================
--- source/Symbol/ClangASTContext.cpp
+++ source/Symbol/ClangASTContext.cpp
@@ -2212,6 +2212,9 @@
       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 @@
 
     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 @@
     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 @@
   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 @@
           VerifyDecl(enumerator_decl);
 #endif
 
-          return true;
+          return enumerator_decl;
         }
       }
     }
   }
-  return false;
+  return nullptr;
 }
 
 CompilerType
Index: source/Plugins/SymbolFile/PDB/SymbolFilePDB.h
===================================================================
--- source/Plugins/SymbolFile/PDB/SymbolFilePDB.h
+++ source/Plugins/SymbolFile/PDB/SymbolFilePDB.h
@@ -179,8 +179,9 @@
       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);
 
Index: source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp
===================================================================
--- source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp
+++ source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp
@@ -551,8 +551,7 @@
       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,33 +578,91 @@
   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;
 
   return pdb->CompleteTypeFromPDB(compiler_type);
 }
 
 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 @@
   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 @@
     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 @@
     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 @@
   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,22 +1401,29 @@
   }
 }
 
-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;
 
   uint32_t matches = 0;
 
   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 @@
     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 @@
     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() {
Index: source/Plugins/SymbolFile/PDB/PDBASTParser.h
===================================================================
--- source/Plugins/SymbolFile/PDB/PDBASTParser.h
+++ source/Plugins/SymbolFile/PDB/PDBASTParser.h
@@ -14,6 +14,8 @@
 
 #include "lldb/Symbol/ClangASTImporter.h"
 
+class SymbolFilePDB;
+
 namespace clang {
 class CharUnits;
 class CXXRecordDecl;
@@ -47,44 +49,65 @@
   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>
       PDBBaseClassSymbolEnumerator;
   typedef llvm::pdb::ConcreteSymbolEnumerator<llvm::pdb::PDBSymbolFunc>
       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
Index: source/Plugins/SymbolFile/PDB/PDBASTParser.cpp
===================================================================
--- source/Plugins/SymbolFile/PDB/PDBASTParser.cpp
+++ source/Plugins/SymbolFile/PDB/PDBASTParser.cpp
@@ -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 @@
   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 @@
     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 @@
 // 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,105 +339,140 @@
       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);
 
-    ClangASTMetadata metadata;
-    metadata.SetUserID(type.getSymIndexId());
-    metadata.SetIsDynamicCXXType(false);
+      auto tag_type_kind = TranslateUdtKind(udt->getUdtKind());
 
-    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());
+      ClangASTMetadata metadata;
+      metadata.SetUserID(type.getSymIndexId());
+      metadata.SetIsDynamicCXXType(false);
 
-    if (udt->isConstType())
-      clang_type = clang_type.AddConstModifier();
+      clang_type = m_ast.CreateRecordType(
+          decl_context, access, name.c_str(), tag_type_kind,
+          lldb::eLanguageTypeC_plus_plus, &metadata);
+      assert(clang_type.IsValid());
 
-    if (udt->isVolatileType())
-      clang_type = clang_type.AddVolatileModifier();
+      auto record_decl =
+          m_ast.GetAsCXXRecordDecl(clang_type.GetOpaqueQualType());
+      assert(record_decl);
+      m_uid_to_decl[type.getSymIndexId()] = record_decl;
 
-    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);
+      auto inheritance_attr = clang::MSInheritanceAttr::CreateImplicit(
+          *m_ast.getASTContext(), GetMSInheritance(*udt));
+      record_decl->addAttr(inheritance_attr);
 
-    ClangASTContext::StartTagDeclarationDefinition(clang_type);
+      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);
+      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);
+        ClangASTContext::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();
+        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();
 
-      m_ast.SetHasExternalStorage(clang_type.GetOpaqueQualType(), true);
+        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();
+
+    if (udt->isVolatileType())
+      clang_type = clang_type.AddVolatileModifier();
 
     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 @@
   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 @@
         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 @@
 
   // 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 @@
   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,274 @@
   }
 }
 
+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);
+
+    // 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(func->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(func->getSymIndexId());
+      if (!type)
+        return nullptr;
+
+      auto storage = func->isStatic() ? clang::StorageClass::SC_Static
+                                      : clang::StorageClass::SC_None;
+
+      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 +1046,15 @@
       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 +1101,10 @@
     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,18 +1138,26 @@
       if (!decl)
         continue;
 
+      m_uid_to_decl[member->getSymIndexId()] = decl;
+
       auto offset = member->getOffset() * 8;
       if (location_type == PDB_LocType::BitField)
         offset += member->getBitPosition();
 
       layout_info.field_offsets.insert(std::make_pair(decl, offset));
 
       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 +1194,12 @@
         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,11 +1217,12 @@
   }
 }
 
-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)
@@ -873,13 +1239,17 @@
     }
 
     // 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;
   }
 }
Index: lit/SymbolFile/PDB/pointers.test
===================================================================
--- lit/SymbolFile/PDB/pointers.test
+++ lit/SymbolFile/PDB/pointers.test
@@ -10,11 +10,11 @@
 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:     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
Index: lit/SymbolFile/PDB/func-symbols.test
===================================================================
--- lit/SymbolFile/PDB/func-symbols.test
+++ lit/SymbolFile/PDB/func-symbols.test
@@ -14,11 +14,11 @@
 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 @@
 
 ; 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'
Index: lit/SymbolFile/PDB/class-layout.test
===================================================================
--- lit/SymbolFile/PDB/class-layout.test
+++ lit/SymbolFile/PDB/class-layout.test
@@ -61,30 +61,30 @@
 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);
Index: lit/SymbolFile/PDB/ast-restore.test
===================================================================
--- /dev/null
+++ lit/SymbolFile/PDB/ast-restore.test
@@ -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();
Index: lit/SymbolFile/PDB/Inputs/AstRestoreTest.cpp
===================================================================
--- /dev/null
+++ lit/SymbolFile/PDB/Inputs/AstRestoreTest.cpp
@@ -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;
+}
Index: include/lldb/Symbol/ClangASTContext.h
===================================================================
--- include/lldb/Symbol/ClangASTContext.h
+++ include/lldb/Symbol/ClangASTContext.h
@@ -214,19 +214,24 @@
   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 @@
   //----------------------------------------------------------------------
   // 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 @@
 
   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 *
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to