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