#include "PdbAstBuilder.h"

#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
#include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"
#include "llvm/DebugInfo/CodeView/RecordName.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/DbiStream.h"
#include "llvm/DebugInfo/PDB/Native/PublicsStream.h"
#include "llvm/DebugInfo/PDB/Native/SymbolStream.h"
#include "llvm/DebugInfo/PDB/Native/TpiStream.h"
#include "llvm/Demangle/MicrosoftDemangle.h"

#include "PdbUtil.h"
#include "Plugins/ExpressionParser/Clang/ClangASTMetadata.h"
#include "Plugins/ExpressionParser/Clang/ClangUtil.h"
#include "Plugins/Language/CPlusPlus/MSVCUndecoratedNameParser.h"
#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
#include "SymbolFileNativePDB.h"
#include "UdtRecordCompleter.h"
#include "lldb/Core/Module.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Utility/LLDBAssert.h"
#include <optional>
#include <string_view>

using namespace lldb_private;
using namespace lldb_private::npdb;
using namespace llvm::codeview;
using namespace llvm::pdb;

namespace {
struct CreateMethodDecl : public TypeVisitorCallbacks {
  CreateMethodDecl(PdbIndex &m_index, TypeSystemClang &m_clang,
                   TypeIndex func_type_index,
                   clang::FunctionDecl *&function_decl,
                   lldb::opaque_compiler_type_t parent_ty,
                   llvm::StringRef proc_name, ConstString mangled_name,
                   CompilerType func_ct)
      : m_index(m_index), m_clang(m_clang), func_type_index(func_type_index),
        function_decl(function_decl), parent_ty(parent_ty),
        proc_name(proc_name), mangled_name(mangled_name), func_ct(func_ct) {}
  PdbIndex &m_index;
  TypeSystemClang &m_clang;
  TypeIndex func_type_index;
  clang::FunctionDecl *&function_decl;
  lldb::opaque_compiler_type_t parent_ty;
  llvm::StringRef proc_name;
  ConstString mangled_name;
  CompilerType func_ct;

  llvm::Error visitKnownMember(CVMemberRecord &cvr,
                               OverloadedMethodRecord &overloaded) override {
    TypeIndex method_list_idx = overloaded.MethodList;

    CVType method_list_type = m_index.tpi().getType(method_list_idx);
    assert(method_list_type.kind() == LF_METHODLIST);

    MethodOverloadListRecord method_list;
    llvm::cantFail(TypeDeserializer::deserializeAs<MethodOverloadListRecord>(
        method_list_type, method_list));

    for (const OneMethodRecord &method : method_list.Methods) {
      if (method.getType().getIndex() == func_type_index.getIndex())
        AddMethod(overloaded.Name, method.getAccess(), method.getOptions(),
                  method.Attrs);
    }

    return llvm::Error::success();
  }

  llvm::Error visitKnownMember(CVMemberRecord &cvr,
                               OneMethodRecord &record) override {
    AddMethod(record.getName(), record.getAccess(), record.getOptions(),
              record.Attrs);
    return llvm::Error::success();
  }

  void AddMethod(llvm::StringRef name, MemberAccess access,
                 MethodOptions options, MemberAttributes attrs) {
    if (name != proc_name || function_decl)
      return;
    lldb::AccessType access_type = TranslateMemberAccess(access);
    bool is_virtual = attrs.isVirtual();
    bool is_static = attrs.isStatic();
    bool is_artificial = (options & MethodOptions::CompilerGenerated) ==
                         MethodOptions::CompilerGenerated;
    function_decl = m_clang.AddMethodToCXXRecordType(
        parent_ty, proc_name, mangled_name, func_ct, /*access=*/access_type,
        /*is_virtual=*/is_virtual, /*is_static=*/is_static,
        /*is_inline=*/false, /*is_explicit=*/false,
        /*is_attr_used=*/false, /*is_artificial=*/is_artificial);
  }
};
} // namespace

static clang::TagTypeKind TranslateUdtKind(const TagRecord &cr) {
  switch (cr.Kind) {
  case TypeRecordKind::Class:
    return clang::TagTypeKind::Class;
  case TypeRecordKind::Struct:
    return clang::TagTypeKind::Struct;
  case TypeRecordKind::Union:
    return clang::TagTypeKind::Union;
  case TypeRecordKind::Interface:
    return clang::TagTypeKind::Interface;
  case TypeRecordKind::Enum:
    return clang::TagTypeKind::Enum;
  default:
    lldbassert(false && "Invalid tag record kind!");
    return clang::TagTypeKind::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 std::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 std::nullopt;
  }
}

static bool IsAnonymousNamespaceName(llvm::StringRef name) {
  return name == "`anonymous namespace'" || name == "`anonymous-namespace'";
}

PdbAstBuilder::PdbAstBuilder(TypeSystemClang &clang) : m_clang(clang) {}

lldb_private::CompilerDeclContext PdbAstBuilder::GetTranslationUnitDecl() {
  return ToCompilerDeclContext(*m_clang.GetTranslationUnitDecl());
}

std::pair<clang::DeclContext *, std::string>
PdbAstBuilder::CreateDeclInfoForType(const TagRecord &record, TypeIndex ti) {
  SymbolFileNativePDB *pdb = static_cast<SymbolFileNativePDB *>(
      m_clang.GetSymbolFile()->GetBackingSymbolFile());
  // FIXME: Move this to GetDeclContextContainingUID.
  if (!record.hasUniqueName())
    return CreateDeclInfoForUndecoratedName(record.Name);

  llvm::ms_demangle::Demangler demangler;
  std::string_view sv(record.UniqueName.begin(), record.UniqueName.size());
  llvm::ms_demangle::TagTypeNode *ttn = demangler.parseTagUniqueName(sv);
  if (demangler.Error)
    return CreateDeclInfoForUndecoratedName(record.Name);

  llvm::ms_demangle::IdentifierNode *idn =
      ttn->QualifiedName->getUnqualifiedIdentifier();
  std::string uname = idn->toString(llvm::ms_demangle::OF_NoTagSpecifier);

  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).
  std::optional<TypeIndex> parent_index = pdb->GetParentType(ti);
  if (!parent_index) {
    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, std::string(record.Name)};

    for (llvm::ms_demangle::Node *scope : scopes) {
      auto *nii = static_cast<llvm::ms_demangle::NamedIdentifierNode *>(scope);
      std::string str = nii->toString();
      context = GetOrCreateNamespaceDecl(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_index);
  if (parent_qt.isNull())
    return {nullptr, ""};

  context = clang::TagDecl::castToDeclContext(parent_qt->getAsTagDecl());
  return {context, uname};
}

