1249261Sdim//===--- ASTDumper.cpp - Dumping implementation for ASTs ------------------===//
2249261Sdim//
3249261Sdim//                     The LLVM Compiler Infrastructure
4249261Sdim//
5249261Sdim// This file is distributed under the University of Illinois Open Source
6249261Sdim// License. See LICENSE.TXT for details.
7249261Sdim//
8249261Sdim//===----------------------------------------------------------------------===//
9249261Sdim//
10249261Sdim// This file implements the AST dump methods, which dump out the
11249261Sdim// AST in a form that exposes type details and other fields.
12249261Sdim//
13249261Sdim//===----------------------------------------------------------------------===//
14249261Sdim
15249261Sdim#include "clang/AST/ASTContext.h"
16249261Sdim#include "clang/AST/Attr.h"
17249261Sdim#include "clang/AST/CommentVisitor.h"
18249261Sdim#include "clang/AST/DeclCXX.h"
19263508Sdim#include "clang/AST/DeclLookups.h"
20249261Sdim#include "clang/AST/DeclObjC.h"
21249261Sdim#include "clang/AST/DeclVisitor.h"
22249261Sdim#include "clang/AST/StmtVisitor.h"
23249261Sdim#include "clang/Basic/Module.h"
24249261Sdim#include "clang/Basic/SourceManager.h"
25249261Sdim#include "llvm/Support/raw_ostream.h"
26249261Sdimusing namespace clang;
27249261Sdimusing namespace clang::comments;
28249261Sdim
29249261Sdim//===----------------------------------------------------------------------===//
30249261Sdim// ASTDumper Visitor
31249261Sdim//===----------------------------------------------------------------------===//
32249261Sdim
33249261Sdimnamespace  {
34249261Sdim  // Colors used for various parts of the AST dump
35266715Sdim  // Do not use bold yellow for any text.  It is hard to read on white screens.
36249261Sdim
37249261Sdim  struct TerminalColor {
38249261Sdim    raw_ostream::Colors Color;
39249261Sdim    bool Bold;
40249261Sdim  };
41249261Sdim
42266715Sdim  // Red           - CastColor
43266715Sdim  // Green         - TypeColor
44266715Sdim  // Bold Green    - DeclKindNameColor, UndeserializedColor
45266715Sdim  // Yellow        - AddressColor, LocationColor
46266715Sdim  // Blue          - CommentColor, NullColor, IndentColor
47266715Sdim  // Bold Blue     - AttrColor
48266715Sdim  // Bold Magenta  - StmtColor
49266715Sdim  // Cyan          - ValueKindColor, ObjectKindColor
50266715Sdim  // Bold Cyan     - ValueColor, DeclNameColor
51266715Sdim
52249261Sdim  // Decl kind names (VarDecl, FunctionDecl, etc)
53249261Sdim  static const TerminalColor DeclKindNameColor = { raw_ostream::GREEN, true };
54249261Sdim  // Attr names (CleanupAttr, GuardedByAttr, etc)
55249261Sdim  static const TerminalColor AttrColor = { raw_ostream::BLUE, true };
56249261Sdim  // Statement names (DeclStmt, ImplicitCastExpr, etc)
57249261Sdim  static const TerminalColor StmtColor = { raw_ostream::MAGENTA, true };
58249261Sdim  // Comment names (FullComment, ParagraphComment, TextComment, etc)
59266715Sdim  static const TerminalColor CommentColor = { raw_ostream::BLUE, false };
60249261Sdim
61249261Sdim  // Type names (int, float, etc, plus user defined types)
62249261Sdim  static const TerminalColor TypeColor = { raw_ostream::GREEN, false };
63249261Sdim
64249261Sdim  // Pointer address
65249261Sdim  static const TerminalColor AddressColor = { raw_ostream::YELLOW, false };
66249261Sdim  // Source locations
67249261Sdim  static const TerminalColor LocationColor = { raw_ostream::YELLOW, false };
68249261Sdim
69249261Sdim  // lvalue/xvalue
70249261Sdim  static const TerminalColor ValueKindColor = { raw_ostream::CYAN, false };
71249261Sdim  // bitfield/objcproperty/objcsubscript/vectorcomponent
72249261Sdim  static const TerminalColor ObjectKindColor = { raw_ostream::CYAN, false };
73249261Sdim
74249261Sdim  // Null statements
75249261Sdim  static const TerminalColor NullColor = { raw_ostream::BLUE, false };
76249261Sdim
77263508Sdim  // Undeserialized entities
78263508Sdim  static const TerminalColor UndeserializedColor = { raw_ostream::GREEN, true };
79263508Sdim
80249261Sdim  // CastKind from CastExpr's
81249261Sdim  static const TerminalColor CastColor = { raw_ostream::RED, false };
82249261Sdim
83249261Sdim  // Value of the statement
84249261Sdim  static const TerminalColor ValueColor = { raw_ostream::CYAN, true };
85249261Sdim  // Decl names
86249261Sdim  static const TerminalColor DeclNameColor = { raw_ostream::CYAN, true };
87249261Sdim
88249261Sdim  // Indents ( `, -. | )
89249261Sdim  static const TerminalColor IndentColor = { raw_ostream::BLUE, false };
90249261Sdim
91249261Sdim  class ASTDumper
92249261Sdim      : public ConstDeclVisitor<ASTDumper>, public ConstStmtVisitor<ASTDumper>,
93249261Sdim        public ConstCommentVisitor<ASTDumper> {
94249261Sdim    raw_ostream &OS;
95249261Sdim    const CommandTraits *Traits;
96249261Sdim    const SourceManager *SM;
97249261Sdim    bool IsFirstLine;
98249261Sdim
99249261Sdim    // Indicates whether more child are expected at the current tree depth
100249261Sdim    enum IndentType { IT_Child, IT_LastChild };
101249261Sdim
102249261Sdim    /// Indents[i] indicates if another child exists at level i.
103249261Sdim    /// Used by Indent() to print the tree structure.
104249261Sdim    llvm::SmallVector<IndentType, 32> Indents;
105249261Sdim
106249261Sdim    /// Indicates that more children will be needed at this indent level.
107249261Sdim    /// If true, prevents lastChild() from marking the node as the last child.
108249261Sdim    /// This is used when there are multiple collections of children to be
109249261Sdim    /// dumped as well as during conditional node dumping.
110249261Sdim    bool MoreChildren;
111249261Sdim
112249261Sdim    /// Keep track of the last location we print out so that we can
113249261Sdim    /// print out deltas from then on out.
114249261Sdim    const char *LastLocFilename;
115249261Sdim    unsigned LastLocLine;
116249261Sdim
117249261Sdim    /// The \c FullComment parent of the comment being dumped.
118249261Sdim    const FullComment *FC;
119249261Sdim
120249261Sdim    bool ShowColors;
121249261Sdim
122249261Sdim    class IndentScope {
123249261Sdim      ASTDumper &Dumper;
124249261Sdim      // Preserve the Dumper's MoreChildren value from the previous IndentScope
125249261Sdim      bool MoreChildren;
126249261Sdim    public:
127249261Sdim      IndentScope(ASTDumper &Dumper) : Dumper(Dumper) {
128249261Sdim        MoreChildren = Dumper.hasMoreChildren();
129249261Sdim        Dumper.setMoreChildren(false);
130249261Sdim        Dumper.indent();
131249261Sdim      }
132249261Sdim      ~IndentScope() {
133249261Sdim        Dumper.setMoreChildren(MoreChildren);
134249261Sdim        Dumper.unindent();
135249261Sdim      }
136249261Sdim    };
137249261Sdim
138249261Sdim    class ColorScope {
139249261Sdim      ASTDumper &Dumper;
140249261Sdim    public:
141249261Sdim      ColorScope(ASTDumper &Dumper, TerminalColor Color)
142249261Sdim        : Dumper(Dumper) {
143249261Sdim        if (Dumper.ShowColors)
144249261Sdim          Dumper.OS.changeColor(Color.Color, Color.Bold);
145249261Sdim      }
146249261Sdim      ~ColorScope() {
147249261Sdim        if (Dumper.ShowColors)
148249261Sdim          Dumper.OS.resetColor();
149249261Sdim      }
150249261Sdim    };
151249261Sdim
152249261Sdim  public:
153249261Sdim    ASTDumper(raw_ostream &OS, const CommandTraits *Traits,
154249261Sdim              const SourceManager *SM)
155249261Sdim      : OS(OS), Traits(Traits), SM(SM), IsFirstLine(true), MoreChildren(false),
156249261Sdim        LastLocFilename(""), LastLocLine(~0U), FC(0),
157249261Sdim        ShowColors(SM && SM->getDiagnostics().getShowColors()) { }
158249261Sdim
159249261Sdim    ASTDumper(raw_ostream &OS, const CommandTraits *Traits,
160249261Sdim              const SourceManager *SM, bool ShowColors)
161249261Sdim      : OS(OS), Traits(Traits), SM(SM), IsFirstLine(true), MoreChildren(false),
162249261Sdim        LastLocFilename(""), LastLocLine(~0U),
163249261Sdim        ShowColors(ShowColors) { }
164249261Sdim
165249261Sdim    ~ASTDumper() {
166249261Sdim      OS << "\n";
167249261Sdim    }
168249261Sdim
169249261Sdim    void dumpDecl(const Decl *D);
170249261Sdim    void dumpStmt(const Stmt *S);
171249261Sdim    void dumpFullComment(const FullComment *C);
172249261Sdim
173249261Sdim    // Formatting
174249261Sdim    void indent();
175249261Sdim    void unindent();
176249261Sdim    void lastChild();
177249261Sdim    bool hasMoreChildren();
178249261Sdim    void setMoreChildren(bool Value);
179249261Sdim
180249261Sdim    // Utilities
181249261Sdim    void dumpPointer(const void *Ptr);
182249261Sdim    void dumpSourceRange(SourceRange R);
183249261Sdim    void dumpLocation(SourceLocation Loc);
184249261Sdim    void dumpBareType(QualType T);
185249261Sdim    void dumpType(QualType T);
186249261Sdim    void dumpBareDeclRef(const Decl *Node);
187249261Sdim    void dumpDeclRef(const Decl *Node, const char *Label = 0);
188249261Sdim    void dumpName(const NamedDecl *D);
189249261Sdim    bool hasNodes(const DeclContext *DC);
190249261Sdim    void dumpDeclContext(const DeclContext *DC);
191263508Sdim    void dumpLookups(const DeclContext *DC);
192249261Sdim    void dumpAttr(const Attr *A);
193249261Sdim
194249261Sdim    // C++ Utilities
195249261Sdim    void dumpAccessSpecifier(AccessSpecifier AS);
196249261Sdim    void dumpCXXCtorInitializer(const CXXCtorInitializer *Init);
197249261Sdim    void dumpTemplateParameters(const TemplateParameterList *TPL);
198249261Sdim    void dumpTemplateArgumentListInfo(const TemplateArgumentListInfo &TALI);
199249261Sdim    void dumpTemplateArgumentLoc(const TemplateArgumentLoc &A);
200249261Sdim    void dumpTemplateArgumentList(const TemplateArgumentList &TAL);
201249261Sdim    void dumpTemplateArgument(const TemplateArgument &A,
202249261Sdim                              SourceRange R = SourceRange());
203249261Sdim
204249261Sdim    // Decls
205249261Sdim    void VisitLabelDecl(const LabelDecl *D);
206249261Sdim    void VisitTypedefDecl(const TypedefDecl *D);
207249261Sdim    void VisitEnumDecl(const EnumDecl *D);
208249261Sdim    void VisitRecordDecl(const RecordDecl *D);
209249261Sdim    void VisitEnumConstantDecl(const EnumConstantDecl *D);
210249261Sdim    void VisitIndirectFieldDecl(const IndirectFieldDecl *D);
211249261Sdim    void VisitFunctionDecl(const FunctionDecl *D);
212249261Sdim    void VisitFieldDecl(const FieldDecl *D);
213249261Sdim    void VisitVarDecl(const VarDecl *D);
214249261Sdim    void VisitFileScopeAsmDecl(const FileScopeAsmDecl *D);
215249261Sdim    void VisitImportDecl(const ImportDecl *D);
216249261Sdim
217249261Sdim    // C++ Decls
218249261Sdim    void VisitNamespaceDecl(const NamespaceDecl *D);
219249261Sdim    void VisitUsingDirectiveDecl(const UsingDirectiveDecl *D);
220249261Sdim    void VisitNamespaceAliasDecl(const NamespaceAliasDecl *D);
221249261Sdim    void VisitTypeAliasDecl(const TypeAliasDecl *D);
222249261Sdim    void VisitTypeAliasTemplateDecl(const TypeAliasTemplateDecl *D);
223249261Sdim    void VisitCXXRecordDecl(const CXXRecordDecl *D);
224249261Sdim    void VisitStaticAssertDecl(const StaticAssertDecl *D);
225249261Sdim    void VisitFunctionTemplateDecl(const FunctionTemplateDecl *D);
226249261Sdim    void VisitClassTemplateDecl(const ClassTemplateDecl *D);
227249261Sdim    void VisitClassTemplateSpecializationDecl(
228249261Sdim        const ClassTemplateSpecializationDecl *D);
229249261Sdim    void VisitClassTemplatePartialSpecializationDecl(
230249261Sdim        const ClassTemplatePartialSpecializationDecl *D);
231249261Sdim    void VisitClassScopeFunctionSpecializationDecl(
232249261Sdim        const ClassScopeFunctionSpecializationDecl *D);
233263508Sdim    void VisitVarTemplateDecl(const VarTemplateDecl *D);
234263508Sdim    void VisitVarTemplateSpecializationDecl(
235263508Sdim        const VarTemplateSpecializationDecl *D);
236263508Sdim    void VisitVarTemplatePartialSpecializationDecl(
237263508Sdim        const VarTemplatePartialSpecializationDecl *D);
238249261Sdim    void VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *D);
239249261Sdim    void VisitNonTypeTemplateParmDecl(const NonTypeTemplateParmDecl *D);
240249261Sdim    void VisitTemplateTemplateParmDecl(const TemplateTemplateParmDecl *D);
241249261Sdim    void VisitUsingDecl(const UsingDecl *D);
242249261Sdim    void VisitUnresolvedUsingTypenameDecl(const UnresolvedUsingTypenameDecl *D);
243249261Sdim    void VisitUnresolvedUsingValueDecl(const UnresolvedUsingValueDecl *D);
244249261Sdim    void VisitUsingShadowDecl(const UsingShadowDecl *D);
245249261Sdim    void VisitLinkageSpecDecl(const LinkageSpecDecl *D);
246249261Sdim    void VisitAccessSpecDecl(const AccessSpecDecl *D);
247249261Sdim    void VisitFriendDecl(const FriendDecl *D);
248249261Sdim
249249261Sdim    // ObjC Decls
250249261Sdim    void VisitObjCIvarDecl(const ObjCIvarDecl *D);
251249261Sdim    void VisitObjCMethodDecl(const ObjCMethodDecl *D);
252249261Sdim    void VisitObjCCategoryDecl(const ObjCCategoryDecl *D);
253249261Sdim    void VisitObjCCategoryImplDecl(const ObjCCategoryImplDecl *D);
254249261Sdim    void VisitObjCProtocolDecl(const ObjCProtocolDecl *D);
255249261Sdim    void VisitObjCInterfaceDecl(const ObjCInterfaceDecl *D);
256249261Sdim    void VisitObjCImplementationDecl(const ObjCImplementationDecl *D);
257249261Sdim    void VisitObjCCompatibleAliasDecl(const ObjCCompatibleAliasDecl *D);
258249261Sdim    void VisitObjCPropertyDecl(const ObjCPropertyDecl *D);
259249261Sdim    void VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D);
260249261Sdim    void VisitBlockDecl(const BlockDecl *D);
261249261Sdim
262249261Sdim    // Stmts.
263249261Sdim    void VisitStmt(const Stmt *Node);
264249261Sdim    void VisitDeclStmt(const DeclStmt *Node);
265249261Sdim    void VisitAttributedStmt(const AttributedStmt *Node);
266249261Sdim    void VisitLabelStmt(const LabelStmt *Node);
267249261Sdim    void VisitGotoStmt(const GotoStmt *Node);
268263508Sdim    void VisitCXXCatchStmt(const CXXCatchStmt *Node);
269249261Sdim
270249261Sdim    // Exprs
271249261Sdim    void VisitExpr(const Expr *Node);
272249261Sdim    void VisitCastExpr(const CastExpr *Node);
273249261Sdim    void VisitDeclRefExpr(const DeclRefExpr *Node);
274249261Sdim    void VisitPredefinedExpr(const PredefinedExpr *Node);
275249261Sdim    void VisitCharacterLiteral(const CharacterLiteral *Node);
276249261Sdim    void VisitIntegerLiteral(const IntegerLiteral *Node);
277249261Sdim    void VisitFloatingLiteral(const FloatingLiteral *Node);
278249261Sdim    void VisitStringLiteral(const StringLiteral *Str);
279249261Sdim    void VisitUnaryOperator(const UnaryOperator *Node);
280249261Sdim    void VisitUnaryExprOrTypeTraitExpr(const UnaryExprOrTypeTraitExpr *Node);
281249261Sdim    void VisitMemberExpr(const MemberExpr *Node);
282249261Sdim    void VisitExtVectorElementExpr(const ExtVectorElementExpr *Node);
283249261Sdim    void VisitBinaryOperator(const BinaryOperator *Node);
284249261Sdim    void VisitCompoundAssignOperator(const CompoundAssignOperator *Node);
285249261Sdim    void VisitAddrLabelExpr(const AddrLabelExpr *Node);
286249261Sdim    void VisitBlockExpr(const BlockExpr *Node);
287249261Sdim    void VisitOpaqueValueExpr(const OpaqueValueExpr *Node);
288249261Sdim
289249261Sdim    // C++
290249261Sdim    void VisitCXXNamedCastExpr(const CXXNamedCastExpr *Node);
291249261Sdim    void VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr *Node);
292249261Sdim    void VisitCXXThisExpr(const CXXThisExpr *Node);
293249261Sdim    void VisitCXXFunctionalCastExpr(const CXXFunctionalCastExpr *Node);
294249261Sdim    void VisitCXXConstructExpr(const CXXConstructExpr *Node);
295249261Sdim    void VisitCXXBindTemporaryExpr(const CXXBindTemporaryExpr *Node);
296263508Sdim    void VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *Node);
297249261Sdim    void VisitExprWithCleanups(const ExprWithCleanups *Node);
298249261Sdim    void VisitUnresolvedLookupExpr(const UnresolvedLookupExpr *Node);
299249261Sdim    void dumpCXXTemporary(const CXXTemporary *Temporary);
300263508Sdim    void VisitLambdaExpr(const LambdaExpr *Node) {
301263508Sdim      VisitExpr(Node);
302263508Sdim      dumpDecl(Node->getLambdaClass());
303263508Sdim    }
304249261Sdim
305249261Sdim    // ObjC
306249261Sdim    void VisitObjCAtCatchStmt(const ObjCAtCatchStmt *Node);
307249261Sdim    void VisitObjCEncodeExpr(const ObjCEncodeExpr *Node);
308249261Sdim    void VisitObjCMessageExpr(const ObjCMessageExpr *Node);
309249261Sdim    void VisitObjCBoxedExpr(const ObjCBoxedExpr *Node);
310249261Sdim    void VisitObjCSelectorExpr(const ObjCSelectorExpr *Node);
311249261Sdim    void VisitObjCProtocolExpr(const ObjCProtocolExpr *Node);
312249261Sdim    void VisitObjCPropertyRefExpr(const ObjCPropertyRefExpr *Node);
313249261Sdim    void VisitObjCSubscriptRefExpr(const ObjCSubscriptRefExpr *Node);
314249261Sdim    void VisitObjCIvarRefExpr(const ObjCIvarRefExpr *Node);
315249261Sdim    void VisitObjCBoolLiteralExpr(const ObjCBoolLiteralExpr *Node);
316249261Sdim
317249261Sdim    // Comments.
318249261Sdim    const char *getCommandName(unsigned CommandID);
319249261Sdim    void dumpComment(const Comment *C);
320249261Sdim
321249261Sdim    // Inline comments.
322249261Sdim    void visitTextComment(const TextComment *C);
323249261Sdim    void visitInlineCommandComment(const InlineCommandComment *C);
324249261Sdim    void visitHTMLStartTagComment(const HTMLStartTagComment *C);
325249261Sdim    void visitHTMLEndTagComment(const HTMLEndTagComment *C);
326249261Sdim
327249261Sdim    // Block comments.
328249261Sdim    void visitBlockCommandComment(const BlockCommandComment *C);
329249261Sdim    void visitParamCommandComment(const ParamCommandComment *C);
330249261Sdim    void visitTParamCommandComment(const TParamCommandComment *C);
331249261Sdim    void visitVerbatimBlockComment(const VerbatimBlockComment *C);
332249261Sdim    void visitVerbatimBlockLineComment(const VerbatimBlockLineComment *C);
333249261Sdim    void visitVerbatimLineComment(const VerbatimLineComment *C);
334249261Sdim  };
335249261Sdim}
336249261Sdim
337249261Sdim//===----------------------------------------------------------------------===//
338249261Sdim//  Utilities
339249261Sdim//===----------------------------------------------------------------------===//
340249261Sdim
341249261Sdim// Print out the appropriate tree structure using the Indents vector.
342249261Sdim// Example of tree and the Indents vector at each level.
343249261Sdim// A        { }
344249261Sdim// |-B      { IT_Child }
345249261Sdim// | `-C    { IT_Child,     IT_LastChild }
346249261Sdim// `-D      { IT_LastChild }
347249261Sdim//   |-E    { IT_LastChild, IT_Child }
348249261Sdim//   `-F    { IT_LastChild, IT_LastChild }
349249261Sdim// Type            non-last element, last element
350249261Sdim// IT_Child        "| "              "|-"
351249261Sdim// IT_LastChild    "  "              "`-"
352249261Sdimvoid ASTDumper::indent() {
353249261Sdim  if (IsFirstLine)
354249261Sdim    IsFirstLine = false;
355249261Sdim  else
356249261Sdim    OS << "\n";
357249261Sdim
358249261Sdim  ColorScope Color(*this, IndentColor);
359263508Sdim  for (SmallVectorImpl<IndentType>::const_iterator I = Indents.begin(),
360263508Sdim                                                   E = Indents.end();
361249261Sdim       I != E; ++I) {
362249261Sdim    switch (*I) {
363249261Sdim    case IT_Child:
364249261Sdim      if (I == E - 1)
365249261Sdim        OS << "|-";
366249261Sdim      else
367249261Sdim        OS << "| ";
368249261Sdim      continue;
369249261Sdim    case IT_LastChild:
370249261Sdim      if (I == E - 1)
371249261Sdim        OS << "`-";
372249261Sdim      else
373249261Sdim        OS << "  ";
374249261Sdim      continue;
375249261Sdim    }
376249261Sdim    llvm_unreachable("Invalid IndentType");
377249261Sdim  }
378249261Sdim  Indents.push_back(IT_Child);
379249261Sdim}
380249261Sdim
381249261Sdimvoid ASTDumper::unindent() {
382249261Sdim  Indents.pop_back();
383249261Sdim}
384249261Sdim
385249261Sdim// Call before each potential last child node is to be dumped.  If MoreChildren
386249261Sdim// is false, then this is the last child, otherwise treat as a regular node.
387249261Sdimvoid ASTDumper::lastChild() {
388249261Sdim  if (!hasMoreChildren())
389249261Sdim    Indents.back() = IT_LastChild;
390249261Sdim}
391249261Sdim
392249261Sdim// MoreChildren should be set before calling another function that may print
393249261Sdim// additional nodes to prevent conflicting final child nodes.
394249261Sdimbool ASTDumper::hasMoreChildren() {
395249261Sdim  return MoreChildren;
396249261Sdim}
397249261Sdim
398249261Sdimvoid ASTDumper::setMoreChildren(bool Value) {
399249261Sdim  MoreChildren = Value;
400249261Sdim}
401249261Sdim
402249261Sdimvoid ASTDumper::dumpPointer(const void *Ptr) {
403249261Sdim  ColorScope Color(*this, AddressColor);
404249261Sdim  OS << ' ' << Ptr;
405249261Sdim}
406249261Sdim
407249261Sdimvoid ASTDumper::dumpLocation(SourceLocation Loc) {
408249261Sdim  ColorScope Color(*this, LocationColor);
409249261Sdim  SourceLocation SpellingLoc = SM->getSpellingLoc(Loc);
410249261Sdim
411249261Sdim  // The general format we print out is filename:line:col, but we drop pieces
412249261Sdim  // that haven't changed since the last loc printed.
413249261Sdim  PresumedLoc PLoc = SM->getPresumedLoc(SpellingLoc);
414249261Sdim
415249261Sdim  if (PLoc.isInvalid()) {
416249261Sdim    OS << "<invalid sloc>";
417249261Sdim    return;
418249261Sdim  }
419249261Sdim
420249261Sdim  if (strcmp(PLoc.getFilename(), LastLocFilename) != 0) {
421249261Sdim    OS << PLoc.getFilename() << ':' << PLoc.getLine()
422249261Sdim       << ':' << PLoc.getColumn();
423249261Sdim    LastLocFilename = PLoc.getFilename();
424249261Sdim    LastLocLine = PLoc.getLine();
425249261Sdim  } else if (PLoc.getLine() != LastLocLine) {
426249261Sdim    OS << "line" << ':' << PLoc.getLine()
427249261Sdim       << ':' << PLoc.getColumn();
428249261Sdim    LastLocLine = PLoc.getLine();
429249261Sdim  } else {
430249261Sdim    OS << "col" << ':' << PLoc.getColumn();
431249261Sdim  }
432249261Sdim}
433249261Sdim
434249261Sdimvoid ASTDumper::dumpSourceRange(SourceRange R) {
435249261Sdim  // Can't translate locations if a SourceManager isn't available.
436249261Sdim  if (!SM)
437249261Sdim    return;
438249261Sdim
439249261Sdim  OS << " <";
440249261Sdim  dumpLocation(R.getBegin());
441249261Sdim  if (R.getBegin() != R.getEnd()) {
442249261Sdim    OS << ", ";
443249261Sdim    dumpLocation(R.getEnd());
444249261Sdim  }
445249261Sdim  OS << ">";
446249261Sdim
447249261Sdim  // <t2.c:123:421[blah], t2.c:412:321>
448249261Sdim
449249261Sdim}
450249261Sdim
451249261Sdimvoid ASTDumper::dumpBareType(QualType T) {
452249261Sdim  ColorScope Color(*this, TypeColor);
453249261Sdim
454249261Sdim  SplitQualType T_split = T.split();
455249261Sdim  OS << "'" << QualType::getAsString(T_split) << "'";
456249261Sdim
457249261Sdim  if (!T.isNull()) {
458249261Sdim    // If the type is sugared, also dump a (shallow) desugared type.
459249261Sdim    SplitQualType D_split = T.getSplitDesugaredType();
460249261Sdim    if (T_split != D_split)
461249261Sdim      OS << ":'" << QualType::getAsString(D_split) << "'";
462249261Sdim  }
463249261Sdim}
464249261Sdim
465249261Sdimvoid ASTDumper::dumpType(QualType T) {
466249261Sdim  OS << ' ';
467249261Sdim  dumpBareType(T);
468249261Sdim}
469249261Sdim
470249261Sdimvoid ASTDumper::dumpBareDeclRef(const Decl *D) {
471249261Sdim  {
472249261Sdim    ColorScope Color(*this, DeclKindNameColor);
473249261Sdim    OS << D->getDeclKindName();
474249261Sdim  }
475249261Sdim  dumpPointer(D);
476249261Sdim
477249261Sdim  if (const NamedDecl *ND = dyn_cast<NamedDecl>(D)) {
478249261Sdim    ColorScope Color(*this, DeclNameColor);
479263508Sdim    OS << " '" << ND->getDeclName() << '\'';
480249261Sdim  }
481249261Sdim
482249261Sdim  if (const ValueDecl *VD = dyn_cast<ValueDecl>(D))
483249261Sdim    dumpType(VD->getType());
484249261Sdim}
485249261Sdim
486249261Sdimvoid ASTDumper::dumpDeclRef(const Decl *D, const char *Label) {
487249261Sdim  if (!D)
488249261Sdim    return;
489249261Sdim
490249261Sdim  IndentScope Indent(*this);
491249261Sdim  if (Label)
492249261Sdim    OS << Label << ' ';
493249261Sdim  dumpBareDeclRef(D);
494249261Sdim}
495249261Sdim
496249261Sdimvoid ASTDumper::dumpName(const NamedDecl *ND) {
497249261Sdim  if (ND->getDeclName()) {
498249261Sdim    ColorScope Color(*this, DeclNameColor);
499249261Sdim    OS << ' ' << ND->getNameAsString();
500249261Sdim  }
501249261Sdim}
502249261Sdim
503249261Sdimbool ASTDumper::hasNodes(const DeclContext *DC) {
504249261Sdim  if (!DC)
505249261Sdim    return false;
506249261Sdim
507263508Sdim  return DC->hasExternalLexicalStorage() ||
508263508Sdim         DC->noload_decls_begin() != DC->noload_decls_end();
509249261Sdim}
510249261Sdim
511249261Sdimvoid ASTDumper::dumpDeclContext(const DeclContext *DC) {
512249261Sdim  if (!DC)
513249261Sdim    return;
514263508Sdim  bool HasUndeserializedDecls = DC->hasExternalLexicalStorage();
515263508Sdim  for (DeclContext::decl_iterator I = DC->noload_decls_begin(),
516263508Sdim                                  E = DC->noload_decls_end();
517249261Sdim       I != E; ++I) {
518249261Sdim    DeclContext::decl_iterator Next = I;
519249261Sdim    ++Next;
520263508Sdim    if (Next == E && !HasUndeserializedDecls)
521249261Sdim      lastChild();
522249261Sdim    dumpDecl(*I);
523249261Sdim  }
524263508Sdim  if (HasUndeserializedDecls) {
525263508Sdim    lastChild();
526263508Sdim    IndentScope Indent(*this);
527263508Sdim    ColorScope Color(*this, UndeserializedColor);
528263508Sdim    OS << "<undeserialized declarations>";
529263508Sdim  }
530249261Sdim}
531249261Sdim
532263508Sdimvoid ASTDumper::dumpLookups(const DeclContext *DC) {
533263508Sdim  IndentScope Indent(*this);
534263508Sdim
535263508Sdim  OS << "StoredDeclsMap ";
536263508Sdim  dumpBareDeclRef(cast<Decl>(DC));
537263508Sdim
538263508Sdim  const DeclContext *Primary = DC->getPrimaryContext();
539263508Sdim  if (Primary != DC) {
540263508Sdim    OS << " primary";
541263508Sdim    dumpPointer(cast<Decl>(Primary));
542263508Sdim  }
543263508Sdim
544263508Sdim  bool HasUndeserializedLookups = Primary->hasExternalVisibleStorage();
545263508Sdim
546263508Sdim  DeclContext::all_lookups_iterator I = Primary->noload_lookups_begin(),
547263508Sdim                                    E = Primary->noload_lookups_end();
548263508Sdim  while (I != E) {
549263508Sdim    DeclarationName Name = I.getLookupName();
550263508Sdim    DeclContextLookupResult R = *I++;
551263508Sdim    if (I == E && !HasUndeserializedLookups)
552263508Sdim      lastChild();
553263508Sdim
554263508Sdim    IndentScope Indent(*this);
555263508Sdim    OS << "DeclarationName ";
556263508Sdim    {
557263508Sdim      ColorScope Color(*this, DeclNameColor);
558263508Sdim      OS << '\'' << Name << '\'';
559263508Sdim    }
560263508Sdim
561263508Sdim    for (DeclContextLookupResult::iterator RI = R.begin(), RE = R.end();
562263508Sdim         RI != RE; ++RI) {
563263508Sdim      if (RI + 1 == RE)
564263508Sdim        lastChild();
565263508Sdim      dumpDeclRef(*RI);
566263508Sdim      if ((*RI)->isHidden())
567263508Sdim        OS << " hidden";
568263508Sdim    }
569263508Sdim  }
570263508Sdim
571263508Sdim  if (HasUndeserializedLookups) {
572263508Sdim    lastChild();
573263508Sdim    IndentScope Indent(*this);
574263508Sdim    ColorScope Color(*this, UndeserializedColor);
575263508Sdim    OS << "<undeserialized lookups>";
576263508Sdim  }
577263508Sdim}
578263508Sdim
579249261Sdimvoid ASTDumper::dumpAttr(const Attr *A) {
580249261Sdim  IndentScope Indent(*this);
581249261Sdim  {
582249261Sdim    ColorScope Color(*this, AttrColor);
583249261Sdim    switch (A->getKind()) {
584249261Sdim#define ATTR(X) case attr::X: OS << #X; break;
585249261Sdim#include "clang/Basic/AttrList.inc"
586249261Sdim    default: llvm_unreachable("unexpected attribute kind");
587249261Sdim    }
588249261Sdim    OS << "Attr";
589249261Sdim  }
590249261Sdim  dumpPointer(A);
591249261Sdim  dumpSourceRange(A->getRange());
592249261Sdim#include "clang/AST/AttrDump.inc"
593249261Sdim}
594249261Sdim
595263508Sdimstatic void dumpPreviousDeclImpl(raw_ostream &OS, ...) {}
596263508Sdim
597263508Sdimtemplate<typename T>
598263508Sdimstatic void dumpPreviousDeclImpl(raw_ostream &OS, const Mergeable<T> *D) {
599263508Sdim  const T *First = D->getFirstDecl();
600263508Sdim  if (First != D)
601263508Sdim    OS << " first " << First;
602249261Sdim}
603249261Sdim
604249261Sdimtemplate<typename T>
605263508Sdimstatic void dumpPreviousDeclImpl(raw_ostream &OS, const Redeclarable<T> *D) {
606263508Sdim  const T *Prev = D->getPreviousDecl();
607263508Sdim  if (Prev)
608263508Sdim    OS << " prev " << Prev;
609249261Sdim}
610249261Sdim
611263508Sdim/// Dump the previous declaration in the redeclaration chain for a declaration,
612263508Sdim/// if any.
613263508Sdimstatic void dumpPreviousDecl(raw_ostream &OS, const Decl *D) {
614249261Sdim  switch (D->getKind()) {
615249261Sdim#define DECL(DERIVED, BASE) \
616249261Sdim  case Decl::DERIVED: \
617263508Sdim    return dumpPreviousDeclImpl(OS, cast<DERIVED##Decl>(D));
618249261Sdim#define ABSTRACT_DECL(DECL)
619249261Sdim#include "clang/AST/DeclNodes.inc"
620249261Sdim  }
621249261Sdim  llvm_unreachable("Decl that isn't part of DeclNodes.inc!");
622249261Sdim}
623249261Sdim
624249261Sdim//===----------------------------------------------------------------------===//
625249261Sdim//  C++ Utilities
626249261Sdim//===----------------------------------------------------------------------===//
627249261Sdim
628249261Sdimvoid ASTDumper::dumpAccessSpecifier(AccessSpecifier AS) {
629249261Sdim  switch (AS) {
630249261Sdim  case AS_none:
631249261Sdim    break;
632249261Sdim  case AS_public:
633249261Sdim    OS << "public";
634249261Sdim    break;
635249261Sdim  case AS_protected:
636249261Sdim    OS << "protected";
637249261Sdim    break;
638249261Sdim  case AS_private:
639249261Sdim    OS << "private";
640249261Sdim    break;
641249261Sdim  }
642249261Sdim}
643249261Sdim
644249261Sdimvoid ASTDumper::dumpCXXCtorInitializer(const CXXCtorInitializer *Init) {
645249261Sdim  IndentScope Indent(*this);
646249261Sdim  OS << "CXXCtorInitializer";
647249261Sdim  if (Init->isAnyMemberInitializer()) {
648249261Sdim    OS << ' ';
649249261Sdim    dumpBareDeclRef(Init->getAnyMember());
650249261Sdim  } else {
651249261Sdim    dumpType(QualType(Init->getBaseClass(), 0));
652249261Sdim  }
653249261Sdim  dumpStmt(Init->getInit());
654249261Sdim}
655249261Sdim
656249261Sdimvoid ASTDumper::dumpTemplateParameters(const TemplateParameterList *TPL) {
657249261Sdim  if (!TPL)
658249261Sdim    return;
659249261Sdim
660249261Sdim  for (TemplateParameterList::const_iterator I = TPL->begin(), E = TPL->end();
661249261Sdim       I != E; ++I)
662249261Sdim    dumpDecl(*I);
663249261Sdim}
664249261Sdim
665249261Sdimvoid ASTDumper::dumpTemplateArgumentListInfo(
666249261Sdim    const TemplateArgumentListInfo &TALI) {
667249261Sdim  for (unsigned i = 0, e = TALI.size(); i < e; ++i) {
668249261Sdim    if (i + 1 == e)
669249261Sdim      lastChild();
670249261Sdim    dumpTemplateArgumentLoc(TALI[i]);
671249261Sdim  }
672249261Sdim}
673249261Sdim
674249261Sdimvoid ASTDumper::dumpTemplateArgumentLoc(const TemplateArgumentLoc &A) {
675249261Sdim  dumpTemplateArgument(A.getArgument(), A.getSourceRange());
676249261Sdim}
677249261Sdim
678249261Sdimvoid ASTDumper::dumpTemplateArgumentList(const TemplateArgumentList &TAL) {
679249261Sdim  for (unsigned i = 0, e = TAL.size(); i < e; ++i)
680249261Sdim    dumpTemplateArgument(TAL[i]);
681249261Sdim}
682249261Sdim
683249261Sdimvoid ASTDumper::dumpTemplateArgument(const TemplateArgument &A, SourceRange R) {
684249261Sdim  IndentScope Indent(*this);
685249261Sdim  OS << "TemplateArgument";
686249261Sdim  if (R.isValid())
687249261Sdim    dumpSourceRange(R);
688249261Sdim
689249261Sdim  switch (A.getKind()) {
690249261Sdim  case TemplateArgument::Null:
691249261Sdim    OS << " null";
692249261Sdim    break;
693249261Sdim  case TemplateArgument::Type:
694249261Sdim    OS << " type";
695249261Sdim    lastChild();
696249261Sdim    dumpType(A.getAsType());
697249261Sdim    break;
698249261Sdim  case TemplateArgument::Declaration:
699249261Sdim    OS << " decl";
700249261Sdim    lastChild();
701249261Sdim    dumpDeclRef(A.getAsDecl());
702249261Sdim    break;
703249261Sdim  case TemplateArgument::NullPtr:
704249261Sdim    OS << " nullptr";
705249261Sdim    break;
706249261Sdim  case TemplateArgument::Integral:
707249261Sdim    OS << " integral " << A.getAsIntegral();
708249261Sdim    break;
709249261Sdim  case TemplateArgument::Template:
710249261Sdim    OS << " template ";
711249261Sdim    A.getAsTemplate().dump(OS);
712249261Sdim    break;
713249261Sdim  case TemplateArgument::TemplateExpansion:
714249261Sdim    OS << " template expansion";
715249261Sdim    A.getAsTemplateOrTemplatePattern().dump(OS);
716249261Sdim    break;
717249261Sdim  case TemplateArgument::Expression:
718249261Sdim    OS << " expr";
719249261Sdim    lastChild();
720249261Sdim    dumpStmt(A.getAsExpr());
721249261Sdim    break;
722249261Sdim  case TemplateArgument::Pack:
723249261Sdim    OS << " pack";
724249261Sdim    for (TemplateArgument::pack_iterator I = A.pack_begin(), E = A.pack_end();
725249261Sdim         I != E; ++I) {
726249261Sdim      if (I + 1 == E)
727249261Sdim        lastChild();
728249261Sdim      dumpTemplateArgument(*I);
729249261Sdim    }
730249261Sdim    break;
731249261Sdim  }
732249261Sdim}
733249261Sdim
734249261Sdim//===----------------------------------------------------------------------===//
735249261Sdim//  Decl dumping methods.
736249261Sdim//===----------------------------------------------------------------------===//
737249261Sdim
738249261Sdimvoid ASTDumper::dumpDecl(const Decl *D) {
739249261Sdim  IndentScope Indent(*this);
740249261Sdim
741249261Sdim  if (!D) {
742249261Sdim    ColorScope Color(*this, NullColor);
743249261Sdim    OS << "<<<NULL>>>";
744249261Sdim    return;
745249261Sdim  }
746249261Sdim
747249261Sdim  {
748249261Sdim    ColorScope Color(*this, DeclKindNameColor);
749249261Sdim    OS << D->getDeclKindName() << "Decl";
750249261Sdim  }
751249261Sdim  dumpPointer(D);
752249261Sdim  if (D->getLexicalDeclContext() != D->getDeclContext())
753249261Sdim    OS << " parent " << cast<Decl>(D->getDeclContext());
754263508Sdim  dumpPreviousDecl(OS, D);
755249261Sdim  dumpSourceRange(D->getSourceRange());
756263508Sdim  if (Module *M = D->getOwningModule())
757263508Sdim    OS << " in " << M->getFullModuleName();
758263508Sdim  if (const NamedDecl *ND = dyn_cast<NamedDecl>(D))
759263508Sdim    if (ND->isHidden())
760263508Sdim      OS << " hidden";
761249261Sdim
762249261Sdim  bool HasAttrs = D->attr_begin() != D->attr_end();
763263508Sdim  const FullComment *Comment =
764263508Sdim      D->getASTContext().getLocalCommentForDeclUncached(D);
765249261Sdim  // Decls within functions are visited by the body
766249261Sdim  bool HasDeclContext = !isa<FunctionDecl>(*D) && !isa<ObjCMethodDecl>(*D) &&
767249261Sdim                         hasNodes(dyn_cast<DeclContext>(D));
768249261Sdim
769263508Sdim  setMoreChildren(HasAttrs || Comment || HasDeclContext);
770249261Sdim  ConstDeclVisitor<ASTDumper>::Visit(D);
771249261Sdim
772263508Sdim  setMoreChildren(Comment || HasDeclContext);
773249261Sdim  for (Decl::attr_iterator I = D->attr_begin(), E = D->attr_end();
774249261Sdim       I != E; ++I) {
775249261Sdim    if (I + 1 == E)
776249261Sdim      lastChild();
777249261Sdim    dumpAttr(*I);
778249261Sdim  }
779249261Sdim
780249261Sdim  setMoreChildren(HasDeclContext);
781249261Sdim  lastChild();
782263508Sdim  dumpFullComment(Comment);
783249261Sdim
784263508Sdim  if (D->isInvalidDecl())
785263508Sdim    OS << " invalid";
786263508Sdim
787249261Sdim  setMoreChildren(false);
788249261Sdim  if (HasDeclContext)
789249261Sdim    dumpDeclContext(cast<DeclContext>(D));
790249261Sdim}
791249261Sdim
792249261Sdimvoid ASTDumper::VisitLabelDecl(const LabelDecl *D) {
793249261Sdim  dumpName(D);
794249261Sdim}
795249261Sdim
796249261Sdimvoid ASTDumper::VisitTypedefDecl(const TypedefDecl *D) {
797249261Sdim  dumpName(D);
798249261Sdim  dumpType(D->getUnderlyingType());
799249261Sdim  if (D->isModulePrivate())
800249261Sdim    OS << " __module_private__";
801249261Sdim}
802249261Sdim
803249261Sdimvoid ASTDumper::VisitEnumDecl(const EnumDecl *D) {
804249261Sdim  if (D->isScoped()) {
805249261Sdim    if (D->isScopedUsingClassTag())
806249261Sdim      OS << " class";
807249261Sdim    else
808249261Sdim      OS << " struct";
809249261Sdim  }
810249261Sdim  dumpName(D);
811249261Sdim  if (D->isModulePrivate())
812249261Sdim    OS << " __module_private__";
813249261Sdim  if (D->isFixed())
814249261Sdim    dumpType(D->getIntegerType());
815249261Sdim}
816249261Sdim
817249261Sdimvoid ASTDumper::VisitRecordDecl(const RecordDecl *D) {
818249261Sdim  OS << ' ' << D->getKindName();
819249261Sdim  dumpName(D);
820249261Sdim  if (D->isModulePrivate())
821249261Sdim    OS << " __module_private__";
822263508Sdim  if (D->isCompleteDefinition())
823263508Sdim    OS << " definition";
824249261Sdim}
825249261Sdim
826249261Sdimvoid ASTDumper::VisitEnumConstantDecl(const EnumConstantDecl *D) {
827249261Sdim  dumpName(D);
828249261Sdim  dumpType(D->getType());
829249261Sdim  if (const Expr *Init = D->getInitExpr()) {
830249261Sdim    lastChild();
831249261Sdim    dumpStmt(Init);
832249261Sdim  }
833249261Sdim}
834249261Sdim
835249261Sdimvoid ASTDumper::VisitIndirectFieldDecl(const IndirectFieldDecl *D) {
836249261Sdim  dumpName(D);
837249261Sdim  dumpType(D->getType());
838249261Sdim  for (IndirectFieldDecl::chain_iterator I = D->chain_begin(),
839249261Sdim                                         E = D->chain_end();
840249261Sdim       I != E; ++I) {
841249261Sdim    if (I + 1 == E)
842249261Sdim      lastChild();
843249261Sdim    dumpDeclRef(*I);
844249261Sdim  }
845249261Sdim}
846249261Sdim
847249261Sdimvoid ASTDumper::VisitFunctionDecl(const FunctionDecl *D) {
848249261Sdim  dumpName(D);
849249261Sdim  dumpType(D->getType());
850249261Sdim
851249261Sdim  StorageClass SC = D->getStorageClass();
852249261Sdim  if (SC != SC_None)
853249261Sdim    OS << ' ' << VarDecl::getStorageClassSpecifierString(SC);
854249261Sdim  if (D->isInlineSpecified())
855249261Sdim    OS << " inline";
856249261Sdim  if (D->isVirtualAsWritten())
857249261Sdim    OS << " virtual";
858249261Sdim  if (D->isModulePrivate())
859249261Sdim    OS << " __module_private__";
860249261Sdim
861249261Sdim  if (D->isPure())
862249261Sdim    OS << " pure";
863249261Sdim  else if (D->isDeletedAsWritten())
864249261Sdim    OS << " delete";
865249261Sdim
866263508Sdim  if (const FunctionProtoType *FPT = D->getType()->getAs<FunctionProtoType>()) {
867263508Sdim    FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo();
868263508Sdim    switch (EPI.ExceptionSpecType) {
869263508Sdim    default: break;
870263508Sdim    case EST_Unevaluated:
871263508Sdim      OS << " noexcept-unevaluated " << EPI.ExceptionSpecDecl;
872263508Sdim      break;
873263508Sdim    case EST_Uninstantiated:
874263508Sdim      OS << " noexcept-uninstantiated " << EPI.ExceptionSpecTemplate;
875263508Sdim      break;
876263508Sdim    }
877263508Sdim  }
878263508Sdim
879249261Sdim  bool OldMoreChildren = hasMoreChildren();
880249261Sdim  const FunctionTemplateSpecializationInfo *FTSI =
881249261Sdim      D->getTemplateSpecializationInfo();
882249261Sdim  bool HasTemplateSpecialization = FTSI;
883249261Sdim
884249261Sdim  bool HasNamedDecls = D->getDeclsInPrototypeScope().begin() !=
885249261Sdim                       D->getDeclsInPrototypeScope().end();
886249261Sdim
887249261Sdim  bool HasFunctionDecls = D->param_begin() != D->param_end();
888249261Sdim
889249261Sdim  const CXXConstructorDecl *C = dyn_cast<CXXConstructorDecl>(D);
890249261Sdim  bool HasCtorInitializers = C && C->init_begin() != C->init_end();
891249261Sdim
892249261Sdim  bool HasDeclarationBody = D->doesThisDeclarationHaveABody();
893249261Sdim
894249261Sdim  setMoreChildren(OldMoreChildren || HasNamedDecls || HasFunctionDecls ||
895249261Sdim                  HasCtorInitializers || HasDeclarationBody);
896249261Sdim  if (HasTemplateSpecialization) {
897249261Sdim    lastChild();
898249261Sdim    dumpTemplateArgumentList(*FTSI->TemplateArguments);
899249261Sdim  }
900249261Sdim
901249261Sdim  setMoreChildren(OldMoreChildren || HasFunctionDecls ||
902249261Sdim                  HasCtorInitializers || HasDeclarationBody);
903249261Sdim  for (ArrayRef<NamedDecl *>::iterator
904249261Sdim       I = D->getDeclsInPrototypeScope().begin(),
905249261Sdim       E = D->getDeclsInPrototypeScope().end(); I != E; ++I) {
906249261Sdim    if (I + 1 == E)
907249261Sdim      lastChild();
908249261Sdim    dumpDecl(*I);
909249261Sdim  }
910249261Sdim
911249261Sdim  setMoreChildren(OldMoreChildren || HasCtorInitializers || HasDeclarationBody);
912249261Sdim  for (FunctionDecl::param_const_iterator I = D->param_begin(),
913249261Sdim                                          E = D->param_end();
914249261Sdim       I != E; ++I) {
915249261Sdim    if (I + 1 == E)
916249261Sdim      lastChild();
917249261Sdim    dumpDecl(*I);
918249261Sdim  }
919249261Sdim
920249261Sdim  setMoreChildren(OldMoreChildren || HasDeclarationBody);
921249261Sdim  if (HasCtorInitializers)
922249261Sdim    for (CXXConstructorDecl::init_const_iterator I = C->init_begin(),
923249261Sdim                                                 E = C->init_end();
924249261Sdim         I != E; ++I) {
925249261Sdim      if (I + 1 == E)
926249261Sdim        lastChild();
927249261Sdim      dumpCXXCtorInitializer(*I);
928249261Sdim  }
929249261Sdim
930249261Sdim  setMoreChildren(OldMoreChildren);
931249261Sdim  if (HasDeclarationBody) {
932249261Sdim    lastChild();
933249261Sdim    dumpStmt(D->getBody());
934249261Sdim  }
935249261Sdim}
936249261Sdim
937249261Sdimvoid ASTDumper::VisitFieldDecl(const FieldDecl *D) {
938249261Sdim  dumpName(D);
939249261Sdim  dumpType(D->getType());
940249261Sdim  if (D->isMutable())
941249261Sdim    OS << " mutable";
942249261Sdim  if (D->isModulePrivate())
943249261Sdim    OS << " __module_private__";
944249261Sdim
945249261Sdim  bool OldMoreChildren = hasMoreChildren();
946249261Sdim  bool IsBitField = D->isBitField();
947249261Sdim  Expr *Init = D->getInClassInitializer();
948249261Sdim  bool HasInit = Init;
949249261Sdim
950249261Sdim  setMoreChildren(OldMoreChildren || HasInit);
951249261Sdim  if (IsBitField) {
952249261Sdim    lastChild();
953249261Sdim    dumpStmt(D->getBitWidth());
954249261Sdim  }
955249261Sdim  setMoreChildren(OldMoreChildren);
956249261Sdim  if (HasInit) {
957249261Sdim    lastChild();
958249261Sdim    dumpStmt(Init);
959249261Sdim  }
960249261Sdim}
961249261Sdim
962249261Sdimvoid ASTDumper::VisitVarDecl(const VarDecl *D) {
963249261Sdim  dumpName(D);
964249261Sdim  dumpType(D->getType());
965249261Sdim  StorageClass SC = D->getStorageClass();
966249261Sdim  if (SC != SC_None)
967249261Sdim    OS << ' ' << VarDecl::getStorageClassSpecifierString(SC);
968251662Sdim  switch (D->getTLSKind()) {
969251662Sdim  case VarDecl::TLS_None: break;
970251662Sdim  case VarDecl::TLS_Static: OS << " tls"; break;
971251662Sdim  case VarDecl::TLS_Dynamic: OS << " tls_dynamic"; break;
972251662Sdim  }
973249261Sdim  if (D->isModulePrivate())
974249261Sdim    OS << " __module_private__";
975249261Sdim  if (D->isNRVOVariable())
976249261Sdim    OS << " nrvo";
977249261Sdim  if (D->hasInit()) {
978249261Sdim    lastChild();
979249261Sdim    dumpStmt(D->getInit());
980249261Sdim  }
981249261Sdim}
982249261Sdim
983249261Sdimvoid ASTDumper::VisitFileScopeAsmDecl(const FileScopeAsmDecl *D) {
984249261Sdim  lastChild();
985249261Sdim  dumpStmt(D->getAsmString());
986249261Sdim}
987249261Sdim
988249261Sdimvoid ASTDumper::VisitImportDecl(const ImportDecl *D) {
989249261Sdim  OS << ' ' << D->getImportedModule()->getFullModuleName();
990249261Sdim}
991249261Sdim
992249261Sdim//===----------------------------------------------------------------------===//
993249261Sdim// C++ Declarations
994249261Sdim//===----------------------------------------------------------------------===//
995249261Sdim
996249261Sdimvoid ASTDumper::VisitNamespaceDecl(const NamespaceDecl *D) {
997249261Sdim  dumpName(D);
998249261Sdim  if (D->isInline())
999249261Sdim    OS << " inline";
1000249261Sdim  if (!D->isOriginalNamespace())
1001249261Sdim    dumpDeclRef(D->getOriginalNamespace(), "original");
1002249261Sdim}
1003249261Sdim
1004249261Sdimvoid ASTDumper::VisitUsingDirectiveDecl(const UsingDirectiveDecl *D) {
1005249261Sdim  OS << ' ';
1006249261Sdim  dumpBareDeclRef(D->getNominatedNamespace());
1007249261Sdim}
1008249261Sdim
1009249261Sdimvoid ASTDumper::VisitNamespaceAliasDecl(const NamespaceAliasDecl *D) {
1010249261Sdim  dumpName(D);
1011249261Sdim  dumpDeclRef(D->getAliasedNamespace());
1012249261Sdim}
1013249261Sdim
1014249261Sdimvoid ASTDumper::VisitTypeAliasDecl(const TypeAliasDecl *D) {
1015249261Sdim  dumpName(D);
1016249261Sdim  dumpType(D->getUnderlyingType());
1017249261Sdim}
1018249261Sdim
1019249261Sdimvoid ASTDumper::VisitTypeAliasTemplateDecl(const TypeAliasTemplateDecl *D) {
1020249261Sdim  dumpName(D);
1021249261Sdim  dumpTemplateParameters(D->getTemplateParameters());
1022249261Sdim  dumpDecl(D->getTemplatedDecl());
1023249261Sdim}
1024249261Sdim
1025249261Sdimvoid ASTDumper::VisitCXXRecordDecl(const CXXRecordDecl *D) {
1026249261Sdim  VisitRecordDecl(D);
1027249261Sdim  if (!D->isCompleteDefinition())
1028249261Sdim    return;
1029249261Sdim
1030249261Sdim  for (CXXRecordDecl::base_class_const_iterator I = D->bases_begin(),
1031249261Sdim                                                E = D->bases_end();
1032249261Sdim       I != E; ++I) {
1033249261Sdim    IndentScope Indent(*this);
1034249261Sdim    if (I->isVirtual())
1035249261Sdim      OS << "virtual ";
1036249261Sdim    dumpAccessSpecifier(I->getAccessSpecifier());
1037249261Sdim    dumpType(I->getType());
1038249261Sdim    if (I->isPackExpansion())
1039249261Sdim      OS << "...";
1040249261Sdim  }
1041249261Sdim}
1042249261Sdim
1043249261Sdimvoid ASTDumper::VisitStaticAssertDecl(const StaticAssertDecl *D) {
1044249261Sdim  dumpStmt(D->getAssertExpr());
1045249261Sdim  lastChild();
1046249261Sdim  dumpStmt(D->getMessage());
1047249261Sdim}
1048249261Sdim
1049249261Sdimvoid ASTDumper::VisitFunctionTemplateDecl(const FunctionTemplateDecl *D) {
1050249261Sdim  dumpName(D);
1051249261Sdim  dumpTemplateParameters(D->getTemplateParameters());
1052249261Sdim  dumpDecl(D->getTemplatedDecl());
1053249261Sdim  for (FunctionTemplateDecl::spec_iterator I = D->spec_begin(),
1054249261Sdim                                           E = D->spec_end();
1055249261Sdim       I != E; ++I) {
1056249261Sdim    FunctionTemplateDecl::spec_iterator Next = I;
1057249261Sdim    ++Next;
1058249261Sdim    if (Next == E)
1059249261Sdim      lastChild();
1060249261Sdim    switch (I->getTemplateSpecializationKind()) {
1061249261Sdim    case TSK_Undeclared:
1062249261Sdim    case TSK_ImplicitInstantiation:
1063249261Sdim    case TSK_ExplicitInstantiationDeclaration:
1064249261Sdim    case TSK_ExplicitInstantiationDefinition:
1065249261Sdim      if (D == D->getCanonicalDecl())
1066249261Sdim        dumpDecl(*I);
1067249261Sdim      else
1068249261Sdim        dumpDeclRef(*I);
1069249261Sdim      break;
1070249261Sdim    case TSK_ExplicitSpecialization:
1071249261Sdim      dumpDeclRef(*I);
1072249261Sdim      break;
1073249261Sdim    }
1074249261Sdim  }
1075249261Sdim}
1076249261Sdim
1077249261Sdimvoid ASTDumper::VisitClassTemplateDecl(const ClassTemplateDecl *D) {
1078249261Sdim  dumpName(D);
1079249261Sdim  dumpTemplateParameters(D->getTemplateParameters());
1080249261Sdim
1081249261Sdim  ClassTemplateDecl::spec_iterator I = D->spec_begin();
1082249261Sdim  ClassTemplateDecl::spec_iterator E = D->spec_end();
1083249261Sdim  if (I == E)
1084249261Sdim    lastChild();
1085249261Sdim  dumpDecl(D->getTemplatedDecl());
1086249261Sdim  for (; I != E; ++I) {
1087249261Sdim    ClassTemplateDecl::spec_iterator Next = I;
1088249261Sdim    ++Next;
1089249261Sdim    if (Next == E)
1090249261Sdim      lastChild();
1091249261Sdim    switch (I->getTemplateSpecializationKind()) {
1092249261Sdim    case TSK_Undeclared:
1093249261Sdim    case TSK_ImplicitInstantiation:
1094249261Sdim      if (D == D->getCanonicalDecl())
1095249261Sdim        dumpDecl(*I);
1096249261Sdim      else
1097249261Sdim        dumpDeclRef(*I);
1098249261Sdim      break;
1099249261Sdim    case TSK_ExplicitSpecialization:
1100249261Sdim    case TSK_ExplicitInstantiationDeclaration:
1101249261Sdim    case TSK_ExplicitInstantiationDefinition:
1102249261Sdim      dumpDeclRef(*I);
1103249261Sdim      break;
1104249261Sdim    }
1105249261Sdim  }
1106249261Sdim}
1107249261Sdim
1108249261Sdimvoid ASTDumper::VisitClassTemplateSpecializationDecl(
1109249261Sdim    const ClassTemplateSpecializationDecl *D) {
1110249261Sdim  VisitCXXRecordDecl(D);
1111249261Sdim  dumpTemplateArgumentList(D->getTemplateArgs());
1112249261Sdim}
1113249261Sdim
1114249261Sdimvoid ASTDumper::VisitClassTemplatePartialSpecializationDecl(
1115249261Sdim    const ClassTemplatePartialSpecializationDecl *D) {
1116249261Sdim  VisitClassTemplateSpecializationDecl(D);
1117249261Sdim  dumpTemplateParameters(D->getTemplateParameters());
1118249261Sdim}
1119249261Sdim
1120249261Sdimvoid ASTDumper::VisitClassScopeFunctionSpecializationDecl(
1121249261Sdim    const ClassScopeFunctionSpecializationDecl *D) {
1122249261Sdim  dumpDeclRef(D->getSpecialization());
1123249261Sdim  if (D->hasExplicitTemplateArgs())
1124249261Sdim    dumpTemplateArgumentListInfo(D->templateArgs());
1125249261Sdim}
1126249261Sdim
1127263508Sdimvoid ASTDumper::VisitVarTemplateDecl(const VarTemplateDecl *D) {
1128263508Sdim  dumpName(D);
1129263508Sdim  dumpTemplateParameters(D->getTemplateParameters());
1130263508Sdim
1131263508Sdim  VarTemplateDecl::spec_iterator I = D->spec_begin();
1132263508Sdim  VarTemplateDecl::spec_iterator E = D->spec_end();
1133263508Sdim  if (I == E)
1134263508Sdim    lastChild();
1135263508Sdim  dumpDecl(D->getTemplatedDecl());
1136263508Sdim  for (; I != E; ++I) {
1137263508Sdim    VarTemplateDecl::spec_iterator Next = I;
1138263508Sdim    ++Next;
1139263508Sdim    if (Next == E)
1140263508Sdim      lastChild();
1141263508Sdim    switch (I->getTemplateSpecializationKind()) {
1142263508Sdim    case TSK_Undeclared:
1143263508Sdim    case TSK_ImplicitInstantiation:
1144263508Sdim      if (D == D->getCanonicalDecl())
1145263508Sdim        dumpDecl(*I);
1146263508Sdim      else
1147263508Sdim        dumpDeclRef(*I);
1148263508Sdim      break;
1149263508Sdim    case TSK_ExplicitSpecialization:
1150263508Sdim    case TSK_ExplicitInstantiationDeclaration:
1151263508Sdim    case TSK_ExplicitInstantiationDefinition:
1152263508Sdim      dumpDeclRef(*I);
1153263508Sdim      break;
1154263508Sdim    }
1155263508Sdim  }
1156263508Sdim}
1157263508Sdim
1158263508Sdimvoid ASTDumper::VisitVarTemplateSpecializationDecl(
1159263508Sdim    const VarTemplateSpecializationDecl *D) {
1160263508Sdim  dumpTemplateArgumentList(D->getTemplateArgs());
1161263508Sdim  VisitVarDecl(D);
1162263508Sdim}
1163263508Sdim
1164263508Sdimvoid ASTDumper::VisitVarTemplatePartialSpecializationDecl(
1165263508Sdim    const VarTemplatePartialSpecializationDecl *D) {
1166263508Sdim  dumpTemplateParameters(D->getTemplateParameters());
1167263508Sdim  VisitVarTemplateSpecializationDecl(D);
1168263508Sdim}
1169263508Sdim
1170249261Sdimvoid ASTDumper::VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *D) {
1171249261Sdim  if (D->wasDeclaredWithTypename())
1172249261Sdim    OS << " typename";
1173249261Sdim  else
1174249261Sdim    OS << " class";
1175249261Sdim  if (D->isParameterPack())
1176249261Sdim    OS << " ...";
1177249261Sdim  dumpName(D);
1178249261Sdim  if (D->hasDefaultArgument())
1179249261Sdim    dumpType(D->getDefaultArgument());
1180249261Sdim}
1181249261Sdim
1182249261Sdimvoid ASTDumper::VisitNonTypeTemplateParmDecl(const NonTypeTemplateParmDecl *D) {
1183249261Sdim  dumpType(D->getType());
1184249261Sdim  if (D->isParameterPack())
1185249261Sdim    OS << " ...";
1186249261Sdim  dumpName(D);
1187249261Sdim  if (D->hasDefaultArgument())
1188249261Sdim    dumpStmt(D->getDefaultArgument());
1189249261Sdim}
1190249261Sdim
1191249261Sdimvoid ASTDumper::VisitTemplateTemplateParmDecl(
1192249261Sdim    const TemplateTemplateParmDecl *D) {
1193249261Sdim  if (D->isParameterPack())
1194249261Sdim    OS << " ...";
1195249261Sdim  dumpName(D);
1196249261Sdim  dumpTemplateParameters(D->getTemplateParameters());
1197249261Sdim  if (D->hasDefaultArgument())
1198249261Sdim    dumpTemplateArgumentLoc(D->getDefaultArgument());
1199249261Sdim}
1200249261Sdim
1201249261Sdimvoid ASTDumper::VisitUsingDecl(const UsingDecl *D) {
1202249261Sdim  OS << ' ';
1203249261Sdim  D->getQualifier()->print(OS, D->getASTContext().getPrintingPolicy());
1204249261Sdim  OS << D->getNameAsString();
1205249261Sdim}
1206249261Sdim
1207249261Sdimvoid ASTDumper::VisitUnresolvedUsingTypenameDecl(
1208249261Sdim    const UnresolvedUsingTypenameDecl *D) {
1209249261Sdim  OS << ' ';
1210249261Sdim  D->getQualifier()->print(OS, D->getASTContext().getPrintingPolicy());
1211249261Sdim  OS << D->getNameAsString();
1212249261Sdim}
1213249261Sdim
1214249261Sdimvoid ASTDumper::VisitUnresolvedUsingValueDecl(const UnresolvedUsingValueDecl *D) {
1215249261Sdim  OS << ' ';
1216249261Sdim  D->getQualifier()->print(OS, D->getASTContext().getPrintingPolicy());
1217249261Sdim  OS << D->getNameAsString();
1218249261Sdim  dumpType(D->getType());
1219249261Sdim}
1220249261Sdim
1221249261Sdimvoid ASTDumper::VisitUsingShadowDecl(const UsingShadowDecl *D) {
1222249261Sdim  OS << ' ';
1223249261Sdim  dumpBareDeclRef(D->getTargetDecl());
1224249261Sdim}
1225249261Sdim
1226249261Sdimvoid ASTDumper::VisitLinkageSpecDecl(const LinkageSpecDecl *D) {
1227249261Sdim  switch (D->getLanguage()) {
1228249261Sdim  case LinkageSpecDecl::lang_c: OS << " C"; break;
1229249261Sdim  case LinkageSpecDecl::lang_cxx: OS << " C++"; break;
1230249261Sdim  }
1231249261Sdim}
1232249261Sdim
1233249261Sdimvoid ASTDumper::VisitAccessSpecDecl(const AccessSpecDecl *D) {
1234249261Sdim  OS << ' ';
1235249261Sdim  dumpAccessSpecifier(D->getAccess());
1236249261Sdim}
1237249261Sdim
1238249261Sdimvoid ASTDumper::VisitFriendDecl(const FriendDecl *D) {
1239249261Sdim  lastChild();
1240249261Sdim  if (TypeSourceInfo *T = D->getFriendType())
1241249261Sdim    dumpType(T->getType());
1242249261Sdim  else
1243249261Sdim    dumpDecl(D->getFriendDecl());
1244249261Sdim}
1245249261Sdim
1246249261Sdim//===----------------------------------------------------------------------===//
1247249261Sdim// Obj-C Declarations
1248249261Sdim//===----------------------------------------------------------------------===//
1249249261Sdim
1250249261Sdimvoid ASTDumper::VisitObjCIvarDecl(const ObjCIvarDecl *D) {
1251249261Sdim  dumpName(D);
1252249261Sdim  dumpType(D->getType());
1253249261Sdim  if (D->getSynthesize())
1254249261Sdim    OS << " synthesize";
1255263508Sdim  if (D->getBackingIvarReferencedInAccessor())
1256263508Sdim    OS << " BackingIvarReferencedInAccessor";
1257249261Sdim
1258249261Sdim  switch (D->getAccessControl()) {
1259249261Sdim  case ObjCIvarDecl::None:
1260249261Sdim    OS << " none";
1261249261Sdim    break;
1262249261Sdim  case ObjCIvarDecl::Private:
1263249261Sdim    OS << " private";
1264249261Sdim    break;
1265249261Sdim  case ObjCIvarDecl::Protected:
1266249261Sdim    OS << " protected";
1267249261Sdim    break;
1268249261Sdim  case ObjCIvarDecl::Public:
1269249261Sdim    OS << " public";
1270249261Sdim    break;
1271249261Sdim  case ObjCIvarDecl::Package:
1272249261Sdim    OS << " package";
1273249261Sdim    break;
1274249261Sdim  }
1275249261Sdim}
1276249261Sdim
1277249261Sdimvoid ASTDumper::VisitObjCMethodDecl(const ObjCMethodDecl *D) {
1278249261Sdim  if (D->isInstanceMethod())
1279249261Sdim    OS << " -";
1280249261Sdim  else
1281249261Sdim    OS << " +";
1282249261Sdim  dumpName(D);
1283249261Sdim  dumpType(D->getResultType());
1284249261Sdim
1285249261Sdim  bool OldMoreChildren = hasMoreChildren();
1286249261Sdim  bool IsVariadic = D->isVariadic();
1287249261Sdim  bool HasBody = D->hasBody();
1288249261Sdim
1289249261Sdim  setMoreChildren(OldMoreChildren || IsVariadic || HasBody);
1290249261Sdim  if (D->isThisDeclarationADefinition()) {
1291249261Sdim    lastChild();
1292249261Sdim    dumpDeclContext(D);
1293249261Sdim  } else {
1294249261Sdim    for (ObjCMethodDecl::param_const_iterator I = D->param_begin(),
1295249261Sdim                                              E = D->param_end();
1296249261Sdim         I != E; ++I) {
1297249261Sdim      if (I + 1 == E)
1298249261Sdim        lastChild();
1299249261Sdim      dumpDecl(*I);
1300249261Sdim    }
1301249261Sdim  }
1302249261Sdim
1303249261Sdim  setMoreChildren(OldMoreChildren || HasBody);
1304249261Sdim  if (IsVariadic) {
1305249261Sdim    lastChild();
1306249261Sdim    IndentScope Indent(*this);
1307249261Sdim    OS << "...";
1308249261Sdim  }
1309249261Sdim
1310249261Sdim  setMoreChildren(OldMoreChildren);
1311249261Sdim  if (HasBody) {
1312249261Sdim    lastChild();
1313249261Sdim    dumpStmt(D->getBody());
1314249261Sdim  }
1315249261Sdim}
1316249261Sdim
1317249261Sdimvoid ASTDumper::VisitObjCCategoryDecl(const ObjCCategoryDecl *D) {
1318249261Sdim  dumpName(D);
1319249261Sdim  dumpDeclRef(D->getClassInterface());
1320249261Sdim  if (D->protocol_begin() == D->protocol_end())
1321249261Sdim    lastChild();
1322249261Sdim  dumpDeclRef(D->getImplementation());
1323249261Sdim  for (ObjCCategoryDecl::protocol_iterator I = D->protocol_begin(),
1324249261Sdim                                           E = D->protocol_end();
1325249261Sdim       I != E; ++I) {
1326249261Sdim    if (I + 1 == E)
1327249261Sdim      lastChild();
1328249261Sdim    dumpDeclRef(*I);
1329249261Sdim  }
1330249261Sdim}
1331249261Sdim
1332249261Sdimvoid ASTDumper::VisitObjCCategoryImplDecl(const ObjCCategoryImplDecl *D) {
1333249261Sdim  dumpName(D);
1334249261Sdim  dumpDeclRef(D->getClassInterface());
1335249261Sdim  lastChild();
1336249261Sdim  dumpDeclRef(D->getCategoryDecl());
1337249261Sdim}
1338249261Sdim
1339249261Sdimvoid ASTDumper::VisitObjCProtocolDecl(const ObjCProtocolDecl *D) {
1340249261Sdim  dumpName(D);
1341249261Sdim  for (ObjCProtocolDecl::protocol_iterator I = D->protocol_begin(),
1342249261Sdim                                           E = D->protocol_end();
1343249261Sdim       I != E; ++I) {
1344249261Sdim    if (I + 1 == E)
1345249261Sdim      lastChild();
1346249261Sdim    dumpDeclRef(*I);
1347249261Sdim  }
1348249261Sdim}
1349249261Sdim
1350249261Sdimvoid ASTDumper::VisitObjCInterfaceDecl(const ObjCInterfaceDecl *D) {
1351249261Sdim  dumpName(D);
1352249261Sdim  dumpDeclRef(D->getSuperClass(), "super");
1353249261Sdim  if (D->protocol_begin() == D->protocol_end())
1354249261Sdim    lastChild();
1355249261Sdim  dumpDeclRef(D->getImplementation());
1356249261Sdim  for (ObjCInterfaceDecl::protocol_iterator I = D->protocol_begin(),
1357249261Sdim                                            E = D->protocol_end();
1358249261Sdim       I != E; ++I) {
1359249261Sdim    if (I + 1 == E)
1360249261Sdim      lastChild();
1361249261Sdim    dumpDeclRef(*I);
1362249261Sdim  }
1363249261Sdim}
1364249261Sdim
1365249261Sdimvoid ASTDumper::VisitObjCImplementationDecl(const ObjCImplementationDecl *D) {
1366249261Sdim  dumpName(D);
1367249261Sdim  dumpDeclRef(D->getSuperClass(), "super");
1368249261Sdim  if (D->init_begin() == D->init_end())
1369249261Sdim    lastChild();
1370249261Sdim  dumpDeclRef(D->getClassInterface());
1371249261Sdim  for (ObjCImplementationDecl::init_const_iterator I = D->init_begin(),
1372249261Sdim                                                   E = D->init_end();
1373249261Sdim       I != E; ++I) {
1374249261Sdim    if (I + 1 == E)
1375249261Sdim      lastChild();
1376249261Sdim    dumpCXXCtorInitializer(*I);
1377249261Sdim  }
1378249261Sdim}
1379249261Sdim
1380249261Sdimvoid ASTDumper::VisitObjCCompatibleAliasDecl(const ObjCCompatibleAliasDecl *D) {
1381249261Sdim  dumpName(D);
1382249261Sdim  lastChild();
1383249261Sdim  dumpDeclRef(D->getClassInterface());
1384249261Sdim}
1385249261Sdim
1386249261Sdimvoid ASTDumper::VisitObjCPropertyDecl(const ObjCPropertyDecl *D) {
1387249261Sdim  dumpName(D);
1388249261Sdim  dumpType(D->getType());
1389249261Sdim
1390249261Sdim  if (D->getPropertyImplementation() == ObjCPropertyDecl::Required)
1391249261Sdim    OS << " required";
1392249261Sdim  else if (D->getPropertyImplementation() == ObjCPropertyDecl::Optional)
1393249261Sdim    OS << " optional";
1394249261Sdim
1395249261Sdim  ObjCPropertyDecl::PropertyAttributeKind Attrs = D->getPropertyAttributes();
1396249261Sdim  if (Attrs != ObjCPropertyDecl::OBJC_PR_noattr) {
1397249261Sdim    if (Attrs & ObjCPropertyDecl::OBJC_PR_readonly)
1398249261Sdim      OS << " readonly";
1399249261Sdim    if (Attrs & ObjCPropertyDecl::OBJC_PR_assign)
1400249261Sdim      OS << " assign";
1401249261Sdim    if (Attrs & ObjCPropertyDecl::OBJC_PR_readwrite)
1402249261Sdim      OS << " readwrite";
1403249261Sdim    if (Attrs & ObjCPropertyDecl::OBJC_PR_retain)
1404249261Sdim      OS << " retain";
1405249261Sdim    if (Attrs & ObjCPropertyDecl::OBJC_PR_copy)
1406249261Sdim      OS << " copy";
1407249261Sdim    if (Attrs & ObjCPropertyDecl::OBJC_PR_nonatomic)
1408249261Sdim      OS << " nonatomic";
1409249261Sdim    if (Attrs & ObjCPropertyDecl::OBJC_PR_atomic)
1410249261Sdim      OS << " atomic";
1411249261Sdim    if (Attrs & ObjCPropertyDecl::OBJC_PR_weak)
1412249261Sdim      OS << " weak";
1413249261Sdim    if (Attrs & ObjCPropertyDecl::OBJC_PR_strong)
1414249261Sdim      OS << " strong";
1415249261Sdim    if (Attrs & ObjCPropertyDecl::OBJC_PR_unsafe_unretained)
1416249261Sdim      OS << " unsafe_unretained";
1417249261Sdim    if (Attrs & ObjCPropertyDecl::OBJC_PR_getter) {
1418249261Sdim      if (!(Attrs & ObjCPropertyDecl::OBJC_PR_setter))
1419249261Sdim        lastChild();
1420249261Sdim      dumpDeclRef(D->getGetterMethodDecl(), "getter");
1421249261Sdim    }
1422249261Sdim    if (Attrs & ObjCPropertyDecl::OBJC_PR_setter) {
1423249261Sdim      lastChild();
1424249261Sdim      dumpDeclRef(D->getSetterMethodDecl(), "setter");
1425249261Sdim    }
1426249261Sdim  }
1427249261Sdim}
1428249261Sdim
1429249261Sdimvoid ASTDumper::VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D) {
1430249261Sdim  dumpName(D->getPropertyDecl());
1431249261Sdim  if (D->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize)
1432249261Sdim    OS << " synthesize";
1433249261Sdim  else
1434249261Sdim    OS << " dynamic";
1435249261Sdim  dumpDeclRef(D->getPropertyDecl());
1436249261Sdim  lastChild();
1437249261Sdim  dumpDeclRef(D->getPropertyIvarDecl());
1438249261Sdim}
1439249261Sdim
1440249261Sdimvoid ASTDumper::VisitBlockDecl(const BlockDecl *D) {
1441249261Sdim  for (BlockDecl::param_const_iterator I = D->param_begin(), E = D->param_end();
1442249261Sdim       I != E; ++I)
1443249261Sdim    dumpDecl(*I);
1444249261Sdim
1445249261Sdim  if (D->isVariadic()) {
1446249261Sdim    IndentScope Indent(*this);
1447249261Sdim    OS << "...";
1448249261Sdim  }
1449249261Sdim
1450249261Sdim  if (D->capturesCXXThis()) {
1451249261Sdim    IndentScope Indent(*this);
1452249261Sdim    OS << "capture this";
1453249261Sdim  }
1454249261Sdim  for (BlockDecl::capture_iterator I = D->capture_begin(), E = D->capture_end();
1455249261Sdim       I != E; ++I) {
1456249261Sdim    IndentScope Indent(*this);
1457249261Sdim    OS << "capture";
1458249261Sdim    if (I->isByRef())
1459249261Sdim      OS << " byref";
1460249261Sdim    if (I->isNested())
1461249261Sdim      OS << " nested";
1462249261Sdim    if (I->getVariable()) {
1463249261Sdim      OS << ' ';
1464249261Sdim      dumpBareDeclRef(I->getVariable());
1465249261Sdim    }
1466249261Sdim    if (I->hasCopyExpr())
1467249261Sdim      dumpStmt(I->getCopyExpr());
1468249261Sdim  }
1469249261Sdim  lastChild();
1470249261Sdim  dumpStmt(D->getBody());
1471249261Sdim}
1472249261Sdim
1473249261Sdim//===----------------------------------------------------------------------===//
1474249261Sdim//  Stmt dumping methods.
1475249261Sdim//===----------------------------------------------------------------------===//
1476249261Sdim
1477249261Sdimvoid ASTDumper::dumpStmt(const Stmt *S) {
1478249261Sdim  IndentScope Indent(*this);
1479249261Sdim
1480249261Sdim  if (!S) {
1481249261Sdim    ColorScope Color(*this, NullColor);
1482249261Sdim    OS << "<<<NULL>>>";
1483249261Sdim    return;
1484249261Sdim  }
1485249261Sdim
1486249261Sdim  if (const DeclStmt *DS = dyn_cast<DeclStmt>(S)) {
1487249261Sdim    VisitDeclStmt(DS);
1488249261Sdim    return;
1489249261Sdim  }
1490249261Sdim
1491263508Sdim  setMoreChildren(!S->children().empty());
1492249261Sdim  ConstStmtVisitor<ASTDumper>::Visit(S);
1493249261Sdim  setMoreChildren(false);
1494249261Sdim  for (Stmt::const_child_range CI = S->children(); CI; ++CI) {
1495249261Sdim    Stmt::const_child_range Next = CI;
1496249261Sdim    ++Next;
1497249261Sdim    if (!Next)
1498249261Sdim      lastChild();
1499249261Sdim    dumpStmt(*CI);
1500249261Sdim  }
1501249261Sdim}
1502249261Sdim
1503249261Sdimvoid ASTDumper::VisitStmt(const Stmt *Node) {
1504249261Sdim  {
1505249261Sdim    ColorScope Color(*this, StmtColor);
1506249261Sdim    OS << Node->getStmtClassName();
1507249261Sdim  }
1508249261Sdim  dumpPointer(Node);
1509249261Sdim  dumpSourceRange(Node->getSourceRange());
1510249261Sdim}
1511249261Sdim
1512249261Sdimvoid ASTDumper::VisitDeclStmt(const DeclStmt *Node) {
1513249261Sdim  VisitStmt(Node);
1514249261Sdim  for (DeclStmt::const_decl_iterator I = Node->decl_begin(),
1515249261Sdim                                     E = Node->decl_end();
1516249261Sdim       I != E; ++I) {
1517249261Sdim    if (I + 1 == E)
1518249261Sdim      lastChild();
1519249261Sdim    dumpDecl(*I);
1520249261Sdim  }
1521249261Sdim}
1522249261Sdim
1523249261Sdimvoid ASTDumper::VisitAttributedStmt(const AttributedStmt *Node) {
1524249261Sdim  VisitStmt(Node);
1525249261Sdim  for (ArrayRef<const Attr *>::iterator I = Node->getAttrs().begin(),
1526249261Sdim                                        E = Node->getAttrs().end();
1527249261Sdim       I != E; ++I) {
1528249261Sdim    if (I + 1 == E)
1529249261Sdim      lastChild();
1530249261Sdim    dumpAttr(*I);
1531249261Sdim  }
1532249261Sdim}
1533249261Sdim
1534249261Sdimvoid ASTDumper::VisitLabelStmt(const LabelStmt *Node) {
1535249261Sdim  VisitStmt(Node);
1536249261Sdim  OS << " '" << Node->getName() << "'";
1537249261Sdim}
1538249261Sdim
1539249261Sdimvoid ASTDumper::VisitGotoStmt(const GotoStmt *Node) {
1540249261Sdim  VisitStmt(Node);
1541249261Sdim  OS << " '" << Node->getLabel()->getName() << "'";
1542249261Sdim  dumpPointer(Node->getLabel());
1543249261Sdim}
1544249261Sdim
1545263508Sdimvoid ASTDumper::VisitCXXCatchStmt(const CXXCatchStmt *Node) {
1546263508Sdim  VisitStmt(Node);
1547263508Sdim  dumpDecl(Node->getExceptionDecl());
1548263508Sdim}
1549263508Sdim
1550249261Sdim//===----------------------------------------------------------------------===//
1551249261Sdim//  Expr dumping methods.
1552249261Sdim//===----------------------------------------------------------------------===//
1553249261Sdim
1554249261Sdimvoid ASTDumper::VisitExpr(const Expr *Node) {
1555249261Sdim  VisitStmt(Node);
1556249261Sdim  dumpType(Node->getType());
1557249261Sdim
1558249261Sdim  {
1559249261Sdim    ColorScope Color(*this, ValueKindColor);
1560249261Sdim    switch (Node->getValueKind()) {
1561249261Sdim    case VK_RValue:
1562249261Sdim      break;
1563249261Sdim    case VK_LValue:
1564249261Sdim      OS << " lvalue";
1565249261Sdim      break;
1566249261Sdim    case VK_XValue:
1567249261Sdim      OS << " xvalue";
1568249261Sdim      break;
1569249261Sdim    }
1570249261Sdim  }
1571249261Sdim
1572249261Sdim  {
1573249261Sdim    ColorScope Color(*this, ObjectKindColor);
1574249261Sdim    switch (Node->getObjectKind()) {
1575249261Sdim    case OK_Ordinary:
1576249261Sdim      break;
1577249261Sdim    case OK_BitField:
1578249261Sdim      OS << " bitfield";
1579249261Sdim      break;
1580249261Sdim    case OK_ObjCProperty:
1581249261Sdim      OS << " objcproperty";
1582249261Sdim      break;
1583249261Sdim    case OK_ObjCSubscript:
1584249261Sdim      OS << " objcsubscript";
1585249261Sdim      break;
1586249261Sdim    case OK_VectorComponent:
1587249261Sdim      OS << " vectorcomponent";
1588249261Sdim      break;
1589249261Sdim    }
1590249261Sdim  }
1591249261Sdim}
1592249261Sdim
1593249261Sdimstatic void dumpBasePath(raw_ostream &OS, const CastExpr *Node) {
1594249261Sdim  if (Node->path_empty())
1595249261Sdim    return;
1596249261Sdim
1597249261Sdim  OS << " (";
1598249261Sdim  bool First = true;
1599249261Sdim  for (CastExpr::path_const_iterator I = Node->path_begin(),
1600249261Sdim                                     E = Node->path_end();
1601249261Sdim       I != E; ++I) {
1602249261Sdim    const CXXBaseSpecifier *Base = *I;
1603249261Sdim    if (!First)
1604249261Sdim      OS << " -> ";
1605249261Sdim
1606249261Sdim    const CXXRecordDecl *RD =
1607249261Sdim    cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
1608249261Sdim
1609249261Sdim    if (Base->isVirtual())
1610249261Sdim      OS << "virtual ";
1611249261Sdim    OS << RD->getName();
1612249261Sdim    First = false;
1613249261Sdim  }
1614249261Sdim
1615249261Sdim  OS << ')';
1616249261Sdim}
1617249261Sdim
1618249261Sdimvoid ASTDumper::VisitCastExpr(const CastExpr *Node) {
1619249261Sdim  VisitExpr(Node);
1620249261Sdim  OS << " <";
1621249261Sdim  {
1622249261Sdim    ColorScope Color(*this, CastColor);
1623249261Sdim    OS << Node->getCastKindName();
1624249261Sdim  }
1625249261Sdim  dumpBasePath(OS, Node);
1626249261Sdim  OS << ">";
1627249261Sdim}
1628249261Sdim
1629249261Sdimvoid ASTDumper::VisitDeclRefExpr(const DeclRefExpr *Node) {
1630249261Sdim  VisitExpr(Node);
1631249261Sdim
1632249261Sdim  OS << " ";
1633249261Sdim  dumpBareDeclRef(Node->getDecl());
1634249261Sdim  if (Node->getDecl() != Node->getFoundDecl()) {
1635249261Sdim    OS << " (";
1636249261Sdim    dumpBareDeclRef(Node->getFoundDecl());
1637249261Sdim    OS << ")";
1638249261Sdim  }
1639249261Sdim}
1640249261Sdim
1641249261Sdimvoid ASTDumper::VisitUnresolvedLookupExpr(const UnresolvedLookupExpr *Node) {
1642249261Sdim  VisitExpr(Node);
1643249261Sdim  OS << " (";
1644249261Sdim  if (!Node->requiresADL())
1645249261Sdim    OS << "no ";
1646249261Sdim  OS << "ADL) = '" << Node->getName() << '\'';
1647249261Sdim
1648249261Sdim  UnresolvedLookupExpr::decls_iterator
1649249261Sdim    I = Node->decls_begin(), E = Node->decls_end();
1650249261Sdim  if (I == E)
1651249261Sdim    OS << " empty";
1652249261Sdim  for (; I != E; ++I)
1653249261Sdim    dumpPointer(*I);
1654249261Sdim}
1655249261Sdim
1656249261Sdimvoid ASTDumper::VisitObjCIvarRefExpr(const ObjCIvarRefExpr *Node) {
1657249261Sdim  VisitExpr(Node);
1658249261Sdim
1659249261Sdim  {
1660249261Sdim    ColorScope Color(*this, DeclKindNameColor);
1661249261Sdim    OS << " " << Node->getDecl()->getDeclKindName() << "Decl";
1662249261Sdim  }
1663249261Sdim  OS << "='" << *Node->getDecl() << "'";
1664249261Sdim  dumpPointer(Node->getDecl());
1665249261Sdim  if (Node->isFreeIvar())
1666249261Sdim    OS << " isFreeIvar";
1667249261Sdim}
1668249261Sdim
1669249261Sdimvoid ASTDumper::VisitPredefinedExpr(const PredefinedExpr *Node) {
1670249261Sdim  VisitExpr(Node);
1671249261Sdim  switch (Node->getIdentType()) {
1672249261Sdim  default: llvm_unreachable("unknown case");
1673249261Sdim  case PredefinedExpr::Func:           OS <<  " __func__"; break;
1674249261Sdim  case PredefinedExpr::Function:       OS <<  " __FUNCTION__"; break;
1675263508Sdim  case PredefinedExpr::FuncDName:      OS <<  " __FUNCDNAME__"; break;
1676249261Sdim  case PredefinedExpr::LFunction:      OS <<  " L__FUNCTION__"; break;
1677249261Sdim  case PredefinedExpr::PrettyFunction: OS <<  " __PRETTY_FUNCTION__";break;
1678249261Sdim  }
1679249261Sdim}
1680249261Sdim
1681249261Sdimvoid ASTDumper::VisitCharacterLiteral(const CharacterLiteral *Node) {
1682249261Sdim  VisitExpr(Node);
1683249261Sdim  ColorScope Color(*this, ValueColor);
1684249261Sdim  OS << " " << Node->getValue();
1685249261Sdim}
1686249261Sdim
1687249261Sdimvoid ASTDumper::VisitIntegerLiteral(const IntegerLiteral *Node) {
1688249261Sdim  VisitExpr(Node);
1689249261Sdim
1690249261Sdim  bool isSigned = Node->getType()->isSignedIntegerType();
1691249261Sdim  ColorScope Color(*this, ValueColor);
1692249261Sdim  OS << " " << Node->getValue().toString(10, isSigned);
1693249261Sdim}
1694249261Sdim
1695249261Sdimvoid ASTDumper::VisitFloatingLiteral(const FloatingLiteral *Node) {
1696249261Sdim  VisitExpr(Node);
1697249261Sdim  ColorScope Color(*this, ValueColor);
1698249261Sdim  OS << " " << Node->getValueAsApproximateDouble();
1699249261Sdim}
1700249261Sdim
1701249261Sdimvoid ASTDumper::VisitStringLiteral(const StringLiteral *Str) {
1702249261Sdim  VisitExpr(Str);
1703249261Sdim  ColorScope Color(*this, ValueColor);
1704249261Sdim  OS << " ";
1705249261Sdim  Str->outputString(OS);
1706249261Sdim}
1707249261Sdim
1708249261Sdimvoid ASTDumper::VisitUnaryOperator(const UnaryOperator *Node) {
1709249261Sdim  VisitExpr(Node);
1710249261Sdim  OS << " " << (Node->isPostfix() ? "postfix" : "prefix")
1711249261Sdim     << " '" << UnaryOperator::getOpcodeStr(Node->getOpcode()) << "'";
1712249261Sdim}
1713249261Sdim
1714249261Sdimvoid ASTDumper::VisitUnaryExprOrTypeTraitExpr(
1715249261Sdim    const UnaryExprOrTypeTraitExpr *Node) {
1716249261Sdim  VisitExpr(Node);
1717249261Sdim  switch(Node->getKind()) {
1718249261Sdim  case UETT_SizeOf:
1719249261Sdim    OS << " sizeof";
1720249261Sdim    break;
1721249261Sdim  case UETT_AlignOf:
1722249261Sdim    OS << " alignof";
1723249261Sdim    break;
1724249261Sdim  case UETT_VecStep:
1725249261Sdim    OS << " vec_step";
1726249261Sdim    break;
1727249261Sdim  }
1728249261Sdim  if (Node->isArgumentType())
1729249261Sdim    dumpType(Node->getArgumentType());
1730249261Sdim}
1731249261Sdim
1732249261Sdimvoid ASTDumper::VisitMemberExpr(const MemberExpr *Node) {
1733249261Sdim  VisitExpr(Node);
1734249261Sdim  OS << " " << (Node->isArrow() ? "->" : ".") << *Node->getMemberDecl();
1735249261Sdim  dumpPointer(Node->getMemberDecl());
1736249261Sdim}
1737249261Sdim
1738249261Sdimvoid ASTDumper::VisitExtVectorElementExpr(const ExtVectorElementExpr *Node) {
1739249261Sdim  VisitExpr(Node);
1740249261Sdim  OS << " " << Node->getAccessor().getNameStart();
1741249261Sdim}
1742249261Sdim
1743249261Sdimvoid ASTDumper::VisitBinaryOperator(const BinaryOperator *Node) {
1744249261Sdim  VisitExpr(Node);
1745249261Sdim  OS << " '" << BinaryOperator::getOpcodeStr(Node->getOpcode()) << "'";
1746249261Sdim}
1747249261Sdim
1748249261Sdimvoid ASTDumper::VisitCompoundAssignOperator(
1749249261Sdim    const CompoundAssignOperator *Node) {
1750249261Sdim  VisitExpr(Node);
1751249261Sdim  OS << " '" << BinaryOperator::getOpcodeStr(Node->getOpcode())
1752249261Sdim     << "' ComputeLHSTy=";
1753249261Sdim  dumpBareType(Node->getComputationLHSType());
1754249261Sdim  OS << " ComputeResultTy=";
1755249261Sdim  dumpBareType(Node->getComputationResultType());
1756249261Sdim}
1757249261Sdim
1758249261Sdimvoid ASTDumper::VisitBlockExpr(const BlockExpr *Node) {
1759249261Sdim  VisitExpr(Node);
1760249261Sdim  dumpDecl(Node->getBlockDecl());
1761249261Sdim}
1762249261Sdim
1763249261Sdimvoid ASTDumper::VisitOpaqueValueExpr(const OpaqueValueExpr *Node) {
1764249261Sdim  VisitExpr(Node);
1765249261Sdim
1766249261Sdim  if (Expr *Source = Node->getSourceExpr()) {
1767249261Sdim    lastChild();
1768249261Sdim    dumpStmt(Source);
1769249261Sdim  }
1770249261Sdim}
1771249261Sdim
1772249261Sdim// GNU extensions.
1773249261Sdim
1774249261Sdimvoid ASTDumper::VisitAddrLabelExpr(const AddrLabelExpr *Node) {
1775249261Sdim  VisitExpr(Node);
1776249261Sdim  OS << " " << Node->getLabel()->getName();
1777249261Sdim  dumpPointer(Node->getLabel());
1778249261Sdim}
1779249261Sdim
1780249261Sdim//===----------------------------------------------------------------------===//
1781249261Sdim// C++ Expressions
1782249261Sdim//===----------------------------------------------------------------------===//
1783249261Sdim
1784249261Sdimvoid ASTDumper::VisitCXXNamedCastExpr(const CXXNamedCastExpr *Node) {
1785249261Sdim  VisitExpr(Node);
1786249261Sdim  OS << " " << Node->getCastName()
1787249261Sdim     << "<" << Node->getTypeAsWritten().getAsString() << ">"
1788249261Sdim     << " <" << Node->getCastKindName();
1789249261Sdim  dumpBasePath(OS, Node);
1790249261Sdim  OS << ">";
1791249261Sdim}
1792249261Sdim
1793249261Sdimvoid ASTDumper::VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr *Node) {
1794249261Sdim  VisitExpr(Node);
1795249261Sdim  OS << " " << (Node->getValue() ? "true" : "false");
1796249261Sdim}
1797249261Sdim
1798249261Sdimvoid ASTDumper::VisitCXXThisExpr(const CXXThisExpr *Node) {
1799249261Sdim  VisitExpr(Node);
1800249261Sdim  OS << " this";
1801249261Sdim}
1802249261Sdim
1803249261Sdimvoid ASTDumper::VisitCXXFunctionalCastExpr(const CXXFunctionalCastExpr *Node) {
1804249261Sdim  VisitExpr(Node);
1805249261Sdim  OS << " functional cast to " << Node->getTypeAsWritten().getAsString()
1806249261Sdim     << " <" << Node->getCastKindName() << ">";
1807249261Sdim}
1808249261Sdim
1809249261Sdimvoid ASTDumper::VisitCXXConstructExpr(const CXXConstructExpr *Node) {
1810249261Sdim  VisitExpr(Node);
1811249261Sdim  CXXConstructorDecl *Ctor = Node->getConstructor();
1812249261Sdim  dumpType(Ctor->getType());
1813249261Sdim  if (Node->isElidable())
1814249261Sdim    OS << " elidable";
1815249261Sdim  if (Node->requiresZeroInitialization())
1816249261Sdim    OS << " zeroing";
1817249261Sdim}
1818249261Sdim
1819249261Sdimvoid ASTDumper::VisitCXXBindTemporaryExpr(const CXXBindTemporaryExpr *Node) {
1820249261Sdim  VisitExpr(Node);
1821249261Sdim  OS << " ";
1822249261Sdim  dumpCXXTemporary(Node->getTemporary());
1823249261Sdim}
1824249261Sdim
1825263508Sdimvoid
1826263508SdimASTDumper::VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *Node) {
1827263508Sdim  VisitExpr(Node);
1828263508Sdim  if (const ValueDecl *VD = Node->getExtendingDecl()) {
1829263508Sdim    OS << " extended by ";
1830263508Sdim    dumpBareDeclRef(VD);
1831263508Sdim  }
1832263508Sdim}
1833263508Sdim
1834249261Sdimvoid ASTDumper::VisitExprWithCleanups(const ExprWithCleanups *Node) {
1835249261Sdim  VisitExpr(Node);
1836249261Sdim  for (unsigned i = 0, e = Node->getNumObjects(); i != e; ++i)
1837249261Sdim    dumpDeclRef(Node->getObject(i), "cleanup");
1838249261Sdim}
1839249261Sdim
1840249261Sdimvoid ASTDumper::dumpCXXTemporary(const CXXTemporary *Temporary) {
1841249261Sdim  OS << "(CXXTemporary";
1842249261Sdim  dumpPointer(Temporary);
1843249261Sdim  OS << ")";
1844249261Sdim}
1845249261Sdim
1846249261Sdim//===----------------------------------------------------------------------===//
1847249261Sdim// Obj-C Expressions
1848249261Sdim//===----------------------------------------------------------------------===//
1849249261Sdim
1850249261Sdimvoid ASTDumper::VisitObjCMessageExpr(const ObjCMessageExpr *Node) {
1851249261Sdim  VisitExpr(Node);
1852249261Sdim  OS << " selector=" << Node->getSelector().getAsString();
1853249261Sdim  switch (Node->getReceiverKind()) {
1854249261Sdim  case ObjCMessageExpr::Instance:
1855249261Sdim    break;
1856249261Sdim
1857249261Sdim  case ObjCMessageExpr::Class:
1858249261Sdim    OS << " class=";
1859249261Sdim    dumpBareType(Node->getClassReceiver());
1860249261Sdim    break;
1861249261Sdim
1862249261Sdim  case ObjCMessageExpr::SuperInstance:
1863249261Sdim    OS << " super (instance)";
1864249261Sdim    break;
1865249261Sdim
1866249261Sdim  case ObjCMessageExpr::SuperClass:
1867249261Sdim    OS << " super (class)";
1868249261Sdim    break;
1869249261Sdim  }
1870249261Sdim}
1871249261Sdim
1872249261Sdimvoid ASTDumper::VisitObjCBoxedExpr(const ObjCBoxedExpr *Node) {
1873249261Sdim  VisitExpr(Node);
1874249261Sdim  OS << " selector=" << Node->getBoxingMethod()->getSelector().getAsString();
1875249261Sdim}
1876249261Sdim
1877249261Sdimvoid ASTDumper::VisitObjCAtCatchStmt(const ObjCAtCatchStmt *Node) {
1878249261Sdim  VisitStmt(Node);
1879249261Sdim  if (const VarDecl *CatchParam = Node->getCatchParamDecl())
1880249261Sdim    dumpDecl(CatchParam);
1881249261Sdim  else
1882249261Sdim    OS << " catch all";
1883249261Sdim}
1884249261Sdim
1885249261Sdimvoid ASTDumper::VisitObjCEncodeExpr(const ObjCEncodeExpr *Node) {
1886249261Sdim  VisitExpr(Node);
1887249261Sdim  dumpType(Node->getEncodedType());
1888249261Sdim}
1889249261Sdim
1890249261Sdimvoid ASTDumper::VisitObjCSelectorExpr(const ObjCSelectorExpr *Node) {
1891249261Sdim  VisitExpr(Node);
1892249261Sdim
1893249261Sdim  OS << " " << Node->getSelector().getAsString();
1894249261Sdim}
1895249261Sdim
1896249261Sdimvoid ASTDumper::VisitObjCProtocolExpr(const ObjCProtocolExpr *Node) {
1897249261Sdim  VisitExpr(Node);
1898249261Sdim
1899249261Sdim  OS << ' ' << *Node->getProtocol();
1900249261Sdim}
1901249261Sdim
1902249261Sdimvoid ASTDumper::VisitObjCPropertyRefExpr(const ObjCPropertyRefExpr *Node) {
1903249261Sdim  VisitExpr(Node);
1904249261Sdim  if (Node->isImplicitProperty()) {
1905249261Sdim    OS << " Kind=MethodRef Getter=\"";
1906249261Sdim    if (Node->getImplicitPropertyGetter())
1907249261Sdim      OS << Node->getImplicitPropertyGetter()->getSelector().getAsString();
1908249261Sdim    else
1909249261Sdim      OS << "(null)";
1910249261Sdim
1911249261Sdim    OS << "\" Setter=\"";
1912249261Sdim    if (ObjCMethodDecl *Setter = Node->getImplicitPropertySetter())
1913249261Sdim      OS << Setter->getSelector().getAsString();
1914249261Sdim    else
1915249261Sdim      OS << "(null)";
1916249261Sdim    OS << "\"";
1917249261Sdim  } else {
1918249261Sdim    OS << " Kind=PropertyRef Property=\"" << *Node->getExplicitProperty() <<'"';
1919249261Sdim  }
1920249261Sdim
1921249261Sdim  if (Node->isSuperReceiver())
1922249261Sdim    OS << " super";
1923249261Sdim
1924249261Sdim  OS << " Messaging=";
1925249261Sdim  if (Node->isMessagingGetter() && Node->isMessagingSetter())
1926249261Sdim    OS << "Getter&Setter";
1927249261Sdim  else if (Node->isMessagingGetter())
1928249261Sdim    OS << "Getter";
1929249261Sdim  else if (Node->isMessagingSetter())
1930249261Sdim    OS << "Setter";
1931249261Sdim}
1932249261Sdim
1933249261Sdimvoid ASTDumper::VisitObjCSubscriptRefExpr(const ObjCSubscriptRefExpr *Node) {
1934249261Sdim  VisitExpr(Node);
1935249261Sdim  if (Node->isArraySubscriptRefExpr())
1936249261Sdim    OS << " Kind=ArraySubscript GetterForArray=\"";
1937249261Sdim  else
1938249261Sdim    OS << " Kind=DictionarySubscript GetterForDictionary=\"";
1939249261Sdim  if (Node->getAtIndexMethodDecl())
1940249261Sdim    OS << Node->getAtIndexMethodDecl()->getSelector().getAsString();
1941249261Sdim  else
1942249261Sdim    OS << "(null)";
1943249261Sdim
1944249261Sdim  if (Node->isArraySubscriptRefExpr())
1945249261Sdim    OS << "\" SetterForArray=\"";
1946249261Sdim  else
1947249261Sdim    OS << "\" SetterForDictionary=\"";
1948249261Sdim  if (Node->setAtIndexMethodDecl())
1949249261Sdim    OS << Node->setAtIndexMethodDecl()->getSelector().getAsString();
1950249261Sdim  else
1951249261Sdim    OS << "(null)";
1952249261Sdim}
1953249261Sdim
1954249261Sdimvoid ASTDumper::VisitObjCBoolLiteralExpr(const ObjCBoolLiteralExpr *Node) {
1955249261Sdim  VisitExpr(Node);
1956249261Sdim  OS << " " << (Node->getValue() ? "__objc_yes" : "__objc_no");
1957249261Sdim}
1958249261Sdim
1959249261Sdim//===----------------------------------------------------------------------===//
1960249261Sdim// Comments
1961249261Sdim//===----------------------------------------------------------------------===//
1962249261Sdim
1963249261Sdimconst char *ASTDumper::getCommandName(unsigned CommandID) {
1964249261Sdim  if (Traits)
1965249261Sdim    return Traits->getCommandInfo(CommandID)->Name;
1966249261Sdim  const CommandInfo *Info = CommandTraits::getBuiltinCommandInfo(CommandID);
1967249261Sdim  if (Info)
1968249261Sdim    return Info->Name;
1969249261Sdim  return "<not a builtin command>";
1970249261Sdim}
1971249261Sdim
1972249261Sdimvoid ASTDumper::dumpFullComment(const FullComment *C) {
1973249261Sdim  if (!C)
1974249261Sdim    return;
1975249261Sdim
1976249261Sdim  FC = C;
1977249261Sdim  dumpComment(C);
1978249261Sdim  FC = 0;
1979249261Sdim}
1980249261Sdim
1981249261Sdimvoid ASTDumper::dumpComment(const Comment *C) {
1982249261Sdim  IndentScope Indent(*this);
1983249261Sdim
1984249261Sdim  if (!C) {
1985249261Sdim    ColorScope Color(*this, NullColor);
1986249261Sdim    OS << "<<<NULL>>>";
1987249261Sdim    return;
1988249261Sdim  }
1989249261Sdim
1990249261Sdim  {
1991249261Sdim    ColorScope Color(*this, CommentColor);
1992249261Sdim    OS << C->getCommentKindName();
1993249261Sdim  }
1994249261Sdim  dumpPointer(C);
1995249261Sdim  dumpSourceRange(C->getSourceRange());
1996249261Sdim  ConstCommentVisitor<ASTDumper>::visit(C);
1997249261Sdim  for (Comment::child_iterator I = C->child_begin(), E = C->child_end();
1998249261Sdim       I != E; ++I) {
1999249261Sdim    if (I + 1 == E)
2000249261Sdim      lastChild();
2001249261Sdim    dumpComment(*I);
2002249261Sdim  }
2003249261Sdim}
2004249261Sdim
2005249261Sdimvoid ASTDumper::visitTextComment(const TextComment *C) {
2006249261Sdim  OS << " Text=\"" << C->getText() << "\"";
2007249261Sdim}
2008249261Sdim
2009249261Sdimvoid ASTDumper::visitInlineCommandComment(const InlineCommandComment *C) {
2010249261Sdim  OS << " Name=\"" << getCommandName(C->getCommandID()) << "\"";
2011249261Sdim  switch (C->getRenderKind()) {
2012249261Sdim  case InlineCommandComment::RenderNormal:
2013249261Sdim    OS << " RenderNormal";
2014249261Sdim    break;
2015249261Sdim  case InlineCommandComment::RenderBold:
2016249261Sdim    OS << " RenderBold";
2017249261Sdim    break;
2018249261Sdim  case InlineCommandComment::RenderMonospaced:
2019249261Sdim    OS << " RenderMonospaced";
2020249261Sdim    break;
2021249261Sdim  case InlineCommandComment::RenderEmphasized:
2022249261Sdim    OS << " RenderEmphasized";
2023249261Sdim    break;
2024249261Sdim  }
2025249261Sdim
2026249261Sdim  for (unsigned i = 0, e = C->getNumArgs(); i != e; ++i)
2027249261Sdim    OS << " Arg[" << i << "]=\"" << C->getArgText(i) << "\"";
2028249261Sdim}
2029249261Sdim
2030249261Sdimvoid ASTDumper::visitHTMLStartTagComment(const HTMLStartTagComment *C) {
2031249261Sdim  OS << " Name=\"" << C->getTagName() << "\"";
2032249261Sdim  if (C->getNumAttrs() != 0) {
2033249261Sdim    OS << " Attrs: ";
2034249261Sdim    for (unsigned i = 0, e = C->getNumAttrs(); i != e; ++i) {
2035249261Sdim      const HTMLStartTagComment::Attribute &Attr = C->getAttr(i);
2036249261Sdim      OS << " \"" << Attr.Name << "=\"" << Attr.Value << "\"";
2037249261Sdim    }
2038249261Sdim  }
2039249261Sdim  if (C->isSelfClosing())
2040249261Sdim    OS << " SelfClosing";
2041249261Sdim}
2042249261Sdim
2043249261Sdimvoid ASTDumper::visitHTMLEndTagComment(const HTMLEndTagComment *C) {
2044249261Sdim  OS << " Name=\"" << C->getTagName() << "\"";
2045249261Sdim}
2046249261Sdim
2047249261Sdimvoid ASTDumper::visitBlockCommandComment(const BlockCommandComment *C) {
2048249261Sdim  OS << " Name=\"" << getCommandName(C->getCommandID()) << "\"";
2049249261Sdim  for (unsigned i = 0, e = C->getNumArgs(); i != e; ++i)
2050249261Sdim    OS << " Arg[" << i << "]=\"" << C->getArgText(i) << "\"";
2051249261Sdim}
2052249261Sdim
2053249261Sdimvoid ASTDumper::visitParamCommandComment(const ParamCommandComment *C) {
2054249261Sdim  OS << " " << ParamCommandComment::getDirectionAsString(C->getDirection());
2055249261Sdim
2056249261Sdim  if (C->isDirectionExplicit())
2057249261Sdim    OS << " explicitly";
2058249261Sdim  else
2059249261Sdim    OS << " implicitly";
2060249261Sdim
2061249261Sdim  if (C->hasParamName()) {
2062249261Sdim    if (C->isParamIndexValid())
2063249261Sdim      OS << " Param=\"" << C->getParamName(FC) << "\"";
2064249261Sdim    else
2065249261Sdim      OS << " Param=\"" << C->getParamNameAsWritten() << "\"";
2066249261Sdim  }
2067249261Sdim
2068249261Sdim  if (C->isParamIndexValid())
2069249261Sdim    OS << " ParamIndex=" << C->getParamIndex();
2070249261Sdim}
2071249261Sdim
2072249261Sdimvoid ASTDumper::visitTParamCommandComment(const TParamCommandComment *C) {
2073249261Sdim  if (C->hasParamName()) {
2074249261Sdim    if (C->isPositionValid())
2075249261Sdim      OS << " Param=\"" << C->getParamName(FC) << "\"";
2076249261Sdim    else
2077249261Sdim      OS << " Param=\"" << C->getParamNameAsWritten() << "\"";
2078249261Sdim  }
2079249261Sdim
2080249261Sdim  if (C->isPositionValid()) {
2081249261Sdim    OS << " Position=<";
2082249261Sdim    for (unsigned i = 0, e = C->getDepth(); i != e; ++i) {
2083249261Sdim      OS << C->getIndex(i);
2084249261Sdim      if (i != e - 1)
2085249261Sdim        OS << ", ";
2086249261Sdim    }
2087249261Sdim    OS << ">";
2088249261Sdim  }
2089249261Sdim}
2090249261Sdim
2091249261Sdimvoid ASTDumper::visitVerbatimBlockComment(const VerbatimBlockComment *C) {
2092249261Sdim  OS << " Name=\"" << getCommandName(C->getCommandID()) << "\""
2093249261Sdim        " CloseName=\"" << C->getCloseName() << "\"";
2094249261Sdim}
2095249261Sdim
2096249261Sdimvoid ASTDumper::visitVerbatimBlockLineComment(
2097249261Sdim    const VerbatimBlockLineComment *C) {
2098249261Sdim  OS << " Text=\"" << C->getText() << "\"";
2099249261Sdim}
2100249261Sdim
2101249261Sdimvoid ASTDumper::visitVerbatimLineComment(const VerbatimLineComment *C) {
2102249261Sdim  OS << " Text=\"" << C->getText() << "\"";
2103249261Sdim}
2104249261Sdim
2105249261Sdim//===----------------------------------------------------------------------===//
2106249261Sdim// Decl method implementations
2107249261Sdim//===----------------------------------------------------------------------===//
2108249261Sdim
2109249261Sdimvoid Decl::dump() const {
2110249261Sdim  dump(llvm::errs());
2111249261Sdim}
2112249261Sdim
2113249261Sdimvoid Decl::dump(raw_ostream &OS) const {
2114249261Sdim  ASTDumper P(OS, &getASTContext().getCommentCommandTraits(),
2115249261Sdim              &getASTContext().getSourceManager());
2116249261Sdim  P.dumpDecl(this);
2117249261Sdim}
2118249261Sdim
2119249261Sdimvoid Decl::dumpColor() const {
2120249261Sdim  ASTDumper P(llvm::errs(), &getASTContext().getCommentCommandTraits(),
2121249261Sdim              &getASTContext().getSourceManager(), /*ShowColors*/true);
2122249261Sdim  P.dumpDecl(this);
2123249261Sdim}
2124263508Sdim
2125263508Sdimvoid DeclContext::dumpLookups() const {
2126263508Sdim  dumpLookups(llvm::errs());
2127263508Sdim}
2128263508Sdim
2129263508Sdimvoid DeclContext::dumpLookups(raw_ostream &OS) const {
2130263508Sdim  const DeclContext *DC = this;
2131263508Sdim  while (!DC->isTranslationUnit())
2132263508Sdim    DC = DC->getParent();
2133263508Sdim  ASTContext &Ctx = cast<TranslationUnitDecl>(DC)->getASTContext();
2134263508Sdim  ASTDumper P(OS, &Ctx.getCommentCommandTraits(), &Ctx.getSourceManager());
2135263508Sdim  P.dumpLookups(this);
2136263508Sdim}
2137263508Sdim
2138249261Sdim//===----------------------------------------------------------------------===//
2139249261Sdim// Stmt method implementations
2140249261Sdim//===----------------------------------------------------------------------===//
2141249261Sdim
2142249261Sdimvoid Stmt::dump(SourceManager &SM) const {
2143249261Sdim  dump(llvm::errs(), SM);
2144249261Sdim}
2145249261Sdim
2146249261Sdimvoid Stmt::dump(raw_ostream &OS, SourceManager &SM) const {
2147249261Sdim  ASTDumper P(OS, 0, &SM);
2148249261Sdim  P.dumpStmt(this);
2149249261Sdim}
2150249261Sdim
2151249261Sdimvoid Stmt::dump() const {
2152249261Sdim  ASTDumper P(llvm::errs(), 0, 0);
2153249261Sdim  P.dumpStmt(this);
2154249261Sdim}
2155249261Sdim
2156249261Sdimvoid Stmt::dumpColor() const {
2157249261Sdim  ASTDumper P(llvm::errs(), 0, 0, /*ShowColors*/true);
2158249261Sdim  P.dumpStmt(this);
2159249261Sdim}
2160249261Sdim
2161249261Sdim//===----------------------------------------------------------------------===//
2162249261Sdim// Comment method implementations
2163249261Sdim//===----------------------------------------------------------------------===//
2164249261Sdim
2165249261Sdimvoid Comment::dump() const {
2166249261Sdim  dump(llvm::errs(), 0, 0);
2167249261Sdim}
2168249261Sdim
2169249261Sdimvoid Comment::dump(const ASTContext &Context) const {
2170249261Sdim  dump(llvm::errs(), &Context.getCommentCommandTraits(),
2171249261Sdim       &Context.getSourceManager());
2172249261Sdim}
2173249261Sdim
2174249261Sdimvoid Comment::dump(raw_ostream &OS, const CommandTraits *Traits,
2175249261Sdim                   const SourceManager *SM) const {
2176249261Sdim  const FullComment *FC = dyn_cast<FullComment>(this);
2177249261Sdim  ASTDumper D(OS, Traits, SM);
2178249261Sdim  D.dumpFullComment(FC);
2179249261Sdim}
2180249261Sdim
2181249261Sdimvoid Comment::dumpColor() const {
2182249261Sdim  const FullComment *FC = dyn_cast<FullComment>(this);
2183249261Sdim  ASTDumper D(llvm::errs(), 0, 0, /*ShowColors*/true);
2184249261Sdim  D.dumpFullComment(FC);
2185249261Sdim}
2186