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 
StmtIteratorBase(Stmt ** s)43   StmtIteratorBase(Stmt **s) : stmt(s) {}
44   StmtIteratorBase(const VariableArrayType *t);
45   StmtIteratorBase(Decl **dgi, Decl **dge);
StmtIteratorBase()46   StmtIteratorBase() : stmt(nullptr) {}
47 
inDeclGroup()48   bool inDeclGroup() const {
49     return (RawVAPtr & Flags) == DeclGroupMode;
50   }
51 
inSizeOfTypeVA()52   bool inSizeOfTypeVA() const {
53     return (RawVAPtr & Flags) == SizeOfTypeVAMode;
54   }
55 
inStmt()56   bool inStmt() const {
57     return (RawVAPtr & Flags) == StmtMode;
58   }
59 
getVAPtr()60   const VariableArrayType *getVAPtr() const {
61     return reinterpret_cast<const VariableArrayType*>(RawVAPtr & ~Flags);
62   }
63 
setVAPtr(const VariableArrayType * P)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 protected:
StmtIteratorImpl(const StmtIteratorBase & RHS)79   StmtIteratorImpl(const StmtIteratorBase& RHS) : StmtIteratorBase(RHS) {}
80 
81 public:
82   using iterator_category = std::forward_iterator_tag;
83   using value_type = REFERENCE;
84   using difference_type = std::ptrdiff_t;
85   using pointer = REFERENCE;
86   using reference = REFERENCE;
87 
88   StmtIteratorImpl() = default;
StmtIteratorImpl(Stmt ** s)89   StmtIteratorImpl(Stmt **s) : StmtIteratorBase(s) {}
StmtIteratorImpl(Decl ** dgi,Decl ** dge)90   StmtIteratorImpl(Decl **dgi, Decl **dge) : StmtIteratorBase(dgi, dge) {}
StmtIteratorImpl(const VariableArrayType * t)91   StmtIteratorImpl(const VariableArrayType *t) : StmtIteratorBase(t) {}
92 
93   DERIVED& operator++() {
94     if (inStmt())
95       ++stmt;
96     else if (getVAPtr())
97       NextVA();
98     else
99       NextDecl();
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   friend bool operator==(const DERIVED &LHS, const DERIVED &RHS) {
111     return LHS.stmt == RHS.stmt && LHS.DGI == RHS.DGI &&
112            LHS.RawVAPtr == RHS.RawVAPtr;
113   }
114 
115   friend bool operator!=(const DERIVED &LHS, const DERIVED &RHS) {
116     return !(LHS == RHS);
117   }
118 
119   REFERENCE operator*() const {
120     return inStmt() ? *stmt : GetDeclExpr();
121   }
122 
123   REFERENCE operator->() const { return operator*(); }
124 };
125 
126 struct ConstStmtIterator;
127 
128 struct StmtIterator : public StmtIteratorImpl<StmtIterator, Stmt*&> {
129   explicit StmtIterator() = default;
StmtIteratorStmtIterator130   StmtIterator(Stmt** S) : StmtIteratorImpl<StmtIterator, Stmt*&>(S) {}
StmtIteratorStmtIterator131   StmtIterator(Decl** dgi, Decl** dge)
132       : StmtIteratorImpl<StmtIterator, Stmt*&>(dgi, dge) {}
StmtIteratorStmtIterator133   StmtIterator(const VariableArrayType *t)
134       : StmtIteratorImpl<StmtIterator, Stmt*&>(t) {}
135 
136 private:
StmtIteratorStmtIterator137   StmtIterator(const StmtIteratorBase &RHS)
138       : StmtIteratorImpl<StmtIterator, Stmt *&>(RHS) {}
139 
140   inline friend StmtIterator
141   cast_away_const(const ConstStmtIterator &RHS);
142 };
143 
144 struct ConstStmtIterator : public StmtIteratorImpl<ConstStmtIterator,
145                                                    const Stmt*> {
146   explicit ConstStmtIterator() = default;
ConstStmtIteratorConstStmtIterator147   ConstStmtIterator(const StmtIterator& RHS)
148       : StmtIteratorImpl<ConstStmtIterator, const Stmt*>(RHS) {}
149 
ConstStmtIteratorConstStmtIterator150   ConstStmtIterator(Stmt * const *S)
151       : StmtIteratorImpl<ConstStmtIterator, const Stmt *>(
152             const_cast<Stmt **>(S)) {}
153 };
154 
cast_away_const(const ConstStmtIterator & RHS)155 inline StmtIterator cast_away_const(const ConstStmtIterator &RHS) {
156   return RHS;
157 }
158 
159 } // namespace clang
160 
161 #endif // LLVM_CLANG_AST_STMTITERATOR_H
162