[Lldb-commits] [lldb] r350243 - [NativePDB] Implement ParseDeclsForContext.

Zachary Turner via lldb-commits lldb-commits at lists.llvm.org
Wed Jan 2 10:33:54 PST 2019


Author: zturner
Date: Wed Jan  2 10:33:54 2019
New Revision: 350243

URL: http://llvm.org/viewvc/llvm-project?rev=350243&view=rev
Log:
[NativePDB] Implement ParseDeclsForContext.

This is a first step towards getting lldb-test symbols working
with the native plugin.  There is a remaining issue, which is
that the plugin expects that ParseDeclsForContext will also
create lldb symbols rather than just the decls, but the native
pdb plugin doesn't currently do this.  This will be addressed
in a followup patch.

Modified:
    lldb/trunk/lit/SymbolFile/PDB/variables-locations.test
    lldb/trunk/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp
    lldb/trunk/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.h
    lldb/trunk/source/Plugins/SymbolFile/NativePDB/PdbIndex.cpp
    lldb/trunk/source/Plugins/SymbolFile/NativePDB/PdbUtil.cpp
    lldb/trunk/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
    lldb/trunk/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h

Modified: lldb/trunk/lit/SymbolFile/PDB/variables-locations.test
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/lit/SymbolFile/PDB/variables-locations.test?rev=350243&r1=350242&r2=350243&view=diff
==============================================================================
--- lldb/trunk/lit/SymbolFile/PDB/variables-locations.test (original)
+++ lldb/trunk/lit/SymbolFile/PDB/variables-locations.test Wed Jan  2 10:33:54 2019
@@ -1,6 +1,6 @@
 REQUIRES: system-windows, lld
 RUN: %build --compiler=clang-cl --output=%t.exe %S/Inputs/VariablesLocationsTest.cpp
-RUN: %lldb -b -s %S/Inputs/VariablesLocationsTest.script -- %t.exe | FileCheck %s
+RUN: env LLDB_USE_NATIVE_PDB_READER=1 %lldb -b -s %S/Inputs/VariablesLocationsTest.script -- %t.exe | FileCheck %s
 
 CHECK: g_var = 2222
 

Modified: lldb/trunk/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp?rev=350243&r1=350242&r2=350243&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp (original)
+++ lldb/trunk/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp Wed Jan  2 10:33:54 2019
@@ -7,6 +7,9 @@
 #include "llvm/DebugInfo/CodeView/SymbolRecordHelpers.h"
 #include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
 #include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h"
+#include "llvm/DebugInfo/PDB/Native/DbiStream.h"
+#include "llvm/DebugInfo/PDB/Native/PublicsStream.h"
+#include "llvm/DebugInfo/PDB/Native/SymbolStream.h"
 #include "llvm/DebugInfo/PDB/Native/TpiStream.h"
 #include "llvm/Demangle/MicrosoftDemangle.h"
 
@@ -150,8 +153,8 @@ TranslateCallingConvention(llvm::codevie
 }
 
 static llvm::Optional<CVTagRecord>
