diff options
Diffstat (limited to 'llvm')
19 files changed, 1087 insertions, 142 deletions
diff --git a/llvm/include/llvm/DebugInfo/CodeView/TypeRecord.h b/llvm/include/llvm/DebugInfo/CodeView/TypeRecord.h index 61ebdf878ce..ee6f53854e7 100644 --- a/llvm/include/llvm/DebugInfo/CodeView/TypeRecord.h +++ b/llvm/include/llvm/DebugInfo/CodeView/TypeRecord.h @@ -923,6 +923,7 @@ public: uint32_t Signature; }; + } // end namespace codeview } // end namespace llvm diff --git a/llvm/include/llvm/DebugInfo/CodeView/TypeRecordHelpers.h b/llvm/include/llvm/DebugInfo/CodeView/TypeRecordHelpers.h new file mode 100644 index 00000000000..389472ed1ae --- /dev/null +++ b/llvm/include/llvm/DebugInfo/CodeView/TypeRecordHelpers.h @@ -0,0 +1,28 @@ +//===- TypeRecordHelpers.h --------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_CODEVIEW_TYPERECORDHELPERS_H +#define LLVM_DEBUGINFO_CODEVIEW_TYPERECORDHELPERS_H + +#include "llvm/DebugInfo/CodeView/TypeRecord.h" + +namespace llvm { + namespace codeview { + /// Given an arbitrary codeview type, determine if it is an LF_STRUCTURE, + /// LF_CLASS, LF_INTERFACE, LF_UNION, or LF_ENUM with the forward ref class + /// option. + bool isUdtForwardRef(CVType CVT); + + /// Given a CVType which is assumed to be an LF_MODIFIER, return the + /// TypeIndex of the type that the LF_MODIFIER modifies. + TypeIndex getModifiedType(const CVType &CVT); + } +} + +#endif diff --git a/llvm/include/llvm/DebugInfo/PDB/IPDBEnumChildren.h b/llvm/include/llvm/DebugInfo/PDB/IPDBEnumChildren.h index 14f13734a2b..7017f2600e9 100644 --- a/llvm/include/llvm/DebugInfo/PDB/IPDBEnumChildren.h +++ b/llvm/include/llvm/DebugInfo/PDB/IPDBEnumChildren.h @@ -35,11 +35,9 @@ class NullEnumerator : public IPDBEnumChildren<ChildType> { virtual uint32_t getChildCount() const override { return 0; } virtual std::unique_ptr<ChildType> getChildAtIndex(uint32_t Index) const override { - assert(false); return nullptr; } virtual std::unique_ptr<ChildType> getNext() override { - assert(false); return nullptr; } virtual void reset() override {} diff --git a/llvm/include/llvm/DebugInfo/PDB/Native/NativeEnumTypes.h b/llvm/include/llvm/DebugInfo/PDB/Native/NativeEnumTypes.h index 59d436172f9..492caf7ee4a 100644 --- a/llvm/include/llvm/DebugInfo/PDB/Native/NativeEnumTypes.h +++ b/llvm/include/llvm/DebugInfo/PDB/Native/NativeEnumTypes.h @@ -26,7 +26,7 @@ class NativeEnumTypes : public IPDBEnumChildren<PDBSymbol> { public: NativeEnumTypes(NativeSession &Session, codeview::LazyRandomTypeCollection &TypeCollection, - codeview::TypeLeafKind Kind); + std::vector<codeview::TypeLeafKind> Kinds); uint32_t getChildCount() const override; std::unique_ptr<PDBSymbol> getChildAtIndex(uint32_t Index) const override; @@ -34,10 +34,6 @@ public: void reset() override; private: - NativeEnumTypes(NativeSession &Session, - const std::vector<codeview::TypeIndex> &Matches, - codeview::TypeLeafKind Kind); - std::vector<codeview::TypeIndex> Matches; uint32_t Index; NativeSession &Session; diff --git a/llvm/include/llvm/DebugInfo/PDB/Native/NativeTypeEnum.h b/llvm/include/llvm/DebugInfo/PDB/Native/NativeTypeEnum.h index 3c6915e4e3f..a5cbefc1811 100644 --- a/llvm/include/llvm/DebugInfo/PDB/Native/NativeTypeEnum.h +++ b/llvm/include/llvm/DebugInfo/PDB/Native/NativeTypeEnum.h @@ -10,6 +10,7 @@ #ifndef LLVM_DEBUGINFO_PDB_NATIVE_NATIVETYPEENUM_H #define LLVM_DEBUGINFO_PDB_NATIVE_NATIVETYPEENUM_H +#include "llvm/ADT/Optional.h" #include "llvm/DebugInfo/CodeView/CodeView.h" #include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h" #include "llvm/DebugInfo/PDB/Native/NativeRawSymbol.h" @@ -26,9 +27,8 @@ public: codeview::EnumRecord Record); NativeTypeEnum(NativeSession &Session, SymIndexId Id, - codeview::TypeIndex ModifierTI, - codeview::ModifierRecord Modifier, - codeview::EnumRecord EnumRecord); + NativeTypeEnum &UnmodifiedType, + codeview::ModifierRecord Modifier); ~NativeTypeEnum() override; void dump(raw_ostream &OS, int Indent, PdbSymbolIdField ShowIdFields, @@ -60,10 +60,12 @@ public: bool isInterfaceUdt() const override; const NativeTypeBuiltin &getUnderlyingBuiltinType() const; + const codeview::EnumRecord &getEnumRecord() const { return *Record; } protected: codeview::TypeIndex Index; - codeview::EnumRecord Record; + Optional<codeview::EnumRecord> Record; + NativeTypeEnum *UnmodifiedType = nullptr; Optional<codeview::ModifierRecord> Modifiers; }; diff --git a/llvm/include/llvm/DebugInfo/PDB/Native/NativeTypeUDT.h b/llvm/include/llvm/DebugInfo/PDB/Native/NativeTypeUDT.h new file mode 100644 index 00000000000..84821d8731b --- /dev/null +++ b/llvm/include/llvm/DebugInfo/PDB/Native/NativeTypeUDT.h @@ -0,0 +1,74 @@ +//===- NativeTypeUDT.h - info about class/struct type ------------*- C++-*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_NATIVE_NATIVETYPEUDT_H +#define LLVM_DEBUGINFO_PDB_NATIVE_NATIVETYPEUDT_H + +#include "llvm/ADT/Optional.h" +#include "llvm/DebugInfo/CodeView/CodeView.h" +#include "llvm/DebugInfo/CodeView/TypeRecord.h" +#include "llvm/DebugInfo/PDB/Native/NativeRawSymbol.h" +#include "llvm/DebugInfo/PDB/Native/NativeSession.h" + +namespace llvm { +namespace pdb { + +class NativeTypeUDT : public NativeRawSymbol { +public: + NativeTypeUDT(NativeSession &Session, SymIndexId Id, codeview::TypeIndex TI, + codeview::ClassRecord Class); + + NativeTypeUDT(NativeSession &Session, SymIndexId Id, codeview::TypeIndex TI, + codeview::UnionRecord Union); + + NativeTypeUDT(NativeSession &Session, SymIndexId Id, + NativeTypeUDT &UnmodifiedType, + codeview::ModifierRecord Modifier); + + ~NativeTypeUDT() override; + + void dump(raw_ostream &OS, int Indent, PdbSymbolIdField ShowIdFields, + PdbSymbolIdField RecurseIdFields) const override; + + std::string getName() const override; + SymIndexId getLexicalParentId() const override; + SymIndexId getUnmodifiedTypeId() const override; + SymIndexId getVirtualTableShapeId() const override; + uint64_t getLength() const override; + PDB_UdtType getUdtKind() const override; + bool hasConstructor() const override; + bool isConstType() const override; + bool hasAssignmentOperator() const override; + bool hasCastOperator() const override; + bool hasNestedTypes() const override; + bool hasOverloadedOperator() const override; + bool isInterfaceUdt() const override; + bool isIntrinsic() const override; + bool isNested() const override; + bool isPacked() const override; + bool isRefUdt() const override; + bool isScoped() const override; + bool isValueUdt() const override; + bool isUnalignedType() const override; + bool isVolatileType() const override; + +protected: + codeview::TypeIndex Index; + + Optional<codeview::ClassRecord> Class; + Optional<codeview::UnionRecord> Union; + NativeTypeUDT *UnmodifiedType = nullptr; + codeview::TagRecord *Tag = nullptr; + Optional<codeview::ModifierRecord> Modifiers; +}; + +} // namespace pdb +} // namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_NATIVE_NATIVETYPEUDT_H
\ No newline at end of file diff --git a/llvm/include/llvm/DebugInfo/PDB/Native/SymbolCache.h b/llvm/include/llvm/DebugInfo/PDB/Native/SymbolCache.h index 3ef01c472b9..c0ffff70c62 100644 --- a/llvm/include/llvm/DebugInfo/PDB/Native/SymbolCache.h +++ b/llvm/include/llvm/DebugInfo/PDB/Native/SymbolCache.h @@ -77,6 +77,9 @@ public: std::unique_ptr<IPDBEnumSymbols> createTypeEnumerator(codeview::TypeLeafKind Kind); + std::unique_ptr<IPDBEnumSymbols> + createTypeEnumerator(std::vector<codeview::TypeLeafKind> Kinds); + SymIndexId findSymbolByTypeIndex(codeview::TypeIndex TI); template <typename ConcreteSymbolT, typename... Args> diff --git a/llvm/lib/DebugInfo/CodeView/CMakeLists.txt b/llvm/lib/DebugInfo/CodeView/CMakeLists.txt index 0515788d85e..e1bdffd30ee 100644 --- a/llvm/lib/DebugInfo/CodeView/CMakeLists.txt +++ b/llvm/lib/DebugInfo/CodeView/CMakeLists.txt @@ -34,6 +34,7 @@ add_llvm_library(LLVMDebugInfoCodeView TypeIndex.cpp TypeIndexDiscovery.cpp TypeHashing.cpp + TypeRecordHelpers.cpp TypeRecordMapping.cpp TypeStreamMerger.cpp TypeTableCollection.cpp diff --git a/llvm/lib/DebugInfo/CodeView/TypeRecordHelpers.cpp b/llvm/lib/DebugInfo/CodeView/TypeRecordHelpers.cpp new file mode 100644 index 00000000000..2a66474cf5b --- /dev/null +++ b/llvm/lib/DebugInfo/CodeView/TypeRecordHelpers.cpp @@ -0,0 +1,53 @@ +//===- TypeRecordHelpers.cpp ------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/DebugInfo/CodeView/TypeRecordHelpers.h" + +#include "llvm/ADT/SmallVector.h" +#include "llvm/DebugInfo/CodeView/TypeIndexDiscovery.h" +#include "llvm/DebugInfo/CodeView/TypeDeserializer.h" + +using namespace llvm; +using namespace llvm::codeview; + +template <typename RecordT> static ClassOptions getUdtOptions(CVType CVT) { + RecordT Record; + if (auto EC = TypeDeserializer::deserializeAs<RecordT>(CVT, Record)) { + consumeError(std::move(EC)); + return ClassOptions::None; + } + return Record.getOptions(); +} + +bool llvm::codeview::isUdtForwardRef(CVType CVT) { + ClassOptions UdtOptions = ClassOptions::None; + switch (CVT.kind()) { + case LF_STRUCTURE: + case LF_CLASS: + case LF_INTERFACE: + UdtOptions = getUdtOptions<ClassRecord>(std::move(CVT)); + break; + case LF_ENUM: + UdtOptions = getUdtOptions<EnumRecord>(std::move(CVT)); + break; + case LF_UNION: + UdtOptions = getUdtOptions<UnionRecord>(std::move(CVT)); + break; + default: + return false; + } + return (UdtOptions & ClassOptions::ForwardReference) != ClassOptions::None; +} + +TypeIndex llvm::codeview::getModifiedType(const CVType &CVT) { + assert(CVT.kind() == LF_MODIFIER); + SmallVector<TypeIndex, 1> Refs; + discoverTypeIndices(CVT, Refs); + return Refs.front(); +} diff --git a/llvm/lib/DebugInfo/PDB/CMakeLists.txt b/llvm/lib/DebugInfo/PDB/CMakeLists.txt index 8bf16c505cb..db39ba3b0ee 100644 --- a/llvm/lib/DebugInfo/PDB/CMakeLists.txt +++ b/llvm/lib/DebugInfo/PDB/CMakeLists.txt @@ -55,6 +55,7 @@ add_pdb_impl_folder(Native Native/NativeTypeBuiltin.cpp Native/NativeTypeEnum.cpp Native/NativeTypePointer.cpp + Native/NativeTypeUDT.cpp Native/NamedStreamMap.cpp Native/NativeSession.cpp Native/PDBFile.cpp diff --git a/llvm/lib/DebugInfo/PDB/Native/NativeEnumTypes.cpp b/llvm/lib/DebugInfo/PDB/Native/NativeEnumTypes.cpp index 97348a55d61..f16b776dc65 100644 --- a/llvm/lib/DebugInfo/PDB/Native/NativeEnumTypes.cpp +++ b/llvm/lib/DebugInfo/PDB/Native/NativeEnumTypes.cpp @@ -10,6 +10,7 @@ #include "llvm/DebugInfo/PDB/Native/NativeEnumTypes.h" #include "llvm/DebugInfo/CodeView/TypeDeserializer.h" +#include "llvm/DebugInfo/CodeView/TypeRecordHelpers.h" #include "llvm/DebugInfo/PDB/IPDBEnumChildren.h" #include "llvm/DebugInfo/PDB/Native/NativeSession.h" #include "llvm/DebugInfo/PDB/Native/NativeTypeEnum.h" @@ -22,21 +23,24 @@ using namespace llvm::pdb; NativeEnumTypes::NativeEnumTypes(NativeSession &PDBSession, LazyRandomTypeCollection &Types, - TypeLeafKind Kind) + std::vector<codeview::TypeLeafKind> Kinds) : Matches(), Index(0), Session(PDBSession) { Optional<TypeIndex> TI = Types.getFirst(); while (TI) { CVType CVT = Types.getType(*TI); TypeLeafKind K = CVT.kind(); - if (K == Kind) - Matches.push_back(*TI); - else if (K == TypeLeafKind::LF_MODIFIER) { - ModifierRecord MR; - if (auto EC = TypeDeserializer::deserializeAs<ModifierRecord>(CVT, MR)) { - consumeError(std::move(EC)); - } else if (!MR.ModifiedType.isSimple()) { - CVType UnmodifiedCVT = Types.getType(MR.ModifiedType); - if (UnmodifiedCVT.kind() == Kind) + if (llvm::is_contained(Kinds, K)) { + // Don't add forward refs, we'll find those later while enumerating. + if (!isUdtForwardRef(CVT)) + Matches.push_back(*TI); + } else if (K == TypeLeafKind::LF_MODIFIER) { + TypeIndex ModifiedTI = getModifiedType(CVT); + if (!ModifiedTI.isSimple()) { + CVType UnmodifiedCVT = Types.getType(ModifiedTI); + // LF_MODIFIERs point to forward refs, but don't worry about that + // here. We're pushing the TypeIndex of the LF_MODIFIER itself, + // so we'll worry about resolving forward refs later. + if (llvm::is_contained(Kinds, UnmodifiedCVT.kind())) Matches.push_back(*TI); } } @@ -44,11 +48,6 @@ NativeEnumTypes::NativeEnumTypes(NativeSession &PDBSession, } } -NativeEnumTypes::NativeEnumTypes(NativeSession &PDBSession, - const std::vector<TypeIndex> &Matches, - TypeLeafKind Kind) - : Matches(Matches), Index(0), Session(PDBSession) {} - uint32_t NativeEnumTypes::getChildCount() const { return static_cast<uint32_t>(Matches.size()); } diff --git a/llvm/lib/DebugInfo/PDB/Native/NativeExeSymbol.cpp b/llvm/lib/DebugInfo/PDB/Native/NativeExeSymbol.cpp index 97d20d4d3bb..ca173808358 100644 --- a/llvm/lib/DebugInfo/PDB/Native/NativeExeSymbol.cpp +++ b/llvm/lib/DebugInfo/PDB/Native/NativeExeSymbol.cpp @@ -45,6 +45,10 @@ NativeExeSymbol::findChildren(PDB_SymType Type) const { return Session.getSymbolCache().createTypeEnumerator(codeview::LF_ENUM); case PDB_SymType::PointerType: return Session.getSymbolCache().createTypeEnumerator(codeview::LF_POINTER); + case PDB_SymType::UDT: + return Session.getSymbolCache().createTypeEnumerator( + {codeview::LF_STRUCTURE, codeview::LF_CLASS, codeview::LF_UNION, + codeview::LF_INTERFACE}); default: break; } diff --git a/llvm/lib/DebugInfo/PDB/Native/NativeRawSymbol.cpp b/llvm/lib/DebugInfo/PDB/Native/NativeRawSymbol.cpp index 1a8c75db998..62950cb3e52 100644 --- a/llvm/lib/DebugInfo/PDB/Native/NativeRawSymbol.cpp +++ b/llvm/lib/DebugInfo/PDB/Native/NativeRawSymbol.cpp @@ -31,68 +31,68 @@ void NativeRawSymbol::dump(raw_ostream &OS, int Indent, std::unique_ptr<IPDBEnumSymbols> NativeRawSymbol::findChildren(PDB_SymType Type) const { - return nullptr; + return llvm::make_unique<NullEnumerator<PDBSymbol>>(); } std::unique_ptr<IPDBEnumSymbols> NativeRawSymbol::findChildren(PDB_SymType Type, StringRef Name, PDB_NameSearchFlags Flags) const { - return nullptr; + return llvm::make_unique<NullEnumerator<PDBSymbol>>(); } std::unique_ptr<IPDBEnumSymbols> NativeRawSymbol::findChildrenByAddr(PDB_SymType Type, StringRef Name, PDB_NameSearchFlags Flags, uint32_t Section, uint32_t Offset) const { - return nullptr; + return llvm::make_unique<NullEnumerator<PDBSymbol>>(); } std::unique_ptr<IPDBEnumSymbols> NativeRawSymbol::findChildrenByVA(PDB_SymType Type, StringRef Name, PDB_NameSearchFlags Flags, uint64_t VA) const { - return nullptr; + return llvm::make_unique<NullEnumerator<PDBSymbol>>(); } std::unique_ptr<IPDBEnumSymbols> NativeRawSymbol::findChildrenByRVA(PDB_SymType Type, StringRef Name, PDB_NameSearchFlags Flags, uint32_t RVA) const { - return nullptr; + return llvm::make_unique<NullEnumerator<PDBSymbol>>(); } std::unique_ptr<IPDBEnumSymbols> NativeRawSymbol::findInlineFramesByAddr(uint32_t Section, uint32_t Offset) const { - return nullptr; + return llvm::make_unique<NullEnumerator<PDBSymbol>>(); } std::unique_ptr<IPDBEnumSymbols> NativeRawSymbol::findInlineFramesByRVA(uint32_t RVA) const { - return nullptr; + return llvm::make_unique<NullEnumerator<PDBSymbol>>(); } std::unique_ptr<IPDBEnumSymbols> NativeRawSymbol::findInlineFramesByVA(uint64_t VA) const { - return nullptr; + return llvm::make_unique<NullEnumerator<PDBSymbol>>(); } std::unique_ptr<IPDBEnumLineNumbers> NativeRawSymbol::findInlineeLines() const { - return nullptr; + return llvm::make_unique<NullEnumerator<IPDBLineNumber>>(); } std::unique_ptr<IPDBEnumLineNumbers> NativeRawSymbol::findInlineeLinesByAddr(uint32_t Section, uint32_t Offset, uint32_t Length) const { - return nullptr; + return llvm::make_unique<NullEnumerator<IPDBLineNumber>>(); } std::unique_ptr<IPDBEnumLineNumbers> NativeRawSymbol::findInlineeLinesByRVA(uint32_t RVA, uint32_t Length) const { - return nullptr; + return llvm::make_unique<NullEnumerator<IPDBLineNumber>>(); } std::unique_ptr<IPDBEnumLineNumbers> NativeRawSymbol::findInlineeLinesByVA(uint64_t VA, uint32_t Length) const { - return nullptr; + return llvm::make_unique<NullEnumerator<IPDBLineNumber>>(); } void NativeRawSymbol::getDataBytes(SmallVector<uint8_t, 32> &bytes) const { diff --git a/llvm/lib/DebugInfo/PDB/Native/NativeTypeEnum.cpp b/llvm/lib/DebugInfo/PDB/Native/NativeTypeEnum.cpp index 0994be4af42..37176fe083b 100644 --- a/llvm/lib/DebugInfo/PDB/Native/NativeTypeEnum.cpp +++ b/llvm/lib/DebugInfo/PDB/Native/NativeTypeEnum.cpp @@ -40,8 +40,7 @@ namespace { class NativeEnumEnumEnumerators : public IPDBEnumSymbols, TypeVisitorCallbacks { public: NativeEnumEnumEnumerators(NativeSession &Session, - const NativeTypeEnum &ClassParent, - const codeview::EnumRecord &CVEnum); + const NativeTypeEnum &ClassParent); uint32_t getChildCount() const override; std::unique_ptr<PDBSymbol> getChildAtIndex(uint32_t Index) const override; @@ -56,7 +55,6 @@ private: NativeSession &Session; const NativeTypeEnum &ClassParent; - const codeview::EnumRecord &CVEnum; std::vector<EnumeratorRecord> Enumerators; Optional<TypeIndex> ContinuationIndex; uint32_t Index = 0; @@ -64,13 +62,12 @@ private: } // namespace NativeEnumEnumEnumerators::NativeEnumEnumEnumerators( - NativeSession &Session, const NativeTypeEnum &ClassParent, - const codeview::EnumRecord &CVEnum) - : Session(Session), ClassParent(ClassParent), CVEnum(CVEnum) { + NativeSession &Session, const NativeTypeEnum &ClassParent) + : Session(Session), ClassParent(ClassParent) { TpiStream &Tpi = cantFail(Session.getPDBFile().getPDBTpiStream()); LazyRandomTypeCollection &Types = Tpi.typeCollection(); - ContinuationIndex = CVEnum.FieldList; + ContinuationIndex = ClassParent.getEnumRecord().FieldList; while (ContinuationIndex) { CVType FieldList = Types.getType(*ContinuationIndex); assert(FieldList.kind() == LF_FIELDLIST); @@ -100,10 +97,10 @@ NativeEnumEnumEnumerators::getChildAtIndex(uint32_t Index) const { if (Index >= getChildCount()) return nullptr; - SymIndexId Id = - Session.getSymbolCache() - .getOrCreateFieldListMember<NativeSymbolEnumerator>( - CVEnum.FieldList, Index, ClassParent, Enumerators[Index]); + SymIndexId Id = Session.getSymbolCache() + .getOrCreateFieldListMember<NativeSymbolEnumerator>( + ClassParent.getEnumRecord().FieldList, Index, + ClassParent, Enumerators[Index]); return Session.getSymbolCache().getSymbolById(Id); } @@ -122,11 +119,10 @@ NativeTypeEnum::NativeTypeEnum(NativeSession &Session, SymIndexId Id, Record(std::move(Record)) {} NativeTypeEnum::NativeTypeEnum(NativeSession &Session, SymIndexId Id, - codeview::TypeIndex ModifierTI, - codeview::ModifierRecord Modifier, - codeview::EnumRecord EnumRecord) - : NativeRawSymbol(Session, PDB_SymType::Enum, Id), Index(ModifierTI), - Record(std::move(EnumRecord)), Modifiers(std::move(Modifier)) {} + NativeTypeEnum &UnmodifiedType, + codeview::ModifierRecord Modifier) + : NativeRawSymbol(Session, PDB_SymType::Enum, Id), + UnmodifiedType(&UnmodifiedType), Modifiers(std::move(Modifier)) {} NativeTypeEnum::~NativeTypeEnum() {} @@ -173,22 +169,20 @@ NativeTypeEnum::findChildren(PDB_SymType Type) const { const NativeTypeEnum *ClassParent = nullptr; if (!Modifiers) ClassParent = this; - else { - NativeRawSymbol &NRS = - Session.getSymbolCache().getNativeSymbolById(getUnmodifiedTypeId()); - assert(NRS.getSymTag() == PDB_SymType::Enum); - ClassParent = static_cast<NativeTypeEnum *>(&NRS); - } - return llvm::make_unique<NativeEnumEnumEnumerators>(Session, *ClassParent, - Record); + else + ClassParent = UnmodifiedType; + return llvm::make_unique<NativeEnumEnumEnumerators>(Session, *ClassParent); } PDB_SymType NativeTypeEnum::getSymTag() const { return PDB_SymType::Enum; } PDB_BuiltinType NativeTypeEnum::getBuiltinType() const { - Session.getSymbolCache().findSymbolByTypeIndex(Record.getUnderlyingType()); + if (UnmodifiedType) + return UnmodifiedType->getBuiltinType(); + + Session.getSymbolCache().findSymbolByTypeIndex(Record->getUnderlyingType()); - codeview::TypeIndex Underlying = Record.getUnderlyingType(); + codeview::TypeIndex Underlying = Record->getUnderlyingType(); // This indicates a corrupt record. if (!Underlying.isSimple() || @@ -255,67 +249,101 @@ PDB_BuiltinType NativeTypeEnum::getBuiltinType() const { } SymIndexId NativeTypeEnum::getUnmodifiedTypeId() const { - if (!Modifiers) - return 0; - - return Session.getSymbolCache().findSymbolByTypeIndex( - Modifiers->ModifiedType); + return UnmodifiedType ? UnmodifiedType->getSymIndexId() : 0; } bool NativeTypeEnum::hasConstructor() const { - return bool(Record.getOptions() & + if (UnmodifiedType) + return UnmodifiedType->hasConstructor(); + + return bool(Record->getOptions() & codeview::ClassOptions::HasConstructorOrDestructor); } bool NativeTypeEnum::hasAssignmentOperator() const { - return bool(Record.getOptions() & + if (UnmodifiedType) + return UnmodifiedType->hasAssignmentOperator(); + + return bool(Record->getOptions() & codeview::ClassOptions::HasOverloadedAssignmentOperator); } bool NativeTypeEnum::hasNestedTypes() const { - return bool(Record.getOptions() & + if (UnmodifiedType) + return UnmodifiedType->hasNestedTypes(); + + return bool(Record->getOptions() & codeview::ClassOptions::ContainsNestedClass); } bool NativeTypeEnum::isIntrinsic() const { - return bool(Record.getOptions() & codeview::ClassOptions::Intrinsic); + if (UnmodifiedType) + return UnmodifiedType->isIntrinsic(); + + return bool(Record->getOptions() & codeview::ClassOptions::Intrinsic); } bool NativeTypeEnum::hasCastOperator() const { - return bool(Record.getOptions() & + if (UnmodifiedType) + return UnmodifiedType->hasCastOperator(); + + return bool(Record->getOptions() & codeview::ClassOptions::HasConversionOperator); } uint64_t NativeTypeEnum::getLength() const { + if (UnmodifiedType) + return UnmodifiedType->getLength(); + const auto Id = Session.getSymbolCache().findSymbolByTypeIndex( - Record.getUnderlyingType()); + Record->getUnderlyingType()); const auto UnderlyingType = Session.getConcreteSymbolById<PDBSymbolTypeBuiltin>(Id); return UnderlyingType ? UnderlyingType->getLength() : 0; } -std::string NativeTypeEnum::getName() const { return Record.getName(); } +std::string NativeTypeEnum::getName() const { + if (UnmodifiedType) + return UnmodifiedType->getName(); + + return Record->getName(); +} bool NativeTypeEnum::isNested() const { - return bool(Record.getOptions() & codeview::ClassOptions::Nested); + if (UnmodifiedType) + return UnmodifiedType->isNested(); + + return bool(Record->getOptions() & codeview::ClassOptions::Nested); } bool NativeTypeEnum::hasOverloadedOperator() const { - return bool(Record.getOptions() & + if (UnmodifiedType) + return UnmodifiedType->hasOverloadedOperator(); + + return bool(Record->getOptions() & codeview::ClassOptions::HasOverloadedOperator); } bool NativeTypeEnum::isPacked() const { - return bool(Record.getOptions() & codeview::ClassOptions::Packed); + if (UnmodifiedType) + return UnmodifiedType->isPacked(); + + return bool(Record->getOptions() & codeview::ClassOptions::Packed); } bool NativeTypeEnum::isScoped() const { - return bool(Record.getOptions() & codeview::ClassOptions::Scoped); + if (UnmodifiedType) + return UnmodifiedType->isScoped(); + + return bool(Record->getOptions() & codeview::ClassOptions::Scoped); } SymIndexId NativeTypeEnum::getTypeId() const { + if (UnmodifiedType) + return UnmodifiedType->getTypeId(); + return Session.getSymbolCache().findSymbolByTypeIndex( - Record.getUnderlyingType()); + Record->getUnderlyingType()); } bool NativeTypeEnum::isRefUdt() const { return false; } @@ -346,6 +374,9 @@ bool NativeTypeEnum::isUnalignedType() const { } const NativeTypeBuiltin &NativeTypeEnum::getUnderlyingBuiltinType() const { + if (UnmodifiedType) + return UnmodifiedType->getUnderlyingBuiltinType(); + return Session.getSymbolCache().getNativeSymbolById<NativeTypeBuiltin>( getTypeId()); } diff --git a/llvm/lib/DebugInfo/PDB/Native/NativeTypeUDT.cpp b/llvm/lib/DebugInfo/PDB/Native/NativeTypeUDT.cpp new file mode 100644 index 00000000000..3abf91dcc6a --- /dev/null +++ b/llvm/lib/DebugInfo/PDB/Native/NativeTypeUDT.cpp @@ -0,0 +1,221 @@ +//===- NativeTypeUDT.cpp - info about class/struct type ---------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/DebugInfo/PDB/Native/NativeTypeUDT.h" + +#include "llvm/DebugInfo/CodeView/TypeDeserializer.h" + +#include <cassert> + +using namespace llvm; +using namespace llvm::codeview; +using namespace llvm::pdb; + +NativeTypeUDT::NativeTypeUDT(NativeSession &Session, SymIndexId Id, + codeview::TypeIndex TI, codeview::ClassRecord CR) + : NativeRawSymbol(Session, PDB_SymType::UDT, Id), Index(TI), + Class(std::move(CR)), Tag(Class.getPointer()) {} + +NativeTypeUDT::NativeTypeUDT(NativeSession &Session, SymIndexId Id, + codeview::TypeIndex TI, codeview::UnionRecord UR) + : NativeRawSymbol(Session, PDB_SymType::UDT, Id), Index(TI), + Union(std::move(UR)), Tag(Union.getPointer()) {} + +NativeTypeUDT::NativeTypeUDT(NativeSession &Session, SymIndexId Id, + NativeTypeUDT &UnmodifiedType, + codeview::ModifierRecord Modifier) + : NativeRawSymbol(Session, PDB_SymType::UDT, Id), + UnmodifiedType(&UnmodifiedType), Modifiers(std::move(Modifier)) {} + +NativeTypeUDT::~NativeTypeUDT() {} + +void NativeTypeUDT::dump(raw_ostream &OS, int Indent, + PdbSymbolIdField ShowIdFields, + PdbSymbolIdField RecurseIdFields) const { + + NativeRawSymbol::dump(OS, Indent, ShowIdFields, RecurseIdFields); + + dumpSymbolField(OS, "name", getName(), Indent); + dumpSymbolIdField(OS, "lexicalParentId", 0, Indent, Session, + PdbSymbolIdField::LexicalParent, ShowIdFields, + RecurseIdFields); + if (Modifiers.hasValue()) + dumpSymbolIdField(OS, "unmodifiedTypeId", getUnmodifiedTypeId(), Indent, + Session, PdbSymbolIdField::UnmodifiedType, ShowIdFields, + RecurseIdFields); + if (getUdtKind() != PDB_UdtType::Union) + dumpSymbolField(OS, "virtualTableShapeId", getVirtualTableShapeId(), + Indent); + dumpSymbolField(OS, "length", getLength(), Indent); + dumpSymbolField(OS, "udtKind", getUdtKind(), Indent); + dumpSymbolField(OS, "constructor", hasConstructor(), Indent); + dumpSymbolField(OS, "constType", isConstType(), Indent); + dumpSymbolField(OS, "hasAssignmentOperator", hasAssignmentOperator(), Indent); + dumpSymbolField(OS, "hasCastOperator", hasCastOperator(), Indent); + dumpSymbolField(OS, "hasNestedTypes", hasNestedTypes(), Indent); + dumpSymbolField(OS, "overloadedOperator", hasOverloadedOperator(), Indent); + dumpSymbolField(OS, "isInterfaceUdt", isInterfaceUdt(), Indent); + dumpSymbolField(OS, "intrinsic", isIntrinsic(), Indent); + dumpSymbolField(OS, "nested", isNested(), Indent); + dumpSymbolField(OS, "packed", isPacked(), Indent); + dumpSymbolField(OS, "isRefUdt", isRefUdt(), Indent); + dumpSymbolField(OS, "scoped", isScoped(), Indent); + dumpSymbolField(OS, "unalignedType", isUnalignedType(), Indent); + dumpSymbolField(OS, "isValueUdt", isValueUdt(), Indent); + dumpSymbolField(OS, "volatileType", isVolatileType(), Indent); +} + +std::string NativeTypeUDT::getName() const { + if (UnmodifiedType) + return UnmodifiedType->getName(); + + return Tag->getName(); +} + +SymIndexId NativeTypeUDT::getLexicalParentId() const { return 0; } + +SymIndexId NativeTypeUDT::getUnmodifiedTypeId() const { + if (UnmodifiedType) + return UnmodifiedType->getSymIndexId(); + + return 0; +} + +SymIndexId NativeTypeUDT::getVirtualTableShapeId() const { + if (UnmodifiedType) + return UnmodifiedType->getVirtualTableShapeId(); + + if (Class) + return Session.getSymbolCache().findSymbolByTypeIndex(Class->VTableShape); + + return 0; +} + +uint64_t NativeTypeUDT::getLength() const { + if (UnmodifiedType) + return UnmodifiedType->getLength(); + + if (Class) + return Class->getSize(); + + return Union->getSize(); +} + +PDB_UdtType NativeTypeUDT::getUdtKind() const { + if (UnmodifiedType) + return UnmodifiedType->getUdtKind(); + + switch (Tag->Kind) { + case TypeRecordKind::Class: + return PDB_UdtType::Class; + case TypeRecordKind::Union: + return PDB_UdtType::Union; + case TypeRecordKind::Struct: + return PDB_UdtType::Struct; + case TypeRecordKind::Interface: + return PDB_UdtType::Interface; + default: + llvm_unreachable("Unexected udt kind"); + } +} + +bool NativeTypeUDT::hasConstructor() const { + if (UnmodifiedType) + return UnmodifiedType->hasConstructor(); + + return (Tag->Options & ClassOptions::HasConstructorOrDestructor) != + ClassOptions::None; +} + +bool NativeTypeUDT::isConstType() const { + if (!Modifiers) + return false; + return (Modifiers->Modifiers & ModifierOptions::Const) != + ModifierOptions::None; +} + +bool NativeTypeUDT::hasAssignmentOperator() const { + if (UnmodifiedType) + return UnmodifiedType->hasAssignmentOperator(); + + return (Tag->Options & ClassOptions::HasOverloadedAssignmentOperator) != + ClassOptions::None; +} + +bool NativeTypeUDT::hasCastOperator() const { + if (UnmodifiedType) + return UnmodifiedType->hasCastOperator(); + + return (Tag->Options & ClassOptions::HasConversionOperator) != + ClassOptions::None; +} + +bool NativeTypeUDT::hasNestedTypes() const { + if (UnmodifiedType) + return UnmodifiedType->hasNestedTypes(); + + return (Tag->Options & ClassOptions::ContainsNestedClass) != + ClassOptions::None; +} + +bool NativeTypeUDT::hasOverloadedOperator() const { + if (UnmodifiedType) + return UnmodifiedType->hasOverloadedOperator(); + + return (Tag->Options & ClassOptions::HasOverloadedOperator) != + ClassOptions::None; +} + +bool NativeTypeUDT::isInterfaceUdt() const { return false; } + +bool NativeTypeUDT::isIntrinsic() const { + if (UnmodifiedType) + return UnmodifiedType->isIntrinsic(); + + return (Tag->Options & ClassOptions::Intrinsic) != ClassOptions::None; +} + +bool NativeTypeUDT::isNested() const { + if (UnmodifiedType) + return UnmodifiedType->isNested(); + + return (Tag->Options & ClassOptions::Nested) != ClassOptions::None; +} + +bool NativeTypeUDT::isPacked() const { + if (UnmodifiedType) + return UnmodifiedType->isPacked(); + + return (Tag->Options & ClassOptions::Packed) != ClassOptions::None; +} + +bool NativeTypeUDT::isRefUdt() const { return false; } + +bool NativeTypeUDT::isScoped() const { + if (UnmodifiedType) + return UnmodifiedType->isScoped(); + + return (Tag->Options & ClassOptions::Scoped) != ClassOptions::None; +} + +bool NativeTypeUDT::isValueUdt() const { return false; } + +bool NativeTypeUDT::isUnalignedType() const { + if (!Modifiers) + return false; + return (Modifiers->Modifiers & ModifierOptions::Unaligned) != + ModifierOptions::None; +} + +bool NativeTypeUDT::isVolatileType() const { + if (!Modifiers) + return false; + return (Modifiers->Modifiers & ModifierOptions::Volatile) != + ModifierOptions::None; +} diff --git a/llvm/lib/DebugInfo/PDB/Native/SymbolCache.cpp b/llvm/lib/DebugInfo/PDB/Native/SymbolCache.cpp index d714177509d..4fd7adf1632 100644 --- a/llvm/lib/DebugInfo/PDB/Native/SymbolCache.cpp +++ b/llvm/lib/DebugInfo/PDB/Native/SymbolCache.cpp @@ -1,6 +1,7 @@ #include "llvm/DebugInfo/PDB/Native/SymbolCache.h" #include "llvm/DebugInfo/CodeView/TypeDeserializer.h" +#include "llvm/DebugInfo/CodeView/TypeRecordHelpers.h" #include "llvm/DebugInfo/PDB/Native/DbiStream.h" #include "llvm/DebugInfo/PDB/Native/NativeCompilandSymbol.h" #include "llvm/DebugInfo/PDB/Native/NativeEnumTypes.h" @@ -9,6 +10,7 @@ #include "llvm/DebugInfo/PDB/Native/NativeTypeBuiltin.h" #include "llvm/DebugInfo/PDB/Native/NativeTypeEnum.h" #include "llvm/DebugInfo/PDB/Native/NativeTypePointer.h" +#include "llvm/DebugInfo/PDB/Native/NativeTypeUDT.h" #include "llvm/DebugInfo/PDB/Native/PDBFile.h" #include "llvm/DebugInfo/PDB/Native/TpiStream.h" #include "llvm/DebugInfo/PDB/PDBSymbol.h" @@ -50,10 +52,18 @@ SymbolCache::SymbolCache(NativeSession &Session, DbiStream *Dbi) if (Dbi) Compilands.resize(Dbi->modules().getModuleCount()); + + auto &Tpi = cantFail(Session.getPDBFile().getPDBTpiStream()); + Tpi.buildHashMap(); +} + +std::unique_ptr<IPDBEnumSymbols> +SymbolCache::createTypeEnumerator(TypeLeafKind Kind) { + return createTypeEnumerator(std::vector<TypeLeafKind>{Kind}); } std::unique_ptr<IPDBEnumSymbols> -SymbolCache::createTypeEnumerator(codeview::TypeLeafKind Kind) { +SymbolCache::createTypeEnumerator(std::vector<TypeLeafKind> Kinds) { auto Tpi = Session.getPDBFile().getPDBTpiStream(); if (!Tpi) { consumeError(Tpi.takeError()); @@ -61,7 +71,7 @@ SymbolCache::createTypeEnumerator(codeview::TypeLeafKind Kind) { } auto &Types = Tpi->typeCollection(); return std::unique_ptr<IPDBEnumSymbols>( - new NativeEnumTypes(Session, Types, Kind)); + new NativeEnumTypes(Session, Types, std::move(Kinds))); } SymIndexId SymbolCache::createSimpleType(TypeIndex Index, @@ -98,38 +108,24 @@ SymbolCache::createSymbolForModifiedType(codeview::TypeIndex ModifierTI, if (Record.ModifiedType.isSimple()) return createSimpleType(Record.ModifiedType, Record.Modifiers); - auto Tpi = Session.getPDBFile().getPDBTpiStream(); - if (!Tpi) { - consumeError(Tpi.takeError()); - return 0; - } - codeview::LazyRandomTypeCollection &Types = Tpi->typeCollection(); - - codeview::CVType UnmodifiedType = Types.getType(Record.ModifiedType); - - switch (UnmodifiedType.kind()) { - case LF_ENUM: { - EnumRecord ER; - if (auto EC = - TypeDeserializer::deserializeAs<EnumRecord>(UnmodifiedType, ER)) { - consumeError(std::move(EC)); - return 0; - } - return createSymbol<NativeTypeEnum>(Record.ModifiedType, std::move(Record), - std::move(ER)); - } - case LF_STRUCTURE: - case LF_UNION: - case LF_CLASS: - // FIXME: Handle these - break; + // Make sure we create and cache a record for the unmodified type. + SymIndexId UnmodifiedId = findSymbolByTypeIndex(Record.ModifiedType); + NativeRawSymbol &UnmodifiedNRS = *Cache[UnmodifiedId]; + + switch (UnmodifiedNRS.getSymTag()) { + case PDB_SymType::Enum: + return createSymbol<NativeTypeEnum>( + static_cast<NativeTypeEnum &>(UnmodifiedNRS), std::move(Record)); + case PDB_SymType::UDT: + return createSymbol<NativeTypeUDT>( + static_cast<NativeTypeUDT &>(UnmodifiedNRS), std::move(Record)); default: // No other types can be modified. (LF_POINTER, for example, records // its modifiers a different way. assert(false && "Invalid LF_MODIFIER record"); break; } - return createSymbolPlaceholder(); + return 0; } SymIndexId SymbolCache::findSymbolByTypeIndex(codeview::TypeIndex Index) { @@ -150,13 +146,37 @@ SymIndexId SymbolCache::findSymbolByTypeIndex(codeview::TypeIndex Index) { } codeview::LazyRandomTypeCollection &Types = Tpi->typeCollection(); codeview::CVType CVT = Types.getType(Index); - // TODO(amccarth): Make this handle all types. - SymIndexId Id = 0; + if (isUdtForwardRef(CVT)) { + Expected<TypeIndex> EFD = Tpi->findFullDeclForForwardRef(Index); + + if (!EFD) + consumeError(EFD.takeError()); + else if (*EFD != Index) { + assert(!isUdtForwardRef(Types.getType(*EFD))); + SymIndexId Result = findSymbolByTypeIndex(*EFD); + // Record a mapping from ForwardRef -> SymIndex of complete type so that + // we'll take the fast path next time. + TypeIndexToSymbolId[Index] = Result; + return Result; + } + } + + // At this point if we still have a forward ref udt it means the full decl was + // not in the PDB. We just have to deal with it and use the forward ref. + SymIndexId Id = 0; switch (CVT.kind()) { case codeview::LF_ENUM: Id = createSymbolForType<NativeTypeEnum, EnumRecord>(Index, std::move(CVT)); break; + case codeview::LF_CLASS: + case codeview::LF_STRUCTURE: + case codeview::LF_INTERFACE: + Id = createSymbolForType<NativeTypeUDT, ClassRecord>(Index, std::move(CVT)); + break; + case codeview::LF_UNION: + Id = createSymbolForType<NativeTypeUDT, UnionRecord>(Index, std::move(CVT)); + break; case codeview::LF_POINTER: Id = createSymbolForType<NativeTypePointer, PointerRecord>(Index, std::move(CVT)); diff --git a/llvm/lib/DebugInfo/PDB/Native/TpiStream.cpp b/llvm/lib/DebugInfo/PDB/Native/TpiStream.cpp index 311c3859acf..96221f7d6ec 100644 --- a/llvm/lib/DebugInfo/PDB/Native/TpiStream.cpp +++ b/llvm/lib/DebugInfo/PDB/Native/TpiStream.cpp @@ -11,9 +11,8 @@ #include "llvm/ADT/iterator_range.h" #include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h" -#include "llvm/DebugInfo/CodeView/TypeDeserializer.h" -#include "llvm/DebugInfo/CodeView/TypeIndexDiscovery.h" #include "llvm/DebugInfo/CodeView/TypeRecord.h" +#include "llvm/DebugInfo/CodeView/TypeRecordHelpers.h" #include "llvm/DebugInfo/MSF/MappedBlockStream.h" #include "llvm/DebugInfo/PDB/Native/Hash.h" #include "llvm/DebugInfo/PDB/Native/PDBFile.h" @@ -161,35 +160,6 @@ void TpiStream::buildHashMap() { bool TpiStream::supportsTypeLookup() const { return !HashMap.empty(); } -template <typename RecordT> static ClassOptions getUdtOptions(CVType CVT) { - RecordT Record; - if (auto EC = TypeDeserializer::deserializeAs<RecordT>(CVT, Record)) { - consumeError(std::move(EC)); - return ClassOptions::None; - } - return Record.getOptions(); -} - -static bool isUdtForwardRef(CVType CVT) { - ClassOptions UdtOptions = ClassOptions::None; - switch (CVT.kind()) { - case LF_STRUCTURE: - case LF_CLASS: - case LF_INTERFACE: - UdtOptions = getUdtOptions<ClassRecord>(std::move(CVT)); - break; - case LF_ENUM: - UdtOptions = getUdtOptions<EnumRecord>(std::move(CVT)); - break; - case LF_UNION: - UdtOptions = getUdtOptions<UnionRecord>(std::move(CVT)); - break; - default: - return false; - } - return (UdtOptions & ClassOptions::ForwardReference) != ClassOptions::None; -} - Expected<TypeIndex> TpiStream::findFullDeclForForwardRef(TypeIndex ForwardRefTI) const { CVType F = Types->getType(ForwardRefTI); diff --git a/llvm/test/DebugInfo/PDB/Native/pdb-native-udts.test b/llvm/test/DebugInfo/PDB/Native/pdb-native-udts.test new file mode 100644 index 00000000000..f9f2358370a --- /dev/null +++ b/llvm/test/DebugInfo/PDB/Native/pdb-native-udts.test @@ -0,0 +1,539 @@ +; RUN: llvm-pdbutil pretty -native -classes %p/../Inputs/every-class.pdb \ +; RUN: | FileCheck -check-prefix=PRETTY %s + +; RUN: llvm-pdbutil diadump -native -udts %p/../Inputs/every-class.pdb \ +; RUN: | FileCheck -check-prefix=DUMP %s + + +PRETTY: struct main::__l2::<unnamed-type-Anonymous> [sizeof = 1] +PRETTY: struct main::__l2::Scoped [sizeof = 1] +PRETTY: struct __vc_attributes::event_sourceAttribute [sizeof = 12] +PRETTY: struct __vc_attributes::helper_attributes::v1_alttypeAttribute [sizeof = 4] +PRETTY: struct __vc_attributes::helper_attributes::usageAttribute [sizeof = 4] +PRETTY: struct __vc_attributes::threadingAttribute [sizeof = 4] +PRETTY: struct __vc_attributes::aggregatableAttribute [sizeof = 4] +PRETTY: struct __vc_attributes::event_receiverAttribute [sizeof = 8] +PRETTY: struct __vc_attributes::moduleAttribute [sizeof = 96] +PRETTY: struct Nested [sizeof = 1] +PRETTY: struct Nested::F [sizeof = 1] +PRETTY: struct Constructor [sizeof = 1] +PRETTY: class Class [sizeof = 1] +PRETTY: union Union [sizeof = 1] +PRETTY: struct Operator [sizeof = 1] +PRETTY: struct Cast [sizeof = 1] +PRETTY: struct Nothing [sizeof = 1] +PRETTY: struct Assignment [sizeof = 1] +PRETTY: const struct Nothing +PRETTY: volatile struct Nothing +PRETTY: const volatile struct Nothing +PRETTY: unaligned struct Nothing + +; DUMP: { +; DUMP-NEXT: symIndexId: 2 +; DUMP-NEXT: symTag: UDT +; DUMP-NEXT: name: main::__l2::<unnamed-type-Anonymous> +; DUMP-NEXT: virtualTableShapeId: 3 +; DUMP-NEXT: length: 1 +; DUMP-NEXT: udtKind: struct +; DUMP-NEXT: constructor: 0 +; DUMP-NEXT: constType: 0 +; DUMP-NEXT: hasAssignmentOperator: 0 +; DUMP-NEXT: hasCastOperator: 0 +; DUMP-NEXT: hasNestedTypes: 0 +; DUMP-NEXT: overloadedOperator: 0 +; DUMP-NEXT: isInterfaceUdt: 0 +; DUMP-NEXT: intrinsic: 0 +; DUMP-NEXT: nested: 0 +; DUMP-NEXT: packed: 0 +; DUMP-NEXT: isRefUdt: 0 +; DUMP-NEXT: scoped: 1 +; DUMP-NEXT: unalignedType: 0 +; DUMP-NEXT: isValueUdt: 0 +; DUMP-NEXT: volatileType: 0 +; DUMP-NEXT: } +; DUMP-NEXT: { +; DUMP-NEXT: symIndexId: 4 +; DUMP-NEXT: symTag: UDT +; DUMP-NEXT: name: main::__l2::Scoped +; DUMP-NEXT: virtualTableShapeId: 3 +; DUMP-NEXT: length: 1 +; DUMP-NEXT: udtKind: struct +; DUMP-NEXT: constructor: 0 +; DUMP-NEXT: constType: 0 +; DUMP-NEXT: hasAssignmentOperator: 0 +; DUMP-NEXT: hasCastOperator: 0 +; DUMP-NEXT: hasNestedTypes: 0 +; DUMP-NEXT: overloadedOperator: 0 +; DUMP-NEXT: isInterfaceUdt: 0 +; DUMP-NEXT: intrinsic: 0 +; DUMP-NEXT: nested: 0 +; DUMP-NEXT: packed: 0 +; DUMP-NEXT: isRefUdt: 0 +; DUMP-NEXT: scoped: 1 +; DUMP-NEXT: unalignedType: 0 +; DUMP-NEXT: isValueUdt: 0 +; DUMP-NEXT: volatileType: 0 +; DUMP-NEXT: } +; DUMP-NEXT: { +; DUMP-NEXT: symIndexId: 5 +; DUMP-NEXT: symTag: UDT +; DUMP-NEXT: name: __vc_attributes::event_sourceAttribute +; DUMP-NEXT: virtualTableShapeId: 3 +; DUMP-NEXT: length: 12 +; DUMP-NEXT: udtKind: struct +; DUMP-NEXT: constructor: 1 +; DUMP-NEXT: constType: 0 +; DUMP-NEXT: hasAssignmentOperator: 0 +; DUMP-NEXT: hasCastOperator: 0 +; DUMP-NEXT: hasNestedTypes: 1 +; DUMP-NEXT: overloadedOperator: 0 +; DUMP-NEXT: isInterfaceUdt: 0 +; DUMP-NEXT: intrinsic: 0 +; DUMP-NEXT: nested: 0 +; DUMP-NEXT: packed: 0 +; DUMP-NEXT: isRefUdt: 0 +; DUMP-NEXT: scoped: 0 +; DUMP-NEXT: unalignedType: 0 +; DUMP-NEXT: isValueUdt: 0 +; DUMP-NEXT: volatileType: 0 +; DUMP-NEXT: } +; DUMP-NEXT: { +; DUMP-NEXT: symIndexId: 6 +; DUMP-NEXT: symTag: UDT +; DUMP-NEXT: name: __vc_attributes::helper_attributes::v1_alttypeAttribute +; DUMP-NEXT: virtualTableShapeId: 3 +; DUMP-NEXT: length: 4 +; DUMP-NEXT: udtKind: struct +; DUMP-NEXT: constructor: 1 +; DUMP-NEXT: constType: 0 +; DUMP-NEXT: hasAssignmentOperator: 0 +; DUMP-NEXT: hasCastOperator: 0 +; DUMP-NEXT: hasNestedTypes: 1 +; DUMP-NEXT: overloadedOperator: 0 +; DUMP-NEXT: isInterfaceUdt: 0 +; DUMP-NEXT: intrinsic: 0 +; DUMP-NEXT: nested: 0 +; DUMP-NEXT: packed: 0 +; DUMP-NEXT: isRefUdt: 0 +; DUMP-NEXT: scoped: 0 +; DUMP-NEXT: unalignedType: 0 +; DUMP-NEXT: isValueUdt: 0 +; DUMP-NEXT: volatileType: 0 +; DUMP-NEXT: } +; DUMP-NEXT: { +; DUMP-NEXT: symIndexId: 7 +; DUMP-NEXT: symTag: UDT +; DUMP-NEXT: name: __vc_attributes::helper_attributes::usageAttribute +; DUMP-NEXT: virtualTableShapeId: 3 +; DUMP-NEXT: length: 4 +; DUMP-NEXT: udtKind: struct +; DUMP-NEXT: constructor: 1 +; DUMP-NEXT: constType: 0 +; DUMP-NEXT: hasAssignmentOperator: 0 +; DUMP-NEXT: hasCastOperator: 0 +; DUMP-NEXT: hasNestedTypes: 1 +; DUMP-NEXT: overloadedOperator: 0 +; DUMP-NEXT: isInterfaceUdt: 0 +; DUMP-NEXT: intrinsic: 0 +; DUMP-NEXT: nested: 0 +; DUMP-NEXT: packed: 0 +; DUMP-NEXT: isRefUdt: 0 +; DUMP-NEXT: scoped: 0 +; DUMP-NEXT: unalignedType: 0 +; DUMP-NEXT: isValueUdt: 0 +; DUMP-NEXT: volatileType: 0 +; DUMP-NEXT: } +; DUMP-NEXT: { +; DUMP-NEXT: symIndexId: 8 +; DUMP-NEXT: symTag: UDT +; DUMP-NEXT: name: __vc_attributes::threadingAttribute +; DUMP-NEXT: virtualTableShapeId: 3 +; DUMP-NEXT: length: 4 +; DUMP-NEXT: udtKind: struct +; DUMP-NEXT: constructor: 1 +; DUMP-NEXT: constType: 0 +; DUMP-NEXT: hasAssignmentOperator: 0 +; DUMP-NEXT: hasCastOperator: 0 +; DUMP-NEXT: hasNestedTypes: 1 +; DUMP-NEXT: overloadedOperator: 0 +; DUMP-NEXT: isInterfaceUdt: 0 +; DUMP-NEXT: intrinsic: 0 +; DUMP-NEXT: nested: 0 +; DUMP-NEXT: packed: 0 +; DUMP-NEXT: isRefUdt: 0 +; DUMP-NEXT: scoped: 0 +; DUMP-NEXT: unalignedType: 0 +; DUMP-NEXT: isValueUdt: 0 +; DUMP-NEXT: volatileType: 0 +; DUMP-NEXT: } +; DUMP-NEXT: { +; DUMP-NEXT: symIndexId: 9 +; DUMP-NEXT: symTag: UDT +; DUMP-NEXT: name: __vc_attributes::aggregatableAttribute +; DUMP-NEXT: virtualTableShapeId: 3 +; DUMP-NEXT: length: 4 +; DUMP-NEXT: udtKind: struct +; DUMP-NEXT: constructor: 1 +; DUMP-NEXT: constType: 0 +; DUMP-NEXT: hasAssignmentOperator: 0 +; DUMP-NEXT: hasCastOperator: 0 +; DUMP-NEXT: hasNestedTypes: 1 +; DUMP-NEXT: overloadedOperator: 0 +; DUMP-NEXT: isInterfaceUdt: 0 +; DUMP-NEXT: intrinsic: 0 +; DUMP-NEXT: nested: 0 +; DUMP-NEXT: packed: 0 +; DUMP-NEXT: isRefUdt: 0 +; DUMP-NEXT: scoped: 0 +; DUMP-NEXT: unalignedType: 0 +; DUMP-NEXT: isValueUdt: 0 +; DUMP-NEXT: volatileType: 0 +; DUMP-NEXT: } +; DUMP-NEXT: { +; DUMP-NEXT: symIndexId: 10 +; DUMP-NEXT: symTag: UDT +; DUMP-NEXT: name: __vc_attributes::event_receiverAttribute +; DUMP-NEXT: virtualTableShapeId: 3 +; DUMP-NEXT: length: 8 +; DUMP-NEXT: udtKind: struct +; DUMP-NEXT: constructor: 1 +; DUMP-NEXT: constType: 0 +; DUMP-NEXT: hasAssignmentOperator: 0 +; DUMP-NEXT: hasCastOperator: 0 +; DUMP-NEXT: hasNestedTypes: 1 +; DUMP-NEXT: overloadedOperator: 0 +; DUMP-NEXT: isInterfaceUdt: 0 +; DUMP-NEXT: intrinsic: 0 +; DUMP-NEXT: nested: 0 +; DUMP-NEXT: packed: 0 +; DUMP-NEXT: isRefUdt: 0 +; DUMP-NEXT: scoped: 0 +; DUMP-NEXT: unalignedType: 0 +; DUMP-NEXT: isValueUdt: 0 +; DUMP-NEXT: volatileType: 0 +; DUMP-NEXT: } +; DUMP-NEXT: { +; DUMP-NEXT: symIndexId: 11 +; DUMP-NEXT: symTag: UDT +; DUMP-NEXT: name: __vc_attributes::moduleAttribute +; DUMP-NEXT: virtualTableShapeId: 3 +; DUMP-NEXT: length: 96 +; DUMP-NEXT: udtKind: struct +; DUMP-NEXT: constructor: 1 +; DUMP-NEXT: constType: 0 +; DUMP-NEXT: hasAssignmentOperator: 0 +; DUMP-NEXT: hasCastOperator: 0 +; DUMP-NEXT: hasNestedTypes: 1 +; DUMP-NEXT: overloadedOperator: 0 +; DUMP-NEXT: isInterfaceUdt: 0 +; DUMP-NEXT: intrinsic: 0 +; DUMP-NEXT: nested: 0 +; DUMP-NEXT: packed: 0 +; DUMP-NEXT: isRefUdt: 0 +; DUMP-NEXT: scoped: 0 +; DUMP-NEXT: unalignedType: 0 +; DUMP-NEXT: isValueUdt: 0 +; DUMP-NEXT: volatileType: 0 +; DUMP-NEXT: } +; DUMP-NEXT: { +; DUMP-NEXT: symIndexId: 12 +; DUMP-NEXT: symTag: UDT +; DUMP-NEXT: name: Nested +; DUMP-NEXT: virtualTableShapeId: 3 +; DUMP-NEXT: length: 1 +; DUMP-NEXT: udtKind: struct +; DUMP-NEXT: constructor: 0 +; DUMP-NEXT: constType: 0 +; DUMP-NEXT: hasAssignmentOperator: 0 +; DUMP-NEXT: hasCastOperator: 0 +; DUMP-NEXT: hasNestedTypes: 1 +; DUMP-NEXT: overloadedOperator: 0 +; DUMP-NEXT: isInterfaceUdt: 0 +; DUMP-NEXT: intrinsic: 0 +; DUMP-NEXT: nested: 0 +; DUMP-NEXT: packed: 0 +; DUMP-NEXT: isRefUdt: 0 +; DUMP-NEXT: scoped: 0 +; DUMP-NEXT: unalignedType: 0 +; DUMP-NEXT: isValueUdt: 0 +; DUMP-NEXT: volatileType: 0 +; DUMP-NEXT: } +; DUMP-NEXT: { +; DUMP-NEXT: symIndexId: 13 +; DUMP-NEXT: symTag: UDT +; DUMP-NEXT: name: Nested::F +; DUMP-NEXT: virtualTableShapeId: 3 +; DUMP-NEXT: length: 1 +; DUMP-NEXT: udtKind: struct +; DUMP-NEXT: constructor: 0 +; DUMP-NEXT: constType: 0 +; DUMP-NEXT: hasAssignmentOperator: 0 +; DUMP-NEXT: hasCastOperator: 0 +; DUMP-NEXT: hasNestedTypes: 0 +; DUMP-NEXT: overloadedOperator: 0 +; DUMP-NEXT: isInterfaceUdt: 0 +; DUMP-NEXT: intrinsic: 0 +; DUMP-NEXT: nested: 1 +; DUMP-NEXT: packed: 0 +; DUMP-NEXT: isRefUdt: 0 +; DUMP-NEXT: scoped: 0 +; DUMP-NEXT: unalignedType: 0 +; DUMP-NEXT: isValueUdt: 0 +; DUMP-NEXT: volatileType: 0 +; DUMP-NEXT: } +; DUMP-NEXT: { +; DUMP-NEXT: symIndexId: 14 +; DUMP-NEXT: symTag: UDT +; DUMP-NEXT: name: Constructor +; DUMP-NEXT: virtualTableShapeId: 3 +; DUMP-NEXT: length: 1 +; DUMP-NEXT: udtKind: struct +; DUMP-NEXT: constructor: 1 +; DUMP-NEXT: constType: 0 +; DUMP-NEXT: hasAssignmentOperator: 0 +; DUMP-NEXT: hasCastOperator: 0 +; DUMP-NEXT: hasNestedTypes: 0 +; DUMP-NEXT: overloadedOperator: 0 +; DUMP-NEXT: isInterfaceUdt: 0 +; DUMP-NEXT: intrinsic: 0 +; DUMP-NEXT: nested: 0 +; DUMP-NEXT: packed: 0 +; DUMP-NEXT: isRefUdt: 0 +; DUMP-NEXT: scoped: 0 +; DUMP-NEXT: unalignedType: 0 +; DUMP-NEXT: isValueUdt: 0 +; DUMP-NEXT: volatileType: 0 +; DUMP-NEXT: } +; DUMP-NEXT: { +; DUMP-NEXT: symIndexId: 15 +; DUMP-NEXT: symTag: UDT +; DUMP-NEXT: name: Class +; DUMP-NEXT: virtualTableShapeId: 3 +; DUMP-NEXT: length: 1 +; DUMP-NEXT: udtKind: class +; DUMP-NEXT: constructor: 0 +; DUMP-NEXT: constType: 0 +; DUMP-NEXT: hasAssignmentOperator: 0 +; DUMP-NEXT: hasCastOperator: 0 +; DUMP-NEXT: hasNestedTypes: 0 +; DUMP-NEXT: overloadedOperator: 0 +; DUMP-NEXT: isInterfaceUdt: 0 +; DUMP-NEXT: intrinsic: 0 +; DUMP-NEXT: nested: 0 +; DUMP-NEXT: packed: 0 +; DUMP-NEXT: isRefUdt: 0 +; DUMP-NEXT: scoped: 0 +; DUMP-NEXT: unalignedType: 0 +; DUMP-NEXT: isValueUdt: 0 +; DUMP-NEXT: volatileType: 0 +; DUMP-NEXT: } +; DUMP-NEXT: { +; DUMP-NEXT: symIndexId: 16 +; DUMP-NEXT: symTag: UDT +; DUMP-NEXT: name: Union +; DUMP-NEXT: length: 1 +; DUMP-NEXT: udtKind: union +; DUMP-NEXT: constructor: 0 +; DUMP-NEXT: constType: 0 +; DUMP-NEXT: hasAssignmentOperator: 0 +; DUMP-NEXT: hasCastOperator: 0 +; DUMP-NEXT: hasNestedTypes: 0 +; DUMP-NEXT: overloadedOperator: 0 +; DUMP-NEXT: isInterfaceUdt: 0 +; DUMP-NEXT: intrinsic: 0 +; DUMP-NEXT: nested: 0 +; DUMP-NEXT: packed: 0 +; DUMP-NEXT: isRefUdt: 0 +; DUMP-NEXT: scoped: 0 +; DUMP-NEXT: unalignedType: 0 +; DUMP-NEXT: isValueUdt: 0 +; DUMP-NEXT: volatileType: 0 +; DUMP-NEXT: } +; DUMP-NEXT: { +; DUMP-NEXT: symIndexId: 17 +; DUMP-NEXT: symTag: UDT +; DUMP-NEXT: name: Operator +; DUMP-NEXT: virtualTableShapeId: 3 +; DUMP-NEXT: length: 1 +; DUMP-NEXT: udtKind: struct +; DUMP-NEXT: constructor: 0 +; DUMP-NEXT: constType: 0 +; DUMP-NEXT: hasAssignmentOperator: 0 +; DUMP-NEXT: hasCastOperator: 0 +; DUMP-NEXT: hasNestedTypes: 0 +; DUMP-NEXT: overloadedOperator: 1 +; DUMP-NEXT: isInterfaceUdt: 0 +; DUMP-NEXT: intrinsic: 0 +; DUMP-NEXT: nested: 0 +; DUMP-NEXT: packed: 0 +; DUMP-NEXT: isRefUdt: 0 +; DUMP-NEXT: scoped: 0 +; DUMP-NEXT: unalignedType: 0 +; DUMP-NEXT: isValueUdt: 0 +; DUMP-NEXT: volatileType: 0 +; DUMP-NEXT: } +; DUMP-NEXT: { +; DUMP-NEXT: symIndexId: 18 +; DUMP-NEXT: symTag: UDT +; DUMP-NEXT: name: Cast +; DUMP-NEXT: virtualTableShapeId: 3 +; DUMP-NEXT: length: 1 +; DUMP-NEXT: udtKind: struct +; DUMP-NEXT: constructor: 0 +; DUMP-NEXT: constType: 0 +; DUMP-NEXT: hasAssignmentOperator: 0 +; DUMP-NEXT: hasCastOperator: 1 +; DUMP-NEXT: hasNestedTypes: 0 +; DUMP-NEXT: overloadedOperator: 1 +; DUMP-NEXT: isInterfaceUdt: 0 +; DUMP-NEXT: intrinsic: 0 +; DUMP-NEXT: nested: 0 +; DUMP-NEXT: packed: 0 +; DUMP-NEXT: isRefUdt: 0 +; DUMP-NEXT: scoped: 0 +; DUMP-NEXT: unalignedType: 0 +; DUMP-NEXT: isValueUdt: 0 +; DUMP-NEXT: volatileType: 0 +; DUMP-NEXT: } +; DUMP-NEXT: { +; DUMP-NEXT: symIndexId: 19 +; DUMP-NEXT: symTag: UDT +; DUMP-NEXT: name: Nothing +; DUMP-NEXT: virtualTableShapeId: 3 +; DUMP-NEXT: length: 1 +; DUMP-NEXT: udtKind: struct +; DUMP-NEXT: constructor: 0 +; DUMP-NEXT: constType: 0 +; DUMP-NEXT: hasAssignmentOperator: 0 +; DUMP-NEXT: hasCastOperator: 0 +; DUMP-NEXT: hasNestedTypes: 0 +; DUMP-NEXT: overloadedOperator: 0 +; DUMP-NEXT: isInterfaceUdt: 0 +; DUMP-NEXT: intrinsic: 0 +; DUMP-NEXT: nested: 0 +; DUMP-NEXT: packed: 0 +; DUMP-NEXT: isRefUdt: 0 +; DUMP-NEXT: scoped: 0 +; DUMP-NEXT: unalignedType: 0 +; DUMP-NEXT: isValueUdt: 0 +; DUMP-NEXT: volatileType: 0 +; DUMP-NEXT: } +; DUMP-NEXT: { +; DUMP-NEXT: symIndexId: 20 +; DUMP-NEXT: symTag: UDT +; DUMP-NEXT: name: Assignment +; DUMP-NEXT: virtualTableShapeId: 3 +; DUMP-NEXT: length: 1 +; DUMP-NEXT: udtKind: struct +; DUMP-NEXT: constructor: 0 +; DUMP-NEXT: constType: 0 +; DUMP-NEXT: hasAssignmentOperator: 1 +; DUMP-NEXT: hasCastOperator: 0 +; DUMP-NEXT: hasNestedTypes: 0 +; DUMP-NEXT: overloadedOperator: 1 +; DUMP-NEXT: isInterfaceUdt: 0 +; DUMP-NEXT: intrinsic: 0 +; DUMP-NEXT: nested: 0 +; DUMP-NEXT: packed: 0 +; DUMP-NEXT: isRefUdt: 0 +; DUMP-NEXT: scoped: 0 +; DUMP-NEXT: unalignedType: 0 +; DUMP-NEXT: isValueUdt: 0 +; DUMP-NEXT: volatileType: 0 +; DUMP-NEXT: } +; DUMP-NEXT: { +; DUMP-NEXT: symIndexId: 21 +; DUMP-NEXT: symTag: UDT +; DUMP-NEXT: name: Nothing +; DUMP-NEXT: unmodifiedTypeId: 19 +; DUMP-NEXT: virtualTableShapeId: 3 +; DUMP-NEXT: length: 1 +; DUMP-NEXT: udtKind: struct +; DUMP-NEXT: constructor: 0 +; DUMP-NEXT: constType: 1 +; DUMP-NEXT: hasAssignmentOperator: 0 +; DUMP-NEXT: hasCastOperator: 0 +; DUMP-NEXT: hasNestedTypes: 0 +; DUMP-NEXT: overloadedOperator: 0 +; DUMP-NEXT: isInterfaceUdt: 0 +; DUMP-NEXT: intrinsic: 0 +; DUMP-NEXT: nested: 0 +; DUMP-NEXT: packed: 0 +; DUMP-NEXT: isRefUdt: 0 +; DUMP-NEXT: scoped: 0 +; DUMP-NEXT: unalignedType: 0 +; DUMP-NEXT: isValueUdt: 0 +; DUMP-NEXT: volatileType: 0 +; DUMP-NEXT: } +; DUMP-NEXT: { +; DUMP-NEXT: symIndexId: 22 +; DUMP-NEXT: symTag: UDT +; DUMP-NEXT: name: Nothing +; DUMP-NEXT: unmodifiedTypeId: 19 +; DUMP-NEXT: virtualTableShapeId: 3 +; DUMP-NEXT: length: 1 +; DUMP-NEXT: udtKind: struct +; DUMP-NEXT: constructor: 0 +; DUMP-NEXT: constType: 0 +; DUMP-NEXT: hasAssignmentOperator: 0 +; DUMP-NEXT: hasCastOperator: 0 +; DUMP-NEXT: hasNestedTypes: 0 +; DUMP-NEXT: overloadedOperator: 0 +; DUMP-NEXT: isInterfaceUdt: 0 +; DUMP-NEXT: intrinsic: 0 +; DUMP-NEXT: nested: 0 +; DUMP-NEXT: packed: 0 +; DUMP-NEXT: isRefUdt: 0 +; DUMP-NEXT: scoped: 0 +; DUMP-NEXT: unalignedType: 0 +; DUMP-NEXT: isValueUdt: 0 +; DUMP-NEXT: volatileType: 1 +; DUMP-NEXT: } +; DUMP-NEXT: { +; DUMP-NEXT: symIndexId: 23 +; DUMP-NEXT: symTag: UDT +; DUMP-NEXT: name: Nothing +; DUMP-NEXT: unmodifiedTypeId: 19 +; DUMP-NEXT: virtualTableShapeId: 3 +; DUMP-NEXT: length: 1 +; DUMP-NEXT: udtKind: struct +; DUMP-NEXT: constructor: 0 +; DUMP-NEXT: constType: 1 +; DUMP-NEXT: hasAssignmentOperator: 0 +; DUMP-NEXT: hasCastOperator: 0 +; DUMP-NEXT: hasNestedTypes: 0 +; DUMP-NEXT: overloadedOperator: 0 +; DUMP-NEXT: isInterfaceUdt: 0 +; DUMP-NEXT: intrinsic: 0 +; DUMP-NEXT: nested: 0 +; DUMP-NEXT: packed: 0 +; DUMP-NEXT: isRefUdt: 0 +; DUMP-NEXT: scoped: 0 +; DUMP-NEXT: unalignedType: 0 +; DUMP-NEXT: isValueUdt: 0 +; DUMP-NEXT: volatileType: 1 +; DUMP-NEXT: } +; DUMP-NEXT: { +; DUMP-NEXT: symIndexId: 24 +; DUMP-NEXT: symTag: UDT +; DUMP-NEXT: name: Nothing +; DUMP-NEXT: unmodifiedTypeId: 19 +; DUMP-NEXT: virtualTableShapeId: 3 +; DUMP-NEXT: length: 1 +; DUMP-NEXT: udtKind: struct +; DUMP-NEXT: constructor: 0 +; DUMP-NEXT: constType: 0 +; DUMP-NEXT: hasAssignmentOperator: 0 +; DUMP-NEXT: hasCastOperator: 0 +; DUMP-NEXT: hasNestedTypes: 0 +; DUMP-NEXT: overloadedOperator: 0 +; DUMP-NEXT: isInterfaceUdt: 0 +; DUMP-NEXT: intrinsic: 0 +; DUMP-NEXT: nested: 0 +; DUMP-NEXT: packed: 0 +; DUMP-NEXT: isRefUdt: 0 +; DUMP-NEXT: scoped: 0 +; DUMP-NEXT: unalignedType: 1 +; DUMP-NEXT: isValueUdt: 0 +; DUMP-NEXT: volatileType: 0 +; DUMP-NEXT: } diff --git a/llvm/tools/llvm-pdbutil/llvm-pdbutil.cpp b/llvm/tools/llvm-pdbutil/llvm-pdbutil.cpp index ab9b4593c2b..4ce1922a006 100644 --- a/llvm/tools/llvm-pdbutil/llvm-pdbutil.cpp +++ b/llvm/tools/llvm-pdbutil/llvm-pdbutil.cpp @@ -986,6 +986,8 @@ static void dumpDia(StringRef Path) { SymTypes.push_back(PDB_SymType::Enum); if (opts::diadump::Pointers) SymTypes.push_back(PDB_SymType::PointerType); + if (opts::diadump::UDTs) + SymTypes.push_back(PDB_SymType::UDT); PdbSymbolIdField Ids = opts::diadump::NoSymIndexIds ? PdbSymbolIdField::None : PdbSymbolIdField::All; @@ -1011,6 +1013,8 @@ static void dumpDia(StringRef Path) { outs() << "\n}\n"; } } + auto Child = Session->getSymbolById(3); + Child->defaultDump(outs(), 2, PdbSymbolIdField::All, PdbSymbolIdField::None); } static void dumpPretty(StringRef Path) { |