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