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