DeclPrinter.cpp revision 0ae7b3f1d5403265f693ed75384603ca8fbba74d
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/raw_ostream.h" 22using namespace clang; 23 24namespace { 25 class DeclPrinter : public DeclVisitor<DeclPrinter> { 26 llvm::raw_ostream &Out; 27 ASTContext &Context; 28 PrintingPolicy Policy; 29 unsigned Indentation; 30 31 llvm::raw_ostream& Indent() { return Indent(Indentation); } 32 llvm::raw_ostream& Indent(unsigned Indentation); 33 void ProcessDeclGroup(llvm::SmallVectorImpl<Decl*>& Decls); 34 35 void Print(AccessSpecifier AS); 36 37 public: 38 DeclPrinter(llvm::raw_ostream &Out, ASTContext &Context, 39 const PrintingPolicy &Policy, 40 unsigned Indentation = 0) 41 : Out(Out), Context(Context), Policy(Policy), Indentation(Indentation) { } 42 43 void VisitDeclContext(DeclContext *DC, bool Indent = true); 44 45 void VisitTranslationUnitDecl(TranslationUnitDecl *D); 46 void VisitTypedefDecl(TypedefDecl *D); 47 void VisitEnumDecl(EnumDecl *D); 48 void VisitRecordDecl(RecordDecl *D); 49 void VisitEnumConstantDecl(EnumConstantDecl *D); 50 void VisitFunctionDecl(FunctionDecl *D); 51 void VisitFieldDecl(FieldDecl *D); 52 void VisitVarDecl(VarDecl *D); 53 void VisitParmVarDecl(ParmVarDecl *D); 54 void VisitFileScopeAsmDecl(FileScopeAsmDecl *D); 55 void VisitNamespaceDecl(NamespaceDecl *D); 56 void VisitUsingDirectiveDecl(UsingDirectiveDecl *D); 57 void VisitNamespaceAliasDecl(NamespaceAliasDecl *D); 58 void VisitCXXRecordDecl(CXXRecordDecl *D); 59 void VisitLinkageSpecDecl(LinkageSpecDecl *D); 60 void VisitTemplateDecl(TemplateDecl *D); 61 void VisitObjCMethodDecl(ObjCMethodDecl *D); 62 void VisitObjCClassDecl(ObjCClassDecl *D); 63 void VisitObjCImplementationDecl(ObjCImplementationDecl *D); 64 void VisitObjCInterfaceDecl(ObjCInterfaceDecl *D); 65 void VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *D); 66 void VisitObjCProtocolDecl(ObjCProtocolDecl *D); 67 void VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D); 68 void VisitObjCCategoryDecl(ObjCCategoryDecl *D); 69 void VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *D); 70 void VisitObjCPropertyDecl(ObjCPropertyDecl *D); 71 void VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D); 72 void VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D); 73 void VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D); 74 void VisitUsingDecl(UsingDecl *D); 75 void VisitUsingShadowDecl(UsingShadowDecl *D); 76 }; 77} 78 79void Decl::print(llvm::raw_ostream &Out, unsigned Indentation) const { 80 print(Out, getASTContext().PrintingPolicy, Indentation); 81} 82 83void Decl::print(llvm::raw_ostream &Out, const PrintingPolicy &Policy, 84 unsigned Indentation) const { 85 DeclPrinter Printer(Out, getASTContext(), Policy, Indentation); 86 Printer.Visit(const_cast<Decl*>(this)); 87} 88 89static QualType GetBaseType(QualType T) { 90 // FIXME: This should be on the Type class! 91 QualType BaseType = T; 92 while (!BaseType->isSpecifierType()) { 93 if (isa<TypedefType>(BaseType)) 94 break; 95 else if (const PointerType* PTy = BaseType->getAs<PointerType>()) 96 BaseType = PTy->getPointeeType(); 97 else if (const ArrayType* ATy = dyn_cast<ArrayType>(BaseType)) 98 BaseType = ATy->getElementType(); 99 else if (const FunctionType* FTy = BaseType->getAs<FunctionType>()) 100 BaseType = FTy->getResultType(); 101 else if (const VectorType *VTy = BaseType->getAs<VectorType>()) 102 BaseType = VTy->getElementType(); 103 else 104 assert(0 && "Unknown declarator!"); 105 } 106 return BaseType; 107} 108 109static QualType getDeclType(Decl* D) { 110 if (TypedefDecl* TDD = dyn_cast<TypedefDecl>(D)) 111 return TDD->getUnderlyingType(); 112 if (ValueDecl* VD = dyn_cast<ValueDecl>(D)) 113 return VD->getType(); 114 return QualType(); 115} 116 117void Decl::printGroup(Decl** Begin, unsigned NumDecls, 118 llvm::raw_ostream &Out, const PrintingPolicy &Policy, 119 unsigned Indentation) { 120 if (NumDecls == 1) { 121 (*Begin)->print(Out, Policy, Indentation); 122 return; 123 } 124 125 Decl** End = Begin + NumDecls; 126 TagDecl* TD = dyn_cast<TagDecl>(*Begin); 127 if (TD) 128 ++Begin; 129 130 PrintingPolicy SubPolicy(Policy); 131 if (TD && TD->isDefinition()) { 132 TD->print(Out, Policy, Indentation); 133 Out << " "; 134 SubPolicy.SuppressTag = true; 135 } 136 137 bool isFirst = true; 138 for ( ; Begin != End; ++Begin) { 139 if (isFirst) { 140 SubPolicy.SuppressSpecifiers = false; 141 isFirst = false; 142 } else { 143 if (!isFirst) Out << ", "; 144 SubPolicy.SuppressSpecifiers = true; 145 } 146 147 (*Begin)->print(Out, SubPolicy, Indentation); 148 } 149} 150 151void Decl::dump() const { 152 print(llvm::errs()); 153} 154 155llvm::raw_ostream& DeclPrinter::Indent(unsigned Indentation) { 156 for (unsigned i = 0; i != Indentation; ++i) 157 Out << " "; 158 return Out; 159} 160 161void DeclPrinter::ProcessDeclGroup(llvm::SmallVectorImpl<Decl*>& Decls) { 162 this->Indent(); 163 Decl::printGroup(Decls.data(), Decls.size(), Out, Policy, Indentation); 164 Out << ";\n"; 165 Decls.clear(); 166 167} 168 169void DeclPrinter::Print(AccessSpecifier AS) { 170 switch(AS) { 171 case AS_none: assert(0 && "No access specifier!"); break; 172 case AS_public: Out << "public"; break; 173 case AS_protected: Out << "protected"; break; 174 case AS_private: Out << " private"; break; 175 } 176} 177 178//---------------------------------------------------------------------------- 179// Common C declarations 180//---------------------------------------------------------------------------- 181 182void DeclPrinter::VisitDeclContext(DeclContext *DC, bool Indent) { 183 if (Indent) 184 Indentation += Policy.Indentation; 185 186 bool PrintAccess = isa<CXXRecordDecl>(DC); 187 AccessSpecifier CurAS = AS_none; 188 189 llvm::SmallVector<Decl*, 2> Decls; 190 for (DeclContext::decl_iterator D = DC->decls_begin(), DEnd = DC->decls_end(); 191 D != DEnd; ++D) { 192 if (!Policy.Dump) { 193 // Skip over implicit declarations in pretty-printing mode. 194 if (D->isImplicit()) continue; 195 // FIXME: Ugly hack so we don't pretty-print the builtin declaration 196 // of __builtin_va_list. There should be some other way to check that. 197 if (isa<NamedDecl>(*D) && cast<NamedDecl>(*D)->getNameAsString() == 198 "__builtin_va_list") 199 continue; 200 } 201 202 if (PrintAccess) { 203 AccessSpecifier AS = D->getAccess(); 204 205 if (AS != CurAS) { 206 if (Indent) 207 this->Indent(Indentation - Policy.Indentation); 208 Print(AS); 209 Out << ":\n"; 210 CurAS = AS; 211 } 212 } 213 214 // The next bits of code handles stuff like "struct {int x;} a,b"; we're 215 // forced to merge the declarations because there's no other way to 216 // refer to the struct in question. This limited merging is safe without 217 // a bunch of other checks because it only merges declarations directly 218 // referring to the tag, not typedefs. 219 // 220 // Check whether the current declaration should be grouped with a previous 221 // unnamed struct. 222 QualType CurDeclType = getDeclType(*D); 223 if (!Decls.empty() && !CurDeclType.isNull()) { 224 QualType BaseType = GetBaseType(CurDeclType); 225 if (!BaseType.isNull() && isa<TagType>(BaseType) && 226 cast<TagType>(BaseType)->getDecl() == Decls[0]) { 227 Decls.push_back(*D); 228 continue; 229 } 230 } 231 232 // If we have a merged group waiting to be handled, handle it now. 233 if (!Decls.empty()) 234 ProcessDeclGroup(Decls); 235 236 // If the current declaration is an unnamed tag type, save it 237 // so we can merge it with the subsequent declaration(s) using it. 238 if (isa<TagDecl>(*D) && !cast<TagDecl>(*D)->getIdentifier()) { 239 Decls.push_back(*D); 240 continue; 241 } 242 this->Indent(); 243 Visit(*D); 244 245 // FIXME: Need to be able to tell the DeclPrinter when 246 const char *Terminator = 0; 247 if (isa<FunctionDecl>(*D) && 248 cast<FunctionDecl>(*D)->isThisDeclarationADefinition()) 249 Terminator = 0; 250 else if (isa<ObjCMethodDecl>(*D) && cast<ObjCMethodDecl>(*D)->getBody()) 251 Terminator = 0; 252 else if (isa<NamespaceDecl>(*D) || isa<LinkageSpecDecl>(*D) || 253 isa<ObjCImplementationDecl>(*D) || 254 isa<ObjCInterfaceDecl>(*D) || 255 isa<ObjCProtocolDecl>(*D) || 256 isa<ObjCCategoryImplDecl>(*D) || 257 isa<ObjCCategoryDecl>(*D)) 258 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