static bool isLocalVariableType(SymbolKind K) {
  switch (K) {
  case S_REGISTER:
  case S_REGREL32:
  case S_LOCAL:
    return true;
  default:
    break;
  }
  return false;
}

clang::Decl *PdbAstBuilder::GetOrCreateSymbolForId(PdbCompilandSymId id) {
  SymbolFileNativePDB *pdb = static_cast<SymbolFileNativePDB *>(
      m_clang.GetSymbolFile()->GetBackingSymbolFile());
  PdbIndex &index = pdb->GetIndex();
  CVSymbol cvs = index.ReadSymbolRecord(id);

  if (isLocalVariableType(cvs.kind())) {
    clang::DeclContext *scope = GetParentDeclContext(id);
    if (!scope)
      return nullptr;
    clang::Decl *scope_decl = clang::Decl::castFromDeclContext(scope);
    PdbCompilandSymId scope_id =
        PdbSymUid(m_decl_to_status[scope_decl].uid).asCompilandSym();
    return GetOrCreateVariableDecl(scope_id, 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_INLINESITE:
    return GetOrCreateInlinedFunctionDecl(id);
  default:
    return nullptr;
  }
}

std::optional<CompilerDecl>
PdbAstBuilder::GetOrCreateDeclForUid(PdbSymUid uid) {
  if (clang::Decl *result = TryGetDecl(uid))
    return ToCompilerDecl(*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 (qt.isNull())
      return std::nullopt;
    if (auto *tag = qt->getAsTagDecl()) {
      result = tag;
      break;
    }
    return std::nullopt;
  }
  default:
    return std::nullopt;
  }

  if (!result)
    return std::nullopt;
  m_uid_to_decl[toOpaqueUid(uid)] = result;
  return ToCompilerDecl(*result);
}

clang::DeclContext *PdbAstBuilder::GetOrCreateDeclContextForUid(PdbSymUid uid) {
  if (uid.kind() == PdbSymUidKind::CompilandSym) {
    if (uid.asCompilandSym().offset == 0)
      return FromCompilerDeclContext(GetTranslationUnitDecl());
  }
  auto option = GetOrCreateDeclForUid(uid);
  if (!option)
    return nullptr;
  clang::Decl *decl = FromCompilerDecl(*option);
  if (!decl)
    return nullptr;

  return clang::Decl::castToDeclContext(decl);
}

std::pair<clang::DeclContext *, std::string>
PdbAstBuilder::CreateDeclInfoForUndecoratedName(llvm::StringRef name) {
  SymbolFileNativePDB *pdb = static_cast<SymbolFileNativePDB *>(
      m_clang.GetSymbolFile()->GetBackingSymbolFile());
  PdbIndex &index = pdb->GetIndex();
  MSVCUndecoratedNameParser parser(name);
  llvm::ArrayRef<MSVCUndecoratedNameSpecifier> specs = parser.GetSpecifiers();

  auto *context = FromCompilerDeclContext(GetTranslationUnitDecl());

  llvm::StringRef uname = specs.back().GetBaseName();
  specs = specs.drop_back();
  if (specs.empty())
    return {context, std::string(name)};

  llvm::StringRef scope_name = specs.back().GetFullName();

  // It might be a class name, try that first.
  std::vector<TypeIndex> types = index.tpi().findRecordsByName(scope_name);
  while (!types.empty()) {
    clang::QualType qt = GetOrCreateType(types.back());
    if (qt.isNull())
      continue;
    clang::TagDecl *tag = qt->getAsTagDecl();
    if (tag)
      return {clang::TagDecl::castToDeclContext(tag), std::string(uname)};
    types.pop_back();
  }

  // If that fails, treat it as a series of namespaces.
  for (const MSVCUndecoratedNameSpecifier &spec : specs) {
    std::string ns_name = spec.GetBaseName().str();
    context = GetOrCreateNamespaceDecl(ns_name.c_str(), *context);
  }
  return {context, std::string(uname)};
}

