2828 lines · cpp
1//===- TypePrinter.cpp - Pretty-Print Clang Types -------------------------===//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-exception6//7//===----------------------------------------------------------------------===//8//9// This contains code to print types from Clang's type system.10//11//===----------------------------------------------------------------------===//12 13#include "clang/AST/ASTContext.h"14#include "clang/AST/Attr.h"15#include "clang/AST/Decl.h"16#include "clang/AST/DeclBase.h"17#include "clang/AST/DeclCXX.h"18#include "clang/AST/DeclObjC.h"19#include "clang/AST/DeclTemplate.h"20#include "clang/AST/Expr.h"21#include "clang/AST/NestedNameSpecifier.h"22#include "clang/AST/PrettyPrinter.h"23#include "clang/AST/TemplateBase.h"24#include "clang/AST/TemplateName.h"25#include "clang/AST/Type.h"26#include "clang/Basic/AddressSpaces.h"27#include "clang/Basic/AttrKinds.h"28#include "clang/Basic/ExceptionSpecificationType.h"29#include "clang/Basic/IdentifierTable.h"30#include "clang/Basic/LLVM.h"31#include "clang/Basic/LangOptions.h"32#include "clang/Basic/SourceLocation.h"33#include "clang/Basic/SourceManager.h"34#include "clang/Basic/Specifiers.h"35#include "llvm/ADT/ArrayRef.h"36#include "llvm/ADT/DenseMap.h"37#include "llvm/ADT/SmallString.h"38#include "llvm/ADT/StringRef.h"39#include "llvm/ADT/Twine.h"40#include "llvm/Support/Compiler.h"41#include "llvm/Support/ErrorHandling.h"42#include "llvm/Support/SaveAndRestore.h"43#include "llvm/Support/raw_ostream.h"44#include <cassert>45#include <string>46 47using namespace clang;48 49namespace {50 51/// RAII object that enables printing of the ARC __strong lifetime52/// qualifier.53class IncludeStrongLifetimeRAII {54 PrintingPolicy &Policy;55 bool Old;56 57public:58 explicit IncludeStrongLifetimeRAII(PrintingPolicy &Policy)59 : Policy(Policy), Old(Policy.SuppressStrongLifetime) {60 if (!Policy.SuppressLifetimeQualifiers)61 Policy.SuppressStrongLifetime = false;62 }63 64 ~IncludeStrongLifetimeRAII() { Policy.SuppressStrongLifetime = Old; }65};66 67class ParamPolicyRAII {68 PrintingPolicy &Policy;69 bool Old;70 71public:72 explicit ParamPolicyRAII(PrintingPolicy &Policy)73 : Policy(Policy), Old(Policy.SuppressSpecifiers) {74 Policy.SuppressSpecifiers = false;75 }76 77 ~ParamPolicyRAII() { Policy.SuppressSpecifiers = Old; }78};79 80class DefaultTemplateArgsPolicyRAII {81 PrintingPolicy &Policy;82 bool Old;83 84public:85 explicit DefaultTemplateArgsPolicyRAII(PrintingPolicy &Policy)86 : Policy(Policy), Old(Policy.SuppressDefaultTemplateArgs) {87 Policy.SuppressDefaultTemplateArgs = false;88 }89 90 ~DefaultTemplateArgsPolicyRAII() { Policy.SuppressDefaultTemplateArgs = Old; }91};92 93class ElaboratedTypePolicyRAII {94 PrintingPolicy &Policy;95 bool SuppressTagKeyword;96 bool SuppressScope;97 98public:99 explicit ElaboratedTypePolicyRAII(PrintingPolicy &Policy) : Policy(Policy) {100 SuppressTagKeyword = Policy.SuppressTagKeyword;101 SuppressScope = Policy.SuppressScope;102 Policy.SuppressTagKeyword = true;103 Policy.SuppressScope = true;104 }105 106 ~ElaboratedTypePolicyRAII() {107 Policy.SuppressTagKeyword = SuppressTagKeyword;108 Policy.SuppressScope = SuppressScope;109 }110};111 112class TypePrinter {113 PrintingPolicy Policy;114 unsigned Indentation;115 bool HasEmptyPlaceHolder = false;116 bool InsideCCAttribute = false;117 118public:119 explicit TypePrinter(const PrintingPolicy &Policy, unsigned Indentation = 0)120 : Policy(Policy), Indentation(Indentation) {}121 122 void print(const Type *ty, Qualifiers qs, raw_ostream &OS,123 StringRef PlaceHolder);124 void print(QualType T, raw_ostream &OS, StringRef PlaceHolder);125 126 static bool canPrefixQualifiers(const Type *T, bool &NeedARCStrongQualifier);127 void spaceBeforePlaceHolder(raw_ostream &OS);128 void printTypeSpec(NamedDecl *D, raw_ostream &OS);129 void printTemplateId(const TemplateSpecializationType *T, raw_ostream &OS,130 bool FullyQualify);131 132 void printBefore(QualType T, raw_ostream &OS);133 void printAfter(QualType T, raw_ostream &OS);134 void printTagType(const TagType *T, raw_ostream &OS);135 void printFunctionAfter(const FunctionType::ExtInfo &Info, raw_ostream &OS);136#define ABSTRACT_TYPE(CLASS, PARENT)137#define TYPE(CLASS, PARENT) \138 void print##CLASS##Before(const CLASS##Type *T, raw_ostream &OS); \139 void print##CLASS##After(const CLASS##Type *T, raw_ostream &OS);140#include "clang/AST/TypeNodes.inc"141 142private:143 void printBefore(const Type *ty, Qualifiers qs, raw_ostream &OS);144 void printAfter(const Type *ty, Qualifiers qs, raw_ostream &OS);145};146 147} // namespace148 149static void AppendTypeQualList(raw_ostream &OS, unsigned TypeQuals,150 bool HasRestrictKeyword) {151 bool appendSpace = false;152 if (TypeQuals & Qualifiers::Const) {153 OS << "const";154 appendSpace = true;155 }156 if (TypeQuals & Qualifiers::Volatile) {157 if (appendSpace) OS << ' ';158 OS << "volatile";159 appendSpace = true;160 }161 if (TypeQuals & Qualifiers::Restrict) {162 if (appendSpace) OS << ' ';163 if (HasRestrictKeyword) {164 OS << "restrict";165 } else {166 OS << "__restrict";167 }168 }169}170 171void TypePrinter::spaceBeforePlaceHolder(raw_ostream &OS) {172 if (!HasEmptyPlaceHolder)173 OS << ' ';174}175 176static SplitQualType splitAccordingToPolicy(QualType QT,177 const PrintingPolicy &Policy) {178 if (Policy.PrintAsCanonical)179 QT = QT.getCanonicalType();180 return QT.split();181}182 183void TypePrinter::print(QualType t, raw_ostream &OS, StringRef PlaceHolder) {184 SplitQualType split = splitAccordingToPolicy(t, Policy);185 print(split.Ty, split.Quals, OS, PlaceHolder);186}187 188void TypePrinter::print(const Type *T, Qualifiers Quals, raw_ostream &OS,189 StringRef PlaceHolder) {190 if (!T) {191 OS << "NULL TYPE";192 return;193 }194 195 SaveAndRestore PHVal(HasEmptyPlaceHolder, PlaceHolder.empty());196 197 printBefore(T, Quals, OS);198 OS << PlaceHolder;199 printAfter(T, Quals, OS);200}201 202bool TypePrinter::canPrefixQualifiers(const Type *T,203 bool &NeedARCStrongQualifier) {204 // CanPrefixQualifiers - We prefer to print type qualifiers before the type,205 // so that we get "const int" instead of "int const", but we can't do this if206 // the type is complex. For example if the type is "int*", we *must* print207 // "int * const", printing "const int *" is different. Only do this when the208 // type expands to a simple string.209 bool CanPrefixQualifiers = false;210 NeedARCStrongQualifier = false;211 const Type *UnderlyingType = T;212 if (const auto *AT = dyn_cast<AutoType>(T))213 UnderlyingType = AT->desugar().getTypePtr();214 if (const auto *Subst = dyn_cast<SubstTemplateTypeParmType>(T))215 UnderlyingType = Subst->getReplacementType().getTypePtr();216 Type::TypeClass TC = UnderlyingType->getTypeClass();217 218 switch (TC) {219 case Type::Auto:220 case Type::Builtin:221 case Type::Complex:222 case Type::UnresolvedUsing:223 case Type::Using:224 case Type::Typedef:225 case Type::TypeOfExpr:226 case Type::TypeOf:227 case Type::Decltype:228 case Type::UnaryTransform:229 case Type::Record:230 case Type::Enum:231 case Type::TemplateTypeParm:232 case Type::SubstTemplateTypeParmPack:233 case Type::SubstBuiltinTemplatePack:234 case Type::DeducedTemplateSpecialization:235 case Type::TemplateSpecialization:236 case Type::InjectedClassName:237 case Type::DependentName:238 case Type::ObjCObject:239 case Type::ObjCTypeParam:240 case Type::ObjCInterface:241 case Type::Atomic:242 case Type::Pipe:243 case Type::BitInt:244 case Type::DependentBitInt:245 case Type::BTFTagAttributed:246 case Type::HLSLAttributedResource:247 case Type::HLSLInlineSpirv:248 case Type::PredefinedSugar:249 CanPrefixQualifiers = true;250 break;251 252 case Type::ObjCObjectPointer:253 CanPrefixQualifiers = T->isObjCIdType() || T->isObjCClassType() ||254 T->isObjCQualifiedIdType() || T->isObjCQualifiedClassType();255 break;256 257 case Type::VariableArray:258 case Type::DependentSizedArray:259 NeedARCStrongQualifier = true;260 [[fallthrough]];261 262 case Type::ConstantArray:263 case Type::IncompleteArray:264 return canPrefixQualifiers(265 cast<ArrayType>(UnderlyingType)->getElementType().getTypePtr(),266 NeedARCStrongQualifier);267 268 case Type::Adjusted:269 case Type::Decayed:270 case Type::ArrayParameter:271 case Type::Pointer:272 case Type::BlockPointer:273 case Type::LValueReference:274 case Type::RValueReference:275 case Type::MemberPointer:276 case Type::DependentAddressSpace:277 case Type::DependentVector:278 case Type::DependentSizedExtVector:279 case Type::Vector:280 case Type::ExtVector:281 case Type::ConstantMatrix:282 case Type::DependentSizedMatrix:283 case Type::FunctionProto:284 case Type::FunctionNoProto:285 case Type::Paren:286 case Type::PackExpansion:287 case Type::SubstTemplateTypeParm:288 case Type::MacroQualified:289 case Type::CountAttributed:290 CanPrefixQualifiers = false;291 break;292 293 case Type::Attributed: {294 // We still want to print the address_space before the type if it is an295 // address_space attribute.296 const auto *AttrTy = cast<AttributedType>(UnderlyingType);297 CanPrefixQualifiers = AttrTy->getAttrKind() == attr::AddressSpace;298 break;299 }300 case Type::PackIndexing: {301 return canPrefixQualifiers(302 cast<PackIndexingType>(UnderlyingType)->getPattern().getTypePtr(),303 NeedARCStrongQualifier);304 }305 }306 307 return CanPrefixQualifiers;308}309 310void TypePrinter::printBefore(QualType T, raw_ostream &OS) {311 SplitQualType Split = splitAccordingToPolicy(T, Policy);312 313 // If we have cv1 T, where T is substituted for cv2 U, only print cv1 - cv2314 // at this level.315 Qualifiers Quals = Split.Quals;316 if (const auto *Subst = dyn_cast<SubstTemplateTypeParmType>(Split.Ty))317 Quals -= QualType(Subst, 0).getQualifiers();318 319 printBefore(Split.Ty, Quals, OS);320}321 322/// Prints the part of the type string before an identifier, e.g. for323/// "int foo[10]" it prints "int ".324void TypePrinter::printBefore(const Type *T,Qualifiers Quals, raw_ostream &OS) {325 if (Policy.SuppressSpecifiers && T->isSpecifierType())326 return;327 328 SaveAndRestore PrevPHIsEmpty(HasEmptyPlaceHolder);329 330 // Print qualifiers as appropriate.331 332 bool CanPrefixQualifiers = false;333 bool NeedARCStrongQualifier = false;334 CanPrefixQualifiers = canPrefixQualifiers(T, NeedARCStrongQualifier);335 336 if (CanPrefixQualifiers && !Quals.empty()) {337 if (NeedARCStrongQualifier) {338 IncludeStrongLifetimeRAII Strong(Policy);339 Quals.print(OS, Policy, /*appendSpaceIfNonEmpty=*/true);340 } else {341 Quals.print(OS, Policy, /*appendSpaceIfNonEmpty=*/true);342 }343 }344 345 bool hasAfterQuals = false;346 if (!CanPrefixQualifiers && !Quals.empty()) {347 hasAfterQuals = !Quals.isEmptyWhenPrinted(Policy);348 if (hasAfterQuals)349 HasEmptyPlaceHolder = false;350 }351 352 switch (T->getTypeClass()) {353#define ABSTRACT_TYPE(CLASS, PARENT)354#define TYPE(CLASS, PARENT) case Type::CLASS: \355 print##CLASS##Before(cast<CLASS##Type>(T), OS); \356 break;357#include "clang/AST/TypeNodes.inc"358 }359 360 if (hasAfterQuals) {361 if (NeedARCStrongQualifier) {362 IncludeStrongLifetimeRAII Strong(Policy);363 Quals.print(OS, Policy, /*appendSpaceIfNonEmpty=*/!PrevPHIsEmpty.get());364 } else {365 Quals.print(OS, Policy, /*appendSpaceIfNonEmpty=*/!PrevPHIsEmpty.get());366 }367 }368}369 370void TypePrinter::printAfter(QualType t, raw_ostream &OS) {371 SplitQualType split = splitAccordingToPolicy(t, Policy);372 printAfter(split.Ty, split.Quals, OS);373}374 375/// Prints the part of the type string after an identifier, e.g. for376/// "int foo[10]" it prints "[10]".377void TypePrinter::printAfter(const Type *T, Qualifiers Quals, raw_ostream &OS) {378 switch (T->getTypeClass()) {379#define ABSTRACT_TYPE(CLASS, PARENT)380#define TYPE(CLASS, PARENT) case Type::CLASS: \381 print##CLASS##After(cast<CLASS##Type>(T), OS); \382 break;383#include "clang/AST/TypeNodes.inc"384 }385}386 387void TypePrinter::printBuiltinBefore(const BuiltinType *T, raw_ostream &OS) {388 OS << T->getName(Policy);389 spaceBeforePlaceHolder(OS);390}391 392void TypePrinter::printBuiltinAfter(const BuiltinType *T, raw_ostream &OS) {}393 394void TypePrinter::printComplexBefore(const ComplexType *T, raw_ostream &OS) {395 OS << "_Complex ";396 printBefore(T->getElementType(), OS);397}398 399void TypePrinter::printComplexAfter(const ComplexType *T, raw_ostream &OS) {400 printAfter(T->getElementType(), OS);401}402 403void TypePrinter::printPointerBefore(const PointerType *T, raw_ostream &OS) {404 IncludeStrongLifetimeRAII Strong(Policy);405 SaveAndRestore NonEmptyPH(HasEmptyPlaceHolder, false);406 printBefore(T->getPointeeType(), OS);407 // Handle things like 'int (*A)[4];' correctly.408 // FIXME: this should include vectors, but vectors use attributes I guess.409 if (isa<ArrayType>(T->getPointeeType()))410 OS << '(';411 OS << '*';412}413 414void TypePrinter::printPointerAfter(const PointerType *T, raw_ostream &OS) {415 IncludeStrongLifetimeRAII Strong(Policy);416 SaveAndRestore NonEmptyPH(HasEmptyPlaceHolder, false);417 // Handle things like 'int (*A)[4];' correctly.418 // FIXME: this should include vectors, but vectors use attributes I guess.419 if (isa<ArrayType>(T->getPointeeType()))420 OS << ')';421 printAfter(T->getPointeeType(), OS);422}423 424void TypePrinter::printBlockPointerBefore(const BlockPointerType *T,425 raw_ostream &OS) {426 SaveAndRestore NonEmptyPH(HasEmptyPlaceHolder, false);427 printBefore(T->getPointeeType(), OS);428 OS << '^';429}430 431void TypePrinter::printBlockPointerAfter(const BlockPointerType *T,432 raw_ostream &OS) {433 SaveAndRestore NonEmptyPH(HasEmptyPlaceHolder, false);434 printAfter(T->getPointeeType(), OS);435}436 437// When printing a reference, the referenced type might also be a reference.438// If so, we want to skip that before printing the inner type.439static QualType skipTopLevelReferences(QualType T) {440 if (auto *Ref = T->getAs<ReferenceType>())441 return skipTopLevelReferences(Ref->getPointeeTypeAsWritten());442 return T;443}444 445void TypePrinter::printLValueReferenceBefore(const LValueReferenceType *T,446 raw_ostream &OS) {447 IncludeStrongLifetimeRAII Strong(Policy);448 SaveAndRestore NonEmptyPH(HasEmptyPlaceHolder, false);449 QualType Inner = skipTopLevelReferences(T->getPointeeTypeAsWritten());450 printBefore(Inner, OS);451 // Handle things like 'int (&A)[4];' correctly.452 // FIXME: this should include vectors, but vectors use attributes I guess.453 if (isa<ArrayType>(Inner))454 OS << '(';455 OS << '&';456}457 458void TypePrinter::printLValueReferenceAfter(const LValueReferenceType *T,459 raw_ostream &OS) {460 IncludeStrongLifetimeRAII Strong(Policy);461 SaveAndRestore NonEmptyPH(HasEmptyPlaceHolder, false);462 QualType Inner = skipTopLevelReferences(T->getPointeeTypeAsWritten());463 // Handle things like 'int (&A)[4];' correctly.464 // FIXME: this should include vectors, but vectors use attributes I guess.465 if (isa<ArrayType>(Inner))466 OS << ')';467 printAfter(Inner, OS);468}469 470void TypePrinter::printRValueReferenceBefore(const RValueReferenceType *T,471 raw_ostream &OS) {472 IncludeStrongLifetimeRAII Strong(Policy);473 SaveAndRestore NonEmptyPH(HasEmptyPlaceHolder, false);474 QualType Inner = skipTopLevelReferences(T->getPointeeTypeAsWritten());475 printBefore(Inner, OS);476 // Handle things like 'int (&&A)[4];' correctly.477 // FIXME: this should include vectors, but vectors use attributes I guess.478 if (isa<ArrayType>(Inner))479 OS << '(';480 OS << "&&";481}482 483void TypePrinter::printRValueReferenceAfter(const RValueReferenceType *T,484 raw_ostream &OS) {485 IncludeStrongLifetimeRAII Strong(Policy);486 SaveAndRestore NonEmptyPH(HasEmptyPlaceHolder, false);487 QualType Inner = skipTopLevelReferences(T->getPointeeTypeAsWritten());488 // Handle things like 'int (&&A)[4];' correctly.489 // FIXME: this should include vectors, but vectors use attributes I guess.490 if (isa<ArrayType>(Inner))491 OS << ')';492 printAfter(Inner, OS);493}494 495void TypePrinter::printMemberPointerBefore(const MemberPointerType *T,496 raw_ostream &OS) {497 IncludeStrongLifetimeRAII Strong(Policy);498 SaveAndRestore NonEmptyPH(HasEmptyPlaceHolder, false);499 printBefore(T->getPointeeType(), OS);500 // Handle things like 'int (Cls::*A)[4];' correctly.501 // FIXME: this should include vectors, but vectors use attributes I guess.502 if (isa<ArrayType>(T->getPointeeType()))503 OS << '(';504 T->getQualifier().print(OS, Policy);505 OS << "*";506}507 508void TypePrinter::printMemberPointerAfter(const MemberPointerType *T,509 raw_ostream &OS) {510 IncludeStrongLifetimeRAII Strong(Policy);511 SaveAndRestore NonEmptyPH(HasEmptyPlaceHolder, false);512 // Handle things like 'int (Cls::*A)[4];' correctly.513 // FIXME: this should include vectors, but vectors use attributes I guess.514 if (isa<ArrayType>(T->getPointeeType()))515 OS << ')';516 printAfter(T->getPointeeType(), OS);517}518 519void TypePrinter::printConstantArrayBefore(const ConstantArrayType *T,520 raw_ostream &OS) {521 IncludeStrongLifetimeRAII Strong(Policy);522 printBefore(T->getElementType(), OS);523}524 525void TypePrinter::printConstantArrayAfter(const ConstantArrayType *T,526 raw_ostream &OS) {527 OS << '[';528 if (T->getIndexTypeQualifiers().hasQualifiers()) {529 AppendTypeQualList(OS, T->getIndexTypeCVRQualifiers(),530 Policy.Restrict);531 OS << ' ';532 }533 534 if (T->getSizeModifier() == ArraySizeModifier::Static)535 OS << "static ";536 537 OS << T->getZExtSize() << ']';538 printAfter(T->getElementType(), OS);539}540 541void TypePrinter::printIncompleteArrayBefore(const IncompleteArrayType *T,542 raw_ostream &OS) {543 IncludeStrongLifetimeRAII Strong(Policy);544 printBefore(T->getElementType(), OS);545}546 547void TypePrinter::printIncompleteArrayAfter(const IncompleteArrayType *T,548 raw_ostream &OS) {549 OS << "[]";550 printAfter(T->getElementType(), OS);551}552 553void TypePrinter::printVariableArrayBefore(const VariableArrayType *T,554 raw_ostream &OS) {555 IncludeStrongLifetimeRAII Strong(Policy);556 printBefore(T->getElementType(), OS);557}558 559void TypePrinter::printVariableArrayAfter(const VariableArrayType *T,560 raw_ostream &OS) {561 OS << '[';562 if (T->getIndexTypeQualifiers().hasQualifiers()) {563 AppendTypeQualList(OS, T->getIndexTypeCVRQualifiers(), Policy.Restrict);564 OS << ' ';565 }566 567 if (T->getSizeModifier() == ArraySizeModifier::Static)568 OS << "static ";569 else if (T->getSizeModifier() == ArraySizeModifier::Star)570 OS << '*';571 572 if (T->getSizeExpr())573 T->getSizeExpr()->printPretty(OS, nullptr, Policy);574 OS << ']';575 576 printAfter(T->getElementType(), OS);577}578 579void TypePrinter::printAdjustedBefore(const AdjustedType *T, raw_ostream &OS) {580 // Print the adjusted representation, otherwise the adjustment will be581 // invisible.582 printBefore(T->getAdjustedType(), OS);583}584 585void TypePrinter::printAdjustedAfter(const AdjustedType *T, raw_ostream &OS) {586 printAfter(T->getAdjustedType(), OS);587}588 589void TypePrinter::printDecayedBefore(const DecayedType *T, raw_ostream &OS) {590 // Print as though it's a pointer.591 printAdjustedBefore(T, OS);592}593 594void TypePrinter::printArrayParameterAfter(const ArrayParameterType *T,595 raw_ostream &OS) {596 printConstantArrayAfter(T, OS);597}598 599void TypePrinter::printArrayParameterBefore(const ArrayParameterType *T,600 raw_ostream &OS) {601 printConstantArrayBefore(T, OS);602}603 604void TypePrinter::printDecayedAfter(const DecayedType *T, raw_ostream &OS) {605 printAdjustedAfter(T, OS);606}607 608void TypePrinter::printDependentSizedArrayBefore(609 const DependentSizedArrayType *T,610 raw_ostream &OS) {611 IncludeStrongLifetimeRAII Strong(Policy);612 printBefore(T->getElementType(), OS);613}614 615void TypePrinter::printDependentSizedArrayAfter(616 const DependentSizedArrayType *T,617 raw_ostream &OS) {618 OS << '[';619 if (T->getSizeExpr())620 T->getSizeExpr()->printPretty(OS, nullptr, Policy);621 OS << ']';622 printAfter(T->getElementType(), OS);623}624 625void TypePrinter::printDependentAddressSpaceBefore(626 const DependentAddressSpaceType *T, raw_ostream &OS) {627 printBefore(T->getPointeeType(), OS);628}629 630void TypePrinter::printDependentAddressSpaceAfter(631 const DependentAddressSpaceType *T, raw_ostream &OS) {632 OS << " __attribute__((address_space(";633 if (T->getAddrSpaceExpr())634 T->getAddrSpaceExpr()->printPretty(OS, nullptr, Policy);635 OS << ")))";636 printAfter(T->getPointeeType(), OS);637}638 639void TypePrinter::printDependentSizedExtVectorBefore(640 const DependentSizedExtVectorType *T,641 raw_ostream &OS) {642 if (Policy.UseHLSLTypes)643 OS << "vector<";644 printBefore(T->getElementType(), OS);645}646 647void TypePrinter::printDependentSizedExtVectorAfter(648 const DependentSizedExtVectorType *T,649 raw_ostream &OS) {650 if (Policy.UseHLSLTypes) {651 OS << ", ";652 if (T->getSizeExpr())653 T->getSizeExpr()->printPretty(OS, nullptr, Policy);654 OS << ">";655 } else {656 OS << " __attribute__((ext_vector_type(";657 if (T->getSizeExpr())658 T->getSizeExpr()->printPretty(OS, nullptr, Policy);659 OS << ")))";660 }661 printAfter(T->getElementType(), OS);662}663 664void TypePrinter::printVectorBefore(const VectorType *T, raw_ostream &OS) {665 switch (T->getVectorKind()) {666 case VectorKind::AltiVecPixel:667 OS << "__vector __pixel ";668 break;669 case VectorKind::AltiVecBool:670 OS << "__vector __bool ";671 printBefore(T->getElementType(), OS);672 break;673 case VectorKind::AltiVecVector:674 OS << "__vector ";675 printBefore(T->getElementType(), OS);676 break;677 case VectorKind::Neon:678 OS << "__attribute__((neon_vector_type("679 << T->getNumElements() << "))) ";680 printBefore(T->getElementType(), OS);681 break;682 case VectorKind::NeonPoly:683 OS << "__attribute__((neon_polyvector_type(" <<684 T->getNumElements() << "))) ";685 printBefore(T->getElementType(), OS);686 break;687 case VectorKind::Generic: {688 // FIXME: We prefer to print the size directly here, but have no way689 // to get the size of the type.690 OS << "__attribute__((__vector_size__("691 << T->getNumElements()692 << " * sizeof(";693 print(T->getElementType(), OS, StringRef());694 OS << ")))) ";695 printBefore(T->getElementType(), OS);696 break;697 }698 case VectorKind::SveFixedLengthData:699 case VectorKind::SveFixedLengthPredicate:700 // FIXME: We prefer to print the size directly here, but have no way701 // to get the size of the type.702 OS << "__attribute__((__arm_sve_vector_bits__(";703 704 if (T->getVectorKind() == VectorKind::SveFixedLengthPredicate)705 // Predicates take a bit per byte of the vector size, multiply by 8 to706 // get the number of bits passed to the attribute.707 OS << T->getNumElements() * 8;708 else709 OS << T->getNumElements();710 711 OS << " * sizeof(";712 print(T->getElementType(), OS, StringRef());713 // Multiply by 8 for the number of bits.714 OS << ") * 8))) ";715 printBefore(T->getElementType(), OS);716 break;717 case VectorKind::RVVFixedLengthData:718 case VectorKind::RVVFixedLengthMask:719 case VectorKind::RVVFixedLengthMask_1:720 case VectorKind::RVVFixedLengthMask_2:721 case VectorKind::RVVFixedLengthMask_4:722 // FIXME: We prefer to print the size directly here, but have no way723 // to get the size of the type.724 OS << "__attribute__((__riscv_rvv_vector_bits__(";725 726 OS << T->getNumElements();727 728 OS << " * sizeof(";729 print(T->getElementType(), OS, StringRef());730 // Multiply by 8 for the number of bits.731 OS << ") * 8))) ";732 printBefore(T->getElementType(), OS);733 break;734 }735}736 737void TypePrinter::printVectorAfter(const VectorType *T, raw_ostream &OS) {738 printAfter(T->getElementType(), OS);739}740 741void TypePrinter::printDependentVectorBefore(742 const DependentVectorType *T, raw_ostream &OS) {743 switch (T->getVectorKind()) {744 case VectorKind::AltiVecPixel:745 OS << "__vector __pixel ";746 break;747 case VectorKind::AltiVecBool:748 OS << "__vector __bool ";749 printBefore(T->getElementType(), OS);750 break;751 case VectorKind::AltiVecVector:752 OS << "__vector ";753 printBefore(T->getElementType(), OS);754 break;755 case VectorKind::Neon:756 OS << "__attribute__((neon_vector_type(";757 if (T->getSizeExpr())758 T->getSizeExpr()->printPretty(OS, nullptr, Policy);759 OS << "))) ";760 printBefore(T->getElementType(), OS);761 break;762 case VectorKind::NeonPoly:763 OS << "__attribute__((neon_polyvector_type(";764 if (T->getSizeExpr())765 T->getSizeExpr()->printPretty(OS, nullptr, Policy);766 OS << "))) ";767 printBefore(T->getElementType(), OS);768 break;769 case VectorKind::Generic: {770 // FIXME: We prefer to print the size directly here, but have no way771 // to get the size of the type.772 OS << "__attribute__((__vector_size__(";773 if (T->getSizeExpr())774 T->getSizeExpr()->printPretty(OS, nullptr, Policy);775 OS << " * sizeof(";776 print(T->getElementType(), OS, StringRef());777 OS << ")))) ";778 printBefore(T->getElementType(), OS);779 break;780 }781 case VectorKind::SveFixedLengthData:782 case VectorKind::SveFixedLengthPredicate:783 // FIXME: We prefer to print the size directly here, but have no way784 // to get the size of the type.785 OS << "__attribute__((__arm_sve_vector_bits__(";786 if (T->getSizeExpr()) {787 T->getSizeExpr()->printPretty(OS, nullptr, Policy);788 if (T->getVectorKind() == VectorKind::SveFixedLengthPredicate)789 // Predicates take a bit per byte of the vector size, multiply by 8 to790 // get the number of bits passed to the attribute.791 OS << " * 8";792 OS << " * sizeof(";793 print(T->getElementType(), OS, StringRef());794 // Multiply by 8 for the number of bits.795 OS << ") * 8";796 }797 OS << "))) ";798 printBefore(T->getElementType(), OS);799 break;800 case VectorKind::RVVFixedLengthData:801 case VectorKind::RVVFixedLengthMask:802 case VectorKind::RVVFixedLengthMask_1:803 case VectorKind::RVVFixedLengthMask_2:804 case VectorKind::RVVFixedLengthMask_4:805 // FIXME: We prefer to print the size directly here, but have no way806 // to get the size of the type.807 OS << "__attribute__((__riscv_rvv_vector_bits__(";808 if (T->getSizeExpr()) {809 T->getSizeExpr()->printPretty(OS, nullptr, Policy);810 OS << " * sizeof(";811 print(T->getElementType(), OS, StringRef());812 // Multiply by 8 for the number of bits.813 OS << ") * 8";814 }815 OS << "))) ";816 printBefore(T->getElementType(), OS);817 break;818 }819}820 821void TypePrinter::printDependentVectorAfter(822 const DependentVectorType *T, raw_ostream &OS) {823 printAfter(T->getElementType(), OS);824}825 826void TypePrinter::printExtVectorBefore(const ExtVectorType *T,827 raw_ostream &OS) {828 if (Policy.UseHLSLTypes)829 OS << "vector<";830 printBefore(T->getElementType(), OS);831}832 833void TypePrinter::printExtVectorAfter(const ExtVectorType *T, raw_ostream &OS) {834 printAfter(T->getElementType(), OS);835 836 if (Policy.UseHLSLTypes) {837 OS << ", ";838 OS << T->getNumElements();839 OS << ">";840 } else {841 OS << " __attribute__((ext_vector_type(";842 OS << T->getNumElements();843 OS << ")))";844 }845}846 847static void printDims(const ConstantMatrixType *T, raw_ostream &OS) {848 OS << T->getNumRows() << ", " << T->getNumColumns();849}850 851static void printHLSLMatrixBefore(TypePrinter &TP, const ConstantMatrixType *T,852 raw_ostream &OS) {853 OS << "matrix<";854 TP.printBefore(T->getElementType(), OS);855}856 857static void printHLSLMatrixAfter(const ConstantMatrixType *T, raw_ostream &OS) {858 OS << ", ";859 printDims(T, OS);860 OS << ">";861}862 863static void printClangMatrixBefore(TypePrinter &TP, const ConstantMatrixType *T,864 raw_ostream &OS) {865 TP.printBefore(T->getElementType(), OS);866 OS << " __attribute__((matrix_type(";867 printDims(T, OS);868 OS << ")))";869}870 871void TypePrinter::printConstantMatrixBefore(const ConstantMatrixType *T,872 raw_ostream &OS) {873 if (Policy.UseHLSLTypes) {874 printHLSLMatrixBefore(*this, T, OS);875 return;876 }877 printClangMatrixBefore(*this, T, OS);878}879 880void TypePrinter::printConstantMatrixAfter(const ConstantMatrixType *T,881 raw_ostream &OS) {882 if (Policy.UseHLSLTypes) {883 printHLSLMatrixAfter(T, OS);884 return;885 }886 printAfter(T->getElementType(), OS);887}888 889void TypePrinter::printDependentSizedMatrixBefore(890 const DependentSizedMatrixType *T, raw_ostream &OS) {891 printBefore(T->getElementType(), OS);892 OS << " __attribute__((matrix_type(";893 if (T->getRowExpr()) {894 T->getRowExpr()->printPretty(OS, nullptr, Policy);895 }896 OS << ", ";897 if (T->getColumnExpr()) {898 T->getColumnExpr()->printPretty(OS, nullptr, Policy);899 }900 OS << ")))";901}902 903void TypePrinter::printDependentSizedMatrixAfter(904 const DependentSizedMatrixType *T, raw_ostream &OS) {905 printAfter(T->getElementType(), OS);906}907 908void909FunctionProtoType::printExceptionSpecification(raw_ostream &OS,910 const PrintingPolicy &Policy)911 const {912 if (hasDynamicExceptionSpec()) {913 OS << " throw(";914 if (getExceptionSpecType() == EST_MSAny)915 OS << "...";916 else917 for (unsigned I = 0, N = getNumExceptions(); I != N; ++I) {918 if (I)919 OS << ", ";920 921 OS << getExceptionType(I).stream(Policy);922 }923 OS << ')';924 } else if (EST_NoThrow == getExceptionSpecType()) {925 OS << " __attribute__((nothrow))";926 } else if (isNoexceptExceptionSpec(getExceptionSpecType())) {927 OS << " noexcept";928 // FIXME:Is it useful to print out the expression for a non-dependent929 // noexcept specification?930 if (isComputedNoexcept(getExceptionSpecType())) {931 OS << '(';932 if (getNoexceptExpr())933 getNoexceptExpr()->printPretty(OS, nullptr, Policy);934 OS << ')';935 }936 }937}938 939void TypePrinter::printFunctionProtoBefore(const FunctionProtoType *T,940 raw_ostream &OS) {941 if (T->hasTrailingReturn()) {942 OS << "auto ";943 if (!HasEmptyPlaceHolder)944 OS << '(';945 } else {946 // If needed for precedence reasons, wrap the inner part in grouping parens.947 SaveAndRestore PrevPHIsEmpty(HasEmptyPlaceHolder, false);948 printBefore(T->getReturnType(), OS);949 if (!PrevPHIsEmpty.get())950 OS << '(';951 }952}953 954StringRef clang::getParameterABISpelling(ParameterABI ABI) {955 switch (ABI) {956 case ParameterABI::Ordinary:957 llvm_unreachable("asking for spelling of ordinary parameter ABI");958 case ParameterABI::SwiftContext:959 return "swift_context";960 case ParameterABI::SwiftAsyncContext:961 return "swift_async_context";962 case ParameterABI::SwiftErrorResult:963 return "swift_error_result";964 case ParameterABI::SwiftIndirectResult:965 return "swift_indirect_result";966 case ParameterABI::HLSLOut:967 return "out";968 case ParameterABI::HLSLInOut:969 return "inout";970 }971 llvm_unreachable("bad parameter ABI kind");972}973 974void TypePrinter::printFunctionProtoAfter(const FunctionProtoType *T,975 raw_ostream &OS) {976 // If needed for precedence reasons, wrap the inner part in grouping parens.977 if (!HasEmptyPlaceHolder)978 OS << ')';979 SaveAndRestore NonEmptyPH(HasEmptyPlaceHolder, false);980 981 OS << '(';982 {983 ParamPolicyRAII ParamPolicy(Policy);984 for (unsigned i = 0, e = T->getNumParams(); i != e; ++i) {985 if (i) OS << ", ";986 987 auto EPI = T->getExtParameterInfo(i);988 if (EPI.isConsumed()) OS << "__attribute__((ns_consumed)) ";989 if (EPI.isNoEscape())990 OS << "__attribute__((noescape)) ";991 auto ABI = EPI.getABI();992 if (ABI == ParameterABI::HLSLInOut || ABI == ParameterABI::HLSLOut) {993 OS << getParameterABISpelling(ABI) << " ";994 if (Policy.UseHLSLTypes) {995 // This is a bit of a hack because we _do_ use reference types in the996 // AST for representing inout and out parameters so that code997 // generation is sane, but when re-printing these for HLSL we need to998 // skip the reference.999 print(T->getParamType(i).getNonReferenceType(), OS, StringRef());1000 continue;1001 }1002 } else if (ABI != ParameterABI::Ordinary)1003 OS << "__attribute__((" << getParameterABISpelling(ABI) << ")) ";1004 1005 print(T->getParamType(i), OS, StringRef());1006 }1007 }1008 1009 if (T->isVariadic()) {1010 if (T->getNumParams())1011 OS << ", ";1012 OS << "...";1013 } else if (T->getNumParams() == 0 && Policy.UseVoidForZeroParams) {1014 // Do not emit int() if we have a proto, emit 'int(void)'.1015 OS << "void";1016 }1017 1018 OS << ')';1019 1020 FunctionType::ExtInfo Info = T->getExtInfo();1021 unsigned SMEBits = T->getAArch64SMEAttributes();1022 1023 if (SMEBits & FunctionType::SME_PStateSMCompatibleMask)1024 OS << " __arm_streaming_compatible";1025 if (SMEBits & FunctionType::SME_PStateSMEnabledMask)1026 OS << " __arm_streaming";1027 if (SMEBits & FunctionType::SME_AgnosticZAStateMask)1028 OS << "__arm_agnostic(\"sme_za_state\")";1029 if (FunctionType::getArmZAState(SMEBits) == FunctionType::ARM_Preserves)1030 OS << " __arm_preserves(\"za\")";1031 if (FunctionType::getArmZAState(SMEBits) == FunctionType::ARM_In)1032 OS << " __arm_in(\"za\")";1033 if (FunctionType::getArmZAState(SMEBits) == FunctionType::ARM_Out)1034 OS << " __arm_out(\"za\")";1035 if (FunctionType::getArmZAState(SMEBits) == FunctionType::ARM_InOut)1036 OS << " __arm_inout(\"za\")";1037 if (FunctionType::getArmZT0State(SMEBits) == FunctionType::ARM_Preserves)1038 OS << " __arm_preserves(\"zt0\")";1039 if (FunctionType::getArmZT0State(SMEBits) == FunctionType::ARM_In)1040 OS << " __arm_in(\"zt0\")";1041 if (FunctionType::getArmZT0State(SMEBits) == FunctionType::ARM_Out)1042 OS << " __arm_out(\"zt0\")";1043 if (FunctionType::getArmZT0State(SMEBits) == FunctionType::ARM_InOut)1044 OS << " __arm_inout(\"zt0\")";1045 1046 printFunctionAfter(Info, OS);1047 1048 if (!T->getMethodQuals().empty())1049 OS << " " << T->getMethodQuals().getAsString();1050 1051 switch (T->getRefQualifier()) {1052 case RQ_None:1053 break;1054 1055 case RQ_LValue:1056 OS << " &";1057 break;1058 1059 case RQ_RValue:1060 OS << " &&";1061 break;1062 }1063 T->printExceptionSpecification(OS, Policy);1064 1065 const FunctionEffectsRef FX = T->getFunctionEffects();1066 for (const auto &CFE : FX) {1067 OS << " __attribute__((" << CFE.Effect.name();1068 if (const Expr *E = CFE.Cond.getCondition()) {1069 OS << '(';1070 E->printPretty(OS, nullptr, Policy);1071 OS << ')';1072 }1073 OS << "))";1074 }1075 1076 if (T->hasCFIUncheckedCallee())1077 OS << " __attribute__((cfi_unchecked_callee))";1078 1079 if (T->hasTrailingReturn()) {1080 OS << " -> ";1081 print(T->getReturnType(), OS, StringRef());1082 } else1083 printAfter(T->getReturnType(), OS);1084}1085 1086void TypePrinter::printFunctionAfter(const FunctionType::ExtInfo &Info,1087 raw_ostream &OS) {1088 if (!InsideCCAttribute) {1089 switch (Info.getCC()) {1090 case CC_C:1091 // The C calling convention is the default on the vast majority of platforms1092 // we support. If the user wrote it explicitly, it will usually be printed1093 // while traversing the AttributedType. If the type has been desugared, let1094 // the canonical spelling be the implicit calling convention.1095 // FIXME: It would be better to be explicit in certain contexts, such as a1096 // cdecl function typedef used to declare a member function with the1097 // Microsoft C++ ABI.1098 break;1099 case CC_X86StdCall:1100 OS << " __attribute__((stdcall))";1101 break;1102 case CC_X86FastCall:1103 OS << " __attribute__((fastcall))";1104 break;1105 case CC_X86ThisCall:1106 OS << " __attribute__((thiscall))";1107 break;1108 case CC_X86VectorCall:1109 OS << " __attribute__((vectorcall))";1110 break;1111 case CC_X86Pascal:1112 OS << " __attribute__((pascal))";1113 break;1114 case CC_AAPCS:1115 OS << " __attribute__((pcs(\"aapcs\")))";1116 break;1117 case CC_AAPCS_VFP:1118 OS << " __attribute__((pcs(\"aapcs-vfp\")))";1119 break;1120 case CC_AArch64VectorCall:1121 OS << " __attribute__((aarch64_vector_pcs))";1122 break;1123 case CC_AArch64SVEPCS:1124 OS << " __attribute__((aarch64_sve_pcs))";1125 break;1126 case CC_DeviceKernel:1127 OS << " __attribute__((device_kernel))";1128 break;1129 case CC_IntelOclBicc:1130 OS << " __attribute__((intel_ocl_bicc))";1131 break;1132 case CC_Win64:1133 OS << " __attribute__((ms_abi))";1134 break;1135 case CC_X86_64SysV:1136 OS << " __attribute__((sysv_abi))";1137 break;1138 case CC_X86RegCall:1139 OS << " __attribute__((regcall))";1140 break;1141 case CC_SpirFunction:1142 // Do nothing. These CCs are not available as attributes.1143 break;1144 case CC_Swift:1145 OS << " __attribute__((swiftcall))";1146 break;1147 case CC_SwiftAsync:1148 OS << "__attribute__((swiftasynccall))";1149 break;1150 case CC_PreserveMost:1151 OS << " __attribute__((preserve_most))";1152 break;1153 case CC_PreserveAll:1154 OS << " __attribute__((preserve_all))";1155 break;1156 case CC_M68kRTD:1157 OS << " __attribute__((m68k_rtd))";1158 break;1159 case CC_PreserveNone:1160 OS << " __attribute__((preserve_none))";1161 break;1162 case CC_RISCVVectorCall:1163 OS << "__attribute__((riscv_vector_cc))";1164 break;1165#define CC_VLS_CASE(ABI_VLEN) \1166 case CC_RISCVVLSCall_##ABI_VLEN: \1167 OS << "__attribute__((riscv_vls_cc" #ABI_VLEN "))"; \1168 break;1169 CC_VLS_CASE(32)1170 CC_VLS_CASE(64)1171 CC_VLS_CASE(128)1172 CC_VLS_CASE(256)1173 CC_VLS_CASE(512)1174 CC_VLS_CASE(1024)1175 CC_VLS_CASE(2048)1176 CC_VLS_CASE(4096)1177 CC_VLS_CASE(8192)1178 CC_VLS_CASE(16384)1179 CC_VLS_CASE(32768)1180 CC_VLS_CASE(65536)1181#undef CC_VLS_CASE1182 }1183 }1184 1185 if (Info.getNoReturn())1186 OS << " __attribute__((noreturn))";1187 if (Info.getCmseNSCall())1188 OS << " __attribute__((cmse_nonsecure_call))";1189 if (Info.getProducesResult())1190 OS << " __attribute__((ns_returns_retained))";1191 if (Info.getRegParm())1192 OS << " __attribute__((regparm ("1193 << Info.getRegParm() << ")))";1194 if (Info.getNoCallerSavedRegs())1195 OS << " __attribute__((no_caller_saved_registers))";1196 if (Info.getNoCfCheck())1197 OS << " __attribute__((nocf_check))";1198}1199 1200void TypePrinter::printFunctionNoProtoBefore(const FunctionNoProtoType *T,1201 raw_ostream &OS) {1202 // If needed for precedence reasons, wrap the inner part in grouping parens.1203 SaveAndRestore PrevPHIsEmpty(HasEmptyPlaceHolder, false);1204 printBefore(T->getReturnType(), OS);1205 if (!PrevPHIsEmpty.get())1206 OS << '(';1207}1208 1209void TypePrinter::printFunctionNoProtoAfter(const FunctionNoProtoType *T,1210 raw_ostream &OS) {1211 // If needed for precedence reasons, wrap the inner part in grouping parens.1212 if (!HasEmptyPlaceHolder)1213 OS << ')';1214 SaveAndRestore NonEmptyPH(HasEmptyPlaceHolder, false);1215 1216 OS << "()";1217 printFunctionAfter(T->getExtInfo(), OS);1218 printAfter(T->getReturnType(), OS);1219}1220 1221void TypePrinter::printTypeSpec(NamedDecl *D, raw_ostream &OS) {1222 1223 // Compute the full nested-name-specifier for this type.1224 // In C, this will always be empty except when the type1225 // being printed is anonymous within other Record.1226 if (!Policy.SuppressScope)1227 D->printNestedNameSpecifier(OS, Policy);1228 1229 IdentifierInfo *II = D->getIdentifier();1230 OS << II->getName();1231 spaceBeforePlaceHolder(OS);1232}1233 1234void TypePrinter::printUnresolvedUsingBefore(const UnresolvedUsingType *T,1235 raw_ostream &OS) {1236 OS << TypeWithKeyword::getKeywordName(T->getKeyword());1237 if (T->getKeyword() != ElaboratedTypeKeyword::None)1238 OS << ' ';1239 auto *D = T->getDecl();1240 if (Policy.FullyQualifiedName || T->isCanonicalUnqualified()) {1241 D->printNestedNameSpecifier(OS, Policy);1242 } else {1243 T->getQualifier().print(OS, Policy);1244 }1245 OS << D->getIdentifier()->getName();1246 spaceBeforePlaceHolder(OS);1247}1248 1249void TypePrinter::printUnresolvedUsingAfter(const UnresolvedUsingType *T,1250 raw_ostream &OS) {}1251 1252void TypePrinter::printUsingBefore(const UsingType *T, raw_ostream &OS) {1253 OS << TypeWithKeyword::getKeywordName(T->getKeyword());1254 if (T->getKeyword() != ElaboratedTypeKeyword::None)1255 OS << ' ';1256 auto *D = T->getDecl();1257 if (Policy.FullyQualifiedName) {1258 D->printNestedNameSpecifier(OS, Policy);1259 } else {1260 T->getQualifier().print(OS, Policy);1261 }1262 OS << D->getIdentifier()->getName();1263 spaceBeforePlaceHolder(OS);1264}1265 1266void TypePrinter::printUsingAfter(const UsingType *T, raw_ostream &OS) {}1267 1268void TypePrinter::printTypedefBefore(const TypedefType *T, raw_ostream &OS) {1269 OS << TypeWithKeyword::getKeywordName(T->getKeyword());1270 if (T->getKeyword() != ElaboratedTypeKeyword::None)1271 OS << ' ';1272 auto *D = T->getDecl();1273 if (Policy.FullyQualifiedName) {1274 D->printNestedNameSpecifier(OS, Policy);1275 } else {1276 T->getQualifier().print(OS, Policy);1277 }1278 OS << D->getIdentifier()->getName();1279 spaceBeforePlaceHolder(OS);1280}1281 1282void TypePrinter::printMacroQualifiedBefore(const MacroQualifiedType *T,1283 raw_ostream &OS) {1284 StringRef MacroName = T->getMacroIdentifier()->getName();1285 OS << MacroName << " ";1286 1287 // Since this type is meant to print the macro instead of the whole attribute,1288 // we trim any attributes and go directly to the original modified type.1289 printBefore(T->getModifiedType(), OS);1290}1291 1292void TypePrinter::printMacroQualifiedAfter(const MacroQualifiedType *T,1293 raw_ostream &OS) {1294 printAfter(T->getModifiedType(), OS);1295}1296 1297void TypePrinter::printTypedefAfter(const TypedefType *T, raw_ostream &OS) {}1298 1299void TypePrinter::printTypeOfExprBefore(const TypeOfExprType *T,1300 raw_ostream &OS) {1301 OS << (T->getKind() == TypeOfKind::Unqualified ? "typeof_unqual "1302 : "typeof ");1303 if (T->getUnderlyingExpr())1304 T->getUnderlyingExpr()->printPretty(OS, nullptr, Policy);1305 spaceBeforePlaceHolder(OS);1306}1307 1308void TypePrinter::printTypeOfExprAfter(const TypeOfExprType *T,1309 raw_ostream &OS) {}1310 1311void TypePrinter::printTypeOfBefore(const TypeOfType *T, raw_ostream &OS) {1312 OS << (T->getKind() == TypeOfKind::Unqualified ? "typeof_unqual("1313 : "typeof(");1314 print(T->getUnmodifiedType(), OS, StringRef());1315 OS << ')';1316 spaceBeforePlaceHolder(OS);1317}1318 1319void TypePrinter::printTypeOfAfter(const TypeOfType *T, raw_ostream &OS) {}1320 1321void TypePrinter::printDecltypeBefore(const DecltypeType *T, raw_ostream &OS) {1322 OS << "decltype(";1323 if (const Expr *E = T->getUnderlyingExpr()) {1324 PrintingPolicy ExprPolicy = Policy;1325 ExprPolicy.PrintAsCanonical = T->isCanonicalUnqualified();1326 E->printPretty(OS, nullptr, ExprPolicy);1327 }1328 OS << ')';1329 spaceBeforePlaceHolder(OS);1330}1331 1332void TypePrinter::printPackIndexingBefore(const PackIndexingType *T,1333 raw_ostream &OS) {1334 if (T->hasSelectedType()) {1335 OS << T->getSelectedType();1336 } else {1337 OS << T->getPattern() << "...[";1338 T->getIndexExpr()->printPretty(OS, nullptr, Policy);1339 OS << "]";1340 }1341 spaceBeforePlaceHolder(OS);1342}1343 1344void TypePrinter::printPackIndexingAfter(const PackIndexingType *T,1345 raw_ostream &OS) {}1346 1347void TypePrinter::printDecltypeAfter(const DecltypeType *T, raw_ostream &OS) {}1348 1349void TypePrinter::printUnaryTransformBefore(const UnaryTransformType *T,1350 raw_ostream &OS) {1351 IncludeStrongLifetimeRAII Strong(Policy);1352 1353 static llvm::DenseMap<int, const char *> Transformation = {{1354#define TRANSFORM_TYPE_TRAIT_DEF(Enum, Trait) \1355 {UnaryTransformType::Enum, "__" #Trait},1356#include "clang/Basic/TransformTypeTraits.def"1357 }};1358 OS << Transformation[T->getUTTKind()] << '(';1359 print(T->getBaseType(), OS, StringRef());1360 OS << ')';1361 spaceBeforePlaceHolder(OS);1362}1363 1364void TypePrinter::printUnaryTransformAfter(const UnaryTransformType *T,1365 raw_ostream &OS) {}1366 1367void TypePrinter::printAutoBefore(const AutoType *T, raw_ostream &OS) {1368 // If the type has been deduced, do not print 'auto'.1369 if (!T->getDeducedType().isNull()) {1370 printBefore(T->getDeducedType(), OS);1371 } else {1372 if (T->isConstrained()) {1373 // FIXME: Track a TypeConstraint as type sugar, so that we can print the1374 // type as it was written.1375 T->getTypeConstraintConcept()->getDeclName().print(OS, Policy);1376 auto Args = T->getTypeConstraintArguments();1377 if (!Args.empty())1378 printTemplateArgumentList(1379 OS, Args, Policy,1380 T->getTypeConstraintConcept()->getTemplateParameters());1381 OS << ' ';1382 }1383 switch (T->getKeyword()) {1384 case AutoTypeKeyword::Auto: OS << "auto"; break;1385 case AutoTypeKeyword::DecltypeAuto: OS << "decltype(auto)"; break;1386 case AutoTypeKeyword::GNUAutoType: OS << "__auto_type"; break;1387 }1388 spaceBeforePlaceHolder(OS);1389 }1390}1391 1392void TypePrinter::printAutoAfter(const AutoType *T, raw_ostream &OS) {1393 // If the type has been deduced, do not print 'auto'.1394 if (!T->getDeducedType().isNull())1395 printAfter(T->getDeducedType(), OS);1396}1397 1398void TypePrinter::printDeducedTemplateSpecializationBefore(1399 const DeducedTemplateSpecializationType *T, raw_ostream &OS) {1400 if (ElaboratedTypeKeyword Keyword = T->getKeyword();1401 T->getKeyword() != ElaboratedTypeKeyword::None)1402 OS << KeywordHelpers::getKeywordName(Keyword) << ' ';1403 1404 TemplateName Name = T->getTemplateName();1405 1406 // If the type has been deduced, print the template arguments, as if this was1407 // printing the deduced type, but including elaboration and template name1408 // qualification.1409 // FIXME: There should probably be a policy which controls this.1410 // We would probably want to do this on diagnostics, but not on -ast-print.1411 ArrayRef<TemplateArgument> Args;1412 TemplateDecl *DeducedTD = nullptr;1413 if (!T->getDeducedType().isNull()) {1414 if (const auto *TST =1415 dyn_cast<TemplateSpecializationType>(T->getDeducedType())) {1416 DeducedTD = TST->getTemplateName().getAsTemplateDecl(1417 /*IgnoreDeduced=*/true);1418 Args = TST->template_arguments();1419 } else {1420 // Should only get here for canonical types.1421 const auto *CD = cast<ClassTemplateSpecializationDecl>(1422 cast<RecordType>(T->getDeducedType())->getDecl());1423 DeducedTD = CD->getSpecializedTemplate();1424 Args = CD->getTemplateArgs().asArray();1425 }1426 1427 // FIXME: Workaround for alias template CTAD not producing guides which1428 // include the alias template specialization type.1429 // Purposefully disregard qualification when building this TemplateName;1430 // any qualification we might have, might not make sense in the1431 // context this was deduced.1432 if (!declaresSameEntity(DeducedTD, Name.getAsTemplateDecl(1433 /*IgnoreDeduced=*/true)))1434 Name = TemplateName(DeducedTD);1435 }1436 1437 {1438 IncludeStrongLifetimeRAII Strong(Policy);1439 Name.print(OS, Policy);1440 }1441 if (DeducedTD) {1442 printTemplateArgumentList(OS, Args, Policy,1443 DeducedTD->getTemplateParameters());1444 }1445 1446 spaceBeforePlaceHolder(OS);1447}1448 1449void TypePrinter::printDeducedTemplateSpecializationAfter(1450 const DeducedTemplateSpecializationType *T, raw_ostream &OS) {1451 // If the type has been deduced, print the deduced type.1452 if (!T->getDeducedType().isNull())1453 printAfter(T->getDeducedType(), OS);1454}1455 1456void TypePrinter::printAtomicBefore(const AtomicType *T, raw_ostream &OS) {1457 IncludeStrongLifetimeRAII Strong(Policy);1458 1459 OS << "_Atomic(";1460 print(T->getValueType(), OS, StringRef());1461 OS << ')';1462 spaceBeforePlaceHolder(OS);1463}1464 1465void TypePrinter::printAtomicAfter(const AtomicType *T, raw_ostream &OS) {}1466 1467void TypePrinter::printPipeBefore(const PipeType *T, raw_ostream &OS) {1468 IncludeStrongLifetimeRAII Strong(Policy);1469 1470 if (T->isReadOnly())1471 OS << "read_only ";1472 else1473 OS << "write_only ";1474 OS << "pipe ";1475 print(T->getElementType(), OS, StringRef());1476 spaceBeforePlaceHolder(OS);1477}1478 1479void TypePrinter::printPipeAfter(const PipeType *T, raw_ostream &OS) {}1480 1481void TypePrinter::printBitIntBefore(const BitIntType *T, raw_ostream &OS) {1482 if (T->isUnsigned())1483 OS << "unsigned ";1484 OS << "_BitInt(" << T->getNumBits() << ")";1485 spaceBeforePlaceHolder(OS);1486}1487 1488void TypePrinter::printBitIntAfter(const BitIntType *T, raw_ostream &OS) {}1489 1490void TypePrinter::printDependentBitIntBefore(const DependentBitIntType *T,1491 raw_ostream &OS) {1492 if (T->isUnsigned())1493 OS << "unsigned ";1494 OS << "_BitInt(";1495 T->getNumBitsExpr()->printPretty(OS, nullptr, Policy);1496 OS << ")";1497 spaceBeforePlaceHolder(OS);1498}1499 1500void TypePrinter::printDependentBitIntAfter(const DependentBitIntType *T,1501 raw_ostream &OS) {}1502 1503void TypePrinter::printPredefinedSugarBefore(const PredefinedSugarType *T,1504 raw_ostream &OS) {1505 OS << T->getIdentifier()->getName();1506 spaceBeforePlaceHolder(OS);1507}1508 1509void TypePrinter::printPredefinedSugarAfter(const PredefinedSugarType *T,1510 raw_ostream &OS) {}1511 1512void TypePrinter::printTagType(const TagType *T, raw_ostream &OS) {1513 TagDecl *D = T->getDecl();1514 1515 if (Policy.IncludeTagDefinition && T->isTagOwned()) {1516 D->print(OS, Policy, Indentation);1517 spaceBeforePlaceHolder(OS);1518 return;1519 }1520 1521 bool HasKindDecoration = false;1522 1523 if (T->isCanonicalUnqualified()) {1524 if (!Policy.SuppressTagKeyword && !D->getTypedefNameForAnonDecl()) {1525 HasKindDecoration = true;1526 OS << D->getKindName();1527 OS << ' ';1528 }1529 } else {1530 OS << TypeWithKeyword::getKeywordName(T->getKeyword());1531 if (T->getKeyword() != ElaboratedTypeKeyword::None)1532 OS << ' ';1533 }1534 1535 if (!Policy.FullyQualifiedName && !T->isCanonicalUnqualified()) {1536 T->getQualifier().print(OS, Policy);1537 } else if (!Policy.SuppressScope) {1538 // Compute the full nested-name-specifier for this type.1539 // In C, this will always be empty except when the type1540 // being printed is anonymous within other Record.1541 D->printNestedNameSpecifier(OS, Policy);1542 }1543 1544 if (const IdentifierInfo *II = D->getIdentifier())1545 OS << II->getName();1546 else if (TypedefNameDecl *Typedef = D->getTypedefNameForAnonDecl()) {1547 assert(Typedef->getIdentifier() && "Typedef without identifier?");1548 OS << Typedef->getIdentifier()->getName();1549 } else {1550 // Make an unambiguous representation for anonymous types, e.g.1551 // (anonymous enum at /usr/include/string.h:120:9)1552 OS << (Policy.MSVCFormatting ? '`' : '(');1553 1554 if (isa<CXXRecordDecl>(D) && cast<CXXRecordDecl>(D)->isLambda()) {1555 OS << "lambda";1556 HasKindDecoration = true;1557 } else if ((isa<RecordDecl>(D) && cast<RecordDecl>(D)->isAnonymousStructOrUnion())) {1558 OS << "anonymous";1559 } else {1560 OS << "unnamed";1561 }1562 1563 if (Policy.AnonymousTagLocations) {1564 // Suppress the redundant tag keyword if we just printed one.1565 // We don't have to worry about ElaboratedTypes here because you can't1566 // refer to an anonymous type with one.1567 if (!HasKindDecoration)1568 OS << " " << D->getKindName();1569 1570 PresumedLoc PLoc = D->getASTContext().getSourceManager().getPresumedLoc(1571 D->getLocation());1572 if (PLoc.isValid()) {1573 OS << " at ";1574 StringRef File = PLoc.getFilename();1575 llvm::SmallString<1024> WrittenFile(File);1576 if (auto *Callbacks = Policy.Callbacks)1577 WrittenFile = Callbacks->remapPath(File);1578 // Fix inconsistent path separator created by1579 // clang::DirectoryLookup::LookupFile when the file path is relative1580 // path.1581 llvm::sys::path::Style Style =1582 llvm::sys::path::is_absolute(WrittenFile)1583 ? llvm::sys::path::Style::native1584 : (Policy.MSVCFormatting1585 ? llvm::sys::path::Style::windows_backslash1586 : llvm::sys::path::Style::posix);1587 llvm::sys::path::native(WrittenFile, Style);1588 OS << WrittenFile << ':' << PLoc.getLine() << ':' << PLoc.getColumn();1589 }1590 }1591 1592 OS << (Policy.MSVCFormatting ? '\'' : ')');1593 }1594 1595 // If this is a class template specialization, print the template1596 // arguments.1597 if (auto *S = dyn_cast<ClassTemplateSpecializationDecl>(D)) {1598 const TemplateParameterList *TParams =1599 S->getSpecializedTemplate()->getTemplateParameters();1600 const ASTTemplateArgumentListInfo *TArgAsWritten =1601 S->getTemplateArgsAsWritten();1602 IncludeStrongLifetimeRAII Strong(Policy);1603 if (TArgAsWritten && !Policy.PrintAsCanonical)1604 printTemplateArgumentList(OS, TArgAsWritten->arguments(), Policy,1605 TParams);1606 else1607 printTemplateArgumentList(OS, S->getTemplateArgs().asArray(), Policy,1608 TParams);1609 }1610 1611 spaceBeforePlaceHolder(OS);1612}1613 1614void TypePrinter::printRecordBefore(const RecordType *T, raw_ostream &OS) {1615 // Print the preferred name if we have one for this type.1616 if (Policy.UsePreferredNames) {1617 for (const auto *PNA : T->getDecl()1618 ->getMostRecentDecl()1619 ->specific_attrs<PreferredNameAttr>()) {1620 if (!declaresSameEntity(PNA->getTypedefType()->getAsCXXRecordDecl(),1621 T->getDecl()))1622 continue;1623 // Find the outermost typedef or alias template.1624 QualType T = PNA->getTypedefType();1625 while (true) {1626 if (auto *TT = dyn_cast<TypedefType>(T))1627 return printTypeSpec(TT->getDecl(), OS);1628 if (auto *TST = dyn_cast<TemplateSpecializationType>(T))1629 return printTemplateId(TST, OS, /*FullyQualify=*/true);1630 T = T->getLocallyUnqualifiedSingleStepDesugaredType();1631 }1632 }1633 }1634 1635 printTagType(T, OS);1636}1637 1638void TypePrinter::printRecordAfter(const RecordType *T, raw_ostream &OS) {}1639 1640void TypePrinter::printEnumBefore(const EnumType *T, raw_ostream &OS) {1641 printTagType(T, OS);1642}1643 1644void TypePrinter::printEnumAfter(const EnumType *T, raw_ostream &OS) {}1645 1646void TypePrinter::printInjectedClassNameBefore(const InjectedClassNameType *T,1647 raw_ostream &OS) {1648 const ASTContext &Ctx = T->getDecl()->getASTContext();1649 IncludeStrongLifetimeRAII Strong(Policy);1650 T->getTemplateName(Ctx).print(OS, Policy);1651 if (Policy.PrintInjectedClassNameWithArguments) {1652 auto *Decl = T->getDecl();1653 // FIXME: Use T->getTemplateArgs(Ctx) when that supports as-written1654 // arguments.1655 if (auto *RD = dyn_cast<ClassTemplateSpecializationDecl>(Decl)) {1656 printTemplateArgumentList(OS, RD->getTemplateArgsAsWritten()->arguments(),1657 Policy,1658 T->getTemplateDecl()->getTemplateParameters());1659 } else {1660 ClassTemplateDecl *TD = Decl->getDescribedClassTemplate();1661 assert(TD);1662 printTemplateArgumentList(1663 OS, TD->getTemplateParameters()->getInjectedTemplateArgs(Ctx), Policy,1664 T->getTemplateDecl()->getTemplateParameters());1665 }1666 }1667 spaceBeforePlaceHolder(OS);1668}1669 1670void TypePrinter::printInjectedClassNameAfter(const InjectedClassNameType *T,1671 raw_ostream &OS) {}1672 1673void TypePrinter::printTemplateTypeParmBefore(const TemplateTypeParmType *T,1674 raw_ostream &OS) {1675 TemplateTypeParmDecl *D = T->getDecl();1676 if (D && D->isImplicit()) {1677 if (auto *TC = D->getTypeConstraint()) {1678 TC->print(OS, Policy);1679 OS << ' ';1680 }1681 OS << "auto";1682 } else if (IdentifierInfo *Id = T->getIdentifier())1683 OS << (Policy.CleanUglifiedParameters ? Id->deuglifiedName()1684 : Id->getName());1685 else1686 OS << "type-parameter-" << T->getDepth() << '-' << T->getIndex();1687 1688 spaceBeforePlaceHolder(OS);1689}1690 1691void TypePrinter::printTemplateTypeParmAfter(const TemplateTypeParmType *T,1692 raw_ostream &OS) {}1693 1694void TypePrinter::printSubstTemplateTypeParmBefore(1695 const SubstTemplateTypeParmType *T,1696 raw_ostream &OS) {1697 IncludeStrongLifetimeRAII Strong(Policy);1698 printBefore(T->getReplacementType(), OS);1699}1700 1701void TypePrinter::printSubstTemplateTypeParmAfter(1702 const SubstTemplateTypeParmType *T,1703 raw_ostream &OS) {1704 IncludeStrongLifetimeRAII Strong(Policy);1705 printAfter(T->getReplacementType(), OS);1706}1707 1708void TypePrinter::printSubstBuiltinTemplatePackBefore(1709 const SubstBuiltinTemplatePackType *T, raw_ostream &OS) {1710 IncludeStrongLifetimeRAII Strong(Policy);1711 OS << "type-pack";1712}1713 1714void TypePrinter::printSubstBuiltinTemplatePackAfter(1715 const SubstBuiltinTemplatePackType *T, raw_ostream &OS) {}1716 1717void TypePrinter::printSubstTemplateTypeParmPackBefore(1718 const SubstTemplateTypeParmPackType *T,1719 raw_ostream &OS) {1720 IncludeStrongLifetimeRAII Strong(Policy);1721 if (const TemplateTypeParmDecl *D = T->getReplacedParameter()) {1722 if (D && D->isImplicit()) {1723 if (auto *TC = D->getTypeConstraint()) {1724 TC->print(OS, Policy);1725 OS << ' ';1726 }1727 OS << "auto";1728 } else if (IdentifierInfo *Id = D->getIdentifier())1729 OS << (Policy.CleanUglifiedParameters ? Id->deuglifiedName()1730 : Id->getName());1731 else1732 OS << "type-parameter-" << D->getDepth() << '-' << D->getIndex();1733 1734 spaceBeforePlaceHolder(OS);1735 }1736}1737 1738void TypePrinter::printSubstTemplateTypeParmPackAfter(1739 const SubstTemplateTypeParmPackType *T,1740 raw_ostream &OS) {1741 IncludeStrongLifetimeRAII Strong(Policy);1742}1743 1744void TypePrinter::printTemplateId(const TemplateSpecializationType *T,1745 raw_ostream &OS, bool FullyQualify) {1746 IncludeStrongLifetimeRAII Strong(Policy);1747 1748 if (ElaboratedTypeKeyword K = T->getKeyword();1749 K != ElaboratedTypeKeyword::None)1750 OS << TypeWithKeyword::getKeywordName(K) << ' ';1751 1752 TemplateDecl *TD =1753 T->getTemplateName().getAsTemplateDecl(/*IgnoreDeduced=*/true);1754 // FIXME: Null TD never exercised in test suite.1755 if (FullyQualify && TD) {1756 if (!Policy.SuppressScope)1757 TD->printNestedNameSpecifier(OS, Policy);1758 1759 OS << TD->getName();1760 } else {1761 T->getTemplateName().print(OS, Policy,1762 !Policy.SuppressScope1763 ? TemplateName::Qualified::AsWritten1764 : TemplateName::Qualified::None);1765 }1766 1767 DefaultTemplateArgsPolicyRAII TemplateArgs(Policy);1768 const TemplateParameterList *TPL = TD ? TD->getTemplateParameters() : nullptr;1769 printTemplateArgumentList(OS, T->template_arguments(), Policy, TPL);1770 spaceBeforePlaceHolder(OS);1771}1772 1773void TypePrinter::printTemplateSpecializationBefore(1774 const TemplateSpecializationType *T,1775 raw_ostream &OS) {1776 printTemplateId(T, OS, Policy.FullyQualifiedName);1777}1778 1779void TypePrinter::printTemplateSpecializationAfter(1780 const TemplateSpecializationType *T,1781 raw_ostream &OS) {}1782 1783void TypePrinter::printParenBefore(const ParenType *T, raw_ostream &OS) {1784 if (!HasEmptyPlaceHolder && !isa<FunctionType>(T->getInnerType())) {1785 printBefore(T->getInnerType(), OS);1786 OS << '(';1787 } else1788 printBefore(T->getInnerType(), OS);1789}1790 1791void TypePrinter::printParenAfter(const ParenType *T, raw_ostream &OS) {1792 if (!HasEmptyPlaceHolder && !isa<FunctionType>(T->getInnerType())) {1793 OS << ')';1794 printAfter(T->getInnerType(), OS);1795 } else1796 printAfter(T->getInnerType(), OS);1797}1798 1799void TypePrinter::printDependentNameBefore(const DependentNameType *T,1800 raw_ostream &OS) {1801 OS << TypeWithKeyword::getKeywordName(T->getKeyword());1802 if (T->getKeyword() != ElaboratedTypeKeyword::None)1803 OS << " ";1804 T->getQualifier().print(OS, Policy);1805 OS << T->getIdentifier()->getName();1806 spaceBeforePlaceHolder(OS);1807}1808 1809void TypePrinter::printDependentNameAfter(const DependentNameType *T,1810 raw_ostream &OS) {}1811 1812void TypePrinter::printPackExpansionBefore(const PackExpansionType *T,1813 raw_ostream &OS) {1814 printBefore(T->getPattern(), OS);1815}1816 1817void TypePrinter::printPackExpansionAfter(const PackExpansionType *T,1818 raw_ostream &OS) {1819 printAfter(T->getPattern(), OS);1820 OS << "...";1821}1822 1823static void printCountAttributedImpl(const CountAttributedType *T,1824 raw_ostream &OS,1825 const PrintingPolicy &Policy) {1826 OS << ' ';1827 if (T->isCountInBytes() && T->isOrNull())1828 OS << "__sized_by_or_null(";1829 else if (T->isCountInBytes())1830 OS << "__sized_by(";1831 else if (T->isOrNull())1832 OS << "__counted_by_or_null(";1833 else1834 OS << "__counted_by(";1835 if (T->getCountExpr())1836 T->getCountExpr()->printPretty(OS, nullptr, Policy);1837 OS << ')';1838}1839 1840void TypePrinter::printCountAttributedBefore(const CountAttributedType *T,1841 raw_ostream &OS) {1842 printBefore(T->desugar(), OS);1843 if (!T->isArrayType())1844 printCountAttributedImpl(T, OS, Policy);1845}1846 1847void TypePrinter::printCountAttributedAfter(const CountAttributedType *T,1848 raw_ostream &OS) {1849 printAfter(T->desugar(), OS);1850 if (T->isArrayType())1851 printCountAttributedImpl(T, OS, Policy);1852}1853 1854void TypePrinter::printAttributedBefore(const AttributedType *T,1855 raw_ostream &OS) {1856 // FIXME: Generate this with TableGen.1857 1858 // Prefer the macro forms of the GC and ownership qualifiers.1859 if (T->getAttrKind() == attr::ObjCGC ||1860 T->getAttrKind() == attr::ObjCOwnership)1861 return printBefore(T->getEquivalentType(), OS);1862 1863 if (T->getAttrKind() == attr::ObjCKindOf)1864 OS << "__kindof ";1865 1866 if (T->getAttrKind() == attr::PreserveNone) {1867 OS << "__attribute__((preserve_none)) ";1868 spaceBeforePlaceHolder(OS);1869 } else if (T->getAttrKind() == attr::PreserveMost) {1870 OS << "__attribute__((preserve_most)) ";1871 spaceBeforePlaceHolder(OS);1872 } else if (T->getAttrKind() == attr::PreserveAll) {1873 OS << "__attribute__((preserve_all)) ";1874 spaceBeforePlaceHolder(OS);1875 }1876 1877 if (T->getAttrKind() == attr::AddressSpace)1878 printBefore(T->getEquivalentType(), OS);1879 else1880 printBefore(T->getModifiedType(), OS);1881 1882 if (T->isMSTypeSpec()) {1883 switch (T->getAttrKind()) {1884 default: return;1885 case attr::Ptr32: OS << " __ptr32"; break;1886 case attr::Ptr64: OS << " __ptr64"; break;1887 case attr::SPtr: OS << " __sptr"; break;1888 case attr::UPtr: OS << " __uptr"; break;1889 }1890 spaceBeforePlaceHolder(OS);1891 }1892 1893 if (T->isWebAssemblyFuncrefSpec())1894 OS << "__funcref";1895 1896 // Print nullability type specifiers.1897 if (T->getImmediateNullability()) {1898 if (T->getAttrKind() == attr::TypeNonNull)1899 OS << " _Nonnull";1900 else if (T->getAttrKind() == attr::TypeNullable)1901 OS << " _Nullable";1902 else if (T->getAttrKind() == attr::TypeNullUnspecified)1903 OS << " _Null_unspecified";1904 else if (T->getAttrKind() == attr::TypeNullableResult)1905 OS << " _Nullable_result";1906 else1907 llvm_unreachable("unhandled nullability");1908 spaceBeforePlaceHolder(OS);1909 }1910}1911 1912void TypePrinter::printAttributedAfter(const AttributedType *T,1913 raw_ostream &OS) {1914 // FIXME: Generate this with TableGen.1915 1916 // Prefer the macro forms of the GC and ownership qualifiers.1917 if (T->getAttrKind() == attr::ObjCGC ||1918 T->getAttrKind() == attr::ObjCOwnership)1919 return printAfter(T->getEquivalentType(), OS);1920 1921 // If this is a calling convention attribute, don't print the implicit CC from1922 // the modified type.1923 SaveAndRestore MaybeSuppressCC(InsideCCAttribute, T->isCallingConv());1924 1925 printAfter(T->getModifiedType(), OS);1926 1927 // Some attributes are printed as qualifiers before the type, so we have1928 // nothing left to do.1929 if (T->getAttrKind() == attr::ObjCKindOf || T->isMSTypeSpec() ||1930 T->getImmediateNullability() || T->isWebAssemblyFuncrefSpec())1931 return;1932 1933 // Don't print the inert __unsafe_unretained attribute at all.1934 if (T->getAttrKind() == attr::ObjCInertUnsafeUnretained)1935 return;1936 1937 // Don't print ns_returns_retained unless it had an effect.1938 if (T->getAttrKind() == attr::NSReturnsRetained &&1939 !T->getEquivalentType()->castAs<FunctionType>()1940 ->getExtInfo().getProducesResult())1941 return;1942 1943 if (T->getAttrKind() == attr::LifetimeBound) {1944 OS << " [[clang::lifetimebound]]";1945 return;1946 }1947 if (T->getAttrKind() == attr::LifetimeCaptureBy) {1948 OS << " [[clang::lifetime_capture_by(";1949 if (auto *attr = dyn_cast_or_null<LifetimeCaptureByAttr>(T->getAttr()))1950 llvm::interleaveComma(attr->getArgIdents(), OS,1951 [&](auto it) { OS << it->getName(); });1952 OS << ")]]";1953 return;1954 }1955 1956 // The printing of the address_space attribute is handled by the qualifier1957 // since it is still stored in the qualifier. Return early to prevent printing1958 // this twice.1959 if (T->getAttrKind() == attr::AddressSpace)1960 return;1961 1962 if (T->getAttrKind() == attr::AnnotateType) {1963 // FIXME: Print the attribute arguments once we have a way to retrieve these1964 // here. For the meantime, we just print `[[clang::annotate_type(...)]]`1965 // without the arguments so that we know at least that we had _some_1966 // annotation on the type.1967 OS << " [[clang::annotate_type(...)]]";1968 return;1969 }1970 1971 if (T->getAttrKind() == attr::ArmStreaming) {1972 OS << "__arm_streaming";1973 return;1974 }1975 if (T->getAttrKind() == attr::ArmStreamingCompatible) {1976 OS << "__arm_streaming_compatible";1977 return;1978 }1979 1980 if (T->getAttrKind() == attr::SwiftAttr) {1981 if (auto *swiftAttr = dyn_cast_or_null<SwiftAttrAttr>(T->getAttr())) {1982 OS << " __attribute__((swift_attr(\"" << swiftAttr->getAttribute()1983 << "\")))";1984 }1985 return;1986 }1987 1988 if (T->getAttrKind() == attr::PreserveAll ||1989 T->getAttrKind() == attr::PreserveMost ||1990 T->getAttrKind() == attr::PreserveNone) {1991 // This has to be printed before the type.1992 return;1993 }1994 1995 OS << " __attribute__((";1996 switch (T->getAttrKind()) {1997#define TYPE_ATTR(NAME)1998#define DECL_OR_TYPE_ATTR(NAME)1999#define ATTR(NAME) case attr::NAME:2000#include "clang/Basic/AttrList.inc"2001 llvm_unreachable("non-type attribute attached to type");2002 2003 case attr::BTFTypeTag:2004 llvm_unreachable("BTFTypeTag attribute handled separately");2005 2006 case attr::HLSLResourceClass:2007 case attr::HLSLROV:2008 case attr::HLSLRawBuffer:2009 case attr::HLSLContainedType:2010 case attr::HLSLIsCounter:2011 llvm_unreachable("HLSL resource type attributes handled separately");2012 2013 case attr::OpenCLPrivateAddressSpace:2014 case attr::OpenCLGlobalAddressSpace:2015 case attr::OpenCLGlobalDeviceAddressSpace:2016 case attr::OpenCLGlobalHostAddressSpace:2017 case attr::OpenCLLocalAddressSpace:2018 case attr::OpenCLConstantAddressSpace:2019 case attr::OpenCLGenericAddressSpace:2020 case attr::HLSLGroupSharedAddressSpace:2021 // FIXME: Update printAttributedBefore to print these once we generate2022 // AttributedType nodes for them.2023 break;2024 2025 case attr::CountedBy:2026 case attr::CountedByOrNull:2027 case attr::SizedBy:2028 case attr::SizedByOrNull:2029 case attr::LifetimeBound:2030 case attr::LifetimeCaptureBy:2031 case attr::TypeNonNull:2032 case attr::TypeNullable:2033 case attr::TypeNullableResult:2034 case attr::TypeNullUnspecified:2035 case attr::ObjCGC:2036 case attr::ObjCInertUnsafeUnretained:2037 case attr::ObjCKindOf:2038 case attr::ObjCOwnership:2039 case attr::Ptr32:2040 case attr::Ptr64:2041 case attr::SPtr:2042 case attr::UPtr:2043 case attr::PointerAuth:2044 case attr::AddressSpace:2045 case attr::CmseNSCall:2046 case attr::AnnotateType:2047 case attr::WebAssemblyFuncref:2048 case attr::ArmAgnostic:2049 case attr::ArmStreaming:2050 case attr::ArmStreamingCompatible:2051 case attr::ArmIn:2052 case attr::ArmOut:2053 case attr::ArmInOut:2054 case attr::ArmPreserves:2055 case attr::NonBlocking:2056 case attr::NonAllocating:2057 case attr::Blocking:2058 case attr::Allocating:2059 case attr::SwiftAttr:2060 case attr::PreserveAll:2061 case attr::PreserveMost:2062 case attr::PreserveNone:2063 llvm_unreachable("This attribute should have been handled already");2064 2065 case attr::NSReturnsRetained:2066 OS << "ns_returns_retained";2067 break;2068 2069 // FIXME: When Sema learns to form this AttributedType, avoid printing the2070 // attribute again in printFunctionProtoAfter.2071 case attr::AnyX86NoCfCheck: OS << "nocf_check"; break;2072 case attr::CDecl: OS << "cdecl"; break;2073 case attr::FastCall: OS << "fastcall"; break;2074 case attr::StdCall: OS << "stdcall"; break;2075 case attr::ThisCall: OS << "thiscall"; break;2076 case attr::SwiftCall: OS << "swiftcall"; break;2077 case attr::SwiftAsyncCall: OS << "swiftasynccall"; break;2078 case attr::VectorCall: OS << "vectorcall"; break;2079 case attr::Pascal: OS << "pascal"; break;2080 case attr::MSABI: OS << "ms_abi"; break;2081 case attr::SysVABI: OS << "sysv_abi"; break;2082 case attr::RegCall: OS << "regcall"; break;2083 case attr::Pcs: {2084 OS << "pcs(";2085 QualType t = T->getEquivalentType();2086 while (!t->isFunctionType())2087 t = t->getPointeeType();2088 OS << (t->castAs<FunctionType>()->getCallConv() == CC_AAPCS ?2089 "\"aapcs\"" : "\"aapcs-vfp\"");2090 OS << ')';2091 break;2092 }2093 case attr::AArch64VectorPcs: OS << "aarch64_vector_pcs"; break;2094 case attr::AArch64SVEPcs: OS << "aarch64_sve_pcs"; break;2095 case attr::IntelOclBicc:2096 OS << "inteloclbicc";2097 break;2098 case attr::M68kRTD:2099 OS << "m68k_rtd";2100 break;2101 case attr::RISCVVectorCC:2102 OS << "riscv_vector_cc";2103 break;2104 case attr::RISCVVLSCC:2105 OS << "riscv_vls_cc";2106 break;2107 case attr::NoDeref:2108 OS << "noderef";2109 break;2110 case attr::CFIUncheckedCallee:2111 OS << "cfi_unchecked_callee";2112 break;2113 case attr::AcquireHandle:2114 OS << "acquire_handle";2115 break;2116 case attr::ArmMveStrictPolymorphism:2117 OS << "__clang_arm_mve_strict_polymorphism";2118 break;2119 case attr::ExtVectorType:2120 OS << "ext_vector_type";2121 break;2122 case attr::CFISalt:2123 OS << "cfi_salt(\"" << cast<CFISaltAttr>(T->getAttr())->getSalt() << "\")";2124 break;2125 }2126 OS << "))";2127}2128 2129void TypePrinter::printBTFTagAttributedBefore(const BTFTagAttributedType *T,2130 raw_ostream &OS) {2131 printBefore(T->getWrappedType(), OS);2132 OS << " __attribute__((btf_type_tag(\"" << T->getAttr()->getBTFTypeTag() << "\")))";2133}2134 2135void TypePrinter::printBTFTagAttributedAfter(const BTFTagAttributedType *T,2136 raw_ostream &OS) {2137 printAfter(T->getWrappedType(), OS);2138}2139 2140void TypePrinter::printHLSLAttributedResourceBefore(2141 const HLSLAttributedResourceType *T, raw_ostream &OS) {2142 printBefore(T->getWrappedType(), OS);2143}2144 2145void TypePrinter::printHLSLAttributedResourceAfter(2146 const HLSLAttributedResourceType *T, raw_ostream &OS) {2147 printAfter(T->getWrappedType(), OS);2148 const HLSLAttributedResourceType::Attributes &Attrs = T->getAttrs();2149 OS << " [[hlsl::resource_class("2150 << HLSLResourceClassAttr::ConvertResourceClassToStr(Attrs.ResourceClass)2151 << ")]]";2152 if (Attrs.IsROV)2153 OS << " [[hlsl::is_rov]]";2154 if (Attrs.RawBuffer)2155 OS << " [[hlsl::raw_buffer]]";2156 if (Attrs.IsCounter)2157 OS << " [[hlsl::is_counter]]";2158 2159 QualType ContainedTy = T->getContainedType();2160 if (!ContainedTy.isNull()) {2161 OS << " [[hlsl::contained_type(";2162 printBefore(ContainedTy, OS);2163 printAfter(ContainedTy, OS);2164 OS << ")]]";2165 }2166}2167 2168void TypePrinter::printHLSLInlineSpirvBefore(const HLSLInlineSpirvType *T,2169 raw_ostream &OS) {2170 OS << "__hlsl_spirv_type<" << T->getOpcode();2171 2172 OS << ", " << T->getSize();2173 OS << ", " << T->getAlignment();2174 2175 for (auto &Operand : T->getOperands()) {2176 using SpirvOperandKind = SpirvOperand::SpirvOperandKind;2177 2178 OS << ", ";2179 switch (Operand.getKind()) {2180 case SpirvOperandKind::ConstantId: {2181 QualType ConstantType = Operand.getResultType();2182 OS << "vk::integral_constant<";2183 printBefore(ConstantType, OS);2184 printAfter(ConstantType, OS);2185 OS << ", ";2186 OS << Operand.getValue();2187 OS << ">";2188 break;2189 }2190 case SpirvOperandKind::Literal:2191 OS << "vk::Literal<vk::integral_constant<uint, ";2192 OS << Operand.getValue();2193 OS << ">>";2194 break;2195 case SpirvOperandKind::TypeId: {2196 QualType Type = Operand.getResultType();2197 printBefore(Type, OS);2198 printAfter(Type, OS);2199 break;2200 }2201 default:2202 llvm_unreachable("Invalid SpirvOperand kind!");2203 break;2204 }2205 }2206 2207 OS << ">";2208}2209 2210void TypePrinter::printHLSLInlineSpirvAfter(const HLSLInlineSpirvType *T,2211 raw_ostream &OS) {2212 // nothing to do2213}2214 2215void TypePrinter::printObjCInterfaceBefore(const ObjCInterfaceType *T,2216 raw_ostream &OS) {2217 OS << T->getDecl()->getName();2218 spaceBeforePlaceHolder(OS);2219}2220 2221void TypePrinter::printObjCInterfaceAfter(const ObjCInterfaceType *T,2222 raw_ostream &OS) {}2223 2224void TypePrinter::printObjCTypeParamBefore(const ObjCTypeParamType *T,2225 raw_ostream &OS) {2226 OS << T->getDecl()->getName();2227 if (!T->qual_empty()) {2228 bool isFirst = true;2229 OS << '<';2230 for (const auto *I : T->quals()) {2231 if (isFirst)2232 isFirst = false;2233 else2234 OS << ',';2235 OS << I->getName();2236 }2237 OS << '>';2238 }2239 2240 spaceBeforePlaceHolder(OS);2241}2242 2243void TypePrinter::printObjCTypeParamAfter(const ObjCTypeParamType *T,2244 raw_ostream &OS) {}2245 2246void TypePrinter::printObjCObjectBefore(const ObjCObjectType *T,2247 raw_ostream &OS) {2248 if (T->qual_empty() && T->isUnspecializedAsWritten() &&2249 !T->isKindOfTypeAsWritten())2250 return printBefore(T->getBaseType(), OS);2251 2252 if (T->isKindOfTypeAsWritten())2253 OS << "__kindof ";2254 2255 print(T->getBaseType(), OS, StringRef());2256 2257 if (T->isSpecializedAsWritten()) {2258 bool isFirst = true;2259 OS << '<';2260 for (auto typeArg : T->getTypeArgsAsWritten()) {2261 if (isFirst)2262 isFirst = false;2263 else2264 OS << ",";2265 2266 print(typeArg, OS, StringRef());2267 }2268 OS << '>';2269 }2270 2271 if (!T->qual_empty()) {2272 bool isFirst = true;2273 OS << '<';2274 for (const auto *I : T->quals()) {2275 if (isFirst)2276 isFirst = false;2277 else2278 OS << ',';2279 OS << I->getName();2280 }2281 OS << '>';2282 }2283 2284 spaceBeforePlaceHolder(OS);2285}2286 2287void TypePrinter::printObjCObjectAfter(const ObjCObjectType *T,2288 raw_ostream &OS) {2289 if (T->qual_empty() && T->isUnspecializedAsWritten() &&2290 !T->isKindOfTypeAsWritten())2291 return printAfter(T->getBaseType(), OS);2292}2293 2294void TypePrinter::printObjCObjectPointerBefore(const ObjCObjectPointerType *T,2295 raw_ostream &OS) {2296 printBefore(T->getPointeeType(), OS);2297 2298 // If we need to print the pointer, print it now.2299 if (!T->isObjCIdType() && !T->isObjCQualifiedIdType() &&2300 !T->isObjCClassType() && !T->isObjCQualifiedClassType()) {2301 if (HasEmptyPlaceHolder)2302 OS << ' ';2303 OS << '*';2304 }2305}2306 2307void TypePrinter::printObjCObjectPointerAfter(const ObjCObjectPointerType *T,2308 raw_ostream &OS) {}2309 2310static2311const TemplateArgument &getArgument(const TemplateArgument &A) { return A; }2312 2313static const TemplateArgument &getArgument(const TemplateArgumentLoc &A) {2314 return A.getArgument();2315}2316 2317static void printArgument(const TemplateArgument &A, const PrintingPolicy &PP,2318 llvm::raw_ostream &OS, bool IncludeType) {2319 A.print(PP, OS, IncludeType);2320}2321 2322static void printArgument(const TemplateArgumentLoc &A,2323 const PrintingPolicy &PP, llvm::raw_ostream &OS,2324 bool IncludeType) {2325 const TemplateArgument::ArgKind &Kind = A.getArgument().getKind();2326 if (Kind == TemplateArgument::ArgKind::Type)2327 return A.getTypeSourceInfo()->getType().print(OS, PP);2328 return A.getArgument().print(PP, OS, IncludeType);2329}2330 2331static bool isSubstitutedTemplateArgument(ASTContext &Ctx, TemplateArgument Arg,2332 TemplateArgument Pattern,2333 ArrayRef<TemplateArgument> Args,2334 unsigned Depth);2335 2336static bool isSubstitutedType(ASTContext &Ctx, QualType T, QualType Pattern,2337 ArrayRef<TemplateArgument> Args, unsigned Depth) {2338 if (Ctx.hasSameType(T, Pattern))2339 return true;2340 2341 // A type parameter matches its argument.2342 if (auto *TTPT = Pattern->getAsCanonical<TemplateTypeParmType>()) {2343 if (TTPT->getDepth() == Depth && TTPT->getIndex() < Args.size() &&2344 Args[TTPT->getIndex()].getKind() == TemplateArgument::Type) {2345 QualType SubstArg = Ctx.getQualifiedType(2346 Args[TTPT->getIndex()].getAsType(), Pattern.getQualifiers());2347 return Ctx.hasSameType(SubstArg, T);2348 }2349 return false;2350 }2351 2352 // FIXME: Recurse into array types.2353 2354 // All other cases will need the types to be identically qualified.2355 Qualifiers TQual, PatQual;2356 T = Ctx.getUnqualifiedArrayType(T, TQual);2357 Pattern = Ctx.getUnqualifiedArrayType(Pattern, PatQual);2358 if (TQual != PatQual)2359 return false;2360 2361 // Recurse into pointer-like types.2362 {2363 QualType TPointee = T->getPointeeType();2364 QualType PPointee = Pattern->getPointeeType();2365 if (!TPointee.isNull() && !PPointee.isNull())2366 return T->getTypeClass() == Pattern->getTypeClass() &&2367 isSubstitutedType(Ctx, TPointee, PPointee, Args, Depth);2368 }2369 2370 // Recurse into template specialization types.2371 if (auto *PTST =2372 Pattern.getCanonicalType()->getAs<TemplateSpecializationType>()) {2373 TemplateName Template;2374 ArrayRef<TemplateArgument> TemplateArgs;2375 if (auto *TTST = T->getAs<TemplateSpecializationType>()) {2376 Template = TTST->getTemplateName();2377 TemplateArgs = TTST->template_arguments();2378 } else if (auto *CTSD = dyn_cast_or_null<ClassTemplateSpecializationDecl>(2379 T->getAsCXXRecordDecl())) {2380 Template = TemplateName(CTSD->getSpecializedTemplate());2381 TemplateArgs = CTSD->getTemplateArgs().asArray();2382 } else {2383 return false;2384 }2385 2386 if (!isSubstitutedTemplateArgument(Ctx, Template, PTST->getTemplateName(),2387 Args, Depth))2388 return false;2389 if (TemplateArgs.size() != PTST->template_arguments().size())2390 return false;2391 for (unsigned I = 0, N = TemplateArgs.size(); I != N; ++I)2392 if (!isSubstitutedTemplateArgument(2393 Ctx, TemplateArgs[I], PTST->template_arguments()[I], Args, Depth))2394 return false;2395 return true;2396 }2397 2398 // FIXME: Handle more cases.2399 return false;2400}2401 2402/// Evaluates the expression template argument 'Pattern' and returns true2403/// if 'Arg' evaluates to the same result.2404static bool templateArgumentExpressionsEqual(ASTContext const &Ctx,2405 TemplateArgument const &Pattern,2406 TemplateArgument const &Arg) {2407 if (Pattern.getKind() != TemplateArgument::Expression)2408 return false;2409 2410 // Can't evaluate value-dependent expressions so bail early2411 Expr const *pattern_expr = Pattern.getAsExpr();2412 if (pattern_expr->isValueDependent() ||2413 !pattern_expr->isIntegerConstantExpr(Ctx))2414 return false;2415 2416 if (Arg.getKind() == TemplateArgument::Integral)2417 return llvm::APSInt::isSameValue(pattern_expr->EvaluateKnownConstInt(Ctx),2418 Arg.getAsIntegral());2419 2420 if (Arg.getKind() == TemplateArgument::Expression) {2421 Expr const *args_expr = Arg.getAsExpr();2422 if (args_expr->isValueDependent() || !args_expr->isIntegerConstantExpr(Ctx))2423 return false;2424 2425 return llvm::APSInt::isSameValue(args_expr->EvaluateKnownConstInt(Ctx),2426 pattern_expr->EvaluateKnownConstInt(Ctx));2427 }2428 2429 return false;2430}2431 2432static bool isSubstitutedTemplateArgument(ASTContext &Ctx, TemplateArgument Arg,2433 TemplateArgument Pattern,2434 ArrayRef<TemplateArgument> Args,2435 unsigned Depth) {2436 Arg = Ctx.getCanonicalTemplateArgument(Arg);2437 Pattern = Ctx.getCanonicalTemplateArgument(Pattern);2438 if (Arg.structurallyEquals(Pattern))2439 return true;2440 2441 if (Pattern.getKind() == TemplateArgument::Expression) {2442 if (auto *DRE =2443 dyn_cast<DeclRefExpr>(Pattern.getAsExpr()->IgnoreParenImpCasts())) {2444 if (auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(DRE->getDecl()))2445 return NTTP->getDepth() == Depth && Args.size() > NTTP->getIndex() &&2446 Args[NTTP->getIndex()].structurallyEquals(Arg);2447 }2448 }2449 2450 if (templateArgumentExpressionsEqual(Ctx, Pattern, Arg))2451 return true;2452 2453 if (Arg.getKind() != Pattern.getKind())2454 return false;2455 2456 if (Arg.getKind() == TemplateArgument::Type)2457 return isSubstitutedType(Ctx, Arg.getAsType(), Pattern.getAsType(), Args,2458 Depth);2459 2460 if (Arg.getKind() == TemplateArgument::Template) {2461 TemplateDecl *PatTD = Pattern.getAsTemplate().getAsTemplateDecl();2462 if (auto *TTPD = dyn_cast_or_null<TemplateTemplateParmDecl>(PatTD))2463 return TTPD->getDepth() == Depth && Args.size() > TTPD->getIndex() &&2464 Ctx.getCanonicalTemplateArgument(Args[TTPD->getIndex()])2465 .structurallyEquals(Arg);2466 }2467 2468 // FIXME: Handle more cases.2469 return false;2470}2471 2472bool clang::isSubstitutedDefaultArgument(ASTContext &Ctx, TemplateArgument Arg,2473 const NamedDecl *Param,2474 ArrayRef<TemplateArgument> Args,2475 unsigned Depth) {2476 // An empty pack is equivalent to not providing a pack argument.2477 if (Arg.getKind() == TemplateArgument::Pack && Arg.pack_size() == 0)2478 return true;2479 2480 if (auto *TTPD = dyn_cast<TemplateTypeParmDecl>(Param)) {2481 return TTPD->hasDefaultArgument() &&2482 isSubstitutedTemplateArgument(2483 Ctx, Arg, TTPD->getDefaultArgument().getArgument(), Args, Depth);2484 } else if (auto *TTPD = dyn_cast<TemplateTemplateParmDecl>(Param)) {2485 return TTPD->hasDefaultArgument() &&2486 isSubstitutedTemplateArgument(2487 Ctx, Arg, TTPD->getDefaultArgument().getArgument(), Args, Depth);2488 } else if (auto *NTTPD = dyn_cast<NonTypeTemplateParmDecl>(Param)) {2489 return NTTPD->hasDefaultArgument() &&2490 isSubstitutedTemplateArgument(2491 Ctx, Arg, NTTPD->getDefaultArgument().getArgument(), Args,2492 Depth);2493 }2494 return false;2495}2496 2497template <typename TA>2498static void2499printTo(raw_ostream &OS, ArrayRef<TA> Args, const PrintingPolicy &Policy,2500 const TemplateParameterList *TPL, bool IsPack, unsigned ParmIndex) {2501 // Drop trailing template arguments that match default arguments.2502 if (TPL && Policy.SuppressDefaultTemplateArgs && !Policy.PrintAsCanonical &&2503 !Args.empty() && !IsPack && Args.size() <= TPL->size()) {2504 llvm::SmallVector<TemplateArgument, 8> OrigArgs;2505 for (const TA &A : Args)2506 OrigArgs.push_back(getArgument(A));2507 while (!Args.empty() && getArgument(Args.back()).getIsDefaulted())2508 Args = Args.drop_back();2509 }2510 2511 const char *Comma = Policy.MSVCFormatting ? "," : ", ";2512 if (!IsPack)2513 OS << '<';2514 2515 bool NeedSpace = false;2516 bool FirstArg = true;2517 for (const auto &Arg : Args) {2518 // Print the argument into a string.2519 SmallString<128> Buf;2520 llvm::raw_svector_ostream ArgOS(Buf);2521 const TemplateArgument &Argument = getArgument(Arg);2522 if (Argument.getKind() == TemplateArgument::Pack) {2523 if (Argument.pack_size() && !FirstArg)2524 OS << Comma;2525 printTo(ArgOS, Argument.getPackAsArray(), Policy, TPL,2526 /*IsPack*/ true, ParmIndex);2527 } else {2528 if (!FirstArg)2529 OS << Comma;2530 // Tries to print the argument with location info if exists.2531 printArgument(Arg, Policy, ArgOS,2532 TemplateParameterList::shouldIncludeTypeForArgument(2533 Policy, TPL, ParmIndex));2534 }2535 StringRef ArgString = ArgOS.str();2536 2537 // If this is the first argument and its string representation2538 // begins with the global scope specifier ('::foo'), add a space2539 // to avoid printing the diagraph '<:'.2540 if (FirstArg && ArgString.starts_with(":"))2541 OS << ' ';2542 2543 OS << ArgString;2544 2545 // If the last character of our string is '>', add another space to2546 // keep the two '>''s separate tokens.2547 if (!ArgString.empty()) {2548 NeedSpace = Policy.SplitTemplateClosers && ArgString.back() == '>';2549 FirstArg = false;2550 }2551 2552 // Use same template parameter for all elements of Pack2553 if (!IsPack)2554 ParmIndex++;2555 }2556 2557 if (!IsPack) {2558 if (NeedSpace)2559 OS << ' ';2560 OS << '>';2561 }2562}2563 2564void clang::printTemplateArgumentList(raw_ostream &OS,2565 const TemplateArgumentListInfo &Args,2566 const PrintingPolicy &Policy,2567 const TemplateParameterList *TPL) {2568 printTemplateArgumentList(OS, Args.arguments(), Policy, TPL);2569}2570 2571void clang::printTemplateArgumentList(raw_ostream &OS,2572 ArrayRef<TemplateArgument> Args,2573 const PrintingPolicy &Policy,2574 const TemplateParameterList *TPL) {2575 PrintingPolicy InnerPolicy = Policy;2576 InnerPolicy.SuppressScope = false;2577 printTo(OS, Args, InnerPolicy, TPL, /*isPack*/ false, /*parmIndex*/ 0);2578}2579 2580void clang::printTemplateArgumentList(raw_ostream &OS,2581 ArrayRef<TemplateArgumentLoc> Args,2582 const PrintingPolicy &Policy,2583 const TemplateParameterList *TPL) {2584 PrintingPolicy InnerPolicy = Policy;2585 InnerPolicy.SuppressScope = false;2586 printTo(OS, Args, InnerPolicy, TPL, /*isPack*/ false, /*parmIndex*/ 0);2587}2588 2589std::string PointerAuthQualifier::getAsString() const {2590 LangOptions LO;2591 return getAsString(PrintingPolicy(LO));2592}2593 2594std::string PointerAuthQualifier::getAsString(const PrintingPolicy &P) const {2595 SmallString<64> Buf;2596 llvm::raw_svector_ostream StrOS(Buf);2597 print(StrOS, P);2598 return StrOS.str().str();2599}2600 2601bool PointerAuthQualifier::isEmptyWhenPrinted(const PrintingPolicy &P) const {2602 return !isPresent();2603}2604 2605void PointerAuthQualifier::print(raw_ostream &OS,2606 const PrintingPolicy &P) const {2607 if (!isPresent())2608 return;2609 2610 OS << "__ptrauth(";2611 OS << getKey();2612 OS << "," << unsigned(isAddressDiscriminated()) << ","2613 << getExtraDiscriminator() << ")";2614}2615 2616std::string Qualifiers::getAsString() const {2617 LangOptions LO;2618 return getAsString(PrintingPolicy(LO));2619}2620 2621// Appends qualifiers to the given string, separated by spaces. Will2622// prefix a space if the string is non-empty. Will not append a final2623// space.2624std::string Qualifiers::getAsString(const PrintingPolicy &Policy) const {2625 SmallString<64> Buf;2626 llvm::raw_svector_ostream StrOS(Buf);2627 print(StrOS, Policy);2628 return std::string(StrOS.str());2629}2630 2631bool Qualifiers::isEmptyWhenPrinted(const PrintingPolicy &Policy) const {2632 if (getCVRQualifiers())2633 return false;2634 2635 if (getAddressSpace() != LangAS::Default)2636 return false;2637 2638 if (getObjCGCAttr())2639 return false;2640 2641 if (Qualifiers::ObjCLifetime lifetime = getObjCLifetime())2642 if (!(lifetime == Qualifiers::OCL_Strong && Policy.SuppressStrongLifetime))2643 return false;2644 2645 if (PointerAuthQualifier PointerAuth = getPointerAuth();2646 PointerAuth && !PointerAuth.isEmptyWhenPrinted(Policy))2647 return false;2648 2649 return true;2650}2651 2652std::string Qualifiers::getAddrSpaceAsString(LangAS AS) {2653 switch (AS) {2654 case LangAS::Default:2655 return "";2656 case LangAS::opencl_global:2657 case LangAS::sycl_global:2658 return "__global";2659 case LangAS::opencl_local:2660 case LangAS::sycl_local:2661 return "__local";2662 case LangAS::opencl_private:2663 case LangAS::sycl_private:2664 return "__private";2665 case LangAS::opencl_constant:2666 return "__constant";2667 case LangAS::opencl_generic:2668 return "__generic";2669 case LangAS::opencl_global_device:2670 case LangAS::sycl_global_device:2671 return "__global_device";2672 case LangAS::opencl_global_host:2673 case LangAS::sycl_global_host:2674 return "__global_host";2675 case LangAS::cuda_device:2676 return "__device__";2677 case LangAS::cuda_constant:2678 return "__constant__";2679 case LangAS::cuda_shared:2680 return "__shared__";2681 case LangAS::ptr32_sptr:2682 return "__sptr __ptr32";2683 case LangAS::ptr32_uptr:2684 return "__uptr __ptr32";2685 case LangAS::ptr64:2686 return "__ptr64";2687 case LangAS::hlsl_groupshared:2688 return "groupshared";2689 case LangAS::hlsl_constant:2690 return "hlsl_constant";2691 case LangAS::hlsl_private:2692 return "hlsl_private";2693 case LangAS::hlsl_device:2694 return "hlsl_device";2695 case LangAS::hlsl_input:2696 return "hlsl_input";2697 case LangAS::wasm_funcref:2698 return "__funcref";2699 default:2700 return std::to_string(toTargetAddressSpace(AS));2701 }2702}2703 2704// Appends qualifiers to the given string, separated by spaces. Will2705// prefix a space if the string is non-empty. Will not append a final2706// space.2707void Qualifiers::print(raw_ostream &OS, const PrintingPolicy& Policy,2708 bool appendSpaceIfNonEmpty) const {2709 bool addSpace = false;2710 2711 unsigned quals = getCVRQualifiers();2712 if (quals) {2713 AppendTypeQualList(OS, quals, Policy.Restrict);2714 addSpace = true;2715 }2716 if (hasUnaligned()) {2717 if (addSpace)2718 OS << ' ';2719 OS << "__unaligned";2720 addSpace = true;2721 }2722 auto ASStr = getAddrSpaceAsString(getAddressSpace());2723 if (!ASStr.empty()) {2724 if (addSpace)2725 OS << ' ';2726 addSpace = true;2727 // Wrap target address space into an attribute syntax2728 if (isTargetAddressSpace(getAddressSpace()))2729 OS << "__attribute__((address_space(" << ASStr << ")))";2730 else2731 OS << ASStr;2732 }2733 2734 if (Qualifiers::GC gc = getObjCGCAttr()) {2735 if (addSpace)2736 OS << ' ';2737 addSpace = true;2738 if (gc == Qualifiers::Weak)2739 OS << "__weak";2740 else2741 OS << "__strong";2742 }2743 if (Qualifiers::ObjCLifetime lifetime = getObjCLifetime()) {2744 if (!(lifetime == Qualifiers::OCL_Strong && Policy.SuppressStrongLifetime)){2745 if (addSpace)2746 OS << ' ';2747 addSpace = true;2748 }2749 2750 switch (lifetime) {2751 case Qualifiers::OCL_None: llvm_unreachable("none but true");2752 case Qualifiers::OCL_ExplicitNone: OS << "__unsafe_unretained"; break;2753 case Qualifiers::OCL_Strong:2754 if (!Policy.SuppressStrongLifetime)2755 OS << "__strong";2756 break;2757 2758 case Qualifiers::OCL_Weak: OS << "__weak"; break;2759 case Qualifiers::OCL_Autoreleasing: OS << "__autoreleasing"; break;2760 }2761 }2762 2763 if (PointerAuthQualifier PointerAuth = getPointerAuth()) {2764 if (addSpace)2765 OS << ' ';2766 addSpace = true;2767 2768 PointerAuth.print(OS, Policy);2769 }2770 2771 if (appendSpaceIfNonEmpty && addSpace)2772 OS << ' ';2773}2774 2775std::string QualType::getAsString() const {2776 return getAsString(split(), LangOptions());2777}2778 2779std::string QualType::getAsString(const PrintingPolicy &Policy) const {2780 std::string S;2781 getAsStringInternal(S, Policy);2782 return S;2783}2784 2785std::string QualType::getAsString(const Type *ty, Qualifiers qs,2786 const PrintingPolicy &Policy) {2787 std::string buffer;2788 getAsStringInternal(ty, qs, buffer, Policy);2789 return buffer;2790}2791 2792void QualType::print(raw_ostream &OS, const PrintingPolicy &Policy,2793 const Twine &PlaceHolder, unsigned Indentation) const {2794 print(splitAccordingToPolicy(*this, Policy), OS, Policy, PlaceHolder,2795 Indentation);2796}2797 2798void QualType::print(const Type *ty, Qualifiers qs,2799 raw_ostream &OS, const PrintingPolicy &policy,2800 const Twine &PlaceHolder, unsigned Indentation) {2801 SmallString<128> PHBuf;2802 StringRef PH = PlaceHolder.toStringRef(PHBuf);2803 2804 TypePrinter(policy, Indentation).print(ty, qs, OS, PH);2805}2806 2807void QualType::getAsStringInternal(std::string &Str,2808 const PrintingPolicy &Policy) const {2809 return getAsStringInternal(splitAccordingToPolicy(*this, Policy), Str,2810 Policy);2811}2812 2813void QualType::getAsStringInternal(const Type *ty, Qualifiers qs,2814 std::string &buffer,2815 const PrintingPolicy &policy) {2816 SmallString<256> Buf;2817 llvm::raw_svector_ostream StrOS(Buf);2818 TypePrinter(policy).print(ty, qs, StrOS, buffer);2819 std::string str = std::string(StrOS.str());2820 buffer.swap(str);2821}2822 2823raw_ostream &clang::operator<<(raw_ostream &OS, QualType QT) {2824 SplitQualType S = QT.split();2825 TypePrinter(LangOptions()).print(S.Ty, S.Quals, OS, /*PlaceHolder=*/"");2826 return OS;2827}2828