DeclPrinter.cpp revision 723df245307a530da5433dfb43accf187dc3e243
12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//===--- DeclPrinter.cpp - Printing implementation for Decl ASTs ----------===// 22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// 32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// The LLVM Compiler Infrastructure 42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// 51320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// This file is distributed under the University of Illinois Open Source 61320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// License. See LICENSE.TXT for details. 72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// 82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//===----------------------------------------------------------------------===// 958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// 102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// This file implements the Decl::dump method, which pretty print the 11868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// AST back out to C/Objective-C/C++/Objective-C++ code. 122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// 132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//===----------------------------------------------------------------------===// 141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "clang/AST/ASTContext.h" 152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "clang/AST/DeclVisitor.h" 162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "clang/AST/Decl.h" 172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "clang/AST/DeclCXX.h" 182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "clang/AST/DeclObjC.h" 192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "clang/AST/Expr.h" 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "clang/AST/ExprCXX.h" 212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "clang/AST/PrettyPrinter.h" 222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "llvm/Support/raw_ostream.h" 232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using namespace clang; 242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace { 262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) class DeclPrinter : public DeclVisitor<DeclPrinter> { 272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) llvm::raw_ostream &Out; 282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASTContext &Context; 292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) PrintingPolicy Policy; 30a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) unsigned Indentation; 312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) llvm::raw_ostream& Indent() { return Indent(Indentation); } 332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) llvm::raw_ostream& Indent(unsigned Indentation); 342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void ProcessDeclGroup(llvm::SmallVectorImpl<Decl*>& Decls); 352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void Print(AccessSpecifier AS); 375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) public: 392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DeclPrinter(llvm::raw_ostream &Out, ASTContext &Context, 402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const PrintingPolicy &Policy, 41a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) unsigned Indentation = 0) 422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) : Out(Out), Context(Context), Policy(Policy), Indentation(Indentation) { } 432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 44a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) void VisitDeclContext(DeclContext *DC, bool Indent = true); 452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void VisitTranslationUnitDecl(TranslationUnitDecl *D); 472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void VisitTypedefDecl(TypedefDecl *D); 482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void VisitEnumDecl(EnumDecl *D); 492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void VisitRecordDecl(RecordDecl *D); 50868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) void VisitEnumConstantDecl(EnumConstantDecl *D); 51868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) void VisitFunctionDecl(FunctionDecl *D); 52868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) void VisitFieldDecl(FieldDecl *D); 53868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) void VisitVarDecl(VarDecl *D); 5458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) void VisitParmVarDecl(ParmVarDecl *D); 5558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) void VisitFileScopeAsmDecl(FileScopeAsmDecl *D); 5658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) void VisitNamespaceDecl(NamespaceDecl *D); 5758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) void VisitUsingDirectiveDecl(UsingDirectiveDecl *D); 582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void VisitNamespaceAliasDecl(NamespaceAliasDecl *D); 59eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch void VisitCXXRecordDecl(CXXRecordDecl *D); 6058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) void VisitLinkageSpecDecl(LinkageSpecDecl *D); 6158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) void VisitTemplateDecl(TemplateDecl *D); 62eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch void VisitObjCMethodDecl(ObjCMethodDecl *D); 63eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch void VisitObjCClassDecl(ObjCClassDecl *D); 642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void VisitObjCImplementationDecl(ObjCImplementationDecl *D); 65868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) void VisitObjCInterfaceDecl(ObjCInterfaceDecl *D); 66868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) void VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *D); 67868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) void VisitObjCProtocolDecl(ObjCProtocolDecl *D); 6890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) void VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D); 697dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch void VisitObjCCategoryDecl(ObjCCategoryDecl *D); 70a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) void VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *D); 7158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) void VisitObjCPropertyDecl(ObjCPropertyDecl *D); 7203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) void VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D); 7303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) void VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D); 74eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch void VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D); 7590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) void VisitUsingDecl(UsingDecl *D); 76a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) void VisitUsingShadowDecl(UsingShadowDecl *D); 772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) }; 782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void Decl::print(llvm::raw_ostream &Out, unsigned Indentation) const { 812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) print(Out, getASTContext().PrintingPolicy, Indentation); 82eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 837dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void Decl::print(llvm::raw_ostream &Out, const PrintingPolicy &Policy, 852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) unsigned Indentation) const { 861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DeclPrinter Printer(Out, getASTContext(), Policy, Indentation); 87 Printer.Visit(const_cast<Decl*>(this)); 88} 89 90static QualType GetBaseType(QualType T) { 91 // FIXME: This should be on the Type class! 92 QualType BaseType = T; 93 while (!BaseType->isSpecifierType()) { 94 if (isa<TypedefType>(BaseType)) 95 break; 96 else if (const PointerType* PTy = BaseType->getAs<PointerType>()) 97 BaseType = PTy->getPointeeType(); 98 else if (const ArrayType* ATy = dyn_cast<ArrayType>(BaseType)) 99 BaseType = ATy->getElementType(); 100 else if (const FunctionType* FTy = BaseType->getAs<FunctionType>()) 101 BaseType = FTy->getResultType(); 102 else if (const VectorType *VTy = BaseType->getAs<VectorType>()) 103 BaseType = VTy->getElementType(); 104 else 105 assert(0 && "Unknown declarator!"); 106 } 107 return BaseType; 108} 109 110static QualType getDeclType(Decl* D) { 111 if (TypedefDecl* TDD = dyn_cast<TypedefDecl>(D)) 112 return TDD->getUnderlyingType(); 113 if (ValueDecl* VD = dyn_cast<ValueDecl>(D)) 114 return VD->getType(); 115 return QualType(); 116} 117 118void Decl::printGroup(Decl** Begin, unsigned NumDecls, 119 llvm::raw_ostream &Out, const PrintingPolicy &Policy, 120 unsigned Indentation) { 121 if (NumDecls == 1) { 122 (*Begin)->print(Out, Policy, Indentation); 123 return; 124 } 125 126 Decl** End = Begin + NumDecls; 127 TagDecl* TD = dyn_cast<TagDecl>(*Begin); 128 if (TD) 129 ++Begin; 130 131 PrintingPolicy SubPolicy(Policy); 132 if (TD && TD->isDefinition()) { 133 TD->print(Out, Policy, Indentation); 134 Out << " "; 135 SubPolicy.SuppressTag = true; 136 } 137 138 bool isFirst = true; 139 for ( ; Begin != End; ++Begin) { 140 if (isFirst) { 141 SubPolicy.SuppressSpecifiers = false; 142 isFirst = false; 143 } else { 144 if (!isFirst) Out << ", "; 145 SubPolicy.SuppressSpecifiers = true; 146 } 147 148 (*Begin)->print(Out, SubPolicy, Indentation); 149 } 150} 151 152void DeclContext::dumpDeclContext() const { 153 // Get the translation unit 154 const DeclContext *DC = this; 155 while (!DC->isTranslationUnit()) 156 DC = DC->getParent(); 157 158 ASTContext &Ctx = cast<TranslationUnitDecl>(DC)->getASTContext(); 159 DeclPrinter Printer(llvm::errs(), Ctx, Ctx.PrintingPolicy, 0); 160 Printer.VisitDeclContext(const_cast<DeclContext *>(this), /*Indent=*/false); 161} 162 163void Decl::dump() const { 164 print(llvm::errs()); 165} 166 167llvm::raw_ostream& DeclPrinter::Indent(unsigned Indentation) { 168 for (unsigned i = 0; i != Indentation; ++i) 169 Out << " "; 170 return Out; 171} 172 173void DeclPrinter::ProcessDeclGroup(llvm::SmallVectorImpl<Decl*>& Decls) { 174 this->Indent(); 175 Decl::printGroup(Decls.data(), Decls.size(), Out, Policy, Indentation); 176 Out << ";\n"; 177 Decls.clear(); 178 179} 180 181void DeclPrinter::Print(AccessSpecifier AS) { 182 switch(AS) { 183 case AS_none: assert(0 && "No access specifier!"); break; 184 case AS_public: Out << "public"; break; 185 case AS_protected: Out << "protected"; break; 186 case AS_private: Out << "private"; break; 187 } 188} 189 190//---------------------------------------------------------------------------- 191// Common C declarations 192//---------------------------------------------------------------------------- 193 194void DeclPrinter::VisitDeclContext(DeclContext *DC, bool Indent) { 195 if (Indent) 196 Indentation += Policy.Indentation; 197 198 llvm::SmallVector<Decl*, 2> Decls; 199 for (DeclContext::decl_iterator D = DC->decls_begin(), DEnd = DC->decls_end(); 200 D != DEnd; ++D) { 201 202 // Don't print ObjCIvarDecls, as they are printed when visiting the 203 // containing ObjCInterfaceDecl. 204 if (isa<ObjCIvarDecl>(*D)) 205 continue; 206 207 if (!Policy.Dump) { 208 // Skip over implicit declarations in pretty-printing mode. 209 if (D->isImplicit()) continue; 210 // FIXME: Ugly hack so we don't pretty-print the builtin declaration 211 // of __builtin_va_list or __[u]int128_t. There should be some other way 212 // to check that. 213 if (NamedDecl *ND = dyn_cast<NamedDecl>(*D)) { 214 if (IdentifierInfo *II = ND->getIdentifier()) { 215 if (II->isStr("__builtin_va_list") || 216 II->isStr("__int128_t") || II->isStr("__uint128_t")) 217 continue; 218 } 219 } 220 } 221 222 // The next bits of code handles stuff like "struct {int x;} a,b"; we're 223 // forced to merge the declarations because there's no other way to 224 // refer to the struct in question. This limited merging is safe without 225 // a bunch of other checks because it only merges declarations directly 226 // referring to the tag, not typedefs. 227 // 228 // Check whether the current declaration should be grouped with a previous 229 // unnamed struct. 230 QualType CurDeclType = getDeclType(*D); 231 if (!Decls.empty() && !CurDeclType.isNull()) { 232 QualType BaseType = GetBaseType(CurDeclType); 233 if (!BaseType.isNull() && isa<TagType>(BaseType) && 234 cast<TagType>(BaseType)->getDecl() == Decls[0]) { 235 Decls.push_back(*D); 236 continue; 237 } 238 } 239 240 // If we have a merged group waiting to be handled, handle it now. 241 if (!Decls.empty()) 242 ProcessDeclGroup(Decls); 243 244 // If the current declaration is an unnamed tag type, save it 245 // so we can merge it with the subsequent declaration(s) using it. 246 if (isa<TagDecl>(*D) && !cast<TagDecl>(*D)->getIdentifier()) { 247 Decls.push_back(*D); 248 continue; 249 } 250 251 if (isa<AccessSpecDecl>(*D)) { 252 Indentation -= Policy.Indentation; 253 this->Indent(); 254 Print(D->getAccess()); 255 Out << ":\n"; 256 Indentation += Policy.Indentation; 257 continue; 258 } 259 260 this->Indent(); 261 Visit(*D); 262 263 // FIXME: Need to be able to tell the DeclPrinter when 264 const char *Terminator = 0; 265 if (isa<FunctionDecl>(*D) && 266 cast<FunctionDecl>(*D)->isThisDeclarationADefinition()) 267 Terminator = 0; 268 else if (isa<ObjCMethodDecl>(*D) && cast<ObjCMethodDecl>(*D)->getBody()) 269 Terminator = 0; 270 else if (isa<NamespaceDecl>(*D) || isa<LinkageSpecDecl>(*D) || 271 isa<ObjCImplementationDecl>(*D) || 272 isa<ObjCInterfaceDecl>(*D) || 273 isa<ObjCProtocolDecl>(*D) || 274 isa<ObjCCategoryImplDecl>(*D) || 275 isa<ObjCCategoryDecl>(*D)) 276 Terminator = 0; 277 else if (isa<EnumConstantDecl>(*D)) { 278 DeclContext::decl_iterator Next = D; 279 ++Next; 280 if (Next != DEnd) 281 Terminator = ","; 282 } else 283 Terminator = ";"; 284 285 if (Terminator) 286 Out << Terminator; 287 Out << "\n"; 288 } 289 290 if (!Decls.empty()) 291 ProcessDeclGroup(Decls); 292 293 if (Indent) 294 Indentation -= Policy.Indentation; 295} 296 297void DeclPrinter::VisitTranslationUnitDecl(TranslationUnitDecl *D) { 298 VisitDeclContext(D, false); 299} 300 301void DeclPrinter::VisitTypedefDecl(TypedefDecl *D) { 302 std::string S = D->getNameAsString(); 303 D->getUnderlyingType().getAsStringInternal(S, Policy); 304 if (!Policy.SuppressSpecifiers) 305 Out << "typedef "; 306 Out << S; 307} 308 309void DeclPrinter::VisitEnumDecl(EnumDecl *D) { 310 Out << "enum "; 311 if (D->isScoped()) { 312 if (D->isScopedUsingClassTag()) 313 Out << "class "; 314 else 315 Out << "struct "; 316 } 317 Out << D; 318 319 if (D->isFixed()) { 320 std::string Underlying; 321 D->getIntegerType().getAsStringInternal(Underlying, Policy); 322 Out << " : " << Underlying; 323 } 324 325 if (D->isDefinition()) { 326 Out << " {\n"; 327 VisitDeclContext(D); 328 Indent() << "}"; 329 } 330} 331 332void DeclPrinter::VisitRecordDecl(RecordDecl *D) { 333 Out << D->getKindName(); 334 if (D->getIdentifier()) 335 Out << ' ' << D; 336 337 if (D->isDefinition()) { 338 Out << " {\n"; 339 VisitDeclContext(D); 340 Indent() << "}"; 341 } 342} 343 344void DeclPrinter::VisitEnumConstantDecl(EnumConstantDecl *D) { 345 Out << D; 346 if (Expr *Init = D->getInitExpr()) { 347 Out << " = "; 348 Init->printPretty(Out, Context, 0, Policy, Indentation); 349 } 350} 351 352void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) { 353 if (!Policy.SuppressSpecifiers) { 354 switch (D->getStorageClass()) { 355 case SC_None: break; 356 case SC_Extern: Out << "extern "; break; 357 case SC_Static: Out << "static "; break; 358 case SC_PrivateExtern: Out << "__private_extern__ "; break; 359 case SC_Auto: case SC_Register: llvm_unreachable("invalid for functions"); 360 } 361 362 if (D->isInlineSpecified()) Out << "inline "; 363 if (D->isVirtualAsWritten()) Out << "virtual "; 364 } 365 366 PrintingPolicy SubPolicy(Policy); 367 SubPolicy.SuppressSpecifiers = false; 368 std::string Proto = D->getNameInfo().getAsString(); 369 370 QualType Ty = D->getType(); 371 while (ParenType* PT = dyn_cast<ParenType>(Ty)) { 372 Proto = '(' + Proto + ')'; 373 Ty = PT->getInnerType(); 374 } 375 376 if (isa<FunctionType>(Ty)) { 377 const FunctionType *AFT = Ty->getAs<FunctionType>(); 378 const FunctionProtoType *FT = 0; 379 if (D->hasWrittenPrototype()) 380 FT = dyn_cast<FunctionProtoType>(AFT); 381 382 Proto += "("; 383 if (FT) { 384 llvm::raw_string_ostream POut(Proto); 385 DeclPrinter ParamPrinter(POut, Context, SubPolicy, Indentation); 386 for (unsigned i = 0, e = D->getNumParams(); i != e; ++i) { 387 if (i) POut << ", "; 388 ParamPrinter.VisitParmVarDecl(D->getParamDecl(i)); 389 } 390 391 if (FT->isVariadic()) { 392 if (D->getNumParams()) POut << ", "; 393 POut << "..."; 394 } 395 } else if (D->isThisDeclarationADefinition() && !D->hasPrototype()) { 396 for (unsigned i = 0, e = D->getNumParams(); i != e; ++i) { 397 if (i) 398 Proto += ", "; 399 Proto += D->getParamDecl(i)->getNameAsString(); 400 } 401 } 402 403 Proto += ")"; 404 405 if (FT && FT->getTypeQuals()) { 406 unsigned TypeQuals = FT->getTypeQuals(); 407 if (TypeQuals & Qualifiers::Const) 408 Proto += " const"; 409 if (TypeQuals & Qualifiers::Volatile) 410 Proto += " volatile"; 411 if (TypeQuals & Qualifiers::Restrict) 412 Proto += " restrict"; 413 } 414 415 if (FT && FT->hasExceptionSpec()) { 416 Proto += " throw("; 417 if (FT->hasAnyExceptionSpec()) 418 Proto += "..."; 419 else 420 for (unsigned I = 0, N = FT->getNumExceptions(); I != N; ++I) { 421 if (I) 422 Proto += ", "; 423 424 425 std::string ExceptionType; 426 FT->getExceptionType(I).getAsStringInternal(ExceptionType, SubPolicy); 427 Proto += ExceptionType; 428 } 429 Proto += ")"; 430 } 431 432 if (D->hasAttr<NoReturnAttr>()) 433 Proto += " __attribute((noreturn))"; 434 if (CXXConstructorDecl *CDecl = dyn_cast<CXXConstructorDecl>(D)) { 435 if (CDecl->getNumBaseOrMemberInitializers() > 0) { 436 Proto += " : "; 437 Out << Proto; 438 Proto.clear(); 439 for (CXXConstructorDecl::init_const_iterator B = CDecl->init_begin(), 440 E = CDecl->init_end(); 441 B != E; ++B) { 442 CXXBaseOrMemberInitializer * BMInitializer = (*B); 443 if (B != CDecl->init_begin()) 444 Out << ", "; 445 if (BMInitializer->isAnyMemberInitializer()) { 446 FieldDecl *FD = BMInitializer->getAnyMember(); 447 Out << FD; 448 } else { 449 Out << QualType(BMInitializer->getBaseClass(), 450 0).getAsString(Policy); 451 } 452 453 Out << "("; 454 if (!BMInitializer->getInit()) { 455 // Nothing to print 456 } else { 457 Expr *Init = BMInitializer->getInit(); 458 if (ExprWithCleanups *Tmp = dyn_cast<ExprWithCleanups>(Init)) 459 Init = Tmp->getSubExpr(); 460 461 Init = Init->IgnoreParens(); 462 463 Expr *SimpleInit = 0; 464 Expr **Args = 0; 465 unsigned NumArgs = 0; 466 if (ParenListExpr *ParenList = dyn_cast<ParenListExpr>(Init)) { 467 Args = ParenList->getExprs(); 468 NumArgs = ParenList->getNumExprs(); 469 } else if (CXXConstructExpr *Construct 470 = dyn_cast<CXXConstructExpr>(Init)) { 471 Args = Construct->getArgs(); 472 NumArgs = Construct->getNumArgs(); 473 } else 474 SimpleInit = Init; 475 476 if (SimpleInit) 477 SimpleInit->printPretty(Out, Context, 0, Policy, Indentation); 478 else { 479 for (unsigned I = 0; I != NumArgs; ++I) { 480 if (isa<CXXDefaultArgExpr>(Args[I])) 481 break; 482 483 if (I) 484 Out << ", "; 485 Args[I]->printPretty(Out, Context, 0, Policy, Indentation); 486 } 487 } 488 } 489 Out << ")"; 490 } 491 } 492 } 493 else 494 AFT->getResultType().getAsStringInternal(Proto, Policy); 495 } else { 496 Ty.getAsStringInternal(Proto, Policy); 497 } 498 499 Out << Proto; 500 501 if (D->isPure()) 502 Out << " = 0"; 503 else if (D->isDeleted()) 504 Out << " = delete"; 505 else if (D->isThisDeclarationADefinition()) { 506 if (!D->hasPrototype() && D->getNumParams()) { 507 // This is a K&R function definition, so we need to print the 508 // parameters. 509 Out << '\n'; 510 DeclPrinter ParamPrinter(Out, Context, SubPolicy, Indentation); 511 Indentation += Policy.Indentation; 512 for (unsigned i = 0, e = D->getNumParams(); i != e; ++i) { 513 Indent(); 514 ParamPrinter.VisitParmVarDecl(D->getParamDecl(i)); 515 Out << ";\n"; 516 } 517 Indentation -= Policy.Indentation; 518 } else 519 Out << ' '; 520 521 D->getBody()->printPretty(Out, Context, 0, SubPolicy, Indentation); 522 Out << '\n'; 523 } 524} 525 526void DeclPrinter::VisitFieldDecl(FieldDecl *D) { 527 if (!Policy.SuppressSpecifiers && D->isMutable()) 528 Out << "mutable "; 529 530 std::string Name = D->getNameAsString(); 531 D->getType().getAsStringInternal(Name, Policy); 532 Out << Name; 533 534 if (D->isBitField()) { 535 Out << " : "; 536 D->getBitWidth()->printPretty(Out, Context, 0, Policy, Indentation); 537 } 538} 539 540void DeclPrinter::VisitVarDecl(VarDecl *D) { 541 if (!Policy.SuppressSpecifiers && D->getStorageClass() != SC_None) 542 Out << VarDecl::getStorageClassSpecifierString(D->getStorageClass()) << " "; 543 544 if (!Policy.SuppressSpecifiers && D->isThreadSpecified()) 545 Out << "__thread "; 546 547 std::string Name = D->getNameAsString(); 548 QualType T = D->getType(); 549 if (ParmVarDecl *Parm = dyn_cast<ParmVarDecl>(D)) 550 T = Parm->getOriginalType(); 551 T.getAsStringInternal(Name, Policy); 552 Out << Name; 553 if (Expr *Init = D->getInit()) { 554 if (D->hasCXXDirectInitializer()) 555 Out << "("; 556 else { 557 CXXConstructExpr *CCE = dyn_cast<CXXConstructExpr>(Init); 558 if (!CCE || CCE->getConstructor()->isCopyConstructor()) 559 Out << " = "; 560 } 561 Init->printPretty(Out, Context, 0, Policy, Indentation); 562 if (D->hasCXXDirectInitializer()) 563 Out << ")"; 564 } 565} 566 567void DeclPrinter::VisitParmVarDecl(ParmVarDecl *D) { 568 VisitVarDecl(D); 569} 570 571void DeclPrinter::VisitFileScopeAsmDecl(FileScopeAsmDecl *D) { 572 Out << "__asm ("; 573 D->getAsmString()->printPretty(Out, Context, 0, Policy, Indentation); 574 Out << ")"; 575} 576 577//---------------------------------------------------------------------------- 578// C++ declarations 579//---------------------------------------------------------------------------- 580void DeclPrinter::VisitNamespaceDecl(NamespaceDecl *D) { 581 Out << "namespace " << D << " {\n"; 582 VisitDeclContext(D); 583 Indent() << "}"; 584} 585 586void DeclPrinter::VisitUsingDirectiveDecl(UsingDirectiveDecl *D) { 587 Out << "using namespace "; 588 if (D->getQualifier()) 589 D->getQualifier()->print(Out, Policy); 590 Out << D->getNominatedNamespaceAsWritten(); 591} 592 593void DeclPrinter::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) { 594 Out << "namespace " << D << " = "; 595 if (D->getQualifier()) 596 D->getQualifier()->print(Out, Policy); 597 Out << D->getAliasedNamespace(); 598} 599 600void DeclPrinter::VisitCXXRecordDecl(CXXRecordDecl *D) { 601 Out << D->getKindName(); 602 if (D->getIdentifier()) 603 Out << ' ' << D; 604 605 if (D->isDefinition()) { 606 // Print the base classes 607 if (D->getNumBases()) { 608 Out << " : "; 609 for (CXXRecordDecl::base_class_iterator Base = D->bases_begin(), 610 BaseEnd = D->bases_end(); Base != BaseEnd; ++Base) { 611 if (Base != D->bases_begin()) 612 Out << ", "; 613 614 if (Base->isVirtual()) 615 Out << "virtual "; 616 617 AccessSpecifier AS = Base->getAccessSpecifierAsWritten(); 618 if (AS != AS_none) 619 Print(AS); 620 Out << " " << Base->getType().getAsString(Policy); 621 } 622 } 623 624 // Print the class definition 625 // FIXME: Doesn't print access specifiers, e.g., "public:" 626 Out << " {\n"; 627 VisitDeclContext(D); 628 Indent() << "}"; 629 } 630} 631 632void DeclPrinter::VisitLinkageSpecDecl(LinkageSpecDecl *D) { 633 const char *l; 634 if (D->getLanguage() == LinkageSpecDecl::lang_c) 635 l = "C"; 636 else { 637 assert(D->getLanguage() == LinkageSpecDecl::lang_cxx && 638 "unknown language in linkage specification"); 639 l = "C++"; 640 } 641 642 Out << "extern \"" << l << "\" "; 643 if (D->hasBraces()) { 644 Out << "{\n"; 645 VisitDeclContext(D); 646 Indent() << "}"; 647 } else 648 Visit(*D->decls_begin()); 649} 650 651void DeclPrinter::VisitTemplateDecl(TemplateDecl *D) { 652 Out << "template <"; 653 654 TemplateParameterList *Params = D->getTemplateParameters(); 655 for (unsigned i = 0, e = Params->size(); i != e; ++i) { 656 if (i != 0) 657 Out << ", "; 658 659 const Decl *Param = Params->getParam(i); 660 if (const TemplateTypeParmDecl *TTP = 661 dyn_cast<TemplateTypeParmDecl>(Param)) { 662 663 QualType ParamType = 664 Context.getTypeDeclType(const_cast<TemplateTypeParmDecl*>(TTP)); 665 666 if (TTP->wasDeclaredWithTypename()) 667 Out << "typename "; 668 else 669 Out << "class "; 670 671 if (TTP->isParameterPack()) 672 Out << "... "; 673 674 Out << ParamType.getAsString(Policy); 675 676 if (TTP->hasDefaultArgument()) { 677 Out << " = "; 678 Out << TTP->getDefaultArgument().getAsString(Policy); 679 }; 680 } else if (const NonTypeTemplateParmDecl *NTTP = 681 dyn_cast<NonTypeTemplateParmDecl>(Param)) { 682 Out << NTTP->getType().getAsString(Policy); 683 684 if (IdentifierInfo *Name = NTTP->getIdentifier()) { 685 Out << ' '; 686 Out << Name->getName(); 687 } 688 689 if (NTTP->hasDefaultArgument()) { 690 Out << " = "; 691 NTTP->getDefaultArgument()->printPretty(Out, Context, 0, Policy, 692 Indentation); 693 } 694 } 695 } 696 697 Out << "> "; 698 699 if (isa<TemplateTemplateParmDecl>(D)) { 700 Out << "class " << D->getName(); 701 } else { 702 Visit(D->getTemplatedDecl()); 703 } 704} 705 706//---------------------------------------------------------------------------- 707// Objective-C declarations 708//---------------------------------------------------------------------------- 709 710void DeclPrinter::VisitObjCClassDecl(ObjCClassDecl *D) { 711 Out << "@class "; 712 for (ObjCClassDecl::iterator I = D->begin(), E = D->end(); 713 I != E; ++I) { 714 if (I != D->begin()) Out << ", "; 715 Out << I->getInterface(); 716 } 717} 718 719void DeclPrinter::VisitObjCMethodDecl(ObjCMethodDecl *OMD) { 720 if (OMD->isInstanceMethod()) 721 Out << "- "; 722 else 723 Out << "+ "; 724 if (!OMD->getResultType().isNull()) 725 Out << '(' << OMD->getResultType().getAsString(Policy) << ")"; 726 727 std::string name = OMD->getSelector().getAsString(); 728 std::string::size_type pos, lastPos = 0; 729 for (ObjCMethodDecl::param_iterator PI = OMD->param_begin(), 730 E = OMD->param_end(); PI != E; ++PI) { 731 // FIXME: selector is missing here! 732 pos = name.find_first_of(":", lastPos); 733 Out << " " << name.substr(lastPos, pos - lastPos); 734 Out << ":(" << (*PI)->getType().getAsString(Policy) << ')' << *PI; 735 lastPos = pos + 1; 736 } 737 738 if (OMD->param_begin() == OMD->param_end()) 739 Out << " " << name; 740 741 if (OMD->isVariadic()) 742 Out << ", ..."; 743 744 if (OMD->getBody()) { 745 Out << ' '; 746 OMD->getBody()->printPretty(Out, Context, 0, Policy); 747 Out << '\n'; 748 } 749} 750 751void DeclPrinter::VisitObjCImplementationDecl(ObjCImplementationDecl *OID) { 752 std::string I = OID->getNameAsString(); 753 ObjCInterfaceDecl *SID = OID->getSuperClass(); 754 755 if (SID) 756 Out << "@implementation " << I << " : " << SID; 757 else 758 Out << "@implementation " << I; 759 Out << "\n"; 760 VisitDeclContext(OID, false); 761 Out << "@end"; 762} 763 764void DeclPrinter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *OID) { 765 std::string I = OID->getNameAsString(); 766 ObjCInterfaceDecl *SID = OID->getSuperClass(); 767 768 if (SID) 769 Out << "@interface " << I << " : " << SID; 770 else 771 Out << "@interface " << I; 772 773 // Protocols? 774 const ObjCList<ObjCProtocolDecl> &Protocols = OID->getReferencedProtocols(); 775 if (!Protocols.empty()) { 776 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(), 777 E = Protocols.end(); I != E; ++I) 778 Out << (I == Protocols.begin() ? '<' : ',') << *I; 779 } 780 781 if (!Protocols.empty()) 782 Out << "> "; 783 784 if (OID->ivar_size() > 0) { 785 Out << "{\n"; 786 Indentation += Policy.Indentation; 787 for (ObjCInterfaceDecl::ivar_iterator I = OID->ivar_begin(), 788 E = OID->ivar_end(); I != E; ++I) { 789 Indent() << (*I)->getType().getAsString(Policy) << ' ' << *I << ";\n"; 790 } 791 Indentation -= Policy.Indentation; 792 Out << "}\n"; 793 } 794 795 VisitDeclContext(OID, false); 796 Out << "@end"; 797 // FIXME: implement the rest... 798} 799 800void DeclPrinter::VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *D) { 801 Out << "@protocol "; 802 for (ObjCForwardProtocolDecl::protocol_iterator I = D->protocol_begin(), 803 E = D->protocol_end(); 804 I != E; ++I) { 805 if (I != D->protocol_begin()) Out << ", "; 806 Out << *I; 807 } 808} 809 810void DeclPrinter::VisitObjCProtocolDecl(ObjCProtocolDecl *PID) { 811 Out << "@protocol " << PID << '\n'; 812 VisitDeclContext(PID, false); 813 Out << "@end"; 814} 815 816void DeclPrinter::VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *PID) { 817 Out << "@implementation " << PID->getClassInterface() << '(' << PID << ")\n"; 818 819 VisitDeclContext(PID, false); 820 Out << "@end"; 821 // FIXME: implement the rest... 822} 823 824void DeclPrinter::VisitObjCCategoryDecl(ObjCCategoryDecl *PID) { 825 Out << "@interface " << PID->getClassInterface() << '(' << PID << ")\n"; 826 VisitDeclContext(PID, false); 827 Out << "@end"; 828 829 // FIXME: implement the rest... 830} 831 832void DeclPrinter::VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *AID) { 833 Out << "@compatibility_alias " << AID 834 << ' ' << AID->getClassInterface() << ";\n"; 835} 836 837/// PrintObjCPropertyDecl - print a property declaration. 838/// 839void DeclPrinter::VisitObjCPropertyDecl(ObjCPropertyDecl *PDecl) { 840 if (PDecl->getPropertyImplementation() == ObjCPropertyDecl::Required) 841 Out << "@required\n"; 842 else if (PDecl->getPropertyImplementation() == ObjCPropertyDecl::Optional) 843 Out << "@optional\n"; 844 845 Out << "@property"; 846 if (PDecl->getPropertyAttributes() != ObjCPropertyDecl::OBJC_PR_noattr) { 847 bool first = true; 848 Out << " ("; 849 if (PDecl->getPropertyAttributes() & 850 ObjCPropertyDecl::OBJC_PR_readonly) { 851 Out << (first ? ' ' : ',') << "readonly"; 852 first = false; 853 } 854 855 if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_getter) { 856 Out << (first ? ' ' : ',') << "getter = " 857 << PDecl->getGetterName().getAsString(); 858 first = false; 859 } 860 if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_setter) { 861 Out << (first ? ' ' : ',') << "setter = " 862 << PDecl->getSetterName().getAsString(); 863 first = false; 864 } 865 866 if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_assign) { 867 Out << (first ? ' ' : ',') << "assign"; 868 first = false; 869 } 870 871 if (PDecl->getPropertyAttributes() & 872 ObjCPropertyDecl::OBJC_PR_readwrite) { 873 Out << (first ? ' ' : ',') << "readwrite"; 874 first = false; 875 } 876 877 if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_retain) { 878 Out << (first ? ' ' : ',') << "retain"; 879 first = false; 880 } 881 882 if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_copy) { 883 Out << (first ? ' ' : ',') << "copy"; 884 first = false; 885 } 886 887 if (PDecl->getPropertyAttributes() & 888 ObjCPropertyDecl::OBJC_PR_nonatomic) { 889 Out << (first ? ' ' : ',') << "nonatomic"; 890 first = false; 891 } 892 Out << " )"; 893 } 894 Out << ' ' << PDecl->getType().getAsString(Policy) << ' ' << PDecl; 895} 896 897void DeclPrinter::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *PID) { 898 if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize) 899 Out << "@synthesize "; 900 else 901 Out << "@dynamic "; 902 Out << PID->getPropertyDecl(); 903 if (PID->getPropertyIvarDecl()) 904 Out << '=' << PID->getPropertyIvarDecl(); 905} 906 907void DeclPrinter::VisitUsingDecl(UsingDecl *D) { 908 Out << "using "; 909 D->getTargetNestedNameDecl()->print(Out, Policy); 910 Out << D; 911} 912 913void 914DeclPrinter::VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D) { 915 Out << "using typename "; 916 D->getTargetNestedNameSpecifier()->print(Out, Policy); 917 Out << D->getDeclName(); 918} 919 920void DeclPrinter::VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D) { 921 Out << "using "; 922 D->getTargetNestedNameSpecifier()->print(Out, Policy); 923 Out << D->getDeclName(); 924} 925 926void DeclPrinter::VisitUsingShadowDecl(UsingShadowDecl *D) { 927 // ignore 928} 929