xref: /netbsd-src/external/apache2/llvm/dist/clang/lib/AST/DeclPrinter.cpp (revision e038c9c4676b0f19b1b7dd08a940c6ed64a6d5ae)
17330f729Sjoerg //===--- DeclPrinter.cpp - Printing implementation for Decl ASTs ----------===//
27330f729Sjoerg //
37330f729Sjoerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
47330f729Sjoerg // See https://llvm.org/LICENSE.txt for license information.
57330f729Sjoerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
67330f729Sjoerg //
77330f729Sjoerg //===----------------------------------------------------------------------===//
87330f729Sjoerg //
97330f729Sjoerg // This file implements the Decl::print method, which pretty prints the
107330f729Sjoerg // AST back out to C/Objective-C/C++/Objective-C++ code.
117330f729Sjoerg //
127330f729Sjoerg //===----------------------------------------------------------------------===//
137330f729Sjoerg #include "clang/AST/ASTContext.h"
147330f729Sjoerg #include "clang/AST/Attr.h"
157330f729Sjoerg #include "clang/AST/Decl.h"
167330f729Sjoerg #include "clang/AST/DeclCXX.h"
177330f729Sjoerg #include "clang/AST/DeclObjC.h"
187330f729Sjoerg #include "clang/AST/DeclTemplate.h"
197330f729Sjoerg #include "clang/AST/DeclVisitor.h"
207330f729Sjoerg #include "clang/AST/Expr.h"
217330f729Sjoerg #include "clang/AST/ExprCXX.h"
227330f729Sjoerg #include "clang/AST/PrettyPrinter.h"
237330f729Sjoerg #include "clang/Basic/Module.h"
247330f729Sjoerg #include "llvm/Support/raw_ostream.h"
257330f729Sjoerg using namespace clang;
267330f729Sjoerg 
277330f729Sjoerg namespace {
287330f729Sjoerg   class DeclPrinter : public DeclVisitor<DeclPrinter> {
297330f729Sjoerg     raw_ostream &Out;
307330f729Sjoerg     PrintingPolicy Policy;
317330f729Sjoerg     const ASTContext &Context;
327330f729Sjoerg     unsigned Indentation;
337330f729Sjoerg     bool PrintInstantiation;
347330f729Sjoerg 
Indent()357330f729Sjoerg     raw_ostream& Indent() { return Indent(Indentation); }
367330f729Sjoerg     raw_ostream& Indent(unsigned Indentation);
377330f729Sjoerg     void ProcessDeclGroup(SmallVectorImpl<Decl*>& Decls);
387330f729Sjoerg 
397330f729Sjoerg     void Print(AccessSpecifier AS);
407330f729Sjoerg     void PrintConstructorInitializers(CXXConstructorDecl *CDecl,
417330f729Sjoerg                                       std::string &Proto);
427330f729Sjoerg 
437330f729Sjoerg     /// Print an Objective-C method type in parentheses.
447330f729Sjoerg     ///
457330f729Sjoerg     /// \param Quals The Objective-C declaration qualifiers.
467330f729Sjoerg     /// \param T The type to print.
477330f729Sjoerg     void PrintObjCMethodType(ASTContext &Ctx, Decl::ObjCDeclQualifier Quals,
487330f729Sjoerg                              QualType T);
497330f729Sjoerg 
507330f729Sjoerg     void PrintObjCTypeParams(ObjCTypeParamList *Params);
517330f729Sjoerg 
527330f729Sjoerg   public:
DeclPrinter(raw_ostream & Out,const PrintingPolicy & Policy,const ASTContext & Context,unsigned Indentation=0,bool PrintInstantiation=false)537330f729Sjoerg     DeclPrinter(raw_ostream &Out, const PrintingPolicy &Policy,
547330f729Sjoerg                 const ASTContext &Context, unsigned Indentation = 0,
557330f729Sjoerg                 bool PrintInstantiation = false)
567330f729Sjoerg         : Out(Out), Policy(Policy), Context(Context), Indentation(Indentation),
577330f729Sjoerg           PrintInstantiation(PrintInstantiation) {}
587330f729Sjoerg 
597330f729Sjoerg     void VisitDeclContext(DeclContext *DC, bool Indent = true);
607330f729Sjoerg 
617330f729Sjoerg     void VisitTranslationUnitDecl(TranslationUnitDecl *D);
627330f729Sjoerg     void VisitTypedefDecl(TypedefDecl *D);
637330f729Sjoerg     void VisitTypeAliasDecl(TypeAliasDecl *D);
647330f729Sjoerg     void VisitEnumDecl(EnumDecl *D);
657330f729Sjoerg     void VisitRecordDecl(RecordDecl *D);
667330f729Sjoerg     void VisitEnumConstantDecl(EnumConstantDecl *D);
677330f729Sjoerg     void VisitEmptyDecl(EmptyDecl *D);
687330f729Sjoerg     void VisitFunctionDecl(FunctionDecl *D);
697330f729Sjoerg     void VisitFriendDecl(FriendDecl *D);
707330f729Sjoerg     void VisitFieldDecl(FieldDecl *D);
717330f729Sjoerg     void VisitVarDecl(VarDecl *D);
727330f729Sjoerg     void VisitLabelDecl(LabelDecl *D);
737330f729Sjoerg     void VisitParmVarDecl(ParmVarDecl *D);
747330f729Sjoerg     void VisitFileScopeAsmDecl(FileScopeAsmDecl *D);
757330f729Sjoerg     void VisitImportDecl(ImportDecl *D);
767330f729Sjoerg     void VisitStaticAssertDecl(StaticAssertDecl *D);
777330f729Sjoerg     void VisitNamespaceDecl(NamespaceDecl *D);
787330f729Sjoerg     void VisitUsingDirectiveDecl(UsingDirectiveDecl *D);
797330f729Sjoerg     void VisitNamespaceAliasDecl(NamespaceAliasDecl *D);
807330f729Sjoerg     void VisitCXXRecordDecl(CXXRecordDecl *D);
817330f729Sjoerg     void VisitLinkageSpecDecl(LinkageSpecDecl *D);
827330f729Sjoerg     void VisitTemplateDecl(const TemplateDecl *D);
837330f729Sjoerg     void VisitFunctionTemplateDecl(FunctionTemplateDecl *D);
847330f729Sjoerg     void VisitClassTemplateDecl(ClassTemplateDecl *D);
857330f729Sjoerg     void VisitClassTemplateSpecializationDecl(
867330f729Sjoerg                                             ClassTemplateSpecializationDecl *D);
877330f729Sjoerg     void VisitClassTemplatePartialSpecializationDecl(
887330f729Sjoerg                                      ClassTemplatePartialSpecializationDecl *D);
897330f729Sjoerg     void VisitObjCMethodDecl(ObjCMethodDecl *D);
907330f729Sjoerg     void VisitObjCImplementationDecl(ObjCImplementationDecl *D);
917330f729Sjoerg     void VisitObjCInterfaceDecl(ObjCInterfaceDecl *D);
927330f729Sjoerg     void VisitObjCProtocolDecl(ObjCProtocolDecl *D);
937330f729Sjoerg     void VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D);
947330f729Sjoerg     void VisitObjCCategoryDecl(ObjCCategoryDecl *D);
957330f729Sjoerg     void VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *D);
967330f729Sjoerg     void VisitObjCPropertyDecl(ObjCPropertyDecl *D);
977330f729Sjoerg     void VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D);
987330f729Sjoerg     void VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D);
997330f729Sjoerg     void VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D);
1007330f729Sjoerg     void VisitUsingDecl(UsingDecl *D);
1017330f729Sjoerg     void VisitUsingShadowDecl(UsingShadowDecl *D);
1027330f729Sjoerg     void VisitOMPThreadPrivateDecl(OMPThreadPrivateDecl *D);
1037330f729Sjoerg     void VisitOMPAllocateDecl(OMPAllocateDecl *D);
1047330f729Sjoerg     void VisitOMPRequiresDecl(OMPRequiresDecl *D);
1057330f729Sjoerg     void VisitOMPDeclareReductionDecl(OMPDeclareReductionDecl *D);
1067330f729Sjoerg     void VisitOMPDeclareMapperDecl(OMPDeclareMapperDecl *D);
1077330f729Sjoerg     void VisitOMPCapturedExprDecl(OMPCapturedExprDecl *D);
108*e038c9c4Sjoerg     void VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *TTP);
109*e038c9c4Sjoerg     void VisitNonTypeTemplateParmDecl(const NonTypeTemplateParmDecl *NTTP);
1107330f729Sjoerg 
1117330f729Sjoerg     void printTemplateParameters(const TemplateParameterList *Params,
1127330f729Sjoerg                                  bool OmitTemplateKW = false);
113*e038c9c4Sjoerg     void printTemplateArguments(llvm::ArrayRef<TemplateArgument> Args,
114*e038c9c4Sjoerg                                 const TemplateParameterList *Params,
115*e038c9c4Sjoerg                                 bool TemplOverloaded);
116*e038c9c4Sjoerg     void printTemplateArguments(llvm::ArrayRef<TemplateArgumentLoc> Args,
117*e038c9c4Sjoerg                                 const TemplateParameterList *Params,
118*e038c9c4Sjoerg                                 bool TemplOverloaded);
1197330f729Sjoerg     void prettyPrintAttributes(Decl *D);
1207330f729Sjoerg     void prettyPrintPragmas(Decl *D);
1217330f729Sjoerg     void printDeclType(QualType T, StringRef DeclName, bool Pack = false);
1227330f729Sjoerg   };
1237330f729Sjoerg }
1247330f729Sjoerg 
print(raw_ostream & Out,unsigned Indentation,bool PrintInstantiation) const1257330f729Sjoerg void Decl::print(raw_ostream &Out, unsigned Indentation,
1267330f729Sjoerg                  bool PrintInstantiation) const {
1277330f729Sjoerg   print(Out, getASTContext().getPrintingPolicy(), Indentation, PrintInstantiation);
1287330f729Sjoerg }
1297330f729Sjoerg 
print(raw_ostream & Out,const PrintingPolicy & Policy,unsigned Indentation,bool PrintInstantiation) const1307330f729Sjoerg void Decl::print(raw_ostream &Out, const PrintingPolicy &Policy,
1317330f729Sjoerg                  unsigned Indentation, bool PrintInstantiation) const {
1327330f729Sjoerg   DeclPrinter Printer(Out, Policy, getASTContext(), Indentation,
1337330f729Sjoerg                       PrintInstantiation);
1347330f729Sjoerg   Printer.Visit(const_cast<Decl*>(this));
1357330f729Sjoerg }
1367330f729Sjoerg 
print(raw_ostream & Out,const ASTContext & Context,bool OmitTemplateKW) const1377330f729Sjoerg void TemplateParameterList::print(raw_ostream &Out, const ASTContext &Context,
1387330f729Sjoerg                                   bool OmitTemplateKW) const {
1397330f729Sjoerg   print(Out, Context, Context.getPrintingPolicy(), OmitTemplateKW);
1407330f729Sjoerg }
1417330f729Sjoerg 
print(raw_ostream & Out,const ASTContext & Context,const PrintingPolicy & Policy,bool OmitTemplateKW) const1427330f729Sjoerg void TemplateParameterList::print(raw_ostream &Out, const ASTContext &Context,
1437330f729Sjoerg                                   const PrintingPolicy &Policy,
1447330f729Sjoerg                                   bool OmitTemplateKW) const {
1457330f729Sjoerg   DeclPrinter Printer(Out, Policy, Context);
1467330f729Sjoerg   Printer.printTemplateParameters(this, OmitTemplateKW);
1477330f729Sjoerg }
1487330f729Sjoerg 
GetBaseType(QualType T)1497330f729Sjoerg static QualType GetBaseType(QualType T) {
1507330f729Sjoerg   // FIXME: This should be on the Type class!
1517330f729Sjoerg   QualType BaseType = T;
1527330f729Sjoerg   while (!BaseType->isSpecifierType()) {
1537330f729Sjoerg     if (const PointerType *PTy = BaseType->getAs<PointerType>())
1547330f729Sjoerg       BaseType = PTy->getPointeeType();
1557330f729Sjoerg     else if (const BlockPointerType *BPy = BaseType->getAs<BlockPointerType>())
1567330f729Sjoerg       BaseType = BPy->getPointeeType();
1577330f729Sjoerg     else if (const ArrayType* ATy = dyn_cast<ArrayType>(BaseType))
1587330f729Sjoerg       BaseType = ATy->getElementType();
1597330f729Sjoerg     else if (const FunctionType* FTy = BaseType->getAs<FunctionType>())
1607330f729Sjoerg       BaseType = FTy->getReturnType();
1617330f729Sjoerg     else if (const VectorType *VTy = BaseType->getAs<VectorType>())
1627330f729Sjoerg       BaseType = VTy->getElementType();
1637330f729Sjoerg     else if (const ReferenceType *RTy = BaseType->getAs<ReferenceType>())
1647330f729Sjoerg       BaseType = RTy->getPointeeType();
1657330f729Sjoerg     else if (const AutoType *ATy = BaseType->getAs<AutoType>())
1667330f729Sjoerg       BaseType = ATy->getDeducedType();
1677330f729Sjoerg     else if (const ParenType *PTy = BaseType->getAs<ParenType>())
1687330f729Sjoerg       BaseType = PTy->desugar();
1697330f729Sjoerg     else
1707330f729Sjoerg       // This must be a syntax error.
1717330f729Sjoerg       break;
1727330f729Sjoerg   }
1737330f729Sjoerg   return BaseType;
1747330f729Sjoerg }
1757330f729Sjoerg 
getDeclType(Decl * D)1767330f729Sjoerg static QualType getDeclType(Decl* D) {
1777330f729Sjoerg   if (TypedefNameDecl* TDD = dyn_cast<TypedefNameDecl>(D))
1787330f729Sjoerg     return TDD->getUnderlyingType();
1797330f729Sjoerg   if (ValueDecl* VD = dyn_cast<ValueDecl>(D))
1807330f729Sjoerg     return VD->getType();
1817330f729Sjoerg   return QualType();
1827330f729Sjoerg }
1837330f729Sjoerg 
printGroup(Decl ** Begin,unsigned NumDecls,raw_ostream & Out,const PrintingPolicy & Policy,unsigned Indentation)1847330f729Sjoerg void Decl::printGroup(Decl** Begin, unsigned NumDecls,
1857330f729Sjoerg                       raw_ostream &Out, const PrintingPolicy &Policy,
1867330f729Sjoerg                       unsigned Indentation) {
1877330f729Sjoerg   if (NumDecls == 1) {
1887330f729Sjoerg     (*Begin)->print(Out, Policy, Indentation);
1897330f729Sjoerg     return;
1907330f729Sjoerg   }
1917330f729Sjoerg 
1927330f729Sjoerg   Decl** End = Begin + NumDecls;
1937330f729Sjoerg   TagDecl* TD = dyn_cast<TagDecl>(*Begin);
1947330f729Sjoerg   if (TD)
1957330f729Sjoerg     ++Begin;
1967330f729Sjoerg 
1977330f729Sjoerg   PrintingPolicy SubPolicy(Policy);
1987330f729Sjoerg 
1997330f729Sjoerg   bool isFirst = true;
2007330f729Sjoerg   for ( ; Begin != End; ++Begin) {
2017330f729Sjoerg     if (isFirst) {
2027330f729Sjoerg       if(TD)
2037330f729Sjoerg         SubPolicy.IncludeTagDefinition = true;
2047330f729Sjoerg       SubPolicy.SuppressSpecifiers = false;
2057330f729Sjoerg       isFirst = false;
2067330f729Sjoerg     } else {
2077330f729Sjoerg       if (!isFirst) Out << ", ";
2087330f729Sjoerg       SubPolicy.IncludeTagDefinition = false;
2097330f729Sjoerg       SubPolicy.SuppressSpecifiers = true;
2107330f729Sjoerg     }
2117330f729Sjoerg 
2127330f729Sjoerg     (*Begin)->print(Out, SubPolicy, Indentation);
2137330f729Sjoerg   }
2147330f729Sjoerg }
2157330f729Sjoerg 
dumpDeclContext() const2167330f729Sjoerg LLVM_DUMP_METHOD void DeclContext::dumpDeclContext() const {
2177330f729Sjoerg   // Get the translation unit
2187330f729Sjoerg   const DeclContext *DC = this;
2197330f729Sjoerg   while (!DC->isTranslationUnit())
2207330f729Sjoerg     DC = DC->getParent();
2217330f729Sjoerg 
2227330f729Sjoerg   ASTContext &Ctx = cast<TranslationUnitDecl>(DC)->getASTContext();
2237330f729Sjoerg   DeclPrinter Printer(llvm::errs(), Ctx.getPrintingPolicy(), Ctx, 0);
2247330f729Sjoerg   Printer.VisitDeclContext(const_cast<DeclContext *>(this), /*Indent=*/false);
2257330f729Sjoerg }
2267330f729Sjoerg 
Indent(unsigned Indentation)2277330f729Sjoerg raw_ostream& DeclPrinter::Indent(unsigned Indentation) {
2287330f729Sjoerg   for (unsigned i = 0; i != Indentation; ++i)
2297330f729Sjoerg     Out << "  ";
2307330f729Sjoerg   return Out;
2317330f729Sjoerg }
2327330f729Sjoerg 
prettyPrintAttributes(Decl * D)2337330f729Sjoerg void DeclPrinter::prettyPrintAttributes(Decl *D) {
2347330f729Sjoerg   if (Policy.PolishForDeclaration)
2357330f729Sjoerg     return;
2367330f729Sjoerg 
2377330f729Sjoerg   if (D->hasAttrs()) {
2387330f729Sjoerg     AttrVec &Attrs = D->getAttrs();
2397330f729Sjoerg     for (auto *A : Attrs) {
2407330f729Sjoerg       if (A->isInherited() || A->isImplicit())
2417330f729Sjoerg         continue;
2427330f729Sjoerg       switch (A->getKind()) {
2437330f729Sjoerg #define ATTR(X)
2447330f729Sjoerg #define PRAGMA_SPELLING_ATTR(X) case attr::X:
2457330f729Sjoerg #include "clang/Basic/AttrList.inc"
2467330f729Sjoerg         break;
2477330f729Sjoerg       default:
2487330f729Sjoerg         A->printPretty(Out, Policy);
2497330f729Sjoerg         break;
2507330f729Sjoerg       }
2517330f729Sjoerg     }
2527330f729Sjoerg   }
2537330f729Sjoerg }
2547330f729Sjoerg 
prettyPrintPragmas(Decl * D)2557330f729Sjoerg void DeclPrinter::prettyPrintPragmas(Decl *D) {
2567330f729Sjoerg   if (Policy.PolishForDeclaration)
2577330f729Sjoerg     return;
2587330f729Sjoerg 
2597330f729Sjoerg   if (D->hasAttrs()) {
2607330f729Sjoerg     AttrVec &Attrs = D->getAttrs();
2617330f729Sjoerg     for (auto *A : Attrs) {
2627330f729Sjoerg       switch (A->getKind()) {
2637330f729Sjoerg #define ATTR(X)
2647330f729Sjoerg #define PRAGMA_SPELLING_ATTR(X) case attr::X:
2657330f729Sjoerg #include "clang/Basic/AttrList.inc"
2667330f729Sjoerg         A->printPretty(Out, Policy);
2677330f729Sjoerg         Indent();
2687330f729Sjoerg         break;
2697330f729Sjoerg       default:
2707330f729Sjoerg         break;
2717330f729Sjoerg       }
2727330f729Sjoerg     }
2737330f729Sjoerg   }
2747330f729Sjoerg }
2757330f729Sjoerg 
printDeclType(QualType T,StringRef DeclName,bool Pack)2767330f729Sjoerg void DeclPrinter::printDeclType(QualType T, StringRef DeclName, bool Pack) {
2777330f729Sjoerg   // Normally, a PackExpansionType is written as T[3]... (for instance, as a
2787330f729Sjoerg   // template argument), but if it is the type of a declaration, the ellipsis
2797330f729Sjoerg   // is placed before the name being declared.
2807330f729Sjoerg   if (auto *PET = T->getAs<PackExpansionType>()) {
2817330f729Sjoerg     Pack = true;
2827330f729Sjoerg     T = PET->getPattern();
2837330f729Sjoerg   }
2847330f729Sjoerg   T.print(Out, Policy, (Pack ? "..." : "") + DeclName, Indentation);
2857330f729Sjoerg }
2867330f729Sjoerg 
ProcessDeclGroup(SmallVectorImpl<Decl * > & Decls)2877330f729Sjoerg void DeclPrinter::ProcessDeclGroup(SmallVectorImpl<Decl*>& Decls) {
2887330f729Sjoerg   this->Indent();
2897330f729Sjoerg   Decl::printGroup(Decls.data(), Decls.size(), Out, Policy, Indentation);
2907330f729Sjoerg   Out << ";\n";
2917330f729Sjoerg   Decls.clear();
2927330f729Sjoerg 
2937330f729Sjoerg }
2947330f729Sjoerg 
Print(AccessSpecifier AS)2957330f729Sjoerg void DeclPrinter::Print(AccessSpecifier AS) {
296*e038c9c4Sjoerg   const auto AccessSpelling = getAccessSpelling(AS);
297*e038c9c4Sjoerg   if (AccessSpelling.empty())
298*e038c9c4Sjoerg     llvm_unreachable("No access specifier!");
299*e038c9c4Sjoerg   Out << AccessSpelling;
3007330f729Sjoerg }
3017330f729Sjoerg 
PrintConstructorInitializers(CXXConstructorDecl * CDecl,std::string & Proto)3027330f729Sjoerg void DeclPrinter::PrintConstructorInitializers(CXXConstructorDecl *CDecl,
3037330f729Sjoerg                                                std::string &Proto) {
3047330f729Sjoerg   bool HasInitializerList = false;
3057330f729Sjoerg   for (const auto *BMInitializer : CDecl->inits()) {
3067330f729Sjoerg     if (BMInitializer->isInClassMemberInitializer())
3077330f729Sjoerg       continue;
3087330f729Sjoerg 
3097330f729Sjoerg     if (!HasInitializerList) {
3107330f729Sjoerg       Proto += " : ";
3117330f729Sjoerg       Out << Proto;
3127330f729Sjoerg       Proto.clear();
3137330f729Sjoerg       HasInitializerList = true;
3147330f729Sjoerg     } else
3157330f729Sjoerg       Out << ", ";
3167330f729Sjoerg 
3177330f729Sjoerg     if (BMInitializer->isAnyMemberInitializer()) {
3187330f729Sjoerg       FieldDecl *FD = BMInitializer->getAnyMember();
3197330f729Sjoerg       Out << *FD;
3207330f729Sjoerg     } else {
3217330f729Sjoerg       Out << QualType(BMInitializer->getBaseClass(), 0).getAsString(Policy);
3227330f729Sjoerg     }
3237330f729Sjoerg 
3247330f729Sjoerg     Out << "(";
3257330f729Sjoerg     if (!BMInitializer->getInit()) {
3267330f729Sjoerg       // Nothing to print
3277330f729Sjoerg     } else {
3287330f729Sjoerg       Expr *Init = BMInitializer->getInit();
3297330f729Sjoerg       if (ExprWithCleanups *Tmp = dyn_cast<ExprWithCleanups>(Init))
3307330f729Sjoerg         Init = Tmp->getSubExpr();
3317330f729Sjoerg 
3327330f729Sjoerg       Init = Init->IgnoreParens();
3337330f729Sjoerg 
3347330f729Sjoerg       Expr *SimpleInit = nullptr;
3357330f729Sjoerg       Expr **Args = nullptr;
3367330f729Sjoerg       unsigned NumArgs = 0;
3377330f729Sjoerg       if (ParenListExpr *ParenList = dyn_cast<ParenListExpr>(Init)) {
3387330f729Sjoerg         Args = ParenList->getExprs();
3397330f729Sjoerg         NumArgs = ParenList->getNumExprs();
3407330f729Sjoerg       } else if (CXXConstructExpr *Construct =
3417330f729Sjoerg                      dyn_cast<CXXConstructExpr>(Init)) {
3427330f729Sjoerg         Args = Construct->getArgs();
3437330f729Sjoerg         NumArgs = Construct->getNumArgs();
3447330f729Sjoerg       } else
3457330f729Sjoerg         SimpleInit = Init;
3467330f729Sjoerg 
3477330f729Sjoerg       if (SimpleInit)
348*e038c9c4Sjoerg         SimpleInit->printPretty(Out, nullptr, Policy, Indentation, "\n",
349*e038c9c4Sjoerg                                 &Context);
3507330f729Sjoerg       else {
3517330f729Sjoerg         for (unsigned I = 0; I != NumArgs; ++I) {
3527330f729Sjoerg           assert(Args[I] != nullptr && "Expected non-null Expr");
3537330f729Sjoerg           if (isa<CXXDefaultArgExpr>(Args[I]))
3547330f729Sjoerg             break;
3557330f729Sjoerg 
3567330f729Sjoerg           if (I)
3577330f729Sjoerg             Out << ", ";
358*e038c9c4Sjoerg           Args[I]->printPretty(Out, nullptr, Policy, Indentation, "\n",
359*e038c9c4Sjoerg                                &Context);
3607330f729Sjoerg         }
3617330f729Sjoerg       }
3627330f729Sjoerg     }
3637330f729Sjoerg     Out << ")";
3647330f729Sjoerg     if (BMInitializer->isPackExpansion())
3657330f729Sjoerg       Out << "...";
3667330f729Sjoerg   }
3677330f729Sjoerg }
3687330f729Sjoerg 
3697330f729Sjoerg //----------------------------------------------------------------------------
3707330f729Sjoerg // Common C declarations
3717330f729Sjoerg //----------------------------------------------------------------------------
3727330f729Sjoerg 
VisitDeclContext(DeclContext * DC,bool Indent)3737330f729Sjoerg void DeclPrinter::VisitDeclContext(DeclContext *DC, bool Indent) {
3747330f729Sjoerg   if (Policy.TerseOutput)
3757330f729Sjoerg     return;
3767330f729Sjoerg 
3777330f729Sjoerg   if (Indent)
3787330f729Sjoerg     Indentation += Policy.Indentation;
3797330f729Sjoerg 
3807330f729Sjoerg   SmallVector<Decl*, 2> Decls;
3817330f729Sjoerg   for (DeclContext::decl_iterator D = DC->decls_begin(), DEnd = DC->decls_end();
3827330f729Sjoerg        D != DEnd; ++D) {
3837330f729Sjoerg 
3847330f729Sjoerg     // Don't print ObjCIvarDecls, as they are printed when visiting the
3857330f729Sjoerg     // containing ObjCInterfaceDecl.
3867330f729Sjoerg     if (isa<ObjCIvarDecl>(*D))
3877330f729Sjoerg       continue;
3887330f729Sjoerg 
3897330f729Sjoerg     // Skip over implicit declarations in pretty-printing mode.
3907330f729Sjoerg     if (D->isImplicit())
3917330f729Sjoerg       continue;
3927330f729Sjoerg 
3937330f729Sjoerg     // Don't print implicit specializations, as they are printed when visiting
3947330f729Sjoerg     // corresponding templates.
3957330f729Sjoerg     if (auto FD = dyn_cast<FunctionDecl>(*D))
3967330f729Sjoerg       if (FD->getTemplateSpecializationKind() == TSK_ImplicitInstantiation &&
3977330f729Sjoerg           !isa<ClassTemplateSpecializationDecl>(DC))
3987330f729Sjoerg         continue;
3997330f729Sjoerg 
4007330f729Sjoerg     // The next bits of code handle stuff like "struct {int x;} a,b"; we're
4017330f729Sjoerg     // forced to merge the declarations because there's no other way to
4027330f729Sjoerg     // refer to the struct in question.  When that struct is named instead, we
4037330f729Sjoerg     // also need to merge to avoid splitting off a stand-alone struct
4047330f729Sjoerg     // declaration that produces the warning ext_no_declarators in some
4057330f729Sjoerg     // contexts.
4067330f729Sjoerg     //
4077330f729Sjoerg     // This limited merging is safe without a bunch of other checks because it
4087330f729Sjoerg     // only merges declarations directly referring to the tag, not typedefs.
4097330f729Sjoerg     //
4107330f729Sjoerg     // Check whether the current declaration should be grouped with a previous
4117330f729Sjoerg     // non-free-standing tag declaration.
4127330f729Sjoerg     QualType CurDeclType = getDeclType(*D);
4137330f729Sjoerg     if (!Decls.empty() && !CurDeclType.isNull()) {
4147330f729Sjoerg       QualType BaseType = GetBaseType(CurDeclType);
4157330f729Sjoerg       if (!BaseType.isNull() && isa<ElaboratedType>(BaseType) &&
4167330f729Sjoerg           cast<ElaboratedType>(BaseType)->getOwnedTagDecl() == Decls[0]) {
4177330f729Sjoerg         Decls.push_back(*D);
4187330f729Sjoerg         continue;
4197330f729Sjoerg       }
4207330f729Sjoerg     }
4217330f729Sjoerg 
4227330f729Sjoerg     // If we have a merged group waiting to be handled, handle it now.
4237330f729Sjoerg     if (!Decls.empty())
4247330f729Sjoerg       ProcessDeclGroup(Decls);
4257330f729Sjoerg 
4267330f729Sjoerg     // If the current declaration is not a free standing declaration, save it
4277330f729Sjoerg     // so we can merge it with the subsequent declaration(s) using it.
4287330f729Sjoerg     if (isa<TagDecl>(*D) && !cast<TagDecl>(*D)->isFreeStanding()) {
4297330f729Sjoerg       Decls.push_back(*D);
4307330f729Sjoerg       continue;
4317330f729Sjoerg     }
4327330f729Sjoerg 
4337330f729Sjoerg     if (isa<AccessSpecDecl>(*D)) {
4347330f729Sjoerg       Indentation -= Policy.Indentation;
4357330f729Sjoerg       this->Indent();
4367330f729Sjoerg       Print(D->getAccess());
4377330f729Sjoerg       Out << ":\n";
4387330f729Sjoerg       Indentation += Policy.Indentation;
4397330f729Sjoerg       continue;
4407330f729Sjoerg     }
4417330f729Sjoerg 
4427330f729Sjoerg     this->Indent();
4437330f729Sjoerg     Visit(*D);
4447330f729Sjoerg 
4457330f729Sjoerg     // FIXME: Need to be able to tell the DeclPrinter when
4467330f729Sjoerg     const char *Terminator = nullptr;
4477330f729Sjoerg     if (isa<OMPThreadPrivateDecl>(*D) || isa<OMPDeclareReductionDecl>(*D) ||
4487330f729Sjoerg         isa<OMPDeclareMapperDecl>(*D) || isa<OMPRequiresDecl>(*D) ||
4497330f729Sjoerg         isa<OMPAllocateDecl>(*D))
4507330f729Sjoerg       Terminator = nullptr;
4517330f729Sjoerg     else if (isa<ObjCMethodDecl>(*D) && cast<ObjCMethodDecl>(*D)->hasBody())
4527330f729Sjoerg       Terminator = nullptr;
4537330f729Sjoerg     else if (auto FD = dyn_cast<FunctionDecl>(*D)) {
4547330f729Sjoerg       if (FD->isThisDeclarationADefinition())
4557330f729Sjoerg         Terminator = nullptr;
4567330f729Sjoerg       else
4577330f729Sjoerg         Terminator = ";";
4587330f729Sjoerg     } else if (auto TD = dyn_cast<FunctionTemplateDecl>(*D)) {
4597330f729Sjoerg       if (TD->getTemplatedDecl()->isThisDeclarationADefinition())
4607330f729Sjoerg         Terminator = nullptr;
4617330f729Sjoerg       else
4627330f729Sjoerg         Terminator = ";";
4637330f729Sjoerg     } else if (isa<NamespaceDecl>(*D) || isa<LinkageSpecDecl>(*D) ||
4647330f729Sjoerg              isa<ObjCImplementationDecl>(*D) ||
4657330f729Sjoerg              isa<ObjCInterfaceDecl>(*D) ||
4667330f729Sjoerg              isa<ObjCProtocolDecl>(*D) ||
4677330f729Sjoerg              isa<ObjCCategoryImplDecl>(*D) ||
4687330f729Sjoerg              isa<ObjCCategoryDecl>(*D))
4697330f729Sjoerg       Terminator = nullptr;
4707330f729Sjoerg     else if (isa<EnumConstantDecl>(*D)) {
4717330f729Sjoerg       DeclContext::decl_iterator Next = D;
4727330f729Sjoerg       ++Next;
4737330f729Sjoerg       if (Next != DEnd)
4747330f729Sjoerg         Terminator = ",";
4757330f729Sjoerg     } else
4767330f729Sjoerg       Terminator = ";";
4777330f729Sjoerg 
4787330f729Sjoerg     if (Terminator)
4797330f729Sjoerg       Out << Terminator;
4807330f729Sjoerg     if (!Policy.TerseOutput &&
4817330f729Sjoerg         ((isa<FunctionDecl>(*D) &&
4827330f729Sjoerg           cast<FunctionDecl>(*D)->doesThisDeclarationHaveABody()) ||
4837330f729Sjoerg          (isa<FunctionTemplateDecl>(*D) &&
4847330f729Sjoerg           cast<FunctionTemplateDecl>(*D)->getTemplatedDecl()->doesThisDeclarationHaveABody())))
4857330f729Sjoerg       ; // StmtPrinter already added '\n' after CompoundStmt.
4867330f729Sjoerg     else
4877330f729Sjoerg       Out << "\n";
4887330f729Sjoerg 
4897330f729Sjoerg     // Declare target attribute is special one, natural spelling for the pragma
4907330f729Sjoerg     // assumes "ending" construct so print it here.
4917330f729Sjoerg     if (D->hasAttr<OMPDeclareTargetDeclAttr>())
4927330f729Sjoerg       Out << "#pragma omp end declare target\n";
4937330f729Sjoerg   }
4947330f729Sjoerg 
4957330f729Sjoerg   if (!Decls.empty())
4967330f729Sjoerg     ProcessDeclGroup(Decls);
4977330f729Sjoerg 
4987330f729Sjoerg   if (Indent)
4997330f729Sjoerg     Indentation -= Policy.Indentation;
5007330f729Sjoerg }
5017330f729Sjoerg 
VisitTranslationUnitDecl(TranslationUnitDecl * D)5027330f729Sjoerg void DeclPrinter::VisitTranslationUnitDecl(TranslationUnitDecl *D) {
5037330f729Sjoerg   VisitDeclContext(D, false);
5047330f729Sjoerg }
5057330f729Sjoerg 
VisitTypedefDecl(TypedefDecl * D)5067330f729Sjoerg void DeclPrinter::VisitTypedefDecl(TypedefDecl *D) {
5077330f729Sjoerg   if (!Policy.SuppressSpecifiers) {
5087330f729Sjoerg     Out << "typedef ";
5097330f729Sjoerg 
5107330f729Sjoerg     if (D->isModulePrivate())
5117330f729Sjoerg       Out << "__module_private__ ";
5127330f729Sjoerg   }
5137330f729Sjoerg   QualType Ty = D->getTypeSourceInfo()->getType();
5147330f729Sjoerg   Ty.print(Out, Policy, D->getName(), Indentation);
5157330f729Sjoerg   prettyPrintAttributes(D);
5167330f729Sjoerg }
5177330f729Sjoerg 
VisitTypeAliasDecl(TypeAliasDecl * D)5187330f729Sjoerg void DeclPrinter::VisitTypeAliasDecl(TypeAliasDecl *D) {
5197330f729Sjoerg   Out << "using " << *D;
5207330f729Sjoerg   prettyPrintAttributes(D);
5217330f729Sjoerg   Out << " = " << D->getTypeSourceInfo()->getType().getAsString(Policy);
5227330f729Sjoerg }
5237330f729Sjoerg 
VisitEnumDecl(EnumDecl * D)5247330f729Sjoerg void DeclPrinter::VisitEnumDecl(EnumDecl *D) {
5257330f729Sjoerg   if (!Policy.SuppressSpecifiers && D->isModulePrivate())
5267330f729Sjoerg     Out << "__module_private__ ";
5277330f729Sjoerg   Out << "enum";
5287330f729Sjoerg   if (D->isScoped()) {
5297330f729Sjoerg     if (D->isScopedUsingClassTag())
5307330f729Sjoerg       Out << " class";
5317330f729Sjoerg     else
5327330f729Sjoerg       Out << " struct";
5337330f729Sjoerg   }
5347330f729Sjoerg 
5357330f729Sjoerg   prettyPrintAttributes(D);
5367330f729Sjoerg 
537*e038c9c4Sjoerg   if (D->getDeclName())
538*e038c9c4Sjoerg     Out << ' ' << D->getDeclName();
5397330f729Sjoerg 
540*e038c9c4Sjoerg   if (D->isFixed())
5417330f729Sjoerg     Out << " : " << D->getIntegerType().stream(Policy);
5427330f729Sjoerg 
5437330f729Sjoerg   if (D->isCompleteDefinition()) {
5447330f729Sjoerg     Out << " {\n";
5457330f729Sjoerg     VisitDeclContext(D);
5467330f729Sjoerg     Indent() << "}";
5477330f729Sjoerg   }
5487330f729Sjoerg }
5497330f729Sjoerg 
VisitRecordDecl(RecordDecl * D)5507330f729Sjoerg void DeclPrinter::VisitRecordDecl(RecordDecl *D) {
5517330f729Sjoerg   if (!Policy.SuppressSpecifiers && D->isModulePrivate())
5527330f729Sjoerg     Out << "__module_private__ ";
5537330f729Sjoerg   Out << D->getKindName();
5547330f729Sjoerg 
5557330f729Sjoerg   prettyPrintAttributes(D);
5567330f729Sjoerg 
5577330f729Sjoerg   if (D->getIdentifier())
5587330f729Sjoerg     Out << ' ' << *D;
5597330f729Sjoerg 
5607330f729Sjoerg   if (D->isCompleteDefinition()) {
5617330f729Sjoerg     Out << " {\n";
5627330f729Sjoerg     VisitDeclContext(D);
5637330f729Sjoerg     Indent() << "}";
5647330f729Sjoerg   }
5657330f729Sjoerg }
5667330f729Sjoerg 
VisitEnumConstantDecl(EnumConstantDecl * D)5677330f729Sjoerg void DeclPrinter::VisitEnumConstantDecl(EnumConstantDecl *D) {
5687330f729Sjoerg   Out << *D;
5697330f729Sjoerg   prettyPrintAttributes(D);
5707330f729Sjoerg   if (Expr *Init = D->getInitExpr()) {
5717330f729Sjoerg     Out << " = ";
5727330f729Sjoerg     Init->printPretty(Out, nullptr, Policy, Indentation, "\n", &Context);
5737330f729Sjoerg   }
5747330f729Sjoerg }
5757330f729Sjoerg 
printExplicitSpecifier(ExplicitSpecifier ES,llvm::raw_ostream & Out,PrintingPolicy & Policy,unsigned Indentation,const ASTContext & Context)5767330f729Sjoerg static void printExplicitSpecifier(ExplicitSpecifier ES, llvm::raw_ostream &Out,
577*e038c9c4Sjoerg                                    PrintingPolicy &Policy, unsigned Indentation,
578*e038c9c4Sjoerg                                    const ASTContext &Context) {
5797330f729Sjoerg   std::string Proto = "explicit";
5807330f729Sjoerg   llvm::raw_string_ostream EOut(Proto);
5817330f729Sjoerg   if (ES.getExpr()) {
5827330f729Sjoerg     EOut << "(";
583*e038c9c4Sjoerg     ES.getExpr()->printPretty(EOut, nullptr, Policy, Indentation, "\n",
584*e038c9c4Sjoerg                               &Context);
5857330f729Sjoerg     EOut << ")";
5867330f729Sjoerg   }
5877330f729Sjoerg   EOut << " ";
5887330f729Sjoerg   EOut.flush();
5897330f729Sjoerg   Out << EOut.str();
5907330f729Sjoerg }
5917330f729Sjoerg 
VisitFunctionDecl(FunctionDecl * D)5927330f729Sjoerg void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
5937330f729Sjoerg   if (!D->getDescribedFunctionTemplate() &&
5947330f729Sjoerg       !D->isFunctionTemplateSpecialization())
5957330f729Sjoerg     prettyPrintPragmas(D);
5967330f729Sjoerg 
5977330f729Sjoerg   if (D->isFunctionTemplateSpecialization())
5987330f729Sjoerg     Out << "template<> ";
5997330f729Sjoerg   else if (!D->getDescribedFunctionTemplate()) {
6007330f729Sjoerg     for (unsigned I = 0, NumTemplateParams = D->getNumTemplateParameterLists();
6017330f729Sjoerg          I < NumTemplateParams; ++I)
6027330f729Sjoerg       printTemplateParameters(D->getTemplateParameterList(I));
6037330f729Sjoerg   }
6047330f729Sjoerg 
6057330f729Sjoerg   CXXConstructorDecl *CDecl = dyn_cast<CXXConstructorDecl>(D);
6067330f729Sjoerg   CXXConversionDecl *ConversionDecl = dyn_cast<CXXConversionDecl>(D);
6077330f729Sjoerg   CXXDeductionGuideDecl *GuideDecl = dyn_cast<CXXDeductionGuideDecl>(D);
6087330f729Sjoerg   if (!Policy.SuppressSpecifiers) {
6097330f729Sjoerg     switch (D->getStorageClass()) {
6107330f729Sjoerg     case SC_None: break;
6117330f729Sjoerg     case SC_Extern: Out << "extern "; break;
6127330f729Sjoerg     case SC_Static: Out << "static "; break;
6137330f729Sjoerg     case SC_PrivateExtern: Out << "__private_extern__ "; break;
6147330f729Sjoerg     case SC_Auto: case SC_Register:
6157330f729Sjoerg       llvm_unreachable("invalid for functions");
6167330f729Sjoerg     }
6177330f729Sjoerg 
6187330f729Sjoerg     if (D->isInlineSpecified())  Out << "inline ";
6197330f729Sjoerg     if (D->isVirtualAsWritten()) Out << "virtual ";
6207330f729Sjoerg     if (D->isModulePrivate())    Out << "__module_private__ ";
6217330f729Sjoerg     if (D->isConstexprSpecified() && !D->isExplicitlyDefaulted())
6227330f729Sjoerg       Out << "constexpr ";
6237330f729Sjoerg     if (D->isConsteval())        Out << "consteval ";
6247330f729Sjoerg     ExplicitSpecifier ExplicitSpec = ExplicitSpecifier::getFromDecl(D);
6257330f729Sjoerg     if (ExplicitSpec.isSpecified())
626*e038c9c4Sjoerg       printExplicitSpecifier(ExplicitSpec, Out, Policy, Indentation, Context);
6277330f729Sjoerg   }
6287330f729Sjoerg 
6297330f729Sjoerg   PrintingPolicy SubPolicy(Policy);
6307330f729Sjoerg   SubPolicy.SuppressSpecifiers = false;
6317330f729Sjoerg   std::string Proto;
6327330f729Sjoerg 
6337330f729Sjoerg   if (Policy.FullyQualifiedName) {
6347330f729Sjoerg     Proto += D->getQualifiedNameAsString();
6357330f729Sjoerg   } else {
636*e038c9c4Sjoerg     llvm::raw_string_ostream OS(Proto);
6377330f729Sjoerg     if (!Policy.SuppressScope) {
6387330f729Sjoerg       if (const NestedNameSpecifier *NS = D->getQualifier()) {
6397330f729Sjoerg         NS->print(OS, Policy);
6407330f729Sjoerg       }
6417330f729Sjoerg     }
642*e038c9c4Sjoerg     D->getNameInfo().printName(OS, Policy);
6437330f729Sjoerg   }
6447330f729Sjoerg 
6457330f729Sjoerg   if (GuideDecl)
6467330f729Sjoerg     Proto = GuideDecl->getDeducedTemplate()->getDeclName().getAsString();
647*e038c9c4Sjoerg   if (D->isFunctionTemplateSpecialization()) {
6487330f729Sjoerg     llvm::raw_string_ostream POut(Proto);
6497330f729Sjoerg     DeclPrinter TArgPrinter(POut, SubPolicy, Context, Indentation);
650*e038c9c4Sjoerg     const auto *TArgAsWritten = D->getTemplateSpecializationArgsAsWritten();
651*e038c9c4Sjoerg     const TemplateParameterList *TPL = D->getTemplateSpecializationInfo()
652*e038c9c4Sjoerg                                            ->getTemplate()
653*e038c9c4Sjoerg                                            ->getTemplateParameters();
654*e038c9c4Sjoerg     if (TArgAsWritten && !Policy.PrintCanonicalTypes)
655*e038c9c4Sjoerg       TArgPrinter.printTemplateArguments(TArgAsWritten->arguments(), TPL,
656*e038c9c4Sjoerg                                          /*TemplOverloaded*/ true);
657*e038c9c4Sjoerg     else if (const TemplateArgumentList *TArgs =
658*e038c9c4Sjoerg                  D->getTemplateSpecializationArgs())
659*e038c9c4Sjoerg       TArgPrinter.printTemplateArguments(TArgs->asArray(), TPL,
660*e038c9c4Sjoerg                                          /*TemplOverloaded*/ true);
6617330f729Sjoerg   }
6627330f729Sjoerg 
6637330f729Sjoerg   QualType Ty = D->getType();
6647330f729Sjoerg   while (const ParenType *PT = dyn_cast<ParenType>(Ty)) {
6657330f729Sjoerg     Proto = '(' + Proto + ')';
6667330f729Sjoerg     Ty = PT->getInnerType();
6677330f729Sjoerg   }
6687330f729Sjoerg 
6697330f729Sjoerg   if (const FunctionType *AFT = Ty->getAs<FunctionType>()) {
6707330f729Sjoerg     const FunctionProtoType *FT = nullptr;
6717330f729Sjoerg     if (D->hasWrittenPrototype())
6727330f729Sjoerg       FT = dyn_cast<FunctionProtoType>(AFT);
6737330f729Sjoerg 
6747330f729Sjoerg     Proto += "(";
6757330f729Sjoerg     if (FT) {
6767330f729Sjoerg       llvm::raw_string_ostream POut(Proto);
6777330f729Sjoerg       DeclPrinter ParamPrinter(POut, SubPolicy, Context, Indentation);
6787330f729Sjoerg       for (unsigned i = 0, e = D->getNumParams(); i != e; ++i) {
6797330f729Sjoerg         if (i) POut << ", ";
6807330f729Sjoerg         ParamPrinter.VisitParmVarDecl(D->getParamDecl(i));
6817330f729Sjoerg       }
6827330f729Sjoerg 
6837330f729Sjoerg       if (FT->isVariadic()) {
6847330f729Sjoerg         if (D->getNumParams()) POut << ", ";
6857330f729Sjoerg         POut << "...";
6867330f729Sjoerg       }
6877330f729Sjoerg     } else if (D->doesThisDeclarationHaveABody() && !D->hasPrototype()) {
6887330f729Sjoerg       for (unsigned i = 0, e = D->getNumParams(); i != e; ++i) {
6897330f729Sjoerg         if (i)
6907330f729Sjoerg           Proto += ", ";
6917330f729Sjoerg         Proto += D->getParamDecl(i)->getNameAsString();
6927330f729Sjoerg       }
6937330f729Sjoerg     }
6947330f729Sjoerg 
6957330f729Sjoerg     Proto += ")";
6967330f729Sjoerg 
6977330f729Sjoerg     if (FT) {
6987330f729Sjoerg       if (FT->isConst())
6997330f729Sjoerg         Proto += " const";
7007330f729Sjoerg       if (FT->isVolatile())
7017330f729Sjoerg         Proto += " volatile";
7027330f729Sjoerg       if (FT->isRestrict())
7037330f729Sjoerg         Proto += " restrict";
7047330f729Sjoerg 
7057330f729Sjoerg       switch (FT->getRefQualifier()) {
7067330f729Sjoerg       case RQ_None:
7077330f729Sjoerg         break;
7087330f729Sjoerg       case RQ_LValue:
7097330f729Sjoerg         Proto += " &";
7107330f729Sjoerg         break;
7117330f729Sjoerg       case RQ_RValue:
7127330f729Sjoerg         Proto += " &&";
7137330f729Sjoerg         break;
7147330f729Sjoerg       }
7157330f729Sjoerg     }
7167330f729Sjoerg 
7177330f729Sjoerg     if (FT && FT->hasDynamicExceptionSpec()) {
7187330f729Sjoerg       Proto += " throw(";
7197330f729Sjoerg       if (FT->getExceptionSpecType() == EST_MSAny)
7207330f729Sjoerg         Proto += "...";
7217330f729Sjoerg       else
7227330f729Sjoerg         for (unsigned I = 0, N = FT->getNumExceptions(); I != N; ++I) {
7237330f729Sjoerg           if (I)
7247330f729Sjoerg             Proto += ", ";
7257330f729Sjoerg 
7267330f729Sjoerg           Proto += FT->getExceptionType(I).getAsString(SubPolicy);
7277330f729Sjoerg         }
7287330f729Sjoerg       Proto += ")";
7297330f729Sjoerg     } else if (FT && isNoexceptExceptionSpec(FT->getExceptionSpecType())) {
7307330f729Sjoerg       Proto += " noexcept";
7317330f729Sjoerg       if (isComputedNoexcept(FT->getExceptionSpecType())) {
7327330f729Sjoerg         Proto += "(";
7337330f729Sjoerg         llvm::raw_string_ostream EOut(Proto);
7347330f729Sjoerg         FT->getNoexceptExpr()->printPretty(EOut, nullptr, SubPolicy,
735*e038c9c4Sjoerg                                            Indentation, "\n", &Context);
7367330f729Sjoerg         EOut.flush();
7377330f729Sjoerg         Proto += EOut.str();
7387330f729Sjoerg         Proto += ")";
7397330f729Sjoerg       }
7407330f729Sjoerg     }
7417330f729Sjoerg 
7427330f729Sjoerg     if (CDecl) {
7437330f729Sjoerg       if (!Policy.TerseOutput)
7447330f729Sjoerg         PrintConstructorInitializers(CDecl, Proto);
7457330f729Sjoerg     } else if (!ConversionDecl && !isa<CXXDestructorDecl>(D)) {
7467330f729Sjoerg       if (FT && FT->hasTrailingReturn()) {
7477330f729Sjoerg         if (!GuideDecl)
7487330f729Sjoerg           Out << "auto ";
7497330f729Sjoerg         Out << Proto << " -> ";
7507330f729Sjoerg         Proto.clear();
7517330f729Sjoerg       }
7527330f729Sjoerg       AFT->getReturnType().print(Out, Policy, Proto);
7537330f729Sjoerg       Proto.clear();
7547330f729Sjoerg     }
7557330f729Sjoerg     Out << Proto;
756*e038c9c4Sjoerg 
757*e038c9c4Sjoerg     if (Expr *TrailingRequiresClause = D->getTrailingRequiresClause()) {
758*e038c9c4Sjoerg       Out << " requires ";
759*e038c9c4Sjoerg       TrailingRequiresClause->printPretty(Out, nullptr, SubPolicy, Indentation,
760*e038c9c4Sjoerg                                           "\n", &Context);
761*e038c9c4Sjoerg     }
7627330f729Sjoerg   } else {
7637330f729Sjoerg     Ty.print(Out, Policy, Proto);
7647330f729Sjoerg   }
7657330f729Sjoerg 
7667330f729Sjoerg   prettyPrintAttributes(D);
7677330f729Sjoerg 
7687330f729Sjoerg   if (D->isPure())
7697330f729Sjoerg     Out << " = 0";
7707330f729Sjoerg   else if (D->isDeletedAsWritten())
7717330f729Sjoerg     Out << " = delete";
7727330f729Sjoerg   else if (D->isExplicitlyDefaulted())
7737330f729Sjoerg     Out << " = default";
7747330f729Sjoerg   else if (D->doesThisDeclarationHaveABody()) {
7757330f729Sjoerg     if (!Policy.TerseOutput) {
7767330f729Sjoerg       if (!D->hasPrototype() && D->getNumParams()) {
7777330f729Sjoerg         // This is a K&R function definition, so we need to print the
7787330f729Sjoerg         // parameters.
7797330f729Sjoerg         Out << '\n';
7807330f729Sjoerg         DeclPrinter ParamPrinter(Out, SubPolicy, Context, Indentation);
7817330f729Sjoerg         Indentation += Policy.Indentation;
7827330f729Sjoerg         for (unsigned i = 0, e = D->getNumParams(); i != e; ++i) {
7837330f729Sjoerg           Indent();
7847330f729Sjoerg           ParamPrinter.VisitParmVarDecl(D->getParamDecl(i));
7857330f729Sjoerg           Out << ";\n";
7867330f729Sjoerg         }
7877330f729Sjoerg         Indentation -= Policy.Indentation;
7887330f729Sjoerg       } else
7897330f729Sjoerg         Out << ' ';
7907330f729Sjoerg 
7917330f729Sjoerg       if (D->getBody())
792*e038c9c4Sjoerg         D->getBody()->printPretty(Out, nullptr, SubPolicy, Indentation, "\n",
793*e038c9c4Sjoerg                                   &Context);
7947330f729Sjoerg     } else {
7957330f729Sjoerg       if (!Policy.TerseOutput && isa<CXXConstructorDecl>(*D))
7967330f729Sjoerg         Out << " {}";
7977330f729Sjoerg     }
7987330f729Sjoerg   }
7997330f729Sjoerg }
8007330f729Sjoerg 
VisitFriendDecl(FriendDecl * D)8017330f729Sjoerg void DeclPrinter::VisitFriendDecl(FriendDecl *D) {
8027330f729Sjoerg   if (TypeSourceInfo *TSI = D->getFriendType()) {
8037330f729Sjoerg     unsigned NumTPLists = D->getFriendTypeNumTemplateParameterLists();
8047330f729Sjoerg     for (unsigned i = 0; i < NumTPLists; ++i)
8057330f729Sjoerg       printTemplateParameters(D->getFriendTypeTemplateParameterList(i));
8067330f729Sjoerg     Out << "friend ";
8077330f729Sjoerg     Out << " " << TSI->getType().getAsString(Policy);
8087330f729Sjoerg   }
8097330f729Sjoerg   else if (FunctionDecl *FD =
8107330f729Sjoerg       dyn_cast<FunctionDecl>(D->getFriendDecl())) {
8117330f729Sjoerg     Out << "friend ";
8127330f729Sjoerg     VisitFunctionDecl(FD);
8137330f729Sjoerg   }
8147330f729Sjoerg   else if (FunctionTemplateDecl *FTD =
8157330f729Sjoerg            dyn_cast<FunctionTemplateDecl>(D->getFriendDecl())) {
8167330f729Sjoerg     Out << "friend ";
8177330f729Sjoerg     VisitFunctionTemplateDecl(FTD);
8187330f729Sjoerg   }
8197330f729Sjoerg   else if (ClassTemplateDecl *CTD =
8207330f729Sjoerg            dyn_cast<ClassTemplateDecl>(D->getFriendDecl())) {
8217330f729Sjoerg     Out << "friend ";
8227330f729Sjoerg     VisitRedeclarableTemplateDecl(CTD);
8237330f729Sjoerg   }
8247330f729Sjoerg }
8257330f729Sjoerg 
VisitFieldDecl(FieldDecl * D)8267330f729Sjoerg void DeclPrinter::VisitFieldDecl(FieldDecl *D) {
8277330f729Sjoerg   // FIXME: add printing of pragma attributes if required.
8287330f729Sjoerg   if (!Policy.SuppressSpecifiers && D->isMutable())
8297330f729Sjoerg     Out << "mutable ";
8307330f729Sjoerg   if (!Policy.SuppressSpecifiers && D->isModulePrivate())
8317330f729Sjoerg     Out << "__module_private__ ";
8327330f729Sjoerg 
8337330f729Sjoerg   Out << D->getASTContext().getUnqualifiedObjCPointerType(D->getType()).
8347330f729Sjoerg          stream(Policy, D->getName(), Indentation);
8357330f729Sjoerg 
8367330f729Sjoerg   if (D->isBitField()) {
8377330f729Sjoerg     Out << " : ";
838*e038c9c4Sjoerg     D->getBitWidth()->printPretty(Out, nullptr, Policy, Indentation, "\n",
839*e038c9c4Sjoerg                                   &Context);
8407330f729Sjoerg   }
8417330f729Sjoerg 
8427330f729Sjoerg   Expr *Init = D->getInClassInitializer();
8437330f729Sjoerg   if (!Policy.SuppressInitializers && Init) {
8447330f729Sjoerg     if (D->getInClassInitStyle() == ICIS_ListInit)
8457330f729Sjoerg       Out << " ";
8467330f729Sjoerg     else
8477330f729Sjoerg       Out << " = ";
848*e038c9c4Sjoerg     Init->printPretty(Out, nullptr, Policy, Indentation, "\n", &Context);
8497330f729Sjoerg   }
8507330f729Sjoerg   prettyPrintAttributes(D);
8517330f729Sjoerg }
8527330f729Sjoerg 
VisitLabelDecl(LabelDecl * D)8537330f729Sjoerg void DeclPrinter::VisitLabelDecl(LabelDecl *D) {
8547330f729Sjoerg   Out << *D << ":";
8557330f729Sjoerg }
8567330f729Sjoerg 
VisitVarDecl(VarDecl * D)8577330f729Sjoerg void DeclPrinter::VisitVarDecl(VarDecl *D) {
8587330f729Sjoerg   prettyPrintPragmas(D);
8597330f729Sjoerg 
8607330f729Sjoerg   QualType T = D->getTypeSourceInfo()
8617330f729Sjoerg     ? D->getTypeSourceInfo()->getType()
8627330f729Sjoerg     : D->getASTContext().getUnqualifiedObjCPointerType(D->getType());
8637330f729Sjoerg 
8647330f729Sjoerg   if (!Policy.SuppressSpecifiers) {
8657330f729Sjoerg     StorageClass SC = D->getStorageClass();
8667330f729Sjoerg     if (SC != SC_None)
8677330f729Sjoerg       Out << VarDecl::getStorageClassSpecifierString(SC) << " ";
8687330f729Sjoerg 
8697330f729Sjoerg     switch (D->getTSCSpec()) {
8707330f729Sjoerg     case TSCS_unspecified:
8717330f729Sjoerg       break;
8727330f729Sjoerg     case TSCS___thread:
8737330f729Sjoerg       Out << "__thread ";
8747330f729Sjoerg       break;
8757330f729Sjoerg     case TSCS__Thread_local:
8767330f729Sjoerg       Out << "_Thread_local ";
8777330f729Sjoerg       break;
8787330f729Sjoerg     case TSCS_thread_local:
8797330f729Sjoerg       Out << "thread_local ";
8807330f729Sjoerg       break;
8817330f729Sjoerg     }
8827330f729Sjoerg 
8837330f729Sjoerg     if (D->isModulePrivate())
8847330f729Sjoerg       Out << "__module_private__ ";
8857330f729Sjoerg 
8867330f729Sjoerg     if (D->isConstexpr()) {
8877330f729Sjoerg       Out << "constexpr ";
8887330f729Sjoerg       T.removeLocalConst();
8897330f729Sjoerg     }
8907330f729Sjoerg   }
8917330f729Sjoerg 
8927330f729Sjoerg   printDeclType(T, D->getName());
8937330f729Sjoerg   Expr *Init = D->getInit();
8947330f729Sjoerg   if (!Policy.SuppressInitializers && Init) {
8957330f729Sjoerg     bool ImplicitInit = false;
8967330f729Sjoerg     if (CXXConstructExpr *Construct =
8977330f729Sjoerg             dyn_cast<CXXConstructExpr>(Init->IgnoreImplicit())) {
8987330f729Sjoerg       if (D->getInitStyle() == VarDecl::CallInit &&
8997330f729Sjoerg           !Construct->isListInitialization()) {
9007330f729Sjoerg         ImplicitInit = Construct->getNumArgs() == 0 ||
9017330f729Sjoerg           Construct->getArg(0)->isDefaultArgument();
9027330f729Sjoerg       }
9037330f729Sjoerg     }
9047330f729Sjoerg     if (!ImplicitInit) {
9057330f729Sjoerg       if ((D->getInitStyle() == VarDecl::CallInit) && !isa<ParenListExpr>(Init))
9067330f729Sjoerg         Out << "(";
9077330f729Sjoerg       else if (D->getInitStyle() == VarDecl::CInit) {
9087330f729Sjoerg         Out << " = ";
9097330f729Sjoerg       }
9107330f729Sjoerg       PrintingPolicy SubPolicy(Policy);
9117330f729Sjoerg       SubPolicy.SuppressSpecifiers = false;
9127330f729Sjoerg       SubPolicy.IncludeTagDefinition = false;
913*e038c9c4Sjoerg       Init->printPretty(Out, nullptr, SubPolicy, Indentation, "\n", &Context);
9147330f729Sjoerg       if ((D->getInitStyle() == VarDecl::CallInit) && !isa<ParenListExpr>(Init))
9157330f729Sjoerg         Out << ")";
9167330f729Sjoerg     }
9177330f729Sjoerg   }
9187330f729Sjoerg   prettyPrintAttributes(D);
9197330f729Sjoerg }
9207330f729Sjoerg 
VisitParmVarDecl(ParmVarDecl * D)9217330f729Sjoerg void DeclPrinter::VisitParmVarDecl(ParmVarDecl *D) {
9227330f729Sjoerg   VisitVarDecl(D);
9237330f729Sjoerg }
9247330f729Sjoerg 
VisitFileScopeAsmDecl(FileScopeAsmDecl * D)9257330f729Sjoerg void DeclPrinter::VisitFileScopeAsmDecl(FileScopeAsmDecl *D) {
9267330f729Sjoerg   Out << "__asm (";
927*e038c9c4Sjoerg   D->getAsmString()->printPretty(Out, nullptr, Policy, Indentation, "\n",
928*e038c9c4Sjoerg                                  &Context);
9297330f729Sjoerg   Out << ")";
9307330f729Sjoerg }
9317330f729Sjoerg 
VisitImportDecl(ImportDecl * D)9327330f729Sjoerg void DeclPrinter::VisitImportDecl(ImportDecl *D) {
9337330f729Sjoerg   Out << "@import " << D->getImportedModule()->getFullModuleName()
9347330f729Sjoerg       << ";\n";
9357330f729Sjoerg }
9367330f729Sjoerg 
VisitStaticAssertDecl(StaticAssertDecl * D)9377330f729Sjoerg void DeclPrinter::VisitStaticAssertDecl(StaticAssertDecl *D) {
9387330f729Sjoerg   Out << "static_assert(";
939*e038c9c4Sjoerg   D->getAssertExpr()->printPretty(Out, nullptr, Policy, Indentation, "\n",
940*e038c9c4Sjoerg                                   &Context);
9417330f729Sjoerg   if (StringLiteral *SL = D->getMessage()) {
9427330f729Sjoerg     Out << ", ";
943*e038c9c4Sjoerg     SL->printPretty(Out, nullptr, Policy, Indentation, "\n", &Context);
9447330f729Sjoerg   }
9457330f729Sjoerg   Out << ")";
9467330f729Sjoerg }
9477330f729Sjoerg 
9487330f729Sjoerg //----------------------------------------------------------------------------
9497330f729Sjoerg // C++ declarations
9507330f729Sjoerg //----------------------------------------------------------------------------
VisitNamespaceDecl(NamespaceDecl * D)9517330f729Sjoerg void DeclPrinter::VisitNamespaceDecl(NamespaceDecl *D) {
9527330f729Sjoerg   if (D->isInline())
9537330f729Sjoerg     Out << "inline ";
954*e038c9c4Sjoerg 
955*e038c9c4Sjoerg   Out << "namespace ";
956*e038c9c4Sjoerg   if (D->getDeclName())
957*e038c9c4Sjoerg     Out << D->getDeclName() << ' ';
958*e038c9c4Sjoerg   Out << "{\n";
959*e038c9c4Sjoerg 
9607330f729Sjoerg   VisitDeclContext(D);
9617330f729Sjoerg   Indent() << "}";
9627330f729Sjoerg }
9637330f729Sjoerg 
VisitUsingDirectiveDecl(UsingDirectiveDecl * D)9647330f729Sjoerg void DeclPrinter::VisitUsingDirectiveDecl(UsingDirectiveDecl *D) {
9657330f729Sjoerg   Out << "using namespace ";
9667330f729Sjoerg   if (D->getQualifier())
9677330f729Sjoerg     D->getQualifier()->print(Out, Policy);
9687330f729Sjoerg   Out << *D->getNominatedNamespaceAsWritten();
9697330f729Sjoerg }
9707330f729Sjoerg 
VisitNamespaceAliasDecl(NamespaceAliasDecl * D)9717330f729Sjoerg void DeclPrinter::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) {
9727330f729Sjoerg   Out << "namespace " << *D << " = ";
9737330f729Sjoerg   if (D->getQualifier())
9747330f729Sjoerg     D->getQualifier()->print(Out, Policy);
9757330f729Sjoerg   Out << *D->getAliasedNamespace();
9767330f729Sjoerg }
9777330f729Sjoerg 
VisitEmptyDecl(EmptyDecl * D)9787330f729Sjoerg void DeclPrinter::VisitEmptyDecl(EmptyDecl *D) {
9797330f729Sjoerg   prettyPrintAttributes(D);
9807330f729Sjoerg }
9817330f729Sjoerg 
VisitCXXRecordDecl(CXXRecordDecl * D)9827330f729Sjoerg void DeclPrinter::VisitCXXRecordDecl(CXXRecordDecl *D) {
9837330f729Sjoerg   // FIXME: add printing of pragma attributes if required.
9847330f729Sjoerg   if (!Policy.SuppressSpecifiers && D->isModulePrivate())
9857330f729Sjoerg     Out << "__module_private__ ";
9867330f729Sjoerg   Out << D->getKindName();
9877330f729Sjoerg 
9887330f729Sjoerg   prettyPrintAttributes(D);
9897330f729Sjoerg 
9907330f729Sjoerg   if (D->getIdentifier()) {
9917330f729Sjoerg     Out << ' ' << *D;
9927330f729Sjoerg 
993*e038c9c4Sjoerg     if (auto S = dyn_cast<ClassTemplateSpecializationDecl>(D)) {
994*e038c9c4Sjoerg       ArrayRef<TemplateArgument> Args = S->getTemplateArgs().asArray();
995*e038c9c4Sjoerg       if (!Policy.PrintCanonicalTypes)
996*e038c9c4Sjoerg         if (const auto* TSI = S->getTypeAsWritten())
997*e038c9c4Sjoerg           if (const auto *TST =
998*e038c9c4Sjoerg                   dyn_cast<TemplateSpecializationType>(TSI->getType()))
999*e038c9c4Sjoerg             Args = TST->template_arguments();
1000*e038c9c4Sjoerg       printTemplateArguments(
1001*e038c9c4Sjoerg           Args, S->getSpecializedTemplate()->getTemplateParameters(),
1002*e038c9c4Sjoerg           /*TemplOverloaded*/ false);
1003*e038c9c4Sjoerg     }
10047330f729Sjoerg   }
10057330f729Sjoerg 
10067330f729Sjoerg   if (D->isCompleteDefinition()) {
10077330f729Sjoerg     // Print the base classes
10087330f729Sjoerg     if (D->getNumBases()) {
10097330f729Sjoerg       Out << " : ";
10107330f729Sjoerg       for (CXXRecordDecl::base_class_iterator Base = D->bases_begin(),
10117330f729Sjoerg              BaseEnd = D->bases_end(); Base != BaseEnd; ++Base) {
10127330f729Sjoerg         if (Base != D->bases_begin())
10137330f729Sjoerg           Out << ", ";
10147330f729Sjoerg 
10157330f729Sjoerg         if (Base->isVirtual())
10167330f729Sjoerg           Out << "virtual ";
10177330f729Sjoerg 
10187330f729Sjoerg         AccessSpecifier AS = Base->getAccessSpecifierAsWritten();
10197330f729Sjoerg         if (AS != AS_none) {
10207330f729Sjoerg           Print(AS);
10217330f729Sjoerg           Out << " ";
10227330f729Sjoerg         }
10237330f729Sjoerg         Out << Base->getType().getAsString(Policy);
10247330f729Sjoerg 
10257330f729Sjoerg         if (Base->isPackExpansion())
10267330f729Sjoerg           Out << "...";
10277330f729Sjoerg       }
10287330f729Sjoerg     }
10297330f729Sjoerg 
10307330f729Sjoerg     // Print the class definition
10317330f729Sjoerg     // FIXME: Doesn't print access specifiers, e.g., "public:"
10327330f729Sjoerg     if (Policy.TerseOutput) {
10337330f729Sjoerg       Out << " {}";
10347330f729Sjoerg     } else {
10357330f729Sjoerg       Out << " {\n";
10367330f729Sjoerg       VisitDeclContext(D);
10377330f729Sjoerg       Indent() << "}";
10387330f729Sjoerg     }
10397330f729Sjoerg   }
10407330f729Sjoerg }
10417330f729Sjoerg 
VisitLinkageSpecDecl(LinkageSpecDecl * D)10427330f729Sjoerg void DeclPrinter::VisitLinkageSpecDecl(LinkageSpecDecl *D) {
10437330f729Sjoerg   const char *l;
1044*e038c9c4Sjoerg   if (D->getLanguage() == LinkageSpecDecl::lang_c)
10457330f729Sjoerg     l = "C";
1046*e038c9c4Sjoerg   else {
1047*e038c9c4Sjoerg     assert(D->getLanguage() == LinkageSpecDecl::lang_cxx &&
1048*e038c9c4Sjoerg            "unknown language in linkage specification");
10497330f729Sjoerg     l = "C++";
10507330f729Sjoerg   }
10517330f729Sjoerg 
10527330f729Sjoerg   Out << "extern \"" << l << "\" ";
10537330f729Sjoerg   if (D->hasBraces()) {
10547330f729Sjoerg     Out << "{\n";
10557330f729Sjoerg     VisitDeclContext(D);
10567330f729Sjoerg     Indent() << "}";
10577330f729Sjoerg   } else
10587330f729Sjoerg     Visit(*D->decls_begin());
10597330f729Sjoerg }
10607330f729Sjoerg 
printTemplateParameters(const TemplateParameterList * Params,bool OmitTemplateKW)10617330f729Sjoerg void DeclPrinter::printTemplateParameters(const TemplateParameterList *Params,
10627330f729Sjoerg                                           bool OmitTemplateKW) {
10637330f729Sjoerg   assert(Params);
10647330f729Sjoerg 
10657330f729Sjoerg   if (!OmitTemplateKW)
10667330f729Sjoerg     Out << "template ";
10677330f729Sjoerg   Out << '<';
10687330f729Sjoerg 
10697330f729Sjoerg   bool NeedComma = false;
10707330f729Sjoerg   for (const Decl *Param : *Params) {
10717330f729Sjoerg     if (Param->isImplicit())
10727330f729Sjoerg       continue;
10737330f729Sjoerg 
10747330f729Sjoerg     if (NeedComma)
10757330f729Sjoerg       Out << ", ";
10767330f729Sjoerg     else
10777330f729Sjoerg       NeedComma = true;
10787330f729Sjoerg 
1079*e038c9c4Sjoerg     if (const auto *TTP = dyn_cast<TemplateTypeParmDecl>(Param)) {
1080*e038c9c4Sjoerg       VisitTemplateTypeParmDecl(TTP);
10817330f729Sjoerg     } else if (auto NTTP = dyn_cast<NonTypeTemplateParmDecl>(Param)) {
1082*e038c9c4Sjoerg       VisitNonTypeTemplateParmDecl(NTTP);
10837330f729Sjoerg     } else if (auto TTPD = dyn_cast<TemplateTemplateParmDecl>(Param)) {
10847330f729Sjoerg       VisitTemplateDecl(TTPD);
10857330f729Sjoerg       // FIXME: print the default argument, if present.
10867330f729Sjoerg     }
10877330f729Sjoerg   }
10887330f729Sjoerg 
10897330f729Sjoerg   Out << '>';
10907330f729Sjoerg   if (!OmitTemplateKW)
10917330f729Sjoerg     Out << ' ';
10927330f729Sjoerg }
10937330f729Sjoerg 
printTemplateArguments(ArrayRef<TemplateArgument> Args,const TemplateParameterList * Params,bool TemplOverloaded)1094*e038c9c4Sjoerg void DeclPrinter::printTemplateArguments(ArrayRef<TemplateArgument> Args,
1095*e038c9c4Sjoerg                                          const TemplateParameterList *Params,
1096*e038c9c4Sjoerg                                          bool TemplOverloaded) {
10977330f729Sjoerg   Out << "<";
10987330f729Sjoerg   for (size_t I = 0, E = Args.size(); I < E; ++I) {
10997330f729Sjoerg     if (I)
11007330f729Sjoerg       Out << ", ";
1101*e038c9c4Sjoerg     if (TemplOverloaded || !Params)
1102*e038c9c4Sjoerg       Args[I].print(Policy, Out, /*IncludeType*/ true);
1103*e038c9c4Sjoerg     else
1104*e038c9c4Sjoerg       Args[I].print(
1105*e038c9c4Sjoerg           Policy, Out,
1106*e038c9c4Sjoerg           TemplateParameterList::shouldIncludeTypeForArgument(Params, I));
11077330f729Sjoerg   }
1108*e038c9c4Sjoerg   Out << ">";
11097330f729Sjoerg }
1110*e038c9c4Sjoerg 
printTemplateArguments(ArrayRef<TemplateArgumentLoc> Args,const TemplateParameterList * Params,bool TemplOverloaded)1111*e038c9c4Sjoerg void DeclPrinter::printTemplateArguments(ArrayRef<TemplateArgumentLoc> Args,
1112*e038c9c4Sjoerg                                          const TemplateParameterList *Params,
1113*e038c9c4Sjoerg                                          bool TemplOverloaded) {
1114*e038c9c4Sjoerg   Out << "<";
1115*e038c9c4Sjoerg   for (size_t I = 0, E = Args.size(); I < E; ++I) {
1116*e038c9c4Sjoerg     if (I)
1117*e038c9c4Sjoerg       Out << ", ";
1118*e038c9c4Sjoerg     if (TemplOverloaded)
1119*e038c9c4Sjoerg       Args[I].getArgument().print(Policy, Out, /*IncludeType*/ true);
1120*e038c9c4Sjoerg     else
1121*e038c9c4Sjoerg       Args[I].getArgument().print(
1122*e038c9c4Sjoerg           Policy, Out,
1123*e038c9c4Sjoerg           TemplateParameterList::shouldIncludeTypeForArgument(Params, I));
11247330f729Sjoerg   }
11257330f729Sjoerg   Out << ">";
11267330f729Sjoerg }
11277330f729Sjoerg 
VisitTemplateDecl(const TemplateDecl * D)11287330f729Sjoerg void DeclPrinter::VisitTemplateDecl(const TemplateDecl *D) {
11297330f729Sjoerg   printTemplateParameters(D->getTemplateParameters());
11307330f729Sjoerg 
11317330f729Sjoerg   if (const TemplateTemplateParmDecl *TTP =
11327330f729Sjoerg         dyn_cast<TemplateTemplateParmDecl>(D)) {
11337330f729Sjoerg     Out << "class";
1134*e038c9c4Sjoerg 
11357330f729Sjoerg     if (TTP->isParameterPack())
11367330f729Sjoerg       Out << " ...";
1137*e038c9c4Sjoerg     else if (TTP->getDeclName())
1138*e038c9c4Sjoerg       Out << ' ';
1139*e038c9c4Sjoerg 
1140*e038c9c4Sjoerg     if (TTP->getDeclName())
1141*e038c9c4Sjoerg       Out << TTP->getDeclName();
11427330f729Sjoerg   } else if (auto *TD = D->getTemplatedDecl())
11437330f729Sjoerg     Visit(TD);
11447330f729Sjoerg   else if (const auto *Concept = dyn_cast<ConceptDecl>(D)) {
11457330f729Sjoerg     Out << "concept " << Concept->getName() << " = " ;
1146*e038c9c4Sjoerg     Concept->getConstraintExpr()->printPretty(Out, nullptr, Policy, Indentation,
1147*e038c9c4Sjoerg                                               "\n", &Context);
11487330f729Sjoerg     Out << ";";
11497330f729Sjoerg   }
11507330f729Sjoerg }
11517330f729Sjoerg 
VisitFunctionTemplateDecl(FunctionTemplateDecl * D)11527330f729Sjoerg void DeclPrinter::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
11537330f729Sjoerg   prettyPrintPragmas(D->getTemplatedDecl());
11547330f729Sjoerg   // Print any leading template parameter lists.
11557330f729Sjoerg   if (const FunctionDecl *FD = D->getTemplatedDecl()) {
11567330f729Sjoerg     for (unsigned I = 0, NumTemplateParams = FD->getNumTemplateParameterLists();
11577330f729Sjoerg          I < NumTemplateParams; ++I)
11587330f729Sjoerg       printTemplateParameters(FD->getTemplateParameterList(I));
11597330f729Sjoerg   }
11607330f729Sjoerg   VisitRedeclarableTemplateDecl(D);
11617330f729Sjoerg   // Declare target attribute is special one, natural spelling for the pragma
11627330f729Sjoerg   // assumes "ending" construct so print it here.
11637330f729Sjoerg   if (D->getTemplatedDecl()->hasAttr<OMPDeclareTargetDeclAttr>())
11647330f729Sjoerg     Out << "#pragma omp end declare target\n";
11657330f729Sjoerg 
11667330f729Sjoerg   // Never print "instantiations" for deduction guides (they don't really
11677330f729Sjoerg   // have them).
11687330f729Sjoerg   if (PrintInstantiation &&
11697330f729Sjoerg       !isa<CXXDeductionGuideDecl>(D->getTemplatedDecl())) {
11707330f729Sjoerg     FunctionDecl *PrevDecl = D->getTemplatedDecl();
11717330f729Sjoerg     const FunctionDecl *Def;
11727330f729Sjoerg     if (PrevDecl->isDefined(Def) && Def != PrevDecl)
11737330f729Sjoerg       return;
11747330f729Sjoerg     for (auto *I : D->specializations())
11757330f729Sjoerg       if (I->getTemplateSpecializationKind() == TSK_ImplicitInstantiation) {
11767330f729Sjoerg         if (!PrevDecl->isThisDeclarationADefinition())
11777330f729Sjoerg           Out << ";\n";
11787330f729Sjoerg         Indent();
11797330f729Sjoerg         prettyPrintPragmas(I);
11807330f729Sjoerg         Visit(I);
11817330f729Sjoerg       }
11827330f729Sjoerg   }
11837330f729Sjoerg }
11847330f729Sjoerg 
VisitClassTemplateDecl(ClassTemplateDecl * D)11857330f729Sjoerg void DeclPrinter::VisitClassTemplateDecl(ClassTemplateDecl *D) {
11867330f729Sjoerg   VisitRedeclarableTemplateDecl(D);
11877330f729Sjoerg 
11887330f729Sjoerg   if (PrintInstantiation) {
11897330f729Sjoerg     for (auto *I : D->specializations())
11907330f729Sjoerg       if (I->getSpecializationKind() == TSK_ImplicitInstantiation) {
11917330f729Sjoerg         if (D->isThisDeclarationADefinition())
11927330f729Sjoerg           Out << ";";
11937330f729Sjoerg         Out << "\n";
11947330f729Sjoerg         Visit(I);
11957330f729Sjoerg       }
11967330f729Sjoerg   }
11977330f729Sjoerg }
11987330f729Sjoerg 
VisitClassTemplateSpecializationDecl(ClassTemplateSpecializationDecl * D)11997330f729Sjoerg void DeclPrinter::VisitClassTemplateSpecializationDecl(
12007330f729Sjoerg                                            ClassTemplateSpecializationDecl *D) {
12017330f729Sjoerg   Out << "template<> ";
12027330f729Sjoerg   VisitCXXRecordDecl(D);
12037330f729Sjoerg }
12047330f729Sjoerg 
VisitClassTemplatePartialSpecializationDecl(ClassTemplatePartialSpecializationDecl * D)12057330f729Sjoerg void DeclPrinter::VisitClassTemplatePartialSpecializationDecl(
12067330f729Sjoerg                                     ClassTemplatePartialSpecializationDecl *D) {
12077330f729Sjoerg   printTemplateParameters(D->getTemplateParameters());
12087330f729Sjoerg   VisitCXXRecordDecl(D);
12097330f729Sjoerg }
12107330f729Sjoerg 
12117330f729Sjoerg //----------------------------------------------------------------------------
12127330f729Sjoerg // Objective-C declarations
12137330f729Sjoerg //----------------------------------------------------------------------------
12147330f729Sjoerg 
PrintObjCMethodType(ASTContext & Ctx,Decl::ObjCDeclQualifier Quals,QualType T)12157330f729Sjoerg void DeclPrinter::PrintObjCMethodType(ASTContext &Ctx,
12167330f729Sjoerg                                       Decl::ObjCDeclQualifier Quals,
12177330f729Sjoerg                                       QualType T) {
12187330f729Sjoerg   Out << '(';
12197330f729Sjoerg   if (Quals & Decl::ObjCDeclQualifier::OBJC_TQ_In)
12207330f729Sjoerg     Out << "in ";
12217330f729Sjoerg   if (Quals & Decl::ObjCDeclQualifier::OBJC_TQ_Inout)
12227330f729Sjoerg     Out << "inout ";
12237330f729Sjoerg   if (Quals & Decl::ObjCDeclQualifier::OBJC_TQ_Out)
12247330f729Sjoerg     Out << "out ";
12257330f729Sjoerg   if (Quals & Decl::ObjCDeclQualifier::OBJC_TQ_Bycopy)
12267330f729Sjoerg     Out << "bycopy ";
12277330f729Sjoerg   if (Quals & Decl::ObjCDeclQualifier::OBJC_TQ_Byref)
12287330f729Sjoerg     Out << "byref ";
12297330f729Sjoerg   if (Quals & Decl::ObjCDeclQualifier::OBJC_TQ_Oneway)
12307330f729Sjoerg     Out << "oneway ";
12317330f729Sjoerg   if (Quals & Decl::ObjCDeclQualifier::OBJC_TQ_CSNullability) {
12327330f729Sjoerg     if (auto nullability = AttributedType::stripOuterNullability(T))
12337330f729Sjoerg       Out << getNullabilitySpelling(*nullability, true) << ' ';
12347330f729Sjoerg   }
12357330f729Sjoerg 
12367330f729Sjoerg   Out << Ctx.getUnqualifiedObjCPointerType(T).getAsString(Policy);
12377330f729Sjoerg   Out << ')';
12387330f729Sjoerg }
12397330f729Sjoerg 
PrintObjCTypeParams(ObjCTypeParamList * Params)12407330f729Sjoerg void DeclPrinter::PrintObjCTypeParams(ObjCTypeParamList *Params) {
12417330f729Sjoerg   Out << "<";
12427330f729Sjoerg   unsigned First = true;
12437330f729Sjoerg   for (auto *Param : *Params) {
12447330f729Sjoerg     if (First) {
12457330f729Sjoerg       First = false;
12467330f729Sjoerg     } else {
12477330f729Sjoerg       Out << ", ";
12487330f729Sjoerg     }
12497330f729Sjoerg 
12507330f729Sjoerg     switch (Param->getVariance()) {
12517330f729Sjoerg     case ObjCTypeParamVariance::Invariant:
12527330f729Sjoerg       break;
12537330f729Sjoerg 
12547330f729Sjoerg     case ObjCTypeParamVariance::Covariant:
12557330f729Sjoerg       Out << "__covariant ";
12567330f729Sjoerg       break;
12577330f729Sjoerg 
12587330f729Sjoerg     case ObjCTypeParamVariance::Contravariant:
12597330f729Sjoerg       Out << "__contravariant ";
12607330f729Sjoerg       break;
12617330f729Sjoerg     }
12627330f729Sjoerg 
1263*e038c9c4Sjoerg     Out << Param->getDeclName();
12647330f729Sjoerg 
12657330f729Sjoerg     if (Param->hasExplicitBound()) {
12667330f729Sjoerg       Out << " : " << Param->getUnderlyingType().getAsString(Policy);
12677330f729Sjoerg     }
12687330f729Sjoerg   }
12697330f729Sjoerg   Out << ">";
12707330f729Sjoerg }
12717330f729Sjoerg 
VisitObjCMethodDecl(ObjCMethodDecl * OMD)12727330f729Sjoerg void DeclPrinter::VisitObjCMethodDecl(ObjCMethodDecl *OMD) {
12737330f729Sjoerg   if (OMD->isInstanceMethod())
12747330f729Sjoerg     Out << "- ";
12757330f729Sjoerg   else
12767330f729Sjoerg     Out << "+ ";
12777330f729Sjoerg   if (!OMD->getReturnType().isNull()) {
12787330f729Sjoerg     PrintObjCMethodType(OMD->getASTContext(), OMD->getObjCDeclQualifier(),
12797330f729Sjoerg                         OMD->getReturnType());
12807330f729Sjoerg   }
12817330f729Sjoerg 
12827330f729Sjoerg   std::string name = OMD->getSelector().getAsString();
12837330f729Sjoerg   std::string::size_type pos, lastPos = 0;
12847330f729Sjoerg   for (const auto *PI : OMD->parameters()) {
12857330f729Sjoerg     // FIXME: selector is missing here!
12867330f729Sjoerg     pos = name.find_first_of(':', lastPos);
12877330f729Sjoerg     if (lastPos != 0)
12887330f729Sjoerg       Out << " ";
12897330f729Sjoerg     Out << name.substr(lastPos, pos - lastPos) << ':';
12907330f729Sjoerg     PrintObjCMethodType(OMD->getASTContext(),
12917330f729Sjoerg                         PI->getObjCDeclQualifier(),
12927330f729Sjoerg                         PI->getType());
12937330f729Sjoerg     Out << *PI;
12947330f729Sjoerg     lastPos = pos + 1;
12957330f729Sjoerg   }
12967330f729Sjoerg 
12977330f729Sjoerg   if (OMD->param_begin() == OMD->param_end())
12987330f729Sjoerg     Out << name;
12997330f729Sjoerg 
13007330f729Sjoerg   if (OMD->isVariadic())
13017330f729Sjoerg       Out << ", ...";
13027330f729Sjoerg 
13037330f729Sjoerg   prettyPrintAttributes(OMD);
13047330f729Sjoerg 
13057330f729Sjoerg   if (OMD->getBody() && !Policy.TerseOutput) {
13067330f729Sjoerg     Out << ' ';
1307*e038c9c4Sjoerg     OMD->getBody()->printPretty(Out, nullptr, Policy, Indentation, "\n",
1308*e038c9c4Sjoerg                                 &Context);
13097330f729Sjoerg   }
13107330f729Sjoerg   else if (Policy.PolishForDeclaration)
13117330f729Sjoerg     Out << ';';
13127330f729Sjoerg }
13137330f729Sjoerg 
VisitObjCImplementationDecl(ObjCImplementationDecl * OID)13147330f729Sjoerg void DeclPrinter::VisitObjCImplementationDecl(ObjCImplementationDecl *OID) {
13157330f729Sjoerg   std::string I = OID->getNameAsString();
13167330f729Sjoerg   ObjCInterfaceDecl *SID = OID->getSuperClass();
13177330f729Sjoerg 
13187330f729Sjoerg   bool eolnOut = false;
13197330f729Sjoerg   if (SID)
13207330f729Sjoerg     Out << "@implementation " << I << " : " << *SID;
13217330f729Sjoerg   else
13227330f729Sjoerg     Out << "@implementation " << I;
13237330f729Sjoerg 
13247330f729Sjoerg   if (OID->ivar_size() > 0) {
13257330f729Sjoerg     Out << "{\n";
13267330f729Sjoerg     eolnOut = true;
13277330f729Sjoerg     Indentation += Policy.Indentation;
13287330f729Sjoerg     for (const auto *I : OID->ivars()) {
13297330f729Sjoerg       Indent() << I->getASTContext().getUnqualifiedObjCPointerType(I->getType()).
13307330f729Sjoerg                     getAsString(Policy) << ' ' << *I << ";\n";
13317330f729Sjoerg     }
13327330f729Sjoerg     Indentation -= Policy.Indentation;
13337330f729Sjoerg     Out << "}\n";
13347330f729Sjoerg   }
13357330f729Sjoerg   else if (SID || (OID->decls_begin() != OID->decls_end())) {
13367330f729Sjoerg     Out << "\n";
13377330f729Sjoerg     eolnOut = true;
13387330f729Sjoerg   }
13397330f729Sjoerg   VisitDeclContext(OID, false);
13407330f729Sjoerg   if (!eolnOut)
13417330f729Sjoerg     Out << "\n";
13427330f729Sjoerg   Out << "@end";
13437330f729Sjoerg }
13447330f729Sjoerg 
VisitObjCInterfaceDecl(ObjCInterfaceDecl * OID)13457330f729Sjoerg void DeclPrinter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *OID) {
13467330f729Sjoerg   std::string I = OID->getNameAsString();
13477330f729Sjoerg   ObjCInterfaceDecl *SID = OID->getSuperClass();
13487330f729Sjoerg 
13497330f729Sjoerg   if (!OID->isThisDeclarationADefinition()) {
13507330f729Sjoerg     Out << "@class " << I;
13517330f729Sjoerg 
13527330f729Sjoerg     if (auto TypeParams = OID->getTypeParamListAsWritten()) {
13537330f729Sjoerg       PrintObjCTypeParams(TypeParams);
13547330f729Sjoerg     }
13557330f729Sjoerg 
13567330f729Sjoerg     Out << ";";
13577330f729Sjoerg     return;
13587330f729Sjoerg   }
13597330f729Sjoerg   bool eolnOut = false;
13607330f729Sjoerg   Out << "@interface " << I;
13617330f729Sjoerg 
13627330f729Sjoerg   if (auto TypeParams = OID->getTypeParamListAsWritten()) {
13637330f729Sjoerg     PrintObjCTypeParams(TypeParams);
13647330f729Sjoerg   }
13657330f729Sjoerg 
13667330f729Sjoerg   if (SID)
13677330f729Sjoerg     Out << " : " << QualType(OID->getSuperClassType(), 0).getAsString(Policy);
13687330f729Sjoerg 
13697330f729Sjoerg   // Protocols?
13707330f729Sjoerg   const ObjCList<ObjCProtocolDecl> &Protocols = OID->getReferencedProtocols();
13717330f729Sjoerg   if (!Protocols.empty()) {
13727330f729Sjoerg     for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
13737330f729Sjoerg          E = Protocols.end(); I != E; ++I)
13747330f729Sjoerg       Out << (I == Protocols.begin() ? '<' : ',') << **I;
13757330f729Sjoerg     Out << "> ";
13767330f729Sjoerg   }
13777330f729Sjoerg 
13787330f729Sjoerg   if (OID->ivar_size() > 0) {
13797330f729Sjoerg     Out << "{\n";
13807330f729Sjoerg     eolnOut = true;
13817330f729Sjoerg     Indentation += Policy.Indentation;
13827330f729Sjoerg     for (const auto *I : OID->ivars()) {
13837330f729Sjoerg       Indent() << I->getASTContext()
13847330f729Sjoerg                       .getUnqualifiedObjCPointerType(I->getType())
13857330f729Sjoerg                       .getAsString(Policy) << ' ' << *I << ";\n";
13867330f729Sjoerg     }
13877330f729Sjoerg     Indentation -= Policy.Indentation;
13887330f729Sjoerg     Out << "}\n";
13897330f729Sjoerg   }
13907330f729Sjoerg   else if (SID || (OID->decls_begin() != OID->decls_end())) {
13917330f729Sjoerg     Out << "\n";
13927330f729Sjoerg     eolnOut = true;
13937330f729Sjoerg   }
13947330f729Sjoerg 
13957330f729Sjoerg   VisitDeclContext(OID, false);
13967330f729Sjoerg   if (!eolnOut)
13977330f729Sjoerg     Out << "\n";
13987330f729Sjoerg   Out << "@end";
13997330f729Sjoerg   // FIXME: implement the rest...
14007330f729Sjoerg }
14017330f729Sjoerg 
VisitObjCProtocolDecl(ObjCProtocolDecl * PID)14027330f729Sjoerg void DeclPrinter::VisitObjCProtocolDecl(ObjCProtocolDecl *PID) {
14037330f729Sjoerg   if (!PID->isThisDeclarationADefinition()) {
14047330f729Sjoerg     Out << "@protocol " << *PID << ";\n";
14057330f729Sjoerg     return;
14067330f729Sjoerg   }
14077330f729Sjoerg   // Protocols?
14087330f729Sjoerg   const ObjCList<ObjCProtocolDecl> &Protocols = PID->getReferencedProtocols();
14097330f729Sjoerg   if (!Protocols.empty()) {
14107330f729Sjoerg     Out << "@protocol " << *PID;
14117330f729Sjoerg     for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
14127330f729Sjoerg          E = Protocols.end(); I != E; ++I)
14137330f729Sjoerg       Out << (I == Protocols.begin() ? '<' : ',') << **I;
14147330f729Sjoerg     Out << ">\n";
14157330f729Sjoerg   } else
14167330f729Sjoerg     Out << "@protocol " << *PID << '\n';
14177330f729Sjoerg   VisitDeclContext(PID, false);
14187330f729Sjoerg   Out << "@end";
14197330f729Sjoerg }
14207330f729Sjoerg 
VisitObjCCategoryImplDecl(ObjCCategoryImplDecl * PID)14217330f729Sjoerg void DeclPrinter::VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *PID) {
1422*e038c9c4Sjoerg   Out << "@implementation ";
1423*e038c9c4Sjoerg   if (const auto *CID = PID->getClassInterface())
1424*e038c9c4Sjoerg     Out << *CID;
1425*e038c9c4Sjoerg   else
1426*e038c9c4Sjoerg     Out << "<<error-type>>";
1427*e038c9c4Sjoerg   Out << '(' << *PID << ")\n";
14287330f729Sjoerg 
14297330f729Sjoerg   VisitDeclContext(PID, false);
14307330f729Sjoerg   Out << "@end";
14317330f729Sjoerg   // FIXME: implement the rest...
14327330f729Sjoerg }
14337330f729Sjoerg 
VisitObjCCategoryDecl(ObjCCategoryDecl * PID)14347330f729Sjoerg void DeclPrinter::VisitObjCCategoryDecl(ObjCCategoryDecl *PID) {
1435*e038c9c4Sjoerg   Out << "@interface ";
1436*e038c9c4Sjoerg   if (const auto *CID = PID->getClassInterface())
1437*e038c9c4Sjoerg     Out << *CID;
1438*e038c9c4Sjoerg   else
1439*e038c9c4Sjoerg     Out << "<<error-type>>";
14407330f729Sjoerg   if (auto TypeParams = PID->getTypeParamList()) {
14417330f729Sjoerg     PrintObjCTypeParams(TypeParams);
14427330f729Sjoerg   }
14437330f729Sjoerg   Out << "(" << *PID << ")\n";
14447330f729Sjoerg   if (PID->ivar_size() > 0) {
14457330f729Sjoerg     Out << "{\n";
14467330f729Sjoerg     Indentation += Policy.Indentation;
14477330f729Sjoerg     for (const auto *I : PID->ivars())
14487330f729Sjoerg       Indent() << I->getASTContext().getUnqualifiedObjCPointerType(I->getType()).
14497330f729Sjoerg                     getAsString(Policy) << ' ' << *I << ";\n";
14507330f729Sjoerg     Indentation -= Policy.Indentation;
14517330f729Sjoerg     Out << "}\n";
14527330f729Sjoerg   }
14537330f729Sjoerg 
14547330f729Sjoerg   VisitDeclContext(PID, false);
14557330f729Sjoerg   Out << "@end";
14567330f729Sjoerg 
14577330f729Sjoerg   // FIXME: implement the rest...
14587330f729Sjoerg }
14597330f729Sjoerg 
VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl * AID)14607330f729Sjoerg void DeclPrinter::VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *AID) {
14617330f729Sjoerg   Out << "@compatibility_alias " << *AID
14627330f729Sjoerg       << ' ' << *AID->getClassInterface() << ";\n";
14637330f729Sjoerg }
14647330f729Sjoerg 
14657330f729Sjoerg /// PrintObjCPropertyDecl - print a property declaration.
14667330f729Sjoerg ///
14677330f729Sjoerg /// Print attributes in the following order:
14687330f729Sjoerg /// - class
14697330f729Sjoerg /// - nonatomic | atomic
14707330f729Sjoerg /// - assign | retain | strong | copy | weak | unsafe_unretained
14717330f729Sjoerg /// - readwrite | readonly
14727330f729Sjoerg /// - getter & setter
14737330f729Sjoerg /// - nullability
VisitObjCPropertyDecl(ObjCPropertyDecl * PDecl)14747330f729Sjoerg void DeclPrinter::VisitObjCPropertyDecl(ObjCPropertyDecl *PDecl) {
14757330f729Sjoerg   if (PDecl->getPropertyImplementation() == ObjCPropertyDecl::Required)
14767330f729Sjoerg     Out << "@required\n";
14777330f729Sjoerg   else if (PDecl->getPropertyImplementation() == ObjCPropertyDecl::Optional)
14787330f729Sjoerg     Out << "@optional\n";
14797330f729Sjoerg 
14807330f729Sjoerg   QualType T = PDecl->getType();
14817330f729Sjoerg 
14827330f729Sjoerg   Out << "@property";
1483*e038c9c4Sjoerg   if (PDecl->getPropertyAttributes() != ObjCPropertyAttribute::kind_noattr) {
14847330f729Sjoerg     bool first = true;
14857330f729Sjoerg     Out << "(";
1486*e038c9c4Sjoerg     if (PDecl->getPropertyAttributes() & ObjCPropertyAttribute::kind_class) {
14877330f729Sjoerg       Out << (first ? "" : ", ") << "class";
14887330f729Sjoerg       first = false;
14897330f729Sjoerg     }
14907330f729Sjoerg 
1491*e038c9c4Sjoerg     if (PDecl->getPropertyAttributes() & ObjCPropertyAttribute::kind_direct) {
1492*e038c9c4Sjoerg       Out << (first ? "" : ", ") << "direct";
1493*e038c9c4Sjoerg       first = false;
1494*e038c9c4Sjoerg     }
1495*e038c9c4Sjoerg 
14967330f729Sjoerg     if (PDecl->getPropertyAttributes() &
1497*e038c9c4Sjoerg         ObjCPropertyAttribute::kind_nonatomic) {
14987330f729Sjoerg       Out << (first ? "" : ", ") << "nonatomic";
14997330f729Sjoerg       first = false;
15007330f729Sjoerg     }
1501*e038c9c4Sjoerg     if (PDecl->getPropertyAttributes() & ObjCPropertyAttribute::kind_atomic) {
15027330f729Sjoerg       Out << (first ? "" : ", ") << "atomic";
15037330f729Sjoerg       first = false;
15047330f729Sjoerg     }
15057330f729Sjoerg 
1506*e038c9c4Sjoerg     if (PDecl->getPropertyAttributes() & ObjCPropertyAttribute::kind_assign) {
15077330f729Sjoerg       Out << (first ? "" : ", ") << "assign";
15087330f729Sjoerg       first = false;
15097330f729Sjoerg     }
1510*e038c9c4Sjoerg     if (PDecl->getPropertyAttributes() & ObjCPropertyAttribute::kind_retain) {
15117330f729Sjoerg       Out << (first ? "" : ", ") << "retain";
15127330f729Sjoerg       first = false;
15137330f729Sjoerg     }
15147330f729Sjoerg 
1515*e038c9c4Sjoerg     if (PDecl->getPropertyAttributes() & ObjCPropertyAttribute::kind_strong) {
15167330f729Sjoerg       Out << (first ? "" : ", ") << "strong";
15177330f729Sjoerg       first = false;
15187330f729Sjoerg     }
1519*e038c9c4Sjoerg     if (PDecl->getPropertyAttributes() & ObjCPropertyAttribute::kind_copy) {
15207330f729Sjoerg       Out << (first ? "" : ", ") << "copy";
15217330f729Sjoerg       first = false;
15227330f729Sjoerg     }
1523*e038c9c4Sjoerg     if (PDecl->getPropertyAttributes() & ObjCPropertyAttribute::kind_weak) {
15247330f729Sjoerg       Out << (first ? "" : ", ") << "weak";
15257330f729Sjoerg       first = false;
15267330f729Sjoerg     }
1527*e038c9c4Sjoerg     if (PDecl->getPropertyAttributes() &
1528*e038c9c4Sjoerg         ObjCPropertyAttribute::kind_unsafe_unretained) {
15297330f729Sjoerg       Out << (first ? "" : ", ") << "unsafe_unretained";
15307330f729Sjoerg       first = false;
15317330f729Sjoerg     }
15327330f729Sjoerg 
15337330f729Sjoerg     if (PDecl->getPropertyAttributes() &
1534*e038c9c4Sjoerg         ObjCPropertyAttribute::kind_readwrite) {
15357330f729Sjoerg       Out << (first ? "" : ", ") << "readwrite";
15367330f729Sjoerg       first = false;
15377330f729Sjoerg     }
1538*e038c9c4Sjoerg     if (PDecl->getPropertyAttributes() & ObjCPropertyAttribute::kind_readonly) {
15397330f729Sjoerg       Out << (first ? "" : ", ") << "readonly";
15407330f729Sjoerg       first = false;
15417330f729Sjoerg     }
15427330f729Sjoerg 
1543*e038c9c4Sjoerg     if (PDecl->getPropertyAttributes() & ObjCPropertyAttribute::kind_getter) {
15447330f729Sjoerg       Out << (first ? "" : ", ") << "getter = ";
15457330f729Sjoerg       PDecl->getGetterName().print(Out);
15467330f729Sjoerg       first = false;
15477330f729Sjoerg     }
1548*e038c9c4Sjoerg     if (PDecl->getPropertyAttributes() & ObjCPropertyAttribute::kind_setter) {
15497330f729Sjoerg       Out << (first ? "" : ", ") << "setter = ";
15507330f729Sjoerg       PDecl->getSetterName().print(Out);
15517330f729Sjoerg       first = false;
15527330f729Sjoerg     }
15537330f729Sjoerg 
15547330f729Sjoerg     if (PDecl->getPropertyAttributes() &
1555*e038c9c4Sjoerg         ObjCPropertyAttribute::kind_nullability) {
15567330f729Sjoerg       if (auto nullability = AttributedType::stripOuterNullability(T)) {
15577330f729Sjoerg         if (*nullability == NullabilityKind::Unspecified &&
15587330f729Sjoerg             (PDecl->getPropertyAttributes() &
1559*e038c9c4Sjoerg              ObjCPropertyAttribute::kind_null_resettable)) {
15607330f729Sjoerg           Out << (first ? "" : ", ") << "null_resettable";
15617330f729Sjoerg         } else {
15627330f729Sjoerg           Out << (first ? "" : ", ")
15637330f729Sjoerg               << getNullabilitySpelling(*nullability, true);
15647330f729Sjoerg         }
15657330f729Sjoerg         first = false;
15667330f729Sjoerg       }
15677330f729Sjoerg     }
15687330f729Sjoerg 
15697330f729Sjoerg     (void) first; // Silence dead store warning due to idiomatic code.
15707330f729Sjoerg     Out << ")";
15717330f729Sjoerg   }
15727330f729Sjoerg   std::string TypeStr = PDecl->getASTContext().getUnqualifiedObjCPointerType(T).
15737330f729Sjoerg       getAsString(Policy);
15747330f729Sjoerg   Out << ' ' << TypeStr;
15757330f729Sjoerg   if (!StringRef(TypeStr).endswith("*"))
15767330f729Sjoerg     Out << ' ';
15777330f729Sjoerg   Out << *PDecl;
15787330f729Sjoerg   if (Policy.PolishForDeclaration)
15797330f729Sjoerg     Out << ';';
15807330f729Sjoerg }
15817330f729Sjoerg 
VisitObjCPropertyImplDecl(ObjCPropertyImplDecl * PID)15827330f729Sjoerg void DeclPrinter::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *PID) {
15837330f729Sjoerg   if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize)
15847330f729Sjoerg     Out << "@synthesize ";
15857330f729Sjoerg   else
15867330f729Sjoerg     Out << "@dynamic ";
15877330f729Sjoerg   Out << *PID->getPropertyDecl();
15887330f729Sjoerg   if (PID->getPropertyIvarDecl())
15897330f729Sjoerg     Out << '=' << *PID->getPropertyIvarDecl();
15907330f729Sjoerg }
15917330f729Sjoerg 
VisitUsingDecl(UsingDecl * D)15927330f729Sjoerg void DeclPrinter::VisitUsingDecl(UsingDecl *D) {
15937330f729Sjoerg   if (!D->isAccessDeclaration())
15947330f729Sjoerg     Out << "using ";
15957330f729Sjoerg   if (D->hasTypename())
15967330f729Sjoerg     Out << "typename ";
15977330f729Sjoerg   D->getQualifier()->print(Out, Policy);
15987330f729Sjoerg 
15997330f729Sjoerg   // Use the correct record name when the using declaration is used for
16007330f729Sjoerg   // inheriting constructors.
16017330f729Sjoerg   for (const auto *Shadow : D->shadows()) {
16027330f729Sjoerg     if (const auto *ConstructorShadow =
16037330f729Sjoerg             dyn_cast<ConstructorUsingShadowDecl>(Shadow)) {
16047330f729Sjoerg       assert(Shadow->getDeclContext() == ConstructorShadow->getDeclContext());
16057330f729Sjoerg       Out << *ConstructorShadow->getNominatedBaseClass();
16067330f729Sjoerg       return;
16077330f729Sjoerg     }
16087330f729Sjoerg   }
16097330f729Sjoerg   Out << *D;
16107330f729Sjoerg }
16117330f729Sjoerg 
16127330f729Sjoerg void
VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl * D)16137330f729Sjoerg DeclPrinter::VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D) {
16147330f729Sjoerg   Out << "using typename ";
16157330f729Sjoerg   D->getQualifier()->print(Out, Policy);
16167330f729Sjoerg   Out << D->getDeclName();
16177330f729Sjoerg }
16187330f729Sjoerg 
VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl * D)16197330f729Sjoerg void DeclPrinter::VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D) {
16207330f729Sjoerg   if (!D->isAccessDeclaration())
16217330f729Sjoerg     Out << "using ";
16227330f729Sjoerg   D->getQualifier()->print(Out, Policy);
16237330f729Sjoerg   Out << D->getDeclName();
16247330f729Sjoerg }
16257330f729Sjoerg 
VisitUsingShadowDecl(UsingShadowDecl * D)16267330f729Sjoerg void DeclPrinter::VisitUsingShadowDecl(UsingShadowDecl *D) {
16277330f729Sjoerg   // ignore
16287330f729Sjoerg }
16297330f729Sjoerg 
VisitOMPThreadPrivateDecl(OMPThreadPrivateDecl * D)16307330f729Sjoerg void DeclPrinter::VisitOMPThreadPrivateDecl(OMPThreadPrivateDecl *D) {
16317330f729Sjoerg   Out << "#pragma omp threadprivate";
16327330f729Sjoerg   if (!D->varlist_empty()) {
16337330f729Sjoerg     for (OMPThreadPrivateDecl::varlist_iterator I = D->varlist_begin(),
16347330f729Sjoerg                                                 E = D->varlist_end();
16357330f729Sjoerg                                                 I != E; ++I) {
16367330f729Sjoerg       Out << (I == D->varlist_begin() ? '(' : ',');
16377330f729Sjoerg       NamedDecl *ND = cast<DeclRefExpr>(*I)->getDecl();
16387330f729Sjoerg       ND->printQualifiedName(Out);
16397330f729Sjoerg     }
16407330f729Sjoerg     Out << ")";
16417330f729Sjoerg   }
16427330f729Sjoerg }
16437330f729Sjoerg 
VisitOMPAllocateDecl(OMPAllocateDecl * D)16447330f729Sjoerg void DeclPrinter::VisitOMPAllocateDecl(OMPAllocateDecl *D) {
16457330f729Sjoerg   Out << "#pragma omp allocate";
16467330f729Sjoerg   if (!D->varlist_empty()) {
16477330f729Sjoerg     for (OMPAllocateDecl::varlist_iterator I = D->varlist_begin(),
16487330f729Sjoerg                                            E = D->varlist_end();
16497330f729Sjoerg          I != E; ++I) {
16507330f729Sjoerg       Out << (I == D->varlist_begin() ? '(' : ',');
16517330f729Sjoerg       NamedDecl *ND = cast<DeclRefExpr>(*I)->getDecl();
16527330f729Sjoerg       ND->printQualifiedName(Out);
16537330f729Sjoerg     }
16547330f729Sjoerg     Out << ")";
16557330f729Sjoerg   }
16567330f729Sjoerg   if (!D->clauselist_empty()) {
16577330f729Sjoerg     Out << " ";
16587330f729Sjoerg     OMPClausePrinter Printer(Out, Policy);
16597330f729Sjoerg     for (OMPClause *C : D->clauselists())
16607330f729Sjoerg       Printer.Visit(C);
16617330f729Sjoerg   }
16627330f729Sjoerg }
16637330f729Sjoerg 
VisitOMPRequiresDecl(OMPRequiresDecl * D)16647330f729Sjoerg void DeclPrinter::VisitOMPRequiresDecl(OMPRequiresDecl *D) {
16657330f729Sjoerg   Out << "#pragma omp requires ";
16667330f729Sjoerg   if (!D->clauselist_empty()) {
16677330f729Sjoerg     OMPClausePrinter Printer(Out, Policy);
16687330f729Sjoerg     for (auto I = D->clauselist_begin(), E = D->clauselist_end(); I != E; ++I)
16697330f729Sjoerg       Printer.Visit(*I);
16707330f729Sjoerg   }
16717330f729Sjoerg }
16727330f729Sjoerg 
VisitOMPDeclareReductionDecl(OMPDeclareReductionDecl * D)16737330f729Sjoerg void DeclPrinter::VisitOMPDeclareReductionDecl(OMPDeclareReductionDecl *D) {
16747330f729Sjoerg   if (!D->isInvalidDecl()) {
16757330f729Sjoerg     Out << "#pragma omp declare reduction (";
16767330f729Sjoerg     if (D->getDeclName().getNameKind() == DeclarationName::CXXOperatorName) {
16777330f729Sjoerg       const char *OpName =
16787330f729Sjoerg           getOperatorSpelling(D->getDeclName().getCXXOverloadedOperator());
16797330f729Sjoerg       assert(OpName && "not an overloaded operator");
16807330f729Sjoerg       Out << OpName;
16817330f729Sjoerg     } else {
16827330f729Sjoerg       assert(D->getDeclName().isIdentifier());
16837330f729Sjoerg       D->printName(Out);
16847330f729Sjoerg     }
16857330f729Sjoerg     Out << " : ";
16867330f729Sjoerg     D->getType().print(Out, Policy);
16877330f729Sjoerg     Out << " : ";
1688*e038c9c4Sjoerg     D->getCombiner()->printPretty(Out, nullptr, Policy, 0, "\n", &Context);
16897330f729Sjoerg     Out << ")";
16907330f729Sjoerg     if (auto *Init = D->getInitializer()) {
16917330f729Sjoerg       Out << " initializer(";
16927330f729Sjoerg       switch (D->getInitializerKind()) {
16937330f729Sjoerg       case OMPDeclareReductionDecl::DirectInit:
16947330f729Sjoerg         Out << "omp_priv(";
16957330f729Sjoerg         break;
16967330f729Sjoerg       case OMPDeclareReductionDecl::CopyInit:
16977330f729Sjoerg         Out << "omp_priv = ";
16987330f729Sjoerg         break;
16997330f729Sjoerg       case OMPDeclareReductionDecl::CallInit:
17007330f729Sjoerg         break;
17017330f729Sjoerg       }
1702*e038c9c4Sjoerg       Init->printPretty(Out, nullptr, Policy, 0, "\n", &Context);
17037330f729Sjoerg       if (D->getInitializerKind() == OMPDeclareReductionDecl::DirectInit)
17047330f729Sjoerg         Out << ")";
17057330f729Sjoerg       Out << ")";
17067330f729Sjoerg     }
17077330f729Sjoerg   }
17087330f729Sjoerg }
17097330f729Sjoerg 
VisitOMPDeclareMapperDecl(OMPDeclareMapperDecl * D)17107330f729Sjoerg void DeclPrinter::VisitOMPDeclareMapperDecl(OMPDeclareMapperDecl *D) {
17117330f729Sjoerg   if (!D->isInvalidDecl()) {
17127330f729Sjoerg     Out << "#pragma omp declare mapper (";
17137330f729Sjoerg     D->printName(Out);
17147330f729Sjoerg     Out << " : ";
17157330f729Sjoerg     D->getType().print(Out, Policy);
17167330f729Sjoerg     Out << " ";
17177330f729Sjoerg     Out << D->getVarName();
17187330f729Sjoerg     Out << ")";
17197330f729Sjoerg     if (!D->clauselist_empty()) {
17207330f729Sjoerg       OMPClausePrinter Printer(Out, Policy);
17217330f729Sjoerg       for (auto *C : D->clauselists()) {
17227330f729Sjoerg         Out << " ";
17237330f729Sjoerg         Printer.Visit(C);
17247330f729Sjoerg       }
17257330f729Sjoerg     }
17267330f729Sjoerg   }
17277330f729Sjoerg }
17287330f729Sjoerg 
VisitOMPCapturedExprDecl(OMPCapturedExprDecl * D)17297330f729Sjoerg void DeclPrinter::VisitOMPCapturedExprDecl(OMPCapturedExprDecl *D) {
1730*e038c9c4Sjoerg   D->getInit()->printPretty(Out, nullptr, Policy, Indentation, "\n", &Context);
17317330f729Sjoerg }
17327330f729Sjoerg 
VisitTemplateTypeParmDecl(const TemplateTypeParmDecl * TTP)1733*e038c9c4Sjoerg void DeclPrinter::VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *TTP) {
1734*e038c9c4Sjoerg   if (const TypeConstraint *TC = TTP->getTypeConstraint())
1735*e038c9c4Sjoerg     TC->print(Out, Policy);
1736*e038c9c4Sjoerg   else if (TTP->wasDeclaredWithTypename())
1737*e038c9c4Sjoerg     Out << "typename";
1738*e038c9c4Sjoerg   else
1739*e038c9c4Sjoerg     Out << "class";
1740*e038c9c4Sjoerg 
1741*e038c9c4Sjoerg   if (TTP->isParameterPack())
1742*e038c9c4Sjoerg     Out << " ...";
1743*e038c9c4Sjoerg   else if (TTP->getDeclName())
1744*e038c9c4Sjoerg     Out << ' ';
1745*e038c9c4Sjoerg 
1746*e038c9c4Sjoerg   if (TTP->getDeclName())
1747*e038c9c4Sjoerg     Out << TTP->getDeclName();
1748*e038c9c4Sjoerg 
1749*e038c9c4Sjoerg   if (TTP->hasDefaultArgument()) {
1750*e038c9c4Sjoerg     Out << " = ";
1751*e038c9c4Sjoerg     Out << TTP->getDefaultArgument().getAsString(Policy);
1752*e038c9c4Sjoerg   }
1753*e038c9c4Sjoerg }
1754*e038c9c4Sjoerg 
VisitNonTypeTemplateParmDecl(const NonTypeTemplateParmDecl * NTTP)1755*e038c9c4Sjoerg void DeclPrinter::VisitNonTypeTemplateParmDecl(
1756*e038c9c4Sjoerg     const NonTypeTemplateParmDecl *NTTP) {
1757*e038c9c4Sjoerg   StringRef Name;
1758*e038c9c4Sjoerg   if (IdentifierInfo *II = NTTP->getIdentifier())
1759*e038c9c4Sjoerg     Name = II->getName();
1760*e038c9c4Sjoerg   printDeclType(NTTP->getType(), Name, NTTP->isParameterPack());
1761*e038c9c4Sjoerg 
1762*e038c9c4Sjoerg   if (NTTP->hasDefaultArgument()) {
1763*e038c9c4Sjoerg     Out << " = ";
1764*e038c9c4Sjoerg     NTTP->getDefaultArgument()->printPretty(Out, nullptr, Policy, Indentation,
1765*e038c9c4Sjoerg                                             "\n", &Context);
1766*e038c9c4Sjoerg   }
1767*e038c9c4Sjoerg }
1768