clang API Documentation

StmtDumper.cpp
Go to the documentation of this file.
00001 //===--- StmtDumper.cpp - Dumping implementation for Stmt ASTs ------------===//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 //
00010 // This file implements the Stmt::dump/Stmt::print methods, which dump out the
00011 // AST in a form that exposes type details and other fields.
00012 //
00013 //===----------------------------------------------------------------------===//
00014 
00015 #include "clang/AST/StmtVisitor.h"
00016 #include "clang/AST/DeclObjC.h"
00017 #include "clang/AST/DeclCXX.h"
00018 #include "clang/AST/PrettyPrinter.h"
00019 #include "clang/Basic/SourceManager.h"
00020 #include "llvm/Support/raw_ostream.h"
00021 using namespace clang;
00022 
00023 //===----------------------------------------------------------------------===//
00024 // StmtDumper Visitor
00025 //===----------------------------------------------------------------------===//
00026 
00027 namespace  {
00028   class StmtDumper : public StmtVisitor<StmtDumper> {
00029     SourceManager *SM;
00030     raw_ostream &OS;
00031     unsigned IndentLevel;
00032 
00033     /// MaxDepth - When doing a normal dump (not dumpAll) we only want to dump
00034     /// the first few levels of an AST.  This keeps track of how many ast levels
00035     /// are left.
00036     unsigned MaxDepth;
00037 
00038     /// LastLocFilename/LastLocLine - Keep track of the last location we print
00039     /// out so that we can print out deltas from then on out.
00040     const char *LastLocFilename;
00041     unsigned LastLocLine;
00042 
00043   public:
00044     StmtDumper(SourceManager *sm, raw_ostream &os, unsigned maxDepth)
00045       : SM(sm), OS(os), IndentLevel(0-1), MaxDepth(maxDepth) {
00046       LastLocFilename = "";
00047       LastLocLine = ~0U;
00048     }
00049 
00050     void DumpSubTree(Stmt *S) {
00051       // Prune the recursion if not using dump all.
00052       if (MaxDepth == 0) return;
00053 
00054       ++IndentLevel;
00055       if (S) {
00056         if (DeclStmt* DS = dyn_cast<DeclStmt>(S))
00057           VisitDeclStmt(DS);
00058         else {
00059           Visit(S);
00060 
00061           // Print out children.
00062           Stmt::child_range CI = S->children();
00063           if (CI) {
00064             while (CI) {
00065               OS << '\n';
00066               DumpSubTree(*CI++);
00067             }
00068           }
00069         }
00070         OS << ')';
00071       } else {
00072         Indent();
00073         OS << "<<<NULL>>>";
00074       }
00075       --IndentLevel;
00076     }
00077 
00078     void DumpDeclarator(Decl *D);
00079 
00080     void Indent() const {
00081       for (int i = 0, e = IndentLevel; i < e; ++i)
00082         OS << "  ";
00083     }
00084 
00085     void DumpType(QualType T) {
00086       SplitQualType T_split = T.split();
00087       OS << "'" << QualType::getAsString(T_split) << "'";
00088 
00089       if (!T.isNull()) {
00090         // If the type is sugared, also dump a (shallow) desugared type.
00091         SplitQualType D_split = T.getSplitDesugaredType();
00092         if (T_split != D_split)
00093           OS << ":'" << QualType::getAsString(D_split) << "'";
00094       }
00095     }
00096     void DumpDeclRef(Decl *node);
00097     void DumpStmt(const Stmt *Node) {
00098       Indent();
00099       OS << "(" << Node->getStmtClassName()
00100          << " " << (void*)Node;
00101       DumpSourceRange(Node);
00102     }
00103     void DumpValueKind(ExprValueKind K) {
00104       switch (K) {
00105       case VK_RValue: break;
00106       case VK_LValue: OS << " lvalue"; break;
00107       case VK_XValue: OS << " xvalue"; break;
00108       }
00109     }
00110     void DumpObjectKind(ExprObjectKind K) {
00111       switch (K) {
00112       case OK_Ordinary: break;
00113       case OK_BitField: OS << " bitfield"; break;
00114       case OK_ObjCProperty: OS << " objcproperty"; break;
00115       case OK_ObjCSubscript: OS << " objcsubscript"; break;
00116       case OK_VectorComponent: OS << " vectorcomponent"; break;
00117       }
00118     }
00119     void DumpExpr(const Expr *Node) {
00120       DumpStmt(Node);
00121       OS << ' ';
00122       DumpType(Node->getType());
00123       DumpValueKind(Node->getValueKind());
00124       DumpObjectKind(Node->getObjectKind());
00125     }
00126     void DumpSourceRange(const Stmt *Node);
00127     void DumpLocation(SourceLocation Loc);
00128 
00129     // Stmts.
00130     void VisitStmt(Stmt *Node);
00131     void VisitDeclStmt(DeclStmt *Node);
00132     void VisitLabelStmt(LabelStmt *Node);
00133     void VisitGotoStmt(GotoStmt *Node);
00134 
00135     // Exprs
00136     void VisitExpr(Expr *Node);
00137     void VisitCastExpr(CastExpr *Node);
00138     void VisitDeclRefExpr(DeclRefExpr *Node);
00139     void VisitPredefinedExpr(PredefinedExpr *Node);
00140     void VisitCharacterLiteral(CharacterLiteral *Node);
00141     void VisitIntegerLiteral(IntegerLiteral *Node);
00142     void VisitFloatingLiteral(FloatingLiteral *Node);
00143     void VisitStringLiteral(StringLiteral *Str);
00144     void VisitUnaryOperator(UnaryOperator *Node);
00145     void VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *Node);
00146     void VisitMemberExpr(MemberExpr *Node);
00147     void VisitExtVectorElementExpr(ExtVectorElementExpr *Node);
00148     void VisitBinaryOperator(BinaryOperator *Node);
00149     void VisitCompoundAssignOperator(CompoundAssignOperator *Node);
00150     void VisitAddrLabelExpr(AddrLabelExpr *Node);
00151     void VisitBlockExpr(BlockExpr *Node);
00152     void VisitOpaqueValueExpr(OpaqueValueExpr *Node);
00153 
00154     // C++
00155     void VisitCXXNamedCastExpr(CXXNamedCastExpr *Node);
00156     void VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *Node);
00157     void VisitCXXThisExpr(CXXThisExpr *Node);
00158     void VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *Node);
00159     void VisitCXXConstructExpr(CXXConstructExpr *Node);
00160     void VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *Node);
00161     void VisitExprWithCleanups(ExprWithCleanups *Node);
00162     void VisitUnresolvedLookupExpr(UnresolvedLookupExpr *Node);
00163     void DumpCXXTemporary(CXXTemporary *Temporary);
00164 
00165     // ObjC
00166     void VisitObjCAtCatchStmt(ObjCAtCatchStmt *Node);
00167     void VisitObjCEncodeExpr(ObjCEncodeExpr *Node);
00168     void VisitObjCMessageExpr(ObjCMessageExpr* Node);
00169     void VisitObjCBoxedExpr(ObjCBoxedExpr* Node);
00170     void VisitObjCSelectorExpr(ObjCSelectorExpr *Node);
00171     void VisitObjCProtocolExpr(ObjCProtocolExpr *Node);
00172     void VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *Node);
00173     void VisitObjCSubscriptRefExpr(ObjCSubscriptRefExpr *Node);
00174     void VisitObjCIvarRefExpr(ObjCIvarRefExpr *Node);
00175     void VisitObjCBoolLiteralExpr(ObjCBoolLiteralExpr *Node);
00176   };
00177 }
00178 
00179 //===----------------------------------------------------------------------===//
00180 //  Utilities
00181 //===----------------------------------------------------------------------===//
00182 
00183 void StmtDumper::DumpLocation(SourceLocation Loc) {
00184   SourceLocation SpellingLoc = SM->getSpellingLoc(Loc);
00185 
00186   // The general format we print out is filename:line:col, but we drop pieces
00187   // that haven't changed since the last loc printed.
00188   PresumedLoc PLoc = SM->getPresumedLoc(SpellingLoc);
00189 
00190   if (PLoc.isInvalid()) {
00191     OS << "<invalid sloc>";
00192     return;
00193   }
00194 
00195   if (strcmp(PLoc.getFilename(), LastLocFilename) != 0) {
00196     OS << PLoc.getFilename() << ':' << PLoc.getLine()
00197        << ':' << PLoc.getColumn();
00198     LastLocFilename = PLoc.getFilename();
00199     LastLocLine = PLoc.getLine();
00200   } else if (PLoc.getLine() != LastLocLine) {
00201     OS << "line" << ':' << PLoc.getLine()
00202        << ':' << PLoc.getColumn();
00203     LastLocLine = PLoc.getLine();
00204   } else {
00205     OS << "col" << ':' << PLoc.getColumn();
00206   }
00207 }
00208 
00209 void StmtDumper::DumpSourceRange(const Stmt *Node) {
00210   // Can't translate locations if a SourceManager isn't available.
00211   if (SM == 0) return;
00212 
00213   // TODO: If the parent expression is available, we can print a delta vs its
00214   // location.
00215   SourceRange R = Node->getSourceRange();
00216 
00217   OS << " <";
00218   DumpLocation(R.getBegin());
00219   if (R.getBegin() != R.getEnd()) {
00220     OS << ", ";
00221     DumpLocation(R.getEnd());
00222   }
00223   OS << ">";
00224 
00225   // <t2.c:123:421[blah], t2.c:412:321>
00226 
00227 }
00228 
00229 
00230 //===----------------------------------------------------------------------===//
00231 //  Stmt printing methods.
00232 //===----------------------------------------------------------------------===//
00233 
00234 void StmtDumper::VisitStmt(Stmt *Node) {
00235   DumpStmt(Node);
00236 }
00237 
00238 void StmtDumper::DumpDeclarator(Decl *D) {
00239   // FIXME: Need to complete/beautify this... this code simply shows the
00240   // nodes are where they need to be.
00241   if (TypedefDecl *localType = dyn_cast<TypedefDecl>(D)) {
00242     OS << "\"typedef " << localType->getUnderlyingType().getAsString()
00243        << ' ' << *localType << '"';
00244   } else if (TypeAliasDecl *localType = dyn_cast<TypeAliasDecl>(D)) {
00245     OS << "\"using " << *localType << " = "
00246        << localType->getUnderlyingType().getAsString() << '"';
00247   } else if (ValueDecl *VD = dyn_cast<ValueDecl>(D)) {
00248     OS << "\"";
00249     // Emit storage class for vardecls.
00250     if (VarDecl *V = dyn_cast<VarDecl>(VD)) {
00251       if (V->getStorageClass() != SC_None)
00252         OS << VarDecl::getStorageClassSpecifierString(V->getStorageClass())
00253            << " ";
00254     }
00255 
00256     std::string Name = VD->getNameAsString();
00257     VD->getType().getAsStringInternal(Name,
00258                           PrintingPolicy(VD->getASTContext().getLangOpts()));
00259     OS << Name;
00260 
00261     // If this is a vardecl with an initializer, emit it.
00262     if (VarDecl *V = dyn_cast<VarDecl>(VD)) {
00263       if (V->getInit()) {
00264         OS << " =\n";
00265         DumpSubTree(V->getInit());
00266       }
00267     }
00268     OS << '"';
00269   } else if (TagDecl *TD = dyn_cast<TagDecl>(D)) {
00270     // print a free standing tag decl (e.g. "struct x;").
00271     const char *tagname;
00272     if (const IdentifierInfo *II = TD->getIdentifier())
00273       tagname = II->getNameStart();
00274     else
00275       tagname = "<anonymous>";
00276     OS << '"' << TD->getKindName() << ' ' << tagname << ";\"";
00277     // FIXME: print tag bodies.
00278   } else if (UsingDirectiveDecl *UD = dyn_cast<UsingDirectiveDecl>(D)) {
00279     // print using-directive decl (e.g. "using namespace x;")
00280     const char *ns;
00281     if (const IdentifierInfo *II = UD->getNominatedNamespace()->getIdentifier())
00282       ns = II->getNameStart();
00283     else
00284       ns = "<anonymous>";
00285     OS << '"' << UD->getDeclKindName() << ns << ";\"";
00286   } else if (UsingDecl *UD = dyn_cast<UsingDecl>(D)) {
00287     // print using decl (e.g. "using std::string;")
00288     const char *tn = UD->isTypeName() ? "typename " : "";
00289     OS << '"' << UD->getDeclKindName() << tn;
00290     UD->getQualifier()->print(OS,
00291                         PrintingPolicy(UD->getASTContext().getLangOpts()));
00292     OS << ";\"";
00293   } else if (LabelDecl *LD = dyn_cast<LabelDecl>(D)) {
00294     OS << "label " << *LD;
00295   } else if (StaticAssertDecl *SAD = dyn_cast<StaticAssertDecl>(D)) {
00296     OS << "\"static_assert(\n";
00297     DumpSubTree(SAD->getAssertExpr());
00298     OS << ",\n";
00299     DumpSubTree(SAD->getMessage());
00300     OS << ");\"";
00301   } else {
00302     llvm_unreachable("Unexpected decl");
00303   }
00304 }
00305 
00306 void StmtDumper::VisitDeclStmt(DeclStmt *Node) {
00307   DumpStmt(Node);
00308   OS << "\n";
00309   for (DeclStmt::decl_iterator DI = Node->decl_begin(), DE = Node->decl_end();
00310        DI != DE; ++DI) {
00311     Decl* D = *DI;
00312     ++IndentLevel;
00313     Indent();
00314     OS << (void*) D << " ";
00315     DumpDeclarator(D);
00316     if (DI+1 != DE)
00317       OS << "\n";
00318     --IndentLevel;
00319   }
00320 }
00321 
00322 void StmtDumper::VisitLabelStmt(LabelStmt *Node) {
00323   DumpStmt(Node);
00324   OS << " '" << Node->getName() << "'";
00325 }
00326 
00327 void StmtDumper::VisitGotoStmt(GotoStmt *Node) {
00328   DumpStmt(Node);
00329   OS << " '" << Node->getLabel()->getName()
00330      << "':" << (void*)Node->getLabel();
00331 }
00332 
00333 //===----------------------------------------------------------------------===//
00334 //  Expr printing methods.
00335 //===----------------------------------------------------------------------===//
00336 
00337 void StmtDumper::VisitExpr(Expr *Node) {
00338   DumpExpr(Node);
00339 }
00340 
00341 static void DumpBasePath(raw_ostream &OS, CastExpr *Node) {
00342   if (Node->path_empty())
00343     return;
00344 
00345   OS << " (";
00346   bool First = true;
00347   for (CastExpr::path_iterator
00348          I = Node->path_begin(), E = Node->path_end(); I != E; ++I) {
00349     const CXXBaseSpecifier *Base = *I;
00350     if (!First)
00351       OS << " -> ";
00352     
00353     const CXXRecordDecl *RD =
00354     cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
00355     
00356     if (Base->isVirtual())
00357       OS << "virtual ";
00358     OS << RD->getName();
00359     First = false;
00360   }
00361     
00362   OS << ')';
00363 }
00364 
00365 void StmtDumper::VisitCastExpr(CastExpr *Node) {
00366   DumpExpr(Node);
00367   OS << " <" << Node->getCastKindName();
00368   DumpBasePath(OS, Node);
00369   OS << ">";
00370 }
00371 
00372 void StmtDumper::VisitDeclRefExpr(DeclRefExpr *Node) {
00373   DumpExpr(Node);
00374 
00375   OS << " ";
00376   DumpDeclRef(Node->getDecl());
00377   if (Node->getDecl() != Node->getFoundDecl()) {
00378     OS << " (";
00379     DumpDeclRef(Node->getFoundDecl());
00380     OS << ")";
00381   }
00382 }
00383 
00384 void StmtDumper::DumpDeclRef(Decl *d) {
00385   OS << d->getDeclKindName() << ' ' << (void*) d;
00386 
00387   if (NamedDecl *nd = dyn_cast<NamedDecl>(d)) {
00388     OS << " '";
00389     nd->getDeclName().printName(OS);
00390     OS << "'";
00391   }
00392 
00393   if (ValueDecl *vd = dyn_cast<ValueDecl>(d)) {
00394     OS << ' '; DumpType(vd->getType());
00395   }
00396 }
00397 
00398 void StmtDumper::VisitUnresolvedLookupExpr(UnresolvedLookupExpr *Node) {
00399   DumpExpr(Node);
00400   OS << " (";
00401   if (!Node->requiresADL()) OS << "no ";
00402   OS << "ADL) = '" << Node->getName() << '\'';
00403 
00404   UnresolvedLookupExpr::decls_iterator
00405     I = Node->decls_begin(), E = Node->decls_end();
00406   if (I == E) OS << " empty";
00407   for (; I != E; ++I)
00408     OS << " " << (void*) *I;
00409 }
00410 
00411 void StmtDumper::VisitObjCIvarRefExpr(ObjCIvarRefExpr *Node) {
00412   DumpExpr(Node);
00413 
00414   OS << " " << Node->getDecl()->getDeclKindName()
00415      << "Decl='" << *Node->getDecl()
00416      << "' " << (void*)Node->getDecl();
00417   if (Node->isFreeIvar())
00418     OS << " isFreeIvar";
00419 }
00420 
00421 void StmtDumper::VisitPredefinedExpr(PredefinedExpr *Node) {
00422   DumpExpr(Node);
00423   switch (Node->getIdentType()) {
00424   default: llvm_unreachable("unknown case");
00425   case PredefinedExpr::Func:           OS <<  " __func__"; break;
00426   case PredefinedExpr::Function:       OS <<  " __FUNCTION__"; break;
00427   case PredefinedExpr::PrettyFunction: OS <<  " __PRETTY_FUNCTION__";break;
00428   }
00429 }
00430 
00431 void StmtDumper::VisitCharacterLiteral(CharacterLiteral *Node) {
00432   DumpExpr(Node);
00433   OS << " " << Node->getValue();
00434 }
00435 
00436 void StmtDumper::VisitIntegerLiteral(IntegerLiteral *Node) {
00437   DumpExpr(Node);
00438 
00439   bool isSigned = Node->getType()->isSignedIntegerType();
00440   OS << " " << Node->getValue().toString(10, isSigned);
00441 }
00442 void StmtDumper::VisitFloatingLiteral(FloatingLiteral *Node) {
00443   DumpExpr(Node);
00444   OS << " " << Node->getValueAsApproximateDouble();
00445 }
00446 
00447 void StmtDumper::VisitStringLiteral(StringLiteral *Str) {
00448   DumpExpr(Str);
00449   // FIXME: this doesn't print wstrings right.
00450   OS << " ";
00451   switch (Str->getKind()) {
00452   case StringLiteral::Ascii: break; // No prefix
00453   case StringLiteral::Wide:  OS << 'L'; break;
00454   case StringLiteral::UTF8:  OS << "u8"; break;
00455   case StringLiteral::UTF16: OS << 'u'; break;
00456   case StringLiteral::UTF32: OS << 'U'; break;
00457   }
00458   OS << '"';
00459   OS.write_escaped(Str->getString());
00460   OS << '"';
00461 }
00462 
00463 void StmtDumper::VisitUnaryOperator(UnaryOperator *Node) {
00464   DumpExpr(Node);
00465   OS << " " << (Node->isPostfix() ? "postfix" : "prefix")
00466      << " '" << UnaryOperator::getOpcodeStr(Node->getOpcode()) << "'";
00467 }
00468 void StmtDumper::VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *Node) {
00469   DumpExpr(Node);
00470   switch(Node->getKind()) {
00471   case UETT_SizeOf:
00472     OS << " sizeof ";
00473     break;
00474   case UETT_AlignOf:
00475     OS << " __alignof ";
00476     break;
00477   case UETT_VecStep:
00478     OS << " vec_step ";
00479     break;
00480   }
00481   if (Node->isArgumentType())
00482     DumpType(Node->getArgumentType());
00483 }
00484 
00485 void StmtDumper::VisitMemberExpr(MemberExpr *Node) {
00486   DumpExpr(Node);
00487   OS << " " << (Node->isArrow() ? "->" : ".")
00488      << *Node->getMemberDecl() << ' '
00489      << (void*)Node->getMemberDecl();
00490 }
00491 void StmtDumper::VisitExtVectorElementExpr(ExtVectorElementExpr *Node) {
00492   DumpExpr(Node);
00493   OS << " " << Node->getAccessor().getNameStart();
00494 }
00495 void StmtDumper::VisitBinaryOperator(BinaryOperator *Node) {
00496   DumpExpr(Node);
00497   OS << " '" << BinaryOperator::getOpcodeStr(Node->getOpcode()) << "'";
00498 }
00499 void StmtDumper::VisitCompoundAssignOperator(CompoundAssignOperator *Node) {
00500   DumpExpr(Node);
00501   OS << " '" << BinaryOperator::getOpcodeStr(Node->getOpcode())
00502      << "' ComputeLHSTy=";
00503   DumpType(Node->getComputationLHSType());
00504   OS << " ComputeResultTy=";
00505   DumpType(Node->getComputationResultType());
00506 }
00507 
00508 void StmtDumper::VisitBlockExpr(BlockExpr *Node) {
00509   DumpExpr(Node);
00510 
00511   BlockDecl *block = Node->getBlockDecl();
00512   OS << " decl=" << block;
00513 
00514   IndentLevel++;
00515   if (block->capturesCXXThis()) {
00516     OS << '\n'; Indent(); OS << "(capture this)";
00517   }
00518   for (BlockDecl::capture_iterator
00519          i = block->capture_begin(), e = block->capture_end(); i != e; ++i) {
00520     OS << '\n';
00521     Indent();
00522     OS << "(capture ";
00523     if (i->isByRef()) OS << "byref ";
00524     if (i->isNested()) OS << "nested ";
00525     if (i->getVariable())
00526       DumpDeclRef(i->getVariable());
00527     if (i->hasCopyExpr()) DumpSubTree(i->getCopyExpr());
00528     OS << ")";
00529   }
00530   IndentLevel--;
00531 
00532   OS << '\n';
00533   DumpSubTree(block->getBody());
00534 }
00535 
00536 void StmtDumper::VisitOpaqueValueExpr(OpaqueValueExpr *Node) {
00537   DumpExpr(Node);
00538 
00539   if (Expr *Source = Node->getSourceExpr()) {
00540     OS << '\n';
00541     DumpSubTree(Source);
00542   }
00543 }
00544 
00545 // GNU extensions.
00546 
00547 void StmtDumper::VisitAddrLabelExpr(AddrLabelExpr *Node) {
00548   DumpExpr(Node);
00549   OS << " " << Node->getLabel()->getName()
00550      << " " << (void*)Node->getLabel();
00551 }
00552 
00553 //===----------------------------------------------------------------------===//
00554 // C++ Expressions
00555 //===----------------------------------------------------------------------===//
00556 
00557 void StmtDumper::VisitCXXNamedCastExpr(CXXNamedCastExpr *Node) {
00558   DumpExpr(Node);
00559   OS << " " << Node->getCastName() 
00560      << "<" << Node->getTypeAsWritten().getAsString() << ">"
00561      << " <" << Node->getCastKindName();
00562   DumpBasePath(OS, Node);
00563   OS << ">";
00564 }
00565 
00566 void StmtDumper::VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *Node) {
00567   DumpExpr(Node);
00568   OS << " " << (Node->getValue() ? "true" : "false");
00569 }
00570 
00571 void StmtDumper::VisitCXXThisExpr(CXXThisExpr *Node) {
00572   DumpExpr(Node);
00573   OS << " this";
00574 }
00575 
00576 void StmtDumper::VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *Node) {
00577   DumpExpr(Node);
00578   OS << " functional cast to " << Node->getTypeAsWritten().getAsString()
00579      << " <" << Node->getCastKindName() << ">";
00580 }
00581 
00582 void StmtDumper::VisitCXXConstructExpr(CXXConstructExpr *Node) {
00583   DumpExpr(Node);
00584   CXXConstructorDecl *Ctor = Node->getConstructor();
00585   DumpType(Ctor->getType());
00586   if (Node->isElidable())
00587     OS << " elidable";
00588   if (Node->requiresZeroInitialization())
00589     OS << " zeroing";
00590 }
00591 
00592 void StmtDumper::VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *Node) {
00593   DumpExpr(Node);
00594   OS << " ";
00595   DumpCXXTemporary(Node->getTemporary());
00596 }
00597 
00598 void StmtDumper::VisitExprWithCleanups(ExprWithCleanups *Node) {
00599   DumpExpr(Node);
00600   ++IndentLevel;
00601   for (unsigned i = 0, e = Node->getNumObjects(); i != e; ++i) {
00602     OS << "\n";
00603     Indent();
00604     OS << "(cleanup ";
00605     DumpDeclRef(Node->getObject(i));
00606     OS << ")";
00607   }
00608   --IndentLevel;
00609 }
00610 
00611 void StmtDumper::DumpCXXTemporary(CXXTemporary *Temporary) {
00612   OS << "(CXXTemporary " << (void *)Temporary << ")";
00613 }
00614 
00615 //===----------------------------------------------------------------------===//
00616 // Obj-C Expressions
00617 //===----------------------------------------------------------------------===//
00618 
00619 void StmtDumper::VisitObjCMessageExpr(ObjCMessageExpr* Node) {
00620   DumpExpr(Node);
00621   OS << " selector=" << Node->getSelector().getAsString();
00622   switch (Node->getReceiverKind()) {
00623   case ObjCMessageExpr::Instance:
00624     break;
00625 
00626   case ObjCMessageExpr::Class:
00627     OS << " class=";
00628     DumpType(Node->getClassReceiver());
00629     break;
00630 
00631   case ObjCMessageExpr::SuperInstance:
00632     OS << " super (instance)";
00633     break;
00634 
00635   case ObjCMessageExpr::SuperClass:
00636     OS << " super (class)";
00637     break;
00638   }
00639 }
00640 
00641 void StmtDumper::VisitObjCBoxedExpr(ObjCBoxedExpr* Node) {
00642   DumpExpr(Node);
00643   OS << " selector=" << Node->getBoxingMethod()->getSelector().getAsString();
00644 }
00645 
00646 void StmtDumper::VisitObjCAtCatchStmt(ObjCAtCatchStmt *Node) {
00647   DumpStmt(Node);
00648   if (VarDecl *CatchParam = Node->getCatchParamDecl()) {
00649     OS << " catch parm = ";
00650     DumpDeclarator(CatchParam);
00651   } else {
00652     OS << " catch all";
00653   }
00654 }
00655 
00656 void StmtDumper::VisitObjCEncodeExpr(ObjCEncodeExpr *Node) {
00657   DumpExpr(Node);
00658   OS << " ";
00659   DumpType(Node->getEncodedType());
00660 }
00661 
00662 void StmtDumper::VisitObjCSelectorExpr(ObjCSelectorExpr *Node) {
00663   DumpExpr(Node);
00664 
00665   OS << " " << Node->getSelector().getAsString();
00666 }
00667 
00668 void StmtDumper::VisitObjCProtocolExpr(ObjCProtocolExpr *Node) {
00669   DumpExpr(Node);
00670 
00671   OS << ' ' <<* Node->getProtocol();
00672 }
00673 
00674 void StmtDumper::VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *Node) {
00675   DumpExpr(Node);
00676   if (Node->isImplicitProperty()) {
00677     OS << " Kind=MethodRef Getter=\"";
00678     if (Node->getImplicitPropertyGetter())
00679       OS << Node->getImplicitPropertyGetter()->getSelector().getAsString();
00680     else
00681       OS << "(null)";
00682 
00683     OS << "\" Setter=\"";
00684     if (ObjCMethodDecl *Setter = Node->getImplicitPropertySetter())
00685       OS << Setter->getSelector().getAsString();
00686     else
00687       OS << "(null)";
00688     OS << "\"";
00689   } else {
00690     OS << " Kind=PropertyRef Property=\"" << *Node->getExplicitProperty() <<'"';
00691   }
00692 
00693   if (Node->isSuperReceiver())
00694     OS << " super";
00695 
00696   OS << " Messaging=";
00697   if (Node->isMessagingGetter() && Node->isMessagingSetter())
00698     OS << "Getter&Setter";
00699   else if (Node->isMessagingGetter())
00700     OS << "Getter";
00701   else if (Node->isMessagingSetter())
00702     OS << "Setter";
00703 }
00704 
00705 void StmtDumper::VisitObjCSubscriptRefExpr(ObjCSubscriptRefExpr *Node) {
00706   DumpExpr(Node);
00707   if (Node->isArraySubscriptRefExpr())
00708     OS << " Kind=ArraySubscript GetterForArray=\"";
00709   else
00710     OS << " Kind=DictionarySubscript GetterForDictionary=\"";
00711   if (Node->getAtIndexMethodDecl())
00712     OS << Node->getAtIndexMethodDecl()->getSelector().getAsString();
00713   else
00714     OS << "(null)";
00715   
00716   if (Node->isArraySubscriptRefExpr())
00717     OS << "\" SetterForArray=\"";
00718   else
00719     OS << "\" SetterForDictionary=\"";
00720   if (Node->setAtIndexMethodDecl())
00721     OS << Node->setAtIndexMethodDecl()->getSelector().getAsString();
00722   else
00723     OS << "(null)";
00724 }
00725 
00726 void StmtDumper::VisitObjCBoolLiteralExpr(ObjCBoolLiteralExpr *Node) {
00727   DumpExpr(Node);
00728   OS << " " << (Node->getValue() ? "__objc_yes" : "__objc_no");
00729 }
00730 
00731 //===----------------------------------------------------------------------===//
00732 // Stmt method implementations
00733 //===----------------------------------------------------------------------===//
00734 
00735 /// dump - This does a local dump of the specified AST fragment.  It dumps the
00736 /// specified node and a few nodes underneath it, but not the whole subtree.
00737 /// This is useful in a debugger.
00738 void Stmt::dump(SourceManager &SM) const {
00739   dump(llvm::errs(), SM);
00740 }
00741 
00742 void Stmt::dump(raw_ostream &OS, SourceManager &SM) const {
00743   StmtDumper P(&SM, OS, 4);
00744   P.DumpSubTree(const_cast<Stmt*>(this));
00745   OS << "\n";
00746 }
00747 
00748 /// dump - This does a local dump of the specified AST fragment.  It dumps the
00749 /// specified node and a few nodes underneath it, but not the whole subtree.
00750 /// This is useful in a debugger.
00751 void Stmt::dump() const {
00752   StmtDumper P(0, llvm::errs(), 4);
00753   P.DumpSubTree(const_cast<Stmt*>(this));
00754   llvm::errs() << "\n";
00755 }
00756 
00757 /// dumpAll - This does a dump of the specified AST fragment and all subtrees.
00758 void Stmt::dumpAll(SourceManager &SM) const {
00759   StmtDumper P(&SM, llvm::errs(), ~0U);
00760   P.DumpSubTree(const_cast<Stmt*>(this));
00761   llvm::errs() << "\n";
00762 }
00763 
00764 /// dumpAll - This does a dump of the specified AST fragment and all subtrees.
00765 void Stmt::dumpAll() const {
00766   StmtDumper P(0, llvm::errs(), ~0U);
00767   P.DumpSubTree(const_cast<Stmt*>(this));
00768   llvm::errs() << "\n";
00769 }