clang::DeclContext *PdbAstBuilder::GetParentDeclContext(PdbSymUid uid) {
  // We must do this *without* calling GetOrCreate on the current uid, as
  // that would be an infinite recursion.
  SymbolFileNativePDB *pdb = static_cast<SymbolFileNativePDB *>(
      m_clang.GetSymbolFile()->GetBackingSymbolFile());
  PdbIndex& index = pdb->GetIndex();
  switch (uid.kind()) {
  case PdbSymUidKind::CompilandSym: {
    std::optional<PdbCompilandSymId> scope =
        pdb->FindSymbolScope(uid.asCompilandSym());
    if (scope)
      return GetOrCreateDeclContextForUid(*scope);

    CVSymbol sym = index.ReadSymbolRecord(uid.asCompilandSym());
    return CreateDeclInfoForUndecoratedName(getSymbolName(sym)).first;
  }
  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.
    PdbTypeSymId type_id = uid.asTypeSym();
    std::optional<TypeIndex> parent_index = pdb->GetParentType(type_id.index);
    if (!parent_index)
      return FromCompilerDeclContext(GetTranslationUnitDecl());
    return GetOrCreateDeclContextForUid(PdbTypeSymId(*parent_index));
  }
  case PdbSymUidKind::FieldListMember:
    // In this case the parent DeclContext is the one for the class that this
    // member is inside of.
    break;
  case PdbSymUidKind::GlobalSym: {
    // If this refers to a compiland symbol, just recurse in with that symbol.
    // The only other possibilities are S_CONSTANT and S_UDT, in which case we
    // need to parse the undecorated name to figure out the scope, then look
    // that up in the TPI stream.  If it's found, it's a type, othewrise it's
    // a series of namespaces.
    // FIXME: do this.
    CVSymbol global = index.ReadSymbolRecord(uid.asGlobalSym());
    switch (global.kind()) {
    case SymbolKind::S_GDATA32:
    case SymbolKind::S_LDATA32:
      return CreateDeclInfoForUndecoratedName(getSymbolName(global)).first;;
    case SymbolKind::S_PROCREF:
    case SymbolKind::S_LPROCREF: {
      ProcRefSym ref{global.kind()};
      llvm::cantFail(
          SymbolDeserializer::deserializeAs<ProcRefSym>(global, ref));
      PdbCompilandSymId cu_sym_id{ref.modi(), ref.SymOffset};
      return GetParentDeclContext(cu_sym_id);
    }
    case SymbolKind::S_CONSTANT:
    case SymbolKind::S_UDT:
      return CreateDeclInfoForUndecoratedName(getSymbolName(global)).first;
    default:
      break;
    }
    break;
  }
  default:
    break;
  }
  return FromCompilerDeclContext(GetTranslationUnitDecl());
}

bool PdbAstBuilder::CompleteType(clang::QualType qt) {
  if (qt.isNull())
    return false;
  clang::TagDecl *tag = qt->getAsTagDecl();
  if (qt->isArrayType()) {
    const clang::Type *element_type = qt->getArrayElementTypeNoTypeQual();
    tag = element_type->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();
  PdbIndex &index = static_cast<SymbolFileNativePDB *>(
                        m_clang.GetSymbolFile()->GetBackingSymbolFile())
                        ->GetIndex();
  lldbassert(IsTagRecord(type_id, index.tpi()));

  clang::QualType tag_qt = m_clang.getASTContext().getCanonicalTagType(&tag);
  TypeSystemClang::SetHasExternalStorage(tag_qt.getAsOpaquePtr(), false);

  TypeIndex tag_ti = type_id.index;
  CVType cvt = index.tpi().getType(tag_ti);
  if (cvt.kind() == LF_MODIFIER)
    tag_ti = LookThroughModifierRecord(cvt);

  PdbTypeSymId best_ti = GetBestPossibleDecl(tag_ti, index.tpi());
  cvt = 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 = index.tpi().getType(field_list_ti);
  if (field_list_cvt.kind() != LF_FIELDLIST)
    return false;
  FieldListRecord field_list;
  if (llvm::Error error = TypeDeserializer::deserializeAs<FieldListRecord>(
          field_list_cvt, field_list))
    llvm::consumeError(std::move(error));

  // 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, index, m_decl_to_status,
                               m_cxx_record_map);
  llvm::Error error =
      llvm::codeview::visitMemberRecordStream(field_list.Data, completer);
  completer.complete();

  m_decl_to_status[&tag].resolved = true;
  if (error) {
    llvm::consumeError(std::move(error));
    return false;
  }
  return true;
}

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());
    if (direct_type.isNull())
      return {};
    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);

  // This can happen for pointers to LF_VTSHAPE records, which we shouldn't
  // create in the AST.
  if (pointee_type.isNull())
    return {};

  if (pointer.isPointerToMember()) {
    MemberPointerInfo mpi = pointer.getMemberInfo();
    clang::QualType class_type = GetOrCreateType(mpi.ContainingType);
    if (class_type.isNull())
      return {};
    if (clang::TagDecl *tag = class_type->getAsTagDecl()) {
      clang::MSInheritanceAttr::Spelling spelling;
      switch (mpi.Representation) {
      case llvm::codeview::PointerToMemberRepresentation::SingleInheritanceData:
      case llvm::codeview::PointerToMemberRepresentation::
          SingleInheritanceFunction:
        spelling =
            clang::MSInheritanceAttr::Spelling::Keyword_single_inheritance;
        break;
      case llvm::codeview::PointerToMemberRepresentation::
          MultipleInheritanceData:
      case llvm::codeview::PointerToMemberRepresentation::
          MultipleInheritanceFunction:
        spelling =
            clang::MSInheritanceAttr::Spelling::Keyword_multiple_inheritance;
        break;
      case llvm::codeview::PointerToMemberRepresentation::
          VirtualInheritanceData:
      case llvm::codeview::PointerToMemberRepresentation::
          VirtualInheritanceFunction:
        spelling =
            clang::MSInheritanceAttr::Spelling::Keyword_virtual_inheritance;
        break;
      case llvm::codeview::PointerToMemberRepresentation::Unknown:
        spelling =
            clang::MSInheritanceAttr::Spelling::Keyword_unspecified_inheritance;
        break;
      default:
        spelling = clang::MSInheritanceAttr::Spelling::SpellingNotCalculated;
        break;
      }
      tag->addAttr(clang::MSInheritanceAttr::CreateImplicit(
          m_clang.getASTContext(), spelling));
    }
    return m_clang.getASTContext().getMemberPointerType(
        pointee_type, /*Qualifier=*/std::nullopt,
        class_type->getAsCXXRecordDecl());
  }

  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 (unmodified_type.isNull())
    return {};

  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 *context = nullptr;
  std::string uname;
  std::tie(context, uname) = CreateDeclInfoForType(record, id.index);
  if (!context)
    return {};

  clang::TagTypeKind ttk = TranslateUdtKind(record);
  lldb::AccessType access = (ttk == clang::TagTypeKind::Class)
                                ? lldb::eAccessPrivate
                                : lldb::eAccessPublic;

  ClangASTMetadata metadata;
  metadata.SetUserID(toOpaqueUid(id));
  metadata.SetIsDynamicCXXType(false);

  CompilerType ct = m_clang.CreateRecordType(
      context, OptionalClangModuleID(), access, uname, llvm::to_underlying(ttk),
      lldb::eLanguageTypeC_plus_plus, metadata);

  lldbassert(ct.IsValid());

  TypeSystemClang::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());

  TypeSystemClang::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(const char *name,
                                        clang::DeclContext &context) {
  clang::NamespaceDecl *ns = m_clang.GetUniqueNamespaceDeclaration(
      IsAnonymousNamespaceName(name) ? nullptr : name, &context,
      OptionalClangModuleID());
  m_known_namespaces.insert(ns);
  m_parent_to_namespaces[&context].insert(ns);
  return ns;
}

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, OptionalClangModuleID());
  m_uid_to_decl.insert({toOpaqueUid(block_id), block_decl});

  DeclStatus status;
  status.resolved = true;
  status.uid = toOpaqueUid(block_id);
  m_decl_to_status.insert({block_decl, status});

  return block_decl;
}

