Path: blob/main/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp
39644 views
#include "PdbAstBuilder.h"12#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"3#include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"4#include "llvm/DebugInfo/CodeView/RecordName.h"5#include "llvm/DebugInfo/CodeView/SymbolDeserializer.h"6#include "llvm/DebugInfo/CodeView/SymbolRecord.h"7#include "llvm/DebugInfo/CodeView/SymbolRecordHelpers.h"8#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"9#include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h"10#include "llvm/DebugInfo/PDB/Native/DbiStream.h"11#include "llvm/DebugInfo/PDB/Native/PublicsStream.h"12#include "llvm/DebugInfo/PDB/Native/SymbolStream.h"13#include "llvm/DebugInfo/PDB/Native/TpiStream.h"14#include "llvm/Demangle/MicrosoftDemangle.h"1516#include "PdbUtil.h"17#include "Plugins/ExpressionParser/Clang/ClangASTMetadata.h"18#include "Plugins/ExpressionParser/Clang/ClangUtil.h"19#include "Plugins/Language/CPlusPlus/MSVCUndecoratedNameParser.h"20#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"21#include "SymbolFileNativePDB.h"22#include "UdtRecordCompleter.h"23#include "lldb/Core/Module.h"24#include "lldb/Symbol/ObjectFile.h"25#include "lldb/Utility/LLDBAssert.h"26#include <optional>27#include <string_view>2829using namespace lldb_private;30using namespace lldb_private::npdb;31using namespace llvm::codeview;32using namespace llvm::pdb;3334namespace {35struct CreateMethodDecl : public TypeVisitorCallbacks {36CreateMethodDecl(PdbIndex &m_index, TypeSystemClang &m_clang,37TypeIndex func_type_index,38clang::FunctionDecl *&function_decl,39lldb::opaque_compiler_type_t parent_ty,40llvm::StringRef proc_name, CompilerType func_ct)41: m_index(m_index), m_clang(m_clang), func_type_index(func_type_index),42function_decl(function_decl), parent_ty(parent_ty),43proc_name(proc_name), func_ct(func_ct) {}44PdbIndex &m_index;45TypeSystemClang &m_clang;46TypeIndex func_type_index;47clang::FunctionDecl *&function_decl;48lldb::opaque_compiler_type_t parent_ty;49llvm::StringRef proc_name;50CompilerType func_ct;5152llvm::Error visitKnownMember(CVMemberRecord &cvr,53OverloadedMethodRecord &overloaded) override {54TypeIndex method_list_idx = overloaded.MethodList;5556CVType method_list_type = m_index.tpi().getType(method_list_idx);57assert(method_list_type.kind() == LF_METHODLIST);5859MethodOverloadListRecord method_list;60llvm::cantFail(TypeDeserializer::deserializeAs<MethodOverloadListRecord>(61method_list_type, method_list));6263for (const OneMethodRecord &method : method_list.Methods) {64if (method.getType().getIndex() == func_type_index.getIndex())65AddMethod(overloaded.Name, method.getAccess(), method.getOptions(),66method.Attrs);67}6869return llvm::Error::success();70}7172llvm::Error visitKnownMember(CVMemberRecord &cvr,73OneMethodRecord &record) override {74AddMethod(record.getName(), record.getAccess(), record.getOptions(),75record.Attrs);76return llvm::Error::success();77}7879void AddMethod(llvm::StringRef name, MemberAccess access,80MethodOptions options, MemberAttributes attrs) {81if (name != proc_name || function_decl)82return;83lldb::AccessType access_type = TranslateMemberAccess(access);84bool is_virtual = attrs.isVirtual();85bool is_static = attrs.isStatic();86bool is_artificial = (options & MethodOptions::CompilerGenerated) ==87MethodOptions::CompilerGenerated;88function_decl = m_clang.AddMethodToCXXRecordType(89parent_ty, proc_name,90/*mangled_name=*/nullptr, func_ct, /*access=*/access_type,91/*is_virtual=*/is_virtual, /*is_static=*/is_static,92/*is_inline=*/false, /*is_explicit=*/false,93/*is_attr_used=*/false, /*is_artificial=*/is_artificial);94}95};96} // namespace9798static clang::TagTypeKind TranslateUdtKind(const TagRecord &cr) {99switch (cr.Kind) {100case TypeRecordKind::Class:101return clang::TagTypeKind::Class;102case TypeRecordKind::Struct:103return clang::TagTypeKind::Struct;104case TypeRecordKind::Union:105return clang::TagTypeKind::Union;106case TypeRecordKind::Interface:107return clang::TagTypeKind::Interface;108case TypeRecordKind::Enum:109return clang::TagTypeKind::Enum;110default:111lldbassert(false && "Invalid tag record kind!");112return clang::TagTypeKind::Struct;113}114}115116static bool IsCVarArgsFunction(llvm::ArrayRef<TypeIndex> args) {117if (args.empty())118return false;119return args.back() == TypeIndex::None();120}121122static bool123AnyScopesHaveTemplateParams(llvm::ArrayRef<llvm::ms_demangle::Node *> scopes) {124for (llvm::ms_demangle::Node *n : scopes) {125auto *idn = static_cast<llvm::ms_demangle::IdentifierNode *>(n);126if (idn->TemplateParams)127return true;128}129return false;130}131132static std::optional<clang::CallingConv>133TranslateCallingConvention(llvm::codeview::CallingConvention conv) {134using CC = llvm::codeview::CallingConvention;135switch (conv) {136137case CC::NearC:138case CC::FarC:139return clang::CallingConv::CC_C;140case CC::NearPascal:141case CC::FarPascal:142return clang::CallingConv::CC_X86Pascal;143case CC::NearFast:144case CC::FarFast:145return clang::CallingConv::CC_X86FastCall;146case CC::NearStdCall:147case CC::FarStdCall:148return clang::CallingConv::CC_X86StdCall;149case CC::ThisCall:150return clang::CallingConv::CC_X86ThisCall;151case CC::NearVector:152return clang::CallingConv::CC_X86VectorCall;153default:154return std::nullopt;155}156}157158static bool IsAnonymousNamespaceName(llvm::StringRef name) {159return name == "`anonymous namespace'" || name == "`anonymous-namespace'";160}161162PdbAstBuilder::PdbAstBuilder(TypeSystemClang &clang) : m_clang(clang) {}163164lldb_private::CompilerDeclContext PdbAstBuilder::GetTranslationUnitDecl() {165return ToCompilerDeclContext(*m_clang.GetTranslationUnitDecl());166}167168std::pair<clang::DeclContext *, std::string>169PdbAstBuilder::CreateDeclInfoForType(const TagRecord &record, TypeIndex ti) {170SymbolFileNativePDB *pdb = static_cast<SymbolFileNativePDB *>(171m_clang.GetSymbolFile()->GetBackingSymbolFile());172// FIXME: Move this to GetDeclContextContainingUID.173if (!record.hasUniqueName())174return CreateDeclInfoForUndecoratedName(record.Name);175176llvm::ms_demangle::Demangler demangler;177std::string_view sv(record.UniqueName.begin(), record.UniqueName.size());178llvm::ms_demangle::TagTypeNode *ttn = demangler.parseTagUniqueName(sv);179if (demangler.Error)180return {m_clang.GetTranslationUnitDecl(), std::string(record.UniqueName)};181182llvm::ms_demangle::IdentifierNode *idn =183ttn->QualifiedName->getUnqualifiedIdentifier();184std::string uname = idn->toString(llvm::ms_demangle::OF_NoTagSpecifier);185186llvm::ms_demangle::NodeArrayNode *name_components =187ttn->QualifiedName->Components;188llvm::ArrayRef<llvm::ms_demangle::Node *> scopes(name_components->Nodes,189name_components->Count - 1);190191clang::DeclContext *context = m_clang.GetTranslationUnitDecl();192193// If this type doesn't have a parent type in the debug info, then the best we194// can do is to say that it's either a series of namespaces (if the scope is195// non-empty), or the translation unit (if the scope is empty).196std::optional<TypeIndex> parent_index = pdb->GetParentType(ti);197if (!parent_index) {198if (scopes.empty())199return {context, uname};200201// If there is no parent in the debug info, but some of the scopes have202// template params, then this is a case of bad debug info. See, for203// example, llvm.org/pr39607. We don't want to create an ambiguity between204// a NamespaceDecl and a CXXRecordDecl, so instead we create a class at205// global scope with the fully qualified name.206if (AnyScopesHaveTemplateParams(scopes))207return {context, std::string(record.Name)};208209for (llvm::ms_demangle::Node *scope : scopes) {210auto *nii = static_cast<llvm::ms_demangle::NamedIdentifierNode *>(scope);211std::string str = nii->toString();212context = GetOrCreateNamespaceDecl(str.c_str(), *context);213}214return {context, uname};215}216217// Otherwise, all we need to do is get the parent type of this type and218// recurse into our lazy type creation / AST reconstruction logic to get an219// LLDB TypeSP for the parent. This will cause the AST to automatically get220// the right DeclContext created for any parent.221clang::QualType parent_qt = GetOrCreateType(*parent_index);222if (parent_qt.isNull())223return {nullptr, ""};224225context = clang::TagDecl::castToDeclContext(parent_qt->getAsTagDecl());226return {context, uname};227}228229static bool isLocalVariableType(SymbolKind K) {230switch (K) {231case S_REGISTER:232case S_REGREL32:233case S_LOCAL:234return true;235default:236break;237}238return false;239}240241clang::Decl *PdbAstBuilder::GetOrCreateSymbolForId(PdbCompilandSymId id) {242SymbolFileNativePDB *pdb = static_cast<SymbolFileNativePDB *>(243m_clang.GetSymbolFile()->GetBackingSymbolFile());244PdbIndex &index = pdb->GetIndex();245CVSymbol cvs = index.ReadSymbolRecord(id);246247if (isLocalVariableType(cvs.kind())) {248clang::DeclContext *scope = GetParentDeclContext(id);249if (!scope)250return nullptr;251clang::Decl *scope_decl = clang::Decl::castFromDeclContext(scope);252PdbCompilandSymId scope_id =253PdbSymUid(m_decl_to_status[scope_decl].uid).asCompilandSym();254return GetOrCreateVariableDecl(scope_id, id);255}256257switch (cvs.kind()) {258case S_GPROC32:259case S_LPROC32:260return GetOrCreateFunctionDecl(id);261case S_GDATA32:262case S_LDATA32:263case S_GTHREAD32:264case S_CONSTANT:265// global variable266return nullptr;267case S_BLOCK32:268return GetOrCreateBlockDecl(id);269case S_INLINESITE:270return GetOrCreateInlinedFunctionDecl(id);271default:272return nullptr;273}274}275276std::optional<CompilerDecl>277PdbAstBuilder::GetOrCreateDeclForUid(PdbSymUid uid) {278if (clang::Decl *result = TryGetDecl(uid))279return ToCompilerDecl(*result);280281clang::Decl *result = nullptr;282switch (uid.kind()) {283case PdbSymUidKind::CompilandSym:284result = GetOrCreateSymbolForId(uid.asCompilandSym());285break;286case PdbSymUidKind::Type: {287clang::QualType qt = GetOrCreateType(uid.asTypeSym());288if (qt.isNull())289return std::nullopt;290if (auto *tag = qt->getAsTagDecl()) {291result = tag;292break;293}294return std::nullopt;295}296default:297return std::nullopt;298}299300if (!result)301return std::nullopt;302m_uid_to_decl[toOpaqueUid(uid)] = result;303return ToCompilerDecl(*result);304}305306clang::DeclContext *PdbAstBuilder::GetOrCreateDeclContextForUid(PdbSymUid uid) {307if (uid.kind() == PdbSymUidKind::CompilandSym) {308if (uid.asCompilandSym().offset == 0)309return FromCompilerDeclContext(GetTranslationUnitDecl());310}311auto option = GetOrCreateDeclForUid(uid);312if (!option)313return nullptr;314clang::Decl *decl = FromCompilerDecl(*option);315if (!decl)316return nullptr;317318return clang::Decl::castToDeclContext(decl);319}320321std::pair<clang::DeclContext *, std::string>322PdbAstBuilder::CreateDeclInfoForUndecoratedName(llvm::StringRef name) {323SymbolFileNativePDB *pdb = static_cast<SymbolFileNativePDB *>(324m_clang.GetSymbolFile()->GetBackingSymbolFile());325PdbIndex &index = pdb->GetIndex();326MSVCUndecoratedNameParser parser(name);327llvm::ArrayRef<MSVCUndecoratedNameSpecifier> specs = parser.GetSpecifiers();328329auto *context = FromCompilerDeclContext(GetTranslationUnitDecl());330331llvm::StringRef uname = specs.back().GetBaseName();332specs = specs.drop_back();333if (specs.empty())334return {context, std::string(name)};335336llvm::StringRef scope_name = specs.back().GetFullName();337338// It might be a class name, try that first.339std::vector<TypeIndex> types = index.tpi().findRecordsByName(scope_name);340while (!types.empty()) {341clang::QualType qt = GetOrCreateType(types.back());342if (qt.isNull())343continue;344clang::TagDecl *tag = qt->getAsTagDecl();345if (tag)346return {clang::TagDecl::castToDeclContext(tag), std::string(uname)};347types.pop_back();348}349350// If that fails, treat it as a series of namespaces.351for (const MSVCUndecoratedNameSpecifier &spec : specs) {352std::string ns_name = spec.GetBaseName().str();353context = GetOrCreateNamespaceDecl(ns_name.c_str(), *context);354}355return {context, std::string(uname)};356}357358clang::DeclContext *PdbAstBuilder::GetParentDeclContext(PdbSymUid uid) {359// We must do this *without* calling GetOrCreate on the current uid, as360// that would be an infinite recursion.361SymbolFileNativePDB *pdb = static_cast<SymbolFileNativePDB *>(362m_clang.GetSymbolFile()->GetBackingSymbolFile());363PdbIndex& index = pdb->GetIndex();364switch (uid.kind()) {365case PdbSymUidKind::CompilandSym: {366std::optional<PdbCompilandSymId> scope =367pdb->FindSymbolScope(uid.asCompilandSym());368if (scope)369return GetOrCreateDeclContextForUid(*scope);370371CVSymbol sym = index.ReadSymbolRecord(uid.asCompilandSym());372return CreateDeclInfoForUndecoratedName(getSymbolName(sym)).first;373}374case PdbSymUidKind::Type: {375// It could be a namespace, class, or global. We don't support nested376// functions yet. Anyway, we just need to consult the parent type map.377PdbTypeSymId type_id = uid.asTypeSym();378std::optional<TypeIndex> parent_index = pdb->GetParentType(type_id.index);379if (!parent_index)380return FromCompilerDeclContext(GetTranslationUnitDecl());381return GetOrCreateDeclContextForUid(PdbTypeSymId(*parent_index));382}383case PdbSymUidKind::FieldListMember:384// In this case the parent DeclContext is the one for the class that this385// member is inside of.386break;387case PdbSymUidKind::GlobalSym: {388// If this refers to a compiland symbol, just recurse in with that symbol.389// The only other possibilities are S_CONSTANT and S_UDT, in which case we390// need to parse the undecorated name to figure out the scope, then look391// that up in the TPI stream. If it's found, it's a type, othewrise it's392// a series of namespaces.393// FIXME: do this.394CVSymbol global = index.ReadSymbolRecord(uid.asGlobalSym());395switch (global.kind()) {396case SymbolKind::S_GDATA32:397case SymbolKind::S_LDATA32:398return CreateDeclInfoForUndecoratedName(getSymbolName(global)).first;;399case SymbolKind::S_PROCREF:400case SymbolKind::S_LPROCREF: {401ProcRefSym ref{global.kind()};402llvm::cantFail(403SymbolDeserializer::deserializeAs<ProcRefSym>(global, ref));404PdbCompilandSymId cu_sym_id{ref.modi(), ref.SymOffset};405return GetParentDeclContext(cu_sym_id);406}407case SymbolKind::S_CONSTANT:408case SymbolKind::S_UDT:409return CreateDeclInfoForUndecoratedName(getSymbolName(global)).first;410default:411break;412}413break;414}415default:416break;417}418return FromCompilerDeclContext(GetTranslationUnitDecl());419}420421bool PdbAstBuilder::CompleteType(clang::QualType qt) {422if (qt.isNull())423return false;424clang::TagDecl *tag = qt->getAsTagDecl();425if (qt->isArrayType()) {426const clang::Type *element_type = qt->getArrayElementTypeNoTypeQual();427tag = element_type->getAsTagDecl();428}429if (!tag)430return false;431432return CompleteTagDecl(*tag);433}434435bool PdbAstBuilder::CompleteTagDecl(clang::TagDecl &tag) {436// If this is not in our map, it's an error.437auto status_iter = m_decl_to_status.find(&tag);438lldbassert(status_iter != m_decl_to_status.end());439440// If it's already complete, just return.441DeclStatus &status = status_iter->second;442if (status.resolved)443return true;444445PdbTypeSymId type_id = PdbSymUid(status.uid).asTypeSym();446PdbIndex &index = static_cast<SymbolFileNativePDB *>(447m_clang.GetSymbolFile()->GetBackingSymbolFile())448->GetIndex();449lldbassert(IsTagRecord(type_id, index.tpi()));450451clang::QualType tag_qt = m_clang.getASTContext().getTypeDeclType(&tag);452TypeSystemClang::SetHasExternalStorage(tag_qt.getAsOpaquePtr(), false);453454TypeIndex tag_ti = type_id.index;455CVType cvt = index.tpi().getType(tag_ti);456if (cvt.kind() == LF_MODIFIER)457tag_ti = LookThroughModifierRecord(cvt);458459PdbTypeSymId best_ti = GetBestPossibleDecl(tag_ti, index.tpi());460cvt = index.tpi().getType(best_ti.index);461lldbassert(IsTagRecord(cvt));462463if (IsForwardRefUdt(cvt)) {464// If we can't find a full decl for this forward ref anywhere in the debug465// info, then we have no way to complete it.466return false;467}468469TypeIndex field_list_ti = GetFieldListIndex(cvt);470CVType field_list_cvt = index.tpi().getType(field_list_ti);471if (field_list_cvt.kind() != LF_FIELDLIST)472return false;473FieldListRecord field_list;474if (llvm::Error error = TypeDeserializer::deserializeAs<FieldListRecord>(475field_list_cvt, field_list))476llvm::consumeError(std::move(error));477478// Visit all members of this class, then perform any finalization necessary479// to complete the class.480CompilerType ct = ToCompilerType(tag_qt);481UdtRecordCompleter completer(best_ti, ct, tag, *this, index, m_decl_to_status,482m_cxx_record_map);483llvm::Error error =484llvm::codeview::visitMemberRecordStream(field_list.Data, completer);485completer.complete();486487m_decl_to_status[&tag].resolved = true;488if (error) {489llvm::consumeError(std::move(error));490return false;491}492return true;493}494495clang::QualType PdbAstBuilder::CreateSimpleType(TypeIndex ti) {496if (ti == TypeIndex::NullptrT())497return GetBasicType(lldb::eBasicTypeNullPtr);498499if (ti.getSimpleMode() != SimpleTypeMode::Direct) {500clang::QualType direct_type = GetOrCreateType(ti.makeDirect());501if (direct_type.isNull())502return {};503return m_clang.getASTContext().getPointerType(direct_type);504}505506if (ti.getSimpleKind() == SimpleTypeKind::NotTranslated)507return {};508509lldb::BasicType bt = GetCompilerTypeForSimpleKind(ti.getSimpleKind());510if (bt == lldb::eBasicTypeInvalid)511return {};512513return GetBasicType(bt);514}515516clang::QualType PdbAstBuilder::CreatePointerType(const PointerRecord &pointer) {517clang::QualType pointee_type = GetOrCreateType(pointer.ReferentType);518519// This can happen for pointers to LF_VTSHAPE records, which we shouldn't520// create in the AST.521if (pointee_type.isNull())522return {};523524if (pointer.isPointerToMember()) {525MemberPointerInfo mpi = pointer.getMemberInfo();526clang::QualType class_type = GetOrCreateType(mpi.ContainingType);527if (class_type.isNull())528return {};529if (clang::TagDecl *tag = class_type->getAsTagDecl()) {530clang::MSInheritanceAttr::Spelling spelling;531switch (mpi.Representation) {532case llvm::codeview::PointerToMemberRepresentation::SingleInheritanceData:533case llvm::codeview::PointerToMemberRepresentation::534SingleInheritanceFunction:535spelling =536clang::MSInheritanceAttr::Spelling::Keyword_single_inheritance;537break;538case llvm::codeview::PointerToMemberRepresentation::539MultipleInheritanceData:540case llvm::codeview::PointerToMemberRepresentation::541MultipleInheritanceFunction:542spelling =543clang::MSInheritanceAttr::Spelling::Keyword_multiple_inheritance;544break;545case llvm::codeview::PointerToMemberRepresentation::546VirtualInheritanceData:547case llvm::codeview::PointerToMemberRepresentation::548VirtualInheritanceFunction:549spelling =550clang::MSInheritanceAttr::Spelling::Keyword_virtual_inheritance;551break;552case llvm::codeview::PointerToMemberRepresentation::Unknown:553spelling =554clang::MSInheritanceAttr::Spelling::Keyword_unspecified_inheritance;555break;556default:557spelling = clang::MSInheritanceAttr::Spelling::SpellingNotCalculated;558break;559}560tag->addAttr(clang::MSInheritanceAttr::CreateImplicit(561m_clang.getASTContext(), spelling));562}563return m_clang.getASTContext().getMemberPointerType(564pointee_type, class_type.getTypePtr());565}566567clang::QualType pointer_type;568if (pointer.getMode() == PointerMode::LValueReference)569pointer_type = m_clang.getASTContext().getLValueReferenceType(pointee_type);570else if (pointer.getMode() == PointerMode::RValueReference)571pointer_type = m_clang.getASTContext().getRValueReferenceType(pointee_type);572else573pointer_type = m_clang.getASTContext().getPointerType(pointee_type);574575if ((pointer.getOptions() & PointerOptions::Const) != PointerOptions::None)576pointer_type.addConst();577578if ((pointer.getOptions() & PointerOptions::Volatile) != PointerOptions::None)579pointer_type.addVolatile();580581if ((pointer.getOptions() & PointerOptions::Restrict) != PointerOptions::None)582pointer_type.addRestrict();583584return pointer_type;585}586587clang::QualType588PdbAstBuilder::CreateModifierType(const ModifierRecord &modifier) {589clang::QualType unmodified_type = GetOrCreateType(modifier.ModifiedType);590if (unmodified_type.isNull())591return {};592593if ((modifier.Modifiers & ModifierOptions::Const) != ModifierOptions::None)594unmodified_type.addConst();595if ((modifier.Modifiers & ModifierOptions::Volatile) != ModifierOptions::None)596unmodified_type.addVolatile();597598return unmodified_type;599}600601clang::QualType PdbAstBuilder::CreateRecordType(PdbTypeSymId id,602const TagRecord &record) {603clang::DeclContext *context = nullptr;604std::string uname;605std::tie(context, uname) = CreateDeclInfoForType(record, id.index);606if (!context)607return {};608609clang::TagTypeKind ttk = TranslateUdtKind(record);610lldb::AccessType access = (ttk == clang::TagTypeKind::Class)611? lldb::eAccessPrivate612: lldb::eAccessPublic;613614ClangASTMetadata metadata;615metadata.SetUserID(toOpaqueUid(id));616metadata.SetIsDynamicCXXType(false);617618CompilerType ct = m_clang.CreateRecordType(619context, OptionalClangModuleID(), access, uname, llvm::to_underlying(ttk),620lldb::eLanguageTypeC_plus_plus, &metadata);621622lldbassert(ct.IsValid());623624TypeSystemClang::StartTagDeclarationDefinition(ct);625626// Even if it's possible, don't complete it at this point. Just mark it627// forward resolved, and if/when LLDB needs the full definition, it can628// ask us.629clang::QualType result =630clang::QualType::getFromOpaquePtr(ct.GetOpaqueQualType());631632TypeSystemClang::SetHasExternalStorage(result.getAsOpaquePtr(), true);633return result;634}635636clang::Decl *PdbAstBuilder::TryGetDecl(PdbSymUid uid) const {637auto iter = m_uid_to_decl.find(toOpaqueUid(uid));638if (iter != m_uid_to_decl.end())639return iter->second;640return nullptr;641}642643clang::NamespaceDecl *644PdbAstBuilder::GetOrCreateNamespaceDecl(const char *name,645clang::DeclContext &context) {646return m_clang.GetUniqueNamespaceDeclaration(647IsAnonymousNamespaceName(name) ? nullptr : name, &context,648OptionalClangModuleID());649}650651clang::BlockDecl *652PdbAstBuilder::GetOrCreateBlockDecl(PdbCompilandSymId block_id) {653if (clang::Decl *decl = TryGetDecl(block_id))654return llvm::dyn_cast<clang::BlockDecl>(decl);655656clang::DeclContext *scope = GetParentDeclContext(block_id);657658clang::BlockDecl *block_decl =659m_clang.CreateBlockDeclaration(scope, OptionalClangModuleID());660m_uid_to_decl.insert({toOpaqueUid(block_id), block_decl});661662DeclStatus status;663status.resolved = true;664status.uid = toOpaqueUid(block_id);665m_decl_to_status.insert({block_decl, status});666667return block_decl;668}669670clang::VarDecl *PdbAstBuilder::CreateVariableDecl(PdbSymUid uid, CVSymbol sym,671clang::DeclContext &scope) {672VariableInfo var_info = GetVariableNameInfo(sym);673clang::QualType qt = GetOrCreateType(var_info.type);674if (qt.isNull())675return nullptr;676677clang::VarDecl *var_decl = m_clang.CreateVariableDeclaration(678&scope, OptionalClangModuleID(), var_info.name.str().c_str(), qt);679680m_uid_to_decl[toOpaqueUid(uid)] = var_decl;681DeclStatus status;682status.resolved = true;683status.uid = toOpaqueUid(uid);684m_decl_to_status.insert({var_decl, status});685return var_decl;686}687688clang::VarDecl *689PdbAstBuilder::GetOrCreateVariableDecl(PdbCompilandSymId scope_id,690PdbCompilandSymId var_id) {691if (clang::Decl *decl = TryGetDecl(var_id))692return llvm::dyn_cast<clang::VarDecl>(decl);693694clang::DeclContext *scope = GetOrCreateDeclContextForUid(scope_id);695if (!scope)696return nullptr;697698SymbolFileNativePDB *pdb = static_cast<SymbolFileNativePDB *>(699m_clang.GetSymbolFile()->GetBackingSymbolFile());700PdbIndex &index = pdb->GetIndex();701CVSymbol sym = index.ReadSymbolRecord(var_id);702return CreateVariableDecl(PdbSymUid(var_id), sym, *scope);703}704705clang::VarDecl *PdbAstBuilder::GetOrCreateVariableDecl(PdbGlobalSymId var_id) {706if (clang::Decl *decl = TryGetDecl(var_id))707return llvm::dyn_cast<clang::VarDecl>(decl);708709SymbolFileNativePDB *pdb = static_cast<SymbolFileNativePDB *>(710m_clang.GetSymbolFile()->GetBackingSymbolFile());711PdbIndex &index = pdb->GetIndex();712CVSymbol sym = index.ReadSymbolRecord(var_id);713auto context = FromCompilerDeclContext(GetTranslationUnitDecl());714return CreateVariableDecl(PdbSymUid(var_id), sym, *context);715}716717clang::TypedefNameDecl *718PdbAstBuilder::GetOrCreateTypedefDecl(PdbGlobalSymId id) {719if (clang::Decl *decl = TryGetDecl(id))720return llvm::dyn_cast<clang::TypedefNameDecl>(decl);721722SymbolFileNativePDB *pdb = static_cast<SymbolFileNativePDB *>(723m_clang.GetSymbolFile()->GetBackingSymbolFile());724PdbIndex &index = pdb->GetIndex();725CVSymbol sym = index.ReadSymbolRecord(id);726lldbassert(sym.kind() == S_UDT);727UDTSym udt = llvm::cantFail(SymbolDeserializer::deserializeAs<UDTSym>(sym));728729clang::DeclContext *scope = GetParentDeclContext(id);730731PdbTypeSymId real_type_id{udt.Type, false};732clang::QualType qt = GetOrCreateType(real_type_id);733if (qt.isNull() || !scope)734return nullptr;735736std::string uname = std::string(DropNameScope(udt.Name));737738CompilerType ct = ToCompilerType(qt).CreateTypedef(739uname.c_str(), ToCompilerDeclContext(*scope), 0);740clang::TypedefNameDecl *tnd = m_clang.GetAsTypedefDecl(ct);741DeclStatus status;742status.resolved = true;743status.uid = toOpaqueUid(id);744m_decl_to_status.insert({tnd, status});745return tnd;746}747748clang::QualType PdbAstBuilder::GetBasicType(lldb::BasicType type) {749CompilerType ct = m_clang.GetBasicType(type);750return clang::QualType::getFromOpaquePtr(ct.GetOpaqueQualType());751}752753clang::QualType PdbAstBuilder::CreateType(PdbTypeSymId type) {754if (type.index.isSimple())755return CreateSimpleType(type.index);756757SymbolFileNativePDB *pdb = static_cast<SymbolFileNativePDB *>(758m_clang.GetSymbolFile()->GetBackingSymbolFile());759PdbIndex &index = pdb->GetIndex();760CVType cvt = index.tpi().getType(type.index);761762if (cvt.kind() == LF_MODIFIER) {763ModifierRecord modifier;764llvm::cantFail(765TypeDeserializer::deserializeAs<ModifierRecord>(cvt, modifier));766return CreateModifierType(modifier);767}768769if (cvt.kind() == LF_POINTER) {770PointerRecord pointer;771llvm::cantFail(772TypeDeserializer::deserializeAs<PointerRecord>(cvt, pointer));773return CreatePointerType(pointer);774}775776if (IsTagRecord(cvt)) {777CVTagRecord tag = CVTagRecord::create(cvt);778if (tag.kind() == CVTagRecord::Union)779return CreateRecordType(type.index, tag.asUnion());780if (tag.kind() == CVTagRecord::Enum)781return CreateEnumType(type.index, tag.asEnum());782return CreateRecordType(type.index, tag.asClass());783}784785if (cvt.kind() == LF_ARRAY) {786ArrayRecord ar;787llvm::cantFail(TypeDeserializer::deserializeAs<ArrayRecord>(cvt, ar));788return CreateArrayType(ar);789}790791if (cvt.kind() == LF_PROCEDURE) {792ProcedureRecord pr;793llvm::cantFail(TypeDeserializer::deserializeAs<ProcedureRecord>(cvt, pr));794return CreateFunctionType(pr.ArgumentList, pr.ReturnType, pr.CallConv);795}796797if (cvt.kind() == LF_MFUNCTION) {798MemberFunctionRecord mfr;799llvm::cantFail(800TypeDeserializer::deserializeAs<MemberFunctionRecord>(cvt, mfr));801return CreateFunctionType(mfr.ArgumentList, mfr.ReturnType, mfr.CallConv);802}803804return {};805}806807clang::QualType PdbAstBuilder::GetOrCreateType(PdbTypeSymId type) {808if (type.index.isNoneType())809return {};810811lldb::user_id_t uid = toOpaqueUid(type);812auto iter = m_uid_to_type.find(uid);813if (iter != m_uid_to_type.end())814return iter->second;815816SymbolFileNativePDB *pdb = static_cast<SymbolFileNativePDB *>(817m_clang.GetSymbolFile()->GetBackingSymbolFile());818PdbIndex &index = pdb->GetIndex();819PdbTypeSymId best_type = GetBestPossibleDecl(type, index.tpi());820821clang::QualType qt;822if (best_type.index != type.index) {823// This is a forward decl. Call GetOrCreate on the full decl, then map the824// forward decl id to the full decl QualType.825clang::QualType qt = GetOrCreateType(best_type);826if (qt.isNull())827return {};828m_uid_to_type[toOpaqueUid(type)] = qt;829return qt;830}831832// This is either a full decl, or a forward decl with no matching full decl833// in the debug info.834qt = CreateType(type);835if (qt.isNull())836return {};837838m_uid_to_type[toOpaqueUid(type)] = qt;839if (IsTagRecord(type, index.tpi())) {840clang::TagDecl *tag = qt->getAsTagDecl();841lldbassert(m_decl_to_status.count(tag) == 0);842843DeclStatus &status = m_decl_to_status[tag];844status.uid = uid;845status.resolved = false;846}847return qt;848}849850clang::FunctionDecl *851PdbAstBuilder::CreateFunctionDecl(PdbCompilandSymId func_id,852llvm::StringRef func_name, TypeIndex func_ti,853CompilerType func_ct, uint32_t param_count,854clang::StorageClass func_storage,855bool is_inline, clang::DeclContext *parent) {856clang::FunctionDecl *function_decl = nullptr;857if (parent->isRecord()) {858SymbolFileNativePDB *pdb = static_cast<SymbolFileNativePDB *>(859m_clang.GetSymbolFile()->GetBackingSymbolFile());860PdbIndex &index = pdb->GetIndex();861clang::QualType parent_qt = llvm::cast<clang::TypeDecl>(parent)862->getTypeForDecl()863->getCanonicalTypeInternal();864lldb::opaque_compiler_type_t parent_opaque_ty =865ToCompilerType(parent_qt).GetOpaqueQualType();866// FIXME: Remove this workaround.867auto iter = m_cxx_record_map.find(parent_opaque_ty);868if (iter != m_cxx_record_map.end()) {869if (iter->getSecond().contains({func_name, func_ct})) {870return nullptr;871}872}873874CVType cvt = index.tpi().getType(func_ti);875MemberFunctionRecord func_record(static_cast<TypeRecordKind>(cvt.kind()));876llvm::cantFail(TypeDeserializer::deserializeAs<MemberFunctionRecord>(877cvt, func_record));878TypeIndex class_index = func_record.getClassType();879880CVType parent_cvt = index.tpi().getType(class_index);881TagRecord tag_record = CVTagRecord::create(parent_cvt).asTag();882// If it's a forward reference, try to get the real TypeIndex.883if (tag_record.isForwardRef()) {884llvm::Expected<TypeIndex> eti =885index.tpi().findFullDeclForForwardRef(class_index);886if (eti) {887tag_record = CVTagRecord::create(index.tpi().getType(*eti)).asTag();888}889}890if (!tag_record.FieldList.isSimple()) {891CVType field_list_cvt = index.tpi().getType(tag_record.FieldList);892FieldListRecord field_list;893if (llvm::Error error = TypeDeserializer::deserializeAs<FieldListRecord>(894field_list_cvt, field_list))895llvm::consumeError(std::move(error));896CreateMethodDecl process(index, m_clang, func_ti, function_decl,897parent_opaque_ty, func_name, func_ct);898if (llvm::Error err = visitMemberRecordStream(field_list.Data, process))899llvm::consumeError(std::move(err));900}901902if (!function_decl) {903function_decl = m_clang.AddMethodToCXXRecordType(904parent_opaque_ty, func_name,905/*mangled_name=*/nullptr, func_ct,906/*access=*/lldb::AccessType::eAccessPublic,907/*is_virtual=*/false, /*is_static=*/false,908/*is_inline=*/false, /*is_explicit=*/false,909/*is_attr_used=*/false, /*is_artificial=*/false);910}911m_cxx_record_map[parent_opaque_ty].insert({func_name, func_ct});912} else {913function_decl = m_clang.CreateFunctionDeclaration(914parent, OptionalClangModuleID(), func_name, func_ct, func_storage,915is_inline);916CreateFunctionParameters(func_id, *function_decl, param_count);917}918return function_decl;919}920921clang::FunctionDecl *922PdbAstBuilder::GetOrCreateInlinedFunctionDecl(PdbCompilandSymId inlinesite_id) {923SymbolFileNativePDB *pdb = static_cast<SymbolFileNativePDB *>(924m_clang.GetSymbolFile()->GetBackingSymbolFile());925PdbIndex &index = pdb->GetIndex();926CompilandIndexItem *cii =927index.compilands().GetCompiland(inlinesite_id.modi);928CVSymbol sym = cii->m_debug_stream.readSymbolAtOffset(inlinesite_id.offset);929InlineSiteSym inline_site(static_cast<SymbolRecordKind>(sym.kind()));930cantFail(SymbolDeserializer::deserializeAs<InlineSiteSym>(sym, inline_site));931932// Inlinee is the id index to the function id record that is inlined.933PdbTypeSymId func_id(inline_site.Inlinee, true);934// Look up the function decl by the id index to see if we have created a935// function decl for a different inlinesite that refers the same function.936if (clang::Decl *decl = TryGetDecl(func_id))937return llvm::dyn_cast<clang::FunctionDecl>(decl);938clang::FunctionDecl *function_decl =939CreateFunctionDeclFromId(func_id, inlinesite_id);940if (function_decl == nullptr)941return nullptr;942943// Use inline site id in m_decl_to_status because it's expected to be a944// PdbCompilandSymId so that we can parse local variables info after it.945uint64_t inlinesite_uid = toOpaqueUid(inlinesite_id);946DeclStatus status;947status.resolved = true;948status.uid = inlinesite_uid;949m_decl_to_status.insert({function_decl, status});950// Use the index in IPI stream as uid in m_uid_to_decl, because index in IPI951// stream are unique and there could be multiple inline sites (different ids)952// referring the same inline function. This avoid creating multiple same953// inline function delcs.954uint64_t func_uid = toOpaqueUid(func_id);955lldbassert(m_uid_to_decl.count(func_uid) == 0);956m_uid_to_decl[func_uid] = function_decl;957return function_decl;958}959960clang::FunctionDecl *961PdbAstBuilder::CreateFunctionDeclFromId(PdbTypeSymId func_tid,962PdbCompilandSymId func_sid) {963lldbassert(func_tid.is_ipi);964SymbolFileNativePDB *pdb = static_cast<SymbolFileNativePDB *>(965m_clang.GetSymbolFile()->GetBackingSymbolFile());966PdbIndex &index = pdb->GetIndex();967CVType func_cvt = index.ipi().getType(func_tid.index);968llvm::StringRef func_name;969TypeIndex func_ti;970clang::DeclContext *parent = nullptr;971switch (func_cvt.kind()) {972case LF_MFUNC_ID: {973MemberFuncIdRecord mfr;974cantFail(975TypeDeserializer::deserializeAs<MemberFuncIdRecord>(func_cvt, mfr));976func_name = mfr.getName();977func_ti = mfr.getFunctionType();978PdbTypeSymId class_type_id(mfr.ClassType, false);979parent = GetOrCreateDeclContextForUid(class_type_id);980break;981}982case LF_FUNC_ID: {983FuncIdRecord fir;984cantFail(TypeDeserializer::deserializeAs<FuncIdRecord>(func_cvt, fir));985func_name = fir.getName();986func_ti = fir.getFunctionType();987parent = FromCompilerDeclContext(GetTranslationUnitDecl());988if (!fir.ParentScope.isNoneType()) {989CVType parent_cvt = index.ipi().getType(fir.ParentScope);990if (parent_cvt.kind() == LF_STRING_ID) {991StringIdRecord sir;992cantFail(993TypeDeserializer::deserializeAs<StringIdRecord>(parent_cvt, sir));994parent = GetOrCreateNamespaceDecl(sir.String.data(), *parent);995}996}997break;998}999default:1000lldbassert(false && "Invalid function id type!");1001}1002clang::QualType func_qt = GetOrCreateType(func_ti);1003if (func_qt.isNull() || !parent)1004return nullptr;1005CompilerType func_ct = ToCompilerType(func_qt);1006uint32_t param_count =1007llvm::cast<clang::FunctionProtoType>(func_qt)->getNumParams();1008return CreateFunctionDecl(func_sid, func_name, func_ti, func_ct, param_count,1009clang::SC_None, true, parent);1010}10111012clang::FunctionDecl *1013PdbAstBuilder::GetOrCreateFunctionDecl(PdbCompilandSymId func_id) {1014if (clang::Decl *decl = TryGetDecl(func_id))1015return llvm::dyn_cast<clang::FunctionDecl>(decl);10161017clang::DeclContext *parent = GetParentDeclContext(PdbSymUid(func_id));1018if (!parent)1019return nullptr;1020std::string context_name;1021if (clang::NamespaceDecl *ns = llvm::dyn_cast<clang::NamespaceDecl>(parent)) {1022context_name = ns->getQualifiedNameAsString();1023} else if (clang::TagDecl *tag = llvm::dyn_cast<clang::TagDecl>(parent)) {1024context_name = tag->getQualifiedNameAsString();1025}10261027SymbolFileNativePDB *pdb = static_cast<SymbolFileNativePDB *>(1028m_clang.GetSymbolFile()->GetBackingSymbolFile());1029PdbIndex &index = pdb->GetIndex();1030CVSymbol cvs = index.ReadSymbolRecord(func_id);1031ProcSym proc(static_cast<SymbolRecordKind>(cvs.kind()));1032llvm::cantFail(SymbolDeserializer::deserializeAs<ProcSym>(cvs, proc));10331034PdbTypeSymId type_id(proc.FunctionType);1035clang::QualType qt = GetOrCreateType(type_id);1036if (qt.isNull())1037return nullptr;10381039clang::StorageClass storage = clang::SC_None;1040if (proc.Kind == SymbolRecordKind::ProcSym)1041storage = clang::SC_Static;10421043const clang::FunctionProtoType *func_type =1044llvm::dyn_cast<clang::FunctionProtoType>(qt);10451046CompilerType func_ct = ToCompilerType(qt);10471048llvm::StringRef proc_name = proc.Name;1049proc_name.consume_front(context_name);1050proc_name.consume_front("::");1051clang::FunctionDecl *function_decl =1052CreateFunctionDecl(func_id, proc_name, proc.FunctionType, func_ct,1053func_type->getNumParams(), storage, false, parent);1054if (function_decl == nullptr)1055return nullptr;10561057lldbassert(m_uid_to_decl.count(toOpaqueUid(func_id)) == 0);1058m_uid_to_decl[toOpaqueUid(func_id)] = function_decl;1059DeclStatus status;1060status.resolved = true;1061status.uid = toOpaqueUid(func_id);1062m_decl_to_status.insert({function_decl, status});10631064return function_decl;1065}10661067void PdbAstBuilder::CreateFunctionParameters(PdbCompilandSymId func_id,1068clang::FunctionDecl &function_decl,1069uint32_t param_count) {1070SymbolFileNativePDB *pdb = static_cast<SymbolFileNativePDB *>(1071m_clang.GetSymbolFile()->GetBackingSymbolFile());1072PdbIndex &index = pdb->GetIndex();1073CompilandIndexItem *cii = index.compilands().GetCompiland(func_id.modi);1074CVSymbolArray scope =1075cii->m_debug_stream.getSymbolArrayForScope(func_id.offset);10761077scope.drop_front();1078auto begin = scope.begin();1079auto end = scope.end();1080std::vector<clang::ParmVarDecl *> params;1081for (uint32_t i = 0; i < param_count && begin != end;) {1082uint32_t record_offset = begin.offset();1083CVSymbol sym = *begin++;10841085TypeIndex param_type;1086llvm::StringRef param_name;1087switch (sym.kind()) {1088case S_REGREL32: {1089RegRelativeSym reg(SymbolRecordKind::RegRelativeSym);1090cantFail(SymbolDeserializer::deserializeAs<RegRelativeSym>(sym, reg));1091param_type = reg.Type;1092param_name = reg.Name;1093break;1094}1095case S_REGISTER: {1096RegisterSym reg(SymbolRecordKind::RegisterSym);1097cantFail(SymbolDeserializer::deserializeAs<RegisterSym>(sym, reg));1098param_type = reg.Index;1099param_name = reg.Name;1100break;1101}1102case S_LOCAL: {1103LocalSym local(SymbolRecordKind::LocalSym);1104cantFail(SymbolDeserializer::deserializeAs<LocalSym>(sym, local));1105if ((local.Flags & LocalSymFlags::IsParameter) == LocalSymFlags::None)1106continue;1107param_type = local.Type;1108param_name = local.Name;1109break;1110}1111case S_BLOCK32:1112case S_INLINESITE:1113case S_INLINESITE2:1114// All parameters should come before the first block/inlinesite. If that1115// isn't the case, then perhaps this is bad debug info that doesn't1116// contain information about all parameters.1117return;1118default:1119continue;1120}11211122PdbCompilandSymId param_uid(func_id.modi, record_offset);1123clang::QualType qt = GetOrCreateType(param_type);1124if (qt.isNull())1125return;11261127CompilerType param_type_ct = m_clang.GetType(qt);1128clang::ParmVarDecl *param = m_clang.CreateParameterDeclaration(1129&function_decl, OptionalClangModuleID(), param_name.str().c_str(),1130param_type_ct, clang::SC_None, true);1131lldbassert(m_uid_to_decl.count(toOpaqueUid(param_uid)) == 0);11321133m_uid_to_decl[toOpaqueUid(param_uid)] = param;1134params.push_back(param);1135++i;1136}11371138if (!params.empty() && params.size() == param_count)1139m_clang.SetFunctionParameters(&function_decl, params);1140}11411142clang::QualType PdbAstBuilder::CreateEnumType(PdbTypeSymId id,1143const EnumRecord &er) {1144clang::DeclContext *decl_context = nullptr;1145std::string uname;1146std::tie(decl_context, uname) = CreateDeclInfoForType(er, id.index);1147if (!decl_context)1148return {};11491150clang::QualType underlying_type = GetOrCreateType(er.UnderlyingType);1151if (underlying_type.isNull())1152return {};11531154Declaration declaration;1155CompilerType enum_ct = m_clang.CreateEnumerationType(1156uname, decl_context, OptionalClangModuleID(), declaration,1157ToCompilerType(underlying_type), er.isScoped());11581159TypeSystemClang::StartTagDeclarationDefinition(enum_ct);1160TypeSystemClang::SetHasExternalStorage(enum_ct.GetOpaqueQualType(), true);11611162return clang::QualType::getFromOpaquePtr(enum_ct.GetOpaqueQualType());1163}11641165clang::QualType PdbAstBuilder::CreateArrayType(const ArrayRecord &ar) {1166clang::QualType element_type = GetOrCreateType(ar.ElementType);11671168SymbolFileNativePDB *pdb = static_cast<SymbolFileNativePDB *>(1169m_clang.GetSymbolFile()->GetBackingSymbolFile());1170PdbIndex &index = pdb->GetIndex();1171uint64_t element_size = GetSizeOfType({ar.ElementType}, index.tpi());1172if (element_type.isNull() || element_size == 0)1173return {};1174uint64_t element_count = ar.Size / element_size;11751176CompilerType array_ct = m_clang.CreateArrayType(ToCompilerType(element_type),1177element_count, false);1178return clang::QualType::getFromOpaquePtr(array_ct.GetOpaqueQualType());1179}11801181clang::QualType PdbAstBuilder::CreateFunctionType(1182TypeIndex args_type_idx, TypeIndex return_type_idx,1183llvm::codeview::CallingConvention calling_convention) {1184SymbolFileNativePDB *pdb = static_cast<SymbolFileNativePDB *>(1185m_clang.GetSymbolFile()->GetBackingSymbolFile());1186PdbIndex &index = pdb->GetIndex();1187TpiStream &stream = index.tpi();1188CVType args_cvt = stream.getType(args_type_idx);1189ArgListRecord args;1190llvm::cantFail(1191TypeDeserializer::deserializeAs<ArgListRecord>(args_cvt, args));11921193llvm::ArrayRef<TypeIndex> arg_indices = llvm::ArrayRef(args.ArgIndices);1194bool is_variadic = IsCVarArgsFunction(arg_indices);1195if (is_variadic)1196arg_indices = arg_indices.drop_back();11971198std::vector<CompilerType> arg_types;1199arg_types.reserve(arg_indices.size());12001201for (TypeIndex arg_index : arg_indices) {1202clang::QualType arg_type = GetOrCreateType(arg_index);1203if (arg_type.isNull())1204continue;1205arg_types.push_back(ToCompilerType(arg_type));1206}12071208clang::QualType return_type = GetOrCreateType(return_type_idx);1209if (return_type.isNull())1210return {};12111212std::optional<clang::CallingConv> cc =1213TranslateCallingConvention(calling_convention);1214if (!cc)1215return {};12161217CompilerType return_ct = ToCompilerType(return_type);1218CompilerType func_sig_ast_type = m_clang.CreateFunctionType(1219return_ct, arg_types.data(), arg_types.size(), is_variadic, 0, *cc);12201221return clang::QualType::getFromOpaquePtr(1222func_sig_ast_type.GetOpaqueQualType());1223}12241225static bool isTagDecl(clang::DeclContext &context) {1226return llvm::isa<clang::TagDecl>(&context);1227}12281229static bool isFunctionDecl(clang::DeclContext &context) {1230return llvm::isa<clang::FunctionDecl>(&context);1231}12321233static bool isBlockDecl(clang::DeclContext &context) {1234return llvm::isa<clang::BlockDecl>(&context);1235}12361237void PdbAstBuilder::ParseNamespace(clang::DeclContext &context) {1238clang::NamespaceDecl *ns = llvm::dyn_cast<clang::NamespaceDecl>(&context);1239if (m_parsed_namespaces.contains(ns))1240return;1241std::string qname = ns->getQualifiedNameAsString();1242SymbolFileNativePDB *pdb = static_cast<SymbolFileNativePDB *>(1243m_clang.GetSymbolFile()->GetBackingSymbolFile());1244PdbIndex &index = pdb->GetIndex();1245TypeIndex ti{index.tpi().TypeIndexBegin()};1246for (const CVType &cvt : index.tpi().typeArray()) {1247PdbTypeSymId tid{ti};1248++ti;12491250if (!IsTagRecord(cvt))1251continue;12521253CVTagRecord tag = CVTagRecord::create(cvt);12541255// Call CreateDeclInfoForType unconditionally so that the namespace info1256// gets created. But only call CreateRecordType if the namespace name1257// matches.1258clang::DeclContext *context = nullptr;1259std::string uname;1260std::tie(context, uname) = CreateDeclInfoForType(tag.asTag(), tid.index);1261if (!context || !context->isNamespace())1262continue;12631264clang::NamespaceDecl *ns = llvm::cast<clang::NamespaceDecl>(context);1265llvm::StringRef ns_name = ns->getName();1266if (ns_name.starts_with(qname)) {1267ns_name = ns_name.drop_front(qname.size());1268if (ns_name.starts_with("::"))1269GetOrCreateType(tid);1270}1271}1272ParseAllFunctionsAndNonLocalVars();1273m_parsed_namespaces.insert(ns);1274}12751276void PdbAstBuilder::ParseAllTypes() {1277llvm::call_once(m_parse_all_types, [this]() {1278SymbolFileNativePDB *pdb = static_cast<SymbolFileNativePDB *>(1279m_clang.GetSymbolFile()->GetBackingSymbolFile());1280PdbIndex &index = pdb->GetIndex();1281TypeIndex ti{index.tpi().TypeIndexBegin()};1282for (const CVType &cvt : index.tpi().typeArray()) {1283PdbTypeSymId tid{ti};1284++ti;12851286if (!IsTagRecord(cvt))1287continue;12881289GetOrCreateType(tid);1290}1291});1292}12931294void PdbAstBuilder::ParseAllFunctionsAndNonLocalVars() {1295llvm::call_once(m_parse_functions_and_non_local_vars, [this]() {1296SymbolFileNativePDB *pdb = static_cast<SymbolFileNativePDB *>(1297m_clang.GetSymbolFile()->GetBackingSymbolFile());1298PdbIndex &index = pdb->GetIndex();1299uint32_t module_count = index.dbi().modules().getModuleCount();1300for (uint16_t modi = 0; modi < module_count; ++modi) {1301CompilandIndexItem &cii = index.compilands().GetOrCreateCompiland(modi);1302const CVSymbolArray &symbols = cii.m_debug_stream.getSymbolArray();1303auto iter = symbols.begin();1304while (iter != symbols.end()) {1305PdbCompilandSymId sym_id{modi, iter.offset()};13061307switch (iter->kind()) {1308case S_GPROC32:1309case S_LPROC32:1310GetOrCreateFunctionDecl(sym_id);1311iter = symbols.at(getScopeEndOffset(*iter));1312break;1313case S_GDATA32:1314case S_GTHREAD32:1315case S_LDATA32:1316case S_LTHREAD32:1317GetOrCreateVariableDecl(PdbCompilandSymId(modi, 0), sym_id);1318++iter;1319break;1320default:1321++iter;1322continue;1323}1324}1325}1326});1327}13281329static CVSymbolArray skipFunctionParameters(clang::Decl &decl,1330const CVSymbolArray &symbols) {1331clang::FunctionDecl *func_decl = llvm::dyn_cast<clang::FunctionDecl>(&decl);1332if (!func_decl)1333return symbols;1334unsigned int params = func_decl->getNumParams();1335if (params == 0)1336return symbols;13371338CVSymbolArray result = symbols;13391340while (!result.empty()) {1341if (params == 0)1342return result;13431344CVSymbol sym = *result.begin();1345result.drop_front();13461347if (!isLocalVariableType(sym.kind()))1348continue;13491350--params;1351}1352return result;1353}13541355void PdbAstBuilder::ParseBlockChildren(PdbCompilandSymId block_id) {1356SymbolFileNativePDB *pdb = static_cast<SymbolFileNativePDB *>(1357m_clang.GetSymbolFile()->GetBackingSymbolFile());1358PdbIndex &index = pdb->GetIndex();1359CVSymbol sym = index.ReadSymbolRecord(block_id);1360lldbassert(sym.kind() == S_GPROC32 || sym.kind() == S_LPROC32 ||1361sym.kind() == S_BLOCK32 || sym.kind() == S_INLINESITE);1362CompilandIndexItem &cii =1363index.compilands().GetOrCreateCompiland(block_id.modi);1364CVSymbolArray symbols =1365cii.m_debug_stream.getSymbolArrayForScope(block_id.offset);13661367// Function parameters should already have been created when the function was1368// parsed.1369if (sym.kind() == S_GPROC32 || sym.kind() == S_LPROC32)1370symbols =1371skipFunctionParameters(*m_uid_to_decl[toOpaqueUid(block_id)], symbols);13721373symbols.drop_front();1374auto begin = symbols.begin();1375while (begin != symbols.end()) {1376PdbCompilandSymId child_sym_id(block_id.modi, begin.offset());1377GetOrCreateSymbolForId(child_sym_id);1378if (begin->kind() == S_BLOCK32 || begin->kind() == S_INLINESITE) {1379ParseBlockChildren(child_sym_id);1380begin = symbols.at(getScopeEndOffset(*begin));1381}1382++begin;1383}1384}13851386void PdbAstBuilder::ParseDeclsForSimpleContext(clang::DeclContext &context) {13871388clang::Decl *decl = clang::Decl::castFromDeclContext(&context);1389lldbassert(decl);13901391auto iter = m_decl_to_status.find(decl);1392lldbassert(iter != m_decl_to_status.end());13931394if (auto *tag = llvm::dyn_cast<clang::TagDecl>(&context)) {1395CompleteTagDecl(*tag);1396return;1397}13981399if (isFunctionDecl(context) || isBlockDecl(context)) {1400PdbCompilandSymId block_id = PdbSymUid(iter->second.uid).asCompilandSym();1401ParseBlockChildren(block_id);1402}1403}14041405void PdbAstBuilder::ParseDeclsForContext(clang::DeclContext &context) {1406// Namespaces aren't explicitly represented in the debug info, and the only1407// way to parse them is to parse all type info, demangling every single type1408// and trying to reconstruct the DeclContext hierarchy this way. Since this1409// is an expensive operation, we have to special case it so that we do other1410// work (such as parsing the items that appear within the namespaces) at the1411// same time.1412if (context.isTranslationUnit()) {1413ParseAllTypes();1414ParseAllFunctionsAndNonLocalVars();1415return;1416}14171418if (context.isNamespace()) {1419ParseNamespace(context);1420return;1421}14221423if (isTagDecl(context) || isFunctionDecl(context) || isBlockDecl(context)) {1424ParseDeclsForSimpleContext(context);1425return;1426}1427}14281429CompilerDecl PdbAstBuilder::ToCompilerDecl(clang::Decl &decl) {1430return m_clang.GetCompilerDecl(&decl);1431}14321433CompilerType PdbAstBuilder::ToCompilerType(clang::QualType qt) {1434return {m_clang.weak_from_this(), qt.getAsOpaquePtr()};1435}14361437CompilerDeclContext1438PdbAstBuilder::ToCompilerDeclContext(clang::DeclContext &context) {1439return m_clang.CreateDeclContext(&context);1440}14411442clang::Decl * PdbAstBuilder::FromCompilerDecl(CompilerDecl decl) {1443return ClangUtil::GetDecl(decl);1444}14451446clang::DeclContext *1447PdbAstBuilder::FromCompilerDeclContext(CompilerDeclContext context) {1448return static_cast<clang::DeclContext *>(context.GetOpaqueDeclContext());1449}14501451void PdbAstBuilder::Dump(Stream &stream) {1452m_clang.Dump(stream.AsRawOstream());1453}145414551456