Index: lldb/trunk/include/lldb/Symbol/CompileUnit.h =================================================================== --- lldb/trunk/include/lldb/Symbol/CompileUnit.h +++ lldb/trunk/include/lldb/Symbol/CompileUnit.h @@ -409,6 +409,11 @@ //------------------------------------------------------------------ bool GetIsOptimized(); + //------------------------------------------------------------------ + /// Returns the number of functions in this compile unit + //------------------------------------------------------------------ + size_t GetNumFunctions() const { return m_functions_by_uid.size(); } + protected: void *m_user_data; ///< User data for the SymbolFile parser to store ///information into. Index: lldb/trunk/lit/SymbolFile/NativePDB/typedefs.cpp =================================================================== --- lldb/trunk/lit/SymbolFile/NativePDB/typedefs.cpp +++ lldb/trunk/lit/SymbolFile/NativePDB/typedefs.cpp @@ -0,0 +1,71 @@ +// clang-format off + +// REQUIRES: system-windows +// RUN: %build --compiler=clang-cl --nodefaultlib -o %t.exe -- %s +// RUN: env LLDB_USE_NATIVE_PDB_READER=1 lldb-test symbols -dump-ast %t.exe | FileCheck %s + +namespace A { + namespace B { + using NamespaceTypedef = double; + } + template + class C { + public: + using ClassTypedef = T; + }; + using ClassTypedef = C::ClassTypedef; + using ClassTypedef2 = C::ClassTypedef; + + template + using AliasTemplate = typename C::ClassTypedef; +} + +namespace { + using AnonNamespaceTypedef = bool; +} + +using IntTypedef = int; + +using ULongArrayTypedef = unsigned long[10]; + +using RefTypedef = long double*&; + +using FuncPtrTypedef = long long(*)(int&, unsigned char**, short[], const double, volatile bool); + +using VarArgsFuncTypedef = char(*)(void*, long, unsigned short, unsigned int, ...); + +using VarArgsFuncTypedefA = float(*)(...); + +int main(int argc, char **argv) { + long double *Ptr; + + A::B::NamespaceTypedef *X0; + A::C::ClassTypedef *X1; + A::C::ClassTypedef *X2; + AnonNamespaceTypedef *X3; + IntTypedef *X4; + ULongArrayTypedef *X5; + RefTypedef X6 = Ptr; + FuncPtrTypedef X7; + VarArgsFuncTypedef X8; + VarArgsFuncTypedefA X9; + A::AliasTemplate X10; + return 0; +} + + +// CHECK: namespace `anonymous namespace' { +// CHECK-NEXT: typedef bool AnonNamespaceTypedef; +// CHECK-NEXT: } +// CHECK-NEXT: typedef unsigned long ULongArrayTypedef[10]; +// CHECK-NEXT: typedef double *&RefTypedef; +// CHECK-NEXT: namespace A { +// CHECK-NEXT: namespace B { +// CHECK-NEXT: typedef double NamespaceTypedef; +// CHECK-NEXT: } +// CHECK-NEXT: typedef float AliasTemplate; +// CHECK-NEXT: } +// CHECK-NEXT: typedef long long (*FuncPtrTypedef)(int &, unsigned char **, short *, const double, volatile bool); +// CHECK-NEXT: typedef char (*VarArgsFuncTypedef)(void *, long, unsigned short, unsigned int, ...); +// CHECK-NEXT: typedef float (*VarArgsFuncTypedefA)(...); +// CHECK-NEXT: typedef int IntTypedef; Index: lldb/trunk/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.h =================================================================== --- lldb/trunk/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.h +++ lldb/trunk/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.h @@ -69,6 +69,7 @@ clang::VarDecl *GetOrCreateVariableDecl(PdbCompilandSymId scope_id, PdbCompilandSymId var_id); clang::VarDecl *GetOrCreateVariableDecl(PdbGlobalSymId var_id); + clang::TypedefNameDecl *GetOrCreateTypedefDecl(PdbGlobalSymId id); void ParseDeclsForContext(clang::DeclContext &context); clang::QualType GetBasicType(lldb::BasicType type); @@ -112,6 +113,8 @@ clang::VarDecl *CreateVariableDecl(PdbSymUid uid, llvm::codeview::CVSymbol sym, clang::DeclContext &scope); + clang::DeclContext * + GetParentDeclContextForSymbol(const llvm::codeview::CVSymbol &sym); void ParseAllNamespacesPlusChildrenOf(llvm::Optional parent); void ParseDeclsForSimpleContext(clang::DeclContext &context); @@ -120,6 +123,8 @@ void BuildParentMap(); std::pair CreateDeclInfoForType(const llvm::codeview::TagRecord &record, TypeIndex ti); + std::pair + CreateDeclInfoForUndecoratedName(llvm::StringRef uname); clang::QualType CreateSimpleType(TypeIndex ti); PdbIndex &m_index; Index: lldb/trunk/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp =================================================================== --- lldb/trunk/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp +++ lldb/trunk/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp @@ -2,6 +2,7 @@ #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h" #include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h" +#include "llvm/DebugInfo/CodeView/RecordName.h" #include "llvm/DebugInfo/CodeView/SymbolDeserializer.h" #include "llvm/DebugInfo/CodeView/SymbolRecord.h" #include "llvm/DebugInfo/CodeView/SymbolRecordHelpers.h" @@ -13,6 +14,7 @@ #include "llvm/DebugInfo/PDB/Native/TpiStream.h" #include "llvm/Demangle/MicrosoftDemangle.h" +#include "Plugins/Language/CPlusPlus/MSVCUndecoratedNameParser.h" #include "lldb/Core/Module.h" #include "lldb/Symbol/ClangASTContext.h" #include "lldb/Symbol/ClangExternalASTSourceCommon.h" @@ -215,10 +217,15 @@ std::pair PdbAstBuilder::CreateDeclInfoForType(const TagRecord &record, TypeIndex ti) { // FIXME: Move this to GetDeclContextContainingUID. + if (!record.hasUniqueName()) + return CreateDeclInfoForUndecoratedName(record.Name); llvm::ms_demangle::Demangler demangler; StringView sv(record.UniqueName.begin(), record.UniqueName.size()); llvm::ms_demangle::TagTypeNode *ttn = demangler.parseTagUniqueName(sv); + if (demangler.Error) + return {m_clang.GetTranslationUnitDecl(), record.UniqueName}; + llvm::ms_demangle::IdentifierNode *idn = ttn->QualifiedName->getUnqualifiedIdentifier(); std::string uname = idn->toString(llvm::ms_demangle::OF_NoTagSpecifier); @@ -491,6 +498,82 @@ return clang::Decl::castToDeclContext(decl); } +std::pair +PdbAstBuilder::CreateDeclInfoForUndecoratedName(llvm::StringRef name) { + MSVCUndecoratedNameParser parser(name); + llvm::ArrayRef specs = parser.GetSpecifiers(); + + clang::DeclContext *context = &GetTranslationUnitDecl(); + + llvm::StringRef uname = specs.back().GetBaseName(); + specs = specs.drop_back(); + if (specs.empty()) + return {context, name}; + + llvm::StringRef scope_name = specs.back().GetFullName(); + + // It might be a class name, try that first. + std::vector types = m_index.tpi().findRecordsByName(scope_name); + while (!types.empty()) { + clang::QualType qt = GetOrCreateType(types.back()); + clang::TagDecl *tag = qt->getAsTagDecl(); + if (tag) + return {clang::TagDecl::castToDeclContext(tag), uname}; + types.pop_back(); + } + + // If that fails, treat it as a series of namespaces. + for (const MSVCUndecoratedNameSpecifier &spec : specs) { + std::string ns_name = spec.GetBaseName().str(); + context = m_clang.GetUniqueNamespaceDeclaration(ns_name.c_str(), context); + } + return {context, uname}; +} + +clang::DeclContext * +PdbAstBuilder::GetParentDeclContextForSymbol(const CVSymbol &sym) { + if (!SymbolHasAddress(sym)) + return CreateDeclInfoForUndecoratedName(getSymbolName(sym)).first; + SegmentOffset addr = GetSegmentAndOffset(sym); + llvm::Optional pub = + FindPublicSym(addr, m_index.symrecords(), m_index.publics()); + if (!pub) + return CreateDeclInfoForUndecoratedName(getSymbolName(sym)).first; + + llvm::ms_demangle::Demangler demangler; + StringView name{pub->Name.begin(), pub->Name.size()}; + llvm::ms_demangle::SymbolNode *node = demangler.parse(name); + if (!node) + return &GetTranslationUnitDecl(); + llvm::ArrayRef name_components{ + node->Name->Components->Nodes, node->Name->Components->Count - 1}; + + if (!name_components.empty()) { + // Render the current list of scope nodes as a fully qualified name, and + // look it up in the debug info as a type name. If we find something, + // this is a type (which may itself be prefixed by a namespace). If we + // don't, this is a list of namespaces. + std::string qname = RenderScopeList(name_components); + std::vector matches = m_index.tpi().findRecordsByName(qname); + while (!matches.empty()) { + clang::QualType qt = GetOrCreateType(matches.back()); + clang::TagDecl *tag = qt->getAsTagDecl(); + if (tag) + return clang::TagDecl::castToDeclContext(tag); + matches.pop_back(); + } + } + + // It's not a type. It must be a series of namespaces. + clang::DeclContext *context = &GetTranslationUnitDecl(); + while (!name_components.empty()) { + std::string ns = name_components.front()->toString(); + context = m_clang.GetUniqueNamespaceDeclaration(ns.c_str(), context); + name_components = name_components.drop_front(); + } + return context; +} + clang::DeclContext *PdbAstBuilder::GetParentDeclContext(PdbSymUid uid) { // We must do this *without* calling GetOrCreate on the current uid, as // that would be an infinite recursion. @@ -502,46 +585,7 @@ return GetOrCreateDeclContextForUid(*scope); CVSymbol sym = m_index.ReadSymbolRecord(uid.asCompilandSym()); - if (!SymbolHasAddress(sym)) - return &GetTranslationUnitDecl(); - SegmentOffset addr = GetSegmentAndOffset(sym); - llvm::Optional pub = - FindPublicSym(addr, m_index.symrecords(), m_index.publics()); - if (!pub) - return &GetTranslationUnitDecl(); - - llvm::ms_demangle::Demangler demangler; - StringView name{pub->Name.begin(), pub->Name.size()}; - llvm::ms_demangle::SymbolNode *node = demangler.parse(name); - if (!node) - return &GetTranslationUnitDecl(); - llvm::ArrayRef name_components{ - node->Name->Components->Nodes, node->Name->Components->Count - 1}; - - if (!name_components.empty()) { - // Render the current list of scope nodes as a fully qualified name, and - // look it up in the debug info as a type name. If we find something, - // this is a type (which may itself be prefixed by a namespace). If we - // don't, this is a list of namespaces. - std::string qname = RenderScopeList(name_components); - std::vector matches = m_index.tpi().findRecordsByName(qname); - while (!matches.empty()) { - clang::QualType qt = GetOrCreateType(matches.back()); - clang::TagDecl *tag = qt->getAsTagDecl(); - if (tag) - return clang::TagDecl::castToDeclContext(tag); - matches.pop_back(); - } - } - - // It's not a type. It must be a series of namespaces. - clang::DeclContext *context = &GetTranslationUnitDecl(); - while (!name_components.empty()) { - std::string ns = name_components.front()->toString(); - context = m_clang.GetUniqueNamespaceDeclaration(ns.c_str(), context); - name_components = name_components.drop_front(); - } - return context; + return GetParentDeclContextForSymbol(sym); } case PdbSymUidKind::Type: { // It could be a namespace, class, or global. We don't support nested @@ -556,6 +600,34 @@ // In this case the parent DeclContext is the one for the class that this // member is inside of. break; + case PdbSymUidKind::GlobalSym: { + // If this refers to a compiland symbol, just recurse in with that symbol. + // The only other possibilities are S_CONSTANT and S_UDT, in which case we + // need to parse the undecorated name to figure out the scope, then look + // that up in the TPI stream. If it's found, it's a type, othewrise it's + // a series of namespaces. + // FIXME: do this. + CVSymbol global = m_index.ReadSymbolRecord(uid.asGlobalSym()); + switch (global.kind()) { + case SymbolKind::S_GDATA32: + case SymbolKind::S_LDATA32: + return GetParentDeclContextForSymbol(global); + case SymbolKind::S_PROCREF: + case SymbolKind::S_LPROCREF: { + ProcRefSym ref{global.kind()}; + llvm::cantFail( + SymbolDeserializer::deserializeAs(global, ref)); + PdbCompilandSymId cu_sym_id{ref.modi(), ref.SymOffset}; + return GetParentDeclContext(cu_sym_id); + } + case SymbolKind::S_CONSTANT: + case SymbolKind::S_UDT: + return CreateDeclInfoForUndecoratedName(getSymbolName(global)).first; + default: + break; + } + break; + } default: break; } @@ -645,6 +717,11 @@ clang::QualType PdbAstBuilder::CreatePointerType(const PointerRecord &pointer) { clang::QualType pointee_type = GetOrCreateType(pointer.ReferentType); + // This can happen for pointers to LF_VTSHAPE records, which we shouldn't + // create in the AST. + if (pointee_type.isNull()) + return {}; + if (pointer.isPointerToMember()) { MemberPointerInfo mpi = pointer.getMemberInfo(); clang::QualType class_type = GetOrCreateType(mpi.ContainingType); @@ -677,8 +754,9 @@ clang::QualType PdbAstBuilder::CreateModifierType(const ModifierRecord &modifier) { - clang::QualType unmodified_type = GetOrCreateType(modifier.ModifiedType); + if (unmodified_type.isNull()) + return {}; if ((modifier.Modifiers & ModifierOptions::Const) != ModifierOptions::None) unmodified_type.addConst(); @@ -786,6 +864,32 @@ return CreateVariableDecl(PdbSymUid(var_id), sym, GetTranslationUnitDecl()); } +clang::TypedefNameDecl * +PdbAstBuilder::GetOrCreateTypedefDecl(PdbGlobalSymId id) { + if (clang::Decl *decl = TryGetDecl(id)) + return llvm::dyn_cast(decl); + + CVSymbol sym = m_index.ReadSymbolRecord(id); + lldbassert(sym.kind() == S_UDT); + UDTSym udt = llvm::cantFail(SymbolDeserializer::deserializeAs(sym)); + + clang::DeclContext *scope = GetParentDeclContext(id); + + PdbTypeSymId real_type_id{udt.Type, false}; + clang::QualType qt = GetOrCreateType(real_type_id); + + std::string uname = DropNameScope(udt.Name); + + CompilerType ct = m_clang.CreateTypedefType(ToCompilerType(qt), uname.c_str(), + ToCompilerDeclContext(*scope)); + clang::TypedefNameDecl *tnd = m_clang.GetAsTypedefDecl(ct); + DeclStatus status; + status.resolved = true; + status.uid = toOpaqueUid(id); + m_decl_to_status.insert({tnd, status}); + return tnd; +} + clang::QualType PdbAstBuilder::GetBasicType(lldb::BasicType type) { CompilerType ct = m_clang.GetBasicType(type); return clang::QualType::getFromOpaquePtr(ct.GetOpaqueQualType()); Index: lldb/trunk/source/Plugins/SymbolFile/NativePDB/PdbUtil.h =================================================================== --- lldb/trunk/source/Plugins/SymbolFile/NativePDB/PdbUtil.h +++ lldb/trunk/source/Plugins/SymbolFile/NativePDB/PdbUtil.h @@ -66,6 +66,14 @@ return cvunion; } + llvm::StringRef name() const { + if (m_kind == Struct || m_kind == Union) + return cvclass.Name; + if (m_kind == Enum) + return cvenum.Name; + return cvunion.Name; + } + private: CVTagRecord(llvm::codeview::ClassRecord &&c); CVTagRecord(llvm::codeview::UnionRecord &&u); Index: lldb/trunk/source/Plugins/SymbolFile/NativePDB/PdbUtil.cpp =================================================================== --- lldb/trunk/source/Plugins/SymbolFile/NativePDB/PdbUtil.cpp +++ lldb/trunk/source/Plugins/SymbolFile/NativePDB/PdbUtil.cpp @@ -17,8 +17,8 @@ #include "llvm/DebugInfo/CodeView/TypeDeserializer.h" #include "llvm/DebugInfo/PDB/Native/TpiStream.h" +#include "Plugins/Language/CPlusPlus/MSVCUndecoratedNameParser.h" #include "lldb/Utility/LLDBAssert.h" - #include "lldb/lldb-enumerations.h" using namespace lldb_private; @@ -449,16 +449,7 @@ } llvm::StringRef lldb_private::npdb::DropNameScope(llvm::StringRef name) { - // Not all PDB names can be parsed with CPlusPlusNameParser. - // E.g. it fails on names containing `anonymous namespace'. - // So we simply drop everything before '::' - - auto offset = name.rfind("::"); - if (offset == llvm::StringRef::npos) - return name; - assert(offset + 2 <= name.size()); - - return name.substr(offset + 2); + return MSVCUndecoratedNameParser::DropScope(name); } VariableInfo lldb_private::npdb::GetVariableNameInfo(CVSymbol sym) { @@ -558,10 +549,6 @@ result.ranges = MakeRangeList(index, loc.Range, loc.Gaps); } else { // FIXME: Handle other kinds - llvm::APSInt value; - value = 42; - result.location = MakeConstantLocationExpression( - TypeIndex::Int32(), index.tpi(), value, module); } return result; } Index: lldb/trunk/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h =================================================================== --- lldb/trunk/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h +++ lldb/trunk/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h @@ -203,12 +203,14 @@ lldb::VariableSP GetOrCreateLocalVariable(PdbCompilandSymId scope_id, PdbCompilandSymId var_id, bool is_param); + lldb::TypeSP GetOrCreateTypedef(PdbGlobalSymId id); lldb::FunctionSP CreateFunction(PdbCompilandSymId func_id, CompileUnit &comp_unit); Block &CreateBlock(PdbCompilandSymId block_id); lldb::VariableSP CreateLocalVariable(PdbCompilandSymId scope_id, PdbCompilandSymId var_id, bool is_param); + lldb::TypeSP CreateTypedef(PdbGlobalSymId id); lldb::CompUnitSP CreateCompileUnit(const CompilandIndexItem &cci); lldb::TypeSP CreateType(PdbTypeSymId type_id, CompilerType ct); lldb::TypeSP CreateAndCacheType(PdbTypeSymId type_id); @@ -222,6 +224,7 @@ llvm::BumpPtrAllocator m_allocator; lldb::addr_t m_obj_load_address = 0; + bool m_done_full_type_scan = false; std::unique_ptr m_index; Index: lldb/trunk/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp =================================================================== --- lldb/trunk/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp +++ lldb/trunk/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp @@ -15,6 +15,7 @@ #include "clang/AST/DeclCXX.h" #include "clang/AST/Type.h" +#include "Plugins/Language/CPlusPlus/MSVCUndecoratedNameParser.h" #include "lldb/Core/Module.h" #include "lldb/Core/PluginManager.h" #include "lldb/Core/StreamBuffer.h" @@ -394,7 +395,11 @@ ProcSym proc(static_cast(sym_record.kind())); cantFail(SymbolDeserializer::deserializeAs(sym_record, proc)); + if (proc.FunctionType == TypeIndex::None()) + return nullptr; TypeSP func_type = GetOrCreateType(proc.FunctionType); + if (!func_type) + return nullptr; PdbTypeSymId sig_id(proc.FunctionType, false); Mangled mangled(proc.Name); @@ -515,9 +520,19 @@ } static std::string GetUnqualifiedTypeName(const TagRecord &record) { + if (!record.hasUniqueName()) { + MSVCUndecoratedNameParser parser(record.Name); + llvm::ArrayRef specs = parser.GetSpecifiers(); + + return specs.back().GetBaseName(); + } + llvm::ms_demangle::Demangler demangler; StringView sv(record.UniqueName.begin(), record.UniqueName.size()); llvm::ms_demangle::TagTypeNode *ttn = demangler.parseTagUniqueName(sv); + if (demangler.Error) + return record.Name; + llvm::ms_demangle::IdentifierNode *idn = ttn->QualifiedName->getUnqualifiedIdentifier(); return idn->toString(); @@ -696,7 +711,10 @@ if (iter != m_types.end()) return iter->second; - return CreateAndCacheType(type_id); + TypeSP type = CreateAndCacheType(type_id); + if (type) + m_obj_file->GetModule()->GetTypeList()->Insert(type); + return type; } VariableSP SymbolFileNativePDB::CreateGlobalVariable(PdbGlobalSymId var_id) { @@ -821,7 +839,6 @@ if (emplace_result.second) emplace_result.first->second = CreateFunction(func_id, comp_unit); - lldbassert(emplace_result.first->second); return emplace_result.first->second; } @@ -887,7 +904,26 @@ size_t SymbolFileNativePDB::ParseCompileUnitFunctions(const SymbolContext &sc) { lldbassert(sc.comp_unit); - return false; + + PdbSymUid uid{sc.comp_unit->GetID()}; + lldbassert(uid.kind() == PdbSymUidKind::Compiland); + uint16_t modi = uid.asCompiland().modi; + CompilandIndexItem &cii = m_index->compilands().GetOrCreateCompiland(modi); + + size_t count = sc.comp_unit->GetNumFunctions(); + const CVSymbolArray &syms = cii.m_debug_stream.getSymbolArray(); + for (auto iter = syms.begin(); iter != syms.end(); ++iter) { + if (iter->kind() != S_LPROC32 && iter->kind() != S_GPROC32) + continue; + + PdbCompilandSymId sym_id{modi, iter.offset()}; + + FunctionSP func = GetOrCreateFunction(sym_id, *sc.comp_unit); + } + + size_t new_count = sc.comp_unit->GetNumFunctions(); + lldbassert(new_count >= count); + return new_count - count; } static bool NeedsResolvedCompileUnit(uint32_t resolve_scope) { @@ -1238,7 +1274,47 @@ return match_count; } -size_t SymbolFileNativePDB::ParseTypes(const SymbolContext &sc) { return 0; } +size_t SymbolFileNativePDB::ParseTypes(const SymbolContext &sc) { + // Only do the full type scan the first time. + if (m_done_full_type_scan) + return 0; + + size_t old_count = m_obj_file->GetModule()->GetTypeList()->GetSize(); + LazyRandomTypeCollection &types = m_index->tpi().typeCollection(); + + // First process the entire TPI stream. + for (auto ti = types.getFirst(); ti; ti = types.getNext(*ti)) { + TypeSP type = GetOrCreateType(*ti); + if (type) + (void)type->GetFullCompilerType(); + } + + // Next look for S_UDT records in the globals stream. + for (const uint32_t gid : m_index->globals().getGlobalsTable()) { + PdbGlobalSymId global{gid, false}; + CVSymbol sym = m_index->ReadSymbolRecord(global); + if (sym.kind() != S_UDT) + continue; + + UDTSym udt = llvm::cantFail(SymbolDeserializer::deserializeAs(sym)); + bool is_typedef = true; + if (IsTagRecord(PdbTypeSymId{udt.Type, false}, m_index->tpi())) { + CVType cvt = m_index->tpi().getType(udt.Type); + llvm::StringRef name = CVTagRecord::create(cvt).name(); + if (name == udt.Name) + is_typedef = false; + } + + if (is_typedef) + GetOrCreateTypedef(global); + } + + size_t new_count = m_obj_file->GetModule()->GetTypeList()->GetSize(); + + m_done_full_type_scan = true; + + return new_count - old_count; +} size_t SymbolFileNativePDB::ParseVariablesForCompileUnit(CompileUnit &comp_unit, @@ -1253,6 +1329,8 @@ bool is_param) { ModuleSP module = GetObjectFile()->GetModule(); VariableInfo var_info = GetVariableLocationInfo(*m_index, var_id, module); + if (!var_info.location || !var_info.ranges) + return nullptr; CompilandIndexItem *cii = m_index->compilands().GetCompiland(var_id.modi); CompUnitSP comp_unit_sp = GetOrCreateCompileUnit(*cii); @@ -1285,6 +1363,32 @@ return CreateLocalVariable(scope_id, var_id, is_param); } +TypeSP SymbolFileNativePDB::CreateTypedef(PdbGlobalSymId id) { + CVSymbol sym = m_index->ReadSymbolRecord(id); + lldbassert(sym.kind() == SymbolKind::S_UDT); + + UDTSym udt = llvm::cantFail(SymbolDeserializer::deserializeAs(sym)); + + TypeSP target_type = GetOrCreateType(udt.Type); + + (void)m_ast->GetOrCreateTypedefDecl(id); + + Declaration decl; + return std::make_shared( + toOpaqueUid(id), this, ConstString(udt.Name), target_type->GetByteSize(), + nullptr, target_type->GetID(), lldb_private::Type::eEncodingIsTypedefUID, + decl, target_type->GetForwardCompilerType(), + lldb_private::Type::eResolveStateForward); +} + +TypeSP SymbolFileNativePDB::GetOrCreateTypedef(PdbGlobalSymId id) { + auto iter = m_types.find(toOpaqueUid(id)); + if (iter != m_types.end()) + return iter->second; + + return CreateTypedef(id); +} + size_t SymbolFileNativePDB::ParseVariablesForBlock(PdbCompilandSymId block_id) { Block &block = GetOrCreateBlock(block_id); @@ -1349,7 +1453,8 @@ variable = GetOrCreateLocalVariable(block_id, child_sym_id, is_param); if (is_param) --params_remaining; - variables->AddVariableIfUnique(variable); + if (variable) + variables->AddVariableIfUnique(variable); break; default: break;