clang::VarDecl *PdbAstBuilder::CreateVariableDecl(PdbSymUid uid, CVSymbol sym,
                                                  clang::DeclContext &scope) {
  VariableInfo var_info = GetVariableNameInfo(sym);
  clang::QualType qt = GetOrCreateType(var_info.type);
  if (qt.isNull())
    return nullptr;

  clang::VarDecl *var_decl = m_clang.CreateVariableDeclaration(
      &scope, OptionalClangModuleID(), var_info.name.str().c_str(), qt);

  m_uid_to_decl[toOpaqueUid(uid)] = var_decl;
  DeclStatus status;
  status.resolved = true;
  status.uid = toOpaqueUid(uid);
  m_decl_to_status.insert({var_decl, status});
  return var_decl;
}

clang::VarDecl *
PdbAstBuilder::GetOrCreateVariableDecl(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);
  if (!scope)
    return nullptr;

  SymbolFileNativePDB *pdb = static_cast<SymbolFileNativePDB *>(
      m_clang.GetSymbolFile()->GetBackingSymbolFile());
  PdbIndex &index = pdb->GetIndex();
  CVSymbol sym = index.ReadSymbolRecord(var_id);
  return CreateVariableDecl(PdbSymUid(var_id), sym, *scope);
}

clang::VarDecl *PdbAstBuilder::GetOrCreateVariableDecl(PdbGlobalSymId var_id) {
  if (clang::Decl *decl = TryGetDecl(var_id))
    return llvm::dyn_cast<clang::VarDecl>(decl);

  SymbolFileNativePDB *pdb = static_cast<SymbolFileNativePDB *>(
      m_clang.GetSymbolFile()->GetBackingSymbolFile());
  PdbIndex &index = pdb->GetIndex();
  CVSymbol sym = index.ReadSymbolRecord(var_id);
  auto context = FromCompilerDeclContext(GetTranslationUnitDecl());
  return CreateVariableDecl(PdbSymUid(var_id), sym, *context);
}

clang::TypedefNameDecl *
PdbAstBuilder::GetOrCreateTypedefDecl(PdbGlobalSymId id) {
  if (clang::Decl *decl = TryGetDecl(id))
    return llvm::dyn_cast<clang::TypedefNameDecl>(decl);

  SymbolFileNativePDB *pdb = static_cast<SymbolFileNativePDB *>(
      m_clang.GetSymbolFile()->GetBackingSymbolFile());
  PdbIndex &index = pdb->GetIndex();
  CVSymbol sym = index.ReadSymbolRecord(id);
  lldbassert(sym.kind() == S_UDT);
  UDTSym udt = llvm::cantFail(SymbolDeserializer::deserializeAs<UDTSym>(sym));

  clang::DeclContext *scope = GetParentDeclContext(id);

  PdbTypeSymId real_type_id{udt.Type, false};
  clang::QualType qt = GetOrCreateType(real_type_id);
  if (qt.isNull() || !scope)
    return nullptr;

  std::string uname = std::string(DropNameScope(udt.Name));

  CompilerType ct = ToCompilerType(qt).CreateTypedef(
      uname.c_str(), ToCompilerDeclContext(*scope), 0);
  clang::TypedefNameDecl *tnd = m_clang.GetAsTypedefDecl(ct);
  DeclStatus status;
  status.resolved = true;
  status.uid = toOpaqueUid(id);
  m_decl_to_status.insert({tnd, status});
  return tnd;
}

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);

  SymbolFileNativePDB *pdb = static_cast<SymbolFileNativePDB *>(
      m_clang.GetSymbolFile()->GetBackingSymbolFile());
  PdbIndex &index = pdb->GetIndex();
  CVType cvt = 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 CreateFunctionType(pr.ArgumentList, pr.ReturnType, pr.CallConv);
  }

  if (cvt.kind() == LF_MFUNCTION) {
    MemberFunctionRecord mfr;
    llvm::cantFail(
        TypeDeserializer::deserializeAs<MemberFunctionRecord>(cvt, mfr));
    return CreateFunctionType(mfr.ArgumentList, mfr.ReturnType, mfr.CallConv);
  }

  return {};
}

