Path: blob/main/contrib/llvm-project/clang/lib/AST/DeclPrinter.cpp
35260 views
//===--- DeclPrinter.cpp - Printing implementation for Decl ASTs ----------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This file implements the Decl::print method, which pretty prints the9// AST back out to C/Objective-C/C++/Objective-C++ code.10//11//===----------------------------------------------------------------------===//12#include "clang/AST/ASTContext.h"13#include "clang/AST/Attr.h"14#include "clang/AST/Decl.h"15#include "clang/AST/DeclCXX.h"16#include "clang/AST/DeclObjC.h"17#include "clang/AST/DeclTemplate.h"18#include "clang/AST/DeclVisitor.h"19#include "clang/AST/Expr.h"20#include "clang/AST/ExprCXX.h"21#include "clang/AST/PrettyPrinter.h"22#include "clang/Basic/Module.h"23#include "clang/Basic/SourceManager.h"24#include "llvm/Support/raw_ostream.h"25using namespace clang;2627namespace {28class DeclPrinter : public DeclVisitor<DeclPrinter> {29raw_ostream &Out;30PrintingPolicy Policy;31const ASTContext &Context;32unsigned Indentation;33bool PrintInstantiation;3435raw_ostream& Indent() { return Indent(Indentation); }36raw_ostream& Indent(unsigned Indentation);37void ProcessDeclGroup(SmallVectorImpl<Decl*>& Decls);3839void Print(AccessSpecifier AS);40void PrintConstructorInitializers(CXXConstructorDecl *CDecl,41std::string &Proto);4243/// Print an Objective-C method type in parentheses.44///45/// \param Quals The Objective-C declaration qualifiers.46/// \param T The type to print.47void PrintObjCMethodType(ASTContext &Ctx, Decl::ObjCDeclQualifier Quals,48QualType T);4950void PrintObjCTypeParams(ObjCTypeParamList *Params);5152public:53DeclPrinter(raw_ostream &Out, const PrintingPolicy &Policy,54const ASTContext &Context, unsigned Indentation = 0,55bool PrintInstantiation = false)56: Out(Out), Policy(Policy), Context(Context), Indentation(Indentation),57PrintInstantiation(PrintInstantiation) {}5859void VisitDeclContext(DeclContext *DC, bool Indent = true);6061void VisitTranslationUnitDecl(TranslationUnitDecl *D);62void VisitTypedefDecl(TypedefDecl *D);63void VisitTypeAliasDecl(TypeAliasDecl *D);64void VisitEnumDecl(EnumDecl *D);65void VisitRecordDecl(RecordDecl *D);66void VisitEnumConstantDecl(EnumConstantDecl *D);67void VisitEmptyDecl(EmptyDecl *D);68void VisitFunctionDecl(FunctionDecl *D);69void VisitFriendDecl(FriendDecl *D);70void VisitFieldDecl(FieldDecl *D);71void VisitVarDecl(VarDecl *D);72void VisitLabelDecl(LabelDecl *D);73void VisitParmVarDecl(ParmVarDecl *D);74void VisitFileScopeAsmDecl(FileScopeAsmDecl *D);75void VisitTopLevelStmtDecl(TopLevelStmtDecl *D);76void VisitImportDecl(ImportDecl *D);77void VisitStaticAssertDecl(StaticAssertDecl *D);78void VisitNamespaceDecl(NamespaceDecl *D);79void VisitUsingDirectiveDecl(UsingDirectiveDecl *D);80void VisitNamespaceAliasDecl(NamespaceAliasDecl *D);81void VisitCXXRecordDecl(CXXRecordDecl *D);82void VisitLinkageSpecDecl(LinkageSpecDecl *D);83void VisitTemplateDecl(const TemplateDecl *D);84void VisitFunctionTemplateDecl(FunctionTemplateDecl *D);85void VisitClassTemplateDecl(ClassTemplateDecl *D);86void VisitClassTemplateSpecializationDecl(87ClassTemplateSpecializationDecl *D);88void VisitClassTemplatePartialSpecializationDecl(89ClassTemplatePartialSpecializationDecl *D);90void VisitObjCMethodDecl(ObjCMethodDecl *D);91void VisitObjCImplementationDecl(ObjCImplementationDecl *D);92void VisitObjCInterfaceDecl(ObjCInterfaceDecl *D);93void VisitObjCProtocolDecl(ObjCProtocolDecl *D);94void VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D);95void VisitObjCCategoryDecl(ObjCCategoryDecl *D);96void VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *D);97void VisitObjCPropertyDecl(ObjCPropertyDecl *D);98void VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D);99void VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D);100void VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D);101void VisitUsingDecl(UsingDecl *D);102void VisitUsingEnumDecl(UsingEnumDecl *D);103void VisitUsingShadowDecl(UsingShadowDecl *D);104void VisitOMPThreadPrivateDecl(OMPThreadPrivateDecl *D);105void VisitOMPAllocateDecl(OMPAllocateDecl *D);106void VisitOMPRequiresDecl(OMPRequiresDecl *D);107void VisitOMPDeclareReductionDecl(OMPDeclareReductionDecl *D);108void VisitOMPDeclareMapperDecl(OMPDeclareMapperDecl *D);109void VisitOMPCapturedExprDecl(OMPCapturedExprDecl *D);110void VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *TTP);111void VisitNonTypeTemplateParmDecl(const NonTypeTemplateParmDecl *NTTP);112void VisitHLSLBufferDecl(HLSLBufferDecl *D);113114void printTemplateParameters(const TemplateParameterList *Params,115bool OmitTemplateKW = false);116void printTemplateArguments(llvm::ArrayRef<TemplateArgument> Args,117const TemplateParameterList *Params);118void printTemplateArguments(llvm::ArrayRef<TemplateArgumentLoc> Args,119const TemplateParameterList *Params);120enum class AttrPosAsWritten { Default = 0, Left, Right };121bool122prettyPrintAttributes(const Decl *D,123AttrPosAsWritten Pos = AttrPosAsWritten::Default);124void prettyPrintPragmas(Decl *D);125void printDeclType(QualType T, StringRef DeclName, bool Pack = false);126};127}128129void Decl::print(raw_ostream &Out, unsigned Indentation,130bool PrintInstantiation) const {131print(Out, getASTContext().getPrintingPolicy(), Indentation, PrintInstantiation);132}133134void Decl::print(raw_ostream &Out, const PrintingPolicy &Policy,135unsigned Indentation, bool PrintInstantiation) const {136DeclPrinter Printer(Out, Policy, getASTContext(), Indentation,137PrintInstantiation);138Printer.Visit(const_cast<Decl*>(this));139}140141void TemplateParameterList::print(raw_ostream &Out, const ASTContext &Context,142bool OmitTemplateKW) const {143print(Out, Context, Context.getPrintingPolicy(), OmitTemplateKW);144}145146void TemplateParameterList::print(raw_ostream &Out, const ASTContext &Context,147const PrintingPolicy &Policy,148bool OmitTemplateKW) const {149DeclPrinter Printer(Out, Policy, Context);150Printer.printTemplateParameters(this, OmitTemplateKW);151}152153static QualType GetBaseType(QualType T) {154// FIXME: This should be on the Type class!155QualType BaseType = T;156while (!BaseType->isSpecifierType()) {157if (const PointerType *PTy = BaseType->getAs<PointerType>())158BaseType = PTy->getPointeeType();159else if (const ObjCObjectPointerType *OPT =160BaseType->getAs<ObjCObjectPointerType>())161BaseType = OPT->getPointeeType();162else if (const BlockPointerType *BPy = BaseType->getAs<BlockPointerType>())163BaseType = BPy->getPointeeType();164else if (const ArrayType *ATy = dyn_cast<ArrayType>(BaseType))165BaseType = ATy->getElementType();166else if (const FunctionType *FTy = BaseType->getAs<FunctionType>())167BaseType = FTy->getReturnType();168else if (const VectorType *VTy = BaseType->getAs<VectorType>())169BaseType = VTy->getElementType();170else if (const ReferenceType *RTy = BaseType->getAs<ReferenceType>())171BaseType = RTy->getPointeeType();172else if (const AutoType *ATy = BaseType->getAs<AutoType>())173BaseType = ATy->getDeducedType();174else if (const ParenType *PTy = BaseType->getAs<ParenType>())175BaseType = PTy->desugar();176else177// This must be a syntax error.178break;179}180return BaseType;181}182183static QualType getDeclType(Decl* D) {184if (TypedefNameDecl* TDD = dyn_cast<TypedefNameDecl>(D))185return TDD->getUnderlyingType();186if (ValueDecl* VD = dyn_cast<ValueDecl>(D))187return VD->getType();188return QualType();189}190191void Decl::printGroup(Decl** Begin, unsigned NumDecls,192raw_ostream &Out, const PrintingPolicy &Policy,193unsigned Indentation) {194if (NumDecls == 1) {195(*Begin)->print(Out, Policy, Indentation);196return;197}198199Decl** End = Begin + NumDecls;200TagDecl* TD = dyn_cast<TagDecl>(*Begin);201if (TD)202++Begin;203204PrintingPolicy SubPolicy(Policy);205206bool isFirst = true;207for ( ; Begin != End; ++Begin) {208if (isFirst) {209if(TD)210SubPolicy.IncludeTagDefinition = true;211SubPolicy.SuppressSpecifiers = false;212isFirst = false;213} else {214if (!isFirst) Out << ", ";215SubPolicy.IncludeTagDefinition = false;216SubPolicy.SuppressSpecifiers = true;217}218219(*Begin)->print(Out, SubPolicy, Indentation);220}221}222223LLVM_DUMP_METHOD void DeclContext::dumpDeclContext() const {224// Get the translation unit225const DeclContext *DC = this;226while (!DC->isTranslationUnit())227DC = DC->getParent();228229ASTContext &Ctx = cast<TranslationUnitDecl>(DC)->getASTContext();230DeclPrinter Printer(llvm::errs(), Ctx.getPrintingPolicy(), Ctx, 0);231Printer.VisitDeclContext(const_cast<DeclContext *>(this), /*Indent=*/false);232}233234raw_ostream& DeclPrinter::Indent(unsigned Indentation) {235for (unsigned i = 0; i != Indentation; ++i)236Out << " ";237return Out;238}239240static DeclPrinter::AttrPosAsWritten getPosAsWritten(const Attr *A,241const Decl *D) {242SourceLocation ALoc = A->getLoc();243SourceLocation DLoc = D->getLocation();244const ASTContext &C = D->getASTContext();245if (ALoc.isInvalid() || DLoc.isInvalid())246return DeclPrinter::AttrPosAsWritten::Left;247248if (C.getSourceManager().isBeforeInTranslationUnit(ALoc, DLoc))249return DeclPrinter::AttrPosAsWritten::Left;250251return DeclPrinter::AttrPosAsWritten::Right;252}253254// returns true if an attribute was printed.255bool DeclPrinter::prettyPrintAttributes(const Decl *D,256AttrPosAsWritten Pos /*=Default*/) {257bool hasPrinted = false;258259if (D->hasAttrs()) {260const AttrVec &Attrs = D->getAttrs();261for (auto *A : Attrs) {262if (A->isInherited() || A->isImplicit())263continue;264// Print out the keyword attributes, they aren't regular attributes.265if (Policy.PolishForDeclaration && !A->isKeywordAttribute())266continue;267switch (A->getKind()) {268#define ATTR(X)269#define PRAGMA_SPELLING_ATTR(X) case attr::X:270#include "clang/Basic/AttrList.inc"271break;272default:273AttrPosAsWritten APos = getPosAsWritten(A, D);274assert(APos != AttrPosAsWritten::Default &&275"Default not a valid for an attribute location");276if (Pos == AttrPosAsWritten::Default || Pos == APos) {277if (Pos != AttrPosAsWritten::Left)278Out << ' ';279A->printPretty(Out, Policy);280hasPrinted = true;281if (Pos == AttrPosAsWritten::Left)282Out << ' ';283}284break;285}286}287}288return hasPrinted;289}290291void DeclPrinter::prettyPrintPragmas(Decl *D) {292if (Policy.PolishForDeclaration)293return;294295if (D->hasAttrs()) {296AttrVec &Attrs = D->getAttrs();297for (auto *A : Attrs) {298switch (A->getKind()) {299#define ATTR(X)300#define PRAGMA_SPELLING_ATTR(X) case attr::X:301#include "clang/Basic/AttrList.inc"302A->printPretty(Out, Policy);303Indent();304break;305default:306break;307}308}309}310}311312void DeclPrinter::printDeclType(QualType T, StringRef DeclName, bool Pack) {313// Normally, a PackExpansionType is written as T[3]... (for instance, as a314// template argument), but if it is the type of a declaration, the ellipsis315// is placed before the name being declared.316if (auto *PET = T->getAs<PackExpansionType>()) {317Pack = true;318T = PET->getPattern();319}320T.print(Out, Policy, (Pack ? "..." : "") + DeclName, Indentation);321}322323void DeclPrinter::ProcessDeclGroup(SmallVectorImpl<Decl*>& Decls) {324this->Indent();325Decl::printGroup(Decls.data(), Decls.size(), Out, Policy, Indentation);326Out << ";\n";327Decls.clear();328329}330331void DeclPrinter::Print(AccessSpecifier AS) {332const auto AccessSpelling = getAccessSpelling(AS);333if (AccessSpelling.empty())334llvm_unreachable("No access specifier!");335Out << AccessSpelling;336}337338void DeclPrinter::PrintConstructorInitializers(CXXConstructorDecl *CDecl,339std::string &Proto) {340bool HasInitializerList = false;341for (const auto *BMInitializer : CDecl->inits()) {342if (BMInitializer->isInClassMemberInitializer())343continue;344if (!BMInitializer->isWritten())345continue;346347if (!HasInitializerList) {348Proto += " : ";349Out << Proto;350Proto.clear();351HasInitializerList = true;352} else353Out << ", ";354355if (BMInitializer->isAnyMemberInitializer()) {356FieldDecl *FD = BMInitializer->getAnyMember();357Out << *FD;358} else if (BMInitializer->isDelegatingInitializer()) {359Out << CDecl->getNameAsString();360} else {361Out << QualType(BMInitializer->getBaseClass(), 0).getAsString(Policy);362}363364if (Expr *Init = BMInitializer->getInit()) {365bool OutParens = !isa<InitListExpr>(Init);366367if (OutParens)368Out << "(";369370if (ExprWithCleanups *Tmp = dyn_cast<ExprWithCleanups>(Init))371Init = Tmp->getSubExpr();372373Init = Init->IgnoreParens();374375Expr *SimpleInit = nullptr;376Expr **Args = nullptr;377unsigned NumArgs = 0;378if (ParenListExpr *ParenList = dyn_cast<ParenListExpr>(Init)) {379Args = ParenList->getExprs();380NumArgs = ParenList->getNumExprs();381} else if (CXXConstructExpr *Construct =382dyn_cast<CXXConstructExpr>(Init)) {383Args = Construct->getArgs();384NumArgs = Construct->getNumArgs();385} else386SimpleInit = Init;387388if (SimpleInit)389SimpleInit->printPretty(Out, nullptr, Policy, Indentation, "\n",390&Context);391else {392for (unsigned I = 0; I != NumArgs; ++I) {393assert(Args[I] != nullptr && "Expected non-null Expr");394if (isa<CXXDefaultArgExpr>(Args[I]))395break;396397if (I)398Out << ", ";399Args[I]->printPretty(Out, nullptr, Policy, Indentation, "\n",400&Context);401}402}403404if (OutParens)405Out << ")";406} else {407Out << "()";408}409410if (BMInitializer->isPackExpansion())411Out << "...";412}413}414415//----------------------------------------------------------------------------416// Common C declarations417//----------------------------------------------------------------------------418419void DeclPrinter::VisitDeclContext(DeclContext *DC, bool Indent) {420if (Policy.TerseOutput)421return;422423if (Indent)424Indentation += Policy.Indentation;425426SmallVector<Decl*, 2> Decls;427for (DeclContext::decl_iterator D = DC->decls_begin(), DEnd = DC->decls_end();428D != DEnd; ++D) {429430// Don't print ObjCIvarDecls, as they are printed when visiting the431// containing ObjCInterfaceDecl.432if (isa<ObjCIvarDecl>(*D))433continue;434435// Skip over implicit declarations in pretty-printing mode.436if (D->isImplicit())437continue;438439// Don't print implicit specializations, as they are printed when visiting440// corresponding templates.441if (auto FD = dyn_cast<FunctionDecl>(*D))442if (FD->getTemplateSpecializationKind() == TSK_ImplicitInstantiation &&443!isa<ClassTemplateSpecializationDecl>(DC))444continue;445446// The next bits of code handle stuff like "struct {int x;} a,b"; we're447// forced to merge the declarations because there's no other way to448// refer to the struct in question. When that struct is named instead, we449// also need to merge to avoid splitting off a stand-alone struct450// declaration that produces the warning ext_no_declarators in some451// contexts.452//453// This limited merging is safe without a bunch of other checks because it454// only merges declarations directly referring to the tag, not typedefs.455//456// Check whether the current declaration should be grouped with a previous457// non-free-standing tag declaration.458QualType CurDeclType = getDeclType(*D);459if (!Decls.empty() && !CurDeclType.isNull()) {460QualType BaseType = GetBaseType(CurDeclType);461if (!BaseType.isNull() && isa<ElaboratedType>(BaseType) &&462cast<ElaboratedType>(BaseType)->getOwnedTagDecl() == Decls[0]) {463Decls.push_back(*D);464continue;465}466}467468// If we have a merged group waiting to be handled, handle it now.469if (!Decls.empty())470ProcessDeclGroup(Decls);471472// If the current declaration is not a free standing declaration, save it473// so we can merge it with the subsequent declaration(s) using it.474if (isa<TagDecl>(*D) && !cast<TagDecl>(*D)->isFreeStanding()) {475Decls.push_back(*D);476continue;477}478479if (isa<AccessSpecDecl>(*D)) {480Indentation -= Policy.Indentation;481this->Indent();482Print(D->getAccess());483Out << ":\n";484Indentation += Policy.Indentation;485continue;486}487488this->Indent();489Visit(*D);490491// FIXME: Need to be able to tell the DeclPrinter when492const char *Terminator = nullptr;493if (isa<OMPThreadPrivateDecl>(*D) || isa<OMPDeclareReductionDecl>(*D) ||494isa<OMPDeclareMapperDecl>(*D) || isa<OMPRequiresDecl>(*D) ||495isa<OMPAllocateDecl>(*D))496Terminator = nullptr;497else if (isa<ObjCMethodDecl>(*D) && cast<ObjCMethodDecl>(*D)->hasBody())498Terminator = nullptr;499else if (auto FD = dyn_cast<FunctionDecl>(*D)) {500if (FD->doesThisDeclarationHaveABody() && !FD->isDefaulted())501Terminator = nullptr;502else503Terminator = ";";504} else if (auto TD = dyn_cast<FunctionTemplateDecl>(*D)) {505if (TD->getTemplatedDecl()->doesThisDeclarationHaveABody())506Terminator = nullptr;507else508Terminator = ";";509} else if (isa<NamespaceDecl, LinkageSpecDecl, ObjCImplementationDecl,510ObjCInterfaceDecl, ObjCProtocolDecl, ObjCCategoryImplDecl,511ObjCCategoryDecl, HLSLBufferDecl>(*D))512Terminator = nullptr;513else if (isa<EnumConstantDecl>(*D)) {514DeclContext::decl_iterator Next = D;515++Next;516if (Next != DEnd)517Terminator = ",";518} else519Terminator = ";";520521if (Terminator)522Out << Terminator;523if (!Policy.TerseOutput &&524((isa<FunctionDecl>(*D) &&525cast<FunctionDecl>(*D)->doesThisDeclarationHaveABody()) ||526(isa<FunctionTemplateDecl>(*D) &&527cast<FunctionTemplateDecl>(*D)->getTemplatedDecl()->doesThisDeclarationHaveABody())))528; // StmtPrinter already added '\n' after CompoundStmt.529else530Out << "\n";531532// Declare target attribute is special one, natural spelling for the pragma533// assumes "ending" construct so print it here.534if (D->hasAttr<OMPDeclareTargetDeclAttr>())535Out << "#pragma omp end declare target\n";536}537538if (!Decls.empty())539ProcessDeclGroup(Decls);540541if (Indent)542Indentation -= Policy.Indentation;543}544545void DeclPrinter::VisitTranslationUnitDecl(TranslationUnitDecl *D) {546VisitDeclContext(D, false);547}548549void DeclPrinter::VisitTypedefDecl(TypedefDecl *D) {550if (!Policy.SuppressSpecifiers) {551Out << "typedef ";552553if (D->isModulePrivate())554Out << "__module_private__ ";555}556QualType Ty = D->getTypeSourceInfo()->getType();557Ty.print(Out, Policy, D->getName(), Indentation);558prettyPrintAttributes(D);559}560561void DeclPrinter::VisitTypeAliasDecl(TypeAliasDecl *D) {562Out << "using " << *D;563prettyPrintAttributes(D);564Out << " = " << D->getTypeSourceInfo()->getType().getAsString(Policy);565}566567void DeclPrinter::VisitEnumDecl(EnumDecl *D) {568if (!Policy.SuppressSpecifiers && D->isModulePrivate())569Out << "__module_private__ ";570Out << "enum";571if (D->isScoped()) {572if (D->isScopedUsingClassTag())573Out << " class";574else575Out << " struct";576}577578prettyPrintAttributes(D);579580if (D->getDeclName())581Out << ' ' << D->getDeclName();582583if (D->isFixed())584Out << " : " << D->getIntegerType().stream(Policy);585586if (D->isCompleteDefinition()) {587Out << " {\n";588VisitDeclContext(D);589Indent() << "}";590}591}592593void DeclPrinter::VisitRecordDecl(RecordDecl *D) {594if (!Policy.SuppressSpecifiers && D->isModulePrivate())595Out << "__module_private__ ";596Out << D->getKindName();597598prettyPrintAttributes(D);599600if (D->getIdentifier())601Out << ' ' << *D;602603if (D->isCompleteDefinition()) {604Out << " {\n";605VisitDeclContext(D);606Indent() << "}";607}608}609610void DeclPrinter::VisitEnumConstantDecl(EnumConstantDecl *D) {611Out << *D;612prettyPrintAttributes(D);613if (Expr *Init = D->getInitExpr()) {614Out << " = ";615Init->printPretty(Out, nullptr, Policy, Indentation, "\n", &Context);616}617}618619static void printExplicitSpecifier(ExplicitSpecifier ES, llvm::raw_ostream &Out,620PrintingPolicy &Policy, unsigned Indentation,621const ASTContext &Context) {622std::string Proto = "explicit";623llvm::raw_string_ostream EOut(Proto);624if (ES.getExpr()) {625EOut << "(";626ES.getExpr()->printPretty(EOut, nullptr, Policy, Indentation, "\n",627&Context);628EOut << ")";629}630EOut << " ";631EOut.flush();632Out << Proto;633}634635static void MaybePrintTagKeywordIfSupressingScopes(PrintingPolicy &Policy,636QualType T,637llvm::raw_ostream &Out) {638StringRef prefix = T->isClassType() ? "class "639: T->isStructureType() ? "struct "640: T->isUnionType() ? "union "641: "";642Out << prefix;643}644645void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {646if (!D->getDescribedFunctionTemplate() &&647!D->isFunctionTemplateSpecialization()) {648prettyPrintPragmas(D);649prettyPrintAttributes(D, AttrPosAsWritten::Left);650}651652if (D->isFunctionTemplateSpecialization())653Out << "template<> ";654else if (!D->getDescribedFunctionTemplate()) {655for (unsigned I = 0, NumTemplateParams = D->getNumTemplateParameterLists();656I < NumTemplateParams; ++I)657printTemplateParameters(D->getTemplateParameterList(I));658}659660CXXConstructorDecl *CDecl = dyn_cast<CXXConstructorDecl>(D);661CXXConversionDecl *ConversionDecl = dyn_cast<CXXConversionDecl>(D);662CXXDeductionGuideDecl *GuideDecl = dyn_cast<CXXDeductionGuideDecl>(D);663if (!Policy.SuppressSpecifiers) {664switch (D->getStorageClass()) {665case SC_None: break;666case SC_Extern: Out << "extern "; break;667case SC_Static: Out << "static "; break;668case SC_PrivateExtern: Out << "__private_extern__ "; break;669case SC_Auto: case SC_Register:670llvm_unreachable("invalid for functions");671}672673if (D->isInlineSpecified()) Out << "inline ";674if (D->isVirtualAsWritten()) Out << "virtual ";675if (D->isModulePrivate()) Out << "__module_private__ ";676if (D->isConstexprSpecified() && !D->isExplicitlyDefaulted())677Out << "constexpr ";678if (D->isConsteval()) Out << "consteval ";679else if (D->isImmediateFunction())680Out << "immediate ";681ExplicitSpecifier ExplicitSpec = ExplicitSpecifier::getFromDecl(D);682if (ExplicitSpec.isSpecified())683printExplicitSpecifier(ExplicitSpec, Out, Policy, Indentation, Context);684}685686PrintingPolicy SubPolicy(Policy);687SubPolicy.SuppressSpecifiers = false;688std::string Proto;689690if (Policy.FullyQualifiedName) {691Proto += D->getQualifiedNameAsString();692} else {693llvm::raw_string_ostream OS(Proto);694if (!Policy.SuppressScope) {695if (const NestedNameSpecifier *NS = D->getQualifier()) {696NS->print(OS, Policy);697}698}699D->getNameInfo().printName(OS, Policy);700}701702if (GuideDecl)703Proto = GuideDecl->getDeducedTemplate()->getDeclName().getAsString();704if (D->isFunctionTemplateSpecialization()) {705llvm::raw_string_ostream POut(Proto);706DeclPrinter TArgPrinter(POut, SubPolicy, Context, Indentation);707const auto *TArgAsWritten = D->getTemplateSpecializationArgsAsWritten();708if (TArgAsWritten && !Policy.PrintCanonicalTypes)709TArgPrinter.printTemplateArguments(TArgAsWritten->arguments(), nullptr);710else if (const TemplateArgumentList *TArgs =711D->getTemplateSpecializationArgs())712TArgPrinter.printTemplateArguments(TArgs->asArray(), nullptr);713}714715QualType Ty = D->getType();716while (const ParenType *PT = dyn_cast<ParenType>(Ty)) {717Proto = '(' + Proto + ')';718Ty = PT->getInnerType();719}720721if (const FunctionType *AFT = Ty->getAs<FunctionType>()) {722const FunctionProtoType *FT = nullptr;723if (D->hasWrittenPrototype())724FT = dyn_cast<FunctionProtoType>(AFT);725726Proto += "(";727if (FT) {728llvm::raw_string_ostream POut(Proto);729DeclPrinter ParamPrinter(POut, SubPolicy, Context, Indentation);730for (unsigned i = 0, e = D->getNumParams(); i != e; ++i) {731if (i) POut << ", ";732ParamPrinter.VisitParmVarDecl(D->getParamDecl(i));733}734735if (FT->isVariadic()) {736if (D->getNumParams()) POut << ", ";737POut << "...";738} else if (!D->getNumParams() && !Context.getLangOpts().CPlusPlus) {739// The function has a prototype, so it needs to retain the prototype740// in C.741POut << "void";742}743} else if (D->doesThisDeclarationHaveABody() && !D->hasPrototype()) {744for (unsigned i = 0, e = D->getNumParams(); i != e; ++i) {745if (i)746Proto += ", ";747Proto += D->getParamDecl(i)->getNameAsString();748}749}750751Proto += ")";752753if (FT) {754if (FT->isConst())755Proto += " const";756if (FT->isVolatile())757Proto += " volatile";758if (FT->isRestrict())759Proto += " restrict";760761switch (FT->getRefQualifier()) {762case RQ_None:763break;764case RQ_LValue:765Proto += " &";766break;767case RQ_RValue:768Proto += " &&";769break;770}771}772773if (FT && FT->hasDynamicExceptionSpec()) {774Proto += " throw(";775if (FT->getExceptionSpecType() == EST_MSAny)776Proto += "...";777else778for (unsigned I = 0, N = FT->getNumExceptions(); I != N; ++I) {779if (I)780Proto += ", ";781782Proto += FT->getExceptionType(I).getAsString(SubPolicy);783}784Proto += ")";785} else if (FT && isNoexceptExceptionSpec(FT->getExceptionSpecType())) {786Proto += " noexcept";787if (isComputedNoexcept(FT->getExceptionSpecType())) {788Proto += "(";789llvm::raw_string_ostream EOut(Proto);790FT->getNoexceptExpr()->printPretty(EOut, nullptr, SubPolicy,791Indentation, "\n", &Context);792EOut.flush();793Proto += ")";794}795}796797if (CDecl) {798if (!Policy.TerseOutput)799PrintConstructorInitializers(CDecl, Proto);800} else if (!ConversionDecl && !isa<CXXDestructorDecl>(D)) {801if (FT && FT->hasTrailingReturn()) {802if (!GuideDecl)803Out << "auto ";804Out << Proto << " -> ";805Proto.clear();806}807if (!Policy.SuppressTagKeyword && Policy.SuppressScope &&808!Policy.SuppressUnwrittenScope)809MaybePrintTagKeywordIfSupressingScopes(Policy, AFT->getReturnType(),810Out);811AFT->getReturnType().print(Out, Policy, Proto);812Proto.clear();813}814Out << Proto;815816if (Expr *TrailingRequiresClause = D->getTrailingRequiresClause()) {817Out << " requires ";818TrailingRequiresClause->printPretty(Out, nullptr, SubPolicy, Indentation,819"\n", &Context);820}821} else {822Ty.print(Out, Policy, Proto);823}824825prettyPrintAttributes(D, AttrPosAsWritten::Right);826827if (D->isPureVirtual())828Out << " = 0";829else if (D->isDeletedAsWritten()) {830Out << " = delete";831if (const StringLiteral *M = D->getDeletedMessage()) {832Out << "(";833M->outputString(Out);834Out << ")";835}836} else if (D->isExplicitlyDefaulted())837Out << " = default";838else if (D->doesThisDeclarationHaveABody()) {839if (!Policy.TerseOutput) {840if (!D->hasPrototype() && D->getNumParams()) {841// This is a K&R function definition, so we need to print the842// parameters.843Out << '\n';844DeclPrinter ParamPrinter(Out, SubPolicy, Context, Indentation);845Indentation += Policy.Indentation;846for (unsigned i = 0, e = D->getNumParams(); i != e; ++i) {847Indent();848ParamPrinter.VisitParmVarDecl(D->getParamDecl(i));849Out << ";\n";850}851Indentation -= Policy.Indentation;852}853854if (D->getBody())855D->getBody()->printPrettyControlled(Out, nullptr, SubPolicy, Indentation, "\n",856&Context);857} else {858if (!Policy.TerseOutput && isa<CXXConstructorDecl>(*D))859Out << " {}";860}861}862}863864void DeclPrinter::VisitFriendDecl(FriendDecl *D) {865if (TypeSourceInfo *TSI = D->getFriendType()) {866unsigned NumTPLists = D->getFriendTypeNumTemplateParameterLists();867for (unsigned i = 0; i < NumTPLists; ++i)868printTemplateParameters(D->getFriendTypeTemplateParameterList(i));869Out << "friend ";870Out << " " << TSI->getType().getAsString(Policy);871}872else if (FunctionDecl *FD =873dyn_cast<FunctionDecl>(D->getFriendDecl())) {874Out << "friend ";875VisitFunctionDecl(FD);876}877else if (FunctionTemplateDecl *FTD =878dyn_cast<FunctionTemplateDecl>(D->getFriendDecl())) {879Out << "friend ";880VisitFunctionTemplateDecl(FTD);881}882else if (ClassTemplateDecl *CTD =883dyn_cast<ClassTemplateDecl>(D->getFriendDecl())) {884Out << "friend ";885VisitRedeclarableTemplateDecl(CTD);886}887}888889void DeclPrinter::VisitFieldDecl(FieldDecl *D) {890// FIXME: add printing of pragma attributes if required.891if (!Policy.SuppressSpecifiers && D->isMutable())892Out << "mutable ";893if (!Policy.SuppressSpecifiers && D->isModulePrivate())894Out << "__module_private__ ";895896Out << D->getASTContext().getUnqualifiedObjCPointerType(D->getType()).897stream(Policy, D->getName(), Indentation);898899if (D->isBitField()) {900Out << " : ";901D->getBitWidth()->printPretty(Out, nullptr, Policy, Indentation, "\n",902&Context);903}904905Expr *Init = D->getInClassInitializer();906if (!Policy.SuppressInitializers && Init) {907if (D->getInClassInitStyle() == ICIS_ListInit)908Out << " ";909else910Out << " = ";911Init->printPretty(Out, nullptr, Policy, Indentation, "\n", &Context);912}913prettyPrintAttributes(D);914}915916void DeclPrinter::VisitLabelDecl(LabelDecl *D) {917Out << *D << ":";918}919920void DeclPrinter::VisitVarDecl(VarDecl *D) {921prettyPrintPragmas(D);922923prettyPrintAttributes(D, AttrPosAsWritten::Left);924925if (const auto *Param = dyn_cast<ParmVarDecl>(D);926Param && Param->isExplicitObjectParameter())927Out << "this ";928929QualType T = D->getTypeSourceInfo()930? D->getTypeSourceInfo()->getType()931: D->getASTContext().getUnqualifiedObjCPointerType(D->getType());932933if (!Policy.SuppressSpecifiers) {934StorageClass SC = D->getStorageClass();935if (SC != SC_None)936Out << VarDecl::getStorageClassSpecifierString(SC) << " ";937938switch (D->getTSCSpec()) {939case TSCS_unspecified:940break;941case TSCS___thread:942Out << "__thread ";943break;944case TSCS__Thread_local:945Out << "_Thread_local ";946break;947case TSCS_thread_local:948Out << "thread_local ";949break;950}951952if (D->isModulePrivate())953Out << "__module_private__ ";954955if (D->isConstexpr()) {956Out << "constexpr ";957T.removeLocalConst();958}959}960961if (!Policy.SuppressTagKeyword && Policy.SuppressScope &&962!Policy.SuppressUnwrittenScope)963MaybePrintTagKeywordIfSupressingScopes(Policy, T, Out);964965printDeclType(T, (isa<ParmVarDecl>(D) && Policy.CleanUglifiedParameters &&966D->getIdentifier())967? D->getIdentifier()->deuglifiedName()968: D->getName());969970prettyPrintAttributes(D, AttrPosAsWritten::Right);971972Expr *Init = D->getInit();973if (!Policy.SuppressInitializers && Init) {974bool ImplicitInit = false;975if (D->isCXXForRangeDecl()) {976// FIXME: We should print the range expression instead.977ImplicitInit = true;978} else if (CXXConstructExpr *Construct =979dyn_cast<CXXConstructExpr>(Init->IgnoreImplicit())) {980if (D->getInitStyle() == VarDecl::CallInit &&981!Construct->isListInitialization()) {982ImplicitInit = Construct->getNumArgs() == 0 ||983Construct->getArg(0)->isDefaultArgument();984}985}986if (!ImplicitInit) {987if ((D->getInitStyle() == VarDecl::CallInit) && !isa<ParenListExpr>(Init))988Out << "(";989else if (D->getInitStyle() == VarDecl::CInit) {990Out << " = ";991}992PrintingPolicy SubPolicy(Policy);993SubPolicy.SuppressSpecifiers = false;994SubPolicy.IncludeTagDefinition = false;995Init->printPretty(Out, nullptr, SubPolicy, Indentation, "\n", &Context);996if ((D->getInitStyle() == VarDecl::CallInit) && !isa<ParenListExpr>(Init))997Out << ")";998}999}1000}10011002void DeclPrinter::VisitParmVarDecl(ParmVarDecl *D) {1003VisitVarDecl(D);1004}10051006void DeclPrinter::VisitFileScopeAsmDecl(FileScopeAsmDecl *D) {1007Out << "__asm (";1008D->getAsmString()->printPretty(Out, nullptr, Policy, Indentation, "\n",1009&Context);1010Out << ")";1011}10121013void DeclPrinter::VisitTopLevelStmtDecl(TopLevelStmtDecl *D) {1014assert(D->getStmt());1015D->getStmt()->printPretty(Out, nullptr, Policy, Indentation, "\n", &Context);1016}10171018void DeclPrinter::VisitImportDecl(ImportDecl *D) {1019Out << "@import " << D->getImportedModule()->getFullModuleName()1020<< ";\n";1021}10221023void DeclPrinter::VisitStaticAssertDecl(StaticAssertDecl *D) {1024Out << "static_assert(";1025D->getAssertExpr()->printPretty(Out, nullptr, Policy, Indentation, "\n",1026&Context);1027if (Expr *E = D->getMessage()) {1028Out << ", ";1029E->printPretty(Out, nullptr, Policy, Indentation, "\n", &Context);1030}1031Out << ")";1032}10331034//----------------------------------------------------------------------------1035// C++ declarations1036//----------------------------------------------------------------------------1037void DeclPrinter::VisitNamespaceDecl(NamespaceDecl *D) {1038if (D->isInline())1039Out << "inline ";10401041Out << "namespace ";1042if (D->getDeclName())1043Out << D->getDeclName() << ' ';1044Out << "{\n";10451046VisitDeclContext(D);1047Indent() << "}";1048}10491050void DeclPrinter::VisitUsingDirectiveDecl(UsingDirectiveDecl *D) {1051Out << "using namespace ";1052if (D->getQualifier())1053D->getQualifier()->print(Out, Policy);1054Out << *D->getNominatedNamespaceAsWritten();1055}10561057void DeclPrinter::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) {1058Out << "namespace " << *D << " = ";1059if (D->getQualifier())1060D->getQualifier()->print(Out, Policy);1061Out << *D->getAliasedNamespace();1062}10631064void DeclPrinter::VisitEmptyDecl(EmptyDecl *D) {1065prettyPrintAttributes(D);1066}10671068void DeclPrinter::VisitCXXRecordDecl(CXXRecordDecl *D) {1069// FIXME: add printing of pragma attributes if required.1070if (!Policy.SuppressSpecifiers && D->isModulePrivate())1071Out << "__module_private__ ";10721073Out << D->getKindName() << ' ';10741075// FIXME: Move before printing the decl kind to match the behavior of the1076// attribute printing for variables and function where they are printed first.1077if (prettyPrintAttributes(D, AttrPosAsWritten::Left))1078Out << ' ';10791080if (D->getIdentifier()) {1081if (auto *NNS = D->getQualifier())1082NNS->print(Out, Policy);1083Out << *D;10841085if (auto *S = dyn_cast<ClassTemplateSpecializationDecl>(D)) {1086const TemplateParameterList *TParams =1087S->getSpecializedTemplate()->getTemplateParameters();1088const ASTTemplateArgumentListInfo *TArgAsWritten =1089S->getTemplateArgsAsWritten();1090if (TArgAsWritten && !Policy.PrintCanonicalTypes)1091printTemplateArguments(TArgAsWritten->arguments(), TParams);1092else1093printTemplateArguments(S->getTemplateArgs().asArray(), TParams);1094}1095}10961097prettyPrintAttributes(D, AttrPosAsWritten::Right);10981099if (D->isCompleteDefinition()) {1100Out << ' ';1101// Print the base classes1102if (D->getNumBases()) {1103Out << ": ";1104for (CXXRecordDecl::base_class_iterator Base = D->bases_begin(),1105BaseEnd = D->bases_end(); Base != BaseEnd; ++Base) {1106if (Base != D->bases_begin())1107Out << ", ";11081109if (Base->isVirtual())1110Out << "virtual ";11111112AccessSpecifier AS = Base->getAccessSpecifierAsWritten();1113if (AS != AS_none) {1114Print(AS);1115Out << " ";1116}1117Out << Base->getType().getAsString(Policy);11181119if (Base->isPackExpansion())1120Out << "...";1121}1122Out << ' ';1123}11241125// Print the class definition1126// FIXME: Doesn't print access specifiers, e.g., "public:"1127if (Policy.TerseOutput) {1128Out << "{}";1129} else {1130Out << "{\n";1131VisitDeclContext(D);1132Indent() << "}";1133}1134}1135}11361137void DeclPrinter::VisitLinkageSpecDecl(LinkageSpecDecl *D) {1138const char *l;1139if (D->getLanguage() == LinkageSpecLanguageIDs::C)1140l = "C";1141else {1142assert(D->getLanguage() == LinkageSpecLanguageIDs::CXX &&1143"unknown language in linkage specification");1144l = "C++";1145}11461147Out << "extern \"" << l << "\" ";1148if (D->hasBraces()) {1149Out << "{\n";1150VisitDeclContext(D);1151Indent() << "}";1152} else1153Visit(*D->decls_begin());1154}11551156void DeclPrinter::printTemplateParameters(const TemplateParameterList *Params,1157bool OmitTemplateKW) {1158assert(Params);11591160// Don't print invented template parameter lists.1161if (!Params->empty() && Params->getParam(0)->isImplicit())1162return;11631164if (!OmitTemplateKW)1165Out << "template ";1166Out << '<';11671168bool NeedComma = false;1169for (const Decl *Param : *Params) {1170if (Param->isImplicit())1171continue;11721173if (NeedComma)1174Out << ", ";1175else1176NeedComma = true;11771178if (const auto *TTP = dyn_cast<TemplateTypeParmDecl>(Param)) {1179VisitTemplateTypeParmDecl(TTP);1180} else if (auto NTTP = dyn_cast<NonTypeTemplateParmDecl>(Param)) {1181VisitNonTypeTemplateParmDecl(NTTP);1182} else if (auto TTPD = dyn_cast<TemplateTemplateParmDecl>(Param)) {1183VisitTemplateDecl(TTPD);1184// FIXME: print the default argument, if present.1185}1186}11871188Out << '>';11891190if (const Expr *RequiresClause = Params->getRequiresClause()) {1191Out << " requires ";1192RequiresClause->printPretty(Out, nullptr, Policy, Indentation, "\n",1193&Context);1194}11951196if (!OmitTemplateKW)1197Out << ' ';1198}11991200void DeclPrinter::printTemplateArguments(ArrayRef<TemplateArgument> Args,1201const TemplateParameterList *Params) {1202Out << "<";1203for (size_t I = 0, E = Args.size(); I < E; ++I) {1204if (I)1205Out << ", ";1206if (!Params)1207Args[I].print(Policy, Out, /*IncludeType*/ true);1208else1209Args[I].print(Policy, Out,1210TemplateParameterList::shouldIncludeTypeForArgument(1211Policy, Params, I));1212}1213Out << ">";1214}12151216void DeclPrinter::printTemplateArguments(ArrayRef<TemplateArgumentLoc> Args,1217const TemplateParameterList *Params) {1218Out << "<";1219for (size_t I = 0, E = Args.size(); I < E; ++I) {1220if (I)1221Out << ", ";1222if (!Params)1223Args[I].getArgument().print(Policy, Out, /*IncludeType*/ true);1224else1225Args[I].getArgument().print(1226Policy, Out,1227TemplateParameterList::shouldIncludeTypeForArgument(Policy, Params,1228I));1229}1230Out << ">";1231}12321233void DeclPrinter::VisitTemplateDecl(const TemplateDecl *D) {1234printTemplateParameters(D->getTemplateParameters());12351236if (const TemplateTemplateParmDecl *TTP =1237dyn_cast<TemplateTemplateParmDecl>(D)) {1238if (TTP->wasDeclaredWithTypename())1239Out << "typename";1240else1241Out << "class";12421243if (TTP->isParameterPack())1244Out << " ...";1245else if (TTP->getDeclName())1246Out << ' ';12471248if (TTP->getDeclName()) {1249if (Policy.CleanUglifiedParameters && TTP->getIdentifier())1250Out << TTP->getIdentifier()->deuglifiedName();1251else1252Out << TTP->getDeclName();1253}1254} else if (auto *TD = D->getTemplatedDecl())1255Visit(TD);1256else if (const auto *Concept = dyn_cast<ConceptDecl>(D)) {1257Out << "concept " << Concept->getName() << " = " ;1258Concept->getConstraintExpr()->printPretty(Out, nullptr, Policy, Indentation,1259"\n", &Context);1260}1261}12621263void DeclPrinter::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {1264prettyPrintPragmas(D->getTemplatedDecl());1265// Print any leading template parameter lists.1266if (const FunctionDecl *FD = D->getTemplatedDecl()) {1267for (unsigned I = 0, NumTemplateParams = FD->getNumTemplateParameterLists();1268I < NumTemplateParams; ++I)1269printTemplateParameters(FD->getTemplateParameterList(I));1270}1271VisitRedeclarableTemplateDecl(D);1272// Declare target attribute is special one, natural spelling for the pragma1273// assumes "ending" construct so print it here.1274if (D->getTemplatedDecl()->hasAttr<OMPDeclareTargetDeclAttr>())1275Out << "#pragma omp end declare target\n";12761277// Never print "instantiations" for deduction guides (they don't really1278// have them).1279if (PrintInstantiation &&1280!isa<CXXDeductionGuideDecl>(D->getTemplatedDecl())) {1281FunctionDecl *PrevDecl = D->getTemplatedDecl();1282const FunctionDecl *Def;1283if (PrevDecl->isDefined(Def) && Def != PrevDecl)1284return;1285for (auto *I : D->specializations())1286if (I->getTemplateSpecializationKind() == TSK_ImplicitInstantiation) {1287if (!PrevDecl->isThisDeclarationADefinition())1288Out << ";\n";1289Indent();1290prettyPrintPragmas(I);1291Visit(I);1292}1293}1294}12951296void DeclPrinter::VisitClassTemplateDecl(ClassTemplateDecl *D) {1297VisitRedeclarableTemplateDecl(D);12981299if (PrintInstantiation) {1300for (auto *I : D->specializations())1301if (I->getSpecializationKind() == TSK_ImplicitInstantiation) {1302if (D->isThisDeclarationADefinition())1303Out << ";";1304Out << "\n";1305Indent();1306Visit(I);1307}1308}1309}13101311void DeclPrinter::VisitClassTemplateSpecializationDecl(1312ClassTemplateSpecializationDecl *D) {1313Out << "template<> ";1314VisitCXXRecordDecl(D);1315}13161317void DeclPrinter::VisitClassTemplatePartialSpecializationDecl(1318ClassTemplatePartialSpecializationDecl *D) {1319printTemplateParameters(D->getTemplateParameters());1320VisitCXXRecordDecl(D);1321}13221323//----------------------------------------------------------------------------1324// Objective-C declarations1325//----------------------------------------------------------------------------13261327void DeclPrinter::PrintObjCMethodType(ASTContext &Ctx,1328Decl::ObjCDeclQualifier Quals,1329QualType T) {1330Out << '(';1331if (Quals & Decl::ObjCDeclQualifier::OBJC_TQ_In)1332Out << "in ";1333if (Quals & Decl::ObjCDeclQualifier::OBJC_TQ_Inout)1334Out << "inout ";1335if (Quals & Decl::ObjCDeclQualifier::OBJC_TQ_Out)1336Out << "out ";1337if (Quals & Decl::ObjCDeclQualifier::OBJC_TQ_Bycopy)1338Out << "bycopy ";1339if (Quals & Decl::ObjCDeclQualifier::OBJC_TQ_Byref)1340Out << "byref ";1341if (Quals & Decl::ObjCDeclQualifier::OBJC_TQ_Oneway)1342Out << "oneway ";1343if (Quals & Decl::ObjCDeclQualifier::OBJC_TQ_CSNullability) {1344if (auto nullability = AttributedType::stripOuterNullability(T))1345Out << getNullabilitySpelling(*nullability, true) << ' ';1346}13471348Out << Ctx.getUnqualifiedObjCPointerType(T).getAsString(Policy);1349Out << ')';1350}13511352void DeclPrinter::PrintObjCTypeParams(ObjCTypeParamList *Params) {1353Out << "<";1354unsigned First = true;1355for (auto *Param : *Params) {1356if (First) {1357First = false;1358} else {1359Out << ", ";1360}13611362switch (Param->getVariance()) {1363case ObjCTypeParamVariance::Invariant:1364break;13651366case ObjCTypeParamVariance::Covariant:1367Out << "__covariant ";1368break;13691370case ObjCTypeParamVariance::Contravariant:1371Out << "__contravariant ";1372break;1373}13741375Out << Param->getDeclName();13761377if (Param->hasExplicitBound()) {1378Out << " : " << Param->getUnderlyingType().getAsString(Policy);1379}1380}1381Out << ">";1382}13831384void DeclPrinter::VisitObjCMethodDecl(ObjCMethodDecl *OMD) {1385if (OMD->isInstanceMethod())1386Out << "- ";1387else1388Out << "+ ";1389if (!OMD->getReturnType().isNull()) {1390PrintObjCMethodType(OMD->getASTContext(), OMD->getObjCDeclQualifier(),1391OMD->getReturnType());1392}13931394std::string name = OMD->getSelector().getAsString();1395std::string::size_type pos, lastPos = 0;1396for (const auto *PI : OMD->parameters()) {1397// FIXME: selector is missing here!1398pos = name.find_first_of(':', lastPos);1399if (lastPos != 0)1400Out << " ";1401Out << name.substr(lastPos, pos - lastPos) << ':';1402PrintObjCMethodType(OMD->getASTContext(),1403PI->getObjCDeclQualifier(),1404PI->getType());1405Out << *PI;1406lastPos = pos + 1;1407}14081409if (OMD->param_begin() == OMD->param_end())1410Out << name;14111412if (OMD->isVariadic())1413Out << ", ...";14141415prettyPrintAttributes(OMD);14161417if (OMD->getBody() && !Policy.TerseOutput) {1418Out << ' ';1419OMD->getBody()->printPretty(Out, nullptr, Policy, Indentation, "\n",1420&Context);1421}1422else if (Policy.PolishForDeclaration)1423Out << ';';1424}14251426void DeclPrinter::VisitObjCImplementationDecl(ObjCImplementationDecl *OID) {1427std::string I = OID->getNameAsString();1428ObjCInterfaceDecl *SID = OID->getSuperClass();14291430bool eolnOut = false;1431if (SID)1432Out << "@implementation " << I << " : " << *SID;1433else1434Out << "@implementation " << I;14351436if (OID->ivar_size() > 0) {1437Out << "{\n";1438eolnOut = true;1439Indentation += Policy.Indentation;1440for (const auto *I : OID->ivars()) {1441Indent() << I->getASTContext().getUnqualifiedObjCPointerType(I->getType()).1442getAsString(Policy) << ' ' << *I << ";\n";1443}1444Indentation -= Policy.Indentation;1445Out << "}\n";1446}1447else if (SID || (OID->decls_begin() != OID->decls_end())) {1448Out << "\n";1449eolnOut = true;1450}1451VisitDeclContext(OID, false);1452if (!eolnOut)1453Out << "\n";1454Out << "@end";1455}14561457void DeclPrinter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *OID) {1458std::string I = OID->getNameAsString();1459ObjCInterfaceDecl *SID = OID->getSuperClass();14601461if (!OID->isThisDeclarationADefinition()) {1462Out << "@class " << I;14631464if (auto TypeParams = OID->getTypeParamListAsWritten()) {1465PrintObjCTypeParams(TypeParams);1466}14671468Out << ";";1469return;1470}1471bool eolnOut = false;1472if (OID->hasAttrs()) {1473prettyPrintAttributes(OID);1474Out << "\n";1475}14761477Out << "@interface " << I;14781479if (auto TypeParams = OID->getTypeParamListAsWritten()) {1480PrintObjCTypeParams(TypeParams);1481}14821483if (SID)1484Out << " : " << QualType(OID->getSuperClassType(), 0).getAsString(Policy);14851486// Protocols?1487const ObjCList<ObjCProtocolDecl> &Protocols = OID->getReferencedProtocols();1488if (!Protocols.empty()) {1489for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),1490E = Protocols.end(); I != E; ++I)1491Out << (I == Protocols.begin() ? '<' : ',') << **I;1492Out << "> ";1493}14941495if (OID->ivar_size() > 0) {1496Out << "{\n";1497eolnOut = true;1498Indentation += Policy.Indentation;1499for (const auto *I : OID->ivars()) {1500Indent() << I->getASTContext()1501.getUnqualifiedObjCPointerType(I->getType())1502.getAsString(Policy) << ' ' << *I << ";\n";1503}1504Indentation -= Policy.Indentation;1505Out << "}\n";1506}1507else if (SID || (OID->decls_begin() != OID->decls_end())) {1508Out << "\n";1509eolnOut = true;1510}15111512VisitDeclContext(OID, false);1513if (!eolnOut)1514Out << "\n";1515Out << "@end";1516// FIXME: implement the rest...1517}15181519void DeclPrinter::VisitObjCProtocolDecl(ObjCProtocolDecl *PID) {1520if (!PID->isThisDeclarationADefinition()) {1521Out << "@protocol " << *PID << ";\n";1522return;1523}1524// Protocols?1525const ObjCList<ObjCProtocolDecl> &Protocols = PID->getReferencedProtocols();1526if (!Protocols.empty()) {1527Out << "@protocol " << *PID;1528for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),1529E = Protocols.end(); I != E; ++I)1530Out << (I == Protocols.begin() ? '<' : ',') << **I;1531Out << ">\n";1532} else1533Out << "@protocol " << *PID << '\n';1534VisitDeclContext(PID, false);1535Out << "@end";1536}15371538void DeclPrinter::VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *PID) {1539Out << "@implementation ";1540if (const auto *CID = PID->getClassInterface())1541Out << *CID;1542else1543Out << "<<error-type>>";1544Out << '(' << *PID << ")\n";15451546VisitDeclContext(PID, false);1547Out << "@end";1548// FIXME: implement the rest...1549}15501551void DeclPrinter::VisitObjCCategoryDecl(ObjCCategoryDecl *PID) {1552Out << "@interface ";1553if (const auto *CID = PID->getClassInterface())1554Out << *CID;1555else1556Out << "<<error-type>>";1557if (auto TypeParams = PID->getTypeParamList()) {1558PrintObjCTypeParams(TypeParams);1559}1560Out << "(" << *PID << ")\n";1561if (PID->ivar_size() > 0) {1562Out << "{\n";1563Indentation += Policy.Indentation;1564for (const auto *I : PID->ivars())1565Indent() << I->getASTContext().getUnqualifiedObjCPointerType(I->getType()).1566getAsString(Policy) << ' ' << *I << ";\n";1567Indentation -= Policy.Indentation;1568Out << "}\n";1569}15701571VisitDeclContext(PID, false);1572Out << "@end";15731574// FIXME: implement the rest...1575}15761577void DeclPrinter::VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *AID) {1578Out << "@compatibility_alias " << *AID1579<< ' ' << *AID->getClassInterface() << ";\n";1580}15811582/// PrintObjCPropertyDecl - print a property declaration.1583///1584/// Print attributes in the following order:1585/// - class1586/// - nonatomic | atomic1587/// - assign | retain | strong | copy | weak | unsafe_unretained1588/// - readwrite | readonly1589/// - getter & setter1590/// - nullability1591void DeclPrinter::VisitObjCPropertyDecl(ObjCPropertyDecl *PDecl) {1592if (PDecl->getPropertyImplementation() == ObjCPropertyDecl::Required)1593Out << "@required\n";1594else if (PDecl->getPropertyImplementation() == ObjCPropertyDecl::Optional)1595Out << "@optional\n";15961597QualType T = PDecl->getType();15981599Out << "@property";1600if (PDecl->getPropertyAttributes() != ObjCPropertyAttribute::kind_noattr) {1601bool first = true;1602Out << "(";1603if (PDecl->getPropertyAttributes() & ObjCPropertyAttribute::kind_class) {1604Out << (first ? "" : ", ") << "class";1605first = false;1606}16071608if (PDecl->getPropertyAttributes() & ObjCPropertyAttribute::kind_direct) {1609Out << (first ? "" : ", ") << "direct";1610first = false;1611}16121613if (PDecl->getPropertyAttributes() &1614ObjCPropertyAttribute::kind_nonatomic) {1615Out << (first ? "" : ", ") << "nonatomic";1616first = false;1617}1618if (PDecl->getPropertyAttributes() & ObjCPropertyAttribute::kind_atomic) {1619Out << (first ? "" : ", ") << "atomic";1620first = false;1621}16221623if (PDecl->getPropertyAttributes() & ObjCPropertyAttribute::kind_assign) {1624Out << (first ? "" : ", ") << "assign";1625first = false;1626}1627if (PDecl->getPropertyAttributes() & ObjCPropertyAttribute::kind_retain) {1628Out << (first ? "" : ", ") << "retain";1629first = false;1630}16311632if (PDecl->getPropertyAttributes() & ObjCPropertyAttribute::kind_strong) {1633Out << (first ? "" : ", ") << "strong";1634first = false;1635}1636if (PDecl->getPropertyAttributes() & ObjCPropertyAttribute::kind_copy) {1637Out << (first ? "" : ", ") << "copy";1638first = false;1639}1640if (PDecl->getPropertyAttributes() & ObjCPropertyAttribute::kind_weak) {1641Out << (first ? "" : ", ") << "weak";1642first = false;1643}1644if (PDecl->getPropertyAttributes() &1645ObjCPropertyAttribute::kind_unsafe_unretained) {1646Out << (first ? "" : ", ") << "unsafe_unretained";1647first = false;1648}16491650if (PDecl->getPropertyAttributes() &1651ObjCPropertyAttribute::kind_readwrite) {1652Out << (first ? "" : ", ") << "readwrite";1653first = false;1654}1655if (PDecl->getPropertyAttributes() & ObjCPropertyAttribute::kind_readonly) {1656Out << (first ? "" : ", ") << "readonly";1657first = false;1658}16591660if (PDecl->getPropertyAttributes() & ObjCPropertyAttribute::kind_getter) {1661Out << (first ? "" : ", ") << "getter = ";1662PDecl->getGetterName().print(Out);1663first = false;1664}1665if (PDecl->getPropertyAttributes() & ObjCPropertyAttribute::kind_setter) {1666Out << (first ? "" : ", ") << "setter = ";1667PDecl->getSetterName().print(Out);1668first = false;1669}16701671if (PDecl->getPropertyAttributes() &1672ObjCPropertyAttribute::kind_nullability) {1673if (auto nullability = AttributedType::stripOuterNullability(T)) {1674if (*nullability == NullabilityKind::Unspecified &&1675(PDecl->getPropertyAttributes() &1676ObjCPropertyAttribute::kind_null_resettable)) {1677Out << (first ? "" : ", ") << "null_resettable";1678} else {1679Out << (first ? "" : ", ")1680<< getNullabilitySpelling(*nullability, true);1681}1682first = false;1683}1684}16851686(void) first; // Silence dead store warning due to idiomatic code.1687Out << ")";1688}1689std::string TypeStr = PDecl->getASTContext().getUnqualifiedObjCPointerType(T).1690getAsString(Policy);1691Out << ' ' << TypeStr;1692if (!StringRef(TypeStr).ends_with("*"))1693Out << ' ';1694Out << *PDecl;1695if (Policy.PolishForDeclaration)1696Out << ';';1697}16981699void DeclPrinter::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *PID) {1700if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize)1701Out << "@synthesize ";1702else1703Out << "@dynamic ";1704Out << *PID->getPropertyDecl();1705if (PID->getPropertyIvarDecl())1706Out << '=' << *PID->getPropertyIvarDecl();1707}17081709void DeclPrinter::VisitUsingDecl(UsingDecl *D) {1710if (!D->isAccessDeclaration())1711Out << "using ";1712if (D->hasTypename())1713Out << "typename ";1714D->getQualifier()->print(Out, Policy);17151716// Use the correct record name when the using declaration is used for1717// inheriting constructors.1718for (const auto *Shadow : D->shadows()) {1719if (const auto *ConstructorShadow =1720dyn_cast<ConstructorUsingShadowDecl>(Shadow)) {1721assert(Shadow->getDeclContext() == ConstructorShadow->getDeclContext());1722Out << *ConstructorShadow->getNominatedBaseClass();1723return;1724}1725}1726Out << *D;1727}17281729void DeclPrinter::VisitUsingEnumDecl(UsingEnumDecl *D) {1730Out << "using enum " << D->getEnumDecl();1731}17321733void1734DeclPrinter::VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D) {1735Out << "using typename ";1736D->getQualifier()->print(Out, Policy);1737Out << D->getDeclName();1738}17391740void DeclPrinter::VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D) {1741if (!D->isAccessDeclaration())1742Out << "using ";1743D->getQualifier()->print(Out, Policy);1744Out << D->getDeclName();1745}17461747void DeclPrinter::VisitUsingShadowDecl(UsingShadowDecl *D) {1748// ignore1749}17501751void DeclPrinter::VisitOMPThreadPrivateDecl(OMPThreadPrivateDecl *D) {1752Out << "#pragma omp threadprivate";1753if (!D->varlist_empty()) {1754for (OMPThreadPrivateDecl::varlist_iterator I = D->varlist_begin(),1755E = D->varlist_end();1756I != E; ++I) {1757Out << (I == D->varlist_begin() ? '(' : ',');1758NamedDecl *ND = cast<DeclRefExpr>(*I)->getDecl();1759ND->printQualifiedName(Out);1760}1761Out << ")";1762}1763}17641765void DeclPrinter::VisitHLSLBufferDecl(HLSLBufferDecl *D) {1766if (D->isCBuffer())1767Out << "cbuffer ";1768else1769Out << "tbuffer ";17701771Out << *D;17721773prettyPrintAttributes(D);17741775Out << " {\n";1776VisitDeclContext(D);1777Indent() << "}";1778}17791780void DeclPrinter::VisitOMPAllocateDecl(OMPAllocateDecl *D) {1781Out << "#pragma omp allocate";1782if (!D->varlist_empty()) {1783for (OMPAllocateDecl::varlist_iterator I = D->varlist_begin(),1784E = D->varlist_end();1785I != E; ++I) {1786Out << (I == D->varlist_begin() ? '(' : ',');1787NamedDecl *ND = cast<DeclRefExpr>(*I)->getDecl();1788ND->printQualifiedName(Out);1789}1790Out << ")";1791}1792if (!D->clauselist_empty()) {1793OMPClausePrinter Printer(Out, Policy);1794for (OMPClause *C : D->clauselists()) {1795Out << " ";1796Printer.Visit(C);1797}1798}1799}18001801void DeclPrinter::VisitOMPRequiresDecl(OMPRequiresDecl *D) {1802Out << "#pragma omp requires ";1803if (!D->clauselist_empty()) {1804OMPClausePrinter Printer(Out, Policy);1805for (auto I = D->clauselist_begin(), E = D->clauselist_end(); I != E; ++I)1806Printer.Visit(*I);1807}1808}18091810void DeclPrinter::VisitOMPDeclareReductionDecl(OMPDeclareReductionDecl *D) {1811if (!D->isInvalidDecl()) {1812Out << "#pragma omp declare reduction (";1813if (D->getDeclName().getNameKind() == DeclarationName::CXXOperatorName) {1814const char *OpName =1815getOperatorSpelling(D->getDeclName().getCXXOverloadedOperator());1816assert(OpName && "not an overloaded operator");1817Out << OpName;1818} else {1819assert(D->getDeclName().isIdentifier());1820D->printName(Out, Policy);1821}1822Out << " : ";1823D->getType().print(Out, Policy);1824Out << " : ";1825D->getCombiner()->printPretty(Out, nullptr, Policy, 0, "\n", &Context);1826Out << ")";1827if (auto *Init = D->getInitializer()) {1828Out << " initializer(";1829switch (D->getInitializerKind()) {1830case OMPDeclareReductionInitKind::Direct:1831Out << "omp_priv(";1832break;1833case OMPDeclareReductionInitKind::Copy:1834Out << "omp_priv = ";1835break;1836case OMPDeclareReductionInitKind::Call:1837break;1838}1839Init->printPretty(Out, nullptr, Policy, 0, "\n", &Context);1840if (D->getInitializerKind() == OMPDeclareReductionInitKind::Direct)1841Out << ")";1842Out << ")";1843}1844}1845}18461847void DeclPrinter::VisitOMPDeclareMapperDecl(OMPDeclareMapperDecl *D) {1848if (!D->isInvalidDecl()) {1849Out << "#pragma omp declare mapper (";1850D->printName(Out, Policy);1851Out << " : ";1852D->getType().print(Out, Policy);1853Out << " ";1854Out << D->getVarName();1855Out << ")";1856if (!D->clauselist_empty()) {1857OMPClausePrinter Printer(Out, Policy);1858for (auto *C : D->clauselists()) {1859Out << " ";1860Printer.Visit(C);1861}1862}1863}1864}18651866void DeclPrinter::VisitOMPCapturedExprDecl(OMPCapturedExprDecl *D) {1867D->getInit()->printPretty(Out, nullptr, Policy, Indentation, "\n", &Context);1868}18691870void DeclPrinter::VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *TTP) {1871if (const TypeConstraint *TC = TTP->getTypeConstraint())1872TC->print(Out, Policy);1873else if (TTP->wasDeclaredWithTypename())1874Out << "typename";1875else1876Out << "class";18771878if (TTP->isParameterPack())1879Out << " ...";1880else if (TTP->getDeclName())1881Out << ' ';18821883if (TTP->getDeclName()) {1884if (Policy.CleanUglifiedParameters && TTP->getIdentifier())1885Out << TTP->getIdentifier()->deuglifiedName();1886else1887Out << TTP->getDeclName();1888}18891890if (TTP->hasDefaultArgument()) {1891Out << " = ";1892TTP->getDefaultArgument().getArgument().print(Policy, Out,1893/*IncludeType=*/false);1894}1895}18961897void DeclPrinter::VisitNonTypeTemplateParmDecl(1898const NonTypeTemplateParmDecl *NTTP) {1899StringRef Name;1900if (IdentifierInfo *II = NTTP->getIdentifier())1901Name =1902Policy.CleanUglifiedParameters ? II->deuglifiedName() : II->getName();1903printDeclType(NTTP->getType(), Name, NTTP->isParameterPack());19041905if (NTTP->hasDefaultArgument()) {1906Out << " = ";1907NTTP->getDefaultArgument().getArgument().print(Policy, Out,1908/*IncludeType=*/false);1909}1910}191119121913