//===-- PDBASTParser.cpp --------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "PDBASTParser.h"

#include "SymbolFilePDB.h"

#include "clang/AST/CharUnits.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"

#include "Plugins/ExpressionParser/Clang/ClangASTMetadata.h"
#include "Plugins/ExpressionParser/Clang/ClangUtil.h"
#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
#include "lldb/Core/Declaration.h"
#include "lldb/Core/Module.h"
#include "lldb/Symbol/SymbolFile.h"
#include "lldb/Symbol/TypeMap.h"
#include "lldb/Symbol/TypeSystem.h"
#include "lldb/Utility/LLDBLog.h"
#include "llvm/DebugInfo/PDB/ConcreteSymbolEnumerator.h"
#include "llvm/DebugInfo/PDB/IPDBLineNumber.h"
#include "llvm/DebugInfo/PDB/IPDBSourceFile.h"
#include "llvm/DebugInfo/PDB/PDBSymbol.h"
#include "llvm/DebugInfo/PDB/PDBSymbolData.h"
#include "llvm/DebugInfo/PDB/PDBSymbolFunc.h"
#include "llvm/DebugInfo/PDB/PDBSymbolTypeArray.h"
#include "llvm/DebugInfo/PDB/PDBSymbolTypeBaseClass.h"
#include "llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h"
#include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h"
#include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionArg.h"
#include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h"
#include "llvm/DebugInfo/PDB/PDBSymbolTypePointer.h"
#include "llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h"
#include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h"

#include "Plugins/Language/CPlusPlus/MSVCUndecoratedNameParser.h"
#include <optional>

using namespace lldb;
using namespace lldb_private;
using namespace llvm::pdb;

static int TranslateUdtKind(PDB_UdtType pdb_kind) {
  switch (pdb_kind) {
  case PDB_UdtType::Class:
    return llvm::to_underlying(clang::TagTypeKind::Class);
  case PDB_UdtType::Struct:
    return llvm::to_underlying(clang::TagTypeKind::Struct);
  case PDB_UdtType::Union:
    return llvm::to_underlying(clang::TagTypeKind::Union);
  case PDB_UdtType::Interface:
    return llvm::to_underlying(clang::TagTypeKind::Interface);
  }
  llvm_unreachable("unsuported PDB UDT type");
}

static lldb::Encoding TranslateBuiltinEncoding(PDB_BuiltinType type) {
  switch (type) {
  case PDB_BuiltinType::Float:
    return lldb::eEncodingIEEE754;
  case PDB_BuiltinType::Int:
  case PDB_BuiltinType::Long:
  case PDB_BuiltinType::Char:
    return lldb::eEncodingSint;
  case PDB_BuiltinType::Bool:
  case PDB_BuiltinType::Char16:
  case PDB_BuiltinType::Char32:
  case PDB_BuiltinType::UInt:
  case PDB_BuiltinType::ULong:
  case PDB_BuiltinType::HResult:
  case PDB_BuiltinType::WCharT:
    return lldb::eEncodingUint;
  default:
    return lldb::eEncodingInvalid;
  }
}

static lldb::Encoding TranslateEnumEncoding(PDB_VariantType type) {
  switch (type) {
  case PDB_VariantType::Int8:
  case PDB_VariantType::Int16:
  case PDB_VariantType::Int32:
  case PDB_VariantType::Int64:
    return lldb::eEncodingSint;

  case PDB_VariantType::UInt8:
  case PDB_VariantType::UInt16:
  case PDB_VariantType::UInt32:
  case PDB_VariantType::UInt64:
    return lldb::eEncodingUint;

  default:
    break;
  }

  return lldb::eEncodingSint;
}

static CompilerType
GetBuiltinTypeForPDBEncodingAndBitSize(TypeSystemClang &clang_ast,
                                       const PDBSymbolTypeBuiltin &pdb_type,
                                       Encoding encoding, uint32_t width) {
  clang::ASTContext &ast = clang_ast.getASTContext();

  switch (pdb_type.getBuiltinType()) {
  default:
    break;
  case PDB_BuiltinType::None:
    return CompilerType();
  case PDB_BuiltinType::Void:
    return clang_ast.GetBasicType(eBasicTypeVoid);
  case PDB_BuiltinType::Char:
    return clang_ast.GetBasicType(eBasicTypeChar);
  case PDB_BuiltinType::Bool:
    return clang_ast.GetBasicType(eBasicTypeBool);
  case PDB_BuiltinType::Long:
    if (width == ast.getTypeSize(ast.LongTy))
      return CompilerType(clang_ast.weak_from_this(),
                          ast.LongTy.getAsOpaquePtr());
    if (width == ast.getTypeSize(ast.LongLongTy))
      return CompilerType(clang_ast.weak_from_this(),
                          ast.LongLongTy.getAsOpaquePtr());
    break;
  case PDB_BuiltinType::ULong:
    if (width == ast.getTypeSize(ast.UnsignedLongTy))
      return CompilerType(clang_ast.weak_from_this(),
                          ast.UnsignedLongTy.getAsOpaquePtr());
    if (width == ast.getTypeSize(ast.UnsignedLongLongTy))
      return CompilerType(clang_ast.weak_from_this(),
                          ast.UnsignedLongLongTy.getAsOpaquePtr());
    break;
  case PDB_BuiltinType::WCharT:
    if (width == ast.getTypeSize(ast.WCharTy))
      return CompilerType(clang_ast.weak_from_this(),
                          ast.WCharTy.getAsOpaquePtr());
    break;
  case PDB_BuiltinType::Char16:
    return CompilerType(clang_ast.weak_from_this(),
                        ast.Char16Ty.getAsOpaquePtr());
  case PDB_BuiltinType::Char32:
    return CompilerType(clang_ast.weak_from_this(),
                        ast.Char32Ty.getAsOpaquePtr());
  case PDB_BuiltinType::Float:
    // Note: types `long double` and `double` have same bit size in MSVC and
    // there is no information in the PDB to distinguish them. So when falling
    // back to default search, the compiler type of `long double` will be
    // represented by the one generated for `double`.
    break;
  }
  // If there is no match on PDB_BuiltinType, fall back to default search by
  // encoding and width only
  return clang_ast.GetBuiltinTypeForEncodingAndBitSize(encoding, width);
}

static ConstString GetPDBBuiltinTypeName(const PDBSymbolTypeBuiltin &pdb_type,
                                         CompilerType &compiler_type) {
  PDB_BuiltinType kind = pdb_type.getBuiltinType();
  switch (kind) {
  default:
    break;
  case PDB_BuiltinType::Currency:
    return ConstString("CURRENCY");
  case PDB_BuiltinType::Date:
    return ConstString("DATE");
  case PDB_BuiltinType::Variant:
    return ConstString("VARIANT");
  case PDB_BuiltinType::Complex:
    return ConstString("complex");
  case PDB_BuiltinType::Bitfield:
    return ConstString("bitfield");
  case PDB_BuiltinType::BSTR:
    return ConstString("BSTR");
  case PDB_BuiltinType::HResult:
    return ConstString("HRESULT");
  case PDB_BuiltinType::BCD:
    return ConstString("BCD");
  case PDB_BuiltinType::Char16:
    return ConstString("char16_t");
  case PDB_BuiltinType::Char32:
    return ConstString("char32_t");
  case PDB_BuiltinType::None:
    return ConstString("...");
  }
  return compiler_type.GetTypeName();
}

