1193326Sed//===--- DeclPrinter.cpp - Printing implementation for Decl ASTs ----------===// 2193326Sed// 3193326Sed// The LLVM Compiler Infrastructure 4193326Sed// 5193326Sed// This file is distributed under the University of Illinois Open Source 6193326Sed// License. See LICENSE.TXT for details. 7193326Sed// 8193326Sed//===----------------------------------------------------------------------===// 9193326Sed// 10249423Sdim// This file implements the Decl::print method, which pretty prints the 11193326Sed// AST back out to C/Objective-C/C++/Objective-C++ code. 12193326Sed// 13193326Sed//===----------------------------------------------------------------------===// 14193326Sed#include "clang/AST/ASTContext.h" 15249423Sdim#include "clang/AST/Attr.h" 16193326Sed#include "clang/AST/Decl.h" 17193326Sed#include "clang/AST/DeclCXX.h" 18193326Sed#include "clang/AST/DeclObjC.h" 19249423Sdim#include "clang/AST/DeclVisitor.h" 20193326Sed#include "clang/AST/Expr.h" 21203955Srdivacky#include "clang/AST/ExprCXX.h" 22193326Sed#include "clang/AST/PrettyPrinter.h" 23234353Sdim#include "clang/Basic/Module.h" 24193326Sed#include "llvm/Support/raw_ostream.h" 25193326Sedusing namespace clang; 26193326Sed 27193326Sednamespace { 28199990Srdivacky class DeclPrinter : public DeclVisitor<DeclPrinter> { 29226633Sdim raw_ostream &Out; 30193326Sed PrintingPolicy Policy; 31193326Sed unsigned Indentation; 32226633Sdim bool PrintInstantiation; 33193326Sed 34226633Sdim raw_ostream& Indent() { return Indent(Indentation); } 35226633Sdim raw_ostream& Indent(unsigned Indentation); 36226633Sdim void ProcessDeclGroup(SmallVectorImpl<Decl*>& Decls); 37193326Sed 38198092Srdivacky void Print(AccessSpecifier AS); 39198092Srdivacky 40193326Sed public: 41239462Sdim DeclPrinter(raw_ostream &Out, const PrintingPolicy &Policy, 42239462Sdim unsigned Indentation = 0, bool PrintInstantiation = false) 43239462Sdim : Out(Out), Policy(Policy), Indentation(Indentation), 44226633Sdim PrintInstantiation(PrintInstantiation) { } 45193326Sed 46193326Sed void VisitDeclContext(DeclContext *DC, bool Indent = true); 47193326Sed 48193326Sed void VisitTranslationUnitDecl(TranslationUnitDecl *D); 49193326Sed void VisitTypedefDecl(TypedefDecl *D); 50221345Sdim void VisitTypeAliasDecl(TypeAliasDecl *D); 51193326Sed void VisitEnumDecl(EnumDecl *D); 52193326Sed void VisitRecordDecl(RecordDecl *D); 53193326Sed void VisitEnumConstantDecl(EnumConstantDecl *D); 54249423Sdim void VisitEmptyDecl(EmptyDecl *D); 55193326Sed void VisitFunctionDecl(FunctionDecl *D); 56249423Sdim void VisitFriendDecl(FriendDecl *D); 57193326Sed void VisitFieldDecl(FieldDecl *D); 58193326Sed void VisitVarDecl(VarDecl *D); 59218893Sdim void VisitLabelDecl(LabelDecl *D); 60193326Sed void VisitParmVarDecl(ParmVarDecl *D); 61193326Sed void VisitFileScopeAsmDecl(FileScopeAsmDecl *D); 62234353Sdim void VisitImportDecl(ImportDecl *D); 63221345Sdim void VisitStaticAssertDecl(StaticAssertDecl *D); 64193326Sed void VisitNamespaceDecl(NamespaceDecl *D); 65193326Sed void VisitUsingDirectiveDecl(UsingDirectiveDecl *D); 66193326Sed void VisitNamespaceAliasDecl(NamespaceAliasDecl *D); 67193326Sed void VisitCXXRecordDecl(CXXRecordDecl *D); 68193326Sed void VisitLinkageSpecDecl(LinkageSpecDecl *D); 69221345Sdim void VisitTemplateDecl(const TemplateDecl *D); 70226633Sdim void VisitFunctionTemplateDecl(FunctionTemplateDecl *D); 71226633Sdim void VisitClassTemplateDecl(ClassTemplateDecl *D); 72193326Sed void VisitObjCMethodDecl(ObjCMethodDecl *D); 73193326Sed void VisitObjCImplementationDecl(ObjCImplementationDecl *D); 74193326Sed void VisitObjCInterfaceDecl(ObjCInterfaceDecl *D); 75193326Sed void VisitObjCProtocolDecl(ObjCProtocolDecl *D); 76193326Sed void VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D); 77193326Sed void VisitObjCCategoryDecl(ObjCCategoryDecl *D); 78193326Sed void VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *D); 79193326Sed void VisitObjCPropertyDecl(ObjCPropertyDecl *D); 80193326Sed void VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D); 81199482Srdivacky void VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D); 82199482Srdivacky void VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D); 83198092Srdivacky void VisitUsingDecl(UsingDecl *D); 84199482Srdivacky void VisitUsingShadowDecl(UsingShadowDecl *D); 85249423Sdim void VisitOMPThreadPrivateDecl(OMPThreadPrivateDecl *D); 86226633Sdim 87226633Sdim void PrintTemplateParameters(const TemplateParameterList *Params, 88249423Sdim const TemplateArgumentList *Args = 0); 89234353Sdim void prettyPrintAttributes(Decl *D); 90193326Sed }; 91193326Sed} 92193326Sed 93226633Sdimvoid Decl::print(raw_ostream &Out, unsigned Indentation, 94226633Sdim bool PrintInstantiation) const { 95226633Sdim print(Out, getASTContext().getPrintingPolicy(), Indentation, PrintInstantiation); 96193326Sed} 97193326Sed 98226633Sdimvoid Decl::print(raw_ostream &Out, const PrintingPolicy &Policy, 99226633Sdim unsigned Indentation, bool PrintInstantiation) const { 100239462Sdim DeclPrinter Printer(Out, Policy, Indentation, PrintInstantiation); 101198092Srdivacky Printer.Visit(const_cast<Decl*>(this)); 102193326Sed} 103193326Sed 104193326Sedstatic QualType GetBaseType(QualType T) { 105193326Sed // FIXME: This should be on the Type class! 106193326Sed QualType BaseType = T; 107193326Sed while (!BaseType->isSpecifierType()) { 108193326Sed if (isa<TypedefType>(BaseType)) 109193326Sed break; 110198092Srdivacky else if (const PointerType* PTy = BaseType->getAs<PointerType>()) 111193326Sed BaseType = PTy->getPointeeType(); 112243830Sdim else if (const BlockPointerType *BPy = BaseType->getAs<BlockPointerType>()) 113243830Sdim BaseType = BPy->getPointeeType(); 114193326Sed else if (const ArrayType* ATy = dyn_cast<ArrayType>(BaseType)) 115193326Sed BaseType = ATy->getElementType(); 116198092Srdivacky else if (const FunctionType* FTy = BaseType->getAs<FunctionType>()) 117193326Sed BaseType = FTy->getResultType(); 118198092Srdivacky else if (const VectorType *VTy = BaseType->getAs<VectorType>()) 119195341Sed BaseType = VTy->getElementType(); 120239462Sdim else if (const ReferenceType *RTy = BaseType->getAs<ReferenceType>()) 121239462Sdim BaseType = RTy->getPointeeType(); 122193326Sed else 123226633Sdim llvm_unreachable("Unknown declarator!"); 124193326Sed } 125193326Sed return BaseType; 126193326Sed} 127193326Sed 128193326Sedstatic QualType getDeclType(Decl* D) { 129221345Sdim if (TypedefNameDecl* TDD = dyn_cast<TypedefNameDecl>(D)) 130193326Sed return TDD->getUnderlyingType(); 131193326Sed if (ValueDecl* VD = dyn_cast<ValueDecl>(D)) 132193326Sed return VD->getType(); 133193326Sed return QualType(); 134193326Sed} 135193326Sed 136193326Sedvoid Decl::printGroup(Decl** Begin, unsigned NumDecls, 137226633Sdim raw_ostream &Out, const PrintingPolicy &Policy, 138193326Sed unsigned Indentation) { 139193326Sed if (NumDecls == 1) { 140195341Sed (*Begin)->print(Out, Policy, Indentation); 141193326Sed return; 142193326Sed } 143193326Sed 144193326Sed Decl** End = Begin + NumDecls; 145193326Sed TagDecl* TD = dyn_cast<TagDecl>(*Begin); 146193326Sed if (TD) 147193326Sed ++Begin; 148193326Sed 149193326Sed PrintingPolicy SubPolicy(Policy); 150226633Sdim if (TD && TD->isCompleteDefinition()) { 151195341Sed TD->print(Out, Policy, Indentation); 152193326Sed Out << " "; 153193326Sed SubPolicy.SuppressTag = true; 154193326Sed } 155193326Sed 156193326Sed bool isFirst = true; 157193326Sed for ( ; Begin != End; ++Begin) { 158193326Sed if (isFirst) { 159193326Sed SubPolicy.SuppressSpecifiers = false; 160193326Sed isFirst = false; 161193326Sed } else { 162193326Sed if (!isFirst) Out << ", "; 163193326Sed SubPolicy.SuppressSpecifiers = true; 164193326Sed } 165193326Sed 166195341Sed (*Begin)->print(Out, SubPolicy, Indentation); 167193326Sed } 168193326Sed} 169193326Sed 170200583Srdivackyvoid DeclContext::dumpDeclContext() const { 171200583Srdivacky // Get the translation unit 172200583Srdivacky const DeclContext *DC = this; 173200583Srdivacky while (!DC->isTranslationUnit()) 174200583Srdivacky DC = DC->getParent(); 175200583Srdivacky 176200583Srdivacky ASTContext &Ctx = cast<TranslationUnitDecl>(DC)->getASTContext(); 177239462Sdim DeclPrinter Printer(llvm::errs(), Ctx.getPrintingPolicy(), 0); 178200583Srdivacky Printer.VisitDeclContext(const_cast<DeclContext *>(this), /*Indent=*/false); 179200583Srdivacky} 180200583Srdivacky 181226633Sdimraw_ostream& DeclPrinter::Indent(unsigned Indentation) { 182199990Srdivacky for (unsigned i = 0; i != Indentation; ++i) 183193326Sed Out << " "; 184193326Sed return Out; 185193326Sed} 186193326Sed 187234353Sdimvoid DeclPrinter::prettyPrintAttributes(Decl *D) { 188249423Sdim if (Policy.PolishForDeclaration) 189243830Sdim return; 190243830Sdim 191234353Sdim if (D->hasAttrs()) { 192234353Sdim AttrVec &Attrs = D->getAttrs(); 193234353Sdim for (AttrVec::const_iterator i=Attrs.begin(), e=Attrs.end(); i!=e; ++i) { 194239462Sdim Attr *A = *i; 195239462Sdim A->printPretty(Out, Policy); 196234353Sdim } 197234353Sdim } 198234353Sdim} 199234353Sdim 200226633Sdimvoid DeclPrinter::ProcessDeclGroup(SmallVectorImpl<Decl*>& Decls) { 201193326Sed this->Indent(); 202195341Sed Decl::printGroup(Decls.data(), Decls.size(), Out, Policy, Indentation); 203193326Sed Out << ";\n"; 204193326Sed Decls.clear(); 205193326Sed 206193326Sed} 207193326Sed 208198092Srdivackyvoid DeclPrinter::Print(AccessSpecifier AS) { 209198092Srdivacky switch(AS) { 210226633Sdim case AS_none: llvm_unreachable("No access specifier!"); 211198092Srdivacky case AS_public: Out << "public"; break; 212198092Srdivacky case AS_protected: Out << "protected"; break; 213210299Sed case AS_private: Out << "private"; break; 214198092Srdivacky } 215198092Srdivacky} 216198092Srdivacky 217193326Sed//---------------------------------------------------------------------------- 218193326Sed// Common C declarations 219193326Sed//---------------------------------------------------------------------------- 220193326Sed 221193326Sedvoid DeclPrinter::VisitDeclContext(DeclContext *DC, bool Indent) { 222243830Sdim if (Policy.TerseOutput) 223243830Sdim return; 224243830Sdim 225193326Sed if (Indent) 226193326Sed Indentation += Policy.Indentation; 227193326Sed 228226633Sdim SmallVector<Decl*, 2> Decls; 229195341Sed for (DeclContext::decl_iterator D = DC->decls_begin(), DEnd = DC->decls_end(); 230193326Sed D != DEnd; ++D) { 231212904Sdim 232212904Sdim // Don't print ObjCIvarDecls, as they are printed when visiting the 233212904Sdim // containing ObjCInterfaceDecl. 234212904Sdim if (isa<ObjCIvarDecl>(*D)) 235212904Sdim continue; 236212904Sdim 237249423Sdim // Skip over implicit declarations in pretty-printing mode. 238249423Sdim if (D->isImplicit()) 239249423Sdim continue; 240249423Sdim 241249423Sdim // FIXME: Ugly hack so we don't pretty-print the builtin declaration 242249423Sdim // of __builtin_va_list or __[u]int128_t. There should be some other way 243249423Sdim // to check that. 244249423Sdim if (NamedDecl *ND = dyn_cast<NamedDecl>(*D)) { 245249423Sdim if (IdentifierInfo *II = ND->getIdentifier()) { 246249423Sdim if (II->isStr("__builtin_va_list") || 247249423Sdim II->isStr("__int128_t") || II->isStr("__uint128_t")) 248249423Sdim continue; 249198092Srdivacky } 250198092Srdivacky } 251198092Srdivacky 252193326Sed // The next bits of code handles stuff like "struct {int x;} a,b"; we're 253193326Sed // forced to merge the declarations because there's no other way to 254193326Sed // refer to the struct in question. This limited merging is safe without 255193326Sed // a bunch of other checks because it only merges declarations directly 256193326Sed // referring to the tag, not typedefs. 257193326Sed // 258193326Sed // Check whether the current declaration should be grouped with a previous 259193326Sed // unnamed struct. 260193326Sed QualType CurDeclType = getDeclType(*D); 261193326Sed if (!Decls.empty() && !CurDeclType.isNull()) { 262193326Sed QualType BaseType = GetBaseType(CurDeclType); 263263508Sdim if (!BaseType.isNull() && isa<ElaboratedType>(BaseType)) 264263508Sdim BaseType = cast<ElaboratedType>(BaseType)->getNamedType(); 265193326Sed if (!BaseType.isNull() && isa<TagType>(BaseType) && 266193326Sed cast<TagType>(BaseType)->getDecl() == Decls[0]) { 267193326Sed Decls.push_back(*D); 268193326Sed continue; 269193326Sed } 270193326Sed } 271193326Sed 272193326Sed // If we have a merged group waiting to be handled, handle it now. 273193326Sed if (!Decls.empty()) 274193326Sed ProcessDeclGroup(Decls); 275193326Sed 276193326Sed // If the current declaration is an unnamed tag type, save it 277193326Sed // so we can merge it with the subsequent declaration(s) using it. 278193326Sed if (isa<TagDecl>(*D) && !cast<TagDecl>(*D)->getIdentifier()) { 279193326Sed Decls.push_back(*D); 280193326Sed continue; 281193326Sed } 282210299Sed 283210299Sed if (isa<AccessSpecDecl>(*D)) { 284210299Sed Indentation -= Policy.Indentation; 285210299Sed this->Indent(); 286210299Sed Print(D->getAccess()); 287210299Sed Out << ":\n"; 288210299Sed Indentation += Policy.Indentation; 289210299Sed continue; 290210299Sed } 291210299Sed 292193326Sed this->Indent(); 293193326Sed Visit(*D); 294198092Srdivacky 295198092Srdivacky // FIXME: Need to be able to tell the DeclPrinter when 296193326Sed const char *Terminator = 0; 297249423Sdim if (isa<OMPThreadPrivateDecl>(*D)) 298193326Sed Terminator = 0; 299249423Sdim else if (isa<FunctionDecl>(*D) && 300249423Sdim cast<FunctionDecl>(*D)->isThisDeclarationADefinition()) 301249423Sdim Terminator = 0; 302193326Sed else if (isa<ObjCMethodDecl>(*D) && cast<ObjCMethodDecl>(*D)->getBody()) 303193326Sed Terminator = 0; 304193326Sed else if (isa<NamespaceDecl>(*D) || isa<LinkageSpecDecl>(*D) || 305198092Srdivacky isa<ObjCImplementationDecl>(*D) || 306193326Sed isa<ObjCInterfaceDecl>(*D) || 307193326Sed isa<ObjCProtocolDecl>(*D) || 308193326Sed isa<ObjCCategoryImplDecl>(*D) || 309193326Sed isa<ObjCCategoryDecl>(*D)) 310193326Sed Terminator = 0; 311193326Sed else if (isa<EnumConstantDecl>(*D)) { 312193326Sed DeclContext::decl_iterator Next = D; 313193326Sed ++Next; 314193326Sed if (Next != DEnd) 315193326Sed Terminator = ","; 316193326Sed } else 317193326Sed Terminator = ";"; 318193326Sed 319193326Sed if (Terminator) 320193326Sed Out << Terminator; 321193326Sed Out << "\n"; 322193326Sed } 323193326Sed 324193326Sed if (!Decls.empty()) 325193326Sed ProcessDeclGroup(Decls); 326193326Sed 327193326Sed if (Indent) 328193326Sed Indentation -= Policy.Indentation; 329193326Sed} 330193326Sed 331193326Sedvoid DeclPrinter::VisitTranslationUnitDecl(TranslationUnitDecl *D) { 332193326Sed VisitDeclContext(D, false); 333193326Sed} 334193326Sed 335193326Sedvoid DeclPrinter::VisitTypedefDecl(TypedefDecl *D) { 336226633Sdim if (!Policy.SuppressSpecifiers) { 337193326Sed Out << "typedef "; 338226633Sdim 339226633Sdim if (D->isModulePrivate()) 340226633Sdim Out << "__module_private__ "; 341226633Sdim } 342263508Sdim D->getTypeSourceInfo()->getType().print(Out, Policy, D->getName()); 343234353Sdim prettyPrintAttributes(D); 344193326Sed} 345193326Sed 346221345Sdimvoid DeclPrinter::VisitTypeAliasDecl(TypeAliasDecl *D) { 347263508Sdim Out << "using " << *D; 348263508Sdim prettyPrintAttributes(D); 349263508Sdim Out << " = " << D->getTypeSourceInfo()->getType().getAsString(Policy); 350221345Sdim} 351221345Sdim 352193326Sedvoid DeclPrinter::VisitEnumDecl(EnumDecl *D) { 353226633Sdim if (!Policy.SuppressSpecifiers && D->isModulePrivate()) 354226633Sdim Out << "__module_private__ "; 355218893Sdim Out << "enum "; 356218893Sdim if (D->isScoped()) { 357218893Sdim if (D->isScopedUsingClassTag()) 358218893Sdim Out << "class "; 359218893Sdim else 360218893Sdim Out << "struct "; 361218893Sdim } 362226633Sdim Out << *D; 363218893Sdim 364239462Sdim if (D->isFixed()) 365239462Sdim Out << " : " << D->getIntegerType().stream(Policy); 366218893Sdim 367226633Sdim if (D->isCompleteDefinition()) { 368218893Sdim Out << " {\n"; 369218893Sdim VisitDeclContext(D); 370218893Sdim Indent() << "}"; 371218893Sdim } 372234353Sdim prettyPrintAttributes(D); 373193326Sed} 374193326Sed 375193326Sedvoid DeclPrinter::VisitRecordDecl(RecordDecl *D) { 376226633Sdim if (!Policy.SuppressSpecifiers && D->isModulePrivate()) 377226633Sdim Out << "__module_private__ "; 378193326Sed Out << D->getKindName(); 379207619Srdivacky if (D->getIdentifier()) 380226633Sdim Out << ' ' << *D; 381198092Srdivacky 382226633Sdim if (D->isCompleteDefinition()) { 383193326Sed Out << " {\n"; 384193326Sed VisitDeclContext(D); 385193326Sed Indent() << "}"; 386193326Sed } 387193326Sed} 388193326Sed 389193326Sedvoid DeclPrinter::VisitEnumConstantDecl(EnumConstantDecl *D) { 390226633Sdim Out << *D; 391193326Sed if (Expr *Init = D->getInitExpr()) { 392193326Sed Out << " = "; 393239462Sdim Init->printPretty(Out, 0, Policy, Indentation); 394193326Sed } 395193326Sed} 396193326Sed 397198092Srdivackyvoid DeclPrinter::VisitFunctionDecl(FunctionDecl *D) { 398249423Sdim CXXConstructorDecl *CDecl = dyn_cast<CXXConstructorDecl>(D); 399193326Sed if (!Policy.SuppressSpecifiers) { 400249423Sdim switch (D->getStorageClass()) { 401212904Sdim case SC_None: break; 402212904Sdim case SC_Extern: Out << "extern "; break; 403212904Sdim case SC_Static: Out << "static "; break; 404212904Sdim case SC_PrivateExtern: Out << "__private_extern__ "; break; 405226633Sdim case SC_Auto: case SC_Register: case SC_OpenCLWorkGroupLocal: 406226633Sdim llvm_unreachable("invalid for functions"); 407193326Sed } 408193326Sed 409226633Sdim if (D->isInlineSpecified()) Out << "inline "; 410193326Sed if (D->isVirtualAsWritten()) Out << "virtual "; 411226633Sdim if (D->isModulePrivate()) Out << "__module_private__ "; 412249423Sdim if (CDecl && CDecl->isExplicitSpecified()) 413249423Sdim Out << "explicit "; 414193326Sed } 415193326Sed 416193326Sed PrintingPolicy SubPolicy(Policy); 417193326Sed SubPolicy.SuppressSpecifiers = false; 418212904Sdim std::string Proto = D->getNameInfo().getAsString(); 419193326Sed 420218893Sdim QualType Ty = D->getType(); 421218893Sdim while (const ParenType *PT = dyn_cast<ParenType>(Ty)) { 422218893Sdim Proto = '(' + Proto + ')'; 423218893Sdim Ty = PT->getInnerType(); 424218893Sdim } 425218893Sdim 426218893Sdim if (isa<FunctionType>(Ty)) { 427218893Sdim const FunctionType *AFT = Ty->getAs<FunctionType>(); 428193326Sed const FunctionProtoType *FT = 0; 429193326Sed if (D->hasWrittenPrototype()) 430193326Sed FT = dyn_cast<FunctionProtoType>(AFT); 431193326Sed 432193326Sed Proto += "("; 433193326Sed if (FT) { 434193326Sed llvm::raw_string_ostream POut(Proto); 435239462Sdim DeclPrinter ParamPrinter(POut, SubPolicy, Indentation); 436193326Sed for (unsigned i = 0, e = D->getNumParams(); i != e; ++i) { 437193326Sed if (i) POut << ", "; 438193326Sed ParamPrinter.VisitParmVarDecl(D->getParamDecl(i)); 439193326Sed } 440198092Srdivacky 441193326Sed if (FT->isVariadic()) { 442193326Sed if (D->getNumParams()) POut << ", "; 443193326Sed POut << "..."; 444193326Sed } 445223017Sdim } else if (D->doesThisDeclarationHaveABody() && !D->hasPrototype()) { 446193326Sed for (unsigned i = 0, e = D->getNumParams(); i != e; ++i) { 447193326Sed if (i) 448193326Sed Proto += ", "; 449193326Sed Proto += D->getParamDecl(i)->getNameAsString(); 450193326Sed } 451193326Sed } 452193326Sed 453193326Sed Proto += ")"; 454200583Srdivacky 455239462Sdim if (FT) { 456239462Sdim if (FT->isConst()) 457218893Sdim Proto += " const"; 458239462Sdim if (FT->isVolatile()) 459218893Sdim Proto += " volatile"; 460239462Sdim if (FT->isRestrict()) 461218893Sdim Proto += " restrict"; 462218893Sdim } 463221345Sdim 464221345Sdim if (FT && FT->hasDynamicExceptionSpec()) { 465200583Srdivacky Proto += " throw("; 466221345Sdim if (FT->getExceptionSpecType() == EST_MSAny) 467200583Srdivacky Proto += "..."; 468200583Srdivacky else 469200583Srdivacky for (unsigned I = 0, N = FT->getNumExceptions(); I != N; ++I) { 470200583Srdivacky if (I) 471200583Srdivacky Proto += ", "; 472221345Sdim 473243830Sdim Proto += FT->getExceptionType(I).getAsString(SubPolicy); 474200583Srdivacky } 475200583Srdivacky Proto += ")"; 476221345Sdim } else if (FT && isNoexceptExceptionSpec(FT->getExceptionSpecType())) { 477221345Sdim Proto += " noexcept"; 478221345Sdim if (FT->getExceptionSpecType() == EST_ComputedNoexcept) { 479221345Sdim Proto += "("; 480221345Sdim llvm::raw_string_ostream EOut(Proto); 481239462Sdim FT->getNoexceptExpr()->printPretty(EOut, 0, SubPolicy, 482221345Sdim Indentation); 483221345Sdim EOut.flush(); 484221345Sdim Proto += EOut.str(); 485221345Sdim Proto += ")"; 486221345Sdim } 487200583Srdivacky } 488200583Srdivacky 489249423Sdim if (CDecl) { 490223017Sdim bool HasInitializerList = false; 491223017Sdim for (CXXConstructorDecl::init_const_iterator B = CDecl->init_begin(), 492223017Sdim E = CDecl->init_end(); 493223017Sdim B != E; ++B) { 494251662Sdim CXXCtorInitializer *BMInitializer = (*B); 495223017Sdim if (BMInitializer->isInClassMemberInitializer()) 496223017Sdim continue; 497223017Sdim 498223017Sdim if (!HasInitializerList) { 499223017Sdim Proto += " : "; 500223017Sdim Out << Proto; 501223017Sdim Proto.clear(); 502223017Sdim HasInitializerList = true; 503223017Sdim } else 504223017Sdim Out << ", "; 505223017Sdim 506223017Sdim if (BMInitializer->isAnyMemberInitializer()) { 507223017Sdim FieldDecl *FD = BMInitializer->getAnyMember(); 508226633Sdim Out << *FD; 509223017Sdim } else { 510226633Sdim Out << QualType(BMInitializer->getBaseClass(), 0).getAsString(Policy); 511223017Sdim } 512223017Sdim 513223017Sdim Out << "("; 514223017Sdim if (!BMInitializer->getInit()) { 515223017Sdim // Nothing to print 516223017Sdim } else { 517223017Sdim Expr *Init = BMInitializer->getInit(); 518223017Sdim if (ExprWithCleanups *Tmp = dyn_cast<ExprWithCleanups>(Init)) 519223017Sdim Init = Tmp->getSubExpr(); 520203955Srdivacky 521223017Sdim Init = Init->IgnoreParens(); 522223017Sdim 523223017Sdim Expr *SimpleInit = 0; 524223017Sdim Expr **Args = 0; 525223017Sdim unsigned NumArgs = 0; 526223017Sdim if (ParenListExpr *ParenList = dyn_cast<ParenListExpr>(Init)) { 527223017Sdim Args = ParenList->getExprs(); 528223017Sdim NumArgs = ParenList->getNumExprs(); 529223017Sdim } else if (CXXConstructExpr *Construct 530223017Sdim = dyn_cast<CXXConstructExpr>(Init)) { 531223017Sdim Args = Construct->getArgs(); 532223017Sdim NumArgs = Construct->getNumArgs(); 533223017Sdim } else 534223017Sdim SimpleInit = Init; 535223017Sdim 536223017Sdim if (SimpleInit) 537239462Sdim SimpleInit->printPretty(Out, 0, Policy, Indentation); 538223017Sdim else { 539223017Sdim for (unsigned I = 0; I != NumArgs; ++I) { 540223017Sdim if (isa<CXXDefaultArgExpr>(Args[I])) 541223017Sdim break; 542223017Sdim 543223017Sdim if (I) 544223017Sdim Out << ", "; 545239462Sdim Args[I]->printPretty(Out, 0, Policy, Indentation); 546203955Srdivacky } 547198092Srdivacky } 548198092Srdivacky } 549223017Sdim Out << ")"; 550198092Srdivacky } 551249423Sdim if (!Proto.empty()) 552249423Sdim Out << Proto; 553249423Sdim } else { 554249423Sdim if (FT && FT->hasTrailingReturn()) { 555249423Sdim Out << "auto " << Proto << " -> "; 556249423Sdim Proto.clear(); 557249423Sdim } 558249423Sdim AFT->getResultType().print(Out, Policy, Proto); 559198092Srdivacky } 560193326Sed } else { 561239462Sdim Ty.print(Out, Policy, Proto); 562193326Sed } 563193326Sed 564234353Sdim prettyPrintAttributes(D); 565193326Sed 566193326Sed if (D->isPure()) 567193326Sed Out << " = 0"; 568223017Sdim else if (D->isDeletedAsWritten()) 569193326Sed Out << " = delete"; 570249423Sdim else if (D->isExplicitlyDefaulted()) 571249423Sdim Out << " = default"; 572243830Sdim else if (D->doesThisDeclarationHaveABody() && !Policy.TerseOutput) { 573193326Sed if (!D->hasPrototype() && D->getNumParams()) { 574193326Sed // This is a K&R function definition, so we need to print the 575193326Sed // parameters. 576193326Sed Out << '\n'; 577239462Sdim DeclPrinter ParamPrinter(Out, SubPolicy, Indentation); 578193326Sed Indentation += Policy.Indentation; 579193326Sed for (unsigned i = 0, e = D->getNumParams(); i != e; ++i) { 580193326Sed Indent(); 581193326Sed ParamPrinter.VisitParmVarDecl(D->getParamDecl(i)); 582193326Sed Out << ";\n"; 583193326Sed } 584193326Sed Indentation -= Policy.Indentation; 585193326Sed } else 586193326Sed Out << ' '; 587193326Sed 588239462Sdim D->getBody()->printPretty(Out, 0, SubPolicy, Indentation); 589193326Sed Out << '\n'; 590193326Sed } 591193326Sed} 592193326Sed 593249423Sdimvoid DeclPrinter::VisitFriendDecl(FriendDecl *D) { 594249423Sdim if (TypeSourceInfo *TSI = D->getFriendType()) { 595249423Sdim unsigned NumTPLists = D->getFriendTypeNumTemplateParameterLists(); 596249423Sdim for (unsigned i = 0; i < NumTPLists; ++i) 597249423Sdim PrintTemplateParameters(D->getFriendTypeTemplateParameterList(i)); 598249423Sdim Out << "friend "; 599249423Sdim Out << " " << TSI->getType().getAsString(Policy); 600249423Sdim } 601249423Sdim else if (FunctionDecl *FD = 602249423Sdim dyn_cast<FunctionDecl>(D->getFriendDecl())) { 603249423Sdim Out << "friend "; 604249423Sdim VisitFunctionDecl(FD); 605249423Sdim } 606249423Sdim else if (FunctionTemplateDecl *FTD = 607249423Sdim dyn_cast<FunctionTemplateDecl>(D->getFriendDecl())) { 608249423Sdim Out << "friend "; 609249423Sdim VisitFunctionTemplateDecl(FTD); 610249423Sdim } 611249423Sdim else if (ClassTemplateDecl *CTD = 612249423Sdim dyn_cast<ClassTemplateDecl>(D->getFriendDecl())) { 613249423Sdim Out << "friend "; 614249423Sdim VisitRedeclarableTemplateDecl(CTD); 615249423Sdim } 616249423Sdim} 617249423Sdim 618193326Sedvoid DeclPrinter::VisitFieldDecl(FieldDecl *D) { 619193326Sed if (!Policy.SuppressSpecifiers && D->isMutable()) 620193326Sed Out << "mutable "; 621226633Sdim if (!Policy.SuppressSpecifiers && D->isModulePrivate()) 622226633Sdim Out << "__module_private__ "; 623193326Sed 624251662Sdim Out << D->getASTContext().getUnqualifiedObjCPointerType(D->getType()). 625251662Sdim stream(Policy, D->getName()); 626193326Sed 627193326Sed if (D->isBitField()) { 628193326Sed Out << " : "; 629239462Sdim D->getBitWidth()->printPretty(Out, 0, Policy, Indentation); 630193326Sed } 631223017Sdim 632223017Sdim Expr *Init = D->getInClassInitializer(); 633223017Sdim if (!Policy.SuppressInitializers && Init) { 634239462Sdim if (D->getInClassInitStyle() == ICIS_ListInit) 635239462Sdim Out << " "; 636239462Sdim else 637239462Sdim Out << " = "; 638239462Sdim Init->printPretty(Out, 0, Policy, Indentation); 639223017Sdim } 640234353Sdim prettyPrintAttributes(D); 641193326Sed} 642193326Sed 643218893Sdimvoid DeclPrinter::VisitLabelDecl(LabelDecl *D) { 644234353Sdim Out << *D << ":"; 645218893Sdim} 646218893Sdim 647218893Sdim 648193326Sedvoid DeclPrinter::VisitVarDecl(VarDecl *D) { 649251662Sdim if (!Policy.SuppressSpecifiers) { 650251662Sdim StorageClass SC = D->getStorageClass(); 651251662Sdim if (SC != SC_None) 652251662Sdim Out << VarDecl::getStorageClassSpecifierString(SC) << " "; 653193326Sed 654251662Sdim switch (D->getTSCSpec()) { 655251662Sdim case TSCS_unspecified: 656251662Sdim break; 657251662Sdim case TSCS___thread: 658251662Sdim Out << "__thread "; 659251662Sdim break; 660251662Sdim case TSCS__Thread_local: 661251662Sdim Out << "_Thread_local "; 662251662Sdim break; 663251662Sdim case TSCS_thread_local: 664251662Sdim Out << "thread_local "; 665251662Sdim break; 666251662Sdim } 667193326Sed 668251662Sdim if (D->isModulePrivate()) 669251662Sdim Out << "__module_private__ "; 670251662Sdim } 671251662Sdim 672263508Sdim QualType T = D->getTypeSourceInfo() 673263508Sdim ? D->getTypeSourceInfo()->getType() 674263508Sdim : D->getASTContext().getUnqualifiedObjCPointerType(D->getType()); 675239462Sdim T.print(Out, Policy, D->getName()); 676221345Sdim Expr *Init = D->getInit(); 677221345Sdim if (!Policy.SuppressInitializers && Init) { 678234353Sdim bool ImplicitInit = false; 679249423Sdim if (CXXConstructExpr *Construct = 680249423Sdim dyn_cast<CXXConstructExpr>(Init->IgnoreImplicit())) { 681249423Sdim if (D->getInitStyle() == VarDecl::CallInit && 682249423Sdim !Construct->isListInitialization()) { 683249423Sdim ImplicitInit = Construct->getNumArgs() == 0 || 684249423Sdim Construct->getArg(0)->isDefaultArgument(); 685249423Sdim } 686249423Sdim } 687234353Sdim if (!ImplicitInit) { 688243830Sdim if ((D->getInitStyle() == VarDecl::CallInit) && !isa<ParenListExpr>(Init)) 689234353Sdim Out << "("; 690234353Sdim else if (D->getInitStyle() == VarDecl::CInit) { 691234353Sdim Out << " = "; 692234353Sdim } 693239462Sdim Init->printPretty(Out, 0, Policy, Indentation); 694243830Sdim if ((D->getInitStyle() == VarDecl::CallInit) && !isa<ParenListExpr>(Init)) 695234353Sdim Out << ")"; 696218893Sdim } 697193326Sed } 698234353Sdim prettyPrintAttributes(D); 699193326Sed} 700193326Sed 701193326Sedvoid DeclPrinter::VisitParmVarDecl(ParmVarDecl *D) { 702193326Sed VisitVarDecl(D); 703193326Sed} 704193326Sed 705193326Sedvoid DeclPrinter::VisitFileScopeAsmDecl(FileScopeAsmDecl *D) { 706193326Sed Out << "__asm ("; 707239462Sdim D->getAsmString()->printPretty(Out, 0, Policy, Indentation); 708193326Sed Out << ")"; 709193326Sed} 710193326Sed 711234353Sdimvoid DeclPrinter::VisitImportDecl(ImportDecl *D) { 712249423Sdim Out << "@import " << D->getImportedModule()->getFullModuleName() 713234353Sdim << ";\n"; 714234353Sdim} 715234353Sdim 716221345Sdimvoid DeclPrinter::VisitStaticAssertDecl(StaticAssertDecl *D) { 717221345Sdim Out << "static_assert("; 718239462Sdim D->getAssertExpr()->printPretty(Out, 0, Policy, Indentation); 719221345Sdim Out << ", "; 720239462Sdim D->getMessage()->printPretty(Out, 0, Policy, Indentation); 721221345Sdim Out << ")"; 722221345Sdim} 723221345Sdim 724193326Sed//---------------------------------------------------------------------------- 725193326Sed// C++ declarations 726193326Sed//---------------------------------------------------------------------------- 727193326Sedvoid DeclPrinter::VisitNamespaceDecl(NamespaceDecl *D) { 728239462Sdim if (D->isInline()) 729239462Sdim Out << "inline "; 730226633Sdim Out << "namespace " << *D << " {\n"; 731193326Sed VisitDeclContext(D); 732193326Sed Indent() << "}"; 733193326Sed} 734193326Sed 735193326Sedvoid DeclPrinter::VisitUsingDirectiveDecl(UsingDirectiveDecl *D) { 736193326Sed Out << "using namespace "; 737193326Sed if (D->getQualifier()) 738193326Sed D->getQualifier()->print(Out, Policy); 739226633Sdim Out << *D->getNominatedNamespaceAsWritten(); 740193326Sed} 741193326Sed 742193326Sedvoid DeclPrinter::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) { 743226633Sdim Out << "namespace " << *D << " = "; 744193326Sed if (D->getQualifier()) 745193326Sed D->getQualifier()->print(Out, Policy); 746226633Sdim Out << *D->getAliasedNamespace(); 747193326Sed} 748193326Sed 749249423Sdimvoid DeclPrinter::VisitEmptyDecl(EmptyDecl *D) { 750249423Sdim prettyPrintAttributes(D); 751249423Sdim} 752249423Sdim 753193326Sedvoid DeclPrinter::VisitCXXRecordDecl(CXXRecordDecl *D) { 754226633Sdim if (!Policy.SuppressSpecifiers && D->isModulePrivate()) 755226633Sdim Out << "__module_private__ "; 756193326Sed Out << D->getKindName(); 757207619Srdivacky if (D->getIdentifier()) 758226633Sdim Out << ' ' << *D; 759198092Srdivacky 760226633Sdim if (D->isCompleteDefinition()) { 761193326Sed // Print the base classes 762193326Sed if (D->getNumBases()) { 763193326Sed Out << " : "; 764198092Srdivacky for (CXXRecordDecl::base_class_iterator Base = D->bases_begin(), 765198092Srdivacky BaseEnd = D->bases_end(); Base != BaseEnd; ++Base) { 766193326Sed if (Base != D->bases_begin()) 767193326Sed Out << ", "; 768193326Sed 769193326Sed if (Base->isVirtual()) 770193326Sed Out << "virtual "; 771193326Sed 772198092Srdivacky AccessSpecifier AS = Base->getAccessSpecifierAsWritten(); 773198092Srdivacky if (AS != AS_none) 774198092Srdivacky Print(AS); 775198092Srdivacky Out << " " << Base->getType().getAsString(Policy); 776221345Sdim 777221345Sdim if (Base->isPackExpansion()) 778221345Sdim Out << "..."; 779193326Sed } 780193326Sed } 781193326Sed 782193326Sed // Print the class definition 783193326Sed // FIXME: Doesn't print access specifiers, e.g., "public:" 784193326Sed Out << " {\n"; 785193326Sed VisitDeclContext(D); 786193326Sed Indent() << "}"; 787198092Srdivacky } 788193326Sed} 789193326Sed 790193326Sedvoid DeclPrinter::VisitLinkageSpecDecl(LinkageSpecDecl *D) { 791193326Sed const char *l; 792193326Sed if (D->getLanguage() == LinkageSpecDecl::lang_c) 793193326Sed l = "C"; 794193326Sed else { 795193326Sed assert(D->getLanguage() == LinkageSpecDecl::lang_cxx && 796193326Sed "unknown language in linkage specification"); 797193326Sed l = "C++"; 798193326Sed } 799193326Sed 800193326Sed Out << "extern \"" << l << "\" "; 801193326Sed if (D->hasBraces()) { 802193326Sed Out << "{\n"; 803193326Sed VisitDeclContext(D); 804193326Sed Indent() << "}"; 805193326Sed } else 806195341Sed Visit(*D->decls_begin()); 807193326Sed} 808193326Sed 809249423Sdimvoid DeclPrinter::PrintTemplateParameters(const TemplateParameterList *Params, 810249423Sdim const TemplateArgumentList *Args) { 811226633Sdim assert(Params); 812226633Sdim assert(!Args || Params->size() == Args->size()); 813226633Sdim 814193576Sed Out << "template <"; 815198092Srdivacky 816193576Sed for (unsigned i = 0, e = Params->size(); i != e; ++i) { 817193576Sed if (i != 0) 818193576Sed Out << ", "; 819198092Srdivacky 820193576Sed const Decl *Param = Params->getParam(i); 821198092Srdivacky if (const TemplateTypeParmDecl *TTP = 822193576Sed dyn_cast<TemplateTypeParmDecl>(Param)) { 823198092Srdivacky 824193576Sed if (TTP->wasDeclaredWithTypename()) 825193576Sed Out << "typename "; 826193576Sed else 827193576Sed Out << "class "; 828193576Sed 829194179Sed if (TTP->isParameterPack()) 830194179Sed Out << "... "; 831198092Srdivacky 832234353Sdim Out << *TTP; 833193576Sed 834226633Sdim if (Args) { 835193576Sed Out << " = "; 836226633Sdim Args->get(i).print(Policy, Out); 837226633Sdim } else if (TTP->hasDefaultArgument()) { 838226633Sdim Out << " = "; 839193576Sed Out << TTP->getDefaultArgument().getAsString(Policy); 840193576Sed }; 841198092Srdivacky } else if (const NonTypeTemplateParmDecl *NTTP = 842193576Sed dyn_cast<NonTypeTemplateParmDecl>(Param)) { 843193576Sed Out << NTTP->getType().getAsString(Policy); 844193576Sed 845218893Sdim if (NTTP->isParameterPack() && !isa<PackExpansionType>(NTTP->getType())) 846218893Sdim Out << "..."; 847218893Sdim 848193576Sed if (IdentifierInfo *Name = NTTP->getIdentifier()) { 849193576Sed Out << ' '; 850193576Sed Out << Name->getName(); 851193576Sed } 852198092Srdivacky 853226633Sdim if (Args) { 854193576Sed Out << " = "; 855226633Sdim Args->get(i).print(Policy, Out); 856226633Sdim } else if (NTTP->hasDefaultArgument()) { 857226633Sdim Out << " = "; 858239462Sdim NTTP->getDefaultArgument()->printPretty(Out, 0, Policy, Indentation); 859193576Sed } 860221345Sdim } else if (const TemplateTemplateParmDecl *TTPD = 861221345Sdim dyn_cast<TemplateTemplateParmDecl>(Param)) { 862221345Sdim VisitTemplateDecl(TTPD); 863221345Sdim // FIXME: print the default argument, if present. 864193576Sed } 865193576Sed } 866198092Srdivacky 867193576Sed Out << "> "; 868226633Sdim} 869193576Sed 870226633Sdimvoid DeclPrinter::VisitTemplateDecl(const TemplateDecl *D) { 871226633Sdim PrintTemplateParameters(D->getTemplateParameters()); 872226633Sdim 873221345Sdim if (const TemplateTemplateParmDecl *TTP = 874221345Sdim dyn_cast<TemplateTemplateParmDecl>(D)) { 875218893Sdim Out << "class "; 876218893Sdim if (TTP->isParameterPack()) 877218893Sdim Out << "..."; 878218893Sdim Out << D->getName(); 879210299Sed } else { 880210299Sed Visit(D->getTemplatedDecl()); 881210299Sed } 882193326Sed} 883193326Sed 884226633Sdimvoid DeclPrinter::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) { 885226633Sdim if (PrintInstantiation) { 886226633Sdim TemplateParameterList *Params = D->getTemplateParameters(); 887226633Sdim for (FunctionTemplateDecl::spec_iterator I = D->spec_begin(), E = D->spec_end(); 888226633Sdim I != E; ++I) { 889226633Sdim PrintTemplateParameters(Params, (*I)->getTemplateSpecializationArgs()); 890226633Sdim Visit(*I); 891226633Sdim } 892226633Sdim } 893226633Sdim 894226633Sdim return VisitRedeclarableTemplateDecl(D); 895226633Sdim} 896226633Sdim 897226633Sdimvoid DeclPrinter::VisitClassTemplateDecl(ClassTemplateDecl *D) { 898226633Sdim if (PrintInstantiation) { 899226633Sdim TemplateParameterList *Params = D->getTemplateParameters(); 900226633Sdim for (ClassTemplateDecl::spec_iterator I = D->spec_begin(), E = D->spec_end(); 901226633Sdim I != E; ++I) { 902226633Sdim PrintTemplateParameters(Params, &(*I)->getTemplateArgs()); 903226633Sdim Visit(*I); 904226633Sdim Out << '\n'; 905226633Sdim } 906226633Sdim } 907226633Sdim 908226633Sdim return VisitRedeclarableTemplateDecl(D); 909226633Sdim} 910226633Sdim 911193326Sed//---------------------------------------------------------------------------- 912193326Sed// Objective-C declarations 913193326Sed//---------------------------------------------------------------------------- 914193326Sed 915193326Sedvoid DeclPrinter::VisitObjCMethodDecl(ObjCMethodDecl *OMD) { 916193326Sed if (OMD->isInstanceMethod()) 917193326Sed Out << "- "; 918198092Srdivacky else 919193326Sed Out << "+ "; 920193326Sed if (!OMD->getResultType().isNull()) 921251662Sdim Out << '(' << OMD->getASTContext().getUnqualifiedObjCPointerType(OMD->getResultType()). 922251662Sdim getAsString(Policy) << ")"; 923198092Srdivacky 924193326Sed std::string name = OMD->getSelector().getAsString(); 925193326Sed std::string::size_type pos, lastPos = 0; 926193326Sed for (ObjCMethodDecl::param_iterator PI = OMD->param_begin(), 927193326Sed E = OMD->param_end(); PI != E; ++PI) { 928198092Srdivacky // FIXME: selector is missing here! 929226633Sdim pos = name.find_first_of(':', lastPos); 930193326Sed Out << " " << name.substr(lastPos, pos - lastPos); 931251662Sdim Out << ":(" << (*PI)->getASTContext().getUnqualifiedObjCPointerType((*PI)->getType()). 932251662Sdim getAsString(Policy) << ')' << **PI; 933193326Sed lastPos = pos + 1; 934193326Sed } 935198092Srdivacky 936193326Sed if (OMD->param_begin() == OMD->param_end()) 937193326Sed Out << " " << name; 938198092Srdivacky 939193326Sed if (OMD->isVariadic()) 940193326Sed Out << ", ..."; 941198092Srdivacky 942243830Sdim if (OMD->getBody() && !Policy.TerseOutput) { 943193326Sed Out << ' '; 944239462Sdim OMD->getBody()->printPretty(Out, 0, Policy); 945193326Sed Out << '\n'; 946193326Sed } 947249423Sdim else if (Policy.PolishForDeclaration) 948249423Sdim Out << ';'; 949193326Sed} 950193326Sed 951193326Sedvoid DeclPrinter::VisitObjCImplementationDecl(ObjCImplementationDecl *OID) { 952193326Sed std::string I = OID->getNameAsString(); 953193326Sed ObjCInterfaceDecl *SID = OID->getSuperClass(); 954193326Sed 955193326Sed if (SID) 956226633Sdim Out << "@implementation " << I << " : " << *SID; 957193326Sed else 958193326Sed Out << "@implementation " << I; 959249423Sdim 960249423Sdim if (OID->ivar_size() > 0) { 961249423Sdim Out << "{\n"; 962249423Sdim Indentation += Policy.Indentation; 963249423Sdim for (ObjCImplementationDecl::ivar_iterator I = OID->ivar_begin(), 964249423Sdim E = OID->ivar_end(); I != E; ++I) { 965251662Sdim Indent() << I->getASTContext().getUnqualifiedObjCPointerType(I->getType()). 966251662Sdim getAsString(Policy) << ' ' << **I << ";\n"; 967249423Sdim } 968249423Sdim Indentation -= Policy.Indentation; 969249423Sdim Out << "}\n"; 970249423Sdim } 971193326Sed VisitDeclContext(OID, false); 972193326Sed Out << "@end"; 973193326Sed} 974193326Sed 975193326Sedvoid DeclPrinter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *OID) { 976193326Sed std::string I = OID->getNameAsString(); 977193326Sed ObjCInterfaceDecl *SID = OID->getSuperClass(); 978193326Sed 979234353Sdim if (!OID->isThisDeclarationADefinition()) { 980234353Sdim Out << "@class " << I << ";"; 981234353Sdim return; 982234353Sdim } 983249423Sdim bool eolnOut = false; 984193326Sed if (SID) 985226633Sdim Out << "@interface " << I << " : " << *SID; 986193326Sed else 987193326Sed Out << "@interface " << I; 988198092Srdivacky 989193326Sed // Protocols? 990193326Sed const ObjCList<ObjCProtocolDecl> &Protocols = OID->getReferencedProtocols(); 991193326Sed if (!Protocols.empty()) { 992193326Sed for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(), 993193326Sed E = Protocols.end(); I != E; ++I) 994226633Sdim Out << (I == Protocols.begin() ? '<' : ',') << **I; 995249423Sdim Out << "> "; 996193326Sed } 997198092Srdivacky 998193326Sed if (OID->ivar_size() > 0) { 999193326Sed Out << "{\n"; 1000249423Sdim eolnOut = true; 1001193326Sed Indentation += Policy.Indentation; 1002193326Sed for (ObjCInterfaceDecl::ivar_iterator I = OID->ivar_begin(), 1003193326Sed E = OID->ivar_end(); I != E; ++I) { 1004251662Sdim Indent() << I->getASTContext().getUnqualifiedObjCPointerType(I->getType()). 1005251662Sdim getAsString(Policy) << ' ' << **I << ";\n"; 1006193326Sed } 1007193326Sed Indentation -= Policy.Indentation; 1008193326Sed Out << "}\n"; 1009193326Sed } 1010249423Sdim else if (SID) { 1011249423Sdim Out << "\n"; 1012249423Sdim eolnOut = true; 1013249423Sdim } 1014198092Srdivacky 1015193326Sed VisitDeclContext(OID, false); 1016249423Sdim if (!eolnOut) 1017249423Sdim Out << ' '; 1018193326Sed Out << "@end"; 1019193326Sed // FIXME: implement the rest... 1020193326Sed} 1021193326Sed 1022234353Sdimvoid DeclPrinter::VisitObjCProtocolDecl(ObjCProtocolDecl *PID) { 1023234353Sdim if (!PID->isThisDeclarationADefinition()) { 1024249423Sdim Out << "@protocol " << *PID << ";\n"; 1025234353Sdim return; 1026193326Sed } 1027249423Sdim // Protocols? 1028249423Sdim const ObjCList<ObjCProtocolDecl> &Protocols = PID->getReferencedProtocols(); 1029249423Sdim if (!Protocols.empty()) { 1030249423Sdim Out << "@protocol " << *PID; 1031249423Sdim for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(), 1032249423Sdim E = Protocols.end(); I != E; ++I) 1033249423Sdim Out << (I == Protocols.begin() ? '<' : ',') << **I; 1034249423Sdim Out << ">\n"; 1035249423Sdim } else 1036249423Sdim Out << "@protocol " << *PID << '\n'; 1037193326Sed VisitDeclContext(PID, false); 1038193326Sed Out << "@end"; 1039193326Sed} 1040193326Sed 1041193326Sedvoid DeclPrinter::VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *PID) { 1042226633Sdim Out << "@implementation " << *PID->getClassInterface() << '(' << *PID <<")\n"; 1043193326Sed 1044193326Sed VisitDeclContext(PID, false); 1045193326Sed Out << "@end"; 1046193326Sed // FIXME: implement the rest... 1047193326Sed} 1048193326Sed 1049193326Sedvoid DeclPrinter::VisitObjCCategoryDecl(ObjCCategoryDecl *PID) { 1050226633Sdim Out << "@interface " << *PID->getClassInterface() << '(' << *PID << ")\n"; 1051249423Sdim if (PID->ivar_size() > 0) { 1052249423Sdim Out << "{\n"; 1053249423Sdim Indentation += Policy.Indentation; 1054249423Sdim for (ObjCCategoryDecl::ivar_iterator I = PID->ivar_begin(), 1055249423Sdim E = PID->ivar_end(); I != E; ++I) { 1056251662Sdim Indent() << I->getASTContext().getUnqualifiedObjCPointerType(I->getType()). 1057251662Sdim getAsString(Policy) << ' ' << **I << ";\n"; 1058249423Sdim } 1059249423Sdim Indentation -= Policy.Indentation; 1060249423Sdim Out << "}\n"; 1061249423Sdim } 1062249423Sdim 1063193326Sed VisitDeclContext(PID, false); 1064193326Sed Out << "@end"; 1065198092Srdivacky 1066193326Sed // FIXME: implement the rest... 1067193326Sed} 1068193326Sed 1069193326Sedvoid DeclPrinter::VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *AID) { 1070226633Sdim Out << "@compatibility_alias " << *AID 1071226633Sdim << ' ' << *AID->getClassInterface() << ";\n"; 1072193326Sed} 1073193326Sed 1074193326Sed/// PrintObjCPropertyDecl - print a property declaration. 1075193326Sed/// 1076193326Sedvoid DeclPrinter::VisitObjCPropertyDecl(ObjCPropertyDecl *PDecl) { 1077193326Sed if (PDecl->getPropertyImplementation() == ObjCPropertyDecl::Required) 1078193326Sed Out << "@required\n"; 1079193326Sed else if (PDecl->getPropertyImplementation() == ObjCPropertyDecl::Optional) 1080193326Sed Out << "@optional\n"; 1081198092Srdivacky 1082193326Sed Out << "@property"; 1083193326Sed if (PDecl->getPropertyAttributes() != ObjCPropertyDecl::OBJC_PR_noattr) { 1084193326Sed bool first = true; 1085193326Sed Out << " ("; 1086198092Srdivacky if (PDecl->getPropertyAttributes() & 1087193326Sed ObjCPropertyDecl::OBJC_PR_readonly) { 1088193326Sed Out << (first ? ' ' : ',') << "readonly"; 1089193326Sed first = false; 1090226633Sdim } 1091198092Srdivacky 1092226633Sdim if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_getter) { 1093226633Sdim Out << (first ? ' ' : ',') << "getter = " 1094226633Sdim << PDecl->getGetterName().getAsString(); 1095226633Sdim first = false; 1096226633Sdim } 1097226633Sdim if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_setter) { 1098226633Sdim Out << (first ? ' ' : ',') << "setter = " 1099226633Sdim << PDecl->getSetterName().getAsString(); 1100226633Sdim first = false; 1101226633Sdim } 1102198092Srdivacky 1103226633Sdim if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_assign) { 1104226633Sdim Out << (first ? ' ' : ',') << "assign"; 1105226633Sdim first = false; 1106226633Sdim } 1107198092Srdivacky 1108226633Sdim if (PDecl->getPropertyAttributes() & 1109226633Sdim ObjCPropertyDecl::OBJC_PR_readwrite) { 1110226633Sdim Out << (first ? ' ' : ',') << "readwrite"; 1111226633Sdim first = false; 1112226633Sdim } 1113198092Srdivacky 1114226633Sdim if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_retain) { 1115226633Sdim Out << (first ? ' ' : ',') << "retain"; 1116226633Sdim first = false; 1117226633Sdim } 1118198092Srdivacky 1119226633Sdim if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_strong) { 1120226633Sdim Out << (first ? ' ' : ',') << "strong"; 1121226633Sdim first = false; 1122226633Sdim } 1123224145Sdim 1124226633Sdim if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_copy) { 1125226633Sdim Out << (first ? ' ' : ',') << "copy"; 1126226633Sdim first = false; 1127226633Sdim } 1128198092Srdivacky 1129226633Sdim if (PDecl->getPropertyAttributes() & 1130226633Sdim ObjCPropertyDecl::OBJC_PR_nonatomic) { 1131226633Sdim Out << (first ? ' ' : ',') << "nonatomic"; 1132226633Sdim first = false; 1133226633Sdim } 1134226633Sdim if (PDecl->getPropertyAttributes() & 1135226633Sdim ObjCPropertyDecl::OBJC_PR_atomic) { 1136226633Sdim Out << (first ? ' ' : ',') << "atomic"; 1137226633Sdim first = false; 1138226633Sdim } 1139226633Sdim 1140226633Sdim (void) first; // Silence dead store warning due to idiomatic code. 1141226633Sdim Out << " )"; 1142193326Sed } 1143251662Sdim Out << ' ' << PDecl->getASTContext().getUnqualifiedObjCPointerType(PDecl->getType()). 1144251662Sdim getAsString(Policy) << ' ' << *PDecl; 1145249423Sdim if (Policy.PolishForDeclaration) 1146249423Sdim Out << ';'; 1147193326Sed} 1148193326Sed 1149193326Sedvoid DeclPrinter::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *PID) { 1150193326Sed if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize) 1151193326Sed Out << "@synthesize "; 1152193326Sed else 1153193326Sed Out << "@dynamic "; 1154226633Sdim Out << *PID->getPropertyDecl(); 1155193326Sed if (PID->getPropertyIvarDecl()) 1156226633Sdim Out << '=' << *PID->getPropertyIvarDecl(); 1157193326Sed} 1158198092Srdivacky 1159198092Srdivackyvoid DeclPrinter::VisitUsingDecl(UsingDecl *D) { 1160263508Sdim if (!D->isAccessDeclaration()) 1161263508Sdim Out << "using "; 1162263508Sdim if (D->hasTypename()) 1163263508Sdim Out << "typename "; 1164219077Sdim D->getQualifier()->print(Out, Policy); 1165226633Sdim Out << *D; 1166198092Srdivacky} 1167198092Srdivacky 1168199482Srdivackyvoid 1169199482SrdivackyDeclPrinter::VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D) { 1170199482Srdivacky Out << "using typename "; 1171219077Sdim D->getQualifier()->print(Out, Policy); 1172207619Srdivacky Out << D->getDeclName(); 1173199482Srdivacky} 1174199482Srdivacky 1175199482Srdivackyvoid DeclPrinter::VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D) { 1176263508Sdim if (!D->isAccessDeclaration()) 1177263508Sdim Out << "using "; 1178219077Sdim D->getQualifier()->print(Out, Policy); 1179249423Sdim Out << D->getName(); 1180198092Srdivacky} 1181199482Srdivacky 1182199482Srdivackyvoid DeclPrinter::VisitUsingShadowDecl(UsingShadowDecl *D) { 1183199482Srdivacky // ignore 1184199482Srdivacky} 1185249423Sdim 1186249423Sdimvoid DeclPrinter::VisitOMPThreadPrivateDecl(OMPThreadPrivateDecl *D) { 1187249423Sdim Out << "#pragma omp threadprivate"; 1188249423Sdim if (!D->varlist_empty()) { 1189249423Sdim for (OMPThreadPrivateDecl::varlist_iterator I = D->varlist_begin(), 1190249423Sdim E = D->varlist_end(); 1191263508Sdim I != E; ++I) { 1192263508Sdim Out << (I == D->varlist_begin() ? '(' : ','); 1193263508Sdim NamedDecl *ND = cast<NamedDecl>(cast<DeclRefExpr>(*I)->getDecl()); 1194263508Sdim ND->printQualifiedName(Out); 1195249423Sdim } 1196249423Sdim Out << ")"; 1197249423Sdim } 1198249423Sdim} 1199249423Sdim 1200