-GetNestedTagRecord(const NestedTypeRecord &Record, const CVTagRecord &parent,
-                   TpiStream &tpi) {
+GetNestedTagDefinition(const NestedTypeRecord &Record,
+                       const CVTagRecord &parent, TpiStream &tpi) {
   // An LF_NESTTYPE is essentially a nested typedef / using declaration, but it
   // is also used to indicate the primary definition of a nested class.  That is
   // to say, if you have:
@@ -218,7 +221,7 @@ PdbAstBuilder::CreateDeclInfoForType(con
   llvm::ms_demangle::TagTypeNode *ttn = demangler.parseTagUniqueName(sv);
   llvm::ms_demangle::IdentifierNode *idn =
       ttn->QualifiedName->getUnqualifiedIdentifier();
-  std::string uname = idn->toString();
+  std::string uname = idn->toString(llvm::ms_demangle::OF_NoTagSpecifier);
 
   llvm::ms_demangle::NodeArrayNode *name_components =
       ttn->QualifiedName->Components;
@@ -261,15 +264,55 @@ PdbAstBuilder::CreateDeclInfoForType(con
   return {context, uname};
 }
 
+static bool IsUniqueNameEnumTag(llvm::StringRef unique_name) {
+  if (unique_name.size() < 4)
+    return false;
+  return unique_name[3] == 'W';
+}
+
+static std::string GetParentUniqueName(llvm::StringRef unique_name) {
+  if (unique_name.size() < 4)
+    return unique_name;
+  size_t start = IsUniqueNameEnumTag(unique_name) ? 5 : 4;
+  size_t end = unique_name.find('@');
+  if (end == llvm::StringRef::npos)
+    return unique_name;
+  std::string result = unique_name.str();
+  return result.erase(start, end - start + 1);
+}
+
 void PdbAstBuilder::BuildParentMap() {
   LazyRandomTypeCollection &types = m_index.tpi().typeCollection();
 
+  llvm::DenseMap<TypeIndex, TypeIndex> forward_to_full;
+  llvm::DenseMap<TypeIndex, TypeIndex> full_to_forward;
+
+  struct RecordIndices {
+    TypeIndex forward;
+    TypeIndex full;
+  };
+
+  llvm::StringMap<RecordIndices> record_indices;
+
   for (auto ti = types.getFirst(); ti; ti = types.getNext(*ti)) {
     CVType type = types.getType(*ti);
     if (!IsTagRecord(type))
       continue;
 
     CVTagRecord tag = CVTagRecord::create(type);
+
+    RecordIndices &indices = record_indices[tag.asTag().getUniqueName()];
+    if (tag.asTag().isForwardRef())
+      indices.forward = *ti;
+    else
+      indices.full = *ti;
+
+    if (indices.full != TypeIndex::None() &&
+        indices.forward != TypeIndex::None()) {
+      forward_to_full[indices.forward] = indices.full;
+      full_to_forward[indices.full] = indices.forward;
+    }
+
     // We're looking for LF_NESTTYPE records in the field list, so ignore
     // forward references (no field list), and anything without a nested class
     // (since there won't be any LF_NESTTYPE records).
@@ -285,27 +328,26 @@ void PdbAstBuilder::BuildParentMap() {
 
       PdbIndex &index;
       llvm::DenseMap<TypeIndex, TypeIndex> &parents;
+
+      unsigned unnamed_type_index = 1;
       TypeIndex parent;
       const CVTagRecord &parent_cvt;
 
       llvm::Error visitKnownMember(CVMemberRecord &CVR,
                                    NestedTypeRecord &Record) override {
+        std::string unnamed_type_name;
+        if (Record.Name.empty()) {
+          unnamed_type_name =
+              llvm::formatv("<unnamed-type-$S{0}>", unnamed_type_index).str();
+          Record.Name = unnamed_type_name;
+          ++unnamed_type_index;
+        }
         llvm::Optional<CVTagRecord> tag =
-            GetNestedTagRecord(Record, parent_cvt, index.tpi());
+            GetNestedTagDefinition(Record, parent_cvt, index.tpi());
         if (!tag)
           return llvm::ErrorSuccess();
 
         parents[Record.Type] = parent;
-        if (!tag->asTag().isForwardRef())
-          return llvm::ErrorSuccess();
-
-        llvm::Expected<TypeIndex> full_decl =
-            index.tpi().findFullDeclForForwardRef(Record.Type);
-        if (!full_decl) {
-          llvm::consumeError(full_decl.takeError());
-          return llvm::ErrorSuccess();
-        }
-        parents[*full_decl] = parent;
         return llvm::ErrorSuccess();
       }
     };
@@ -316,11 +358,102 @@ void PdbAstBuilder::BuildParentMap() {
     if (error)
       llvm::consumeError(std::move(error));
   }
+
+  // Now that we know the forward -> full mapping of all type indices, we can
+  // re-write all the indices.  At the end of this process, we want a mapping
+  // consisting of fwd -> full and full -> full for all child -> parent indices.
+  // We can re-write the values in place, but for the keys, we must save them
+  // off so that we don't modify the map in place while also iterating it.
+  std::vector<TypeIndex> full_keys;
+  std::vector<TypeIndex> fwd_keys;
+  for (auto &entry : m_parent_types) {
+    TypeIndex key, value;
+    std::tie(key, value) = entry;
+
+    auto iter = forward_to_full.find(value);
+    if (iter != forward_to_full.end())
+      entry.second = iter->second;
+
+    iter = forward_to_full.find(key);
+    if (iter != forward_to_full.end())
+      fwd_keys.push_back(key);
+    else
+      full_keys.push_back(key);
+  }
+  for (TypeIndex fwd : fwd_keys) {
+    TypeIndex full = forward_to_full[fwd];
+    m_parent_types[full] = m_parent_types[fwd];
+  }
+  for (TypeIndex full : full_keys) {
+    TypeIndex fwd = full_to_forward[full];
+    m_parent_types[fwd] = m_parent_types[full];
+  }
+
+  // Now that
+}
+
+static bool isLocalVariableType(SymbolKind K) {
+  switch (K) {
+  case S_REGISTER:
+  case S_REGREL32:
+  case S_LOCAL:
+    return true;
+  default:
+    break;
+  }
+  return false;
+}
+
+static std::string
+RenderScopeList(llvm::ArrayRef<llvm::ms_demangle::Node *> nodes) {
+  lldbassert(!nodes.empty());
+
+  std::string result = nodes.front()->toString();
+  nodes = nodes.drop_front();
+  while (!nodes.empty()) {
+    result += "::";
+    result += nodes.front()->toString(llvm::ms_demangle::OF_NoTagSpecifier);
+    nodes = nodes.drop_front();
+  }
+  return result;
+}
+
+static llvm::Optional<PublicSym32> FindPublicSym(const SegmentOffset &addr,
+                                                 SymbolStream &syms,
+                                                 PublicsStream &publics) {
+  llvm::FixedStreamArray<ulittle32_t> addr_map = publics.getAddressMap();
+  auto iter = std::lower_bound(
+      addr_map.begin(), addr_map.end(), addr,
+      [&](const ulittle32_t &x, const SegmentOffset &y) {
+        CVSymbol s1 = syms.readRecord(x);
+        lldbassert(s1.kind() == S_PUB32);
+        PublicSym32 p1;
+        llvm::cantFail(SymbolDeserializer::deserializeAs<PublicSym32>(s1, p1));
+        if (p1.Segment < y.segment)
+          return true;
+        return p1.Offset < y.offset;
+      });
+  if (iter == addr_map.end())
+    return llvm::None;
+  CVSymbol sym = syms.readRecord(*iter);
+  lldbassert(sym.kind() == S_PUB32);
+  PublicSym32 p;
+  llvm::cantFail(SymbolDeserializer::deserializeAs<PublicSym32>(sym, p));
+  if (p.Segment == addr.segment && p.Offset == addr.offset)
+    return p;
+  return llvm::None;
 }
 
 clang::Decl *PdbAstBuilder::GetOrCreateSymbolForId(PdbCompilandSymId id) {
   CVSymbol cvs = m_index.ReadSymbolRecord(id);
 
+  if (isLocalVariableType(cvs.kind())) {
+    clang::DeclContext *scope = GetParentDeclContext(id);
+    clang::Decl *scope_decl = clang::Decl::castFromDeclContext(scope);
+    PdbCompilandSymId scope_id(id.modi, m_decl_to_status[scope_decl].uid);
+    return GetOrCreateVariableDecl(scope_id, id);
+  }
+
   switch (cvs.kind()) {
   case S_GPROC32:
   case S_LPROC32:
@@ -333,14 +466,6 @@ clang::Decl *PdbAstBuilder::GetOrCreateS
     return nullptr;
   case S_BLOCK32:
     return GetOrCreateBlockDecl(id);
-  case S_REGISTER:
-  case S_REGREL32:
-  case S_LOCAL: {
-    clang::DeclContext *scope = GetParentDeclContext(id);
-    clang::Decl *scope_decl = clang::Decl::castFromDeclContext(scope);
-    PdbCompilandSymId scope_id(id.modi, m_decl_to_status[scope_decl].uid);
-    return GetOrCreateLocalVariableDecl(scope_id, id);
-  }
   default:
     return nullptr;
   }
@@ -371,6 +496,11 @@ clang::Decl *PdbAstBuilder::GetOrCreateD
 }
 
 clang::DeclContext *PdbAstBuilder::GetOrCreateDeclContextForUid(PdbSymUid uid) {
+  if (uid.kind() == PdbSymUidKind::CompilandSym) {
+    if (uid.asCompilandSym().offset == 0)
+      return &GetTranslationUnitDecl();
+  }
+
   clang::Decl *decl = GetOrCreateDeclForUid(uid);
   if (!decl)
     return nullptr;
@@ -385,14 +515,60 @@ clang::DeclContext *PdbAstBuilder::GetPa
   case PdbSymUidKind::CompilandSym: {
     llvm::Optional<PdbCompilandSymId> scope =
         FindSymbolScope(m_index, uid.asCompilandSym());
-    if (!scope)
+    if (scope)
+      return GetOrCreateDeclContextForUid(*scope);
+
+    CVSymbol sym = m_index.ReadSymbolRecord(uid.asCompilandSym());
+    if (!SymbolHasAddress(sym))
+      return &GetTranslationUnitDecl();
+    SegmentOffset addr = GetSegmentAndOffset(sym);
+    llvm::Optional<PublicSym32> pub =
+        FindPublicSym(addr, m_index.symrecords(), m_index.publics());
+    if (!pub)
+      return &GetTranslationUnitDecl();
+
+    llvm::ms_demangle::Demangler demangler;
+    StringView name{pub->Name.begin(), pub->Name.size()};
+    llvm::ms_demangle::SymbolNode *node = demangler.parse(name);
+    if (!node)
       return &GetTranslationUnitDecl();
-    return GetOrCreateDeclContextForUid(*scope);
+    llvm::ArrayRef<llvm::ms_demangle::Node *> name_components{
+        node->Name->Components->Nodes, node->Name->Components->Count - 1};
+
+    if (!name_components.empty()) {
+      // Render the current list of scope nodes as a fully qualified name, and
+      // look it up in the debug info as a type name.  If we find something,
+      // this is a type (which may itself be prefixed by a namespace).  If we
+      // don't, this is a list of namespaces.
+      std::string qname = RenderScopeList(name_components);
+      std::vector<TypeIndex> matches = m_index.tpi().findRecordsByName(qname);
+      while (!matches.empty()) {
+        clang::QualType qt = GetOrCreateType(matches.back());
+        clang::TagDecl *tag = qt->getAsTagDecl();
+        if (tag)
+          return clang::TagDecl::castToDeclContext(tag);
+        matches.pop_back();
+      }
+    }
+
+    // It's not a type.  It must be a series of namespaces.
+    clang::DeclContext *context = &GetTranslationUnitDecl();
+    while (!name_components.empty()) {
+      std::string ns = name_components.front()->toString();
+      context = m_clang.GetUniqueNamespaceDeclaration(ns.c_str(), context);
+      name_components = name_components.drop_front();
+    }
+    return context;
   }
-  case PdbSymUidKind::Type:
+  case PdbSymUidKind::Type: {
     // It could be a namespace, class, or global.  We don't support nested
     // functions yet.  Anyway, we just need to consult the parent type map.
-    break;
+    PdbTypeSymId type_id = uid.asTypeSym();
+    auto iter = m_parent_types.find(type_id.index);
+    if (iter == m_parent_types.end())
+      return &GetTranslationUnitDecl();
+    return GetOrCreateDeclContextForUid(PdbTypeSymId(iter->second));
+  }
   case PdbSymUidKind::FieldListMember:
     // In this case the parent DeclContext is the one for the class that this
     // member is inside of.
@@ -531,10 +707,9 @@ PdbAstBuilder::CreateModifierType(const
 
 clang::QualType PdbAstBuilder::CreateRecordType(PdbTypeSymId id,
                                                 const TagRecord &record) {
-  clang::DeclContext *decl_context = nullptr;
+  clang::DeclContext *context = nullptr;
   std::string uname;
-  std::tie(decl_context, uname) = CreateDeclInfoForType(record, id.index);
-
+  std::tie(context, uname) = CreateDeclInfoForType(record, id.index);
   clang::TagTypeKind ttk = TranslateUdtKind(record);
   lldb::AccessType access =
       (ttk == clang::TTK_Class) ? lldb::eAccessPrivate : lldb::eAccessPublic;
@@ -544,7 +719,7 @@ clang::QualType PdbAstBuilder::CreateRec
   metadata.SetIsDynamicCXXType(false);
 
   CompilerType ct =
-      m_clang.CreateRecordType(decl_context, access, uname.c_str(), ttk,
+      m_clang.CreateRecordType(context, access, uname.c_str(), ttk,
                                lldb::eLanguageTypeC_plus_plus, &metadata);
 
   lldbassert(ct.IsValid());
@@ -583,6 +758,12 @@ PdbAstBuilder::GetOrCreateBlockDecl(PdbC
 
   clang::BlockDecl *block_decl = m_clang.CreateBlockDeclaration(scope);
   m_uid_to_decl.insert({toOpaqueUid(block_id), block_decl});
+
+  DeclStatus status;
+  status.resolved = true;
+  status.uid = toOpaqueUid(block_id);
+  m_decl_to_status.insert({block_decl, status});
+
   return block_decl;
 }
 
@@ -595,12 +776,16 @@ clang::VarDecl *PdbAstBuilder::CreateVar
       &scope, var_info.name.str().c_str(), qt);
 
   m_uid_to_decl[toOpaqueUid(uid)] = var_decl;
+  DeclStatus status;
+  status.resolved = true;
+  status.uid = toOpaqueUid(uid);
+  m_decl_to_status.insert({var_decl, status});
   return var_decl;
 }
 
 clang::VarDecl *
-PdbAstBuilder::GetOrCreateLocalVariableDecl(PdbCompilandSymId scope_id,
-                                            PdbCompilandSymId var_id) {
+PdbAstBuilder::GetOrCreateVariableDecl(PdbCompilandSymId scope_id,
+                                       PdbCompilandSymId var_id) {
   if (clang::Decl *decl = TryGetDecl(var_id))
     return llvm::dyn_cast<clang::VarDecl>(decl);
 
@@ -610,8 +795,7 @@ PdbAstBuilder::GetOrCreateLocalVariableD
   return CreateVariableDecl(PdbSymUid(var_id), sym, *scope);
 }
 
-clang::VarDecl *
-PdbAstBuilder::GetOrCreateGlobalVariableDecl(PdbGlobalSymId var_id) {
+clang::VarDecl *PdbAstBuilder::GetOrCreateVariableDecl(PdbGlobalSymId var_id) {
   if (clang::Decl *decl = TryGetDecl(var_id))
     return llvm::dyn_cast<clang::VarDecl>(decl);
 
@@ -706,6 +890,12 @@ PdbAstBuilder::GetOrCreateFunctionDecl(P
     return llvm::dyn_cast<clang::FunctionDecl>(decl);
 
   clang::DeclContext *parent = GetParentDeclContext(PdbSymUid(func_id));
+  std::string context_name;
+  if (clang::NamespaceDecl *ns = llvm::dyn_cast<clang::NamespaceDecl>(parent)) {
+    context_name = ns->getQualifiedNameAsString();
+  } else if (clang::TagDecl *tag = llvm::dyn_cast<clang::TagDecl>(parent)) {
+    context_name = tag->getQualifiedNameAsString();
+  }
 
   CVSymbol cvs = m_index.ReadSymbolRecord(func_id);
   ProcSym proc(static_cast<SymbolRecordKind>(cvs.kind()));
@@ -713,6 +903,8 @@ PdbAstBuilder::GetOrCreateFunctionDecl(P
 
   PdbTypeSymId type_id(proc.FunctionType);
   clang::QualType qt = GetOrCreateType(type_id);
+  if (qt.isNull())
+    return nullptr;
 
   clang::StorageClass storage = clang::SC_None;
   if (proc.Kind == SymbolRecordKind::ProcSym)
@@ -723,11 +915,19 @@ PdbAstBuilder::GetOrCreateFunctionDecl(P
 
   CompilerType func_ct = ToCompilerType(qt);
 
+  llvm::StringRef proc_name = proc.Name;
+  proc_name.consume_front(context_name);
+  proc_name.consume_front("::");
+
   clang::FunctionDecl *function_decl = m_clang.CreateFunctionDeclaration(
-      parent, proc.Name.str().c_str(), func_ct, storage, false);
+      parent, proc_name.str().c_str(), func_ct, storage, false);
 
   lldbassert(m_uid_to_decl.count(toOpaqueUid(func_id)) == 0);
   m_uid_to_decl[toOpaqueUid(func_id)] = function_decl;
+  DeclStatus status;
+  status.resolved = true;
+  status.uid = toOpaqueUid(func_id);
+  m_decl_to_status.insert({function_decl, status});
 
   CreateFunctionParameters(func_id, *function_decl, func_type->getNumParams());
 
@@ -866,6 +1066,180 @@ PdbAstBuilder::CreateProcedureType(const
       func_sig_ast_type.GetOpaqueQualType());
 }
 
+static bool isTagDecl(clang::DeclContext &context) {
+  return !!llvm::dyn_cast<clang::TagDecl>(&context);
+}
+
+static bool isFunctionDecl(clang::DeclContext &context) {
+  return !!llvm::dyn_cast<clang::FunctionDecl>(&context);
+}
+
+static bool isBlockDecl(clang::DeclContext &context) {
+  return !!llvm::dyn_cast<clang::BlockDecl>(&context);
+}
+
+void PdbAstBuilder::ParseAllNamespacesPlusChildrenOf(
+    llvm::Optional<llvm::StringRef> parent) {
+  TypeIndex ti{m_index.tpi().TypeIndexBegin()};
+  for (const CVType &cvt : m_index.tpi().typeArray()) {
+    PdbTypeSymId tid{ti};
+    ++ti;
+
+    if (!IsTagRecord(cvt))
+      continue;
+
+    CVTagRecord tag = CVTagRecord::create(cvt);
+
+    if (!parent.hasValue()) {
+      clang::QualType qt = GetOrCreateType(tid);
+      CompleteType(qt);
+      continue;
+    }
+
+    // Call CreateDeclInfoForType unconditionally so that the namespace info
+    // gets created.  But only call CreateRecordType if the namespace name
+    // matches.
+    clang::DeclContext *context = nullptr;
+    std::string uname;
+    std::tie(context, uname) = CreateDeclInfoForType(tag.asTag(), tid.index);
+    if (!context->isNamespace())
+      continue;
+
+    clang::NamespaceDecl *ns = llvm::dyn_cast<clang::NamespaceDecl>(context);
+    std::string actual_ns = ns->getQualifiedNameAsString();
+    if (llvm::StringRef(actual_ns).startswith(*parent)) {
+      clang::QualType qt = GetOrCreateType(tid);
+      CompleteType(qt);
+      continue;
+    }
+  }
+
+  uint32_t module_count = m_index.dbi().modules().getModuleCount();
+  for (uint16_t modi = 0; modi < module_count; ++modi) {
+    CompilandIndexItem &cii = m_index.compilands().GetOrCreateCompiland(modi);
+    const CVSymbolArray &symbols = cii.m_debug_stream.getSymbolArray();
+    auto iter = symbols.begin();
+    while (iter != symbols.end()) {
+      PdbCompilandSymId sym_id{modi, iter.offset()};
+
+      switch (iter->kind()) {
+      case S_GPROC32:
+      case S_LPROC32:
+        GetOrCreateFunctionDecl(sym_id);
+        iter = symbols.at(getScopeEndOffset(*iter));
+        break;
+      case S_GDATA32:
+      case S_GTHREAD32:
+      case S_LDATA32:
+      case S_LTHREAD32:
+        GetOrCreateVariableDecl(PdbCompilandSymId(modi, 0), sym_id);
+        ++iter;
+        break;
+      default:
+        ++iter;
+        continue;
+      }
+    }
+  }
+}
+
+static CVSymbolArray skipFunctionParameters(clang::Decl &decl,
+                                            const CVSymbolArray &symbols) {
+  clang::FunctionDecl *func_decl = llvm::dyn_cast<clang::FunctionDecl>(&decl);
+  if (!func_decl)
+    return symbols;
+  unsigned int params = func_decl->getNumParams();
+  if (params == 0)
+    return symbols;
+
+  CVSymbolArray result = symbols;
+
+  while (!result.empty()) {
+    if (params == 0)
+      return result;
+
+    CVSymbol sym = *result.begin();
+    result.drop_front();
+
+    if (!isLocalVariableType(sym.kind()))
+      continue;
+
+    --params;
+  }
+  return result;
+}
+
+void PdbAstBuilder::ParseBlockChildren(PdbCompilandSymId block_id) {
+  CVSymbol sym = m_index.ReadSymbolRecord(block_id);
+  lldbassert(sym.kind() == S_GPROC32 || sym.kind() == S_LPROC32 ||
+             sym.kind() == S_BLOCK32);
+  CompilandIndexItem &cii =
+      m_index.compilands().GetOrCreateCompiland(block_id.modi);
+  CVSymbolArray symbols =
+      cii.m_debug_stream.getSymbolArrayForScope(block_id.offset);
+
+  // Function parameters should already have been created when the function was
+  // parsed.
+  if (sym.kind() == S_GPROC32 || sym.kind() == S_LPROC32)
+    symbols =
+        skipFunctionParameters(*m_uid_to_decl[toOpaqueUid(block_id)], symbols);
+
+  auto begin = symbols.begin();
+  while (begin != symbols.end()) {
+    PdbCompilandSymId child_sym_id(block_id.modi, begin.offset());
+    GetOrCreateSymbolForId(child_sym_id);
+    if (begin->kind() == S_BLOCK32) {
+      ParseBlockChildren(child_sym_id);
+      begin = symbols.at(getScopeEndOffset(*begin));
+    }
+    ++begin;
+  }
+}
+
+void PdbAstBuilder::ParseDeclsForSimpleContext(clang::DeclContext &context) {
+
+  clang::Decl *decl = clang::Decl::castFromDeclContext(&context);
+  lldbassert(decl);
+
+  auto iter = m_decl_to_status.find(decl);
+  lldbassert(iter != m_decl_to_status.end());
+
+  if (auto *tag = llvm::dyn_cast<clang::TagDecl>(&context)) {
+    CompleteTagDecl(*tag);
+    return;
+  }
+
+  if (isFunctionDecl(context) || isBlockDecl(context)) {
+    PdbCompilandSymId block_id = PdbSymUid(iter->second.uid).asCompilandSym();
+    ParseBlockChildren(block_id);
+  }
+}
+
+void PdbAstBuilder::ParseDeclsForContext(clang::DeclContext &context) {
+  // Namespaces aren't explicitly represented in the debug info, and the only
+  // way to parse them is to parse all type info, demangling every single type
+  // and trying to reconstruct the DeclContext hierarchy this way.  Since this
+  // is an expensive operation, we have to special case it so that we do other
+  // work (such as parsing the items that appear within the namespaces) at the
+  // same time.
+  if (context.isTranslationUnit()) {
+    ParseAllNamespacesPlusChildrenOf(llvm::None);
+    return;
+  }
+
+  if (context.isNamespace()) {
+    clang::NamespaceDecl &ns = *llvm::dyn_cast<clang::NamespaceDecl>(&context);
+    std::string qname = ns.getQualifiedNameAsString();
+    ParseAllNamespacesPlusChildrenOf(llvm::StringRef{qname});
+    return;
+  }
+
+  if (isTagDecl(context) || isFunctionDecl(context) || isBlockDecl(context)) {
+    ParseDeclsForSimpleContext(context);
+    return;
+  }
+}
+
 CompilerDecl PdbAstBuilder::ToCompilerDecl(clang::Decl &decl) {
   return {&m_clang, &decl};
 }
@@ -879,4 +1253,9 @@ PdbAstBuilder::ToCompilerDeclContext(cla
   return {&m_clang, &context};
 }
 
+clang::DeclContext *
+PdbAstBuilder::FromCompilerDeclContext(CompilerDeclContext context) {
+  return static_cast<clang::DeclContext *>(context.GetOpaqueDeclContext());
+}
+
 void PdbAstBuilder::Dump(Stream &stream) { m_clang.Dump(stream); }

Modified: lldb/trunk/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.h?rev=350243&r1=350242&r2=350243&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.h (original)
+++ lldb/trunk/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.h Wed Jan  2 10:33:54 2019
@@ -66,9 +66,10 @@ public:
                                                  clang::DeclContext &context);
   clang::FunctionDecl *GetOrCreateFunctionDecl(PdbCompilandSymId func_id);
   clang::BlockDecl *GetOrCreateBlockDecl(PdbCompilandSymId block_id);
-  clang::VarDecl *GetOrCreateLocalVariableDecl(PdbCompilandSymId scope_id,
-                                               PdbCompilandSymId var_id);
-  clang::VarDecl *GetOrCreateGlobalVariableDecl(PdbGlobalSymId var_id);
+  clang::VarDecl *GetOrCreateVariableDecl(PdbCompilandSymId scope_id,
+                                          PdbCompilandSymId var_id);
+  clang::VarDecl *GetOrCreateVariableDecl(PdbGlobalSymId var_id);
+  void ParseDeclsForContext(clang::DeclContext &context);
 
   clang::QualType GetBasicType(lldb::BasicType type);
   clang::QualType GetOrCreateType(PdbTypeSymId type);
@@ -79,6 +80,7 @@ public:
   CompilerDecl ToCompilerDecl(clang::Decl &decl);
   CompilerType ToCompilerType(clang::QualType qt);
   CompilerDeclContext ToCompilerDeclContext(clang::DeclContext &context);
+  clang::DeclContext *FromCompilerDeclContext(CompilerDeclContext context);
 
   ClangASTContext &clang() { return m_clang; }
   ClangASTImporter &importer() { return m_importer; }
@@ -111,6 +113,10 @@ private:
                                      llvm::codeview::CVSymbol sym,
                                      clang::DeclContext &scope);
 
+  void ParseAllNamespacesPlusChildrenOf(llvm::Optional<llvm::StringRef> parent);
+  void ParseDeclsForSimpleContext(clang::DeclContext &context);
+  void ParseBlockChildren(PdbCompilandSymId block_id);
+
   void BuildParentMap();
   std::pair<clang::DeclContext *, std::string>
   CreateDeclInfoForType(const llvm::codeview::TagRecord &record, TypeIndex ti);

Modified: lldb/trunk/source/Plugins/SymbolFile/NativePDB/PdbIndex.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/NativePDB/PdbIndex.cpp?rev=350243&r1=350242&r2=350243&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/SymbolFile/NativePDB/PdbIndex.cpp (original)
+++ lldb/trunk/source/Plugins/SymbolFile/NativePDB/PdbIndex.cpp Wed Jan  2 10:33:54 2019
@@ -136,15 +136,7 @@ void PdbIndex::BuildAddrToSymbolMap(Comp
     // If the debug info is incorrect, we could have multiple symbols with the
     // same address.  So use try_emplace instead of insert, and the first one
     // will win.
-    auto insert_result =
-        cci.m_symbols_by_va.insert(std::make_pair(va, PdbSymUid(cu_sym_id)));
-    (void)insert_result;
-
-    // The odds of an error in some function such as GetSegmentAndOffset or
-    // MakeVirtualAddress are much higher than the odds of encountering bad
-    // debug info, so assert that this item was inserted in the map as opposed
-    // to having already been there.
-    lldbassert(insert_result.second);
+    cci.m_symbols_by_va.try_emplace(va, PdbSymUid(cu_sym_id));
   }
 }
 

Modified: lldb/trunk/source/Plugins/SymbolFile/NativePDB/PdbUtil.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/NativePDB/PdbUtil.cpp?rev=350243&r1=350242&r2=350243&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/SymbolFile/NativePDB/PdbUtil.cpp (original)
+++ lldb/trunk/source/Plugins/SymbolFile/NativePDB/PdbUtil.cpp Wed Jan  2 10:33:54 2019
@@ -733,7 +733,11 @@ size_t lldb_private::npdb::GetSizeOfType
     return 0;
   }
 
-  CVType cvt = tpi.getType(id.index);
+  TypeIndex index = id.index;
+  if (IsForwardRefUdt(index, tpi))
+    index = llvm::cantFail(tpi.findFullDeclForForwardRef(index));
+
+  CVType cvt = tpi.getType(index);
   switch (cvt.kind()) {
   case LF_MODIFIER:
     return GetSizeOfType({LookThroughModifierRecord(cvt)}, tpi);

Modified: lldb/trunk/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp?rev=350243&r1=350242&r2=350243&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp (original)
+++ lldb/trunk/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp Wed Jan  2 10:33:54 2019
@@ -759,7 +759,7 @@ VariableSP SymbolFileNativePDB::CreateGl
       std::make_shared<SymbolFileType>(*this, toOpaqueUid(tid));
   Variable::RangeList ranges;
 
-  m_ast->GetOrCreateGlobalVariableDecl(var_id);
+  m_ast->GetOrCreateVariableDecl(var_id);
 
   DWARFExpression location = MakeGlobalLocationExpression(
       section, offset, GetObjectFile()->GetModule());
@@ -845,6 +845,14 @@ Block &SymbolFileNativePDB::GetOrCreateB
   return CreateBlock(block_id);
 }
 
+void SymbolFileNativePDB::ParseDeclsForContext(
+    lldb_private::CompilerDeclContext decl_ctx) {
+  clang::DeclContext *context = m_ast->FromCompilerDeclContext(decl_ctx);
+  if (!context)
+    return;
+  m_ast->ParseDeclsForContext(*context);
+}
+
 lldb::CompUnitSP SymbolFileNativePDB::ParseCompileUnitAtIndex(uint32_t index) {
   if (index >= GetNumCompileUnits())
     return CompUnitSP();
@@ -1262,7 +1270,7 @@ VariableSP SymbolFileNativePDB::CreateLo
       false, false);
 
   if (!is_param)
-    m_ast->GetOrCreateLocalVariableDecl(scope_id, var_id);
+    m_ast->GetOrCreateVariableDecl(scope_id, var_id);
 
   m_local_variables[toOpaqueUid(var_id)] = var_sp;
   return var_sp;

Modified: lldb/trunk/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h?rev=350243&r1=350242&r2=350243&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h (original)
+++ lldb/trunk/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h Wed Jan  2 10:33:54 2019
@@ -77,6 +77,9 @@ public:
 
   uint32_t GetNumCompileUnits() override;
 
+  void
+  ParseDeclsForContext(lldb_private::CompilerDeclContext decl_ctx) override;
+
   lldb::CompUnitSP ParseCompileUnitAtIndex(uint32_t index) override;
 
   lldb::LanguageType ParseCompileUnitLanguage(const SymbolContext &sc) override;




More information about the lldb-commits mailing list