[lit] Remove LitTestCase
[llvm-complete.git] / tools / llvm-pdbutil / MinimalTypeDumper.cpp
bloba6622480c9ff2116d165729a3fb97f672d1d42c2
1 //===- MinimalTypeDumper.cpp ---------------------------------- *- C++ --*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
9 #include "MinimalTypeDumper.h"
11 #include "FormatUtil.h"
12 #include "LinePrinter.h"
14 #include "llvm-pdbutil.h"
15 #include "llvm/DebugInfo/CodeView/CVRecord.h"
16 #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
17 #include "llvm/DebugInfo/CodeView/CodeView.h"
18 #include "llvm/DebugInfo/CodeView/Formatters.h"
19 #include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"
20 #include "llvm/DebugInfo/CodeView/TypeRecord.h"
21 #include "llvm/DebugInfo/PDB/Native/TpiHashing.h"
22 #include "llvm/DebugInfo/PDB/Native/TpiStream.h"
23 #include "llvm/Support/FormatVariadic.h"
24 #include "llvm/Support/MathExtras.h"
26 using namespace llvm;
27 using namespace llvm::codeview;
28 using namespace llvm::pdb;
30 static std::string formatClassOptions(uint32_t IndentLevel,
31 ClassOptions Options, TpiStream *Stream,
32 TypeIndex CurrentTypeIndex) {
33 std::vector<std::string> Opts;
35 if (Stream && Stream->supportsTypeLookup() &&
36 !opts::dump::DontResolveForwardRefs &&
37 ((Options & ClassOptions::ForwardReference) != ClassOptions::None)) {
38 // If we're able to resolve forward references, do that.
39 Expected<TypeIndex> ETI =
40 Stream->findFullDeclForForwardRef(CurrentTypeIndex);
41 if (!ETI) {
42 consumeError(ETI.takeError());
43 PUSH_FLAG(ClassOptions, ForwardReference, Options, "forward ref (??\?)");
44 } else {
45 const char *Direction = (*ETI == CurrentTypeIndex)
46 ? "="
47 : ((*ETI < CurrentTypeIndex) ? "<-" : "->");
48 std::string Formatted =
49 formatv("forward ref ({0} {1})", Direction, *ETI).str();
50 PUSH_FLAG(ClassOptions, ForwardReference, Options, std::move(Formatted));
52 } else {
53 PUSH_FLAG(ClassOptions, ForwardReference, Options, "forward ref");
56 PUSH_FLAG(ClassOptions, HasConstructorOrDestructor, Options,
57 "has ctor / dtor");
58 PUSH_FLAG(ClassOptions, ContainsNestedClass, Options,
59 "contains nested class");
60 PUSH_FLAG(ClassOptions, HasConversionOperator, Options,
61 "conversion operator");
62 PUSH_FLAG(ClassOptions, HasUniqueName, Options, "has unique name");
63 PUSH_FLAG(ClassOptions, Intrinsic, Options, "intrin");
64 PUSH_FLAG(ClassOptions, Nested, Options, "is nested");
65 PUSH_FLAG(ClassOptions, HasOverloadedOperator, Options,
66 "overloaded operator");
67 PUSH_FLAG(ClassOptions, HasOverloadedAssignmentOperator, Options,
68 "overloaded operator=");
69 PUSH_FLAG(ClassOptions, Packed, Options, "packed");
70 PUSH_FLAG(ClassOptions, Scoped, Options, "scoped");
71 PUSH_FLAG(ClassOptions, Sealed, Options, "sealed");
73 return typesetItemList(Opts, 4, IndentLevel, " | ");
76 static std::string pointerOptions(PointerOptions Options) {
77 std::vector<std::string> Opts;
78 PUSH_FLAG(PointerOptions, Flat32, Options, "flat32");
79 PUSH_FLAG(PointerOptions, Volatile, Options, "volatile");
80 PUSH_FLAG(PointerOptions, Const, Options, "const");
81 PUSH_FLAG(PointerOptions, Unaligned, Options, "unaligned");
82 PUSH_FLAG(PointerOptions, Restrict, Options, "restrict");
83 PUSH_FLAG(PointerOptions, WinRTSmartPointer, Options, "winrt");
84 if (Opts.empty())
85 return "None";
86 return join(Opts, " | ");
89 static std::string modifierOptions(ModifierOptions Options) {
90 std::vector<std::string> Opts;
91 PUSH_FLAG(ModifierOptions, Const, Options, "const");
92 PUSH_FLAG(ModifierOptions, Volatile, Options, "volatile");
93 PUSH_FLAG(ModifierOptions, Unaligned, Options, "unaligned");
94 if (Opts.empty())
95 return "None";
96 return join(Opts, " | ");
99 static std::string formatCallingConvention(CallingConvention Convention) {
100 switch (Convention) {
101 RETURN_CASE(CallingConvention, AlphaCall, "alphacall");
102 RETURN_CASE(CallingConvention, AM33Call, "am33call");
103 RETURN_CASE(CallingConvention, ArmCall, "armcall");
104 RETURN_CASE(CallingConvention, ClrCall, "clrcall");
105 RETURN_CASE(CallingConvention, FarC, "far cdecl");
106 RETURN_CASE(CallingConvention, FarFast, "far fastcall");
107 RETURN_CASE(CallingConvention, FarPascal, "far pascal");
108 RETURN_CASE(CallingConvention, FarStdCall, "far stdcall");
109 RETURN_CASE(CallingConvention, FarSysCall, "far syscall");
110 RETURN_CASE(CallingConvention, Generic, "generic");
111 RETURN_CASE(CallingConvention, Inline, "inline");
112 RETURN_CASE(CallingConvention, M32RCall, "m32rcall");
113 RETURN_CASE(CallingConvention, MipsCall, "mipscall");
114 RETURN_CASE(CallingConvention, NearC, "cdecl");
115 RETURN_CASE(CallingConvention, NearFast, "fastcall");
116 RETURN_CASE(CallingConvention, NearPascal, "pascal");
117 RETURN_CASE(CallingConvention, NearStdCall, "stdcall");
118 RETURN_CASE(CallingConvention, NearSysCall, "near syscall");
119 RETURN_CASE(CallingConvention, NearVector, "vectorcall");
120 RETURN_CASE(CallingConvention, PpcCall, "ppccall");
121 RETURN_CASE(CallingConvention, SHCall, "shcall");
122 RETURN_CASE(CallingConvention, SH5Call, "sh5call");
123 RETURN_CASE(CallingConvention, ThisCall, "thiscall");
124 RETURN_CASE(CallingConvention, TriCall, "tricall");
126 return formatUnknownEnum(Convention);
129 static std::string formatPointerMode(PointerMode Mode) {
130 switch (Mode) {
131 RETURN_CASE(PointerMode, LValueReference, "ref");
132 RETURN_CASE(PointerMode, Pointer, "pointer");
133 RETURN_CASE(PointerMode, PointerToDataMember, "data member pointer");
134 RETURN_CASE(PointerMode, PointerToMemberFunction, "member fn pointer");
135 RETURN_CASE(PointerMode, RValueReference, "rvalue ref");
137 return formatUnknownEnum(Mode);
140 static std::string memberAccess(MemberAccess Access) {
141 switch (Access) {
142 RETURN_CASE(MemberAccess, None, "");
143 RETURN_CASE(MemberAccess, Private, "private");
144 RETURN_CASE(MemberAccess, Protected, "protected");
145 RETURN_CASE(MemberAccess, Public, "public");
147 return formatUnknownEnum(Access);
150 static std::string methodKind(MethodKind Kind) {
151 switch (Kind) {
152 RETURN_CASE(MethodKind, Vanilla, "");
153 RETURN_CASE(MethodKind, Virtual, "virtual");
154 RETURN_CASE(MethodKind, Static, "static");
155 RETURN_CASE(MethodKind, Friend, "friend");
156 RETURN_CASE(MethodKind, IntroducingVirtual, "intro virtual");
157 RETURN_CASE(MethodKind, PureVirtual, "pure virtual");
158 RETURN_CASE(MethodKind, PureIntroducingVirtual, "pure intro virtual");
160 return formatUnknownEnum(Kind);
163 static std::string pointerKind(PointerKind Kind) {
164 switch (Kind) {
165 RETURN_CASE(PointerKind, Near16, "ptr16");
166 RETURN_CASE(PointerKind, Far16, "far ptr16");
167 RETURN_CASE(PointerKind, Huge16, "huge ptr16");
168 RETURN_CASE(PointerKind, BasedOnSegment, "segment based");
169 RETURN_CASE(PointerKind, BasedOnValue, "value based");
170 RETURN_CASE(PointerKind, BasedOnSegmentValue, "segment value based");
171 RETURN_CASE(PointerKind, BasedOnAddress, "address based");
172 RETURN_CASE(PointerKind, BasedOnSegmentAddress, "segment address based");
173 RETURN_CASE(PointerKind, BasedOnType, "type based");
174 RETURN_CASE(PointerKind, BasedOnSelf, "self based");
175 RETURN_CASE(PointerKind, Near32, "ptr32");
176 RETURN_CASE(PointerKind, Far32, "far ptr32");
177 RETURN_CASE(PointerKind, Near64, "ptr64");
179 return formatUnknownEnum(Kind);
182 static std::string memberAttributes(const MemberAttributes &Attrs) {
183 std::vector<std::string> Opts;
184 std::string Access = memberAccess(Attrs.getAccess());
185 std::string Kind = methodKind(Attrs.getMethodKind());
186 if (!Access.empty())
187 Opts.push_back(Access);
188 if (!Kind.empty())
189 Opts.push_back(Kind);
190 MethodOptions Flags = Attrs.getFlags();
191 PUSH_FLAG(MethodOptions, Pseudo, Flags, "pseudo");
192 PUSH_FLAG(MethodOptions, NoInherit, Flags, "noinherit");
193 PUSH_FLAG(MethodOptions, NoConstruct, Flags, "noconstruct");
194 PUSH_FLAG(MethodOptions, CompilerGenerated, Flags, "compiler-generated");
195 PUSH_FLAG(MethodOptions, Sealed, Flags, "sealed");
196 return join(Opts, " ");
199 static std::string formatPointerAttrs(const PointerRecord &Record) {
200 PointerMode Mode = Record.getMode();
201 PointerOptions Opts = Record.getOptions();
202 PointerKind Kind = Record.getPointerKind();
203 return formatv("mode = {0}, opts = {1}, kind = {2}", formatPointerMode(Mode),
204 pointerOptions(Opts), pointerKind(Kind));
207 static std::string formatFunctionOptions(FunctionOptions Options) {
208 std::vector<std::string> Opts;
210 PUSH_FLAG(FunctionOptions, CxxReturnUdt, Options, "returns cxx udt");
211 PUSH_FLAG(FunctionOptions, ConstructorWithVirtualBases, Options,
212 "constructor with virtual bases");
213 PUSH_FLAG(FunctionOptions, Constructor, Options, "constructor");
214 if (Opts.empty())
215 return "None";
216 return join(Opts, " | ");
219 Error MinimalTypeDumpVisitor::visitTypeBegin(CVType &Record, TypeIndex Index) {
220 CurrentTypeIndex = Index;
221 // formatLine puts the newline at the beginning, so we use formatLine here
222 // to start a new line, and then individual visit methods use format to
223 // append to the existing line.
224 if (!Hashes) {
225 P.formatLine("{0} | {1} [size = {2}]",
226 fmt_align(Index, AlignStyle::Right, Width),
227 formatTypeLeafKind(Record.Type), Record.length());
228 } else {
229 std::string H;
230 if (Index.toArrayIndex() >= HashValues.size()) {
231 H = "(not present)";
232 } else {
233 uint32_t Hash = HashValues[Index.toArrayIndex()];
234 Expected<uint32_t> MaybeHash = hashTypeRecord(Record);
235 if (!MaybeHash)
236 return MaybeHash.takeError();
237 uint32_t OurHash = *MaybeHash;
238 OurHash %= NumHashBuckets;
239 if (Hash == OurHash)
240 H = "0x" + utohexstr(Hash);
241 else
242 H = "0x" + utohexstr(Hash) + ", our hash = 0x" + utohexstr(OurHash);
244 P.formatLine("{0} | {1} [size = {2}, hash = {3}]",
245 fmt_align(Index, AlignStyle::Right, Width),
246 formatTypeLeafKind(Record.Type), Record.length(), H);
248 P.Indent(Width + 3);
249 return Error::success();
251 Error MinimalTypeDumpVisitor::visitTypeEnd(CVType &Record) {
252 P.Unindent(Width + 3);
253 if (RecordBytes) {
254 AutoIndent Indent(P, 9);
255 P.formatBinary("Bytes", Record.RecordData, 0);
257 return Error::success();
260 Error MinimalTypeDumpVisitor::visitMemberBegin(CVMemberRecord &Record) {
261 P.formatLine("- {0}", formatTypeLeafKind(Record.Kind));
262 return Error::success();
265 Error MinimalTypeDumpVisitor::visitMemberEnd(CVMemberRecord &Record) {
266 if (RecordBytes) {
267 AutoIndent Indent(P, 2);
268 P.formatBinary("Bytes", Record.Data, 0);
270 return Error::success();
273 StringRef MinimalTypeDumpVisitor::getTypeName(TypeIndex TI) const {
274 if (TI.isNoneType())
275 return "";
276 return Types.getTypeName(TI);
279 Error MinimalTypeDumpVisitor::visitKnownRecord(CVType &CVR,
280 FieldListRecord &FieldList) {
281 if (auto EC = codeview::visitMemberRecordStream(FieldList.Data, *this))
282 return EC;
284 return Error::success();
287 Error MinimalTypeDumpVisitor::visitKnownRecord(CVType &CVR,
288 StringIdRecord &String) {
289 P.format(" ID: {0}, String: {1}", String.getId(), String.getString());
290 return Error::success();
293 Error MinimalTypeDumpVisitor::visitKnownRecord(CVType &CVR,
294 ArgListRecord &Args) {
295 auto Indices = Args.getIndices();
296 if (Indices.empty())
297 return Error::success();
299 auto Max = std::max_element(Indices.begin(), Indices.end());
300 uint32_t W = NumDigits(Max->getIndex()) + 2;
302 for (auto I : Indices)
303 P.formatLine("{0}: `{1}`", fmt_align(I, AlignStyle::Right, W),
304 getTypeName(I));
305 return Error::success();
308 Error MinimalTypeDumpVisitor::visitKnownRecord(CVType &CVR,
309 StringListRecord &Strings) {
310 auto Indices = Strings.getIndices();
311 if (Indices.empty())
312 return Error::success();
314 auto Max = std::max_element(Indices.begin(), Indices.end());
315 uint32_t W = NumDigits(Max->getIndex()) + 2;
317 for (auto I : Indices)
318 P.formatLine("{0}: `{1}`", fmt_align(I, AlignStyle::Right, W),
319 getTypeName(I));
320 return Error::success();
323 Error MinimalTypeDumpVisitor::visitKnownRecord(CVType &CVR,
324 ClassRecord &Class) {
325 P.format(" `{0}`", Class.Name);
326 if (Class.hasUniqueName())
327 P.formatLine("unique name: `{0}`", Class.UniqueName);
328 P.formatLine("vtable: {0}, base list: {1}, field list: {2}",
329 Class.VTableShape, Class.DerivationList, Class.FieldList);
330 P.formatLine("options: {0}, sizeof {1}",
331 formatClassOptions(P.getIndentLevel(), Class.Options, Stream,
332 CurrentTypeIndex),
333 Class.Size);
334 return Error::success();
337 Error MinimalTypeDumpVisitor::visitKnownRecord(CVType &CVR,
338 UnionRecord &Union) {
339 P.format(" `{0}`", Union.Name);
340 if (Union.hasUniqueName())
341 P.formatLine("unique name: `{0}`", Union.UniqueName);
342 P.formatLine("field list: {0}", Union.FieldList);
343 P.formatLine("options: {0}, sizeof {1}",
344 formatClassOptions(P.getIndentLevel(), Union.Options, Stream,
345 CurrentTypeIndex),
346 Union.Size);
347 return Error::success();
350 Error MinimalTypeDumpVisitor::visitKnownRecord(CVType &CVR, EnumRecord &Enum) {
351 P.format(" `{0}`", Enum.Name);
352 if (Enum.hasUniqueName())
353 P.formatLine("unique name: `{0}`", Enum.UniqueName);
354 P.formatLine("field list: {0}, underlying type: {1}", Enum.FieldList,
355 Enum.UnderlyingType);
356 P.formatLine("options: {0}",
357 formatClassOptions(P.getIndentLevel(), Enum.Options, Stream,
358 CurrentTypeIndex));
359 return Error::success();
362 Error MinimalTypeDumpVisitor::visitKnownRecord(CVType &CVR, ArrayRecord &AT) {
363 if (AT.Name.empty()) {
364 P.formatLine("size: {0}, index type: {1}, element type: {2}", AT.Size,
365 AT.IndexType, AT.ElementType);
366 } else {
367 P.formatLine("name: {0}, size: {1}, index type: {2}, element type: {3}",
368 AT.Name, AT.Size, AT.IndexType, AT.ElementType);
370 return Error::success();
373 Error MinimalTypeDumpVisitor::visitKnownRecord(CVType &CVR,
374 VFTableRecord &VFT) {
375 P.formatLine("offset: {0}, complete class: {1}, overridden vftable: {2}",
376 VFT.VFPtrOffset, VFT.CompleteClass, VFT.OverriddenVFTable);
377 P.formatLine("method names: ");
378 if (!VFT.MethodNames.empty()) {
379 std::string Sep =
380 formatv("\n{0}",
381 fmt_repeat(' ', P.getIndentLevel() + strlen("method names: ")))
382 .str();
383 P.print(join(VFT.MethodNames, Sep));
385 return Error::success();
388 Error MinimalTypeDumpVisitor::visitKnownRecord(CVType &CVR,
389 MemberFuncIdRecord &Id) {
390 P.formatLine("name = {0}, type = {1}, class type = {2}", Id.Name,
391 Id.FunctionType, Id.ClassType);
392 return Error::success();
395 Error MinimalTypeDumpVisitor::visitKnownRecord(CVType &CVR,
396 ProcedureRecord &Proc) {
397 P.formatLine("return type = {0}, # args = {1}, param list = {2}",
398 Proc.ReturnType, Proc.ParameterCount, Proc.ArgumentList);
399 P.formatLine("calling conv = {0}, options = {1}",
400 formatCallingConvention(Proc.CallConv),
401 formatFunctionOptions(Proc.Options));
402 return Error::success();
405 Error MinimalTypeDumpVisitor::visitKnownRecord(CVType &CVR,
406 MemberFunctionRecord &MF) {
407 P.formatLine("return type = {0}, # args = {1}, param list = {2}",
408 MF.ReturnType, MF.ParameterCount, MF.ArgumentList);
409 P.formatLine("class type = {0}, this type = {1}, this adjust = {2}",
410 MF.ClassType, MF.ThisType, MF.ThisPointerAdjustment);
411 P.formatLine("calling conv = {0}, options = {1}",
412 formatCallingConvention(MF.CallConv),
413 formatFunctionOptions(MF.Options));
414 return Error::success();
417 Error MinimalTypeDumpVisitor::visitKnownRecord(CVType &CVR,
418 FuncIdRecord &Func) {
419 P.formatLine("name = {0}, type = {1}, parent scope = {2}", Func.Name,
420 Func.FunctionType, Func.ParentScope);
421 return Error::success();
424 Error MinimalTypeDumpVisitor::visitKnownRecord(CVType &CVR,
425 TypeServer2Record &TS) {
426 P.formatLine("name = {0}, age = {1}, guid = {2}", TS.Name, TS.Age, TS.Guid);
427 return Error::success();
430 Error MinimalTypeDumpVisitor::visitKnownRecord(CVType &CVR,
431 PointerRecord &Ptr) {
432 P.formatLine("referent = {0}, {1}", Ptr.ReferentType,
433 formatPointerAttrs(Ptr));
434 return Error::success();
437 Error MinimalTypeDumpVisitor::visitKnownRecord(CVType &CVR,
438 ModifierRecord &Mod) {
439 P.formatLine("referent = {0}, modifiers = {1}", Mod.ModifiedType,
440 modifierOptions(Mod.Modifiers));
441 return Error::success();
444 Error MinimalTypeDumpVisitor::visitKnownRecord(CVType &CVR,
445 VFTableShapeRecord &Shape) {
446 return Error::success();
449 Error MinimalTypeDumpVisitor::visitKnownRecord(CVType &CVR,
450 UdtModSourceLineRecord &U) {
451 P.formatLine("udt = {0}, mod = {1}, file = {2}, line = {3}", U.UDT, U.Module,
452 U.SourceFile.getIndex(), U.LineNumber);
453 return Error::success();
456 Error MinimalTypeDumpVisitor::visitKnownRecord(CVType &CVR,
457 UdtSourceLineRecord &U) {
458 P.formatLine("udt = {0}, file = {1}, line = {2}", U.UDT,
459 U.SourceFile.getIndex(), U.LineNumber);
460 return Error::success();
463 Error MinimalTypeDumpVisitor::visitKnownRecord(CVType &CVR,
464 BitFieldRecord &BF) {
465 P.formatLine("type = {0}, bit offset = {1}, # bits = {2}", BF.Type,
466 BF.BitOffset, BF.BitSize);
467 return Error::success();
470 Error MinimalTypeDumpVisitor::visitKnownRecord(
471 CVType &CVR, MethodOverloadListRecord &Overloads) {
472 for (auto &M : Overloads.Methods)
473 P.formatLine("- Method [type = {0}, vftable offset = {1}, attrs = {2}]",
474 M.Type, M.VFTableOffset, memberAttributes(M.Attrs));
475 return Error::success();
478 Error MinimalTypeDumpVisitor::visitKnownRecord(CVType &CVR,
479 BuildInfoRecord &BI) {
480 auto Indices = BI.ArgIndices;
481 if (Indices.empty())
482 return Error::success();
484 auto Max = std::max_element(Indices.begin(), Indices.end());
485 uint32_t W = NumDigits(Max->getIndex()) + 2;
487 for (auto I : Indices)
488 P.formatLine("{0}: `{1}`", fmt_align(I, AlignStyle::Right, W),
489 getTypeName(I));
490 return Error::success();
493 Error MinimalTypeDumpVisitor::visitKnownRecord(CVType &CVR, LabelRecord &R) {
494 std::string Type = (R.Mode == LabelType::Far) ? "far" : "near";
495 P.format(" type = {0}", Type);
496 return Error::success();
499 Error MinimalTypeDumpVisitor::visitKnownRecord(CVType &CVR,
500 PrecompRecord &Precomp) {
501 P.format(" start index = {0:X+}, types count = {1:X+}, signature = {2:X+},"
502 " precomp path = {3}",
503 Precomp.StartTypeIndex, Precomp.TypesCount, Precomp.Signature,
504 Precomp.PrecompFilePath);
505 return Error::success();
508 Error MinimalTypeDumpVisitor::visitKnownRecord(CVType &CVR,
509 EndPrecompRecord &EP) {
510 P.format(" signature = {0:X+}", EP.Signature);
511 return Error::success();
514 Error MinimalTypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR,
515 NestedTypeRecord &Nested) {
516 P.format(" [name = `{0}`, parent = {1}]", Nested.Name, Nested.Type);
517 return Error::success();
520 Error MinimalTypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR,
521 OneMethodRecord &Method) {
522 P.format(" [name = `{0}`]", Method.Name);
523 AutoIndent Indent(P);
524 P.formatLine("type = {0}, vftable offset = {1}, attrs = {2}", Method.Type,
525 Method.VFTableOffset, memberAttributes(Method.Attrs));
526 return Error::success();
529 Error MinimalTypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR,
530 OverloadedMethodRecord &Method) {
531 P.format(" [name = `{0}`, # overloads = {1}, overload list = {2}]",
532 Method.Name, Method.NumOverloads, Method.MethodList);
533 return Error::success();
536 Error MinimalTypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR,
537 DataMemberRecord &Field) {
538 P.format(" [name = `{0}`, Type = {1}, offset = {2}, attrs = {3}]", Field.Name,
539 Field.Type, Field.FieldOffset, memberAttributes(Field.Attrs));
540 return Error::success();
543 Error MinimalTypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR,
544 StaticDataMemberRecord &Field) {
545 P.format(" [name = `{0}`, type = {1}, attrs = {2}]", Field.Name, Field.Type,
546 memberAttributes(Field.Attrs));
547 return Error::success();
550 Error MinimalTypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR,
551 EnumeratorRecord &Enum) {
552 P.format(" [{0} = {1}]", Enum.Name,
553 Enum.Value.toString(10, Enum.Value.isSigned()));
554 return Error::success();
557 Error MinimalTypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR,
558 BaseClassRecord &Base) {
559 AutoIndent Indent(P);
560 P.formatLine("type = {0}, offset = {1}, attrs = {2}", Base.Type, Base.Offset,
561 memberAttributes(Base.Attrs));
562 return Error::success();
565 Error MinimalTypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR,
566 VirtualBaseClassRecord &Base) {
567 AutoIndent Indent(P);
568 P.formatLine(
569 "base = {0}, vbptr = {1}, vbptr offset = {2}, vtable index = {3}",
570 Base.BaseType, Base.VBPtrType, Base.VBPtrOffset, Base.VTableIndex);
571 P.formatLine("attrs = {0}", memberAttributes(Base.Attrs));
572 return Error::success();
575 Error MinimalTypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR,
576 ListContinuationRecord &Cont) {
577 P.format(" continuation = {0}", Cont.ContinuationIndex);
578 return Error::success();
581 Error MinimalTypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR,
582 VFPtrRecord &VFP) {
583 P.format(" type = {0}", VFP.Type);
584 return Error::success();