1 //===--- StmtDumper.cpp - Dumping implementation for Stmt 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 Stmt::dump/Stmt::print methods, which dump out the 11 // AST in a form that exposes type details and other fields. 12 // 13 //===----------------------------------------------------------------------===// 14 15 #include "clang/AST/StmtVisitor.h" 16 #include "clang/AST/DeclObjC.h" 17 #include "clang/AST/DeclCXX.h" 18 #include "clang/AST/PrettyPrinter.h" 19 #include "clang/Basic/SourceManager.h" 20 #include "llvm/Support/raw_ostream.h" 21 using namespace clang; 22 23 //===----------------------------------------------------------------------===// 24 // StmtDumper Visitor 25 //===----------------------------------------------------------------------===// 26 27 namespace { 28 class StmtDumper : public StmtVisitor<StmtDumper> { 29 SourceManager *SM; 30 raw_ostream &OS; 31 unsigned IndentLevel; 32 33 /// MaxDepth - When doing a normal dump (not dumpAll) we only want to dump 34 /// the first few levels of an AST. This keeps track of how many ast levels 35 /// are left. 36 unsigned MaxDepth; 37 38 /// LastLocFilename/LastLocLine - Keep track of the last location we print 39 /// out so that we can print out deltas from then on out. 40 const char *LastLocFilename; 41 unsigned LastLocLine; 42 43 public: 44 StmtDumper(SourceManager *sm, raw_ostream &os, unsigned maxDepth) 45 : SM(sm), OS(os), IndentLevel(0-1), MaxDepth(maxDepth) { 46 LastLocFilename = ""; 47 LastLocLine = ~0U; 48 } 49 50 void DumpSubTree(Stmt *S) { 51 // Prune the recursion if not using dump all. 52 if (MaxDepth == 0) return; 53 54 ++IndentLevel; 55 if (S) { 56 if (DeclStmt* DS = dyn_cast<DeclStmt>(S)) 57 VisitDeclStmt(DS); 58 else { 59 Visit(S); 60 61 // Print out children. 62 Stmt::child_range CI = S->children(); 63 if (CI) { 64 while (CI) { 65 OS << '\n'; 66 DumpSubTree(*CI++); 67 } 68 } 69 } 70 OS << ')'; 71 } else { 72 Indent(); 73 OS << "<<<NULL>>>"; 74 } 75 --IndentLevel; 76 } 77 78 void DumpDeclarator(Decl *D); 79 80 void Indent() const { 81 for (int i = 0, e = IndentLevel; i < e; ++i) 82 OS << " "; 83 } 84 85 void DumpType(QualType T) { 86 SplitQualType T_split = T.split(); 87 OS << "'" << QualType::getAsString(T_split) << "'"; 88 89 if (!T.isNull()) { 90 // If the type is sugared, also dump a (shallow) desugared type. 91 SplitQualType D_split = T.getSplitDesugaredType(); 92 if (T_split != D_split) 93 OS << ":'" << QualType::getAsString(D_split) << "'"; 94 } 95 } 96 void DumpDeclRef(Decl *node); 97 void DumpStmt(const Stmt *Node) { 98 Indent(); 99 OS << "(" << Node->getStmtClassName() 100 << " " << (void*)Node; 101 DumpSourceRange(Node); 102 } 103 void DumpValueKind(ExprValueKind K) { 104 switch (K) { 105 case VK_RValue: break; 106 case VK_LValue: OS << " lvalue"; break; 107 case VK_XValue: OS << " xvalue"; break; 108 } 109 } 110 void DumpObjectKind(ExprObjectKind K) { 111 switch (K) { 112 case OK_Ordinary: break; 113 case OK_BitField: OS << " bitfield"; break; 114 case OK_ObjCProperty: OS << " objcproperty"; break; 115 case OK_ObjCSubscript: OS << " objcsubscript"; break; 116 case OK_VectorComponent: OS << " vectorcomponent"; break; 117 } 118 } 119 void DumpExpr(const Expr *Node) { 120 DumpStmt(Node); 121 OS << ' '; 122 DumpType(Node->getType()); 123 DumpValueKind(Node->getValueKind()); 124 DumpObjectKind(Node->getObjectKind()); 125 } 126 void DumpSourceRange(const Stmt *Node); 127 void DumpLocation(SourceLocation Loc); 128 129 // Stmts. 130 void VisitStmt(Stmt *Node); 131 void VisitDeclStmt(DeclStmt *Node); 132 void VisitLabelStmt(LabelStmt *Node); 133 void VisitGotoStmt(GotoStmt *Node); 134 135 // Exprs 136 void VisitExpr(Expr *Node); 137 void VisitCastExpr(CastExpr *Node); 138 void VisitDeclRefExpr(DeclRefExpr *Node); 139 void VisitPredefinedExpr(PredefinedExpr *Node); 140 void VisitCharacterLiteral(CharacterLiteral *Node); 141 void VisitIntegerLiteral(IntegerLiteral *Node); 142 void VisitFloatingLiteral(FloatingLiteral *Node); 143 void VisitStringLiteral(StringLiteral *Str); 144 void VisitUnaryOperator(UnaryOperator *Node); 145 void VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *Node); 146 void VisitMemberExpr(MemberExpr *Node); 147 void VisitExtVectorElementExpr(ExtVectorElementExpr *Node); 148 void VisitBinaryOperator(BinaryOperator *Node); 149 void VisitCompoundAssignOperator(CompoundAssignOperator *Node); 150 void VisitAddrLabelExpr(AddrLabelExpr *Node); 151 void VisitBlockExpr(BlockExpr *Node); 152 void VisitOpaqueValueExpr(OpaqueValueExpr *Node); 153 154 // C++ 155 void VisitCXXNamedCastExpr(CXXNamedCastExpr *Node); 156 void VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *Node); 157 void VisitCXXThisExpr(CXXThisExpr *Node); 158 void VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *Node); 159 void VisitCXXConstructExpr(CXXConstructExpr *Node); 160 void VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *Node); 161 void VisitExprWithCleanups(ExprWithCleanups *Node); 162 void VisitUnresolvedLookupExpr(UnresolvedLookupExpr *Node); 163 void DumpCXXTemporary(CXXTemporary *Temporary); 164 165 // ObjC 166 void VisitObjCAtCatchStmt(ObjCAtCatchStmt *Node); 167 void VisitObjCEncodeExpr(ObjCEncodeExpr *Node); 168 void VisitObjCMessageExpr(ObjCMessageExpr* Node); 169 void VisitObjCSelectorExpr(ObjCSelectorExpr *Node); 170 void VisitObjCProtocolExpr(ObjCProtocolExpr *Node); 171 void VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *Node); 172 void VisitObjCSubscriptRefExpr(ObjCSubscriptRefExpr *Node); 173 void VisitObjCIvarRefExpr(ObjCIvarRefExpr *Node); 174 void VisitObjCBoolLiteralExpr(ObjCBoolLiteralExpr *Node); 175 }; 176 } 177 178 //===----------------------------------------------------------------------===// 179 // Utilities 180 //===----------------------------------------------------------------------===// 181 182 void StmtDumper::DumpLocation(SourceLocation Loc) { 183 SourceLocation SpellingLoc = SM->getSpellingLoc(Loc); 184 185 // The general format we print out is filename:line:col, but we drop pieces 186 // that haven't changed since the last loc printed. 187 PresumedLoc PLoc = SM->getPresumedLoc(SpellingLoc); 188 189 if (PLoc.isInvalid()) { 190 OS << "<invalid sloc>"; 191 return; 192 } 193 194 if (strcmp(PLoc.getFilename(), LastLocFilename) != 0) { 195 OS << PLoc.getFilename() << ':' << PLoc.getLine() 196 << ':' << PLoc.getColumn(); 197 LastLocFilename = PLoc.getFilename(); 198 LastLocLine = PLoc.getLine(); 199 } else if (PLoc.getLine() != LastLocLine) { 200 OS << "line" << ':' << PLoc.getLine() 201 << ':' << PLoc.getColumn(); 202 LastLocLine = PLoc.getLine(); 203 } else { 204 OS << "col" << ':' << PLoc.getColumn(); 205 } 206 } 207 208 void StmtDumper::DumpSourceRange(const Stmt *Node) { 209 // Can't translate locations if a SourceManager isn't available. 210 if (SM == 0) return; 211 212 // TODO: If the parent expression is available, we can print a delta vs its 213 // location. 214 SourceRange R = Node->getSourceRange(); 215 216 OS << " <"; 217 DumpLocation(R.getBegin()); 218 if (R.getBegin() != R.getEnd()) { 219 OS << ", "; 220 DumpLocation(R.getEnd()); 221 } 222 OS << ">"; 223 224 // <t2.c:123:421[blah], t2.c:412:321> 225 226 } 227 228 229 //===----------------------------------------------------------------------===// 230 // Stmt printing methods. 231 //===----------------------------------------------------------------------===// 232 233 void StmtDumper::VisitStmt(Stmt *Node) { 234 DumpStmt(Node); 235 } 236 237 void StmtDumper::DumpDeclarator(Decl *D) { 238 // FIXME: Need to complete/beautify this... this code simply shows the 239 // nodes are where they need to be. 240 if (TypedefDecl *localType = dyn_cast<TypedefDecl>(D)) { 241 OS << "\"typedef " << localType->getUnderlyingType().getAsString() 242 << ' ' << *localType << '"'; 243 } else if (TypeAliasDecl *localType = dyn_cast<TypeAliasDecl>(D)) { 244 OS << "\"using " << *localType << " = " 245 << localType->getUnderlyingType().getAsString() << '"'; 246 } else if (ValueDecl *VD = dyn_cast<ValueDecl>(D)) { 247 OS << "\""; 248 // Emit storage class for vardecls. 249 if (VarDecl *V = dyn_cast<VarDecl>(VD)) { 250 if (V->getStorageClass() != SC_None) 251 OS << VarDecl::getStorageClassSpecifierString(V->getStorageClass()) 252 << " "; 253 } 254 255 std::string Name = VD->getNameAsString(); 256 VD->getType().getAsStringInternal(Name, 257 PrintingPolicy(VD->getASTContext().getLangOpts())); 258 OS << Name; 259 260 // If this is a vardecl with an initializer, emit it. 261 if (VarDecl *V = dyn_cast<VarDecl>(VD)) { 262 if (V->getInit()) { 263 OS << " =\n"; 264 DumpSubTree(V->getInit()); 265 } 266 } 267 OS << '"'; 268 } else if (TagDecl *TD = dyn_cast<TagDecl>(D)) { 269 // print a free standing tag decl (e.g. "struct x;"). 270 const char *tagname; 271 if (const IdentifierInfo *II = TD->getIdentifier()) 272 tagname = II->getNameStart(); 273 else 274 tagname = "<anonymous>"; 275 OS << '"' << TD->getKindName() << ' ' << tagname << ";\""; 276 // FIXME: print tag bodies. 277 } else if (UsingDirectiveDecl *UD = dyn_cast<UsingDirectiveDecl>(D)) { 278 // print using-directive decl (e.g. "using namespace x;") 279 const char *ns; 280 if (const IdentifierInfo *II = UD->getNominatedNamespace()->getIdentifier()) 281 ns = II->getNameStart(); 282 else 283 ns = "<anonymous>"; 284 OS << '"' << UD->getDeclKindName() << ns << ";\""; 285 } else if (UsingDecl *UD = dyn_cast<UsingDecl>(D)) { 286 // print using decl (e.g. "using std::string;") 287 const char *tn = UD->isTypeName() ? "typename " : ""; 288 OS << '"' << UD->getDeclKindName() << tn; 289 UD->getQualifier()->print(OS, 290 PrintingPolicy(UD->getASTContext().getLangOpts())); 291 OS << ";\""; 292 } else if (LabelDecl *LD = dyn_cast<LabelDecl>(D)) { 293 OS << "label " << *LD; 294 } else if (StaticAssertDecl *SAD = dyn_cast<StaticAssertDecl>(D)) { 295 OS << "\"static_assert(\n"; 296 DumpSubTree(SAD->getAssertExpr()); 297 OS << ",\n"; 298 DumpSubTree(SAD->getMessage()); 299 OS << ");\""; 300 } else { 301 llvm_unreachable("Unexpected decl"); 302 } 303 } 304 305 void StmtDumper::VisitDeclStmt(DeclStmt *Node) { 306 DumpStmt(Node); 307 OS << "\n"; 308 for (DeclStmt::decl_iterator DI = Node->decl_begin(), DE = Node->decl_end(); 309 DI != DE; ++DI) { 310 Decl* D = *DI; 311 ++IndentLevel; 312 Indent(); 313 OS << (void*) D << " "; 314 DumpDeclarator(D); 315 if (DI+1 != DE) 316 OS << "\n"; 317 --IndentLevel; 318 } 319 } 320 321 void StmtDumper::VisitLabelStmt(LabelStmt *Node) { 322 DumpStmt(Node); 323 OS << " '" << Node->getName() << "'"; 324 } 325 326 void StmtDumper::VisitGotoStmt(GotoStmt *Node) { 327 DumpStmt(Node); 328 OS << " '" << Node->getLabel()->getName() 329 << "':" << (void*)Node->getLabel(); 330 } 331 332 //===----------------------------------------------------------------------===// 333 // Expr printing methods. 334 //===----------------------------------------------------------------------===// 335 336 void StmtDumper::VisitExpr(Expr *Node) { 337 DumpExpr(Node); 338 } 339 340 static void DumpBasePath(raw_ostream &OS, CastExpr *Node) { 341 if (Node->path_empty()) 342 return; 343 344 OS << " ("; 345 bool First = true; 346 for (CastExpr::path_iterator 347 I = Node->path_begin(), E = Node->path_end(); I != E; ++I) { 348 const CXXBaseSpecifier *Base = *I; 349 if (!First) 350 OS << " -> "; 351 352 const CXXRecordDecl *RD = 353 cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl()); 354 355 if (Base->isVirtual()) 356 OS << "virtual "; 357 OS << RD->getName(); 358 First = false; 359 } 360 361 OS << ')'; 362 } 363 364 void StmtDumper::VisitCastExpr(CastExpr *Node) { 365 DumpExpr(Node); 366 OS << " <" << Node->getCastKindName(); 367 DumpBasePath(OS, Node); 368 OS << ">"; 369 } 370 371 void StmtDumper::VisitDeclRefExpr(DeclRefExpr *Node) { 372 DumpExpr(Node); 373 374 OS << " "; 375 DumpDeclRef(Node->getDecl()); 376 if (Node->getDecl() != Node->getFoundDecl()) { 377 OS << " ("; 378 DumpDeclRef(Node->getFoundDecl()); 379 OS << ")"; 380 } 381 } 382 383 void StmtDumper::DumpDeclRef(Decl *d) { 384 OS << d->getDeclKindName() << ' ' << (void*) d; 385 386 if (NamedDecl *nd = dyn_cast<NamedDecl>(d)) { 387 OS << " '"; 388 nd->getDeclName().printName(OS); 389 OS << "'"; 390 } 391 392 if (ValueDecl *vd = dyn_cast<ValueDecl>(d)) { 393 OS << ' '; DumpType(vd->getType()); 394 } 395 } 396 397 void StmtDumper::VisitUnresolvedLookupExpr(UnresolvedLookupExpr *Node) { 398 DumpExpr(Node); 399 OS << " ("; 400 if (!Node->requiresADL()) OS << "no "; 401 OS << "ADL) = '" << Node->getName() << '\''; 402 403 UnresolvedLookupExpr::decls_iterator 404 I = Node->decls_begin(), E = Node->decls_end(); 405 if (I == E) OS << " empty"; 406 for (; I != E; ++I) 407 OS << " " << (void*) *I; 408 } 409 410 void StmtDumper::VisitObjCIvarRefExpr(ObjCIvarRefExpr *Node) { 411 DumpExpr(Node); 412 413 OS << " " << Node->getDecl()->getDeclKindName() 414 << "Decl='" << *Node->getDecl() 415 << "' " << (void*)Node->getDecl(); 416 if (Node->isFreeIvar()) 417 OS << " isFreeIvar"; 418 } 419 420 void StmtDumper::VisitPredefinedExpr(PredefinedExpr *Node) { 421 DumpExpr(Node); 422 switch (Node->getIdentType()) { 423 default: llvm_unreachable("unknown case"); 424 case PredefinedExpr::Func: OS << " __func__"; break; 425 case PredefinedExpr::Function: OS << " __FUNCTION__"; break; 426 case PredefinedExpr::PrettyFunction: OS << " __PRETTY_FUNCTION__";break; 427 } 428 } 429 430 void StmtDumper::VisitCharacterLiteral(CharacterLiteral *Node) { 431 DumpExpr(Node); 432 OS << " " << Node->getValue(); 433 } 434 435 void StmtDumper::VisitIntegerLiteral(IntegerLiteral *Node) { 436 DumpExpr(Node); 437 438 bool isSigned = Node->getType()->isSignedIntegerType(); 439 OS << " " << Node->getValue().toString(10, isSigned); 440 } 441 void StmtDumper::VisitFloatingLiteral(FloatingLiteral *Node) { 442 DumpExpr(Node); 443 OS << " " << Node->getValueAsApproximateDouble(); 444 } 445 446 void StmtDumper::VisitStringLiteral(StringLiteral *Str) { 447 DumpExpr(Str); 448 // FIXME: this doesn't print wstrings right. 449 OS << " "; 450 switch (Str->getKind()) { 451 case StringLiteral::Ascii: break; // No prefix 452 case StringLiteral::Wide: OS << 'L'; break; 453 case StringLiteral::UTF8: OS << "u8"; break; 454 case StringLiteral::UTF16: OS << 'u'; break; 455 case StringLiteral::UTF32: OS << 'U'; break; 456 } 457 OS << '"'; 458 OS.write_escaped(Str->getString()); 459 OS << '"'; 460 } 461 462 void StmtDumper::VisitUnaryOperator(UnaryOperator *Node) { 463 DumpExpr(Node); 464 OS << " " << (Node->isPostfix() ? "postfix" : "prefix") 465 << " '" << UnaryOperator::getOpcodeStr(Node->getOpcode()) << "'"; 466 } 467 void StmtDumper::VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *Node) { 468 DumpExpr(Node); 469 switch(Node->getKind()) { 470 case UETT_SizeOf: 471 OS << " sizeof "; 472 break; 473 case UETT_AlignOf: 474 OS << " __alignof "; 475 break; 476 case UETT_VecStep: 477 OS << " vec_step "; 478 break; 479 } 480 if (Node->isArgumentType()) 481 DumpType(Node->getArgumentType()); 482 } 483 484 void StmtDumper::VisitMemberExpr(MemberExpr *Node) { 485 DumpExpr(Node); 486 OS << " " << (Node->isArrow() ? "->" : ".") 487 << *Node->getMemberDecl() << ' ' 488 << (void*)Node->getMemberDecl(); 489 } 490 void StmtDumper::VisitExtVectorElementExpr(ExtVectorElementExpr *Node) { 491 DumpExpr(Node); 492 OS << " " << Node->getAccessor().getNameStart(); 493 } 494 void StmtDumper::VisitBinaryOperator(BinaryOperator *Node) { 495 DumpExpr(Node); 496 OS << " '" << BinaryOperator::getOpcodeStr(Node->getOpcode()) << "'"; 497 } 498 void StmtDumper::VisitCompoundAssignOperator(CompoundAssignOperator *Node) { 499 DumpExpr(Node); 500 OS << " '" << BinaryOperator::getOpcodeStr(Node->getOpcode()) 501 << "' ComputeLHSTy="; 502 DumpType(Node->getComputationLHSType()); 503 OS << " ComputeResultTy="; 504 DumpType(Node->getComputationResultType()); 505 } 506 507 void StmtDumper::VisitBlockExpr(BlockExpr *Node) { 508 DumpExpr(Node); 509 510 BlockDecl *block = Node->getBlockDecl(); 511 OS << " decl=" << block; 512 513 IndentLevel++; 514 if (block->capturesCXXThis()) { 515 OS << '\n'; Indent(); OS << "(capture this)"; 516 } 517 for (BlockDecl::capture_iterator 518 i = block->capture_begin(), e = block->capture_end(); i != e; ++i) { 519 OS << '\n'; 520 Indent(); 521 OS << "(capture "; 522 if (i->isByRef()) OS << "byref "; 523 if (i->isNested()) OS << "nested "; 524 if (i->getVariable()) 525 DumpDeclRef(i->getVariable()); 526 if (i->hasCopyExpr()) DumpSubTree(i->getCopyExpr()); 527 OS << ")"; 528 } 529 IndentLevel--; 530 531 OS << '\n'; 532 DumpSubTree(block->getBody()); 533 } 534 535 void StmtDumper::VisitOpaqueValueExpr(OpaqueValueExpr *Node) { 536 DumpExpr(Node); 537 538 if (Expr *Source = Node->getSourceExpr()) { 539 OS << '\n'; 540 DumpSubTree(Source); 541 } 542 } 543 544 // GNU extensions. 545 546 void StmtDumper::VisitAddrLabelExpr(AddrLabelExpr *Node) { 547 DumpExpr(Node); 548 OS << " " << Node->getLabel()->getName() 549 << " " << (void*)Node->getLabel(); 550 } 551 552 //===----------------------------------------------------------------------===// 553 // C++ Expressions 554 //===----------------------------------------------------------------------===// 555 556 void StmtDumper::VisitCXXNamedCastExpr(CXXNamedCastExpr *Node) { 557 DumpExpr(Node); 558 OS << " " << Node->getCastName() 559 << "<" << Node->getTypeAsWritten().getAsString() << ">" 560 << " <" << Node->getCastKindName(); 561 DumpBasePath(OS, Node); 562 OS << ">"; 563 } 564 565 void StmtDumper::VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *Node) { 566 DumpExpr(Node); 567 OS << " " << (Node->getValue() ? "true" : "false"); 568 } 569 570 void StmtDumper::VisitCXXThisExpr(CXXThisExpr *Node) { 571 DumpExpr(Node); 572 OS << " this"; 573 } 574 575 void StmtDumper::VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *Node) { 576 DumpExpr(Node); 577 OS << " functional cast to " << Node->getTypeAsWritten().getAsString() 578 << " <" << Node->getCastKindName() << ">"; 579 } 580 581 void StmtDumper::VisitCXXConstructExpr(CXXConstructExpr *Node) { 582 DumpExpr(Node); 583 CXXConstructorDecl *Ctor = Node->getConstructor(); 584 DumpType(Ctor->getType()); 585 if (Node->isElidable()) 586 OS << " elidable"; 587 if (Node->requiresZeroInitialization()) 588 OS << " zeroing"; 589 } 590 591 void StmtDumper::VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *Node) { 592 DumpExpr(Node); 593 OS << " "; 594 DumpCXXTemporary(Node->getTemporary()); 595 } 596 597 void StmtDumper::VisitExprWithCleanups(ExprWithCleanups *Node) { 598 DumpExpr(Node); 599 ++IndentLevel; 600 for (unsigned i = 0, e = Node->getNumObjects(); i != e; ++i) { 601 OS << "\n"; 602 Indent(); 603 OS << "(cleanup "; 604 DumpDeclRef(Node->getObject(i)); 605 OS << ")"; 606 } 607 --IndentLevel; 608 } 609 610 void StmtDumper::DumpCXXTemporary(CXXTemporary *Temporary) { 611 OS << "(CXXTemporary " << (void *)Temporary << ")"; 612 } 613 614 //===----------------------------------------------------------------------===// 615 // Obj-C Expressions 616 //===----------------------------------------------------------------------===// 617 618 void StmtDumper::VisitObjCMessageExpr(ObjCMessageExpr* Node) { 619 DumpExpr(Node); 620 OS << " selector=" << Node->getSelector().getAsString(); 621 switch (Node->getReceiverKind()) { 622 case ObjCMessageExpr::Instance: 623 break; 624 625 case ObjCMessageExpr::Class: 626 OS << " class="; 627 DumpType(Node->getClassReceiver()); 628 break; 629 630 case ObjCMessageExpr::SuperInstance: 631 OS << " super (instance)"; 632 break; 633 634 case ObjCMessageExpr::SuperClass: 635 OS << " super (class)"; 636 break; 637 } 638 } 639 640 void StmtDumper::VisitObjCAtCatchStmt(ObjCAtCatchStmt *Node) { 641 DumpStmt(Node); 642 if (VarDecl *CatchParam = Node->getCatchParamDecl()) { 643 OS << " catch parm = "; 644 DumpDeclarator(CatchParam); 645 } else { 646 OS << " catch all"; 647 } 648 } 649 650 void StmtDumper::VisitObjCEncodeExpr(ObjCEncodeExpr *Node) { 651 DumpExpr(Node); 652 OS << " "; 653 DumpType(Node->getEncodedType()); 654 } 655 656 void StmtDumper::VisitObjCSelectorExpr(ObjCSelectorExpr *Node) { 657 DumpExpr(Node); 658 659 OS << " " << Node->getSelector().getAsString(); 660 } 661 662 void StmtDumper::VisitObjCProtocolExpr(ObjCProtocolExpr *Node) { 663 DumpExpr(Node); 664 665 OS << ' ' <<* Node->getProtocol(); 666 } 667 668 void StmtDumper::VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *Node) { 669 DumpExpr(Node); 670 if (Node->isImplicitProperty()) { 671 OS << " Kind=MethodRef Getter=\""; 672 if (Node->getImplicitPropertyGetter()) 673 OS << Node->getImplicitPropertyGetter()->getSelector().getAsString(); 674 else 675 OS << "(null)"; 676 677 OS << "\" Setter=\""; 678 if (ObjCMethodDecl *Setter = Node->getImplicitPropertySetter()) 679 OS << Setter->getSelector().getAsString(); 680 else 681 OS << "(null)"; 682 OS << "\""; 683 } else { 684 OS << " Kind=PropertyRef Property=\"" << *Node->getExplicitProperty() <<'"'; 685 } 686 687 if (Node->isSuperReceiver()) 688 OS << " super"; 689 690 OS << " Messaging="; 691 if (Node->isMessagingGetter() && Node->isMessagingSetter()) 692 OS << "Getter&Setter"; 693 else if (Node->isMessagingGetter()) 694 OS << "Getter"; 695 else if (Node->isMessagingSetter()) 696 OS << "Setter"; 697 } 698 699 void StmtDumper::VisitObjCSubscriptRefExpr(ObjCSubscriptRefExpr *Node) { 700 DumpExpr(Node); 701 if (Node->isArraySubscriptRefExpr()) 702 OS << " Kind=ArraySubscript GetterForArray=\""; 703 else 704 OS << " Kind=DictionarySubscript GetterForDictionary=\""; 705 if (Node->getAtIndexMethodDecl()) 706 OS << Node->getAtIndexMethodDecl()->getSelector().getAsString(); 707 else 708 OS << "(null)"; 709 710 if (Node->isArraySubscriptRefExpr()) 711 OS << "\" SetterForArray=\""; 712 else 713 OS << "\" SetterForDictionary=\""; 714 if (Node->setAtIndexMethodDecl()) 715 OS << Node->setAtIndexMethodDecl()->getSelector().getAsString(); 716 else 717 OS << "(null)"; 718 } 719 720 void StmtDumper::VisitObjCBoolLiteralExpr(ObjCBoolLiteralExpr *Node) { 721 DumpExpr(Node); 722 OS << " " << (Node->getValue() ? "__objc_yes" : "__objc_no"); 723 } 724 725 //===----------------------------------------------------------------------===// 726 // Stmt method implementations 727 //===----------------------------------------------------------------------===// 728 729 /// dump - This does a local dump of the specified AST fragment. It dumps the 730 /// specified node and a few nodes underneath it, but not the whole subtree. 731 /// This is useful in a debugger. 732 void Stmt::dump(SourceManager &SM) const { 733 dump(llvm::errs(), SM); 734 } 735 736 void Stmt::dump(raw_ostream &OS, SourceManager &SM) const { 737 StmtDumper P(&SM, OS, 4); 738 P.DumpSubTree(const_cast<Stmt*>(this)); 739 OS << "\n"; 740 } 741 742 /// dump - This does a local dump of the specified AST fragment. It dumps the 743 /// specified node and a few nodes underneath it, but not the whole subtree. 744 /// This is useful in a debugger. 745 void Stmt::dump() const { 746 StmtDumper P(0, llvm::errs(), 4); 747 P.DumpSubTree(const_cast<Stmt*>(this)); 748 llvm::errs() << "\n"; 749 } 750 751 /// dumpAll - This does a dump of the specified AST fragment and all subtrees. 752 void Stmt::dumpAll(SourceManager &SM) const { 753 StmtDumper P(&SM, llvm::errs(), ~0U); 754 P.DumpSubTree(const_cast<Stmt*>(this)); 755 llvm::errs() << "\n"; 756 } 757 758 /// dumpAll - This does a dump of the specified AST fragment and all subtrees. 759 void Stmt::dumpAll() const { 760 StmtDumper P(0, llvm::errs(), ~0U); 761 P.DumpSubTree(const_cast<Stmt*>(this)); 762 llvm::errs() << "\n"; 763 } 764