static bool AddSourceInfoToDecl(const PDBSymbol &symbol, Declaration &decl) {
  auto &raw_sym = symbol.getRawSymbol();
  auto first_line_up = raw_sym.getSrcLineOnTypeDefn();

  if (!first_line_up) {
    auto lines_up = symbol.getSession().findLineNumbersByAddress(
        raw_sym.getVirtualAddress(), raw_sym.getLength());
    if (!lines_up)
      return false;
    first_line_up = lines_up->getNext();
    if (!first_line_up)
      return false;
  }
  uint32_t src_file_id = first_line_up->getSourceFileId();
  auto src_file_up = symbol.getSession().getSourceFileById(src_file_id);
  if (!src_file_up)
    return false;

  FileSpec spec(src_file_up->getFileName());
  decl.SetFile(spec);
  decl.SetColumn(first_line_up->getColumnNumber());
  decl.SetLine(first_line_up->getLineNumber());
  return true;
}

static AccessType TranslateMemberAccess(PDB_MemberAccess access) {
  switch (access) {
  case PDB_MemberAccess::Private:
    return eAccessPrivate;
  case PDB_MemberAccess::Protected:
    return eAccessProtected;
  case PDB_MemberAccess::Public:
    return eAccessPublic;
  }
  return eAccessNone;
}

static AccessType GetDefaultAccessibilityForUdtKind(PDB_UdtType udt_kind) {
  switch (udt_kind) {
  case PDB_UdtType::Struct:
  case PDB_UdtType::Union:
    return eAccessPublic;
  case PDB_UdtType::Class:
  case PDB_UdtType::Interface:
    return eAccessPrivate;
  }
  llvm_unreachable("unsupported PDB UDT type");
}

static AccessType GetAccessibilityForUdt(const PDBSymbolTypeUDT &udt) {
  AccessType access = TranslateMemberAccess(udt.getAccess());
  if (access != lldb::eAccessNone || !udt.isNested())
    return access;

  auto parent = udt.getClassParent();
  if (!parent)
    return lldb::eAccessNone;

  auto parent_udt = llvm::dyn_cast<PDBSymbolTypeUDT>(parent.get());
  if (!parent_udt)
    return lldb::eAccessNone;

  return GetDefaultAccessibilityForUdtKind(parent_udt->getUdtKind());
}

static clang::MSInheritanceAttr::Spelling
GetMSInheritance(const PDBSymbolTypeUDT &udt) {
  int base_count = 0;
  bool has_virtual = false;

  auto bases_enum = udt.findAllChildren<PDBSymbolTypeBaseClass>();
  if (bases_enum) {
    while (auto base = bases_enum->getNext()) {
      base_count++;
      has_virtual |= base->isVirtualBaseClass();
    }
  }

  if (has_virtual)
    return clang::MSInheritanceAttr::Keyword_virtual_inheritance;
  if (base_count > 1)
    return clang::MSInheritanceAttr::Keyword_multiple_inheritance;
  return clang::MSInheritanceAttr::Keyword_single_inheritance;
}

static std::unique_ptr<llvm::pdb::PDBSymbol>
GetClassOrFunctionParent(const llvm::pdb::PDBSymbol &symbol) {
  const IPDBSession &session = symbol.getSession();
  const IPDBRawSymbol &raw = symbol.getRawSymbol();
  auto tag = symbol.getSymTag();

  // For items that are nested inside of a class, return the class that it is
  // nested inside of.
  // Note that only certain items can be nested inside of classes.
  switch (tag) {
  case PDB_SymType::Function:
  case PDB_SymType::Data:
  case PDB_SymType::UDT:
  case PDB_SymType::Enum:
  case PDB_SymType::FunctionSig:
  case PDB_SymType::Typedef:
  case PDB_SymType::BaseClass:
  case PDB_SymType::VTable: {
    auto class_parent_id = raw.getClassParentId();
    if (auto class_parent = session.getSymbolById(class_parent_id))
      return class_parent;
    break;
  }
  default:
    break;
  }

  // Otherwise, if it is nested inside of a function, return the function.
  // Note that only certain items can be nested inside of functions.
  switch (tag) {
  case PDB_SymType::Block:
  case PDB_SymType::Data: {
    auto lexical_parent_id = raw.getLexicalParentId();
    auto lexical_parent = session.getSymbolById(lexical_parent_id);
    if (!lexical_parent)
      return nullptr;

    auto lexical_parent_tag = lexical_parent->getSymTag();
    if (lexical_parent_tag == PDB_SymType::Function)
      return lexical_parent;
    if (lexical_parent_tag == PDB_SymType::Exe)
      return nullptr;

    return GetClassOrFunctionParent(*lexical_parent);
  }
  default:
    return nullptr;
  }
}

static clang::NamedDecl *
GetDeclFromContextByName(const clang::ASTContext &ast,
                         const clang::DeclContext &decl_context,
                         llvm::StringRef name) {
  clang::IdentifierInfo &ident = ast.Idents.get(name);
  clang::DeclarationName decl_name = ast.DeclarationNames.getIdentifier(&ident);
  clang::DeclContext::lookup_result result = decl_context.lookup(decl_name);
  if (result.empty())
    return nullptr;

  return *result.begin();
}

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

static clang::CallingConv TranslateCallingConvention(PDB_CallingConv pdb_cc) {
  switch (pdb_cc) {
  case llvm::codeview::CallingConvention::NearC:
    return clang::CC_C;
  case llvm::codeview::CallingConvention::NearStdCall:
    return clang::CC_X86StdCall;
  case llvm::codeview::CallingConvention::NearFast:
    return clang::CC_X86FastCall;
  case llvm::codeview::CallingConvention::ThisCall:
    return clang::CC_X86ThisCall;
  case llvm::codeview::CallingConvention::NearVector:
    return clang::CC_X86VectorCall;
  case llvm::codeview::CallingConvention::NearPascal:
    return clang::CC_X86Pascal;
  default:
    assert(false && "Unknown calling convention");
    return clang::CC_C;
  }
}

PDBASTParser::PDBASTParser(lldb_private::TypeSystemClang &ast) : m_ast(ast) {}

PDBASTParser::~PDBASTParser() = default;

// DebugInfoASTParser interface

