StmtPrinter.cpp revision 97b7f26a92d87e514530a5b652460190ce48c974
1//===--- StmtPrinter.cpp - Printing 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::dumpPretty/Stmt::printPretty methods, which 11// pretty print the AST back out to C code. 12// 13//===----------------------------------------------------------------------===// 14 15#include "clang/AST/StmtVisitor.h" 16#include "clang/AST/Decl.h" 17#include "clang/AST/DeclObjC.h" 18#include "clang/AST/ExprCXX.h" 19#include "clang/AST/PrettyPrinter.h" 20#include "clang/Basic/IdentifierTable.h" 21#include "llvm/Support/Compiler.h" 22#include "llvm/Support/Streams.h" 23#include <iomanip> 24using namespace clang; 25 26//===----------------------------------------------------------------------===// 27// StmtPrinter Visitor 28//===----------------------------------------------------------------------===// 29 30namespace { 31 class VISIBILITY_HIDDEN StmtPrinter : public StmtVisitor<StmtPrinter> { 32 std::ostream &OS; 33 unsigned IndentLevel; 34 clang::PrinterHelper* Helper; 35 public: 36 StmtPrinter(std::ostream &os, PrinterHelper* helper) : 37 OS(os), IndentLevel(0), Helper(helper) {} 38 39 void PrintStmt(Stmt *S, int SubIndent = 1) { 40 IndentLevel += SubIndent; 41 if (S && isa<Expr>(S)) { 42 // If this is an expr used in a stmt context, indent and newline it. 43 Indent(); 44 Visit(S); 45 OS << ";\n"; 46 } else if (S) { 47 Visit(S); 48 } else { 49 Indent() << "<<<NULL STATEMENT>>>\n"; 50 } 51 IndentLevel -= SubIndent; 52 } 53 54 void PrintRawCompoundStmt(CompoundStmt *S); 55 void PrintRawDecl(Decl *D); 56 void PrintRawIfStmt(IfStmt *If); 57 58 void PrintExpr(Expr *E) { 59 if (E) 60 Visit(E); 61 else 62 OS << "<null expr>"; 63 } 64 65 std::ostream &Indent(int Delta = 0) const { 66 for (int i = 0, e = IndentLevel+Delta; i < e; ++i) 67 OS << " "; 68 return OS; 69 } 70 71 bool PrintOffsetOfDesignator(Expr *E); 72 void VisitUnaryOffsetOf(UnaryOperator *Node); 73 74 void Visit(Stmt* S) { 75 if (Helper && Helper->handledStmt(S,OS)) 76 return; 77 else StmtVisitor<StmtPrinter>::Visit(S); 78 } 79 80 void VisitStmt(Stmt *Node); 81#define STMT(N, CLASS, PARENT) \ 82 void Visit##CLASS(CLASS *Node); 83#include "clang/AST/StmtNodes.def" 84 }; 85} 86 87//===----------------------------------------------------------------------===// 88// Stmt printing methods. 89//===----------------------------------------------------------------------===// 90 91void StmtPrinter::VisitStmt(Stmt *Node) { 92 Indent() << "<<unknown stmt type>>\n"; 93} 94 95/// PrintRawCompoundStmt - Print a compound stmt without indenting the {, and 96/// with no newline after the }. 97void StmtPrinter::PrintRawCompoundStmt(CompoundStmt *Node) { 98 OS << "{\n"; 99 for (CompoundStmt::body_iterator I = Node->body_begin(), E = Node->body_end(); 100 I != E; ++I) 101 PrintStmt(*I); 102 103 Indent() << "}"; 104} 105 106void StmtPrinter::PrintRawDecl(Decl *D) { 107 // FIXME: Need to complete/beautify this... this code simply shows the 108 // nodes are where they need to be. 109 if (TypedefDecl *localType = dyn_cast<TypedefDecl>(D)) { 110 OS << "typedef " << localType->getUnderlyingType().getAsString(); 111 OS << " " << localType->getName(); 112 } else if (ValueDecl *VD = dyn_cast<ValueDecl>(D)) { 113 // Emit storage class for vardecls. 114 if (VarDecl *V = dyn_cast<VarDecl>(VD)) { 115 switch (V->getStorageClass()) { 116 default: assert(0 && "Unknown storage class!"); 117 case VarDecl::None: break; 118 case VarDecl::Extern: OS << "extern "; break; 119 case VarDecl::Static: OS << "static "; break; 120 case VarDecl::Auto: OS << "auto "; break; 121 case VarDecl::Register: OS << "register "; break; 122 } 123 } 124 125 std::string Name = VD->getName(); 126 VD->getType().getAsStringInternal(Name); 127 OS << Name; 128 129 // If this is a vardecl with an initializer, emit it. 130 if (VarDecl *V = dyn_cast<VarDecl>(VD)) { 131 if (V->getInit()) { 132 OS << " = "; 133 PrintExpr(V->getInit()); 134 } 135 } 136 } else if (TagDecl *TD = dyn_cast<TagDecl>(D)) { 137 // print a free standing tag decl (e.g. "struct x;"). 138 OS << TD->getKindName(); 139 OS << " "; 140 if (const IdentifierInfo *II = TD->getIdentifier()) 141 OS << II->getName(); 142 else 143 OS << "<anonymous>"; 144 // FIXME: print tag bodies. 145 } else { 146 assert(0 && "Unexpected decl"); 147 } 148} 149 150 151void StmtPrinter::VisitNullStmt(NullStmt *Node) { 152 Indent() << ";\n"; 153} 154 155void StmtPrinter::VisitDeclStmt(DeclStmt *Node) { 156 for (ScopedDecl *D = Node->getDecl(); D; D = D->getNextDeclarator()) { 157 Indent(); 158 PrintRawDecl(D); 159 OS << ";\n"; 160 } 161} 162 163void StmtPrinter::VisitCompoundStmt(CompoundStmt *Node) { 164 Indent(); 165 PrintRawCompoundStmt(Node); 166 OS << "\n"; 167} 168 169void StmtPrinter::VisitCaseStmt(CaseStmt *Node) { 170 Indent(-1) << "case "; 171 PrintExpr(Node->getLHS()); 172 if (Node->getRHS()) { 173 OS << " ... "; 174 PrintExpr(Node->getRHS()); 175 } 176 OS << ":\n"; 177 178 PrintStmt(Node->getSubStmt(), 0); 179} 180 181void StmtPrinter::VisitDefaultStmt(DefaultStmt *Node) { 182 Indent(-1) << "default:\n"; 183 PrintStmt(Node->getSubStmt(), 0); 184} 185 186void StmtPrinter::VisitLabelStmt(LabelStmt *Node) { 187 Indent(-1) << Node->getName() << ":\n"; 188 PrintStmt(Node->getSubStmt(), 0); 189} 190 191void StmtPrinter::PrintRawIfStmt(IfStmt *If) { 192 OS << "if "; 193 PrintExpr(If->getCond()); 194 195 if (CompoundStmt *CS = dyn_cast<CompoundStmt>(If->getThen())) { 196 OS << ' '; 197 PrintRawCompoundStmt(CS); 198 OS << (If->getElse() ? ' ' : '\n'); 199 } else { 200 OS << '\n'; 201 PrintStmt(If->getThen()); 202 if (If->getElse()) Indent(); 203 } 204 205 if (Stmt *Else = If->getElse()) { 206 OS << "else"; 207 208 if (CompoundStmt *CS = dyn_cast<CompoundStmt>(Else)) { 209 OS << ' '; 210 PrintRawCompoundStmt(CS); 211 OS << '\n'; 212 } else if (IfStmt *ElseIf = dyn_cast<IfStmt>(Else)) { 213 OS << ' '; 214 PrintRawIfStmt(ElseIf); 215 } else { 216 OS << '\n'; 217 PrintStmt(If->getElse()); 218 } 219 } 220} 221 222void StmtPrinter::VisitIfStmt(IfStmt *If) { 223 Indent(); 224 PrintRawIfStmt(If); 225} 226 227void StmtPrinter::VisitSwitchStmt(SwitchStmt *Node) { 228 Indent() << "switch ("; 229 PrintExpr(Node->getCond()); 230 OS << ")"; 231 232 // Pretty print compoundstmt bodies (very common). 233 if (CompoundStmt *CS = dyn_cast<CompoundStmt>(Node->getBody())) { 234 OS << " "; 235 PrintRawCompoundStmt(CS); 236 OS << "\n"; 237 } else { 238 OS << "\n"; 239 PrintStmt(Node->getBody()); 240 } 241} 242 243void StmtPrinter::VisitSwitchCase(SwitchCase*) { 244 assert(0 && "SwitchCase is an abstract class"); 245} 246 247void StmtPrinter::VisitWhileStmt(WhileStmt *Node) { 248 Indent() << "while ("; 249 PrintExpr(Node->getCond()); 250 OS << ")\n"; 251 PrintStmt(Node->getBody()); 252} 253 254void StmtPrinter::VisitDoStmt(DoStmt *Node) { 255 Indent() << "do "; 256 if (CompoundStmt *CS = dyn_cast<CompoundStmt>(Node->getBody())) { 257 PrintRawCompoundStmt(CS); 258 OS << " "; 259 } else { 260 OS << "\n"; 261 PrintStmt(Node->getBody()); 262 Indent(); 263 } 264 265 OS << "while "; 266 PrintExpr(Node->getCond()); 267 OS << ";\n"; 268} 269 270void StmtPrinter::VisitForStmt(ForStmt *Node) { 271 Indent() << "for ("; 272 if (Node->getInit()) { 273 if (DeclStmt *DS = dyn_cast<DeclStmt>(Node->getInit())) 274 PrintRawDecl(DS->getDecl()); 275 else 276 PrintExpr(cast<Expr>(Node->getInit())); 277 } 278 OS << ";"; 279 if (Node->getCond()) { 280 OS << " "; 281 PrintExpr(Node->getCond()); 282 } 283 OS << ";"; 284 if (Node->getInc()) { 285 OS << " "; 286 PrintExpr(Node->getInc()); 287 } 288 OS << ") "; 289 290 if (CompoundStmt *CS = dyn_cast<CompoundStmt>(Node->getBody())) { 291 PrintRawCompoundStmt(CS); 292 OS << "\n"; 293 } else { 294 OS << "\n"; 295 PrintStmt(Node->getBody()); 296 } 297} 298 299void StmtPrinter::VisitObjCForCollectionStmt(ObjCForCollectionStmt *Node) { 300 Indent() << "for ("; 301 if (DeclStmt *DS = dyn_cast<DeclStmt>(Node->getElement())) 302 PrintRawDecl(DS->getDecl()); 303 else 304 PrintExpr(cast<Expr>(Node->getElement())); 305 OS << " in "; 306 PrintExpr(Node->getCollection()); 307 OS << ") "; 308 309 if (CompoundStmt *CS = dyn_cast<CompoundStmt>(Node->getBody())) { 310 PrintRawCompoundStmt(CS); 311 OS << "\n"; 312 } else { 313 OS << "\n"; 314 PrintStmt(Node->getBody()); 315 } 316} 317 318void StmtPrinter::VisitGotoStmt(GotoStmt *Node) { 319 Indent() << "goto " << Node->getLabel()->getName() << ";\n"; 320} 321 322void StmtPrinter::VisitIndirectGotoStmt(IndirectGotoStmt *Node) { 323 Indent() << "goto *"; 324 PrintExpr(Node->getTarget()); 325 OS << ";\n"; 326} 327 328void StmtPrinter::VisitContinueStmt(ContinueStmt *Node) { 329 Indent() << "continue;\n"; 330} 331 332void StmtPrinter::VisitBreakStmt(BreakStmt *Node) { 333 Indent() << "break;\n"; 334} 335 336 337void StmtPrinter::VisitReturnStmt(ReturnStmt *Node) { 338 Indent() << "return"; 339 if (Node->getRetValue()) { 340 OS << " "; 341 PrintExpr(Node->getRetValue()); 342 } 343 OS << ";\n"; 344} 345 346 347void StmtPrinter::VisitAsmStmt(AsmStmt *Node) { 348 Indent() << "asm "; 349 350 if (Node->isVolatile()) 351 OS << "volatile "; 352 353 OS << "("; 354 VisitStringLiteral(Node->getAsmString()); 355 356 // Outputs 357 if (Node->getNumOutputs() != 0 || Node->getNumInputs() != 0 || 358 Node->getNumClobbers() != 0) 359 OS << " : "; 360 361 for (unsigned i = 0, e = Node->getNumOutputs(); i != e; ++i) { 362 if (i != 0) 363 OS << ", "; 364 365 if (!Node->getOutputName(i).empty()) { 366 OS << '['; 367 OS << Node->getOutputName(i); 368 OS << "] "; 369 } 370 371 VisitStringLiteral(Node->getOutputConstraint(i)); 372 OS << " "; 373 Visit(Node->getOutputExpr(i)); 374 } 375 376 // Inputs 377 if (Node->getNumInputs() != 0 || Node->getNumClobbers() != 0) 378 OS << " : "; 379 380 for (unsigned i = 0, e = Node->getNumInputs(); i != e; ++i) { 381 if (i != 0) 382 OS << ", "; 383 384 if (!Node->getInputName(i).empty()) { 385 OS << '['; 386 OS << Node->getInputName(i); 387 OS << "] "; 388 } 389 390 VisitStringLiteral(Node->getInputConstraint(i)); 391 OS << " "; 392 Visit(Node->getInputExpr(i)); 393 } 394 395 // Clobbers 396 if (Node->getNumClobbers() != 0) 397 OS << " : "; 398 399 for (unsigned i = 0, e = Node->getNumClobbers(); i != e; ++i) { 400 if (i != 0) 401 OS << ", "; 402 403 VisitStringLiteral(Node->getClobber(i)); 404 } 405 406 OS << ");\n"; 407} 408 409void StmtPrinter::VisitObjCAtTryStmt(ObjCAtTryStmt *Node) { 410 Indent() << "@try"; 411 if (CompoundStmt *TS = dyn_cast<CompoundStmt>(Node->getTryBody())) { 412 PrintRawCompoundStmt(TS); 413 OS << "\n"; 414 } 415 416 for (ObjCAtCatchStmt *catchStmt = 417 static_cast<ObjCAtCatchStmt *>(Node->getCatchStmts()); 418 catchStmt; 419 catchStmt = 420 static_cast<ObjCAtCatchStmt *>(catchStmt->getNextCatchStmt())) { 421 Indent() << "@catch("; 422 if (catchStmt->getCatchParamStmt()) { 423 if (DeclStmt *DS = dyn_cast<DeclStmt>(catchStmt->getCatchParamStmt())) 424 PrintRawDecl(DS->getDecl()); 425 } 426 OS << ")"; 427 if (CompoundStmt *CS = dyn_cast<CompoundStmt>(catchStmt->getCatchBody())) 428 { 429 PrintRawCompoundStmt(CS); 430 OS << "\n"; 431 } 432 } 433 434 if (ObjCAtFinallyStmt *FS =static_cast<ObjCAtFinallyStmt *>( 435 Node->getFinallyStmt())) { 436 Indent() << "@finally"; 437 PrintRawCompoundStmt(dyn_cast<CompoundStmt>(FS->getFinallyBody())); 438 OS << "\n"; 439 } 440} 441 442void StmtPrinter::VisitObjCAtFinallyStmt(ObjCAtFinallyStmt *Node) { 443} 444 445void StmtPrinter::VisitObjCAtCatchStmt (ObjCAtCatchStmt *Node) { 446 Indent() << "@catch (...) { /* todo */ } \n"; 447} 448 449void StmtPrinter::VisitObjCAtThrowStmt(ObjCAtThrowStmt *Node) { 450 Indent() << "@throw"; 451 if (Node->getThrowExpr()) { 452 OS << " "; 453 PrintExpr(Node->getThrowExpr()); 454 } 455 OS << ";\n"; 456} 457 458void StmtPrinter::VisitObjCAtSynchronizedStmt(ObjCAtSynchronizedStmt *Node) { 459 Indent() << "@synchronized ("; 460 PrintExpr(Node->getSynchExpr()); 461 OS << ")"; 462 PrintRawCompoundStmt(Node->getSynchBody()); 463 OS << "\n"; 464} 465 466//===----------------------------------------------------------------------===// 467// Expr printing methods. 468//===----------------------------------------------------------------------===// 469 470void StmtPrinter::VisitExpr(Expr *Node) { 471 OS << "<<unknown expr type>>"; 472} 473 474void StmtPrinter::VisitDeclRefExpr(DeclRefExpr *Node) { 475 OS << Node->getDecl()->getName(); 476} 477 478void StmtPrinter::VisitObjCIvarRefExpr(ObjCIvarRefExpr *Node) { 479 if (Node->getBase()) { 480 PrintExpr(Node->getBase()); 481 OS << (Node->isArrow() ? "->" : "."); 482 } 483 OS << Node->getDecl()->getName(); 484} 485 486void StmtPrinter::VisitPreDefinedExpr(PreDefinedExpr *Node) { 487 switch (Node->getIdentType()) { 488 default: 489 assert(0 && "unknown case"); 490 case PreDefinedExpr::Func: 491 OS << "__func__"; 492 break; 493 case PreDefinedExpr::Function: 494 OS << "__FUNCTION__"; 495 break; 496 case PreDefinedExpr::PrettyFunction: 497 OS << "__PRETTY_FUNCTION__"; 498 break; 499 } 500} 501 502void StmtPrinter::VisitCharacterLiteral(CharacterLiteral *Node) { 503 // FIXME should print an L for wchar_t constants 504 unsigned value = Node->getValue(); 505 switch (value) { 506 case '\\': 507 OS << "'\\\\'"; 508 break; 509 case '\'': 510 OS << "'\\''"; 511 break; 512 case '\a': 513 // TODO: K&R: the meaning of '\\a' is different in traditional C 514 OS << "'\\a'"; 515 break; 516 case '\b': 517 OS << "'\\b'"; 518 break; 519 // Nonstandard escape sequence. 520 /*case '\e': 521 OS << "'\\e'"; 522 break;*/ 523 case '\f': 524 OS << "'\\f'"; 525 break; 526 case '\n': 527 OS << "'\\n'"; 528 break; 529 case '\r': 530 OS << "'\\r'"; 531 break; 532 case '\t': 533 OS << "'\\t'"; 534 break; 535 case '\v': 536 OS << "'\\v'"; 537 break; 538 default: 539 if (value < 256 && isprint(value)) { 540 OS << "'" << (char)value << "'"; 541 } else if (value < 256) { 542 OS << "'\\x" << std::hex << value << std::dec << "'"; 543 } else { 544 // FIXME what to really do here? 545 OS << value; 546 } 547 } 548} 549 550void StmtPrinter::VisitIntegerLiteral(IntegerLiteral *Node) { 551 bool isSigned = Node->getType()->isSignedIntegerType(); 552 OS << Node->getValue().toString(10, isSigned); 553 554 // Emit suffixes. Integer literals are always a builtin integer type. 555 switch (cast<BuiltinType>(Node->getType().getCanonicalType())->getKind()) { 556 default: assert(0 && "Unexpected type for integer literal!"); 557 case BuiltinType::Int: break; // no suffix. 558 case BuiltinType::UInt: OS << 'U'; break; 559 case BuiltinType::Long: OS << 'L'; break; 560 case BuiltinType::ULong: OS << "UL"; break; 561 case BuiltinType::LongLong: OS << "LL"; break; 562 case BuiltinType::ULongLong: OS << "ULL"; break; 563 } 564} 565void StmtPrinter::VisitFloatingLiteral(FloatingLiteral *Node) { 566 // FIXME: print value more precisely. 567 OS << Node->getValueAsDouble(); 568} 569 570void StmtPrinter::VisitImaginaryLiteral(ImaginaryLiteral *Node) { 571 PrintExpr(Node->getSubExpr()); 572 OS << "i"; 573} 574 575void StmtPrinter::VisitStringLiteral(StringLiteral *Str) { 576 if (Str->isWide()) OS << 'L'; 577 OS << '"'; 578 579 // FIXME: this doesn't print wstrings right. 580 for (unsigned i = 0, e = Str->getByteLength(); i != e; ++i) { 581 switch (Str->getStrData()[i]) { 582 default: OS << Str->getStrData()[i]; break; 583 // Handle some common ones to make dumps prettier. 584 case '\\': OS << "\\\\"; break; 585 case '"': OS << "\\\""; break; 586 case '\n': OS << "\\n"; break; 587 case '\t': OS << "\\t"; break; 588 case '\a': OS << "\\a"; break; 589 case '\b': OS << "\\b"; break; 590 } 591 } 592 OS << '"'; 593} 594void StmtPrinter::VisitParenExpr(ParenExpr *Node) { 595 OS << "("; 596 PrintExpr(Node->getSubExpr()); 597 OS << ")"; 598} 599void StmtPrinter::VisitUnaryOperator(UnaryOperator *Node) { 600 if (!Node->isPostfix()) { 601 OS << UnaryOperator::getOpcodeStr(Node->getOpcode()); 602 603 // Print a space if this is an "identifier operator" like sizeof or __real. 604 switch (Node->getOpcode()) { 605 default: break; 606 case UnaryOperator::SizeOf: 607 case UnaryOperator::AlignOf: 608 case UnaryOperator::Real: 609 case UnaryOperator::Imag: 610 case UnaryOperator::Extension: 611 OS << ' '; 612 break; 613 } 614 } 615 PrintExpr(Node->getSubExpr()); 616 617 if (Node->isPostfix()) 618 OS << UnaryOperator::getOpcodeStr(Node->getOpcode()); 619} 620 621bool StmtPrinter::PrintOffsetOfDesignator(Expr *E) { 622 if (isa<CompoundLiteralExpr>(E)) { 623 // Base case, print the type and comma. 624 OS << E->getType().getAsString() << ", "; 625 return true; 626 } else if (ArraySubscriptExpr *ASE = dyn_cast<ArraySubscriptExpr>(E)) { 627 PrintOffsetOfDesignator(ASE->getLHS()); 628 OS << "["; 629 PrintExpr(ASE->getRHS()); 630 OS << "]"; 631 return false; 632 } else { 633 MemberExpr *ME = cast<MemberExpr>(E); 634 bool IsFirst = PrintOffsetOfDesignator(ME->getBase()); 635 OS << (IsFirst ? "" : ".") << ME->getMemberDecl()->getName(); 636 return false; 637 } 638} 639 640void StmtPrinter::VisitUnaryOffsetOf(UnaryOperator *Node) { 641 OS << "__builtin_offsetof("; 642 PrintOffsetOfDesignator(Node->getSubExpr()); 643 OS << ")"; 644} 645 646void StmtPrinter::VisitSizeOfAlignOfTypeExpr(SizeOfAlignOfTypeExpr *Node) { 647 OS << (Node->isSizeOf() ? "sizeof(" : "__alignof("); 648 OS << Node->getArgumentType().getAsString() << ")"; 649} 650void StmtPrinter::VisitArraySubscriptExpr(ArraySubscriptExpr *Node) { 651 PrintExpr(Node->getLHS()); 652 OS << "["; 653 PrintExpr(Node->getRHS()); 654 OS << "]"; 655} 656 657void StmtPrinter::VisitCallExpr(CallExpr *Call) { 658 PrintExpr(Call->getCallee()); 659 OS << "("; 660 for (unsigned i = 0, e = Call->getNumArgs(); i != e; ++i) { 661 if (isa<CXXDefaultArgExpr>(Call->getArg(i))) { 662 // Don't print any defaulted arguments 663 break; 664 } 665 666 if (i) OS << ", "; 667 PrintExpr(Call->getArg(i)); 668 } 669 OS << ")"; 670} 671void StmtPrinter::VisitMemberExpr(MemberExpr *Node) { 672 PrintExpr(Node->getBase()); 673 OS << (Node->isArrow() ? "->" : "."); 674 675 FieldDecl *Field = Node->getMemberDecl(); 676 assert(Field && "MemberExpr should alway reference a field!"); 677 OS << Field->getName(); 678} 679void StmtPrinter::VisitOCUVectorElementExpr(OCUVectorElementExpr *Node) { 680 PrintExpr(Node->getBase()); 681 OS << "."; 682 OS << Node->getAccessor().getName(); 683} 684void StmtPrinter::VisitCastExpr(CastExpr *Node) { 685 OS << "(" << Node->getType().getAsString() << ")"; 686 PrintExpr(Node->getSubExpr()); 687} 688void StmtPrinter::VisitCompoundLiteralExpr(CompoundLiteralExpr *Node) { 689 OS << "(" << Node->getType().getAsString() << ")"; 690 PrintExpr(Node->getInitializer()); 691} 692void StmtPrinter::VisitImplicitCastExpr(ImplicitCastExpr *Node) { 693 // No need to print anything, simply forward to the sub expression. 694 PrintExpr(Node->getSubExpr()); 695} 696void StmtPrinter::VisitBinaryOperator(BinaryOperator *Node) { 697 PrintExpr(Node->getLHS()); 698 OS << " " << BinaryOperator::getOpcodeStr(Node->getOpcode()) << " "; 699 PrintExpr(Node->getRHS()); 700} 701void StmtPrinter::VisitCompoundAssignOperator(CompoundAssignOperator *Node) { 702 PrintExpr(Node->getLHS()); 703 OS << " " << BinaryOperator::getOpcodeStr(Node->getOpcode()) << " "; 704 PrintExpr(Node->getRHS()); 705} 706void StmtPrinter::VisitConditionalOperator(ConditionalOperator *Node) { 707 PrintExpr(Node->getCond()); 708 709 if (Node->getLHS()) { 710 OS << " ? "; 711 PrintExpr(Node->getLHS()); 712 OS << " : "; 713 } 714 else { // Handle GCC extention where LHS can be NULL. 715 OS << " ?: "; 716 } 717 718 PrintExpr(Node->getRHS()); 719} 720 721// GNU extensions. 722 723void StmtPrinter::VisitAddrLabelExpr(AddrLabelExpr *Node) { 724 OS << "&&" << Node->getLabel()->getName(); 725} 726 727void StmtPrinter::VisitStmtExpr(StmtExpr *E) { 728 OS << "("; 729 PrintRawCompoundStmt(E->getSubStmt()); 730 OS << ")"; 731} 732 733void StmtPrinter::VisitTypesCompatibleExpr(TypesCompatibleExpr *Node) { 734 OS << "__builtin_types_compatible_p("; 735 OS << Node->getArgType1().getAsString() << ","; 736 OS << Node->getArgType2().getAsString() << ")"; 737} 738 739void StmtPrinter::VisitChooseExpr(ChooseExpr *Node) { 740 OS << "__builtin_choose_expr("; 741 PrintExpr(Node->getCond()); 742 OS << ", "; 743 PrintExpr(Node->getLHS()); 744 OS << ", "; 745 PrintExpr(Node->getRHS()); 746 OS << ")"; 747} 748 749void StmtPrinter::VisitOverloadExpr(OverloadExpr *Node) { 750 OS << "__builtin_overload("; 751 for (unsigned i = 0, e = Node->getNumSubExprs(); i != e; ++i) { 752 if (i) OS << ", "; 753 PrintExpr(Node->getExpr(i)); 754 } 755 OS << ")"; 756} 757 758void StmtPrinter::VisitInitListExpr(InitListExpr* Node) { 759 OS << "{ "; 760 for (unsigned i = 0, e = Node->getNumInits(); i != e; ++i) { 761 if (i) OS << ", "; 762 PrintExpr(Node->getInit(i)); 763 } 764 OS << " }"; 765} 766 767void StmtPrinter::VisitVAArgExpr(VAArgExpr *Node) { 768 OS << "va_arg("; 769 PrintExpr(Node->getSubExpr()); 770 OS << ", "; 771 OS << Node->getType().getAsString(); 772 OS << ")"; 773} 774 775// C++ 776 777void StmtPrinter::VisitCXXCastExpr(CXXCastExpr *Node) { 778 OS << CXXCastExpr::getOpcodeStr(Node->getOpcode()) << '<'; 779 OS << Node->getDestType().getAsString() << ">("; 780 PrintExpr(Node->getSubExpr()); 781 OS << ")"; 782} 783 784void StmtPrinter::VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *Node) { 785 OS << (Node->getValue() ? "true" : "false"); 786} 787 788void StmtPrinter::VisitCXXThrowExpr(CXXThrowExpr *Node) { 789 if (Node->getSubExpr() == 0) 790 OS << "throw"; 791 else { 792 OS << "throw "; 793 PrintExpr(Node->getSubExpr()); 794 } 795} 796 797void StmtPrinter::VisitCXXDefaultArgExpr(CXXDefaultArgExpr *Node) { 798 // Nothing to print: we picked up the default argument 799} 800 801// Obj-C 802 803void StmtPrinter::VisitObjCStringLiteral(ObjCStringLiteral *Node) { 804 OS << "@"; 805 VisitStringLiteral(Node->getString()); 806} 807 808void StmtPrinter::VisitObjCEncodeExpr(ObjCEncodeExpr *Node) { 809 OS << "@encode(" << Node->getEncodedType().getAsString() << ")"; 810} 811 812void StmtPrinter::VisitObjCSelectorExpr(ObjCSelectorExpr *Node) { 813 OS << "@selector(" << Node->getSelector().getName() << ")"; 814} 815 816void StmtPrinter::VisitObjCProtocolExpr(ObjCProtocolExpr *Node) { 817 OS << "@protocol(" << Node->getProtocol()->getName() << ")"; 818} 819 820void StmtPrinter::VisitObjCMessageExpr(ObjCMessageExpr *Mess) { 821 OS << "["; 822 Expr *receiver = Mess->getReceiver(); 823 if (receiver) PrintExpr(receiver); 824 else OS << Mess->getClassName()->getName(); 825 Selector selector = Mess->getSelector(); 826 if (selector.isUnarySelector()) { 827 OS << " " << selector.getIdentifierInfoForSlot(0)->getName(); 828 } else { 829 for (unsigned i = 0, e = Mess->getNumArgs(); i != e; ++i) { 830 if (selector.getIdentifierInfoForSlot(i)) 831 OS << selector.getIdentifierInfoForSlot(i)->getName() << ":"; 832 else 833 OS << ":"; 834 PrintExpr(Mess->getArg(i)); 835 } 836 } 837 OS << "]"; 838} 839 840//===----------------------------------------------------------------------===// 841// Stmt method implementations 842//===----------------------------------------------------------------------===// 843 844void Stmt::dumpPretty() const { 845 printPretty(*llvm::cerr.stream()); 846} 847 848void Stmt::printPretty(std::ostream &OS, PrinterHelper* Helper) const { 849 if (this == 0) { 850 OS << "<NULL>"; 851 return; 852 } 853 854 StmtPrinter P(OS, Helper); 855 P.Visit(const_cast<Stmt*>(this)); 856} 857 858//===----------------------------------------------------------------------===// 859// PrinterHelper 860//===----------------------------------------------------------------------===// 861 862// Implement virtual destructor. 863PrinterHelper::~PrinterHelper() {} 864