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