clang::QualType PdbAstBuilder::GetOrCreateType(PdbTypeSymId type) {
  if (type.index.isNoneType())
    return {};

  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;

  SymbolFileNativePDB *pdb = static_cast<SymbolFileNativePDB *>(
      m_clang.GetSymbolFile()->GetBackingSymbolFile());
  PdbIndex &index = pdb->GetIndex();
  PdbTypeSymId best_type = GetBestPossibleDecl(type, 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);
    if (qt.isNull())
      return {};
    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);
  if (qt.isNull())
    return {};

  m_uid_to_type[toOpaqueUid(type)] = qt;
  if (IsTagRecord(type, 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::CreateFunctionDecl(PdbCompilandSymId func_id,
                                  llvm::StringRef func_name, TypeIndex func_ti,
                                  CompilerType func_ct, uint32_t param_count,
                                  clang::StorageClass func_storage,
                                  bool is_inline, clang::DeclContext *parent) {
  clang::FunctionDecl *function_decl = nullptr;
  if (parent->isRecord()) {
    SymbolFileNativePDB *pdb = static_cast<SymbolFileNativePDB *>(
        m_clang.GetSymbolFile()->GetBackingSymbolFile());
    PdbIndex &index = pdb->GetIndex();
    clang::CanQualType parent_qt =
        m_clang.getASTContext().getCanonicalTypeDeclType(
            llvm::cast<clang::TypeDecl>(parent));
    lldb::opaque_compiler_type_t parent_opaque_ty =
        ToCompilerType(parent_qt).GetOpaqueQualType();
    // FIXME: Remove this workaround.
    auto iter = m_cxx_record_map.find(parent_opaque_ty);
    if (iter != m_cxx_record_map.end()) {
      if (iter->getSecond().contains({func_name, func_ct})) {
        return nullptr;
      }
    }

    CVType cvt = index.tpi().getType(func_ti);
    MemberFunctionRecord func_record(static_cast<TypeRecordKind>(cvt.kind()));
    llvm::cantFail(TypeDeserializer::deserializeAs<MemberFunctionRecord>(
        cvt, func_record));
    TypeIndex class_index = func_record.getClassType();

    CVType parent_cvt = index.tpi().getType(class_index);
    TagRecord tag_record = CVTagRecord::create(parent_cvt).asTag();
    // If it's a forward reference, try to get the real TypeIndex.
    if (tag_record.isForwardRef()) {
      llvm::Expected<TypeIndex> eti =
          index.tpi().findFullDeclForForwardRef(class_index);
      if (eti) {
        tag_record = CVTagRecord::create(index.tpi().getType(*eti)).asTag();
      }
    }

    ConstString mangled_name(
        pdb->FindMangledFunctionName(func_id).value_or(llvm::StringRef()));

    if (!tag_record.FieldList.isSimple()) {
      CVType field_list_cvt = index.tpi().getType(tag_record.FieldList);
      FieldListRecord field_list;
      if (llvm::Error error = TypeDeserializer::deserializeAs<FieldListRecord>(
              field_list_cvt, field_list))
        llvm::consumeError(std::move(error));
      CreateMethodDecl process(index, m_clang, func_ti, function_decl,
                               parent_opaque_ty, func_name, mangled_name,
                               func_ct);
      if (llvm::Error err = visitMemberRecordStream(field_list.Data, process))
        llvm::consumeError(std::move(err));
    }

    if (!function_decl) {
      function_decl = m_clang.AddMethodToCXXRecordType(
          parent_opaque_ty, func_name, mangled_name, func_ct,
          /*access=*/lldb::AccessType::eAccessPublic,
          /*is_virtual=*/false, /*is_static=*/false,
          /*is_inline=*/false, /*is_explicit=*/false,
          /*is_attr_used=*/false, /*is_artificial=*/false);
    }
    m_cxx_record_map[parent_opaque_ty].insert({func_name, func_ct});
  } else {
    function_decl = m_clang.CreateFunctionDeclaration(
        parent, OptionalClangModuleID(), func_name, func_ct, func_storage,
        is_inline, /*asm_label=*/{});
    CreateFunctionParameters(func_id, *function_decl, param_count);
  }
  return function_decl;
}

clang::FunctionDecl *
PdbAstBuilder::GetOrCreateInlinedFunctionDecl(PdbCompilandSymId inlinesite_id) {
  SymbolFileNativePDB *pdb = static_cast<SymbolFileNativePDB *>(
      m_clang.GetSymbolFile()->GetBackingSymbolFile());
  PdbIndex &index = pdb->GetIndex();
  CompilandIndexItem *cii =
      index.compilands().GetCompiland(inlinesite_id.modi);
  CVSymbol sym = cii->m_debug_stream.readSymbolAtOffset(inlinesite_id.offset);
  InlineSiteSym inline_site(static_cast<SymbolRecordKind>(sym.kind()));
  cantFail(SymbolDeserializer::deserializeAs<InlineSiteSym>(sym, inline_site));

  // Inlinee is the id index to the function id record that is inlined.
  PdbTypeSymId func_id(inline_site.Inlinee, true);
  // Look up the function decl by the id index to see if we have created a
  // function decl for a different inlinesite that refers the same function.
  if (clang::Decl *decl = TryGetDecl(func_id))
    return llvm::dyn_cast<clang::FunctionDecl>(decl);
  clang::FunctionDecl *function_decl =
      CreateFunctionDeclFromId(func_id, inlinesite_id);
  if (function_decl == nullptr)
    return nullptr;

  // Use inline site id in m_decl_to_status because it's expected to be a
  // PdbCompilandSymId so that we can parse local variables info after it.
  uint64_t inlinesite_uid = toOpaqueUid(inlinesite_id);
  DeclStatus status;
  status.resolved = true;
  status.uid = inlinesite_uid;
  m_decl_to_status.insert({function_decl, status});
  // Use the index in IPI stream as uid in m_uid_to_decl, because index in IPI
  // stream are unique and there could be multiple inline sites (different ids)
  // referring the same inline function. This avoid creating multiple same
  // inline function delcs.
  uint64_t func_uid = toOpaqueUid(func_id);
  lldbassert(m_uid_to_decl.count(func_uid) == 0);
  m_uid_to_decl[func_uid] = function_decl;
  return function_decl;
}

clang::FunctionDecl *
PdbAstBuilder::CreateFunctionDeclFromId(PdbTypeSymId func_tid,
                                        PdbCompilandSymId func_sid) {
  lldbassert(func_tid.is_ipi);
  SymbolFileNativePDB *pdb = static_cast<SymbolFileNativePDB *>(
      m_clang.GetSymbolFile()->GetBackingSymbolFile());
  PdbIndex &index = pdb->GetIndex();
  CVType func_cvt = index.ipi().getType(func_tid.index);
  llvm::StringRef func_name;
  TypeIndex func_ti;
  clang::DeclContext *parent = nullptr;
  switch (func_cvt.kind()) {
  case LF_MFUNC_ID: {
    MemberFuncIdRecord mfr;
    cantFail(
        TypeDeserializer::deserializeAs<MemberFuncIdRecord>(func_cvt, mfr));
    func_name = mfr.getName();
    func_ti = mfr.getFunctionType();
    PdbTypeSymId class_type_id(mfr.ClassType, false);
    parent = GetOrCreateDeclContextForUid(class_type_id);
    break;
  }
  case LF_FUNC_ID: {
    FuncIdRecord fir;
    cantFail(TypeDeserializer::deserializeAs<FuncIdRecord>(func_cvt, fir));
    func_name = fir.getName();
    func_ti = fir.getFunctionType();
    parent = FromCompilerDeclContext(GetTranslationUnitDecl());
    if (!fir.ParentScope.isNoneType()) {
      CVType parent_cvt = index.ipi().getType(fir.ParentScope);
      if (parent_cvt.kind() == LF_STRING_ID) {
        StringIdRecord sir;
        cantFail(
            TypeDeserializer::deserializeAs<StringIdRecord>(parent_cvt, sir));
        parent = GetOrCreateNamespaceDecl(sir.String.data(), *parent);
      }
    }
    break;
  }
  default:
    lldbassert(false && "Invalid function id type!");
  }
  clang::QualType func_qt = GetOrCreateType(func_ti);
  if (func_qt.isNull() || !parent)
    return nullptr;
  CompilerType func_ct = ToCompilerType(func_qt);
  uint32_t param_count =
      llvm::cast<clang::FunctionProtoType>(func_qt)->getNumParams();
  return CreateFunctionDecl(func_sid, func_name, func_ti, func_ct, param_count,
                            clang::SC_None, true, parent);
}

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));
  if (!parent)
    return nullptr;
  std::string context_name;
  if (clang::NamespaceDecl *ns = llvm::dyn_cast<clang::NamespaceDecl>(parent)) {
    context_name = ns->getQualifiedNameAsString();
  } else if (clang::TagDecl *tag = llvm::dyn_cast<clang::TagDecl>(parent)) {
    context_name = tag->getQualifiedNameAsString();
  }

  SymbolFileNativePDB *pdb = static_cast<SymbolFileNativePDB *>(
      m_clang.GetSymbolFile()->GetBackingSymbolFile());
  PdbIndex &index = pdb->GetIndex();
  CVSymbol cvs = 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);
  if (qt.isNull())
    return nullptr;

  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);

  llvm::StringRef proc_name = proc.Name;
  proc_name.consume_front(context_name);
  proc_name.consume_front("::");
  clang::FunctionDecl *function_decl =
      CreateFunctionDecl(func_id, proc_name, proc.FunctionType, func_ct,
                         func_type->getNumParams(), storage, false, parent);
  if (function_decl == nullptr)
    return nullptr;

  lldbassert(m_uid_to_decl.count(toOpaqueUid(func_id)) == 0);
  m_uid_to_decl[toOpaqueUid(func_id)] = function_decl;
  DeclStatus status;
  status.resolved = true;
  status.uid = toOpaqueUid(func_id);
  m_decl_to_status.insert({function_decl, status});

  return function_decl;
}