lldb::TypeSP PDBASTParser::CreateLLDBTypeFromPDBType(const PDBSymbol &type) {
  Declaration decl;
  switch (type.getSymTag()) {
  case PDB_SymType::BaseClass: {
    auto symbol_file = m_ast.GetSymbolFile();
    if (!symbol_file)
      return nullptr;

    auto ty = symbol_file->ResolveTypeUID(type.getRawSymbol().getTypeId());
    return ty ? ty->shared_from_this() : nullptr;
  } break;
  case PDB_SymType::UDT: {
    auto udt = llvm::dyn_cast<PDBSymbolTypeUDT>(&type);
    assert(udt);

    // Note that, unnamed UDT being typedef-ed is generated as a UDT symbol
    // other than a Typedef symbol in PDB. For example,
    //    typedef union { short Row; short Col; } Union;
    // is generated as a named UDT in PDB:
    //    union Union { short Row; short Col; }
    // Such symbols will be handled here.

    // Some UDT with trival ctor has zero length. Just ignore.
    if (udt->getLength() == 0)
      return nullptr;

    // Ignore unnamed-tag UDTs.
    std::string name =
        std::string(MSVCUndecoratedNameParser::DropScope(udt->getName()));
    if (name.empty())
      return nullptr;

    auto decl_context = GetDeclContextContainingSymbol(type);

    // Check if such an UDT already exists in the current context.
    // This may occur with const or volatile types. There are separate type
    // symbols in PDB for types with const or volatile modifiers, but we need
    // to create only one declaration for them all.
    Type::ResolveState type_resolve_state;
    CompilerType clang_type =
        m_ast.GetTypeForIdentifier<clang::CXXRecordDecl>(name, decl_context);
    if (!clang_type.IsValid()) {
      auto access = GetAccessibilityForUdt(*udt);

      auto tag_type_kind = TranslateUdtKind(udt->getUdtKind());

      ClangASTMetadata metadata;
      metadata.SetUserID(type.getSymIndexId());
      metadata.SetIsDynamicCXXType(false);

      clang_type = m_ast.CreateRecordType(
          decl_context, OptionalClangModuleID(), access, name, tag_type_kind,
          lldb::eLanguageTypeC_plus_plus, metadata);
      assert(clang_type.IsValid());

      auto record_decl =
          m_ast.GetAsCXXRecordDecl(clang_type.GetOpaqueQualType());
      assert(record_decl);
      m_uid_to_decl[type.getSymIndexId()] = record_decl;

      auto inheritance_attr = clang::MSInheritanceAttr::CreateImplicit(
          m_ast.getASTContext(), GetMSInheritance(*udt));
      record_decl->addAttr(inheritance_attr);

      TypeSystemClang::StartTagDeclarationDefinition(clang_type);

      auto children = udt->findAllChildren();
      if (!children || children->getChildCount() == 0) {
        // PDB does not have symbol of forwarder. We assume we get an udt w/o
        // any fields. Just complete it at this point.
        TypeSystemClang::CompleteTagDeclarationDefinition(clang_type);

        TypeSystemClang::SetHasExternalStorage(clang_type.GetOpaqueQualType(),
                                               false);

        type_resolve_state = Type::ResolveState::Full;
      } else {
        // Add the type to the forward declarations. It will help us to avoid
        // an endless recursion in CompleteTypeFromUdt function.
        m_forward_decl_to_uid[record_decl] = type.getSymIndexId();

        TypeSystemClang::SetHasExternalStorage(clang_type.GetOpaqueQualType(),
                                               true);

        type_resolve_state = Type::ResolveState::Forward;
      }
    } else
      type_resolve_state = Type::ResolveState::Forward;

    if (udt->isConstType())
      clang_type = clang_type.AddConstModifier();

    if (udt->isVolatileType())
      clang_type = clang_type.AddVolatileModifier();

    AddSourceInfoToDecl(type, decl);
    return m_ast.GetSymbolFile()->MakeType(
        type.getSymIndexId(), ConstString(name), udt->getLength(), nullptr,
        LLDB_INVALID_UID, lldb_private::Type::eEncodingIsUID, decl, clang_type,
        type_resolve_state);
  } break;
  case PDB_SymType::Enum: {
    auto enum_type = llvm::dyn_cast<PDBSymbolTypeEnum>(&type);
    assert(enum_type);

    std::string name =
        std::string(MSVCUndecoratedNameParser::DropScope(enum_type->getName()));
    auto decl_context = GetDeclContextContainingSymbol(type);
    uint64_t bytes = enum_type->getLength();

    // Check if such an enum already exists in the current context
    CompilerType ast_enum =
        m_ast.GetTypeForIdentifier<clang::EnumDecl>(name, decl_context);
    if (!ast_enum.IsValid()) {
      auto underlying_type_up = enum_type->getUnderlyingType();
      if (!underlying_type_up)
        return nullptr;

      lldb::Encoding encoding =
          TranslateBuiltinEncoding(underlying_type_up->getBuiltinType());
      // FIXME: Type of underlying builtin is always `Int`. We correct it with
      // the very first enumerator's encoding if any.
      auto first_child = enum_type->findOneChild<PDBSymbolData>();
      if (first_child)
        encoding = TranslateEnumEncoding(first_child->getValue().Type);

      CompilerType builtin_type;
      if (bytes > 0)
        builtin_type = GetBuiltinTypeForPDBEncodingAndBitSize(
            m_ast, *underlying_type_up, encoding, bytes * 8);
      else
        builtin_type = m_ast.GetBasicType(eBasicTypeInt);

      // FIXME: PDB does not have information about scoped enumeration (Enum
      // Class). Set it false for now.
      bool isScoped = false;

      ast_enum = m_ast.CreateEnumerationType(name, decl_context,
                                             OptionalClangModuleID(), decl,
                                             builtin_type, isScoped);

      auto enum_decl = TypeSystemClang::GetAsEnumDecl(ast_enum);
      assert(enum_decl);
      m_uid_to_decl[type.getSymIndexId()] = enum_decl;

      auto enum_values = enum_type->findAllChildren<PDBSymbolData>();
      if (enum_values) {
        while (auto enum_value = enum_values->getNext()) {
          if (enum_value->getDataKind() != PDB_DataKind::Constant)
            continue;
          AddEnumValue(ast_enum, *enum_value);
        }
      }

      if (TypeSystemClang::StartTagDeclarationDefinition(ast_enum))
        TypeSystemClang::CompleteTagDeclarationDefinition(ast_enum);
    }

    if (enum_type->isConstType())
      ast_enum = ast_enum.AddConstModifier();

    if (enum_type->isVolatileType())
      ast_enum = ast_enum.AddVolatileModifier();

    AddSourceInfoToDecl(type, decl);
    return m_ast.GetSymbolFile()->MakeType(
        type.getSymIndexId(), ConstString(name), bytes, nullptr,
        LLDB_INVALID_UID, lldb_private::Type::eEncodingIsUID, decl, ast_enum,
        lldb_private::Type::ResolveState::Full);
  } break;
  case PDB_SymType::Typedef: {
    auto type_def = llvm::dyn_cast<PDBSymbolTypeTypedef>(&type);
    assert(type_def);

    SymbolFile *symbol_file = m_ast.GetSymbolFile();
    if (!symbol_file)
      return nullptr;

    lldb_private::Type *target_type =
        symbol_file->ResolveTypeUID(type_def->getTypeId());
    if (!target_type)
      return nullptr;

    std::string name =
        std::string(MSVCUndecoratedNameParser::DropScope(type_def->getName()));
    auto decl_ctx = GetDeclContextContainingSymbol(type);

    // Check if such a typedef already exists in the current context
    CompilerType ast_typedef =
        m_ast.GetTypeForIdentifier<clang::TypedefNameDecl>(name, decl_ctx);
    if (!ast_typedef.IsValid()) {
      CompilerType target_ast_type = target_type->GetFullCompilerType();

      ast_typedef = target_ast_type.CreateTypedef(
          name.c_str(), m_ast.CreateDeclContext(decl_ctx), 0);
      if (!ast_typedef)
        return nullptr;

      auto typedef_decl = TypeSystemClang::GetAsTypedefDecl(ast_typedef);
      assert(typedef_decl);
      m_uid_to_decl[type.getSymIndexId()] = typedef_decl;
    }

    if (type_def->isConstType())
      ast_typedef = ast_typedef.AddConstModifier();

    if (type_def->isVolatileType())
      ast_typedef = ast_typedef.AddVolatileModifier();

    AddSourceInfoToDecl(type, decl);
    std::optional<uint64_t> size;
    if (type_def->getLength())
      size = type_def->getLength();
    return m_ast.GetSymbolFile()->MakeType(
        type_def->getSymIndexId(), ConstString(name), size, nullptr,
        target_type->GetID(), lldb_private::Type::eEncodingIsTypedefUID, decl,
        ast_typedef, lldb_private::Type::ResolveState::Full);
  } break;
  case PDB_SymType::Function:
  case PDB_SymType::FunctionSig: {
    std::string name;
    PDBSymbolTypeFunctionSig *func_sig = nullptr;
    if (auto pdb_func = llvm::dyn_cast<PDBSymbolFunc>(&type)) {
      if (pdb_func->isCompilerGenerated())
        return nullptr;

      auto sig = pdb_func->getSignature();
      if (!sig)
        return nullptr;
      func_sig = sig.release();
      // Function type is named.
      name = std::string(
          MSVCUndecoratedNameParser::DropScope(pdb_func->getName()));
    } else if (auto pdb_func_sig =
                   llvm::dyn_cast<PDBSymbolTypeFunctionSig>(&type)) {
      func_sig = const_cast<PDBSymbolTypeFunctionSig *>(pdb_func_sig);
    } else
      llvm_unreachable("Unexpected PDB symbol!");

    auto arg_enum = func_sig->getArguments();
    uint32_t num_args = arg_enum->getChildCount();
    std::vector<CompilerType> arg_list;

    bool is_variadic = func_sig->isCVarArgs();
    // Drop last variadic argument.
    if (is_variadic)
      --num_args;
    for (uint32_t arg_idx = 0; arg_idx < num_args; arg_idx++) {
      auto arg = arg_enum->getChildAtIndex(arg_idx);
      if (!arg)
        break;

      SymbolFile *symbol_file = m_ast.GetSymbolFile();
      if (!symbol_file)
        return nullptr;

      lldb_private::Type *arg_type =
          symbol_file->ResolveTypeUID(arg->getSymIndexId());
      // If there's some error looking up one of the dependent types of this
      // function signature, bail.
      if (!arg_type)
        return nullptr;
      CompilerType arg_ast_type = arg_type->GetFullCompilerType();
      arg_list.push_back(arg_ast_type);
    }
    lldbassert(arg_list.size() <= num_args);

    auto pdb_return_type = func_sig->getReturnType();
    SymbolFile *symbol_file = m_ast.GetSymbolFile();
    if (!symbol_file)
      return nullptr;

    lldb_private::Type *return_type =
        symbol_file->ResolveTypeUID(pdb_return_type->getSymIndexId());
    // If there's some error looking up one of the dependent types of this
    // function signature, bail.
    if (!return_type)
      return nullptr;
    CompilerType return_ast_type = return_type->GetFullCompilerType();
    uint32_t type_quals = 0;
    if (func_sig->isConstType())
      type_quals |= clang::Qualifiers::Const;
    if (func_sig->isVolatileType())
      type_quals |= clang::Qualifiers::Volatile;
    auto cc = TranslateCallingConvention(func_sig->getCallingConvention());
    CompilerType func_sig_ast_type =
        m_ast.CreateFunctionType(return_ast_type, arg_list.data(),
                                 arg_list.size(), is_variadic, type_quals, cc);

    AddSourceInfoToDecl(type, decl);
    return m_ast.GetSymbolFile()->MakeType(
        type.getSymIndexId(), ConstString(name), std::nullopt, nullptr,
        LLDB_INVALID_UID, lldb_private::Type::eEncodingIsUID, decl,
        func_sig_ast_type, lldb_private::Type::ResolveState::Full);
  } break;
  case PDB_SymType::ArrayType: {
    auto array_type = llvm::dyn_cast<PDBSymbolTypeArray>(&type);
    assert(array_type);
    uint32_t num_elements = array_type->getCount();
    uint32_t element_uid = array_type->getElementTypeId();
    std::optional<uint64_t> bytes;
    if (uint64_t size = array_type->getLength())
      bytes = size;

    SymbolFile *symbol_file = m_ast.GetSymbolFile();
    if (!symbol_file)
      return nullptr;

    // If array rank > 0, PDB gives the element type at N=0. So element type
    // will parsed in the order N=0, N=1,..., N=rank sequentially.
    lldb_private::Type *element_type = symbol_file->ResolveTypeUID(element_uid);
    if (!element_type)
      return nullptr;

    CompilerType element_ast_type = element_type->GetForwardCompilerType();
    // If element type is UDT, it needs to be complete.
    if (TypeSystemClang::IsCXXClassType(element_ast_type) &&
        !element_ast_type.GetCompleteType()) {
      if (TypeSystemClang::StartTagDeclarationDefinition(element_ast_type)) {
        TypeSystemClang::CompleteTagDeclarationDefinition(element_ast_type);
      } else {
        // We are not able to start definition.
        return nullptr;
      }
    }
    CompilerType array_ast_type = m_ast.CreateArrayType(
        element_ast_type, num_elements, /*is_gnu_vector*/ false);
    TypeSP type_sp = m_ast.GetSymbolFile()->MakeType(
        array_type->getSymIndexId(), ConstString(), bytes, nullptr,
        LLDB_INVALID_UID, lldb_private::Type::eEncodingIsUID, decl,
        array_ast_type, lldb_private::Type::ResolveState::Full);
    type_sp->SetEncodingType(element_type);
    return type_sp;
  } break;
  case PDB_SymType::BuiltinType: {
    auto *builtin_type = llvm::dyn_cast<PDBSymbolTypeBuiltin>(&type);
    assert(builtin_type);
    PDB_BuiltinType builtin_kind = builtin_type->getBuiltinType();
    if (builtin_kind == PDB_BuiltinType::None)
      return nullptr;

    std::optional<uint64_t> bytes;
    if (uint64_t size = builtin_type->getLength())
      bytes = size;
    Encoding encoding = TranslateBuiltinEncoding(builtin_kind);
    CompilerType builtin_ast_type = GetBuiltinTypeForPDBEncodingAndBitSize(
        m_ast, *builtin_type, encoding, bytes.value_or(0) * 8);

    if (builtin_type->isConstType())
      builtin_ast_type = builtin_ast_type.AddConstModifier();

    if (builtin_type->isVolatileType())
      builtin_ast_type = builtin_ast_type.AddVolatileModifier();

    auto type_name = GetPDBBuiltinTypeName(*builtin_type, builtin_ast_type);

    return m_ast.GetSymbolFile()->MakeType(
        builtin_type->getSymIndexId(), type_name, bytes, nullptr,
        LLDB_INVALID_UID, lldb_private::Type::eEncodingIsUID, decl,
        builtin_ast_type, lldb_private::Type::ResolveState::Full);
  } break;
  case PDB_SymType::PointerType: {
    auto *pointer_type = llvm::dyn_cast<PDBSymbolTypePointer>(&type);
    assert(pointer_type);

    SymbolFile *symbol_file = m_ast.GetSymbolFile();
    if (!symbol_file)
      return nullptr;

    Type *pointee_type = symbol_file->ResolveTypeUID(
        pointer_type->getPointeeType()->getSymIndexId());
    if (!pointee_type)
      return nullptr;

    if (pointer_type->isPointerToDataMember() ||
        pointer_type->isPointerToMemberFunction()) {
      auto class_parent_uid = pointer_type->getRawSymbol().getClassParentId();
      auto class_parent_type = symbol_file->ResolveTypeUID(class_parent_uid);
      assert(class_parent_type);

      CompilerType pointer_ast_type;
      pointer_ast_type = TypeSystemClang::CreateMemberPointerType(
          class_parent_type->GetLayoutCompilerType(),
          pointee_type->GetForwardCompilerType());
      assert(pointer_ast_type);

      return m_ast.GetSymbolFile()->MakeType(
          pointer_type->getSymIndexId(), ConstString(),
          pointer_type->getLength(), nullptr, LLDB_INVALID_UID,
          lldb_private::Type::eEncodingIsUID, decl, pointer_ast_type,
          lldb_private::Type::ResolveState::Forward);
    }

    CompilerType pointer_ast_type;
    pointer_ast_type = pointee_type->GetFullCompilerType();
    if (pointer_type->isReference())
      pointer_ast_type = pointer_ast_type.GetLValueReferenceType();
    else if (pointer_type->isRValueReference())
      pointer_ast_type = pointer_ast_type.GetRValueReferenceType();
    else
      pointer_ast_type = pointer_ast_type.GetPointerType();

    if (pointer_type->isConstType())
      pointer_ast_type = pointer_ast_type.AddConstModifier();

    if (pointer_type->isVolatileType())
      pointer_ast_type = pointer_ast_type.AddVolatileModifier();

    if (pointer_type->isRestrictedType())
      pointer_ast_type = pointer_ast_type.AddRestrictModifier();

    return m_ast.GetSymbolFile()->MakeType(
        pointer_type->getSymIndexId(), ConstString(), pointer_type->getLength(),
        nullptr, LLDB_INVALID_UID, lldb_private::Type::eEncodingIsUID, decl,
        pointer_ast_type, lldb_private::Type::ResolveState::Full);
  } break;
  default:
    break;
  }
  return nullptr;
}

