Stmt.h revision 5e97d4b5ec7ce97e311d7aa4e8bd2b4fd9dbfa2e
1//===--- Stmt.h - Classes for representing statements -----------*- C++ -*-===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file was developed by Chris Lattner and is distributed under
6// the University of Illinois Open Source License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10//  This file defines the Stmt interface and subclasses.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef LLVM_CLANG_AST_STMT_H
15#define LLVM_CLANG_AST_STMT_H
16
17#include "clang/Basic/SourceLocation.h"
18#include "llvm/ADT/SmallVector.h"
19#include "llvm/ADT/iterator"
20#include "llvm/ADT/GraphTraits.h"
21#include <iosfwd>
22
23namespace clang {
24  class Expr;
25  class Decl;
26  class ScopedDecl;
27  class IdentifierInfo;
28  class SourceManager;
29  class SwitchStmt;
30  class PrinterHelper;
31
32/// Stmt - This represents one statement.
33///
34class Stmt {
35public:
36  enum StmtClass {
37#define STMT(N, CLASS, PARENT) CLASS##Class = N,
38#define FIRST_STMT(N) firstStmtConstant = N,
39#define LAST_STMT(N) lastStmtConstant = N,
40#define FIRST_EXPR(N) firstExprConstant = N,
41#define LAST_EXPR(N) lastExprConstant = N
42#include "clang/AST/StmtNodes.def"
43};
44private:
45  const StmtClass sClass;
46public:
47  Stmt(StmtClass SC) : sClass(SC) {
48    if (Stmt::CollectingStats()) Stmt::addStmtClass(SC);
49  }
50  virtual ~Stmt() {}
51
52  StmtClass getStmtClass() const { return sClass; }
53  const char *getStmtClassName() const;
54
55  /// SourceLocation tokens are not useful in isolation - they are low level
56  /// value objects created/interpreted by SourceManager. We assume AST
57  /// clients will have a pointer to the respective SourceManager.
58  virtual SourceRange getSourceRange() const = 0;
59  SourceLocation getLocStart() const { return getSourceRange().Begin(); }
60  SourceLocation getLocEnd() const { return getSourceRange().End(); }
61
62  // global temp stats (until we have a per-module visitor)
63  static void addStmtClass(const StmtClass s);
64  static bool CollectingStats(bool enable=false);
65  static void PrintStats();
66
67  /// dump - This does a local dump of the specified AST fragment.  It dumps the
68  /// specified node and a few nodes underneath it, but not the whole subtree.
69  /// This is useful in a debugger.
70  void dump() const;
71  void dump(SourceManager &SM) const;
72
73  /// dumpAll - This does a dump of the specified AST fragment and all subtrees.
74  void dumpAll() const;
75  void dumpAll(SourceManager &SM) const;
76
77  /// dumpPretty/printPretty - These two methods do a "pretty print" of the AST
78  /// back to its original source language syntax.
79  void dumpPretty() const;
80  void printPretty(std::ostream &OS, PrinterHelper* = NULL) const;
81
82  // Implement isa<T> support.
83  static bool classof(const Stmt *) { return true; }
84
85  /// Child Iterators: All subclasses must implement child_begin and child_end
86  ///  to permit easy iteration over the substatements/subexpessions of an
87  ///  AST node.  This permits easy iteration over all nodes in the AST.
88  typedef Stmt**                                               child_iterator;
89  typedef Stmt* const *                                  const_child_iterator;
90
91  typedef std::reverse_iterator<child_iterator>
92  reverse_child_iterator;
93  typedef std::reverse_iterator<const_child_iterator>
94  const_reverse_child_iterator;
95
96  virtual child_iterator child_begin() = 0;
97  virtual child_iterator child_end()   = 0;
98
99  const_child_iterator child_begin() const {
100    return (child_iterator) const_cast<Stmt*>(this)->child_begin();
101  }
102
103  const_child_iterator child_end() const {
104    return (child_iterator) const_cast<Stmt*>(this)->child_end();
105  }
106
107  reverse_child_iterator child_rbegin() {
108    return reverse_child_iterator(child_end());
109  }
110
111  reverse_child_iterator child_rend() {
112    return reverse_child_iterator(child_begin());
113  }
114
115  const_reverse_child_iterator child_rbegin() const {
116    return const_reverse_child_iterator(child_end());
117  }
118
119  const_reverse_child_iterator child_rend() const {
120    return const_reverse_child_iterator(child_begin());
121  }
122};
123
124/// DeclStmt - Adaptor class for mixing declarations with statements and
125/// expressions. For example, CompoundStmt mixes statements, expressions
126/// and declarations (variables, types). Another example is ForStmt, where
127/// the first statement can be an expression or a declaration.
128///
129class DeclStmt : public Stmt {
130  ScopedDecl *TheDecl;
131public:
132  DeclStmt(ScopedDecl *D) : Stmt(DeclStmtClass), TheDecl(D) {}
133
134  const ScopedDecl *getDecl() const { return TheDecl; }
135  ScopedDecl *getDecl() { return TheDecl; }
136
137  virtual SourceRange getSourceRange() const { return SourceRange(); }
138
139  static bool classof(const Stmt *T) {
140    return T->getStmtClass() == DeclStmtClass;
141  }
142  static bool classof(const DeclStmt *) { return true; }
143
144  // Iterators
145  virtual child_iterator child_begin();
146  virtual child_iterator child_end();
147};
148
149/// NullStmt - This is the null statement ";": C99 6.8.3p3.
150///
151class NullStmt : public Stmt {
152  SourceLocation SemiLoc;
153public:
154  NullStmt(SourceLocation L) : Stmt(NullStmtClass), SemiLoc(L) {}
155
156  SourceLocation getSemiLoc() const { return SemiLoc; }
157
158  virtual SourceRange getSourceRange() const { return SourceRange(SemiLoc); }
159
160  static bool classof(const Stmt *T) {
161    return T->getStmtClass() == NullStmtClass;
162  }
163  static bool classof(const NullStmt *) { return true; }
164
165  // Iterators
166  virtual child_iterator child_begin();
167  virtual child_iterator child_end();
168};
169
170/// CompoundStmt - This represents a group of statements like { stmt stmt }.
171///
172class CompoundStmt : public Stmt {
173  llvm::SmallVector<Stmt*, 16> Body;
174  SourceLocation LBracLoc, RBracLoc;
175public:
176  CompoundStmt(Stmt **StmtStart, unsigned NumStmts,
177               SourceLocation LB, SourceLocation RB)
178    : Stmt(CompoundStmtClass), Body(StmtStart, StmtStart+NumStmts),
179      LBracLoc(LB), RBracLoc(RB) {}
180
181  bool body_empty() const { return Body.empty(); }
182
183  typedef llvm::SmallVector<Stmt*, 16>::iterator body_iterator;
184  body_iterator body_begin() { return Body.begin(); }
185  body_iterator body_end() { return Body.end(); }
186  Stmt *body_back() { return Body.back(); }
187
188  typedef llvm::SmallVector<Stmt*, 16>::const_iterator const_body_iterator;
189  const_body_iterator body_begin() const { return Body.begin(); }
190  const_body_iterator body_end() const { return Body.end(); }
191  const Stmt *body_back() const { return Body.back(); }
192
193  typedef llvm::SmallVector<Stmt*, 16>::reverse_iterator reverse_body_iterator;
194  reverse_body_iterator body_rbegin() { return Body.rbegin(); }
195  reverse_body_iterator body_rend() { return Body.rend(); }
196
197  typedef llvm::SmallVector<Stmt*, 16>::const_reverse_iterator
198    const_reverse_body_iterator;
199  const_reverse_body_iterator body_rbegin() const { return Body.rbegin(); }
200  const_reverse_body_iterator body_rend() const { return Body.rend(); }
201
202  void push_back(Stmt *S) { Body.push_back(S); }
203
204  virtual SourceRange getSourceRange() const {
205    return SourceRange(LBracLoc, RBracLoc);
206  }
207  static bool classof(const Stmt *T) {
208    return T->getStmtClass() == CompoundStmtClass;
209  }
210  static bool classof(const CompoundStmt *) { return true; }
211
212  // Iterators
213  virtual child_iterator child_begin();
214  virtual child_iterator child_end();
215};
216
217// SwitchCase is the base class for CaseStmt and DefaultStmt,
218class SwitchCase : public Stmt {
219  // A pointer to the following CaseStmt or DefaultStmt class,
220  // used by SwitchStmt.
221  SwitchCase *NextSwitchCase;
222protected:
223  SwitchCase(StmtClass SC) : Stmt(SC), NextSwitchCase(0) {}
224
225public:
226  const SwitchCase *getNextSwitchCase() const { return NextSwitchCase; }
227
228  SwitchCase *getNextSwitchCase() { return NextSwitchCase; }
229
230  void setNextSwitchCase(SwitchCase *SC) { NextSwitchCase = SC; }
231
232  virtual Stmt* v_getSubStmt() = 0;
233  Stmt *getSubStmt() { return v_getSubStmt(); }
234
235  virtual SourceRange getSourceRange() const { return SourceRange(); }
236
237  static bool classof(const Stmt *T) {
238    return T->getStmtClass() == CaseStmtClass ||
239    T->getStmtClass() == DefaultStmtClass;
240  }
241  static bool classof(const SwitchCase *) { return true; }
242};
243
244class CaseStmt : public SwitchCase {
245  enum { SUBSTMT, LHS, RHS, END_EXPR };
246  Stmt* SubExprs[END_EXPR];  // The expression for the RHS is Non-null for
247                             // GNU "case 1 ... 4" extension
248  SourceLocation CaseLoc;
249public:
250  CaseStmt(Expr *lhs, Expr *rhs, Stmt *substmt, SourceLocation caseLoc)
251    : SwitchCase(CaseStmtClass) {
252    SubExprs[SUBSTMT] = substmt;
253    SubExprs[LHS] = reinterpret_cast<Stmt*>(lhs);
254    SubExprs[RHS] = reinterpret_cast<Stmt*>(rhs);
255    CaseLoc = caseLoc;
256  }
257
258  Expr *getLHS() { return reinterpret_cast<Expr*>(SubExprs[LHS]); }
259  Expr *getRHS() { return reinterpret_cast<Expr*>(SubExprs[RHS]); }
260  Stmt *getSubStmt() { return SubExprs[SUBSTMT]; }
261  virtual Stmt* v_getSubStmt() { return getSubStmt(); }
262
263  virtual SourceRange getSourceRange() const {
264    return SourceRange(CaseLoc, SubExprs[SUBSTMT]->getLocEnd());
265  }
266  static bool classof(const Stmt *T) {
267    return T->getStmtClass() == CaseStmtClass;
268  }
269  static bool classof(const CaseStmt *) { return true; }
270
271  // Iterators
272  virtual child_iterator child_begin();
273  virtual child_iterator child_end();
274};
275
276class DefaultStmt : public SwitchCase {
277  Stmt* SubStmt;
278  SourceLocation DefaultLoc;
279public:
280  DefaultStmt(SourceLocation DL, Stmt *substmt) :
281    SwitchCase(DefaultStmtClass), SubStmt(substmt), DefaultLoc(DL) {}
282
283  Stmt *getSubStmt() { return SubStmt; }
284  virtual Stmt* v_getSubStmt() { return getSubStmt(); }
285
286  SourceLocation getDefaultLoc() const { return DefaultLoc; }
287
288  virtual SourceRange getSourceRange() const {
289    return SourceRange(DefaultLoc, SubStmt->getLocEnd());
290  }
291  static bool classof(const Stmt *T) {
292    return T->getStmtClass() == DefaultStmtClass;
293  }
294  static bool classof(const DefaultStmt *) { return true; }
295
296  // Iterators
297  virtual child_iterator child_begin();
298  virtual child_iterator child_end();
299};
300
301class LabelStmt : public Stmt {
302  IdentifierInfo *Label;
303  Stmt *SubStmt;
304  SourceLocation IdentLoc;
305public:
306  LabelStmt(SourceLocation IL, IdentifierInfo *label, Stmt *substmt)
307    : Stmt(LabelStmtClass), Label(label),
308      SubStmt(substmt), IdentLoc(IL) {}
309
310  SourceLocation getIdentLoc() const { return IdentLoc; }
311  IdentifierInfo *getID() const { return Label; }
312  const char *getName() const;
313  Stmt *getSubStmt() { return SubStmt; }
314  const Stmt *getSubStmt() const { return SubStmt; }
315
316  void setIdentLoc(SourceLocation L) { IdentLoc = L; }
317  void setSubStmt(Stmt *SS) { SubStmt = SS; }
318
319  virtual SourceRange getSourceRange() const {
320    return SourceRange(IdentLoc, SubStmt->getLocEnd());
321  }
322  static bool classof(const Stmt *T) {
323    return T->getStmtClass() == LabelStmtClass;
324  }
325  static bool classof(const LabelStmt *) { return true; }
326
327  // Iterators
328  virtual child_iterator child_begin();
329  virtual child_iterator child_end();
330};
331
332
333/// IfStmt - This represents an if/then/else.
334///
335class IfStmt : public Stmt {
336  enum { COND, THEN, ELSE, END_EXPR };
337  Stmt* SubExprs[END_EXPR];
338  SourceLocation IfLoc;
339public:
340  IfStmt(SourceLocation IL, Expr *cond, Stmt *then, Stmt *elsev = 0)
341    : Stmt(IfStmtClass)  {
342    SubExprs[COND] = reinterpret_cast<Stmt*>(cond);
343    SubExprs[THEN] = then;
344    SubExprs[ELSE] = elsev;
345    IfLoc = IL;
346  }
347
348  const Expr *getCond() const { return reinterpret_cast<Expr*>(SubExprs[COND]);}
349  const Stmt *getThen() const { return SubExprs[THEN]; }
350  const Stmt *getElse() const { return SubExprs[ELSE]; }
351
352  Expr *getCond() { return reinterpret_cast<Expr*>(SubExprs[COND]); }
353  Stmt *getThen() { return SubExprs[THEN]; }
354  Stmt *getElse() { return SubExprs[ELSE]; }
355
356  virtual SourceRange getSourceRange() const {
357    if (SubExprs[ELSE])
358      return SourceRange(IfLoc, SubExprs[ELSE]->getLocEnd());
359    else
360      return SourceRange(IfLoc, SubExprs[THEN]->getLocEnd());
361  }
362
363  static bool classof(const Stmt *T) {
364    return T->getStmtClass() == IfStmtClass;
365  }
366  static bool classof(const IfStmt *) { return true; }
367
368  // Iterators
369  virtual child_iterator child_begin();
370  virtual child_iterator child_end();
371};
372
373/// SwitchStmt - This represents a 'switch' stmt.
374///
375class SwitchStmt : public Stmt {
376  enum { COND, BODY, END_EXPR };
377  Stmt* SubExprs[END_EXPR];
378  // This points to a linked list of case and default statements.
379  SwitchCase *FirstCase;
380  SourceLocation SwitchLoc;
381public:
382  SwitchStmt(Expr *cond) : Stmt(SwitchStmtClass), FirstCase(0) {
383      SubExprs[COND] = reinterpret_cast<Stmt*>(cond);
384      SubExprs[BODY] = NULL;
385    }
386
387  const Expr *getCond() const { return reinterpret_cast<Expr*>(SubExprs[COND]);}
388  const Stmt *getBody() const { return SubExprs[BODY]; }
389  const SwitchCase *getSwitchCaseList() const { return FirstCase; }
390
391  Expr *getCond() { return reinterpret_cast<Expr*>(SubExprs[COND]);}
392  Stmt *getBody() { return SubExprs[BODY]; }
393  SwitchCase *getSwitchCaseList() { return FirstCase; }
394
395  void setBody(Stmt *S, SourceLocation SL) {
396    SubExprs[BODY] = S;
397    SwitchLoc = SL;
398  }
399  void addSwitchCase(SwitchCase *SC) {
400    if (FirstCase)
401      SC->setNextSwitchCase(FirstCase);
402
403    FirstCase = SC;
404  }
405  virtual SourceRange getSourceRange() const {
406    return SourceRange(SwitchLoc, SubExprs[BODY]->getLocEnd());
407  }
408  static bool classof(const Stmt *T) {
409    return T->getStmtClass() == SwitchStmtClass;
410  }
411  static bool classof(const SwitchStmt *) { return true; }
412
413  // Iterators
414  virtual child_iterator child_begin();
415  virtual child_iterator child_end();
416};
417
418
419/// WhileStmt - This represents a 'while' stmt.
420///
421class WhileStmt : public Stmt {
422  enum { COND, BODY, END_EXPR };
423  Stmt* SubExprs[END_EXPR];
424  SourceLocation WhileLoc;
425public:
426  WhileStmt(Expr *cond, Stmt *body, SourceLocation WL) : Stmt(WhileStmtClass) {
427    SubExprs[COND] = reinterpret_cast<Stmt*>(cond);
428    SubExprs[BODY] = body;
429    WhileLoc = WL;
430  }
431
432  Expr *getCond() { return reinterpret_cast<Expr*>(SubExprs[COND]); }
433  const Expr *getCond() const { return reinterpret_cast<Expr*>(SubExprs[COND]);}
434  Stmt *getBody() { return SubExprs[BODY]; }
435  const Stmt *getBody() const { return SubExprs[BODY]; }
436
437  virtual SourceRange getSourceRange() const {
438    return SourceRange(WhileLoc, SubExprs[BODY]->getLocEnd());
439  }
440  static bool classof(const Stmt *T) {
441    return T->getStmtClass() == WhileStmtClass;
442  }
443  static bool classof(const WhileStmt *) { return true; }
444
445  // Iterators
446  virtual child_iterator child_begin();
447  virtual child_iterator child_end();
448};
449
450/// DoStmt - This represents a 'do/while' stmt.
451///
452class DoStmt : public Stmt {
453  enum { COND, BODY, END_EXPR };
454  Stmt* SubExprs[END_EXPR];
455  SourceLocation DoLoc;
456public:
457  DoStmt(Stmt *body, Expr *cond, SourceLocation DL)
458    : Stmt(DoStmtClass), DoLoc(DL) {
459    SubExprs[COND] = reinterpret_cast<Stmt*>(cond);
460    SubExprs[BODY] = body;
461    DoLoc = DL;
462  }
463
464  Expr *getCond() { return reinterpret_cast<Expr*>(SubExprs[COND]); }
465  const Expr *getCond() const { return reinterpret_cast<Expr*>(SubExprs[COND]);}
466  Stmt *getBody() { return SubExprs[BODY]; }
467  const Stmt *getBody() const { return SubExprs[BODY]; }
468
469  virtual SourceRange getSourceRange() const {
470    return SourceRange(DoLoc, SubExprs[BODY]->getLocEnd());
471  }
472  static bool classof(const Stmt *T) {
473    return T->getStmtClass() == DoStmtClass;
474  }
475  static bool classof(const DoStmt *) { return true; }
476
477  // Iterators
478  virtual child_iterator child_begin();
479  virtual child_iterator child_end();
480};
481
482
483/// ForStmt - This represents a 'for (init;cond;inc)' stmt.  Note that any of
484/// the init/cond/inc parts of the ForStmt will be null if they were not
485/// specified in the source.
486///
487class ForStmt : public Stmt {
488  enum { INIT, COND, INC, BODY, END_EXPR };
489  Stmt* SubExprs[END_EXPR]; // SubExprs[INIT] is an expression or declstmt.
490  SourceLocation ForLoc;
491public:
492  ForStmt(Stmt *Init, Expr *Cond, Expr *Inc, Stmt *Body, SourceLocation FL)
493    : Stmt(ForStmtClass) {
494    SubExprs[INIT] = Init;
495    SubExprs[COND] = reinterpret_cast<Stmt*>(Cond);
496    SubExprs[INC] = reinterpret_cast<Stmt*>(Inc);
497    SubExprs[BODY] = Body;
498    ForLoc = FL;
499  }
500
501  Stmt *getInit() { return SubExprs[INIT]; }
502  Expr *getCond() { return reinterpret_cast<Expr*>(SubExprs[COND]); }
503  Expr *getInc()  { return reinterpret_cast<Expr*>(SubExprs[INC]); }
504  Stmt *getBody() { return SubExprs[BODY]; }
505
506  const Stmt *getInit() const { return SubExprs[INIT]; }
507  const Expr *getCond() const { return reinterpret_cast<Expr*>(SubExprs[COND]);}
508  const Expr *getInc()  const { return reinterpret_cast<Expr*>(SubExprs[INC]); }
509  const Stmt *getBody() const { return SubExprs[BODY]; }
510
511  virtual SourceRange getSourceRange() const {
512    return SourceRange(ForLoc, SubExprs[BODY]->getLocEnd());
513  }
514  static bool classof(const Stmt *T) {
515    return T->getStmtClass() == ForStmtClass;
516  }
517  static bool classof(const ForStmt *) { return true; }
518
519  // Iterators
520  virtual child_iterator child_begin();
521  virtual child_iterator child_end();
522};
523
524/// GotoStmt - This represents a direct goto.
525///
526class GotoStmt : public Stmt {
527  LabelStmt *Label;
528  SourceLocation GotoLoc;
529  SourceLocation LabelLoc;
530public:
531  GotoStmt(LabelStmt *label, SourceLocation GL, SourceLocation LL)
532    : Stmt(GotoStmtClass), Label(label), GotoLoc(GL), LabelLoc(LL) {}
533
534  LabelStmt *getLabel() const { return Label; }
535
536  virtual SourceRange getSourceRange() const {
537    return SourceRange(GotoLoc, LabelLoc);
538  }
539  static bool classof(const Stmt *T) {
540    return T->getStmtClass() == GotoStmtClass;
541  }
542  static bool classof(const GotoStmt *) { return true; }
543
544  // Iterators
545  virtual child_iterator child_begin();
546  virtual child_iterator child_end();
547};
548
549/// IndirectGotoStmt - This represents an indirect goto.
550///
551class IndirectGotoStmt : public Stmt {
552  Expr *Target;
553public:
554  IndirectGotoStmt(Expr *target) : Stmt(IndirectGotoStmtClass), Target(target){}
555
556  Expr *getTarget() { return Target; }
557  const Expr *getTarget() const { return Target; }
558
559  virtual SourceRange getSourceRange() const { return SourceRange(); }
560
561  static bool classof(const Stmt *T) {
562    return T->getStmtClass() == IndirectGotoStmtClass;
563  }
564  static bool classof(const IndirectGotoStmt *) { return true; }
565
566  // Iterators
567  virtual child_iterator child_begin();
568  virtual child_iterator child_end();
569};
570
571
572/// ContinueStmt - This represents a continue.
573///
574class ContinueStmt : public Stmt {
575  SourceLocation ContinueLoc;
576public:
577  ContinueStmt(SourceLocation CL) : Stmt(ContinueStmtClass), ContinueLoc(CL) {}
578
579  virtual SourceRange getSourceRange() const {
580    return SourceRange(ContinueLoc);
581  }
582  static bool classof(const Stmt *T) {
583    return T->getStmtClass() == ContinueStmtClass;
584  }
585  static bool classof(const ContinueStmt *) { return true; }
586
587  // Iterators
588  virtual child_iterator child_begin();
589  virtual child_iterator child_end();
590};
591
592/// BreakStmt - This represents a break.
593///
594class BreakStmt : public Stmt {
595  SourceLocation BreakLoc;
596public:
597  BreakStmt(SourceLocation BL) : Stmt(BreakStmtClass), BreakLoc(BL) {}
598
599  virtual SourceRange getSourceRange() const { return SourceRange(BreakLoc); }
600
601  static bool classof(const Stmt *T) {
602    return T->getStmtClass() == BreakStmtClass;
603  }
604  static bool classof(const BreakStmt *) { return true; }
605
606  // Iterators
607  virtual child_iterator child_begin();
608  virtual child_iterator child_end();
609};
610
611
612/// ReturnStmt - This represents a return, optionally of an expression.
613///
614class ReturnStmt : public Stmt {
615  Expr *RetExpr;
616  SourceLocation RetLoc;
617public:
618  ReturnStmt(SourceLocation RL, Expr *E = 0) : Stmt(ReturnStmtClass),
619    RetExpr(E), RetLoc(RL) {}
620
621  const Expr *getRetValue() const { return RetExpr; }
622  Expr *getRetValue() { return RetExpr; }
623
624  virtual SourceRange getSourceRange() const;
625
626  static bool classof(const Stmt *T) {
627    return T->getStmtClass() == ReturnStmtClass;
628  }
629  static bool classof(const ReturnStmt *) { return true; }
630
631  // Iterators
632  virtual child_iterator child_begin();
633  virtual child_iterator child_end();
634};
635
636}  // end namespace clang
637
638//===----------------------------------------------------------------------===//
639// GraphTraits specialization to treat ASTs (Stmt*) as graphs
640//===----------------------------------------------------------------------===//
641
642namespace llvm {
643
644template <> struct GraphTraits<clang::Stmt*> {
645  typedef clang::Stmt                  NodeType;
646  typedef clang::Stmt::child_iterator  ChildIteratorType;
647
648  static NodeType* getEntryNode(clang::Stmt* S) { return S; }
649
650  static inline ChildIteratorType child_begin(NodeType* N) {
651    return N->child_begin();
652  }
653
654  static inline ChildIteratorType child_end(NodeType* N) {
655    return N->child_end();
656  }
657};
658
659template <> struct GraphTraits<const clang::Stmt*> {
660  typedef const clang::Stmt                  NodeType;
661  typedef clang::Stmt::const_child_iterator  ChildIteratorType;
662
663  static NodeType* getEntryNode(const clang::Stmt* S) { return S; }
664
665  static inline ChildIteratorType child_begin(NodeType* N) {
666    return N->child_begin();
667  }
668
669  static inline ChildIteratorType child_end(NodeType* N) {
670    return N->child_end();
671  }
672};
673
674} // end namespace llvm
675#endif
676