void PdbAstBuilder::CreateFunctionParameters(PdbCompilandSymId func_id,
                                             clang::FunctionDecl &function_decl,
                                             uint32_t param_count) {
  SymbolFileNativePDB *pdb = static_cast<SymbolFileNativePDB *>(
      m_clang.GetSymbolFile()->GetBackingSymbolFile());
  PdbIndex &index = pdb->GetIndex();
  CompilandIndexItem *cii = index.compilands().GetCompiland(func_id.modi);
  CVSymbolArray scope =
      cii->m_debug_stream.getSymbolArrayForScope(func_id.offset);

  scope.drop_front();
  auto begin = scope.begin();
  auto end = scope.end();
  std::vector<clang::ParmVarDecl *> params;
  for (uint32_t i = 0; i < param_count && begin != end;) {
    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:
    case S_INLINESITE:
    case S_INLINESITE2:
      // All parameters should come before the first block/inlinesite.  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);
    if (qt.isNull())
      return;

    CompilerType param_type_ct = m_clang.GetType(qt);
    clang::ParmVarDecl *param = m_clang.CreateParameterDeclaration(
        &function_decl, OptionalClangModuleID(), param_name.str().c_str(),
        param_type_ct, clang::SC_None, true);
    lldbassert(m_uid_to_decl.count(toOpaqueUid(param_uid)) == 0);

    m_uid_to_decl[toOpaqueUid(param_uid)] = param;
    params.push_back(param);
    ++i;
  }

  if (!params.empty() && params.size() == param_count)
    function_decl.setParams(params);
}

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);
  if (!decl_context)
    return {};

  clang::QualType underlying_type = GetOrCreateType(er.UnderlyingType);
  if (underlying_type.isNull())
    return {};

  Declaration declaration;
  CompilerType enum_ct = m_clang.CreateEnumerationType(
      uname, decl_context, OptionalClangModuleID(), declaration,
      ToCompilerType(underlying_type), er.isScoped());

  TypeSystemClang::StartTagDeclarationDefinition(enum_ct);
  TypeSystemClang::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);
  TypeSystemClang::RequireCompleteType(ToCompilerType(element_type));

  SymbolFileNativePDB *pdb = static_cast<SymbolFileNativePDB *>(
      m_clang.GetSymbolFile()->GetBackingSymbolFile());
  PdbIndex &index = pdb->GetIndex();
  uint64_t element_size = GetSizeOfType({ar.ElementType}, index.tpi());
  if (element_type.isNull() || element_size == 0)
    return {};
  uint64_t element_count = ar.Size / element_size;

  CompilerType array_ct = m_clang.CreateArrayType(ToCompilerType(element_type),
                                                  element_count, false);
  return clang::QualType::getFromOpaquePtr(array_ct.GetOpaqueQualType());
}