bool PDBASTParser::CompleteTypeFromPDB(
    lldb_private::CompilerType &compiler_type) {
  if (GetClangASTImporter().CanImport(compiler_type))
    return GetClangASTImporter().CompleteType(compiler_type);

  // Remove the type from the forward declarations to avoid
  // an endless recursion for types like a linked list.
  clang::CXXRecordDecl *record_decl =
      m_ast.GetAsCXXRecordDecl(compiler_type.GetOpaqueQualType());
  auto uid_it = m_forward_decl_to_uid.find(record_decl);
  if (uid_it == m_forward_decl_to_uid.end())
    return true;

  auto symbol_file = static_cast<SymbolFilePDB *>(
      m_ast.GetSymbolFile()->GetBackingSymbolFile());
  if (!symbol_file)
    return false;

  std::unique_ptr<PDBSymbol> symbol =
      symbol_file->GetPDBSession().getSymbolById(uid_it->getSecond());
  if (!symbol)
    return false;

  m_forward_decl_to_uid.erase(uid_it);

  TypeSystemClang::SetHasExternalStorage(compiler_type.GetOpaqueQualType(),
                                         false);

  switch (symbol->getSymTag()) {
  case PDB_SymType::UDT: {
    auto udt = llvm::dyn_cast<PDBSymbolTypeUDT>(symbol.get());
    if (!udt)
      return false;

    return CompleteTypeFromUDT(*symbol_file, compiler_type, *udt);
  }
  default:
    llvm_unreachable("not a forward clang type decl!");
  }
}

