DeclPrinter.cpp revision 198092
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/PrettyPrinter.h" 21#include "llvm/Support/Compiler.h" 22#include "llvm/Support/Format.h" 23#include "llvm/Support/raw_ostream.h" 24using namespace clang; 25 26namespace { 27 class VISIBILITY_HIDDEN DeclPrinter : public DeclVisitor<DeclPrinter> { 28 llvm::raw_ostream &Out; 29 ASTContext &Context; 30 PrintingPolicy Policy; 31 unsigned Indentation; 32 33 llvm::raw_ostream& Indent(); 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 VisitOriginalParmVarDecl(OriginalParmVarDecl *D); 56 void VisitFileScopeAsmDecl(FileScopeAsmDecl *D); 57 void VisitOverloadedFunctionDecl(OverloadedFunctionDecl *D); 58 void VisitNamespaceDecl(NamespaceDecl *D); 59 void VisitUsingDirectiveDecl(UsingDirectiveDecl *D); 60 void VisitNamespaceAliasDecl(NamespaceAliasDecl *D); 61 void VisitCXXRecordDecl(CXXRecordDecl *D); 62 void VisitLinkageSpecDecl(LinkageSpecDecl *D); 63 void VisitTemplateDecl(TemplateDecl *D); 64 void VisitObjCMethodDecl(ObjCMethodDecl *D); 65 void VisitObjCClassDecl(ObjCClassDecl *D); 66 void VisitObjCImplementationDecl(ObjCImplementationDecl *D); 67 void VisitObjCInterfaceDecl(ObjCInterfaceDecl *D); 68 void VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *D); 69 void VisitObjCProtocolDecl(ObjCProtocolDecl *D); 70 void VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D); 71 void VisitObjCCategoryDecl(ObjCCategoryDecl *D); 72 void VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *D); 73 void VisitObjCPropertyDecl(ObjCPropertyDecl *D); 74 void VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D); 75 void VisitUnresolvedUsingDecl(UnresolvedUsingDecl *D); 76 void VisitUsingDecl(UsingDecl *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 Decl::dump() const { 153 print(llvm::errs()); 154} 155 156llvm::raw_ostream& DeclPrinter::Indent() { 157 for (unsigned i = 0; i < Indentation; ++i) 158 Out << " "; 159 return Out; 160} 161 162void DeclPrinter::ProcessDeclGroup(llvm::SmallVectorImpl<Decl*>& Decls) { 163 this->Indent(); 164 Decl::printGroup(Decls.data(), Decls.size(), Out, Policy, Indentation); 165 Out << ";\n"; 166 Decls.clear(); 167 168} 169 170void DeclPrinter::Print(AccessSpecifier AS) { 171 switch(AS) { 172 case AS_none: assert(0 && "No access specifier!"); break; 173 case AS_public: Out << "public"; break; 174 case AS_protected: Out << "protected"; break; 175 case AS_private: Out << " private"; break; 176 } 177} 178 179//---------------------------------------------------------------------------- 180// Common C declarations 181//---------------------------------------------------------------------------- 182 183void DeclPrinter::VisitDeclContext(DeclContext *DC, bool Indent) { 184 if (Indent) 185 Indentation += Policy.Indentation; 186 187 bool PrintAccess = isa<CXXRecordDecl>(DC); 188 AccessSpecifier CurAS = AS_none; 189 190 llvm::SmallVector<Decl*, 2> Decls; 191 for (DeclContext::decl_iterator D = DC->decls_begin(), DEnd = DC->decls_end(); 192 D != DEnd; ++D) { 193 if (!Policy.Dump) { 194 // Skip over implicit declarations in pretty-printing mode. 195 if (D->isImplicit()) continue; 196 // FIXME: Ugly hack so we don't pretty-print the builtin declaration 197 // of __builtin_va_list. There should be some other way to check that. 198 if (isa<NamedDecl>(*D) && cast<NamedDecl>(*D)->getNameAsString() == 199 "__builtin_va_list") 200 continue; 201 } 202 203 if (PrintAccess) { 204 AccessSpecifier AS = D->getAccess(); 205 206 if (AS != CurAS) { 207 Print(AS); 208 Out << ":\n"; 209 CurAS = AS; 210 } 211 } 212 213 // The next bits of code handles stuff like "struct {int x;} a,b"; we're 214 // forced to merge the declarations because there's no other way to 215 // refer to the struct in question. This limited merging is safe without 216 // a bunch of other checks because it only merges declarations directly 217 // referring to the tag, not typedefs. 218 // 219 // Check whether the current declaration should be grouped with a previous 220 // unnamed struct. 221 QualType CurDeclType = getDeclType(*D); 222 if (!Decls.empty() && !CurDeclType.isNull()) { 223 QualType BaseType = GetBaseType(CurDeclType); 224 if (!BaseType.isNull() && isa<TagType>(BaseType) && 225 cast<TagType>(BaseType)->getDecl() == Decls[0]) { 226 Decls.push_back(*D); 227 continue; 228 } 229 } 230 231 // If we have a merged group waiting to be handled, handle it now. 232 if (!Decls.empty()) 233 ProcessDeclGroup(Decls); 234 235 // If the current declaration is an unnamed tag type, save it 236 // so we can merge it with the subsequent declaration(s) using it. 237 if (isa<TagDecl>(*D) && !cast<TagDecl>(*D)->getIdentifier()) { 238 Decls.push_back(*D); 239 continue; 240 } 241 this->Indent(); 242 Visit(*D); 243 244 // FIXME: Need to be able to tell the DeclPrinter when 245 const char *Terminator = 0; 246 if (isa<FunctionDecl>(*D) && 247 cast<FunctionDecl>(*D)->isThisDeclarationADefinition()) 248 Terminator = 0; 249 else if (isa<ObjCMethodDecl>(*D) && cast<ObjCMethodDecl>(*D)->getBody()) 250 Terminator = 0; 251 else if (isa<NamespaceDecl>(*D) || isa<LinkageSpecDecl>(*D) || 252 isa<ObjCImplementationDecl>(*D) || 253 isa<ObjCInterfaceDecl>(*D) || 254 isa<ObjCProtocolDecl>(*D) || 255 isa<ObjCCategoryImplDecl>(*D) || 256 isa<ObjCCategoryDecl>(*D)) 257 Terminator = 0; 258 else if (isa<EnumConstantDecl>(*D)) { 259 DeclContext::decl_iterator Next = D; 260 ++Next; 261 if (Next != DEnd) 262 Terminator = ","; 263 } else 264 Terminator = ";"; 265 266 if (Terminator) 267 Out << Terminator; 268 Out << "\n"; 269 } 270 271 if (!Decls.empty()) 272 ProcessDeclGroup(Decls); 273 274 if (Indent) 275 Indentation -= Policy.Indentation; 276} 277 278void DeclPrinter::VisitTranslationUnitDecl(TranslationUnitDecl *D) { 279 VisitDeclContext(D, false); 280} 281 282void DeclPrinter::VisitTypedefDecl(TypedefDecl *D) { 283 std::string S = D->getNameAsString(); 284 D->getUnderlyingType().getAsStringInternal(S, Policy); 285 if (!Policy.SuppressSpecifiers) 286 Out << "typedef "; 287 Out << S; 288} 289 290void DeclPrinter::VisitEnumDecl(EnumDecl *D) { 291 Out << "enum " << D->getNameAsString() << " {\n"; 292 VisitDeclContext(D); 293 Indent() << "}"; 294} 295 296void DeclPrinter::VisitRecordDecl(RecordDecl *D) { 297 Out << D->getKindName(); 298 if (D->getIdentifier()) { 299 Out << " "; 300 Out << D->getNameAsString(); 301 } 302 303 if (D->isDefinition()) { 304 Out << " {\n"; 305 VisitDeclContext(D); 306 Indent() << "}"; 307 } 308} 309 310void DeclPrinter::VisitEnumConstantDecl(EnumConstantDecl *D) { 311 Out << D->getNameAsString(); 312 if (Expr *Init = D->getInitExpr()) { 313 Out << " = "; 314 Init->printPretty(Out, Context, 0, Policy, Indentation); 315 } 316} 317 318void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) { 319 if (!Policy.SuppressSpecifiers) { 320 switch (D->getStorageClass()) { 321 case FunctionDecl::None: break; 322 case FunctionDecl::Extern: Out << "extern "; break; 323 case FunctionDecl::Static: Out << "static "; break; 324 case FunctionDecl::PrivateExtern: Out << "__private_extern__ "; break; 325 } 326 327 if (D->isInline()) Out << "inline "; 328 if (D->isVirtualAsWritten()) Out << "virtual "; 329 } 330 331 PrintingPolicy SubPolicy(Policy); 332 SubPolicy.SuppressSpecifiers = false; 333 std::string Proto = D->getNameAsString(); 334 if (isa<FunctionType>(D->getType().getTypePtr())) { 335 const FunctionType *AFT = D->getType()->getAs<FunctionType>(); 336 337 const FunctionProtoType *FT = 0; 338 if (D->hasWrittenPrototype()) 339 FT = dyn_cast<FunctionProtoType>(AFT); 340 341 Proto += "("; 342 if (FT) { 343 llvm::raw_string_ostream POut(Proto); 344 DeclPrinter ParamPrinter(POut, Context, SubPolicy, Indentation); 345 for (unsigned i = 0, e = D->getNumParams(); i != e; ++i) { 346 if (i) POut << ", "; 347 ParamPrinter.VisitParmVarDecl(D->getParamDecl(i)); 348 } 349 350 if (FT->isVariadic()) { 351 if (D->getNumParams()) POut << ", "; 352 POut << "..."; 353 } 354 } else if (D->isThisDeclarationADefinition() && !D->hasPrototype()) { 355 for (unsigned i = 0, e = D->getNumParams(); i != e; ++i) { 356 if (i) 357 Proto += ", "; 358 Proto += D->getParamDecl(i)->getNameAsString(); 359 } 360 } 361 362 Proto += ")"; 363 if (D->hasAttr<NoReturnAttr>()) 364 Proto += " __attribute((noreturn))"; 365 if (CXXConstructorDecl *CDecl = dyn_cast<CXXConstructorDecl>(D)) { 366 if (CDecl->getNumBaseOrMemberInitializers() > 0) { 367 Proto += " : "; 368 Out << Proto; 369 Proto.clear(); 370 for (CXXConstructorDecl::init_const_iterator B = CDecl->init_begin(), 371 E = CDecl->init_end(); 372 B != E; ++B) { 373 CXXBaseOrMemberInitializer * BMInitializer = (*B); 374 if (B != CDecl->init_begin()) 375 Out << ", "; 376 bool hasArguments = (BMInitializer->arg_begin() != 377 BMInitializer->arg_end()); 378 if (BMInitializer->isMemberInitializer()) { 379 FieldDecl *FD = BMInitializer->getMember(); 380 Out << FD->getNameAsString(); 381 } 382 else // FIXME. skip dependent types for now. 383 if (const RecordType *RT = 384 BMInitializer->getBaseClass()->getAs<RecordType>()) { 385 const CXXRecordDecl *BaseDecl = 386 cast<CXXRecordDecl>(RT->getDecl()); 387 Out << BaseDecl->getNameAsString(); 388 } 389 if (hasArguments) { 390 Out << "("; 391 for (CXXBaseOrMemberInitializer::const_arg_iterator BE = 392 BMInitializer->const_arg_begin(), 393 EE = BMInitializer->const_arg_end(); BE != EE; ++BE) { 394 if (BE != BMInitializer->const_arg_begin()) 395 Out<< ", "; 396 const Expr *Exp = (*BE); 397 Exp->printPretty(Out, Context, 0, Policy, Indentation); 398 } 399 Out << ")"; 400 } else 401 Out << "()"; 402 } 403 } 404 } 405 else if (CXXDestructorDecl *DDecl = dyn_cast<CXXDestructorDecl>(D)) { 406 if (DDecl->getNumBaseOrMemberDestructions() > 0) { 407 // List order of base/member destruction for visualization purposes. 408 assert (D->isThisDeclarationADefinition() && "Destructor with dtor-list"); 409 Proto += "/* : "; 410 for (CXXDestructorDecl::destr_const_iterator *B = DDecl->destr_begin(), 411 *E = DDecl->destr_end(); 412 B != E; ++B) { 413 uintptr_t BaseOrMember = (*B); 414 if (B != DDecl->destr_begin()) 415 Proto += ", "; 416 417 if (DDecl->isMemberToDestroy(BaseOrMember)) { 418 FieldDecl *FD = DDecl->getMemberToDestroy(BaseOrMember); 419 Proto += "~"; 420 Proto += FD->getNameAsString(); 421 } 422 else // FIXME. skip dependent types for now. 423 if (const RecordType *RT = 424 DDecl->getAnyBaseClassToDestroy(BaseOrMember) 425 ->getAs<RecordType>()) { 426 const CXXRecordDecl *BaseDecl = 427 cast<CXXRecordDecl>(RT->getDecl()); 428 Proto += "~"; 429 Proto += BaseDecl->getNameAsString(); 430 } 431 Proto += "()"; 432 } 433 Proto += " */"; 434 } 435 } 436 else 437 AFT->getResultType().getAsStringInternal(Proto, Policy); 438 } else { 439 D->getType().getAsStringInternal(Proto, Policy); 440 } 441 442 Out << Proto; 443 444 if (D->isPure()) 445 Out << " = 0"; 446 else if (D->isDeleted()) 447 Out << " = delete"; 448 else if (D->isThisDeclarationADefinition()) { 449 if (!D->hasPrototype() && D->getNumParams()) { 450 // This is a K&R function definition, so we need to print the 451 // parameters. 452 Out << '\n'; 453 DeclPrinter ParamPrinter(Out, Context, SubPolicy, Indentation); 454 Indentation += Policy.Indentation; 455 for (unsigned i = 0, e = D->getNumParams(); i != e; ++i) { 456 Indent(); 457 ParamPrinter.VisitParmVarDecl(D->getParamDecl(i)); 458 Out << ";\n"; 459 } 460 Indentation -= Policy.Indentation; 461 } else 462 Out << ' '; 463 464 D->getBody()->printPretty(Out, Context, 0, SubPolicy, Indentation); 465 Out << '\n'; 466 } 467} 468 469void DeclPrinter::VisitFieldDecl(FieldDecl *D) { 470 if (!Policy.SuppressSpecifiers && D->isMutable()) 471 Out << "mutable "; 472 473 std::string Name = D->getNameAsString(); 474 D->getType().getAsStringInternal(Name, Policy); 475 Out << Name; 476 477 if (D->isBitField()) { 478 Out << " : "; 479 D->getBitWidth()->printPretty(Out, Context, 0, Policy, Indentation); 480 } 481} 482 483void DeclPrinter::VisitVarDecl(VarDecl *D) { 484 if (!Policy.SuppressSpecifiers && D->getStorageClass() != VarDecl::None) 485 Out << VarDecl::getStorageClassSpecifierString(D->getStorageClass()) << " "; 486 487 if (!Policy.SuppressSpecifiers && D->isThreadSpecified()) 488 Out << "__thread "; 489 490 std::string Name = D->getNameAsString(); 491 QualType T = D->getType(); 492 if (OriginalParmVarDecl *Parm = dyn_cast<OriginalParmVarDecl>(D)) 493 T = Parm->getOriginalType(); 494 T.getAsStringInternal(Name, Policy); 495 Out << Name; 496 if (D->getInit()) { 497 if (D->hasCXXDirectInitializer()) 498 Out << "("; 499 else 500 Out << " = "; 501 D->getInit()->printPretty(Out, Context, 0, Policy, Indentation); 502 if (D->hasCXXDirectInitializer()) 503 Out << ")"; 504 } 505} 506 507void DeclPrinter::VisitParmVarDecl(ParmVarDecl *D) { 508 VisitVarDecl(D); 509} 510 511void DeclPrinter::VisitOriginalParmVarDecl(OriginalParmVarDecl *D) { 512 VisitVarDecl(D); 513} 514 515void DeclPrinter::VisitFileScopeAsmDecl(FileScopeAsmDecl *D) { 516 Out << "__asm ("; 517 D->getAsmString()->printPretty(Out, Context, 0, Policy, Indentation); 518 Out << ")"; 519} 520 521//---------------------------------------------------------------------------- 522// C++ declarations 523//---------------------------------------------------------------------------- 524void DeclPrinter::VisitOverloadedFunctionDecl(OverloadedFunctionDecl *D) { 525 assert(false && 526 "OverloadedFunctionDecls aren't really decls and are never printed"); 527} 528 529void DeclPrinter::VisitNamespaceDecl(NamespaceDecl *D) { 530 Out << "namespace " << D->getNameAsString() << " {\n"; 531 VisitDeclContext(D); 532 Indent() << "}"; 533} 534 535void DeclPrinter::VisitUsingDirectiveDecl(UsingDirectiveDecl *D) { 536 Out << "using namespace "; 537 if (D->getQualifier()) 538 D->getQualifier()->print(Out, Policy); 539 Out << D->getNominatedNamespace()->getNameAsString(); 540} 541 542void DeclPrinter::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) { 543 Out << "namespace " << D->getNameAsString() << " = "; 544 if (D->getQualifier()) 545 D->getQualifier()->print(Out, Policy); 546 Out << D->getAliasedNamespace()->getNameAsString(); 547} 548 549void DeclPrinter::VisitCXXRecordDecl(CXXRecordDecl *D) { 550 Out << D->getKindName(); 551 if (D->getIdentifier()) { 552 Out << " "; 553 Out << D->getNameAsString(); 554 } 555 556 if (D->isDefinition()) { 557 // Print the base classes 558 if (D->getNumBases()) { 559 Out << " : "; 560 for (CXXRecordDecl::base_class_iterator Base = D->bases_begin(), 561 BaseEnd = D->bases_end(); Base != BaseEnd; ++Base) { 562 if (Base != D->bases_begin()) 563 Out << ", "; 564 565 if (Base->isVirtual()) 566 Out << "virtual "; 567 568 AccessSpecifier AS = Base->getAccessSpecifierAsWritten(); 569 if (AS != AS_none) 570 Print(AS); 571 Out << " " << Base->getType().getAsString(Policy); 572 } 573 } 574 575 // Print the class definition 576 // FIXME: Doesn't print access specifiers, e.g., "public:" 577 Out << " {\n"; 578 VisitDeclContext(D); 579 Indent() << "}"; 580 } 581} 582 583void DeclPrinter::VisitLinkageSpecDecl(LinkageSpecDecl *D) { 584 const char *l; 585 if (D->getLanguage() == LinkageSpecDecl::lang_c) 586 l = "C"; 587 else { 588 assert(D->getLanguage() == LinkageSpecDecl::lang_cxx && 589 "unknown language in linkage specification"); 590 l = "C++"; 591 } 592 593 Out << "extern \"" << l << "\" "; 594 if (D->hasBraces()) { 595 Out << "{\n"; 596 VisitDeclContext(D); 597 Indent() << "}"; 598 } else 599 Visit(*D->decls_begin()); 600} 601 602void DeclPrinter::VisitTemplateDecl(TemplateDecl *D) { 603 Out << "template <"; 604 605 TemplateParameterList *Params = D->getTemplateParameters(); 606 for (unsigned i = 0, e = Params->size(); i != e; ++i) { 607 if (i != 0) 608 Out << ", "; 609 610 const Decl *Param = Params->getParam(i); 611 if (const TemplateTypeParmDecl *TTP = 612 dyn_cast<TemplateTypeParmDecl>(Param)) { 613 614 QualType ParamType = 615 Context.getTypeDeclType(const_cast<TemplateTypeParmDecl*>(TTP)); 616 617 if (TTP->wasDeclaredWithTypename()) 618 Out << "typename "; 619 else 620 Out << "class "; 621 622 if (TTP->isParameterPack()) 623 Out << "... "; 624 625 Out << ParamType.getAsString(Policy); 626 627 if (TTP->hasDefaultArgument()) { 628 Out << " = "; 629 Out << TTP->getDefaultArgument().getAsString(Policy); 630 }; 631 } else if (const NonTypeTemplateParmDecl *NTTP = 632 dyn_cast<NonTypeTemplateParmDecl>(Param)) { 633 Out << NTTP->getType().getAsString(Policy); 634 635 if (IdentifierInfo *Name = NTTP->getIdentifier()) { 636 Out << ' '; 637 Out << Name->getName(); 638 } 639 640 if (NTTP->hasDefaultArgument()) { 641 Out << " = "; 642 NTTP->getDefaultArgument()->printPretty(Out, Context, 0, Policy, 643 Indentation); 644 } 645 } 646 } 647 648 Out << "> "; 649 650 Visit(D->getTemplatedDecl()); 651} 652 653//---------------------------------------------------------------------------- 654// Objective-C declarations 655//---------------------------------------------------------------------------- 656 657void DeclPrinter::VisitObjCClassDecl(ObjCClassDecl *D) { 658 Out << "@class "; 659 for (ObjCClassDecl::iterator I = D->begin(), E = D->end(); 660 I != E; ++I) { 661 if (I != D->begin()) Out << ", "; 662 Out << (*I)->getNameAsString(); 663 } 664} 665 666void DeclPrinter::VisitObjCMethodDecl(ObjCMethodDecl *OMD) { 667 if (OMD->isInstanceMethod()) 668 Out << "- "; 669 else 670 Out << "+ "; 671 if (!OMD->getResultType().isNull()) 672 Out << '(' << OMD->getResultType().getAsString(Policy) << ")"; 673 674 std::string name = OMD->getSelector().getAsString(); 675 std::string::size_type pos, lastPos = 0; 676 for (ObjCMethodDecl::param_iterator PI = OMD->param_begin(), 677 E = OMD->param_end(); PI != E; ++PI) { 678 // FIXME: selector is missing here! 679 pos = name.find_first_of(":", lastPos); 680 Out << " " << name.substr(lastPos, pos - lastPos); 681 Out << ":(" << (*PI)->getType().getAsString(Policy) << ")" 682 << (*PI)->getNameAsString(); 683 lastPos = pos + 1; 684 } 685 686 if (OMD->param_begin() == OMD->param_end()) 687 Out << " " << name; 688 689 if (OMD->isVariadic()) 690 Out << ", ..."; 691 692 if (OMD->getBody()) { 693 Out << ' '; 694 OMD->getBody()->printPretty(Out, Context, 0, Policy); 695 Out << '\n'; 696 } 697} 698 699void DeclPrinter::VisitObjCImplementationDecl(ObjCImplementationDecl *OID) { 700 std::string I = OID->getNameAsString(); 701 ObjCInterfaceDecl *SID = OID->getSuperClass(); 702 703 if (SID) 704 Out << "@implementation " << I << " : " << SID->getNameAsString(); 705 else 706 Out << "@implementation " << I; 707 Out << "\n"; 708 VisitDeclContext(OID, false); 709 Out << "@end"; 710} 711 712void DeclPrinter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *OID) { 713 std::string I = OID->getNameAsString(); 714 ObjCInterfaceDecl *SID = OID->getSuperClass(); 715 716 if (SID) 717 Out << "@interface " << I << " : " << SID->getNameAsString(); 718 else 719 Out << "@interface " << I; 720 721 // Protocols? 722 const ObjCList<ObjCProtocolDecl> &Protocols = OID->getReferencedProtocols(); 723 if (!Protocols.empty()) { 724 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(), 725 E = Protocols.end(); I != E; ++I) 726 Out << (I == Protocols.begin() ? '<' : ',') << (*I)->getNameAsString(); 727 } 728 729 if (!Protocols.empty()) 730 Out << "> "; 731 732 if (OID->ivar_size() > 0) { 733 Out << "{\n"; 734 Indentation += Policy.Indentation; 735 for (ObjCInterfaceDecl::ivar_iterator I = OID->ivar_begin(), 736 E = OID->ivar_end(); I != E; ++I) { 737 Indent() << (*I)->getType().getAsString(Policy) 738 << ' ' << (*I)->getNameAsString() << ";\n"; 739 } 740 Indentation -= Policy.Indentation; 741 Out << "}\n"; 742 } 743 744 VisitDeclContext(OID, false); 745 Out << "@end"; 746 // FIXME: implement the rest... 747} 748 749void DeclPrinter::VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *D) { 750 Out << "@protocol "; 751 for (ObjCForwardProtocolDecl::protocol_iterator I = D->protocol_begin(), 752 E = D->protocol_end(); 753 I != E; ++I) { 754 if (I != D->protocol_begin()) Out << ", "; 755 Out << (*I)->getNameAsString(); 756 } 757} 758 759void DeclPrinter::VisitObjCProtocolDecl(ObjCProtocolDecl *PID) { 760 Out << "@protocol " << PID->getNameAsString() << '\n'; 761 VisitDeclContext(PID, false); 762 Out << "@end"; 763} 764 765void DeclPrinter::VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *PID) { 766 Out << "@implementation " 767 << PID->getClassInterface()->getNameAsString() 768 << '(' << PID->getNameAsString() << ")\n"; 769 770 VisitDeclContext(PID, false); 771 Out << "@end"; 772 // FIXME: implement the rest... 773} 774 775void DeclPrinter::VisitObjCCategoryDecl(ObjCCategoryDecl *PID) { 776 Out << "@interface " 777 << PID->getClassInterface()->getNameAsString() 778 << '(' << PID->getNameAsString() << ")\n"; 779 VisitDeclContext(PID, false); 780 Out << "@end"; 781 782 // FIXME: implement the rest... 783} 784 785void DeclPrinter::VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *AID) { 786 Out << "@compatibility_alias " << AID->getNameAsString() 787 << ' ' << AID->getClassInterface()->getNameAsString() << ";\n"; 788} 789 790/// PrintObjCPropertyDecl - print a property declaration. 791/// 792void DeclPrinter::VisitObjCPropertyDecl(ObjCPropertyDecl *PDecl) { 793 if (PDecl->getPropertyImplementation() == ObjCPropertyDecl::Required) 794 Out << "@required\n"; 795 else if (PDecl->getPropertyImplementation() == ObjCPropertyDecl::Optional) 796 Out << "@optional\n"; 797 798 Out << "@property"; 799 if (PDecl->getPropertyAttributes() != ObjCPropertyDecl::OBJC_PR_noattr) { 800 bool first = true; 801 Out << " ("; 802 if (PDecl->getPropertyAttributes() & 803 ObjCPropertyDecl::OBJC_PR_readonly) { 804 Out << (first ? ' ' : ',') << "readonly"; 805 first = false; 806 } 807 808 if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_getter) { 809 Out << (first ? ' ' : ',') << "getter = " 810 << PDecl->getGetterName().getAsString(); 811 first = false; 812 } 813 if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_setter) { 814 Out << (first ? ' ' : ',') << "setter = " 815 << PDecl->getSetterName().getAsString(); 816 first = false; 817 } 818 819 if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_assign) { 820 Out << (first ? ' ' : ',') << "assign"; 821 first = false; 822 } 823 824 if (PDecl->getPropertyAttributes() & 825 ObjCPropertyDecl::OBJC_PR_readwrite) { 826 Out << (first ? ' ' : ',') << "readwrite"; 827 first = false; 828 } 829 830 if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_retain) { 831 Out << (first ? ' ' : ',') << "retain"; 832 first = false; 833 } 834 835 if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_copy) { 836 Out << (first ? ' ' : ',') << "copy"; 837 first = false; 838 } 839 840 if (PDecl->getPropertyAttributes() & 841 ObjCPropertyDecl::OBJC_PR_nonatomic) { 842 Out << (first ? ' ' : ',') << "nonatomic"; 843 first = false; 844 } 845 Out << " )"; 846 } 847 Out << ' ' << PDecl->getType().getAsString(Policy) 848 << ' ' << PDecl->getNameAsString(); 849} 850 851void DeclPrinter::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *PID) { 852 if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize) 853 Out << "@synthesize "; 854 else 855 Out << "@dynamic "; 856 Out << PID->getPropertyDecl()->getNameAsString(); 857 if (PID->getPropertyIvarDecl()) 858 Out << "=" << PID->getPropertyIvarDecl()->getNameAsString(); 859} 860 861void DeclPrinter::VisitUsingDecl(UsingDecl *D) { 862 Out << "using "; 863 D->getTargetNestedNameDecl()->print(Out, Policy); 864 Out << D->getTargetDecl()->getNameAsString(); 865} 866 867void DeclPrinter::VisitUnresolvedUsingDecl(UnresolvedUsingDecl *D) { 868 Out << "using "; 869 D->getTargetNestedNameSpecifier()->print(Out, Policy); 870 Out << D->getTargetName().getAsString(); 871} 872