1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | #ifndef LLVM_CLANG_AST_ATTRITERATOR_H |
14 | #define LLVM_CLANG_AST_ATTRITERATOR_H |
15 | |
16 | #include "clang/Basic/LLVM.h" |
17 | #include "llvm/ADT/SmallVector.h" |
18 | #include "llvm/Support/Casting.h" |
19 | #include <cassert> |
20 | #include <cstddef> |
21 | #include <iterator> |
22 | |
23 | namespace clang { |
24 | |
25 | class ASTContext; |
26 | class Attr; |
27 | |
28 | |
29 | using AttrVec = SmallVector<Attr *, 4>; |
30 | |
31 | |
32 | |
33 | template <typename SpecificAttr, typename Container = AttrVec> |
34 | class specific_attr_iterator { |
35 | using Iterator = typename Container::const_iterator; |
36 | |
37 | |
38 | |
39 | |
40 | |
41 | |
42 | |
43 | |
44 | mutable Iterator Current; |
45 | |
46 | void AdvanceToNext() const { |
47 | while (!isa<SpecificAttr>(*Current)) |
48 | ++Current; |
49 | } |
50 | |
51 | void AdvanceToNext(Iterator I) const { |
52 | while (Current != I && !isa<SpecificAttr>(*Current)) |
53 | ++Current; |
54 | } |
55 | |
56 | public: |
57 | using value_type = SpecificAttr *; |
58 | using reference = SpecificAttr *; |
59 | using pointer = SpecificAttr *; |
60 | using iterator_category = std::forward_iterator_tag; |
61 | using difference_type = std::ptrdiff_t; |
62 | |
63 | specific_attr_iterator() = default; |
64 | explicit specific_attr_iterator(Iterator i) : Current(i) {} |
65 | |
66 | reference operator*() const { |
67 | AdvanceToNext(); |
68 | return cast<SpecificAttr>(*Current); |
69 | } |
70 | pointer operator->() const { |
71 | AdvanceToNext(); |
72 | return cast<SpecificAttr>(*Current); |
73 | } |
74 | |
75 | specific_attr_iterator& operator++() { |
76 | ++Current; |
77 | return *this; |
78 | } |
79 | specific_attr_iterator operator++(int) { |
80 | specific_attr_iterator Tmp(*this); |
81 | ++(*this); |
82 | return Tmp; |
83 | } |
84 | |
85 | friend bool operator==(specific_attr_iterator Left, |
86 | specific_attr_iterator Right) { |
87 | assert((Left.Current == nullptr) == (Right.Current == nullptr)); |
88 | if (Left.Current < Right.Current) |
89 | Left.AdvanceToNext(Right.Current); |
90 | else |
91 | Right.AdvanceToNext(Left.Current); |
92 | return Left.Current == Right.Current; |
93 | } |
94 | friend bool operator!=(specific_attr_iterator Left, |
95 | specific_attr_iterator Right) { |
96 | return !(Left == Right); |
97 | } |
98 | }; |
99 | |
100 | template <typename SpecificAttr, typename Container> |
101 | inline specific_attr_iterator<SpecificAttr, Container> |
102 | specific_attr_begin(const Container& container) { |
103 | return specific_attr_iterator<SpecificAttr, Container>(container.begin()); |
104 | } |
105 | template <typename SpecificAttr, typename Container> |
106 | inline specific_attr_iterator<SpecificAttr, Container> |
107 | specific_attr_end(const Container& container) { |
108 | return specific_attr_iterator<SpecificAttr, Container>(container.end()); |
109 | } |
110 | |
111 | template <typename SpecificAttr, typename Container> |
112 | inline bool hasSpecificAttr(const Container& container) { |
113 | return specific_attr_begin<SpecificAttr>(container) != |
114 | specific_attr_end<SpecificAttr>(container); |
115 | } |
116 | template <typename SpecificAttr, typename Container> |
117 | inline SpecificAttr *getSpecificAttr(const Container& container) { |
118 | specific_attr_iterator<SpecificAttr, Container> i = |
119 | specific_attr_begin<SpecificAttr>(container); |
120 | if (i != specific_attr_end<SpecificAttr>(container)) |
121 | return *i; |
122 | else |
123 | return nullptr; |
124 | } |
125 | |
126 | } |
127 | |
128 | #endif |
129 | |