clang::Decl *
PDBASTParser::GetDeclForSymbol(const llvm::pdb::PDBSymbol &symbol) {
  uint32_t sym_id = symbol.getSymIndexId();
  auto it = m_uid_to_decl.find(sym_id);
  if (it != m_uid_to_decl.end())
    return it->second;

  auto symbol_file = static_cast<SymbolFilePDB *>(
      m_ast.GetSymbolFile()->GetBackingSymbolFile());
  if (!symbol_file)
    return nullptr;

  // First of all, check if the symbol is a member of a class. Resolve the full
  // class type and return the declaration from the cache if so.
  auto tag = symbol.getSymTag();
  if (tag == PDB_SymType::Data || tag == PDB_SymType::Function) {
    const IPDBSession &session = symbol.getSession();
    const IPDBRawSymbol &raw = symbol.getRawSymbol();

    auto class_parent_id = raw.getClassParentId();
    if (std::unique_ptr<PDBSymbol> class_parent =
            session.getSymbolById(class_parent_id)) {
      auto class_parent_type = symbol_file->ResolveTypeUID(class_parent_id);
      if (!class_parent_type)
        return nullptr;

      CompilerType class_parent_ct = class_parent_type->GetFullCompilerType();

      // Look a declaration up in the cache after completing the class
      clang::Decl *decl = m_uid_to_decl.lookup(sym_id);
      if (decl)
        return decl;

      // A declaration was not found in the cache. It means that the symbol
      // has the class parent, but the class doesn't have the symbol in its
      // children list.
      if (auto func = llvm::dyn_cast_or_null<PDBSymbolFunc>(&symbol)) {
        // Try to find a class child method with the same RVA and use its
        // declaration if found.
        if (uint32_t rva = func->getRelativeVirtualAddress()) {
          if (std::unique_ptr<ConcreteSymbolEnumerator<PDBSymbolFunc>>
                  methods_enum =
                      class_parent->findAllChildren<PDBSymbolFunc>()) {
            while (std::unique_ptr<PDBSymbolFunc> method =
                       methods_enum->getNext()) {
              if (method->getRelativeVirtualAddress() == rva) {
                decl = m_uid_to_decl.lookup(method->getSymIndexId());
                if (decl)
                  break;
              }
            }
          }
        }

        // If no class methods with the same RVA were found, then create a new
        // method. It is possible for template methods.
        if (!decl)
          decl = AddRecordMethod(*symbol_file, class_parent_ct, *func);
      }

      if (decl)
        m_uid_to_decl[sym_id] = decl;

      return decl;
    }
  }

  // If we are here, then the symbol is not belonging to a class and is not
  // contained in the cache. So create a declaration for it.
  switch (symbol.getSymTag()) {
  case PDB_SymType::Data: {
    auto data = llvm::dyn_cast<PDBSymbolData>(&symbol);
    assert(data);

    auto decl_context = GetDeclContextContainingSymbol(symbol);
    assert(decl_context);

    // May be the current context is a class really, but we haven't found
    // any class parent. This happens e.g. in the case of class static
    // variables - they has two symbols, one is a child of the class when
    // another is a child of the exe. So always complete the parent and use
    // an existing declaration if possible.
    if (auto parent_decl = llvm::dyn_cast_or_null<clang::TagDecl>(decl_context))
      m_ast.GetCompleteDecl(parent_decl);

    std::string name =
        std::string(MSVCUndecoratedNameParser::DropScope(data->getName()));

    // Check if the current context already contains the symbol with the name.
    clang::Decl *decl =
        GetDeclFromContextByName(m_ast.getASTContext(), *decl_context, name);
    if (!decl) {
      auto type = symbol_file->ResolveTypeUID(data->getTypeId());
      if (!type)
        return nullptr;

      decl = m_ast.CreateVariableDeclaration(
          decl_context, OptionalClangModuleID(), name.c_str(),
          ClangUtil::GetQualType(type->GetLayoutCompilerType()));
    }

    m_uid_to_decl[sym_id] = decl;

    return decl;
  }
  case PDB_SymType::Function: {
    auto func = llvm::dyn_cast<PDBSymbolFunc>(&symbol);
    assert(func);

    auto decl_context = GetDeclContextContainingSymbol(symbol);
    assert(decl_context);

    std::string name =
        std::string(MSVCUndecoratedNameParser::DropScope(func->getName()));

    Type *type = symbol_file->ResolveTypeUID(sym_id);
    if (!type)
      return nullptr;

    auto storage = func->isStatic() ? clang::StorageClass::SC_Static
                                    : clang::StorageClass::SC_None;

    auto decl = m_ast.CreateFunctionDeclaration(
        decl_context, OptionalClangModuleID(), name,
        type->GetForwardCompilerType(), storage, func->hasInlineAttribute());

    std::vector<clang::ParmVarDecl *> params;
    if (std::unique_ptr<PDBSymbolTypeFunctionSig> sig = func->getSignature()) {
      if (std::unique_ptr<ConcreteSymbolEnumerator<PDBSymbolTypeFunctionArg>>
              arg_enum = sig->findAllChildren<PDBSymbolTypeFunctionArg>()) {
        while (std::unique_ptr<PDBSymbolTypeFunctionArg> arg =
                   arg_enum->getNext()) {
          Type *arg_type = symbol_file->ResolveTypeUID(arg->getTypeId());
          if (!arg_type)
            continue;

          clang::ParmVarDecl *param = m_ast.CreateParameterDeclaration(
              decl, OptionalClangModuleID(), nullptr,
              arg_type->GetForwardCompilerType(), clang::SC_None, true);
          if (param)
            params.push_back(param);
        }
      }
    }
    if (params.size())
      m_ast.SetFunctionParameters(decl, params);

    m_uid_to_decl[sym_id] = decl;

    return decl;
  }
  default: {
    // It's not a variable and not a function, check if it's a type
    Type *type = symbol_file->ResolveTypeUID(sym_id);
    if (!type)
      return nullptr;

    return m_uid_to_decl.lookup(sym_id);
  }
  }
}

