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_STMTITERATOR_H
15#define LLVM_CLANG_AST_STMTITERATOR_H
16
17#include "llvm/Support/Compiler.h"
18#include "llvm/Support/DataTypes.h"
19#include <cassert>
20#include <cstddef>
21#include <iterator>
22#include <utility>
23
24namespace clang {
25
26class Stmt;
27class Decl;
28class VariableArrayType;
29
30class StmtIteratorBase {
31protected:
32  enum { StmtMode = 0x0, SizeOfTypeVAMode = 0x1, DeclGroupMode = 0x2,
33         Flags = 0x3 };
34
35  union {
36    Stmt **stmt;
37    Decl **DGI;
38  };
39  uintptr_t RawVAPtr;
40  Decl **DGE;
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) == StmtMode;
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 (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), RawVAPtr(0) {}
70  StmtIteratorBase(const VariableArrayType *t);
71  StmtIteratorBase(Decl **dgi, Decl **dge);
72  StmtIteratorBase() : stmt(nullptr), 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(const VariableArrayType *t) : StmtIteratorBase(t) {}
88
89  DERIVED& operator++() {
90    if (inStmt())
91      ++stmt;
92    else if (getVAPtr())
93      NextVA();
94    else
95      NextDecl();
96
97    return static_cast<DERIVED&>(*this);
98  }
99
100  DERIVED operator++(int) {
101    DERIVED tmp = static_cast<DERIVED&>(*this);
102    operator++();
103    return tmp;
104  }
105
106  bool operator==(const DERIVED& RHS) const {
107    return stmt == RHS.stmt && DGI == RHS.DGI && RawVAPtr == RHS.RawVAPtr;
108  }
109
110  bool operator!=(const DERIVED& RHS) const {
111    return stmt != RHS.stmt || DGI != RHS.DGI || RawVAPtr != RHS.RawVAPtr;
112  }
113
114  REFERENCE operator*() const {
115    return inStmt() ? *stmt : GetDeclExpr();
116  }
117
118  REFERENCE operator->() const { return operator*(); }
119};
120
121struct StmtIterator : public StmtIteratorImpl<StmtIterator,Stmt*&> {
122  explicit StmtIterator() : StmtIteratorImpl<StmtIterator,Stmt*&>() {}
123
124  StmtIterator(Stmt** S) : StmtIteratorImpl<StmtIterator,Stmt*&>(S) {}
125
126  StmtIterator(Decl** dgi, Decl** dge)
127   : StmtIteratorImpl<StmtIterator,Stmt*&>(dgi, dge) {}
128
129  StmtIterator(const VariableArrayType *t)
130    : StmtIteratorImpl<StmtIterator,Stmt*&>(t) {}
131};
132
133struct ConstStmtIterator : public StmtIteratorImpl<ConstStmtIterator,
134                                                   const Stmt*> {
135  explicit ConstStmtIterator() :
136    StmtIteratorImpl<ConstStmtIterator,const Stmt*>() {}
137
138  ConstStmtIterator(const StmtIterator& RHS) :
139    StmtIteratorImpl<ConstStmtIterator,const Stmt*>(RHS) {}
140};
141
142} // end namespace clang
143
144#endif
145