llvm.org GIT mirror llvm / efac373
[PDB] Better native API support for pointers. We didn't properly detect when a pointer was a member pointer, and when that was the case we were not properly returning class parent info. This caused member pointers to render incorrectly in pretty mode. However, we didn't even have pretty tests for pointers in native mode, so those are also added now to ensure this. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@343393 91177308-0d34-0410-b5e6-96231b3b80d8 Zachary Turner 11 months ago
8 changed file(s) with 220 addition(s) and 64 deletion(s). Raw diff Collapse all Expand all
3232 void dump(raw_ostream &OS, int Indent, PdbSymbolIdField ShowIdFields,
3333 PdbSymbolIdField RecurseIdFields) const override;
3434
35 SymIndexId getClassParentId() const override;
3536 bool isConstType() const override;
3637 uint64_t getLength() const override;
3738 bool isReference() const override;
4344 bool isVolatileType() const override;
4445 bool isUnalignedType() const override;
4546
47 bool isSingleInheritance() const override;
48 bool isMultipleInheritance() const override;
49 bool isVirtualInheritance() const override;
50
4651 protected:
52 bool isMemberPointer() const;
4753 codeview::TypeIndex TI;
4854 Optional Record;
4955 };
2424 void dumpRight(PDBSymDumper &Dumper) const override;
2525
2626 FORWARD_SYMBOL_METHOD(isConstType)
27 FORWARD_SYMBOL_ID_METHOD(getClassParent)
2728 FORWARD_SYMBOL_METHOD(getLength)
2829 FORWARD_SYMBOL_ID_METHOD(getLexicalParent)
2930 FORWARD_SYMBOL_METHOD(isReference)
3636 PdbSymbolIdField RecurseIdFields) const {
3737 NativeRawSymbol::dump(OS, Indent, ShowIdFields, RecurseIdFields);
3838
39 if (isMemberPointer()) {
40 dumpSymbolIdField(OS, "classParentId", getClassParentId(), Indent, Session,
41 PdbSymbolIdField::ClassParent, ShowIdFields,
42 RecurseIdFields);
43 }
3944 dumpSymbolIdField(OS, "lexicalParentId", 0, Indent, Session,
4045 PdbSymbolIdField::LexicalParent, ShowIdFields,
4146 RecurseIdFields);
4954 dumpSymbolField(OS, "RValueReference", isRValueReference(), Indent);
5055 dumpSymbolField(OS, "reference", isReference(), Indent);
5156 dumpSymbolField(OS, "restrictedType", isRestrictedType(), Indent);
57 if (isMemberPointer()) {
58 if (isSingleInheritance())
59 dumpSymbolField(OS, "isSingleInheritance", 1, Indent);
60 else if (isMultipleInheritance())
61 dumpSymbolField(OS, "isMultipleInheritance", 1, Indent);
62 else if (isVirtualInheritance())
63 dumpSymbolField(OS, "isVirtualInheritance", 1, Indent);
64 }
5265 dumpSymbolField(OS, "unalignedType", isUnalignedType(), Indent);
5366 dumpSymbolField(OS, "volatileType", isVolatileType(), Indent);
67 }
68
69 SymIndexId NativeTypePointer::getClassParentId() const {
70 if (!isMemberPointer())
71 return 0;
72
73 assert(Record);
74 const MemberPointerInfo &MPI = Record->getMemberInfo();
75 return Session.getSymbolCache().findSymbolByTypeIndex(MPI.ContainingType);
5476 }
5577
5678 uint64_t NativeTypePointer::getLength() const {
132154 return (Record->getOptions() & PointerOptions::Unaligned) !=
133155 PointerOptions::None;
134156 }
157
158 static inline bool isInheritanceKind(const MemberPointerInfo &MPI,
159 PointerToMemberRepresentation P1,
160 PointerToMemberRepresentation P2) {
161 return (MPI.getRepresentation() == P1 || MPI.getRepresentation() == P2);
162 }
163
164 bool NativeTypePointer::isSingleInheritance() const {
165 if (!isMemberPointer())
166 return false;
167 return isInheritanceKind(
168 Record->getMemberInfo(),
169 PointerToMemberRepresentation::SingleInheritanceData,
170 PointerToMemberRepresentation::SingleInheritanceFunction);
171 }
172
173 bool NativeTypePointer::isMultipleInheritance() const {
174 if (!isMemberPointer())
175 return false;
176 return isInheritanceKind(
177 Record->getMemberInfo(),
178 PointerToMemberRepresentation::MultipleInheritanceData,
179 PointerToMemberRepresentation::MultipleInheritanceFunction);
180 }
181
182 bool NativeTypePointer::isVirtualInheritance() const {
183 if (!isMemberPointer())
184 return false;
185 return isInheritanceKind(
186 Record->getMemberInfo(),
187 PointerToMemberRepresentation::VirtualInheritanceData,
188 PointerToMemberRepresentation::VirtualInheritanceFunction);
189 }
190
191 bool NativeTypePointer::isMemberPointer() const {
192 return isPointerToDataMember() || isPointerToMemberFunction();
193 }
11 ; being checked against is golden output generated by llvm-pdbutil without
22 ; the -native flag. Then we check that we generate the same output.
33
4 ; RUN: llvm-pdbutil pretty -native -pointers \
5 ; RUN: %p/../Inputs/every-pointer.pdb | FileCheck %s --check-prefix=PRETTY
46 ; RUN: llvm-pdbutil diadump -no-ids -native -pointers \
57 ; RUN: %p/../Inputs/every-pointer.pdb | FileCheck %s
68
9 ; PRETTY: Pointers: (29 items)
10 ; PRETTY-NEXT: char**
11 ; PRETTY-NEXT: struct Foo*
12 ; PRETTY-NEXT: int&
13 ; PRETTY-NEXT: const int*
14 ; PRETTY-NEXT: volatile int*
15 ; PRETTY-NEXT: const volatile int*
16 ; PRETTY-NEXT: int*
17 ; PRETTY-NEXT: int*
18 ; PRETTY-NEXT: struct __vc_attributes::event_sourceAttribute*
19 ; PRETTY-NEXT: struct __vc_attributes::helper_attributes::v1_alttypeAttribute*
20 ; PRETTY-NEXT: struct __vc_attributes::helper_attributes::usageAttribute*
21 ; PRETTY-NEXT: struct __vc_attributes::threadingAttribute*
22 ; PRETTY-NEXT: struct __vc_attributes::aggregatableAttribute*
23 ; PRETTY-NEXT: struct __vc_attributes::event_receiverAttribute*
24 ; PRETTY-NEXT: struct __vc_attributes::moduleAttribute*
25 ; PRETTY-NEXT: const char*
26 ; PRETTY-NEXT: int&&
27 ; PRETTY-NEXT: struct Foo*
28 ; PRETTY-NEXT: void (__cdecl Foo::*)()
29 ; PRETTY-NEXT: int Foo::*
30 ; PRETTY-NEXT: int (__cdecl Foo::*)()
31 ; PRETTY-NEXT: void (__cdecl *)()
32 ; PRETTY-NEXT: unaligned struct Foo*
33 ; PRETTY-NEXT: struct Foo*
34 ; PRETTY-NEXT: const struct Foo*
35 ; PRETTY-NEXT: volatile struct Foo*
36 ; PRETTY-NEXT: const volatile struct Foo*
37 ; PRETTY-NEXT: struct Foo&&
38 ; PRETTY-NEXT: struct Foo
39
740 ; CHECK: {
841 ; CHECK-NEXT: symTag: PointerType
942 ; CHECK-NEXT: length: 8
226259 ; CHECK-NEXT: constType: 0
227260 ; CHECK-NEXT: isPointerToDataMember: 0
228261 ; CHECK-NEXT: isPointerToMemberFunction: 1
229 ; FIXME: isSingleInheritance: 1 # DIA has this property for member pointers
230 ; CHECK-NEXT: RValueReference: 0
231 ; CHECK-NEXT: reference: 0
232 ; CHECK-NEXT: restrictedType: 0
262 ; CHECK-NEXT: RValueReference: 0
263 ; CHECK-NEXT: reference: 0
264 ; CHECK-NEXT: restrictedType: 0
265 ; CHECK-NEXT: isSingleInheritance: 1
233266 ; CHECK-NEXT: unalignedType: 0
234267 ; CHECK-NEXT: volatileType: 0
235268 ; CHECK-NEXT: }
242275 ; CHECK-NEXT: RValueReference: 0
243276 ; CHECK-NEXT: reference: 0
244277 ; CHECK-NEXT: restrictedType: 0
245 ; FIXME: isSingleInheritance: 1 # DIA has this property for member pointers
278 ; CHECK-NEXT: isSingleInheritance: 1
246279 ; CHECK-NEXT: unalignedType: 0
247280 ; CHECK-NEXT: volatileType: 0
248281 ; CHECK-NEXT: }
255288 ; CHECK-NEXT: RValueReference: 0
256289 ; CHECK-NEXT: reference: 0
257290 ; CHECK-NEXT: restrictedType: 0
258 ; FIXME: isSingleInheritance: 1 # DIA has this property for member pointers
291 ; CHECK-NEXT: isSingleInheritance: 1
259292 ; CHECK-NEXT: unalignedType: 0
260293 ; CHECK-NEXT: volatileType: 0
261294 ; CHECK-NEXT: }
2121 #include "llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h"
2222 #include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h"
2323 #include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h"
24 #include "llvm/DebugInfo/PDB/PDBSymbolTypePointer.h"
2425 #include "llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h"
2526 #include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h"
2627 #include "llvm/DebugInfo/PDB/UDTLayout.h"
135136
136137 TypeDumper::TypeDumper(LinePrinter &P) : PDBSymDumper(true), Printer(P) {}
137138
139 template
140 static bool isTypeExcluded(LinePrinter &Printer, const T &Symbol) {
141 return false;
142 }
143
144 static bool isTypeExcluded(LinePrinter &Printer,
145 const PDBSymbolTypeEnum &Enum) {
146 if (Printer.IsTypeExcluded(Enum.getName(), Enum.getLength()))
147 return true;
148 // Dump member enums when dumping their class definition.
149 if (nullptr != Enum.getClassParent())
150 return true;
151 return false;
152 }
153
154 static bool isTypeExcluded(LinePrinter &Printer,
155 const PDBSymbolTypeTypedef &Typedef) {
156 return Printer.IsTypeExcluded(Typedef.getName(), Typedef.getLength());
157 }
158
159 template
160 static void dumpSymbolCategory(LinePrinter &Printer, const PDBSymbolExe &Exe,
161 TypeDumper &TD, StringRef Label) {
162 if (auto Children = Exe.findAllChildren()) {
163 Printer.NewLine();
164 WithColor(Printer, PDB_ColorItem::Identifier).get() << Label;
165 Printer << ": (" << Children->getChildCount() << " items)";
166 Printer.Indent();
167 while (auto Child = Children->getNext()) {
168 if (isTypeExcluded(Printer, *Child))
169 continue;
170
171 Printer.NewLine();
172 Child->dump(TD);
173 }
174 Printer.Unindent();
175 }
176 }
177
178 static void printClassDecl(LinePrinter &Printer,
179 const PDBSymbolTypeUDT &Class) {
180 if (Class.getUnmodifiedTypeId() != 0) {
181 if (Class.isConstType())
182 WithColor(Printer, PDB_ColorItem::Keyword).get() << "const ";
183 if (Class.isVolatileType())
184 WithColor(Printer, PDB_ColorItem::Keyword).get() << "volatile ";
185 if (Class.isUnalignedType())
186 WithColor(Printer, PDB_ColorItem::Keyword).get() << "unaligned ";
187 }
188 WithColor(Printer, PDB_ColorItem::Keyword).get() << Class.getUdtKind() << " ";
189 WithColor(Printer, PDB_ColorItem::Type).get() << Class.getName();
190 }
191
138192 void TypeDumper::start(const PDBSymbolExe &Exe) {
139 if (opts::pretty::Enums) {
140 if (auto Enums = Exe.findAllChildren()) {
141 Printer.NewLine();
142 WithColor(Printer, PDB_ColorItem::Identifier).get() << "Enums";
143 Printer << ": (" << Enums->getChildCount() << " items)";
144 Printer.Indent();
145 while (auto Enum = Enums->getNext())
146 Enum->dump(*this);
147 Printer.Unindent();
148 }
149 }
150
151 if (opts::pretty::Funcsigs) {
152 if (auto Funcsigs = Exe.findAllChildren()) {
153 Printer.NewLine();
154 WithColor(Printer, PDB_ColorItem::Identifier).get()
155 << "Function Signatures";
156 Printer << ": (" << Funcsigs->getChildCount() << " items)";
157 Printer.Indent();
158 while (auto FS = Funcsigs->getNext())
159 FS->dump(*this);
160 Printer.Unindent();
161 }
162 }
163
164 if (opts::pretty::Typedefs) {
165 if (auto Typedefs = Exe.findAllChildren()) {
166 Printer.NewLine();
167 WithColor(Printer, PDB_ColorItem::Identifier).get() << "Typedefs";
168 Printer << ": (" << Typedefs->getChildCount() << " items)";
169 Printer.Indent();
170 while (auto Typedef = Typedefs->getNext())
171 Typedef->dump(*this);
172 Printer.Unindent();
173 }
174 }
193 if (opts::pretty::Enums)
194 dumpSymbolCategory(Printer, Exe, *this, "Enums");
195
196 if (opts::pretty::Funcsigs)
197 dumpSymbolCategory(Printer, Exe, *this,
198 "Function Signatures");
199
200 if (opts::pretty::Typedefs)
201 dumpSymbolCategory(Printer, Exe, *this, "Typedefs");
202
203 if (opts::pretty::Pointers)
204 dumpSymbolCategory(Printer, Exe, *this, "Pointers");
175205
176206 if (opts::pretty::Classes) {
177207 if (auto Classes = Exe.findAllChildren()) {
213243 if (Printer.IsTypeExcluded(Class->getName(), Class->getLength()))
214244 continue;
215245
246 // No point duplicating a full class layout. Just print the modified
247 // declaration and continue.
216248 if (Class->getUnmodifiedTypeId() != 0) {
217249 Printer.NewLine();
218 if (Class->isConstType())
219 WithColor(Printer, PDB_ColorItem::Keyword).get() << "const ";
220 if (Class->isVolatileType())
221 WithColor(Printer, PDB_ColorItem::Keyword).get() << "volatile ";
222 if (Class->isUnalignedType())
223 WithColor(Printer, PDB_ColorItem::Keyword).get() << "unaligned ";
224 WithColor(Printer, PDB_ColorItem::Keyword).get()
225 << Class->getUdtKind() << " ";
226 WithColor(Printer, PDB_ColorItem::Type).get() << Class->getName();
250 printClassDecl(Printer, *Class);
227251 continue;
228252 }
229253
243267 void TypeDumper::dump(const PDBSymbolTypeEnum &Symbol) {
244268 assert(opts::pretty::Enums);
245269
246 if (Printer.IsTypeExcluded(Symbol.getName(), Symbol.getLength()))
247 return;
248 // Dump member enums when dumping their class definition.
249 if (nullptr != Symbol.getClassParent())
250 return;
251
252 Printer.NewLine();
253270 EnumDumper Dumper(Printer);
254271 Dumper.start(Symbol);
255272 }
256273
274 void TypeDumper::dump(const PDBSymbolTypeBuiltin &Symbol) {
275 BuiltinDumper BD(Printer);
276 BD.start(Symbol);
277 }
278
257279 void TypeDumper::dump(const PDBSymbolTypeTypedef &Symbol) {
258280 assert(opts::pretty::Typedefs);
259281
260 if (Printer.IsTypeExcluded(Symbol.getName(), Symbol.getLength()))
261 return;
262
263 Printer.NewLine();
264282 TypedefDumper Dumper(Printer);
265283 Dumper.start(Symbol);
266284 }
267285
268286 void TypeDumper::dump(const PDBSymbolTypeFunctionSig &Symbol) {
269 Printer.NewLine();
270287 FunctionDumper Dumper(Printer);
271288 Dumper.start(Symbol, nullptr, FunctionDumper::PointerType::None);
289 }
290
291 void TypeDumper::dump(const PDBSymbolTypePointer &Symbol) {
292 std::unique_ptr P = Symbol.getPointeeType();
293
294 if (auto *FS = dyn_cast(P.get())) {
295 FunctionDumper Dumper(Printer);
296 FunctionDumper::PointerType PT =
297 Symbol.isReference() ? FunctionDumper::PointerType::Reference
298 : FunctionDumper::PointerType::Pointer;
299 Dumper.start(*FS, nullptr, PT);
300 return;
301 }
302
303 if (auto *UDT = dyn_cast(P.get())) {
304 printClassDecl(Printer, *UDT);
305 } else {
306 P->dump(*this);
307 }
308
309 if (auto Parent = Symbol.getClassParent()) {
310 auto UDT = llvm::unique_dyn_cast(std::move(Parent));
311 if (UDT)
312 Printer << " " << UDT->getName() << "::";
313 }
314
315 if (Symbol.isReference())
316 Printer << "&";
317 else if (Symbol.isRValueReference())
318 Printer << "&&";
319 else
320 Printer << "*";
272321 }
273322
274323 void TypeDumper::dumpClassLayout(const ClassLayout &Class) {
2525 void dump(const PDBSymbolTypeEnum &Symbol) override;
2626 void dump(const PDBSymbolTypeTypedef &Symbol) override;
2727 void dump(const PDBSymbolTypeFunctionSig &Symbol) override;
28 void dump(const PDBSymbolTypeBuiltin &Symbol) override;
29 void dump(const PDBSymbolTypePointer &Symbol) override;
2830
2931 void dumpClassLayout(const ClassLayout &Class);
3032
242242 cl::cat(TypeCategory), cl::sub(PrettySubcommand));
243243 cl::opt Funcsigs("funcsigs", cl::desc("Display function signatures"),
244244 cl::cat(TypeCategory), cl::sub(PrettySubcommand));
245 cl::opt Pointers("pointers", cl::desc("Display pointer types"),
246 cl::cat(TypeCategory), cl::sub(PrettySubcommand));
247
245248 cl::opt SymbolOrder(
246249 "symbol-order", cl::desc("symbol sort order"),
247250 cl::init(SymbolSortMode::None),
11781181 }
11791182
11801183 if (opts::pretty::Classes || opts::pretty::Enums || opts::pretty::Typedefs ||
1181 opts::pretty::Funcsigs) {
1184 opts::pretty::Funcsigs || opts::pretty::Pointers) {
11821185 Printer.NewLine();
11831186 WithColor(Printer, PDB_ColorItem::SectionHeader).get() << "---TYPES---";
11841187 Printer.Indent();
15151518 opts::pretty::Classes = true;
15161519 opts::pretty::Typedefs = true;
15171520 opts::pretty::Enums = true;
1521 opts::pretty::Pointers = true;
1522 opts::pretty::Funcsigs = true;
15181523 }
15191524
15201525 // When adding filters for excluded compilands and types, we need to
8383 extern llvm::cl::opt Enums;
8484 extern llvm::cl::opt Funcsigs;
8585 extern llvm::cl::opt Typedefs;
86 extern llvm::cl::opt Pointers;
8687 extern llvm::cl::opt All;
8788 extern llvm::cl::opt ExcludeCompilerGenerated;
8889