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