forked from OSchip/llvm-project
[PDB] Add native reading support for UDT / class types.
This allows the native reader to find records of class/struct/ union type and dump them. This behavior is tested by using the diadump subcommand against golden output produced by actual DIA SDK on the same PDB file, and again using pretty -native to confirm that we actually dump the classes. We don't find class members or anything like that yet, for now it's just the class itself. llvm-svn: 342779
This commit is contained in:
parent
10febb0779
commit
355ffb0032
|
@ -923,6 +923,7 @@ public:
|
|||
|
||||
uint32_t Signature;
|
||||
};
|
||||
|
||||
} // end namespace codeview
|
||||
} // end namespace llvm
|
||||
|
||||
|
|
|
@ -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
|
|
@ -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 {}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
@ -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
|
|
@ -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>
|
||||
|
|
|
@ -34,6 +34,7 @@ add_llvm_library(LLVMDebugInfoCodeView
|
|||
TypeIndex.cpp
|
||||
TypeIndexDiscovery.cpp
|
||||
TypeHashing.cpp
|
||||
TypeRecordHelpers.cpp
|
||||
TypeRecordMapping.cpp
|
||||
TypeStreamMerger.cpp
|
||||
TypeTableCollection.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();
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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();
|
||||
|
||||
codeview::TypeIndex Underlying = Record.getUnderlyingType();
|
||||
Session.getSymbolCache().findSymbolByTypeIndex(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());
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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(codeview::TypeLeafKind Kind) {
|
||||
SymbolCache::createTypeEnumerator(TypeLeafKind Kind) {
|
||||
return createTypeEnumerator(std::vector<TypeLeafKind>{Kind});
|
||||
}
|
||||
|
||||
std::unique_ptr<IPDBEnumSymbols>
|
||||
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();
|
||||
// Make sure we create and cache a record for the unmodified type.
|
||||
SymIndexId UnmodifiedId = findSymbolByTypeIndex(Record.ModifiedType);
|
||||
NativeRawSymbol &UnmodifiedNRS = *Cache[UnmodifiedId];
|
||||
|
||||
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;
|
||||
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));
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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: }
|
|
@ -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) {
|
||||
|
|
Loading…
Reference in New Issue