File indexing completed on 2026-05-10 08:43:42
0001
0002
0003
0004
0005
0006
0007
0008
0009 #ifndef LLVM_DEBUGINFO_DWARF_DWARFTYPEPRINTER_H
0010 #define LLVM_DEBUGINFO_DWARF_DWARFTYPEPRINTER_H
0011
0012 #include "llvm/ADT/StringExtras.h"
0013 #include "llvm/ADT/StringRef.h"
0014 #include "llvm/BinaryFormat/Dwarf.h"
0015 #include "llvm/Support/Error.h"
0016
0017 #include <string>
0018
0019 namespace llvm {
0020
0021 class raw_ostream;
0022
0023
0024
0025 template <typename DieType> struct DWARFTypePrinter {
0026 raw_ostream &OS;
0027 bool Word = true;
0028 bool EndedWithTemplate = false;
0029
0030 DWARFTypePrinter(raw_ostream &OS) : OS(OS) {}
0031
0032
0033 void appendTypeTagName(dwarf::Tag T);
0034
0035 void appendArrayType(const DieType &D);
0036
0037 DieType skipQualifiers(DieType D);
0038
0039 bool needsParens(DieType D);
0040
0041 void appendPointerLikeTypeBefore(DieType D, DieType Inner, StringRef Ptr);
0042
0043 DieType appendUnqualifiedNameBefore(DieType D,
0044 std::string *OriginalFullName = nullptr);
0045
0046 void appendUnqualifiedNameAfter(DieType D, DieType Inner,
0047 bool SkipFirstParamIfArtificial = false);
0048 void appendQualifiedName(DieType D);
0049 DieType appendQualifiedNameBefore(DieType D);
0050 bool appendTemplateParameters(DieType D, bool *FirstParameter = nullptr);
0051 void appendAndTerminateTemplateParameters(DieType D);
0052 void decomposeConstVolatile(DieType &N, DieType &T, DieType &C, DieType &V);
0053 void appendConstVolatileQualifierAfter(DieType N);
0054 void appendConstVolatileQualifierBefore(DieType N);
0055
0056
0057 void appendUnqualifiedName(DieType D,
0058 std::string *OriginalFullName = nullptr);
0059
0060 void appendSubroutineNameAfter(DieType D, DieType Inner,
0061 bool SkipFirstParamIfArtificial, bool Const,
0062 bool Volatile);
0063 void appendScopes(DieType D);
0064
0065 private:
0066
0067 static inline bool scopedTAGs(dwarf::Tag Tag) {
0068 switch (Tag) {
0069 case dwarf::DW_TAG_structure_type:
0070 case dwarf::DW_TAG_class_type:
0071 case dwarf::DW_TAG_union_type:
0072 case dwarf::DW_TAG_namespace:
0073 case dwarf::DW_TAG_enumeration_type:
0074 case dwarf::DW_TAG_typedef:
0075 return true;
0076 default:
0077 break;
0078 }
0079 return false;
0080 }
0081 };
0082
0083 template <typename DieType>
0084 void DWARFTypePrinter<DieType>::appendTypeTagName(dwarf::Tag T) {
0085 StringRef TagStr = TagString(T);
0086 static constexpr StringRef Prefix = "DW_TAG_";
0087 static constexpr StringRef Suffix = "_type";
0088 if (!TagStr.starts_with(Prefix) || !TagStr.ends_with(Suffix))
0089 return;
0090 OS << TagStr.substr(Prefix.size(),
0091 TagStr.size() - (Prefix.size() + Suffix.size()))
0092 << " ";
0093 }
0094
0095 template <typename DieType>
0096 void DWARFTypePrinter<DieType>::appendArrayType(const DieType &D) {
0097 for (const DieType &C : D.children()) {
0098 if (C.getTag() != dwarf::DW_TAG_subrange_type)
0099 continue;
0100 std::optional<uint64_t> LB;
0101 std::optional<uint64_t> Count;
0102 std::optional<uint64_t> UB;
0103 std::optional<unsigned> DefaultLB;
0104 if (std::optional<typename DieType::DWARFFormValue> L =
0105 C.find(dwarf::DW_AT_lower_bound))
0106 LB = L->getAsUnsignedConstant();
0107 if (std::optional<typename DieType::DWARFFormValue> CountV =
0108 C.find(dwarf::DW_AT_count))
0109 Count = CountV->getAsUnsignedConstant();
0110 if (std::optional<typename DieType::DWARFFormValue> UpperV =
0111 C.find(dwarf::DW_AT_upper_bound))
0112 UB = UpperV->getAsUnsignedConstant();
0113 if (std::optional<uint64_t> LV = D.getLanguage())
0114 if ((DefaultLB =
0115 LanguageLowerBound(static_cast<dwarf::SourceLanguage>(*LV))))
0116 if (LB && *LB == *DefaultLB)
0117 LB = std::nullopt;
0118 if (!LB && !Count && !UB)
0119 OS << "[]";
0120 else if (!LB && (Count || UB) && DefaultLB)
0121 OS << '[' << (Count ? *Count : *UB - *DefaultLB + 1) << ']';
0122 else {
0123 OS << "[[";
0124 if (LB)
0125 OS << *LB;
0126 else
0127 OS << '?';
0128 OS << ", ";
0129 if (Count)
0130 if (LB)
0131 OS << *LB + *Count;
0132 else
0133 OS << "? + " << *Count;
0134 else if (UB)
0135 OS << *UB + 1;
0136 else
0137 OS << '?';
0138 OS << ")]";
0139 }
0140 }
0141 EndedWithTemplate = false;
0142 }
0143
0144 namespace detail {
0145 template <typename DieType>
0146 DieType resolveReferencedType(DieType D,
0147 dwarf::Attribute Attr = dwarf::DW_AT_type) {
0148 return D.resolveReferencedType(Attr);
0149 }
0150 template <typename DieType>
0151 DieType resolveReferencedType(DieType D, typename DieType::DWARFFormValue F) {
0152 return D.resolveReferencedType(F);
0153 }
0154 template <typename DWARFFormValueType>
0155 const char *toString(std::optional<DWARFFormValueType> F) {
0156 if (F) {
0157 llvm::Expected<const char *> E = F->getAsCString();
0158 if (E)
0159 return *E;
0160 llvm::consumeError(E.takeError());
0161 }
0162 return nullptr;
0163 }
0164 }
0165
0166 template <typename DieType>
0167 DieType DWARFTypePrinter<DieType>::skipQualifiers(DieType D) {
0168 while (D && (D.getTag() == dwarf::DW_TAG_const_type ||
0169 D.getTag() == dwarf::DW_TAG_volatile_type))
0170 D = detail::resolveReferencedType(D);
0171 return D;
0172 }
0173
0174 template <typename DieType>
0175 bool DWARFTypePrinter<DieType>::needsParens(DieType D) {
0176 D = skipQualifiers(D);
0177 return D && (D.getTag() == dwarf::DW_TAG_subroutine_type ||
0178 D.getTag() == dwarf::DW_TAG_array_type);
0179 }
0180
0181 template <typename DieType>
0182 void DWARFTypePrinter<DieType>::appendPointerLikeTypeBefore(DieType D,
0183 DieType Inner,
0184 StringRef Ptr) {
0185 appendQualifiedNameBefore(Inner);
0186 if (Word)
0187 OS << ' ';
0188 if (needsParens(Inner))
0189 OS << '(';
0190 OS << Ptr;
0191 Word = false;
0192 EndedWithTemplate = false;
0193 }
0194
0195 template <typename DieType>
0196 DieType DWARFTypePrinter<DieType>::appendUnqualifiedNameBefore(
0197 DieType D, std::string *OriginalFullName) {
0198 Word = true;
0199 if (!D) {
0200 OS << "void";
0201 return DieType();
0202 }
0203 DieType InnerDIE;
0204 auto Inner = [&] { return InnerDIE = detail::resolveReferencedType(D); };
0205 const dwarf::Tag T = D.getTag();
0206 switch (T) {
0207 case dwarf::DW_TAG_pointer_type: {
0208 appendPointerLikeTypeBefore(D, Inner(), "*");
0209 break;
0210 }
0211 case dwarf::DW_TAG_subroutine_type: {
0212 appendQualifiedNameBefore(Inner());
0213 if (Word) {
0214 OS << ' ';
0215 }
0216 Word = false;
0217 break;
0218 }
0219 case dwarf::DW_TAG_array_type: {
0220 appendQualifiedNameBefore(Inner());
0221 break;
0222 }
0223 case dwarf::DW_TAG_reference_type:
0224 appendPointerLikeTypeBefore(D, Inner(), "&");
0225 break;
0226 case dwarf::DW_TAG_rvalue_reference_type:
0227 appendPointerLikeTypeBefore(D, Inner(), "&&");
0228 break;
0229 case dwarf::DW_TAG_ptr_to_member_type: {
0230 appendQualifiedNameBefore(Inner());
0231 if (needsParens(InnerDIE))
0232 OS << '(';
0233 else if (Word)
0234 OS << ' ';
0235 if (DieType Cont =
0236 detail::resolveReferencedType(D, dwarf::DW_AT_containing_type)) {
0237 appendQualifiedName(Cont);
0238 EndedWithTemplate = false;
0239 OS << "::";
0240 }
0241 OS << "*";
0242 Word = false;
0243 break;
0244 }
0245 case dwarf::DW_TAG_LLVM_ptrauth_type:
0246 appendQualifiedNameBefore(Inner());
0247 break;
0248 case dwarf::DW_TAG_const_type:
0249 case dwarf::DW_TAG_volatile_type:
0250 appendConstVolatileQualifierBefore(D);
0251 break;
0252 case dwarf::DW_TAG_namespace: {
0253 if (const char *Name = detail::toString(D.find(dwarf::DW_AT_name)))
0254 OS << Name;
0255 else
0256 OS << "(anonymous namespace)";
0257 break;
0258 }
0259 case dwarf::DW_TAG_unspecified_type: {
0260 StringRef TypeName = D.getShortName();
0261 if (TypeName == "decltype(nullptr)")
0262 TypeName = "std::nullptr_t";
0263 Word = true;
0264 OS << TypeName;
0265 EndedWithTemplate = false;
0266 break;
0267 }
0268
0269
0270
0271
0272
0273
0274 default: {
0275 const char *NamePtr = detail::toString(D.find(dwarf::DW_AT_name));
0276 if (!NamePtr) {
0277 appendTypeTagName(D.getTag());
0278 return DieType();
0279 }
0280 Word = true;
0281 StringRef Name = NamePtr;
0282 static constexpr StringRef MangledPrefix = "_STN|";
0283 if (Name.consume_front(MangledPrefix)) {
0284 auto Separator = Name.find('|');
0285 assert(Separator != StringRef::npos);
0286 StringRef BaseName = Name.substr(0, Separator);
0287 StringRef TemplateArgs = Name.substr(Separator + 1);
0288 if (OriginalFullName)
0289 *OriginalFullName = (BaseName + TemplateArgs).str();
0290 Name = BaseName;
0291 } else
0292 EndedWithTemplate = Name.ends_with(">");
0293 OS << Name;
0294
0295
0296
0297 if (Name.ends_with(">"))
0298 break;
0299 if (!appendTemplateParameters(D))
0300 break;
0301
0302 if (EndedWithTemplate)
0303 OS << ' ';
0304 OS << '>';
0305 EndedWithTemplate = true;
0306 Word = true;
0307 break;
0308 }
0309 }
0310 return InnerDIE;
0311 }
0312
0313 template <typename DieType>
0314 void DWARFTypePrinter<DieType>::appendUnqualifiedNameAfter(
0315 DieType D, DieType Inner, bool SkipFirstParamIfArtificial) {
0316 if (!D)
0317 return;
0318 switch (D.getTag()) {
0319 case dwarf::DW_TAG_subroutine_type: {
0320 appendSubroutineNameAfter(D, Inner, SkipFirstParamIfArtificial, false,
0321 false);
0322 break;
0323 }
0324 case dwarf::DW_TAG_array_type: {
0325 appendArrayType(D);
0326 break;
0327 }
0328 case dwarf::DW_TAG_const_type:
0329 case dwarf::DW_TAG_volatile_type:
0330 appendConstVolatileQualifierAfter(D);
0331 break;
0332 case dwarf::DW_TAG_ptr_to_member_type:
0333 case dwarf::DW_TAG_reference_type:
0334 case dwarf::DW_TAG_rvalue_reference_type:
0335 case dwarf::DW_TAG_pointer_type: {
0336 if (needsParens(Inner))
0337 OS << ')';
0338 appendUnqualifiedNameAfter(Inner, detail::resolveReferencedType(Inner),
0339 D.getTag() ==
0340 dwarf::DW_TAG_ptr_to_member_type);
0341 break;
0342 }
0343 case dwarf::DW_TAG_LLVM_ptrauth_type: {
0344 auto getValOrNull = [&](dwarf::Attribute Attr) -> uint64_t {
0345 if (auto Form = D.find(Attr))
0346 return *Form->getAsUnsignedConstant();
0347 return 0;
0348 };
0349 SmallVector<const char *, 2> optionsVec;
0350 if (getValOrNull(dwarf::DW_AT_LLVM_ptrauth_isa_pointer))
0351 optionsVec.push_back("isa-pointer");
0352 if (getValOrNull(dwarf::DW_AT_LLVM_ptrauth_authenticates_null_values))
0353 optionsVec.push_back("authenticates-null-values");
0354 if (auto AuthenticationMode =
0355 D.find(dwarf::DW_AT_LLVM_ptrauth_authentication_mode)) {
0356 switch (*AuthenticationMode->getAsUnsignedConstant()) {
0357 case 0:
0358 case 1:
0359 optionsVec.push_back("strip");
0360 break;
0361 case 2:
0362 optionsVec.push_back("sign-and-strip");
0363 break;
0364 default:
0365
0366 break;
0367 }
0368 }
0369 std::string options;
0370 for (const auto *option : optionsVec) {
0371 if (options.size())
0372 options += ",";
0373 options += option;
0374 }
0375 if (options.size())
0376 options = ", \"" + options + "\"";
0377 std::string PtrauthString;
0378 llvm::raw_string_ostream PtrauthStream(PtrauthString);
0379 PtrauthStream
0380 << "__ptrauth(" << getValOrNull(dwarf::DW_AT_LLVM_ptrauth_key) << ", "
0381 << getValOrNull(dwarf::DW_AT_LLVM_ptrauth_address_discriminated)
0382 << ", 0x0"
0383 << utohexstr(
0384 getValOrNull(dwarf::DW_AT_LLVM_ptrauth_extra_discriminator),
0385 true)
0386 << options << ")";
0387 OS << PtrauthStream.str();
0388 break;
0389 }
0390
0391
0392
0393
0394
0395
0396
0397 default:
0398 break;
0399 }
0400 }
0401
0402 template <typename DieType>
0403 void DWARFTypePrinter<DieType>::appendQualifiedName(DieType D) {
0404 if (D && scopedTAGs(D.getTag()))
0405 appendScopes(D.getParent());
0406 appendUnqualifiedName(D);
0407 }
0408
0409 template <typename DieType>
0410 DieType DWARFTypePrinter<DieType>::appendQualifiedNameBefore(DieType D) {
0411 if (D && scopedTAGs(D.getTag()))
0412 appendScopes(D.getParent());
0413 return appendUnqualifiedNameBefore(D);
0414 }
0415
0416 template <typename DieType>
0417 bool DWARFTypePrinter<DieType>::appendTemplateParameters(DieType D,
0418 bool *FirstParameter) {
0419 bool FirstParameterValue = true;
0420 bool IsTemplate = false;
0421 if (!FirstParameter)
0422 FirstParameter = &FirstParameterValue;
0423 for (const DieType &C : D) {
0424 auto Sep = [&] {
0425 if (*FirstParameter)
0426 OS << '<';
0427 else
0428 OS << ", ";
0429 IsTemplate = true;
0430 EndedWithTemplate = false;
0431 *FirstParameter = false;
0432 };
0433 if (C.getTag() == dwarf::DW_TAG_GNU_template_parameter_pack) {
0434 IsTemplate = true;
0435 appendTemplateParameters(C, FirstParameter);
0436 }
0437 if (C.getTag() == dwarf::DW_TAG_template_value_parameter) {
0438 DieType T = detail::resolveReferencedType(C);
0439 Sep();
0440 if (T.getTag() == dwarf::DW_TAG_enumeration_type) {
0441 OS << '(';
0442 appendQualifiedName(T);
0443 OS << ')';
0444 auto V = C.find(dwarf::DW_AT_const_value);
0445 OS << std::to_string(*V->getAsSignedConstant());
0446 continue;
0447 }
0448
0449
0450
0451 if (T.getTag() == dwarf::DW_TAG_pointer_type ||
0452 T.getTag() == dwarf::DW_TAG_reference_type)
0453 continue;
0454 const char *RawName = detail::toString(T.find(dwarf::DW_AT_name));
0455 assert(RawName);
0456 StringRef Name = RawName;
0457 auto V = C.find(dwarf::DW_AT_const_value);
0458 bool IsQualifiedChar = false;
0459 if (Name == "bool") {
0460 OS << (*V->getAsUnsignedConstant() ? "true" : "false");
0461 } else if (Name == "short") {
0462 OS << "(short)";
0463 OS << std::to_string(*V->getAsSignedConstant());
0464 } else if (Name == "unsigned short") {
0465 OS << "(unsigned short)";
0466 OS << std::to_string(*V->getAsSignedConstant());
0467 } else if (Name == "int")
0468 OS << std::to_string(*V->getAsSignedConstant());
0469 else if (Name == "long") {
0470 OS << std::to_string(*V->getAsSignedConstant());
0471 OS << "L";
0472 } else if (Name == "long long") {
0473 OS << std::to_string(*V->getAsSignedConstant());
0474 OS << "LL";
0475 } else if (Name == "unsigned int") {
0476 OS << std::to_string(*V->getAsUnsignedConstant());
0477 OS << "U";
0478 } else if (Name == "unsigned long") {
0479 OS << std::to_string(*V->getAsUnsignedConstant());
0480 OS << "UL";
0481 } else if (Name == "unsigned long long") {
0482 OS << std::to_string(*V->getAsUnsignedConstant());
0483 OS << "ULL";
0484 } else if (Name == "char" ||
0485 (IsQualifiedChar =
0486 (Name == "unsigned char" || Name == "signed char"))) {
0487
0488
0489 auto Val = *V->getAsSignedConstant();
0490
0491
0492
0493
0494 if (IsQualifiedChar) {
0495 OS << '(';
0496 OS << Name;
0497 OS << ')';
0498 }
0499 switch (Val) {
0500 case '\\':
0501 OS << "'\\\\'";
0502 break;
0503 case '\'':
0504 OS << "'\\''";
0505 break;
0506 case '\a':
0507
0508 OS << "'\\a'";
0509 break;
0510 case '\b':
0511 OS << "'\\b'";
0512 break;
0513 case '\f':
0514 OS << "'\\f'";
0515 break;
0516 case '\n':
0517 OS << "'\\n'";
0518 break;
0519 case '\r':
0520 OS << "'\\r'";
0521 break;
0522 case '\t':
0523 OS << "'\\t'";
0524 break;
0525 case '\v':
0526 OS << "'\\v'";
0527 break;
0528 default:
0529 if ((Val & ~0xFFu) == ~0xFFu)
0530 Val &= 0xFFu;
0531 if (Val < 127 && Val >= 32) {
0532 OS << "'";
0533 OS << (char)Val;
0534 OS << "'";
0535 } else if (Val < 256)
0536 OS << llvm::format("'\\x%02" PRIx64 "'", Val);
0537 else if (Val <= 0xFFFF)
0538 OS << llvm::format("'\\u%04" PRIx64 "'", Val);
0539 else
0540 OS << llvm::format("'\\U%08" PRIx64 "'", Val);
0541 }
0542 }
0543 continue;
0544 }
0545 if (C.getTag() == dwarf::DW_TAG_GNU_template_template_param) {
0546 const char *RawName =
0547 detail::toString(C.find(dwarf::DW_AT_GNU_template_name));
0548 assert(RawName);
0549 StringRef Name = RawName;
0550 Sep();
0551 OS << Name;
0552 continue;
0553 }
0554 if (C.getTag() != dwarf::DW_TAG_template_type_parameter)
0555 continue;
0556 auto TypeAttr = C.find(dwarf::DW_AT_type);
0557 Sep();
0558 appendQualifiedName(TypeAttr ? detail::resolveReferencedType(C, *TypeAttr)
0559 : DieType());
0560 }
0561 if (IsTemplate && *FirstParameter && FirstParameter == &FirstParameterValue) {
0562 OS << '<';
0563 EndedWithTemplate = false;
0564 }
0565 return IsTemplate;
0566 }
0567
0568 template <typename DieType>
0569 void DWARFTypePrinter<DieType>::appendAndTerminateTemplateParameters(
0570 DieType D) {
0571 bool R = appendTemplateParameters(D);
0572 if (!R)
0573 return;
0574
0575 if (EndedWithTemplate)
0576 OS << " ";
0577 OS << ">";
0578 EndedWithTemplate = true;
0579 Word = true;
0580 }
0581
0582 template <typename DieType>
0583 void DWARFTypePrinter<DieType>::decomposeConstVolatile(DieType &N, DieType &T,
0584 DieType &C, DieType &V) {
0585 (N.getTag() == dwarf::DW_TAG_const_type ? C : V) = N;
0586 T = detail::resolveReferencedType(N);
0587 if (T) {
0588 auto Tag = T.getTag();
0589 if (Tag == dwarf::DW_TAG_const_type) {
0590 C = T;
0591 T = detail::resolveReferencedType(T);
0592 } else if (Tag == dwarf::DW_TAG_volatile_type) {
0593 V = T;
0594 T = detail::resolveReferencedType(T);
0595 }
0596 }
0597 }
0598
0599 template <typename DieType>
0600 void DWARFTypePrinter<DieType>::appendConstVolatileQualifierAfter(DieType N) {
0601 DieType C;
0602 DieType V;
0603 DieType T;
0604 decomposeConstVolatile(N, T, C, V);
0605 if (T && T.getTag() == dwarf::DW_TAG_subroutine_type)
0606 appendSubroutineNameAfter(T, detail::resolveReferencedType(T), false,
0607 static_cast<bool>(C), static_cast<bool>(V));
0608 else
0609 appendUnqualifiedNameAfter(T, detail::resolveReferencedType(T));
0610 }
0611
0612 template <typename DieType>
0613 void DWARFTypePrinter<DieType>::appendConstVolatileQualifierBefore(DieType N) {
0614 DieType C;
0615 DieType V;
0616 DieType T;
0617 decomposeConstVolatile(N, T, C, V);
0618 bool Subroutine = T && T.getTag() == dwarf::DW_TAG_subroutine_type;
0619 DieType A = T;
0620 while (A && A.getTag() == dwarf::DW_TAG_array_type)
0621 A = detail::resolveReferencedType(A);
0622 bool Leading =
0623 (!A || (A.getTag() != dwarf::DW_TAG_pointer_type &&
0624 A.getTag() != llvm::dwarf::DW_TAG_ptr_to_member_type)) &&
0625 !Subroutine;
0626 if (Leading) {
0627 if (C)
0628 OS << "const ";
0629 if (V)
0630 OS << "volatile ";
0631 }
0632 appendQualifiedNameBefore(T);
0633 if (!Leading && !Subroutine) {
0634 Word = true;
0635 if (C)
0636 OS << "const";
0637 if (V) {
0638 if (C)
0639 OS << ' ';
0640 OS << "volatile";
0641 }
0642 }
0643 }
0644
0645 template <typename DieType>
0646 void DWARFTypePrinter<DieType>::appendUnqualifiedName(
0647 DieType D, std::string *OriginalFullName) {
0648
0649
0650 DieType Inner = appendUnqualifiedNameBefore(D, OriginalFullName);
0651 appendUnqualifiedNameAfter(D, Inner);
0652 }
0653
0654 template <typename DieType>
0655 void DWARFTypePrinter<DieType>::appendSubroutineNameAfter(
0656 DieType D, DieType Inner, bool SkipFirstParamIfArtificial, bool Const,
0657 bool Volatile) {
0658 DieType FirstParamIfArtificial;
0659 OS << '(';
0660 EndedWithTemplate = false;
0661 bool First = true;
0662 bool RealFirst = true;
0663 for (DieType P : D) {
0664 if (P.getTag() != dwarf::DW_TAG_formal_parameter &&
0665 P.getTag() != dwarf::DW_TAG_unspecified_parameters)
0666 return;
0667 DieType T = detail::resolveReferencedType(P);
0668 if (SkipFirstParamIfArtificial && RealFirst &&
0669 P.find(dwarf::DW_AT_artificial)) {
0670 FirstParamIfArtificial = T;
0671 RealFirst = false;
0672 continue;
0673 }
0674 if (!First) {
0675 OS << ", ";
0676 }
0677 First = false;
0678 if (P.getTag() == dwarf::DW_TAG_unspecified_parameters)
0679 OS << "...";
0680 else
0681 appendQualifiedName(T);
0682 }
0683 EndedWithTemplate = false;
0684 OS << ')';
0685 if (FirstParamIfArtificial) {
0686 if (DieType P = FirstParamIfArtificial) {
0687 if (P.getTag() == dwarf::DW_TAG_pointer_type) {
0688 auto CVStep = [&](DieType CV) {
0689 if (DieType U = detail::resolveReferencedType(CV)) {
0690 Const |= U.getTag() == dwarf::DW_TAG_const_type;
0691 Volatile |= U.getTag() == dwarf::DW_TAG_volatile_type;
0692 return U;
0693 }
0694 return DieType();
0695 };
0696 if (DieType CV = CVStep(P)) {
0697 CVStep(CV);
0698 }
0699 }
0700 }
0701 }
0702
0703 if (auto CC = D.find(dwarf::DW_AT_calling_convention)) {
0704 switch (*CC->getAsUnsignedConstant()) {
0705 case dwarf::CallingConvention::DW_CC_BORLAND_stdcall:
0706 OS << " __attribute__((stdcall))";
0707 break;
0708 case dwarf::CallingConvention::DW_CC_BORLAND_msfastcall:
0709 OS << " __attribute__((fastcall))";
0710 break;
0711 case dwarf::CallingConvention::DW_CC_BORLAND_thiscall:
0712 OS << " __attribute__((thiscall))";
0713 break;
0714 case dwarf::CallingConvention::DW_CC_LLVM_vectorcall:
0715 OS << " __attribute__((vectorcall))";
0716 break;
0717 case dwarf::CallingConvention::DW_CC_BORLAND_pascal:
0718 OS << " __attribute__((pascal))";
0719 break;
0720 case dwarf::CallingConvention::DW_CC_LLVM_Win64:
0721 OS << " __attribute__((ms_abi))";
0722 break;
0723 case dwarf::CallingConvention::DW_CC_LLVM_X86_64SysV:
0724 OS << " __attribute__((sysv_abi))";
0725 break;
0726 case dwarf::CallingConvention::DW_CC_LLVM_AAPCS:
0727
0728 OS << " __attribute__((pcs(\"aapcs\")))";
0729 break;
0730 case dwarf::CallingConvention::DW_CC_LLVM_AAPCS_VFP:
0731 OS << " __attribute__((pcs(\"aapcs-vfp\")))";
0732 break;
0733 case dwarf::CallingConvention::DW_CC_LLVM_IntelOclBicc:
0734 OS << " __attribute__((intel_ocl_bicc))";
0735 break;
0736 case dwarf::CallingConvention::DW_CC_LLVM_SpirFunction:
0737 case dwarf::CallingConvention::DW_CC_LLVM_OpenCLKernel:
0738
0739
0740
0741
0742
0743 break;
0744 case dwarf::CallingConvention::DW_CC_LLVM_Swift:
0745
0746 OS << " __attribute__((swiftcall))";
0747 break;
0748 case dwarf::CallingConvention::DW_CC_LLVM_PreserveMost:
0749 OS << " __attribute__((preserve_most))";
0750 break;
0751 case dwarf::CallingConvention::DW_CC_LLVM_PreserveAll:
0752 OS << " __attribute__((preserve_all))";
0753 break;
0754 case dwarf::CallingConvention::DW_CC_LLVM_PreserveNone:
0755 OS << " __attribute__((preserve_none))";
0756 break;
0757 case dwarf::CallingConvention::DW_CC_LLVM_X86RegCall:
0758 OS << " __attribute__((regcall))";
0759 break;
0760 case dwarf::CallingConvention::DW_CC_LLVM_M68kRTD:
0761 OS << " __attribute__((m68k_rtd))";
0762 break;
0763 }
0764 }
0765
0766 if (Const)
0767 OS << " const";
0768 if (Volatile)
0769 OS << " volatile";
0770 if (D.find(dwarf::DW_AT_reference))
0771 OS << " &";
0772 if (D.find(dwarf::DW_AT_rvalue_reference))
0773 OS << " &&";
0774
0775 appendUnqualifiedNameAfter(Inner, detail::resolveReferencedType(Inner));
0776 }
0777
0778 template <typename DieType>
0779 void DWARFTypePrinter<DieType>::appendScopes(DieType D) {
0780 if (D.getTag() == dwarf::DW_TAG_compile_unit)
0781 return;
0782 if (D.getTag() == dwarf::DW_TAG_type_unit)
0783 return;
0784 if (D.getTag() == dwarf::DW_TAG_skeleton_unit)
0785 return;
0786 if (D.getTag() == dwarf::DW_TAG_subprogram)
0787 return;
0788 if (D.getTag() == dwarf::DW_TAG_lexical_block)
0789 return;
0790 D = D.resolveTypeUnitReference();
0791 if (DieType P = D.getParent())
0792 appendScopes(P);
0793 appendUnqualifiedName(D);
0794 OS << "::";
0795 }
0796 }
0797
0798 #endif