clang API Documentation

AttrIterator.h
Go to the documentation of this file.
00001 //===--- AttrIterator.h - Classes for attribute iteration -------*- 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 Attr vector and specific_attr_iterator interfaces.
00011 //
00012 //===----------------------------------------------------------------------===//
00013 
00014 #ifndef LLVM_CLANG_AST_ATTRITERATOR_H
00015 #define LLVM_CLANG_AST_ATTRITERATOR_H
00016 
00017 #include "clang/Basic/LLVM.h"
00018 #include <iterator>
00019 
00020 namespace clang {
00021   class ASTContext;
00022   class Attr;
00023 }
00024 
00025 // Defined in ASTContext.h
00026 void *operator new(size_t Bytes, const clang::ASTContext &C,
00027                    size_t Alignment = 16);
00028 // FIXME: Being forced to not have a default argument here due to redeclaration
00029 //        rules on default arguments sucks
00030 void *operator new[](size_t Bytes, const clang::ASTContext &C,
00031                      size_t Alignment);
00032 
00033 // It is good practice to pair new/delete operators.  Also, MSVC gives many
00034 // warnings if a matching delete overload is not declared, even though the
00035 // throw() spec guarantees it will not be implicitly called.
00036 void operator delete(void *Ptr, const clang::ASTContext &C, size_t);
00037 void operator delete[](void *Ptr, const clang::ASTContext &C, size_t);
00038 
00039 namespace clang {
00040 
00041 /// AttrVec - A vector of Attr, which is how they are stored on the AST.
00042 typedef SmallVector<Attr*, 2> AttrVec;
00043 typedef SmallVector<const Attr*, 2> ConstAttrVec;
00044 
00045 /// specific_attr_iterator - Iterates over a subrange of an AttrVec, only
00046 /// providing attributes that are of a specific type.
00047 template <typename SpecificAttr, typename Container = AttrVec>
00048 class specific_attr_iterator {
00049   typedef typename Container::const_iterator Iterator;
00050 
00051   /// Current - The current, underlying iterator.
00052   /// In order to ensure we don't dereference an invalid iterator unless
00053   /// specifically requested, we don't necessarily advance this all the
00054   /// way. Instead, we advance it when an operation is requested; if the
00055   /// operation is acting on what should be a past-the-end iterator,
00056   /// then we offer no guarantees, but this way we do not dereference a
00057   /// past-the-end iterator when we move to a past-the-end position.
00058   mutable Iterator Current;
00059 
00060   void AdvanceToNext() const {
00061     while (!isa<SpecificAttr>(*Current))
00062       ++Current;
00063   }
00064 
00065   void AdvanceToNext(Iterator I) const {
00066     while (Current != I && !isa<SpecificAttr>(*Current))
00067       ++Current;
00068   }
00069 
00070 public:
00071   typedef SpecificAttr*             value_type;
00072   typedef SpecificAttr*             reference;
00073   typedef SpecificAttr*             pointer;
00074   typedef std::forward_iterator_tag iterator_category;
00075   typedef std::ptrdiff_t            difference_type;
00076 
00077   specific_attr_iterator() : Current() { }
00078   explicit specific_attr_iterator(Iterator i) : Current(i) { }
00079 
00080   reference operator*() const {
00081     AdvanceToNext();
00082     return cast<SpecificAttr>(*Current);
00083   }
00084   pointer operator->() const {
00085     AdvanceToNext();
00086     return cast<SpecificAttr>(*Current);
00087   }
00088 
00089   specific_attr_iterator& operator++() {
00090     ++Current;
00091     return *this;
00092   }
00093   specific_attr_iterator operator++(int) {
00094     specific_attr_iterator Tmp(*this);
00095     ++(*this);
00096     return Tmp;
00097   }
00098 
00099   friend bool operator==(specific_attr_iterator Left,
00100                          specific_attr_iterator Right) {
00101     assert((Left.Current == nullptr) == (Right.Current == nullptr));
00102     if (Left.Current < Right.Current)
00103       Left.AdvanceToNext(Right.Current); 
00104     else
00105       Right.AdvanceToNext(Left.Current);
00106     return Left.Current == Right.Current;
00107   }
00108   friend bool operator!=(specific_attr_iterator Left,
00109                          specific_attr_iterator Right) {
00110     return !(Left == Right);
00111   }
00112 };
00113 
00114 template <typename SpecificAttr, typename Container>
00115 inline specific_attr_iterator<SpecificAttr, Container>
00116           specific_attr_begin(const Container& container) {
00117   return specific_attr_iterator<SpecificAttr, Container>(container.begin());
00118 }
00119 template <typename SpecificAttr, typename Container>
00120 inline specific_attr_iterator<SpecificAttr, Container>
00121           specific_attr_end(const Container& container) {
00122   return specific_attr_iterator<SpecificAttr, Container>(container.end());
00123 }
00124 
00125 template <typename SpecificAttr, typename Container>
00126 inline bool hasSpecificAttr(const Container& container) {
00127   return specific_attr_begin<SpecificAttr>(container) !=
00128           specific_attr_end<SpecificAttr>(container);
00129 }
00130 template <typename SpecificAttr, typename Container>
00131 inline SpecificAttr *getSpecificAttr(const Container& container) {
00132   specific_attr_iterator<SpecificAttr, Container> i =
00133       specific_attr_begin<SpecificAttr>(container);
00134   if (i != specific_attr_end<SpecificAttr>(container))
00135     return *i;
00136   else
00137     return nullptr;
00138 }
00139 
00140 }  // end namespace clang
00141 
00142 #endif