xref: /aosp_15_r20/external/clang/include/clang/AST/AttrIterator.h (revision 67e74705e28f6214e480b399dd47ea732279e315)
1*67e74705SXin Li //===--- AttrIterator.h - Classes for attribute iteration -------*- C++ -*-===//
2*67e74705SXin Li //
3*67e74705SXin Li //                     The LLVM Compiler Infrastructure
4*67e74705SXin Li //
5*67e74705SXin Li // This file is distributed under the University of Illinois Open Source
6*67e74705SXin Li // License. See LICENSE.TXT for details.
7*67e74705SXin Li //
8*67e74705SXin Li //===----------------------------------------------------------------------===//
9*67e74705SXin Li //
10*67e74705SXin Li //  This file defines the Attr vector and specific_attr_iterator interfaces.
11*67e74705SXin Li //
12*67e74705SXin Li //===----------------------------------------------------------------------===//
13*67e74705SXin Li 
14*67e74705SXin Li #ifndef LLVM_CLANG_AST_ATTRITERATOR_H
15*67e74705SXin Li #define LLVM_CLANG_AST_ATTRITERATOR_H
16*67e74705SXin Li 
17*67e74705SXin Li #include "clang/Basic/LLVM.h"
18*67e74705SXin Li #include <iterator>
19*67e74705SXin Li 
20*67e74705SXin Li namespace clang {
21*67e74705SXin Li   class ASTContext;
22*67e74705SXin Li   class Attr;
23*67e74705SXin Li }
24*67e74705SXin Li 
25*67e74705SXin Li // Defined in ASTContext.h
26*67e74705SXin Li void *operator new(size_t Bytes, const clang::ASTContext &C,
27*67e74705SXin Li                    size_t Alignment = 8);
28*67e74705SXin Li // FIXME: Being forced to not have a default argument here due to redeclaration
29*67e74705SXin Li //        rules on default arguments sucks
30*67e74705SXin Li void *operator new[](size_t Bytes, const clang::ASTContext &C,
31*67e74705SXin Li                      size_t Alignment);
32*67e74705SXin Li 
33*67e74705SXin Li // It is good practice to pair new/delete operators.  Also, MSVC gives many
34*67e74705SXin Li // warnings if a matching delete overload is not declared, even though the
35*67e74705SXin Li // throw() spec guarantees it will not be implicitly called.
36*67e74705SXin Li void operator delete(void *Ptr, const clang::ASTContext &C, size_t);
37*67e74705SXin Li void operator delete[](void *Ptr, const clang::ASTContext &C, size_t);
38*67e74705SXin Li 
39*67e74705SXin Li namespace clang {
40*67e74705SXin Li 
41*67e74705SXin Li /// AttrVec - A vector of Attr, which is how they are stored on the AST.
42*67e74705SXin Li typedef SmallVector<Attr*, 2> AttrVec;
43*67e74705SXin Li typedef SmallVector<const Attr*, 2> ConstAttrVec;
44*67e74705SXin Li 
45*67e74705SXin Li /// specific_attr_iterator - Iterates over a subrange of an AttrVec, only
46*67e74705SXin Li /// providing attributes that are of a specific type.
47*67e74705SXin Li template <typename SpecificAttr, typename Container = AttrVec>
48*67e74705SXin Li class specific_attr_iterator {
49*67e74705SXin Li   typedef typename Container::const_iterator Iterator;
50*67e74705SXin Li 
51*67e74705SXin Li   /// Current - The current, underlying iterator.
52*67e74705SXin Li   /// In order to ensure we don't dereference an invalid iterator unless
53*67e74705SXin Li   /// specifically requested, we don't necessarily advance this all the
54*67e74705SXin Li   /// way. Instead, we advance it when an operation is requested; if the
55*67e74705SXin Li   /// operation is acting on what should be a past-the-end iterator,
56*67e74705SXin Li   /// then we offer no guarantees, but this way we do not dereference a
57*67e74705SXin Li   /// past-the-end iterator when we move to a past-the-end position.
58*67e74705SXin Li   mutable Iterator Current;
59*67e74705SXin Li 
AdvanceToNext()60*67e74705SXin Li   void AdvanceToNext() const {
61*67e74705SXin Li     while (!isa<SpecificAttr>(*Current))
62*67e74705SXin Li       ++Current;
63*67e74705SXin Li   }
64*67e74705SXin Li 
AdvanceToNext(Iterator I)65*67e74705SXin Li   void AdvanceToNext(Iterator I) const {
66*67e74705SXin Li     while (Current != I && !isa<SpecificAttr>(*Current))
67*67e74705SXin Li       ++Current;
68*67e74705SXin Li   }
69*67e74705SXin Li 
70*67e74705SXin Li public:
71*67e74705SXin Li   typedef SpecificAttr*             value_type;
72*67e74705SXin Li   typedef SpecificAttr*             reference;
73*67e74705SXin Li   typedef SpecificAttr*             pointer;
74*67e74705SXin Li   typedef std::forward_iterator_tag iterator_category;
75*67e74705SXin Li   typedef std::ptrdiff_t            difference_type;
76*67e74705SXin Li 
specific_attr_iterator()77*67e74705SXin Li   specific_attr_iterator() : Current() { }
specific_attr_iterator(Iterator i)78*67e74705SXin Li   explicit specific_attr_iterator(Iterator i) : Current(i) { }
79*67e74705SXin Li 
80*67e74705SXin Li   reference operator*() const {
81*67e74705SXin Li     AdvanceToNext();
82*67e74705SXin Li     return cast<SpecificAttr>(*Current);
83*67e74705SXin Li   }
84*67e74705SXin Li   pointer operator->() const {
85*67e74705SXin Li     AdvanceToNext();
86*67e74705SXin Li     return cast<SpecificAttr>(*Current);
87*67e74705SXin Li   }
88*67e74705SXin Li 
89*67e74705SXin Li   specific_attr_iterator& operator++() {
90*67e74705SXin Li     ++Current;
91*67e74705SXin Li     return *this;
92*67e74705SXin Li   }
93*67e74705SXin Li   specific_attr_iterator operator++(int) {
94*67e74705SXin Li     specific_attr_iterator Tmp(*this);
95*67e74705SXin Li     ++(*this);
96*67e74705SXin Li     return Tmp;
97*67e74705SXin Li   }
98*67e74705SXin Li 
99*67e74705SXin Li   friend bool operator==(specific_attr_iterator Left,
100*67e74705SXin Li                          specific_attr_iterator Right) {
101*67e74705SXin Li     assert((Left.Current == nullptr) == (Right.Current == nullptr));
102*67e74705SXin Li     if (Left.Current < Right.Current)
103*67e74705SXin Li       Left.AdvanceToNext(Right.Current);
104*67e74705SXin Li     else
105*67e74705SXin Li       Right.AdvanceToNext(Left.Current);
106*67e74705SXin Li     return Left.Current == Right.Current;
107*67e74705SXin Li   }
108*67e74705SXin Li   friend bool operator!=(specific_attr_iterator Left,
109*67e74705SXin Li                          specific_attr_iterator Right) {
110*67e74705SXin Li     return !(Left == Right);
111*67e74705SXin Li   }
112*67e74705SXin Li };
113*67e74705SXin Li 
114*67e74705SXin Li template <typename SpecificAttr, typename Container>
115*67e74705SXin Li inline specific_attr_iterator<SpecificAttr, Container>
specific_attr_begin(const Container & container)116*67e74705SXin Li           specific_attr_begin(const Container& container) {
117*67e74705SXin Li   return specific_attr_iterator<SpecificAttr, Container>(container.begin());
118*67e74705SXin Li }
119*67e74705SXin Li template <typename SpecificAttr, typename Container>
120*67e74705SXin Li inline specific_attr_iterator<SpecificAttr, Container>
specific_attr_end(const Container & container)121*67e74705SXin Li           specific_attr_end(const Container& container) {
122*67e74705SXin Li   return specific_attr_iterator<SpecificAttr, Container>(container.end());
123*67e74705SXin Li }
124*67e74705SXin Li 
125*67e74705SXin Li template <typename SpecificAttr, typename Container>
hasSpecificAttr(const Container & container)126*67e74705SXin Li inline bool hasSpecificAttr(const Container& container) {
127*67e74705SXin Li   return specific_attr_begin<SpecificAttr>(container) !=
128*67e74705SXin Li           specific_attr_end<SpecificAttr>(container);
129*67e74705SXin Li }
130*67e74705SXin Li template <typename SpecificAttr, typename Container>
getSpecificAttr(const Container & container)131*67e74705SXin Li inline SpecificAttr *getSpecificAttr(const Container& container) {
132*67e74705SXin Li   specific_attr_iterator<SpecificAttr, Container> i =
133*67e74705SXin Li       specific_attr_begin<SpecificAttr>(container);
134*67e74705SXin Li   if (i != specific_attr_end<SpecificAttr>(container))
135*67e74705SXin Li     return *i;
136*67e74705SXin Li   else
137*67e74705SXin Li     return nullptr;
138*67e74705SXin Li }
139*67e74705SXin Li 
140*67e74705SXin Li }  // end namespace clang
141*67e74705SXin Li 
142*67e74705SXin Li #endif
143