clang::DeclContext *
PDBASTParser::GetDeclContextForSymbol(const llvm::pdb::PDBSymbol &symbol) {
  if (symbol.getSymTag() == PDB_SymType::Function) {
    clang::DeclContext *result =
        llvm::dyn_cast_or_null<clang::FunctionDecl>(GetDeclForSymbol(symbol));

    if (result)
      m_decl_context_to_uid[result] = symbol.getSymIndexId();

    return result;
  }

  auto symbol_file = static_cast<SymbolFilePDB *>(
      m_ast.GetSymbolFile()->GetBackingSymbolFile());
  if (!symbol_file)
    return nullptr;

  auto type = symbol_file->ResolveTypeUID(symbol.getSymIndexId());
  if (!type)
    return nullptr;

  clang::DeclContext *result =
      m_ast.GetDeclContextForType(type->GetForwardCompilerType());

  if (result)
    m_decl_context_to_uid[result] = symbol.getSymIndexId();

  return result;
}

clang::DeclContext *PDBASTParser::GetDeclContextContainingSymbol(
    const llvm::pdb::PDBSymbol &symbol) {
  auto parent = GetClassOrFunctionParent(symbol);
  while (parent) {
    if (auto parent_context = GetDeclContextForSymbol(*parent))
      return parent_context;

    parent = GetClassOrFunctionParent(*parent);
  }

  // We can't find any class or function parent of the symbol. So analyze
  // the full symbol name. The symbol may be belonging to a namespace
  // or function (or even to a class if it's e.g. a static variable symbol).

  // TODO: Make clang to emit full names for variables in namespaces
  // (as MSVC does)

  std::string name(symbol.getRawSymbol().getName());
  MSVCUndecoratedNameParser parser(name);
  llvm::ArrayRef<MSVCUndecoratedNameSpecifier> specs = parser.GetSpecifiers();
  if (specs.empty())
    return m_ast.GetTranslationUnitDecl();

  auto symbol_file = static_cast<SymbolFilePDB *>(
      m_ast.GetSymbolFile()->GetBackingSymbolFile());
  if (!symbol_file)
    return m_ast.GetTranslationUnitDecl();

  auto global = symbol_file->GetPDBSession().getGlobalScope();
  if (!global)
    return m_ast.GetTranslationUnitDecl();

  bool has_type_or_function_parent = false;
  clang::DeclContext *curr_context = m_ast.GetTranslationUnitDecl();
  for (std::size_t i = 0; i < specs.size() - 1; i++) {
    // Check if there is a function or a type with the current context's name.
    if (std::unique_ptr<IPDBEnumSymbols> children_enum = global->findChildren(
            PDB_SymType::None, specs[i].GetFullName(), NS_CaseSensitive)) {
      while (IPDBEnumChildren<PDBSymbol>::ChildTypePtr child =
                 children_enum->getNext()) {
        if (clang::DeclContext *child_context =
                GetDeclContextForSymbol(*child)) {
          // Note that `GetDeclContextForSymbol' retrieves
          // a declaration context for functions and types only,
          // so if we are here then `child_context' is guaranteed
          // a function or a type declaration context.
          has_type_or_function_parent = true;
          curr_context = child_context;
        }
      }
    }

    // If there were no functions or types above then retrieve a namespace with
    // the current context's name. There can be no namespaces inside a function
    // or a type. We check it to avoid fake namespaces such as `__l2':
    // `N0::N1::CClass::PrivateFunc::__l2::InnerFuncStruct'
    if (!has_type_or_function_parent) {
      std::string namespace_name = std::string(specs[i].GetBaseName());
      const char *namespace_name_c_str =
          IsAnonymousNamespaceName(namespace_name) ? nullptr
                                                   : namespace_name.data();
      clang::NamespaceDecl *namespace_decl =
          m_ast.GetUniqueNamespaceDeclaration(
              namespace_name_c_str, curr_context, OptionalClangModuleID());

      m_parent_to_namespaces[curr_context].insert(namespace_decl);
      m_namespaces.insert(namespace_decl);

      curr_context = namespace_decl;
    }
  }

  return curr_context;
}

