1e5dd7070Spatrick //===--- DeclPrinter.cpp - Printing implementation for Decl ASTs ----------===// 2e5dd7070Spatrick // 3e5dd7070Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4e5dd7070Spatrick // See https://llvm.org/LICENSE.txt for license information. 5e5dd7070Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6e5dd7070Spatrick // 7e5dd7070Spatrick //===----------------------------------------------------------------------===// 8e5dd7070Spatrick // 9e5dd7070Spatrick // This file implements the Decl::print method, which pretty prints the 10e5dd7070Spatrick // AST back out to C/Objective-C/C++/Objective-C++ code. 11e5dd7070Spatrick // 12e5dd7070Spatrick //===----------------------------------------------------------------------===// 13e5dd7070Spatrick #include "clang/AST/ASTContext.h" 14e5dd7070Spatrick #include "clang/AST/Attr.h" 15e5dd7070Spatrick #include "clang/AST/Decl.h" 16e5dd7070Spatrick #include "clang/AST/DeclCXX.h" 17e5dd7070Spatrick #include "clang/AST/DeclObjC.h" 18e5dd7070Spatrick #include "clang/AST/DeclTemplate.h" 19e5dd7070Spatrick #include "clang/AST/DeclVisitor.h" 20e5dd7070Spatrick #include "clang/AST/Expr.h" 21e5dd7070Spatrick #include "clang/AST/ExprCXX.h" 22e5dd7070Spatrick #include "clang/AST/PrettyPrinter.h" 23e5dd7070Spatrick #include "clang/Basic/Module.h" 24e5dd7070Spatrick #include "llvm/Support/raw_ostream.h" 25e5dd7070Spatrick using namespace clang; 26e5dd7070Spatrick 27e5dd7070Spatrick namespace { 28e5dd7070Spatrick class DeclPrinter : public DeclVisitor<DeclPrinter> { 29e5dd7070Spatrick raw_ostream &Out; 30e5dd7070Spatrick PrintingPolicy Policy; 31e5dd7070Spatrick const ASTContext &Context; 32e5dd7070Spatrick unsigned Indentation; 33e5dd7070Spatrick bool PrintInstantiation; 34e5dd7070Spatrick 35e5dd7070Spatrick raw_ostream& Indent() { return Indent(Indentation); } 36e5dd7070Spatrick raw_ostream& Indent(unsigned Indentation); 37e5dd7070Spatrick void ProcessDeclGroup(SmallVectorImpl<Decl*>& Decls); 38e5dd7070Spatrick 39e5dd7070Spatrick void Print(AccessSpecifier AS); 40e5dd7070Spatrick void PrintConstructorInitializers(CXXConstructorDecl *CDecl, 41e5dd7070Spatrick std::string &Proto); 42e5dd7070Spatrick 43e5dd7070Spatrick /// Print an Objective-C method type in parentheses. 44e5dd7070Spatrick /// 45e5dd7070Spatrick /// \param Quals The Objective-C declaration qualifiers. 46e5dd7070Spatrick /// \param T The type to print. 47e5dd7070Spatrick void PrintObjCMethodType(ASTContext &Ctx, Decl::ObjCDeclQualifier Quals, 48e5dd7070Spatrick QualType T); 49e5dd7070Spatrick 50e5dd7070Spatrick void PrintObjCTypeParams(ObjCTypeParamList *Params); 51e5dd7070Spatrick 52e5dd7070Spatrick public: 53e5dd7070Spatrick DeclPrinter(raw_ostream &Out, const PrintingPolicy &Policy, 54e5dd7070Spatrick const ASTContext &Context, unsigned Indentation = 0, 55e5dd7070Spatrick bool PrintInstantiation = false) 56e5dd7070Spatrick : Out(Out), Policy(Policy), Context(Context), Indentation(Indentation), 57e5dd7070Spatrick PrintInstantiation(PrintInstantiation) {} 58e5dd7070Spatrick 59e5dd7070Spatrick void VisitDeclContext(DeclContext *DC, bool Indent = true); 60e5dd7070Spatrick 61e5dd7070Spatrick void VisitTranslationUnitDecl(TranslationUnitDecl *D); 62e5dd7070Spatrick void VisitTypedefDecl(TypedefDecl *D); 63e5dd7070Spatrick void VisitTypeAliasDecl(TypeAliasDecl *D); 64e5dd7070Spatrick void VisitEnumDecl(EnumDecl *D); 65e5dd7070Spatrick void VisitRecordDecl(RecordDecl *D); 66e5dd7070Spatrick void VisitEnumConstantDecl(EnumConstantDecl *D); 67e5dd7070Spatrick void VisitEmptyDecl(EmptyDecl *D); 68e5dd7070Spatrick void VisitFunctionDecl(FunctionDecl *D); 69e5dd7070Spatrick void VisitFriendDecl(FriendDecl *D); 70e5dd7070Spatrick void VisitFieldDecl(FieldDecl *D); 71e5dd7070Spatrick void VisitVarDecl(VarDecl *D); 72e5dd7070Spatrick void VisitLabelDecl(LabelDecl *D); 73e5dd7070Spatrick void VisitParmVarDecl(ParmVarDecl *D); 74e5dd7070Spatrick void VisitFileScopeAsmDecl(FileScopeAsmDecl *D); 75e5dd7070Spatrick void VisitImportDecl(ImportDecl *D); 76e5dd7070Spatrick void VisitStaticAssertDecl(StaticAssertDecl *D); 77e5dd7070Spatrick void VisitNamespaceDecl(NamespaceDecl *D); 78e5dd7070Spatrick void VisitUsingDirectiveDecl(UsingDirectiveDecl *D); 79e5dd7070Spatrick void VisitNamespaceAliasDecl(NamespaceAliasDecl *D); 80e5dd7070Spatrick void VisitCXXRecordDecl(CXXRecordDecl *D); 81e5dd7070Spatrick void VisitLinkageSpecDecl(LinkageSpecDecl *D); 82e5dd7070Spatrick void VisitTemplateDecl(const TemplateDecl *D); 83e5dd7070Spatrick void VisitFunctionTemplateDecl(FunctionTemplateDecl *D); 84e5dd7070Spatrick void VisitClassTemplateDecl(ClassTemplateDecl *D); 85e5dd7070Spatrick void VisitClassTemplateSpecializationDecl( 86e5dd7070Spatrick ClassTemplateSpecializationDecl *D); 87e5dd7070Spatrick void VisitClassTemplatePartialSpecializationDecl( 88e5dd7070Spatrick ClassTemplatePartialSpecializationDecl *D); 89e5dd7070Spatrick void VisitObjCMethodDecl(ObjCMethodDecl *D); 90e5dd7070Spatrick void VisitObjCImplementationDecl(ObjCImplementationDecl *D); 91e5dd7070Spatrick void VisitObjCInterfaceDecl(ObjCInterfaceDecl *D); 92e5dd7070Spatrick void VisitObjCProtocolDecl(ObjCProtocolDecl *D); 93e5dd7070Spatrick void VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D); 94e5dd7070Spatrick void VisitObjCCategoryDecl(ObjCCategoryDecl *D); 95e5dd7070Spatrick void VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *D); 96e5dd7070Spatrick void VisitObjCPropertyDecl(ObjCPropertyDecl *D); 97e5dd7070Spatrick void VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D); 98e5dd7070Spatrick void VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D); 99e5dd7070Spatrick void VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D); 100e5dd7070Spatrick void VisitUsingDecl(UsingDecl *D); 101*a9ac8606Spatrick void VisitUsingEnumDecl(UsingEnumDecl *D); 102e5dd7070Spatrick void VisitUsingShadowDecl(UsingShadowDecl *D); 103e5dd7070Spatrick void VisitOMPThreadPrivateDecl(OMPThreadPrivateDecl *D); 104e5dd7070Spatrick void VisitOMPAllocateDecl(OMPAllocateDecl *D); 105e5dd7070Spatrick void VisitOMPRequiresDecl(OMPRequiresDecl *D); 106e5dd7070Spatrick void VisitOMPDeclareReductionDecl(OMPDeclareReductionDecl *D); 107e5dd7070Spatrick void VisitOMPDeclareMapperDecl(OMPDeclareMapperDecl *D); 108e5dd7070Spatrick void VisitOMPCapturedExprDecl(OMPCapturedExprDecl *D); 109ec727ea7Spatrick void VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *TTP); 110ec727ea7Spatrick void VisitNonTypeTemplateParmDecl(const NonTypeTemplateParmDecl *NTTP); 111e5dd7070Spatrick 112e5dd7070Spatrick void printTemplateParameters(const TemplateParameterList *Params, 113e5dd7070Spatrick bool OmitTemplateKW = false); 114*a9ac8606Spatrick void printTemplateArguments(llvm::ArrayRef<TemplateArgument> Args, 115*a9ac8606Spatrick const TemplateParameterList *Params, 116*a9ac8606Spatrick bool TemplOverloaded); 117*a9ac8606Spatrick void printTemplateArguments(llvm::ArrayRef<TemplateArgumentLoc> Args, 118*a9ac8606Spatrick const TemplateParameterList *Params, 119*a9ac8606Spatrick bool TemplOverloaded); 120e5dd7070Spatrick void prettyPrintAttributes(Decl *D); 121e5dd7070Spatrick void prettyPrintPragmas(Decl *D); 122e5dd7070Spatrick void printDeclType(QualType T, StringRef DeclName, bool Pack = false); 123e5dd7070Spatrick }; 124e5dd7070Spatrick } 125e5dd7070Spatrick 126e5dd7070Spatrick void Decl::print(raw_ostream &Out, unsigned Indentation, 127e5dd7070Spatrick bool PrintInstantiation) const { 128e5dd7070Spatrick print(Out, getASTContext().getPrintingPolicy(), Indentation, PrintInstantiation); 129e5dd7070Spatrick } 130e5dd7070Spatrick 131e5dd7070Spatrick void Decl::print(raw_ostream &Out, const PrintingPolicy &Policy, 132e5dd7070Spatrick unsigned Indentation, bool PrintInstantiation) const { 133e5dd7070Spatrick DeclPrinter Printer(Out, Policy, getASTContext(), Indentation, 134e5dd7070Spatrick PrintInstantiation); 135e5dd7070Spatrick Printer.Visit(const_cast<Decl*>(this)); 136e5dd7070Spatrick } 137e5dd7070Spatrick 138e5dd7070Spatrick void TemplateParameterList::print(raw_ostream &Out, const ASTContext &Context, 139e5dd7070Spatrick bool OmitTemplateKW) const { 140e5dd7070Spatrick print(Out, Context, Context.getPrintingPolicy(), OmitTemplateKW); 141e5dd7070Spatrick } 142e5dd7070Spatrick 143e5dd7070Spatrick void TemplateParameterList::print(raw_ostream &Out, const ASTContext &Context, 144e5dd7070Spatrick const PrintingPolicy &Policy, 145e5dd7070Spatrick bool OmitTemplateKW) const { 146e5dd7070Spatrick DeclPrinter Printer(Out, Policy, Context); 147e5dd7070Spatrick Printer.printTemplateParameters(this, OmitTemplateKW); 148e5dd7070Spatrick } 149e5dd7070Spatrick 150e5dd7070Spatrick static QualType GetBaseType(QualType T) { 151e5dd7070Spatrick // FIXME: This should be on the Type class! 152e5dd7070Spatrick QualType BaseType = T; 153e5dd7070Spatrick while (!BaseType->isSpecifierType()) { 154e5dd7070Spatrick if (const PointerType *PTy = BaseType->getAs<PointerType>()) 155e5dd7070Spatrick BaseType = PTy->getPointeeType(); 156e5dd7070Spatrick else if (const BlockPointerType *BPy = BaseType->getAs<BlockPointerType>()) 157e5dd7070Spatrick BaseType = BPy->getPointeeType(); 158e5dd7070Spatrick else if (const ArrayType* ATy = dyn_cast<ArrayType>(BaseType)) 159e5dd7070Spatrick BaseType = ATy->getElementType(); 160e5dd7070Spatrick else if (const FunctionType* FTy = BaseType->getAs<FunctionType>()) 161e5dd7070Spatrick BaseType = FTy->getReturnType(); 162e5dd7070Spatrick else if (const VectorType *VTy = BaseType->getAs<VectorType>()) 163e5dd7070Spatrick BaseType = VTy->getElementType(); 164e5dd7070Spatrick else if (const ReferenceType *RTy = BaseType->getAs<ReferenceType>()) 165e5dd7070Spatrick BaseType = RTy->getPointeeType(); 166e5dd7070Spatrick else if (const AutoType *ATy = BaseType->getAs<AutoType>()) 167e5dd7070Spatrick BaseType = ATy->getDeducedType(); 168e5dd7070Spatrick else if (const ParenType *PTy = BaseType->getAs<ParenType>()) 169e5dd7070Spatrick BaseType = PTy->desugar(); 170e5dd7070Spatrick else 171e5dd7070Spatrick // This must be a syntax error. 172e5dd7070Spatrick break; 173e5dd7070Spatrick } 174e5dd7070Spatrick return BaseType; 175e5dd7070Spatrick } 176e5dd7070Spatrick 177e5dd7070Spatrick static QualType getDeclType(Decl* D) { 178e5dd7070Spatrick if (TypedefNameDecl* TDD = dyn_cast<TypedefNameDecl>(D)) 179e5dd7070Spatrick return TDD->getUnderlyingType(); 180e5dd7070Spatrick if (ValueDecl* VD = dyn_cast<ValueDecl>(D)) 181e5dd7070Spatrick return VD->getType(); 182e5dd7070Spatrick return QualType(); 183e5dd7070Spatrick } 184e5dd7070Spatrick 185e5dd7070Spatrick void Decl::printGroup(Decl** Begin, unsigned NumDecls, 186e5dd7070Spatrick raw_ostream &Out, const PrintingPolicy &Policy, 187e5dd7070Spatrick unsigned Indentation) { 188e5dd7070Spatrick if (NumDecls == 1) { 189e5dd7070Spatrick (*Begin)->print(Out, Policy, Indentation); 190e5dd7070Spatrick return; 191e5dd7070Spatrick } 192e5dd7070Spatrick 193e5dd7070Spatrick Decl** End = Begin + NumDecls; 194e5dd7070Spatrick TagDecl* TD = dyn_cast<TagDecl>(*Begin); 195e5dd7070Spatrick if (TD) 196e5dd7070Spatrick ++Begin; 197e5dd7070Spatrick 198e5dd7070Spatrick PrintingPolicy SubPolicy(Policy); 199e5dd7070Spatrick 200e5dd7070Spatrick bool isFirst = true; 201e5dd7070Spatrick for ( ; Begin != End; ++Begin) { 202e5dd7070Spatrick if (isFirst) { 203e5dd7070Spatrick if(TD) 204e5dd7070Spatrick SubPolicy.IncludeTagDefinition = true; 205e5dd7070Spatrick SubPolicy.SuppressSpecifiers = false; 206e5dd7070Spatrick isFirst = false; 207e5dd7070Spatrick } else { 208e5dd7070Spatrick if (!isFirst) Out << ", "; 209e5dd7070Spatrick SubPolicy.IncludeTagDefinition = false; 210e5dd7070Spatrick SubPolicy.SuppressSpecifiers = true; 211e5dd7070Spatrick } 212e5dd7070Spatrick 213e5dd7070Spatrick (*Begin)->print(Out, SubPolicy, Indentation); 214e5dd7070Spatrick } 215e5dd7070Spatrick } 216e5dd7070Spatrick 217e5dd7070Spatrick LLVM_DUMP_METHOD void DeclContext::dumpDeclContext() const { 218e5dd7070Spatrick // Get the translation unit 219e5dd7070Spatrick const DeclContext *DC = this; 220e5dd7070Spatrick while (!DC->isTranslationUnit()) 221e5dd7070Spatrick DC = DC->getParent(); 222e5dd7070Spatrick 223e5dd7070Spatrick ASTContext &Ctx = cast<TranslationUnitDecl>(DC)->getASTContext(); 224e5dd7070Spatrick DeclPrinter Printer(llvm::errs(), Ctx.getPrintingPolicy(), Ctx, 0); 225e5dd7070Spatrick Printer.VisitDeclContext(const_cast<DeclContext *>(this), /*Indent=*/false); 226e5dd7070Spatrick } 227e5dd7070Spatrick 228e5dd7070Spatrick raw_ostream& DeclPrinter::Indent(unsigned Indentation) { 229e5dd7070Spatrick for (unsigned i = 0; i != Indentation; ++i) 230e5dd7070Spatrick Out << " "; 231e5dd7070Spatrick return Out; 232e5dd7070Spatrick } 233e5dd7070Spatrick 234e5dd7070Spatrick void DeclPrinter::prettyPrintAttributes(Decl *D) { 235e5dd7070Spatrick if (Policy.PolishForDeclaration) 236e5dd7070Spatrick return; 237e5dd7070Spatrick 238e5dd7070Spatrick if (D->hasAttrs()) { 239e5dd7070Spatrick AttrVec &Attrs = D->getAttrs(); 240e5dd7070Spatrick for (auto *A : Attrs) { 241e5dd7070Spatrick if (A->isInherited() || A->isImplicit()) 242e5dd7070Spatrick continue; 243e5dd7070Spatrick switch (A->getKind()) { 244e5dd7070Spatrick #define ATTR(X) 245e5dd7070Spatrick #define PRAGMA_SPELLING_ATTR(X) case attr::X: 246e5dd7070Spatrick #include "clang/Basic/AttrList.inc" 247e5dd7070Spatrick break; 248e5dd7070Spatrick default: 249e5dd7070Spatrick A->printPretty(Out, Policy); 250e5dd7070Spatrick break; 251e5dd7070Spatrick } 252e5dd7070Spatrick } 253e5dd7070Spatrick } 254e5dd7070Spatrick } 255e5dd7070Spatrick 256e5dd7070Spatrick void DeclPrinter::prettyPrintPragmas(Decl *D) { 257e5dd7070Spatrick if (Policy.PolishForDeclaration) 258e5dd7070Spatrick return; 259e5dd7070Spatrick 260e5dd7070Spatrick if (D->hasAttrs()) { 261e5dd7070Spatrick AttrVec &Attrs = D->getAttrs(); 262e5dd7070Spatrick for (auto *A : Attrs) { 263e5dd7070Spatrick switch (A->getKind()) { 264e5dd7070Spatrick #define ATTR(X) 265e5dd7070Spatrick #define PRAGMA_SPELLING_ATTR(X) case attr::X: 266e5dd7070Spatrick #include "clang/Basic/AttrList.inc" 267e5dd7070Spatrick A->printPretty(Out, Policy); 268e5dd7070Spatrick Indent(); 269e5dd7070Spatrick break; 270e5dd7070Spatrick default: 271e5dd7070Spatrick break; 272e5dd7070Spatrick } 273e5dd7070Spatrick } 274e5dd7070Spatrick } 275e5dd7070Spatrick } 276e5dd7070Spatrick 277e5dd7070Spatrick void DeclPrinter::printDeclType(QualType T, StringRef DeclName, bool Pack) { 278e5dd7070Spatrick // Normally, a PackExpansionType is written as T[3]... (for instance, as a 279e5dd7070Spatrick // template argument), but if it is the type of a declaration, the ellipsis 280e5dd7070Spatrick // is placed before the name being declared. 281e5dd7070Spatrick if (auto *PET = T->getAs<PackExpansionType>()) { 282e5dd7070Spatrick Pack = true; 283e5dd7070Spatrick T = PET->getPattern(); 284e5dd7070Spatrick } 285e5dd7070Spatrick T.print(Out, Policy, (Pack ? "..." : "") + DeclName, Indentation); 286e5dd7070Spatrick } 287e5dd7070Spatrick 288e5dd7070Spatrick void DeclPrinter::ProcessDeclGroup(SmallVectorImpl<Decl*>& Decls) { 289e5dd7070Spatrick this->Indent(); 290e5dd7070Spatrick Decl::printGroup(Decls.data(), Decls.size(), Out, Policy, Indentation); 291e5dd7070Spatrick Out << ";\n"; 292e5dd7070Spatrick Decls.clear(); 293e5dd7070Spatrick 294e5dd7070Spatrick } 295e5dd7070Spatrick 296e5dd7070Spatrick void DeclPrinter::Print(AccessSpecifier AS) { 297ec727ea7Spatrick const auto AccessSpelling = getAccessSpelling(AS); 298ec727ea7Spatrick if (AccessSpelling.empty()) 299ec727ea7Spatrick llvm_unreachable("No access specifier!"); 300ec727ea7Spatrick Out << AccessSpelling; 301e5dd7070Spatrick } 302e5dd7070Spatrick 303e5dd7070Spatrick void DeclPrinter::PrintConstructorInitializers(CXXConstructorDecl *CDecl, 304e5dd7070Spatrick std::string &Proto) { 305e5dd7070Spatrick bool HasInitializerList = false; 306e5dd7070Spatrick for (const auto *BMInitializer : CDecl->inits()) { 307e5dd7070Spatrick if (BMInitializer->isInClassMemberInitializer()) 308e5dd7070Spatrick continue; 309e5dd7070Spatrick 310e5dd7070Spatrick if (!HasInitializerList) { 311e5dd7070Spatrick Proto += " : "; 312e5dd7070Spatrick Out << Proto; 313e5dd7070Spatrick Proto.clear(); 314e5dd7070Spatrick HasInitializerList = true; 315e5dd7070Spatrick } else 316e5dd7070Spatrick Out << ", "; 317e5dd7070Spatrick 318e5dd7070Spatrick if (BMInitializer->isAnyMemberInitializer()) { 319e5dd7070Spatrick FieldDecl *FD = BMInitializer->getAnyMember(); 320e5dd7070Spatrick Out << *FD; 321e5dd7070Spatrick } else { 322e5dd7070Spatrick Out << QualType(BMInitializer->getBaseClass(), 0).getAsString(Policy); 323e5dd7070Spatrick } 324e5dd7070Spatrick 325e5dd7070Spatrick Out << "("; 326e5dd7070Spatrick if (!BMInitializer->getInit()) { 327e5dd7070Spatrick // Nothing to print 328e5dd7070Spatrick } else { 329e5dd7070Spatrick Expr *Init = BMInitializer->getInit(); 330e5dd7070Spatrick if (ExprWithCleanups *Tmp = dyn_cast<ExprWithCleanups>(Init)) 331e5dd7070Spatrick Init = Tmp->getSubExpr(); 332e5dd7070Spatrick 333e5dd7070Spatrick Init = Init->IgnoreParens(); 334e5dd7070Spatrick 335e5dd7070Spatrick Expr *SimpleInit = nullptr; 336e5dd7070Spatrick Expr **Args = nullptr; 337e5dd7070Spatrick unsigned NumArgs = 0; 338e5dd7070Spatrick if (ParenListExpr *ParenList = dyn_cast<ParenListExpr>(Init)) { 339e5dd7070Spatrick Args = ParenList->getExprs(); 340e5dd7070Spatrick NumArgs = ParenList->getNumExprs(); 341e5dd7070Spatrick } else if (CXXConstructExpr *Construct = 342e5dd7070Spatrick dyn_cast<CXXConstructExpr>(Init)) { 343e5dd7070Spatrick Args = Construct->getArgs(); 344e5dd7070Spatrick NumArgs = Construct->getNumArgs(); 345e5dd7070Spatrick } else 346e5dd7070Spatrick SimpleInit = Init; 347e5dd7070Spatrick 348e5dd7070Spatrick if (SimpleInit) 349*a9ac8606Spatrick SimpleInit->printPretty(Out, nullptr, Policy, Indentation, "\n", 350*a9ac8606Spatrick &Context); 351e5dd7070Spatrick else { 352e5dd7070Spatrick for (unsigned I = 0; I != NumArgs; ++I) { 353e5dd7070Spatrick assert(Args[I] != nullptr && "Expected non-null Expr"); 354e5dd7070Spatrick if (isa<CXXDefaultArgExpr>(Args[I])) 355e5dd7070Spatrick break; 356e5dd7070Spatrick 357e5dd7070Spatrick if (I) 358e5dd7070Spatrick Out << ", "; 359*a9ac8606Spatrick Args[I]->printPretty(Out, nullptr, Policy, Indentation, "\n", 360*a9ac8606Spatrick &Context); 361e5dd7070Spatrick } 362e5dd7070Spatrick } 363e5dd7070Spatrick } 364e5dd7070Spatrick Out << ")"; 365e5dd7070Spatrick if (BMInitializer->isPackExpansion()) 366e5dd7070Spatrick Out << "..."; 367e5dd7070Spatrick } 368e5dd7070Spatrick } 369e5dd7070Spatrick 370e5dd7070Spatrick //---------------------------------------------------------------------------- 371e5dd7070Spatrick // Common C declarations 372e5dd7070Spatrick //---------------------------------------------------------------------------- 373e5dd7070Spatrick 374e5dd7070Spatrick void DeclPrinter::VisitDeclContext(DeclContext *DC, bool Indent) { 375e5dd7070Spatrick if (Policy.TerseOutput) 376e5dd7070Spatrick return; 377e5dd7070Spatrick 378e5dd7070Spatrick if (Indent) 379e5dd7070Spatrick Indentation += Policy.Indentation; 380e5dd7070Spatrick 381e5dd7070Spatrick SmallVector<Decl*, 2> Decls; 382e5dd7070Spatrick for (DeclContext::decl_iterator D = DC->decls_begin(), DEnd = DC->decls_end(); 383e5dd7070Spatrick D != DEnd; ++D) { 384e5dd7070Spatrick 385e5dd7070Spatrick // Don't print ObjCIvarDecls, as they are printed when visiting the 386e5dd7070Spatrick // containing ObjCInterfaceDecl. 387e5dd7070Spatrick if (isa<ObjCIvarDecl>(*D)) 388e5dd7070Spatrick continue; 389e5dd7070Spatrick 390e5dd7070Spatrick // Skip over implicit declarations in pretty-printing mode. 391e5dd7070Spatrick if (D->isImplicit()) 392e5dd7070Spatrick continue; 393e5dd7070Spatrick 394e5dd7070Spatrick // Don't print implicit specializations, as they are printed when visiting 395e5dd7070Spatrick // corresponding templates. 396e5dd7070Spatrick if (auto FD = dyn_cast<FunctionDecl>(*D)) 397e5dd7070Spatrick if (FD->getTemplateSpecializationKind() == TSK_ImplicitInstantiation && 398e5dd7070Spatrick !isa<ClassTemplateSpecializationDecl>(DC)) 399e5dd7070Spatrick continue; 400e5dd7070Spatrick 401e5dd7070Spatrick // The next bits of code handle stuff like "struct {int x;} a,b"; we're 402e5dd7070Spatrick // forced to merge the declarations because there's no other way to 403e5dd7070Spatrick // refer to the struct in question. When that struct is named instead, we 404e5dd7070Spatrick // also need to merge to avoid splitting off a stand-alone struct 405e5dd7070Spatrick // declaration that produces the warning ext_no_declarators in some 406e5dd7070Spatrick // contexts. 407e5dd7070Spatrick // 408e5dd7070Spatrick // This limited merging is safe without a bunch of other checks because it 409e5dd7070Spatrick // only merges declarations directly referring to the tag, not typedefs. 410e5dd7070Spatrick // 411e5dd7070Spatrick // Check whether the current declaration should be grouped with a previous 412e5dd7070Spatrick // non-free-standing tag declaration. 413e5dd7070Spatrick QualType CurDeclType = getDeclType(*D); 414e5dd7070Spatrick if (!Decls.empty() && !CurDeclType.isNull()) { 415e5dd7070Spatrick QualType BaseType = GetBaseType(CurDeclType); 416e5dd7070Spatrick if (!BaseType.isNull() && isa<ElaboratedType>(BaseType) && 417e5dd7070Spatrick cast<ElaboratedType>(BaseType)->getOwnedTagDecl() == Decls[0]) { 418e5dd7070Spatrick Decls.push_back(*D); 419e5dd7070Spatrick continue; 420e5dd7070Spatrick } 421e5dd7070Spatrick } 422e5dd7070Spatrick 423e5dd7070Spatrick // If we have a merged group waiting to be handled, handle it now. 424e5dd7070Spatrick if (!Decls.empty()) 425e5dd7070Spatrick ProcessDeclGroup(Decls); 426e5dd7070Spatrick 427e5dd7070Spatrick // If the current declaration is not a free standing declaration, save it 428e5dd7070Spatrick // so we can merge it with the subsequent declaration(s) using it. 429e5dd7070Spatrick if (isa<TagDecl>(*D) && !cast<TagDecl>(*D)->isFreeStanding()) { 430e5dd7070Spatrick Decls.push_back(*D); 431e5dd7070Spatrick continue; 432e5dd7070Spatrick } 433e5dd7070Spatrick 434e5dd7070Spatrick if (isa<AccessSpecDecl>(*D)) { 435e5dd7070Spatrick Indentation -= Policy.Indentation; 436e5dd7070Spatrick this->Indent(); 437e5dd7070Spatrick Print(D->getAccess()); 438e5dd7070Spatrick Out << ":\n"; 439e5dd7070Spatrick Indentation += Policy.Indentation; 440e5dd7070Spatrick continue; 441e5dd7070Spatrick } 442e5dd7070Spatrick 443e5dd7070Spatrick this->Indent(); 444e5dd7070Spatrick Visit(*D); 445e5dd7070Spatrick 446e5dd7070Spatrick // FIXME: Need to be able to tell the DeclPrinter when 447e5dd7070Spatrick const char *Terminator = nullptr; 448e5dd7070Spatrick if (isa<OMPThreadPrivateDecl>(*D) || isa<OMPDeclareReductionDecl>(*D) || 449e5dd7070Spatrick isa<OMPDeclareMapperDecl>(*D) || isa<OMPRequiresDecl>(*D) || 450e5dd7070Spatrick isa<OMPAllocateDecl>(*D)) 451e5dd7070Spatrick Terminator = nullptr; 452e5dd7070Spatrick else if (isa<ObjCMethodDecl>(*D) && cast<ObjCMethodDecl>(*D)->hasBody()) 453e5dd7070Spatrick Terminator = nullptr; 454e5dd7070Spatrick else if (auto FD = dyn_cast<FunctionDecl>(*D)) { 455e5dd7070Spatrick if (FD->isThisDeclarationADefinition()) 456e5dd7070Spatrick Terminator = nullptr; 457e5dd7070Spatrick else 458e5dd7070Spatrick Terminator = ";"; 459e5dd7070Spatrick } else if (auto TD = dyn_cast<FunctionTemplateDecl>(*D)) { 460e5dd7070Spatrick if (TD->getTemplatedDecl()->isThisDeclarationADefinition()) 461e5dd7070Spatrick Terminator = nullptr; 462e5dd7070Spatrick else 463e5dd7070Spatrick Terminator = ";"; 464e5dd7070Spatrick } else if (isa<NamespaceDecl>(*D) || isa<LinkageSpecDecl>(*D) || 465e5dd7070Spatrick isa<ObjCImplementationDecl>(*D) || 466e5dd7070Spatrick isa<ObjCInterfaceDecl>(*D) || 467e5dd7070Spatrick isa<ObjCProtocolDecl>(*D) || 468e5dd7070Spatrick isa<ObjCCategoryImplDecl>(*D) || 469e5dd7070Spatrick isa<ObjCCategoryDecl>(*D)) 470e5dd7070Spatrick Terminator = nullptr; 471e5dd7070Spatrick else if (isa<EnumConstantDecl>(*D)) { 472e5dd7070Spatrick DeclContext::decl_iterator Next = D; 473e5dd7070Spatrick ++Next; 474e5dd7070Spatrick if (Next != DEnd) 475e5dd7070Spatrick Terminator = ","; 476e5dd7070Spatrick } else 477e5dd7070Spatrick Terminator = ";"; 478e5dd7070Spatrick 479e5dd7070Spatrick if (Terminator) 480e5dd7070Spatrick Out << Terminator; 481e5dd7070Spatrick if (!Policy.TerseOutput && 482e5dd7070Spatrick ((isa<FunctionDecl>(*D) && 483e5dd7070Spatrick cast<FunctionDecl>(*D)->doesThisDeclarationHaveABody()) || 484e5dd7070Spatrick (isa<FunctionTemplateDecl>(*D) && 485e5dd7070Spatrick cast<FunctionTemplateDecl>(*D)->getTemplatedDecl()->doesThisDeclarationHaveABody()))) 486e5dd7070Spatrick ; // StmtPrinter already added '\n' after CompoundStmt. 487e5dd7070Spatrick else 488e5dd7070Spatrick Out << "\n"; 489e5dd7070Spatrick 490e5dd7070Spatrick // Declare target attribute is special one, natural spelling for the pragma 491e5dd7070Spatrick // assumes "ending" construct so print it here. 492e5dd7070Spatrick if (D->hasAttr<OMPDeclareTargetDeclAttr>()) 493e5dd7070Spatrick Out << "#pragma omp end declare target\n"; 494e5dd7070Spatrick } 495e5dd7070Spatrick 496e5dd7070Spatrick if (!Decls.empty()) 497e5dd7070Spatrick ProcessDeclGroup(Decls); 498e5dd7070Spatrick 499e5dd7070Spatrick if (Indent) 500e5dd7070Spatrick Indentation -= Policy.Indentation; 501e5dd7070Spatrick } 502e5dd7070Spatrick 503e5dd7070Spatrick void DeclPrinter::VisitTranslationUnitDecl(TranslationUnitDecl *D) { 504e5dd7070Spatrick VisitDeclContext(D, false); 505e5dd7070Spatrick } 506e5dd7070Spatrick 507e5dd7070Spatrick void DeclPrinter::VisitTypedefDecl(TypedefDecl *D) { 508e5dd7070Spatrick if (!Policy.SuppressSpecifiers) { 509e5dd7070Spatrick Out << "typedef "; 510e5dd7070Spatrick 511e5dd7070Spatrick if (D->isModulePrivate()) 512e5dd7070Spatrick Out << "__module_private__ "; 513e5dd7070Spatrick } 514e5dd7070Spatrick QualType Ty = D->getTypeSourceInfo()->getType(); 515e5dd7070Spatrick Ty.print(Out, Policy, D->getName(), Indentation); 516e5dd7070Spatrick prettyPrintAttributes(D); 517e5dd7070Spatrick } 518e5dd7070Spatrick 519e5dd7070Spatrick void DeclPrinter::VisitTypeAliasDecl(TypeAliasDecl *D) { 520e5dd7070Spatrick Out << "using " << *D; 521e5dd7070Spatrick prettyPrintAttributes(D); 522e5dd7070Spatrick Out << " = " << D->getTypeSourceInfo()->getType().getAsString(Policy); 523e5dd7070Spatrick } 524e5dd7070Spatrick 525e5dd7070Spatrick void DeclPrinter::VisitEnumDecl(EnumDecl *D) { 526e5dd7070Spatrick if (!Policy.SuppressSpecifiers && D->isModulePrivate()) 527e5dd7070Spatrick Out << "__module_private__ "; 528e5dd7070Spatrick Out << "enum"; 529e5dd7070Spatrick if (D->isScoped()) { 530e5dd7070Spatrick if (D->isScopedUsingClassTag()) 531e5dd7070Spatrick Out << " class"; 532e5dd7070Spatrick else 533e5dd7070Spatrick Out << " struct"; 534e5dd7070Spatrick } 535e5dd7070Spatrick 536e5dd7070Spatrick prettyPrintAttributes(D); 537e5dd7070Spatrick 538*a9ac8606Spatrick if (D->getDeclName()) 539*a9ac8606Spatrick Out << ' ' << D->getDeclName(); 540e5dd7070Spatrick 541ec727ea7Spatrick if (D->isFixed()) 542e5dd7070Spatrick Out << " : " << D->getIntegerType().stream(Policy); 543e5dd7070Spatrick 544e5dd7070Spatrick if (D->isCompleteDefinition()) { 545e5dd7070Spatrick Out << " {\n"; 546e5dd7070Spatrick VisitDeclContext(D); 547e5dd7070Spatrick Indent() << "}"; 548e5dd7070Spatrick } 549e5dd7070Spatrick } 550e5dd7070Spatrick 551e5dd7070Spatrick void DeclPrinter::VisitRecordDecl(RecordDecl *D) { 552e5dd7070Spatrick if (!Policy.SuppressSpecifiers && D->isModulePrivate()) 553e5dd7070Spatrick Out << "__module_private__ "; 554e5dd7070Spatrick Out << D->getKindName(); 555e5dd7070Spatrick 556e5dd7070Spatrick prettyPrintAttributes(D); 557e5dd7070Spatrick 558e5dd7070Spatrick if (D->getIdentifier()) 559e5dd7070Spatrick Out << ' ' << *D; 560e5dd7070Spatrick 561e5dd7070Spatrick if (D->isCompleteDefinition()) { 562e5dd7070Spatrick Out << " {\n"; 563e5dd7070Spatrick VisitDeclContext(D); 564e5dd7070Spatrick Indent() << "}"; 565e5dd7070Spatrick } 566e5dd7070Spatrick } 567e5dd7070Spatrick 568e5dd7070Spatrick void DeclPrinter::VisitEnumConstantDecl(EnumConstantDecl *D) { 569e5dd7070Spatrick Out << *D; 570e5dd7070Spatrick prettyPrintAttributes(D); 571e5dd7070Spatrick if (Expr *Init = D->getInitExpr()) { 572e5dd7070Spatrick Out << " = "; 573e5dd7070Spatrick Init->printPretty(Out, nullptr, Policy, Indentation, "\n", &Context); 574e5dd7070Spatrick } 575e5dd7070Spatrick } 576e5dd7070Spatrick 577e5dd7070Spatrick static void printExplicitSpecifier(ExplicitSpecifier ES, llvm::raw_ostream &Out, 578*a9ac8606Spatrick PrintingPolicy &Policy, unsigned Indentation, 579*a9ac8606Spatrick const ASTContext &Context) { 580e5dd7070Spatrick std::string Proto = "explicit"; 581e5dd7070Spatrick llvm::raw_string_ostream EOut(Proto); 582e5dd7070Spatrick if (ES.getExpr()) { 583e5dd7070Spatrick EOut << "("; 584*a9ac8606Spatrick ES.getExpr()->printPretty(EOut, nullptr, Policy, Indentation, "\n", 585*a9ac8606Spatrick &Context); 586e5dd7070Spatrick EOut << ")"; 587e5dd7070Spatrick } 588e5dd7070Spatrick EOut << " "; 589e5dd7070Spatrick EOut.flush(); 590e5dd7070Spatrick Out << EOut.str(); 591e5dd7070Spatrick } 592e5dd7070Spatrick 593e5dd7070Spatrick void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) { 594e5dd7070Spatrick if (!D->getDescribedFunctionTemplate() && 595e5dd7070Spatrick !D->isFunctionTemplateSpecialization()) 596e5dd7070Spatrick prettyPrintPragmas(D); 597e5dd7070Spatrick 598e5dd7070Spatrick if (D->isFunctionTemplateSpecialization()) 599e5dd7070Spatrick Out << "template<> "; 600e5dd7070Spatrick else if (!D->getDescribedFunctionTemplate()) { 601e5dd7070Spatrick for (unsigned I = 0, NumTemplateParams = D->getNumTemplateParameterLists(); 602e5dd7070Spatrick I < NumTemplateParams; ++I) 603e5dd7070Spatrick printTemplateParameters(D->getTemplateParameterList(I)); 604e5dd7070Spatrick } 605e5dd7070Spatrick 606e5dd7070Spatrick CXXConstructorDecl *CDecl = dyn_cast<CXXConstructorDecl>(D); 607e5dd7070Spatrick CXXConversionDecl *ConversionDecl = dyn_cast<CXXConversionDecl>(D); 608e5dd7070Spatrick CXXDeductionGuideDecl *GuideDecl = dyn_cast<CXXDeductionGuideDecl>(D); 609e5dd7070Spatrick if (!Policy.SuppressSpecifiers) { 610e5dd7070Spatrick switch (D->getStorageClass()) { 611e5dd7070Spatrick case SC_None: break; 612e5dd7070Spatrick case SC_Extern: Out << "extern "; break; 613e5dd7070Spatrick case SC_Static: Out << "static "; break; 614e5dd7070Spatrick case SC_PrivateExtern: Out << "__private_extern__ "; break; 615e5dd7070Spatrick case SC_Auto: case SC_Register: 616e5dd7070Spatrick llvm_unreachable("invalid for functions"); 617e5dd7070Spatrick } 618e5dd7070Spatrick 619e5dd7070Spatrick if (D->isInlineSpecified()) Out << "inline "; 620e5dd7070Spatrick if (D->isVirtualAsWritten()) Out << "virtual "; 621e5dd7070Spatrick if (D->isModulePrivate()) Out << "__module_private__ "; 622e5dd7070Spatrick if (D->isConstexprSpecified() && !D->isExplicitlyDefaulted()) 623e5dd7070Spatrick Out << "constexpr "; 624e5dd7070Spatrick if (D->isConsteval()) Out << "consteval "; 625e5dd7070Spatrick ExplicitSpecifier ExplicitSpec = ExplicitSpecifier::getFromDecl(D); 626e5dd7070Spatrick if (ExplicitSpec.isSpecified()) 627*a9ac8606Spatrick printExplicitSpecifier(ExplicitSpec, Out, Policy, Indentation, Context); 628e5dd7070Spatrick } 629e5dd7070Spatrick 630e5dd7070Spatrick PrintingPolicy SubPolicy(Policy); 631e5dd7070Spatrick SubPolicy.SuppressSpecifiers = false; 632e5dd7070Spatrick std::string Proto; 633e5dd7070Spatrick 634e5dd7070Spatrick if (Policy.FullyQualifiedName) { 635e5dd7070Spatrick Proto += D->getQualifiedNameAsString(); 636e5dd7070Spatrick } else { 637e5dd7070Spatrick llvm::raw_string_ostream OS(Proto); 638e5dd7070Spatrick if (!Policy.SuppressScope) { 639e5dd7070Spatrick if (const NestedNameSpecifier *NS = D->getQualifier()) { 640e5dd7070Spatrick NS->print(OS, Policy); 641e5dd7070Spatrick } 642e5dd7070Spatrick } 643e5dd7070Spatrick D->getNameInfo().printName(OS, Policy); 644e5dd7070Spatrick } 645e5dd7070Spatrick 646e5dd7070Spatrick if (GuideDecl) 647e5dd7070Spatrick Proto = GuideDecl->getDeducedTemplate()->getDeclName().getAsString(); 648e5dd7070Spatrick if (D->isFunctionTemplateSpecialization()) { 649e5dd7070Spatrick llvm::raw_string_ostream POut(Proto); 650e5dd7070Spatrick DeclPrinter TArgPrinter(POut, SubPolicy, Context, Indentation); 651e5dd7070Spatrick const auto *TArgAsWritten = D->getTemplateSpecializationArgsAsWritten(); 652*a9ac8606Spatrick const TemplateParameterList *TPL = D->getTemplateSpecializationInfo() 653*a9ac8606Spatrick ->getTemplate() 654*a9ac8606Spatrick ->getTemplateParameters(); 655e5dd7070Spatrick if (TArgAsWritten && !Policy.PrintCanonicalTypes) 656*a9ac8606Spatrick TArgPrinter.printTemplateArguments(TArgAsWritten->arguments(), TPL, 657*a9ac8606Spatrick /*TemplOverloaded*/ true); 658e5dd7070Spatrick else if (const TemplateArgumentList *TArgs = 659e5dd7070Spatrick D->getTemplateSpecializationArgs()) 660*a9ac8606Spatrick TArgPrinter.printTemplateArguments(TArgs->asArray(), TPL, 661*a9ac8606Spatrick /*TemplOverloaded*/ true); 662e5dd7070Spatrick } 663e5dd7070Spatrick 664e5dd7070Spatrick QualType Ty = D->getType(); 665e5dd7070Spatrick while (const ParenType *PT = dyn_cast<ParenType>(Ty)) { 666e5dd7070Spatrick Proto = '(' + Proto + ')'; 667e5dd7070Spatrick Ty = PT->getInnerType(); 668e5dd7070Spatrick } 669e5dd7070Spatrick 670e5dd7070Spatrick if (const FunctionType *AFT = Ty->getAs<FunctionType>()) { 671e5dd7070Spatrick const FunctionProtoType *FT = nullptr; 672e5dd7070Spatrick if (D->hasWrittenPrototype()) 673e5dd7070Spatrick FT = dyn_cast<FunctionProtoType>(AFT); 674e5dd7070Spatrick 675e5dd7070Spatrick Proto += "("; 676e5dd7070Spatrick if (FT) { 677e5dd7070Spatrick llvm::raw_string_ostream POut(Proto); 678e5dd7070Spatrick DeclPrinter ParamPrinter(POut, SubPolicy, Context, Indentation); 679e5dd7070Spatrick for (unsigned i = 0, e = D->getNumParams(); i != e; ++i) { 680e5dd7070Spatrick if (i) POut << ", "; 681e5dd7070Spatrick ParamPrinter.VisitParmVarDecl(D->getParamDecl(i)); 682e5dd7070Spatrick } 683e5dd7070Spatrick 684e5dd7070Spatrick if (FT->isVariadic()) { 685e5dd7070Spatrick if (D->getNumParams()) POut << ", "; 686e5dd7070Spatrick POut << "..."; 687e5dd7070Spatrick } 688e5dd7070Spatrick } else if (D->doesThisDeclarationHaveABody() && !D->hasPrototype()) { 689e5dd7070Spatrick for (unsigned i = 0, e = D->getNumParams(); i != e; ++i) { 690e5dd7070Spatrick if (i) 691e5dd7070Spatrick Proto += ", "; 692e5dd7070Spatrick Proto += D->getParamDecl(i)->getNameAsString(); 693e5dd7070Spatrick } 694e5dd7070Spatrick } 695e5dd7070Spatrick 696e5dd7070Spatrick Proto += ")"; 697e5dd7070Spatrick 698e5dd7070Spatrick if (FT) { 699e5dd7070Spatrick if (FT->isConst()) 700e5dd7070Spatrick Proto += " const"; 701e5dd7070Spatrick if (FT->isVolatile()) 702e5dd7070Spatrick Proto += " volatile"; 703e5dd7070Spatrick if (FT->isRestrict()) 704e5dd7070Spatrick Proto += " restrict"; 705e5dd7070Spatrick 706e5dd7070Spatrick switch (FT->getRefQualifier()) { 707e5dd7070Spatrick case RQ_None: 708e5dd7070Spatrick break; 709e5dd7070Spatrick case RQ_LValue: 710e5dd7070Spatrick Proto += " &"; 711e5dd7070Spatrick break; 712e5dd7070Spatrick case RQ_RValue: 713e5dd7070Spatrick Proto += " &&"; 714e5dd7070Spatrick break; 715e5dd7070Spatrick } 716e5dd7070Spatrick } 717e5dd7070Spatrick 718e5dd7070Spatrick if (FT && FT->hasDynamicExceptionSpec()) { 719e5dd7070Spatrick Proto += " throw("; 720e5dd7070Spatrick if (FT->getExceptionSpecType() == EST_MSAny) 721e5dd7070Spatrick Proto += "..."; 722e5dd7070Spatrick else 723e5dd7070Spatrick for (unsigned I = 0, N = FT->getNumExceptions(); I != N; ++I) { 724e5dd7070Spatrick if (I) 725e5dd7070Spatrick Proto += ", "; 726e5dd7070Spatrick 727e5dd7070Spatrick Proto += FT->getExceptionType(I).getAsString(SubPolicy); 728e5dd7070Spatrick } 729e5dd7070Spatrick Proto += ")"; 730e5dd7070Spatrick } else if (FT && isNoexceptExceptionSpec(FT->getExceptionSpecType())) { 731e5dd7070Spatrick Proto += " noexcept"; 732e5dd7070Spatrick if (isComputedNoexcept(FT->getExceptionSpecType())) { 733e5dd7070Spatrick Proto += "("; 734e5dd7070Spatrick llvm::raw_string_ostream EOut(Proto); 735e5dd7070Spatrick FT->getNoexceptExpr()->printPretty(EOut, nullptr, SubPolicy, 736*a9ac8606Spatrick Indentation, "\n", &Context); 737e5dd7070Spatrick EOut.flush(); 738e5dd7070Spatrick Proto += EOut.str(); 739e5dd7070Spatrick Proto += ")"; 740e5dd7070Spatrick } 741e5dd7070Spatrick } 742e5dd7070Spatrick 743e5dd7070Spatrick if (CDecl) { 744e5dd7070Spatrick if (!Policy.TerseOutput) 745e5dd7070Spatrick PrintConstructorInitializers(CDecl, Proto); 746e5dd7070Spatrick } else if (!ConversionDecl && !isa<CXXDestructorDecl>(D)) { 747e5dd7070Spatrick if (FT && FT->hasTrailingReturn()) { 748e5dd7070Spatrick if (!GuideDecl) 749e5dd7070Spatrick Out << "auto "; 750e5dd7070Spatrick Out << Proto << " -> "; 751e5dd7070Spatrick Proto.clear(); 752e5dd7070Spatrick } 753e5dd7070Spatrick AFT->getReturnType().print(Out, Policy, Proto); 754e5dd7070Spatrick Proto.clear(); 755e5dd7070Spatrick } 756e5dd7070Spatrick Out << Proto; 757e5dd7070Spatrick 758e5dd7070Spatrick if (Expr *TrailingRequiresClause = D->getTrailingRequiresClause()) { 759e5dd7070Spatrick Out << " requires "; 760*a9ac8606Spatrick TrailingRequiresClause->printPretty(Out, nullptr, SubPolicy, Indentation, 761*a9ac8606Spatrick "\n", &Context); 762e5dd7070Spatrick } 763e5dd7070Spatrick } else { 764e5dd7070Spatrick Ty.print(Out, Policy, Proto); 765e5dd7070Spatrick } 766e5dd7070Spatrick 767e5dd7070Spatrick prettyPrintAttributes(D); 768e5dd7070Spatrick 769e5dd7070Spatrick if (D->isPure()) 770e5dd7070Spatrick Out << " = 0"; 771e5dd7070Spatrick else if (D->isDeletedAsWritten()) 772e5dd7070Spatrick Out << " = delete"; 773e5dd7070Spatrick else if (D->isExplicitlyDefaulted()) 774e5dd7070Spatrick Out << " = default"; 775e5dd7070Spatrick else if (D->doesThisDeclarationHaveABody()) { 776e5dd7070Spatrick if (!Policy.TerseOutput) { 777e5dd7070Spatrick if (!D->hasPrototype() && D->getNumParams()) { 778e5dd7070Spatrick // This is a K&R function definition, so we need to print the 779e5dd7070Spatrick // parameters. 780e5dd7070Spatrick Out << '\n'; 781e5dd7070Spatrick DeclPrinter ParamPrinter(Out, SubPolicy, Context, Indentation); 782e5dd7070Spatrick Indentation += Policy.Indentation; 783e5dd7070Spatrick for (unsigned i = 0, e = D->getNumParams(); i != e; ++i) { 784e5dd7070Spatrick Indent(); 785e5dd7070Spatrick ParamPrinter.VisitParmVarDecl(D->getParamDecl(i)); 786e5dd7070Spatrick Out << ";\n"; 787e5dd7070Spatrick } 788e5dd7070Spatrick Indentation -= Policy.Indentation; 789e5dd7070Spatrick } else 790e5dd7070Spatrick Out << ' '; 791e5dd7070Spatrick 792e5dd7070Spatrick if (D->getBody()) 793*a9ac8606Spatrick D->getBody()->printPretty(Out, nullptr, SubPolicy, Indentation, "\n", 794*a9ac8606Spatrick &Context); 795e5dd7070Spatrick } else { 796e5dd7070Spatrick if (!Policy.TerseOutput && isa<CXXConstructorDecl>(*D)) 797e5dd7070Spatrick Out << " {}"; 798e5dd7070Spatrick } 799e5dd7070Spatrick } 800e5dd7070Spatrick } 801e5dd7070Spatrick 802e5dd7070Spatrick void DeclPrinter::VisitFriendDecl(FriendDecl *D) { 803e5dd7070Spatrick if (TypeSourceInfo *TSI = D->getFriendType()) { 804e5dd7070Spatrick unsigned NumTPLists = D->getFriendTypeNumTemplateParameterLists(); 805e5dd7070Spatrick for (unsigned i = 0; i < NumTPLists; ++i) 806e5dd7070Spatrick printTemplateParameters(D->getFriendTypeTemplateParameterList(i)); 807e5dd7070Spatrick Out << "friend "; 808e5dd7070Spatrick Out << " " << TSI->getType().getAsString(Policy); 809e5dd7070Spatrick } 810e5dd7070Spatrick else if (FunctionDecl *FD = 811e5dd7070Spatrick dyn_cast<FunctionDecl>(D->getFriendDecl())) { 812e5dd7070Spatrick Out << "friend "; 813e5dd7070Spatrick VisitFunctionDecl(FD); 814e5dd7070Spatrick } 815e5dd7070Spatrick else if (FunctionTemplateDecl *FTD = 816e5dd7070Spatrick dyn_cast<FunctionTemplateDecl>(D->getFriendDecl())) { 817e5dd7070Spatrick Out << "friend "; 818e5dd7070Spatrick VisitFunctionTemplateDecl(FTD); 819e5dd7070Spatrick } 820e5dd7070Spatrick else if (ClassTemplateDecl *CTD = 821e5dd7070Spatrick dyn_cast<ClassTemplateDecl>(D->getFriendDecl())) { 822e5dd7070Spatrick Out << "friend "; 823e5dd7070Spatrick VisitRedeclarableTemplateDecl(CTD); 824e5dd7070Spatrick } 825e5dd7070Spatrick } 826e5dd7070Spatrick 827e5dd7070Spatrick void DeclPrinter::VisitFieldDecl(FieldDecl *D) { 828e5dd7070Spatrick // FIXME: add printing of pragma attributes if required. 829e5dd7070Spatrick if (!Policy.SuppressSpecifiers && D->isMutable()) 830e5dd7070Spatrick Out << "mutable "; 831e5dd7070Spatrick if (!Policy.SuppressSpecifiers && D->isModulePrivate()) 832e5dd7070Spatrick Out << "__module_private__ "; 833e5dd7070Spatrick 834e5dd7070Spatrick Out << D->getASTContext().getUnqualifiedObjCPointerType(D->getType()). 835e5dd7070Spatrick stream(Policy, D->getName(), Indentation); 836e5dd7070Spatrick 837e5dd7070Spatrick if (D->isBitField()) { 838e5dd7070Spatrick Out << " : "; 839*a9ac8606Spatrick D->getBitWidth()->printPretty(Out, nullptr, Policy, Indentation, "\n", 840*a9ac8606Spatrick &Context); 841e5dd7070Spatrick } 842e5dd7070Spatrick 843e5dd7070Spatrick Expr *Init = D->getInClassInitializer(); 844e5dd7070Spatrick if (!Policy.SuppressInitializers && Init) { 845e5dd7070Spatrick if (D->getInClassInitStyle() == ICIS_ListInit) 846e5dd7070Spatrick Out << " "; 847e5dd7070Spatrick else 848e5dd7070Spatrick Out << " = "; 849*a9ac8606Spatrick Init->printPretty(Out, nullptr, Policy, Indentation, "\n", &Context); 850e5dd7070Spatrick } 851e5dd7070Spatrick prettyPrintAttributes(D); 852e5dd7070Spatrick } 853e5dd7070Spatrick 854e5dd7070Spatrick void DeclPrinter::VisitLabelDecl(LabelDecl *D) { 855e5dd7070Spatrick Out << *D << ":"; 856e5dd7070Spatrick } 857e5dd7070Spatrick 858e5dd7070Spatrick void DeclPrinter::VisitVarDecl(VarDecl *D) { 859e5dd7070Spatrick prettyPrintPragmas(D); 860e5dd7070Spatrick 861e5dd7070Spatrick QualType T = D->getTypeSourceInfo() 862e5dd7070Spatrick ? D->getTypeSourceInfo()->getType() 863e5dd7070Spatrick : D->getASTContext().getUnqualifiedObjCPointerType(D->getType()); 864e5dd7070Spatrick 865e5dd7070Spatrick if (!Policy.SuppressSpecifiers) { 866e5dd7070Spatrick StorageClass SC = D->getStorageClass(); 867e5dd7070Spatrick if (SC != SC_None) 868e5dd7070Spatrick Out << VarDecl::getStorageClassSpecifierString(SC) << " "; 869e5dd7070Spatrick 870e5dd7070Spatrick switch (D->getTSCSpec()) { 871e5dd7070Spatrick case TSCS_unspecified: 872e5dd7070Spatrick break; 873e5dd7070Spatrick case TSCS___thread: 874e5dd7070Spatrick Out << "__thread "; 875e5dd7070Spatrick break; 876e5dd7070Spatrick case TSCS__Thread_local: 877e5dd7070Spatrick Out << "_Thread_local "; 878e5dd7070Spatrick break; 879e5dd7070Spatrick case TSCS_thread_local: 880e5dd7070Spatrick Out << "thread_local "; 881e5dd7070Spatrick break; 882e5dd7070Spatrick } 883e5dd7070Spatrick 884e5dd7070Spatrick if (D->isModulePrivate()) 885e5dd7070Spatrick Out << "__module_private__ "; 886e5dd7070Spatrick 887e5dd7070Spatrick if (D->isConstexpr()) { 888e5dd7070Spatrick Out << "constexpr "; 889e5dd7070Spatrick T.removeLocalConst(); 890e5dd7070Spatrick } 891e5dd7070Spatrick } 892e5dd7070Spatrick 893e5dd7070Spatrick printDeclType(T, D->getName()); 894e5dd7070Spatrick Expr *Init = D->getInit(); 895e5dd7070Spatrick if (!Policy.SuppressInitializers && Init) { 896e5dd7070Spatrick bool ImplicitInit = false; 897e5dd7070Spatrick if (CXXConstructExpr *Construct = 898e5dd7070Spatrick dyn_cast<CXXConstructExpr>(Init->IgnoreImplicit())) { 899e5dd7070Spatrick if (D->getInitStyle() == VarDecl::CallInit && 900e5dd7070Spatrick !Construct->isListInitialization()) { 901e5dd7070Spatrick ImplicitInit = Construct->getNumArgs() == 0 || 902e5dd7070Spatrick Construct->getArg(0)->isDefaultArgument(); 903e5dd7070Spatrick } 904e5dd7070Spatrick } 905e5dd7070Spatrick if (!ImplicitInit) { 906e5dd7070Spatrick if ((D->getInitStyle() == VarDecl::CallInit) && !isa<ParenListExpr>(Init)) 907e5dd7070Spatrick Out << "("; 908e5dd7070Spatrick else if (D->getInitStyle() == VarDecl::CInit) { 909e5dd7070Spatrick Out << " = "; 910e5dd7070Spatrick } 911e5dd7070Spatrick PrintingPolicy SubPolicy(Policy); 912e5dd7070Spatrick SubPolicy.SuppressSpecifiers = false; 913e5dd7070Spatrick SubPolicy.IncludeTagDefinition = false; 914*a9ac8606Spatrick Init->printPretty(Out, nullptr, SubPolicy, Indentation, "\n", &Context); 915e5dd7070Spatrick if ((D->getInitStyle() == VarDecl::CallInit) && !isa<ParenListExpr>(Init)) 916e5dd7070Spatrick Out << ")"; 917e5dd7070Spatrick } 918e5dd7070Spatrick } 919e5dd7070Spatrick prettyPrintAttributes(D); 920e5dd7070Spatrick } 921e5dd7070Spatrick 922e5dd7070Spatrick void DeclPrinter::VisitParmVarDecl(ParmVarDecl *D) { 923e5dd7070Spatrick VisitVarDecl(D); 924e5dd7070Spatrick } 925e5dd7070Spatrick 926e5dd7070Spatrick void DeclPrinter::VisitFileScopeAsmDecl(FileScopeAsmDecl *D) { 927e5dd7070Spatrick Out << "__asm ("; 928*a9ac8606Spatrick D->getAsmString()->printPretty(Out, nullptr, Policy, Indentation, "\n", 929*a9ac8606Spatrick &Context); 930e5dd7070Spatrick Out << ")"; 931e5dd7070Spatrick } 932e5dd7070Spatrick 933e5dd7070Spatrick void DeclPrinter::VisitImportDecl(ImportDecl *D) { 934e5dd7070Spatrick Out << "@import " << D->getImportedModule()->getFullModuleName() 935e5dd7070Spatrick << ";\n"; 936e5dd7070Spatrick } 937e5dd7070Spatrick 938e5dd7070Spatrick void DeclPrinter::VisitStaticAssertDecl(StaticAssertDecl *D) { 939e5dd7070Spatrick Out << "static_assert("; 940*a9ac8606Spatrick D->getAssertExpr()->printPretty(Out, nullptr, Policy, Indentation, "\n", 941*a9ac8606Spatrick &Context); 942e5dd7070Spatrick if (StringLiteral *SL = D->getMessage()) { 943e5dd7070Spatrick Out << ", "; 944*a9ac8606Spatrick SL->printPretty(Out, nullptr, Policy, Indentation, "\n", &Context); 945e5dd7070Spatrick } 946e5dd7070Spatrick Out << ")"; 947e5dd7070Spatrick } 948e5dd7070Spatrick 949e5dd7070Spatrick //---------------------------------------------------------------------------- 950e5dd7070Spatrick // C++ declarations 951e5dd7070Spatrick //---------------------------------------------------------------------------- 952e5dd7070Spatrick void DeclPrinter::VisitNamespaceDecl(NamespaceDecl *D) { 953e5dd7070Spatrick if (D->isInline()) 954e5dd7070Spatrick Out << "inline "; 955*a9ac8606Spatrick 956*a9ac8606Spatrick Out << "namespace "; 957*a9ac8606Spatrick if (D->getDeclName()) 958*a9ac8606Spatrick Out << D->getDeclName() << ' '; 959*a9ac8606Spatrick Out << "{\n"; 960*a9ac8606Spatrick 961e5dd7070Spatrick VisitDeclContext(D); 962e5dd7070Spatrick Indent() << "}"; 963e5dd7070Spatrick } 964e5dd7070Spatrick 965e5dd7070Spatrick void DeclPrinter::VisitUsingDirectiveDecl(UsingDirectiveDecl *D) { 966e5dd7070Spatrick Out << "using namespace "; 967e5dd7070Spatrick if (D->getQualifier()) 968e5dd7070Spatrick D->getQualifier()->print(Out, Policy); 969e5dd7070Spatrick Out << *D->getNominatedNamespaceAsWritten(); 970e5dd7070Spatrick } 971e5dd7070Spatrick 972e5dd7070Spatrick void DeclPrinter::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) { 973e5dd7070Spatrick Out << "namespace " << *D << " = "; 974e5dd7070Spatrick if (D->getQualifier()) 975e5dd7070Spatrick D->getQualifier()->print(Out, Policy); 976e5dd7070Spatrick Out << *D->getAliasedNamespace(); 977e5dd7070Spatrick } 978e5dd7070Spatrick 979e5dd7070Spatrick void DeclPrinter::VisitEmptyDecl(EmptyDecl *D) { 980e5dd7070Spatrick prettyPrintAttributes(D); 981e5dd7070Spatrick } 982e5dd7070Spatrick 983e5dd7070Spatrick void DeclPrinter::VisitCXXRecordDecl(CXXRecordDecl *D) { 984e5dd7070Spatrick // FIXME: add printing of pragma attributes if required. 985e5dd7070Spatrick if (!Policy.SuppressSpecifiers && D->isModulePrivate()) 986e5dd7070Spatrick Out << "__module_private__ "; 987e5dd7070Spatrick Out << D->getKindName(); 988e5dd7070Spatrick 989e5dd7070Spatrick prettyPrintAttributes(D); 990e5dd7070Spatrick 991e5dd7070Spatrick if (D->getIdentifier()) { 992e5dd7070Spatrick Out << ' ' << *D; 993e5dd7070Spatrick 994e5dd7070Spatrick if (auto S = dyn_cast<ClassTemplateSpecializationDecl>(D)) { 995e5dd7070Spatrick ArrayRef<TemplateArgument> Args = S->getTemplateArgs().asArray(); 996e5dd7070Spatrick if (!Policy.PrintCanonicalTypes) 997e5dd7070Spatrick if (const auto* TSI = S->getTypeAsWritten()) 998e5dd7070Spatrick if (const auto *TST = 999e5dd7070Spatrick dyn_cast<TemplateSpecializationType>(TSI->getType())) 1000e5dd7070Spatrick Args = TST->template_arguments(); 1001*a9ac8606Spatrick printTemplateArguments( 1002*a9ac8606Spatrick Args, S->getSpecializedTemplate()->getTemplateParameters(), 1003*a9ac8606Spatrick /*TemplOverloaded*/ false); 1004e5dd7070Spatrick } 1005e5dd7070Spatrick } 1006e5dd7070Spatrick 1007e5dd7070Spatrick if (D->isCompleteDefinition()) { 1008e5dd7070Spatrick // Print the base classes 1009e5dd7070Spatrick if (D->getNumBases()) { 1010e5dd7070Spatrick Out << " : "; 1011e5dd7070Spatrick for (CXXRecordDecl::base_class_iterator Base = D->bases_begin(), 1012e5dd7070Spatrick BaseEnd = D->bases_end(); Base != BaseEnd; ++Base) { 1013e5dd7070Spatrick if (Base != D->bases_begin()) 1014e5dd7070Spatrick Out << ", "; 1015e5dd7070Spatrick 1016e5dd7070Spatrick if (Base->isVirtual()) 1017e5dd7070Spatrick Out << "virtual "; 1018e5dd7070Spatrick 1019e5dd7070Spatrick AccessSpecifier AS = Base->getAccessSpecifierAsWritten(); 1020e5dd7070Spatrick if (AS != AS_none) { 1021e5dd7070Spatrick Print(AS); 1022e5dd7070Spatrick Out << " "; 1023e5dd7070Spatrick } 1024e5dd7070Spatrick Out << Base->getType().getAsString(Policy); 1025e5dd7070Spatrick 1026e5dd7070Spatrick if (Base->isPackExpansion()) 1027e5dd7070Spatrick Out << "..."; 1028e5dd7070Spatrick } 1029e5dd7070Spatrick } 1030e5dd7070Spatrick 1031e5dd7070Spatrick // Print the class definition 1032e5dd7070Spatrick // FIXME: Doesn't print access specifiers, e.g., "public:" 1033e5dd7070Spatrick if (Policy.TerseOutput) { 1034e5dd7070Spatrick Out << " {}"; 1035e5dd7070Spatrick } else { 1036e5dd7070Spatrick Out << " {\n"; 1037e5dd7070Spatrick VisitDeclContext(D); 1038e5dd7070Spatrick Indent() << "}"; 1039e5dd7070Spatrick } 1040e5dd7070Spatrick } 1041e5dd7070Spatrick } 1042e5dd7070Spatrick 1043e5dd7070Spatrick void DeclPrinter::VisitLinkageSpecDecl(LinkageSpecDecl *D) { 1044e5dd7070Spatrick const char *l; 1045e5dd7070Spatrick if (D->getLanguage() == LinkageSpecDecl::lang_c) 1046e5dd7070Spatrick l = "C"; 1047e5dd7070Spatrick else { 1048e5dd7070Spatrick assert(D->getLanguage() == LinkageSpecDecl::lang_cxx && 1049e5dd7070Spatrick "unknown language in linkage specification"); 1050e5dd7070Spatrick l = "C++"; 1051e5dd7070Spatrick } 1052e5dd7070Spatrick 1053e5dd7070Spatrick Out << "extern \"" << l << "\" "; 1054e5dd7070Spatrick if (D->hasBraces()) { 1055e5dd7070Spatrick Out << "{\n"; 1056e5dd7070Spatrick VisitDeclContext(D); 1057e5dd7070Spatrick Indent() << "}"; 1058e5dd7070Spatrick } else 1059e5dd7070Spatrick Visit(*D->decls_begin()); 1060e5dd7070Spatrick } 1061e5dd7070Spatrick 1062e5dd7070Spatrick void DeclPrinter::printTemplateParameters(const TemplateParameterList *Params, 1063e5dd7070Spatrick bool OmitTemplateKW) { 1064e5dd7070Spatrick assert(Params); 1065e5dd7070Spatrick 1066e5dd7070Spatrick if (!OmitTemplateKW) 1067e5dd7070Spatrick Out << "template "; 1068e5dd7070Spatrick Out << '<'; 1069e5dd7070Spatrick 1070e5dd7070Spatrick bool NeedComma = false; 1071e5dd7070Spatrick for (const Decl *Param : *Params) { 1072e5dd7070Spatrick if (Param->isImplicit()) 1073e5dd7070Spatrick continue; 1074e5dd7070Spatrick 1075e5dd7070Spatrick if (NeedComma) 1076e5dd7070Spatrick Out << ", "; 1077e5dd7070Spatrick else 1078e5dd7070Spatrick NeedComma = true; 1079e5dd7070Spatrick 1080ec727ea7Spatrick if (const auto *TTP = dyn_cast<TemplateTypeParmDecl>(Param)) { 1081ec727ea7Spatrick VisitTemplateTypeParmDecl(TTP); 1082e5dd7070Spatrick } else if (auto NTTP = dyn_cast<NonTypeTemplateParmDecl>(Param)) { 1083ec727ea7Spatrick VisitNonTypeTemplateParmDecl(NTTP); 1084e5dd7070Spatrick } else if (auto TTPD = dyn_cast<TemplateTemplateParmDecl>(Param)) { 1085e5dd7070Spatrick VisitTemplateDecl(TTPD); 1086e5dd7070Spatrick // FIXME: print the default argument, if present. 1087e5dd7070Spatrick } 1088e5dd7070Spatrick } 1089e5dd7070Spatrick 1090e5dd7070Spatrick Out << '>'; 1091e5dd7070Spatrick if (!OmitTemplateKW) 1092e5dd7070Spatrick Out << ' '; 1093e5dd7070Spatrick } 1094e5dd7070Spatrick 1095*a9ac8606Spatrick void DeclPrinter::printTemplateArguments(ArrayRef<TemplateArgument> Args, 1096*a9ac8606Spatrick const TemplateParameterList *Params, 1097*a9ac8606Spatrick bool TemplOverloaded) { 1098e5dd7070Spatrick Out << "<"; 1099e5dd7070Spatrick for (size_t I = 0, E = Args.size(); I < E; ++I) { 1100e5dd7070Spatrick if (I) 1101e5dd7070Spatrick Out << ", "; 1102*a9ac8606Spatrick if (TemplOverloaded || !Params) 1103*a9ac8606Spatrick Args[I].print(Policy, Out, /*IncludeType*/ true); 1104*a9ac8606Spatrick else 1105*a9ac8606Spatrick Args[I].print( 1106*a9ac8606Spatrick Policy, Out, 1107*a9ac8606Spatrick TemplateParameterList::shouldIncludeTypeForArgument(Params, I)); 1108e5dd7070Spatrick } 1109e5dd7070Spatrick Out << ">"; 1110e5dd7070Spatrick } 1111e5dd7070Spatrick 1112*a9ac8606Spatrick void DeclPrinter::printTemplateArguments(ArrayRef<TemplateArgumentLoc> Args, 1113*a9ac8606Spatrick const TemplateParameterList *Params, 1114*a9ac8606Spatrick bool TemplOverloaded) { 1115e5dd7070Spatrick Out << "<"; 1116e5dd7070Spatrick for (size_t I = 0, E = Args.size(); I < E; ++I) { 1117e5dd7070Spatrick if (I) 1118e5dd7070Spatrick Out << ", "; 1119*a9ac8606Spatrick if (TemplOverloaded) 1120*a9ac8606Spatrick Args[I].getArgument().print(Policy, Out, /*IncludeType*/ true); 1121*a9ac8606Spatrick else 1122*a9ac8606Spatrick Args[I].getArgument().print( 1123*a9ac8606Spatrick Policy, Out, 1124*a9ac8606Spatrick TemplateParameterList::shouldIncludeTypeForArgument(Params, I)); 1125e5dd7070Spatrick } 1126e5dd7070Spatrick Out << ">"; 1127e5dd7070Spatrick } 1128e5dd7070Spatrick 1129e5dd7070Spatrick void DeclPrinter::VisitTemplateDecl(const TemplateDecl *D) { 1130e5dd7070Spatrick printTemplateParameters(D->getTemplateParameters()); 1131e5dd7070Spatrick 1132e5dd7070Spatrick if (const TemplateTemplateParmDecl *TTP = 1133e5dd7070Spatrick dyn_cast<TemplateTemplateParmDecl>(D)) { 1134e5dd7070Spatrick Out << "class"; 1135*a9ac8606Spatrick 1136e5dd7070Spatrick if (TTP->isParameterPack()) 1137e5dd7070Spatrick Out << " ..."; 1138*a9ac8606Spatrick else if (TTP->getDeclName()) 1139*a9ac8606Spatrick Out << ' '; 1140*a9ac8606Spatrick 1141*a9ac8606Spatrick if (TTP->getDeclName()) 1142*a9ac8606Spatrick Out << TTP->getDeclName(); 1143e5dd7070Spatrick } else if (auto *TD = D->getTemplatedDecl()) 1144e5dd7070Spatrick Visit(TD); 1145e5dd7070Spatrick else if (const auto *Concept = dyn_cast<ConceptDecl>(D)) { 1146e5dd7070Spatrick Out << "concept " << Concept->getName() << " = " ; 1147*a9ac8606Spatrick Concept->getConstraintExpr()->printPretty(Out, nullptr, Policy, Indentation, 1148*a9ac8606Spatrick "\n", &Context); 1149e5dd7070Spatrick } 1150e5dd7070Spatrick } 1151e5dd7070Spatrick 1152e5dd7070Spatrick void DeclPrinter::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) { 1153e5dd7070Spatrick prettyPrintPragmas(D->getTemplatedDecl()); 1154e5dd7070Spatrick // Print any leading template parameter lists. 1155e5dd7070Spatrick if (const FunctionDecl *FD = D->getTemplatedDecl()) { 1156e5dd7070Spatrick for (unsigned I = 0, NumTemplateParams = FD->getNumTemplateParameterLists(); 1157e5dd7070Spatrick I < NumTemplateParams; ++I) 1158e5dd7070Spatrick printTemplateParameters(FD->getTemplateParameterList(I)); 1159e5dd7070Spatrick } 1160e5dd7070Spatrick VisitRedeclarableTemplateDecl(D); 1161e5dd7070Spatrick // Declare target attribute is special one, natural spelling for the pragma 1162e5dd7070Spatrick // assumes "ending" construct so print it here. 1163e5dd7070Spatrick if (D->getTemplatedDecl()->hasAttr<OMPDeclareTargetDeclAttr>()) 1164e5dd7070Spatrick Out << "#pragma omp end declare target\n"; 1165e5dd7070Spatrick 1166e5dd7070Spatrick // Never print "instantiations" for deduction guides (they don't really 1167e5dd7070Spatrick // have them). 1168e5dd7070Spatrick if (PrintInstantiation && 1169e5dd7070Spatrick !isa<CXXDeductionGuideDecl>(D->getTemplatedDecl())) { 1170e5dd7070Spatrick FunctionDecl *PrevDecl = D->getTemplatedDecl(); 1171e5dd7070Spatrick const FunctionDecl *Def; 1172e5dd7070Spatrick if (PrevDecl->isDefined(Def) && Def != PrevDecl) 1173e5dd7070Spatrick return; 1174e5dd7070Spatrick for (auto *I : D->specializations()) 1175e5dd7070Spatrick if (I->getTemplateSpecializationKind() == TSK_ImplicitInstantiation) { 1176e5dd7070Spatrick if (!PrevDecl->isThisDeclarationADefinition()) 1177e5dd7070Spatrick Out << ";\n"; 1178e5dd7070Spatrick Indent(); 1179e5dd7070Spatrick prettyPrintPragmas(I); 1180e5dd7070Spatrick Visit(I); 1181e5dd7070Spatrick } 1182e5dd7070Spatrick } 1183e5dd7070Spatrick } 1184e5dd7070Spatrick 1185e5dd7070Spatrick void DeclPrinter::VisitClassTemplateDecl(ClassTemplateDecl *D) { 1186e5dd7070Spatrick VisitRedeclarableTemplateDecl(D); 1187e5dd7070Spatrick 1188e5dd7070Spatrick if (PrintInstantiation) { 1189e5dd7070Spatrick for (auto *I : D->specializations()) 1190e5dd7070Spatrick if (I->getSpecializationKind() == TSK_ImplicitInstantiation) { 1191e5dd7070Spatrick if (D->isThisDeclarationADefinition()) 1192e5dd7070Spatrick Out << ";"; 1193e5dd7070Spatrick Out << "\n"; 1194e5dd7070Spatrick Visit(I); 1195e5dd7070Spatrick } 1196e5dd7070Spatrick } 1197e5dd7070Spatrick } 1198e5dd7070Spatrick 1199e5dd7070Spatrick void DeclPrinter::VisitClassTemplateSpecializationDecl( 1200e5dd7070Spatrick ClassTemplateSpecializationDecl *D) { 1201e5dd7070Spatrick Out << "template<> "; 1202e5dd7070Spatrick VisitCXXRecordDecl(D); 1203e5dd7070Spatrick } 1204e5dd7070Spatrick 1205e5dd7070Spatrick void DeclPrinter::VisitClassTemplatePartialSpecializationDecl( 1206e5dd7070Spatrick ClassTemplatePartialSpecializationDecl *D) { 1207e5dd7070Spatrick printTemplateParameters(D->getTemplateParameters()); 1208e5dd7070Spatrick VisitCXXRecordDecl(D); 1209e5dd7070Spatrick } 1210e5dd7070Spatrick 1211e5dd7070Spatrick //---------------------------------------------------------------------------- 1212e5dd7070Spatrick // Objective-C declarations 1213e5dd7070Spatrick //---------------------------------------------------------------------------- 1214e5dd7070Spatrick 1215e5dd7070Spatrick void DeclPrinter::PrintObjCMethodType(ASTContext &Ctx, 1216e5dd7070Spatrick Decl::ObjCDeclQualifier Quals, 1217e5dd7070Spatrick QualType T) { 1218e5dd7070Spatrick Out << '('; 1219e5dd7070Spatrick if (Quals & Decl::ObjCDeclQualifier::OBJC_TQ_In) 1220e5dd7070Spatrick Out << "in "; 1221e5dd7070Spatrick if (Quals & Decl::ObjCDeclQualifier::OBJC_TQ_Inout) 1222e5dd7070Spatrick Out << "inout "; 1223e5dd7070Spatrick if (Quals & Decl::ObjCDeclQualifier::OBJC_TQ_Out) 1224e5dd7070Spatrick Out << "out "; 1225e5dd7070Spatrick if (Quals & Decl::ObjCDeclQualifier::OBJC_TQ_Bycopy) 1226e5dd7070Spatrick Out << "bycopy "; 1227e5dd7070Spatrick if (Quals & Decl::ObjCDeclQualifier::OBJC_TQ_Byref) 1228e5dd7070Spatrick Out << "byref "; 1229e5dd7070Spatrick if (Quals & Decl::ObjCDeclQualifier::OBJC_TQ_Oneway) 1230e5dd7070Spatrick Out << "oneway "; 1231e5dd7070Spatrick if (Quals & Decl::ObjCDeclQualifier::OBJC_TQ_CSNullability) { 1232e5dd7070Spatrick if (auto nullability = AttributedType::stripOuterNullability(T)) 1233e5dd7070Spatrick Out << getNullabilitySpelling(*nullability, true) << ' '; 1234e5dd7070Spatrick } 1235e5dd7070Spatrick 1236e5dd7070Spatrick Out << Ctx.getUnqualifiedObjCPointerType(T).getAsString(Policy); 1237e5dd7070Spatrick Out << ')'; 1238e5dd7070Spatrick } 1239e5dd7070Spatrick 1240e5dd7070Spatrick void DeclPrinter::PrintObjCTypeParams(ObjCTypeParamList *Params) { 1241e5dd7070Spatrick Out << "<"; 1242e5dd7070Spatrick unsigned First = true; 1243e5dd7070Spatrick for (auto *Param : *Params) { 1244e5dd7070Spatrick if (First) { 1245e5dd7070Spatrick First = false; 1246e5dd7070Spatrick } else { 1247e5dd7070Spatrick Out << ", "; 1248e5dd7070Spatrick } 1249e5dd7070Spatrick 1250e5dd7070Spatrick switch (Param->getVariance()) { 1251e5dd7070Spatrick case ObjCTypeParamVariance::Invariant: 1252e5dd7070Spatrick break; 1253e5dd7070Spatrick 1254e5dd7070Spatrick case ObjCTypeParamVariance::Covariant: 1255e5dd7070Spatrick Out << "__covariant "; 1256e5dd7070Spatrick break; 1257e5dd7070Spatrick 1258e5dd7070Spatrick case ObjCTypeParamVariance::Contravariant: 1259e5dd7070Spatrick Out << "__contravariant "; 1260e5dd7070Spatrick break; 1261e5dd7070Spatrick } 1262e5dd7070Spatrick 1263*a9ac8606Spatrick Out << Param->getDeclName(); 1264e5dd7070Spatrick 1265e5dd7070Spatrick if (Param->hasExplicitBound()) { 1266e5dd7070Spatrick Out << " : " << Param->getUnderlyingType().getAsString(Policy); 1267e5dd7070Spatrick } 1268e5dd7070Spatrick } 1269e5dd7070Spatrick Out << ">"; 1270e5dd7070Spatrick } 1271e5dd7070Spatrick 1272e5dd7070Spatrick void DeclPrinter::VisitObjCMethodDecl(ObjCMethodDecl *OMD) { 1273e5dd7070Spatrick if (OMD->isInstanceMethod()) 1274e5dd7070Spatrick Out << "- "; 1275e5dd7070Spatrick else 1276e5dd7070Spatrick Out << "+ "; 1277e5dd7070Spatrick if (!OMD->getReturnType().isNull()) { 1278e5dd7070Spatrick PrintObjCMethodType(OMD->getASTContext(), OMD->getObjCDeclQualifier(), 1279e5dd7070Spatrick OMD->getReturnType()); 1280e5dd7070Spatrick } 1281e5dd7070Spatrick 1282e5dd7070Spatrick std::string name = OMD->getSelector().getAsString(); 1283e5dd7070Spatrick std::string::size_type pos, lastPos = 0; 1284e5dd7070Spatrick for (const auto *PI : OMD->parameters()) { 1285e5dd7070Spatrick // FIXME: selector is missing here! 1286e5dd7070Spatrick pos = name.find_first_of(':', lastPos); 1287e5dd7070Spatrick if (lastPos != 0) 1288e5dd7070Spatrick Out << " "; 1289e5dd7070Spatrick Out << name.substr(lastPos, pos - lastPos) << ':'; 1290e5dd7070Spatrick PrintObjCMethodType(OMD->getASTContext(), 1291e5dd7070Spatrick PI->getObjCDeclQualifier(), 1292e5dd7070Spatrick PI->getType()); 1293e5dd7070Spatrick Out << *PI; 1294e5dd7070Spatrick lastPos = pos + 1; 1295e5dd7070Spatrick } 1296e5dd7070Spatrick 1297e5dd7070Spatrick if (OMD->param_begin() == OMD->param_end()) 1298e5dd7070Spatrick Out << name; 1299e5dd7070Spatrick 1300e5dd7070Spatrick if (OMD->isVariadic()) 1301e5dd7070Spatrick Out << ", ..."; 1302e5dd7070Spatrick 1303e5dd7070Spatrick prettyPrintAttributes(OMD); 1304e5dd7070Spatrick 1305e5dd7070Spatrick if (OMD->getBody() && !Policy.TerseOutput) { 1306e5dd7070Spatrick Out << ' '; 1307*a9ac8606Spatrick OMD->getBody()->printPretty(Out, nullptr, Policy, Indentation, "\n", 1308*a9ac8606Spatrick &Context); 1309e5dd7070Spatrick } 1310e5dd7070Spatrick else if (Policy.PolishForDeclaration) 1311e5dd7070Spatrick Out << ';'; 1312e5dd7070Spatrick } 1313e5dd7070Spatrick 1314e5dd7070Spatrick void DeclPrinter::VisitObjCImplementationDecl(ObjCImplementationDecl *OID) { 1315e5dd7070Spatrick std::string I = OID->getNameAsString(); 1316e5dd7070Spatrick ObjCInterfaceDecl *SID = OID->getSuperClass(); 1317e5dd7070Spatrick 1318e5dd7070Spatrick bool eolnOut = false; 1319e5dd7070Spatrick if (SID) 1320e5dd7070Spatrick Out << "@implementation " << I << " : " << *SID; 1321e5dd7070Spatrick else 1322e5dd7070Spatrick Out << "@implementation " << I; 1323e5dd7070Spatrick 1324e5dd7070Spatrick if (OID->ivar_size() > 0) { 1325e5dd7070Spatrick Out << "{\n"; 1326e5dd7070Spatrick eolnOut = true; 1327e5dd7070Spatrick Indentation += Policy.Indentation; 1328e5dd7070Spatrick for (const auto *I : OID->ivars()) { 1329e5dd7070Spatrick Indent() << I->getASTContext().getUnqualifiedObjCPointerType(I->getType()). 1330e5dd7070Spatrick getAsString(Policy) << ' ' << *I << ";\n"; 1331e5dd7070Spatrick } 1332e5dd7070Spatrick Indentation -= Policy.Indentation; 1333e5dd7070Spatrick Out << "}\n"; 1334e5dd7070Spatrick } 1335e5dd7070Spatrick else if (SID || (OID->decls_begin() != OID->decls_end())) { 1336e5dd7070Spatrick Out << "\n"; 1337e5dd7070Spatrick eolnOut = true; 1338e5dd7070Spatrick } 1339e5dd7070Spatrick VisitDeclContext(OID, false); 1340e5dd7070Spatrick if (!eolnOut) 1341e5dd7070Spatrick Out << "\n"; 1342e5dd7070Spatrick Out << "@end"; 1343e5dd7070Spatrick } 1344e5dd7070Spatrick 1345e5dd7070Spatrick void DeclPrinter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *OID) { 1346e5dd7070Spatrick std::string I = OID->getNameAsString(); 1347e5dd7070Spatrick ObjCInterfaceDecl *SID = OID->getSuperClass(); 1348e5dd7070Spatrick 1349e5dd7070Spatrick if (!OID->isThisDeclarationADefinition()) { 1350e5dd7070Spatrick Out << "@class " << I; 1351e5dd7070Spatrick 1352e5dd7070Spatrick if (auto TypeParams = OID->getTypeParamListAsWritten()) { 1353e5dd7070Spatrick PrintObjCTypeParams(TypeParams); 1354e5dd7070Spatrick } 1355e5dd7070Spatrick 1356e5dd7070Spatrick Out << ";"; 1357e5dd7070Spatrick return; 1358e5dd7070Spatrick } 1359e5dd7070Spatrick bool eolnOut = false; 1360e5dd7070Spatrick Out << "@interface " << I; 1361e5dd7070Spatrick 1362e5dd7070Spatrick if (auto TypeParams = OID->getTypeParamListAsWritten()) { 1363e5dd7070Spatrick PrintObjCTypeParams(TypeParams); 1364e5dd7070Spatrick } 1365e5dd7070Spatrick 1366e5dd7070Spatrick if (SID) 1367e5dd7070Spatrick Out << " : " << QualType(OID->getSuperClassType(), 0).getAsString(Policy); 1368e5dd7070Spatrick 1369e5dd7070Spatrick // Protocols? 1370e5dd7070Spatrick const ObjCList<ObjCProtocolDecl> &Protocols = OID->getReferencedProtocols(); 1371e5dd7070Spatrick if (!Protocols.empty()) { 1372e5dd7070Spatrick for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(), 1373e5dd7070Spatrick E = Protocols.end(); I != E; ++I) 1374e5dd7070Spatrick Out << (I == Protocols.begin() ? '<' : ',') << **I; 1375e5dd7070Spatrick Out << "> "; 1376e5dd7070Spatrick } 1377e5dd7070Spatrick 1378e5dd7070Spatrick if (OID->ivar_size() > 0) { 1379e5dd7070Spatrick Out << "{\n"; 1380e5dd7070Spatrick eolnOut = true; 1381e5dd7070Spatrick Indentation += Policy.Indentation; 1382e5dd7070Spatrick for (const auto *I : OID->ivars()) { 1383e5dd7070Spatrick Indent() << I->getASTContext() 1384e5dd7070Spatrick .getUnqualifiedObjCPointerType(I->getType()) 1385e5dd7070Spatrick .getAsString(Policy) << ' ' << *I << ";\n"; 1386e5dd7070Spatrick } 1387e5dd7070Spatrick Indentation -= Policy.Indentation; 1388e5dd7070Spatrick Out << "}\n"; 1389e5dd7070Spatrick } 1390e5dd7070Spatrick else if (SID || (OID->decls_begin() != OID->decls_end())) { 1391e5dd7070Spatrick Out << "\n"; 1392e5dd7070Spatrick eolnOut = true; 1393e5dd7070Spatrick } 1394e5dd7070Spatrick 1395e5dd7070Spatrick VisitDeclContext(OID, false); 1396e5dd7070Spatrick if (!eolnOut) 1397e5dd7070Spatrick Out << "\n"; 1398e5dd7070Spatrick Out << "@end"; 1399e5dd7070Spatrick // FIXME: implement the rest... 1400e5dd7070Spatrick } 1401e5dd7070Spatrick 1402e5dd7070Spatrick void DeclPrinter::VisitObjCProtocolDecl(ObjCProtocolDecl *PID) { 1403e5dd7070Spatrick if (!PID->isThisDeclarationADefinition()) { 1404e5dd7070Spatrick Out << "@protocol " << *PID << ";\n"; 1405e5dd7070Spatrick return; 1406e5dd7070Spatrick } 1407e5dd7070Spatrick // Protocols? 1408e5dd7070Spatrick const ObjCList<ObjCProtocolDecl> &Protocols = PID->getReferencedProtocols(); 1409e5dd7070Spatrick if (!Protocols.empty()) { 1410e5dd7070Spatrick Out << "@protocol " << *PID; 1411e5dd7070Spatrick for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(), 1412e5dd7070Spatrick E = Protocols.end(); I != E; ++I) 1413e5dd7070Spatrick Out << (I == Protocols.begin() ? '<' : ',') << **I; 1414e5dd7070Spatrick Out << ">\n"; 1415e5dd7070Spatrick } else 1416e5dd7070Spatrick Out << "@protocol " << *PID << '\n'; 1417e5dd7070Spatrick VisitDeclContext(PID, false); 1418e5dd7070Spatrick Out << "@end"; 1419e5dd7070Spatrick } 1420e5dd7070Spatrick 1421e5dd7070Spatrick void DeclPrinter::VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *PID) { 1422ec727ea7Spatrick Out << "@implementation "; 1423ec727ea7Spatrick if (const auto *CID = PID->getClassInterface()) 1424ec727ea7Spatrick Out << *CID; 1425ec727ea7Spatrick else 1426ec727ea7Spatrick Out << "<<error-type>>"; 1427ec727ea7Spatrick Out << '(' << *PID << ")\n"; 1428e5dd7070Spatrick 1429e5dd7070Spatrick VisitDeclContext(PID, false); 1430e5dd7070Spatrick Out << "@end"; 1431e5dd7070Spatrick // FIXME: implement the rest... 1432e5dd7070Spatrick } 1433e5dd7070Spatrick 1434e5dd7070Spatrick void DeclPrinter::VisitObjCCategoryDecl(ObjCCategoryDecl *PID) { 1435ec727ea7Spatrick Out << "@interface "; 1436ec727ea7Spatrick if (const auto *CID = PID->getClassInterface()) 1437ec727ea7Spatrick Out << *CID; 1438ec727ea7Spatrick else 1439ec727ea7Spatrick Out << "<<error-type>>"; 1440e5dd7070Spatrick if (auto TypeParams = PID->getTypeParamList()) { 1441e5dd7070Spatrick PrintObjCTypeParams(TypeParams); 1442e5dd7070Spatrick } 1443e5dd7070Spatrick Out << "(" << *PID << ")\n"; 1444e5dd7070Spatrick if (PID->ivar_size() > 0) { 1445e5dd7070Spatrick Out << "{\n"; 1446e5dd7070Spatrick Indentation += Policy.Indentation; 1447e5dd7070Spatrick for (const auto *I : PID->ivars()) 1448e5dd7070Spatrick Indent() << I->getASTContext().getUnqualifiedObjCPointerType(I->getType()). 1449e5dd7070Spatrick getAsString(Policy) << ' ' << *I << ";\n"; 1450e5dd7070Spatrick Indentation -= Policy.Indentation; 1451e5dd7070Spatrick Out << "}\n"; 1452e5dd7070Spatrick } 1453e5dd7070Spatrick 1454e5dd7070Spatrick VisitDeclContext(PID, false); 1455e5dd7070Spatrick Out << "@end"; 1456e5dd7070Spatrick 1457e5dd7070Spatrick // FIXME: implement the rest... 1458e5dd7070Spatrick } 1459e5dd7070Spatrick 1460e5dd7070Spatrick void DeclPrinter::VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *AID) { 1461e5dd7070Spatrick Out << "@compatibility_alias " << *AID 1462e5dd7070Spatrick << ' ' << *AID->getClassInterface() << ";\n"; 1463e5dd7070Spatrick } 1464e5dd7070Spatrick 1465e5dd7070Spatrick /// PrintObjCPropertyDecl - print a property declaration. 1466e5dd7070Spatrick /// 1467e5dd7070Spatrick /// Print attributes in the following order: 1468e5dd7070Spatrick /// - class 1469e5dd7070Spatrick /// - nonatomic | atomic 1470e5dd7070Spatrick /// - assign | retain | strong | copy | weak | unsafe_unretained 1471e5dd7070Spatrick /// - readwrite | readonly 1472e5dd7070Spatrick /// - getter & setter 1473e5dd7070Spatrick /// - nullability 1474e5dd7070Spatrick void DeclPrinter::VisitObjCPropertyDecl(ObjCPropertyDecl *PDecl) { 1475e5dd7070Spatrick if (PDecl->getPropertyImplementation() == ObjCPropertyDecl::Required) 1476e5dd7070Spatrick Out << "@required\n"; 1477e5dd7070Spatrick else if (PDecl->getPropertyImplementation() == ObjCPropertyDecl::Optional) 1478e5dd7070Spatrick Out << "@optional\n"; 1479e5dd7070Spatrick 1480e5dd7070Spatrick QualType T = PDecl->getType(); 1481e5dd7070Spatrick 1482e5dd7070Spatrick Out << "@property"; 1483ec727ea7Spatrick if (PDecl->getPropertyAttributes() != ObjCPropertyAttribute::kind_noattr) { 1484e5dd7070Spatrick bool first = true; 1485e5dd7070Spatrick Out << "("; 1486ec727ea7Spatrick if (PDecl->getPropertyAttributes() & ObjCPropertyAttribute::kind_class) { 1487e5dd7070Spatrick Out << (first ? "" : ", ") << "class"; 1488e5dd7070Spatrick first = false; 1489e5dd7070Spatrick } 1490e5dd7070Spatrick 1491ec727ea7Spatrick if (PDecl->getPropertyAttributes() & ObjCPropertyAttribute::kind_direct) { 1492e5dd7070Spatrick Out << (first ? "" : ", ") << "direct"; 1493e5dd7070Spatrick first = false; 1494e5dd7070Spatrick } 1495e5dd7070Spatrick 1496e5dd7070Spatrick if (PDecl->getPropertyAttributes() & 1497ec727ea7Spatrick ObjCPropertyAttribute::kind_nonatomic) { 1498e5dd7070Spatrick Out << (first ? "" : ", ") << "nonatomic"; 1499e5dd7070Spatrick first = false; 1500e5dd7070Spatrick } 1501ec727ea7Spatrick if (PDecl->getPropertyAttributes() & ObjCPropertyAttribute::kind_atomic) { 1502e5dd7070Spatrick Out << (first ? "" : ", ") << "atomic"; 1503e5dd7070Spatrick first = false; 1504e5dd7070Spatrick } 1505e5dd7070Spatrick 1506ec727ea7Spatrick if (PDecl->getPropertyAttributes() & ObjCPropertyAttribute::kind_assign) { 1507e5dd7070Spatrick Out << (first ? "" : ", ") << "assign"; 1508e5dd7070Spatrick first = false; 1509e5dd7070Spatrick } 1510ec727ea7Spatrick if (PDecl->getPropertyAttributes() & ObjCPropertyAttribute::kind_retain) { 1511e5dd7070Spatrick Out << (first ? "" : ", ") << "retain"; 1512e5dd7070Spatrick first = false; 1513e5dd7070Spatrick } 1514e5dd7070Spatrick 1515ec727ea7Spatrick if (PDecl->getPropertyAttributes() & ObjCPropertyAttribute::kind_strong) { 1516e5dd7070Spatrick Out << (first ? "" : ", ") << "strong"; 1517e5dd7070Spatrick first = false; 1518e5dd7070Spatrick } 1519ec727ea7Spatrick if (PDecl->getPropertyAttributes() & ObjCPropertyAttribute::kind_copy) { 1520e5dd7070Spatrick Out << (first ? "" : ", ") << "copy"; 1521e5dd7070Spatrick first = false; 1522e5dd7070Spatrick } 1523ec727ea7Spatrick if (PDecl->getPropertyAttributes() & ObjCPropertyAttribute::kind_weak) { 1524e5dd7070Spatrick Out << (first ? "" : ", ") << "weak"; 1525e5dd7070Spatrick first = false; 1526e5dd7070Spatrick } 1527ec727ea7Spatrick if (PDecl->getPropertyAttributes() & 1528ec727ea7Spatrick ObjCPropertyAttribute::kind_unsafe_unretained) { 1529e5dd7070Spatrick Out << (first ? "" : ", ") << "unsafe_unretained"; 1530e5dd7070Spatrick first = false; 1531e5dd7070Spatrick } 1532e5dd7070Spatrick 1533e5dd7070Spatrick if (PDecl->getPropertyAttributes() & 1534ec727ea7Spatrick ObjCPropertyAttribute::kind_readwrite) { 1535e5dd7070Spatrick Out << (first ? "" : ", ") << "readwrite"; 1536e5dd7070Spatrick first = false; 1537e5dd7070Spatrick } 1538ec727ea7Spatrick if (PDecl->getPropertyAttributes() & ObjCPropertyAttribute::kind_readonly) { 1539e5dd7070Spatrick Out << (first ? "" : ", ") << "readonly"; 1540e5dd7070Spatrick first = false; 1541e5dd7070Spatrick } 1542e5dd7070Spatrick 1543ec727ea7Spatrick if (PDecl->getPropertyAttributes() & ObjCPropertyAttribute::kind_getter) { 1544e5dd7070Spatrick Out << (first ? "" : ", ") << "getter = "; 1545e5dd7070Spatrick PDecl->getGetterName().print(Out); 1546e5dd7070Spatrick first = false; 1547e5dd7070Spatrick } 1548ec727ea7Spatrick if (PDecl->getPropertyAttributes() & ObjCPropertyAttribute::kind_setter) { 1549e5dd7070Spatrick Out << (first ? "" : ", ") << "setter = "; 1550e5dd7070Spatrick PDecl->getSetterName().print(Out); 1551e5dd7070Spatrick first = false; 1552e5dd7070Spatrick } 1553e5dd7070Spatrick 1554e5dd7070Spatrick if (PDecl->getPropertyAttributes() & 1555ec727ea7Spatrick ObjCPropertyAttribute::kind_nullability) { 1556e5dd7070Spatrick if (auto nullability = AttributedType::stripOuterNullability(T)) { 1557e5dd7070Spatrick if (*nullability == NullabilityKind::Unspecified && 1558e5dd7070Spatrick (PDecl->getPropertyAttributes() & 1559ec727ea7Spatrick ObjCPropertyAttribute::kind_null_resettable)) { 1560e5dd7070Spatrick Out << (first ? "" : ", ") << "null_resettable"; 1561e5dd7070Spatrick } else { 1562e5dd7070Spatrick Out << (first ? "" : ", ") 1563e5dd7070Spatrick << getNullabilitySpelling(*nullability, true); 1564e5dd7070Spatrick } 1565e5dd7070Spatrick first = false; 1566e5dd7070Spatrick } 1567e5dd7070Spatrick } 1568e5dd7070Spatrick 1569e5dd7070Spatrick (void) first; // Silence dead store warning due to idiomatic code. 1570e5dd7070Spatrick Out << ")"; 1571e5dd7070Spatrick } 1572e5dd7070Spatrick std::string TypeStr = PDecl->getASTContext().getUnqualifiedObjCPointerType(T). 1573e5dd7070Spatrick getAsString(Policy); 1574e5dd7070Spatrick Out << ' ' << TypeStr; 1575e5dd7070Spatrick if (!StringRef(TypeStr).endswith("*")) 1576e5dd7070Spatrick Out << ' '; 1577e5dd7070Spatrick Out << *PDecl; 1578e5dd7070Spatrick if (Policy.PolishForDeclaration) 1579e5dd7070Spatrick Out << ';'; 1580e5dd7070Spatrick } 1581e5dd7070Spatrick 1582e5dd7070Spatrick void DeclPrinter::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *PID) { 1583e5dd7070Spatrick if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize) 1584e5dd7070Spatrick Out << "@synthesize "; 1585e5dd7070Spatrick else 1586e5dd7070Spatrick Out << "@dynamic "; 1587e5dd7070Spatrick Out << *PID->getPropertyDecl(); 1588e5dd7070Spatrick if (PID->getPropertyIvarDecl()) 1589e5dd7070Spatrick Out << '=' << *PID->getPropertyIvarDecl(); 1590e5dd7070Spatrick } 1591e5dd7070Spatrick 1592e5dd7070Spatrick void DeclPrinter::VisitUsingDecl(UsingDecl *D) { 1593e5dd7070Spatrick if (!D->isAccessDeclaration()) 1594e5dd7070Spatrick Out << "using "; 1595e5dd7070Spatrick if (D->hasTypename()) 1596e5dd7070Spatrick Out << "typename "; 1597e5dd7070Spatrick D->getQualifier()->print(Out, Policy); 1598e5dd7070Spatrick 1599e5dd7070Spatrick // Use the correct record name when the using declaration is used for 1600e5dd7070Spatrick // inheriting constructors. 1601e5dd7070Spatrick for (const auto *Shadow : D->shadows()) { 1602e5dd7070Spatrick if (const auto *ConstructorShadow = 1603e5dd7070Spatrick dyn_cast<ConstructorUsingShadowDecl>(Shadow)) { 1604e5dd7070Spatrick assert(Shadow->getDeclContext() == ConstructorShadow->getDeclContext()); 1605e5dd7070Spatrick Out << *ConstructorShadow->getNominatedBaseClass(); 1606e5dd7070Spatrick return; 1607e5dd7070Spatrick } 1608e5dd7070Spatrick } 1609e5dd7070Spatrick Out << *D; 1610e5dd7070Spatrick } 1611e5dd7070Spatrick 1612*a9ac8606Spatrick void DeclPrinter::VisitUsingEnumDecl(UsingEnumDecl *D) { 1613*a9ac8606Spatrick Out << "using enum " << D->getEnumDecl(); 1614*a9ac8606Spatrick } 1615*a9ac8606Spatrick 1616e5dd7070Spatrick void 1617e5dd7070Spatrick DeclPrinter::VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D) { 1618e5dd7070Spatrick Out << "using typename "; 1619e5dd7070Spatrick D->getQualifier()->print(Out, Policy); 1620e5dd7070Spatrick Out << D->getDeclName(); 1621e5dd7070Spatrick } 1622e5dd7070Spatrick 1623e5dd7070Spatrick void DeclPrinter::VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D) { 1624e5dd7070Spatrick if (!D->isAccessDeclaration()) 1625e5dd7070Spatrick Out << "using "; 1626e5dd7070Spatrick D->getQualifier()->print(Out, Policy); 1627e5dd7070Spatrick Out << D->getDeclName(); 1628e5dd7070Spatrick } 1629e5dd7070Spatrick 1630e5dd7070Spatrick void DeclPrinter::VisitUsingShadowDecl(UsingShadowDecl *D) { 1631e5dd7070Spatrick // ignore 1632e5dd7070Spatrick } 1633e5dd7070Spatrick 1634e5dd7070Spatrick void DeclPrinter::VisitOMPThreadPrivateDecl(OMPThreadPrivateDecl *D) { 1635e5dd7070Spatrick Out << "#pragma omp threadprivate"; 1636e5dd7070Spatrick if (!D->varlist_empty()) { 1637e5dd7070Spatrick for (OMPThreadPrivateDecl::varlist_iterator I = D->varlist_begin(), 1638e5dd7070Spatrick E = D->varlist_end(); 1639e5dd7070Spatrick I != E; ++I) { 1640e5dd7070Spatrick Out << (I == D->varlist_begin() ? '(' : ','); 1641e5dd7070Spatrick NamedDecl *ND = cast<DeclRefExpr>(*I)->getDecl(); 1642e5dd7070Spatrick ND->printQualifiedName(Out); 1643e5dd7070Spatrick } 1644e5dd7070Spatrick Out << ")"; 1645e5dd7070Spatrick } 1646e5dd7070Spatrick } 1647e5dd7070Spatrick 1648e5dd7070Spatrick void DeclPrinter::VisitOMPAllocateDecl(OMPAllocateDecl *D) { 1649e5dd7070Spatrick Out << "#pragma omp allocate"; 1650e5dd7070Spatrick if (!D->varlist_empty()) { 1651e5dd7070Spatrick for (OMPAllocateDecl::varlist_iterator I = D->varlist_begin(), 1652e5dd7070Spatrick E = D->varlist_end(); 1653e5dd7070Spatrick I != E; ++I) { 1654e5dd7070Spatrick Out << (I == D->varlist_begin() ? '(' : ','); 1655e5dd7070Spatrick NamedDecl *ND = cast<DeclRefExpr>(*I)->getDecl(); 1656e5dd7070Spatrick ND->printQualifiedName(Out); 1657e5dd7070Spatrick } 1658e5dd7070Spatrick Out << ")"; 1659e5dd7070Spatrick } 1660e5dd7070Spatrick if (!D->clauselist_empty()) { 1661e5dd7070Spatrick Out << " "; 1662e5dd7070Spatrick OMPClausePrinter Printer(Out, Policy); 1663e5dd7070Spatrick for (OMPClause *C : D->clauselists()) 1664e5dd7070Spatrick Printer.Visit(C); 1665e5dd7070Spatrick } 1666e5dd7070Spatrick } 1667e5dd7070Spatrick 1668e5dd7070Spatrick void DeclPrinter::VisitOMPRequiresDecl(OMPRequiresDecl *D) { 1669e5dd7070Spatrick Out << "#pragma omp requires "; 1670e5dd7070Spatrick if (!D->clauselist_empty()) { 1671e5dd7070Spatrick OMPClausePrinter Printer(Out, Policy); 1672e5dd7070Spatrick for (auto I = D->clauselist_begin(), E = D->clauselist_end(); I != E; ++I) 1673e5dd7070Spatrick Printer.Visit(*I); 1674e5dd7070Spatrick } 1675e5dd7070Spatrick } 1676e5dd7070Spatrick 1677e5dd7070Spatrick void DeclPrinter::VisitOMPDeclareReductionDecl(OMPDeclareReductionDecl *D) { 1678e5dd7070Spatrick if (!D->isInvalidDecl()) { 1679e5dd7070Spatrick Out << "#pragma omp declare reduction ("; 1680e5dd7070Spatrick if (D->getDeclName().getNameKind() == DeclarationName::CXXOperatorName) { 1681e5dd7070Spatrick const char *OpName = 1682e5dd7070Spatrick getOperatorSpelling(D->getDeclName().getCXXOverloadedOperator()); 1683e5dd7070Spatrick assert(OpName && "not an overloaded operator"); 1684e5dd7070Spatrick Out << OpName; 1685e5dd7070Spatrick } else { 1686e5dd7070Spatrick assert(D->getDeclName().isIdentifier()); 1687e5dd7070Spatrick D->printName(Out); 1688e5dd7070Spatrick } 1689e5dd7070Spatrick Out << " : "; 1690e5dd7070Spatrick D->getType().print(Out, Policy); 1691e5dd7070Spatrick Out << " : "; 1692*a9ac8606Spatrick D->getCombiner()->printPretty(Out, nullptr, Policy, 0, "\n", &Context); 1693e5dd7070Spatrick Out << ")"; 1694e5dd7070Spatrick if (auto *Init = D->getInitializer()) { 1695e5dd7070Spatrick Out << " initializer("; 1696e5dd7070Spatrick switch (D->getInitializerKind()) { 1697e5dd7070Spatrick case OMPDeclareReductionDecl::DirectInit: 1698e5dd7070Spatrick Out << "omp_priv("; 1699e5dd7070Spatrick break; 1700e5dd7070Spatrick case OMPDeclareReductionDecl::CopyInit: 1701e5dd7070Spatrick Out << "omp_priv = "; 1702e5dd7070Spatrick break; 1703e5dd7070Spatrick case OMPDeclareReductionDecl::CallInit: 1704e5dd7070Spatrick break; 1705e5dd7070Spatrick } 1706*a9ac8606Spatrick Init->printPretty(Out, nullptr, Policy, 0, "\n", &Context); 1707e5dd7070Spatrick if (D->getInitializerKind() == OMPDeclareReductionDecl::DirectInit) 1708e5dd7070Spatrick Out << ")"; 1709e5dd7070Spatrick Out << ")"; 1710e5dd7070Spatrick } 1711e5dd7070Spatrick } 1712e5dd7070Spatrick } 1713e5dd7070Spatrick 1714e5dd7070Spatrick void DeclPrinter::VisitOMPDeclareMapperDecl(OMPDeclareMapperDecl *D) { 1715e5dd7070Spatrick if (!D->isInvalidDecl()) { 1716e5dd7070Spatrick Out << "#pragma omp declare mapper ("; 1717e5dd7070Spatrick D->printName(Out); 1718e5dd7070Spatrick Out << " : "; 1719e5dd7070Spatrick D->getType().print(Out, Policy); 1720e5dd7070Spatrick Out << " "; 1721e5dd7070Spatrick Out << D->getVarName(); 1722e5dd7070Spatrick Out << ")"; 1723e5dd7070Spatrick if (!D->clauselist_empty()) { 1724e5dd7070Spatrick OMPClausePrinter Printer(Out, Policy); 1725e5dd7070Spatrick for (auto *C : D->clauselists()) { 1726e5dd7070Spatrick Out << " "; 1727e5dd7070Spatrick Printer.Visit(C); 1728e5dd7070Spatrick } 1729e5dd7070Spatrick } 1730e5dd7070Spatrick } 1731e5dd7070Spatrick } 1732e5dd7070Spatrick 1733e5dd7070Spatrick void DeclPrinter::VisitOMPCapturedExprDecl(OMPCapturedExprDecl *D) { 1734*a9ac8606Spatrick D->getInit()->printPretty(Out, nullptr, Policy, Indentation, "\n", &Context); 1735e5dd7070Spatrick } 1736e5dd7070Spatrick 1737ec727ea7Spatrick void DeclPrinter::VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *TTP) { 1738ec727ea7Spatrick if (const TypeConstraint *TC = TTP->getTypeConstraint()) 1739ec727ea7Spatrick TC->print(Out, Policy); 1740ec727ea7Spatrick else if (TTP->wasDeclaredWithTypename()) 1741ec727ea7Spatrick Out << "typename"; 1742ec727ea7Spatrick else 1743ec727ea7Spatrick Out << "class"; 1744ec727ea7Spatrick 1745ec727ea7Spatrick if (TTP->isParameterPack()) 1746ec727ea7Spatrick Out << " ..."; 1747*a9ac8606Spatrick else if (TTP->getDeclName()) 1748ec727ea7Spatrick Out << ' '; 1749ec727ea7Spatrick 1750*a9ac8606Spatrick if (TTP->getDeclName()) 1751*a9ac8606Spatrick Out << TTP->getDeclName(); 1752ec727ea7Spatrick 1753ec727ea7Spatrick if (TTP->hasDefaultArgument()) { 1754ec727ea7Spatrick Out << " = "; 1755ec727ea7Spatrick Out << TTP->getDefaultArgument().getAsString(Policy); 1756ec727ea7Spatrick } 1757ec727ea7Spatrick } 1758ec727ea7Spatrick 1759ec727ea7Spatrick void DeclPrinter::VisitNonTypeTemplateParmDecl( 1760ec727ea7Spatrick const NonTypeTemplateParmDecl *NTTP) { 1761ec727ea7Spatrick StringRef Name; 1762ec727ea7Spatrick if (IdentifierInfo *II = NTTP->getIdentifier()) 1763ec727ea7Spatrick Name = II->getName(); 1764ec727ea7Spatrick printDeclType(NTTP->getType(), Name, NTTP->isParameterPack()); 1765ec727ea7Spatrick 1766ec727ea7Spatrick if (NTTP->hasDefaultArgument()) { 1767ec727ea7Spatrick Out << " = "; 1768*a9ac8606Spatrick NTTP->getDefaultArgument()->printPretty(Out, nullptr, Policy, Indentation, 1769*a9ac8606Spatrick "\n", &Context); 1770ec727ea7Spatrick } 1771ec727ea7Spatrick } 1772