uint32_t Signature;
};
+
} // end namespace codeview
} // end namespace llvm
--- /dev/null
+//===- 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
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 {}
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;
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;
#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"
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,
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;
};
--- /dev/null
+//===- 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
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>
TypeIndex.cpp
TypeIndexDiscovery.cpp
TypeHashing.cpp
+ TypeRecordHelpers.cpp
TypeRecordMapping.cpp
TypeStreamMerger.cpp
TypeTableCollection.cpp
--- /dev/null
+//===- 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();
+}
Native/NativeTypeBuiltin.cpp
Native/NativeTypeEnum.cpp
Native/NativeTypePointer.cpp
+ Native/NativeTypeUDT.cpp
Native/NamedStreamMap.cpp
Native/NativeSession.cpp
Native/PDBFile.cpp
#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"
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);
}
}
}
}
-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());
}
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;
}
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 {
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;
NativeSession &Session;
const NativeTypeEnum &ClassParent;
- const codeview::EnumRecord &CVEnum;
std::vector<EnumeratorRecord> Enumerators;
Optional<TypeIndex> ContinuationIndex;
uint32_t Index = 0;
} // 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);
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);
}
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() {}
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() ||
}
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; }
}
const NativeTypeBuiltin &NativeTypeEnum::getUnderlyingBuiltinType() const {
+ if (UnmodifiedType)
+ return UnmodifiedType->getUnderlyingBuiltinType();
+
return Session.getSymbolCache().getNativeSymbolById<NativeTypeBuiltin>(
getTypeId());
}
--- /dev/null
+//===- 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;
+}
#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"
#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"
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());
}
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,
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) {
}
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));
#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"
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);
--- /dev/null
+; 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: }
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;
outs() << "\n}\n";
}
}
+ auto Child = Session->getSymbolById(3);
+ Child->defaultDump(outs(), 2, PdbSymbolIdField::All, PdbSymbolIdField::None);
}
static void dumpPretty(StringRef Path) {