clang::QualType PdbAstBuilder::CreateFunctionType(
    TypeIndex args_type_idx, TypeIndex return_type_idx,
    llvm::codeview::CallingConvention calling_convention) {
  SymbolFileNativePDB *pdb = static_cast<SymbolFileNativePDB *>(
      m_clang.GetSymbolFile()->GetBackingSymbolFile());
  PdbIndex &index = pdb->GetIndex();
  TpiStream &stream = index.tpi();
  CVType args_cvt = stream.getType(args_type_idx);
  ArgListRecord args;
  llvm::cantFail(
      TypeDeserializer::deserializeAs<ArgListRecord>(args_cvt, args));

  llvm::ArrayRef<TypeIndex> arg_indices = llvm::ArrayRef(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);
    if (arg_type.isNull())
      continue;
    arg_types.push_back(ToCompilerType(arg_type));
  }

  clang::QualType return_type = GetOrCreateType(return_type_idx);
  if (return_type.isNull())
    return {};

  std::optional<clang::CallingConv> cc =
      TranslateCallingConvention(calling_convention);
  if (!cc)
    return {};

  CompilerType return_ct = ToCompilerType(return_type);
  CompilerType func_sig_ast_type =
      m_clang.CreateFunctionType(return_ct, arg_types, is_variadic, 0, *cc);

  return clang::QualType::getFromOpaquePtr(
      func_sig_ast_type.GetOpaqueQualType());
}

static bool isTagDecl(clang::DeclContext &context) {
  return llvm::isa<clang::TagDecl>(&context);
}

static bool isFunctionDecl(clang::DeclContext &context) {
  return llvm::isa<clang::FunctionDecl>(&context);
}

static bool isBlockDecl(clang::DeclContext &context) {
  return llvm::isa<clang::BlockDecl>(&context);
}

void PdbAstBuilder::ParseNamespace(clang::DeclContext &context) {
  clang::NamespaceDecl *ns = llvm::dyn_cast<clang::NamespaceDecl>(&context);
  if (m_parsed_namespaces.contains(ns))
    return;
  std::string qname = ns->getQualifiedNameAsString();
  SymbolFileNativePDB *pdb = static_cast<SymbolFileNativePDB *>(
      m_clang.GetSymbolFile()->GetBackingSymbolFile());
  PdbIndex &index = pdb->GetIndex();
  TypeIndex ti{index.tpi().TypeIndexBegin()};
  for (const CVType &cvt : index.tpi().typeArray()) {
    PdbTypeSymId tid{ti};
    ++ti;

    if (!IsTagRecord(cvt))
      continue;

    CVTagRecord tag = CVTagRecord::create(cvt);

    // Call CreateDeclInfoForType unconditionally so that the namespace info
    // gets created.  But only call CreateRecordType if the namespace name
    // matches.
    clang::DeclContext *context = nullptr;
    std::string uname;
    std::tie(context, uname) = CreateDeclInfoForType(tag.asTag(), tid.index);
    if (!context || !context->isNamespace())
      continue;

    clang::NamespaceDecl *ns = llvm::cast<clang::NamespaceDecl>(context);
    llvm::StringRef ns_name = ns->getName();
    if (ns_name.starts_with(qname)) {
      ns_name = ns_name.drop_front(qname.size());
      if (ns_name.starts_with("::"))
        GetOrCreateType(tid);
    }
  }
  ParseAllFunctionsAndNonLocalVars();
  m_parsed_namespaces.insert(ns);
}

void PdbAstBuilder::ParseAllTypes() {
  llvm::call_once(m_parse_all_types, [this]() {
    SymbolFileNativePDB *pdb = static_cast<SymbolFileNativePDB *>(
        m_clang.GetSymbolFile()->GetBackingSymbolFile());
    PdbIndex &index = pdb->GetIndex();
    TypeIndex ti{index.tpi().TypeIndexBegin()};
    for (const CVType &cvt : index.tpi().typeArray()) {
      PdbTypeSymId tid{ti};
      ++ti;

      if (!IsTagRecord(cvt))
        continue;

      GetOrCreateType(tid);
    }
  });
}

void PdbAstBuilder::ParseAllFunctionsAndNonLocalVars() {
  llvm::call_once(m_parse_functions_and_non_local_vars, [this]() {
    SymbolFileNativePDB *pdb = static_cast<SymbolFileNativePDB *>(
        m_clang.GetSymbolFile()->GetBackingSymbolFile());
    PdbIndex &index = pdb->GetIndex();
    uint32_t module_count = index.dbi().modules().getModuleCount();
    for (uint16_t modi = 0; modi < module_count; ++modi) {
      CompilandIndexItem &cii = index.compilands().GetOrCreateCompiland(modi);
      const CVSymbolArray &symbols = cii.m_debug_stream.getSymbolArray();
      auto iter = symbols.begin();
      while (iter != symbols.end()) {
        PdbCompilandSymId sym_id{modi, iter.offset()};

        switch (iter->kind()) {
        case S_GPROC32:
        case S_LPROC32:
          GetOrCreateFunctionDecl(sym_id);
          iter = symbols.at(getScopeEndOffset(*iter));
          break;
        case S_GDATA32:
        case S_GTHREAD32:
        case S_LDATA32:
        case S_LTHREAD32:
          GetOrCreateVariableDecl(PdbCompilandSymId(modi, 0), sym_id);
          ++iter;
          break;
        default:
          ++iter;
          continue;
        }
      }
    }
  });
}

