StmtIterator.h revision 165ce3c8a16542182adedae6475ed08ae4972e31
1//===--- StmtIterator.h - Iterators for Statements --------------*- C++ -*-===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file defines the StmtIterator and ConstStmtIterator classes.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef LLVM_CLANG_AST_STMT_ITR_H
15#define LLVM_CLANG_AST_STMT_ITR_H
16
17#include "llvm/Support/DataTypes.h"
18#include <cassert>
19#include <cstddef>
20#include <iterator>
21#include <utility>
22
23namespace clang {
24
25class Stmt;
26class Decl;
27class VariableArrayType;
28
29class StmtIteratorBase {
30protected:
31  enum { DeclMode = 0x1, SizeOfTypeVAMode = 0x2, DeclGroupMode = 0x3,
32         Flags = 0x3 };
33
34  Stmt **stmt;
35  union { Decl *decl; Decl **DGI; };
36  uintptr_t RawVAPtr;
37  Decl **DGE;
38
39  bool inDecl() const {
40    return (RawVAPtr & Flags) == DeclMode;
41  }
42
43  bool inDeclGroup() const {
44    return (RawVAPtr & Flags) == DeclGroupMode;
45  }
46
47  bool inSizeOfTypeVA() const {
48    return (RawVAPtr & Flags) == SizeOfTypeVAMode;
49  }
50
51  bool inStmt() const {
52    return (RawVAPtr & Flags) == 0;
53  }
54
55  const VariableArrayType *getVAPtr() const {
56    return reinterpret_cast<const VariableArrayType*>(RawVAPtr & ~Flags);
57  }
58
59  void setVAPtr(const VariableArrayType *P) {
60    assert (inDecl() || inDeclGroup() || inSizeOfTypeVA());
61    RawVAPtr = reinterpret_cast<uintptr_t>(P) | (RawVAPtr & Flags);
62  }
63
64  void NextDecl(bool ImmediateAdvance = true);
65  bool HandleDecl(Decl* D);
66  void NextVA();
67
68  Stmt*& GetDeclExpr() const;
69
70  StmtIteratorBase(Stmt **s) : stmt(s), decl(0), RawVAPtr(0) {}
71  StmtIteratorBase(Decl *d, Stmt **s);
72  StmtIteratorBase(const VariableArrayType *t);
73  StmtIteratorBase(Decl **dgi, Decl **dge);
74  StmtIteratorBase() : stmt(0), decl(0), RawVAPtr(0) {}
75};
76
77
78template <typename DERIVED, typename REFERENCE>
79class StmtIteratorImpl : public StmtIteratorBase,
80                         public std::iterator<std::forward_iterator_tag,
81                                              REFERENCE, ptrdiff_t,
82                                              REFERENCE, REFERENCE> {
83protected:
84  StmtIteratorImpl(const StmtIteratorBase& RHS) : StmtIteratorBase(RHS) {}
85public:
86  StmtIteratorImpl() {}
87  StmtIteratorImpl(Stmt **s) : StmtIteratorBase(s) {}
88  StmtIteratorImpl(Decl **dgi, Decl **dge) : StmtIteratorBase(dgi, dge) {}
89  StmtIteratorImpl(Decl *d, Stmt **s) : StmtIteratorBase(d, s) {}
90  StmtIteratorImpl(const VariableArrayType *t) : StmtIteratorBase(t) {}
91
92  DERIVED& operator++() {
93    if (inStmt())
94      ++stmt;
95    else if (getVAPtr())
96      NextVA();
97    else
98      NextDecl();
99
100    return static_cast<DERIVED&>(*this);
101  }
102
103  DERIVED operator++(int) {
104    DERIVED tmp = static_cast<DERIVED&>(*this);
105    operator++();
106    return tmp;
107  }
108
109  bool operator==(const DERIVED& RHS) const {
110    return stmt == RHS.stmt && decl == RHS.decl && RawVAPtr == RHS.RawVAPtr;
111  }
112
113  bool operator!=(const DERIVED& RHS) const {
114    return stmt != RHS.stmt || decl != RHS.decl || RawVAPtr != RHS.RawVAPtr;
115  }
116
117  REFERENCE operator*() const {
118    return (REFERENCE) (inStmt() ? *stmt : GetDeclExpr());
119  }
120
121  REFERENCE operator->() const { return operator*(); }
122};
123
124struct StmtIterator : public StmtIteratorImpl<StmtIterator,Stmt*&> {
125  explicit StmtIterator() : StmtIteratorImpl<StmtIterator,Stmt*&>() {}
126
127  StmtIterator(Stmt** S) : StmtIteratorImpl<StmtIterator,Stmt*&>(S) {}
128
129  StmtIterator(Decl** dgi, Decl** dge)
130   : StmtIteratorImpl<StmtIterator,Stmt*&>(dgi, dge) {}
131
132  StmtIterator(const VariableArrayType *t)
133    : StmtIteratorImpl<StmtIterator,Stmt*&>(t) {}
134
135  StmtIterator(Decl* D, Stmt **s = 0)
136    : StmtIteratorImpl<StmtIterator,Stmt*&>(D, s) {}
137};
138
139struct ConstStmtIterator : public StmtIteratorImpl<ConstStmtIterator,
140                                                   const Stmt*> {
141  explicit ConstStmtIterator() :
142    StmtIteratorImpl<ConstStmtIterator,const Stmt*>() {}
143
144  ConstStmtIterator(const StmtIterator& RHS) :
145    StmtIteratorImpl<ConstStmtIterator,const Stmt*>(RHS) {}
146};
147
148/// A range of statement iterators.
149///
150/// This class provides some extra functionality beyond std::pair
151/// in order to allow the following idiom:
152///   for (StmtRange range = stmt->children(); range; ++range)
153struct StmtRange : std::pair<StmtIterator,StmtIterator> {
154  StmtRange() {}
155  StmtRange(const StmtIterator &begin, const StmtIterator &end)
156    : std::pair<StmtIterator,StmtIterator>(begin, end) {}
157
158  bool empty() const { return first == second; }
159  operator bool() const { return !empty(); }
160
161  Stmt *operator->() const { return first.operator->(); }
162  Stmt *&operator*() const { return first.operator*(); }
163
164  StmtRange &operator++() {
165    assert(!empty() && "incrementing on empty range");
166    ++first;
167    return *this;
168  }
169
170  StmtRange operator++(int) {
171    assert(!empty() && "incrementing on empty range");
172    StmtRange copy = *this;
173    ++first;
174    return copy;
175  }
176
177  friend const StmtIterator &begin(const StmtRange &range) {
178    return range.first;
179  }
180  friend const StmtIterator &end(const StmtRange &range) {
181    return range.second;
182  }
183};
184
185/// A range of const statement iterators.
186///
187/// This class provides some extra functionality beyond std::pair
188/// in order to allow the following idiom:
189///   for (ConstStmtRange range = stmt->children(); range; ++range)
190struct ConstStmtRange : std::pair<ConstStmtIterator,ConstStmtIterator> {
191  ConstStmtRange() {}
192  ConstStmtRange(const ConstStmtIterator &begin,
193                 const ConstStmtIterator &end)
194    : std::pair<ConstStmtIterator,ConstStmtIterator>(begin, end) {}
195  ConstStmtRange(const StmtRange &range)
196    : std::pair<ConstStmtIterator,ConstStmtIterator>(range.first, range.second)
197  {}
198  ConstStmtRange(const StmtIterator &begin, const StmtIterator &end)
199    : std::pair<ConstStmtIterator,ConstStmtIterator>(begin, end) {}
200
201  bool empty() const { return first == second; }
202  operator bool() const { return !empty(); }
203
204  const Stmt *operator->() const { return first.operator->(); }
205  const Stmt *operator*() const { return first.operator*(); }
206
207  ConstStmtRange &operator++() {
208    assert(!empty() && "incrementing on empty range");
209    ++first;
210    return *this;
211  }
212
213  ConstStmtRange operator++(int) {
214    assert(!empty() && "incrementing on empty range");
215    ConstStmtRange copy = *this;
216    ++first;
217    return copy;
218  }
219
220  friend const ConstStmtIterator &begin(const ConstStmtRange &range) {
221    return range.first;
222  }
223  friend const ConstStmtIterator &end(const ConstStmtRange &range) {
224    return range.second;
225  }
226};
227
228} // end namespace clang
229
230#endif
231