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