10b57cec5SDimitry Andric //===--- DeclPrinter.cpp - Printing implementation for Decl ASTs ----------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // This file implements the Decl::print method, which pretty prints the 100b57cec5SDimitry Andric // AST back out to C/Objective-C/C++/Objective-C++ code. 110b57cec5SDimitry Andric // 120b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 130b57cec5SDimitry Andric #include "clang/AST/ASTContext.h" 140b57cec5SDimitry Andric #include "clang/AST/Attr.h" 150b57cec5SDimitry Andric #include "clang/AST/Decl.h" 160b57cec5SDimitry Andric #include "clang/AST/DeclCXX.h" 170b57cec5SDimitry Andric #include "clang/AST/DeclObjC.h" 180b57cec5SDimitry Andric #include "clang/AST/DeclTemplate.h" 190b57cec5SDimitry Andric #include "clang/AST/DeclVisitor.h" 200b57cec5SDimitry Andric #include "clang/AST/Expr.h" 210b57cec5SDimitry Andric #include "clang/AST/ExprCXX.h" 220b57cec5SDimitry Andric #include "clang/AST/PrettyPrinter.h" 230b57cec5SDimitry Andric #include "clang/Basic/Module.h" 24*0fca6ea1SDimitry Andric #include "clang/Basic/SourceManager.h" 250b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 260b57cec5SDimitry Andric using namespace clang; 270b57cec5SDimitry Andric 280b57cec5SDimitry Andric namespace { 290b57cec5SDimitry Andric class DeclPrinter : public DeclVisitor<DeclPrinter> { 300b57cec5SDimitry Andric raw_ostream &Out; 310b57cec5SDimitry Andric PrintingPolicy Policy; 320b57cec5SDimitry Andric const ASTContext &Context; 330b57cec5SDimitry Andric unsigned Indentation; 340b57cec5SDimitry Andric bool PrintInstantiation; 350b57cec5SDimitry Andric 360b57cec5SDimitry Andric raw_ostream& Indent() { return Indent(Indentation); } 370b57cec5SDimitry Andric raw_ostream& Indent(unsigned Indentation); 380b57cec5SDimitry Andric void ProcessDeclGroup(SmallVectorImpl<Decl*>& Decls); 390b57cec5SDimitry Andric 400b57cec5SDimitry Andric void Print(AccessSpecifier AS); 410b57cec5SDimitry Andric void PrintConstructorInitializers(CXXConstructorDecl *CDecl, 420b57cec5SDimitry Andric std::string &Proto); 430b57cec5SDimitry Andric 440b57cec5SDimitry Andric /// Print an Objective-C method type in parentheses. 450b57cec5SDimitry Andric /// 460b57cec5SDimitry Andric /// \param Quals The Objective-C declaration qualifiers. 470b57cec5SDimitry Andric /// \param T The type to print. 480b57cec5SDimitry Andric void PrintObjCMethodType(ASTContext &Ctx, Decl::ObjCDeclQualifier Quals, 490b57cec5SDimitry Andric QualType T); 500b57cec5SDimitry Andric 510b57cec5SDimitry Andric void PrintObjCTypeParams(ObjCTypeParamList *Params); 520b57cec5SDimitry Andric 530b57cec5SDimitry Andric public: 540b57cec5SDimitry Andric DeclPrinter(raw_ostream &Out, const PrintingPolicy &Policy, 550b57cec5SDimitry Andric const ASTContext &Context, unsigned Indentation = 0, 560b57cec5SDimitry Andric bool PrintInstantiation = false) 570b57cec5SDimitry Andric : Out(Out), Policy(Policy), Context(Context), Indentation(Indentation), 580b57cec5SDimitry Andric PrintInstantiation(PrintInstantiation) {} 590b57cec5SDimitry Andric 600b57cec5SDimitry Andric void VisitDeclContext(DeclContext *DC, bool Indent = true); 610b57cec5SDimitry Andric 620b57cec5SDimitry Andric void VisitTranslationUnitDecl(TranslationUnitDecl *D); 630b57cec5SDimitry Andric void VisitTypedefDecl(TypedefDecl *D); 640b57cec5SDimitry Andric void VisitTypeAliasDecl(TypeAliasDecl *D); 650b57cec5SDimitry Andric void VisitEnumDecl(EnumDecl *D); 660b57cec5SDimitry Andric void VisitRecordDecl(RecordDecl *D); 670b57cec5SDimitry Andric void VisitEnumConstantDecl(EnumConstantDecl *D); 680b57cec5SDimitry Andric void VisitEmptyDecl(EmptyDecl *D); 690b57cec5SDimitry Andric void VisitFunctionDecl(FunctionDecl *D); 700b57cec5SDimitry Andric void VisitFriendDecl(FriendDecl *D); 710b57cec5SDimitry Andric void VisitFieldDecl(FieldDecl *D); 720b57cec5SDimitry Andric void VisitVarDecl(VarDecl *D); 730b57cec5SDimitry Andric void VisitLabelDecl(LabelDecl *D); 740b57cec5SDimitry Andric void VisitParmVarDecl(ParmVarDecl *D); 750b57cec5SDimitry Andric void VisitFileScopeAsmDecl(FileScopeAsmDecl *D); 76bdd1243dSDimitry Andric void VisitTopLevelStmtDecl(TopLevelStmtDecl *D); 770b57cec5SDimitry Andric void VisitImportDecl(ImportDecl *D); 780b57cec5SDimitry Andric void VisitStaticAssertDecl(StaticAssertDecl *D); 790b57cec5SDimitry Andric void VisitNamespaceDecl(NamespaceDecl *D); 800b57cec5SDimitry Andric void VisitUsingDirectiveDecl(UsingDirectiveDecl *D); 810b57cec5SDimitry Andric void VisitNamespaceAliasDecl(NamespaceAliasDecl *D); 820b57cec5SDimitry Andric void VisitCXXRecordDecl(CXXRecordDecl *D); 830b57cec5SDimitry Andric void VisitLinkageSpecDecl(LinkageSpecDecl *D); 840b57cec5SDimitry Andric void VisitTemplateDecl(const TemplateDecl *D); 850b57cec5SDimitry Andric void VisitFunctionTemplateDecl(FunctionTemplateDecl *D); 860b57cec5SDimitry Andric void VisitClassTemplateDecl(ClassTemplateDecl *D); 870b57cec5SDimitry Andric void VisitClassTemplateSpecializationDecl( 880b57cec5SDimitry Andric ClassTemplateSpecializationDecl *D); 890b57cec5SDimitry Andric void VisitClassTemplatePartialSpecializationDecl( 900b57cec5SDimitry Andric ClassTemplatePartialSpecializationDecl *D); 910b57cec5SDimitry Andric void VisitObjCMethodDecl(ObjCMethodDecl *D); 920b57cec5SDimitry Andric void VisitObjCImplementationDecl(ObjCImplementationDecl *D); 930b57cec5SDimitry Andric void VisitObjCInterfaceDecl(ObjCInterfaceDecl *D); 940b57cec5SDimitry Andric void VisitObjCProtocolDecl(ObjCProtocolDecl *D); 950b57cec5SDimitry Andric void VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D); 960b57cec5SDimitry Andric void VisitObjCCategoryDecl(ObjCCategoryDecl *D); 970b57cec5SDimitry Andric void VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *D); 980b57cec5SDimitry Andric void VisitObjCPropertyDecl(ObjCPropertyDecl *D); 990b57cec5SDimitry Andric void VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D); 1000b57cec5SDimitry Andric void VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D); 1010b57cec5SDimitry Andric void VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D); 1020b57cec5SDimitry Andric void VisitUsingDecl(UsingDecl *D); 103fe6060f1SDimitry Andric void VisitUsingEnumDecl(UsingEnumDecl *D); 1040b57cec5SDimitry Andric void VisitUsingShadowDecl(UsingShadowDecl *D); 1050b57cec5SDimitry Andric void VisitOMPThreadPrivateDecl(OMPThreadPrivateDecl *D); 1060b57cec5SDimitry Andric void VisitOMPAllocateDecl(OMPAllocateDecl *D); 1070b57cec5SDimitry Andric void VisitOMPRequiresDecl(OMPRequiresDecl *D); 1080b57cec5SDimitry Andric void VisitOMPDeclareReductionDecl(OMPDeclareReductionDecl *D); 1090b57cec5SDimitry Andric void VisitOMPDeclareMapperDecl(OMPDeclareMapperDecl *D); 1100b57cec5SDimitry Andric void VisitOMPCapturedExprDecl(OMPCapturedExprDecl *D); 1115ffd83dbSDimitry Andric void VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *TTP); 1125ffd83dbSDimitry Andric void VisitNonTypeTemplateParmDecl(const NonTypeTemplateParmDecl *NTTP); 113bdd1243dSDimitry Andric void VisitHLSLBufferDecl(HLSLBufferDecl *D); 1140b57cec5SDimitry Andric 1150b57cec5SDimitry Andric void printTemplateParameters(const TemplateParameterList *Params, 1160b57cec5SDimitry Andric bool OmitTemplateKW = false); 117fe6060f1SDimitry Andric void printTemplateArguments(llvm::ArrayRef<TemplateArgument> Args, 118349cc55cSDimitry Andric const TemplateParameterList *Params); 119fe6060f1SDimitry Andric void printTemplateArguments(llvm::ArrayRef<TemplateArgumentLoc> Args, 120349cc55cSDimitry Andric const TemplateParameterList *Params); 121*0fca6ea1SDimitry Andric enum class AttrPosAsWritten { Default = 0, Left, Right }; 122*0fca6ea1SDimitry Andric bool 123*0fca6ea1SDimitry Andric prettyPrintAttributes(const Decl *D, 124*0fca6ea1SDimitry Andric AttrPosAsWritten Pos = AttrPosAsWritten::Default); 1250b57cec5SDimitry Andric void prettyPrintPragmas(Decl *D); 1260b57cec5SDimitry Andric void printDeclType(QualType T, StringRef DeclName, bool Pack = false); 1270b57cec5SDimitry Andric }; 1280b57cec5SDimitry Andric } 1290b57cec5SDimitry Andric 1300b57cec5SDimitry Andric void Decl::print(raw_ostream &Out, unsigned Indentation, 1310b57cec5SDimitry Andric bool PrintInstantiation) const { 1320b57cec5SDimitry Andric print(Out, getASTContext().getPrintingPolicy(), Indentation, PrintInstantiation); 1330b57cec5SDimitry Andric } 1340b57cec5SDimitry Andric 1350b57cec5SDimitry Andric void Decl::print(raw_ostream &Out, const PrintingPolicy &Policy, 1360b57cec5SDimitry Andric unsigned Indentation, bool PrintInstantiation) const { 1370b57cec5SDimitry Andric DeclPrinter Printer(Out, Policy, getASTContext(), Indentation, 1380b57cec5SDimitry Andric PrintInstantiation); 1390b57cec5SDimitry Andric Printer.Visit(const_cast<Decl*>(this)); 1400b57cec5SDimitry Andric } 1410b57cec5SDimitry Andric 1420b57cec5SDimitry Andric void TemplateParameterList::print(raw_ostream &Out, const ASTContext &Context, 1430b57cec5SDimitry Andric bool OmitTemplateKW) const { 1440b57cec5SDimitry Andric print(Out, Context, Context.getPrintingPolicy(), OmitTemplateKW); 1450b57cec5SDimitry Andric } 1460b57cec5SDimitry Andric 1470b57cec5SDimitry Andric void TemplateParameterList::print(raw_ostream &Out, const ASTContext &Context, 1480b57cec5SDimitry Andric const PrintingPolicy &Policy, 1490b57cec5SDimitry Andric bool OmitTemplateKW) const { 1500b57cec5SDimitry Andric DeclPrinter Printer(Out, Policy, Context); 1510b57cec5SDimitry Andric Printer.printTemplateParameters(this, OmitTemplateKW); 1520b57cec5SDimitry Andric } 1530b57cec5SDimitry Andric 1540b57cec5SDimitry Andric static QualType GetBaseType(QualType T) { 1550b57cec5SDimitry Andric // FIXME: This should be on the Type class! 1560b57cec5SDimitry Andric QualType BaseType = T; 1570b57cec5SDimitry Andric while (!BaseType->isSpecifierType()) { 1580b57cec5SDimitry Andric if (const PointerType *PTy = BaseType->getAs<PointerType>()) 1590b57cec5SDimitry Andric BaseType = PTy->getPointeeType(); 160349cc55cSDimitry Andric else if (const ObjCObjectPointerType *OPT = 161349cc55cSDimitry Andric BaseType->getAs<ObjCObjectPointerType>()) 162349cc55cSDimitry Andric BaseType = OPT->getPointeeType(); 1630b57cec5SDimitry Andric else if (const BlockPointerType *BPy = BaseType->getAs<BlockPointerType>()) 1640b57cec5SDimitry Andric BaseType = BPy->getPointeeType(); 1650b57cec5SDimitry Andric else if (const ArrayType *ATy = dyn_cast<ArrayType>(BaseType)) 1660b57cec5SDimitry Andric BaseType = ATy->getElementType(); 1670b57cec5SDimitry Andric else if (const FunctionType *FTy = BaseType->getAs<FunctionType>()) 1680b57cec5SDimitry Andric BaseType = FTy->getReturnType(); 1690b57cec5SDimitry Andric else if (const VectorType *VTy = BaseType->getAs<VectorType>()) 1700b57cec5SDimitry Andric BaseType = VTy->getElementType(); 1710b57cec5SDimitry Andric else if (const ReferenceType *RTy = BaseType->getAs<ReferenceType>()) 1720b57cec5SDimitry Andric BaseType = RTy->getPointeeType(); 1730b57cec5SDimitry Andric else if (const AutoType *ATy = BaseType->getAs<AutoType>()) 1740b57cec5SDimitry Andric BaseType = ATy->getDeducedType(); 1750b57cec5SDimitry Andric else if (const ParenType *PTy = BaseType->getAs<ParenType>()) 1760b57cec5SDimitry Andric BaseType = PTy->desugar(); 1770b57cec5SDimitry Andric else 1780b57cec5SDimitry Andric // This must be a syntax error. 1790b57cec5SDimitry Andric break; 1800b57cec5SDimitry Andric } 1810b57cec5SDimitry Andric return BaseType; 1820b57cec5SDimitry Andric } 1830b57cec5SDimitry Andric 1840b57cec5SDimitry Andric static QualType getDeclType(Decl* D) { 1850b57cec5SDimitry Andric if (TypedefNameDecl* TDD = dyn_cast<TypedefNameDecl>(D)) 1860b57cec5SDimitry Andric return TDD->getUnderlyingType(); 1870b57cec5SDimitry Andric if (ValueDecl* VD = dyn_cast<ValueDecl>(D)) 1880b57cec5SDimitry Andric return VD->getType(); 1890b57cec5SDimitry Andric return QualType(); 1900b57cec5SDimitry Andric } 1910b57cec5SDimitry Andric 1920b57cec5SDimitry Andric void Decl::printGroup(Decl** Begin, unsigned NumDecls, 1930b57cec5SDimitry Andric raw_ostream &Out, const PrintingPolicy &Policy, 1940b57cec5SDimitry Andric unsigned Indentation) { 1950b57cec5SDimitry Andric if (NumDecls == 1) { 1960b57cec5SDimitry Andric (*Begin)->print(Out, Policy, Indentation); 1970b57cec5SDimitry Andric return; 1980b57cec5SDimitry Andric } 1990b57cec5SDimitry Andric 2000b57cec5SDimitry Andric Decl** End = Begin + NumDecls; 2010b57cec5SDimitry Andric TagDecl* TD = dyn_cast<TagDecl>(*Begin); 2020b57cec5SDimitry Andric if (TD) 2030b57cec5SDimitry Andric ++Begin; 2040b57cec5SDimitry Andric 2050b57cec5SDimitry Andric PrintingPolicy SubPolicy(Policy); 2060b57cec5SDimitry Andric 2070b57cec5SDimitry Andric bool isFirst = true; 2080b57cec5SDimitry Andric for ( ; Begin != End; ++Begin) { 2090b57cec5SDimitry Andric if (isFirst) { 2100b57cec5SDimitry Andric if(TD) 2110b57cec5SDimitry Andric SubPolicy.IncludeTagDefinition = true; 2120b57cec5SDimitry Andric SubPolicy.SuppressSpecifiers = false; 2130b57cec5SDimitry Andric isFirst = false; 2140b57cec5SDimitry Andric } else { 2150b57cec5SDimitry Andric if (!isFirst) Out << ", "; 2160b57cec5SDimitry Andric SubPolicy.IncludeTagDefinition = false; 2170b57cec5SDimitry Andric SubPolicy.SuppressSpecifiers = true; 2180b57cec5SDimitry Andric } 2190b57cec5SDimitry Andric 2200b57cec5SDimitry Andric (*Begin)->print(Out, SubPolicy, Indentation); 2210b57cec5SDimitry Andric } 2220b57cec5SDimitry Andric } 2230b57cec5SDimitry Andric 2240b57cec5SDimitry Andric LLVM_DUMP_METHOD void DeclContext::dumpDeclContext() const { 2250b57cec5SDimitry Andric // Get the translation unit 2260b57cec5SDimitry Andric const DeclContext *DC = this; 2270b57cec5SDimitry Andric while (!DC->isTranslationUnit()) 2280b57cec5SDimitry Andric DC = DC->getParent(); 2290b57cec5SDimitry Andric 2300b57cec5SDimitry Andric ASTContext &Ctx = cast<TranslationUnitDecl>(DC)->getASTContext(); 2310b57cec5SDimitry Andric DeclPrinter Printer(llvm::errs(), Ctx.getPrintingPolicy(), Ctx, 0); 2320b57cec5SDimitry Andric Printer.VisitDeclContext(const_cast<DeclContext *>(this), /*Indent=*/false); 2330b57cec5SDimitry Andric } 2340b57cec5SDimitry Andric 2350b57cec5SDimitry Andric raw_ostream& DeclPrinter::Indent(unsigned Indentation) { 2360b57cec5SDimitry Andric for (unsigned i = 0; i != Indentation; ++i) 2370b57cec5SDimitry Andric Out << " "; 2380b57cec5SDimitry Andric return Out; 2390b57cec5SDimitry Andric } 2400b57cec5SDimitry Andric 241*0fca6ea1SDimitry Andric static DeclPrinter::AttrPosAsWritten getPosAsWritten(const Attr *A, 242*0fca6ea1SDimitry Andric const Decl *D) { 243*0fca6ea1SDimitry Andric SourceLocation ALoc = A->getLoc(); 244*0fca6ea1SDimitry Andric SourceLocation DLoc = D->getLocation(); 245*0fca6ea1SDimitry Andric const ASTContext &C = D->getASTContext(); 246*0fca6ea1SDimitry Andric if (ALoc.isInvalid() || DLoc.isInvalid()) 247*0fca6ea1SDimitry Andric return DeclPrinter::AttrPosAsWritten::Left; 2485f757f3fSDimitry Andric 249*0fca6ea1SDimitry Andric if (C.getSourceManager().isBeforeInTranslationUnit(ALoc, DLoc)) 250*0fca6ea1SDimitry Andric return DeclPrinter::AttrPosAsWritten::Left; 2515f757f3fSDimitry Andric 252*0fca6ea1SDimitry Andric return DeclPrinter::AttrPosAsWritten::Right; 2535f757f3fSDimitry Andric } 2545f757f3fSDimitry Andric 255*0fca6ea1SDimitry Andric // returns true if an attribute was printed. 256*0fca6ea1SDimitry Andric bool DeclPrinter::prettyPrintAttributes(const Decl *D, 257*0fca6ea1SDimitry Andric AttrPosAsWritten Pos /*=Default*/) { 258*0fca6ea1SDimitry Andric bool hasPrinted = false; 2590b57cec5SDimitry Andric 2600b57cec5SDimitry Andric if (D->hasAttrs()) { 261*0fca6ea1SDimitry Andric const AttrVec &Attrs = D->getAttrs(); 2620b57cec5SDimitry Andric for (auto *A : Attrs) { 2630b57cec5SDimitry Andric if (A->isInherited() || A->isImplicit()) 2640b57cec5SDimitry Andric continue; 265*0fca6ea1SDimitry Andric // Print out the keyword attributes, they aren't regular attributes. 266*0fca6ea1SDimitry Andric if (Policy.PolishForDeclaration && !A->isKeywordAttribute()) 267*0fca6ea1SDimitry Andric continue; 268*0fca6ea1SDimitry Andric switch (A->getKind()) { 269*0fca6ea1SDimitry Andric #define ATTR(X) 270*0fca6ea1SDimitry Andric #define PRAGMA_SPELLING_ATTR(X) case attr::X: 271*0fca6ea1SDimitry Andric #include "clang/Basic/AttrList.inc" 272*0fca6ea1SDimitry Andric break; 273*0fca6ea1SDimitry Andric default: 274*0fca6ea1SDimitry Andric AttrPosAsWritten APos = getPosAsWritten(A, D); 275*0fca6ea1SDimitry Andric assert(APos != AttrPosAsWritten::Default && 276*0fca6ea1SDimitry Andric "Default not a valid for an attribute location"); 277*0fca6ea1SDimitry Andric if (Pos == AttrPosAsWritten::Default || Pos == APos) { 278*0fca6ea1SDimitry Andric if (Pos != AttrPosAsWritten::Left) 279*0fca6ea1SDimitry Andric Out << ' '; 2805f757f3fSDimitry Andric A->printPretty(Out, Policy); 281*0fca6ea1SDimitry Andric hasPrinted = true; 282*0fca6ea1SDimitry Andric if (Pos == AttrPosAsWritten::Left) 283*0fca6ea1SDimitry Andric Out << ' '; 284*0fca6ea1SDimitry Andric } 285*0fca6ea1SDimitry Andric break; 2860b57cec5SDimitry Andric } 2870b57cec5SDimitry Andric } 2880b57cec5SDimitry Andric } 289*0fca6ea1SDimitry Andric return hasPrinted; 290*0fca6ea1SDimitry Andric } 2910b57cec5SDimitry Andric 2920b57cec5SDimitry Andric void DeclPrinter::prettyPrintPragmas(Decl *D) { 2930b57cec5SDimitry Andric if (Policy.PolishForDeclaration) 2940b57cec5SDimitry Andric return; 2950b57cec5SDimitry Andric 2960b57cec5SDimitry Andric if (D->hasAttrs()) { 2970b57cec5SDimitry Andric AttrVec &Attrs = D->getAttrs(); 2980b57cec5SDimitry Andric for (auto *A : Attrs) { 2990b57cec5SDimitry Andric switch (A->getKind()) { 3000b57cec5SDimitry Andric #define ATTR(X) 3010b57cec5SDimitry Andric #define PRAGMA_SPELLING_ATTR(X) case attr::X: 3020b57cec5SDimitry Andric #include "clang/Basic/AttrList.inc" 3030b57cec5SDimitry Andric A->printPretty(Out, Policy); 3040b57cec5SDimitry Andric Indent(); 3050b57cec5SDimitry Andric break; 3060b57cec5SDimitry Andric default: 3070b57cec5SDimitry Andric break; 3080b57cec5SDimitry Andric } 3090b57cec5SDimitry Andric } 3100b57cec5SDimitry Andric } 3110b57cec5SDimitry Andric } 3120b57cec5SDimitry Andric 3130b57cec5SDimitry Andric void DeclPrinter::printDeclType(QualType T, StringRef DeclName, bool Pack) { 3140b57cec5SDimitry Andric // Normally, a PackExpansionType is written as T[3]... (for instance, as a 3150b57cec5SDimitry Andric // template argument), but if it is the type of a declaration, the ellipsis 3160b57cec5SDimitry Andric // is placed before the name being declared. 3170b57cec5SDimitry Andric if (auto *PET = T->getAs<PackExpansionType>()) { 3180b57cec5SDimitry Andric Pack = true; 3190b57cec5SDimitry Andric T = PET->getPattern(); 3200b57cec5SDimitry Andric } 3210b57cec5SDimitry Andric T.print(Out, Policy, (Pack ? "..." : "") + DeclName, Indentation); 3220b57cec5SDimitry Andric } 3230b57cec5SDimitry Andric 3240b57cec5SDimitry Andric void DeclPrinter::ProcessDeclGroup(SmallVectorImpl<Decl*>& Decls) { 3250b57cec5SDimitry Andric this->Indent(); 3260b57cec5SDimitry Andric Decl::printGroup(Decls.data(), Decls.size(), Out, Policy, Indentation); 3270b57cec5SDimitry Andric Out << ";\n"; 3280b57cec5SDimitry Andric Decls.clear(); 3290b57cec5SDimitry Andric 3300b57cec5SDimitry Andric } 3310b57cec5SDimitry Andric 3320b57cec5SDimitry Andric void DeclPrinter::Print(AccessSpecifier AS) { 3335ffd83dbSDimitry Andric const auto AccessSpelling = getAccessSpelling(AS); 3345ffd83dbSDimitry Andric if (AccessSpelling.empty()) 3355ffd83dbSDimitry Andric llvm_unreachable("No access specifier!"); 3365ffd83dbSDimitry Andric Out << AccessSpelling; 3370b57cec5SDimitry Andric } 3380b57cec5SDimitry Andric 3390b57cec5SDimitry Andric void DeclPrinter::PrintConstructorInitializers(CXXConstructorDecl *CDecl, 3400b57cec5SDimitry Andric std::string &Proto) { 3410b57cec5SDimitry Andric bool HasInitializerList = false; 3420b57cec5SDimitry Andric for (const auto *BMInitializer : CDecl->inits()) { 3430b57cec5SDimitry Andric if (BMInitializer->isInClassMemberInitializer()) 3440b57cec5SDimitry Andric continue; 3455f757f3fSDimitry Andric if (!BMInitializer->isWritten()) 3465f757f3fSDimitry Andric continue; 3470b57cec5SDimitry Andric 3480b57cec5SDimitry Andric if (!HasInitializerList) { 3490b57cec5SDimitry Andric Proto += " : "; 3500b57cec5SDimitry Andric Out << Proto; 3510b57cec5SDimitry Andric Proto.clear(); 3520b57cec5SDimitry Andric HasInitializerList = true; 3530b57cec5SDimitry Andric } else 3540b57cec5SDimitry Andric Out << ", "; 3550b57cec5SDimitry Andric 3560b57cec5SDimitry Andric if (BMInitializer->isAnyMemberInitializer()) { 3570b57cec5SDimitry Andric FieldDecl *FD = BMInitializer->getAnyMember(); 3580b57cec5SDimitry Andric Out << *FD; 3595f757f3fSDimitry Andric } else if (BMInitializer->isDelegatingInitializer()) { 3605f757f3fSDimitry Andric Out << CDecl->getNameAsString(); 3610b57cec5SDimitry Andric } else { 3620b57cec5SDimitry Andric Out << QualType(BMInitializer->getBaseClass(), 0).getAsString(Policy); 3630b57cec5SDimitry Andric } 3640b57cec5SDimitry Andric 3655f757f3fSDimitry Andric if (Expr *Init = BMInitializer->getInit()) { 3665f757f3fSDimitry Andric bool OutParens = !isa<InitListExpr>(Init); 3675f757f3fSDimitry Andric 3685f757f3fSDimitry Andric if (OutParens) 3690b57cec5SDimitry Andric Out << "("; 3705f757f3fSDimitry Andric 3710b57cec5SDimitry Andric if (ExprWithCleanups *Tmp = dyn_cast<ExprWithCleanups>(Init)) 3720b57cec5SDimitry Andric Init = Tmp->getSubExpr(); 3730b57cec5SDimitry Andric 3740b57cec5SDimitry Andric Init = Init->IgnoreParens(); 3750b57cec5SDimitry Andric 3760b57cec5SDimitry Andric Expr *SimpleInit = nullptr; 3770b57cec5SDimitry Andric Expr **Args = nullptr; 3780b57cec5SDimitry Andric unsigned NumArgs = 0; 3790b57cec5SDimitry Andric if (ParenListExpr *ParenList = dyn_cast<ParenListExpr>(Init)) { 3800b57cec5SDimitry Andric Args = ParenList->getExprs(); 3810b57cec5SDimitry Andric NumArgs = ParenList->getNumExprs(); 3820b57cec5SDimitry Andric } else if (CXXConstructExpr *Construct = 3830b57cec5SDimitry Andric dyn_cast<CXXConstructExpr>(Init)) { 3840b57cec5SDimitry Andric Args = Construct->getArgs(); 3850b57cec5SDimitry Andric NumArgs = Construct->getNumArgs(); 3860b57cec5SDimitry Andric } else 3870b57cec5SDimitry Andric SimpleInit = Init; 3880b57cec5SDimitry Andric 3890b57cec5SDimitry Andric if (SimpleInit) 390fe6060f1SDimitry Andric SimpleInit->printPretty(Out, nullptr, Policy, Indentation, "\n", 391fe6060f1SDimitry Andric &Context); 3920b57cec5SDimitry Andric else { 3930b57cec5SDimitry Andric for (unsigned I = 0; I != NumArgs; ++I) { 3940b57cec5SDimitry Andric assert(Args[I] != nullptr && "Expected non-null Expr"); 3950b57cec5SDimitry Andric if (isa<CXXDefaultArgExpr>(Args[I])) 3960b57cec5SDimitry Andric break; 3970b57cec5SDimitry Andric 3980b57cec5SDimitry Andric if (I) 3990b57cec5SDimitry Andric Out << ", "; 400fe6060f1SDimitry Andric Args[I]->printPretty(Out, nullptr, Policy, Indentation, "\n", 401fe6060f1SDimitry Andric &Context); 4020b57cec5SDimitry Andric } 4030b57cec5SDimitry Andric } 4045f757f3fSDimitry Andric 4055f757f3fSDimitry Andric if (OutParens) 4060b57cec5SDimitry Andric Out << ")"; 4075f757f3fSDimitry Andric } else { 4085f757f3fSDimitry Andric Out << "()"; 4095f757f3fSDimitry Andric } 4105f757f3fSDimitry Andric 4110b57cec5SDimitry Andric if (BMInitializer->isPackExpansion()) 4120b57cec5SDimitry Andric Out << "..."; 4130b57cec5SDimitry Andric } 4140b57cec5SDimitry Andric } 4150b57cec5SDimitry Andric 4160b57cec5SDimitry Andric //---------------------------------------------------------------------------- 4170b57cec5SDimitry Andric // Common C declarations 4180b57cec5SDimitry Andric //---------------------------------------------------------------------------- 4190b57cec5SDimitry Andric 4200b57cec5SDimitry Andric void DeclPrinter::VisitDeclContext(DeclContext *DC, bool Indent) { 4210b57cec5SDimitry Andric if (Policy.TerseOutput) 4220b57cec5SDimitry Andric return; 4230b57cec5SDimitry Andric 4240b57cec5SDimitry Andric if (Indent) 4250b57cec5SDimitry Andric Indentation += Policy.Indentation; 4260b57cec5SDimitry Andric 4270b57cec5SDimitry Andric SmallVector<Decl*, 2> Decls; 4280b57cec5SDimitry Andric for (DeclContext::decl_iterator D = DC->decls_begin(), DEnd = DC->decls_end(); 4290b57cec5SDimitry Andric D != DEnd; ++D) { 4300b57cec5SDimitry Andric 4310b57cec5SDimitry Andric // Don't print ObjCIvarDecls, as they are printed when visiting the 4320b57cec5SDimitry Andric // containing ObjCInterfaceDecl. 4330b57cec5SDimitry Andric if (isa<ObjCIvarDecl>(*D)) 4340b57cec5SDimitry Andric continue; 4350b57cec5SDimitry Andric 4360b57cec5SDimitry Andric // Skip over implicit declarations in pretty-printing mode. 4370b57cec5SDimitry Andric if (D->isImplicit()) 4380b57cec5SDimitry Andric continue; 4390b57cec5SDimitry Andric 4400b57cec5SDimitry Andric // Don't print implicit specializations, as they are printed when visiting 4410b57cec5SDimitry Andric // corresponding templates. 4420b57cec5SDimitry Andric if (auto FD = dyn_cast<FunctionDecl>(*D)) 4430b57cec5SDimitry Andric if (FD->getTemplateSpecializationKind() == TSK_ImplicitInstantiation && 4440b57cec5SDimitry Andric !isa<ClassTemplateSpecializationDecl>(DC)) 4450b57cec5SDimitry Andric continue; 4460b57cec5SDimitry Andric 4470b57cec5SDimitry Andric // The next bits of code handle stuff like "struct {int x;} a,b"; we're 4480b57cec5SDimitry Andric // forced to merge the declarations because there's no other way to 4490b57cec5SDimitry Andric // refer to the struct in question. When that struct is named instead, we 4500b57cec5SDimitry Andric // also need to merge to avoid splitting off a stand-alone struct 4510b57cec5SDimitry Andric // declaration that produces the warning ext_no_declarators in some 4520b57cec5SDimitry Andric // contexts. 4530b57cec5SDimitry Andric // 4540b57cec5SDimitry Andric // This limited merging is safe without a bunch of other checks because it 4550b57cec5SDimitry Andric // only merges declarations directly referring to the tag, not typedefs. 4560b57cec5SDimitry Andric // 4570b57cec5SDimitry Andric // Check whether the current declaration should be grouped with a previous 4580b57cec5SDimitry Andric // non-free-standing tag declaration. 4590b57cec5SDimitry Andric QualType CurDeclType = getDeclType(*D); 4600b57cec5SDimitry Andric if (!Decls.empty() && !CurDeclType.isNull()) { 4610b57cec5SDimitry Andric QualType BaseType = GetBaseType(CurDeclType); 4620b57cec5SDimitry Andric if (!BaseType.isNull() && isa<ElaboratedType>(BaseType) && 4630b57cec5SDimitry Andric cast<ElaboratedType>(BaseType)->getOwnedTagDecl() == Decls[0]) { 4640b57cec5SDimitry Andric Decls.push_back(*D); 4650b57cec5SDimitry Andric continue; 4660b57cec5SDimitry Andric } 4670b57cec5SDimitry Andric } 4680b57cec5SDimitry Andric 4690b57cec5SDimitry Andric // If we have a merged group waiting to be handled, handle it now. 4700b57cec5SDimitry Andric if (!Decls.empty()) 4710b57cec5SDimitry Andric ProcessDeclGroup(Decls); 4720b57cec5SDimitry Andric 4730b57cec5SDimitry Andric // If the current declaration is not a free standing declaration, save it 4740b57cec5SDimitry Andric // so we can merge it with the subsequent declaration(s) using it. 4750b57cec5SDimitry Andric if (isa<TagDecl>(*D) && !cast<TagDecl>(*D)->isFreeStanding()) { 4760b57cec5SDimitry Andric Decls.push_back(*D); 4770b57cec5SDimitry Andric continue; 4780b57cec5SDimitry Andric } 4790b57cec5SDimitry Andric 4800b57cec5SDimitry Andric if (isa<AccessSpecDecl>(*D)) { 4810b57cec5SDimitry Andric Indentation -= Policy.Indentation; 4820b57cec5SDimitry Andric this->Indent(); 4830b57cec5SDimitry Andric Print(D->getAccess()); 4840b57cec5SDimitry Andric Out << ":\n"; 4850b57cec5SDimitry Andric Indentation += Policy.Indentation; 4860b57cec5SDimitry Andric continue; 4870b57cec5SDimitry Andric } 4880b57cec5SDimitry Andric 4890b57cec5SDimitry Andric this->Indent(); 4900b57cec5SDimitry Andric Visit(*D); 4910b57cec5SDimitry Andric 4920b57cec5SDimitry Andric // FIXME: Need to be able to tell the DeclPrinter when 4930b57cec5SDimitry Andric const char *Terminator = nullptr; 4940b57cec5SDimitry Andric if (isa<OMPThreadPrivateDecl>(*D) || isa<OMPDeclareReductionDecl>(*D) || 4950b57cec5SDimitry Andric isa<OMPDeclareMapperDecl>(*D) || isa<OMPRequiresDecl>(*D) || 4960b57cec5SDimitry Andric isa<OMPAllocateDecl>(*D)) 4970b57cec5SDimitry Andric Terminator = nullptr; 4980b57cec5SDimitry Andric else if (isa<ObjCMethodDecl>(*D) && cast<ObjCMethodDecl>(*D)->hasBody()) 4990b57cec5SDimitry Andric Terminator = nullptr; 5000b57cec5SDimitry Andric else if (auto FD = dyn_cast<FunctionDecl>(*D)) { 5015f757f3fSDimitry Andric if (FD->doesThisDeclarationHaveABody() && !FD->isDefaulted()) 5020b57cec5SDimitry Andric Terminator = nullptr; 5030b57cec5SDimitry Andric else 5040b57cec5SDimitry Andric Terminator = ";"; 5050b57cec5SDimitry Andric } else if (auto TD = dyn_cast<FunctionTemplateDecl>(*D)) { 5065f757f3fSDimitry Andric if (TD->getTemplatedDecl()->doesThisDeclarationHaveABody()) 5070b57cec5SDimitry Andric Terminator = nullptr; 5080b57cec5SDimitry Andric else 5090b57cec5SDimitry Andric Terminator = ";"; 510bdd1243dSDimitry Andric } else if (isa<NamespaceDecl, LinkageSpecDecl, ObjCImplementationDecl, 511bdd1243dSDimitry Andric ObjCInterfaceDecl, ObjCProtocolDecl, ObjCCategoryImplDecl, 512bdd1243dSDimitry Andric ObjCCategoryDecl, HLSLBufferDecl>(*D)) 5130b57cec5SDimitry Andric Terminator = nullptr; 5140b57cec5SDimitry Andric else if (isa<EnumConstantDecl>(*D)) { 5150b57cec5SDimitry Andric DeclContext::decl_iterator Next = D; 5160b57cec5SDimitry Andric ++Next; 5170b57cec5SDimitry Andric if (Next != DEnd) 5180b57cec5SDimitry Andric Terminator = ","; 5190b57cec5SDimitry Andric } else 5200b57cec5SDimitry Andric Terminator = ";"; 5210b57cec5SDimitry Andric 5220b57cec5SDimitry Andric if (Terminator) 5230b57cec5SDimitry Andric Out << Terminator; 5240b57cec5SDimitry Andric if (!Policy.TerseOutput && 5250b57cec5SDimitry Andric ((isa<FunctionDecl>(*D) && 5260b57cec5SDimitry Andric cast<FunctionDecl>(*D)->doesThisDeclarationHaveABody()) || 5270b57cec5SDimitry Andric (isa<FunctionTemplateDecl>(*D) && 5280b57cec5SDimitry Andric cast<FunctionTemplateDecl>(*D)->getTemplatedDecl()->doesThisDeclarationHaveABody()))) 5290b57cec5SDimitry Andric ; // StmtPrinter already added '\n' after CompoundStmt. 5300b57cec5SDimitry Andric else 5310b57cec5SDimitry Andric Out << "\n"; 5320b57cec5SDimitry Andric 5330b57cec5SDimitry Andric // Declare target attribute is special one, natural spelling for the pragma 5340b57cec5SDimitry Andric // assumes "ending" construct so print it here. 5350b57cec5SDimitry Andric if (D->hasAttr<OMPDeclareTargetDeclAttr>()) 5360b57cec5SDimitry Andric Out << "#pragma omp end declare target\n"; 5370b57cec5SDimitry Andric } 5380b57cec5SDimitry Andric 5390b57cec5SDimitry Andric if (!Decls.empty()) 5400b57cec5SDimitry Andric ProcessDeclGroup(Decls); 5410b57cec5SDimitry Andric 5420b57cec5SDimitry Andric if (Indent) 5430b57cec5SDimitry Andric Indentation -= Policy.Indentation; 5440b57cec5SDimitry Andric } 5450b57cec5SDimitry Andric 5460b57cec5SDimitry Andric void DeclPrinter::VisitTranslationUnitDecl(TranslationUnitDecl *D) { 5470b57cec5SDimitry Andric VisitDeclContext(D, false); 5480b57cec5SDimitry Andric } 5490b57cec5SDimitry Andric 5500b57cec5SDimitry Andric void DeclPrinter::VisitTypedefDecl(TypedefDecl *D) { 5510b57cec5SDimitry Andric if (!Policy.SuppressSpecifiers) { 5520b57cec5SDimitry Andric Out << "typedef "; 5530b57cec5SDimitry Andric 5540b57cec5SDimitry Andric if (D->isModulePrivate()) 5550b57cec5SDimitry Andric Out << "__module_private__ "; 5560b57cec5SDimitry Andric } 5570b57cec5SDimitry Andric QualType Ty = D->getTypeSourceInfo()->getType(); 5580b57cec5SDimitry Andric Ty.print(Out, Policy, D->getName(), Indentation); 5590b57cec5SDimitry Andric prettyPrintAttributes(D); 5600b57cec5SDimitry Andric } 5610b57cec5SDimitry Andric 5620b57cec5SDimitry Andric void DeclPrinter::VisitTypeAliasDecl(TypeAliasDecl *D) { 5630b57cec5SDimitry Andric Out << "using " << *D; 5640b57cec5SDimitry Andric prettyPrintAttributes(D); 5650b57cec5SDimitry Andric Out << " = " << D->getTypeSourceInfo()->getType().getAsString(Policy); 5660b57cec5SDimitry Andric } 5670b57cec5SDimitry Andric 5680b57cec5SDimitry Andric void DeclPrinter::VisitEnumDecl(EnumDecl *D) { 5690b57cec5SDimitry Andric if (!Policy.SuppressSpecifiers && D->isModulePrivate()) 5700b57cec5SDimitry Andric Out << "__module_private__ "; 5710b57cec5SDimitry Andric Out << "enum"; 5720b57cec5SDimitry Andric if (D->isScoped()) { 5730b57cec5SDimitry Andric if (D->isScopedUsingClassTag()) 5740b57cec5SDimitry Andric Out << " class"; 5750b57cec5SDimitry Andric else 5760b57cec5SDimitry Andric Out << " struct"; 5770b57cec5SDimitry Andric } 5780b57cec5SDimitry Andric 5790b57cec5SDimitry Andric prettyPrintAttributes(D); 5800b57cec5SDimitry Andric 581e8d8bef9SDimitry Andric if (D->getDeclName()) 582e8d8bef9SDimitry Andric Out << ' ' << D->getDeclName(); 5830b57cec5SDimitry Andric 5845ffd83dbSDimitry Andric if (D->isFixed()) 5850b57cec5SDimitry Andric Out << " : " << D->getIntegerType().stream(Policy); 5860b57cec5SDimitry Andric 5870b57cec5SDimitry Andric if (D->isCompleteDefinition()) { 5880b57cec5SDimitry Andric Out << " {\n"; 5890b57cec5SDimitry Andric VisitDeclContext(D); 5900b57cec5SDimitry Andric Indent() << "}"; 5910b57cec5SDimitry Andric } 5920b57cec5SDimitry Andric } 5930b57cec5SDimitry Andric 5940b57cec5SDimitry Andric void DeclPrinter::VisitRecordDecl(RecordDecl *D) { 5950b57cec5SDimitry Andric if (!Policy.SuppressSpecifiers && D->isModulePrivate()) 5960b57cec5SDimitry Andric Out << "__module_private__ "; 5970b57cec5SDimitry Andric Out << D->getKindName(); 5980b57cec5SDimitry Andric 5990b57cec5SDimitry Andric prettyPrintAttributes(D); 6000b57cec5SDimitry Andric 6010b57cec5SDimitry Andric if (D->getIdentifier()) 6020b57cec5SDimitry Andric Out << ' ' << *D; 6030b57cec5SDimitry Andric 6040b57cec5SDimitry Andric if (D->isCompleteDefinition()) { 6050b57cec5SDimitry Andric Out << " {\n"; 6060b57cec5SDimitry Andric VisitDeclContext(D); 6070b57cec5SDimitry Andric Indent() << "}"; 6080b57cec5SDimitry Andric } 6090b57cec5SDimitry Andric } 6100b57cec5SDimitry Andric 6110b57cec5SDimitry Andric void DeclPrinter::VisitEnumConstantDecl(EnumConstantDecl *D) { 6120b57cec5SDimitry Andric Out << *D; 6130b57cec5SDimitry Andric prettyPrintAttributes(D); 6140b57cec5SDimitry Andric if (Expr *Init = D->getInitExpr()) { 6150b57cec5SDimitry Andric Out << " = "; 6160b57cec5SDimitry Andric Init->printPretty(Out, nullptr, Policy, Indentation, "\n", &Context); 6170b57cec5SDimitry Andric } 6180b57cec5SDimitry Andric } 6190b57cec5SDimitry Andric 6200b57cec5SDimitry Andric static void printExplicitSpecifier(ExplicitSpecifier ES, llvm::raw_ostream &Out, 621fe6060f1SDimitry Andric PrintingPolicy &Policy, unsigned Indentation, 622fe6060f1SDimitry Andric const ASTContext &Context) { 6230b57cec5SDimitry Andric std::string Proto = "explicit"; 6240b57cec5SDimitry Andric llvm::raw_string_ostream EOut(Proto); 6250b57cec5SDimitry Andric if (ES.getExpr()) { 6260b57cec5SDimitry Andric EOut << "("; 627fe6060f1SDimitry Andric ES.getExpr()->printPretty(EOut, nullptr, Policy, Indentation, "\n", 628fe6060f1SDimitry Andric &Context); 6290b57cec5SDimitry Andric EOut << ")"; 6300b57cec5SDimitry Andric } 6310b57cec5SDimitry Andric EOut << " "; 6320b57cec5SDimitry Andric EOut.flush(); 63304eeddc0SDimitry Andric Out << Proto; 6340b57cec5SDimitry Andric } 6350b57cec5SDimitry Andric 636*0fca6ea1SDimitry Andric static void MaybePrintTagKeywordIfSupressingScopes(PrintingPolicy &Policy, 637*0fca6ea1SDimitry Andric QualType T, 638*0fca6ea1SDimitry Andric llvm::raw_ostream &Out) { 639*0fca6ea1SDimitry Andric StringRef prefix = T->isClassType() ? "class " 640*0fca6ea1SDimitry Andric : T->isStructureType() ? "struct " 641*0fca6ea1SDimitry Andric : T->isUnionType() ? "union " 642*0fca6ea1SDimitry Andric : ""; 643*0fca6ea1SDimitry Andric Out << prefix; 644*0fca6ea1SDimitry Andric } 645*0fca6ea1SDimitry Andric 6460b57cec5SDimitry Andric void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) { 6470b57cec5SDimitry Andric if (!D->getDescribedFunctionTemplate() && 648*0fca6ea1SDimitry Andric !D->isFunctionTemplateSpecialization()) { 6490b57cec5SDimitry Andric prettyPrintPragmas(D); 650*0fca6ea1SDimitry Andric prettyPrintAttributes(D, AttrPosAsWritten::Left); 651*0fca6ea1SDimitry Andric } 6520b57cec5SDimitry Andric 6530b57cec5SDimitry Andric if (D->isFunctionTemplateSpecialization()) 6540b57cec5SDimitry Andric Out << "template<> "; 6550b57cec5SDimitry Andric else if (!D->getDescribedFunctionTemplate()) { 6560b57cec5SDimitry Andric for (unsigned I = 0, NumTemplateParams = D->getNumTemplateParameterLists(); 6570b57cec5SDimitry Andric I < NumTemplateParams; ++I) 6580b57cec5SDimitry Andric printTemplateParameters(D->getTemplateParameterList(I)); 6590b57cec5SDimitry Andric } 6600b57cec5SDimitry Andric 6610b57cec5SDimitry Andric CXXConstructorDecl *CDecl = dyn_cast<CXXConstructorDecl>(D); 6620b57cec5SDimitry Andric CXXConversionDecl *ConversionDecl = dyn_cast<CXXConversionDecl>(D); 6630b57cec5SDimitry Andric CXXDeductionGuideDecl *GuideDecl = dyn_cast<CXXDeductionGuideDecl>(D); 6640b57cec5SDimitry Andric if (!Policy.SuppressSpecifiers) { 6650b57cec5SDimitry Andric switch (D->getStorageClass()) { 6660b57cec5SDimitry Andric case SC_None: break; 6670b57cec5SDimitry Andric case SC_Extern: Out << "extern "; break; 6680b57cec5SDimitry Andric case SC_Static: Out << "static "; break; 6690b57cec5SDimitry Andric case SC_PrivateExtern: Out << "__private_extern__ "; break; 6700b57cec5SDimitry Andric case SC_Auto: case SC_Register: 6710b57cec5SDimitry Andric llvm_unreachable("invalid for functions"); 6720b57cec5SDimitry Andric } 6730b57cec5SDimitry Andric 6740b57cec5SDimitry Andric if (D->isInlineSpecified()) Out << "inline "; 6750b57cec5SDimitry Andric if (D->isVirtualAsWritten()) Out << "virtual "; 6760b57cec5SDimitry Andric if (D->isModulePrivate()) Out << "__module_private__ "; 6770b57cec5SDimitry Andric if (D->isConstexprSpecified() && !D->isExplicitlyDefaulted()) 6780b57cec5SDimitry Andric Out << "constexpr "; 6790b57cec5SDimitry Andric if (D->isConsteval()) Out << "consteval "; 68006c3fb27SDimitry Andric else if (D->isImmediateFunction()) 68106c3fb27SDimitry Andric Out << "immediate "; 6820b57cec5SDimitry Andric ExplicitSpecifier ExplicitSpec = ExplicitSpecifier::getFromDecl(D); 6830b57cec5SDimitry Andric if (ExplicitSpec.isSpecified()) 684fe6060f1SDimitry Andric printExplicitSpecifier(ExplicitSpec, Out, Policy, Indentation, Context); 6850b57cec5SDimitry Andric } 6860b57cec5SDimitry Andric 6870b57cec5SDimitry Andric PrintingPolicy SubPolicy(Policy); 6880b57cec5SDimitry Andric SubPolicy.SuppressSpecifiers = false; 6890b57cec5SDimitry Andric std::string Proto; 6900b57cec5SDimitry Andric 6910b57cec5SDimitry Andric if (Policy.FullyQualifiedName) { 6920b57cec5SDimitry Andric Proto += D->getQualifiedNameAsString(); 6930b57cec5SDimitry Andric } else { 694480093f4SDimitry Andric llvm::raw_string_ostream OS(Proto); 6950b57cec5SDimitry Andric if (!Policy.SuppressScope) { 6960b57cec5SDimitry Andric if (const NestedNameSpecifier *NS = D->getQualifier()) { 6970b57cec5SDimitry Andric NS->print(OS, Policy); 6980b57cec5SDimitry Andric } 6990b57cec5SDimitry Andric } 700480093f4SDimitry Andric D->getNameInfo().printName(OS, Policy); 7010b57cec5SDimitry Andric } 7020b57cec5SDimitry Andric 7030b57cec5SDimitry Andric if (GuideDecl) 7040b57cec5SDimitry Andric Proto = GuideDecl->getDeducedTemplate()->getDeclName().getAsString(); 705480093f4SDimitry Andric if (D->isFunctionTemplateSpecialization()) { 7060b57cec5SDimitry Andric llvm::raw_string_ostream POut(Proto); 7070b57cec5SDimitry Andric DeclPrinter TArgPrinter(POut, SubPolicy, Context, Indentation); 708480093f4SDimitry Andric const auto *TArgAsWritten = D->getTemplateSpecializationArgsAsWritten(); 709480093f4SDimitry Andric if (TArgAsWritten && !Policy.PrintCanonicalTypes) 710349cc55cSDimitry Andric TArgPrinter.printTemplateArguments(TArgAsWritten->arguments(), nullptr); 711480093f4SDimitry Andric else if (const TemplateArgumentList *TArgs = 712480093f4SDimitry Andric D->getTemplateSpecializationArgs()) 713349cc55cSDimitry Andric TArgPrinter.printTemplateArguments(TArgs->asArray(), nullptr); 7140b57cec5SDimitry Andric } 7150b57cec5SDimitry Andric 7160b57cec5SDimitry Andric QualType Ty = D->getType(); 7170b57cec5SDimitry Andric while (const ParenType *PT = dyn_cast<ParenType>(Ty)) { 7180b57cec5SDimitry Andric Proto = '(' + Proto + ')'; 7190b57cec5SDimitry Andric Ty = PT->getInnerType(); 7200b57cec5SDimitry Andric } 7210b57cec5SDimitry Andric 7220b57cec5SDimitry Andric if (const FunctionType *AFT = Ty->getAs<FunctionType>()) { 7230b57cec5SDimitry Andric const FunctionProtoType *FT = nullptr; 7240b57cec5SDimitry Andric if (D->hasWrittenPrototype()) 7250b57cec5SDimitry Andric FT = dyn_cast<FunctionProtoType>(AFT); 7260b57cec5SDimitry Andric 7270b57cec5SDimitry Andric Proto += "("; 7280b57cec5SDimitry Andric if (FT) { 7290b57cec5SDimitry Andric llvm::raw_string_ostream POut(Proto); 7300b57cec5SDimitry Andric DeclPrinter ParamPrinter(POut, SubPolicy, Context, Indentation); 7310b57cec5SDimitry Andric for (unsigned i = 0, e = D->getNumParams(); i != e; ++i) { 7320b57cec5SDimitry Andric if (i) POut << ", "; 7330b57cec5SDimitry Andric ParamPrinter.VisitParmVarDecl(D->getParamDecl(i)); 7340b57cec5SDimitry Andric } 7350b57cec5SDimitry Andric 7360b57cec5SDimitry Andric if (FT->isVariadic()) { 7370b57cec5SDimitry Andric if (D->getNumParams()) POut << ", "; 7380b57cec5SDimitry Andric POut << "..."; 73981ad6265SDimitry Andric } else if (!D->getNumParams() && !Context.getLangOpts().CPlusPlus) { 74081ad6265SDimitry Andric // The function has a prototype, so it needs to retain the prototype 74181ad6265SDimitry Andric // in C. 74281ad6265SDimitry Andric POut << "void"; 7430b57cec5SDimitry Andric } 7440b57cec5SDimitry Andric } else if (D->doesThisDeclarationHaveABody() && !D->hasPrototype()) { 7450b57cec5SDimitry Andric for (unsigned i = 0, e = D->getNumParams(); i != e; ++i) { 7460b57cec5SDimitry Andric if (i) 7470b57cec5SDimitry Andric Proto += ", "; 7480b57cec5SDimitry Andric Proto += D->getParamDecl(i)->getNameAsString(); 7490b57cec5SDimitry Andric } 7500b57cec5SDimitry Andric } 7510b57cec5SDimitry Andric 7520b57cec5SDimitry Andric Proto += ")"; 7530b57cec5SDimitry Andric 7540b57cec5SDimitry Andric if (FT) { 7550b57cec5SDimitry Andric if (FT->isConst()) 7560b57cec5SDimitry Andric Proto += " const"; 7570b57cec5SDimitry Andric if (FT->isVolatile()) 7580b57cec5SDimitry Andric Proto += " volatile"; 7590b57cec5SDimitry Andric if (FT->isRestrict()) 7600b57cec5SDimitry Andric Proto += " restrict"; 7610b57cec5SDimitry Andric 7620b57cec5SDimitry Andric switch (FT->getRefQualifier()) { 7630b57cec5SDimitry Andric case RQ_None: 7640b57cec5SDimitry Andric break; 7650b57cec5SDimitry Andric case RQ_LValue: 7660b57cec5SDimitry Andric Proto += " &"; 7670b57cec5SDimitry Andric break; 7680b57cec5SDimitry Andric case RQ_RValue: 7690b57cec5SDimitry Andric Proto += " &&"; 7700b57cec5SDimitry Andric break; 7710b57cec5SDimitry Andric } 7720b57cec5SDimitry Andric } 7730b57cec5SDimitry Andric 7740b57cec5SDimitry Andric if (FT && FT->hasDynamicExceptionSpec()) { 7750b57cec5SDimitry Andric Proto += " throw("; 7760b57cec5SDimitry Andric if (FT->getExceptionSpecType() == EST_MSAny) 7770b57cec5SDimitry Andric Proto += "..."; 7780b57cec5SDimitry Andric else 7790b57cec5SDimitry Andric for (unsigned I = 0, N = FT->getNumExceptions(); I != N; ++I) { 7800b57cec5SDimitry Andric if (I) 7810b57cec5SDimitry Andric Proto += ", "; 7820b57cec5SDimitry Andric 7830b57cec5SDimitry Andric Proto += FT->getExceptionType(I).getAsString(SubPolicy); 7840b57cec5SDimitry Andric } 7850b57cec5SDimitry Andric Proto += ")"; 7860b57cec5SDimitry Andric } else if (FT && isNoexceptExceptionSpec(FT->getExceptionSpecType())) { 7870b57cec5SDimitry Andric Proto += " noexcept"; 7880b57cec5SDimitry Andric if (isComputedNoexcept(FT->getExceptionSpecType())) { 7890b57cec5SDimitry Andric Proto += "("; 7900b57cec5SDimitry Andric llvm::raw_string_ostream EOut(Proto); 7910b57cec5SDimitry Andric FT->getNoexceptExpr()->printPretty(EOut, nullptr, SubPolicy, 792fe6060f1SDimitry Andric Indentation, "\n", &Context); 7930b57cec5SDimitry Andric EOut.flush(); 7940b57cec5SDimitry Andric Proto += ")"; 7950b57cec5SDimitry Andric } 7960b57cec5SDimitry Andric } 7970b57cec5SDimitry Andric 7980b57cec5SDimitry Andric if (CDecl) { 7990b57cec5SDimitry Andric if (!Policy.TerseOutput) 8000b57cec5SDimitry Andric PrintConstructorInitializers(CDecl, Proto); 8010b57cec5SDimitry Andric } else if (!ConversionDecl && !isa<CXXDestructorDecl>(D)) { 8020b57cec5SDimitry Andric if (FT && FT->hasTrailingReturn()) { 8030b57cec5SDimitry Andric if (!GuideDecl) 8040b57cec5SDimitry Andric Out << "auto "; 8050b57cec5SDimitry Andric Out << Proto << " -> "; 8060b57cec5SDimitry Andric Proto.clear(); 8070b57cec5SDimitry Andric } 808*0fca6ea1SDimitry Andric if (!Policy.SuppressTagKeyword && Policy.SuppressScope && 809*0fca6ea1SDimitry Andric !Policy.SuppressUnwrittenScope) 810*0fca6ea1SDimitry Andric MaybePrintTagKeywordIfSupressingScopes(Policy, AFT->getReturnType(), 811*0fca6ea1SDimitry Andric Out); 8120b57cec5SDimitry Andric AFT->getReturnType().print(Out, Policy, Proto); 8130b57cec5SDimitry Andric Proto.clear(); 8140b57cec5SDimitry Andric } 8150b57cec5SDimitry Andric Out << Proto; 816480093f4SDimitry Andric 817480093f4SDimitry Andric if (Expr *TrailingRequiresClause = D->getTrailingRequiresClause()) { 818480093f4SDimitry Andric Out << " requires "; 819fe6060f1SDimitry Andric TrailingRequiresClause->printPretty(Out, nullptr, SubPolicy, Indentation, 820fe6060f1SDimitry Andric "\n", &Context); 821480093f4SDimitry Andric } 8220b57cec5SDimitry Andric } else { 8230b57cec5SDimitry Andric Ty.print(Out, Policy, Proto); 8240b57cec5SDimitry Andric } 8250b57cec5SDimitry Andric 826*0fca6ea1SDimitry Andric prettyPrintAttributes(D, AttrPosAsWritten::Right); 8270b57cec5SDimitry Andric 8287a6dacacSDimitry Andric if (D->isPureVirtual()) 8290b57cec5SDimitry Andric Out << " = 0"; 830*0fca6ea1SDimitry Andric else if (D->isDeletedAsWritten()) { 8310b57cec5SDimitry Andric Out << " = delete"; 832*0fca6ea1SDimitry Andric if (const StringLiteral *M = D->getDeletedMessage()) { 833*0fca6ea1SDimitry Andric Out << "("; 834*0fca6ea1SDimitry Andric M->outputString(Out); 835*0fca6ea1SDimitry Andric Out << ")"; 836*0fca6ea1SDimitry Andric } 837*0fca6ea1SDimitry Andric } else if (D->isExplicitlyDefaulted()) 8380b57cec5SDimitry Andric Out << " = default"; 8390b57cec5SDimitry Andric else if (D->doesThisDeclarationHaveABody()) { 8400b57cec5SDimitry Andric if (!Policy.TerseOutput) { 8410b57cec5SDimitry Andric if (!D->hasPrototype() && D->getNumParams()) { 8420b57cec5SDimitry Andric // This is a K&R function definition, so we need to print the 8430b57cec5SDimitry Andric // parameters. 8440b57cec5SDimitry Andric Out << '\n'; 8450b57cec5SDimitry Andric DeclPrinter ParamPrinter(Out, SubPolicy, Context, Indentation); 8460b57cec5SDimitry Andric Indentation += Policy.Indentation; 8470b57cec5SDimitry Andric for (unsigned i = 0, e = D->getNumParams(); i != e; ++i) { 8480b57cec5SDimitry Andric Indent(); 8490b57cec5SDimitry Andric ParamPrinter.VisitParmVarDecl(D->getParamDecl(i)); 8500b57cec5SDimitry Andric Out << ";\n"; 8510b57cec5SDimitry Andric } 8520b57cec5SDimitry Andric Indentation -= Policy.Indentation; 853349cc55cSDimitry Andric } 8540b57cec5SDimitry Andric 8550b57cec5SDimitry Andric if (D->getBody()) 856349cc55cSDimitry Andric D->getBody()->printPrettyControlled(Out, nullptr, SubPolicy, Indentation, "\n", 857fe6060f1SDimitry Andric &Context); 8580b57cec5SDimitry Andric } else { 8590b57cec5SDimitry Andric if (!Policy.TerseOutput && isa<CXXConstructorDecl>(*D)) 8600b57cec5SDimitry Andric Out << " {}"; 8610b57cec5SDimitry Andric } 8620b57cec5SDimitry Andric } 8630b57cec5SDimitry Andric } 8640b57cec5SDimitry Andric 8650b57cec5SDimitry Andric void DeclPrinter::VisitFriendDecl(FriendDecl *D) { 8660b57cec5SDimitry Andric if (TypeSourceInfo *TSI = D->getFriendType()) { 8670b57cec5SDimitry Andric unsigned NumTPLists = D->getFriendTypeNumTemplateParameterLists(); 8680b57cec5SDimitry Andric for (unsigned i = 0; i < NumTPLists; ++i) 8690b57cec5SDimitry Andric printTemplateParameters(D->getFriendTypeTemplateParameterList(i)); 8700b57cec5SDimitry Andric Out << "friend "; 8710b57cec5SDimitry Andric Out << " " << TSI->getType().getAsString(Policy); 8720b57cec5SDimitry Andric } 8730b57cec5SDimitry Andric else if (FunctionDecl *FD = 8740b57cec5SDimitry Andric dyn_cast<FunctionDecl>(D->getFriendDecl())) { 8750b57cec5SDimitry Andric Out << "friend "; 8760b57cec5SDimitry Andric VisitFunctionDecl(FD); 8770b57cec5SDimitry Andric } 8780b57cec5SDimitry Andric else if (FunctionTemplateDecl *FTD = 8790b57cec5SDimitry Andric dyn_cast<FunctionTemplateDecl>(D->getFriendDecl())) { 8800b57cec5SDimitry Andric Out << "friend "; 8810b57cec5SDimitry Andric VisitFunctionTemplateDecl(FTD); 8820b57cec5SDimitry Andric } 8830b57cec5SDimitry Andric else if (ClassTemplateDecl *CTD = 8840b57cec5SDimitry Andric dyn_cast<ClassTemplateDecl>(D->getFriendDecl())) { 8850b57cec5SDimitry Andric Out << "friend "; 8860b57cec5SDimitry Andric VisitRedeclarableTemplateDecl(CTD); 8870b57cec5SDimitry Andric } 8880b57cec5SDimitry Andric } 8890b57cec5SDimitry Andric 8900b57cec5SDimitry Andric void DeclPrinter::VisitFieldDecl(FieldDecl *D) { 8910b57cec5SDimitry Andric // FIXME: add printing of pragma attributes if required. 8920b57cec5SDimitry Andric if (!Policy.SuppressSpecifiers && D->isMutable()) 8930b57cec5SDimitry Andric Out << "mutable "; 8940b57cec5SDimitry Andric if (!Policy.SuppressSpecifiers && D->isModulePrivate()) 8950b57cec5SDimitry Andric Out << "__module_private__ "; 8960b57cec5SDimitry Andric 8970b57cec5SDimitry Andric Out << D->getASTContext().getUnqualifiedObjCPointerType(D->getType()). 8980b57cec5SDimitry Andric stream(Policy, D->getName(), Indentation); 8990b57cec5SDimitry Andric 9000b57cec5SDimitry Andric if (D->isBitField()) { 9010b57cec5SDimitry Andric Out << " : "; 902fe6060f1SDimitry Andric D->getBitWidth()->printPretty(Out, nullptr, Policy, Indentation, "\n", 903fe6060f1SDimitry Andric &Context); 9040b57cec5SDimitry Andric } 9050b57cec5SDimitry Andric 9060b57cec5SDimitry Andric Expr *Init = D->getInClassInitializer(); 9070b57cec5SDimitry Andric if (!Policy.SuppressInitializers && Init) { 9080b57cec5SDimitry Andric if (D->getInClassInitStyle() == ICIS_ListInit) 9090b57cec5SDimitry Andric Out << " "; 9100b57cec5SDimitry Andric else 9110b57cec5SDimitry Andric Out << " = "; 912fe6060f1SDimitry Andric Init->printPretty(Out, nullptr, Policy, Indentation, "\n", &Context); 9130b57cec5SDimitry Andric } 9140b57cec5SDimitry Andric prettyPrintAttributes(D); 9150b57cec5SDimitry Andric } 9160b57cec5SDimitry Andric 9170b57cec5SDimitry Andric void DeclPrinter::VisitLabelDecl(LabelDecl *D) { 9180b57cec5SDimitry Andric Out << *D << ":"; 9190b57cec5SDimitry Andric } 9200b57cec5SDimitry Andric 9210b57cec5SDimitry Andric void DeclPrinter::VisitVarDecl(VarDecl *D) { 9220b57cec5SDimitry Andric prettyPrintPragmas(D); 9230b57cec5SDimitry Andric 924*0fca6ea1SDimitry Andric prettyPrintAttributes(D, AttrPosAsWritten::Left); 925*0fca6ea1SDimitry Andric 9265f757f3fSDimitry Andric if (const auto *Param = dyn_cast<ParmVarDecl>(D); 9275f757f3fSDimitry Andric Param && Param->isExplicitObjectParameter()) 9285f757f3fSDimitry Andric Out << "this "; 9295f757f3fSDimitry Andric 9300b57cec5SDimitry Andric QualType T = D->getTypeSourceInfo() 9310b57cec5SDimitry Andric ? D->getTypeSourceInfo()->getType() 9320b57cec5SDimitry Andric : D->getASTContext().getUnqualifiedObjCPointerType(D->getType()); 9330b57cec5SDimitry Andric 9340b57cec5SDimitry Andric if (!Policy.SuppressSpecifiers) { 9350b57cec5SDimitry Andric StorageClass SC = D->getStorageClass(); 9360b57cec5SDimitry Andric if (SC != SC_None) 9370b57cec5SDimitry Andric Out << VarDecl::getStorageClassSpecifierString(SC) << " "; 9380b57cec5SDimitry Andric 9390b57cec5SDimitry Andric switch (D->getTSCSpec()) { 9400b57cec5SDimitry Andric case TSCS_unspecified: 9410b57cec5SDimitry Andric break; 9420b57cec5SDimitry Andric case TSCS___thread: 9430b57cec5SDimitry Andric Out << "__thread "; 9440b57cec5SDimitry Andric break; 9450b57cec5SDimitry Andric case TSCS__Thread_local: 9460b57cec5SDimitry Andric Out << "_Thread_local "; 9470b57cec5SDimitry Andric break; 9480b57cec5SDimitry Andric case TSCS_thread_local: 9490b57cec5SDimitry Andric Out << "thread_local "; 9500b57cec5SDimitry Andric break; 9510b57cec5SDimitry Andric } 9520b57cec5SDimitry Andric 9530b57cec5SDimitry Andric if (D->isModulePrivate()) 9540b57cec5SDimitry Andric Out << "__module_private__ "; 9550b57cec5SDimitry Andric 9560b57cec5SDimitry Andric if (D->isConstexpr()) { 9570b57cec5SDimitry Andric Out << "constexpr "; 9580b57cec5SDimitry Andric T.removeLocalConst(); 9590b57cec5SDimitry Andric } 9600b57cec5SDimitry Andric } 9610b57cec5SDimitry Andric 962*0fca6ea1SDimitry Andric if (!Policy.SuppressTagKeyword && Policy.SuppressScope && 963*0fca6ea1SDimitry Andric !Policy.SuppressUnwrittenScope) 964*0fca6ea1SDimitry Andric MaybePrintTagKeywordIfSupressingScopes(Policy, T, Out); 9655f757f3fSDimitry Andric 966*0fca6ea1SDimitry Andric printDeclType(T, (isa<ParmVarDecl>(D) && Policy.CleanUglifiedParameters && 96704eeddc0SDimitry Andric D->getIdentifier()) 96804eeddc0SDimitry Andric ? D->getIdentifier()->deuglifiedName() 969*0fca6ea1SDimitry Andric : D->getName()); 9705f757f3fSDimitry Andric 971*0fca6ea1SDimitry Andric prettyPrintAttributes(D, AttrPosAsWritten::Right); 9725f757f3fSDimitry Andric 9730b57cec5SDimitry Andric Expr *Init = D->getInit(); 9740b57cec5SDimitry Andric if (!Policy.SuppressInitializers && Init) { 9750b57cec5SDimitry Andric bool ImplicitInit = false; 97681ad6265SDimitry Andric if (D->isCXXForRangeDecl()) { 97781ad6265SDimitry Andric // FIXME: We should print the range expression instead. 97881ad6265SDimitry Andric ImplicitInit = true; 97981ad6265SDimitry Andric } else if (CXXConstructExpr *Construct = 9800b57cec5SDimitry Andric dyn_cast<CXXConstructExpr>(Init->IgnoreImplicit())) { 9810b57cec5SDimitry Andric if (D->getInitStyle() == VarDecl::CallInit && 9820b57cec5SDimitry Andric !Construct->isListInitialization()) { 9830b57cec5SDimitry Andric ImplicitInit = Construct->getNumArgs() == 0 || 9840b57cec5SDimitry Andric Construct->getArg(0)->isDefaultArgument(); 9850b57cec5SDimitry Andric } 9860b57cec5SDimitry Andric } 9870b57cec5SDimitry Andric if (!ImplicitInit) { 9880b57cec5SDimitry Andric if ((D->getInitStyle() == VarDecl::CallInit) && !isa<ParenListExpr>(Init)) 9890b57cec5SDimitry Andric Out << "("; 9900b57cec5SDimitry Andric else if (D->getInitStyle() == VarDecl::CInit) { 9910b57cec5SDimitry Andric Out << " = "; 9920b57cec5SDimitry Andric } 9930b57cec5SDimitry Andric PrintingPolicy SubPolicy(Policy); 9940b57cec5SDimitry Andric SubPolicy.SuppressSpecifiers = false; 9950b57cec5SDimitry Andric SubPolicy.IncludeTagDefinition = false; 996fe6060f1SDimitry Andric Init->printPretty(Out, nullptr, SubPolicy, Indentation, "\n", &Context); 9970b57cec5SDimitry Andric if ((D->getInitStyle() == VarDecl::CallInit) && !isa<ParenListExpr>(Init)) 9980b57cec5SDimitry Andric Out << ")"; 9990b57cec5SDimitry Andric } 10000b57cec5SDimitry Andric } 10010b57cec5SDimitry Andric } 10020b57cec5SDimitry Andric 10030b57cec5SDimitry Andric void DeclPrinter::VisitParmVarDecl(ParmVarDecl *D) { 10040b57cec5SDimitry Andric VisitVarDecl(D); 10050b57cec5SDimitry Andric } 10060b57cec5SDimitry Andric 10070b57cec5SDimitry Andric void DeclPrinter::VisitFileScopeAsmDecl(FileScopeAsmDecl *D) { 10080b57cec5SDimitry Andric Out << "__asm ("; 1009fe6060f1SDimitry Andric D->getAsmString()->printPretty(Out, nullptr, Policy, Indentation, "\n", 1010fe6060f1SDimitry Andric &Context); 10110b57cec5SDimitry Andric Out << ")"; 10120b57cec5SDimitry Andric } 10130b57cec5SDimitry Andric 1014bdd1243dSDimitry Andric void DeclPrinter::VisitTopLevelStmtDecl(TopLevelStmtDecl *D) { 1015bdd1243dSDimitry Andric assert(D->getStmt()); 1016bdd1243dSDimitry Andric D->getStmt()->printPretty(Out, nullptr, Policy, Indentation, "\n", &Context); 1017bdd1243dSDimitry Andric } 1018bdd1243dSDimitry Andric 10190b57cec5SDimitry Andric void DeclPrinter::VisitImportDecl(ImportDecl *D) { 10200b57cec5SDimitry Andric Out << "@import " << D->getImportedModule()->getFullModuleName() 10210b57cec5SDimitry Andric << ";\n"; 10220b57cec5SDimitry Andric } 10230b57cec5SDimitry Andric 10240b57cec5SDimitry Andric void DeclPrinter::VisitStaticAssertDecl(StaticAssertDecl *D) { 10250b57cec5SDimitry Andric Out << "static_assert("; 1026fe6060f1SDimitry Andric D->getAssertExpr()->printPretty(Out, nullptr, Policy, Indentation, "\n", 1027fe6060f1SDimitry Andric &Context); 102806c3fb27SDimitry Andric if (Expr *E = D->getMessage()) { 10290b57cec5SDimitry Andric Out << ", "; 103006c3fb27SDimitry Andric E->printPretty(Out, nullptr, Policy, Indentation, "\n", &Context); 10310b57cec5SDimitry Andric } 10320b57cec5SDimitry Andric Out << ")"; 10330b57cec5SDimitry Andric } 10340b57cec5SDimitry Andric 10350b57cec5SDimitry Andric //---------------------------------------------------------------------------- 10360b57cec5SDimitry Andric // C++ declarations 10370b57cec5SDimitry Andric //---------------------------------------------------------------------------- 10380b57cec5SDimitry Andric void DeclPrinter::VisitNamespaceDecl(NamespaceDecl *D) { 10390b57cec5SDimitry Andric if (D->isInline()) 10400b57cec5SDimitry Andric Out << "inline "; 1041e8d8bef9SDimitry Andric 1042e8d8bef9SDimitry Andric Out << "namespace "; 1043e8d8bef9SDimitry Andric if (D->getDeclName()) 1044e8d8bef9SDimitry Andric Out << D->getDeclName() << ' '; 1045e8d8bef9SDimitry Andric Out << "{\n"; 1046e8d8bef9SDimitry Andric 10470b57cec5SDimitry Andric VisitDeclContext(D); 10480b57cec5SDimitry Andric Indent() << "}"; 10490b57cec5SDimitry Andric } 10500b57cec5SDimitry Andric 10510b57cec5SDimitry Andric void DeclPrinter::VisitUsingDirectiveDecl(UsingDirectiveDecl *D) { 10520b57cec5SDimitry Andric Out << "using namespace "; 10530b57cec5SDimitry Andric if (D->getQualifier()) 10540b57cec5SDimitry Andric D->getQualifier()->print(Out, Policy); 10550b57cec5SDimitry Andric Out << *D->getNominatedNamespaceAsWritten(); 10560b57cec5SDimitry Andric } 10570b57cec5SDimitry Andric 10580b57cec5SDimitry Andric void DeclPrinter::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) { 10590b57cec5SDimitry Andric Out << "namespace " << *D << " = "; 10600b57cec5SDimitry Andric if (D->getQualifier()) 10610b57cec5SDimitry Andric D->getQualifier()->print(Out, Policy); 10620b57cec5SDimitry Andric Out << *D->getAliasedNamespace(); 10630b57cec5SDimitry Andric } 10640b57cec5SDimitry Andric 10650b57cec5SDimitry Andric void DeclPrinter::VisitEmptyDecl(EmptyDecl *D) { 10660b57cec5SDimitry Andric prettyPrintAttributes(D); 10670b57cec5SDimitry Andric } 10680b57cec5SDimitry Andric 10690b57cec5SDimitry Andric void DeclPrinter::VisitCXXRecordDecl(CXXRecordDecl *D) { 10700b57cec5SDimitry Andric // FIXME: add printing of pragma attributes if required. 10710b57cec5SDimitry Andric if (!Policy.SuppressSpecifiers && D->isModulePrivate()) 10720b57cec5SDimitry Andric Out << "__module_private__ "; 10730b57cec5SDimitry Andric 1074*0fca6ea1SDimitry Andric Out << D->getKindName() << ' '; 1075*0fca6ea1SDimitry Andric 1076*0fca6ea1SDimitry Andric // FIXME: Move before printing the decl kind to match the behavior of the 1077*0fca6ea1SDimitry Andric // attribute printing for variables and function where they are printed first. 1078*0fca6ea1SDimitry Andric if (prettyPrintAttributes(D, AttrPosAsWritten::Left)) 1079*0fca6ea1SDimitry Andric Out << ' '; 10800b57cec5SDimitry Andric 10810b57cec5SDimitry Andric if (D->getIdentifier()) { 108206c3fb27SDimitry Andric if (auto *NNS = D->getQualifier()) 108306c3fb27SDimitry Andric NNS->print(Out, Policy); 108406c3fb27SDimitry Andric Out << *D; 10850b57cec5SDimitry Andric 1086*0fca6ea1SDimitry Andric if (auto *S = dyn_cast<ClassTemplateSpecializationDecl>(D)) { 1087*0fca6ea1SDimitry Andric const TemplateParameterList *TParams = 1088*0fca6ea1SDimitry Andric S->getSpecializedTemplate()->getTemplateParameters(); 1089*0fca6ea1SDimitry Andric const ASTTemplateArgumentListInfo *TArgAsWritten = 1090*0fca6ea1SDimitry Andric S->getTemplateArgsAsWritten(); 1091*0fca6ea1SDimitry Andric if (TArgAsWritten && !Policy.PrintCanonicalTypes) 1092*0fca6ea1SDimitry Andric printTemplateArguments(TArgAsWritten->arguments(), TParams); 1093*0fca6ea1SDimitry Andric else 1094*0fca6ea1SDimitry Andric printTemplateArguments(S->getTemplateArgs().asArray(), TParams); 1095480093f4SDimitry Andric } 10960b57cec5SDimitry Andric } 10970b57cec5SDimitry Andric 1098*0fca6ea1SDimitry Andric prettyPrintAttributes(D, AttrPosAsWritten::Right); 1099753f127fSDimitry Andric 11000b57cec5SDimitry Andric if (D->isCompleteDefinition()) { 1101*0fca6ea1SDimitry Andric Out << ' '; 11020b57cec5SDimitry Andric // Print the base classes 11030b57cec5SDimitry Andric if (D->getNumBases()) { 11040b57cec5SDimitry Andric Out << ": "; 11050b57cec5SDimitry Andric for (CXXRecordDecl::base_class_iterator Base = D->bases_begin(), 11060b57cec5SDimitry Andric BaseEnd = D->bases_end(); Base != BaseEnd; ++Base) { 11070b57cec5SDimitry Andric if (Base != D->bases_begin()) 11080b57cec5SDimitry Andric Out << ", "; 11090b57cec5SDimitry Andric 11100b57cec5SDimitry Andric if (Base->isVirtual()) 11110b57cec5SDimitry Andric Out << "virtual "; 11120b57cec5SDimitry Andric 11130b57cec5SDimitry Andric AccessSpecifier AS = Base->getAccessSpecifierAsWritten(); 11140b57cec5SDimitry Andric if (AS != AS_none) { 11150b57cec5SDimitry Andric Print(AS); 11160b57cec5SDimitry Andric Out << " "; 11170b57cec5SDimitry Andric } 11180b57cec5SDimitry Andric Out << Base->getType().getAsString(Policy); 11190b57cec5SDimitry Andric 11200b57cec5SDimitry Andric if (Base->isPackExpansion()) 11210b57cec5SDimitry Andric Out << "..."; 11220b57cec5SDimitry Andric } 1123*0fca6ea1SDimitry Andric Out << ' '; 11240b57cec5SDimitry Andric } 11250b57cec5SDimitry Andric 11260b57cec5SDimitry Andric // Print the class definition 11270b57cec5SDimitry Andric // FIXME: Doesn't print access specifiers, e.g., "public:" 11280b57cec5SDimitry Andric if (Policy.TerseOutput) { 11290b57cec5SDimitry Andric Out << "{}"; 11300b57cec5SDimitry Andric } else { 11310b57cec5SDimitry Andric Out << "{\n"; 11320b57cec5SDimitry Andric VisitDeclContext(D); 11330b57cec5SDimitry Andric Indent() << "}"; 11340b57cec5SDimitry Andric } 11350b57cec5SDimitry Andric } 11360b57cec5SDimitry Andric } 11370b57cec5SDimitry Andric 11380b57cec5SDimitry Andric void DeclPrinter::VisitLinkageSpecDecl(LinkageSpecDecl *D) { 11390b57cec5SDimitry Andric const char *l; 11405f757f3fSDimitry Andric if (D->getLanguage() == LinkageSpecLanguageIDs::C) 11410b57cec5SDimitry Andric l = "C"; 1142480093f4SDimitry Andric else { 11435f757f3fSDimitry Andric assert(D->getLanguage() == LinkageSpecLanguageIDs::CXX && 1144480093f4SDimitry Andric "unknown language in linkage specification"); 11450b57cec5SDimitry Andric l = "C++"; 11460b57cec5SDimitry Andric } 11470b57cec5SDimitry Andric 11480b57cec5SDimitry Andric Out << "extern \"" << l << "\" "; 11490b57cec5SDimitry Andric if (D->hasBraces()) { 11500b57cec5SDimitry Andric Out << "{\n"; 11510b57cec5SDimitry Andric VisitDeclContext(D); 11520b57cec5SDimitry Andric Indent() << "}"; 11530b57cec5SDimitry Andric } else 11540b57cec5SDimitry Andric Visit(*D->decls_begin()); 11550b57cec5SDimitry Andric } 11560b57cec5SDimitry Andric 11570b57cec5SDimitry Andric void DeclPrinter::printTemplateParameters(const TemplateParameterList *Params, 11580b57cec5SDimitry Andric bool OmitTemplateKW) { 11590b57cec5SDimitry Andric assert(Params); 11600b57cec5SDimitry Andric 1161*0fca6ea1SDimitry Andric // Don't print invented template parameter lists. 1162*0fca6ea1SDimitry Andric if (!Params->empty() && Params->getParam(0)->isImplicit()) 1163*0fca6ea1SDimitry Andric return; 1164*0fca6ea1SDimitry Andric 11650b57cec5SDimitry Andric if (!OmitTemplateKW) 11660b57cec5SDimitry Andric Out << "template "; 11670b57cec5SDimitry Andric Out << '<'; 11680b57cec5SDimitry Andric 11690b57cec5SDimitry Andric bool NeedComma = false; 11700b57cec5SDimitry Andric for (const Decl *Param : *Params) { 11710b57cec5SDimitry Andric if (Param->isImplicit()) 11720b57cec5SDimitry Andric continue; 11730b57cec5SDimitry Andric 11740b57cec5SDimitry Andric if (NeedComma) 11750b57cec5SDimitry Andric Out << ", "; 11760b57cec5SDimitry Andric else 11770b57cec5SDimitry Andric NeedComma = true; 11780b57cec5SDimitry Andric 11795ffd83dbSDimitry Andric if (const auto *TTP = dyn_cast<TemplateTypeParmDecl>(Param)) { 11805ffd83dbSDimitry Andric VisitTemplateTypeParmDecl(TTP); 11810b57cec5SDimitry Andric } else if (auto NTTP = dyn_cast<NonTypeTemplateParmDecl>(Param)) { 11825ffd83dbSDimitry Andric VisitNonTypeTemplateParmDecl(NTTP); 11830b57cec5SDimitry Andric } else if (auto TTPD = dyn_cast<TemplateTemplateParmDecl>(Param)) { 11840b57cec5SDimitry Andric VisitTemplateDecl(TTPD); 11850b57cec5SDimitry Andric // FIXME: print the default argument, if present. 11860b57cec5SDimitry Andric } 11870b57cec5SDimitry Andric } 11880b57cec5SDimitry Andric 11890b57cec5SDimitry Andric Out << '>'; 1190*0fca6ea1SDimitry Andric 1191*0fca6ea1SDimitry Andric if (const Expr *RequiresClause = Params->getRequiresClause()) { 1192*0fca6ea1SDimitry Andric Out << " requires "; 1193*0fca6ea1SDimitry Andric RequiresClause->printPretty(Out, nullptr, Policy, Indentation, "\n", 1194*0fca6ea1SDimitry Andric &Context); 1195*0fca6ea1SDimitry Andric } 1196*0fca6ea1SDimitry Andric 11970b57cec5SDimitry Andric if (!OmitTemplateKW) 11980b57cec5SDimitry Andric Out << ' '; 11990b57cec5SDimitry Andric } 12000b57cec5SDimitry Andric 1201fe6060f1SDimitry Andric void DeclPrinter::printTemplateArguments(ArrayRef<TemplateArgument> Args, 1202349cc55cSDimitry Andric const TemplateParameterList *Params) { 12030b57cec5SDimitry Andric Out << "<"; 12040b57cec5SDimitry Andric for (size_t I = 0, E = Args.size(); I < E; ++I) { 12050b57cec5SDimitry Andric if (I) 12060b57cec5SDimitry Andric Out << ", "; 1207349cc55cSDimitry Andric if (!Params) 1208fe6060f1SDimitry Andric Args[I].print(Policy, Out, /*IncludeType*/ true); 1209fe6060f1SDimitry Andric else 1210349cc55cSDimitry Andric Args[I].print(Policy, Out, 1211349cc55cSDimitry Andric TemplateParameterList::shouldIncludeTypeForArgument( 1212349cc55cSDimitry Andric Policy, Params, I)); 12130b57cec5SDimitry Andric } 1214480093f4SDimitry Andric Out << ">"; 12150b57cec5SDimitry Andric } 1216480093f4SDimitry Andric 1217fe6060f1SDimitry Andric void DeclPrinter::printTemplateArguments(ArrayRef<TemplateArgumentLoc> Args, 1218349cc55cSDimitry Andric const TemplateParameterList *Params) { 1219480093f4SDimitry Andric Out << "<"; 1220480093f4SDimitry Andric for (size_t I = 0, E = Args.size(); I < E; ++I) { 1221480093f4SDimitry Andric if (I) 1222480093f4SDimitry Andric Out << ", "; 1223349cc55cSDimitry Andric if (!Params) 1224fe6060f1SDimitry Andric Args[I].getArgument().print(Policy, Out, /*IncludeType*/ true); 1225fe6060f1SDimitry Andric else 1226fe6060f1SDimitry Andric Args[I].getArgument().print( 1227fe6060f1SDimitry Andric Policy, Out, 1228349cc55cSDimitry Andric TemplateParameterList::shouldIncludeTypeForArgument(Policy, Params, 1229349cc55cSDimitry Andric I)); 12300b57cec5SDimitry Andric } 12310b57cec5SDimitry Andric Out << ">"; 12320b57cec5SDimitry Andric } 12330b57cec5SDimitry Andric 12340b57cec5SDimitry Andric void DeclPrinter::VisitTemplateDecl(const TemplateDecl *D) { 12350b57cec5SDimitry Andric printTemplateParameters(D->getTemplateParameters()); 12360b57cec5SDimitry Andric 12370b57cec5SDimitry Andric if (const TemplateTemplateParmDecl *TTP = 12380b57cec5SDimitry Andric dyn_cast<TemplateTemplateParmDecl>(D)) { 1239*0fca6ea1SDimitry Andric if (TTP->wasDeclaredWithTypename()) 1240*0fca6ea1SDimitry Andric Out << "typename"; 1241*0fca6ea1SDimitry Andric else 12420b57cec5SDimitry Andric Out << "class"; 1243e8d8bef9SDimitry Andric 12440b57cec5SDimitry Andric if (TTP->isParameterPack()) 12450b57cec5SDimitry Andric Out << " ..."; 1246e8d8bef9SDimitry Andric else if (TTP->getDeclName()) 1247e8d8bef9SDimitry Andric Out << ' '; 1248e8d8bef9SDimitry Andric 124904eeddc0SDimitry Andric if (TTP->getDeclName()) { 125004eeddc0SDimitry Andric if (Policy.CleanUglifiedParameters && TTP->getIdentifier()) 125104eeddc0SDimitry Andric Out << TTP->getIdentifier()->deuglifiedName(); 125204eeddc0SDimitry Andric else 1253e8d8bef9SDimitry Andric Out << TTP->getDeclName(); 125404eeddc0SDimitry Andric } 12550b57cec5SDimitry Andric } else if (auto *TD = D->getTemplatedDecl()) 12560b57cec5SDimitry Andric Visit(TD); 12570b57cec5SDimitry Andric else if (const auto *Concept = dyn_cast<ConceptDecl>(D)) { 12580b57cec5SDimitry Andric Out << "concept " << Concept->getName() << " = " ; 1259fe6060f1SDimitry Andric Concept->getConstraintExpr()->printPretty(Out, nullptr, Policy, Indentation, 1260fe6060f1SDimitry Andric "\n", &Context); 12610b57cec5SDimitry Andric } 12620b57cec5SDimitry Andric } 12630b57cec5SDimitry Andric 12640b57cec5SDimitry Andric void DeclPrinter::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) { 12650b57cec5SDimitry Andric prettyPrintPragmas(D->getTemplatedDecl()); 12660b57cec5SDimitry Andric // Print any leading template parameter lists. 12670b57cec5SDimitry Andric if (const FunctionDecl *FD = D->getTemplatedDecl()) { 12680b57cec5SDimitry Andric for (unsigned I = 0, NumTemplateParams = FD->getNumTemplateParameterLists(); 12690b57cec5SDimitry Andric I < NumTemplateParams; ++I) 12700b57cec5SDimitry Andric printTemplateParameters(FD->getTemplateParameterList(I)); 12710b57cec5SDimitry Andric } 12720b57cec5SDimitry Andric VisitRedeclarableTemplateDecl(D); 12730b57cec5SDimitry Andric // Declare target attribute is special one, natural spelling for the pragma 12740b57cec5SDimitry Andric // assumes "ending" construct so print it here. 12750b57cec5SDimitry Andric if (D->getTemplatedDecl()->hasAttr<OMPDeclareTargetDeclAttr>()) 12760b57cec5SDimitry Andric Out << "#pragma omp end declare target\n"; 12770b57cec5SDimitry Andric 12780b57cec5SDimitry Andric // Never print "instantiations" for deduction guides (they don't really 12790b57cec5SDimitry Andric // have them). 12800b57cec5SDimitry Andric if (PrintInstantiation && 12810b57cec5SDimitry Andric !isa<CXXDeductionGuideDecl>(D->getTemplatedDecl())) { 12820b57cec5SDimitry Andric FunctionDecl *PrevDecl = D->getTemplatedDecl(); 12830b57cec5SDimitry Andric const FunctionDecl *Def; 12840b57cec5SDimitry Andric if (PrevDecl->isDefined(Def) && Def != PrevDecl) 12850b57cec5SDimitry Andric return; 12860b57cec5SDimitry Andric for (auto *I : D->specializations()) 12870b57cec5SDimitry Andric if (I->getTemplateSpecializationKind() == TSK_ImplicitInstantiation) { 12880b57cec5SDimitry Andric if (!PrevDecl->isThisDeclarationADefinition()) 12890b57cec5SDimitry Andric Out << ";\n"; 12900b57cec5SDimitry Andric Indent(); 12910b57cec5SDimitry Andric prettyPrintPragmas(I); 12920b57cec5SDimitry Andric Visit(I); 12930b57cec5SDimitry Andric } 12940b57cec5SDimitry Andric } 12950b57cec5SDimitry Andric } 12960b57cec5SDimitry Andric 12970b57cec5SDimitry Andric void DeclPrinter::VisitClassTemplateDecl(ClassTemplateDecl *D) { 12980b57cec5SDimitry Andric VisitRedeclarableTemplateDecl(D); 12990b57cec5SDimitry Andric 13000b57cec5SDimitry Andric if (PrintInstantiation) { 13010b57cec5SDimitry Andric for (auto *I : D->specializations()) 13020b57cec5SDimitry Andric if (I->getSpecializationKind() == TSK_ImplicitInstantiation) { 13030b57cec5SDimitry Andric if (D->isThisDeclarationADefinition()) 13040b57cec5SDimitry Andric Out << ";"; 13050b57cec5SDimitry Andric Out << "\n"; 1306349cc55cSDimitry Andric Indent(); 13070b57cec5SDimitry Andric Visit(I); 13080b57cec5SDimitry Andric } 13090b57cec5SDimitry Andric } 13100b57cec5SDimitry Andric } 13110b57cec5SDimitry Andric 13120b57cec5SDimitry Andric void DeclPrinter::VisitClassTemplateSpecializationDecl( 13130b57cec5SDimitry Andric ClassTemplateSpecializationDecl *D) { 13140b57cec5SDimitry Andric Out << "template<> "; 13150b57cec5SDimitry Andric VisitCXXRecordDecl(D); 13160b57cec5SDimitry Andric } 13170b57cec5SDimitry Andric 13180b57cec5SDimitry Andric void DeclPrinter::VisitClassTemplatePartialSpecializationDecl( 13190b57cec5SDimitry Andric ClassTemplatePartialSpecializationDecl *D) { 13200b57cec5SDimitry Andric printTemplateParameters(D->getTemplateParameters()); 13210b57cec5SDimitry Andric VisitCXXRecordDecl(D); 13220b57cec5SDimitry Andric } 13230b57cec5SDimitry Andric 13240b57cec5SDimitry Andric //---------------------------------------------------------------------------- 13250b57cec5SDimitry Andric // Objective-C declarations 13260b57cec5SDimitry Andric //---------------------------------------------------------------------------- 13270b57cec5SDimitry Andric 13280b57cec5SDimitry Andric void DeclPrinter::PrintObjCMethodType(ASTContext &Ctx, 13290b57cec5SDimitry Andric Decl::ObjCDeclQualifier Quals, 13300b57cec5SDimitry Andric QualType T) { 13310b57cec5SDimitry Andric Out << '('; 13320b57cec5SDimitry Andric if (Quals & Decl::ObjCDeclQualifier::OBJC_TQ_In) 13330b57cec5SDimitry Andric Out << "in "; 13340b57cec5SDimitry Andric if (Quals & Decl::ObjCDeclQualifier::OBJC_TQ_Inout) 13350b57cec5SDimitry Andric Out << "inout "; 13360b57cec5SDimitry Andric if (Quals & Decl::ObjCDeclQualifier::OBJC_TQ_Out) 13370b57cec5SDimitry Andric Out << "out "; 13380b57cec5SDimitry Andric if (Quals & Decl::ObjCDeclQualifier::OBJC_TQ_Bycopy) 13390b57cec5SDimitry Andric Out << "bycopy "; 13400b57cec5SDimitry Andric if (Quals & Decl::ObjCDeclQualifier::OBJC_TQ_Byref) 13410b57cec5SDimitry Andric Out << "byref "; 13420b57cec5SDimitry Andric if (Quals & Decl::ObjCDeclQualifier::OBJC_TQ_Oneway) 13430b57cec5SDimitry Andric Out << "oneway "; 13440b57cec5SDimitry Andric if (Quals & Decl::ObjCDeclQualifier::OBJC_TQ_CSNullability) { 13450b57cec5SDimitry Andric if (auto nullability = AttributedType::stripOuterNullability(T)) 13460b57cec5SDimitry Andric Out << getNullabilitySpelling(*nullability, true) << ' '; 13470b57cec5SDimitry Andric } 13480b57cec5SDimitry Andric 13490b57cec5SDimitry Andric Out << Ctx.getUnqualifiedObjCPointerType(T).getAsString(Policy); 13500b57cec5SDimitry Andric Out << ')'; 13510b57cec5SDimitry Andric } 13520b57cec5SDimitry Andric 13530b57cec5SDimitry Andric void DeclPrinter::PrintObjCTypeParams(ObjCTypeParamList *Params) { 13540b57cec5SDimitry Andric Out << "<"; 13550b57cec5SDimitry Andric unsigned First = true; 13560b57cec5SDimitry Andric for (auto *Param : *Params) { 13570b57cec5SDimitry Andric if (First) { 13580b57cec5SDimitry Andric First = false; 13590b57cec5SDimitry Andric } else { 13600b57cec5SDimitry Andric Out << ", "; 13610b57cec5SDimitry Andric } 13620b57cec5SDimitry Andric 13630b57cec5SDimitry Andric switch (Param->getVariance()) { 13640b57cec5SDimitry Andric case ObjCTypeParamVariance::Invariant: 13650b57cec5SDimitry Andric break; 13660b57cec5SDimitry Andric 13670b57cec5SDimitry Andric case ObjCTypeParamVariance::Covariant: 13680b57cec5SDimitry Andric Out << "__covariant "; 13690b57cec5SDimitry Andric break; 13700b57cec5SDimitry Andric 13710b57cec5SDimitry Andric case ObjCTypeParamVariance::Contravariant: 13720b57cec5SDimitry Andric Out << "__contravariant "; 13730b57cec5SDimitry Andric break; 13740b57cec5SDimitry Andric } 13750b57cec5SDimitry Andric 1376e8d8bef9SDimitry Andric Out << Param->getDeclName(); 13770b57cec5SDimitry Andric 13780b57cec5SDimitry Andric if (Param->hasExplicitBound()) { 13790b57cec5SDimitry Andric Out << " : " << Param->getUnderlyingType().getAsString(Policy); 13800b57cec5SDimitry Andric } 13810b57cec5SDimitry Andric } 13820b57cec5SDimitry Andric Out << ">"; 13830b57cec5SDimitry Andric } 13840b57cec5SDimitry Andric 13850b57cec5SDimitry Andric void DeclPrinter::VisitObjCMethodDecl(ObjCMethodDecl *OMD) { 13860b57cec5SDimitry Andric if (OMD->isInstanceMethod()) 13870b57cec5SDimitry Andric Out << "- "; 13880b57cec5SDimitry Andric else 13890b57cec5SDimitry Andric Out << "+ "; 13900b57cec5SDimitry Andric if (!OMD->getReturnType().isNull()) { 13910b57cec5SDimitry Andric PrintObjCMethodType(OMD->getASTContext(), OMD->getObjCDeclQualifier(), 13920b57cec5SDimitry Andric OMD->getReturnType()); 13930b57cec5SDimitry Andric } 13940b57cec5SDimitry Andric 13950b57cec5SDimitry Andric std::string name = OMD->getSelector().getAsString(); 13960b57cec5SDimitry Andric std::string::size_type pos, lastPos = 0; 13970b57cec5SDimitry Andric for (const auto *PI : OMD->parameters()) { 13980b57cec5SDimitry Andric // FIXME: selector is missing here! 13990b57cec5SDimitry Andric pos = name.find_first_of(':', lastPos); 14000b57cec5SDimitry Andric if (lastPos != 0) 14010b57cec5SDimitry Andric Out << " "; 14020b57cec5SDimitry Andric Out << name.substr(lastPos, pos - lastPos) << ':'; 14030b57cec5SDimitry Andric PrintObjCMethodType(OMD->getASTContext(), 14040b57cec5SDimitry Andric PI->getObjCDeclQualifier(), 14050b57cec5SDimitry Andric PI->getType()); 14060b57cec5SDimitry Andric Out << *PI; 14070b57cec5SDimitry Andric lastPos = pos + 1; 14080b57cec5SDimitry Andric } 14090b57cec5SDimitry Andric 14100b57cec5SDimitry Andric if (OMD->param_begin() == OMD->param_end()) 14110b57cec5SDimitry Andric Out << name; 14120b57cec5SDimitry Andric 14130b57cec5SDimitry Andric if (OMD->isVariadic()) 14140b57cec5SDimitry Andric Out << ", ..."; 14150b57cec5SDimitry Andric 14160b57cec5SDimitry Andric prettyPrintAttributes(OMD); 14170b57cec5SDimitry Andric 14180b57cec5SDimitry Andric if (OMD->getBody() && !Policy.TerseOutput) { 14190b57cec5SDimitry Andric Out << ' '; 1420fe6060f1SDimitry Andric OMD->getBody()->printPretty(Out, nullptr, Policy, Indentation, "\n", 1421fe6060f1SDimitry Andric &Context); 14220b57cec5SDimitry Andric } 14230b57cec5SDimitry Andric else if (Policy.PolishForDeclaration) 14240b57cec5SDimitry Andric Out << ';'; 14250b57cec5SDimitry Andric } 14260b57cec5SDimitry Andric 14270b57cec5SDimitry Andric void DeclPrinter::VisitObjCImplementationDecl(ObjCImplementationDecl *OID) { 14280b57cec5SDimitry Andric std::string I = OID->getNameAsString(); 14290b57cec5SDimitry Andric ObjCInterfaceDecl *SID = OID->getSuperClass(); 14300b57cec5SDimitry Andric 14310b57cec5SDimitry Andric bool eolnOut = false; 14320b57cec5SDimitry Andric if (SID) 14330b57cec5SDimitry Andric Out << "@implementation " << I << " : " << *SID; 14340b57cec5SDimitry Andric else 14350b57cec5SDimitry Andric Out << "@implementation " << I; 14360b57cec5SDimitry Andric 14370b57cec5SDimitry Andric if (OID->ivar_size() > 0) { 14380b57cec5SDimitry Andric Out << "{\n"; 14390b57cec5SDimitry Andric eolnOut = true; 14400b57cec5SDimitry Andric Indentation += Policy.Indentation; 14410b57cec5SDimitry Andric for (const auto *I : OID->ivars()) { 14420b57cec5SDimitry Andric Indent() << I->getASTContext().getUnqualifiedObjCPointerType(I->getType()). 14430b57cec5SDimitry Andric getAsString(Policy) << ' ' << *I << ";\n"; 14440b57cec5SDimitry Andric } 14450b57cec5SDimitry Andric Indentation -= Policy.Indentation; 14460b57cec5SDimitry Andric Out << "}\n"; 14470b57cec5SDimitry Andric } 14480b57cec5SDimitry Andric else if (SID || (OID->decls_begin() != OID->decls_end())) { 14490b57cec5SDimitry Andric Out << "\n"; 14500b57cec5SDimitry Andric eolnOut = true; 14510b57cec5SDimitry Andric } 14520b57cec5SDimitry Andric VisitDeclContext(OID, false); 14530b57cec5SDimitry Andric if (!eolnOut) 14540b57cec5SDimitry Andric Out << "\n"; 14550b57cec5SDimitry Andric Out << "@end"; 14560b57cec5SDimitry Andric } 14570b57cec5SDimitry Andric 14580b57cec5SDimitry Andric void DeclPrinter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *OID) { 14590b57cec5SDimitry Andric std::string I = OID->getNameAsString(); 14600b57cec5SDimitry Andric ObjCInterfaceDecl *SID = OID->getSuperClass(); 14610b57cec5SDimitry Andric 14620b57cec5SDimitry Andric if (!OID->isThisDeclarationADefinition()) { 14630b57cec5SDimitry Andric Out << "@class " << I; 14640b57cec5SDimitry Andric 14650b57cec5SDimitry Andric if (auto TypeParams = OID->getTypeParamListAsWritten()) { 14660b57cec5SDimitry Andric PrintObjCTypeParams(TypeParams); 14670b57cec5SDimitry Andric } 14680b57cec5SDimitry Andric 14690b57cec5SDimitry Andric Out << ";"; 14700b57cec5SDimitry Andric return; 14710b57cec5SDimitry Andric } 14720b57cec5SDimitry Andric bool eolnOut = false; 1473*0fca6ea1SDimitry Andric if (OID->hasAttrs()) { 1474*0fca6ea1SDimitry Andric prettyPrintAttributes(OID); 1475*0fca6ea1SDimitry Andric Out << "\n"; 1476*0fca6ea1SDimitry Andric } 1477*0fca6ea1SDimitry Andric 14780b57cec5SDimitry Andric Out << "@interface " << I; 14790b57cec5SDimitry Andric 14800b57cec5SDimitry Andric if (auto TypeParams = OID->getTypeParamListAsWritten()) { 14810b57cec5SDimitry Andric PrintObjCTypeParams(TypeParams); 14820b57cec5SDimitry Andric } 14830b57cec5SDimitry Andric 14840b57cec5SDimitry Andric if (SID) 14850b57cec5SDimitry Andric Out << " : " << QualType(OID->getSuperClassType(), 0).getAsString(Policy); 14860b57cec5SDimitry Andric 14870b57cec5SDimitry Andric // Protocols? 14880b57cec5SDimitry Andric const ObjCList<ObjCProtocolDecl> &Protocols = OID->getReferencedProtocols(); 14890b57cec5SDimitry Andric if (!Protocols.empty()) { 14900b57cec5SDimitry Andric for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(), 14910b57cec5SDimitry Andric E = Protocols.end(); I != E; ++I) 14920b57cec5SDimitry Andric Out << (I == Protocols.begin() ? '<' : ',') << **I; 14930b57cec5SDimitry Andric Out << "> "; 14940b57cec5SDimitry Andric } 14950b57cec5SDimitry Andric 14960b57cec5SDimitry Andric if (OID->ivar_size() > 0) { 14970b57cec5SDimitry Andric Out << "{\n"; 14980b57cec5SDimitry Andric eolnOut = true; 14990b57cec5SDimitry Andric Indentation += Policy.Indentation; 15000b57cec5SDimitry Andric for (const auto *I : OID->ivars()) { 15010b57cec5SDimitry Andric Indent() << I->getASTContext() 15020b57cec5SDimitry Andric .getUnqualifiedObjCPointerType(I->getType()) 15030b57cec5SDimitry Andric .getAsString(Policy) << ' ' << *I << ";\n"; 15040b57cec5SDimitry Andric } 15050b57cec5SDimitry Andric Indentation -= Policy.Indentation; 15060b57cec5SDimitry Andric Out << "}\n"; 15070b57cec5SDimitry Andric } 15080b57cec5SDimitry Andric else if (SID || (OID->decls_begin() != OID->decls_end())) { 15090b57cec5SDimitry Andric Out << "\n"; 15100b57cec5SDimitry Andric eolnOut = true; 15110b57cec5SDimitry Andric } 15120b57cec5SDimitry Andric 15130b57cec5SDimitry Andric VisitDeclContext(OID, false); 15140b57cec5SDimitry Andric if (!eolnOut) 15150b57cec5SDimitry Andric Out << "\n"; 15160b57cec5SDimitry Andric Out << "@end"; 15170b57cec5SDimitry Andric // FIXME: implement the rest... 15180b57cec5SDimitry Andric } 15190b57cec5SDimitry Andric 15200b57cec5SDimitry Andric void DeclPrinter::VisitObjCProtocolDecl(ObjCProtocolDecl *PID) { 15210b57cec5SDimitry Andric if (!PID->isThisDeclarationADefinition()) { 15220b57cec5SDimitry Andric Out << "@protocol " << *PID << ";\n"; 15230b57cec5SDimitry Andric return; 15240b57cec5SDimitry Andric } 15250b57cec5SDimitry Andric // Protocols? 15260b57cec5SDimitry Andric const ObjCList<ObjCProtocolDecl> &Protocols = PID->getReferencedProtocols(); 15270b57cec5SDimitry Andric if (!Protocols.empty()) { 15280b57cec5SDimitry Andric Out << "@protocol " << *PID; 15290b57cec5SDimitry Andric for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(), 15300b57cec5SDimitry Andric E = Protocols.end(); I != E; ++I) 15310b57cec5SDimitry Andric Out << (I == Protocols.begin() ? '<' : ',') << **I; 15320b57cec5SDimitry Andric Out << ">\n"; 15330b57cec5SDimitry Andric } else 15340b57cec5SDimitry Andric Out << "@protocol " << *PID << '\n'; 15350b57cec5SDimitry Andric VisitDeclContext(PID, false); 15360b57cec5SDimitry Andric Out << "@end"; 15370b57cec5SDimitry Andric } 15380b57cec5SDimitry Andric 15390b57cec5SDimitry Andric void DeclPrinter::VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *PID) { 15405ffd83dbSDimitry Andric Out << "@implementation "; 15415ffd83dbSDimitry Andric if (const auto *CID = PID->getClassInterface()) 15425ffd83dbSDimitry Andric Out << *CID; 15435ffd83dbSDimitry Andric else 15445ffd83dbSDimitry Andric Out << "<<error-type>>"; 15455ffd83dbSDimitry Andric Out << '(' << *PID << ")\n"; 15460b57cec5SDimitry Andric 15470b57cec5SDimitry Andric VisitDeclContext(PID, false); 15480b57cec5SDimitry Andric Out << "@end"; 15490b57cec5SDimitry Andric // FIXME: implement the rest... 15500b57cec5SDimitry Andric } 15510b57cec5SDimitry Andric 15520b57cec5SDimitry Andric void DeclPrinter::VisitObjCCategoryDecl(ObjCCategoryDecl *PID) { 15535ffd83dbSDimitry Andric Out << "@interface "; 15545ffd83dbSDimitry Andric if (const auto *CID = PID->getClassInterface()) 15555ffd83dbSDimitry Andric Out << *CID; 15565ffd83dbSDimitry Andric else 15575ffd83dbSDimitry Andric Out << "<<error-type>>"; 15580b57cec5SDimitry Andric if (auto TypeParams = PID->getTypeParamList()) { 15590b57cec5SDimitry Andric PrintObjCTypeParams(TypeParams); 15600b57cec5SDimitry Andric } 15610b57cec5SDimitry Andric Out << "(" << *PID << ")\n"; 15620b57cec5SDimitry Andric if (PID->ivar_size() > 0) { 15630b57cec5SDimitry Andric Out << "{\n"; 15640b57cec5SDimitry Andric Indentation += Policy.Indentation; 15650b57cec5SDimitry Andric for (const auto *I : PID->ivars()) 15660b57cec5SDimitry Andric Indent() << I->getASTContext().getUnqualifiedObjCPointerType(I->getType()). 15670b57cec5SDimitry Andric getAsString(Policy) << ' ' << *I << ";\n"; 15680b57cec5SDimitry Andric Indentation -= Policy.Indentation; 15690b57cec5SDimitry Andric Out << "}\n"; 15700b57cec5SDimitry Andric } 15710b57cec5SDimitry Andric 15720b57cec5SDimitry Andric VisitDeclContext(PID, false); 15730b57cec5SDimitry Andric Out << "@end"; 15740b57cec5SDimitry Andric 15750b57cec5SDimitry Andric // FIXME: implement the rest... 15760b57cec5SDimitry Andric } 15770b57cec5SDimitry Andric 15780b57cec5SDimitry Andric void DeclPrinter::VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *AID) { 15790b57cec5SDimitry Andric Out << "@compatibility_alias " << *AID 15800b57cec5SDimitry Andric << ' ' << *AID->getClassInterface() << ";\n"; 15810b57cec5SDimitry Andric } 15820b57cec5SDimitry Andric 15830b57cec5SDimitry Andric /// PrintObjCPropertyDecl - print a property declaration. 15840b57cec5SDimitry Andric /// 15850b57cec5SDimitry Andric /// Print attributes in the following order: 15860b57cec5SDimitry Andric /// - class 15870b57cec5SDimitry Andric /// - nonatomic | atomic 15880b57cec5SDimitry Andric /// - assign | retain | strong | copy | weak | unsafe_unretained 15890b57cec5SDimitry Andric /// - readwrite | readonly 15900b57cec5SDimitry Andric /// - getter & setter 15910b57cec5SDimitry Andric /// - nullability 15920b57cec5SDimitry Andric void DeclPrinter::VisitObjCPropertyDecl(ObjCPropertyDecl *PDecl) { 15930b57cec5SDimitry Andric if (PDecl->getPropertyImplementation() == ObjCPropertyDecl::Required) 15940b57cec5SDimitry Andric Out << "@required\n"; 15950b57cec5SDimitry Andric else if (PDecl->getPropertyImplementation() == ObjCPropertyDecl::Optional) 15960b57cec5SDimitry Andric Out << "@optional\n"; 15970b57cec5SDimitry Andric 15980b57cec5SDimitry Andric QualType T = PDecl->getType(); 15990b57cec5SDimitry Andric 16000b57cec5SDimitry Andric Out << "@property"; 16015ffd83dbSDimitry Andric if (PDecl->getPropertyAttributes() != ObjCPropertyAttribute::kind_noattr) { 16020b57cec5SDimitry Andric bool first = true; 16030b57cec5SDimitry Andric Out << "("; 16045ffd83dbSDimitry Andric if (PDecl->getPropertyAttributes() & ObjCPropertyAttribute::kind_class) { 16050b57cec5SDimitry Andric Out << (first ? "" : ", ") << "class"; 16060b57cec5SDimitry Andric first = false; 16070b57cec5SDimitry Andric } 16080b57cec5SDimitry Andric 16095ffd83dbSDimitry Andric if (PDecl->getPropertyAttributes() & ObjCPropertyAttribute::kind_direct) { 1610480093f4SDimitry Andric Out << (first ? "" : ", ") << "direct"; 1611480093f4SDimitry Andric first = false; 1612480093f4SDimitry Andric } 1613480093f4SDimitry Andric 16140b57cec5SDimitry Andric if (PDecl->getPropertyAttributes() & 16155ffd83dbSDimitry Andric ObjCPropertyAttribute::kind_nonatomic) { 16160b57cec5SDimitry Andric Out << (first ? "" : ", ") << "nonatomic"; 16170b57cec5SDimitry Andric first = false; 16180b57cec5SDimitry Andric } 16195ffd83dbSDimitry Andric if (PDecl->getPropertyAttributes() & ObjCPropertyAttribute::kind_atomic) { 16200b57cec5SDimitry Andric Out << (first ? "" : ", ") << "atomic"; 16210b57cec5SDimitry Andric first = false; 16220b57cec5SDimitry Andric } 16230b57cec5SDimitry Andric 16245ffd83dbSDimitry Andric if (PDecl->getPropertyAttributes() & ObjCPropertyAttribute::kind_assign) { 16250b57cec5SDimitry Andric Out << (first ? "" : ", ") << "assign"; 16260b57cec5SDimitry Andric first = false; 16270b57cec5SDimitry Andric } 16285ffd83dbSDimitry Andric if (PDecl->getPropertyAttributes() & ObjCPropertyAttribute::kind_retain) { 16290b57cec5SDimitry Andric Out << (first ? "" : ", ") << "retain"; 16300b57cec5SDimitry Andric first = false; 16310b57cec5SDimitry Andric } 16320b57cec5SDimitry Andric 16335ffd83dbSDimitry Andric if (PDecl->getPropertyAttributes() & ObjCPropertyAttribute::kind_strong) { 16340b57cec5SDimitry Andric Out << (first ? "" : ", ") << "strong"; 16350b57cec5SDimitry Andric first = false; 16360b57cec5SDimitry Andric } 16375ffd83dbSDimitry Andric if (PDecl->getPropertyAttributes() & ObjCPropertyAttribute::kind_copy) { 16380b57cec5SDimitry Andric Out << (first ? "" : ", ") << "copy"; 16390b57cec5SDimitry Andric first = false; 16400b57cec5SDimitry Andric } 16415ffd83dbSDimitry Andric if (PDecl->getPropertyAttributes() & ObjCPropertyAttribute::kind_weak) { 16420b57cec5SDimitry Andric Out << (first ? "" : ", ") << "weak"; 16430b57cec5SDimitry Andric first = false; 16440b57cec5SDimitry Andric } 16455ffd83dbSDimitry Andric if (PDecl->getPropertyAttributes() & 16465ffd83dbSDimitry Andric ObjCPropertyAttribute::kind_unsafe_unretained) { 16470b57cec5SDimitry Andric Out << (first ? "" : ", ") << "unsafe_unretained"; 16480b57cec5SDimitry Andric first = false; 16490b57cec5SDimitry Andric } 16500b57cec5SDimitry Andric 16510b57cec5SDimitry Andric if (PDecl->getPropertyAttributes() & 16525ffd83dbSDimitry Andric ObjCPropertyAttribute::kind_readwrite) { 16530b57cec5SDimitry Andric Out << (first ? "" : ", ") << "readwrite"; 16540b57cec5SDimitry Andric first = false; 16550b57cec5SDimitry Andric } 16565ffd83dbSDimitry Andric if (PDecl->getPropertyAttributes() & ObjCPropertyAttribute::kind_readonly) { 16570b57cec5SDimitry Andric Out << (first ? "" : ", ") << "readonly"; 16580b57cec5SDimitry Andric first = false; 16590b57cec5SDimitry Andric } 16600b57cec5SDimitry Andric 16615ffd83dbSDimitry Andric if (PDecl->getPropertyAttributes() & ObjCPropertyAttribute::kind_getter) { 16620b57cec5SDimitry Andric Out << (first ? "" : ", ") << "getter = "; 16630b57cec5SDimitry Andric PDecl->getGetterName().print(Out); 16640b57cec5SDimitry Andric first = false; 16650b57cec5SDimitry Andric } 16665ffd83dbSDimitry Andric if (PDecl->getPropertyAttributes() & ObjCPropertyAttribute::kind_setter) { 16670b57cec5SDimitry Andric Out << (first ? "" : ", ") << "setter = "; 16680b57cec5SDimitry Andric PDecl->getSetterName().print(Out); 16690b57cec5SDimitry Andric first = false; 16700b57cec5SDimitry Andric } 16710b57cec5SDimitry Andric 16720b57cec5SDimitry Andric if (PDecl->getPropertyAttributes() & 16735ffd83dbSDimitry Andric ObjCPropertyAttribute::kind_nullability) { 16740b57cec5SDimitry Andric if (auto nullability = AttributedType::stripOuterNullability(T)) { 16750b57cec5SDimitry Andric if (*nullability == NullabilityKind::Unspecified && 16760b57cec5SDimitry Andric (PDecl->getPropertyAttributes() & 16775ffd83dbSDimitry Andric ObjCPropertyAttribute::kind_null_resettable)) { 16780b57cec5SDimitry Andric Out << (first ? "" : ", ") << "null_resettable"; 16790b57cec5SDimitry Andric } else { 16800b57cec5SDimitry Andric Out << (first ? "" : ", ") 16810b57cec5SDimitry Andric << getNullabilitySpelling(*nullability, true); 16820b57cec5SDimitry Andric } 16830b57cec5SDimitry Andric first = false; 16840b57cec5SDimitry Andric } 16850b57cec5SDimitry Andric } 16860b57cec5SDimitry Andric 16870b57cec5SDimitry Andric (void) first; // Silence dead store warning due to idiomatic code. 16880b57cec5SDimitry Andric Out << ")"; 16890b57cec5SDimitry Andric } 16900b57cec5SDimitry Andric std::string TypeStr = PDecl->getASTContext().getUnqualifiedObjCPointerType(T). 16910b57cec5SDimitry Andric getAsString(Policy); 16920b57cec5SDimitry Andric Out << ' ' << TypeStr; 16935f757f3fSDimitry Andric if (!StringRef(TypeStr).ends_with("*")) 16940b57cec5SDimitry Andric Out << ' '; 16950b57cec5SDimitry Andric Out << *PDecl; 16960b57cec5SDimitry Andric if (Policy.PolishForDeclaration) 16970b57cec5SDimitry Andric Out << ';'; 16980b57cec5SDimitry Andric } 16990b57cec5SDimitry Andric 17000b57cec5SDimitry Andric void DeclPrinter::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *PID) { 17010b57cec5SDimitry Andric if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize) 17020b57cec5SDimitry Andric Out << "@synthesize "; 17030b57cec5SDimitry Andric else 17040b57cec5SDimitry Andric Out << "@dynamic "; 17050b57cec5SDimitry Andric Out << *PID->getPropertyDecl(); 17060b57cec5SDimitry Andric if (PID->getPropertyIvarDecl()) 17070b57cec5SDimitry Andric Out << '=' << *PID->getPropertyIvarDecl(); 17080b57cec5SDimitry Andric } 17090b57cec5SDimitry Andric 17100b57cec5SDimitry Andric void DeclPrinter::VisitUsingDecl(UsingDecl *D) { 17110b57cec5SDimitry Andric if (!D->isAccessDeclaration()) 17120b57cec5SDimitry Andric Out << "using "; 17130b57cec5SDimitry Andric if (D->hasTypename()) 17140b57cec5SDimitry Andric Out << "typename "; 17150b57cec5SDimitry Andric D->getQualifier()->print(Out, Policy); 17160b57cec5SDimitry Andric 17170b57cec5SDimitry Andric // Use the correct record name when the using declaration is used for 17180b57cec5SDimitry Andric // inheriting constructors. 17190b57cec5SDimitry Andric for (const auto *Shadow : D->shadows()) { 17200b57cec5SDimitry Andric if (const auto *ConstructorShadow = 17210b57cec5SDimitry Andric dyn_cast<ConstructorUsingShadowDecl>(Shadow)) { 17220b57cec5SDimitry Andric assert(Shadow->getDeclContext() == ConstructorShadow->getDeclContext()); 17230b57cec5SDimitry Andric Out << *ConstructorShadow->getNominatedBaseClass(); 17240b57cec5SDimitry Andric return; 17250b57cec5SDimitry Andric } 17260b57cec5SDimitry Andric } 17270b57cec5SDimitry Andric Out << *D; 17280b57cec5SDimitry Andric } 17290b57cec5SDimitry Andric 1730fe6060f1SDimitry Andric void DeclPrinter::VisitUsingEnumDecl(UsingEnumDecl *D) { 1731fe6060f1SDimitry Andric Out << "using enum " << D->getEnumDecl(); 1732fe6060f1SDimitry Andric } 1733fe6060f1SDimitry Andric 17340b57cec5SDimitry Andric void 17350b57cec5SDimitry Andric DeclPrinter::VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D) { 17360b57cec5SDimitry Andric Out << "using typename "; 17370b57cec5SDimitry Andric D->getQualifier()->print(Out, Policy); 17380b57cec5SDimitry Andric Out << D->getDeclName(); 17390b57cec5SDimitry Andric } 17400b57cec5SDimitry Andric 17410b57cec5SDimitry Andric void DeclPrinter::VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D) { 17420b57cec5SDimitry Andric if (!D->isAccessDeclaration()) 17430b57cec5SDimitry Andric Out << "using "; 17440b57cec5SDimitry Andric D->getQualifier()->print(Out, Policy); 17450b57cec5SDimitry Andric Out << D->getDeclName(); 17460b57cec5SDimitry Andric } 17470b57cec5SDimitry Andric 17480b57cec5SDimitry Andric void DeclPrinter::VisitUsingShadowDecl(UsingShadowDecl *D) { 17490b57cec5SDimitry Andric // ignore 17500b57cec5SDimitry Andric } 17510b57cec5SDimitry Andric 17520b57cec5SDimitry Andric void DeclPrinter::VisitOMPThreadPrivateDecl(OMPThreadPrivateDecl *D) { 17530b57cec5SDimitry Andric Out << "#pragma omp threadprivate"; 17540b57cec5SDimitry Andric if (!D->varlist_empty()) { 17550b57cec5SDimitry Andric for (OMPThreadPrivateDecl::varlist_iterator I = D->varlist_begin(), 17560b57cec5SDimitry Andric E = D->varlist_end(); 17570b57cec5SDimitry Andric I != E; ++I) { 17580b57cec5SDimitry Andric Out << (I == D->varlist_begin() ? '(' : ','); 17590b57cec5SDimitry Andric NamedDecl *ND = cast<DeclRefExpr>(*I)->getDecl(); 17600b57cec5SDimitry Andric ND->printQualifiedName(Out); 17610b57cec5SDimitry Andric } 17620b57cec5SDimitry Andric Out << ")"; 17630b57cec5SDimitry Andric } 17640b57cec5SDimitry Andric } 17650b57cec5SDimitry Andric 1766bdd1243dSDimitry Andric void DeclPrinter::VisitHLSLBufferDecl(HLSLBufferDecl *D) { 1767bdd1243dSDimitry Andric if (D->isCBuffer()) 1768bdd1243dSDimitry Andric Out << "cbuffer "; 1769bdd1243dSDimitry Andric else 1770bdd1243dSDimitry Andric Out << "tbuffer "; 1771bdd1243dSDimitry Andric 1772bdd1243dSDimitry Andric Out << *D; 1773bdd1243dSDimitry Andric 1774bdd1243dSDimitry Andric prettyPrintAttributes(D); 1775bdd1243dSDimitry Andric 1776bdd1243dSDimitry Andric Out << " {\n"; 1777bdd1243dSDimitry Andric VisitDeclContext(D); 1778bdd1243dSDimitry Andric Indent() << "}"; 1779bdd1243dSDimitry Andric } 1780bdd1243dSDimitry Andric 17810b57cec5SDimitry Andric void DeclPrinter::VisitOMPAllocateDecl(OMPAllocateDecl *D) { 17820b57cec5SDimitry Andric Out << "#pragma omp allocate"; 17830b57cec5SDimitry Andric if (!D->varlist_empty()) { 17840b57cec5SDimitry Andric for (OMPAllocateDecl::varlist_iterator I = D->varlist_begin(), 17850b57cec5SDimitry Andric E = D->varlist_end(); 17860b57cec5SDimitry Andric I != E; ++I) { 17870b57cec5SDimitry Andric Out << (I == D->varlist_begin() ? '(' : ','); 17880b57cec5SDimitry Andric NamedDecl *ND = cast<DeclRefExpr>(*I)->getDecl(); 17890b57cec5SDimitry Andric ND->printQualifiedName(Out); 17900b57cec5SDimitry Andric } 17910b57cec5SDimitry Andric Out << ")"; 17920b57cec5SDimitry Andric } 17930b57cec5SDimitry Andric if (!D->clauselist_empty()) { 17940b57cec5SDimitry Andric OMPClausePrinter Printer(Out, Policy); 1795349cc55cSDimitry Andric for (OMPClause *C : D->clauselists()) { 1796349cc55cSDimitry Andric Out << " "; 17970b57cec5SDimitry Andric Printer.Visit(C); 17980b57cec5SDimitry Andric } 17990b57cec5SDimitry Andric } 1800349cc55cSDimitry Andric } 18010b57cec5SDimitry Andric 18020b57cec5SDimitry Andric void DeclPrinter::VisitOMPRequiresDecl(OMPRequiresDecl *D) { 18030b57cec5SDimitry Andric Out << "#pragma omp requires "; 18040b57cec5SDimitry Andric if (!D->clauselist_empty()) { 18050b57cec5SDimitry Andric OMPClausePrinter Printer(Out, Policy); 18060b57cec5SDimitry Andric for (auto I = D->clauselist_begin(), E = D->clauselist_end(); I != E; ++I) 18070b57cec5SDimitry Andric Printer.Visit(*I); 18080b57cec5SDimitry Andric } 18090b57cec5SDimitry Andric } 18100b57cec5SDimitry Andric 18110b57cec5SDimitry Andric void DeclPrinter::VisitOMPDeclareReductionDecl(OMPDeclareReductionDecl *D) { 18120b57cec5SDimitry Andric if (!D->isInvalidDecl()) { 18130b57cec5SDimitry Andric Out << "#pragma omp declare reduction ("; 18140b57cec5SDimitry Andric if (D->getDeclName().getNameKind() == DeclarationName::CXXOperatorName) { 18150b57cec5SDimitry Andric const char *OpName = 18160b57cec5SDimitry Andric getOperatorSpelling(D->getDeclName().getCXXOverloadedOperator()); 18170b57cec5SDimitry Andric assert(OpName && "not an overloaded operator"); 18180b57cec5SDimitry Andric Out << OpName; 18190b57cec5SDimitry Andric } else { 18200b57cec5SDimitry Andric assert(D->getDeclName().isIdentifier()); 1821bdd1243dSDimitry Andric D->printName(Out, Policy); 18220b57cec5SDimitry Andric } 18230b57cec5SDimitry Andric Out << " : "; 18240b57cec5SDimitry Andric D->getType().print(Out, Policy); 18250b57cec5SDimitry Andric Out << " : "; 1826fe6060f1SDimitry Andric D->getCombiner()->printPretty(Out, nullptr, Policy, 0, "\n", &Context); 18270b57cec5SDimitry Andric Out << ")"; 18280b57cec5SDimitry Andric if (auto *Init = D->getInitializer()) { 18290b57cec5SDimitry Andric Out << " initializer("; 18300b57cec5SDimitry Andric switch (D->getInitializerKind()) { 18315f757f3fSDimitry Andric case OMPDeclareReductionInitKind::Direct: 18320b57cec5SDimitry Andric Out << "omp_priv("; 18330b57cec5SDimitry Andric break; 18345f757f3fSDimitry Andric case OMPDeclareReductionInitKind::Copy: 18350b57cec5SDimitry Andric Out << "omp_priv = "; 18360b57cec5SDimitry Andric break; 18375f757f3fSDimitry Andric case OMPDeclareReductionInitKind::Call: 18380b57cec5SDimitry Andric break; 18390b57cec5SDimitry Andric } 1840fe6060f1SDimitry Andric Init->printPretty(Out, nullptr, Policy, 0, "\n", &Context); 18415f757f3fSDimitry Andric if (D->getInitializerKind() == OMPDeclareReductionInitKind::Direct) 18420b57cec5SDimitry Andric Out << ")"; 18430b57cec5SDimitry Andric Out << ")"; 18440b57cec5SDimitry Andric } 18450b57cec5SDimitry Andric } 18460b57cec5SDimitry Andric } 18470b57cec5SDimitry Andric 18480b57cec5SDimitry Andric void DeclPrinter::VisitOMPDeclareMapperDecl(OMPDeclareMapperDecl *D) { 18490b57cec5SDimitry Andric if (!D->isInvalidDecl()) { 18500b57cec5SDimitry Andric Out << "#pragma omp declare mapper ("; 1851bdd1243dSDimitry Andric D->printName(Out, Policy); 18520b57cec5SDimitry Andric Out << " : "; 18530b57cec5SDimitry Andric D->getType().print(Out, Policy); 18540b57cec5SDimitry Andric Out << " "; 18550b57cec5SDimitry Andric Out << D->getVarName(); 18560b57cec5SDimitry Andric Out << ")"; 18570b57cec5SDimitry Andric if (!D->clauselist_empty()) { 18580b57cec5SDimitry Andric OMPClausePrinter Printer(Out, Policy); 18590b57cec5SDimitry Andric for (auto *C : D->clauselists()) { 18600b57cec5SDimitry Andric Out << " "; 18610b57cec5SDimitry Andric Printer.Visit(C); 18620b57cec5SDimitry Andric } 18630b57cec5SDimitry Andric } 18640b57cec5SDimitry Andric } 18650b57cec5SDimitry Andric } 18660b57cec5SDimitry Andric 18670b57cec5SDimitry Andric void DeclPrinter::VisitOMPCapturedExprDecl(OMPCapturedExprDecl *D) { 1868fe6060f1SDimitry Andric D->getInit()->printPretty(Out, nullptr, Policy, Indentation, "\n", &Context); 18690b57cec5SDimitry Andric } 18700b57cec5SDimitry Andric 18715ffd83dbSDimitry Andric void DeclPrinter::VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *TTP) { 18725ffd83dbSDimitry Andric if (const TypeConstraint *TC = TTP->getTypeConstraint()) 18735ffd83dbSDimitry Andric TC->print(Out, Policy); 18745ffd83dbSDimitry Andric else if (TTP->wasDeclaredWithTypename()) 18755ffd83dbSDimitry Andric Out << "typename"; 18765ffd83dbSDimitry Andric else 18775ffd83dbSDimitry Andric Out << "class"; 18785ffd83dbSDimitry Andric 18795ffd83dbSDimitry Andric if (TTP->isParameterPack()) 18805ffd83dbSDimitry Andric Out << " ..."; 1881e8d8bef9SDimitry Andric else if (TTP->getDeclName()) 18825ffd83dbSDimitry Andric Out << ' '; 18835ffd83dbSDimitry Andric 188404eeddc0SDimitry Andric if (TTP->getDeclName()) { 188504eeddc0SDimitry Andric if (Policy.CleanUglifiedParameters && TTP->getIdentifier()) 188604eeddc0SDimitry Andric Out << TTP->getIdentifier()->deuglifiedName(); 188704eeddc0SDimitry Andric else 1888e8d8bef9SDimitry Andric Out << TTP->getDeclName(); 188904eeddc0SDimitry Andric } 18905ffd83dbSDimitry Andric 18915ffd83dbSDimitry Andric if (TTP->hasDefaultArgument()) { 18925ffd83dbSDimitry Andric Out << " = "; 1893*0fca6ea1SDimitry Andric TTP->getDefaultArgument().getArgument().print(Policy, Out, 1894*0fca6ea1SDimitry Andric /*IncludeType=*/false); 18955ffd83dbSDimitry Andric } 18965ffd83dbSDimitry Andric } 18975ffd83dbSDimitry Andric 18985ffd83dbSDimitry Andric void DeclPrinter::VisitNonTypeTemplateParmDecl( 18995ffd83dbSDimitry Andric const NonTypeTemplateParmDecl *NTTP) { 19005ffd83dbSDimitry Andric StringRef Name; 19015ffd83dbSDimitry Andric if (IdentifierInfo *II = NTTP->getIdentifier()) 190204eeddc0SDimitry Andric Name = 190304eeddc0SDimitry Andric Policy.CleanUglifiedParameters ? II->deuglifiedName() : II->getName(); 19045ffd83dbSDimitry Andric printDeclType(NTTP->getType(), Name, NTTP->isParameterPack()); 19055ffd83dbSDimitry Andric 19065ffd83dbSDimitry Andric if (NTTP->hasDefaultArgument()) { 19075ffd83dbSDimitry Andric Out << " = "; 1908*0fca6ea1SDimitry Andric NTTP->getDefaultArgument().getArgument().print(Policy, Out, 1909*0fca6ea1SDimitry Andric /*IncludeType=*/false); 19105ffd83dbSDimitry Andric } 19115ffd83dbSDimitry Andric } 1912