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