#include "PdbAstBuilderClang.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.getOptions(), method.Attrs);
    }

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

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

  void AddMethod(llvm::StringRef name, MethodOptions options,
                 MemberAttributes attrs) {
    if (name != proc_name || function_decl)
      return;
    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,
        /*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'";
}

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

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

std::pair<clang::DeclContext *, std::string>
PdbAstBuilderClang::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 = GetOrCreateClangType(*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_REGREL32_INDIR:
  case S_LOCAL:
    return true;
  default:
    break;
  }
  return false;
}

clang::Decl *PdbAstBuilderClang::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 = GetParentClangDeclContext(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;
  }
}

CompilerDecl PdbAstBuilderClang::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 = GetOrCreateClangType(uid.asTypeSym());
    if (qt.isNull())
      return CompilerDecl();
    if (auto *tag = qt->getAsTagDecl()) {
      result = tag;
      break;
    }
    return CompilerDecl();
  }
  default:
    return CompilerDecl();
  }

  if (!result)
    return CompilerDecl();
  m_uid_to_decl[toOpaqueUid(uid)] = result;
  return ToCompilerDecl(result);
}

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

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

CompilerDeclContext
PdbAstBuilderClang::GetOrCreateDeclContextForUid(PdbSymUid uid) {
  return ToCompilerDeclContext(GetOrCreateClangDeclContextForUid(uid));
}

std::pair<clang::DeclContext *, std::string>
PdbAstBuilderClang::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 = GetOrCreateClangType(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 *
PdbAstBuilderClang::GetParentClangDeclContext(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 GetOrCreateClangDeclContextForUid(*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 GetOrCreateClangDeclContextForUid(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 GetParentClangDeclContext(cu_sym_id);
    }
    case SymbolKind::S_CONSTANT:
    case SymbolKind::S_UDT:
      return CreateDeclInfoForUndecoratedName(getSymbolName(global)).first;
    default:
      break;
    }
    break;
  }
  default:
    break;
  }
  return FromCompilerDeclContext(GetTranslationUnitDecl());
}

CompilerDeclContext PdbAstBuilderClang::GetParentDeclContext(PdbSymUid uid) {
  return ToCompilerDeclContext(GetParentClangDeclContext(uid));
}

bool PdbAstBuilderClang::CompleteType(CompilerType ct) {
  if (GetClangASTImporter().CanImport(ct))
    return GetClangASTImporter().CompleteType(ct);

  clang::QualType qt = FromCompilerType(ct);
  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 PdbAstBuilderClang::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 PdbAstBuilderClang::CreateSimpleType(TypeIndex ti) {
  if (ti == TypeIndex::NullptrT())
    return GetBasicType(lldb::eBasicTypeNullPtr);

  if (ti.getSimpleMode() != SimpleTypeMode::Direct) {
    clang::QualType direct_type = GetOrCreateClangType(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
PdbAstBuilderClang::CreatePointerType(const PointerRecord &pointer) {
  clang::QualType pointee_type = GetOrCreateClangType(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 = GetOrCreateClangType(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
PdbAstBuilderClang::CreateModifierType(const ModifierRecord &modifier) {
  clang::QualType unmodified_type = GetOrCreateClangType(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 PdbAstBuilderClang::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);
  ClangASTMetadata metadata;
  metadata.SetUserID(toOpaqueUid(id));
  metadata.SetIsDynamicCXXType(false);

  CompilerType ct = m_clang.CreateRecordType(
      context, OptionalClangModuleID(), 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 *PdbAstBuilderClang::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 *
PdbAstBuilderClang::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 *
PdbAstBuilderClang::GetOrCreateBlockDecl(PdbCompilandSymId block_id) {
  if (clang::Decl *decl = TryGetDecl(block_id))
    return llvm::dyn_cast<clang::BlockDecl>(decl);

  clang::DeclContext *scope = GetParentClangDeclContext(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 *
PdbAstBuilderClang::CreateVariableDecl(PdbSymUid uid, CVSymbol sym,
                                       clang::DeclContext &scope) {
  VariableInfo var_info = GetVariableNameInfo(sym);
  clang::QualType qt = GetOrCreateClangType(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 *
PdbAstBuilderClang::GetOrCreateVariableDecl(PdbCompilandSymId scope_id,
                                            PdbCompilandSymId var_id) {
  if (clang::Decl *decl = TryGetDecl(var_id))
    return llvm::dyn_cast<clang::VarDecl>(decl);

  clang::DeclContext *scope = GetOrCreateClangDeclContextForUid(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 *
PdbAstBuilderClang::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);
}

CompilerType PdbAstBuilderClang::GetOrCreateTypedefType(PdbGlobalSymId id) {
  if (clang::Decl *decl = TryGetDecl(id)) {
    if (auto *tnd = llvm::dyn_cast<clang::TypedefNameDecl>(decl))
      return ToCompilerType(m_clang.getASTContext().getTypeDeclType(tnd));
    return CompilerType();
  }

  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 = GetParentClangDeclContext(id);

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

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

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

clang::QualType PdbAstBuilderClang::GetBasicType(lldb::BasicType type) {
  CompilerType ct = m_clang.GetBasicType(type);
  return clang::QualType::getFromOpaquePtr(ct.GetOpaqueQualType());
}

clang::QualType PdbAstBuilderClang::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 PdbAstBuilderClang::GetOrCreateClangType(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 = GetOrCreateClangType(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;
}

CompilerType PdbAstBuilderClang::GetOrCreateType(PdbTypeSymId type) {
  clang::QualType qt = GetOrCreateClangType(type);
  if (qt.isNull())
    return {};
  return ToCompilerType(qt);
}

clang::FunctionDecl *PdbAstBuilderClang::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,
          /*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 *PdbAstBuilderClang::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 *
PdbAstBuilderClang::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();
  std::optional<CVType> func_cvt =
      index.ipi().typeCollection().tryGetType(func_tid.index);
  if (!func_cvt)
    return nullptr;
  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 = GetOrCreateClangDeclContextForUid(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 = GetOrCreateClangType(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 *
PdbAstBuilderClang::GetOrCreateFunctionDecl(PdbCompilandSymId func_id) {
  if (clang::Decl *decl = TryGetDecl(func_id))
    return llvm::dyn_cast<clang::FunctionDecl>(decl);

  clang::DeclContext *parent = GetParentClangDeclContext(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 = GetOrCreateClangType(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 PdbAstBuilderClang::EnsureFunction(PdbCompilandSymId func_id) {
  GetOrCreateFunctionDecl(func_id);
}

void PdbAstBuilderClang::EnsureInlinedFunction(
    PdbCompilandSymId inlinesite_id) {
  GetOrCreateInlinedFunctionDecl(inlinesite_id);
}

void PdbAstBuilderClang::EnsureBlock(PdbCompilandSymId block_id) {
  GetOrCreateBlockDecl(block_id);
}

void PdbAstBuilderClang::EnsureVariable(PdbCompilandSymId scope_id,
                                        PdbCompilandSymId var_id) {
  GetOrCreateVariableDecl(scope_id, var_id);
}

void PdbAstBuilderClang::EnsureVariable(PdbGlobalSymId var_id) {
  GetOrCreateVariableDecl(var_id);
}

void PdbAstBuilderClang::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_REGREL32_INDIR: {
      RegRelativeIndirSym reg(SymbolRecordKind::RegRelativeIndirSym);
      cantFail(
          SymbolDeserializer::deserializeAs<RegRelativeIndirSym>(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 = GetOrCreateClangType(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 PdbAstBuilderClang::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 = GetOrCreateClangType(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 PdbAstBuilderClang::CreateArrayType(const ArrayRecord &ar) {
  clang::QualType element_type = GetOrCreateClangType(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 PdbAstBuilderClang::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 = GetOrCreateClangType(arg_index);
    if (arg_type.isNull())
      continue;
    arg_types.push_back(ToCompilerType(arg_type));
  }

  clang::QualType return_type = GetOrCreateClangType(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 PdbAstBuilderClang::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("::"))
        GetOrCreateClangType(tid);
    }
  }
  ParseAllFunctionsAndNonLocalVars();
  m_parsed_namespaces.insert(ns);
}

void PdbAstBuilderClang::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;

      GetOrCreateClangType(tid);
    }
  });
}

void PdbAstBuilderClang::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 PdbAstBuilderClang::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 PdbAstBuilderClang::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 PdbAstBuilderClang::ParseDeclsForContext(CompilerDeclContext context) {
  clang::DeclContext *dc = FromCompilerDeclContext(context);
  if (!dc)
    return;

  // 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 (dc->isTranslationUnit()) {
    ParseAllTypes();
    ParseAllFunctionsAndNonLocalVars();
    return;
  }

  if (dc->isNamespace()) {
    ParseNamespace(*dc);
    return;
  }

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

CompilerDecl PdbAstBuilderClang::ToCompilerDecl(clang::Decl *decl) {
  return m_clang.GetCompilerDecl(decl);
}

CompilerType PdbAstBuilderClang::ToCompilerType(clang::QualType qt) {
  return m_clang.GetType(qt);
}

clang::QualType PdbAstBuilderClang::FromCompilerType(CompilerType ct) {
  return ClangUtil::GetQualType(ct);
}

CompilerDeclContext
PdbAstBuilderClang::ToCompilerDeclContext(clang::DeclContext *context) {
  return m_clang.CreateDeclContext(context);
}

clang::Decl *PdbAstBuilderClang::FromCompilerDecl(CompilerDecl decl) {
  if (decl.GetTypeSystem() != nullptr)
    return ClangUtil::GetDecl(decl);
  return nullptr;
}

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

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

CompilerDeclContext
PdbAstBuilderClang::FindNamespaceDecl(CompilerDeclContext parent_ctx,
                                      llvm::StringRef name) {
  clang::DeclContext *parent = FromCompilerDeclContext(parent_ctx);
  NamespaceSet *set;

  if (parent) {
    auto it = m_parent_to_namespaces.find(parent);
    if (it == m_parent_to_namespaces.end())
      return {};

    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 ToCompilerDeclContext(namespace_decl);

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

  return {};
}
