StmtIterator.h revision f4c7371fb1d3cebcfb40abad4537bb82515704ea
1//===--- StmtIterator.h - Iterators for Statements ------------------------===//
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
22namespace clang {
23
24class Stmt;
25class Decl;
26class VariableArrayType;
27
28class StmtIteratorBase {
29protected:
30  enum { DeclMode = 0x1, SizeOfTypeVAMode = 0x2, DeclGroupMode = 0x3,
31         Flags = 0x3 };
32
33  Stmt **stmt;
34  union { Decl *decl; Decl **DGI; };
35  uintptr_t RawVAPtr;
36  Decl **DGE;
37
38  bool inDecl() const {
39    return (RawVAPtr & Flags) == DeclMode;
40  }
41
42  bool inDeclGroup() const {
43    return (RawVAPtr & Flags) == DeclGroupMode;
44  }
45
46  bool inSizeOfTypeVA() const {
47    return (RawVAPtr & Flags) == SizeOfTypeVAMode;
48  }
49
50  bool inStmt() const {
51    return (RawVAPtr & Flags) == 0;
52  }
53
54  const VariableArrayType *getVAPtr() const {
55    return reinterpret_cast<const VariableArrayType*>(RawVAPtr & ~Flags);
56  }
57
58  void setVAPtr(const VariableArrayType *P) {
59    assert (inDecl() || inDeclGroup() || inSizeOfTypeVA());
60    RawVAPtr = reinterpret_cast<uintptr_t>(P) | (RawVAPtr & Flags);
61  }
62
63  void NextDecl(bool ImmediateAdvance = true);
64  bool HandleDecl(Decl* D);
65  void NextVA();
66
67  Stmt*& GetDeclExpr() const;
68
69  StmtIteratorBase(Stmt **s) : stmt(s), decl(0), RawVAPtr(0) {}
70  StmtIteratorBase(Decl *d, Stmt **s);
71  StmtIteratorBase(const VariableArrayType *t);
72  StmtIteratorBase(Decl **dgi, Decl **dge);
73  StmtIteratorBase() : stmt(0), decl(0), RawVAPtr(0) {}
74};
75
76
77template <typename DERIVED, typename REFERENCE>
78class StmtIteratorImpl : public StmtIteratorBase,
79                         public std::iterator<std::forward_iterator_tag,
80                                              REFERENCE, ptrdiff_t,
81                                              REFERENCE, REFERENCE> {
82protected:
83  StmtIteratorImpl(const StmtIteratorBase& RHS) : StmtIteratorBase(RHS) {}
84public:
85  StmtIteratorImpl() {}
86  StmtIteratorImpl(Stmt **s) : StmtIteratorBase(s) {}
87  StmtIteratorImpl(Decl **dgi, Decl **dge) : StmtIteratorBase(dgi, dge) {}
88  StmtIteratorImpl(Decl *d, Stmt **s) : StmtIteratorBase(d, s) {}
89  StmtIteratorImpl(const VariableArrayType *t) : StmtIteratorBase(t) {}
90
91  DERIVED& operator++() {
92    if (inDecl() || inDeclGroup()) {
93      if (getVAPtr()) NextVA();
94      else NextDecl();
95    }
96    else if (inSizeOfTypeVA())
97      NextVA();
98    else
99      ++stmt;
100
101    return static_cast<DERIVED&>(*this);
102  }
103
104  DERIVED operator++(int) {
105    DERIVED tmp = static_cast<DERIVED&>(*this);
106    operator++();
107    return tmp;
108  }
109
110  bool operator==(const DERIVED& RHS) const {
111    return stmt == RHS.stmt && decl == RHS.decl && RawVAPtr == RHS.RawVAPtr;
112  }
113
114  bool operator!=(const DERIVED& RHS) const {
115    return stmt != RHS.stmt || decl != RHS.decl || RawVAPtr != RHS.RawVAPtr;
116  }
117
118  REFERENCE operator*() const {
119    return (REFERENCE) (inStmt() ? *stmt : GetDeclExpr());
120  }
121
122  REFERENCE operator->() const { return operator*(); }
123};
124
125struct StmtIterator : public StmtIteratorImpl<StmtIterator,Stmt*&> {
126  explicit StmtIterator() : StmtIteratorImpl<StmtIterator,Stmt*&>() {}
127
128  StmtIterator(Stmt** S) : StmtIteratorImpl<StmtIterator,Stmt*&>(S) {}
129
130  StmtIterator(Decl** dgi, Decl** dge)
131   : StmtIteratorImpl<StmtIterator,Stmt*&>(dgi, dge) {}
132
133  StmtIterator(const VariableArrayType *t)
134    : StmtIteratorImpl<StmtIterator,Stmt*&>(t) {}
135
136  StmtIterator(Decl* D, Stmt **s = 0)
137    : StmtIteratorImpl<StmtIterator,Stmt*&>(D, s) {}
138};
139
140struct ConstStmtIterator : public StmtIteratorImpl<ConstStmtIterator,
141                                                   const Stmt*> {
142  explicit ConstStmtIterator() :
143    StmtIteratorImpl<ConstStmtIterator,const Stmt*>() {}
144
145  ConstStmtIterator(const StmtIterator& RHS) :
146    StmtIteratorImpl<ConstStmtIterator,const Stmt*>(RHS) {}
147};
148
149} // end namespace clang
150
151#endif
152