clang API Documentation

StmtIterator.h
Go to the documentation of this file.
00001 //===--- StmtIterator.h - Iterators for Statements --------------*- C++ -*-===//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 //
00010 // This file defines the StmtIterator and ConstStmtIterator classes.
00011 //
00012 //===----------------------------------------------------------------------===//
00013 
00014 #ifndef LLVM_CLANG_AST_STMTITERATOR_H
00015 #define LLVM_CLANG_AST_STMTITERATOR_H
00016 
00017 #include "llvm/Support/Compiler.h"
00018 #include "llvm/Support/DataTypes.h"
00019 #include <cassert>
00020 #include <cstddef>
00021 #include <iterator>
00022 #include <utility>
00023 
00024 namespace clang {
00025 
00026 class Stmt;
00027 class Decl;
00028 class VariableArrayType;
00029 
00030 class StmtIteratorBase {
00031 protected:
00032   enum { StmtMode = 0x0, SizeOfTypeVAMode = 0x1, DeclGroupMode = 0x2,
00033          Flags = 0x3 };
00034   
00035   Stmt **stmt;
00036   Decl **DGI;
00037   uintptr_t RawVAPtr;
00038   Decl **DGE;
00039   
00040   bool inDeclGroup() const {
00041     return (RawVAPtr & Flags) == DeclGroupMode;
00042   }
00043 
00044   bool inSizeOfTypeVA() const {
00045     return (RawVAPtr & Flags) == SizeOfTypeVAMode;
00046   }
00047 
00048   bool inStmt() const {
00049     return (RawVAPtr & Flags) == StmtMode;
00050   }
00051 
00052   const VariableArrayType *getVAPtr() const {
00053     return reinterpret_cast<const VariableArrayType*>(RawVAPtr & ~Flags);
00054   }
00055 
00056   void setVAPtr(const VariableArrayType *P) {
00057     assert (inDeclGroup() || inSizeOfTypeVA());
00058     RawVAPtr = reinterpret_cast<uintptr_t>(P) | (RawVAPtr & Flags);
00059   }
00060 
00061   void NextDecl(bool ImmediateAdvance = true);
00062   bool HandleDecl(Decl* D);
00063   void NextVA();
00064 
00065   Stmt*& GetDeclExpr() const;
00066 
00067   StmtIteratorBase(Stmt **s) : stmt(s), DGI(nullptr), RawVAPtr(0) {}
00068   StmtIteratorBase(const VariableArrayType *t);
00069   StmtIteratorBase(Decl **dgi, Decl **dge);
00070   StmtIteratorBase() : stmt(nullptr), DGI(nullptr), RawVAPtr(0) {}
00071 };
00072 
00073 
00074 template <typename DERIVED, typename REFERENCE>
00075 class StmtIteratorImpl : public StmtIteratorBase,
00076                          public std::iterator<std::forward_iterator_tag,
00077                                               REFERENCE, ptrdiff_t,
00078                                               REFERENCE, REFERENCE> {
00079 protected:
00080   StmtIteratorImpl(const StmtIteratorBase& RHS) : StmtIteratorBase(RHS) {}
00081 public:
00082   StmtIteratorImpl() {}
00083   StmtIteratorImpl(Stmt **s) : StmtIteratorBase(s) {}
00084   StmtIteratorImpl(Decl **dgi, Decl **dge) : StmtIteratorBase(dgi, dge) {}
00085   StmtIteratorImpl(const VariableArrayType *t) : StmtIteratorBase(t) {}
00086 
00087   DERIVED& operator++() {
00088     if (inStmt())
00089       ++stmt;
00090     else if (getVAPtr())
00091       NextVA();
00092     else
00093       NextDecl();
00094 
00095     return static_cast<DERIVED&>(*this);
00096   }
00097 
00098   DERIVED operator++(int) {
00099     DERIVED tmp = static_cast<DERIVED&>(*this);
00100     operator++();
00101     return tmp;
00102   }
00103 
00104   bool operator==(const DERIVED& RHS) const {
00105     return stmt == RHS.stmt && DGI == RHS.DGI && RawVAPtr == RHS.RawVAPtr;
00106   }
00107 
00108   bool operator!=(const DERIVED& RHS) const {
00109     return stmt != RHS.stmt || DGI != RHS.DGI || RawVAPtr != RHS.RawVAPtr;
00110   }
00111 
00112   REFERENCE operator*() const {
00113     return inStmt() ? *stmt : GetDeclExpr();
00114   }
00115 
00116   REFERENCE operator->() const { return operator*(); }
00117 };
00118 
00119 struct StmtIterator : public StmtIteratorImpl<StmtIterator,Stmt*&> {
00120   explicit StmtIterator() : StmtIteratorImpl<StmtIterator,Stmt*&>() {}
00121 
00122   StmtIterator(Stmt** S) : StmtIteratorImpl<StmtIterator,Stmt*&>(S) {}
00123 
00124   StmtIterator(Decl** dgi, Decl** dge)
00125    : StmtIteratorImpl<StmtIterator,Stmt*&>(dgi, dge) {}
00126 
00127   StmtIterator(const VariableArrayType *t)
00128     : StmtIteratorImpl<StmtIterator,Stmt*&>(t) {}
00129 };
00130 
00131 struct ConstStmtIterator : public StmtIteratorImpl<ConstStmtIterator,
00132                                                    const Stmt*> {
00133   explicit ConstStmtIterator() :
00134     StmtIteratorImpl<ConstStmtIterator,const Stmt*>() {}
00135 
00136   ConstStmtIterator(const StmtIterator& RHS) :
00137     StmtIteratorImpl<ConstStmtIterator,const Stmt*>(RHS) {}
00138 };
00139 
00140 /// A range of statement iterators.
00141 ///
00142 /// This class provides some extra functionality beyond std::pair
00143 /// in order to allow the following idiom:
00144 ///   for (StmtRange range = stmt->children(); range; ++range)
00145 struct StmtRange : std::pair<StmtIterator,StmtIterator> {
00146   StmtRange() {}
00147   StmtRange(const StmtIterator &begin, const StmtIterator &end)
00148     : std::pair<StmtIterator,StmtIterator>(begin, end) {}
00149 
00150   bool empty() const { return first == second; }
00151   LLVM_EXPLICIT operator bool() const { return !empty(); }
00152 
00153   Stmt *operator->() const { return first.operator->(); }
00154   Stmt *&operator*() const { return first.operator*(); }
00155 
00156   StmtRange &operator++() {
00157     assert(!empty() && "incrementing on empty range");
00158     ++first;
00159     return *this;
00160   }
00161 
00162   StmtRange operator++(int) {
00163     assert(!empty() && "incrementing on empty range");
00164     StmtRange copy = *this;
00165     ++first;
00166     return copy;
00167   }
00168 
00169   friend const StmtIterator &begin(const StmtRange &range) {
00170     return range.first;
00171   }
00172   friend const StmtIterator &end(const StmtRange &range) {
00173     return range.second;
00174   }
00175 };
00176 
00177 /// A range of const statement iterators.
00178 ///
00179 /// This class provides some extra functionality beyond std::pair
00180 /// in order to allow the following idiom:
00181 ///   for (ConstStmtRange range = stmt->children(); range; ++range)
00182 struct ConstStmtRange : std::pair<ConstStmtIterator,ConstStmtIterator> {
00183   ConstStmtRange() {}
00184   ConstStmtRange(const ConstStmtIterator &begin,
00185                  const ConstStmtIterator &end)
00186     : std::pair<ConstStmtIterator,ConstStmtIterator>(begin, end) {}
00187   ConstStmtRange(const StmtRange &range)
00188     : std::pair<ConstStmtIterator,ConstStmtIterator>(range.first, range.second)
00189   {}
00190   ConstStmtRange(const StmtIterator &begin, const StmtIterator &end)
00191     : std::pair<ConstStmtIterator,ConstStmtIterator>(begin, end) {}
00192 
00193   bool empty() const { return first == second; }
00194   LLVM_EXPLICIT operator bool() const { return !empty(); }
00195 
00196   const Stmt *operator->() const { return first.operator->(); }
00197   const Stmt *operator*() const { return first.operator*(); }
00198 
00199   ConstStmtRange &operator++() {
00200     assert(!empty() && "incrementing on empty range");
00201     ++first;
00202     return *this;
00203   }
00204 
00205   ConstStmtRange operator++(int) {
00206     assert(!empty() && "incrementing on empty range");
00207     ConstStmtRange copy = *this;
00208     ++first;
00209     return copy;
00210   }
00211 
00212   friend const ConstStmtIterator &begin(const ConstStmtRange &range) {
00213     return range.first;
00214   }
00215   friend const ConstStmtIterator &end(const ConstStmtRange &range) {
00216     return range.second;
00217   }
00218 };
00219 
00220 } // end namespace clang
00221 
00222 #endif