DeclPrinter.cpp revision 198092
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// 10193326Sed// This file implements the Decl::dump method, which pretty print the 11193326Sed// AST back out to C/Objective-C/C++/Objective-C++ code. 12193326Sed// 13193326Sed//===----------------------------------------------------------------------===// 14193326Sed#include "clang/AST/ASTContext.h" 15193326Sed#include "clang/AST/DeclVisitor.h" 16193326Sed#include "clang/AST/Decl.h" 17193326Sed#include "clang/AST/DeclCXX.h" 18193326Sed#include "clang/AST/DeclObjC.h" 19193326Sed#include "clang/AST/Expr.h" 20193326Sed#include "clang/AST/PrettyPrinter.h" 21193326Sed#include "llvm/Support/Compiler.h" 22193326Sed#include "llvm/Support/Format.h" 23193326Sed#include "llvm/Support/raw_ostream.h" 24193326Sedusing namespace clang; 25193326Sed 26193326Sednamespace { 27193326Sed class VISIBILITY_HIDDEN DeclPrinter : public DeclVisitor<DeclPrinter> { 28193326Sed llvm::raw_ostream &Out; 29193326Sed ASTContext &Context; 30193326Sed PrintingPolicy Policy; 31193326Sed unsigned Indentation; 32193326Sed 33193326Sed llvm::raw_ostream& Indent(); 34193326Sed void ProcessDeclGroup(llvm::SmallVectorImpl<Decl*>& Decls); 35193326Sed 36198092Srdivacky void Print(AccessSpecifier AS); 37198092Srdivacky 38193326Sed public: 39198092Srdivacky DeclPrinter(llvm::raw_ostream &Out, ASTContext &Context, 40193326Sed const PrintingPolicy &Policy, 41193326Sed unsigned Indentation = 0) 42193326Sed : Out(Out), Context(Context), Policy(Policy), Indentation(Indentation) { } 43193326Sed 44193326Sed void VisitDeclContext(DeclContext *DC, bool Indent = true); 45193326Sed 46193326Sed void VisitTranslationUnitDecl(TranslationUnitDecl *D); 47193326Sed void VisitTypedefDecl(TypedefDecl *D); 48193326Sed void VisitEnumDecl(EnumDecl *D); 49193326Sed void VisitRecordDecl(RecordDecl *D); 50193326Sed void VisitEnumConstantDecl(EnumConstantDecl *D); 51193326Sed void VisitFunctionDecl(FunctionDecl *D); 52193326Sed void VisitFieldDecl(FieldDecl *D); 53193326Sed void VisitVarDecl(VarDecl *D); 54193326Sed void VisitParmVarDecl(ParmVarDecl *D); 55193326Sed void VisitOriginalParmVarDecl(OriginalParmVarDecl *D); 56193326Sed void VisitFileScopeAsmDecl(FileScopeAsmDecl *D); 57193326Sed void VisitOverloadedFunctionDecl(OverloadedFunctionDecl *D); 58193326Sed void VisitNamespaceDecl(NamespaceDecl *D); 59193326Sed void VisitUsingDirectiveDecl(UsingDirectiveDecl *D); 60193326Sed void VisitNamespaceAliasDecl(NamespaceAliasDecl *D); 61193326Sed void VisitCXXRecordDecl(CXXRecordDecl *D); 62193326Sed void VisitLinkageSpecDecl(LinkageSpecDecl *D); 63193326Sed void VisitTemplateDecl(TemplateDecl *D); 64193326Sed void VisitObjCMethodDecl(ObjCMethodDecl *D); 65193326Sed void VisitObjCClassDecl(ObjCClassDecl *D); 66193326Sed void VisitObjCImplementationDecl(ObjCImplementationDecl *D); 67193326Sed void VisitObjCInterfaceDecl(ObjCInterfaceDecl *D); 68193326Sed void VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *D); 69193326Sed void VisitObjCProtocolDecl(ObjCProtocolDecl *D); 70193326Sed void VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D); 71193326Sed void VisitObjCCategoryDecl(ObjCCategoryDecl *D); 72193326Sed void VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *D); 73193326Sed void VisitObjCPropertyDecl(ObjCPropertyDecl *D); 74193326Sed void VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D); 75198092Srdivacky void VisitUnresolvedUsingDecl(UnresolvedUsingDecl *D); 76198092Srdivacky void VisitUsingDecl(UsingDecl *D); 77193326Sed }; 78193326Sed} 79193326Sed 80198092Srdivackyvoid Decl::print(llvm::raw_ostream &Out, unsigned Indentation) const { 81195341Sed print(Out, getASTContext().PrintingPolicy, Indentation); 82193326Sed} 83193326Sed 84195341Sedvoid Decl::print(llvm::raw_ostream &Out, const PrintingPolicy &Policy, 85198092Srdivacky unsigned Indentation) const { 86195341Sed DeclPrinter Printer(Out, getASTContext(), Policy, Indentation); 87198092Srdivacky Printer.Visit(const_cast<Decl*>(this)); 88193326Sed} 89193326Sed 90193326Sedstatic QualType GetBaseType(QualType T) { 91193326Sed // FIXME: This should be on the Type class! 92193326Sed QualType BaseType = T; 93193326Sed while (!BaseType->isSpecifierType()) { 94193326Sed if (isa<TypedefType>(BaseType)) 95193326Sed break; 96198092Srdivacky else if (const PointerType* PTy = BaseType->getAs<PointerType>()) 97193326Sed BaseType = PTy->getPointeeType(); 98193326Sed else if (const ArrayType* ATy = dyn_cast<ArrayType>(BaseType)) 99193326Sed BaseType = ATy->getElementType(); 100198092Srdivacky else if (const FunctionType* FTy = BaseType->getAs<FunctionType>()) 101193326Sed BaseType = FTy->getResultType(); 102198092Srdivacky else if (const VectorType *VTy = BaseType->getAs<VectorType>()) 103195341Sed BaseType = VTy->getElementType(); 104193326Sed else 105193326Sed assert(0 && "Unknown declarator!"); 106193326Sed } 107193326Sed return BaseType; 108193326Sed} 109193326Sed 110193326Sedstatic QualType getDeclType(Decl* D) { 111193326Sed if (TypedefDecl* TDD = dyn_cast<TypedefDecl>(D)) 112193326Sed return TDD->getUnderlyingType(); 113193326Sed if (ValueDecl* VD = dyn_cast<ValueDecl>(D)) 114193326Sed return VD->getType(); 115193326Sed return QualType(); 116193326Sed} 117193326Sed 118193326Sedvoid Decl::printGroup(Decl** Begin, unsigned NumDecls, 119195341Sed llvm::raw_ostream &Out, const PrintingPolicy &Policy, 120193326Sed unsigned Indentation) { 121193326Sed if (NumDecls == 1) { 122195341Sed (*Begin)->print(Out, Policy, Indentation); 123193326Sed return; 124193326Sed } 125193326Sed 126193326Sed Decl** End = Begin + NumDecls; 127193326Sed TagDecl* TD = dyn_cast<TagDecl>(*Begin); 128193326Sed if (TD) 129193326Sed ++Begin; 130193326Sed 131193326Sed PrintingPolicy SubPolicy(Policy); 132193326Sed if (TD && TD->isDefinition()) { 133195341Sed TD->print(Out, Policy, Indentation); 134193326Sed Out << " "; 135193326Sed SubPolicy.SuppressTag = true; 136193326Sed } 137193326Sed 138193326Sed bool isFirst = true; 139193326Sed for ( ; Begin != End; ++Begin) { 140193326Sed if (isFirst) { 141193326Sed SubPolicy.SuppressSpecifiers = false; 142193326Sed isFirst = false; 143193326Sed } else { 144193326Sed if (!isFirst) Out << ", "; 145193326Sed SubPolicy.SuppressSpecifiers = true; 146193326Sed } 147193326Sed 148195341Sed (*Begin)->print(Out, SubPolicy, Indentation); 149193326Sed } 150193326Sed} 151193326Sed 152198092Srdivackyvoid Decl::dump() const { 153195341Sed print(llvm::errs()); 154193326Sed} 155193326Sed 156193326Sedllvm::raw_ostream& DeclPrinter::Indent() { 157193326Sed for (unsigned i = 0; i < Indentation; ++i) 158193326Sed Out << " "; 159193326Sed return Out; 160193326Sed} 161193326Sed 162193326Sedvoid DeclPrinter::ProcessDeclGroup(llvm::SmallVectorImpl<Decl*>& Decls) { 163193326Sed this->Indent(); 164195341Sed Decl::printGroup(Decls.data(), Decls.size(), Out, Policy, Indentation); 165193326Sed Out << ";\n"; 166193326Sed Decls.clear(); 167193326Sed 168193326Sed} 169193326Sed 170198092Srdivackyvoid DeclPrinter::Print(AccessSpecifier AS) { 171198092Srdivacky switch(AS) { 172198092Srdivacky case AS_none: assert(0 && "No access specifier!"); break; 173198092Srdivacky case AS_public: Out << "public"; break; 174198092Srdivacky case AS_protected: Out << "protected"; break; 175198092Srdivacky case AS_private: Out << " private"; break; 176198092Srdivacky } 177198092Srdivacky} 178198092Srdivacky 179193326Sed//---------------------------------------------------------------------------- 180193326Sed// Common C declarations 181193326Sed//---------------------------------------------------------------------------- 182193326Sed 183193326Sedvoid DeclPrinter::VisitDeclContext(DeclContext *DC, bool Indent) { 184193326Sed if (Indent) 185193326Sed Indentation += Policy.Indentation; 186193326Sed 187198092Srdivacky bool PrintAccess = isa<CXXRecordDecl>(DC); 188198092Srdivacky AccessSpecifier CurAS = AS_none; 189198092Srdivacky 190193326Sed llvm::SmallVector<Decl*, 2> Decls; 191195341Sed for (DeclContext::decl_iterator D = DC->decls_begin(), DEnd = DC->decls_end(); 192193326Sed D != DEnd; ++D) { 193193326Sed if (!Policy.Dump) { 194193326Sed // Skip over implicit declarations in pretty-printing mode. 195193326Sed if (D->isImplicit()) continue; 196193326Sed // FIXME: Ugly hack so we don't pretty-print the builtin declaration 197193326Sed // of __builtin_va_list. There should be some other way to check that. 198193326Sed if (isa<NamedDecl>(*D) && cast<NamedDecl>(*D)->getNameAsString() == 199193326Sed "__builtin_va_list") 200193326Sed continue; 201193326Sed } 202193326Sed 203198092Srdivacky if (PrintAccess) { 204198092Srdivacky AccessSpecifier AS = D->getAccess(); 205198092Srdivacky 206198092Srdivacky if (AS != CurAS) { 207198092Srdivacky Print(AS); 208198092Srdivacky Out << ":\n"; 209198092Srdivacky CurAS = AS; 210198092Srdivacky } 211198092Srdivacky } 212198092Srdivacky 213193326Sed // The next bits of code handles stuff like "struct {int x;} a,b"; we're 214193326Sed // forced to merge the declarations because there's no other way to 215193326Sed // refer to the struct in question. This limited merging is safe without 216193326Sed // a bunch of other checks because it only merges declarations directly 217193326Sed // referring to the tag, not typedefs. 218193326Sed // 219193326Sed // Check whether the current declaration should be grouped with a previous 220193326Sed // unnamed struct. 221193326Sed QualType CurDeclType = getDeclType(*D); 222193326Sed if (!Decls.empty() && !CurDeclType.isNull()) { 223193326Sed QualType BaseType = GetBaseType(CurDeclType); 224193326Sed if (!BaseType.isNull() && isa<TagType>(BaseType) && 225193326Sed cast<TagType>(BaseType)->getDecl() == Decls[0]) { 226193326Sed Decls.push_back(*D); 227193326Sed continue; 228193326Sed } 229193326Sed } 230193326Sed 231193326Sed // If we have a merged group waiting to be handled, handle it now. 232193326Sed if (!Decls.empty()) 233193326Sed ProcessDeclGroup(Decls); 234193326Sed 235193326Sed // If the current declaration is an unnamed tag type, save it 236193326Sed // so we can merge it with the subsequent declaration(s) using it. 237193326Sed if (isa<TagDecl>(*D) && !cast<TagDecl>(*D)->getIdentifier()) { 238193326Sed Decls.push_back(*D); 239193326Sed continue; 240193326Sed } 241193326Sed this->Indent(); 242193326Sed Visit(*D); 243198092Srdivacky 244198092Srdivacky // FIXME: Need to be able to tell the DeclPrinter when 245193326Sed const char *Terminator = 0; 246198092Srdivacky if (isa<FunctionDecl>(*D) && 247193326Sed cast<FunctionDecl>(*D)->isThisDeclarationADefinition()) 248193326Sed Terminator = 0; 249193326Sed else if (isa<ObjCMethodDecl>(*D) && cast<ObjCMethodDecl>(*D)->getBody()) 250193326Sed Terminator = 0; 251193326Sed else if (isa<NamespaceDecl>(*D) || isa<LinkageSpecDecl>(*D) || 252198092Srdivacky isa<ObjCImplementationDecl>(*D) || 253193326Sed isa<ObjCInterfaceDecl>(*D) || 254193326Sed isa<ObjCProtocolDecl>(*D) || 255193326Sed isa<ObjCCategoryImplDecl>(*D) || 256193326Sed isa<ObjCCategoryDecl>(*D)) 257193326Sed Terminator = 0; 258193326Sed else if (isa<EnumConstantDecl>(*D)) { 259193326Sed DeclContext::decl_iterator Next = D; 260193326Sed ++Next; 261193326Sed if (Next != DEnd) 262193326Sed Terminator = ","; 263193326Sed } else 264193326Sed Terminator = ";"; 265193326Sed 266193326Sed if (Terminator) 267193326Sed Out << Terminator; 268193326Sed Out << "\n"; 269193326Sed } 270193326Sed 271193326Sed if (!Decls.empty()) 272193326Sed ProcessDeclGroup(Decls); 273193326Sed 274193326Sed if (Indent) 275193326Sed Indentation -= Policy.Indentation; 276193326Sed} 277193326Sed 278193326Sedvoid DeclPrinter::VisitTranslationUnitDecl(TranslationUnitDecl *D) { 279193326Sed VisitDeclContext(D, false); 280193326Sed} 281193326Sed 282193326Sedvoid DeclPrinter::VisitTypedefDecl(TypedefDecl *D) { 283193326Sed std::string S = D->getNameAsString(); 284193326Sed D->getUnderlyingType().getAsStringInternal(S, Policy); 285193326Sed if (!Policy.SuppressSpecifiers) 286193326Sed Out << "typedef "; 287193326Sed Out << S; 288193326Sed} 289193326Sed 290193326Sedvoid DeclPrinter::VisitEnumDecl(EnumDecl *D) { 291193326Sed Out << "enum " << D->getNameAsString() << " {\n"; 292193326Sed VisitDeclContext(D); 293193326Sed Indent() << "}"; 294193326Sed} 295193326Sed 296193326Sedvoid DeclPrinter::VisitRecordDecl(RecordDecl *D) { 297193326Sed Out << D->getKindName(); 298193326Sed if (D->getIdentifier()) { 299193326Sed Out << " "; 300193326Sed Out << D->getNameAsString(); 301193326Sed } 302198092Srdivacky 303193326Sed if (D->isDefinition()) { 304193326Sed Out << " {\n"; 305193326Sed VisitDeclContext(D); 306193326Sed Indent() << "}"; 307193326Sed } 308193326Sed} 309193326Sed 310193326Sedvoid DeclPrinter::VisitEnumConstantDecl(EnumConstantDecl *D) { 311193326Sed Out << D->getNameAsString(); 312193326Sed if (Expr *Init = D->getInitExpr()) { 313193326Sed Out << " = "; 314193326Sed Init->printPretty(Out, Context, 0, Policy, Indentation); 315193326Sed } 316193326Sed} 317193326Sed 318198092Srdivackyvoid DeclPrinter::VisitFunctionDecl(FunctionDecl *D) { 319193326Sed if (!Policy.SuppressSpecifiers) { 320193326Sed switch (D->getStorageClass()) { 321193326Sed case FunctionDecl::None: break; 322193326Sed case FunctionDecl::Extern: Out << "extern "; break; 323193326Sed case FunctionDecl::Static: Out << "static "; break; 324193326Sed case FunctionDecl::PrivateExtern: Out << "__private_extern__ "; break; 325193326Sed } 326193326Sed 327193326Sed if (D->isInline()) Out << "inline "; 328193326Sed if (D->isVirtualAsWritten()) Out << "virtual "; 329193326Sed } 330193326Sed 331193326Sed PrintingPolicy SubPolicy(Policy); 332193326Sed SubPolicy.SuppressSpecifiers = false; 333193326Sed std::string Proto = D->getNameAsString(); 334193326Sed if (isa<FunctionType>(D->getType().getTypePtr())) { 335198092Srdivacky const FunctionType *AFT = D->getType()->getAs<FunctionType>(); 336193326Sed 337193326Sed const FunctionProtoType *FT = 0; 338193326Sed if (D->hasWrittenPrototype()) 339193326Sed FT = dyn_cast<FunctionProtoType>(AFT); 340193326Sed 341193326Sed Proto += "("; 342193326Sed if (FT) { 343193326Sed llvm::raw_string_ostream POut(Proto); 344193326Sed DeclPrinter ParamPrinter(POut, Context, SubPolicy, Indentation); 345193326Sed for (unsigned i = 0, e = D->getNumParams(); i != e; ++i) { 346193326Sed if (i) POut << ", "; 347193326Sed ParamPrinter.VisitParmVarDecl(D->getParamDecl(i)); 348193326Sed } 349198092Srdivacky 350193326Sed if (FT->isVariadic()) { 351193326Sed if (D->getNumParams()) POut << ", "; 352193326Sed POut << "..."; 353193326Sed } 354193326Sed } else if (D->isThisDeclarationADefinition() && !D->hasPrototype()) { 355193326Sed for (unsigned i = 0, e = D->getNumParams(); i != e; ++i) { 356193326Sed if (i) 357193326Sed Proto += ", "; 358193326Sed Proto += D->getParamDecl(i)->getNameAsString(); 359193326Sed } 360193326Sed } 361193326Sed 362193326Sed Proto += ")"; 363198092Srdivacky if (D->hasAttr<NoReturnAttr>()) 364198092Srdivacky Proto += " __attribute((noreturn))"; 365198092Srdivacky if (CXXConstructorDecl *CDecl = dyn_cast<CXXConstructorDecl>(D)) { 366198092Srdivacky if (CDecl->getNumBaseOrMemberInitializers() > 0) { 367198092Srdivacky Proto += " : "; 368198092Srdivacky Out << Proto; 369198092Srdivacky Proto.clear(); 370198092Srdivacky for (CXXConstructorDecl::init_const_iterator B = CDecl->init_begin(), 371198092Srdivacky E = CDecl->init_end(); 372198092Srdivacky B != E; ++B) { 373198092Srdivacky CXXBaseOrMemberInitializer * BMInitializer = (*B); 374198092Srdivacky if (B != CDecl->init_begin()) 375198092Srdivacky Out << ", "; 376198092Srdivacky bool hasArguments = (BMInitializer->arg_begin() != 377198092Srdivacky BMInitializer->arg_end()); 378198092Srdivacky if (BMInitializer->isMemberInitializer()) { 379198092Srdivacky FieldDecl *FD = BMInitializer->getMember(); 380198092Srdivacky Out << FD->getNameAsString(); 381198092Srdivacky } 382198092Srdivacky else // FIXME. skip dependent types for now. 383198092Srdivacky if (const RecordType *RT = 384198092Srdivacky BMInitializer->getBaseClass()->getAs<RecordType>()) { 385198092Srdivacky const CXXRecordDecl *BaseDecl = 386198092Srdivacky cast<CXXRecordDecl>(RT->getDecl()); 387198092Srdivacky Out << BaseDecl->getNameAsString(); 388198092Srdivacky } 389198092Srdivacky if (hasArguments) { 390198092Srdivacky Out << "("; 391198092Srdivacky for (CXXBaseOrMemberInitializer::const_arg_iterator BE = 392198092Srdivacky BMInitializer->const_arg_begin(), 393198092Srdivacky EE = BMInitializer->const_arg_end(); BE != EE; ++BE) { 394198092Srdivacky if (BE != BMInitializer->const_arg_begin()) 395198092Srdivacky Out<< ", "; 396198092Srdivacky const Expr *Exp = (*BE); 397198092Srdivacky Exp->printPretty(Out, Context, 0, Policy, Indentation); 398198092Srdivacky } 399198092Srdivacky Out << ")"; 400198092Srdivacky } else 401198092Srdivacky Out << "()"; 402198092Srdivacky } 403198092Srdivacky } 404198092Srdivacky } 405198092Srdivacky else if (CXXDestructorDecl *DDecl = dyn_cast<CXXDestructorDecl>(D)) { 406198092Srdivacky if (DDecl->getNumBaseOrMemberDestructions() > 0) { 407198092Srdivacky // List order of base/member destruction for visualization purposes. 408198092Srdivacky assert (D->isThisDeclarationADefinition() && "Destructor with dtor-list"); 409198092Srdivacky Proto += "/* : "; 410198092Srdivacky for (CXXDestructorDecl::destr_const_iterator *B = DDecl->destr_begin(), 411198092Srdivacky *E = DDecl->destr_end(); 412198092Srdivacky B != E; ++B) { 413198092Srdivacky uintptr_t BaseOrMember = (*B); 414198092Srdivacky if (B != DDecl->destr_begin()) 415198092Srdivacky Proto += ", "; 416198092Srdivacky 417198092Srdivacky if (DDecl->isMemberToDestroy(BaseOrMember)) { 418198092Srdivacky FieldDecl *FD = DDecl->getMemberToDestroy(BaseOrMember); 419198092Srdivacky Proto += "~"; 420198092Srdivacky Proto += FD->getNameAsString(); 421198092Srdivacky } 422198092Srdivacky else // FIXME. skip dependent types for now. 423198092Srdivacky if (const RecordType *RT = 424198092Srdivacky DDecl->getAnyBaseClassToDestroy(BaseOrMember) 425198092Srdivacky ->getAs<RecordType>()) { 426198092Srdivacky const CXXRecordDecl *BaseDecl = 427198092Srdivacky cast<CXXRecordDecl>(RT->getDecl()); 428198092Srdivacky Proto += "~"; 429198092Srdivacky Proto += BaseDecl->getNameAsString(); 430198092Srdivacky } 431198092Srdivacky Proto += "()"; 432198092Srdivacky } 433198092Srdivacky Proto += " */"; 434198092Srdivacky } 435198092Srdivacky } 436198092Srdivacky else 437198092Srdivacky AFT->getResultType().getAsStringInternal(Proto, Policy); 438193326Sed } else { 439193326Sed D->getType().getAsStringInternal(Proto, Policy); 440193326Sed } 441193326Sed 442193326Sed Out << Proto; 443193326Sed 444193326Sed if (D->isPure()) 445193326Sed Out << " = 0"; 446193326Sed else if (D->isDeleted()) 447193326Sed Out << " = delete"; 448193326Sed else if (D->isThisDeclarationADefinition()) { 449193326Sed if (!D->hasPrototype() && D->getNumParams()) { 450193326Sed // This is a K&R function definition, so we need to print the 451193326Sed // parameters. 452193326Sed Out << '\n'; 453193326Sed DeclPrinter ParamPrinter(Out, Context, SubPolicy, Indentation); 454193326Sed Indentation += Policy.Indentation; 455193326Sed for (unsigned i = 0, e = D->getNumParams(); i != e; ++i) { 456193326Sed Indent(); 457193326Sed ParamPrinter.VisitParmVarDecl(D->getParamDecl(i)); 458193326Sed Out << ";\n"; 459193326Sed } 460193326Sed Indentation -= Policy.Indentation; 461193326Sed } else 462193326Sed Out << ' '; 463193326Sed 464195341Sed D->getBody()->printPretty(Out, Context, 0, SubPolicy, Indentation); 465193326Sed Out << '\n'; 466193326Sed } 467193326Sed} 468193326Sed 469193326Sedvoid DeclPrinter::VisitFieldDecl(FieldDecl *D) { 470193326Sed if (!Policy.SuppressSpecifiers && D->isMutable()) 471193326Sed Out << "mutable "; 472193326Sed 473193326Sed std::string Name = D->getNameAsString(); 474193326Sed D->getType().getAsStringInternal(Name, Policy); 475193326Sed Out << Name; 476193326Sed 477193326Sed if (D->isBitField()) { 478193326Sed Out << " : "; 479193326Sed D->getBitWidth()->printPretty(Out, Context, 0, Policy, Indentation); 480193326Sed } 481193326Sed} 482193326Sed 483193326Sedvoid DeclPrinter::VisitVarDecl(VarDecl *D) { 484193326Sed if (!Policy.SuppressSpecifiers && D->getStorageClass() != VarDecl::None) 485193326Sed Out << VarDecl::getStorageClassSpecifierString(D->getStorageClass()) << " "; 486193326Sed 487193326Sed if (!Policy.SuppressSpecifiers && D->isThreadSpecified()) 488193326Sed Out << "__thread "; 489193326Sed 490193326Sed std::string Name = D->getNameAsString(); 491193326Sed QualType T = D->getType(); 492193326Sed if (OriginalParmVarDecl *Parm = dyn_cast<OriginalParmVarDecl>(D)) 493193326Sed T = Parm->getOriginalType(); 494193326Sed T.getAsStringInternal(Name, Policy); 495193326Sed Out << Name; 496193326Sed if (D->getInit()) { 497193326Sed if (D->hasCXXDirectInitializer()) 498193326Sed Out << "("; 499193326Sed else 500193326Sed Out << " = "; 501193326Sed D->getInit()->printPretty(Out, Context, 0, Policy, Indentation); 502193326Sed if (D->hasCXXDirectInitializer()) 503193326Sed Out << ")"; 504193326Sed } 505193326Sed} 506193326Sed 507193326Sedvoid DeclPrinter::VisitParmVarDecl(ParmVarDecl *D) { 508193326Sed VisitVarDecl(D); 509193326Sed} 510193326Sed 511193326Sedvoid DeclPrinter::VisitOriginalParmVarDecl(OriginalParmVarDecl *D) { 512193326Sed VisitVarDecl(D); 513193326Sed} 514193326Sed 515193326Sedvoid DeclPrinter::VisitFileScopeAsmDecl(FileScopeAsmDecl *D) { 516193326Sed Out << "__asm ("; 517193326Sed D->getAsmString()->printPretty(Out, Context, 0, Policy, Indentation); 518193326Sed Out << ")"; 519193326Sed} 520193326Sed 521193326Sed//---------------------------------------------------------------------------- 522193326Sed// C++ declarations 523193326Sed//---------------------------------------------------------------------------- 524193326Sedvoid DeclPrinter::VisitOverloadedFunctionDecl(OverloadedFunctionDecl *D) { 525198092Srdivacky assert(false && 526193326Sed "OverloadedFunctionDecls aren't really decls and are never printed"); 527193326Sed} 528193326Sed 529193326Sedvoid DeclPrinter::VisitNamespaceDecl(NamespaceDecl *D) { 530193326Sed Out << "namespace " << D->getNameAsString() << " {\n"; 531193326Sed VisitDeclContext(D); 532193326Sed Indent() << "}"; 533193326Sed} 534193326Sed 535193326Sedvoid DeclPrinter::VisitUsingDirectiveDecl(UsingDirectiveDecl *D) { 536193326Sed Out << "using namespace "; 537193326Sed if (D->getQualifier()) 538193326Sed D->getQualifier()->print(Out, Policy); 539193326Sed Out << D->getNominatedNamespace()->getNameAsString(); 540193326Sed} 541193326Sed 542193326Sedvoid DeclPrinter::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) { 543193326Sed Out << "namespace " << D->getNameAsString() << " = "; 544193326Sed if (D->getQualifier()) 545193326Sed D->getQualifier()->print(Out, Policy); 546193326Sed Out << D->getAliasedNamespace()->getNameAsString(); 547193326Sed} 548193326Sed 549193326Sedvoid DeclPrinter::VisitCXXRecordDecl(CXXRecordDecl *D) { 550193326Sed Out << D->getKindName(); 551193326Sed if (D->getIdentifier()) { 552193326Sed Out << " "; 553193326Sed Out << D->getNameAsString(); 554193326Sed } 555198092Srdivacky 556193326Sed if (D->isDefinition()) { 557193326Sed // Print the base classes 558193326Sed if (D->getNumBases()) { 559193326Sed Out << " : "; 560198092Srdivacky for (CXXRecordDecl::base_class_iterator Base = D->bases_begin(), 561198092Srdivacky BaseEnd = D->bases_end(); Base != BaseEnd; ++Base) { 562193326Sed if (Base != D->bases_begin()) 563193326Sed Out << ", "; 564193326Sed 565193326Sed if (Base->isVirtual()) 566193326Sed Out << "virtual "; 567193326Sed 568198092Srdivacky AccessSpecifier AS = Base->getAccessSpecifierAsWritten(); 569198092Srdivacky if (AS != AS_none) 570198092Srdivacky Print(AS); 571198092Srdivacky Out << " " << Base->getType().getAsString(Policy); 572193326Sed } 573193326Sed } 574193326Sed 575193326Sed // Print the class definition 576193326Sed // FIXME: Doesn't print access specifiers, e.g., "public:" 577193326Sed Out << " {\n"; 578193326Sed VisitDeclContext(D); 579193326Sed Indent() << "}"; 580198092Srdivacky } 581193326Sed} 582193326Sed 583193326Sedvoid DeclPrinter::VisitLinkageSpecDecl(LinkageSpecDecl *D) { 584193326Sed const char *l; 585193326Sed if (D->getLanguage() == LinkageSpecDecl::lang_c) 586193326Sed l = "C"; 587193326Sed else { 588193326Sed assert(D->getLanguage() == LinkageSpecDecl::lang_cxx && 589193326Sed "unknown language in linkage specification"); 590193326Sed l = "C++"; 591193326Sed } 592193326Sed 593193326Sed Out << "extern \"" << l << "\" "; 594193326Sed if (D->hasBraces()) { 595193326Sed Out << "{\n"; 596193326Sed VisitDeclContext(D); 597193326Sed Indent() << "}"; 598193326Sed } else 599195341Sed Visit(*D->decls_begin()); 600193326Sed} 601193326Sed 602193326Sedvoid DeclPrinter::VisitTemplateDecl(TemplateDecl *D) { 603193576Sed Out << "template <"; 604198092Srdivacky 605193576Sed TemplateParameterList *Params = D->getTemplateParameters(); 606193576Sed for (unsigned i = 0, e = Params->size(); i != e; ++i) { 607193576Sed if (i != 0) 608193576Sed Out << ", "; 609198092Srdivacky 610193576Sed const Decl *Param = Params->getParam(i); 611198092Srdivacky if (const TemplateTypeParmDecl *TTP = 612193576Sed dyn_cast<TemplateTypeParmDecl>(Param)) { 613198092Srdivacky 614198092Srdivacky QualType ParamType = 615193576Sed Context.getTypeDeclType(const_cast<TemplateTypeParmDecl*>(TTP)); 616193576Sed 617193576Sed if (TTP->wasDeclaredWithTypename()) 618193576Sed Out << "typename "; 619193576Sed else 620193576Sed Out << "class "; 621193576Sed 622194179Sed if (TTP->isParameterPack()) 623194179Sed Out << "... "; 624198092Srdivacky 625193576Sed Out << ParamType.getAsString(Policy); 626193576Sed 627193576Sed if (TTP->hasDefaultArgument()) { 628193576Sed Out << " = "; 629193576Sed Out << TTP->getDefaultArgument().getAsString(Policy); 630193576Sed }; 631198092Srdivacky } else if (const NonTypeTemplateParmDecl *NTTP = 632193576Sed dyn_cast<NonTypeTemplateParmDecl>(Param)) { 633193576Sed Out << NTTP->getType().getAsString(Policy); 634193576Sed 635193576Sed if (IdentifierInfo *Name = NTTP->getIdentifier()) { 636193576Sed Out << ' '; 637193576Sed Out << Name->getName(); 638193576Sed } 639198092Srdivacky 640193576Sed if (NTTP->hasDefaultArgument()) { 641193576Sed Out << " = "; 642198092Srdivacky NTTP->getDefaultArgument()->printPretty(Out, Context, 0, Policy, 643193576Sed Indentation); 644193576Sed } 645193576Sed } 646193576Sed } 647198092Srdivacky 648193576Sed Out << "> "; 649193576Sed 650193326Sed Visit(D->getTemplatedDecl()); 651193326Sed} 652193326Sed 653193326Sed//---------------------------------------------------------------------------- 654193326Sed// Objective-C declarations 655193326Sed//---------------------------------------------------------------------------- 656193326Sed 657193326Sedvoid DeclPrinter::VisitObjCClassDecl(ObjCClassDecl *D) { 658193326Sed Out << "@class "; 659193326Sed for (ObjCClassDecl::iterator I = D->begin(), E = D->end(); 660193326Sed I != E; ++I) { 661193326Sed if (I != D->begin()) Out << ", "; 662193326Sed Out << (*I)->getNameAsString(); 663193326Sed } 664193326Sed} 665193326Sed 666193326Sedvoid DeclPrinter::VisitObjCMethodDecl(ObjCMethodDecl *OMD) { 667193326Sed if (OMD->isInstanceMethod()) 668193326Sed Out << "- "; 669198092Srdivacky else 670193326Sed Out << "+ "; 671193326Sed if (!OMD->getResultType().isNull()) 672193326Sed Out << '(' << OMD->getResultType().getAsString(Policy) << ")"; 673198092Srdivacky 674193326Sed std::string name = OMD->getSelector().getAsString(); 675193326Sed std::string::size_type pos, lastPos = 0; 676193326Sed for (ObjCMethodDecl::param_iterator PI = OMD->param_begin(), 677193326Sed E = OMD->param_end(); PI != E; ++PI) { 678198092Srdivacky // FIXME: selector is missing here! 679193326Sed pos = name.find_first_of(":", lastPos); 680193326Sed Out << " " << name.substr(lastPos, pos - lastPos); 681193326Sed Out << ":(" << (*PI)->getType().getAsString(Policy) << ")" 682198092Srdivacky << (*PI)->getNameAsString(); 683193326Sed lastPos = pos + 1; 684193326Sed } 685198092Srdivacky 686193326Sed if (OMD->param_begin() == OMD->param_end()) 687193326Sed Out << " " << name; 688198092Srdivacky 689193326Sed if (OMD->isVariadic()) 690193326Sed Out << ", ..."; 691198092Srdivacky 692193326Sed if (OMD->getBody()) { 693193326Sed Out << ' '; 694193326Sed OMD->getBody()->printPretty(Out, Context, 0, Policy); 695193326Sed Out << '\n'; 696193326Sed } 697193326Sed} 698193326Sed 699193326Sedvoid DeclPrinter::VisitObjCImplementationDecl(ObjCImplementationDecl *OID) { 700193326Sed std::string I = OID->getNameAsString(); 701193326Sed ObjCInterfaceDecl *SID = OID->getSuperClass(); 702193326Sed 703193326Sed if (SID) 704193326Sed Out << "@implementation " << I << " : " << SID->getNameAsString(); 705193326Sed else 706193326Sed Out << "@implementation " << I; 707193326Sed Out << "\n"; 708193326Sed VisitDeclContext(OID, false); 709193326Sed Out << "@end"; 710193326Sed} 711193326Sed 712193326Sedvoid DeclPrinter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *OID) { 713193326Sed std::string I = OID->getNameAsString(); 714193326Sed ObjCInterfaceDecl *SID = OID->getSuperClass(); 715193326Sed 716193326Sed if (SID) 717193326Sed Out << "@interface " << I << " : " << SID->getNameAsString(); 718193326Sed else 719193326Sed Out << "@interface " << I; 720198092Srdivacky 721193326Sed // Protocols? 722193326Sed const ObjCList<ObjCProtocolDecl> &Protocols = OID->getReferencedProtocols(); 723193326Sed if (!Protocols.empty()) { 724193326Sed for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(), 725193326Sed E = Protocols.end(); I != E; ++I) 726193326Sed Out << (I == Protocols.begin() ? '<' : ',') << (*I)->getNameAsString(); 727193326Sed } 728198092Srdivacky 729193326Sed if (!Protocols.empty()) 730193326Sed Out << "> "; 731198092Srdivacky 732193326Sed if (OID->ivar_size() > 0) { 733193326Sed Out << "{\n"; 734193326Sed Indentation += Policy.Indentation; 735193326Sed for (ObjCInterfaceDecl::ivar_iterator I = OID->ivar_begin(), 736193326Sed E = OID->ivar_end(); I != E; ++I) { 737193326Sed Indent() << (*I)->getType().getAsString(Policy) 738198092Srdivacky << ' ' << (*I)->getNameAsString() << ";\n"; 739193326Sed } 740193326Sed Indentation -= Policy.Indentation; 741193326Sed Out << "}\n"; 742193326Sed } 743198092Srdivacky 744193326Sed VisitDeclContext(OID, false); 745193326Sed Out << "@end"; 746193326Sed // FIXME: implement the rest... 747193326Sed} 748193326Sed 749193326Sedvoid DeclPrinter::VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *D) { 750193326Sed Out << "@protocol "; 751198092Srdivacky for (ObjCForwardProtocolDecl::protocol_iterator I = D->protocol_begin(), 752193326Sed E = D->protocol_end(); 753193326Sed I != E; ++I) { 754193326Sed if (I != D->protocol_begin()) Out << ", "; 755193326Sed Out << (*I)->getNameAsString(); 756193326Sed } 757193326Sed} 758193326Sed 759193326Sedvoid DeclPrinter::VisitObjCProtocolDecl(ObjCProtocolDecl *PID) { 760193326Sed Out << "@protocol " << PID->getNameAsString() << '\n'; 761193326Sed VisitDeclContext(PID, false); 762193326Sed Out << "@end"; 763193326Sed} 764193326Sed 765193326Sedvoid DeclPrinter::VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *PID) { 766193326Sed Out << "@implementation " 767193326Sed << PID->getClassInterface()->getNameAsString() 768198092Srdivacky << '(' << PID->getNameAsString() << ")\n"; 769193326Sed 770193326Sed VisitDeclContext(PID, false); 771193326Sed Out << "@end"; 772193326Sed // FIXME: implement the rest... 773193326Sed} 774193326Sed 775193326Sedvoid DeclPrinter::VisitObjCCategoryDecl(ObjCCategoryDecl *PID) { 776198092Srdivacky Out << "@interface " 777193326Sed << PID->getClassInterface()->getNameAsString() 778193326Sed << '(' << PID->getNameAsString() << ")\n"; 779193326Sed VisitDeclContext(PID, false); 780193326Sed Out << "@end"; 781198092Srdivacky 782193326Sed // FIXME: implement the rest... 783193326Sed} 784193326Sed 785193326Sedvoid DeclPrinter::VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *AID) { 786198092Srdivacky Out << "@compatibility_alias " << AID->getNameAsString() 787198092Srdivacky << ' ' << AID->getClassInterface()->getNameAsString() << ";\n"; 788193326Sed} 789193326Sed 790193326Sed/// PrintObjCPropertyDecl - print a property declaration. 791193326Sed/// 792193326Sedvoid DeclPrinter::VisitObjCPropertyDecl(ObjCPropertyDecl *PDecl) { 793193326Sed if (PDecl->getPropertyImplementation() == ObjCPropertyDecl::Required) 794193326Sed Out << "@required\n"; 795193326Sed else if (PDecl->getPropertyImplementation() == ObjCPropertyDecl::Optional) 796193326Sed Out << "@optional\n"; 797198092Srdivacky 798193326Sed Out << "@property"; 799193326Sed if (PDecl->getPropertyAttributes() != ObjCPropertyDecl::OBJC_PR_noattr) { 800193326Sed bool first = true; 801193326Sed Out << " ("; 802198092Srdivacky if (PDecl->getPropertyAttributes() & 803193326Sed ObjCPropertyDecl::OBJC_PR_readonly) { 804193326Sed Out << (first ? ' ' : ',') << "readonly"; 805193326Sed first = false; 806193326Sed } 807198092Srdivacky 808193326Sed if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_getter) { 809193326Sed Out << (first ? ' ' : ',') << "getter = " 810193326Sed << PDecl->getGetterName().getAsString(); 811193326Sed first = false; 812193326Sed } 813193326Sed if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_setter) { 814193326Sed Out << (first ? ' ' : ',') << "setter = " 815193326Sed << PDecl->getSetterName().getAsString(); 816193326Sed first = false; 817193326Sed } 818198092Srdivacky 819193326Sed if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_assign) { 820193326Sed Out << (first ? ' ' : ',') << "assign"; 821193326Sed first = false; 822193326Sed } 823198092Srdivacky 824193326Sed if (PDecl->getPropertyAttributes() & 825193326Sed ObjCPropertyDecl::OBJC_PR_readwrite) { 826193326Sed Out << (first ? ' ' : ',') << "readwrite"; 827193326Sed first = false; 828193326Sed } 829198092Srdivacky 830193326Sed if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_retain) { 831193326Sed Out << (first ? ' ' : ',') << "retain"; 832193326Sed first = false; 833193326Sed } 834198092Srdivacky 835193326Sed if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_copy) { 836193326Sed Out << (first ? ' ' : ',') << "copy"; 837193326Sed first = false; 838193326Sed } 839198092Srdivacky 840198092Srdivacky if (PDecl->getPropertyAttributes() & 841193326Sed ObjCPropertyDecl::OBJC_PR_nonatomic) { 842193326Sed Out << (first ? ' ' : ',') << "nonatomic"; 843193326Sed first = false; 844193326Sed } 845193326Sed Out << " )"; 846193326Sed } 847193326Sed Out << ' ' << PDecl->getType().getAsString(Policy) 848193326Sed << ' ' << PDecl->getNameAsString(); 849193326Sed} 850193326Sed 851193326Sedvoid DeclPrinter::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *PID) { 852193326Sed if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize) 853193326Sed Out << "@synthesize "; 854193326Sed else 855193326Sed Out << "@dynamic "; 856193326Sed Out << PID->getPropertyDecl()->getNameAsString(); 857193326Sed if (PID->getPropertyIvarDecl()) 858193326Sed Out << "=" << PID->getPropertyIvarDecl()->getNameAsString(); 859193326Sed} 860198092Srdivacky 861198092Srdivackyvoid DeclPrinter::VisitUsingDecl(UsingDecl *D) { 862198092Srdivacky Out << "using "; 863198092Srdivacky D->getTargetNestedNameDecl()->print(Out, Policy); 864198092Srdivacky Out << D->getTargetDecl()->getNameAsString(); 865198092Srdivacky} 866198092Srdivacky 867198092Srdivackyvoid DeclPrinter::VisitUnresolvedUsingDecl(UnresolvedUsingDecl *D) { 868198092Srdivacky Out << "using "; 869198092Srdivacky D->getTargetNestedNameSpecifier()->print(Out, Policy); 870198092Srdivacky Out << D->getTargetName().getAsString(); 871198092Srdivacky} 872