DeclPrinter.cpp revision 0ae7b3f1d5403265f693ed75384603ca8fbba74d
18d3ba23f2d9e6c87794d059412a0808c9cbacb25Dmitri Gribenko//===--- DeclPrinter.cpp - Printing implementation for Decl ASTs ----------===// 28d3ba23f2d9e6c87794d059412a0808c9cbacb25Dmitri Gribenko// 38d3ba23f2d9e6c87794d059412a0808c9cbacb25Dmitri Gribenko// The LLVM Compiler Infrastructure 48d3ba23f2d9e6c87794d059412a0808c9cbacb25Dmitri Gribenko// 58d3ba23f2d9e6c87794d059412a0808c9cbacb25Dmitri Gribenko// This file is distributed under the University of Illinois Open Source 68d3ba23f2d9e6c87794d059412a0808c9cbacb25Dmitri Gribenko// License. See LICENSE.TXT for details. 78d3ba23f2d9e6c87794d059412a0808c9cbacb25Dmitri Gribenko// 88d3ba23f2d9e6c87794d059412a0808c9cbacb25Dmitri Gribenko//===----------------------------------------------------------------------===// 98d3ba23f2d9e6c87794d059412a0808c9cbacb25Dmitri Gribenko// 108d3ba23f2d9e6c87794d059412a0808c9cbacb25Dmitri Gribenko// This file implements the Decl::dump method, which pretty print the 118d3ba23f2d9e6c87794d059412a0808c9cbacb25Dmitri Gribenko// AST back out to C/Objective-C/C++/Objective-C++ code. 128d3ba23f2d9e6c87794d059412a0808c9cbacb25Dmitri Gribenko// 138d3ba23f2d9e6c87794d059412a0808c9cbacb25Dmitri Gribenko//===----------------------------------------------------------------------===// 148d3ba23f2d9e6c87794d059412a0808c9cbacb25Dmitri Gribenko#include "clang/AST/ASTContext.h" 158d3ba23f2d9e6c87794d059412a0808c9cbacb25Dmitri Gribenko#include "clang/AST/DeclVisitor.h" 168d3ba23f2d9e6c87794d059412a0808c9cbacb25Dmitri Gribenko#include "clang/AST/Decl.h" 1730a2e16f6c27f888dd11eba6bbbae1e980078fcbChandler Carruth#include "clang/AST/DeclCXX.h" 18a5ef44ff5d93a3be6ca67782828157a71894cf0cDmitri Gribenko#include "clang/AST/DeclObjC.h" 198d3ba23f2d9e6c87794d059412a0808c9cbacb25Dmitri Gribenko#include "clang/AST/Expr.h" 208d3ba23f2d9e6c87794d059412a0808c9cbacb25Dmitri Gribenko#include "clang/AST/PrettyPrinter.h" 2196b098674908eaa59a9128f3305cda6fbbdad563Dmitri Gribenko#include "llvm/Support/raw_ostream.h" 2230a2e16f6c27f888dd11eba6bbbae1e980078fcbChandler Carruthusing namespace clang; 238d3ba23f2d9e6c87794d059412a0808c9cbacb25Dmitri Gribenko 248d3ba23f2d9e6c87794d059412a0808c9cbacb25Dmitri Gribenkonamespace { 258d3ba23f2d9e6c87794d059412a0808c9cbacb25Dmitri Gribenko class DeclPrinter : public DeclVisitor<DeclPrinter> { 26a5ef44ff5d93a3be6ca67782828157a71894cf0cDmitri Gribenko llvm::raw_ostream &Out; 27a5ef44ff5d93a3be6ca67782828157a71894cf0cDmitri Gribenko ASTContext &Context; 281952354bd376062c3ab3d328c0fc6c36530c9309Dmitri Gribenko PrintingPolicy Policy; 29a5ef44ff5d93a3be6ca67782828157a71894cf0cDmitri Gribenko unsigned Indentation; 308d3ba23f2d9e6c87794d059412a0808c9cbacb25Dmitri Gribenko 31aa58081902ad31927df02e8537d972eabe29d6dfDmitri Gribenko llvm::raw_ostream& Indent() { return Indent(Indentation); } 328d3ba23f2d9e6c87794d059412a0808c9cbacb25Dmitri Gribenko llvm::raw_ostream& Indent(unsigned Indentation); 338d3ba23f2d9e6c87794d059412a0808c9cbacb25Dmitri Gribenko void ProcessDeclGroup(llvm::SmallVectorImpl<Decl*>& Decls); 34da5922f4864b5da254c6676af8833c42adaa6d86Dmitri Gribenko 35da5922f4864b5da254c6676af8833c42adaa6d86Dmitri Gribenko void Print(AccessSpecifier AS); 366f36366c85dc81d67d70efdeeea4cfc382053febDmitri Gribenko 37a5ef44ff5d93a3be6ca67782828157a71894cf0cDmitri Gribenko public: 388d3ba23f2d9e6c87794d059412a0808c9cbacb25Dmitri Gribenko DeclPrinter(llvm::raw_ostream &Out, ASTContext &Context, 398d3ba23f2d9e6c87794d059412a0808c9cbacb25Dmitri Gribenko const PrintingPolicy &Policy, 40a5ef44ff5d93a3be6ca67782828157a71894cf0cDmitri Gribenko unsigned Indentation = 0) 41a5ef44ff5d93a3be6ca67782828157a71894cf0cDmitri Gribenko : Out(Out), Context(Context), Policy(Policy), Indentation(Indentation) { } 42a5ef44ff5d93a3be6ca67782828157a71894cf0cDmitri Gribenko 43a5ef44ff5d93a3be6ca67782828157a71894cf0cDmitri Gribenko void VisitDeclContext(DeclContext *DC, bool Indent = true); 44a5ef44ff5d93a3be6ca67782828157a71894cf0cDmitri Gribenko 45e4330a302ac20b41b9800267ebd4b5b01f8553f8Dmitri Gribenko void VisitTranslationUnitDecl(TranslationUnitDecl *D); 46aa58081902ad31927df02e8537d972eabe29d6dfDmitri Gribenko void VisitTypedefDecl(TypedefDecl *D); 471952354bd376062c3ab3d328c0fc6c36530c9309Dmitri Gribenko void VisitEnumDecl(EnumDecl *D); 481952354bd376062c3ab3d328c0fc6c36530c9309Dmitri Gribenko void VisitRecordDecl(RecordDecl *D); 491ca7ecc8854ffea215c033a0d8482551bf1b73f0Dmitri Gribenko void VisitEnumConstantDecl(EnumConstantDecl *D); 501ca7ecc8854ffea215c033a0d8482551bf1b73f0Dmitri Gribenko void VisitFunctionDecl(FunctionDecl *D); 518487c524fdfcea3da858fd0af850b4784c8096d0Dmitri Gribenko void VisitFieldDecl(FieldDecl *D); 5296b098674908eaa59a9128f3305cda6fbbdad563Dmitri Gribenko void VisitVarDecl(VarDecl *D); 5396b098674908eaa59a9128f3305cda6fbbdad563Dmitri Gribenko void VisitParmVarDecl(ParmVarDecl *D); 5496b098674908eaa59a9128f3305cda6fbbdad563Dmitri Gribenko void VisitFileScopeAsmDecl(FileScopeAsmDecl *D); 551ca7ecc8854ffea215c033a0d8482551bf1b73f0Dmitri Gribenko void VisitNamespaceDecl(NamespaceDecl *D); 5696b098674908eaa59a9128f3305cda6fbbdad563Dmitri Gribenko void VisitUsingDirectiveDecl(UsingDirectiveDecl *D); 5796b098674908eaa59a9128f3305cda6fbbdad563Dmitri Gribenko void VisitNamespaceAliasDecl(NamespaceAliasDecl *D); 589443c57150e870e308406e1e4e6d9d64712b417eDmitri Gribenko void VisitCXXRecordDecl(CXXRecordDecl *D); 599443c57150e870e308406e1e4e6d9d64712b417eDmitri Gribenko void VisitLinkageSpecDecl(LinkageSpecDecl *D); 609443c57150e870e308406e1e4e6d9d64712b417eDmitri Gribenko void VisitTemplateDecl(TemplateDecl *D); 61f843a580c4a54ca147f22422ee8ccfd2347784fcFariborz Jahanian void VisitObjCMethodDecl(ObjCMethodDecl *D); 62f843a580c4a54ca147f22422ee8ccfd2347784fcFariborz Jahanian void VisitObjCClassDecl(ObjCClassDecl *D); 639443c57150e870e308406e1e4e6d9d64712b417eDmitri Gribenko void VisitObjCImplementationDecl(ObjCImplementationDecl *D); 64a5ef44ff5d93a3be6ca67782828157a71894cf0cDmitri Gribenko void VisitObjCInterfaceDecl(ObjCInterfaceDecl *D); 65a5ef44ff5d93a3be6ca67782828157a71894cf0cDmitri Gribenko void VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *D); 66a5ef44ff5d93a3be6ca67782828157a71894cf0cDmitri Gribenko void VisitObjCProtocolDecl(ObjCProtocolDecl *D); 67a5ef44ff5d93a3be6ca67782828157a71894cf0cDmitri Gribenko void VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D); 68a5ef44ff5d93a3be6ca67782828157a71894cf0cDmitri Gribenko void VisitObjCCategoryDecl(ObjCCategoryDecl *D); 69a5ef44ff5d93a3be6ca67782828157a71894cf0cDmitri Gribenko void VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *D); 703f38bf2d441fac379c427f86153fbb0cb41256c6Dmitri Gribenko void VisitObjCPropertyDecl(ObjCPropertyDecl *D); 71a5ef44ff5d93a3be6ca67782828157a71894cf0cDmitri Gribenko void VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D); 728d3ba23f2d9e6c87794d059412a0808c9cbacb25Dmitri Gribenko void VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D); 73a5ef44ff5d93a3be6ca67782828157a71894cf0cDmitri Gribenko void VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D); 741952354bd376062c3ab3d328c0fc6c36530c9309Dmitri Gribenko void VisitUsingDecl(UsingDecl *D); 751952354bd376062c3ab3d328c0fc6c36530c9309Dmitri Gribenko void VisitUsingShadowDecl(UsingShadowDecl *D); 76a5ef44ff5d93a3be6ca67782828157a71894cf0cDmitri Gribenko }; 77a5ef44ff5d93a3be6ca67782828157a71894cf0cDmitri Gribenko} 788d3ba23f2d9e6c87794d059412a0808c9cbacb25Dmitri Gribenko 7996b098674908eaa59a9128f3305cda6fbbdad563Dmitri Gribenkovoid Decl::print(llvm::raw_ostream &Out, unsigned Indentation) const { 8096b098674908eaa59a9128f3305cda6fbbdad563Dmitri Gribenko print(Out, getASTContext().PrintingPolicy, Indentation); 8196b098674908eaa59a9128f3305cda6fbbdad563Dmitri Gribenko} 8296b098674908eaa59a9128f3305cda6fbbdad563Dmitri Gribenko 8396b098674908eaa59a9128f3305cda6fbbdad563Dmitri Gribenkovoid Decl::print(llvm::raw_ostream &Out, const PrintingPolicy &Policy, 8496b098674908eaa59a9128f3305cda6fbbdad563Dmitri Gribenko unsigned Indentation) const { 8596b098674908eaa59a9128f3305cda6fbbdad563Dmitri Gribenko DeclPrinter Printer(Out, getASTContext(), Policy, Indentation); 8696b098674908eaa59a9128f3305cda6fbbdad563Dmitri Gribenko Printer.Visit(const_cast<Decl*>(this)); 876bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines} 886bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 8996b098674908eaa59a9128f3305cda6fbbdad563Dmitri Gribenkostatic QualType GetBaseType(QualType T) { 9096b098674908eaa59a9128f3305cda6fbbdad563Dmitri Gribenko // FIXME: This should be on the Type class! 918d3ba23f2d9e6c87794d059412a0808c9cbacb25Dmitri Gribenko QualType BaseType = T; 928d3ba23f2d9e6c87794d059412a0808c9cbacb25Dmitri Gribenko while (!BaseType->isSpecifierType()) { 938d3ba23f2d9e6c87794d059412a0808c9cbacb25Dmitri Gribenko if (isa<TypedefType>(BaseType)) 948d3ba23f2d9e6c87794d059412a0808c9cbacb25Dmitri Gribenko break; 958d3ba23f2d9e6c87794d059412a0808c9cbacb25Dmitri Gribenko else if (const PointerType* PTy = BaseType->getAs<PointerType>()) 968536fa14ee1048e5e2d62cb3dc11fc640c7dc00dFariborz Jahanian BaseType = PTy->getPointeeType(); 97808383d2d6d58a7c7db85f8c7618fb74d821309fDmitri Gribenko else if (const ArrayType* ATy = dyn_cast<ArrayType>(BaseType)) 988d3ba23f2d9e6c87794d059412a0808c9cbacb25Dmitri Gribenko BaseType = ATy->getElementType(); 997d9b51107999c1c1fada7319c4687fe570eb2c0bDmitri Gribenko else if (const FunctionType* FTy = BaseType->getAs<FunctionType>()) 1007d9b51107999c1c1fada7319c4687fe570eb2c0bDmitri Gribenko BaseType = FTy->getResultType(); 1018d3ba23f2d9e6c87794d059412a0808c9cbacb25Dmitri Gribenko else if (const VectorType *VTy = BaseType->getAs<VectorType>()) 1027d9b51107999c1c1fada7319c4687fe570eb2c0bDmitri Gribenko BaseType = VTy->getElementType(); 1037d9b51107999c1c1fada7319c4687fe570eb2c0bDmitri Gribenko else 1048d3ba23f2d9e6c87794d059412a0808c9cbacb25Dmitri Gribenko assert(0 && "Unknown declarator!"); 1058d3ba23f2d9e6c87794d059412a0808c9cbacb25Dmitri Gribenko } 1068d3ba23f2d9e6c87794d059412a0808c9cbacb25Dmitri Gribenko return BaseType; 1078536fa14ee1048e5e2d62cb3dc11fc640c7dc00dFariborz Jahanian} 108808383d2d6d58a7c7db85f8c7618fb74d821309fDmitri Gribenko 1098d3ba23f2d9e6c87794d059412a0808c9cbacb25Dmitri Gribenkostatic QualType getDeclType(Decl* D) { 1107d9b51107999c1c1fada7319c4687fe570eb2c0bDmitri Gribenko if (TypedefDecl* TDD = dyn_cast<TypedefDecl>(D)) 1117d9b51107999c1c1fada7319c4687fe570eb2c0bDmitri Gribenko return TDD->getUnderlyingType(); 1127d9b51107999c1c1fada7319c4687fe570eb2c0bDmitri Gribenko if (ValueDecl* VD = dyn_cast<ValueDecl>(D)) 1137d9b51107999c1c1fada7319c4687fe570eb2c0bDmitri Gribenko return VD->getType(); 114a5ef44ff5d93a3be6ca67782828157a71894cf0cDmitri Gribenko return QualType(); 1157d9b51107999c1c1fada7319c4687fe570eb2c0bDmitri Gribenko} 1167d9b51107999c1c1fada7319c4687fe570eb2c0bDmitri Gribenko 1177d9b51107999c1c1fada7319c4687fe570eb2c0bDmitri Gribenkovoid Decl::printGroup(Decl** Begin, unsigned NumDecls, 1187d9b51107999c1c1fada7319c4687fe570eb2c0bDmitri Gribenko llvm::raw_ostream &Out, const PrintingPolicy &Policy, 1198d3ba23f2d9e6c87794d059412a0808c9cbacb25Dmitri Gribenko unsigned Indentation) { 1207d9b51107999c1c1fada7319c4687fe570eb2c0bDmitri Gribenko if (NumDecls == 1) { 1217d9b51107999c1c1fada7319c4687fe570eb2c0bDmitri Gribenko (*Begin)->print(Out, Policy, Indentation); 1228d3ba23f2d9e6c87794d059412a0808c9cbacb25Dmitri Gribenko return; 12396b098674908eaa59a9128f3305cda6fbbdad563Dmitri Gribenko } 12496b098674908eaa59a9128f3305cda6fbbdad563Dmitri Gribenko 1258536fa14ee1048e5e2d62cb3dc11fc640c7dc00dFariborz Jahanian Decl** End = Begin + NumDecls; 126808383d2d6d58a7c7db85f8c7618fb74d821309fDmitri Gribenko TagDecl* TD = dyn_cast<TagDecl>(*Begin); 12796b098674908eaa59a9128f3305cda6fbbdad563Dmitri Gribenko if (TD) 1287d9b51107999c1c1fada7319c4687fe570eb2c0bDmitri Gribenko ++Begin; 1297d9b51107999c1c1fada7319c4687fe570eb2c0bDmitri Gribenko 1307d9b51107999c1c1fada7319c4687fe570eb2c0bDmitri Gribenko PrintingPolicy SubPolicy(Policy); 1317d9b51107999c1c1fada7319c4687fe570eb2c0bDmitri Gribenko if (TD && TD->isDefinition()) { 13296b098674908eaa59a9128f3305cda6fbbdad563Dmitri Gribenko TD->print(Out, Policy, Indentation); 1337d9b51107999c1c1fada7319c4687fe570eb2c0bDmitri Gribenko Out << " "; 1347d9b51107999c1c1fada7319c4687fe570eb2c0bDmitri Gribenko SubPolicy.SuppressTag = true; 13596b098674908eaa59a9128f3305cda6fbbdad563Dmitri Gribenko } 1368d3ba23f2d9e6c87794d059412a0808c9cbacb25Dmitri Gribenko 1378d3ba23f2d9e6c87794d059412a0808c9cbacb25Dmitri Gribenko bool isFirst = true; 138e4330a302ac20b41b9800267ebd4b5b01f8553f8Dmitri Gribenko for ( ; Begin != End; ++Begin) { 1398d3ba23f2d9e6c87794d059412a0808c9cbacb25Dmitri Gribenko if (isFirst) { 1408d3ba23f2d9e6c87794d059412a0808c9cbacb25Dmitri Gribenko SubPolicy.SuppressSpecifiers = false; 1418d3ba23f2d9e6c87794d059412a0808c9cbacb25Dmitri Gribenko isFirst = false; 142e4330a302ac20b41b9800267ebd4b5b01f8553f8Dmitri Gribenko } else { 1438d3ba23f2d9e6c87794d059412a0808c9cbacb25Dmitri Gribenko if (!isFirst) Out << ", "; 1448d3ba23f2d9e6c87794d059412a0808c9cbacb25Dmitri Gribenko SubPolicy.SuppressSpecifiers = true; 1458d3ba23f2d9e6c87794d059412a0808c9cbacb25Dmitri Gribenko } 1468d3ba23f2d9e6c87794d059412a0808c9cbacb25Dmitri Gribenko 1478d3ba23f2d9e6c87794d059412a0808c9cbacb25Dmitri Gribenko (*Begin)->print(Out, SubPolicy, Indentation); 1488d3ba23f2d9e6c87794d059412a0808c9cbacb25Dmitri Gribenko } 149b0b8a96df25660cbdbf35d23c3ff5887c33f82f9Dmitri Gribenko} 150b0b8a96df25660cbdbf35d23c3ff5887c33f82f9Dmitri Gribenko 151b0b8a96df25660cbdbf35d23c3ff5887c33f82f9Dmitri Gribenkovoid Decl::dump() const { 152b0b8a96df25660cbdbf35d23c3ff5887c33f82f9Dmitri Gribenko print(llvm::errs()); 153b0b8a96df25660cbdbf35d23c3ff5887c33f82f9Dmitri Gribenko} 1548d3ba23f2d9e6c87794d059412a0808c9cbacb25Dmitri Gribenko 1558d3ba23f2d9e6c87794d059412a0808c9cbacb25Dmitri Gribenkollvm::raw_ostream& DeclPrinter::Indent(unsigned Indentation) { 1568d3ba23f2d9e6c87794d059412a0808c9cbacb25Dmitri Gribenko for (unsigned i = 0; i != Indentation; ++i) 1578d3ba23f2d9e6c87794d059412a0808c9cbacb25Dmitri Gribenko Out << " "; 1588d3ba23f2d9e6c87794d059412a0808c9cbacb25Dmitri Gribenko return Out; 1598d3ba23f2d9e6c87794d059412a0808c9cbacb25Dmitri Gribenko} 160e4330a302ac20b41b9800267ebd4b5b01f8553f8Dmitri Gribenko 1618d3ba23f2d9e6c87794d059412a0808c9cbacb25Dmitri Gribenkovoid DeclPrinter::ProcessDeclGroup(llvm::SmallVectorImpl<Decl*>& Decls) { 1628d3ba23f2d9e6c87794d059412a0808c9cbacb25Dmitri Gribenko this->Indent(); 1638d3ba23f2d9e6c87794d059412a0808c9cbacb25Dmitri Gribenko Decl::printGroup(Decls.data(), Decls.size(), Out, Policy, Indentation); 1648d3ba23f2d9e6c87794d059412a0808c9cbacb25Dmitri Gribenko Out << ";\n"; 1657d9b51107999c1c1fada7319c4687fe570eb2c0bDmitri Gribenko Decls.clear(); 1667d9b51107999c1c1fada7319c4687fe570eb2c0bDmitri Gribenko 1677d9b51107999c1c1fada7319c4687fe570eb2c0bDmitri Gribenko} 1687d9b51107999c1c1fada7319c4687fe570eb2c0bDmitri Gribenko 1698d3ba23f2d9e6c87794d059412a0808c9cbacb25Dmitri Gribenkovoid DeclPrinter::Print(AccessSpecifier AS) { 1708d3ba23f2d9e6c87794d059412a0808c9cbacb25Dmitri Gribenko switch(AS) { 171e4330a302ac20b41b9800267ebd4b5b01f8553f8Dmitri Gribenko case AS_none: assert(0 && "No access specifier!"); break; 1728d3ba23f2d9e6c87794d059412a0808c9cbacb25Dmitri Gribenko case AS_public: Out << "public"; break; 1738d3ba23f2d9e6c87794d059412a0808c9cbacb25Dmitri Gribenko case AS_protected: Out << "protected"; break; 1748d3ba23f2d9e6c87794d059412a0808c9cbacb25Dmitri Gribenko case AS_private: Out << " private"; break; 1753f38bf2d441fac379c427f86153fbb0cb41256c6Dmitri Gribenko } 1763f38bf2d441fac379c427f86153fbb0cb41256c6Dmitri Gribenko} 1778d3ba23f2d9e6c87794d059412a0808c9cbacb25Dmitri Gribenko 1787d9b51107999c1c1fada7319c4687fe570eb2c0bDmitri Gribenko//---------------------------------------------------------------------------- 1797d9b51107999c1c1fada7319c4687fe570eb2c0bDmitri Gribenko// Common C declarations 1807d9b51107999c1c1fada7319c4687fe570eb2c0bDmitri Gribenko//---------------------------------------------------------------------------- 1817d9b51107999c1c1fada7319c4687fe570eb2c0bDmitri Gribenko 1828d3ba23f2d9e6c87794d059412a0808c9cbacb25Dmitri Gribenkovoid DeclPrinter::VisitDeclContext(DeclContext *DC, bool Indent) { 1833f38bf2d441fac379c427f86153fbb0cb41256c6Dmitri Gribenko if (Indent) 1843f38bf2d441fac379c427f86153fbb0cb41256c6Dmitri Gribenko Indentation += Policy.Indentation; 1853f38bf2d441fac379c427f86153fbb0cb41256c6Dmitri Gribenko 1868d3ba23f2d9e6c87794d059412a0808c9cbacb25Dmitri Gribenko bool PrintAccess = isa<CXXRecordDecl>(DC); 1878d3ba23f2d9e6c87794d059412a0808c9cbacb25Dmitri Gribenko AccessSpecifier CurAS = AS_none; 1888d3ba23f2d9e6c87794d059412a0808c9cbacb25Dmitri Gribenko 189a5ef44ff5d93a3be6ca67782828157a71894cf0cDmitri Gribenko llvm::SmallVector<Decl*, 2> Decls; 190a5ef44ff5d93a3be6ca67782828157a71894cf0cDmitri Gribenko for (DeclContext::decl_iterator D = DC->decls_begin(), DEnd = DC->decls_end(); 19189ab7d0012ffe02a335b765eeb9b48977a5ecd79Dmitri Gribenko D != DEnd; ++D) { 19289ab7d0012ffe02a335b765eeb9b48977a5ecd79Dmitri Gribenko if (!Policy.Dump) { 1939443c57150e870e308406e1e4e6d9d64712b417eDmitri Gribenko // Skip over implicit declarations in pretty-printing mode. 1949443c57150e870e308406e1e4e6d9d64712b417eDmitri Gribenko if (D->isImplicit()) continue; 1959443c57150e870e308406e1e4e6d9d64712b417eDmitri Gribenko // FIXME: Ugly hack so we don't pretty-print the builtin declaration 1969443c57150e870e308406e1e4e6d9d64712b417eDmitri Gribenko // of __builtin_va_list. There should be some other way to check that. 1970bd9838751384181ff387f2fb346896792b89617Dmitri Gribenko if (isa<NamedDecl>(*D) && cast<NamedDecl>(*D)->getNameAsString() == 1982a268f2629b49958427e8eb02f2c3d565be71accFariborz Jahanian "__builtin_va_list") 1992a268f2629b49958427e8eb02f2c3d565be71accFariborz Jahanian continue; 20028c1cd2138f700742235e1e720c1f7e6dc75a11aFariborz Jahanian } 20128c1cd2138f700742235e1e720c1f7e6dc75a11aFariborz Jahanian 20228c1cd2138f700742235e1e720c1f7e6dc75a11aFariborz Jahanian if (PrintAccess) { 20328c1cd2138f700742235e1e720c1f7e6dc75a11aFariborz Jahanian AccessSpecifier AS = D->getAccess(); 2040bd9838751384181ff387f2fb346896792b89617Dmitri Gribenko 2059edd2c8a2ff6c6326ff2d5b081929e4baaa798edDmitri Gribenko if (AS != CurAS) { 2069edd2c8a2ff6c6326ff2d5b081929e4baaa798edDmitri Gribenko if (Indent) 2079edd2c8a2ff6c6326ff2d5b081929e4baaa798edDmitri Gribenko this->Indent(Indentation - Policy.Indentation); 2089edd2c8a2ff6c6326ff2d5b081929e4baaa798edDmitri Gribenko Print(AS); 2098487c524fdfcea3da858fd0af850b4784c8096d0Dmitri Gribenko Out << ":\n"; 210eb8f69f094e95d0132e4a6817a2111ad188ab087Fariborz Jahanian CurAS = AS; 211a558d2e29817e36798875c96efb62251e53ff024Dmitri Gribenko } 212a558d2e29817e36798875c96efb62251e53ff024Dmitri Gribenko } 213a558d2e29817e36798875c96efb62251e53ff024Dmitri Gribenko 21499a7057098c56211e641705e1ff38d4b7c8b309dFariborz Jahanian // The next bits of code handles stuff like "struct {int x;} a,b"; we're 215c5b0054693b3b3cafe6a13549358c22e07fcd4ffDmitri Gribenko // forced to merge the declarations because there's no other way to 21699a7057098c56211e641705e1ff38d4b7c8b309dFariborz Jahanian // refer to the struct in question. This limited merging is safe without 217664e860beb2550bef24fb8946192f61648a71d7fFariborz Jahanian // a bunch of other checks because it only merges declarations directly 21804bf29eb1b197e0a103139ab5d63b0b97432f004Dmitri Gribenko // referring to the tag, not typedefs. 219b421b56d5a83c5bcae576b714ebd9df7b745368dFariborz Jahanian // 220b421b56d5a83c5bcae576b714ebd9df7b745368dFariborz Jahanian // Check whether the current declaration should be grouped with a previous 22128c1cd2138f700742235e1e720c1f7e6dc75a11aFariborz Jahanian // unnamed struct. 22228c1cd2138f700742235e1e720c1f7e6dc75a11aFariborz Jahanian QualType CurDeclType = getDeclType(*D); 22328c1cd2138f700742235e1e720c1f7e6dc75a11aFariborz Jahanian if (!Decls.empty() && !CurDeclType.isNull()) { 2242d588b4bc7127adf1a1c621002dfe452a99fef6fFariborz Jahanian QualType BaseType = GetBaseType(CurDeclType); 2252d588b4bc7127adf1a1c621002dfe452a99fef6fFariborz Jahanian if (!BaseType.isNull() && isa<TagType>(BaseType) && 22696b098674908eaa59a9128f3305cda6fbbdad563Dmitri Gribenko cast<TagType>(BaseType)->getDecl() == Decls[0]) { 2278487c524fdfcea3da858fd0af850b4784c8096d0Dmitri Gribenko Decls.push_back(*D); 2288487c524fdfcea3da858fd0af850b4784c8096d0Dmitri Gribenko continue; 2291ca7ecc8854ffea215c033a0d8482551bf1b73f0Dmitri Gribenko } 2301ca7ecc8854ffea215c033a0d8482551bf1b73f0Dmitri Gribenko } 2318487c524fdfcea3da858fd0af850b4784c8096d0Dmitri Gribenko 2328487c524fdfcea3da858fd0af850b4784c8096d0Dmitri Gribenko // If we have a merged group waiting to be handled, handle it now. 233a5ef44ff5d93a3be6ca67782828157a71894cf0cDmitri Gribenko if (!Decls.empty()) 234a5ef44ff5d93a3be6ca67782828157a71894cf0cDmitri Gribenko ProcessDeclGroup(Decls); 2358487c524fdfcea3da858fd0af850b4784c8096d0Dmitri Gribenko 236a5ef44ff5d93a3be6ca67782828157a71894cf0cDmitri Gribenko // If the current declaration is an unnamed tag type, save it 237a5ef44ff5d93a3be6ca67782828157a71894cf0cDmitri Gribenko // so we can merge it with the subsequent declaration(s) using it. 238a5ef44ff5d93a3be6ca67782828157a71894cf0cDmitri Gribenko if (isa<TagDecl>(*D) && !cast<TagDecl>(*D)->getIdentifier()) { 239a5ef44ff5d93a3be6ca67782828157a71894cf0cDmitri Gribenko Decls.push_back(*D); 2408487c524fdfcea3da858fd0af850b4784c8096d0Dmitri Gribenko continue; 241a5ef44ff5d93a3be6ca67782828157a71894cf0cDmitri Gribenko } 24296b098674908eaa59a9128f3305cda6fbbdad563Dmitri Gribenko this->Indent(); 24396b098674908eaa59a9128f3305cda6fbbdad563Dmitri Gribenko Visit(*D); 24496b098674908eaa59a9128f3305cda6fbbdad563Dmitri Gribenko 24596b098674908eaa59a9128f3305cda6fbbdad563Dmitri Gribenko // FIXME: Need to be able to tell the DeclPrinter when 24696b098674908eaa59a9128f3305cda6fbbdad563Dmitri Gribenko const char *Terminator = 0; 24796b098674908eaa59a9128f3305cda6fbbdad563Dmitri Gribenko if (isa<FunctionDecl>(*D) && 24896b098674908eaa59a9128f3305cda6fbbdad563Dmitri Gribenko cast<FunctionDecl>(*D)->isThisDeclarationADefinition()) 24996b098674908eaa59a9128f3305cda6fbbdad563Dmitri Gribenko Terminator = 0; 2502d66a5016d4aacce362f89290261c8a1a6eef0d3Dmitri Gribenko else if (isa<ObjCMethodDecl>(*D) && cast<ObjCMethodDecl>(*D)->getBody()) 2512d66a5016d4aacce362f89290261c8a1a6eef0d3Dmitri Gribenko Terminator = 0; 2528d3ba23f2d9e6c87794d059412a0808c9cbacb25Dmitri Gribenko else if (isa<NamespaceDecl>(*D) || isa<LinkageSpecDecl>(*D) || 2538d3ba23f2d9e6c87794d059412a0808c9cbacb25Dmitri Gribenko isa<ObjCImplementationDecl>(*D) || 2548d3ba23f2d9e6c87794d059412a0808c9cbacb25Dmitri Gribenko isa<ObjCInterfaceDecl>(*D) || 2558d3ba23f2d9e6c87794d059412a0808c9cbacb25Dmitri Gribenko isa<ObjCProtocolDecl>(*D) || 2568d3ba23f2d9e6c87794d059412a0808c9cbacb25Dmitri Gribenko isa<ObjCCategoryImplDecl>(*D) || 2578d3ba23f2d9e6c87794d059412a0808c9cbacb25Dmitri Gribenko isa<ObjCCategoryDecl>(*D)) 2588d3ba23f2d9e6c87794d059412a0808c9cbacb25Dmitri Gribenko Terminator = 0; 259 else if (isa<EnumConstantDecl>(*D)) { 260 DeclContext::decl_iterator Next = D; 261 ++Next; 262 if (Next != DEnd) 263 Terminator = ","; 264 } else 265 Terminator = ";"; 266 267 if (Terminator) 268 Out << Terminator; 269 Out << "\n"; 270 } 271 272 if (!Decls.empty()) 273 ProcessDeclGroup(Decls); 274 275 if (Indent) 276 Indentation -= Policy.Indentation; 277} 278 279void DeclPrinter::VisitTranslationUnitDecl(TranslationUnitDecl *D) { 280 VisitDeclContext(D, false); 281} 282 283void DeclPrinter::VisitTypedefDecl(TypedefDecl *D) { 284 std::string S = D->getNameAsString(); 285 D->getUnderlyingType().getAsStringInternal(S, Policy); 286 if (!Policy.SuppressSpecifiers) 287 Out << "typedef "; 288 Out << S; 289} 290 291void DeclPrinter::VisitEnumDecl(EnumDecl *D) { 292 Out << "enum " << D->getNameAsString() << " {\n"; 293 VisitDeclContext(D); 294 Indent() << "}"; 295} 296 297void DeclPrinter::VisitRecordDecl(RecordDecl *D) { 298 Out << D->getKindName(); 299 if (D->getIdentifier()) { 300 Out << " "; 301 Out << D->getNameAsString(); 302 } 303 304 if (D->isDefinition()) { 305 Out << " {\n"; 306 VisitDeclContext(D); 307 Indent() << "}"; 308 } 309} 310 311void DeclPrinter::VisitEnumConstantDecl(EnumConstantDecl *D) { 312 Out << D->getNameAsString(); 313 if (Expr *Init = D->getInitExpr()) { 314 Out << " = "; 315 Init->printPretty(Out, Context, 0, Policy, Indentation); 316 } 317} 318 319void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) { 320 if (!Policy.SuppressSpecifiers) { 321 switch (D->getStorageClass()) { 322 case FunctionDecl::None: break; 323 case FunctionDecl::Extern: Out << "extern "; break; 324 case FunctionDecl::Static: Out << "static "; break; 325 case FunctionDecl::PrivateExtern: Out << "__private_extern__ "; break; 326 } 327 328 if (D->isInlineSpecified()) Out << "inline "; 329 if (D->isVirtualAsWritten()) Out << "virtual "; 330 } 331 332 PrintingPolicy SubPolicy(Policy); 333 SubPolicy.SuppressSpecifiers = false; 334 std::string Proto = D->getNameAsString(); 335 if (isa<FunctionType>(D->getType().getTypePtr())) { 336 const FunctionType *AFT = D->getType()->getAs<FunctionType>(); 337 338 const FunctionProtoType *FT = 0; 339 if (D->hasWrittenPrototype()) 340 FT = dyn_cast<FunctionProtoType>(AFT); 341 342 Proto += "("; 343 if (FT) { 344 llvm::raw_string_ostream POut(Proto); 345 DeclPrinter ParamPrinter(POut, Context, SubPolicy, Indentation); 346 for (unsigned i = 0, e = D->getNumParams(); i != e; ++i) { 347 if (i) POut << ", "; 348 ParamPrinter.VisitParmVarDecl(D->getParamDecl(i)); 349 } 350 351 if (FT->isVariadic()) { 352 if (D->getNumParams()) POut << ", "; 353 POut << "..."; 354 } 355 } else if (D->isThisDeclarationADefinition() && !D->hasPrototype()) { 356 for (unsigned i = 0, e = D->getNumParams(); i != e; ++i) { 357 if (i) 358 Proto += ", "; 359 Proto += D->getParamDecl(i)->getNameAsString(); 360 } 361 } 362 363 Proto += ")"; 364 365 if (FT && FT->hasExceptionSpec()) { 366 Proto += " throw("; 367 if (FT->hasAnyExceptionSpec()) 368 Proto += "..."; 369 else 370 for (unsigned I = 0, N = FT->getNumExceptions(); I != N; ++I) { 371 if (I) 372 Proto += ", "; 373 374 375 std::string ExceptionType; 376 FT->getExceptionType(I).getAsStringInternal(ExceptionType, SubPolicy); 377 Proto += ExceptionType; 378 } 379 Proto += ")"; 380 } 381 382 if (D->hasAttr<NoReturnAttr>()) 383 Proto += " __attribute((noreturn))"; 384 if (CXXConstructorDecl *CDecl = dyn_cast<CXXConstructorDecl>(D)) { 385 if (CDecl->getNumBaseOrMemberInitializers() > 0) { 386 Proto += " : "; 387 Out << Proto; 388 Proto.clear(); 389 for (CXXConstructorDecl::init_const_iterator B = CDecl->init_begin(), 390 E = CDecl->init_end(); 391 B != E; ++B) { 392 CXXBaseOrMemberInitializer * BMInitializer = (*B); 393 if (B != CDecl->init_begin()) 394 Out << ", "; 395 bool hasArguments = (BMInitializer->arg_begin() != 396 BMInitializer->arg_end()); 397 if (BMInitializer->isMemberInitializer()) { 398 FieldDecl *FD = BMInitializer->getMember(); 399 Out << FD->getNameAsString(); 400 } 401 else // FIXME. skip dependent types for now. 402 if (const RecordType *RT = 403 BMInitializer->getBaseClass()->getAs<RecordType>()) { 404 const CXXRecordDecl *BaseDecl = 405 cast<CXXRecordDecl>(RT->getDecl()); 406 Out << BaseDecl->getNameAsString(); 407 } 408 if (hasArguments) { 409 Out << "("; 410 for (CXXBaseOrMemberInitializer::const_arg_iterator BE = 411 BMInitializer->const_arg_begin(), 412 EE = BMInitializer->const_arg_end(); BE != EE; ++BE) { 413 if (BE != BMInitializer->const_arg_begin()) 414 Out<< ", "; 415 const Expr *Exp = (*BE); 416 Exp->printPretty(Out, Context, 0, Policy, Indentation); 417 } 418 Out << ")"; 419 } else 420 Out << "()"; 421 } 422 } 423 } 424 else 425 AFT->getResultType().getAsStringInternal(Proto, Policy); 426 } else { 427 D->getType().getAsStringInternal(Proto, Policy); 428 } 429 430 Out << Proto; 431 432 if (D->isPure()) 433 Out << " = 0"; 434 else if (D->isDeleted()) 435 Out << " = delete"; 436 else if (D->isThisDeclarationADefinition()) { 437 if (!D->hasPrototype() && D->getNumParams()) { 438 // This is a K&R function definition, so we need to print the 439 // parameters. 440 Out << '\n'; 441 DeclPrinter ParamPrinter(Out, Context, SubPolicy, Indentation); 442 Indentation += Policy.Indentation; 443 for (unsigned i = 0, e = D->getNumParams(); i != e; ++i) { 444 Indent(); 445 ParamPrinter.VisitParmVarDecl(D->getParamDecl(i)); 446 Out << ";\n"; 447 } 448 Indentation -= Policy.Indentation; 449 } else 450 Out << ' '; 451 452 D->getBody()->printPretty(Out, Context, 0, SubPolicy, Indentation); 453 Out << '\n'; 454 } 455} 456 457void DeclPrinter::VisitFieldDecl(FieldDecl *D) { 458 if (!Policy.SuppressSpecifiers && D->isMutable()) 459 Out << "mutable "; 460 461 std::string Name = D->getNameAsString(); 462 D->getType().getAsStringInternal(Name, Policy); 463 Out << Name; 464 465 if (D->isBitField()) { 466 Out << " : "; 467 D->getBitWidth()->printPretty(Out, Context, 0, Policy, Indentation); 468 } 469} 470 471void DeclPrinter::VisitVarDecl(VarDecl *D) { 472 if (!Policy.SuppressSpecifiers && D->getStorageClass() != VarDecl::None) 473 Out << VarDecl::getStorageClassSpecifierString(D->getStorageClass()) << " "; 474 475 if (!Policy.SuppressSpecifiers && D->isThreadSpecified()) 476 Out << "__thread "; 477 478 std::string Name = D->getNameAsString(); 479 QualType T = D->getType(); 480 if (ParmVarDecl *Parm = dyn_cast<ParmVarDecl>(D)) 481 T = Parm->getOriginalType(); 482 T.getAsStringInternal(Name, Policy); 483 Out << Name; 484 if (D->getInit()) { 485 if (D->hasCXXDirectInitializer()) 486 Out << "("; 487 else 488 Out << " = "; 489 D->getInit()->printPretty(Out, Context, 0, Policy, Indentation); 490 if (D->hasCXXDirectInitializer()) 491 Out << ")"; 492 } 493} 494 495void DeclPrinter::VisitParmVarDecl(ParmVarDecl *D) { 496 VisitVarDecl(D); 497} 498 499void DeclPrinter::VisitFileScopeAsmDecl(FileScopeAsmDecl *D) { 500 Out << "__asm ("; 501 D->getAsmString()->printPretty(Out, Context, 0, Policy, Indentation); 502 Out << ")"; 503} 504 505//---------------------------------------------------------------------------- 506// C++ declarations 507//---------------------------------------------------------------------------- 508void DeclPrinter::VisitNamespaceDecl(NamespaceDecl *D) { 509 Out << "namespace " << D->getNameAsString() << " {\n"; 510 VisitDeclContext(D); 511 Indent() << "}"; 512} 513 514void DeclPrinter::VisitUsingDirectiveDecl(UsingDirectiveDecl *D) { 515 Out << "using namespace "; 516 if (D->getQualifier()) 517 D->getQualifier()->print(Out, Policy); 518 Out << D->getNominatedNamespaceAsWritten()->getNameAsString(); 519} 520 521void DeclPrinter::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) { 522 Out << "namespace " << D->getNameAsString() << " = "; 523 if (D->getQualifier()) 524 D->getQualifier()->print(Out, Policy); 525 Out << D->getAliasedNamespace()->getNameAsString(); 526} 527 528void DeclPrinter::VisitCXXRecordDecl(CXXRecordDecl *D) { 529 Out << D->getKindName(); 530 if (D->getIdentifier()) { 531 Out << " "; 532 Out << D->getNameAsString(); 533 } 534 535 if (D->isDefinition()) { 536 // Print the base classes 537 if (D->getNumBases()) { 538 Out << " : "; 539 for (CXXRecordDecl::base_class_iterator Base = D->bases_begin(), 540 BaseEnd = D->bases_end(); Base != BaseEnd; ++Base) { 541 if (Base != D->bases_begin()) 542 Out << ", "; 543 544 if (Base->isVirtual()) 545 Out << "virtual "; 546 547 AccessSpecifier AS = Base->getAccessSpecifierAsWritten(); 548 if (AS != AS_none) 549 Print(AS); 550 Out << " " << Base->getType().getAsString(Policy); 551 } 552 } 553 554 // Print the class definition 555 // FIXME: Doesn't print access specifiers, e.g., "public:" 556 Out << " {\n"; 557 VisitDeclContext(D); 558 Indent() << "}"; 559 } 560} 561 562void DeclPrinter::VisitLinkageSpecDecl(LinkageSpecDecl *D) { 563 const char *l; 564 if (D->getLanguage() == LinkageSpecDecl::lang_c) 565 l = "C"; 566 else { 567 assert(D->getLanguage() == LinkageSpecDecl::lang_cxx && 568 "unknown language in linkage specification"); 569 l = "C++"; 570 } 571 572 Out << "extern \"" << l << "\" "; 573 if (D->hasBraces()) { 574 Out << "{\n"; 575 VisitDeclContext(D); 576 Indent() << "}"; 577 } else 578 Visit(*D->decls_begin()); 579} 580 581void DeclPrinter::VisitTemplateDecl(TemplateDecl *D) { 582 Out << "template <"; 583 584 TemplateParameterList *Params = D->getTemplateParameters(); 585 for (unsigned i = 0, e = Params->size(); i != e; ++i) { 586 if (i != 0) 587 Out << ", "; 588 589 const Decl *Param = Params->getParam(i); 590 if (const TemplateTypeParmDecl *TTP = 591 dyn_cast<TemplateTypeParmDecl>(Param)) { 592 593 QualType ParamType = 594 Context.getTypeDeclType(const_cast<TemplateTypeParmDecl*>(TTP)); 595 596 if (TTP->wasDeclaredWithTypename()) 597 Out << "typename "; 598 else 599 Out << "class "; 600 601 if (TTP->isParameterPack()) 602 Out << "... "; 603 604 Out << ParamType.getAsString(Policy); 605 606 if (TTP->hasDefaultArgument()) { 607 Out << " = "; 608 Out << TTP->getDefaultArgument().getAsString(Policy); 609 }; 610 } else if (const NonTypeTemplateParmDecl *NTTP = 611 dyn_cast<NonTypeTemplateParmDecl>(Param)) { 612 Out << NTTP->getType().getAsString(Policy); 613 614 if (IdentifierInfo *Name = NTTP->getIdentifier()) { 615 Out << ' '; 616 Out << Name->getName(); 617 } 618 619 if (NTTP->hasDefaultArgument()) { 620 Out << " = "; 621 NTTP->getDefaultArgument()->printPretty(Out, Context, 0, Policy, 622 Indentation); 623 } 624 } 625 } 626 627 Out << "> "; 628 629 Visit(D->getTemplatedDecl()); 630} 631 632//---------------------------------------------------------------------------- 633// Objective-C declarations 634//---------------------------------------------------------------------------- 635 636void DeclPrinter::VisitObjCClassDecl(ObjCClassDecl *D) { 637 Out << "@class "; 638 for (ObjCClassDecl::iterator I = D->begin(), E = D->end(); 639 I != E; ++I) { 640 if (I != D->begin()) Out << ", "; 641 Out << I->getInterface()->getNameAsString(); 642 } 643} 644 645void DeclPrinter::VisitObjCMethodDecl(ObjCMethodDecl *OMD) { 646 if (OMD->isInstanceMethod()) 647 Out << "- "; 648 else 649 Out << "+ "; 650 if (!OMD->getResultType().isNull()) 651 Out << '(' << OMD->getResultType().getAsString(Policy) << ")"; 652 653 std::string name = OMD->getSelector().getAsString(); 654 std::string::size_type pos, lastPos = 0; 655 for (ObjCMethodDecl::param_iterator PI = OMD->param_begin(), 656 E = OMD->param_end(); PI != E; ++PI) { 657 // FIXME: selector is missing here! 658 pos = name.find_first_of(":", lastPos); 659 Out << " " << name.substr(lastPos, pos - lastPos); 660 Out << ":(" << (*PI)->getType().getAsString(Policy) << ")" 661 << (*PI)->getNameAsString(); 662 lastPos = pos + 1; 663 } 664 665 if (OMD->param_begin() == OMD->param_end()) 666 Out << " " << name; 667 668 if (OMD->isVariadic()) 669 Out << ", ..."; 670 671 if (OMD->getBody()) { 672 Out << ' '; 673 OMD->getBody()->printPretty(Out, Context, 0, Policy); 674 Out << '\n'; 675 } 676} 677 678void DeclPrinter::VisitObjCImplementationDecl(ObjCImplementationDecl *OID) { 679 std::string I = OID->getNameAsString(); 680 ObjCInterfaceDecl *SID = OID->getSuperClass(); 681 682 if (SID) 683 Out << "@implementation " << I << " : " << SID->getNameAsString(); 684 else 685 Out << "@implementation " << I; 686 Out << "\n"; 687 VisitDeclContext(OID, false); 688 Out << "@end"; 689} 690 691void DeclPrinter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *OID) { 692 std::string I = OID->getNameAsString(); 693 ObjCInterfaceDecl *SID = OID->getSuperClass(); 694 695 if (SID) 696 Out << "@interface " << I << " : " << SID->getNameAsString(); 697 else 698 Out << "@interface " << I; 699 700 // Protocols? 701 const ObjCList<ObjCProtocolDecl> &Protocols = OID->getReferencedProtocols(); 702 if (!Protocols.empty()) { 703 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(), 704 E = Protocols.end(); I != E; ++I) 705 Out << (I == Protocols.begin() ? '<' : ',') << (*I)->getNameAsString(); 706 } 707 708 if (!Protocols.empty()) 709 Out << "> "; 710 711 if (OID->ivar_size() > 0) { 712 Out << "{\n"; 713 Indentation += Policy.Indentation; 714 for (ObjCInterfaceDecl::ivar_iterator I = OID->ivar_begin(), 715 E = OID->ivar_end(); I != E; ++I) { 716 Indent() << (*I)->getType().getAsString(Policy) 717 << ' ' << (*I)->getNameAsString() << ";\n"; 718 } 719 Indentation -= Policy.Indentation; 720 Out << "}\n"; 721 } 722 723 VisitDeclContext(OID, false); 724 Out << "@end"; 725 // FIXME: implement the rest... 726} 727 728void DeclPrinter::VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *D) { 729 Out << "@protocol "; 730 for (ObjCForwardProtocolDecl::protocol_iterator I = D->protocol_begin(), 731 E = D->protocol_end(); 732 I != E; ++I) { 733 if (I != D->protocol_begin()) Out << ", "; 734 Out << (*I)->getNameAsString(); 735 } 736} 737 738void DeclPrinter::VisitObjCProtocolDecl(ObjCProtocolDecl *PID) { 739 Out << "@protocol " << PID->getNameAsString() << '\n'; 740 VisitDeclContext(PID, false); 741 Out << "@end"; 742} 743 744void DeclPrinter::VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *PID) { 745 Out << "@implementation " 746 << PID->getClassInterface()->getNameAsString() 747 << '(' << PID->getNameAsString() << ")\n"; 748 749 VisitDeclContext(PID, false); 750 Out << "@end"; 751 // FIXME: implement the rest... 752} 753 754void DeclPrinter::VisitObjCCategoryDecl(ObjCCategoryDecl *PID) { 755 Out << "@interface " 756 << PID->getClassInterface()->getNameAsString() 757 << '(' << PID->getNameAsString() << ")\n"; 758 VisitDeclContext(PID, false); 759 Out << "@end"; 760 761 // FIXME: implement the rest... 762} 763 764void DeclPrinter::VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *AID) { 765 Out << "@compatibility_alias " << AID->getNameAsString() 766 << ' ' << AID->getClassInterface()->getNameAsString() << ";\n"; 767} 768 769/// PrintObjCPropertyDecl - print a property declaration. 770/// 771void DeclPrinter::VisitObjCPropertyDecl(ObjCPropertyDecl *PDecl) { 772 if (PDecl->getPropertyImplementation() == ObjCPropertyDecl::Required) 773 Out << "@required\n"; 774 else if (PDecl->getPropertyImplementation() == ObjCPropertyDecl::Optional) 775 Out << "@optional\n"; 776 777 Out << "@property"; 778 if (PDecl->getPropertyAttributes() != ObjCPropertyDecl::OBJC_PR_noattr) { 779 bool first = true; 780 Out << " ("; 781 if (PDecl->getPropertyAttributes() & 782 ObjCPropertyDecl::OBJC_PR_readonly) { 783 Out << (first ? ' ' : ',') << "readonly"; 784 first = false; 785 } 786 787 if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_getter) { 788 Out << (first ? ' ' : ',') << "getter = " 789 << PDecl->getGetterName().getAsString(); 790 first = false; 791 } 792 if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_setter) { 793 Out << (first ? ' ' : ',') << "setter = " 794 << PDecl->getSetterName().getAsString(); 795 first = false; 796 } 797 798 if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_assign) { 799 Out << (first ? ' ' : ',') << "assign"; 800 first = false; 801 } 802 803 if (PDecl->getPropertyAttributes() & 804 ObjCPropertyDecl::OBJC_PR_readwrite) { 805 Out << (first ? ' ' : ',') << "readwrite"; 806 first = false; 807 } 808 809 if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_retain) { 810 Out << (first ? ' ' : ',') << "retain"; 811 first = false; 812 } 813 814 if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_copy) { 815 Out << (first ? ' ' : ',') << "copy"; 816 first = false; 817 } 818 819 if (PDecl->getPropertyAttributes() & 820 ObjCPropertyDecl::OBJC_PR_nonatomic) { 821 Out << (first ? ' ' : ',') << "nonatomic"; 822 first = false; 823 } 824 Out << " )"; 825 } 826 Out << ' ' << PDecl->getType().getAsString(Policy) 827 << ' ' << PDecl->getNameAsString(); 828} 829 830void DeclPrinter::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *PID) { 831 if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize) 832 Out << "@synthesize "; 833 else 834 Out << "@dynamic "; 835 Out << PID->getPropertyDecl()->getNameAsString(); 836 if (PID->getPropertyIvarDecl()) 837 Out << "=" << PID->getPropertyIvarDecl()->getNameAsString(); 838} 839 840void DeclPrinter::VisitUsingDecl(UsingDecl *D) { 841 Out << "using "; 842 D->getTargetNestedNameDecl()->print(Out, Policy); 843 Out << D->getNameAsString(); 844} 845 846void 847DeclPrinter::VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D) { 848 Out << "using typename "; 849 D->getTargetNestedNameSpecifier()->print(Out, Policy); 850 Out << D->getDeclName().getAsString(); 851} 852 853void DeclPrinter::VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D) { 854 Out << "using "; 855 D->getTargetNestedNameSpecifier()->print(Out, Policy); 856 Out << D->getDeclName().getAsString(); 857} 858 859void DeclPrinter::VisitUsingShadowDecl(UsingShadowDecl *D) { 860 // ignore 861} 862