void PDBASTParser::ParseDeclsForDeclContext(
    const clang::DeclContext *decl_context) {
  auto symbol_file = static_cast<SymbolFilePDB *>(
      m_ast.GetSymbolFile()->GetBackingSymbolFile());
  if (!symbol_file)
    return;

  IPDBSession &session = symbol_file->GetPDBSession();
  auto symbol_up =
      session.getSymbolById(m_decl_context_to_uid.lookup(decl_context));
  auto global_up = session.getGlobalScope();

  PDBSymbol *symbol;
  if (symbol_up)
    symbol = symbol_up.get();
  else if (global_up)
    symbol = global_up.get();
  else
    return;

  if (auto children = symbol->findAllChildren())
    while (auto child = children->getNext())
      GetDeclForSymbol(*child);
}

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

    set = &pit->second;
  } else {
    set = &m_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;
}

bool PDBASTParser::AddEnumValue(CompilerType enum_type,
                                const PDBSymbolData &enum_value) {
  Declaration decl;
  Variant v = enum_value.getValue();
  std::string name =
      std::string(MSVCUndecoratedNameParser::DropScope(enum_value.getName()));
  int64_t raw_value;
  switch (v.Type) {
  case PDB_VariantType::Int8:
    raw_value = v.Value.Int8;
    break;
  case PDB_VariantType::Int16:
    raw_value = v.Value.Int16;
    break;
  case PDB_VariantType::Int32:
    raw_value = v.Value.Int32;
    break;
  case PDB_VariantType::Int64:
    raw_value = v.Value.Int64;
    break;
  case PDB_VariantType::UInt8:
    raw_value = v.Value.UInt8;
    break;
  case PDB_VariantType::UInt16:
    raw_value = v.Value.UInt16;
    break;
  case PDB_VariantType::UInt32:
    raw_value = v.Value.UInt32;
    break;
  case PDB_VariantType::UInt64:
    raw_value = v.Value.UInt64;
    break;
  default:
    return false;
  }
  CompilerType underlying_type = m_ast.GetEnumerationIntegerType(enum_type);
  uint32_t byte_size = m_ast.getASTContext().getTypeSize(
      ClangUtil::GetQualType(underlying_type));
  auto enum_constant_decl = m_ast.AddEnumerationValueToEnumerationType(
      enum_type, decl, name.c_str(), raw_value, byte_size * 8);
  if (!enum_constant_decl)
    return false;

  m_uid_to_decl[enum_value.getSymIndexId()] = enum_constant_decl;

  return true;
}

bool PDBASTParser::CompleteTypeFromUDT(
    lldb_private::SymbolFile &symbol_file,
    lldb_private::CompilerType &compiler_type,
    llvm::pdb::PDBSymbolTypeUDT &udt) {
  ClangASTImporter::LayoutInfo layout_info;
  layout_info.bit_size = udt.getLength() * 8;

  auto nested_enums = udt.findAllChildren<PDBSymbolTypeUDT>();
  if (nested_enums)
    while (auto nested = nested_enums->getNext())
      symbol_file.ResolveTypeUID(nested->getSymIndexId());

  auto bases_enum = udt.findAllChildren<PDBSymbolTypeBaseClass>();
  if (bases_enum)
    AddRecordBases(symbol_file, compiler_type,
                   TranslateUdtKind(udt.getUdtKind()), *bases_enum,
                   layout_info);

  auto members_enum = udt.findAllChildren<PDBSymbolData>();
  if (members_enum)
    AddRecordMembers(symbol_file, compiler_type, *members_enum, layout_info);

  auto methods_enum = udt.findAllChildren<PDBSymbolFunc>();
  if (methods_enum)
    AddRecordMethods(symbol_file, compiler_type, *methods_enum);

  m_ast.AddMethodOverridesForCXXRecordType(compiler_type.GetOpaqueQualType());
  TypeSystemClang::BuildIndirectFields(compiler_type);
  TypeSystemClang::CompleteTagDeclarationDefinition(compiler_type);

  clang::CXXRecordDecl *record_decl =
      m_ast.GetAsCXXRecordDecl(compiler_type.GetOpaqueQualType());
  if (!record_decl)
    return static_cast<bool>(compiler_type);

  GetClangASTImporter().SetRecordLayout(record_decl, layout_info);

  return static_cast<bool>(compiler_type);
}

