<div dir="ltr"><div dir="ltr"><br><br><div class="gmail_quote"><div dir="ltr">On Thu, Sep 20, 2018 at 5:51 PM Zachary Turner via llvm-commits <<a href="mailto:llvm-commits@lists.llvm.org">llvm-commits@lists.llvm.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Author: zturner<br>
Date: Thu Sep 20 08:50:13 2018<br>
New Revision: 342656<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=342656&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project?rev=342656&view=rev</a><br>
Log:<br>
[PDB] Add the ability to map forward references to full decls.<br>
<br>
Some records point to an LF_CLASS, LF_UNION, LF_STRUCTURE, or LF_ENUM<br>
which is a forward reference and doesn't contain complete debug<br>
information. In these cases, we'd like to be able to quickly locate the<br>
full record. The TPI stream stores an array of pre-computed record hash<br>
values, one for each type record. If we pre-process this on startup, we<br>
can build a mapping from hash value -> {list of possible matching type<br>
indices}. Since hashes of full records are only based on the name and or<br>
unique name and not the full record contents, we can then use forward<br>
ref record to compute the hash of what *would* be the full record by<br>
just hashing the name, use this to get the list of possible matches, and<br>
iterate those looking for a match on name or unique name.<br>
<br>
llvm-pdbutil is updated to resolve forward references for the purposes<br>
of testing (plus it's just useful).<br>
<br>
Differential Revision: <a href="https://reviews.llvm.org/D52283" rel="noreferrer" target="_blank">https://reviews.llvm.org/D52283</a><br>
<br>
Added:<br>
llvm/trunk/test/DebugInfo/PDB/Inputs/every-class.cpp<br>
llvm/trunk/test/DebugInfo/PDB/Inputs/every-class.pdb (with props)<br>
llvm/trunk/test/DebugInfo/PDB/pdb-resolve-forward-refs.test<br>
Modified:<br>
llvm/trunk/include/llvm/DebugInfo/PDB/Native/RawTypes.h<br>
llvm/trunk/include/llvm/DebugInfo/PDB/Native/TpiHashing.h<br>
llvm/trunk/include/llvm/DebugInfo/PDB/Native/TpiStream.h<br>
llvm/trunk/lib/DebugInfo/PDB/Native/TpiHashing.cpp<br>
llvm/trunk/lib/DebugInfo/PDB/Native/TpiStream.cpp<br>
llvm/trunk/test/DebugInfo/PDB/every-type.test<br>
llvm/trunk/test/DebugInfo/PDB/pdbdump-headers.test<br>
llvm/trunk/tools/llvm-pdbutil/DumpOutputStyle.cpp<br>
llvm/trunk/tools/llvm-pdbutil/MinimalTypeDumper.cpp<br>
llvm/trunk/tools/llvm-pdbutil/MinimalTypeDumper.h<br>
llvm/trunk/tools/llvm-pdbutil/llvm-pdbutil.cpp<br>
llvm/trunk/tools/llvm-pdbutil/llvm-pdbutil.h<br>
<br>
Modified: llvm/trunk/include/llvm/DebugInfo/PDB/Native/RawTypes.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/PDB/Native/RawTypes.h?rev=342656&r1=342655&r2=342656&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/PDB/Native/RawTypes.h?rev=342656&r1=342655&r2=342656&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/include/llvm/DebugInfo/PDB/Native/RawTypes.h (original)<br>
+++ llvm/trunk/include/llvm/DebugInfo/PDB/Native/RawTypes.h Thu Sep 20 08:50:13 2018<br>
@@ -343,7 +343,6 @@ struct SrcHeaderBlockEntry {<br>
char Reserved[8];<br>
};<br>
<br>
-constexpr int I = sizeof(SrcHeaderBlockEntry);<br>
static_assert(sizeof(SrcHeaderBlockEntry) == 40, "Incorrect struct size!");<br>
<br>
} // namespace pdb<br>
<br>
Modified: llvm/trunk/include/llvm/DebugInfo/PDB/Native/TpiHashing.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/PDB/Native/TpiHashing.h?rev=342656&r1=342655&r2=342656&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/PDB/Native/TpiHashing.h?rev=342656&r1=342655&r2=342656&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/include/llvm/DebugInfo/PDB/Native/TpiHashing.h (original)<br>
+++ llvm/trunk/include/llvm/DebugInfo/PDB/Native/TpiHashing.h Thu Sep 20 08:50:13 2018<br>
@@ -18,6 +18,54 @@ namespace pdb {<br>
<br>
Expected<uint32_t> hashTypeRecord(const llvm::codeview::CVType &Type);<br>
<br>
+struct TagRecordHash {<br>
+ explicit TagRecordHash(codeview::ClassRecord CR, uint32_t Full,<br>
+ uint32_t Forward)<br>
+ : Class(std::move(CR)), FullRecordHash(Full), ForwardDeclHash(Forward) {<br>
+ State = 0;<br>
+ }<br>
+<br>
+ explicit TagRecordHash(codeview::EnumRecord ER, uint32_t Full,<br>
+ uint32_t Forward)<br>
+ : Enum(std::move(ER)), FullRecordHash(Full), ForwardDeclHash(Forward) {<br>
+ State = 1;<br>
+ }<br>
+<br>
+ explicit TagRecordHash(codeview::UnionRecord UR, uint32_t Full,<br>
+ uint32_t Forward)<br>
+ : Union(std::move(UR)), FullRecordHash(Full), ForwardDeclHash(Forward) {<br>
+ State = 2;<br>
+ }<br>
+<br>
+ uint32_t FullRecordHash;<br>
+ uint32_t ForwardDeclHash;<br>
+<br>
+ codeview::TagRecord &getRecord() {<br>
+ switch (State) {<br>
+ case 0:<br>
+ return Class;<br>
+ case 1:<br>
+ return Enum;<br>
+ case 2:<br>
+ return Union;<br>
+ }<br>
+ llvm_unreachable("unreachable!");<br>
+ }<br>
+<br>
+private:<br>
+ union {<br>
+ codeview::ClassRecord Class;<br>
+ codeview::EnumRecord Enum;<br>
+ codeview::UnionRecord Union;<br>
+ };<br>
+<br>
+ uint8_t State = 0;<br>
+};<br>
+<br>
+/// Given a CVType referring to a class, structure, union, or enum, compute<br>
+/// the hash of its forward decl and full decl.<br>
+Expected<TagRecordHash> hashTagRecord(const codeview::CVType &Type);<br>
+<br>
} // end namespace pdb<br>
} // end namespace llvm<br>
<br>
<br>
Modified: llvm/trunk/include/llvm/DebugInfo/PDB/Native/TpiStream.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/PDB/Native/TpiStream.h?rev=342656&r1=342655&r2=342656&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/PDB/Native/TpiStream.h?rev=342656&r1=342655&r2=342656&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/include/llvm/DebugInfo/PDB/Native/TpiStream.h (original)<br>
+++ llvm/trunk/include/llvm/DebugInfo/PDB/Native/TpiStream.h Thu Sep 20 08:50:13 2018<br>
@@ -58,10 +58,17 @@ public:<br>
<br>
codeview::LazyRandomTypeCollection &typeCollection() { return *Types; }<br>
<br>
+ Expected<codeview::TypeIndex><br>
+ findFullDeclForForwardRef(codeview::TypeIndex ForwardRefTI) const;<br>
+<br>
BinarySubstreamRef getTypeRecordsSubstream() const;<br>
<br>
Error commit();<br>
<br>
+ void buildHashMap();<br>
+<br>
+ bool supportsTypeLookup() const;<br>
+<br>
private:<br>
PDBFile &Pdb;<br>
std::unique_ptr<msf::MappedBlockStream> Stream;<br>
@@ -77,6 +84,8 @@ private:<br>
FixedStreamArray<codeview::TypeIndexOffset> TypeIndexOffsets;<br>
HashTable<support::ulittle32_t> HashAdjusters;<br>
<br>
+ std::vector<std::vector<codeview::TypeIndex>> HashMap;<br>
+<br>
const TpiStreamHeader *Header;<br>
};<br>
}<br>
<br>
Modified: llvm/trunk/lib/DebugInfo/PDB/Native/TpiHashing.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/PDB/Native/TpiHashing.cpp?rev=342656&r1=342655&r2=342656&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/PDB/Native/TpiHashing.cpp?rev=342656&r1=342655&r2=342656&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/DebugInfo/PDB/Native/TpiHashing.cpp (original)<br>
+++ llvm/trunk/lib/DebugInfo/PDB/Native/TpiHashing.cpp Thu Sep 20 08:50:13 2018<br>
@@ -50,6 +50,32 @@ static Expected<uint32_t> getHashForUdt(<br>
}<br>
<br>
template <typename T><br>
+static Expected<TagRecordHash> getTagRecordHashForUdt(const CVType &Rec) {<br>
+ T Deserialized;<br>
+ if (auto E = TypeDeserializer::deserializeAs(const_cast<CVType &>(Rec),<br>
+ Deserialized))<br>
+ return std::move(E);<br>
+<br>
+ ClassOptions Opts = Deserialized.getOptions();<br>
+<br>
+ bool ForwardRef = bool(Opts & ClassOptions::ForwardReference);<br>
+<br>
+ uint32_t ThisRecordHash = getHashForUdt(Deserialized, Rec.data());<br>
+<br>
+ // If we don't have a forward ref we can't compute the hash of it from the<br>
+ // full record because it requires hashing the entire buffer.<br>
+ if (!ForwardRef)<br>
+ return TagRecordHash{std::move(Deserialized), ThisRecordHash, 0};<br>
+<br>
+ bool Scoped = bool(Opts & ClassOptions::Scoped);<br>
+<br>
+ StringRef NameToHash =<br>
+ Scoped ? Deserialized.getUniqueName() : Deserialized.getName();<br>
+ uint32_t FullHash = hashStringV1(NameToHash);<br>
+ return TagRecordHash{std::move(Deserialized), FullHash, ThisRecordHash};<br>
+}<br>
+<br>
+template <typename T><br>
static Expected<uint32_t> getSourceLineHash(const CVType &Rec) {<br>
T Deserialized;<br>
if (auto E = TypeDeserializer::deserializeAs(const_cast<CVType &>(Rec),<br>
@@ -60,6 +86,23 @@ static Expected<uint32_t> getSourceLineH<br>
return hashStringV1(StringRef(Buf, 4));<br>
}<br>
<br>
+Expected<TagRecordHash> llvm::pdb::hashTagRecord(const codeview::CVType &Type) {<br>
+ switch (Type.kind()) {<br>
+ case LF_CLASS:<br>
+ case LF_STRUCTURE:<br>
+ case LF_INTERFACE:<br>
+ return getTagRecordHashForUdt<ClassRecord>(Type);<br>
+ case LF_UNION:<br>
+ return getTagRecordHashForUdt<UnionRecord>(Type);<br>
+ case LF_ENUM:<br>
+ return getTagRecordHashForUdt<EnumRecord>(Type);<br>
+ default:<br>
+ assert(false && "Type is not a tag record!");<br>
+ }<br>
+ return make_error<StringError>("Invalid record type",<br>
+ inconvertibleErrorCode());<br>
+}<br>
+<br>
Expected<uint32_t> llvm::pdb::hashTypeRecord(const CVType &Rec) {<br>
switch (Rec.kind()) {<br>
case LF_CLASS:<br>
<br>
Modified: llvm/trunk/lib/DebugInfo/PDB/Native/TpiStream.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/PDB/Native/TpiStream.cpp?rev=342656&r1=342655&r2=342656&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/PDB/Native/TpiStream.cpp?rev=342656&r1=342655&r2=342656&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/DebugInfo/PDB/Native/TpiStream.cpp (original)<br>
+++ llvm/trunk/lib/DebugInfo/PDB/Native/TpiStream.cpp Thu Sep 20 08:50:13 2018<br>
@@ -11,8 +11,11 @@<br>
<br>
#include "llvm/ADT/iterator_range.h"<br>
#include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"<br>
+#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"<br>
+#include "llvm/DebugInfo/CodeView/TypeIndexDiscovery.h"<br>
#include "llvm/DebugInfo/CodeView/TypeRecord.h"<br>
#include "llvm/DebugInfo/MSF/MappedBlockStream.h"<br>
+#include "llvm/DebugInfo/PDB/Native/Hash.h"<br>
#include "llvm/DebugInfo/PDB/Native/PDBFile.h"<br>
#include "llvm/DebugInfo/PDB/Native/RawConstants.h"<br>
#include "llvm/DebugInfo/PDB/Native/RawError.h"<br>
@@ -140,6 +143,93 @@ uint16_t TpiStream::getTypeHashStreamAux<br>
uint32_t TpiStream::getNumHashBuckets() const { return Header->NumHashBuckets; }<br>
uint32_t TpiStream::getHashKeySize() const { return Header->HashKeySize; }<br>
<br>
+void TpiStream::buildHashMap() {<br>
+ if (!HashMap.empty())<br>
+ return;<br>
+ if (HashValues.empty())<br>
+ return;<br>
+<br>
+ HashMap.resize(Header->NumHashBuckets);<br>
+<br>
+ TypeIndex TIB{Header->TypeIndexBegin};<br>
+ TypeIndex TIE{Header->TypeIndexEnd};<br>
+ while (TIB < TIE) {<br>
+ uint32_t HV = HashValues[TIB.toArrayIndex()];<br>
+ HashMap[HV].push_back(TIB++);<br>
+ }<br>
+}<br>
+<br>
+bool TpiStream::supportsTypeLookup() const { return !HashMap.empty(); }<br>
+<br>
+template <typename RecordT> static ClassOptions getUdtOptions(CVType CVT) {<br>
+ RecordT Record;<br>
+ if (auto EC = TypeDeserializer::deserializeAs<RecordT>(CVT, Record)) {<br>
+ consumeError(std::move(EC));<br>
+ return ClassOptions::None;<br>
+ }<br>
+ return Record.getOptions();<br>
+}<br>
+<br>
+static bool isUdtForwardRef(CVType CVT) {<br>
+ ClassOptions UdtOptions = ClassOptions::None;<br>
+ switch (CVT.kind()) {<br>
+ case LF_STRUCTURE:<br>
+ case LF_CLASS:<br>
+ case LF_INTERFACE:<br>
+ UdtOptions = getUdtOptions<ClassRecord>(std::move(CVT));<br>
+ break;<br>
+ case LF_ENUM:<br>
+ UdtOptions = getUdtOptions<EnumRecord>(std::move(CVT));<br>
+ break;<br>
+ case LF_UNION:<br>
+ UdtOptions = getUdtOptions<UnionRecord>(std::move(CVT));<br>
+ break;<br>
+ default:<br>
+ return false;<br>
+ }<br>
+ return (UdtOptions & ClassOptions::ForwardReference) != ClassOptions::None;<br>
+}<br>
+<br>
+Expected<TypeIndex><br>
+TpiStream::findFullDeclForForwardRef(TypeIndex ForwardRefTI) const {<br>
+ CVType F = Types->getType(ForwardRefTI);<br>
+ if (!isUdtForwardRef(F))<br>
+ return ForwardRefTI;<br>
+<br>
+ Expected<TagRecordHash> ForwardTRH = hashTagRecord(F);<br>
+ if (!ForwardTRH)<br>
+ return ForwardTRH.takeError();<br>
+<br>
+ TagRecordHash Copy = std::move(*ForwardTRH);<br></blockquote><div><br></div><div>lib/DebugInfo/PDB/Native/TpiStream.cpp:203:17: error: unused variable 'Copy' [-Werror,-Wunused-variable]</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
+ uint32_t BucketIdx = ForwardTRH->FullRecordHash % Header->NumHashBuckets;<br>
+<br>
+ for (TypeIndex TI : HashMap[BucketIdx]) {<br>
+ CVType CVT = Types->getType(TI);<br>
+ if (CVT.kind() != F.kind())<br>
+ continue;<br>
+<br>
+ Expected<TagRecordHash> FullTRH = hashTagRecord(CVT);<br>
+ if (!FullTRH)<br>
+ return FullTRH.takeError();<br>
+ if (ForwardTRH->FullRecordHash != FullTRH->FullRecordHash)<br>
+ continue;<br>
+ TagRecord &ForwardTR = ForwardTRH->getRecord();<br>
+ TagRecord &FullTR = FullTRH->getRecord();<br>
+<br>
+ if (!ForwardTR.hasUniqueName()) {<br>
+ if (ForwardTR.getName() == FullTR.getName())<br>
+ return TI;<br>
+ continue;<br>
+ }<br>
+<br>
+ if (!FullTR.hasUniqueName())<br>
+ continue;<br>
+ if (ForwardTR.getUniqueName() == FullTR.getUniqueName())<br>
+ return TI;<br>
+ }<br>
+ return ForwardRefTI;<br>
+}<br>
+<br>
BinarySubstreamRef TpiStream::getTypeRecordsSubstream() const {<br>
return TypeRecordsSubstream;<br>
}<br>
<br>
Added: llvm/trunk/test/DebugInfo/PDB/Inputs/every-class.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/PDB/Inputs/every-class.cpp?rev=342656&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/PDB/Inputs/every-class.cpp?rev=342656&view=auto</a><br>
==============================================================================<br>
--- llvm/trunk/test/DebugInfo/PDB/Inputs/every-class.cpp (added)<br>
+++ llvm/trunk/test/DebugInfo/PDB/Inputs/every-class.cpp Thu Sep 20 08:50:13 2018<br>
@@ -0,0 +1,61 @@<br>
+// Build with "cl.exe /Z7 /GR- /GS- /GX- every-class.cpp /link /debug:full /nodefaultlib /incremental:no /entry:main"<br>
+<br>
+#include <stdint.h><br>
+<br>
+// clang-format off<br>
+void *__purecall = 0;<br>
+<br>
+void __cdecl operator delete(void *, unsigned int) {}<br>
+void __cdecl operator delete(void *, unsigned __int64) {}<br>
+<br>
+struct Nothing {};<br>
+struct Constructor { Constructor() {} };<br>
+struct Assignment {<br>
+ Assignment &operator=(Assignment Other) { return *this; }<br>
+};<br>
+struct Cast {<br>
+ operator int() { return 42; }<br>
+};<br>
+<br>
+struct Nested {<br>
+ struct F {};<br>
+};<br>
+struct Operator {<br>
+ int operator+(int X) { return 42; }<br>
+};<br>
+<br>
+class Class {};<br>
+<br>
+union Union {};<br>
+<br>
+enum class Enum {A};<br>
+<br>
+<br>
+template<typename T> void f(T t) {}<br>
+<br>
+int main(int argc, char **argv) {<br>
+ struct Scoped {};<br>
+ <br>
+ struct { } Anonymous;<br>
+<br>
+ f(Nothing{});<br>
+ f(Constructor{});<br>
+ f(Assignment{});<br>
+ f(Cast{});<br>
+ f(Nested{});<br>
+ f(Operator{});<br>
+ f(Nested::F{});<br>
+ f(Scoped{});<br>
+ f(Class{});<br>
+ f(Union{});<br>
+ f(Anonymous);<br>
+ f(Enum::A);<br>
+ <br>
+<br>
+ f<const Nothing>(Nothing{});<br>
+ f<volatile Nothing>(Nothing{});<br>
+ f<const volatile Nothing>(Nothing{});<br>
+ f<__unaligned Nothing>(Nothing{});<br>
+<br>
+ return 0;<br>
+}<br>
<br>
Added: llvm/trunk/test/DebugInfo/PDB/Inputs/every-class.pdb<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/PDB/Inputs/every-class.pdb?rev=342656&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/PDB/Inputs/every-class.pdb?rev=342656&view=auto</a><br>
==============================================================================<br>
Binary file - no diff available.<br>
<br>
Propchange: llvm/trunk/test/DebugInfo/PDB/Inputs/every-class.pdb<br>
------------------------------------------------------------------------------<br>
svn:mime-type = application/octet-stream<br>
<br>
Modified: llvm/trunk/test/DebugInfo/PDB/every-type.test<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/PDB/every-type.test?rev=342656&r1=342655&r2=342656&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/PDB/every-type.test?rev=342656&r1=342655&r2=342656&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/test/DebugInfo/PDB/every-type.test (original)<br>
+++ llvm/trunk/test/DebugInfo/PDB/every-type.test Thu Sep 20 08:50:13 2018<br>
@@ -9,12 +9,14 @@ we claim to understand. We then test th<br>
<br>
<br>
RUN: llvm-pdbutil dump -type-index=0x101A,0x102C,0x103D,0x104D,0x1098,0x10AA,0x10AC \<br>
-RUN: -dependents %p/Inputs/every-type.pdb | FileCheck --check-prefix=TYPES %s<br>
+RUN: -dont-resolve-forward-refs -dependents %p/Inputs/every-type.pdb \<br>
+RUN: | FileCheck --check-prefix=TYPES %s<br>
<br>
RUN: llvm-pdbutil pdb2yaml -tpi-stream -ipi-stream %p/Inputs/every-type.pdb > %t.pdb.yaml<br>
RUN: llvm-pdbutil yaml2pdb -pdb=%t.yaml.pdb %t.pdb.yaml<br>
RUN: llvm-pdbutil dump -type-index=0x101A,0x102C,0x103D,0x104D,0x1098,0x10AA,0x10AC \<br>
-RUN: -dependents %t.yaml.pdb | FileCheck --check-prefix=TYPES %s<br>
+RUN: -dependents -dont-resolve-forward-refs %t.yaml.pdb \<br>
+RUN: | FileCheck --check-prefix=TYPES %s<br>
<br>
TYPES: Types (TPI Stream)<br>
TYPES-NEXT: ============================================================<br>
<br>
Added: llvm/trunk/test/DebugInfo/PDB/pdb-resolve-forward-refs.test<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/PDB/pdb-resolve-forward-refs.test?rev=342656&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/PDB/pdb-resolve-forward-refs.test?rev=342656&view=auto</a><br>
==============================================================================<br>
--- llvm/trunk/test/DebugInfo/PDB/pdb-resolve-forward-refs.test (added)<br>
+++ llvm/trunk/test/DebugInfo/PDB/pdb-resolve-forward-refs.test Thu Sep 20 08:50:13 2018<br>
@@ -0,0 +1,98 @@<br>
+; RUN: llvm-pdbutil dump -types %p/Inputs/every-class.pdb \<br>
+; RUN: | FileCheck %s<br>
+<br>
+; CHECK: Types (TPI Stream) <br>
+; CHECK: ============================================================<br>
+; CHECK: Showing 157 records<br>
+; CHECK: 0x1008 | LF_STRUCTURE [size = 124] `main::__l2::<unnamed-type-Anonymous>`<br>
+; CHECK: unique name: `.?AU<unnamed-type-Anonymous>@?1??main@@YAHHPEAPEAD@Z@`aa6523bc`<br>
+; CHECK: vtable: <no type>, base list: <no type>, field list: 0x1007<br>
+; CHECK: options: has unique name | scoped, sizeof 1<br>
+; CHECK: 0x1009 | LF_STRUCTURE [size = 88] `main::__l2::Scoped`<br>
+; CHECK: unique name: `.?AUScoped@?1??main@@YAHHPEAPEAD@Z@`aa6523bc`<br>
+; CHECK: vtable: <no type>, base list: <no type>, field list: 0x1007<br>
+; CHECK: options: has unique name | scoped, sizeof 1<br>
+; CHECK: 0x1054 | LF_STRUCTURE [size = 48] `Nested::F`<br>
+; CHECK: unique name: `.?AUF@Nested@@`<br>
+; CHECK: vtable: <no type>, base list: <no type>, field list: <no type><br>
+; CHECK: options: forward ref (-> 0x1057) | has unique name | is nested, sizeof 0<br>
+; CHECK: 0x1056 | LF_STRUCTURE [size = 44] `Nested`<br>
+; CHECK: unique name: `.?AUNested@@`<br>
+; CHECK: vtable: <no type>, base list: <no type>, field list: 0x1055<br>
+; CHECK: options: contains nested class | has unique name, sizeof 1<br>
+; CHECK: 0x1057 | LF_STRUCTURE [size = 48] `Nested::F`<br>
+; CHECK: unique name: `.?AUF@Nested@@`<br>
+; CHECK: vtable: <no type>, base list: <no type>, field list: 0x1007<br>
+; CHECK: options: has unique name | is nested, sizeof 1<br>
+; CHECK: 0x1058 | LF_STRUCTURE [size = 52] `Constructor`<br>
+; CHECK: unique name: `.?AUConstructor@@`<br>
+; CHECK: vtable: <no type>, base list: <no type>, field list: <no type><br>
+; CHECK: options: forward ref (-> 0x105C) | has unique name, sizeof 0<br>
+; CHECK: 0x105C | LF_STRUCTURE [size = 52] `Constructor`<br>
+; CHECK: unique name: `.?AUConstructor@@`<br>
+; CHECK: vtable: <no type>, base list: <no type>, field list: 0x105B<br>
+; CHECK: options: has ctor / dtor | has unique name, sizeof 1<br>
+; CHECK: 0x105D | LF_CLASS [size = 40] `Class`<br>
+; CHECK: unique name: `.?AVClass@@`<br>
+; CHECK: vtable: <no type>, base list: <no type>, field list: 0x1007<br>
+; CHECK: options: has unique name, sizeof 1<br>
+; CHECK: 0x105E | LF_UNION [size = 32] `Union`<br>
+; CHECK: unique name: `.?ATUnion@@`<br>
+; CHECK: field list: 0x1007<br>
+; CHECK: options: has unique name | sealed, sizeof 1<br>
+; CHECK: 0x105F | LF_STRUCTURE [size = 48] `Operator`<br>
+; CHECK: unique name: `.?AUOperator@@`<br>
+; CHECK: vtable: <no type>, base list: <no type>, field list: <no type><br>
+; CHECK: options: forward ref (-> 0x1064) | has unique name, sizeof 0<br>
+; CHECK: 0x1064 | LF_STRUCTURE [size = 48] `Operator`<br>
+; CHECK: unique name: `.?AUOperator@@`<br>
+; CHECK: vtable: <no type>, base list: <no type>, field list: 0x1063<br>
+; CHECK: options: has unique name | overloaded operator, sizeof 1<br>
+; CHECK: 0x1066 | LF_ENUM [size = 36] `Enum`<br>
+; CHECK: unique name: `.?AW4Enum@@`<br>
+; CHECK: field list: 0x1065, underlying type: 0x0074 (int)<br>
+; CHECK: options: has unique name<br>
+; CHECK: 0x1067 | LF_STRUCTURE [size = 40] `Cast`<br>
+; CHECK: unique name: `.?AUCast@@`<br>
+; CHECK: vtable: <no type>, base list: <no type>, field list: <no type><br>
+; CHECK: options: forward ref (-> 0x106B) | has unique name, sizeof 0<br>
+; CHECK: 0x106B | LF_STRUCTURE [size = 40] `Cast`<br>
+; CHECK: unique name: `.?AUCast@@`<br>
+; CHECK: vtable: <no type>, base list: <no type>, field list: 0x106A<br>
+; CHECK: options: conversion operator | has unique name | overloaded operator, sizeof 1<br>
+; CHECK: 0x106C | LF_STRUCTURE [size = 44] `Nothing`<br>
+; CHECK: unique name: `.?AUNothing@@`<br>
+; CHECK: vtable: <no type>, base list: <no type>, field list: 0x1007<br>
+; CHECK: options: has unique name, sizeof 1<br>
+; CHECK: 0x106D | LF_STRUCTURE [size = 52] `Assignment`<br>
+; CHECK: unique name: `.?AUAssignment@@`<br>
+; CHECK: vtable: <no type>, base list: <no type>, field list: <no type><br>
+; CHECK: options: forward ref (-> 0x1073) | has unique name, sizeof 0<br>
+; CHECK: 0x1073 | LF_STRUCTURE [size = 52] `Assignment`<br>
+; CHECK: unique name: `.?AUAssignment@@`<br>
+; CHECK: vtable: <no type>, base list: <no type>, field list: 0x1072<br>
+; CHECK: options: has unique name | overloaded operator | overloaded operator=, sizeof 1<br>
+; CHECK: 0x1074 | LF_STRUCTURE [size = 44] `Nothing`<br>
+; CHECK: unique name: `.?AUNothing@@`<br>
+; CHECK: vtable: <no type>, base list: <no type>, field list: <no type><br>
+; CHECK: options: forward ref (<- 0x106C) | has unique name, sizeof 0<br>
+; CHECK: 0x1081 | LF_UNION [size = 32] `Union`<br>
+; CHECK: unique name: `.?ATUnion@@`<br>
+; CHECK: field list: <no type><br>
+; CHECK: options: forward ref (<- 0x105E) | has unique name, sizeof 0<br>
+; CHECK: 0x1084 | LF_STRUCTURE [size = 124] `main::__l2::<unnamed-type-Anonymous>`<br>
+; CHECK: unique name: `.?AU<unnamed-type-Anonymous>@?1??main@@YAHHPEAPEAD@Z@`aa6523bc`<br>
+; CHECK: vtable: <no type>, base list: <no type>, field list: <no type><br>
+; CHECK: options: forward ref (<- 0x1008) | has unique name | scoped, sizeof 0<br>
+; CHECK: 0x108E | LF_STRUCTURE [size = 44] `Nested`<br>
+; CHECK: unique name: `.?AUNested@@`<br>
+; CHECK: vtable: <no type>, base list: <no type>, field list: <no type><br>
+; CHECK: options: forward ref (<- 0x1056) | has unique name, sizeof 0<br>
+; CHECK: 0x1095 | LF_STRUCTURE [size = 88] `main::__l2::Scoped`<br>
+; CHECK: unique name: `.?AUScoped@?1??main@@YAHHPEAPEAD@Z@`aa6523bc`<br>
+; CHECK: vtable: <no type>, base list: <no type>, field list: <no type><br>
+; CHECK: options: forward ref (<- 0x1009) | has unique name | scoped, sizeof 0<br>
+; CHECK: 0x1098 | LF_CLASS [size = 40] `Class`<br>
+; CHECK: unique name: `.?AVClass@@`<br>
+; CHECK: vtable: <no type>, base list: <no type>, field list: <no type><br>
+; CHECK: options: forward ref (<- 0x105D) | has unique name, sizeof 0<br>
<br>
Modified: llvm/trunk/test/DebugInfo/PDB/pdbdump-headers.test<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/PDB/pdbdump-headers.test?rev=342656&r1=342655&r2=342656&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/PDB/pdbdump-headers.test?rev=342656&r1=342655&r2=342656&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/test/DebugInfo/PDB/pdbdump-headers.test (original)<br>
+++ llvm/trunk/test/DebugInfo/PDB/pdbdump-headers.test Thu Sep 20 08:50:13 2018<br>
@@ -1,7 +1,9 @@<br>
-; RUN: llvm-pdbutil dump -all %p/Inputs/empty.pdb | FileCheck -check-prefix=ALL %s<br>
+; RUN: llvm-pdbutil dump -all -dont-resolve-forward-refs %p/Inputs/empty.pdb \<br>
+; RUN: | FileCheck -check-prefix=ALL %s<br>
; RUN: llvm-pdbutil dump -summary -modules -files \<br>
; RUN: %p/Inputs/big-read.pdb | FileCheck -check-prefix=BIG %s<br>
-; RUN: not llvm-pdbutil dump -summary %p/Inputs/bad-block-size.pdb 2>&1 | FileCheck -check-prefix=BAD-BLOCK-SIZE %s<br>
+; RUN: not llvm-pdbutil dump -summary %p/Inputs/bad-block-size.pdb 2>&1 \<br>
+; RUN: | FileCheck -check-prefix=BAD-BLOCK-SIZE %s<br>
<br>
ALL: Summary<br>
ALL-NEXT: ============================================================<br>
<br>
Modified: llvm/trunk/tools/llvm-pdbutil/DumpOutputStyle.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbutil/DumpOutputStyle.cpp?rev=342656&r1=342655&r2=342656&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbutil/DumpOutputStyle.cpp?rev=342656&r1=342655&r2=342656&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/tools/llvm-pdbutil/DumpOutputStyle.cpp (original)<br>
+++ llvm/trunk/tools/llvm-pdbutil/DumpOutputStyle.cpp Thu Sep 20 08:50:13 2018<br>
@@ -1241,13 +1241,13 @@ static void<br>
dumpFullTypeStream(LinePrinter &Printer, LazyRandomTypeCollection &Types,<br>
uint32_t NumTypeRecords, uint32_t NumHashBuckets,<br>
FixedStreamArray<support::ulittle32_t> HashValues,<br>
- bool Bytes, bool Extras) {<br>
+ TpiStream *Stream, bool Bytes, bool Extras) {<br>
<br>
Printer.formatLine("Showing {0:N} records", NumTypeRecords);<br>
uint32_t Width = NumDigits(TypeIndex::FirstNonSimpleIndex + NumTypeRecords);<br>
<br>
MinimalTypeDumpVisitor V(Printer, Width + 2, Bytes, Extras, Types,<br>
- NumHashBuckets, HashValues);<br>
+ NumHashBuckets, HashValues, Stream);<br>
<br>
if (auto EC = codeview::visitTypeStream(Types, V)) {<br>
Printer.formatLine("An error occurred dumping type records: {0}",<br>
@@ -1263,7 +1263,8 @@ static void dumpPartialTypeStream(LinePr<br>
NumDigits(TypeIndex::FirstNonSimpleIndex + Stream.getNumTypeRecords());<br>
<br>
MinimalTypeDumpVisitor V(Printer, Width + 2, Bytes, Extras, Types,<br>
- Stream.getNumHashBuckets(), Stream.getHashValues());<br>
+ Stream.getNumHashBuckets(), Stream.getHashValues(),<br>
+ &Stream);<br>
<br>
if (opts::dump::DumpTypeDependents) {<br>
// If we need to dump all dependents, then iterate each index and find<br>
@@ -1325,7 +1326,8 @@ Error DumpOutputStyle::dumpTypesFromObje<br>
Types.reset(Reader, 100);<br>
<br>
if (opts::dump::DumpTypes) {<br>
- dumpFullTypeStream(P, Types, 0, 0, {}, opts::dump::DumpTypeData, false);<br>
+ dumpFullTypeStream(P, Types, 0, 0, {}, nullptr, opts::dump::DumpTypeData,<br>
+ false);<br>
} else if (opts::dump::DumpTypeExtras) {<br>
auto LocalHashes = LocallyHashedType::hashTypeCollection(Types);<br>
auto GlobalHashes = GloballyHashedType::hashTypeCollection(Types);<br>
@@ -1394,11 +1396,14 @@ Error DumpOutputStyle::dumpTpiStream(uin<br>
<br>
auto &Types = (StreamIdx == StreamTPI) ? File.types() : File.ids();<br>
<br>
+ // Enable resolving forward decls.<br>
+ Stream.buildHashMap();<br>
+<br>
if (DumpTypes || !Indices.empty()) {<br>
if (Indices.empty())<br>
dumpFullTypeStream(P, Types, Stream.getNumTypeRecords(),<br>
Stream.getNumHashBuckets(), Stream.getHashValues(),<br>
- DumpBytes, DumpExtras);<br>
+ &Stream, DumpBytes, DumpExtras);<br>
else {<br>
std::vector<TypeIndex> TiList(Indices.begin(), Indices.end());<br>
dumpPartialTypeStream(P, Types, Stream, TiList, DumpBytes, DumpExtras,<br>
<br>
Modified: llvm/trunk/tools/llvm-pdbutil/MinimalTypeDumper.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbutil/MinimalTypeDumper.cpp?rev=342656&r1=342655&r2=342656&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbutil/MinimalTypeDumper.cpp?rev=342656&r1=342655&r2=342656&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/tools/llvm-pdbutil/MinimalTypeDumper.cpp (original)<br>
+++ llvm/trunk/tools/llvm-pdbutil/MinimalTypeDumper.cpp Thu Sep 20 08:50:13 2018<br>
@@ -12,6 +12,7 @@<br>
#include "FormatUtil.h"<br>
#include "LinePrinter.h"<br>
<br>
+#include "llvm-pdbutil.h"<br>
#include "llvm/DebugInfo/CodeView/CVRecord.h"<br>
#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"<br>
#include "llvm/DebugInfo/CodeView/CodeView.h"<br>
@@ -19,6 +20,7 @@<br>
#include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"<br>
#include "llvm/DebugInfo/CodeView/TypeRecord.h"<br>
#include "llvm/DebugInfo/PDB/Native/TpiHashing.h"<br>
+#include "llvm/DebugInfo/PDB/Native/TpiStream.h"<br>
#include "llvm/Support/FormatVariadic.h"<br>
#include "llvm/Support/MathExtras.h"<br>
<br>
@@ -27,15 +29,37 @@ using namespace llvm::codeview;<br>
using namespace llvm::pdb;<br>
<br>
static std::string formatClassOptions(uint32_t IndentLevel,<br>
- ClassOptions Options) {<br>
+ ClassOptions Options, TpiStream *Stream,<br>
+ TypeIndex CurrentTypeIndex) {<br>
std::vector<std::string> Opts;<br>
+<br>
+ if (Stream && Stream->supportsTypeLookup() &&<br>
+ !opts::dump::DontResolveForwardRefs &&<br>
+ ((Options & ClassOptions::ForwardReference) != ClassOptions::None)) {<br>
+ // If we're able to resolve forward references, do that.<br>
+ Expected<TypeIndex> ETI =<br>
+ Stream->findFullDeclForForwardRef(CurrentTypeIndex);<br>
+ if (!ETI) {<br>
+ consumeError(ETI.takeError());<br>
+ PUSH_FLAG(ClassOptions, ForwardReference, Options, "forward ref (???)");<br>
+ } else {<br>
+ const char *Direction = (*ETI == CurrentTypeIndex)<br>
+ ? "="<br>
+ : ((*ETI < CurrentTypeIndex) ? "<-" : "->");<br>
+ std::string Formatted =<br>
+ formatv("forward ref ({0} {1})", Direction, *ETI).str();<br>
+ PUSH_FLAG(ClassOptions, ForwardReference, Options, std::move(Formatted));<br>
+ }<br>
+ } else {<br>
+ PUSH_FLAG(ClassOptions, ForwardReference, Options, "forward ref");<br>
+ }<br>
+<br>
PUSH_FLAG(ClassOptions, HasConstructorOrDestructor, Options,<br>
"has ctor / dtor");<br>
PUSH_FLAG(ClassOptions, ContainsNestedClass, Options,<br>
"contains nested class");<br>
PUSH_FLAG(ClassOptions, HasConversionOperator, Options,<br>
"conversion operator");<br>
- PUSH_FLAG(ClassOptions, ForwardReference, Options, "forward ref");<br>
PUSH_FLAG(ClassOptions, HasUniqueName, Options, "has unique name");<br>
PUSH_FLAG(ClassOptions, Intrinsic, Options, "intrin");<br>
PUSH_FLAG(ClassOptions, Nested, Options, "is nested");<br>
@@ -194,6 +218,7 @@ static std::string formatFunctionOptions<br>
}<br>
<br>
Error MinimalTypeDumpVisitor::visitTypeBegin(CVType &Record, TypeIndex Index) {<br>
+ CurrentTypeIndex = Index;<br>
// formatLine puts the newline at the beginning, so we use formatLine here<br>
// to start a new line, and then individual visit methods use format to<br>
// append to the existing line.<br>
@@ -304,7 +329,8 @@ Error MinimalTypeDumpVisitor::visitKnown<br>
P.formatLine("vtable: {0}, base list: {1}, field list: {2}",<br>
Class.VTableShape, Class.DerivationList, Class.FieldList);<br>
P.formatLine("options: {0}, sizeof {1}",<br>
- formatClassOptions(P.getIndentLevel(), Class.Options),<br>
+ formatClassOptions(P.getIndentLevel(), Class.Options, Stream,<br>
+ CurrentTypeIndex),<br>
Class.Size);<br>
return Error::success();<br>
}<br>
@@ -316,7 +342,8 @@ Error MinimalTypeDumpVisitor::visitKnown<br>
P.formatLine("unique name: `{0}`", Union.UniqueName);<br>
P.formatLine("field list: {0}", Union.FieldList);<br>
P.formatLine("options: {0}, sizeof {1}",<br>
- formatClassOptions(P.getIndentLevel(), Union.Options),<br>
+ formatClassOptions(P.getIndentLevel(), Union.Options, Stream,<br>
+ CurrentTypeIndex),<br>
Union.Size);<br>
return Error::success();<br>
}<br>
@@ -328,7 +355,8 @@ Error MinimalTypeDumpVisitor::visitKnown<br>
P.formatLine("field list: {0}, underlying type: {1}", Enum.FieldList,<br>
Enum.UnderlyingType);<br>
P.formatLine("options: {0}",<br>
- formatClassOptions(P.getIndentLevel(), Enum.Options));<br>
+ formatClassOptions(P.getIndentLevel(), Enum.Options, Stream,<br>
+ CurrentTypeIndex));<br>
return Error::success();<br>
}<br>
<br>
<br>
Modified: llvm/trunk/tools/llvm-pdbutil/MinimalTypeDumper.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbutil/MinimalTypeDumper.h?rev=342656&r1=342655&r2=342656&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbutil/MinimalTypeDumper.h?rev=342656&r1=342655&r2=342656&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/tools/llvm-pdbutil/MinimalTypeDumper.h (original)<br>
+++ llvm/trunk/tools/llvm-pdbutil/MinimalTypeDumper.h Thu Sep 20 08:50:13 2018<br>
@@ -20,15 +20,18 @@ class LazyRandomTypeCollection;<br>
<br>
namespace pdb {<br>
class LinePrinter;<br>
+class TpiStream;<br>
<br>
class MinimalTypeDumpVisitor : public codeview::TypeVisitorCallbacks {<br>
public:<br>
MinimalTypeDumpVisitor(LinePrinter &P, uint32_t Width, bool RecordBytes,<br>
bool Hashes, codeview::LazyRandomTypeCollection &Types,<br>
uint32_t NumHashBuckets,<br>
- FixedStreamArray<support::ulittle32_t> HashValues)<br>
+ FixedStreamArray<support::ulittle32_t> HashValues,<br>
+ pdb::TpiStream *Stream)<br>
: P(P), Width(Width), RecordBytes(RecordBytes), Hashes(Hashes),<br>
- Types(Types), NumHashBuckets(NumHashBuckets), HashValues(HashValues) {}<br>
+ Types(Types), NumHashBuckets(NumHashBuckets), HashValues(HashValues),<br>
+ Stream(Stream) {}<br>
<br>
Error visitTypeBegin(codeview::CVType &Record,<br>
codeview::TypeIndex Index) override;<br>
@@ -55,7 +58,9 @@ private:<br>
bool Hashes = false;<br>
codeview::LazyRandomTypeCollection &Types;<br>
uint32_t NumHashBuckets;<br>
+ codeview::TypeIndex CurrentTypeIndex;<br>
FixedStreamArray<support::ulittle32_t> HashValues;<br>
+ pdb::TpiStream *Stream = nullptr;<br>
};<br>
} // namespace pdb<br>
} // namespace llvm<br>
<br>
Modified: llvm/trunk/tools/llvm-pdbutil/llvm-pdbutil.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbutil/llvm-pdbutil.cpp?rev=342656&r1=342655&r2=342656&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbutil/llvm-pdbutil.cpp?rev=342656&r1=342655&r2=342656&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/tools/llvm-pdbutil/llvm-pdbutil.cpp (original)<br>
+++ llvm/trunk/tools/llvm-pdbutil/llvm-pdbutil.cpp Thu Sep 20 08:50:13 2018<br>
@@ -183,6 +183,8 @@ static cl::opt<bool> Enums("enums", cl::<br>
cl::sub(DiaDumpSubcommand));<br>
static cl::opt<bool> Pointers("pointers", cl::desc("Dump enum types"),<br>
cl::sub(DiaDumpSubcommand));<br>
+static cl::opt<bool> UDTs("udts", cl::desc("Dump udt types"),<br>
+ cl::sub(DiaDumpSubcommand));<br>
static cl::opt<bool> Compilands("compilands",<br>
cl::desc("Dump compiland information"),<br>
cl::sub(DiaDumpSubcommand));<br>
@@ -465,6 +467,12 @@ cl::opt<bool> DumpTypeExtras("type-extra<br>
cl::desc("dump type hashes and index offsets"),<br>
cl::cat(TypeOptions), cl::sub(DumpSubcommand));<br>
<br>
+cl::opt<bool> DontResolveForwardRefs(<br>
+ "dont-resolve-forward-refs",<br>
+ cl::desc("When dumping type records for classes, unions, enums, and "<br>
+ "structs, don't try to resolve forward references"),<br>
+ cl::cat(TypeOptions), cl::sub(DumpSubcommand));<br>
+<br>
cl::list<uint32_t> DumpTypeIndex(<br>
"type-index", cl::ZeroOrMore, cl::CommaSeparated,<br>
cl::desc("only dump types with the specified hexadecimal type index"),<br>
<br>
Modified: llvm/trunk/tools/llvm-pdbutil/llvm-pdbutil.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbutil/llvm-pdbutil.h?rev=342656&r1=342655&r2=342656&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbutil/llvm-pdbutil.h?rev=342656&r1=342655&r2=342656&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/tools/llvm-pdbutil/llvm-pdbutil.h (original)<br>
+++ llvm/trunk/tools/llvm-pdbutil/llvm-pdbutil.h Thu Sep 20 08:50:13 2018<br>
@@ -160,6 +160,7 @@ extern llvm::cl::opt<bool> DumpIdExtras;<br>
extern llvm::cl::list<uint32_t> DumpIdIndex;<br>
extern llvm::cl::opt<uint32_t> DumpModi;<br>
extern llvm::cl::opt<bool> JustMyCode;<br>
+extern llvm::cl::opt<bool> DontResolveForwardRefs;<br>
extern llvm::cl::opt<bool> DumpSymbols;<br>
extern llvm::cl::opt<bool> DumpSymRecordBytes;<br>
extern llvm::cl::opt<bool> DumpGSIRecords;<br>
<br>
<br>
_______________________________________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@lists.llvm.org" target="_blank">llvm-commits@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits</a><br>
</blockquote></div></div></div>