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    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, 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_ObjCSubscript: OS << " objcsubscript"; break;
116      case OK_VectorComponent: OS << " vectorcomponent"; break;
117      }
118    }
119    void DumpExpr(const Expr *Node) {
120      DumpStmt(Node);
121      OS << ' ';
122      DumpType(Node->getType());
123      DumpValueKind(Node->getValueKind());
124      DumpObjectKind(Node->getObjectKind());
125    }
126    void DumpSourceRange(const Stmt *Node);
127    void DumpLocation(SourceLocation Loc);
128
129    // Stmts.
130    void VisitStmt(Stmt *Node);
131    void VisitDeclStmt(DeclStmt *Node);
132    void VisitLabelStmt(LabelStmt *Node);
133    void VisitGotoStmt(GotoStmt *Node);
134
135    // Exprs
136    void VisitExpr(Expr *Node);
137    void VisitCastExpr(CastExpr *Node);
138    void VisitDeclRefExpr(DeclRefExpr *Node);
139    void VisitPredefinedExpr(PredefinedExpr *Node);
140    void VisitCharacterLiteral(CharacterLiteral *Node);
141    void VisitIntegerLiteral(IntegerLiteral *Node);
142    void VisitFloatingLiteral(FloatingLiteral *Node);
143    void VisitStringLiteral(StringLiteral *Str);
144    void VisitUnaryOperator(UnaryOperator *Node);
145    void VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *Node);
146    void VisitMemberExpr(MemberExpr *Node);
147    void VisitExtVectorElementExpr(ExtVectorElementExpr *Node);
148    void VisitBinaryOperator(BinaryOperator *Node);
149    void VisitCompoundAssignOperator(CompoundAssignOperator *Node);
150    void VisitAddrLabelExpr(AddrLabelExpr *Node);
151    void VisitBlockExpr(BlockExpr *Node);
152    void VisitOpaqueValueExpr(OpaqueValueExpr *Node);
153
154    // C++
155    void VisitCXXNamedCastExpr(CXXNamedCastExpr *Node);
156    void VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *Node);
157    void VisitCXXThisExpr(CXXThisExpr *Node);
158    void VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *Node);
159    void VisitCXXConstructExpr(CXXConstructExpr *Node);
160    void VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *Node);
161    void VisitExprWithCleanups(ExprWithCleanups *Node);
162    void VisitUnresolvedLookupExpr(UnresolvedLookupExpr *Node);
163    void DumpCXXTemporary(CXXTemporary *Temporary);
164
165    // ObjC
166    void VisitObjCAtCatchStmt(ObjCAtCatchStmt *Node);
167    void VisitObjCEncodeExpr(ObjCEncodeExpr *Node);
168    void VisitObjCMessageExpr(ObjCMessageExpr* Node);
169    void VisitObjCSelectorExpr(ObjCSelectorExpr *Node);
170    void VisitObjCProtocolExpr(ObjCProtocolExpr *Node);
171    void VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *Node);
172    void VisitObjCSubscriptRefExpr(ObjCSubscriptRefExpr *Node);
173    void VisitObjCIvarRefExpr(ObjCIvarRefExpr *Node);
174    void VisitObjCBoolLiteralExpr(ObjCBoolLiteralExpr *Node);
175  };
176}
177
178//===----------------------------------------------------------------------===//
179//  Utilities
180//===----------------------------------------------------------------------===//
181
182void StmtDumper::DumpLocation(SourceLocation Loc) {
183  SourceLocation SpellingLoc = SM->getSpellingLoc(Loc);
184
185  // The general format we print out is filename:line:col, but we drop pieces
186  // that haven't changed since the last loc printed.
187  PresumedLoc PLoc = SM->getPresumedLoc(SpellingLoc);
188
189  if (PLoc.isInvalid()) {
190    OS << "<invalid sloc>";
191    return;
192  }
193
194  if (strcmp(PLoc.getFilename(), LastLocFilename) != 0) {
195    OS << PLoc.getFilename() << ':' << PLoc.getLine()
196       << ':' << PLoc.getColumn();
197    LastLocFilename = PLoc.getFilename();
198    LastLocLine = PLoc.getLine();
199  } else if (PLoc.getLine() != LastLocLine) {
200    OS << "line" << ':' << PLoc.getLine()
201       << ':' << PLoc.getColumn();
202    LastLocLine = PLoc.getLine();
203  } else {
204    OS << "col" << ':' << PLoc.getColumn();
205  }
206}
207
208void StmtDumper::DumpSourceRange(const Stmt *Node) {
209  // Can't translate locations if a SourceManager isn't available.
210  if (SM == 0) return;
211
212  // TODO: If the parent expression is available, we can print a delta vs its
213  // location.
214  SourceRange R = Node->getSourceRange();
215
216  OS << " <";
217  DumpLocation(R.getBegin());
218  if (R.getBegin() != R.getEnd()) {
219    OS << ", ";
220    DumpLocation(R.getEnd());
221  }
222  OS << ">";
223
224  // <t2.c:123:421[blah], t2.c:412:321>
225
226}
227
228
229//===----------------------------------------------------------------------===//
230//  Stmt printing methods.
231//===----------------------------------------------------------------------===//
232
233void StmtDumper::VisitStmt(Stmt *Node) {
234  DumpStmt(Node);
235}
236
237void StmtDumper::DumpDeclarator(Decl *D) {
238  // FIXME: Need to complete/beautify this... this code simply shows the
239  // nodes are where they need to be.
240  if (TypedefDecl *localType = dyn_cast<TypedefDecl>(D)) {
241    OS << "\"typedef " << localType->getUnderlyingType().getAsString()
242       << ' ' << *localType << '"';
243  } else if (TypeAliasDecl *localType = dyn_cast<TypeAliasDecl>(D)) {
244    OS << "\"using " << *localType << " = "
245       << localType->getUnderlyingType().getAsString() << '"';
246  } else if (ValueDecl *VD = dyn_cast<ValueDecl>(D)) {
247    OS << "\"";
248    // Emit storage class for vardecls.
249    if (VarDecl *V = dyn_cast<VarDecl>(VD)) {
250      if (V->getStorageClass() != SC_None)
251        OS << VarDecl::getStorageClassSpecifierString(V->getStorageClass())
252           << " ";
253    }
254
255    std::string Name = VD->getNameAsString();
256    VD->getType().getAsStringInternal(Name,
257                          PrintingPolicy(VD->getASTContext().getLangOpts()));
258    OS << Name;
259
260    // If this is a vardecl with an initializer, emit it.
261    if (VarDecl *V = dyn_cast<VarDecl>(VD)) {
262      if (V->getInit()) {
263        OS << " =\n";
264        DumpSubTree(V->getInit());
265      }
266    }
267    OS << '"';
268  } else if (TagDecl *TD = dyn_cast<TagDecl>(D)) {
269    // print a free standing tag decl (e.g. "struct x;").
270    const char *tagname;
271    if (const IdentifierInfo *II = TD->getIdentifier())
272      tagname = II->getNameStart();
273    else
274      tagname = "<anonymous>";
275    OS << '"' << TD->getKindName() << ' ' << tagname << ";\"";
276    // FIXME: print tag bodies.
277  } else if (UsingDirectiveDecl *UD = dyn_cast<UsingDirectiveDecl>(D)) {
278    // print using-directive decl (e.g. "using namespace x;")
279    const char *ns;
280    if (const IdentifierInfo *II = UD->getNominatedNamespace()->getIdentifier())
281      ns = II->getNameStart();
282    else
283      ns = "<anonymous>";
284    OS << '"' << UD->getDeclKindName() << ns << ";\"";
285  } else if (UsingDecl *UD = dyn_cast<UsingDecl>(D)) {
286    // print using decl (e.g. "using std::string;")
287    const char *tn = UD->isTypeName() ? "typename " : "";
288    OS << '"' << UD->getDeclKindName() << tn;
289    UD->getQualifier()->print(OS,
290                        PrintingPolicy(UD->getASTContext().getLangOpts()));
291    OS << ";\"";
292  } else if (LabelDecl *LD = dyn_cast<LabelDecl>(D)) {
293    OS << "label " << *LD;
294  } else if (StaticAssertDecl *SAD = dyn_cast<StaticAssertDecl>(D)) {
295    OS << "\"static_assert(\n";
296    DumpSubTree(SAD->getAssertExpr());
297    OS << ",\n";
298    DumpSubTree(SAD->getMessage());
299    OS << ");\"";
300  } else {
301    llvm_unreachable("Unexpected decl");
302  }
303}
304
305void StmtDumper::VisitDeclStmt(DeclStmt *Node) {
306  DumpStmt(Node);
307  OS << "\n";
308  for (DeclStmt::decl_iterator DI = Node->decl_begin(), DE = Node->decl_end();
309       DI != DE; ++DI) {
310    Decl* D = *DI;
311    ++IndentLevel;
312    Indent();
313    OS << (void*) D << " ";
314    DumpDeclarator(D);
315    if (DI+1 != DE)
316      OS << "\n";
317    --IndentLevel;
318  }
319}
320
321void StmtDumper::VisitLabelStmt(LabelStmt *Node) {
322  DumpStmt(Node);
323  OS << " '" << Node->getName() << "'";
324}
325
326void StmtDumper::VisitGotoStmt(GotoStmt *Node) {
327  DumpStmt(Node);
328  OS << " '" << Node->getLabel()->getName()
329     << "':" << (void*)Node->getLabel();
330}
331
332//===----------------------------------------------------------------------===//
333//  Expr printing methods.
334//===----------------------------------------------------------------------===//
335
336void StmtDumper::VisitExpr(Expr *Node) {
337  DumpExpr(Node);
338}
339
340static void DumpBasePath(raw_ostream &OS, CastExpr *Node) {
341  if (Node->path_empty())
342    return;
343
344  OS << " (";
345  bool First = true;
346  for (CastExpr::path_iterator
347         I = Node->path_begin(), E = Node->path_end(); I != E; ++I) {
348    const CXXBaseSpecifier *Base = *I;
349    if (!First)
350      OS << " -> ";
351
352    const CXXRecordDecl *RD =
353    cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
354
355    if (Base->isVirtual())
356      OS << "virtual ";
357    OS << RD->getName();
358    First = false;
359  }
360
361  OS << ')';
362}
363
364void StmtDumper::VisitCastExpr(CastExpr *Node) {
365  DumpExpr(Node);
366  OS << " <" << Node->getCastKindName();
367  DumpBasePath(OS, Node);
368  OS << ">";
369}
370
371void StmtDumper::VisitDeclRefExpr(DeclRefExpr *Node) {
372  DumpExpr(Node);
373
374  OS << " ";
375  DumpDeclRef(Node->getDecl());
376  if (Node->getDecl() != Node->getFoundDecl()) {
377    OS << " (";
378    DumpDeclRef(Node->getFoundDecl());
379    OS << ")";
380  }
381}
382
383void StmtDumper::DumpDeclRef(Decl *d) {
384  OS << d->getDeclKindName() << ' ' << (void*) d;
385
386  if (NamedDecl *nd = dyn_cast<NamedDecl>(d)) {
387    OS << " '";
388    nd->getDeclName().printName(OS);
389    OS << "'";
390  }
391
392  if (ValueDecl *vd = dyn_cast<ValueDecl>(d)) {
393    OS << ' '; DumpType(vd->getType());
394  }
395}
396
397void StmtDumper::VisitUnresolvedLookupExpr(UnresolvedLookupExpr *Node) {
398  DumpExpr(Node);
399  OS << " (";
400  if (!Node->requiresADL()) OS << "no ";
401  OS << "ADL) = '" << Node->getName() << '\'';
402
403  UnresolvedLookupExpr::decls_iterator
404    I = Node->decls_begin(), E = Node->decls_end();
405  if (I == E) OS << " empty";
406  for (; I != E; ++I)
407    OS << " " << (void*) *I;
408}
409
410void StmtDumper::VisitObjCIvarRefExpr(ObjCIvarRefExpr *Node) {
411  DumpExpr(Node);
412
413  OS << " " << Node->getDecl()->getDeclKindName()
414     << "Decl='" << *Node->getDecl()
415     << "' " << (void*)Node->getDecl();
416  if (Node->isFreeIvar())
417    OS << " isFreeIvar";
418}
419
420void StmtDumper::VisitPredefinedExpr(PredefinedExpr *Node) {
421  DumpExpr(Node);
422  switch (Node->getIdentType()) {
423  default: llvm_unreachable("unknown case");
424  case PredefinedExpr::Func:           OS <<  " __func__"; break;
425  case PredefinedExpr::Function:       OS <<  " __FUNCTION__"; break;
426  case PredefinedExpr::PrettyFunction: OS <<  " __PRETTY_FUNCTION__";break;
427  }
428}
429
430void StmtDumper::VisitCharacterLiteral(CharacterLiteral *Node) {
431  DumpExpr(Node);
432  OS << " " << Node->getValue();
433}
434
435void StmtDumper::VisitIntegerLiteral(IntegerLiteral *Node) {
436  DumpExpr(Node);
437
438  bool isSigned = Node->getType()->isSignedIntegerType();
439  OS << " " << Node->getValue().toString(10, isSigned);
440}
441void StmtDumper::VisitFloatingLiteral(FloatingLiteral *Node) {
442  DumpExpr(Node);
443  OS << " " << Node->getValueAsApproximateDouble();
444}
445
446void StmtDumper::VisitStringLiteral(StringLiteral *Str) {
447  DumpExpr(Str);
448  // FIXME: this doesn't print wstrings right.
449  OS << " ";
450  switch (Str->getKind()) {
451  case StringLiteral::Ascii: break; // No prefix
452  case StringLiteral::Wide:  OS << 'L'; break;
453  case StringLiteral::UTF8:  OS << "u8"; break;
454  case StringLiteral::UTF16: OS << 'u'; break;
455  case StringLiteral::UTF32: OS << 'U'; break;
456  }
457  OS << '"';
458  OS.write_escaped(Str->getString());
459  OS << '"';
460}
461
462void StmtDumper::VisitUnaryOperator(UnaryOperator *Node) {
463  DumpExpr(Node);
464  OS << " " << (Node->isPostfix() ? "postfix" : "prefix")
465     << " '" << UnaryOperator::getOpcodeStr(Node->getOpcode()) << "'";
466}
467void StmtDumper::VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *Node) {
468  DumpExpr(Node);
469  switch(Node->getKind()) {
470  case UETT_SizeOf:
471    OS << " sizeof ";
472    break;
473  case UETT_AlignOf:
474    OS << " __alignof ";
475    break;
476  case UETT_VecStep:
477    OS << " vec_step ";
478    break;
479  }
480  if (Node->isArgumentType())
481    DumpType(Node->getArgumentType());
482}
483
484void StmtDumper::VisitMemberExpr(MemberExpr *Node) {
485  DumpExpr(Node);
486  OS << " " << (Node->isArrow() ? "->" : ".")
487     << *Node->getMemberDecl() << ' '
488     << (void*)Node->getMemberDecl();
489}
490void StmtDumper::VisitExtVectorElementExpr(ExtVectorElementExpr *Node) {
491  DumpExpr(Node);
492  OS << " " << Node->getAccessor().getNameStart();
493}
494void StmtDumper::VisitBinaryOperator(BinaryOperator *Node) {
495  DumpExpr(Node);
496  OS << " '" << BinaryOperator::getOpcodeStr(Node->getOpcode()) << "'";
497}
498void StmtDumper::VisitCompoundAssignOperator(CompoundAssignOperator *Node) {
499  DumpExpr(Node);
500  OS << " '" << BinaryOperator::getOpcodeStr(Node->getOpcode())
501     << "' ComputeLHSTy=";
502  DumpType(Node->getComputationLHSType());
503  OS << " ComputeResultTy=";
504  DumpType(Node->getComputationResultType());
505}
506
507void StmtDumper::VisitBlockExpr(BlockExpr *Node) {
508  DumpExpr(Node);
509
510  BlockDecl *block = Node->getBlockDecl();
511  OS << " decl=" << block;
512
513  IndentLevel++;
514  if (block->capturesCXXThis()) {
515    OS << '\n'; Indent(); OS << "(capture this)";
516  }
517  for (BlockDecl::capture_iterator
518         i = block->capture_begin(), e = block->capture_end(); i != e; ++i) {
519    OS << '\n';
520    Indent();
521    OS << "(capture ";
522    if (i->isByRef()) OS << "byref ";
523    if (i->isNested()) OS << "nested ";
524    if (i->getVariable())
525      DumpDeclRef(i->getVariable());
526    if (i->hasCopyExpr()) DumpSubTree(i->getCopyExpr());
527    OS << ")";
528  }
529  IndentLevel--;
530
531  OS << '\n';
532  DumpSubTree(block->getBody());
533}
534
535void StmtDumper::VisitOpaqueValueExpr(OpaqueValueExpr *Node) {
536  DumpExpr(Node);
537
538  if (Expr *Source = Node->getSourceExpr()) {
539    OS << '\n';
540    DumpSubTree(Source);
541  }
542}
543
544// GNU extensions.
545
546void StmtDumper::VisitAddrLabelExpr(AddrLabelExpr *Node) {
547  DumpExpr(Node);
548  OS << " " << Node->getLabel()->getName()
549     << " " << (void*)Node->getLabel();
550}
551
552//===----------------------------------------------------------------------===//
553// C++ Expressions
554//===----------------------------------------------------------------------===//
555
556void StmtDumper::VisitCXXNamedCastExpr(CXXNamedCastExpr *Node) {
557  DumpExpr(Node);
558  OS << " " << Node->getCastName()
559     << "<" << Node->getTypeAsWritten().getAsString() << ">"
560     << " <" << Node->getCastKindName();
561  DumpBasePath(OS, Node);
562  OS << ">";
563}
564
565void StmtDumper::VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *Node) {
566  DumpExpr(Node);
567  OS << " " << (Node->getValue() ? "true" : "false");
568}
569
570void StmtDumper::VisitCXXThisExpr(CXXThisExpr *Node) {
571  DumpExpr(Node);
572  OS << " this";
573}
574
575void StmtDumper::VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *Node) {
576  DumpExpr(Node);
577  OS << " functional cast to " << Node->getTypeAsWritten().getAsString()
578     << " <" << Node->getCastKindName() << ">";
579}
580
581void StmtDumper::VisitCXXConstructExpr(CXXConstructExpr *Node) {
582  DumpExpr(Node);
583  CXXConstructorDecl *Ctor = Node->getConstructor();
584  DumpType(Ctor->getType());
585  if (Node->isElidable())
586    OS << " elidable";
587  if (Node->requiresZeroInitialization())
588    OS << " zeroing";
589}
590
591void StmtDumper::VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *Node) {
592  DumpExpr(Node);
593  OS << " ";
594  DumpCXXTemporary(Node->getTemporary());
595}
596
597void StmtDumper::VisitExprWithCleanups(ExprWithCleanups *Node) {
598  DumpExpr(Node);
599  ++IndentLevel;
600  for (unsigned i = 0, e = Node->getNumObjects(); i != e; ++i) {
601    OS << "\n";
602    Indent();
603    OS << "(cleanup ";
604    DumpDeclRef(Node->getObject(i));
605    OS << ")";
606  }
607  --IndentLevel;
608}
609
610void StmtDumper::DumpCXXTemporary(CXXTemporary *Temporary) {
611  OS << "(CXXTemporary " << (void *)Temporary << ")";
612}
613
614//===----------------------------------------------------------------------===//
615// Obj-C Expressions
616//===----------------------------------------------------------------------===//
617
618void StmtDumper::VisitObjCMessageExpr(ObjCMessageExpr* Node) {
619  DumpExpr(Node);
620  OS << " selector=" << Node->getSelector().getAsString();
621  switch (Node->getReceiverKind()) {
622  case ObjCMessageExpr::Instance:
623    break;
624
625  case ObjCMessageExpr::Class:
626    OS << " class=";
627    DumpType(Node->getClassReceiver());
628    break;
629
630  case ObjCMessageExpr::SuperInstance:
631    OS << " super (instance)";
632    break;
633
634  case ObjCMessageExpr::SuperClass:
635    OS << " super (class)";
636    break;
637  }
638}
639
640void StmtDumper::VisitObjCAtCatchStmt(ObjCAtCatchStmt *Node) {
641  DumpStmt(Node);
642  if (VarDecl *CatchParam = Node->getCatchParamDecl()) {
643    OS << " catch parm = ";
644    DumpDeclarator(CatchParam);
645  } else {
646    OS << " catch all";
647  }
648}
649
650void StmtDumper::VisitObjCEncodeExpr(ObjCEncodeExpr *Node) {
651  DumpExpr(Node);
652  OS << " ";
653  DumpType(Node->getEncodedType());
654}
655
656void StmtDumper::VisitObjCSelectorExpr(ObjCSelectorExpr *Node) {
657  DumpExpr(Node);
658
659  OS << " " << Node->getSelector().getAsString();
660}
661
662void StmtDumper::VisitObjCProtocolExpr(ObjCProtocolExpr *Node) {
663  DumpExpr(Node);
664
665  OS << ' ' <<* Node->getProtocol();
666}
667
668void StmtDumper::VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *Node) {
669  DumpExpr(Node);
670  if (Node->isImplicitProperty()) {
671    OS << " Kind=MethodRef Getter=\"";
672    if (Node->getImplicitPropertyGetter())
673      OS << Node->getImplicitPropertyGetter()->getSelector().getAsString();
674    else
675      OS << "(null)";
676
677    OS << "\" Setter=\"";
678    if (ObjCMethodDecl *Setter = Node->getImplicitPropertySetter())
679      OS << Setter->getSelector().getAsString();
680    else
681      OS << "(null)";
682    OS << "\"";
683  } else {
684    OS << " Kind=PropertyRef Property=\"" << *Node->getExplicitProperty() <<'"';
685  }
686
687  if (Node->isSuperReceiver())
688    OS << " super";
689
690  OS << " Messaging=";
691  if (Node->isMessagingGetter() && Node->isMessagingSetter())
692    OS << "Getter&Setter";
693  else if (Node->isMessagingGetter())
694    OS << "Getter";
695  else if (Node->isMessagingSetter())
696    OS << "Setter";
697}
698
699void StmtDumper::VisitObjCSubscriptRefExpr(ObjCSubscriptRefExpr *Node) {
700  DumpExpr(Node);
701  if (Node->isArraySubscriptRefExpr())
702    OS << " Kind=ArraySubscript GetterForArray=\"";
703  else
704    OS << " Kind=DictionarySubscript GetterForDictionary=\"";
705  if (Node->getAtIndexMethodDecl())
706    OS << Node->getAtIndexMethodDecl()->getSelector().getAsString();
707  else
708    OS << "(null)";
709
710  if (Node->isArraySubscriptRefExpr())
711    OS << "\" SetterForArray=\"";
712  else
713    OS << "\" SetterForDictionary=\"";
714  if (Node->setAtIndexMethodDecl())
715    OS << Node->setAtIndexMethodDecl()->getSelector().getAsString();
716  else
717    OS << "(null)";
718}
719
720void StmtDumper::VisitObjCBoolLiteralExpr(ObjCBoolLiteralExpr *Node) {
721  DumpExpr(Node);
722  OS << " " << (Node->getValue() ? "__objc_yes" : "__objc_no");
723}
724
725//===----------------------------------------------------------------------===//
726// Stmt method implementations
727//===----------------------------------------------------------------------===//
728
729/// dump - This does a local dump of the specified AST fragment.  It dumps the
730/// specified node and a few nodes underneath it, but not the whole subtree.
731/// This is useful in a debugger.
732void Stmt::dump(SourceManager &SM) const {
733  dump(llvm::errs(), SM);
734}
735
736void Stmt::dump(raw_ostream &OS, SourceManager &SM) const {
737  StmtDumper P(&SM, OS, 4);
738  P.DumpSubTree(const_cast<Stmt*>(this));
739  OS << "\n";
740}
741
742/// dump - This does a local dump of the specified AST fragment.  It dumps the
743/// specified node and a few nodes underneath it, but not the whole subtree.
744/// This is useful in a debugger.
745void Stmt::dump() const {
746  StmtDumper P(0, llvm::errs(), 4);
747  P.DumpSubTree(const_cast<Stmt*>(this));
748  llvm::errs() << "\n";
749}
750
751/// dumpAll - This does a dump of the specified AST fragment and all subtrees.
752void Stmt::dumpAll(SourceManager &SM) const {
753  StmtDumper P(&SM, llvm::errs(), ~0U);
754  P.DumpSubTree(const_cast<Stmt*>(this));
755  llvm::errs() << "\n";
756}
757
758/// dumpAll - This does a dump of the specified AST fragment and all subtrees.
759void Stmt::dumpAll() const {
760  StmtDumper P(0, llvm::errs(), ~0U);
761  P.DumpSubTree(const_cast<Stmt*>(this));
762  llvm::errs() << "\n";
763}
764