StmtIterator.h revision 699e9fbeae34cdd651b8e6308649c8939f090cbd
1//===--- StmtIterator.h - Iterators for Statements ------------------------===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file was developed by Ted Kremenek 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 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/ADT/iterator"
18#include <cassert>
19
20namespace clang {
21
22class Stmt;
23class ScopedDecl;
24class VariableArrayType;
25
26class StmtIteratorBase {
27protected:
28  enum { DeclMode = 0x1, VASizeMode = 0x2, Flags = 0x3 };
29  union { Stmt** stmt; ScopedDecl* decl; };
30  uintptr_t RawVAPtr;
31
32  bool inDeclMode() const { return RawVAPtr & DeclMode ? true : false; }
33  bool inVASizeMode() const { return RawVAPtr & VASizeMode ? true : false; }
34  bool hasFlags() const { return RawVAPtr & Flags ? true : false; }
35
36  VariableArrayType* getVAPtr() const {
37    return reinterpret_cast<VariableArrayType*>(RawVAPtr & ~Flags);
38  }
39
40  void setVAPtr(VariableArrayType* P) {
41    assert (inDeclMode() || inVASizeMode());
42    RawVAPtr = reinterpret_cast<uintptr_t>(P) | (RawVAPtr & Flags);
43  }
44
45  void NextDecl(bool ImmediateAdvance = true);
46  void NextVA();
47
48  Stmt*& GetDeclExpr() const;
49
50  StmtIteratorBase(Stmt** s) : stmt(s), RawVAPtr(0) {}
51  StmtIteratorBase(ScopedDecl* d);
52  StmtIteratorBase(VariableArrayType* t);
53  StmtIteratorBase() : stmt(NULL), RawVAPtr(0) {}
54};
55
56
57template <typename DERIVED, typename REFERENCE>
58class StmtIteratorImpl : public StmtIteratorBase,
59                         public std::iterator<std::forward_iterator_tag,
60                                              REFERENCE, ptrdiff_t,
61                                              REFERENCE, REFERENCE> {
62protected:
63  StmtIteratorImpl(const StmtIteratorBase& RHS) : StmtIteratorBase(RHS) {}
64public:
65  StmtIteratorImpl() {}
66  StmtIteratorImpl(Stmt** s) : StmtIteratorBase(s) {}
67  StmtIteratorImpl(ScopedDecl* d) : StmtIteratorBase(d) {}
68  StmtIteratorImpl(VariableArrayType* t) : StmtIteratorBase(t) {}
69
70  DERIVED& operator++() {
71    if (inDeclMode()) {
72      if (getVAPtr()) NextVA();
73      else NextDecl();
74    }
75    else if (inVASizeMode())
76      NextVA();
77    else
78      ++stmt;
79
80    return static_cast<DERIVED&>(*this);
81  }
82
83  DERIVED operator++(int) {
84    DERIVED tmp = static_cast<DERIVED&>(*this);
85    operator++();
86    return tmp;
87  }
88
89  bool operator==(const DERIVED& RHS) const {
90    return stmt == RHS.stmt && RawVAPtr == RHS.RawVAPtr;
91  }
92
93  bool operator!=(const DERIVED& RHS) const {
94    return stmt != RHS.stmt || RawVAPtr != RHS.RawVAPtr;
95  }
96
97  REFERENCE operator*() const {
98    return (REFERENCE) (hasFlags() ? GetDeclExpr() : *stmt);
99  }
100
101  REFERENCE operator->() const { return operator*(); }
102};
103
104struct StmtIterator : public StmtIteratorImpl<StmtIterator,Stmt*&> {
105  explicit StmtIterator() : StmtIteratorImpl<StmtIterator,Stmt*&>() {}
106  StmtIterator(Stmt** S) : StmtIteratorImpl<StmtIterator,Stmt*&>(S) {}
107  StmtIterator(VariableArrayType* t):StmtIteratorImpl<StmtIterator,Stmt*&>(t) {}
108  StmtIterator(ScopedDecl* D) : StmtIteratorImpl<StmtIterator,Stmt*&>(D) {}
109};
110
111struct ConstStmtIterator : public StmtIteratorImpl<ConstStmtIterator,
112                                                   const Stmt*> {
113  explicit ConstStmtIterator() :
114    StmtIteratorImpl<ConstStmtIterator,const Stmt*>() {}
115
116  ConstStmtIterator(const StmtIterator& RHS) :
117    StmtIteratorImpl<ConstStmtIterator,const Stmt*>(RHS) {}
118};
119
120} // end namespace clang
121
122#endif
123