Home | History | Annotate | Download | only in AST
      1 //===--- DeclPrinter.cpp - Printing implementation for Decl ASTs ----------===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 //
     10 // This file implements the Decl::print method, which pretty prints the
     11 // AST back out to C/Objective-C/C++/Objective-C++ code.
     12 //
     13 //===----------------------------------------------------------------------===//
     14 #include "clang/AST/ASTContext.h"
     15 #include "clang/AST/Attr.h"
     16 #include "clang/AST/Decl.h"
     17 #include "clang/AST/DeclCXX.h"
     18 #include "clang/AST/DeclObjC.h"
     19 #include "clang/AST/DeclVisitor.h"
     20 #include "clang/AST/Expr.h"
     21 #include "clang/AST/ExprCXX.h"
     22 #include "clang/AST/PrettyPrinter.h"
     23 #include "clang/Basic/Module.h"
     24 #include "llvm/Support/raw_ostream.h"
     25 using namespace clang;
     26 
     27 namespace {
     28   class DeclPrinter : public DeclVisitor<DeclPrinter> {
     29     raw_ostream &Out;
     30     PrintingPolicy Policy;
     31     unsigned Indentation;
     32     bool PrintInstantiation;
     33 
     34     raw_ostream& Indent() { return Indent(Indentation); }
     35     raw_ostream& Indent(unsigned Indentation);
     36     void ProcessDeclGroup(SmallVectorImpl<Decl*>& Decls);
     37 
     38     void Print(AccessSpecifier AS);
     39 
     40     /// Print an Objective-C method type in parentheses.
     41     ///
     42     /// \param Quals The Objective-C declaration qualifiers.
     43     /// \param T The type to print.
     44     void PrintObjCMethodType(ASTContext &Ctx, Decl::ObjCDeclQualifier Quals,
     45                              QualType T);
     46 
     47     void PrintObjCTypeParams(ObjCTypeParamList *Params);
     48 
     49   public:
     50     DeclPrinter(raw_ostream &Out, const PrintingPolicy &Policy,
     51                 unsigned Indentation = 0, bool PrintInstantiation = false)
     52       : Out(Out), Policy(Policy), Indentation(Indentation),
     53         PrintInstantiation(PrintInstantiation) { }
     54 
     55     void VisitDeclContext(DeclContext *DC, bool Indent = true);
     56 
     57     void VisitTranslationUnitDecl(TranslationUnitDecl *D);
     58     void VisitTypedefDecl(TypedefDecl *D);
     59     void VisitTypeAliasDecl(TypeAliasDecl *D);
     60     void VisitEnumDecl(EnumDecl *D);
     61     void VisitRecordDecl(RecordDecl *D);
     62     void VisitEnumConstantDecl(EnumConstantDecl *D);
     63     void VisitEmptyDecl(EmptyDecl *D);
     64     void VisitFunctionDecl(FunctionDecl *D);
     65     void VisitFriendDecl(FriendDecl *D);
     66     void VisitFieldDecl(FieldDecl *D);
     67     void VisitVarDecl(VarDecl *D);
     68     void VisitLabelDecl(LabelDecl *D);
     69     void VisitParmVarDecl(ParmVarDecl *D);
     70     void VisitFileScopeAsmDecl(FileScopeAsmDecl *D);
     71     void VisitImportDecl(ImportDecl *D);
     72     void VisitStaticAssertDecl(StaticAssertDecl *D);
     73     void VisitNamespaceDecl(NamespaceDecl *D);
     74     void VisitUsingDirectiveDecl(UsingDirectiveDecl *D);
     75     void VisitNamespaceAliasDecl(NamespaceAliasDecl *D);
     76     void VisitCXXRecordDecl(CXXRecordDecl *D);
     77     void VisitLinkageSpecDecl(LinkageSpecDecl *D);
     78     void VisitTemplateDecl(const TemplateDecl *D);
     79     void VisitFunctionTemplateDecl(FunctionTemplateDecl *D);
     80     void VisitClassTemplateDecl(ClassTemplateDecl *D);
     81     void VisitObjCMethodDecl(ObjCMethodDecl *D);
     82     void VisitObjCImplementationDecl(ObjCImplementationDecl *D);
     83     void VisitObjCInterfaceDecl(ObjCInterfaceDecl *D);
     84     void VisitObjCProtocolDecl(ObjCProtocolDecl *D);
     85     void VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D);
     86     void VisitObjCCategoryDecl(ObjCCategoryDecl *D);
     87     void VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *D);
     88     void VisitObjCPropertyDecl(ObjCPropertyDecl *D);
     89     void VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D);
     90     void VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D);
     91     void VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D);
     92     void VisitUsingDecl(UsingDecl *D);
     93     void VisitUsingShadowDecl(UsingShadowDecl *D);
     94     void VisitOMPThreadPrivateDecl(OMPThreadPrivateDecl *D);
     95 
     96     void PrintTemplateParameters(const TemplateParameterList *Params,
     97                                  const TemplateArgumentList *Args = nullptr);
     98     void prettyPrintAttributes(Decl *D);
     99     void prettyPrintPragmas(Decl *D);
    100     void printDeclType(QualType T, StringRef DeclName, bool Pack = false);
    101   };
    102 }
    103 
    104 void Decl::print(raw_ostream &Out, unsigned Indentation,
    105                  bool PrintInstantiation) const {
    106   print(Out, getASTContext().getPrintingPolicy(), Indentation, PrintInstantiation);
    107 }
    108 
    109 void Decl::print(raw_ostream &Out, const PrintingPolicy &Policy,
    110                  unsigned Indentation, bool PrintInstantiation) const {
    111   DeclPrinter Printer(Out, Policy, Indentation, PrintInstantiation);
    112   Printer.Visit(const_cast<Decl*>(this));
    113 }
    114 
    115 static QualType GetBaseType(QualType T) {
    116   // FIXME: This should be on the Type class!
    117   QualType BaseType = T;
    118   while (!BaseType->isSpecifierType()) {
    119     if (isa<TypedefType>(BaseType))
    120       break;
    121     else if (const PointerType* PTy = BaseType->getAs<PointerType>())
    122       BaseType = PTy->getPointeeType();
    123     else if (const BlockPointerType *BPy = BaseType->getAs<BlockPointerType>())
    124       BaseType = BPy->getPointeeType();
    125     else if (const ArrayType* ATy = dyn_cast<ArrayType>(BaseType))
    126       BaseType = ATy->getElementType();
    127     else if (const FunctionType* FTy = BaseType->getAs<FunctionType>())
    128       BaseType = FTy->getReturnType();
    129     else if (const VectorType *VTy = BaseType->getAs<VectorType>())
    130       BaseType = VTy->getElementType();
    131     else if (const ReferenceType *RTy = BaseType->getAs<ReferenceType>())
    132       BaseType = RTy->getPointeeType();
    133     else
    134       llvm_unreachable("Unknown declarator!");
    135   }
    136   return BaseType;
    137 }
    138 
    139 static QualType getDeclType(Decl* D) {
    140   if (TypedefNameDecl* TDD = dyn_cast<TypedefNameDecl>(D))
    141     return TDD->getUnderlyingType();
    142   if (ValueDecl* VD = dyn_cast<ValueDecl>(D))
    143     return VD->getType();
    144   return QualType();
    145 }
    146 
    147 void Decl::printGroup(Decl** Begin, unsigned NumDecls,
    148                       raw_ostream &Out, const PrintingPolicy &Policy,
    149                       unsigned Indentation) {
    150   if (NumDecls == 1) {
    151     (*Begin)->print(Out, Policy, Indentation);
    152     return;
    153   }
    154 
    155   Decl** End = Begin + NumDecls;
    156   TagDecl* TD = dyn_cast<TagDecl>(*Begin);
    157   if (TD)
    158     ++Begin;
    159 
    160   PrintingPolicy SubPolicy(Policy);
    161   if (TD && TD->isCompleteDefinition()) {
    162     TD->print(Out, Policy, Indentation);
    163     Out << " ";
    164     SubPolicy.SuppressTag = true;
    165   }
    166 
    167   bool isFirst = true;
    168   for ( ; Begin != End; ++Begin) {
    169     if (isFirst) {
    170       SubPolicy.SuppressSpecifiers = false;
    171       isFirst = false;
    172     } else {
    173       if (!isFirst) Out << ", ";
    174       SubPolicy.SuppressSpecifiers = true;
    175     }
    176 
    177     (*Begin)->print(Out, SubPolicy, Indentation);
    178   }
    179 }
    180 
    181 LLVM_DUMP_METHOD void DeclContext::dumpDeclContext() const {
    182   // Get the translation unit
    183   const DeclContext *DC = this;
    184   while (!DC->isTranslationUnit())
    185     DC = DC->getParent();
    186 
    187   ASTContext &Ctx = cast<TranslationUnitDecl>(DC)->getASTContext();
    188   DeclPrinter Printer(llvm::errs(), Ctx.getPrintingPolicy(), 0);
    189   Printer.VisitDeclContext(const_cast<DeclContext *>(this), /*Indent=*/false);
    190 }
    191 
    192 raw_ostream& DeclPrinter::Indent(unsigned Indentation) {
    193   for (unsigned i = 0; i != Indentation; ++i)
    194     Out << "  ";
    195   return Out;
    196 }
    197 
    198 void DeclPrinter::prettyPrintAttributes(Decl *D) {
    199   if (Policy.PolishForDeclaration)
    200     return;
    201 
    202   if (D->hasAttrs()) {
    203     AttrVec &Attrs = D->getAttrs();
    204     for (auto *A : Attrs) {
    205       switch (A->getKind()) {
    206 #define ATTR(X)
    207 #define PRAGMA_SPELLING_ATTR(X) case attr::X:
    208 #include "clang/Basic/AttrList.inc"
    209         break;
    210       default:
    211         A->printPretty(Out, Policy);
    212         break;
    213       }
    214     }
    215   }
    216 }
    217 
    218 void DeclPrinter::prettyPrintPragmas(Decl *D) {
    219   if (Policy.PolishForDeclaration)
    220     return;
    221 
    222   if (D->hasAttrs()) {
    223     AttrVec &Attrs = D->getAttrs();
    224     for (auto *A : Attrs) {
    225       switch (A->getKind()) {
    226 #define ATTR(X)
    227 #define PRAGMA_SPELLING_ATTR(X) case attr::X:
    228 #include "clang/Basic/AttrList.inc"
    229         A->printPretty(Out, Policy);
    230         Indent();
    231         break;
    232       default:
    233         break;
    234       }
    235     }
    236   }
    237 }
    238 
    239 void DeclPrinter::printDeclType(QualType T, StringRef DeclName, bool Pack) {
    240   // Normally, a PackExpansionType is written as T[3]... (for instance, as a
    241   // template argument), but if it is the type of a declaration, the ellipsis
    242   // is placed before the name being declared.
    243   if (auto *PET = T->getAs<PackExpansionType>()) {
    244     Pack = true;
    245     T = PET->getPattern();
    246   }
    247   T.print(Out, Policy, (Pack ? "..." : "") + DeclName);
    248 }
    249 
    250 void DeclPrinter::ProcessDeclGroup(SmallVectorImpl<Decl*>& Decls) {
    251   this->Indent();
    252   Decl::printGroup(Decls.data(), Decls.size(), Out, Policy, Indentation);
    253   Out << ";\n";
    254   Decls.clear();
    255 
    256 }
    257 
    258 void DeclPrinter::Print(AccessSpecifier AS) {
    259   switch(AS) {
    260   case AS_none:      llvm_unreachable("No access specifier!");
    261   case AS_public:    Out << "public"; break;
    262   case AS_protected: Out << "protected"; break;
    263   case AS_private:   Out << "private"; break;
    264   }
    265 }
    266 
    267 //----------------------------------------------------------------------------
    268 // Common C declarations
    269 //----------------------------------------------------------------------------
    270 
    271 void DeclPrinter::VisitDeclContext(DeclContext *DC, bool Indent) {
    272   if (Policy.TerseOutput)
    273     return;
    274 
    275   if (Indent)
    276     Indentation += Policy.Indentation;
    277 
    278   SmallVector<Decl*, 2> Decls;
    279   for (DeclContext::decl_iterator D = DC->decls_begin(), DEnd = DC->decls_end();
    280        D != DEnd; ++D) {
    281 
    282     // Don't print ObjCIvarDecls, as they are printed when visiting the
    283     // containing ObjCInterfaceDecl.
    284     if (isa<ObjCIvarDecl>(*D))
    285       continue;
    286 
    287     // Skip over implicit declarations in pretty-printing mode.
    288     if (D->isImplicit())
    289       continue;
    290 
    291     // The next bits of code handles stuff like "struct {int x;} a,b"; we're
    292     // forced to merge the declarations because there's no other way to
    293     // refer to the struct in question.  This limited merging is safe without
    294     // a bunch of other checks because it only merges declarations directly
    295     // referring to the tag, not typedefs.
    296     //
    297     // Check whether the current declaration should be grouped with a previous
    298     // unnamed struct.
    299     QualType CurDeclType = getDeclType(*D);
    300     if (!Decls.empty() && !CurDeclType.isNull()) {
    301       QualType BaseType = GetBaseType(CurDeclType);
    302       if (!BaseType.isNull() && isa<ElaboratedType>(BaseType))
    303         BaseType = cast<ElaboratedType>(BaseType)->getNamedType();
    304       if (!BaseType.isNull() && isa<TagType>(BaseType) &&
    305           cast<TagType>(BaseType)->getDecl() == Decls[0]) {
    306         Decls.push_back(*D);
    307         continue;
    308       }
    309     }
    310 
    311     // If we have a merged group waiting to be handled, handle it now.
    312     if (!Decls.empty())
    313       ProcessDeclGroup(Decls);
    314 
    315     // If the current declaration is an unnamed tag type, save it
    316     // so we can merge it with the subsequent declaration(s) using it.
    317     if (isa<TagDecl>(*D) && !cast<TagDecl>(*D)->getIdentifier()) {
    318       Decls.push_back(*D);
    319       continue;
    320     }
    321 
    322     if (isa<AccessSpecDecl>(*D)) {
    323       Indentation -= Policy.Indentation;
    324       this->Indent();
    325       Print(D->getAccess());
    326       Out << ":\n";
    327       Indentation += Policy.Indentation;
    328       continue;
    329     }
    330 
    331     this->Indent();
    332     Visit(*D);
    333 
    334     // FIXME: Need to be able to tell the DeclPrinter when
    335     const char *Terminator = nullptr;
    336     if (isa<OMPThreadPrivateDecl>(*D))
    337       Terminator = nullptr;
    338     else if (isa<FunctionDecl>(*D) &&
    339              cast<FunctionDecl>(*D)->isThisDeclarationADefinition())
    340       Terminator = nullptr;
    341     else if (isa<ObjCMethodDecl>(*D) && cast<ObjCMethodDecl>(*D)->getBody())
    342       Terminator = nullptr;
    343     else if (isa<NamespaceDecl>(*D) || isa<LinkageSpecDecl>(*D) ||
    344              isa<ObjCImplementationDecl>(*D) ||
    345              isa<ObjCInterfaceDecl>(*D) ||
    346              isa<ObjCProtocolDecl>(*D) ||
    347              isa<ObjCCategoryImplDecl>(*D) ||
    348              isa<ObjCCategoryDecl>(*D))
    349       Terminator = nullptr;
    350     else if (isa<EnumConstantDecl>(*D)) {
    351       DeclContext::decl_iterator Next = D;
    352       ++Next;
    353       if (Next != DEnd)
    354         Terminator = ",";
    355     } else
    356       Terminator = ";";
    357 
    358     if (Terminator)
    359       Out << Terminator;
    360     Out << "\n";
    361   }
    362 
    363   if (!Decls.empty())
    364     ProcessDeclGroup(Decls);
    365 
    366   if (Indent)
    367     Indentation -= Policy.Indentation;
    368 }
    369 
    370 void DeclPrinter::VisitTranslationUnitDecl(TranslationUnitDecl *D) {
    371   VisitDeclContext(D, false);
    372 }
    373 
    374 void DeclPrinter::VisitTypedefDecl(TypedefDecl *D) {
    375   if (!Policy.SuppressSpecifiers) {
    376     Out << "typedef ";
    377 
    378     if (D->isModulePrivate())
    379       Out << "__module_private__ ";
    380   }
    381   D->getTypeSourceInfo()->getType().print(Out, Policy, D->getName());
    382   prettyPrintAttributes(D);
    383 }
    384 
    385 void DeclPrinter::VisitTypeAliasDecl(TypeAliasDecl *D) {
    386   Out << "using " << *D;
    387   prettyPrintAttributes(D);
    388   Out << " = " << D->getTypeSourceInfo()->getType().getAsString(Policy);
    389 }
    390 
    391 void DeclPrinter::VisitEnumDecl(EnumDecl *D) {
    392   if (!Policy.SuppressSpecifiers && D->isModulePrivate())
    393     Out << "__module_private__ ";
    394   Out << "enum ";
    395   if (D->isScoped()) {
    396     if (D->isScopedUsingClassTag())
    397       Out << "class ";
    398     else
    399       Out << "struct ";
    400   }
    401   Out << *D;
    402 
    403   if (D->isFixed())
    404     Out << " : " << D->getIntegerType().stream(Policy);
    405 
    406   if (D->isCompleteDefinition()) {
    407     Out << " {\n";
    408     VisitDeclContext(D);
    409     Indent() << "}";
    410   }
    411   prettyPrintAttributes(D);
    412 }
    413 
    414 void DeclPrinter::VisitRecordDecl(RecordDecl *D) {
    415   if (!Policy.SuppressSpecifiers && D->isModulePrivate())
    416     Out << "__module_private__ ";
    417   Out << D->getKindName();
    418 
    419   prettyPrintAttributes(D);
    420 
    421   if (D->getIdentifier())
    422     Out << ' ' << *D;
    423 
    424   if (D->isCompleteDefinition()) {
    425     Out << " {\n";
    426     VisitDeclContext(D);
    427     Indent() << "}";
    428   }
    429 }
    430 
    431 void DeclPrinter::VisitEnumConstantDecl(EnumConstantDecl *D) {
    432   Out << *D;
    433   if (Expr *Init = D->getInitExpr()) {
    434     Out << " = ";
    435     Init->printPretty(Out, nullptr, Policy, Indentation);
    436   }
    437 }
    438 
    439 void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
    440   if (!D->getDescribedFunctionTemplate() &&
    441       !D->isFunctionTemplateSpecialization())
    442     prettyPrintPragmas(D);
    443 
    444   CXXConstructorDecl *CDecl = dyn_cast<CXXConstructorDecl>(D);
    445   CXXConversionDecl *ConversionDecl = dyn_cast<CXXConversionDecl>(D);
    446   if (!Policy.SuppressSpecifiers) {
    447     switch (D->getStorageClass()) {
    448     case SC_None: break;
    449     case SC_Extern: Out << "extern "; break;
    450     case SC_Static: Out << "static "; break;
    451     case SC_PrivateExtern: Out << "__private_extern__ "; break;
    452     case SC_Auto: case SC_Register:
    453       llvm_unreachable("invalid for functions");
    454     }
    455 
    456     if (D->isInlineSpecified())  Out << "inline ";
    457     if (D->isVirtualAsWritten()) Out << "virtual ";
    458     if (D->isModulePrivate())    Out << "__module_private__ ";
    459     if (D->isConstexpr() && !D->isExplicitlyDefaulted()) Out << "constexpr ";
    460     if ((CDecl && CDecl->isExplicitSpecified()) ||
    461         (ConversionDecl && ConversionDecl->isExplicit()))
    462       Out << "explicit ";
    463   }
    464 
    465   PrintingPolicy SubPolicy(Policy);
    466   SubPolicy.SuppressSpecifiers = false;
    467   std::string Proto = D->getNameInfo().getAsString();
    468 
    469   QualType Ty = D->getType();
    470   while (const ParenType *PT = dyn_cast<ParenType>(Ty)) {
    471     Proto = '(' + Proto + ')';
    472     Ty = PT->getInnerType();
    473   }
    474 
    475   if (const FunctionType *AFT = Ty->getAs<FunctionType>()) {
    476     const FunctionProtoType *FT = nullptr;
    477     if (D->hasWrittenPrototype())
    478       FT = dyn_cast<FunctionProtoType>(AFT);
    479 
    480     Proto += "(";
    481     if (FT) {
    482       llvm::raw_string_ostream POut(Proto);
    483       DeclPrinter ParamPrinter(POut, SubPolicy, Indentation);
    484       for (unsigned i = 0, e = D->getNumParams(); i != e; ++i) {
    485         if (i) POut << ", ";
    486         ParamPrinter.VisitParmVarDecl(D->getParamDecl(i));
    487       }
    488 
    489       if (FT->isVariadic()) {
    490         if (D->getNumParams()) POut << ", ";
    491         POut << "...";
    492       }
    493     } else if (D->doesThisDeclarationHaveABody() && !D->hasPrototype()) {
    494       for (unsigned i = 0, e = D->getNumParams(); i != e; ++i) {
    495         if (i)
    496           Proto += ", ";
    497         Proto += D->getParamDecl(i)->getNameAsString();
    498       }
    499     }
    500 
    501     Proto += ")";
    502 
    503     if (FT) {
    504       if (FT->isConst())
    505         Proto += " const";
    506       if (FT->isVolatile())
    507         Proto += " volatile";
    508       if (FT->isRestrict())
    509         Proto += " restrict";
    510 
    511       switch (FT->getRefQualifier()) {
    512       case RQ_None:
    513         break;
    514       case RQ_LValue:
    515         Proto += " &";
    516         break;
    517       case RQ_RValue:
    518         Proto += " &&";
    519         break;
    520       }
    521     }
    522 
    523     if (FT && FT->hasDynamicExceptionSpec()) {
    524       Proto += " throw(";
    525       if (FT->getExceptionSpecType() == EST_MSAny)
    526         Proto += "...";
    527       else
    528         for (unsigned I = 0, N = FT->getNumExceptions(); I != N; ++I) {
    529           if (I)
    530             Proto += ", ";
    531 
    532           Proto += FT->getExceptionType(I).getAsString(SubPolicy);
    533         }
    534       Proto += ")";
    535     } else if (FT && isNoexceptExceptionSpec(FT->getExceptionSpecType())) {
    536       Proto += " noexcept";
    537       if (FT->getExceptionSpecType() == EST_ComputedNoexcept) {
    538         Proto += "(";
    539         llvm::raw_string_ostream EOut(Proto);
    540         FT->getNoexceptExpr()->printPretty(EOut, nullptr, SubPolicy,
    541                                            Indentation);
    542         EOut.flush();
    543         Proto += EOut.str();
    544         Proto += ")";
    545       }
    546     }
    547 
    548     if (CDecl) {
    549       bool HasInitializerList = false;
    550       for (const auto *BMInitializer : CDecl->inits()) {
    551         if (BMInitializer->isInClassMemberInitializer())
    552           continue;
    553 
    554         if (!HasInitializerList) {
    555           Proto += " : ";
    556           Out << Proto;
    557           Proto.clear();
    558           HasInitializerList = true;
    559         } else
    560           Out << ", ";
    561 
    562         if (BMInitializer->isAnyMemberInitializer()) {
    563           FieldDecl *FD = BMInitializer->getAnyMember();
    564           Out << *FD;
    565         } else {
    566           Out << QualType(BMInitializer->getBaseClass(), 0).getAsString(Policy);
    567         }
    568 
    569         Out << "(";
    570         if (!BMInitializer->getInit()) {
    571           // Nothing to print
    572         } else {
    573           Expr *Init = BMInitializer->getInit();
    574           if (ExprWithCleanups *Tmp = dyn_cast<ExprWithCleanups>(Init))
    575             Init = Tmp->getSubExpr();
    576 
    577           Init = Init->IgnoreParens();
    578 
    579           Expr *SimpleInit = nullptr;
    580           Expr **Args = nullptr;
    581           unsigned NumArgs = 0;
    582           if (ParenListExpr *ParenList = dyn_cast<ParenListExpr>(Init)) {
    583             Args = ParenList->getExprs();
    584             NumArgs = ParenList->getNumExprs();
    585           } else if (CXXConstructExpr *Construct
    586                                         = dyn_cast<CXXConstructExpr>(Init)) {
    587             Args = Construct->getArgs();
    588             NumArgs = Construct->getNumArgs();
    589           } else
    590             SimpleInit = Init;
    591 
    592           if (SimpleInit)
    593             SimpleInit->printPretty(Out, nullptr, Policy, Indentation);
    594           else {
    595             for (unsigned I = 0; I != NumArgs; ++I) {
    596               assert(Args[I] != nullptr && "Expected non-null Expr");
    597               if (isa<CXXDefaultArgExpr>(Args[I]))
    598                 break;
    599 
    600               if (I)
    601                 Out << ", ";
    602               Args[I]->printPretty(Out, nullptr, Policy, Indentation);
    603             }
    604           }
    605         }
    606         Out << ")";
    607         if (BMInitializer->isPackExpansion())
    608           Out << "...";
    609       }
    610     } else if (!ConversionDecl && !isa<CXXDestructorDecl>(D)) {
    611       if (FT && FT->hasTrailingReturn()) {
    612         Out << "auto " << Proto << " -> ";
    613         Proto.clear();
    614       }
    615       AFT->getReturnType().print(Out, Policy, Proto);
    616       Proto.clear();
    617     }
    618     Out << Proto;
    619   } else {
    620     Ty.print(Out, Policy, Proto);
    621   }
    622 
    623   prettyPrintAttributes(D);
    624 
    625   if (D->isPure())
    626     Out << " = 0";
    627   else if (D->isDeletedAsWritten())
    628     Out << " = delete";
    629   else if (D->isExplicitlyDefaulted())
    630     Out << " = default";
    631   else if (D->doesThisDeclarationHaveABody() && !Policy.TerseOutput) {
    632     if (!D->hasPrototype() && D->getNumParams()) {
    633       // This is a K&R function definition, so we need to print the
    634       // parameters.
    635       Out << '\n';
    636       DeclPrinter ParamPrinter(Out, SubPolicy, Indentation);
    637       Indentation += Policy.Indentation;
    638       for (unsigned i = 0, e = D->getNumParams(); i != e; ++i) {
    639         Indent();
    640         ParamPrinter.VisitParmVarDecl(D->getParamDecl(i));
    641         Out << ";\n";
    642       }
    643       Indentation -= Policy.Indentation;
    644     } else
    645       Out << ' ';
    646 
    647     if (D->getBody())
    648       D->getBody()->printPretty(Out, nullptr, SubPolicy, Indentation);
    649     Out << '\n';
    650   }
    651 }
    652 
    653 void DeclPrinter::VisitFriendDecl(FriendDecl *D) {
    654   if (TypeSourceInfo *TSI = D->getFriendType()) {
    655     unsigned NumTPLists = D->getFriendTypeNumTemplateParameterLists();
    656     for (unsigned i = 0; i < NumTPLists; ++i)
    657       PrintTemplateParameters(D->getFriendTypeTemplateParameterList(i));
    658     Out << "friend ";
    659     Out << " " << TSI->getType().getAsString(Policy);
    660   }
    661   else if (FunctionDecl *FD =
    662       dyn_cast<FunctionDecl>(D->getFriendDecl())) {
    663     Out << "friend ";
    664     VisitFunctionDecl(FD);
    665   }
    666   else if (FunctionTemplateDecl *FTD =
    667            dyn_cast<FunctionTemplateDecl>(D->getFriendDecl())) {
    668     Out << "friend ";
    669     VisitFunctionTemplateDecl(FTD);
    670   }
    671   else if (ClassTemplateDecl *CTD =
    672            dyn_cast<ClassTemplateDecl>(D->getFriendDecl())) {
    673     Out << "friend ";
    674     VisitRedeclarableTemplateDecl(CTD);
    675   }
    676 }
    677 
    678 void DeclPrinter::VisitFieldDecl(FieldDecl *D) {
    679   // FIXME: add printing of pragma attributes if required.
    680   if (!Policy.SuppressSpecifiers && D->isMutable())
    681     Out << "mutable ";
    682   if (!Policy.SuppressSpecifiers && D->isModulePrivate())
    683     Out << "__module_private__ ";
    684 
    685   Out << D->getASTContext().getUnqualifiedObjCPointerType(D->getType()).
    686             stream(Policy, D->getName());
    687 
    688   if (D->isBitField()) {
    689     Out << " : ";
    690     D->getBitWidth()->printPretty(Out, nullptr, Policy, Indentation);
    691   }
    692 
    693   Expr *Init = D->getInClassInitializer();
    694   if (!Policy.SuppressInitializers && Init) {
    695     if (D->getInClassInitStyle() == ICIS_ListInit)
    696       Out << " ";
    697     else
    698       Out << " = ";
    699     Init->printPretty(Out, nullptr, Policy, Indentation);
    700   }
    701   prettyPrintAttributes(D);
    702 }
    703 
    704 void DeclPrinter::VisitLabelDecl(LabelDecl *D) {
    705   Out << *D << ":";
    706 }
    707 
    708 void DeclPrinter::VisitVarDecl(VarDecl *D) {
    709   prettyPrintPragmas(D);
    710   if (!Policy.SuppressSpecifiers) {
    711     StorageClass SC = D->getStorageClass();
    712     if (SC != SC_None)
    713       Out << VarDecl::getStorageClassSpecifierString(SC) << " ";
    714 
    715     switch (D->getTSCSpec()) {
    716     case TSCS_unspecified:
    717       break;
    718     case TSCS___thread:
    719       Out << "__thread ";
    720       break;
    721     case TSCS__Thread_local:
    722       Out << "_Thread_local ";
    723       break;
    724     case TSCS_thread_local:
    725       Out << "thread_local ";
    726       break;
    727     }
    728 
    729     if (D->isModulePrivate())
    730       Out << "__module_private__ ";
    731   }
    732 
    733   QualType T = D->getTypeSourceInfo()
    734     ? D->getTypeSourceInfo()->getType()
    735     : D->getASTContext().getUnqualifiedObjCPointerType(D->getType());
    736   printDeclType(T, D->getName());
    737   Expr *Init = D->getInit();
    738   if (!Policy.SuppressInitializers && Init) {
    739     bool ImplicitInit = false;
    740     if (CXXConstructExpr *Construct =
    741             dyn_cast<CXXConstructExpr>(Init->IgnoreImplicit())) {
    742       if (D->getInitStyle() == VarDecl::CallInit &&
    743           !Construct->isListInitialization()) {
    744         ImplicitInit = Construct->getNumArgs() == 0 ||
    745           Construct->getArg(0)->isDefaultArgument();
    746       }
    747     }
    748     if (!ImplicitInit) {
    749       if ((D->getInitStyle() == VarDecl::CallInit) && !isa<ParenListExpr>(Init))
    750         Out << "(";
    751       else if (D->getInitStyle() == VarDecl::CInit) {
    752         Out << " = ";
    753       }
    754       Init->printPretty(Out, nullptr, Policy, Indentation);
    755       if ((D->getInitStyle() == VarDecl::CallInit) && !isa<ParenListExpr>(Init))
    756         Out << ")";
    757     }
    758   }
    759   prettyPrintAttributes(D);
    760 }
    761 
    762 void DeclPrinter::VisitParmVarDecl(ParmVarDecl *D) {
    763   VisitVarDecl(D);
    764 }
    765 
    766 void DeclPrinter::VisitFileScopeAsmDecl(FileScopeAsmDecl *D) {
    767   Out << "__asm (";
    768   D->getAsmString()->printPretty(Out, nullptr, Policy, Indentation);
    769   Out << ")";
    770 }
    771 
    772 void DeclPrinter::VisitImportDecl(ImportDecl *D) {
    773   Out << "@import " << D->getImportedModule()->getFullModuleName()
    774       << ";\n";
    775 }
    776 
    777 void DeclPrinter::VisitStaticAssertDecl(StaticAssertDecl *D) {
    778   Out << "static_assert(";
    779   D->getAssertExpr()->printPretty(Out, nullptr, Policy, Indentation);
    780   if (StringLiteral *SL = D->getMessage()) {
    781     Out << ", ";
    782     SL->printPretty(Out, nullptr, Policy, Indentation);
    783   }
    784   Out << ")";
    785 }
    786 
    787 //----------------------------------------------------------------------------
    788 // C++ declarations
    789 //----------------------------------------------------------------------------
    790 void DeclPrinter::VisitNamespaceDecl(NamespaceDecl *D) {
    791   if (D->isInline())
    792     Out << "inline ";
    793   Out << "namespace " << *D << " {\n";
    794   VisitDeclContext(D);
    795   Indent() << "}";
    796 }
    797 
    798 void DeclPrinter::VisitUsingDirectiveDecl(UsingDirectiveDecl *D) {
    799   Out << "using namespace ";
    800   if (D->getQualifier())
    801     D->getQualifier()->print(Out, Policy);
    802   Out << *D->getNominatedNamespaceAsWritten();
    803 }
    804 
    805 void DeclPrinter::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) {
    806   Out << "namespace " << *D << " = ";
    807   if (D->getQualifier())
    808     D->getQualifier()->print(Out, Policy);
    809   Out << *D->getAliasedNamespace();
    810 }
    811 
    812 void DeclPrinter::VisitEmptyDecl(EmptyDecl *D) {
    813   prettyPrintAttributes(D);
    814 }
    815 
    816 void DeclPrinter::VisitCXXRecordDecl(CXXRecordDecl *D) {
    817   // FIXME: add printing of pragma attributes if required.
    818   if (!Policy.SuppressSpecifiers && D->isModulePrivate())
    819     Out << "__module_private__ ";
    820   Out << D->getKindName();
    821 
    822   prettyPrintAttributes(D);
    823 
    824   if (D->getIdentifier())
    825     Out << ' ' << *D;
    826 
    827   if (D->isCompleteDefinition()) {
    828     // Print the base classes
    829     if (D->getNumBases()) {
    830       Out << " : ";
    831       for (CXXRecordDecl::base_class_iterator Base = D->bases_begin(),
    832              BaseEnd = D->bases_end(); Base != BaseEnd; ++Base) {
    833         if (Base != D->bases_begin())
    834           Out << ", ";
    835 
    836         if (Base->isVirtual())
    837           Out << "virtual ";
    838 
    839         AccessSpecifier AS = Base->getAccessSpecifierAsWritten();
    840         if (AS != AS_none) {
    841           Print(AS);
    842           Out << " ";
    843         }
    844         Out << Base->getType().getAsString(Policy);
    845 
    846         if (Base->isPackExpansion())
    847           Out << "...";
    848       }
    849     }
    850 
    851     // Print the class definition
    852     // FIXME: Doesn't print access specifiers, e.g., "public:"
    853     Out << " {\n";
    854     VisitDeclContext(D);
    855     Indent() << "}";
    856   }
    857 }
    858 
    859 void DeclPrinter::VisitLinkageSpecDecl(LinkageSpecDecl *D) {
    860   const char *l;
    861   if (D->getLanguage() == LinkageSpecDecl::lang_c)
    862     l = "C";
    863   else {
    864     assert(D->getLanguage() == LinkageSpecDecl::lang_cxx &&
    865            "unknown language in linkage specification");
    866     l = "C++";
    867   }
    868 
    869   Out << "extern \"" << l << "\" ";
    870   if (D->hasBraces()) {
    871     Out << "{\n";
    872     VisitDeclContext(D);
    873     Indent() << "}";
    874   } else
    875     Visit(*D->decls_begin());
    876 }
    877 
    878 void DeclPrinter::PrintTemplateParameters(const TemplateParameterList *Params,
    879                                           const TemplateArgumentList *Args) {
    880   assert(Params);
    881   assert(!Args || Params->size() == Args->size());
    882 
    883   Out << "template <";
    884 
    885   for (unsigned i = 0, e = Params->size(); i != e; ++i) {
    886     if (i != 0)
    887       Out << ", ";
    888 
    889     const Decl *Param = Params->getParam(i);
    890     if (const TemplateTypeParmDecl *TTP =
    891           dyn_cast<TemplateTypeParmDecl>(Param)) {
    892 
    893       if (TTP->wasDeclaredWithTypename())
    894         Out << "typename ";
    895       else
    896         Out << "class ";
    897 
    898       if (TTP->isParameterPack())
    899         Out << "...";
    900 
    901       Out << *TTP;
    902 
    903       if (Args) {
    904         Out << " = ";
    905         Args->get(i).print(Policy, Out);
    906       } else if (TTP->hasDefaultArgument()) {
    907         Out << " = ";
    908         Out << TTP->getDefaultArgument().getAsString(Policy);
    909       };
    910     } else if (const NonTypeTemplateParmDecl *NTTP =
    911                  dyn_cast<NonTypeTemplateParmDecl>(Param)) {
    912       StringRef Name;
    913       if (IdentifierInfo *II = NTTP->getIdentifier())
    914         Name = II->getName();
    915       printDeclType(NTTP->getType(), Name, NTTP->isParameterPack());
    916 
    917       if (Args) {
    918         Out << " = ";
    919         Args->get(i).print(Policy, Out);
    920       } else if (NTTP->hasDefaultArgument()) {
    921         Out << " = ";
    922         NTTP->getDefaultArgument()->printPretty(Out, nullptr, Policy,
    923                                                 Indentation);
    924       }
    925     } else if (const TemplateTemplateParmDecl *TTPD =
    926                  dyn_cast<TemplateTemplateParmDecl>(Param)) {
    927       VisitTemplateDecl(TTPD);
    928       // FIXME: print the default argument, if present.
    929     }
    930   }
    931 
    932   Out << "> ";
    933 }
    934 
    935 void DeclPrinter::VisitTemplateDecl(const TemplateDecl *D) {
    936   PrintTemplateParameters(D->getTemplateParameters());
    937 
    938   if (const TemplateTemplateParmDecl *TTP =
    939         dyn_cast<TemplateTemplateParmDecl>(D)) {
    940     Out << "class ";
    941     if (TTP->isParameterPack())
    942       Out << "...";
    943     Out << D->getName();
    944   } else {
    945     Visit(D->getTemplatedDecl());
    946   }
    947 }
    948 
    949 void DeclPrinter::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
    950   if (PrintInstantiation) {
    951     TemplateParameterList *Params = D->getTemplateParameters();
    952     for (auto *I : D->specializations()) {
    953       prettyPrintPragmas(I);
    954       PrintTemplateParameters(Params, I->getTemplateSpecializationArgs());
    955       Visit(I);
    956     }
    957   }
    958 
    959   prettyPrintPragmas(D->getTemplatedDecl());
    960   return VisitRedeclarableTemplateDecl(D);
    961 }
    962 
    963 void DeclPrinter::VisitClassTemplateDecl(ClassTemplateDecl *D) {
    964   if (PrintInstantiation) {
    965     TemplateParameterList *Params = D->getTemplateParameters();
    966     for (auto *I : D->specializations()) {
    967       PrintTemplateParameters(Params, &I->getTemplateArgs());
    968       Visit(I);
    969       Out << '\n';
    970     }
    971   }
    972 
    973   return VisitRedeclarableTemplateDecl(D);
    974 }
    975 
    976 //----------------------------------------------------------------------------
    977 // Objective-C declarations
    978 //----------------------------------------------------------------------------
    979 
    980 void DeclPrinter::PrintObjCMethodType(ASTContext &Ctx,
    981                                       Decl::ObjCDeclQualifier Quals,
    982                                       QualType T) {
    983   Out << '(';
    984   if (Quals & Decl::ObjCDeclQualifier::OBJC_TQ_In)
    985     Out << "in ";
    986   if (Quals & Decl::ObjCDeclQualifier::OBJC_TQ_Inout)
    987     Out << "inout ";
    988   if (Quals & Decl::ObjCDeclQualifier::OBJC_TQ_Out)
    989     Out << "out ";
    990   if (Quals & Decl::ObjCDeclQualifier::OBJC_TQ_Bycopy)
    991     Out << "bycopy ";
    992   if (Quals & Decl::ObjCDeclQualifier::OBJC_TQ_Byref)
    993     Out << "byref ";
    994   if (Quals & Decl::ObjCDeclQualifier::OBJC_TQ_Oneway)
    995     Out << "oneway ";
    996   if (Quals & Decl::ObjCDeclQualifier::OBJC_TQ_CSNullability) {
    997     if (auto nullability = AttributedType::stripOuterNullability(T))
    998       Out << getNullabilitySpelling(*nullability, true) << ' ';
    999   }
   1000 
   1001   Out << Ctx.getUnqualifiedObjCPointerType(T).getAsString(Policy);
   1002   Out << ')';
   1003 }
   1004 
   1005 void DeclPrinter::PrintObjCTypeParams(ObjCTypeParamList *Params) {
   1006   Out << "<";
   1007   unsigned First = true;
   1008   for (auto *Param : *Params) {
   1009     if (First) {
   1010       First = false;
   1011     } else {
   1012       Out << ", ";
   1013     }
   1014 
   1015     switch (Param->getVariance()) {
   1016     case ObjCTypeParamVariance::Invariant:
   1017       break;
   1018 
   1019     case ObjCTypeParamVariance::Covariant:
   1020       Out << "__covariant ";
   1021       break;
   1022 
   1023     case ObjCTypeParamVariance::Contravariant:
   1024       Out << "__contravariant ";
   1025       break;
   1026     }
   1027 
   1028     Out << Param->getDeclName().getAsString();
   1029 
   1030     if (Param->hasExplicitBound()) {
   1031       Out << " : " << Param->getUnderlyingType().getAsString(Policy);
   1032     }
   1033   }
   1034   Out << ">";
   1035 }
   1036 
   1037 void DeclPrinter::VisitObjCMethodDecl(ObjCMethodDecl *OMD) {
   1038   if (OMD->isInstanceMethod())
   1039     Out << "- ";
   1040   else
   1041     Out << "+ ";
   1042   if (!OMD->getReturnType().isNull()) {
   1043     PrintObjCMethodType(OMD->getASTContext(), OMD->getObjCDeclQualifier(),
   1044                         OMD->getReturnType());
   1045   }
   1046 
   1047   std::string name = OMD->getSelector().getAsString();
   1048   std::string::size_type pos, lastPos = 0;
   1049   for (const auto *PI : OMD->params()) {
   1050     // FIXME: selector is missing here!
   1051     pos = name.find_first_of(':', lastPos);
   1052     Out << " " << name.substr(lastPos, pos - lastPos) << ':';
   1053     PrintObjCMethodType(OMD->getASTContext(),
   1054                         PI->getObjCDeclQualifier(),
   1055                         PI->getType());
   1056     Out << *PI;
   1057     lastPos = pos + 1;
   1058   }
   1059 
   1060   if (OMD->param_begin() == OMD->param_end())
   1061     Out << " " << name;
   1062 
   1063   if (OMD->isVariadic())
   1064       Out << ", ...";
   1065 
   1066   prettyPrintAttributes(OMD);
   1067 
   1068   if (OMD->getBody() && !Policy.TerseOutput) {
   1069     Out << ' ';
   1070     OMD->getBody()->printPretty(Out, nullptr, Policy);
   1071   }
   1072   else if (Policy.PolishForDeclaration)
   1073     Out << ';';
   1074 }
   1075 
   1076 void DeclPrinter::VisitObjCImplementationDecl(ObjCImplementationDecl *OID) {
   1077   std::string I = OID->getNameAsString();
   1078   ObjCInterfaceDecl *SID = OID->getSuperClass();
   1079 
   1080   bool eolnOut = false;
   1081   if (SID)
   1082     Out << "@implementation " << I << " : " << *SID;
   1083   else
   1084     Out << "@implementation " << I;
   1085 
   1086   if (OID->ivar_size() > 0) {
   1087     Out << "{\n";
   1088     eolnOut = true;
   1089     Indentation += Policy.Indentation;
   1090     for (const auto *I : OID->ivars()) {
   1091       Indent() << I->getASTContext().getUnqualifiedObjCPointerType(I->getType()).
   1092                     getAsString(Policy) << ' ' << *I << ";\n";
   1093     }
   1094     Indentation -= Policy.Indentation;
   1095     Out << "}\n";
   1096   }
   1097   else if (SID || (OID->decls_begin() != OID->decls_end())) {
   1098     Out << "\n";
   1099     eolnOut = true;
   1100   }
   1101   VisitDeclContext(OID, false);
   1102   if (!eolnOut)
   1103     Out << "\n";
   1104   Out << "@end";
   1105 }
   1106 
   1107 void DeclPrinter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *OID) {
   1108   std::string I = OID->getNameAsString();
   1109   ObjCInterfaceDecl *SID = OID->getSuperClass();
   1110 
   1111   if (!OID->isThisDeclarationADefinition()) {
   1112     Out << "@class " << I;
   1113 
   1114     if (auto TypeParams = OID->getTypeParamListAsWritten()) {
   1115       PrintObjCTypeParams(TypeParams);
   1116     }
   1117 
   1118     Out << ";";
   1119     return;
   1120   }
   1121   bool eolnOut = false;
   1122   Out << "@interface " << I;
   1123 
   1124   if (auto TypeParams = OID->getTypeParamListAsWritten()) {
   1125     PrintObjCTypeParams(TypeParams);
   1126   }
   1127 
   1128   if (SID)
   1129     Out << " : " << QualType(OID->getSuperClassType(), 0).getAsString(Policy);
   1130 
   1131   // Protocols?
   1132   const ObjCList<ObjCProtocolDecl> &Protocols = OID->getReferencedProtocols();
   1133   if (!Protocols.empty()) {
   1134     for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
   1135          E = Protocols.end(); I != E; ++I)
   1136       Out << (I == Protocols.begin() ? '<' : ',') << **I;
   1137     Out << "> ";
   1138   }
   1139 
   1140   if (OID->ivar_size() > 0) {
   1141     Out << "{\n";
   1142     eolnOut = true;
   1143     Indentation += Policy.Indentation;
   1144     for (const auto *I : OID->ivars()) {
   1145       Indent() << I->getASTContext()
   1146                       .getUnqualifiedObjCPointerType(I->getType())
   1147                       .getAsString(Policy) << ' ' << *I << ";\n";
   1148     }
   1149     Indentation -= Policy.Indentation;
   1150     Out << "}\n";
   1151   }
   1152   else if (SID || (OID->decls_begin() != OID->decls_end())) {
   1153     Out << "\n";
   1154     eolnOut = true;
   1155   }
   1156 
   1157   VisitDeclContext(OID, false);
   1158   if (!eolnOut)
   1159     Out << "\n";
   1160   Out << "@end";
   1161   // FIXME: implement the rest...
   1162 }
   1163 
   1164 void DeclPrinter::VisitObjCProtocolDecl(ObjCProtocolDecl *PID) {
   1165   if (!PID->isThisDeclarationADefinition()) {
   1166     Out << "@protocol " << *PID << ";\n";
   1167     return;
   1168   }
   1169   // Protocols?
   1170   const ObjCList<ObjCProtocolDecl> &Protocols = PID->getReferencedProtocols();
   1171   if (!Protocols.empty()) {
   1172     Out << "@protocol " << *PID;
   1173     for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
   1174          E = Protocols.end(); I != E; ++I)
   1175       Out << (I == Protocols.begin() ? '<' : ',') << **I;
   1176     Out << ">\n";
   1177   } else
   1178     Out << "@protocol " << *PID << '\n';
   1179   VisitDeclContext(PID, false);
   1180   Out << "@end";
   1181 }
   1182 
   1183 void DeclPrinter::VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *PID) {
   1184   Out << "@implementation " << *PID->getClassInterface() << '(' << *PID <<")\n";
   1185 
   1186   VisitDeclContext(PID, false);
   1187   Out << "@end";
   1188   // FIXME: implement the rest...
   1189 }
   1190 
   1191 void DeclPrinter::VisitObjCCategoryDecl(ObjCCategoryDecl *PID) {
   1192   Out << "@interface " << *PID->getClassInterface();
   1193   if (auto TypeParams = PID->getTypeParamList()) {
   1194     PrintObjCTypeParams(TypeParams);
   1195   }
   1196   Out << "(" << *PID << ")\n";
   1197   if (PID->ivar_size() > 0) {
   1198     Out << "{\n";
   1199     Indentation += Policy.Indentation;
   1200     for (const auto *I : PID->ivars())
   1201       Indent() << I->getASTContext().getUnqualifiedObjCPointerType(I->getType()).
   1202                     getAsString(Policy) << ' ' << *I << ";\n";
   1203     Indentation -= Policy.Indentation;
   1204     Out << "}\n";
   1205   }
   1206 
   1207   VisitDeclContext(PID, false);
   1208   Out << "@end";
   1209 
   1210   // FIXME: implement the rest...
   1211 }
   1212 
   1213 void DeclPrinter::VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *AID) {
   1214   Out << "@compatibility_alias " << *AID
   1215       << ' ' << *AID->getClassInterface() << ";\n";
   1216 }
   1217 
   1218 /// PrintObjCPropertyDecl - print a property declaration.
   1219 ///
   1220 void DeclPrinter::VisitObjCPropertyDecl(ObjCPropertyDecl *PDecl) {
   1221   if (PDecl->getPropertyImplementation() == ObjCPropertyDecl::Required)
   1222     Out << "@required\n";
   1223   else if (PDecl->getPropertyImplementation() == ObjCPropertyDecl::Optional)
   1224     Out << "@optional\n";
   1225 
   1226   QualType T = PDecl->getType();
   1227 
   1228   Out << "@property";
   1229   if (PDecl->getPropertyAttributes() != ObjCPropertyDecl::OBJC_PR_noattr) {
   1230     bool first = true;
   1231     Out << " (";
   1232     if (PDecl->getPropertyAttributes() &
   1233         ObjCPropertyDecl::OBJC_PR_readonly) {
   1234       Out << (first ? ' ' : ',') << "readonly";
   1235       first = false;
   1236     }
   1237 
   1238     if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_getter) {
   1239       Out << (first ? ' ' : ',') << "getter = ";
   1240       PDecl->getGetterName().print(Out);
   1241       first = false;
   1242     }
   1243     if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_setter) {
   1244       Out << (first ? ' ' : ',') << "setter = ";
   1245       PDecl->getSetterName().print(Out);
   1246       first = false;
   1247     }
   1248 
   1249     if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_assign) {
   1250       Out << (first ? ' ' : ',') << "assign";
   1251       first = false;
   1252     }
   1253 
   1254     if (PDecl->getPropertyAttributes() &
   1255         ObjCPropertyDecl::OBJC_PR_readwrite) {
   1256       Out << (first ? ' ' : ',') << "readwrite";
   1257       first = false;
   1258     }
   1259 
   1260     if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_retain) {
   1261       Out << (first ? ' ' : ',') << "retain";
   1262       first = false;
   1263     }
   1264 
   1265     if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_strong) {
   1266       Out << (first ? ' ' : ',') << "strong";
   1267       first = false;
   1268     }
   1269 
   1270     if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_copy) {
   1271       Out << (first ? ' ' : ',') << "copy";
   1272       first = false;
   1273     }
   1274 
   1275     if (PDecl->getPropertyAttributes() &
   1276         ObjCPropertyDecl::OBJC_PR_nonatomic) {
   1277       Out << (first ? ' ' : ',') << "nonatomic";
   1278       first = false;
   1279     }
   1280     if (PDecl->getPropertyAttributes() &
   1281         ObjCPropertyDecl::OBJC_PR_atomic) {
   1282       Out << (first ? ' ' : ',') << "atomic";
   1283       first = false;
   1284     }
   1285 
   1286     if (PDecl->getPropertyAttributes() &
   1287         ObjCPropertyDecl::OBJC_PR_nullability) {
   1288       if (auto nullability = AttributedType::stripOuterNullability(T)) {
   1289         if (*nullability == NullabilityKind::Unspecified &&
   1290             (PDecl->getPropertyAttributes() &
   1291                ObjCPropertyDecl::OBJC_PR_null_resettable)) {
   1292           Out << (first ? ' ' : ',') << "null_resettable";
   1293         } else {
   1294           Out << (first ? ' ' : ',')
   1295               << getNullabilitySpelling(*nullability, true);
   1296         }
   1297         first = false;
   1298       }
   1299     }
   1300 
   1301     (void) first; // Silence dead store warning due to idiomatic code.
   1302     Out << " )";
   1303   }
   1304   Out << ' ' << PDecl->getASTContext().getUnqualifiedObjCPointerType(T).
   1305                   getAsString(Policy) << ' ' << *PDecl;
   1306   if (Policy.PolishForDeclaration)
   1307     Out << ';';
   1308 }
   1309 
   1310 void DeclPrinter::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *PID) {
   1311   if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize)
   1312     Out << "@synthesize ";
   1313   else
   1314     Out << "@dynamic ";
   1315   Out << *PID->getPropertyDecl();
   1316   if (PID->getPropertyIvarDecl())
   1317     Out << '=' << *PID->getPropertyIvarDecl();
   1318 }
   1319 
   1320 void DeclPrinter::VisitUsingDecl(UsingDecl *D) {
   1321   if (!D->isAccessDeclaration())
   1322     Out << "using ";
   1323   if (D->hasTypename())
   1324     Out << "typename ";
   1325   D->getQualifier()->print(Out, Policy);
   1326   Out << *D;
   1327 }
   1328 
   1329 void
   1330 DeclPrinter::VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D) {
   1331   Out << "using typename ";
   1332   D->getQualifier()->print(Out, Policy);
   1333   Out << D->getDeclName();
   1334 }
   1335 
   1336 void DeclPrinter::VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D) {
   1337   if (!D->isAccessDeclaration())
   1338     Out << "using ";
   1339   D->getQualifier()->print(Out, Policy);
   1340   Out << D->getDeclName();
   1341 }
   1342 
   1343 void DeclPrinter::VisitUsingShadowDecl(UsingShadowDecl *D) {
   1344   // ignore
   1345 }
   1346 
   1347 void DeclPrinter::VisitOMPThreadPrivateDecl(OMPThreadPrivateDecl *D) {
   1348   Out << "#pragma omp threadprivate";
   1349   if (!D->varlist_empty()) {
   1350     for (OMPThreadPrivateDecl::varlist_iterator I = D->varlist_begin(),
   1351                                                 E = D->varlist_end();
   1352                                                 I != E; ++I) {
   1353       Out << (I == D->varlist_begin() ? '(' : ',');
   1354       NamedDecl *ND = cast<NamedDecl>(cast<DeclRefExpr>(*I)->getDecl());
   1355       ND->printQualifiedName(Out);
   1356     }
   1357     Out << ")";
   1358   }
   1359 }
   1360 
   1361