]> CyberLeo.Net >> Repos - FreeBSD/releng/9.1.git/blob - contrib/llvm/tools/clang/lib/AST/StmtDumper.cpp
Copy stable/9 to releng/9.1 as part of the 9.1-RELEASE release process.
[FreeBSD/releng/9.1.git] / contrib / llvm / tools / clang / lib / AST / StmtDumper.cpp
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"
21 using namespace clang;
22
23 //===----------------------------------------------------------------------===//
24 // StmtDumper Visitor
25 //===----------------------------------------------------------------------===//
26
27 namespace  {
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
182 void 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
208 void 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
233 void StmtDumper::VisitStmt(Stmt *Node) {
234   DumpStmt(Node);
235 }
236
237 void 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
305 void 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
321 void StmtDumper::VisitLabelStmt(LabelStmt *Node) {
322   DumpStmt(Node);
323   OS << " '" << Node->getName() << "'";
324 }
325
326 void 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
336 void StmtDumper::VisitExpr(Expr *Node) {
337   DumpExpr(Node);
338 }
339
340 static 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
364 void StmtDumper::VisitCastExpr(CastExpr *Node) {
365   DumpExpr(Node);
366   OS << " <" << Node->getCastKindName();
367   DumpBasePath(OS, Node);
368   OS << ">";
369 }
370
371 void 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
383 void 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
397 void 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
410 void 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
420 void 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
430 void StmtDumper::VisitCharacterLiteral(CharacterLiteral *Node) {
431   DumpExpr(Node);
432   OS << " " << Node->getValue();
433 }
434
435 void StmtDumper::VisitIntegerLiteral(IntegerLiteral *Node) {
436   DumpExpr(Node);
437
438   bool isSigned = Node->getType()->isSignedIntegerType();
439   OS << " " << Node->getValue().toString(10, isSigned);
440 }
441 void StmtDumper::VisitFloatingLiteral(FloatingLiteral *Node) {
442   DumpExpr(Node);
443   OS << " " << Node->getValueAsApproximateDouble();
444 }
445
446 void 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
462 void StmtDumper::VisitUnaryOperator(UnaryOperator *Node) {
463   DumpExpr(Node);
464   OS << " " << (Node->isPostfix() ? "postfix" : "prefix")
465      << " '" << UnaryOperator::getOpcodeStr(Node->getOpcode()) << "'";
466 }
467 void 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
484 void StmtDumper::VisitMemberExpr(MemberExpr *Node) {
485   DumpExpr(Node);
486   OS << " " << (Node->isArrow() ? "->" : ".")
487      << *Node->getMemberDecl() << ' '
488      << (void*)Node->getMemberDecl();
489 }
490 void StmtDumper::VisitExtVectorElementExpr(ExtVectorElementExpr *Node) {
491   DumpExpr(Node);
492   OS << " " << Node->getAccessor().getNameStart();
493 }
494 void StmtDumper::VisitBinaryOperator(BinaryOperator *Node) {
495   DumpExpr(Node);
496   OS << " '" << BinaryOperator::getOpcodeStr(Node->getOpcode()) << "'";
497 }
498 void 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
507 void 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
535 void 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
546 void StmtDumper::VisitAddrLabelExpr(AddrLabelExpr *Node) {
547   DumpExpr(Node);
548   OS << " " << Node->getLabel()->getName()
549      << " " << (void*)Node->getLabel();
550 }
551
552 //===----------------------------------------------------------------------===//
553 // C++ Expressions
554 //===----------------------------------------------------------------------===//
555
556 void 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
565 void StmtDumper::VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *Node) {
566   DumpExpr(Node);
567   OS << " " << (Node->getValue() ? "true" : "false");
568 }
569
570 void StmtDumper::VisitCXXThisExpr(CXXThisExpr *Node) {
571   DumpExpr(Node);
572   OS << " this";
573 }
574
575 void StmtDumper::VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *Node) {
576   DumpExpr(Node);
577   OS << " functional cast to " << Node->getTypeAsWritten().getAsString()
578      << " <" << Node->getCastKindName() << ">";
579 }
580
581 void 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
591 void StmtDumper::VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *Node) {
592   DumpExpr(Node);
593   OS << " ";
594   DumpCXXTemporary(Node->getTemporary());
595 }
596
597 void 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
610 void StmtDumper::DumpCXXTemporary(CXXTemporary *Temporary) {
611   OS << "(CXXTemporary " << (void *)Temporary << ")";
612 }
613
614 //===----------------------------------------------------------------------===//
615 // Obj-C Expressions
616 //===----------------------------------------------------------------------===//
617
618 void 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
640 void 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
650 void StmtDumper::VisitObjCEncodeExpr(ObjCEncodeExpr *Node) {
651   DumpExpr(Node);
652   OS << " ";
653   DumpType(Node->getEncodedType());
654 }
655
656 void StmtDumper::VisitObjCSelectorExpr(ObjCSelectorExpr *Node) {
657   DumpExpr(Node);
658
659   OS << " " << Node->getSelector().getAsString();
660 }
661
662 void StmtDumper::VisitObjCProtocolExpr(ObjCProtocolExpr *Node) {
663   DumpExpr(Node);
664
665   OS << ' ' <<* Node->getProtocol();
666 }
667
668 void 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
699 void 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
720 void 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.
732 void Stmt::dump(SourceManager &SM) const {
733   dump(llvm::errs(), SM);
734 }
735
736 void 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.
745 void 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.
752 void 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.
759 void Stmt::dumpAll() const {
760   StmtDumper P(0, llvm::errs(), ~0U);
761   P.DumpSubTree(const_cast<Stmt*>(this));
762   llvm::errs() << "\n";
763 }