DeclPrinter.cpp revision a88cefd266c428be33cc06f7e8b00ff8fc97c1ff
1//===--- DeclPrinter.cpp - Printing implementation for Decl ASTs ----------===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// 10// This file implements the Decl::dump method, which pretty print the 11// AST back out to C/Objective-C/C++/Objective-C++ code. 12// 13//===----------------------------------------------------------------------===// 14#include "clang/AST/ASTContext.h" 15#include "clang/AST/DeclVisitor.h" 16#include "clang/AST/Decl.h" 17#include "clang/AST/DeclCXX.h" 18#include "clang/AST/DeclObjC.h" 19#include "clang/AST/Expr.h" 20#include "clang/AST/ExprCXX.h" 21#include "clang/AST/PrettyPrinter.h" 22#include "llvm/Support/raw_ostream.h" 23using namespace clang; 24 25namespace { 26 class DeclPrinter : public DeclVisitor<DeclPrinter> { 27 llvm::raw_ostream &Out; 28 ASTContext &Context; 29 PrintingPolicy Policy; 30 unsigned Indentation; 31 32 llvm::raw_ostream& Indent() { return Indent(Indentation); } 33 llvm::raw_ostream& Indent(unsigned Indentation); 34 void ProcessDeclGroup(llvm::SmallVectorImpl<Decl*>& Decls); 35 36 void Print(AccessSpecifier AS); 37 38 public: 39 DeclPrinter(llvm::raw_ostream &Out, ASTContext &Context, 40 const PrintingPolicy &Policy, 41 unsigned Indentation = 0) 42 : Out(Out), Context(Context), Policy(Policy), Indentation(Indentation) { } 43 44 void VisitDeclContext(DeclContext *DC, bool Indent = true); 45 46 void VisitTranslationUnitDecl(TranslationUnitDecl *D); 47 void VisitTypedefDecl(TypedefDecl *D); 48 void VisitEnumDecl(EnumDecl *D); 49 void VisitRecordDecl(RecordDecl *D); 50 void VisitEnumConstantDecl(EnumConstantDecl *D); 51 void VisitFunctionDecl(FunctionDecl *D); 52 void VisitFieldDecl(FieldDecl *D); 53 void VisitVarDecl(VarDecl *D); 54 void VisitParmVarDecl(ParmVarDecl *D); 55 void VisitFileScopeAsmDecl(FileScopeAsmDecl *D); 56 void VisitNamespaceDecl(NamespaceDecl *D); 57 void VisitUsingDirectiveDecl(UsingDirectiveDecl *D); 58 void VisitNamespaceAliasDecl(NamespaceAliasDecl *D); 59 void VisitCXXRecordDecl(CXXRecordDecl *D); 60 void VisitLinkageSpecDecl(LinkageSpecDecl *D); 61 void VisitTemplateDecl(TemplateDecl *D); 62 void VisitObjCMethodDecl(ObjCMethodDecl *D); 63 void VisitObjCClassDecl(ObjCClassDecl *D); 64 void VisitObjCImplementationDecl(ObjCImplementationDecl *D); 65 void VisitObjCInterfaceDecl(ObjCInterfaceDecl *D); 66 void VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *D); 67 void VisitObjCProtocolDecl(ObjCProtocolDecl *D); 68 void VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D); 69 void VisitObjCCategoryDecl(ObjCCategoryDecl *D); 70 void VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *D); 71 void VisitObjCPropertyDecl(ObjCPropertyDecl *D); 72 void VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D); 73 void VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D); 74 void VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D); 75 void VisitUsingDecl(UsingDecl *D); 76 void VisitUsingShadowDecl(UsingShadowDecl *D); 77 }; 78} 79 80void Decl::print(llvm::raw_ostream &Out, unsigned Indentation) const { 81 print(Out, getASTContext().PrintingPolicy, Indentation); 82} 83 84void Decl::print(llvm::raw_ostream &Out, const PrintingPolicy &Policy, 85 unsigned Indentation) const { 86 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 if (isa<FunctionType>(D->getType().getTypePtr())) { 370 const FunctionType *AFT = D->getType()->getAs<FunctionType>(); 371 372 const FunctionProtoType *FT = 0; 373 if (D->hasWrittenPrototype()) 374 FT = dyn_cast<FunctionProtoType>(AFT); 375 376 Proto += "("; 377 if (FT) { 378 llvm::raw_string_ostream POut(Proto); 379 DeclPrinter ParamPrinter(POut, Context, SubPolicy, Indentation); 380 for (unsigned i = 0, e = D->getNumParams(); i != e; ++i) { 381 if (i) POut << ", "; 382 ParamPrinter.VisitParmVarDecl(D->getParamDecl(i)); 383 } 384 385 if (FT->isVariadic()) { 386 if (D->getNumParams()) POut << ", "; 387 POut << "..."; 388 } 389 } else if (D->isThisDeclarationADefinition() && !D->hasPrototype()) { 390 for (unsigned i = 0, e = D->getNumParams(); i != e; ++i) { 391 if (i) 392 Proto += ", "; 393 Proto += D->getParamDecl(i)->getNameAsString(); 394 } 395 } 396 397 Proto += ")"; 398 399 if (FT && FT->getTypeQuals()) { 400 unsigned TypeQuals = FT->getTypeQuals(); 401 if (TypeQuals & Qualifiers::Const) 402 Proto += " const"; 403 if (TypeQuals & Qualifiers::Volatile) 404 Proto += " volatile"; 405 if (TypeQuals & Qualifiers::Restrict) 406 Proto += " restrict"; 407 } 408 409 if (FT && FT->hasExceptionSpec()) { 410 Proto += " throw("; 411 if (FT->hasAnyExceptionSpec()) 412 Proto += "..."; 413 else 414 for (unsigned I = 0, N = FT->getNumExceptions(); I != N; ++I) { 415 if (I) 416 Proto += ", "; 417 418 419 std::string ExceptionType; 420 FT->getExceptionType(I).getAsStringInternal(ExceptionType, SubPolicy); 421 Proto += ExceptionType; 422 } 423 Proto += ")"; 424 } 425 426 if (D->hasAttr<NoReturnAttr>()) 427 Proto += " __attribute((noreturn))"; 428 if (CXXConstructorDecl *CDecl = dyn_cast<CXXConstructorDecl>(D)) { 429 if (CDecl->getNumBaseOrMemberInitializers() > 0) { 430 Proto += " : "; 431 Out << Proto; 432 Proto.clear(); 433 for (CXXConstructorDecl::init_const_iterator B = CDecl->init_begin(), 434 E = CDecl->init_end(); 435 B != E; ++B) { 436 CXXBaseOrMemberInitializer * BMInitializer = (*B); 437 if (B != CDecl->init_begin()) 438 Out << ", "; 439 if (BMInitializer->isMemberInitializer()) { 440 FieldDecl *FD = BMInitializer->getMember(); 441 Out << FD; 442 } else { 443 Out << QualType(BMInitializer->getBaseClass(), 444 0).getAsString(Policy); 445 } 446 447 Out << "("; 448 if (!BMInitializer->getInit()) { 449 // Nothing to print 450 } else { 451 Expr *Init = BMInitializer->getInit(); 452 if (CXXExprWithTemporaries *Tmp 453 = dyn_cast<CXXExprWithTemporaries>(Init)) 454 Init = Tmp->getSubExpr(); 455 456 Init = Init->IgnoreParens(); 457 458 Expr *SimpleInit = 0; 459 Expr **Args = 0; 460 unsigned NumArgs = 0; 461 if (ParenListExpr *ParenList = dyn_cast<ParenListExpr>(Init)) { 462 Args = ParenList->getExprs(); 463 NumArgs = ParenList->getNumExprs(); 464 } else if (CXXConstructExpr *Construct 465 = dyn_cast<CXXConstructExpr>(Init)) { 466 Args = Construct->getArgs(); 467 NumArgs = Construct->getNumArgs(); 468 } else 469 SimpleInit = Init; 470 471 if (SimpleInit) 472 SimpleInit->printPretty(Out, Context, 0, Policy, Indentation); 473 else { 474 for (unsigned I = 0; I != NumArgs; ++I) { 475 if (isa<CXXDefaultArgExpr>(Args[I])) 476 break; 477 478 if (I) 479 Out << ", "; 480 Args[I]->printPretty(Out, Context, 0, Policy, Indentation); 481 } 482 } 483 } 484 Out << ")"; 485 } 486 } 487 } 488 else 489 AFT->getResultType().getAsStringInternal(Proto, Policy); 490 } else { 491 D->getType().getAsStringInternal(Proto, Policy); 492 } 493 494 Out << Proto; 495 496 if (D->isPure()) 497 Out << " = 0"; 498 else if (D->isDeleted()) 499 Out << " = delete"; 500 else if (D->isThisDeclarationADefinition()) { 501 if (!D->hasPrototype() && D->getNumParams()) { 502 // This is a K&R function definition, so we need to print the 503 // parameters. 504 Out << '\n'; 505 DeclPrinter ParamPrinter(Out, Context, SubPolicy, Indentation); 506 Indentation += Policy.Indentation; 507 for (unsigned i = 0, e = D->getNumParams(); i != e; ++i) { 508 Indent(); 509 ParamPrinter.VisitParmVarDecl(D->getParamDecl(i)); 510 Out << ";\n"; 511 } 512 Indentation -= Policy.Indentation; 513 } else 514 Out << ' '; 515 516 D->getBody()->printPretty(Out, Context, 0, SubPolicy, Indentation); 517 Out << '\n'; 518 } 519} 520 521void DeclPrinter::VisitFieldDecl(FieldDecl *D) { 522 if (!Policy.SuppressSpecifiers && D->isMutable()) 523 Out << "mutable "; 524 525 std::string Name = D->getNameAsString(); 526 D->getType().getAsStringInternal(Name, Policy); 527 Out << Name; 528 529 if (D->isBitField()) { 530 Out << " : "; 531 D->getBitWidth()->printPretty(Out, Context, 0, Policy, Indentation); 532 } 533} 534 535void DeclPrinter::VisitVarDecl(VarDecl *D) { 536 if (!Policy.SuppressSpecifiers && D->getStorageClass() != SC_None) 537 Out << VarDecl::getStorageClassSpecifierString(D->getStorageClass()) << " "; 538 539 if (!Policy.SuppressSpecifiers && D->isThreadSpecified()) 540 Out << "__thread "; 541 542 std::string Name = D->getNameAsString(); 543 QualType T = D->getType(); 544 if (ParmVarDecl *Parm = dyn_cast<ParmVarDecl>(D)) 545 T = Parm->getOriginalType(); 546 T.getAsStringInternal(Name, Policy); 547 Out << Name; 548 if (Expr *Init = D->getInit()) { 549 if (D->hasCXXDirectInitializer()) 550 Out << "("; 551 else { 552 CXXConstructExpr *CCE = dyn_cast<CXXConstructExpr>(Init); 553 if (!CCE || CCE->getConstructor()->isCopyConstructor()) 554 Out << " = "; 555 } 556 Init->printPretty(Out, Context, 0, Policy, Indentation); 557 if (D->hasCXXDirectInitializer()) 558 Out << ")"; 559 } 560} 561 562void DeclPrinter::VisitParmVarDecl(ParmVarDecl *D) { 563 VisitVarDecl(D); 564} 565 566void DeclPrinter::VisitFileScopeAsmDecl(FileScopeAsmDecl *D) { 567 Out << "__asm ("; 568 D->getAsmString()->printPretty(Out, Context, 0, Policy, Indentation); 569 Out << ")"; 570} 571 572//---------------------------------------------------------------------------- 573// C++ declarations 574//---------------------------------------------------------------------------- 575void DeclPrinter::VisitNamespaceDecl(NamespaceDecl *D) { 576 Out << "namespace " << D << " {\n"; 577 VisitDeclContext(D); 578 Indent() << "}"; 579} 580 581void DeclPrinter::VisitUsingDirectiveDecl(UsingDirectiveDecl *D) { 582 Out << "using namespace "; 583 if (D->getQualifier()) 584 D->getQualifier()->print(Out, Policy); 585 Out << D->getNominatedNamespaceAsWritten(); 586} 587 588void DeclPrinter::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) { 589 Out << "namespace " << D << " = "; 590 if (D->getQualifier()) 591 D->getQualifier()->print(Out, Policy); 592 Out << D->getAliasedNamespace(); 593} 594 595void DeclPrinter::VisitCXXRecordDecl(CXXRecordDecl *D) { 596 Out << D->getKindName(); 597 if (D->getIdentifier()) 598 Out << ' ' << D; 599 600 if (D->isDefinition()) { 601 // Print the base classes 602 if (D->getNumBases()) { 603 Out << " : "; 604 for (CXXRecordDecl::base_class_iterator Base = D->bases_begin(), 605 BaseEnd = D->bases_end(); Base != BaseEnd; ++Base) { 606 if (Base != D->bases_begin()) 607 Out << ", "; 608 609 if (Base->isVirtual()) 610 Out << "virtual "; 611 612 AccessSpecifier AS = Base->getAccessSpecifierAsWritten(); 613 if (AS != AS_none) 614 Print(AS); 615 Out << " " << Base->getType().getAsString(Policy); 616 } 617 } 618 619 // Print the class definition 620 // FIXME: Doesn't print access specifiers, e.g., "public:" 621 Out << " {\n"; 622 VisitDeclContext(D); 623 Indent() << "}"; 624 } 625} 626 627void DeclPrinter::VisitLinkageSpecDecl(LinkageSpecDecl *D) { 628 const char *l; 629 if (D->getLanguage() == LinkageSpecDecl::lang_c) 630 l = "C"; 631 else { 632 assert(D->getLanguage() == LinkageSpecDecl::lang_cxx && 633 "unknown language in linkage specification"); 634 l = "C++"; 635 } 636 637 Out << "extern \"" << l << "\" "; 638 if (D->hasBraces()) { 639 Out << "{\n"; 640 VisitDeclContext(D); 641 Indent() << "}"; 642 } else 643 Visit(*D->decls_begin()); 644} 645 646void DeclPrinter::VisitTemplateDecl(TemplateDecl *D) { 647 Out << "template <"; 648 649 TemplateParameterList *Params = D->getTemplateParameters(); 650 for (unsigned i = 0, e = Params->size(); i != e; ++i) { 651 if (i != 0) 652 Out << ", "; 653 654 const Decl *Param = Params->getParam(i); 655 if (const TemplateTypeParmDecl *TTP = 656 dyn_cast<TemplateTypeParmDecl>(Param)) { 657 658 QualType ParamType = 659 Context.getTypeDeclType(const_cast<TemplateTypeParmDecl*>(TTP)); 660 661 if (TTP->wasDeclaredWithTypename()) 662 Out << "typename "; 663 else 664 Out << "class "; 665 666 if (TTP->isParameterPack()) 667 Out << "... "; 668 669 Out << ParamType.getAsString(Policy); 670 671 if (TTP->hasDefaultArgument()) { 672 Out << " = "; 673 Out << TTP->getDefaultArgument().getAsString(Policy); 674 }; 675 } else if (const NonTypeTemplateParmDecl *NTTP = 676 dyn_cast<NonTypeTemplateParmDecl>(Param)) { 677 Out << NTTP->getType().getAsString(Policy); 678 679 if (IdentifierInfo *Name = NTTP->getIdentifier()) { 680 Out << ' '; 681 Out << Name->getName(); 682 } 683 684 if (NTTP->hasDefaultArgument()) { 685 Out << " = "; 686 NTTP->getDefaultArgument()->printPretty(Out, Context, 0, Policy, 687 Indentation); 688 } 689 } 690 } 691 692 Out << "> "; 693 694 if (isa<TemplateTemplateParmDecl>(D)) { 695 Out << "class " << D->getName(); 696 } else { 697 Visit(D->getTemplatedDecl()); 698 } 699} 700 701//---------------------------------------------------------------------------- 702// Objective-C declarations 703//---------------------------------------------------------------------------- 704 705void DeclPrinter::VisitObjCClassDecl(ObjCClassDecl *D) { 706 Out << "@class "; 707 for (ObjCClassDecl::iterator I = D->begin(), E = D->end(); 708 I != E; ++I) { 709 if (I != D->begin()) Out << ", "; 710 Out << I->getInterface(); 711 } 712} 713 714void DeclPrinter::VisitObjCMethodDecl(ObjCMethodDecl *OMD) { 715 if (OMD->isInstanceMethod()) 716 Out << "- "; 717 else 718 Out << "+ "; 719 if (!OMD->getResultType().isNull()) 720 Out << '(' << OMD->getResultType().getAsString(Policy) << ")"; 721 722 std::string name = OMD->getSelector().getAsString(); 723 std::string::size_type pos, lastPos = 0; 724 for (ObjCMethodDecl::param_iterator PI = OMD->param_begin(), 725 E = OMD->param_end(); PI != E; ++PI) { 726 // FIXME: selector is missing here! 727 pos = name.find_first_of(":", lastPos); 728 Out << " " << name.substr(lastPos, pos - lastPos); 729 Out << ":(" << (*PI)->getType().getAsString(Policy) << ')' << *PI; 730 lastPos = pos + 1; 731 } 732 733 if (OMD->param_begin() == OMD->param_end()) 734 Out << " " << name; 735 736 if (OMD->isVariadic()) 737 Out << ", ..."; 738 739 if (OMD->getBody()) { 740 Out << ' '; 741 OMD->getBody()->printPretty(Out, Context, 0, Policy); 742 Out << '\n'; 743 } 744} 745 746void DeclPrinter::VisitObjCImplementationDecl(ObjCImplementationDecl *OID) { 747 std::string I = OID->getNameAsString(); 748 ObjCInterfaceDecl *SID = OID->getSuperClass(); 749 750 if (SID) 751 Out << "@implementation " << I << " : " << SID; 752 else 753 Out << "@implementation " << I; 754 Out << "\n"; 755 VisitDeclContext(OID, false); 756 Out << "@end"; 757} 758 759void DeclPrinter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *OID) { 760 std::string I = OID->getNameAsString(); 761 ObjCInterfaceDecl *SID = OID->getSuperClass(); 762 763 if (SID) 764 Out << "@interface " << I << " : " << SID; 765 else 766 Out << "@interface " << I; 767 768 // Protocols? 769 const ObjCList<ObjCProtocolDecl> &Protocols = OID->getReferencedProtocols(); 770 if (!Protocols.empty()) { 771 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(), 772 E = Protocols.end(); I != E; ++I) 773 Out << (I == Protocols.begin() ? '<' : ',') << *I; 774 } 775 776 if (!Protocols.empty()) 777 Out << "> "; 778 779 if (OID->ivar_size() > 0) { 780 Out << "{\n"; 781 Indentation += Policy.Indentation; 782 for (ObjCInterfaceDecl::ivar_iterator I = OID->ivar_begin(), 783 E = OID->ivar_end(); I != E; ++I) { 784 Indent() << (*I)->getType().getAsString(Policy) << ' ' << *I << ";\n"; 785 } 786 Indentation -= Policy.Indentation; 787 Out << "}\n"; 788 } 789 790 VisitDeclContext(OID, false); 791 Out << "@end"; 792 // FIXME: implement the rest... 793} 794 795void DeclPrinter::VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *D) { 796 Out << "@protocol "; 797 for (ObjCForwardProtocolDecl::protocol_iterator I = D->protocol_begin(), 798 E = D->protocol_end(); 799 I != E; ++I) { 800 if (I != D->protocol_begin()) Out << ", "; 801 Out << *I; 802 } 803} 804 805void DeclPrinter::VisitObjCProtocolDecl(ObjCProtocolDecl *PID) { 806 Out << "@protocol " << PID << '\n'; 807 VisitDeclContext(PID, false); 808 Out << "@end"; 809} 810 811void DeclPrinter::VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *PID) { 812 Out << "@implementation " << PID->getClassInterface() << '(' << PID << ")\n"; 813 814 VisitDeclContext(PID, false); 815 Out << "@end"; 816 // FIXME: implement the rest... 817} 818 819void DeclPrinter::VisitObjCCategoryDecl(ObjCCategoryDecl *PID) { 820 Out << "@interface " << PID->getClassInterface() << '(' << PID << ")\n"; 821 VisitDeclContext(PID, false); 822 Out << "@end"; 823 824 // FIXME: implement the rest... 825} 826 827void DeclPrinter::VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *AID) { 828 Out << "@compatibility_alias " << AID 829 << ' ' << AID->getClassInterface() << ";\n"; 830} 831 832/// PrintObjCPropertyDecl - print a property declaration. 833/// 834void DeclPrinter::VisitObjCPropertyDecl(ObjCPropertyDecl *PDecl) { 835 if (PDecl->getPropertyImplementation() == ObjCPropertyDecl::Required) 836 Out << "@required\n"; 837 else if (PDecl->getPropertyImplementation() == ObjCPropertyDecl::Optional) 838 Out << "@optional\n"; 839 840 Out << "@property"; 841 if (PDecl->getPropertyAttributes() != ObjCPropertyDecl::OBJC_PR_noattr) { 842 bool first = true; 843 Out << " ("; 844 if (PDecl->getPropertyAttributes() & 845 ObjCPropertyDecl::OBJC_PR_readonly) { 846 Out << (first ? ' ' : ',') << "readonly"; 847 first = false; 848 } 849 850 if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_getter) { 851 Out << (first ? ' ' : ',') << "getter = " 852 << PDecl->getGetterName().getAsString(); 853 first = false; 854 } 855 if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_setter) { 856 Out << (first ? ' ' : ',') << "setter = " 857 << PDecl->getSetterName().getAsString(); 858 first = false; 859 } 860 861 if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_assign) { 862 Out << (first ? ' ' : ',') << "assign"; 863 first = false; 864 } 865 866 if (PDecl->getPropertyAttributes() & 867 ObjCPropertyDecl::OBJC_PR_readwrite) { 868 Out << (first ? ' ' : ',') << "readwrite"; 869 first = false; 870 } 871 872 if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_retain) { 873 Out << (first ? ' ' : ',') << "retain"; 874 first = false; 875 } 876 877 if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_copy) { 878 Out << (first ? ' ' : ',') << "copy"; 879 first = false; 880 } 881 882 if (PDecl->getPropertyAttributes() & 883 ObjCPropertyDecl::OBJC_PR_nonatomic) { 884 Out << (first ? ' ' : ',') << "nonatomic"; 885 first = false; 886 } 887 Out << " )"; 888 } 889 Out << ' ' << PDecl->getType().getAsString(Policy) << ' ' << PDecl; 890} 891 892void DeclPrinter::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *PID) { 893 if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize) 894 Out << "@synthesize "; 895 else 896 Out << "@dynamic "; 897 Out << PID->getPropertyDecl(); 898 if (PID->getPropertyIvarDecl()) 899 Out << '=' << PID->getPropertyIvarDecl(); 900} 901 902void DeclPrinter::VisitUsingDecl(UsingDecl *D) { 903 Out << "using "; 904 D->getTargetNestedNameDecl()->print(Out, Policy); 905 Out << D; 906} 907 908void 909DeclPrinter::VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D) { 910 Out << "using typename "; 911 D->getTargetNestedNameSpecifier()->print(Out, Policy); 912 Out << D->getDeclName(); 913} 914 915void DeclPrinter::VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D) { 916 Out << "using "; 917 D->getTargetNestedNameSpecifier()->print(Out, Policy); 918 Out << D->getDeclName(); 919} 920 921void DeclPrinter::VisitUsingShadowDecl(UsingShadowDecl *D) { 922 // ignore 923} 924