LLVM 19.0.0git
DWARFTypePrinter.cpp
Go to the documentation of this file.
5namespace llvm {
6using namespace dwarf;
8 StringRef TagStr = TagString(T);
9 static constexpr StringRef Prefix = "DW_TAG_";
10 static constexpr StringRef Suffix = "_type";
11 if (!TagStr.starts_with(Prefix) || !TagStr.ends_with(Suffix))
12 return;
13 OS << TagStr.substr(Prefix.size(),
14 TagStr.size() - (Prefix.size() + Suffix.size()))
15 << " ";
16}
17
19 for (const DWARFDie &C : D.children()) {
20 if (C.getTag() != DW_TAG_subrange_type)
21 continue;
22 std::optional<uint64_t> LB;
23 std::optional<uint64_t> Count;
24 std::optional<uint64_t> UB;
25 std::optional<unsigned> DefaultLB;
26 if (std::optional<DWARFFormValue> L = C.find(DW_AT_lower_bound))
27 LB = L->getAsUnsignedConstant();
28 if (std::optional<DWARFFormValue> CountV = C.find(DW_AT_count))
29 Count = CountV->getAsUnsignedConstant();
30 if (std::optional<DWARFFormValue> UpperV = C.find(DW_AT_upper_bound))
31 UB = UpperV->getAsUnsignedConstant();
32 if (std::optional<DWARFFormValue> LV =
33 D.getDwarfUnit()->getUnitDIE().find(DW_AT_language))
34 if (std::optional<uint64_t> LC = LV->getAsUnsignedConstant())
35 if ((DefaultLB =
36 LanguageLowerBound(static_cast<dwarf::SourceLanguage>(*LC))))
37 if (LB && *LB == *DefaultLB)
38 LB = std::nullopt;
39 if (!LB && !Count && !UB)
40 OS << "[]";
41 else if (!LB && (Count || UB) && DefaultLB)
42 OS << '[' << (Count ? *Count : *UB - *DefaultLB + 1) << ']';
43 else {
44 OS << "[[";
45 if (LB)
46 OS << *LB;
47 else
48 OS << '?';
49 OS << ", ";
50 if (Count)
51 if (LB)
52 OS << *LB + *Count;
53 else
54 OS << "? + " << *Count;
55 else if (UB)
56 OS << *UB + 1;
57 else
58 OS << '?';
59 OS << ")]";
60 }
61 }
62 EndedWithTemplate = false;
63}
64
66 dwarf::Attribute Attr = DW_AT_type) {
67 return D.getAttributeValueAsReferencedDie(Attr).resolveTypeUnitReference();
68}
70 return D.getAttributeValueAsReferencedDie(F).resolveTypeUnitReference();
71}
73 while (D && (D.getTag() == DW_TAG_const_type ||
74 D.getTag() == DW_TAG_volatile_type))
76 return D;
77}
78
81 return D && (D.getTag() == DW_TAG_subroutine_type ||
82 D.getTag() == DW_TAG_array_type);
83}
84
86 StringRef Ptr) {
88 if (Word)
89 OS << ' ';
90 if (needsParens(Inner))
91 OS << '(';
92 OS << Ptr;
93 Word = false;
94 EndedWithTemplate = false;
95}
96
99 std::string *OriginalFullName) {
100 Word = true;
101 if (!D) {
102 OS << "void";
103 return DWARFDie();
104 }
105 DWARFDie InnerDIE;
106 auto Inner = [&] { return InnerDIE = resolveReferencedType(D); };
107 const dwarf::Tag T = D.getTag();
108 switch (T) {
109 case DW_TAG_pointer_type: {
110 appendPointerLikeTypeBefore(D, Inner(), "*");
111 break;
112 }
113 case DW_TAG_subroutine_type: {
115 if (Word) {
116 OS << ' ';
117 }
118 Word = false;
119 break;
120 }
121 case DW_TAG_array_type: {
123 break;
124 }
125 case DW_TAG_reference_type:
126 appendPointerLikeTypeBefore(D, Inner(), "&");
127 break;
128 case DW_TAG_rvalue_reference_type:
129 appendPointerLikeTypeBefore(D, Inner(), "&&");
130 break;
131 case DW_TAG_ptr_to_member_type: {
133 if (needsParens(InnerDIE))
134 OS << '(';
135 else if (Word)
136 OS << ' ';
137 if (DWARFDie Cont = resolveReferencedType(D, DW_AT_containing_type)) {
139 EndedWithTemplate = false;
140 OS << "::";
141 }
142 OS << "*";
143 Word = false;
144 break;
145 }
146 case DW_TAG_LLVM_ptrauth_type:
148 break;
149 case DW_TAG_const_type:
150 case DW_TAG_volatile_type:
152 break;
153 case DW_TAG_namespace: {
154 if (const char *Name = dwarf::toString(D.find(DW_AT_name), nullptr))
155 OS << Name;
156 else
157 OS << "(anonymous namespace)";
158 break;
159 }
160 case DW_TAG_unspecified_type: {
161 StringRef TypeName = D.getShortName();
162 if (TypeName == "decltype(nullptr)")
163 TypeName = "std::nullptr_t";
164 Word = true;
165 OS << TypeName;
166 EndedWithTemplate = false;
167 break;
168 }
169 /*
170 case DW_TAG_structure_type:
171 case DW_TAG_class_type:
172 case DW_TAG_enumeration_type:
173 case DW_TAG_base_type:
174 */
175 default: {
176 const char *NamePtr = dwarf::toString(D.find(DW_AT_name), nullptr);
177 if (!NamePtr) {
178 appendTypeTagName(D.getTag());
179 return DWARFDie();
180 }
181 Word = true;
182 StringRef Name = NamePtr;
183 static constexpr StringRef MangledPrefix = "_STN|";
184 if (Name.consume_front(MangledPrefix)) {
185 auto Separator = Name.find('|');
186 assert(Separator != StringRef::npos);
187 StringRef BaseName = Name.substr(0, Separator);
188 StringRef TemplateArgs = Name.substr(Separator + 1);
189 if (OriginalFullName)
190 *OriginalFullName = (BaseName + TemplateArgs).str();
191 Name = BaseName;
192 } else
193 EndedWithTemplate = Name.ends_with(">");
194 OS << Name;
195 // This check would be insufficient for operator overloads like
196 // "operator>>" - but for now Clang doesn't try to simplify them, so this
197 // is OK. Add more nuanced operator overload handling here if/when needed.
198 if (Name.ends_with(">"))
199 break;
201 break;
202
204 OS << ' ';
205 OS << '>';
206 EndedWithTemplate = true;
207 Word = true;
208 break;
209 }
210 }
211 return InnerDIE;
212}
213
215 DWARFDie D, DWARFDie Inner, bool SkipFirstParamIfArtificial) {
216 if (!D)
217 return;
218 switch (D.getTag()) {
219 case DW_TAG_subroutine_type: {
220 appendSubroutineNameAfter(D, Inner, SkipFirstParamIfArtificial, false,
221 false);
222 break;
223 }
224 case DW_TAG_array_type: {
226 break;
227 }
228 case DW_TAG_const_type:
229 case DW_TAG_volatile_type:
231 break;
232 case DW_TAG_ptr_to_member_type:
233 case DW_TAG_reference_type:
234 case DW_TAG_rvalue_reference_type:
235 case DW_TAG_pointer_type: {
236 if (needsParens(Inner))
237 OS << ')';
239 /*SkipFirstParamIfArtificial=*/D.getTag() ==
240 DW_TAG_ptr_to_member_type);
241 break;
242 }
243 case DW_TAG_LLVM_ptrauth_type: {
244 auto getValOrNull = [&](dwarf::Attribute Attr) -> uint64_t {
245 if (auto Form = D.find(Attr))
246 return *Form->getAsUnsignedConstant();
247 return 0;
248 };
250 if (getValOrNull(DW_AT_LLVM_ptrauth_isa_pointer))
251 optionsVec.push_back("isa-pointer");
252 if (getValOrNull(DW_AT_LLVM_ptrauth_authenticates_null_values))
253 optionsVec.push_back("authenticates-null-values");
254 if (auto AuthenticationMode =
255 D.find(DW_AT_LLVM_ptrauth_authentication_mode)) {
256 switch (*AuthenticationMode->getAsUnsignedConstant()) {
257 case 0:
258 case 1:
259 optionsVec.push_back("strip");
260 break;
261 case 2:
262 optionsVec.push_back("sign-and-strip");
263 break;
264 default:
265 // Default authentication policy
266 break;
267 }
268 }
269 std::string options;
270 for (const auto *option : optionsVec) {
271 if (options.size())
272 options += ",";
273 options += option;
274 }
275 if (options.size())
276 options = ", \"" + options + "\"";
277 std::string PtrauthString;
278 llvm::raw_string_ostream PtrauthStream(PtrauthString);
279 PtrauthStream
280 << "__ptrauth(" << getValOrNull(DW_AT_LLVM_ptrauth_key) << ", "
281 << getValOrNull(DW_AT_LLVM_ptrauth_address_discriminated) << ", 0x0"
282 << utohexstr(getValOrNull(DW_AT_LLVM_ptrauth_extra_discriminator), true)
283 << options << ")";
284 OS << PtrauthStream.str();
285 break;
286 }
287 /*
288 case DW_TAG_structure_type:
289 case DW_TAG_class_type:
290 case DW_TAG_enumeration_type:
291 case DW_TAG_base_type:
292 case DW_TAG_namespace:
293 */
294 default:
295 break;
296 }
297}
298
299/// Returns True if the DIE TAG is one of the ones that is scopped.
301 switch (Tag) {
302 case dwarf::DW_TAG_structure_type:
303 case dwarf::DW_TAG_class_type:
304 case dwarf::DW_TAG_union_type:
305 case dwarf::DW_TAG_namespace:
306 case dwarf::DW_TAG_enumeration_type:
307 return true;
308 default:
309 break;
310 }
311 return false;
312}
314 if (D && scopedTAGs(D.getTag()))
315 appendScopes(D.getParent());
317}
319 if (D && scopedTAGs(D.getTag()))
320 appendScopes(D.getParent());
322}
324 bool *FirstParameter) {
325 bool FirstParameterValue = true;
326 bool IsTemplate = false;
327 if (!FirstParameter)
328 FirstParameter = &FirstParameterValue;
329 for (const DWARFDie &C : D) {
330 auto Sep = [&] {
331 if (*FirstParameter)
332 OS << '<';
333 else
334 OS << ", ";
335 IsTemplate = true;
336 EndedWithTemplate = false;
337 *FirstParameter = false;
338 };
339 if (C.getTag() == dwarf::DW_TAG_GNU_template_parameter_pack) {
340 IsTemplate = true;
341 appendTemplateParameters(C, FirstParameter);
342 }
343 if (C.getTag() == dwarf::DW_TAG_template_value_parameter) {
345 Sep();
346 if (T.getTag() == DW_TAG_enumeration_type) {
347 OS << '(';
349 OS << ')';
350 auto V = C.find(DW_AT_const_value);
351 OS << std::to_string(*V->getAsSignedConstant());
352 continue;
353 }
354 // /Maybe/ we could do pointer type parameters, looking for the
355 // symbol in the ELF symbol table to get back to the variable...
356 // but probably not worth it.
357 if (T.getTag() == DW_TAG_pointer_type)
358 continue;
359 const char *RawName = dwarf::toString(T.find(DW_AT_name), nullptr);
360 assert(RawName);
361 StringRef Name = RawName;
362 auto V = C.find(DW_AT_const_value);
363 bool IsQualifiedChar = false;
364 if (Name == "bool") {
365 OS << (*V->getAsUnsignedConstant() ? "true" : "false");
366 } else if (Name == "short") {
367 OS << "(short)";
368 OS << std::to_string(*V->getAsSignedConstant());
369 } else if (Name == "unsigned short") {
370 OS << "(unsigned short)";
371 OS << std::to_string(*V->getAsSignedConstant());
372 } else if (Name == "int")
373 OS << std::to_string(*V->getAsSignedConstant());
374 else if (Name == "long") {
375 OS << std::to_string(*V->getAsSignedConstant());
376 OS << "L";
377 } else if (Name == "long long") {
378 OS << std::to_string(*V->getAsSignedConstant());
379 OS << "LL";
380 } else if (Name == "unsigned int") {
381 OS << std::to_string(*V->getAsUnsignedConstant());
382 OS << "U";
383 } else if (Name == "unsigned long") {
384 OS << std::to_string(*V->getAsUnsignedConstant());
385 OS << "UL";
386 } else if (Name == "unsigned long long") {
387 OS << std::to_string(*V->getAsUnsignedConstant());
388 OS << "ULL";
389 } else if (Name == "char" ||
390 (IsQualifiedChar =
391 (Name == "unsigned char" || Name == "signed char"))) {
392 // FIXME: check T's DW_AT_type to see if it's signed or not (since
393 // char signedness is implementation defined).
394 auto Val = *V->getAsSignedConstant();
395 // Copied/hacked up from Clang's CharacterLiteral::print - incomplete
396 // (doesn't actually support different character types/widths, sign
397 // handling's not done, and doesn't correctly test if a character is
398 // printable or needs to use a numeric escape sequence instead)
399 if (IsQualifiedChar) {
400 OS << '(';
401 OS << Name;
402 OS << ')';
403 }
404 switch (Val) {
405 case '\\':
406 OS << "'\\\\'";
407 break;
408 case '\'':
409 OS << "'\\''";
410 break;
411 case '\a':
412 // TODO: K&R: the meaning of '\\a' is different in traditional C
413 OS << "'\\a'";
414 break;
415 case '\b':
416 OS << "'\\b'";
417 break;
418 case '\f':
419 OS << "'\\f'";
420 break;
421 case '\n':
422 OS << "'\\n'";
423 break;
424 case '\r':
425 OS << "'\\r'";
426 break;
427 case '\t':
428 OS << "'\\t'";
429 break;
430 case '\v':
431 OS << "'\\v'";
432 break;
433 default:
434 if ((Val & ~0xFFu) == ~0xFFu)
435 Val &= 0xFFu;
436 if (Val < 127 && Val >= 32) {
437 OS << "'";
438 OS << (char)Val;
439 OS << "'";
440 } else if (Val < 256)
441 OS << llvm::format("'\\x%02" PRIx64 "'", Val);
442 else if (Val <= 0xFFFF)
443 OS << llvm::format("'\\u%04" PRIx64 "'", Val);
444 else
445 OS << llvm::format("'\\U%08" PRIx64 "'", Val);
446 }
447 }
448 continue;
449 }
450 if (C.getTag() == dwarf::DW_TAG_GNU_template_template_param) {
451 const char *RawName =
452 dwarf::toString(C.find(DW_AT_GNU_template_name), nullptr);
453 assert(RawName);
454 StringRef Name = RawName;
455 Sep();
456 OS << Name;
457 continue;
458 }
459 if (C.getTag() != dwarf::DW_TAG_template_type_parameter)
460 continue;
461 auto TypeAttr = C.find(DW_AT_type);
462 Sep();
464 : DWARFDie());
465 }
466 if (IsTemplate && *FirstParameter && FirstParameter == &FirstParameterValue) {
467 OS << '<';
468 EndedWithTemplate = false;
469 }
470 return IsTemplate;
471}
473 DWARFDie &C, DWARFDie &V) {
474 (N.getTag() == DW_TAG_const_type ? C : V) = N;
476 if (T) {
477 auto Tag = T.getTag();
478 if (Tag == DW_TAG_const_type) {
479 C = T;
481 } else if (Tag == DW_TAG_volatile_type) {
482 V = T;
484 }
485 }
486}
488 DWARFDie C;
489 DWARFDie V;
490 DWARFDie T;
492 if (T && T.getTag() == DW_TAG_subroutine_type)
494 V.isValid());
495 else
497}
499 DWARFDie C;
500 DWARFDie V;
501 DWARFDie T;
503 bool Subroutine = T && T.getTag() == DW_TAG_subroutine_type;
504 DWARFDie A = T;
505 while (A && A.getTag() == DW_TAG_array_type)
507 bool Leading =
508 (!A || (A.getTag() != DW_TAG_pointer_type &&
509 A.getTag() != llvm::dwarf::DW_TAG_ptr_to_member_type)) &&
510 !Subroutine;
511 if (Leading) {
512 if (C)
513 OS << "const ";
514 if (V)
515 OS << "volatile ";
516 }
518 if (!Leading && !Subroutine) {
519 Word = true;
520 if (C)
521 OS << "const";
522 if (V) {
523 if (C)
524 OS << ' ';
525 OS << "volatile";
526 }
527 }
528}
530 std::string *OriginalFullName) {
531 // FIXME: We should have pretty printers per language. Currently we print
532 // everything as if it was C++ and fall back to the TAG type name.
533 DWARFDie Inner = appendUnqualifiedNameBefore(D, OriginalFullName);
535}
537 DWARFDie D, DWARFDie Inner, bool SkipFirstParamIfArtificial, bool Const,
538 bool Volatile) {
539 DWARFDie FirstParamIfArtificial;
540 OS << '(';
541 EndedWithTemplate = false;
542 bool First = true;
543 bool RealFirst = true;
544 for (DWARFDie P : D) {
545 if (P.getTag() != DW_TAG_formal_parameter &&
546 P.getTag() != DW_TAG_unspecified_parameters)
547 return;
549 if (SkipFirstParamIfArtificial && RealFirst && P.find(DW_AT_artificial)) {
550 FirstParamIfArtificial = T;
551 RealFirst = false;
552 continue;
553 }
554 if (!First) {
555 OS << ", ";
556 }
557 First = false;
558 if (P.getTag() == DW_TAG_unspecified_parameters)
559 OS << "...";
560 else
562 }
563 EndedWithTemplate = false;
564 OS << ')';
565 if (FirstParamIfArtificial) {
566 if (DWARFDie P = FirstParamIfArtificial) {
567 if (P.getTag() == DW_TAG_pointer_type) {
568 auto CVStep = [&](DWARFDie CV) {
569 if (DWARFDie U = resolveReferencedType(CV)) {
570 Const |= U.getTag() == DW_TAG_const_type;
571 Volatile |= U.getTag() == DW_TAG_volatile_type;
572 return U;
573 }
574 return DWARFDie();
575 };
576 if (DWARFDie CV = CVStep(P)) {
577 CVStep(CV);
578 }
579 }
580 }
581 }
582
583 if (auto CC = D.find(DW_AT_calling_convention)) {
584 switch (*CC->getAsUnsignedConstant()) {
585 case CallingConvention::DW_CC_BORLAND_stdcall:
586 OS << " __attribute__((stdcall))";
587 break;
588 case CallingConvention::DW_CC_BORLAND_msfastcall:
589 OS << " __attribute__((fastcall))";
590 break;
591 case CallingConvention::DW_CC_BORLAND_thiscall:
592 OS << " __attribute__((thiscall))";
593 break;
594 case CallingConvention::DW_CC_LLVM_vectorcall:
595 OS << " __attribute__((vectorcall))";
596 break;
597 case CallingConvention::DW_CC_BORLAND_pascal:
598 OS << " __attribute__((pascal))";
599 break;
600 case CallingConvention::DW_CC_LLVM_Win64:
601 OS << " __attribute__((ms_abi))";
602 break;
603 case CallingConvention::DW_CC_LLVM_X86_64SysV:
604 OS << " __attribute__((sysv_abi))";
605 break;
606 case CallingConvention::DW_CC_LLVM_AAPCS:
607 // AArch64VectorCall missing?
608 OS << " __attribute__((pcs(\"aapcs\")))";
609 break;
610 case CallingConvention::DW_CC_LLVM_AAPCS_VFP:
611 OS << " __attribute__((pcs(\"aapcs-vfp\")))";
612 break;
613 case CallingConvention::DW_CC_LLVM_IntelOclBicc:
614 OS << " __attribute__((intel_ocl_bicc))";
615 break;
616 case CallingConvention::DW_CC_LLVM_SpirFunction:
617 case CallingConvention::DW_CC_LLVM_OpenCLKernel:
618 // These aren't available as attributes, but maybe we should still
619 // render them somehow? (Clang doesn't render them, but that's an issue
620 // for template names too - since then the DWARF names of templates
621 // instantiated with function types with these calling conventions won't
622 // have distinct names - so we'd need to fix that too)
623 break;
624 case CallingConvention::DW_CC_LLVM_Swift:
625 // SwiftAsync missing
626 OS << " __attribute__((swiftcall))";
627 break;
628 case CallingConvention::DW_CC_LLVM_PreserveMost:
629 OS << " __attribute__((preserve_most))";
630 break;
631 case CallingConvention::DW_CC_LLVM_PreserveAll:
632 OS << " __attribute__((preserve_all))";
633 break;
634 case CallingConvention::DW_CC_LLVM_PreserveNone:
635 OS << " __attribute__((preserve_none))";
636 break;
637 case CallingConvention::DW_CC_LLVM_X86RegCall:
638 OS << " __attribute__((regcall))";
639 break;
640 case CallingConvention::DW_CC_LLVM_M68kRTD:
641 OS << " __attribute__((m68k_rtd))";
642 break;
643 }
644 }
645
646 if (Const)
647 OS << " const";
648 if (Volatile)
649 OS << " volatile";
650 if (D.find(DW_AT_reference))
651 OS << " &";
652 if (D.find(DW_AT_rvalue_reference))
653 OS << " &&";
654
656}
658 if (D.getTag() == DW_TAG_compile_unit)
659 return;
660 if (D.getTag() == DW_TAG_type_unit)
661 return;
662 if (D.getTag() == DW_TAG_skeleton_unit)
663 return;
664 if (D.getTag() == DW_TAG_subprogram)
665 return;
666 if (D.getTag() == DW_TAG_lexical_block)
667 return;
668 D = D.resolveTypeUnitReference();
669 if (DWARFDie P = D.getParent())
672 OS << "::";
673}
674} // namespace llvm
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
std::string Name
#define F(x, y, z)
Definition: MD5.cpp:55
#define T
#define P(N)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static dwarf::Attribute TypeAttr[]
Utility class that carries the DWARF compile/type unit and the debug info entry in an object.
Definition: DWARFDie.h:42
void push_back(const T &Elt)
Definition: SmallVector.h:426
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1209
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
constexpr StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
Definition: StringRef.h:567
bool starts_with(StringRef Prefix) const
Check if this string starts with the given Prefix.
Definition: StringRef.h:257
constexpr size_t size() const
size - Get the string size.
Definition: StringRef.h:137
bool ends_with(StringRef Suffix) const
Check if this string ends with the given Suffix.
Definition: StringRef.h:271
static constexpr size_t npos
Definition: StringRef.h:52
A raw_ostream that writes to an std::string.
Definition: raw_ostream.h:660
std::string & str()
Returns the string's reference.
Definition: raw_ostream.h:678
StringRef TagString(unsigned Tag)
Definition: Dwarf.cpp:21
@ C
The default llvm calling convention, compatible with C.
Definition: CallingConv.h:34
Attribute
Attributes.
Definition: Dwarf.h:123
std::optional< unsigned > LanguageLowerBound(SourceLanguage L)
Definition: Dwarf.cpp:403
std::optional< const char * > toString(const std::optional< DWARFFormValue > &V)
Take an optional DWARFFormValue and try to extract a string value from it.
SourceLanguage
Definition: Dwarf.h:204
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
Definition: Format.h:125
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.
static DWARFDie resolveReferencedType(DWARFDie D, dwarf::Attribute Attr=DW_AT_type)
static bool scopedTAGs(dwarf::Tag Tag)
Returns True if the DIE TAG is one of the ones that is scopped.
#define N
void appendQualifiedName(DWARFDie D)
void appendUnqualifiedNameAfter(DWARFDie D, DWARFDie Inner, bool SkipFirstParamIfArtificial=false)
void appendUnqualifiedName(DWARFDie D, std::string *OriginalFullName=nullptr)
Recursively append the DIE type name when applicable.
DWARFDie appendUnqualifiedNameBefore(DWARFDie D, std::string *OriginalFullName=nullptr)
void appendSubroutineNameAfter(DWARFDie D, DWARFDie Inner, bool SkipFirstParamIfArtificial, bool Const, bool Volatile)
bool appendTemplateParameters(DWARFDie D, bool *FirstParameter=nullptr)
bool needsParens(DWARFDie D)
void appendConstVolatileQualifierBefore(DWARFDie N)
void appendPointerLikeTypeBefore(DWARFDie D, DWARFDie Inner, StringRef Ptr)
DWARFDie appendQualifiedNameBefore(DWARFDie D)
void decomposeConstVolatile(DWARFDie &N, DWARFDie &T, DWARFDie &C, DWARFDie &V)
void appendConstVolatileQualifierAfter(DWARFDie N)
DWARFDie skipQualifiers(DWARFDie D)
void appendTypeTagName(dwarf::Tag T)
Dump the name encoded in the type tag.
void appendScopes(DWARFDie D)
void appendArrayType(const DWARFDie &D)