[Lldb-commits] [lldb] r349383 - [NativePDB] Decouple AST reconstruction from lldb Symbol creation.

Zachary Turner via lldb-commits lldb-commits at lists.llvm.org
Mon Dec 17 11:43:33 PST 2018


Author: zturner
Date: Mon Dec 17 11:43:33 2018
New Revision: 349383

URL: http://llvm.org/viewvc/llvm-project?rev=349383&view=rev
Log:
[NativePDB] Decouple AST reconstruction from lldb Symbol creation.

Previously the code that parsed debug info to create lldb's Symbol
objects such as Variable, Type, Function, etc was tightly coupled
to the AST reconstruction code.  This made it difficult / impossible
to implement functions such as ParseDeclsForContext() that were only
supposed to be operating on clang AST's.  By splitting these apart,
the logic becomes much cleaner and we have a clear separation of
responsibilities.

Added:
    lldb/trunk/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp
    lldb/trunk/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.h
Modified:
    lldb/trunk/lit/SymbolFile/NativePDB/function-types-classes.cpp
    lldb/trunk/source/Plugins/SymbolFile/NativePDB/CMakeLists.txt
    lldb/trunk/source/Plugins/SymbolFile/NativePDB/PdbUtil.cpp
    lldb/trunk/source/Plugins/SymbolFile/NativePDB/PdbUtil.h
    lldb/trunk/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
    lldb/trunk/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h
    lldb/trunk/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp
    lldb/trunk/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.h

Modified: lldb/trunk/lit/SymbolFile/NativePDB/function-types-classes.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/lit/SymbolFile/NativePDB/function-types-classes.cpp?rev=349383&r1=349382&r2=349383&view=diff
==============================================================================
--- lldb/trunk/lit/SymbolFile/NativePDB/function-types-classes.cpp (original)
+++ lldb/trunk/lit/SymbolFile/NativePDB/function-types-classes.cpp Mon Dec 17 11:43:33 2018
@@ -108,10 +108,10 @@ auto incomplete = &three<Incomplete*, In
 // CHECK: (Incomplete *(*)(Incomplete **, const Incomplete *)) incomplete = {{.*}}
 
 // CHECK: TranslationUnitDecl {{.*}}
-// CHECK: |-CXXRecordDecl {{.*}} class C definition
-// CHECK: |-CXXRecordDecl {{.*}} union U definition
+// CHECK: |-CXXRecordDecl {{.*}} class C
+// CHECK: |-CXXRecordDecl {{.*}} union U
 // CHECK: |-EnumDecl {{.*}} E
-// CHECK: |-CXXRecordDecl {{.*}} struct S definition
+// CHECK: |-CXXRecordDecl {{.*}} struct S
 // CHECK: |-CXXRecordDecl {{.*}} struct B
 // CHECK: | |-CXXRecordDecl {{.*}} struct A
 // CHECK: | | |-CXXRecordDecl {{.*}} struct S
@@ -119,11 +119,11 @@ auto incomplete = &three<Incomplete*, In
 // CHECK: | |-CXXRecordDecl {{.*}} struct C
 // CHECK: | | |-CXXRecordDecl {{.*}} struct S
 // CHECK: | `-NamespaceDecl {{.*}} B