void PDBASTParser::AddRecordMembers(
    lldb_private::SymbolFile &symbol_file,
    lldb_private::CompilerType &record_type,
    PDBDataSymbolEnumerator &members_enum,
    lldb_private::ClangASTImporter::LayoutInfo &layout_info) {
  while (auto member = members_enum.getNext()) {
    if (member->isCompilerGenerated())
      continue;

    auto member_name = member->getName();

    auto member_type = symbol_file.ResolveTypeUID(member->getTypeId());
    if (!member_type)
      continue;

    auto member_comp_type = member_type->GetLayoutCompilerType();
    if (!member_comp_type.GetCompleteType()) {
      symbol_file.GetObjectFile()->GetModule()->ReportError(
          ":: Class '{0}' has a member '{1}' of type '{2}' "
          "which does not have a complete definition.",
          record_type.GetTypeName().GetCString(), member_name.c_str(),
          member_comp_type.GetTypeName().GetCString());
      if (TypeSystemClang::StartTagDeclarationDefinition(member_comp_type))
        TypeSystemClang::CompleteTagDeclarationDefinition(member_comp_type);
    }

    auto access = TranslateMemberAccess(member->getAccess());

    switch (member->getDataKind()) {
    case PDB_DataKind::Member: {
      auto location_type = member->getLocationType();

      auto bit_size = member->getLength();
      if (location_type == PDB_LocType::ThisRel)
        bit_size *= 8;

      auto decl = TypeSystemClang::AddFieldToRecordType(
          record_type, member_name.c_str(), member_comp_type, access, bit_size);
      if (!decl)
        continue;

      m_uid_to_decl[member->getSymIndexId()] = decl;

      auto offset = member->getOffset() * 8;
      if (location_type == PDB_LocType::BitField)
        offset += member->getBitPosition();

      layout_info.field_offsets.insert(std::make_pair(decl, offset));

      break;
    }
    case PDB_DataKind::StaticMember: {
      auto decl = TypeSystemClang::AddVariableToRecordType(
          record_type, member_name.c_str(), member_comp_type, access);
      if (!decl)
        continue;

      // Static constant members may be a const[expr] declaration.
      // Query the symbol's value as the variable initializer if valid.
      if (member_comp_type.IsConst()) {
        auto value = member->getValue();
        if (value.Type == llvm::pdb::Empty) {
          LLDB_LOG(GetLog(LLDBLog::AST),
                   "Class '{0}' has member '{1}' of type '{2}' with an unknown "
                   "constant size.",
                   record_type.GetTypeName(), member_name,
                   member_comp_type.GetTypeName());
          continue;
        }

        clang::QualType qual_type = decl->getType();
        unsigned type_width = m_ast.getASTContext().getIntWidth(qual_type);
        unsigned constant_width = value.getBitWidth();

        if (qual_type->isIntegralOrEnumerationType()) {
          if (type_width >= constant_width) {
            TypeSystemClang::SetIntegerInitializerForVariable(
                decl, value.toAPSInt().extOrTrunc(type_width));
          } else {
            LLDB_LOG(GetLog(LLDBLog::AST),
                     "Class '{0}' has a member '{1}' of type '{2}' ({3} bits) "
                     "which resolves to a wider constant value ({4} bits). "
                     "Ignoring constant.",
                     record_type.GetTypeName(), member_name,
                     member_comp_type.GetTypeName(), type_width,
                     constant_width);
          }
        } else {
          switch (member_comp_type.GetBasicTypeEnumeration()) {
          case lldb::eBasicTypeFloat:
          case lldb::eBasicTypeDouble:
          case lldb::eBasicTypeLongDouble:
            if (type_width == constant_width) {
              TypeSystemClang::SetFloatingInitializerForVariable(
                  decl, value.toAPFloat());
              decl->setConstexpr(true);
            } else {
              LLDB_LOG(GetLog(LLDBLog::AST),
                       "Class '{0}' has a member '{1}' of type '{2}' ({3} "
                       "bits) which resolves to a constant value of mismatched "
                       "width ({4} bits). Ignoring constant.",
                       record_type.GetTypeName(), member_name,
                       member_comp_type.GetTypeName(), type_width,
                       constant_width);
            }
            break;
          default:
            break;
          }
        }
      }

      m_uid_to_decl[member->getSymIndexId()] = decl;

      break;
    }
    default:
      llvm_unreachable("unsupported PDB data kind");
    }
  }
}

void PDBASTParser::AddRecordBases(
    lldb_private::SymbolFile &symbol_file,
    lldb_private::CompilerType &record_type, int record_kind,
    PDBBaseClassSymbolEnumerator &bases_enum,
    lldb_private::ClangASTImporter::LayoutInfo &layout_info) const {
  std::vector<std::unique_ptr<clang::CXXBaseSpecifier>> base_classes;

  while (auto base = bases_enum.getNext()) {
    auto base_type = symbol_file.ResolveTypeUID(base->getTypeId());
    if (!base_type)
      continue;

    auto base_comp_type = base_type->GetFullCompilerType();
    if (!base_comp_type.GetCompleteType()) {
      symbol_file.GetObjectFile()->GetModule()->ReportError(
          ":: Class '{0}' has a base class '{1}' "
          "which does not have a complete definition.",
          record_type.GetTypeName().GetCString(),
          base_comp_type.GetTypeName().GetCString());
      if (TypeSystemClang::StartTagDeclarationDefinition(base_comp_type))
        TypeSystemClang::CompleteTagDeclarationDefinition(base_comp_type);
    }

    auto access = TranslateMemberAccess(base->getAccess());

    auto is_virtual = base->isVirtualBaseClass();

    std::unique_ptr<clang::CXXBaseSpecifier> base_spec =
        m_ast.CreateBaseClassSpecifier(
            base_comp_type.GetOpaqueQualType(), access, is_virtual,
            record_kind == llvm::to_underlying(clang::TagTypeKind::Class));
    lldbassert(base_spec);

    base_classes.push_back(std::move(base_spec));

    if (is_virtual)
      continue;

    auto decl = m_ast.GetAsCXXRecordDecl(base_comp_type.GetOpaqueQualType());
    if (!decl)
      continue;

    auto offset = clang::CharUnits::fromQuantity(base->getOffset());
    layout_info.base_offsets.insert(std::make_pair(decl, offset));
  }

  m_ast.TransferBaseClasses(record_type.GetOpaqueQualType(),
                            std::move(base_classes));
}

void PDBASTParser::AddRecordMethods(lldb_private::SymbolFile &symbol_file,
                                    lldb_private::CompilerType &record_type,
                                    PDBFuncSymbolEnumerator &methods_enum) {
  while (std::unique_ptr<PDBSymbolFunc> method = methods_enum.getNext())
    if (clang::CXXMethodDecl *decl =
            AddRecordMethod(symbol_file, record_type, *method))
      m_uid_to_decl[method->getSymIndexId()] = decl;
}

clang::CXXMethodDecl *
PDBASTParser::AddRecordMethod(lldb_private::SymbolFile &symbol_file,
                              lldb_private::CompilerType &record_type,
                              const llvm::pdb::PDBSymbolFunc &method) const {
  std::string name =
      std::string(MSVCUndecoratedNameParser::DropScope(method.getName()));

  Type *method_type = symbol_file.ResolveTypeUID(method.getSymIndexId());
  // MSVC specific __vecDelDtor.
  if (!method_type)
    return nullptr;

  CompilerType method_comp_type = method_type->GetFullCompilerType();
  if (!method_comp_type.GetCompleteType()) {
    symbol_file.GetObjectFile()->GetModule()->ReportError(
        ":: Class '{0}' has a method '{1}' whose type cannot be completed.",
        record_type.GetTypeName().GetCString(),
        method_comp_type.GetTypeName().GetCString());
    if (TypeSystemClang::StartTagDeclarationDefinition(method_comp_type))
      TypeSystemClang::CompleteTagDeclarationDefinition(method_comp_type);
  }

  AccessType access = TranslateMemberAccess(method.getAccess());
  if (access == eAccessNone)
    access = eAccessPublic;

  // TODO: get mangled name for the method.
  return m_ast.AddMethodToCXXRecordType(
      record_type.GetOpaqueQualType(), name.c_str(),
      /*mangled_name*/ nullptr, method_comp_type, access, method.isVirtual(),
      method.isStatic(), method.hasInlineAttribute(),
      /*is_explicit*/ false, // FIXME: Need this field in CodeView.
      /*is_attr_used*/ false,
      /*is_artificial*/ method.isCompilerGenerated());
}