static CVSymbolArray skipFunctionParameters(clang::Decl &decl,
                                            const CVSymbolArray &symbols) {
  clang::FunctionDecl *func_decl = llvm::dyn_cast<clang::FunctionDecl>(&decl);
  if (!func_decl)
    return symbols;
  unsigned int params = func_decl->getNumParams();
  if (params == 0)
    return symbols;

  CVSymbolArray result = symbols;

  while (!result.empty()) {
    if (params == 0)
      return result;

    CVSymbol sym = *result.begin();
    result.drop_front();

    if (!isLocalVariableType(sym.kind()))
      continue;

    --params;
  }
  return result;
}

void PdbAstBuilder::ParseBlockChildren(PdbCompilandSymId block_id) {
  SymbolFileNativePDB *pdb = static_cast<SymbolFileNativePDB *>(
      m_clang.GetSymbolFile()->GetBackingSymbolFile());
  PdbIndex &index = pdb->GetIndex();
  CVSymbol sym = index.ReadSymbolRecord(block_id);
  lldbassert(sym.kind() == S_GPROC32 || sym.kind() == S_LPROC32 ||
             sym.kind() == S_BLOCK32 || sym.kind() == S_INLINESITE);
  CompilandIndexItem &cii =
      index.compilands().GetOrCreateCompiland(block_id.modi);
  CVSymbolArray symbols =
      cii.m_debug_stream.getSymbolArrayForScope(block_id.offset);

  // Function parameters should already have been created when the function was
  // parsed.
  if (sym.kind() == S_GPROC32 || sym.kind() == S_LPROC32)
    symbols =
        skipFunctionParameters(*m_uid_to_decl[toOpaqueUid(block_id)], symbols);

  symbols.drop_front();
  auto begin = symbols.begin();
  while (begin != symbols.end()) {
    PdbCompilandSymId child_sym_id(block_id.modi, begin.offset());
    GetOrCreateSymbolForId(child_sym_id);
    if (begin->kind() == S_BLOCK32 || begin->kind() == S_INLINESITE) {
      ParseBlockChildren(child_sym_id);
      begin = symbols.at(getScopeEndOffset(*begin));
    }
    ++begin;
  }
}

void PdbAstBuilder::ParseDeclsForSimpleContext(clang::DeclContext &context) {

  clang::Decl *decl = clang::Decl::castFromDeclContext(&context);
  lldbassert(decl);

  auto iter = m_decl_to_status.find(decl);
  lldbassert(iter != m_decl_to_status.end());

  if (auto *tag = llvm::dyn_cast<clang::TagDecl>(&context)) {
    CompleteTagDecl(*tag);
    return;
  }

  if (isFunctionDecl(context) || isBlockDecl(context)) {
    PdbCompilandSymId block_id = PdbSymUid(iter->second.uid).asCompilandSym();
    ParseBlockChildren(block_id);
  }
}

void PdbAstBuilder::ParseDeclsForContext(clang::DeclContext &context) {
  // Namespaces aren't explicitly represented in the debug info, and the only
  // way to parse them is to parse all type info, demangling every single type
  // and trying to reconstruct the DeclContext hierarchy this way.  Since this
  // is an expensive operation, we have to special case it so that we do other
  // work (such as parsing the items that appear within the namespaces) at the
  // same time.
  if (context.isTranslationUnit()) {
    ParseAllTypes();
    ParseAllFunctionsAndNonLocalVars();
    return;
  }

  if (context.isNamespace()) {
    ParseNamespace(context);
    return;
  }

  if (isTagDecl(context) || isFunctionDecl(context) || isBlockDecl(context)) {
    ParseDeclsForSimpleContext(context);
    return;
  }
}

CompilerDecl PdbAstBuilder::ToCompilerDecl(clang::Decl &decl) {
  return m_clang.GetCompilerDecl(&decl);
}

CompilerType PdbAstBuilder::ToCompilerType(clang::QualType qt) {
  return {m_clang.weak_from_this(), qt.getAsOpaquePtr()};
}

CompilerDeclContext
PdbAstBuilder::ToCompilerDeclContext(clang::DeclContext &context) {
  return m_clang.CreateDeclContext(&context);
}

clang::Decl * PdbAstBuilder::FromCompilerDecl(CompilerDecl decl) {
  return ClangUtil::GetDecl(decl);
}

clang::DeclContext *
PdbAstBuilder::FromCompilerDeclContext(CompilerDeclContext context) {
  return static_cast<clang::DeclContext *>(context.GetOpaqueDeclContext());
}

void PdbAstBuilder::Dump(Stream &stream, llvm::StringRef filter,
                         bool show_color) {
  m_clang.Dump(stream.AsRawOstream(), filter, show_color);
}

clang::NamespaceDecl *
PdbAstBuilder::FindNamespaceDecl(const clang::DeclContext *parent,
                                 llvm::StringRef name) {
  NamespaceSet *set;
  if (parent) {
    auto it = m_parent_to_namespaces.find(parent);
    if (it == m_parent_to_namespaces.end())
      return nullptr;

    set = &it->second;
  } else {
    // In this case, search through all known namespaces
    set = &m_known_namespaces;
  }
  assert(set);

  for (clang::NamespaceDecl *namespace_decl : *set)
    if (namespace_decl->getName() == name)
      return namespace_decl;

  for (clang::NamespaceDecl *namespace_decl : *set)
    if (namespace_decl->isAnonymousNamespace())
      return FindNamespaceDecl(namespace_decl, name);

  return nullptr;
}
