1 //===- StmtIterator.h - Iterators for Statements ----------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file defines the StmtIterator and ConstStmtIterator classes.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #ifndef LLVM_CLANG_AST_STMTITERATOR_H
14 #define LLVM_CLANG_AST_STMTITERATOR_H
15 
16 #include <cassert>
17 #include <cstddef>
18 #include <cstdint>
19 #include <iterator>
20 
21 namespace clang {
22 
23 class Decl;
24 class Stmt;
25 class VariableArrayType;
26 
27 class StmtIteratorBase {
28 protected:
29   enum {
30     StmtMode = 0x0,
31     SizeOfTypeVAMode = 0x1,
32     DeclGroupMode = 0x2,
33     Flags = 0x3
34   };
35 
36   union {
37     Stmt **stmt;
38     Decl **DGI;
39   };
40   uintptr_t RawVAPtr = 0;
41   Decl **DGE;
42 
43   StmtIteratorBase(Stmt **s) : stmt(s) {}
44   StmtIteratorBase(const VariableArrayType *t);
45   StmtIteratorBase(Decl **dgi, Decl **dge);
46   StmtIteratorBase() : stmt(nullptr) {}
47 
48   bool inDeclGroup() const {
49     return (RawVAPtr & Flags) == DeclGroupMode;
50   }
51 
52   bool inSizeOfTypeVA() const {
53     return (RawVAPtr & Flags) == SizeOfTypeVAMode;
54   }
55 
56   bool inStmt() const {
57     return (RawVAPtr & Flags) == StmtMode;
58   }
59 
60   const VariableArrayType *getVAPtr() const {
61     return reinterpret_cast<const VariableArrayType*>(RawVAPtr & ~Flags);
62   }
63 
64   void setVAPtr(const VariableArrayType *P) {
65     assert(inDeclGroup() || inSizeOfTypeVA());
66     RawVAPtr = reinterpret_cast<uintptr_t>(P) | (RawVAPtr & Flags);
67   }
68 
69   void NextDecl(bool ImmediateAdvance = true);
70   bool HandleDecl(Decl* D);
71   void NextVA();
72 
73   Stmt*& GetDeclExpr() const;
74 };
75 
76 template <typename DERIVED, typename REFERENCE>
77 class StmtIteratorImpl : public StmtIteratorBase,
78                          public std::iterator<std::forward_iterator_tag,
79                                               REFERENCE, ptrdiff_t,
80                                               REFERENCE, REFERENCE> {
81 protected:
82   StmtIteratorImpl(const StmtIteratorBase& RHS) : StmtIteratorBase(RHS) {}
83 
84 public:
85   StmtIteratorImpl() = default;
86   StmtIteratorImpl(Stmt **s) : StmtIteratorBase(s) {}
87   StmtIteratorImpl(Decl **dgi, Decl **dge) : StmtIteratorBase(dgi, dge) {}
88   StmtIteratorImpl(const VariableArrayType *t) : StmtIteratorBase(t) {}
89 
90   DERIVED& operator++() {
91     if (inStmt())
92       ++stmt;
93     else if (getVAPtr())
94       NextVA();
95     else
96       NextDecl();
97 
98     return static_cast<DERIVED&>(*this);
99   }
100 
101   DERIVED operator++(int) {
102     DERIVED tmp = static_cast<DERIVED&>(*this);
103     operator++();
104     return tmp;
105   }
106 
107   friend bool operator==(const DERIVED &LHS, const DERIVED &RHS) {
108     return LHS.stmt == RHS.stmt && LHS.DGI == RHS.DGI &&
109            LHS.RawVAPtr == RHS.RawVAPtr;
110   }
111 
112   friend bool operator!=(const DERIVED &LHS, const DERIVED &RHS) {
113     return !(LHS == RHS);
114   }
115 
116   REFERENCE operator*() const {
117     return inStmt() ? *stmt : GetDeclExpr();
118   }
119 
120   REFERENCE operator->() const { return operator*(); }
121 };
122 
123 struct ConstStmtIterator;
124 
125 struct StmtIterator : public StmtIteratorImpl<StmtIterator, Stmt*&> {
126   explicit StmtIterator() = default;
127   StmtIterator(Stmt** S) : StmtIteratorImpl<StmtIterator, Stmt*&>(S) {}
128   StmtIterator(Decl** dgi, Decl** dge)
129       : StmtIteratorImpl<StmtIterator, Stmt*&>(dgi, dge) {}
130   StmtIterator(const VariableArrayType *t)
131       : StmtIteratorImpl<StmtIterator, Stmt*&>(t) {}
132 
133 private:
134   StmtIterator(const StmtIteratorBase &RHS)
135       : StmtIteratorImpl<StmtIterator, Stmt *&>(RHS) {}
136 
137   inline friend StmtIterator
138   cast_away_const(const ConstStmtIterator &RHS);
139 };
140 
141 struct ConstStmtIterator : public StmtIteratorImpl<ConstStmtIterator,
142                                                    const Stmt*> {
143   explicit ConstStmtIterator() = default;
144   ConstStmtIterator(const StmtIterator& RHS)
145       : StmtIteratorImpl<ConstStmtIterator, const Stmt*>(RHS) {}
146 
147   ConstStmtIterator(Stmt * const *S)
148       : StmtIteratorImpl<ConstStmtIterator, const Stmt *>(
149             const_cast<Stmt **>(S)) {}
150 };
151 
152 inline StmtIterator cast_away_const(const ConstStmtIterator &RHS) {
153   return RHS;
154 }
155 
156 } // namespace clang
157 
158 #endif // LLVM_CLANG_AST_STMTITERATOR_H
159