-// CHECK: |   `-CXXRecordDecl {{.*}} struct S definition
-// CHECK: |-CXXRecordDecl {{.*}} struct TC<int> definition
-// CHECK: |-CXXRecordDecl {{.*}} struct TC<struct TC<int>> definition
-// CHECK: |-CXXRecordDecl {{.*}} struct TC<struct A::B::S> definition
-// CHECK: |-CXXRecordDecl {{.*}} struct TC<void> definition
+// CHECK: |   `-CXXRecordDecl {{.*}} struct S
+// CHECK: |-CXXRecordDecl {{.*}} struct TC<int>
+// CHECK: |-CXXRecordDecl {{.*}} struct TC<struct TC<int>>
+// CHECK: |-CXXRecordDecl {{.*}} struct TC<struct A::B::S>
+// CHECK: |-CXXRecordDecl {{.*}} struct TC<void>
 // CHECK: |-CXXRecordDecl {{.*}} struct Incomplete
 
 int main(int argc, char **argv) {

Modified: lldb/trunk/source/Plugins/SymbolFile/NativePDB/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/NativePDB/CMakeLists.txt?rev=349383&r1=349382&r2=349383&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/SymbolFile/NativePDB/CMakeLists.txt (original)
+++ lldb/trunk/source/Plugins/SymbolFile/NativePDB/CMakeLists.txt Mon Dec 17 11:43:33 2018
@@ -1,6 +1,7 @@
 add_lldb_library(lldbPluginSymbolFileNativePDB PLUGIN
   CompileUnitIndex.cpp
   DWARFLocationExpression.cpp
+  PdbASTBuilder.cpp
   PdbIndex.cpp
   PdbSymUid.cpp
   PdbUtil.cpp

Added: lldb/trunk/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp?rev=349383&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp (added)
+++ lldb/trunk/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp Mon Dec 17 11:43:33 2018
@@ -0,0 +1,865 @@
+#include "PdbAstBuilder.h"
+
+#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
+#include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"
+#include "llvm/DebugInfo/CodeView/SymbolDeserializer.h"
+#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
+#include "llvm/DebugInfo/CodeView/SymbolRecordHelpers.h"
+#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
+#include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h"
+#include "llvm/DebugInfo/PDB/Native/TpiStream.h"
+#include "llvm/Demangle/MicrosoftDemangle.h"
+
+#include "lldb/Core/Module.h"
+#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Symbol/ClangExternalASTSourceCommon.h"
+#include "lldb/Symbol/ClangUtil.h"
+#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Utility/LLDBAssert.h"
+
+#include "PdbUtil.h"
+#include "UdtRecordCompleter.h"
+
+using namespace lldb_private;
+using namespace lldb_private::npdb;
+using namespace llvm::codeview;
+using namespace llvm::pdb;
+
+static llvm::Optional<PdbCompilandSymId> FindSymbolScope(PdbIndex &index,
+                                                         PdbCompilandSymId id) {
+  CVSymbol sym = index.ReadSymbolRecord(id);
+  if (symbolOpensScope(sym.kind())) {
+    // If this exact symbol opens a scope, we can just directly access its
+    // parent.
+    id.offset = getScopeParentOffset(sym);
+    // Global symbols have parent offset of 0.  Return llvm::None to indicate
+    // this.
+    if (id.offset == 0)
+      return llvm::None;
+    return id;
+  }
+
+  // Otherwise we need to start at the beginning and iterate forward until we
+  // reach (or pass) this particular symbol
+  CompilandIndexItem &cii = index.compilands().GetOrCreateCompiland(id.modi);
+  const CVSymbolArray &syms = cii.m_debug_stream.getSymbolArray();
+
+  auto begin = syms.begin();
+  auto end = syms.at(id.offset);
+  std::vector<PdbCompilandSymId> scope_stack;
+
+  while (begin != end) {
+    if (id.offset == begin.offset()) {
+      // We have a match!  Return the top of the stack
+      if (scope_stack.empty())
+        return llvm::None;
+      return scope_stack.back();
+    }
+    if (begin.offset() > id.offset) {
+      // We passed it.  We couldn't even find this symbol record.
+      lldbassert(false && "Invalid compiland symbol id!");
+      return llvm::None;
+    }
+
+    // We haven't found the symbol yet.  Check if we need to open or close the
+    // scope stack.
+    if (symbolOpensScope(begin->kind())) {
+      // We can use the end offset of the scope to determine whether or not
+      // we can just outright skip this entire scope.
+      uint32_t scope_end = getScopeEndOffset(*begin);
+      if (scope_end < id.modi) {
+        begin = syms.at(scope_end);
+      } else {
+        // The symbol we're looking for is somewhere in this scope.
+        scope_stack.emplace_back(id.modi, begin.offset());
+      }
+    } else if (symbolEndsScope(begin->kind())) {
+      scope_stack.pop_back();
+    }
+    ++begin;
+  }
+
+  return llvm::None;
+}
+
+static clang::TagTypeKind TranslateUdtKind(const TagRecord &cr) {
+  switch (cr.Kind) {
+  case TypeRecordKind::Class:
+    return clang::TTK_Class;
+  case TypeRecordKind::Struct:
+    return clang::TTK_Struct;
+  case TypeRecordKind::Union:
+    return clang::TTK_Union;
+  case TypeRecordKind::Interface:
+    return clang::TTK_Interface;
+  case TypeRecordKind::Enum:
+    return clang::TTK_Enum;
+  default:
+    lldbassert(false && "Invalid tag record kind!");
+    return clang::TTK_Struct;
+  }
+}
+
+static bool IsCVarArgsFunction(llvm::ArrayRef<TypeIndex> args) {
+  if (args.empty())
+    return false;
+  return args.back() == TypeIndex::None();
+}
+
+static bool
+AnyScopesHaveTemplateParams(llvm::ArrayRef<llvm::ms_demangle::Node *> scopes) {
+  for (llvm::ms_demangle::Node *n : scopes) {
+    auto *idn = static_cast<llvm::ms_demangle::IdentifierNode *>(n);
+    if (idn->TemplateParams)
+      return true;
+  }
+  return false;
+}
+
+static ClangASTContext &GetClangASTContext(ObjectFile &obj) {
+  TypeSystem *ts =
+      obj.GetModule()->GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus);
+  lldbassert(ts);
+  return static_cast<ClangASTContext &>(*ts);
+}
+
+static llvm::Optional<clang::CallingConv>
+TranslateCallingConvention(llvm::codeview::CallingConvention conv) {
+  using CC = llvm::codeview::CallingConvention;
+  switch (conv) {
+
+  case CC::NearC:
+  case CC::FarC:
+    return clang::CallingConv::CC_C;
+  case CC::NearPascal:
+  case CC::FarPascal:
+    return clang::CallingConv::CC_X86Pascal;
+  case CC::NearFast:
+  case CC::FarFast:
+    return clang::CallingConv::CC_X86FastCall;
+  case CC::NearStdCall:
+  case CC::FarStdCall:
+    return clang::CallingConv::CC_X86StdCall;
+  case CC::ThisCall:
+    return clang::CallingConv::CC_X86ThisCall;
+  case CC::NearVector:
+    return clang::CallingConv::CC_X86VectorCall;
+  default:
+    return llvm::None;
+  }
+}
+
+static llvm::Optional<CVTagRecord>
+GetNestedTagRecord(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:
+  // struct A {
+  //   struct B {};
+  //   using C = B;
+  // };
+  // Then in the debug info, this will appear as:
+  // LF_STRUCTURE `A::B` [type index = N]
+  // LF_STRUCTURE `A`
+  //   LF_NESTTYPE [name = `B`, index = N]
+  //   LF_NESTTYPE [name = `C`, index = N]
+  // In order to accurately reconstruct the decl context hierarchy, we need to
+  // know which ones are actual definitions and which ones are just aliases.
+
+  // If it's a simple type, then this is something like `using foo = int`.
+  if (Record.Type.isSimple())
+    return llvm::None;
+
+  CVType cvt = tpi.getType(Record.Type);
+
+  if (!IsTagRecord(cvt))
+    return llvm::None;
+
+  // If it's an inner definition, then treat whatever name we have here as a
+  // single component of a mangled name.  So we can inject it into the parent's
+  // mangled name to see if it matches.
+  CVTagRecord child = CVTagRecord::create(cvt);
+  std::string qname = parent.asTag().getUniqueName();
+  if (qname.size() < 4 || child.asTag().getUniqueName().size() < 4)
+    return llvm::None;
+
+  // qname[3] is the tag type identifier (struct, class, union, etc).  Since the
+  // inner tag type is not necessarily the same as the outer tag type, re-write
+  // it to match the inner tag type.
+  qname[3] = child.asTag().getUniqueName()[3];
+  std::string piece = Record.Name;
+  piece.push_back('@');
+  qname.insert(4, std::move(piece));
+  if (qname != child.asTag().UniqueName)
+    return llvm::None;
+
+  return std::move(child);
+}
+
+PdbAstBuilder::PdbAstBuilder(ObjectFile &obj, PdbIndex &index)
+    : m_index(index), m_clang(GetClangASTContext(obj)) {
+  BuildParentMap();
+}
+
+clang::DeclContext &PdbAstBuilder::GetTranslationUnitDecl() {
+  return *m_clang.GetTranslationUnitDecl();
+}
+
+std::pair<clang::DeclContext *, std::string>
+PdbAstBuilder::CreateDeclInfoForType(const TagRecord &record, TypeIndex ti) {
+  // FIXME: Move this to GetDeclContextContainingUID.
+
+  llvm::ms_demangle::Demangler demangler;
+  StringView sv(record.UniqueName.begin(), record.UniqueName.size());
+  llvm::ms_demangle::TagTypeNode *ttn = demangler.parseTagUniqueName(sv);
+  llvm::ms_demangle::IdentifierNode *idn =
+      ttn->QualifiedName->getUnqualifiedIdentifier();
+  std::string uname = idn->toString();
+
+  llvm::ms_demangle::NodeArrayNode *name_components =
+      ttn->QualifiedName->Components;
+  llvm::ArrayRef<llvm::ms_demangle::Node *> scopes(name_components->Nodes,
+                                                   name_components->Count - 1);
+
+  clang::DeclContext *context = m_clang.GetTranslationUnitDecl();
+
+  // If this type doesn't have a parent type in the debug info, then the best we
+  // can do is to say that it's either a series of namespaces (if the scope is
+  // non-empty), or the translation unit (if the scope is empty).
+  auto parent_iter = m_parent_types.find(ti);
+  if (parent_iter == m_parent_types.end()) {
+    if (scopes.empty())
+      return {context, uname};
+
+    // If there is no parent in the debug info, but some of the scopes have
+    // template params, then this is a case of bad debug info.  See, for
+    // example, llvm.org/pr39607.  We don't want to create an ambiguity between
+    // a NamespaceDecl and a CXXRecordDecl, so instead we create a class at
+    // global scope with the fully qualified name.
+    if (AnyScopesHaveTemplateParams(scopes))
+      return {context, record.Name};
+
+    for (llvm::ms_demangle::Node *scope : scopes) {
+      auto *nii = static_cast<llvm::ms_demangle::NamedIdentifierNode *>(scope);
+      std::string str = nii->toString();
+      context = m_clang.GetUniqueNamespaceDeclaration(str.c_str(), context);
+    }
+    return {context, uname};
+  }
+
+  // Otherwise, all we need to do is get the parent type of this type and
+  // recurse into our lazy type creation / AST reconstruction logic to get an
+  // LLDB TypeSP for the parent.  This will cause the AST to automatically get
+  // the right DeclContext created for any parent.
+  clang::QualType parent_qt = GetOrCreateType(parent_iter->second);
+
+  context = clang::TagDecl::castToDeclContext(parent_qt->getAsTagDecl());
+  return {context, uname};
+}
+
+void PdbAstBuilder::BuildParentMap() {
+  LazyRandomTypeCollection &types = m_index.tpi().typeCollection();
+
+  for (auto ti = types.getFirst(); ti; ti = types.getNext(*ti)) {
+    CVType type = types.getType(*ti);
+    if (!IsTagRecord(type))
+      continue;
+
+    CVTagRecord tag = CVTagRecord::create(type);
+    // 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).
+    if (tag.asTag().isForwardRef() || !tag.asTag().containsNestedClass())
+      continue;
+
+    struct ProcessTpiStream : public TypeVisitorCallbacks {
+      ProcessTpiStream(PdbIndex &index, TypeIndex parent,
+                       const CVTagRecord &parent_cvt,
+                       llvm::DenseMap<TypeIndex, TypeIndex> &parents)
+          : index(index), parents(parents), parent(parent),
+            parent_cvt(parent_cvt) {}
+
+      PdbIndex &index;
+      llvm::DenseMap<TypeIndex, TypeIndex> &parents;
+      TypeIndex parent;
+      const CVTagRecord &parent_cvt;
+
+      llvm::Error visitKnownMember(CVMemberRecord &CVR,
+                                   NestedTypeRecord &Record) override {
+        llvm::Optional<CVTagRecord> tag =
+            GetNestedTagRecord(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();
+      }
+    };
+
+    CVType field_list = m_index.tpi().getType(tag.asTag().FieldList);
+    ProcessTpiStream process(m_index, *ti, tag, m_parent_types);
+    llvm::Error error = visitMemberRecordStream(field_list.data(), process);
+    if (error)
+      llvm::consumeError(std::move(error));
+  }
+}
+
+clang::Decl *PdbAstBuilder::GetOrCreateSymbolForId(PdbCompilandSymId id) {
+  CVSymbol cvs = m_index.ReadSymbolRecord(id);
+
+  switch (cvs.kind()) {
+  case S_GPROC32:
+  case S_LPROC32:
+    return GetOrCreateFunctionDecl(id);
+  case S_GDATA32:
+  case S_LDATA32:
+  case S_GTHREAD32:
+  case S_CONSTANT:
+    // global variable
+    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;
+  }
+}
+
+clang::Decl *PdbAstBuilder::GetOrCreateDeclForUid(PdbSymUid uid) {
+  if (clang::Decl *result = TryGetDecl(uid))
+    return result;
+
+  clang::Decl *result = nullptr;
+  switch (uid.kind()) {
+  case PdbSymUidKind::CompilandSym:
+    result = GetOrCreateSymbolForId(uid.asCompilandSym());
+    break;
+  case PdbSymUidKind::Type: {
+    clang::QualType qt = GetOrCreateType(uid.asTypeSym());
+    if (auto *tag = qt->getAsTagDecl()) {
+      result = tag;
+      break;
+    }
+    return nullptr;
+  }
+  default:
+    return nullptr;
+  }
+  m_uid_to_decl[toOpaqueUid(uid)] = result;
+  return result;
+}
+
+clang::DeclContext *PdbAstBuilder::GetOrCreateDeclContextForUid(PdbSymUid uid) {
+  clang::Decl *decl = GetOrCreateDeclForUid(uid);
+  if (!decl)
+    return nullptr;
+
+  return clang::Decl::castToDeclContext(decl);
+}
+
+clang::DeclContext *PdbAstBuilder::GetParentDeclContext(PdbSymUid uid) {
+  // We must do this *without* calling GetOrCreate on the current uid, as
+  // that would be an infinite recursion.
+  switch (uid.kind()) {
+  case PdbSymUidKind::CompilandSym: {
+    llvm::Optional<PdbCompilandSymId> scope =
+        FindSymbolScope(m_index, uid.asCompilandSym());
+    if (!scope)
+      return &GetTranslationUnitDecl();
+    return GetOrCreateDeclContextForUid(*scope);
+  }
+  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;
+  case PdbSymUidKind::FieldListMember:
+    // In this case the parent DeclContext is the one for the class that this
+    // member is inside of.
+    break;
+  default:
+    break;
+  }
+  return &GetTranslationUnitDecl();
+}
+
+bool PdbAstBuilder::CompleteType(clang::QualType qt) {
+  clang::TagDecl *tag = qt->getAsTagDecl();
+  if (!tag)
+    return false;
+
+  return CompleteTagDecl(*tag);
+}
+
+bool PdbAstBuilder::CompleteTagDecl(clang::TagDecl &tag) {
+  // If this is not in our map, it's an error.
+  auto status_iter = m_decl_to_status.find(&tag);
+  lldbassert(status_iter != m_decl_to_status.end());
+
+  // If it's already complete, just return.
+  DeclStatus &status = status_iter->second;
+  if (status.resolved)
+    return true;
+
+  PdbTypeSymId type_id = PdbSymUid(status.uid).asTypeSym();
+
+  lldbassert(IsTagRecord(type_id, m_index.tpi()));
+
+  clang::QualType tag_qt = m_clang.getASTContext()->getTypeDeclType(&tag);
+  ClangASTContext::SetHasExternalStorage(tag_qt.getAsOpaquePtr(), false);
+
+  TypeIndex tag_ti = type_id.index;
+  CVType cvt = m_index.tpi().getType(tag_ti);
+  if (cvt.kind() == LF_MODIFIER)
+    tag_ti = LookThroughModifierRecord(cvt);
+
+  PdbTypeSymId best_ti = GetBestPossibleDecl(tag_ti, m_index.tpi());
+  cvt = m_index.tpi().getType(best_ti.index);
+  lldbassert(IsTagRecord(cvt));
+
+  if (IsForwardRefUdt(cvt)) {
+    // If we can't find a full decl for this forward ref anywhere in the debug
+    // info, then we have no way to complete it.
+    return false;
+  }
+
+  TypeIndex field_list_ti = GetFieldListIndex(cvt);
+  CVType field_list_cvt = m_index.tpi().getType(field_list_ti);
+  if (field_list_cvt.kind() != LF_FIELDLIST)
+    return false;
+
+  // Visit all members of this class, then perform any finalization necessary
+  // to complete the class.
+  CompilerType ct = ToCompilerType(tag_qt);
+  UdtRecordCompleter completer(best_ti, ct, tag, *this, m_index.tpi());
+  auto error =
+      llvm::codeview::visitMemberRecordStream(field_list_cvt.data(), completer);
+  completer.complete();
+
+  status.resolved = true;
+  if (!error)
+    return true;
+
+  llvm::consumeError(std::move(error));
+  return false;
+}
+
+clang::QualType PdbAstBuilder::CreateSimpleType(TypeIndex ti) {
+  if (ti == TypeIndex::NullptrT())
+    return GetBasicType(lldb::eBasicTypeNullPtr);
+
+  if (ti.getSimpleMode() != SimpleTypeMode::Direct) {
+    clang::QualType direct_type = GetOrCreateType(ti.makeDirect());
+    return m_clang.getASTContext()->getPointerType(direct_type);
+  }
+
+  if (ti.getSimpleKind() == SimpleTypeKind::NotTranslated)
+    return {};
+
+  lldb::BasicType bt = GetCompilerTypeForSimpleKind(ti.getSimpleKind());
+  if (bt == lldb::eBasicTypeInvalid)
+    return {};
+
+  return GetBasicType(bt);
+}
+
+clang::QualType PdbAstBuilder::CreatePointerType(const PointerRecord &pointer) {
+  clang::QualType pointee_type = GetOrCreateType(pointer.ReferentType);
+
+  if (pointer.isPointerToMember()) {
+    MemberPointerInfo mpi = pointer.getMemberInfo();
+    clang::QualType class_type = GetOrCreateType(mpi.ContainingType);
+
+    return m_clang.getASTContext()->getMemberPointerType(
+        pointee_type, class_type.getTypePtr());
+  }
+
+  clang::QualType pointer_type;
+  if (pointer.getMode() == PointerMode::LValueReference)
+    pointer_type =
+        m_clang.getASTContext()->getLValueReferenceType(pointee_type);
+  else if (pointer.getMode() == PointerMode::RValueReference)
+    pointer_type =
+        m_clang.getASTContext()->getRValueReferenceType(pointee_type);
+  else
+    pointer_type = m_clang.getASTContext()->getPointerType(pointee_type);
+
+  if ((pointer.getOptions() & PointerOptions::Const) != PointerOptions::None)
+    pointer_type.addConst();
+
+  if ((pointer.getOptions() & PointerOptions::Volatile) != PointerOptions::None)
+    pointer_type.addVolatile();
+
+  if ((pointer.getOptions() & PointerOptions::Restrict) != PointerOptions::None)
+    pointer_type.addRestrict();
+
+  return pointer_type;
+}
+
+clang::QualType
+PdbAstBuilder::CreateModifierType(const ModifierRecord &modifier) {
+
+  clang::QualType unmodified_type = GetOrCreateType(modifier.ModifiedType);
+
+  if ((modifier.Modifiers & ModifierOptions::Const) != ModifierOptions::None)
+    unmodified_type.addConst();
+  if ((modifier.Modifiers & ModifierOptions::Volatile) != ModifierOptions::None)
+    unmodified_type.addVolatile();
+
+  return unmodified_type;
+}
+
+clang::QualType PdbAstBuilder::CreateRecordType(PdbTypeSymId id,
+                                                const TagRecord &record) {
+  clang::DeclContext *decl_context = nullptr;
+  std::string uname;
+  std::tie(decl_context, uname) = CreateDeclInfoForType(record, id.index);
+
+  clang::TagTypeKind ttk = TranslateUdtKind(record);
+  lldb::AccessType access =
+      (ttk == clang::TTK_Class) ? lldb::eAccessPrivate : lldb::eAccessPublic;
+
+  ClangASTMetadata metadata;
+  metadata.SetUserID(toOpaqueUid(id));
+  metadata.SetIsDynamicCXXType(false);
+
+  CompilerType ct =
+      m_clang.CreateRecordType(decl_context, access, uname.c_str(), ttk,
+                               lldb::eLanguageTypeC_plus_plus, &metadata);
+
+  lldbassert(ct.IsValid());
+
+  ClangASTContext::StartTagDeclarationDefinition(ct);
+
+  // Even if it's possible, don't complete it at this point. Just mark it
+  // forward resolved, and if/when LLDB needs the full definition, it can
+  // ask us.
+  clang::QualType result =
+      clang::QualType::getFromOpaquePtr(ct.GetOpaqueQualType());
+
+  ClangASTContext::SetHasExternalStorage(result.getAsOpaquePtr(), true);
+  return result;
+}
+
+clang::Decl *PdbAstBuilder::TryGetDecl(PdbSymUid uid) const {
+  auto iter = m_uid_to_decl.find(toOpaqueUid(uid));
+  if (iter != m_uid_to_decl.end())
+    return iter->second;
+  return nullptr;
+}
+
+clang::NamespaceDecl *
+PdbAstBuilder::GetOrCreateNamespaceDecl(llvm::StringRef name,
+                                        clang::DeclContext &context) {
+  return m_clang.GetUniqueNamespaceDeclaration(name.str().c_str(), &context);
+}
+
+clang::BlockDecl *
+PdbAstBuilder::GetOrCreateBlockDecl(PdbCompilandSymId block_id) {
+  if (clang::Decl *decl = TryGetDecl(block_id))
+    return llvm::dyn_cast<clang::BlockDecl>(decl);
+
+  clang::DeclContext *scope = GetParentDeclContext(block_id);
+
+  clang::BlockDecl *block_decl = m_clang.CreateBlockDeclaration(scope);
+  m_uid_to_decl.insert({toOpaqueUid(block_id), block_decl});
+  return block_decl;
+}
+
+clang::VarDecl *
+PdbAstBuilder::GetOrCreateLocalVariableDecl(PdbCompilandSymId scope_id,
+                                            PdbCompilandSymId var_id) {
+  if (clang::Decl *decl = TryGetDecl(var_id))
+    return llvm::dyn_cast<clang::VarDecl>(decl);
+
+  clang::DeclContext *scope = GetOrCreateDeclContextForUid(scope_id);
+
+  CVSymbol var = m_index.ReadSymbolRecord(var_id);
+  VariableInfo var_info = GetVariableNameInfo(var);
+  clang::QualType qt = GetOrCreateType(var_info.type);
+
+  clang::VarDecl *var_decl =
+      m_clang.CreateVariableDeclaration(scope, var_info.name.str().c_str(), qt);
+
+  m_uid_to_decl[toOpaqueUid(var_id)] = var_decl;
+  return var_decl;
+}
+
+clang::QualType PdbAstBuilder::GetBasicType(lldb::BasicType type) {
+  CompilerType ct = m_clang.GetBasicType(type);
+  return clang::QualType::getFromOpaquePtr(ct.GetOpaqueQualType());
+}
+
+clang::QualType PdbAstBuilder::CreateType(PdbTypeSymId type) {
+  if (type.index.isSimple())
+    return CreateSimpleType(type.index);
+
+  CVType cvt = m_index.tpi().getType(type.index);
+
+  if (cvt.kind() == LF_MODIFIER) {
+    ModifierRecord modifier;
+    llvm::cantFail(
+        TypeDeserializer::deserializeAs<ModifierRecord>(cvt, modifier));
+    return CreateModifierType(modifier);
+  }
+
+  if (cvt.kind() == LF_POINTER) {
+    PointerRecord pointer;
+    llvm::cantFail(
+        TypeDeserializer::deserializeAs<PointerRecord>(cvt, pointer));
+    return CreatePointerType(pointer);
+  }
+
+  if (IsTagRecord(cvt)) {
+    CVTagRecord tag = CVTagRecord::create(cvt);
+    if (tag.kind() == CVTagRecord::Union)
+      return CreateRecordType(type.index, tag.asUnion());
+    if (tag.kind() == CVTagRecord::Enum)
+      return CreateEnumType(type.index, tag.asEnum());
+    return CreateRecordType(type.index, tag.asClass());
+  }
+
+  if (cvt.kind() == LF_ARRAY) {
+    ArrayRecord ar;
+    llvm::cantFail(TypeDeserializer::deserializeAs<ArrayRecord>(cvt, ar));
+    return CreateArrayType(ar);
+  }
+
+  if (cvt.kind() == LF_PROCEDURE) {
+    ProcedureRecord pr;
+    llvm::cantFail(TypeDeserializer::deserializeAs<ProcedureRecord>(cvt, pr));
+    return CreateProcedureType(pr);
+  }
+
+  return {};
+}
+
+clang::QualType PdbAstBuilder::GetOrCreateType(PdbTypeSymId type) {
+  lldb::user_id_t uid = toOpaqueUid(type);
+  auto iter = m_uid_to_type.find(uid);
+  if (iter != m_uid_to_type.end())
+    return iter->second;
+
+  PdbTypeSymId best_type = GetBestPossibleDecl(type, m_index.tpi());
+
+  clang::QualType qt;
+  if (best_type.index != type.index) {
+    // This is a forward decl.  Call GetOrCreate on the full decl, then map the
+    // forward decl id to the full decl QualType.
+    clang::QualType qt = GetOrCreateType(best_type);
+    m_uid_to_type[toOpaqueUid(type)] = qt;
+    return qt;
+  }
+
+  // This is either a full decl, or a forward decl with no matching full decl
+  // in the debug info.
+  qt = CreateType(type);
+  m_uid_to_type[toOpaqueUid(type)] = qt;
+  if (IsTagRecord(type, m_index.tpi())) {
+    clang::TagDecl *tag = qt->getAsTagDecl();
+    lldbassert(m_decl_to_status.count(tag) == 0);
+
+    DeclStatus &status = m_decl_to_status[tag];
+    status.uid = uid;
+    status.resolved = false;
+  }
+  return qt;
+}
+
+clang::FunctionDecl *
+PdbAstBuilder::GetOrCreateFunctionDecl(PdbCompilandSymId func_id) {
+  if (clang::Decl *decl = TryGetDecl(func_id))
+    return llvm::dyn_cast<clang::FunctionDecl>(decl);
+
+  clang::DeclContext *parent = GetParentDeclContext(PdbSymUid(func_id));
+
+  CVSymbol cvs = m_index.ReadSymbolRecord(func_id);
+  ProcSym proc(static_cast<SymbolRecordKind>(cvs.kind()));
+  llvm::cantFail(SymbolDeserializer::deserializeAs<ProcSym>(cvs, proc));
+
+  PdbTypeSymId type_id(proc.FunctionType);
+  clang::QualType qt = GetOrCreateType(type_id);
+
+  clang::StorageClass storage = clang::SC_None;
+  if (proc.Kind == SymbolRecordKind::ProcSym)
+    storage = clang::SC_Static;
+
+  const clang::FunctionProtoType *func_type =
+      llvm::dyn_cast<clang::FunctionProtoType>(qt);
+
+  CompilerType func_ct = ToCompilerType(qt);
+
+  clang::FunctionDecl *function_decl = m_clang.CreateFunctionDeclaration(
+      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;
+
+  CreateFunctionParameters(func_id, *function_decl, func_type->getNumParams());
+
+  return function_decl;
+}
+
+void PdbAstBuilder::CreateFunctionParameters(PdbCompilandSymId func_id,
+                                             clang::FunctionDecl &function_decl,
+                                             uint32_t param_count) {
+  CompilandIndexItem *cii = m_index.compilands().GetCompiland(func_id.modi);
+  CVSymbolArray scope =
+      cii->m_debug_stream.getSymbolArrayForScope(func_id.offset);
+
+  auto begin = scope.begin();
+  auto end = scope.end();
+  std::vector<clang::ParmVarDecl *> params;
+  while (begin != end && param_count > 0) {
+    uint32_t record_offset = begin.offset();
+    CVSymbol sym = *begin++;
+
+    TypeIndex param_type;
+    llvm::StringRef param_name;
+    switch (sym.kind()) {
+    case S_REGREL32: {
+      RegRelativeSym reg(SymbolRecordKind::RegRelativeSym);
+      cantFail(SymbolDeserializer::deserializeAs<RegRelativeSym>(sym, reg));
+      param_type = reg.Type;
+      param_name = reg.Name;
+      break;
+    }
+    case S_REGISTER: {
+      RegisterSym reg(SymbolRecordKind::RegisterSym);
+      cantFail(SymbolDeserializer::deserializeAs<RegisterSym>(sym, reg));
+      param_type = reg.Index;
+      param_name = reg.Name;
+      break;
+    }
+    case S_LOCAL: {
+      LocalSym local(SymbolRecordKind::LocalSym);
+      cantFail(SymbolDeserializer::deserializeAs<LocalSym>(sym, local));
+      if ((local.Flags & LocalSymFlags::IsParameter) == LocalSymFlags::None)
+        continue;
+      param_type = local.Type;
+      param_name = local.Name;
+      break;
+    }
+    case S_BLOCK32:
+      // All parameters should come before the first block.  If that isn't the
+      // case, then perhaps this is bad debug info that doesn't contain
+      // information about all parameters.
+      return;
+    default:
+      continue;
+    }
+
+    PdbCompilandSymId param_uid(func_id.modi, record_offset);
+    clang::QualType qt = GetOrCreateType(param_type);
+
+    CompilerType param_type_ct(&m_clang, qt.getAsOpaquePtr());
+    clang::ParmVarDecl *param = m_clang.CreateParameterDeclaration(
+        &function_decl, param_name.str().c_str(), param_type_ct,
+        clang::SC_None);
+    lldbassert(m_uid_to_decl.count(toOpaqueUid(param_uid)) == 0);
+
+    m_uid_to_decl[toOpaqueUid(param_uid)] = param;
+    params.push_back(param);
+    --param_count;
+  }
+
+  if (!params.empty())
+    m_clang.SetFunctionParameters(&function_decl, params.data(), params.size());
+}
+
+clang::QualType PdbAstBuilder::CreateEnumType(PdbTypeSymId id,
+                                              const EnumRecord &er) {
+  clang::DeclContext *decl_context = nullptr;
+  std::string uname;
+  std::tie(decl_context, uname) = CreateDeclInfoForType(er, id.index);
+  clang::QualType underlying_type = GetOrCreateType(er.UnderlyingType);
+
+  Declaration declaration;
+  CompilerType enum_ct = m_clang.CreateEnumerationType(
+      uname.c_str(), decl_context, declaration, ToCompilerType(underlying_type),
+      er.isScoped());
+
+  ClangASTContext::StartTagDeclarationDefinition(enum_ct);
+  ClangASTContext::SetHasExternalStorage(enum_ct.GetOpaqueQualType(), true);
+
+  return clang::QualType::getFromOpaquePtr(enum_ct.GetOpaqueQualType());
+}
+
+clang::QualType PdbAstBuilder::CreateArrayType(const ArrayRecord &ar) {
+  clang::QualType element_type = GetOrCreateType(ar.ElementType);
+
+  uint64_t element_count =
+      ar.Size / GetSizeOfType({ar.ElementType}, m_index.tpi());
+
+  CompilerType array_ct = m_clang.CreateArrayType(ToCompilerType(element_type),
+                                                  element_count, false);
+  return clang::QualType::getFromOpaquePtr(array_ct.GetOpaqueQualType());
+}
+
+clang::QualType
+PdbAstBuilder::CreateProcedureType(const ProcedureRecord &proc) {
+  TpiStream &stream = m_index.tpi();
+  CVType args_cvt = stream.getType(proc.ArgumentList);
+  ArgListRecord args;
+  llvm::cantFail(
+      TypeDeserializer::deserializeAs<ArgListRecord>(args_cvt, args));
+
+  llvm::ArrayRef<TypeIndex> arg_indices = llvm::makeArrayRef(args.ArgIndices);
+  bool is_variadic = IsCVarArgsFunction(arg_indices);
+  if (is_variadic)
+    arg_indices = arg_indices.drop_back();
+
+  std::vector<CompilerType> arg_types;
+  arg_types.reserve(arg_indices.size());
+
+  for (TypeIndex arg_index : arg_indices) {
+    clang::QualType arg_type = GetOrCreateType(arg_index);
+    arg_types.push_back(ToCompilerType(arg_type));
+  }
+
+  clang::QualType return_type = GetOrCreateType(proc.ReturnType);
+
+  llvm::Optional<clang::CallingConv> cc =
+      TranslateCallingConvention(proc.CallConv);
+  if (!cc)
+    return {};
+
+  CompilerType return_ct = ToCompilerType(return_type);
+  CompilerType func_sig_ast_type = m_clang.CreateFunctionType(
+      return_ct, arg_types.data(), arg_types.size(), is_variadic, 0, *cc);
+
+  return clang::QualType::getFromOpaquePtr(
+      func_sig_ast_type.GetOpaqueQualType());
+}
+
+CompilerDecl PdbAstBuilder::ToCompilerDecl(clang::Decl &decl) {
+  return {&m_clang, &decl};
+}
+
+CompilerType PdbAstBuilder::ToCompilerType(clang::QualType qt) {
+  return {&m_clang, qt.getAsOpaquePtr()};
+}
+
+CompilerDeclContext
+PdbAstBuilder::ToCompilerDeclContext(clang::DeclContext &context) {
+  return {&m_clang, &context};
+}
+
+void PdbAstBuilder::Dump(Stream &stream) { m_clang.Dump(stream); }

Added: lldb/trunk/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.h?rev=349383&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.h (added)
+++ lldb/trunk/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.h Mon Dec 17 11:43:33 2018
@@ -0,0 +1,129 @@
+//===-- PdbAstBuilder.h -----------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_PLUGINS_SYMBOLFILE_NATIVEPDB_PDBASTBUILDER_H
+#define LLDB_PLUGINS_SYMBOLFILE_NATIVEPDB_PDBASTBUILDER_H
+
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/StringRef.h"
+
+#include "lldb/Symbol/ClangASTImporter.h"
+
+#include "PdbIndex.h"
+#include "PdbSymUid.h"
+
+namespace clang {
+class TagDecl;
+class DeclContext;
+class Decl;
+class QualType;
+class FunctionDecl;
+class NamespaceDecl;
+} // namespace clang
+
+namespace llvm {
+namespace codeview {
+class ProcSym;
+}
+} // namespace llvm
+
+namespace lldb_private {
+class ClangASTImporter;
+class ObjectFile;
+
+namespace npdb {
+class PdbIndex;
+struct VariableInfo;
+
+struct DeclStatus {
+  DeclStatus() = default;
+  DeclStatus(lldb::user_id_t uid, bool resolved)
+      : uid(uid), resolved(resolved) {}
+  lldb::user_id_t uid = 0;
+  bool resolved = false;
+};
+
+class PdbAstBuilder {
+public:
+  //------------------------------------------------------------------
+  // Constructors and Destructors
+  //------------------------------------------------------------------
+  PdbAstBuilder(ObjectFile &obj, PdbIndex &index);
+
+  clang::DeclContext &GetTranslationUnitDecl();
+
+  clang::Decl *GetOrCreateDeclForUid(PdbSymUid uid);
+  clang::DeclContext *GetOrCreateDeclContextForUid(PdbSymUid uid);
+  clang::DeclContext *GetParentDeclContext(PdbSymUid uid);
+
+  clang::NamespaceDecl *GetOrCreateNamespaceDecl(llvm::StringRef name,
+                                                 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::QualType GetBasicType(lldb::BasicType type);
+  clang::QualType GetOrCreateType(PdbTypeSymId type);
+
+  bool CompleteTagDecl(clang::TagDecl &tag);
+  bool CompleteType(clang::QualType qt);
+
+  CompilerDecl ToCompilerDecl(clang::Decl &decl);
+  CompilerType ToCompilerType(clang::QualType qt);
+  CompilerDeclContext ToCompilerDeclContext(clang::DeclContext &context);
+
+  ClangASTContext &clang() { return m_clang; }
+  ClangASTImporter &importer() { return m_importer; }
+
+  void Dump(Stream &stream);
+
+private:
+  clang::Decl *TryGetDecl(PdbSymUid uid) const;
+
+  using TypeIndex = llvm::codeview::TypeIndex;
+
+  clang::QualType
+  CreatePointerType(const llvm::codeview::PointerRecord &pointer);
+  clang::QualType
+  CreateModifierType(const llvm::codeview::ModifierRecord &modifier);
+  clang::QualType CreateArrayType(const llvm::codeview::ArrayRecord &array);
+  clang::QualType CreateRecordType(PdbTypeSymId id,
+                                   const llvm::codeview::TagRecord &record);
+  clang::QualType CreateEnumType(PdbTypeSymId id,
+                                 const llvm::codeview::EnumRecord &record);
+  clang::QualType
+  CreateProcedureType(const llvm::codeview::ProcedureRecord &proc);
+  clang::QualType CreateType(PdbTypeSymId type);
+
+  void CreateFunctionParameters(PdbCompilandSymId func_id,
+                                clang::FunctionDecl &function_decl,
+                                uint32_t param_count);
+  clang::Decl *GetOrCreateSymbolForId(PdbCompilandSymId id);
+
+  void BuildParentMap();
+  std::pair<clang::DeclContext *, std::string>
+  CreateDeclInfoForType(const llvm::codeview::TagRecord &record, TypeIndex ti);
+  clang::QualType CreateSimpleType(TypeIndex ti);
+
+  PdbIndex &m_index;
+  ClangASTContext &m_clang;
+
+  ClangASTImporter m_importer;
+
+  llvm::DenseMap<TypeIndex, TypeIndex> m_parent_types;
+  llvm::DenseMap<clang::Decl *, DeclStatus> m_decl_to_status;
+  llvm::DenseMap<lldb::user_id_t, clang::Decl *> m_uid_to_decl;
+  llvm::DenseMap<lldb::user_id_t, clang::QualType> m_uid_to_type;
+};
+
+} // namespace npdb
+} // namespace lldb_private
+
+#endif // lldb_Plugins_SymbolFile_PDB_SymbolFilePDB_h_

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=349383&r1=349382&r2=349383&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/SymbolFile/NativePDB/PdbUtil.cpp (original)
+++ lldb/trunk/source/Plugins/SymbolFile/NativePDB/PdbUtil.cpp Mon Dec 17 11:43:33 2018
@@ -8,6 +8,9 @@
 //===----------------------------------------------------------------------===//
 
 #include "PdbUtil.h"
+
+#include "DWARFLocationExpression.h"
+#include "PdbIndex.h"
 #include "PdbSymUid.h"
 
 #include "llvm/DebugInfo/CodeView/SymbolDeserializer.h"
@@ -23,6 +26,27 @@ using namespace lldb_private::npdb;
 using namespace llvm::codeview;
 using namespace llvm::pdb;
 
+static Variable::RangeList
+MakeRangeList(const PdbIndex &index, const LocalVariableAddrRange &range,
+              llvm::ArrayRef<LocalVariableAddrGap> gaps) {
+  lldb::addr_t start =
+      index.MakeVirtualAddress(range.ISectStart, range.OffsetStart);
+  lldb::addr_t end = start + range.Range;
+
+  Variable::RangeList result;
+  while (!gaps.empty()) {
+    const LocalVariableAddrGap &gap = gaps.front();
+
+    lldb::addr_t size = gap.GapStartOffset - start;
+    result.Append(start, size);
+    start += gap.Range;
+    gaps = gaps.drop_front();
+  }
+
+  result.Append(start, end);
+  return result;
+}
+
 CVTagRecord CVTagRecord::create(CVType type) {
   assert(IsTagRecord(type) && "type is not a tag record!");
   switch (type.kind()) {
@@ -354,6 +378,17 @@ bool lldb_private::npdb::IsTagRecord(llv
   }
 }
 
+bool lldb_private::npdb::IsClassStructUnion(llvm::codeview::CVType cvt) {
+  switch (cvt.kind()) {
+  case LF_CLASS:
+  case LF_STRUCTURE:
+  case LF_UNION:
+    return true;
+  default:
+    return false;
+  }
+}
+
 bool lldb_private::npdb::IsForwardRefUdt(const PdbTypeSymId &id,
                                          TpiStream &tpi) {
   if (id.is_ipi || id.index.isSimple())
@@ -426,6 +461,90 @@ llvm::StringRef lldb_private::npdb::Drop
   return name.substr(offset + 2);
 }
 
+VariableInfo lldb_private::npdb::GetVariableNameInfo(CVSymbol sym) {
+  VariableInfo result;
+
+  if (sym.kind() == S_REGREL32) {
+    RegRelativeSym reg(SymbolRecordKind::RegRelativeSym);
+    cantFail(SymbolDeserializer::deserializeAs<RegRelativeSym>(sym, reg));
+    result.type = reg.Type;
+    result.name = reg.Name;
+    return result;
+  }
+
+  if (sym.kind() == S_REGISTER) {
+    RegisterSym reg(SymbolRecordKind::RegisterSym);
+    cantFail(SymbolDeserializer::deserializeAs<RegisterSym>(sym, reg));
+    result.type = reg.Index;
+    result.name = reg.Name;
+    return result;
+  }
+
+  if (sym.kind() == S_LOCAL) {
+    LocalSym local(SymbolRecordKind::LocalSym);
+    cantFail(SymbolDeserializer::deserializeAs<LocalSym>(sym, local));
+    result.type = local.Type;
+    result.name = local.Name;
+    return result;
+  }
+
+  lldbassert(false && "Invalid variable record kind!");
+  return {};
+}
+
+VariableInfo lldb_private::npdb::GetVariableLocationInfo(
+    PdbIndex &index, PdbCompilandSymId var_id, lldb::ModuleSP module) {
+
+  CVSymbol sym = index.ReadSymbolRecord(var_id);
+
+  VariableInfo result = GetVariableNameInfo(sym);
+
+  if (sym.kind() == S_REGREL32) {
+    RegRelativeSym reg(SymbolRecordKind::RegRelativeSym);
+    cantFail(SymbolDeserializer::deserializeAs<RegRelativeSym>(sym, reg));
+    result.location =
+        MakeRegRelLocationExpression(reg.Register, reg.Offset, module);
+    result.ranges.emplace();
+    return result;
+  }
+
+  if (sym.kind() == S_REGISTER) {
+    RegisterSym reg(SymbolRecordKind::RegisterSym);
+    cantFail(SymbolDeserializer::deserializeAs<RegisterSym>(sym, reg));
+    result.location = MakeEnregisteredLocationExpression(reg.Register, module);
+    result.ranges.emplace();
+    return result;
+  }
+
+  if (sym.kind() == S_LOCAL) {
+    LocalSym local(SymbolRecordKind::LocalSym);
+    cantFail(SymbolDeserializer::deserializeAs<LocalSym>(sym, local));
+
+    PdbCompilandSymId loc_specifier_id(var_id.modi,
+                                       var_id.offset + sym.RecordData.size());
+    CVSymbol loc_specifier_cvs = index.ReadSymbolRecord(loc_specifier_id);
+    if (loc_specifier_cvs.kind() == S_DEFRANGE_FRAMEPOINTER_REL) {
+      DefRangeFramePointerRelSym loc(
+          SymbolRecordKind::DefRangeFramePointerRelSym);
+      cantFail(SymbolDeserializer::deserializeAs<DefRangeFramePointerRelSym>(
+          loc_specifier_cvs, loc));
+      // FIXME: The register needs to come from the S_FRAMEPROC symbol.
+      result.location =
+          MakeRegRelLocationExpression(RegisterId::RSP, loc.Offset, module);
+      result.ranges = MakeRangeList(index, loc.Range, loc.Gaps);
+    } else {
+      // FIXME: Handle other kinds
+      llvm::APSInt value;
+      value = 42;
+      result.location = MakeConstantLocationExpression(
+          TypeIndex::Int32(), index.tpi(), value, module);
+    }
+    return result;
+  }
+  llvm_unreachable("Symbol is not a local variable!");
+  return result;
+}
+
 lldb::BasicType
 lldb_private::npdb::GetCompilerTypeForSimpleKind(SimpleTypeKind kind) {
   switch (kind) {
@@ -545,3 +664,72 @@ size_t lldb_private::npdb::GetTypeSizeFo
     return 0;
   }
 }
+
+PdbTypeSymId lldb_private::npdb::GetBestPossibleDecl(PdbTypeSymId id,
+                                                     TpiStream &tpi) {
+  if (id.index.isSimple())
+    return id;
+
+  CVType cvt = tpi.getType(id.index);
+
+  // Only tag records have a best and a worst record.
+  if (!IsTagRecord(cvt))
+    return id;
+
+  // Tag records that are not forward decls are full decls, hence they are the
+  // best.
+  if (!IsForwardRefUdt(cvt))
+    return id;
+
+  return llvm::cantFail(tpi.findFullDeclForForwardRef(id.index));
+}
+
+template <typename RecordType> static size_t GetSizeOfTypeInternal(CVType cvt) {
+  RecordType record;
+  llvm::cantFail(TypeDeserializer::deserializeAs<RecordType>(cvt, record));
+  return record.getSize();
+}
+
+size_t lldb_private::npdb::GetSizeOfType(PdbTypeSymId id,
+                                         llvm::pdb::TpiStream &tpi) {
+  if (id.index.isSimple()) {
+    switch (id.index.getSimpleMode()) {
+    case SimpleTypeMode::Direct:
+      return GetTypeSizeForSimpleKind(id.index.getSimpleKind());
+    case SimpleTypeMode::NearPointer32:
+    case SimpleTypeMode::FarPointer32:
+      return 4;
+    case SimpleTypeMode::NearPointer64:
+      return 8;
+    case SimpleTypeMode::NearPointer128:
+      return 16;
+    default:
+      break;
+    }
+    return 0;
+  }
+
+  CVType cvt = tpi.getType(id.index);
+  switch (cvt.kind()) {
+  case LF_MODIFIER:
+    return GetSizeOfType({LookThroughModifierRecord(cvt)}, tpi);
+  case LF_ENUM: {
+    EnumRecord record;
+    llvm::cantFail(TypeDeserializer::deserializeAs<EnumRecord>(cvt, record));
+    return GetSizeOfType({record.UnderlyingType}, tpi);
+  }
+  case LF_POINTER:
+    return GetSizeOfTypeInternal<PointerRecord>(cvt);
+  case LF_ARRAY:
+    return GetSizeOfTypeInternal<ArrayRecord>(cvt);
+  case LF_CLASS:
+  case LF_STRUCTURE:
+  case LF_INTERFACE:
+    return GetSizeOfTypeInternal<ClassRecord>(cvt);
+  case LF_UNION:
+    return GetSizeOfTypeInternal<UnionRecord>(cvt);
+  default:
+    break;
+  }
+  return 0;
+}

Modified: lldb/trunk/source/Plugins/SymbolFile/NativePDB/PdbUtil.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/NativePDB/PdbUtil.h?rev=349383&r1=349382&r2=349383&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/SymbolFile/NativePDB/PdbUtil.h (original)
+++ lldb/trunk/source/Plugins/SymbolFile/NativePDB/PdbUtil.h Mon Dec 17 11:43:33 2018
@@ -10,13 +10,18 @@
 #ifndef LLDB_PLUGINS_SYMBOLFILENATIVEPDB_PDBUTIL_H
 #define LLDB_PLUGINS_SYMBOLFILENATIVEPDB_PDBUTIL_H
 
+#include "lldb/Expression/DWARFExpression.h"
+#include "lldb/Symbol/Variable.h"
 #include "lldb/lldb-enumerations.h"
 
+#include "llvm/ADT/Optional.h"
 #include "llvm/DebugInfo/CodeView/CodeView.h"
 #include "llvm/DebugInfo/CodeView/SymbolRecord.h"
 #include "llvm/DebugInfo/CodeView/TypeRecord.h"
 #include "llvm/DebugInfo/PDB/PDBTypes.h"
 
+#include "PdbSymUid.h"
+
 #include <tuple>
 #include <utility>
 
@@ -29,7 +34,7 @@ class TpiStream;
 namespace lldb_private {
 namespace npdb {
 
-struct PdbTypeSymId;
+class PdbIndex;
 
 struct CVTagRecord {
   enum Kind { Class, Struct, Union, Enum };
@@ -88,6 +93,13 @@ struct SegmentOffsetLength {
   uint32_t length = 0;
 };
 
+struct VariableInfo {
+  llvm::StringRef name;
+  llvm::codeview::TypeIndex type;
+  llvm::Optional<DWARFExpression> location;
+  llvm::Optional<Variable::RangeList> ranges;
+};
+
 llvm::pdb::PDB_SymType CVSymToPDBSym(llvm::codeview::SymbolKind kind);
 llvm::pdb::PDB_SymType CVTypeToPDBType(llvm::codeview::TypeLeafKind kind);
 
@@ -109,6 +121,7 @@ inline bool IsValidRecord(const llvm::co
 
 bool IsForwardRefUdt(llvm::codeview::CVType cvt);
 bool IsTagRecord(llvm::codeview::CVType cvt);
+bool IsClassStructUnion(llvm::codeview::CVType cvt);
 
 bool IsForwardRefUdt(const PdbTypeSymId &id, llvm::pdb::TpiStream &tpi);
 bool IsTagRecord(const PdbTypeSymId &id, llvm::pdb::TpiStream &tpi);
@@ -120,10 +133,18 @@ LookThroughModifierRecord(llvm::codeview
 
 llvm::StringRef DropNameScope(llvm::StringRef name);
 
+VariableInfo GetVariableNameInfo(llvm::codeview::CVSymbol symbol);
+VariableInfo GetVariableLocationInfo(PdbIndex &index, PdbCompilandSymId var_id,
+                                     lldb::ModuleSP module);
+
 size_t GetTypeSizeForSimpleKind(llvm::codeview::SimpleTypeKind kind);
 lldb::BasicType
 GetCompilerTypeForSimpleKind(llvm::codeview::SimpleTypeKind kind);
 
+PdbTypeSymId GetBestPossibleDecl(PdbTypeSymId id, llvm::pdb::TpiStream &tpi);
+
+size_t GetSizeOfType(PdbTypeSymId id, llvm::pdb::TpiStream &tpi);
+
 } // namespace npdb
 } // namespace lldb_private
 

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=349383&r1=349382&r2=349383&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp (original)
+++ lldb/trunk/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp Mon Dec 17 11:43:33 2018
@@ -56,6 +56,7 @@
 #include "llvm/Support/MemoryBuffer.h"
 
 #include "DWARFLocationExpression.h"
+#include "PdbAstBuilder.h"
 #include "PdbSymUid.h"
 #include "PdbUtil.h"
 #include "UdtRecordCompleter.h"
@@ -66,15 +67,6 @@ using namespace npdb;
 using namespace llvm::codeview;
 using namespace llvm::pdb;
 
-namespace {
-struct VariableInfo {
-  llvm::StringRef name;
-  TypeIndex type;
-  llvm::Optional<DWARFExpression> location;
-  llvm::Optional<Variable::RangeList> ranges;
-};
-} // namespace
-
 static lldb::LanguageType TranslateLanguage(PDB_Lang lang) {
   switch (lang) {
   case PDB_Lang::Cpp:
@@ -171,30 +163,6 @@ static bool IsFunctionEpilogue(const Com
   return false;
 }
 
-static clang::MSInheritanceAttr::Spelling
-GetMSInheritance(LazyRandomTypeCollection &tpi, const ClassRecord &record) {
-  if (record.DerivationList == TypeIndex::None())
-    return clang::MSInheritanceAttr::Spelling::Keyword_single_inheritance;
-
-  CVType bases = tpi.getType(record.DerivationList);
-  ArgListRecord base_list;
-  cantFail(TypeDeserializer::deserializeAs<ArgListRecord>(bases, base_list));
-  if (base_list.ArgIndices.empty())
-    return clang::MSInheritanceAttr::Spelling::Keyword_single_inheritance;
-
-  int base_count = 0;
-  for (TypeIndex ti : base_list.ArgIndices) {
-    CVType base = tpi.getType(ti);
-    if (base.kind() == LF_VBCLASS || base.kind() == LF_IVBCLASS)
-      return clang::MSInheritanceAttr::Spelling::Keyword_virtual_inheritance;
-    ++base_count;
-  }
-
-  if (base_count > 1)
-    return clang::MSInheritanceAttr::Keyword_multiple_inheritance;
-  return clang::MSInheritanceAttr::Keyword_single_inheritance;
-}
-
 static llvm::StringRef GetSimpleTypeName(SimpleTypeKind kind) {
   switch (kind) {
   case SimpleTypeKind::Boolean128:
@@ -273,144 +241,6 @@ static bool IsClassRecord(TypeLeafKind k
   }
 }
 
-static bool IsCVarArgsFunction(llvm::ArrayRef<TypeIndex> args) {
-  if (args.empty())
-    return false;
-  return args.back() == TypeIndex::None();
-}
-
-static clang::TagTypeKind TranslateUdtKind(const TagRecord &cr) {
-  switch (cr.Kind) {
-  case TypeRecordKind::Class:
-    return clang::TTK_Class;
-  case TypeRecordKind::Struct:
-    return clang::TTK_Struct;
-  case TypeRecordKind::Union:
-    return clang::TTK_Union;
-  case TypeRecordKind::Interface:
-    return clang::TTK_Interface;
-  case TypeRecordKind::Enum:
-    return clang::TTK_Enum;
-  default:
-    lldbassert(false && "Invalid tag record kind!");
-    return clang::TTK_Struct;
-  }
-}
-
-static llvm::Optional<clang::CallingConv>
-TranslateCallingConvention(llvm::codeview::CallingConvention conv) {
-  using CC = llvm::codeview::CallingConvention;
-  switch (conv) {
-
-  case CC::NearC:
-  case CC::FarC:
-    return clang::CallingConv::CC_C;
-  case CC::NearPascal:
-  case CC::FarPascal:
-    return clang::CallingConv::CC_X86Pascal;
-  case CC::NearFast:
-  case CC::FarFast:
-    return clang::CallingConv::CC_X86FastCall;
-  case CC::NearStdCall:
-  case CC::FarStdCall:
-    return clang::CallingConv::CC_X86StdCall;
-  case CC::ThisCall:
-    return clang::CallingConv::CC_X86ThisCall;
-  case CC::NearVector:
-    return clang::CallingConv::CC_X86VectorCall;
-  default:
-    return llvm::None;
-  }
-}
-
-static Variable::RangeList
-MakeRangeList(const PdbIndex &index, const LocalVariableAddrRange &range,
-              llvm::ArrayRef<LocalVariableAddrGap> gaps) {
-  lldb::addr_t start =
-      index.MakeVirtualAddress(range.ISectStart, range.OffsetStart);
-  lldb::addr_t end = start + range.Range;
-
-  Variable::RangeList result;
-  while (!gaps.empty()) {
-    const LocalVariableAddrGap &gap = gaps.front();
-
-    lldb::addr_t size = gap.GapStartOffset - start;
-    result.Append(start, size);
-    start += gap.Range;
-    gaps = gaps.drop_front();
-  }
-
-  result.Append(start, end);
-  return result;
-}
-
-static VariableInfo GetVariableInformation(PdbIndex &index,
-                                           PdbCompilandSymId var_id,
-                                           ModuleSP module,
-                                           bool get_location_info) {
-  VariableInfo result;
-  CVSymbol sym = index.ReadSymbolRecord(var_id);
-
-  if (sym.kind() == S_REGREL32) {
-    RegRelativeSym reg(SymbolRecordKind::RegRelativeSym);
-    cantFail(SymbolDeserializer::deserializeAs<RegRelativeSym>(sym, reg));
-    result.type = reg.Type;
-    result.name = reg.Name;
-    if (get_location_info) {
-      result.location =
-          MakeRegRelLocationExpression(reg.Register, reg.Offset, module);
-      result.ranges.emplace();
-    }
-    return result;
-  }
-
-  if (sym.kind() == S_REGISTER) {
-    RegisterSym reg(SymbolRecordKind::RegisterSym);
-    cantFail(SymbolDeserializer::deserializeAs<RegisterSym>(sym, reg));
-    result.type = reg.Index;
-    result.name = reg.Name;
-    if (get_location_info) {
-      result.location =
-          MakeEnregisteredLocationExpression(reg.Register, module);
-      result.ranges.emplace();
-    }
-    return result;
-  }
-
-  if (sym.kind() == S_LOCAL) {
-    LocalSym local(SymbolRecordKind::LocalSym);
-    cantFail(SymbolDeserializer::deserializeAs<LocalSym>(sym, local));
-    result.type = local.Type;
-    result.name = local.Name;
-
-    if (!get_location_info)
-      return result;
-
-    PdbCompilandSymId loc_specifier_id(var_id.modi,
-                                       var_id.offset + sym.RecordData.size());
-    CVSymbol loc_specifier_cvs = index.ReadSymbolRecord(loc_specifier_id);
-    if (loc_specifier_cvs.kind() == S_DEFRANGE_FRAMEPOINTER_REL) {
-      DefRangeFramePointerRelSym loc(
-          SymbolRecordKind::DefRangeFramePointerRelSym);
-      cantFail(SymbolDeserializer::deserializeAs<DefRangeFramePointerRelSym>(
-          loc_specifier_cvs, loc));
-      // FIXME: The register needs to come from the S_FRAMEPROC symbol.
-      result.location =
-          MakeRegRelLocationExpression(RegisterId::RSP, loc.Offset, module);
-      result.ranges = MakeRangeList(index, loc.Range, loc.Gaps);
-    } else {
-      // FIXME: Handle other kinds
-      llvm::APSInt value;
-      value = 42;
-      result.location = MakeConstantLocationExpression(
-          TypeIndex::Int32(), index.tpi(), value, module);
-    }
-    return result;
-  }
-  llvm_unreachable("Symbol is not a local variable!");
-  return result;
-}
-
 void SymbolFileNativePDB::Initialize() {
   PluginManager::RegisterPlugin(GetPluginNameStatic(),
                                 GetPluginDescriptionStatic(), CreateInstance,
@@ -489,117 +319,12 @@ void SymbolFileNativePDB::InitializeObje
   m_index->SetLoadAddress(m_obj_load_address);
   m_index->ParseSectionContribs();
 
-  TypeSystem *ts = GetTypeSystemForLanguage(eLanguageTypeC_plus_plus);
-  m_clang = llvm::dyn_cast_or_null<ClangASTContext>(ts);
-  m_importer = llvm::make_unique<ClangASTImporter>();
-
-  PreprocessTpiStream();
-  lldbassert(m_clang);
-}
-
-static llvm::Optional<CVTagRecord>
-GetNestedTagRecord(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:
-  // struct A {
-  //   struct B {};
-  //   using C = B;
-  // };
-  // Then in the debug info, this will appear as:
-  // LF_STRUCTURE `A::B` [type index = N]
-  // LF_STRUCTURE `A`
-  //   LF_NESTTYPE [name = `B`, index = N]
-  //   LF_NESTTYPE [name = `C`, index = N]
-  // In order to accurately reconstruct the decl context hierarchy, we need to
-  // know which ones are actual definitions and which ones are just aliases.
-
-  // If it's a simple type, then this is something like `using foo = int`.
-  if (Record.Type.isSimple())
-    return llvm::None;
-
-  CVType cvt = tpi.getType(Record.Type);
-
-  if (!IsTagRecord(cvt))
-    return llvm::None;
-
-  // If it's an inner definition, then treat whatever name we have here as a
-  // single component of a mangled name.  So we can inject it into the parent's
-  // mangled name to see if it matches.
-  CVTagRecord child = CVTagRecord::create(cvt);
-  std::string qname = parent.asTag().getUniqueName();
-  if (qname.size() < 4 || child.asTag().getUniqueName().size() < 4)
-    return llvm::None;
-
-  // qname[3] is the tag type identifier (struct, class, union, etc).  Since the
-  // inner tag type is not necessarily the same as the outer tag type, re-write
-  // it to match the inner tag type.
-  qname[3] = child.asTag().getUniqueName()[3];
-  std::string piece = Record.Name;
-  piece.push_back('@');
-  qname.insert(4, std::move(piece));
-  if (qname != child.asTag().UniqueName)
-    return llvm::None;
-
-  return std::move(child);
-}
-
-void SymbolFileNativePDB::PreprocessTpiStream() {
-  LazyRandomTypeCollection &types = m_index->tpi().typeCollection();
-
-  for (auto ti = types.getFirst(); ti; ti = types.getNext(*ti)) {
-    CVType type = types.getType(*ti);
-    if (!IsTagRecord(type))
-      continue;
-
-    CVTagRecord tag = CVTagRecord::create(type);
-    // 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).
-    if (tag.asTag().isForwardRef() || !tag.asTag().containsNestedClass())
-      continue;
-
-    struct ProcessTpiStream : public TypeVisitorCallbacks {
-      ProcessTpiStream(PdbIndex &index, TypeIndex parent,
-                       const CVTagRecord &parent_cvt,
-                       llvm::DenseMap<TypeIndex, TypeIndex> &parents)
-          : index(index), parents(parents), parent(parent),
-            parent_cvt(parent_cvt) {}
-
-      PdbIndex &index;
-      llvm::DenseMap<TypeIndex, TypeIndex> &parents;
-      TypeIndex parent;
-      const CVTagRecord &parent_cvt;
-
-      llvm::Error visitKnownMember(CVMemberRecord &CVR,
-                                   NestedTypeRecord &Record) override {
-        llvm::Optional<CVTagRecord> tag =
-            GetNestedTagRecord(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();
-      }
-    };
+  TypeSystem *ts = m_obj_file->GetModule()->GetTypeSystemForLanguage(
+      lldb::eLanguageTypeC_plus_plus);
+  if (ts)
+    ts->SetSymbolFile(this);
 
-    CVType field_list = m_index->tpi().getType(tag.asTag().FieldList);
-    ProcessTpiStream process(*m_index, *ti, tag, m_parent_types);
-    llvm::Error error = visitMemberRecordStream(field_list.data(), process);
-    if (error)
-      llvm::consumeError(std::move(error));
-  }
+  m_ast = llvm::make_unique<PdbAstBuilder>(*m_obj_file, *m_index);
 }
 
 uint32_t SymbolFileNativePDB::GetNumCompileUnits() {
@@ -620,7 +345,6 @@ uint32_t SymbolFileNativePDB::GetNumComp
 Block &SymbolFileNativePDB::CreateBlock(PdbCompilandSymId block_id) {
   CompilandIndexItem *cii = m_index->compilands().GetCompiland(block_id.modi);
   CVSymbol sym = cii->m_debug_stream.readSymbolAtOffset(block_id.offset);
-  clang::DeclContext *parent_decl_ctx = m_clang->GetTranslationUnitDecl();
 
   if (sym.kind() == S_GPROC32 || sym.kind() == S_LPROC32) {
     // This is a function.  It must be global.  Creating the Function entry for
@@ -639,18 +363,13 @@ Block &SymbolFileNativePDB::CreateBlock(
   lldbassert(block.Parent != 0);
   PdbCompilandSymId parent_id(block_id.modi, block.Parent);
   Block &parent_block = GetOrCreateBlock(parent_id);
-
   lldb::user_id_t opaque_block_uid = toOpaqueUid(block_id);
   BlockSP child_block = std::make_shared<Block>(opaque_block_uid);
   parent_block.AddChild(child_block);
-  CompilerDeclContext cdc = GetDeclContextForUID(parent_block.GetID());
-  parent_decl_ctx =
-      static_cast<clang::DeclContext *>(cdc.GetOpaqueDeclContext());
-  clang::BlockDecl *block_decl =
-      m_clang->CreateBlockDeclaration(parent_decl_ctx);
+
+  m_ast->GetOrCreateBlockDecl(block_id);
 
   m_blocks.insert({opaque_block_uid, child_block});
-  m_uid_to_decl.insert({opaque_block_uid, block_decl});
   return *child_block;
 }
 
@@ -685,73 +404,7 @@ lldb::FunctionSP SymbolFileNativePDB::Cr
 
   comp_unit.AddFunction(func_sp);
 
-  user_id_t opaque_func_uid = toOpaqueUid(func_id);
-
-  clang::StorageClass storage = clang::SC_None;
-  if (sym_record.kind() == S_LPROC32)
-    storage = clang::SC_Static;
-
-  // The function signature only tells us the number of types of arguments, but
-  // not the names.  So we need to iterate the symbol stream looking for the
-  // corresponding symbol records to properly construct the AST.
-  CVType sig_cvt;
-  ProcedureRecord sig_record;
-
-  sig_cvt = m_index->tpi().getType(proc.FunctionType);
-  if (sig_cvt.kind() != LF_PROCEDURE)
-    return func_sp;
-  cantFail(
-      TypeDeserializer::deserializeAs<ProcedureRecord>(sig_cvt, sig_record));
-
-  CompilerDeclContext context = GetDeclContextContainingUID(opaque_func_uid);
-
-  clang::DeclContext *decl_context =
-      static_cast<clang::DeclContext *>(context.GetOpaqueDeclContext());
-  clang::FunctionDecl *function_decl = m_clang->CreateFunctionDeclaration(
-      decl_context, proc.Name.str().c_str(),
-      func_type->GetForwardCompilerType(), storage, false);
-
-  lldbassert(m_uid_to_decl.count(opaque_func_uid) == 0);
-  m_uid_to_decl[opaque_func_uid] = function_decl;
-
-  CVSymbolArray scope = limitSymbolArrayToScope(
-      cci->m_debug_stream.getSymbolArray(), func_id.offset);
-
-  uint32_t params_remaining = sig_record.getParameterCount();
-  auto begin = scope.begin();
-  auto end = scope.end();
-  std::vector<clang::ParmVarDecl *> params;
-  while (begin != end && params_remaining > 0) {
-    CVSymbol sym = *begin;
-    switch (sym.kind()) {
-    case S_REGREL32:
-    case S_REGISTER:
-    case S_LOCAL:
-      break;
-    case S_BLOCK32:
-      params_remaining = 0;
-      continue;
-    default:
-      ++begin;
-      continue;
-    }
-    PdbCompilandSymId param_uid(func_id.modi, begin.offset());
-    VariableInfo var_info = GetVariableInformation(
-        *m_index, param_uid, GetObjectFile()->GetModule(), false);
-
-    TypeSP type_sp = GetOrCreateType(var_info.type);
-    clang::ParmVarDecl *param = m_clang->CreateParameterDeclaration(
-        function_decl, var_info.name.str().c_str(),
-        type_sp->GetForwardCompilerType(), clang::SC_None);
-    lldbassert(m_uid_to_decl.count(toOpaqueUid(param_uid)) == 0);
-
-    m_uid_to_decl[toOpaqueUid(param_uid)] = param;
-    params.push_back(param);
-    --params_remaining;
-    ++begin;
-  }
-  if (!params.empty())
-    m_clang->SetFunctionParameters(function_decl, params.data(), params.size());
+  m_ast->GetOrCreateFunctionDecl(func_id);
 
   return func_sp;
 }
@@ -780,76 +433,48 @@ SymbolFileNativePDB::CreateCompileUnit(c
 }
 
 lldb::TypeSP SymbolFileNativePDB::CreateModifierType(PdbTypeSymId type_id,
-                                                     const ModifierRecord &mr) {
+                                                     const ModifierRecord &mr,
+                                                     CompilerType ct) {
   TpiStream &stream = m_index->tpi();
 
-  TypeSP t = GetOrCreateType(mr.ModifiedType);
-  CompilerType ct = t->GetForwardCompilerType();
-  if ((mr.Modifiers & ModifierOptions::Const) != ModifierOptions::None)
-    ct = ct.AddConstModifier();
-  if ((mr.Modifiers & ModifierOptions::Volatile) != ModifierOptions::None)
-    ct = ct.AddVolatileModifier();
   std::string name;
   if (mr.ModifiedType.isSimple())
     name = GetSimpleTypeName(mr.ModifiedType.getSimpleKind());
   else
     name = computeTypeName(stream.typeCollection(), mr.ModifiedType);
   Declaration decl;
-  return std::make_shared<Type>(toOpaqueUid(type_id), m_clang->GetSymbolFile(),
-                                ConstString(name), t->GetByteSize(), nullptr,
+  lldb::TypeSP modified_type = GetOrCreateType(mr.ModifiedType);
+
+  return std::make_shared<Type>(toOpaqueUid(type_id), this, ConstString(name),
+                                modified_type->GetByteSize(), nullptr,
                                 LLDB_INVALID_UID, Type::eEncodingIsUID, decl,
                                 ct, Type::eResolveStateFull);
 }
 
-lldb::TypeSP SymbolFileNativePDB::CreatePointerType(
-    PdbTypeSymId type_id, const llvm::codeview::PointerRecord &pr) {
+lldb::TypeSP
+SymbolFileNativePDB::CreatePointerType(PdbTypeSymId type_id,
+                                       const llvm::codeview::PointerRecord &pr,
+                                       CompilerType ct) {
   TypeSP pointee = GetOrCreateType(pr.ReferentType);
   if (!pointee)
     return nullptr;
-  CompilerType pointee_ct = pointee->GetForwardCompilerType();
-  lldbassert(pointee_ct);
-  Declaration decl;
 
   if (pr.isPointerToMember()) {
     MemberPointerInfo mpi = pr.getMemberInfo();
-    TypeSP class_type = GetOrCreateType(mpi.ContainingType);
-
-    CompilerType ct = ClangASTContext::CreateMemberPointerType(
-        class_type->GetLayoutCompilerType(), pointee_ct);
-
-    return std::make_shared<Type>(
-        toOpaqueUid(type_id), m_clang->GetSymbolFile(), ConstString(),
-        pr.getSize(), nullptr, LLDB_INVALID_UID, Type::eEncodingIsUID, decl, ct,
-        Type::eResolveStateFull);
+    GetOrCreateType(mpi.ContainingType);
   }
 
-  CompilerType pointer_ct = pointee_ct;
-  if (pr.getMode() == PointerMode::LValueReference)
-    pointer_ct = pointer_ct.GetLValueReferenceType();
-  else if (pr.getMode() == PointerMode::RValueReference)
-    pointer_ct = pointer_ct.GetRValueReferenceType();
-  else
-    pointer_ct = pointer_ct.GetPointerType();
-
-  if ((pr.getOptions() & PointerOptions::Const) != PointerOptions::None)
-    pointer_ct = pointer_ct.AddConstModifier();
-
-  if ((pr.getOptions() & PointerOptions::Volatile) != PointerOptions::None)
-    pointer_ct = pointer_ct.AddVolatileModifier();
-
-  if ((pr.getOptions() & PointerOptions::Restrict) != PointerOptions::None)
-    pointer_ct = pointer_ct.AddRestrictModifier();
-
-  return std::make_shared<Type>(toOpaqueUid(type_id), m_clang->GetSymbolFile(),
-                                ConstString(), pr.getSize(), nullptr,
-                                LLDB_INVALID_UID, Type::eEncodingIsUID, decl,
-                                pointer_ct, Type::eResolveStateFull);
+  Declaration decl;
+  return std::make_shared<Type>(toOpaqueUid(type_id), this, ConstString(),
+                                pr.getSize(), nullptr, LLDB_INVALID_UID,
+                                Type::eEncodingIsUID, decl, ct,
+                                Type::eResolveStateFull);
 }
 
-lldb::TypeSP SymbolFileNativePDB::CreateSimpleType(TypeIndex ti) {
+lldb::TypeSP SymbolFileNativePDB::CreateSimpleType(TypeIndex ti,
+                                                   CompilerType ct) {
   uint64_t uid = toOpaqueUid(PdbTypeSymId(ti, false));
   if (ti == TypeIndex::NullptrT()) {
-    CompilerType ct = m_clang->GetBasicType(eBasicTypeNullPtr);
     Declaration decl;
     return std::make_shared<Type>(
         uid, this, ConstString("std::nullptr_t"), 0, nullptr, LLDB_INVALID_UID,
@@ -858,8 +483,6 @@ lldb::TypeSP SymbolFileNativePDB::Create
 
   if (ti.getSimpleMode() != SimpleTypeMode::Direct) {
     TypeSP direct_sp = GetOrCreateType(ti.makeDirect());
-    CompilerType ct = direct_sp->GetFullCompilerType();
-    ct = ct.GetPointerType();
     uint32_t pointer_size = 0;
     switch (ti.getSimpleMode()) {
     case SimpleTypeMode::FarPointer32:
@@ -874,253 +497,101 @@ lldb::TypeSP SymbolFileNativePDB::Create
       return nullptr;
     }
     Declaration decl;
-    return std::make_shared<Type>(uid, m_clang->GetSymbolFile(), ConstString(),
-                                  pointer_size, nullptr, LLDB_INVALID_UID,
-                                  Type::eEncodingIsUID, decl, ct,
-                                  Type::eResolveStateFull);
+    return std::make_shared<Type>(
+        uid, this, ConstString(), pointer_size, nullptr, LLDB_INVALID_UID,
+        Type::eEncodingIsUID, decl, ct, Type::eResolveStateFull);
   }
 
   if (ti.getSimpleKind() == SimpleTypeKind::NotTranslated)
     return nullptr;
 
-  lldb::BasicType bt = GetCompilerTypeForSimpleKind(ti.getSimpleKind());
-  if (bt == lldb::eBasicTypeInvalid)
-    return nullptr;
-  CompilerType ct = m_clang->GetBasicType(bt);
   size_t size = GetTypeSizeForSimpleKind(ti.getSimpleKind());
-
   llvm::StringRef type_name = GetSimpleTypeName(ti.getSimpleKind());
 
   Declaration decl;
-  return std::make_shared<Type>(uid, m_clang->GetSymbolFile(),
-                                ConstString(type_name), size, nullptr,
-                                LLDB_INVALID_UID, Type::eEncodingIsUID, decl,
-                                ct, Type::eResolveStateFull);
-}
-
-static std::string RenderDemanglerNode(llvm::ms_demangle::Node *n) {
-  OutputStream OS;
-  initializeOutputStream(nullptr, nullptr, OS, 1024);
-  n->output(OS, llvm::ms_demangle::OF_Default);
-  OS << '\0';
-  return {OS.getBuffer()};
-}
-
-static bool
-AnyScopesHaveTemplateParams(llvm::ArrayRef<llvm::ms_demangle::Node *> scopes) {
-  for (llvm::ms_demangle::Node *n : scopes) {
-    auto *idn = static_cast<llvm::ms_demangle::IdentifierNode *>(n);
-    if (idn->TemplateParams)
-      return true;
-  }
-  return false;
+  return std::make_shared<Type>(uid, this, ConstString(type_name), size,
+                                nullptr, LLDB_INVALID_UID, Type::eEncodingIsUID,
+                                decl, ct, Type::eResolveStateFull);
 }
 
-std::pair<clang::DeclContext *, std::string>
-SymbolFileNativePDB::CreateDeclInfoForType(const TagRecord &record,
-                                           TypeIndex ti) {
-  // FIXME: Move this to GetDeclContextContainingUID.
-
+static std::string GetUnqualifiedTypeName(const TagRecord &record) {
   llvm::ms_demangle::Demangler demangler;
   StringView sv(record.UniqueName.begin(), record.UniqueName.size());
   llvm::ms_demangle::TagTypeNode *ttn = demangler.parseTagUniqueName(sv);
   llvm::ms_demangle::IdentifierNode *idn =
       ttn->QualifiedName->getUnqualifiedIdentifier();
-  std::string uname = RenderDemanglerNode(idn);
-
-  llvm::ms_demangle::NodeArrayNode *name_components =
-      ttn->QualifiedName->Components;
-  llvm::ArrayRef<llvm::ms_demangle::Node *> scopes(name_components->Nodes,
-                                                   name_components->Count - 1);
-
-  clang::DeclContext *context = m_clang->GetTranslationUnitDecl();
-
-  // If this type doesn't have a parent type in the debug info, then the best we
-  // can do is to say that it's either a series of namespaces (if the scope is
-  // non-empty), or the translation unit (if the scope is empty).
-  auto parent_iter = m_parent_types.find(ti);
-  if (parent_iter == m_parent_types.end()) {
-    if (scopes.empty())
-      return {context, uname};
-
-    // If there is no parent in the debug info, but some of the scopes have
-    // template params, then this is a case of bad debug info.  See, for
-    // example, llvm.org/pr39607.  We don't want to create an ambiguity between
-    // a NamespaceDecl and a CXXRecordDecl, so instead we create a class at
-    // global scope with the fully qualified name.
-    if (AnyScopesHaveTemplateParams(scopes))
-      return {context, record.Name};
-
-    for (llvm::ms_demangle::Node *scope : scopes) {
-      auto *nii = static_cast<llvm::ms_demangle::NamedIdentifierNode *>(scope);
-      std::string str = RenderDemanglerNode(nii);
-      context = m_clang->GetUniqueNamespaceDeclaration(str.c_str(), context);
-    }
-    return {context, uname};
-  }
-
-  // Otherwise, all we need to do is get the parent type of this type and
-  // recurse into our lazy type creation / AST reconstruction logic to get an
-  // LLDB TypeSP for the parent.  This will cause the AST to automatically get
-  // the right DeclContext created for any parent.
-  TypeSP parent = GetOrCreateType(parent_iter->second);
-  if (!parent)
-    return {context, uname};
-  CompilerType parent_ct = parent->GetForwardCompilerType();
-  clang::QualType qt = ClangUtil::GetCanonicalQualType(parent_ct);
-  context = clang::TagDecl::castToDeclContext(qt->getAsTagDecl());
-  return {context, uname};
+  return idn->toString();
 }
 
-lldb::TypeSP SymbolFileNativePDB::CreateClassStructUnion(
-    PdbTypeSymId type_id, const llvm::codeview::TagRecord &record, size_t size,
-    clang::TagTypeKind ttk, clang::MSInheritanceAttr::Spelling inheritance) {
+lldb::TypeSP
+SymbolFileNativePDB::CreateClassStructUnion(PdbTypeSymId type_id,
+                                            const TagRecord &record,
+                                            size_t size, CompilerType ct) {
 
-  clang::DeclContext *decl_context = nullptr;
-  std::string uname;
-  std::tie(decl_context, uname) = CreateDeclInfoForType(record, type_id.index);
-
-  lldb::AccessType access =
-      (ttk == clang::TTK_Class) ? lldb::eAccessPrivate : lldb::eAccessPublic;
-
-  ClangASTMetadata metadata;
-  metadata.SetUserID(toOpaqueUid(type_id));
-  metadata.SetIsDynamicCXXType(false);
-
-  CompilerType ct =
-      m_clang->CreateRecordType(decl_context, access, uname.c_str(), ttk,
-                                lldb::eLanguageTypeC_plus_plus, &metadata);
-
-  lldbassert(ct.IsValid());
-
-  clang::CXXRecordDecl *record_decl =
-      m_clang->GetAsCXXRecordDecl(ct.GetOpaqueQualType());
-  lldbassert(record_decl);
-
-  clang::MSInheritanceAttr *attr = clang::MSInheritanceAttr::CreateImplicit(
-      *m_clang->getASTContext(), inheritance);
-  record_decl->addAttr(attr);
-
-  ClangASTContext::StartTagDeclarationDefinition(ct);
-
-  // Even if it's possible, don't complete it at this point. Just mark it
-  // forward resolved, and if/when LLDB needs the full definition, it can
-  // ask us.
-  ClangASTContext::SetHasExternalStorage(ct.GetOpaqueQualType(), true);
+  std::string uname = GetUnqualifiedTypeName(record);
 
   // FIXME: Search IPI stream for LF_UDT_MOD_SRC_LINE.
   Declaration decl;
-  return std::make_shared<Type>(toOpaqueUid(type_id), m_clang->GetSymbolFile(),
-                                ConstString(uname), size, nullptr,
-                                LLDB_INVALID_UID, Type::eEncodingIsUID, decl,
-                                ct, Type::eResolveStateForward);
+  return std::make_shared<Type>(toOpaqueUid(type_id), this, ConstString(uname),
+                                size, nullptr, LLDB_INVALID_UID,
+                                Type::eEncodingIsUID, decl, ct,
+                                Type::eResolveStateForward);
 }
 
 lldb::TypeSP SymbolFileNativePDB::CreateTagType(PdbTypeSymId type_id,
-                                                const ClassRecord &cr) {
-  clang::TagTypeKind ttk = TranslateUdtKind(cr);
-
-  clang::MSInheritanceAttr::Spelling inheritance =
-      GetMSInheritance(m_index->tpi().typeCollection(), cr);
-  return CreateClassStructUnion(type_id, cr, cr.getSize(), ttk, inheritance);
+                                                const ClassRecord &cr,
+                                                CompilerType ct) {
+  return CreateClassStructUnion(type_id, cr, cr.getSize(), ct);
 }
 
 lldb::TypeSP SymbolFileNativePDB::CreateTagType(PdbTypeSymId type_id,
-                                                const UnionRecord &ur) {
-  return CreateClassStructUnion(
-      type_id, ur, ur.getSize(), clang::TTK_Union,
-      clang::MSInheritanceAttr::Spelling::Keyword_single_inheritance);
+                                                const UnionRecord &ur,
+                                                CompilerType ct) {
+  return CreateClassStructUnion(type_id, ur, ur.getSize(), ct);
 }
 
 lldb::TypeSP SymbolFileNativePDB::CreateTagType(PdbTypeSymId type_id,
-                                                const EnumRecord &er) {
-  clang::DeclContext *decl_context = nullptr;
-  std::string uname;
-  std::tie(decl_context, uname) = CreateDeclInfoForType(er, type_id.index);
+                                                const EnumRecord &er,
+                                                CompilerType ct) {
+  std::string uname = GetUnqualifiedTypeName(er);
 
   Declaration decl;
   TypeSP underlying_type = GetOrCreateType(er.UnderlyingType);
-  CompilerType enum_ct = m_clang->CreateEnumerationType(
-      uname.c_str(), decl_context, decl, underlying_type->GetFullCompilerType(),
-      er.isScoped());
 
-  ClangASTContext::StartTagDeclarationDefinition(enum_ct);
-  ClangASTContext::SetHasExternalStorage(enum_ct.GetOpaqueQualType(), true);
-
-  // We're just going to forward resolve this for now.  We'll complete
-  // it only if the user requests.
   return std::make_shared<lldb_private::Type>(
-      toOpaqueUid(type_id), m_clang->GetSymbolFile(), ConstString(uname),
+      toOpaqueUid(type_id), this, ConstString(uname),
       underlying_type->GetByteSize(), nullptr, LLDB_INVALID_UID,
-      lldb_private::Type::eEncodingIsUID, decl, enum_ct,
+      lldb_private::Type::eEncodingIsUID, decl, ct,
       lldb_private::Type::eResolveStateForward);
 }
 
 TypeSP SymbolFileNativePDB::CreateArrayType(PdbTypeSymId type_id,
-                                            const ArrayRecord &ar) {
+                                            const ArrayRecord &ar,
+                                            CompilerType ct) {
   TypeSP element_type = GetOrCreateType(ar.ElementType);
-  uint64_t element_count = ar.Size / element_type->GetByteSize();
-
-  CompilerType element_ct = element_type->GetFullCompilerType();
-
-  CompilerType array_ct =
-      m_clang->CreateArrayType(element_ct, element_count, false);
 
   Declaration decl;
   TypeSP array_sp = std::make_shared<lldb_private::Type>(
-      toOpaqueUid(type_id), m_clang->GetSymbolFile(), ConstString(), ar.Size,
-      nullptr, LLDB_INVALID_UID, lldb_private::Type::eEncodingIsUID, decl,
-      array_ct, lldb_private::Type::eResolveStateFull);
+      toOpaqueUid(type_id), this, ConstString(), ar.Size, nullptr,
+      LLDB_INVALID_UID, lldb_private::Type::eEncodingIsUID, decl, ct,
+      lldb_private::Type::eResolveStateFull);
   array_sp->SetEncodingType(element_type.get());
   return array_sp;
 }
 
 TypeSP SymbolFileNativePDB::CreateProcedureType(PdbTypeSymId type_id,
-                                                const ProcedureRecord &pr) {
-  TpiStream &stream = m_index->tpi();
-  CVType args_cvt = stream.getType(pr.ArgumentList);
-  ArgListRecord args;
-  llvm::cantFail(
-      TypeDeserializer::deserializeAs<ArgListRecord>(args_cvt, args));
-
-  llvm::ArrayRef<TypeIndex> arg_indices = llvm::makeArrayRef(args.ArgIndices);
-  bool is_variadic = IsCVarArgsFunction(arg_indices);
-  if (is_variadic)
-    arg_indices = arg_indices.drop_back();
-
-  std::vector<CompilerType> arg_list;
-  arg_list.reserve(arg_list.size());
-
-  for (TypeIndex arg_index : arg_indices) {
-    TypeSP arg_sp = GetOrCreateType(arg_index);
-    if (!arg_sp)
-      return nullptr;
-    arg_list.push_back(arg_sp->GetFullCompilerType());
-  }
-
-  TypeSP return_type_sp = GetOrCreateType(pr.ReturnType);
-  if (!return_type_sp)
-    return nullptr;
-
-  llvm::Optional<clang::CallingConv> cc =
-      TranslateCallingConvention(pr.CallConv);
-  if (!cc)
-    return nullptr;
-
-  CompilerType return_ct = return_type_sp->GetFullCompilerType();
-  CompilerType func_sig_ast_type = m_clang->CreateFunctionType(
-      return_ct, arg_list.data(), arg_list.size(), is_variadic, 0, *cc);
-
+                                                const ProcedureRecord &pr,
+                                                CompilerType ct) {
   Declaration decl;
   return std::make_shared<lldb_private::Type>(
       toOpaqueUid(type_id), this, ConstString(), 0, nullptr, LLDB_INVALID_UID,
-      lldb_private::Type::eEncodingIsUID, decl, func_sig_ast_type,
+      lldb_private::Type::eEncodingIsUID, decl, ct,
       lldb_private::Type::eResolveStateFull);
 }
 
-TypeSP SymbolFileNativePDB::CreateType(PdbTypeSymId type_id) {
+TypeSP SymbolFileNativePDB::CreateType(PdbTypeSymId type_id, CompilerType ct) {
   if (type_id.index.isSimple())
-    return CreateSimpleType(type_id.index);
+    return CreateSimpleType(type_id.index, ct);
 
   TpiStream &stream = type_id.is_ipi ? m_index->ipi() : m_index->tpi();
   CVType cvt = stream.getType(type_id.index);
@@ -1129,44 +600,44 @@ TypeSP SymbolFileNativePDB::CreateType(P
     ModifierRecord modifier;
     llvm::cantFail(
         TypeDeserializer::deserializeAs<ModifierRecord>(cvt, modifier));
-    return CreateModifierType(type_id, modifier);
+    return CreateModifierType(type_id, modifier, ct);
   }
 
   if (cvt.kind() == LF_POINTER) {
     PointerRecord pointer;
     llvm::cantFail(
         TypeDeserializer::deserializeAs<PointerRecord>(cvt, pointer));
-    return CreatePointerType(type_id, pointer);
+    return CreatePointerType(type_id, pointer, ct);
   }
 
   if (IsClassRecord(cvt.kind())) {
     ClassRecord cr;
     llvm::cantFail(TypeDeserializer::deserializeAs<ClassRecord>(cvt, cr));
-    return CreateTagType(type_id, cr);
+    return CreateTagType(type_id, cr, ct);
   }
 
   if (cvt.kind() == LF_ENUM) {
     EnumRecord er;
     llvm::cantFail(TypeDeserializer::deserializeAs<EnumRecord>(cvt, er));
-    return CreateTagType(type_id, er);
+    return CreateTagType(type_id, er, ct);
   }
 
   if (cvt.kind() == LF_UNION) {
     UnionRecord ur;
     llvm::cantFail(TypeDeserializer::deserializeAs<UnionRecord>(cvt, ur));
-    return CreateTagType(type_id, ur);
+    return CreateTagType(type_id, ur, ct);
   }
 
   if (cvt.kind() == LF_ARRAY) {
     ArrayRecord ar;
     llvm::cantFail(TypeDeserializer::deserializeAs<ArrayRecord>(cvt, ar));
-    return CreateArrayType(type_id, ar);
+    return CreateArrayType(type_id, ar, ct);
   }
 
   if (cvt.kind() == LF_PROCEDURE) {
     ProcedureRecord pr;
     llvm::cantFail(TypeDeserializer::deserializeAs<ProcedureRecord>(cvt, pr));
-    return CreateProcedureType(type_id, pr);
+    return CreateProcedureType(type_id, pr, ct);
   }
 
   return nullptr;
@@ -1200,7 +671,10 @@ TypeSP SymbolFileNativePDB::CreateAndCac
   }
 
   PdbTypeSymId best_decl_id = full_decl_uid ? *full_decl_uid : type_id;
-  TypeSP result = CreateType(best_decl_id);
+
+  clang::QualType qt = m_ast->GetOrCreateType(best_decl_id);
+
+  TypeSP result = CreateType(best_decl_id, m_ast->ToCompilerType(qt));
   if (!result)
     return nullptr;
 
@@ -1211,15 +685,6 @@ TypeSP SymbolFileNativePDB::CreateAndCac
   if (full_decl_uid)
     m_types[toOpaqueUid(type_id)] = result;
 
-  if (IsTagRecord(best_decl_id, m_index->tpi())) {
-    clang::TagDecl *record_decl =
-        m_clang->GetAsTagDecl(result->GetForwardCompilerType());
-    lldbassert(record_decl);
-
-    m_uid_to_decl[best_uid] = record_decl;
-    m_decl_to_status[record_decl] =
-        DeclStatus(best_uid, Type::eResolveStateForward);
-  }
   return result;
 }
 
@@ -1631,11 +1096,7 @@ size_t SymbolFileNativePDB::ParseFunctio
   return 1;
 }
 
-void SymbolFileNativePDB::DumpClangAST(Stream &s) {
-  if (!m_clang)
-    return;
-  m_clang->Dump(s);
-}
+void SymbolFileNativePDB::DumpClangAST(Stream &s) { m_ast->Dump(s); }
 
 uint32_t SymbolFileNativePDB::FindGlobalVariables(
     const ConstString &name, const CompilerDeclContext *parent_decl_ctx,
@@ -1764,8 +1225,7 @@ VariableSP SymbolFileNativePDB::CreateLo
                                                     PdbCompilandSymId var_id,
                                                     bool is_param) {
   ModuleSP module = GetObjectFile()->GetModule();
-  VariableInfo var_info =
-      GetVariableInformation(*m_index, var_id, module, true);
+  VariableInfo var_info = GetVariableLocationInfo(*m_index, var_id, module);
 
   CompilandIndexItem *cii = m_index->compilands().GetCompiland(var_id.modi);
   CompUnitSP comp_unit_sp = GetOrCreateCompileUnit(*cii);
@@ -1782,20 +1242,8 @@ VariableSP SymbolFileNativePDB::CreateLo
       comp_unit_sp.get(), *var_info.ranges, &decl, *var_info.location, false,
       false, false);
 
-  CompilerDeclContext cdc = GetDeclContextForUID(toOpaqueUid(scope_id));
-  clang::DeclContext *decl_ctx =
-      static_cast<clang::DeclContext *>(cdc.GetOpaqueDeclContext());
-
-  // Parameter info should have already been added to the AST.
-  if (!is_param) {
-    clang::QualType qt =
-        ClangUtil::GetCanonicalQualType(type_sp->GetForwardCompilerType());
-
-    clang::VarDecl *var_decl =
-        m_clang->CreateVariableDeclaration(decl_ctx, name.c_str(), qt);
-    lldbassert(m_uid_to_decl.count(toOpaqueUid(var_id)) == 0);
-    m_uid_to_decl[toOpaqueUid(var_id)] = var_decl;
-  }
+  if (!is_param)
+    m_ast->GetOrCreateLocalVariableDecl(scope_id, var_id);
 
   m_local_variables[toOpaqueUid(var_id)] = var_sp;
   return var_sp;
@@ -1919,44 +1367,25 @@ size_t SymbolFileNativePDB::ParseVariabl
 }
 
 CompilerDecl SymbolFileNativePDB::GetDeclForUID(lldb::user_id_t uid) {
-  auto iter = m_uid_to_decl.find(uid);
-  if (iter == m_uid_to_decl.end())
-    return CompilerDecl();
+  clang::Decl *decl = m_ast->GetOrCreateDeclForUid(PdbSymUid(uid));
 
-  return {m_clang, iter->second};
+  return m_ast->ToCompilerDecl(*decl);
 }
 
 CompilerDeclContext
 SymbolFileNativePDB::GetDeclContextForUID(lldb::user_id_t uid) {
-  CompilerDecl compiler_decl = GetDeclForUID(uid);
-  clang::Decl *decl = static_cast<clang::Decl *>(compiler_decl.GetOpaqueDecl());
-  return {m_clang, clang::Decl::castToDeclContext(decl)};
+  clang::DeclContext *context =
+      m_ast->GetOrCreateDeclContextForUid(PdbSymUid(uid));
+  if (!context)
+    return {};
+
+  return m_ast->ToCompilerDeclContext(*context);
 }
 
 CompilerDeclContext
 SymbolFileNativePDB::GetDeclContextContainingUID(lldb::user_id_t uid) {
-  // FIXME: This should look up the uid, decide if it's a symbol or a type, and
-  // depending which it is, find the appropriate DeclContext.  Possibilities:
-  // For classes and typedefs:
-  //   * Function
-  //   * Namespace
-  //   * Global
-  //   * Block
-  //   * Class
-  // For field list members:
-  //   * Class
-  // For variables:
-  //   * Function
-  //   * Namespace
-  //   * Global
-  //   * Block
-  // For functions:
-  //   * Namespace
-  //   * Global
-  //   * Class
-  //
-  // It is an error to call this function with a uid for any other symbol type.
-  return {m_clang, m_clang->GetTranslationUnitDecl()};
+  clang::DeclContext *context = m_ast->GetParentDeclContext(PdbSymUid(uid));
+  return m_ast->ToCompilerDeclContext(*context);
 }
 
 Type *SymbolFileNativePDB::ResolveTypeUID(lldb::user_id_t type_uid) {
@@ -1987,73 +1416,10 @@ SymbolFileNativePDB::GetDynamicArrayInfo
 
 
 bool SymbolFileNativePDB::CompleteType(CompilerType &compiler_type) {
-  // If this is not in our map, it's an error.
-  clang::TagDecl *tag_decl = m_clang->GetAsTagDecl(compiler_type);
-  lldbassert(tag_decl);
-  auto status_iter = m_decl_to_status.find(tag_decl);
-  lldbassert(status_iter != m_decl_to_status.end());
-
-  // If it's already complete, just return.
-  DeclStatus &status = status_iter->second;
-  if (status.status == Type::eResolveStateFull)
-    return true;
-
-  PdbTypeSymId type_id = PdbSymUid(status.uid).asTypeSym();
+  clang::QualType qt =
+      clang::QualType::getFromOpaquePtr(compiler_type.GetOpaqueQualType());
 
-  lldbassert(IsTagRecord(type_id, m_index->tpi()));
-
-  ClangASTContext::SetHasExternalStorage(compiler_type.GetOpaqueQualType(),
-                                         false);
-
-  // In CreateAndCacheType, we already go out of our way to resolve forward
-  // ref UDTs to full decls, and the uids we vend out always refer to full
-  // decls if a full decl exists in the debug info.  So if we don't have a full
-  // decl here, it means one doesn't exist in the debug info, and we can't
-  // complete the type.
-  CVType cvt = m_index->tpi().getType(TypeIndex(type_id.index));
-  if (IsForwardRefUdt(cvt))
-    return false;
-
-  auto types_iter = m_types.find(status.uid);
-  lldbassert(types_iter != m_types.end());
-
-  if (cvt.kind() == LF_MODIFIER) {
-    TypeIndex unmodified_type = LookThroughModifierRecord(cvt);
-    cvt = m_index->tpi().getType(unmodified_type);
-    // LF_MODIFIERS usually point to forward decls, so this is the one case
-    // where we won't have been able to resolve a forward decl to a full decl
-    // earlier on.  So we need to do that now.
-    if (IsForwardRefUdt(cvt)) {
-      llvm::Expected<TypeIndex> expected_full_ti =
-          m_index->tpi().findFullDeclForForwardRef(unmodified_type);
-      if (!expected_full_ti) {
-        llvm::consumeError(expected_full_ti.takeError());
-        return false;
-      }
-      cvt = m_index->tpi().getType(*expected_full_ti);
-      lldbassert(!IsForwardRefUdt(cvt));
-      unmodified_type = *expected_full_ti;
-    }
-    type_id = PdbTypeSymId(unmodified_type, false);
-  }
-  TypeIndex field_list_ti = GetFieldListIndex(cvt);
-  CVType field_list_cvt = m_index->tpi().getType(field_list_ti);
-  if (field_list_cvt.kind() != LF_FIELDLIST)
-    return false;
-
-  // Visit all members of this class, then perform any finalization necessary
-  // to complete the class.
-  UdtRecordCompleter completer(type_id, compiler_type, *tag_decl, *this);
-  auto error =
-      llvm::codeview::visitMemberRecordStream(field_list_cvt.data(), completer);
-  completer.complete();
-
-  status.status = Type::eResolveStateFull;
-  if (!error)
-    return true;
-
-  llvm::consumeError(std::move(error));
-  return false;
+  return m_ast->CompleteType(qt);
 }
 
 size_t SymbolFileNativePDB::GetTypes(lldb_private::SymbolContextScope *sc_scope,

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=349383&r1=349382&r2=349383&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h (original)
+++ lldb/trunk/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h Mon Dec 17 11:43:33 2018
@@ -39,14 +39,7 @@ namespace lldb_private {
 class ClangASTImporter;
 
 namespace npdb {
-
-struct DeclStatus {
-  DeclStatus() = default;
-  DeclStatus(lldb::user_id_t uid, Type::ResolveStateTag status)
-      : uid(uid), status(status) {}
-  lldb::user_id_t uid = 0;
-  Type::ResolveStateTag status = Type::eResolveStateForward;
-};
+class PdbAstBuilder;
 
 class SymbolFileNativePDB : public SymbolFile {
   friend class UdtRecordCompleter;
@@ -158,40 +151,38 @@ public:
   llvm::pdb::PDBFile &GetPDBFile() { return m_index->pdb(); }
   const llvm::pdb::PDBFile &GetPDBFile() const { return m_index->pdb(); }
 
-  ClangASTContext &GetASTContext() { return *m_clang; }
-  ClangASTImporter &GetASTImporter() { return *m_importer; }
-
   void DumpClangAST(Stream &s) override;
 
 private:
-  std::pair<clang::DeclContext *, std::string>
-  CreateDeclInfoForType(const llvm::codeview::TagRecord &record,
-                        llvm::codeview::TypeIndex ti);
 
-  void PreprocessTpiStream();
   size_t FindTypesByName(llvm::StringRef name, uint32_t max_matches,
                          TypeMap &types);
 
   lldb::TypeSP CreateModifierType(PdbTypeSymId type_id,
-                                  const llvm::codeview::ModifierRecord &mr);
+                                  const llvm::codeview::ModifierRecord &mr,
+                                  CompilerType ct);
   lldb::TypeSP CreatePointerType(PdbTypeSymId type_id,
-                                 const llvm::codeview::PointerRecord &pr);
-  lldb::TypeSP CreateSimpleType(llvm::codeview::TypeIndex ti);
+                                 const llvm::codeview::PointerRecord &pr,
+                                 CompilerType ct);
+  lldb::TypeSP CreateSimpleType(llvm::codeview::TypeIndex ti, CompilerType ct);
   lldb::TypeSP CreateTagType(PdbTypeSymId type_id,
-                             const llvm::codeview::ClassRecord &cr);
+                             const llvm::codeview::ClassRecord &cr,
+                             CompilerType ct);
   lldb::TypeSP CreateTagType(PdbTypeSymId type_id,
-                             const llvm::codeview::EnumRecord &er);
+                             const llvm::codeview::EnumRecord &er,
+                             CompilerType ct);
   lldb::TypeSP CreateTagType(PdbTypeSymId type_id,
-                             const llvm::codeview::UnionRecord &ur);
+                             const llvm::codeview::UnionRecord &ur,
+                             CompilerType ct);
   lldb::TypeSP CreateArrayType(PdbTypeSymId type_id,
-                               const llvm::codeview::ArrayRecord &ar);
+                               const llvm::codeview::ArrayRecord &ar,
+                               CompilerType ct);
   lldb::TypeSP CreateProcedureType(PdbTypeSymId type_id,
-                                   const llvm::codeview::ProcedureRecord &pr);
-  lldb::TypeSP
-  CreateClassStructUnion(PdbTypeSymId type_id,
-                         const llvm::codeview::TagRecord &record, size_t size,
-                         clang::TagTypeKind ttk,
-                         clang::MSInheritanceAttr::Spelling inheritance);
+                                   const llvm::codeview::ProcedureRecord &pr,
+                                   CompilerType ct);
+  lldb::TypeSP CreateClassStructUnion(PdbTypeSymId type_id,
+                                      const llvm::codeview::TagRecord &record,
+                                      size_t size, CompilerType ct);
 
   lldb::FunctionSP GetOrCreateFunction(PdbCompilandSymId func_id,
                                        CompileUnit &comp_unit);
@@ -210,7 +201,7 @@ private:
   lldb::VariableSP CreateLocalVariable(PdbCompilandSymId scope_id,
                                        PdbCompilandSymId var_id, bool is_param);
   lldb::CompUnitSP CreateCompileUnit(const CompilandIndexItem &cci);
-  lldb::TypeSP CreateType(PdbTypeSymId type_id);
+  lldb::TypeSP CreateType(PdbTypeSymId type_id, CompilerType ct);
   lldb::TypeSP CreateAndCacheType(PdbTypeSymId type_id);
   lldb::VariableSP CreateGlobalVariable(PdbGlobalSymId var_id);
   lldb::VariableSP CreateConstantSymbol(PdbGlobalSymId var_id,
@@ -224,14 +215,8 @@ private:
   lldb::addr_t m_obj_load_address = 0;
 
   std::unique_ptr<PdbIndex> m_index;
-  std::unique_ptr<ClangASTImporter> m_importer;
-  ClangASTContext *m_clang = nullptr;
-
-  llvm::DenseMap<clang::TagDecl *, DeclStatus> m_decl_to_status;
 
-  llvm::DenseMap<lldb::user_id_t, clang::Decl *> m_uid_to_decl;
-  llvm::DenseMap<llvm::codeview::TypeIndex, llvm::codeview::TypeIndex>
-      m_parent_types;
+  std::unique_ptr<PdbAstBuilder> m_ast;
 
   llvm::DenseMap<lldb::user_id_t, lldb::VariableSP> m_global_vars;
   llvm::DenseMap<lldb::user_id_t, lldb::VariableSP> m_local_variables;

Modified: lldb/trunk/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp?rev=349383&r1=349382&r2=349383&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp (original)
+++ lldb/trunk/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp Mon Dec 17 11:43:33 2018
@@ -1,11 +1,12 @@
 #include "UdtRecordCompleter.h"
 
+#include "PdbAstBuilder.h"
 #include "PdbIndex.h"
 #include "PdbSymUid.h"
 #include "PdbUtil.h"
-#include "SymbolFileNativePDB.h"
 
 #include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Symbol/ClangASTImporter.h"
 #include "lldb/Symbol/Type.h"
 #include "lldb/Utility/LLDBAssert.h"
 #include "lldb/lldb-enumerations.h"
@@ -27,11 +28,11 @@ using Error = llvm::Error;
 UdtRecordCompleter::UdtRecordCompleter(PdbTypeSymId id,
                                        CompilerType &derived_ct,
                                        clang::TagDecl &tag_decl,
-                                       SymbolFileNativePDB &symbol_file)
+                                       PdbAstBuilder &ast_builder,
+                                       TpiStream &tpi)
     : m_id(id), m_derived_ct(derived_ct), m_tag_decl(tag_decl),
-      m_symbol_file(symbol_file) {
-  TpiStream &tpi = symbol_file.m_index->tpi();
-  CVType cvt = tpi.getType(m_id.index);
+      m_ast_builder(ast_builder), m_tpi(tpi) {
+  CVType cvt = m_tpi.getType(m_id.index);
   switch (cvt.kind()) {
   case LF_ENUM:
     llvm::cantFail(TypeDeserializer::deserializeAs<EnumRecord>(cvt, m_cvr.er));
@@ -48,29 +49,29 @@ UdtRecordCompleter::UdtRecordCompleter(P
   }
 }
 
-lldb::opaque_compiler_type_t UdtRecordCompleter::AddBaseClassForTypeIndex(
+clang::QualType UdtRecordCompleter::AddBaseClassForTypeIndex(
     llvm::codeview::TypeIndex ti, llvm::codeview::MemberAccess access) {
-  TypeSP base_type = m_symbol_file.GetOrCreateType(ti);
-  CompilerType base_ct = base_type->GetFullCompilerType();
+  PdbTypeSymId type_id(ti);
+  clang::QualType qt = m_ast_builder.GetOrCreateType(type_id);
 
-  CVType udt_cvt = m_symbol_file.m_index->tpi().getType(ti);
+  CVType udt_cvt = m_tpi.getType(ti);
 
-  lldb::opaque_compiler_type_t base_qt = base_ct.GetOpaqueQualType();
   std::unique_ptr<clang::CXXBaseSpecifier> base_spec =
-      m_symbol_file.GetASTContext().CreateBaseClassSpecifier(
-          base_qt, TranslateMemberAccess(access), false,
+      m_ast_builder.clang().CreateBaseClassSpecifier(
+          qt.getAsOpaquePtr(), TranslateMemberAccess(access), false,
           udt_cvt.kind() == LF_CLASS);
   lldbassert(base_spec);
   m_bases.push_back(std::move(base_spec));
-  return base_qt;
+  return qt;
 }
 
 Error UdtRecordCompleter::visitKnownMember(CVMemberRecord &cvr,
                                            BaseClassRecord &base) {
-  lldb::opaque_compiler_type_t base_qt =
+  clang::QualType base_qt =
       AddBaseClassForTypeIndex(base.Type, base.getAccess());
 
-  auto decl = m_symbol_file.GetASTContext().GetAsCXXRecordDecl(base_qt);
+  auto decl =
+      m_ast_builder.clang().GetAsCXXRecordDecl(base_qt.getAsOpaquePtr());
   lldbassert(decl);
 
   auto offset = clang::CharUnits::fromQuantity(base.getBaseOffset());
@@ -99,13 +100,17 @@ Error UdtRecordCompleter::visitKnownMemb
 
 Error UdtRecordCompleter::visitKnownMember(
     CVMemberRecord &cvr, StaticDataMemberRecord &static_data_member) {
-  TypeSP member_type = m_symbol_file.GetOrCreateType(static_data_member.Type);
-  CompilerType complete_member_type = member_type->GetFullCompilerType();
+  clang::QualType member_type =
+      m_ast_builder.GetOrCreateType(PdbTypeSymId(static_data_member.Type));
+
+  m_ast_builder.CompleteType(member_type);
+
+  CompilerType member_ct = m_ast_builder.ToCompilerType(member_type);
 
   lldb::AccessType access =
       TranslateMemberAccess(static_data_member.getAccess());
   ClangASTContext::AddVariableToRecordType(
-      m_derived_ct, static_data_member.Name, complete_member_type, access);
+      m_derived_ct, static_data_member.Name, member_ct, access);
 
   // FIXME: Add a PdbSymUid namespace for field list members and update
   // the m_uid_to_decl map with this decl.
@@ -123,11 +128,9 @@ Error UdtRecordCompleter::visitKnownMemb
   uint64_t offset = data_member.FieldOffset * 8;
   uint32_t bitfield_width = 0;
 
-  TypeSP member_type;
-  TpiStream &tpi = m_symbol_file.m_index->tpi();
   TypeIndex ti(data_member.Type);
   if (!ti.isSimple()) {
-    CVType cvt = tpi.getType(ti);
+    CVType cvt = m_tpi.getType(ti);
     if (cvt.kind() == LF_BITFIELD) {
       BitFieldRecord bfr;
       llvm::cantFail(TypeDeserializer::deserializeAs<BitFieldRecord>(cvt, bfr));
@@ -137,13 +140,14 @@ Error UdtRecordCompleter::visitKnownMemb
     }
   }
 
-  member_type = m_symbol_file.GetOrCreateType(ti);
-  CompilerType complete_member_type = member_type->GetFullCompilerType();
+  clang::QualType member_qt = m_ast_builder.GetOrCreateType(PdbTypeSymId(ti));
+  m_ast_builder.CompleteType(member_qt);
+
   lldb::AccessType access = TranslateMemberAccess(data_member.getAccess());
 
   clang::FieldDecl *decl = ClangASTContext::AddFieldToRecordType(
-      m_derived_ct, data_member.Name, complete_member_type, access,
-      bitfield_width);
+      m_derived_ct, data_member.Name, m_ast_builder.ToCompilerType(member_qt),
+      access, bitfield_width);
   // FIXME: Add a PdbSymUid namespace for field list members and update
   // the m_uid_to_decl map with this decl.
 
@@ -164,22 +168,16 @@ Error UdtRecordCompleter::visitKnownMemb
 
 Error UdtRecordCompleter::visitKnownMember(CVMemberRecord &cvr,
                                            EnumeratorRecord &enumerator) {
-  ClangASTContext &clang = m_symbol_file.GetASTContext();
-
   Declaration decl;
   llvm::StringRef name = DropNameScope(enumerator.getName());
-  TypeSP underlying_type =
-      m_symbol_file.GetOrCreateType(m_cvr.er.getUnderlyingType());
 
-  uint64_t byte_size = underlying_type->GetByteSize();
-  clang.AddEnumerationValueToEnumerationType(
-      m_derived_ct, decl, name.str().c_str(), enumerator.Value.getSExtValue(),
-      byte_size * 8);
+  m_ast_builder.clang().AddEnumerationValueToEnumerationType(
+      m_derived_ct, decl, name.str().c_str(), enumerator.Value);
   return Error::success();
 }
 
 void UdtRecordCompleter::complete() {
-  ClangASTContext &clang = m_symbol_file.GetASTContext();
+  ClangASTContext &clang = m_ast_builder.clang();
   clang.TransferBaseClasses(m_derived_ct.GetOpaqueQualType(),
                             std::move(m_bases));
 
@@ -188,6 +186,6 @@ void UdtRecordCompleter::complete() {
   ClangASTContext::CompleteTagDeclarationDefinition(m_derived_ct);
 
   if (auto *record_decl = llvm::dyn_cast<clang::CXXRecordDecl>(&m_tag_decl)) {
-    m_symbol_file.GetASTImporter().InsertRecordDecl(record_decl, m_layout);
+    m_ast_builder.importer().InsertRecordDecl(record_decl, m_layout);
   }
 }

Modified: lldb/trunk/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.h?rev=349383&r1=349382&r2=349383&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.h (original)
+++ lldb/trunk/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.h Mon Dec 17 11:43:33 2018
@@ -19,14 +19,21 @@
 
 namespace clang {
 class CXXBaseSpecifier;
+class QualType;
 class TagDecl;
 } // namespace clang
 
+namespace llvm {
+namespace pdb {
+class TpiStream;
+}
+} // namespace llvm
+
 namespace lldb_private {
 class Type;
 class CompilerType;
 namespace npdb {
-class SymbolFileNativePDB;
+class PdbAstBuilder;
 
 class UdtRecordCompleter : public llvm::codeview::TypeVisitorCallbacks {
   union UdtTagRecord {
@@ -39,14 +46,15 @@ class UdtRecordCompleter : public llvm::
   PdbTypeSymId m_id;
   CompilerType &m_derived_ct;
   clang::TagDecl &m_tag_decl;
-  SymbolFileNativePDB &m_symbol_file;
+  PdbAstBuilder &m_ast_builder;
+  llvm::pdb::TpiStream &m_tpi;
   std::vector<std::unique_ptr<clang::CXXBaseSpecifier>> m_bases;
   ClangASTImporter::LayoutInfo m_layout;
 
 public:
   UdtRecordCompleter(PdbTypeSymId id, CompilerType &derived_ct,
-                     clang::TagDecl &tag_decl,
-                     SymbolFileNativePDB &symbol_file);
+                     clang::TagDecl &tag_decl, PdbAstBuilder &ast_builder,
+                     llvm::pdb::TpiStream &tpi);
 
 #define MEMBER_RECORD(EnumName, EnumVal, Name)                                 \
   llvm::Error visitKnownMember(llvm::codeview::CVMemberRecord &CVR,            \
@@ -57,9 +65,8 @@ public:
   void complete();
 
 private:
-  lldb::opaque_compiler_type_t
-  AddBaseClassForTypeIndex(llvm::codeview::TypeIndex ti,
-                           llvm::codeview::MemberAccess access);
+  clang::QualType AddBaseClassForTypeIndex(llvm::codeview::TypeIndex ti,
+                                           llvm::codeview::MemberAccess access);
 };
 
 } // namespace npdb




More information about the lldb-commits mailing list