StmtIterator.h revision ea285162342df160e7860e26528bc7110bc6c0cd
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/System/DataTypes.h"
18#include <cassert>
19#include <iterator>
20
21namespace clang {
22
23class Stmt;
24class Decl;
25class VariableArrayType;
26
27class StmtIteratorBase {
28protected:
29  enum { DeclMode = 0x1, SizeOfTypeVAMode = 0x2, DeclGroupMode = 0x3,
30         Flags = 0x3 };
31
32  Stmt **stmt;
33  union { Decl *decl; Decl **DGI; };
34  uintptr_t RawVAPtr;
35  Decl **DGE;
36
37  bool inDecl() const {
38    return (RawVAPtr & Flags) == DeclMode;
39  }
40
41  bool inDeclGroup() const {
42    return (RawVAPtr & Flags) == DeclGroupMode;
43  }
44
45  bool inSizeOfTypeVA() const {
46    return (RawVAPtr & Flags) == SizeOfTypeVAMode;
47  }
48
49  bool inStmt() const {
50    return (RawVAPtr & Flags) == 0;
51  }
52
53  VariableArrayType* getVAPtr() const {
54    return reinterpret_cast<VariableArrayType*>(RawVAPtr & ~Flags);
55  }
56
57  void setVAPtr(VariableArrayType* P) {
58    assert (inDecl() || inDeclGroup() || inSizeOfTypeVA());
59    RawVAPtr = reinterpret_cast<uintptr_t>(P) | (RawVAPtr & Flags);
60  }
61
62  void NextDecl(bool ImmediateAdvance = true);
63  bool HandleDecl(Decl* D);
64  void NextVA();
65
66  Stmt*& GetDeclExpr() const;
67
68  StmtIteratorBase(Stmt **s) : stmt(s), decl(0), RawVAPtr(0) {}
69  StmtIteratorBase(Decl *d, Stmt **s);
70  StmtIteratorBase(VariableArrayType *t);
71  StmtIteratorBase(Decl **dgi, Decl **dge);
72  StmtIteratorBase() : stmt(0), decl(0), RawVAPtr(0) {}
73};
74
75
76template <typename DERIVED, typename REFERENCE>
77class StmtIteratorImpl : public StmtIteratorBase,
78                         public std::iterator<std::forward_iterator_tag,
79                                              REFERENCE, ptrdiff_t,
80                                              REFERENCE, REFERENCE> {
81protected:
82  StmtIteratorImpl(const StmtIteratorBase& RHS) : StmtIteratorBase(RHS) {}
83public:
84  StmtIteratorImpl() {}
85  StmtIteratorImpl(Stmt **s) : StmtIteratorBase(s) {}
86  StmtIteratorImpl(Decl **dgi, Decl **dge) : StmtIteratorBase(dgi, dge) {}
87  StmtIteratorImpl(Decl *d, Stmt **s) : StmtIteratorBase(d, s) {}
88  StmtIteratorImpl(VariableArrayType* t) : StmtIteratorBase(t) {}
89
90  DERIVED& operator++() {
91    if (inDecl() || inDeclGroup()) {
92      if (getVAPtr()) NextVA();
93      else NextDecl();
94    }
95    else if (inSizeOfTypeVA())
96      NextVA();
97    else
98      ++stmt;
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(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} // end namespace clang
149
150#endif
151