/src/hermes/external/llvh/include/llvh/ADT/iterator.h
Line | Count | Source |
1 | | //===- iterator.h - Utilities for using and defining iterators --*- C++ -*-===// |
2 | | // |
3 | | // The LLVM Compiler Infrastructure |
4 | | // |
5 | | // This file is distributed under the University of Illinois Open Source |
6 | | // License. See LICENSE.TXT for details. |
7 | | // |
8 | | //===----------------------------------------------------------------------===// |
9 | | |
10 | | #ifndef LLVM_ADT_ITERATOR_H |
11 | | #define LLVM_ADT_ITERATOR_H |
12 | | |
13 | | #include "llvh/ADT/iterator_range.h" |
14 | | #include <algorithm> |
15 | | #include <cstddef> |
16 | | #include <iterator> |
17 | | #include <type_traits> |
18 | | #include <utility> |
19 | | |
20 | | namespace llvh { |
21 | | |
22 | | /// CRTP base class which implements the entire standard iterator facade |
23 | | /// in terms of a minimal subset of the interface. |
24 | | /// |
25 | | /// Use this when it is reasonable to implement most of the iterator |
26 | | /// functionality in terms of a core subset. If you need special behavior or |
27 | | /// there are performance implications for this, you may want to override the |
28 | | /// relevant members instead. |
29 | | /// |
30 | | /// Note, one abstraction that this does *not* provide is implementing |
31 | | /// subtraction in terms of addition by negating the difference. Negation isn't |
32 | | /// always information preserving, and I can see very reasonable iterator |
33 | | /// designs where this doesn't work well. It doesn't really force much added |
34 | | /// boilerplate anyways. |
35 | | /// |
36 | | /// Another abstraction that this doesn't provide is implementing increment in |
37 | | /// terms of addition of one. These aren't equivalent for all iterator |
38 | | /// categories, and respecting that adds a lot of complexity for little gain. |
39 | | /// |
40 | | /// Classes wishing to use `iterator_facade_base` should implement the following |
41 | | /// methods: |
42 | | /// |
43 | | /// Forward Iterators: |
44 | | /// (All of the following methods) |
45 | | /// - DerivedT &operator=(const DerivedT &R); |
46 | | /// - bool operator==(const DerivedT &R) const; |
47 | | /// - const T &operator*() const; |
48 | | /// - T &operator*(); |
49 | | /// - DerivedT &operator++(); |
50 | | /// |
51 | | /// Bidirectional Iterators: |
52 | | /// (All methods of forward iterators, plus the following) |
53 | | /// - DerivedT &operator--(); |
54 | | /// |
55 | | /// Random-access Iterators: |
56 | | /// (All methods of bidirectional iterators excluding the following) |
57 | | /// - DerivedT &operator++(); |
58 | | /// - DerivedT &operator--(); |
59 | | /// (and plus the following) |
60 | | /// - bool operator<(const DerivedT &RHS) const; |
61 | | /// - DifferenceTypeT operator-(const DerivedT &R) const; |
62 | | /// - DerivedT &operator+=(DifferenceTypeT N); |
63 | | /// - DerivedT &operator-=(DifferenceTypeT N); |
64 | | /// |
65 | | template <typename DerivedT, typename IteratorCategoryT, typename T, |
66 | | typename DifferenceTypeT = std::ptrdiff_t, typename PointerT = T *, |
67 | | typename ReferenceT = T &> |
68 | | class iterator_facade_base { |
69 | | public: |
70 | | using iterator_category = IteratorCategoryT; |
71 | | using value_type = T; |
72 | | using difference_type = DifferenceTypeT; |
73 | | using pointer = PointerT; |
74 | | using reference = ReferenceT; |
75 | | |
76 | | protected: |
77 | | enum { |
78 | | IsRandomAccess = std::is_base_of<std::random_access_iterator_tag, |
79 | | IteratorCategoryT>::value, |
80 | | IsBidirectional = std::is_base_of<std::bidirectional_iterator_tag, |
81 | | IteratorCategoryT>::value, |
82 | | }; |
83 | | |
84 | | /// A proxy object for computing a reference via indirecting a copy of an |
85 | | /// iterator. This is used in APIs which need to produce a reference via |
86 | | /// indirection but for which the iterator object might be a temporary. The |
87 | | /// proxy preserves the iterator internally and exposes the indirected |
88 | | /// reference via a conversion operator. |
89 | | class ReferenceProxy { |
90 | | friend iterator_facade_base; |
91 | | |
92 | | DerivedT I; |
93 | | |
94 | | ReferenceProxy(DerivedT I) : I(std::move(I)) {} |
95 | | |
96 | | public: |
97 | | operator ReferenceT() const { return *I; } |
98 | | }; |
99 | | |
100 | | public: |
101 | | DerivedT operator+(DifferenceTypeT n) const { |
102 | | static_assert(std::is_base_of<iterator_facade_base, DerivedT>::value, |
103 | | "Must pass the derived type to this template!"); |
104 | | static_assert( |
105 | | IsRandomAccess, |
106 | | "The '+' operator is only defined for random access iterators."); |
107 | | DerivedT tmp = *static_cast<const DerivedT *>(this); |
108 | | tmp += n; |
109 | | return tmp; |
110 | | } |
111 | | friend DerivedT operator+(DifferenceTypeT n, const DerivedT &i) { |
112 | | static_assert( |
113 | | IsRandomAccess, |
114 | | "The '+' operator is only defined for random access iterators."); |
115 | | return i + n; |
116 | | } |
117 | | DerivedT operator-(DifferenceTypeT n) const { |
118 | | static_assert( |
119 | | IsRandomAccess, |
120 | | "The '-' operator is only defined for random access iterators."); |
121 | | DerivedT tmp = *static_cast<const DerivedT *>(this); |
122 | | tmp -= n; |
123 | | return tmp; |
124 | | } |
125 | | |
126 | 411k | DerivedT &operator++() { |
127 | 411k | static_assert(std::is_base_of<iterator_facade_base, DerivedT>::value, |
128 | 411k | "Must pass the derived type to this template!"); |
129 | 411k | return static_cast<DerivedT *>(this)->operator+=(1); |
130 | 411k | } llvh::iterator_facade_base<llvh::SuccIterator<hermes::TerminatorInst const, hermes::BasicBlock const>, std::__1::random_access_iterator_tag, hermes::BasicBlock const, int, hermes::BasicBlock const*, hermes::BasicBlock const*>::operator++() Line | Count | Source | 126 | 81.3k | DerivedT &operator++() { | 127 | 81.3k | static_assert(std::is_base_of<iterator_facade_base, DerivedT>::value, | 128 | 81.3k | "Must pass the derived type to this template!"); | 129 | 81.3k | return static_cast<DerivedT *>(this)->operator+=(1); | 130 | 81.3k | } |
llvh::iterator_facade_base<llvh::SuccIterator<hermes::TerminatorInst, hermes::BasicBlock>, std::__1::random_access_iterator_tag, hermes::BasicBlock, int, hermes::BasicBlock*, hermes::BasicBlock*>::operator++() Line | Count | Source | 126 | 330k | DerivedT &operator++() { | 127 | 330k | static_assert(std::is_base_of<iterator_facade_base, DerivedT>::value, | 128 | 330k | "Must pass the derived type to this template!"); | 129 | 330k | return static_cast<DerivedT *>(this)->operator+=(1); | 130 | 330k | } |
|
131 | 255k | DerivedT operator++(int) { |
132 | 255k | DerivedT tmp = *static_cast<DerivedT *>(this); |
133 | 255k | ++*static_cast<DerivedT *>(this); |
134 | 255k | return tmp; |
135 | 255k | } |
136 | 22.9k | DerivedT &operator--() { |
137 | 22.9k | static_assert( |
138 | 22.9k | IsBidirectional, |
139 | 22.9k | "The decrement operator is only defined for bidirectional iterators."); |
140 | 22.9k | return static_cast<DerivedT *>(this)->operator-=(1); |
141 | 22.9k | } |
142 | | DerivedT operator--(int) { |
143 | | static_assert( |
144 | | IsBidirectional, |
145 | | "The decrement operator is only defined for bidirectional iterators."); |
146 | | DerivedT tmp = *static_cast<DerivedT *>(this); |
147 | | --*static_cast<DerivedT *>(this); |
148 | | return tmp; |
149 | | } |
150 | | |
151 | 6.33M | bool operator!=(const DerivedT &RHS) const { |
152 | 6.33M | return !static_cast<const DerivedT *>(this)->operator==(RHS); |
153 | 6.33M | } Unexecuted instantiation: llvh::iterator_facade_base<llvh::SmallSetIterator<unsigned int, 8u, std::__1::less<unsigned int> >, std::__1::forward_iterator_tag, unsigned int, long, unsigned int*, unsigned int&>::operator!=(llvh::SmallSetIterator<unsigned int, 8u, std::__1::less<unsigned int> > const&) const llvh::iterator_facade_base<hermes::vm::AlignedHeapSegment::HeapCellIterator, std::__1::forward_iterator_tag, hermes::vm::GCCell*, long, hermes::vm::GCCell**, hermes::vm::GCCell*&>::operator!=(hermes::vm::AlignedHeapSegment::HeapCellIterator const&) const Line | Count | Source | 151 | 5.44M | bool operator!=(const DerivedT &RHS) const { | 152 | 5.44M | return !static_cast<const DerivedT *>(this)->operator==(RHS); | 153 | 5.44M | } |
llvh::iterator_facade_base<llvh::SuccIterator<hermes::TerminatorInst const, hermes::BasicBlock const>, std::__1::random_access_iterator_tag, hermes::BasicBlock const, int, hermes::BasicBlock const*, hermes::BasicBlock const*>::operator!=(llvh::SuccIterator<hermes::TerminatorInst const, hermes::BasicBlock const> const&) const Line | Count | Source | 151 | 177k | bool operator!=(const DerivedT &RHS) const { | 152 | 177k | return !static_cast<const DerivedT *>(this)->operator==(RHS); | 153 | 177k | } |
llvh::iterator_facade_base<llvh::SuccIterator<hermes::TerminatorInst, hermes::BasicBlock>, std::__1::random_access_iterator_tag, hermes::BasicBlock, int, hermes::BasicBlock*, hermes::BasicBlock*>::operator!=(llvh::SuccIterator<hermes::TerminatorInst, hermes::BasicBlock> const&) const Line | Count | Source | 151 | 716k | bool operator!=(const DerivedT &RHS) const { | 152 | 716k | return !static_cast<const DerivedT *>(this)->operator==(RHS); | 153 | 716k | } |
Unexecuted instantiation: llvh::iterator_facade_base<llvh::sys::path::const_iterator, std::__1::input_iterator_tag, llvh::StringRef const, long, llvh::StringRef const*, llvh::StringRef const&>::operator!=(llvh::sys::path::const_iterator const&) const |
154 | | |
155 | | bool operator>(const DerivedT &RHS) const { |
156 | | static_assert( |
157 | | IsRandomAccess, |
158 | | "Relational operators are only defined for random access iterators."); |
159 | | return !static_cast<const DerivedT *>(this)->operator<(RHS) && |
160 | | !static_cast<const DerivedT *>(this)->operator==(RHS); |
161 | | } |
162 | | bool operator<=(const DerivedT &RHS) const { |
163 | | static_assert( |
164 | | IsRandomAccess, |
165 | | "Relational operators are only defined for random access iterators."); |
166 | | return !static_cast<const DerivedT *>(this)->operator>(RHS); |
167 | | } |
168 | | bool operator>=(const DerivedT &RHS) const { |
169 | | static_assert( |
170 | | IsRandomAccess, |
171 | | "Relational operators are only defined for random access iterators."); |
172 | | return !static_cast<const DerivedT *>(this)->operator<(RHS); |
173 | | } |
174 | | |
175 | 0 | PointerT operator->() { return &static_cast<DerivedT *>(this)->operator*(); }Unexecuted instantiation: ESTreeIRGen-expr.cpp:llvh::iterator_facade_base<llvh::StringMapIterator<hermes::irgen::ESTreeIRGen::genObjectExpr(hermes::ESTree::ObjectExpressionNode*)::PropertyValue>, std::__1::forward_iterator_tag, llvh::StringMapEntry<hermes::irgen::ESTreeIRGen::genObjectExpr(hermes::ESTree::ObjectExpressionNode*)::PropertyValue>, long, llvh::StringMapEntry<hermes::irgen::ESTreeIRGen::genObjectExpr(hermes::ESTree::ObjectExpressionNode*)::PropertyValue>*, llvh::StringMapEntry<hermes::irgen::ESTreeIRGen::genObjectExpr(hermes::ESTree::ObjectExpressionNode*)::PropertyValue>&>::operator->() Unexecuted instantiation: llvh::iterator_facade_base<llvh::StringMapIterator<llvh::SMRange>, std::__1::forward_iterator_tag, llvh::StringMapEntry<llvh::SMRange>, long, llvh::StringMapEntry<llvh::SMRange>*, llvh::StringMapEntry<llvh::SMRange>&>::operator->() Unexecuted instantiation: llvh::iterator_facade_base<llvh::sys::path::const_iterator, std::__1::input_iterator_tag, llvh::StringRef const, long, llvh::StringRef const*, llvh::StringRef const&>::operator->() Unexecuted instantiation: llvh::iterator_facade_base<llvh::StringMapIterator<std::__1::pair<llvh::TimerGroup*, llvh::StringMap<llvh::Timer, llvh::MallocAllocator> > >, std::__1::forward_iterator_tag, llvh::StringMapEntry<std::__1::pair<llvh::TimerGroup*, llvh::StringMap<llvh::Timer, llvh::MallocAllocator> > >, long, llvh::StringMapEntry<std::__1::pair<llvh::TimerGroup*, llvh::StringMap<llvh::Timer, llvh::MallocAllocator> > >*, llvh::StringMapEntry<std::__1::pair<llvh::TimerGroup*, llvh::StringMap<llvh::Timer, llvh::MallocAllocator> > >&>::operator->() Unexecuted instantiation: llvh::iterator_facade_base<llvh::StringMapIterator<llvh::Timer>, std::__1::forward_iterator_tag, llvh::StringMapEntry<llvh::Timer>, long, llvh::StringMapEntry<llvh::Timer>*, llvh::StringMapEntry<llvh::Timer>&>::operator->() Unexecuted instantiation: llvh::iterator_facade_base<llvh::StringMapIterator<llvh::cl::Option*>, std::__1::forward_iterator_tag, llvh::StringMapEntry<llvh::cl::Option*>, long, llvh::StringMapEntry<llvh::cl::Option*>*, llvh::StringMapEntry<llvh::cl::Option*>&>::operator->() Unexecuted instantiation: llvh::iterator_facade_base<llvh::StringMapConstIterator<llvh::cl::Option*>, std::__1::forward_iterator_tag, llvh::StringMapEntry<llvh::cl::Option*> const, long, llvh::StringMapEntry<llvh::cl::Option*> const*, llvh::StringMapEntry<llvh::cl::Option*> const&>::operator->() Unexecuted instantiation: llvh::iterator_facade_base<llvh::StringMapIterator<bool>, std::__1::forward_iterator_tag, llvh::StringMapEntry<bool>, long, llvh::StringMapEntry<bool>*, llvh::StringMapEntry<bool>&>::operator->() |
176 | | PointerT operator->() const { |
177 | | return &static_cast<const DerivedT *>(this)->operator*(); |
178 | | } |
179 | | ReferenceProxy operator[](DifferenceTypeT n) { |
180 | | static_assert(IsRandomAccess, |
181 | | "Subscripting is only defined for random access iterators."); |
182 | | return ReferenceProxy(static_cast<DerivedT *>(this)->operator+(n)); |
183 | | } |
184 | | ReferenceProxy operator[](DifferenceTypeT n) const { |
185 | | static_assert(IsRandomAccess, |
186 | | "Subscripting is only defined for random access iterators."); |
187 | | return ReferenceProxy(static_cast<const DerivedT *>(this)->operator+(n)); |
188 | | } |
189 | | }; |
190 | | |
191 | | /// CRTP base class for adapting an iterator to a different type. |
192 | | /// |
193 | | /// This class can be used through CRTP to adapt one iterator into another. |
194 | | /// Typically this is done through providing in the derived class a custom \c |
195 | | /// operator* implementation. Other methods can be overridden as well. |
196 | | template < |
197 | | typename DerivedT, typename WrappedIteratorT, |
198 | | typename IteratorCategoryT = |
199 | | typename std::iterator_traits<WrappedIteratorT>::iterator_category, |
200 | | typename T = typename std::iterator_traits<WrappedIteratorT>::value_type, |
201 | | typename DifferenceTypeT = |
202 | | typename std::iterator_traits<WrappedIteratorT>::difference_type, |
203 | | typename PointerT = typename std::conditional< |
204 | | std::is_same<T, typename std::iterator_traits< |
205 | | WrappedIteratorT>::value_type>::value, |
206 | | typename std::iterator_traits<WrappedIteratorT>::pointer, T *>::type, |
207 | | typename ReferenceT = typename std::conditional< |
208 | | std::is_same<T, typename std::iterator_traits< |
209 | | WrappedIteratorT>::value_type>::value, |
210 | | typename std::iterator_traits<WrappedIteratorT>::reference, T &>::type, |
211 | | // Don't provide these, they are mostly to act as aliases below. |
212 | | typename WrappedTraitsT = std::iterator_traits<WrappedIteratorT>> |
213 | | class iterator_adaptor_base |
214 | | : public iterator_facade_base<DerivedT, IteratorCategoryT, T, |
215 | | DifferenceTypeT, PointerT, ReferenceT> { |
216 | | using BaseT = typename iterator_adaptor_base::iterator_facade_base; |
217 | | |
218 | | protected: |
219 | | WrappedIteratorT I; |
220 | | |
221 | | iterator_adaptor_base() = default; |
222 | | |
223 | | explicit iterator_adaptor_base(WrappedIteratorT u) : I(std::move(u)) { |
224 | | static_assert(std::is_base_of<iterator_adaptor_base, DerivedT>::value, |
225 | | "Must pass the derived type to this template!"); |
226 | | } |
227 | | |
228 | | const WrappedIteratorT &wrapped() const { return I; } |
229 | | |
230 | | public: |
231 | | using difference_type = DifferenceTypeT; |
232 | | |
233 | | DerivedT &operator+=(difference_type n) { |
234 | | static_assert( |
235 | | BaseT::IsRandomAccess, |
236 | | "The '+=' operator is only defined for random access iterators."); |
237 | | I += n; |
238 | | return *static_cast<DerivedT *>(this); |
239 | | } |
240 | | DerivedT &operator-=(difference_type n) { |
241 | | static_assert( |
242 | | BaseT::IsRandomAccess, |
243 | | "The '-=' operator is only defined for random access iterators."); |
244 | | I -= n; |
245 | | return *static_cast<DerivedT *>(this); |
246 | | } |
247 | | using BaseT::operator-; |
248 | | difference_type operator-(const DerivedT &RHS) const { |
249 | | static_assert( |
250 | | BaseT::IsRandomAccess, |
251 | | "The '-' operator is only defined for random access iterators."); |
252 | | return I - RHS.I; |
253 | | } |
254 | | |
255 | | // We have to explicitly provide ++ and -- rather than letting the facade |
256 | | // forward to += because WrappedIteratorT might not support +=. |
257 | | using BaseT::operator++; |
258 | 0 | DerivedT &operator++() { |
259 | 0 | ++I; |
260 | 0 | return *static_cast<DerivedT *>(this); |
261 | 0 | } |
262 | | using BaseT::operator--; |
263 | | DerivedT &operator--() { |
264 | | static_assert( |
265 | | BaseT::IsBidirectional, |
266 | | "The decrement operator is only defined for bidirectional iterators."); |
267 | | --I; |
268 | | return *static_cast<DerivedT *>(this); |
269 | | } |
270 | | |
271 | | friend bool operator==(const DerivedT &LHS, const DerivedT &RHS) { |
272 | | return LHS.I == RHS.I; |
273 | | } |
274 | 0 | friend bool operator!=(const DerivedT &LHS, const DerivedT &RHS) { |
275 | 0 | return LHS.I != RHS.I; |
276 | 0 | } |
277 | | bool operator<(const DerivedT &RHS) const { |
278 | | static_assert( |
279 | | BaseT::IsRandomAccess, |
280 | | "Relational operators are only defined for random access iterators."); |
281 | | return I < RHS.I; |
282 | | } |
283 | | |
284 | | ReferenceT operator*() const { return *I; } |
285 | | }; |
286 | | |
287 | | /// An iterator type that allows iterating over the pointees via some |
288 | | /// other iterator. |
289 | | /// |
290 | | /// The typical usage of this is to expose a type that iterates over Ts, but |
291 | | /// which is implemented with some iterator over T*s: |
292 | | /// |
293 | | /// \code |
294 | | /// using iterator = pointee_iterator<SmallVectorImpl<T *>::iterator>; |
295 | | /// \endcode |
296 | | template <typename WrappedIteratorT, |
297 | | typename T = typename std::remove_reference< |
298 | | decltype(**std::declval<WrappedIteratorT>())>::type> |
299 | | struct pointee_iterator |
300 | | : iterator_adaptor_base< |
301 | | pointee_iterator<WrappedIteratorT, T>, WrappedIteratorT, |
302 | | typename std::iterator_traits<WrappedIteratorT>::iterator_category, |
303 | | T> { |
304 | | pointee_iterator() = default; |
305 | | template <typename U> |
306 | | pointee_iterator(U &&u) |
307 | | : pointee_iterator::iterator_adaptor_base(std::forward<U &&>(u)) {} |
308 | | |
309 | | T &operator*() const { return **this->I; } |
310 | | }; |
311 | | |
312 | | template <typename RangeT, typename WrappedIteratorT = |
313 | | decltype(std::begin(std::declval<RangeT>()))> |
314 | | iterator_range<pointee_iterator<WrappedIteratorT>> |
315 | | make_pointee_range(RangeT &&Range) { |
316 | | using PointeeIteratorT = pointee_iterator<WrappedIteratorT>; |
317 | | return make_range(PointeeIteratorT(std::begin(std::forward<RangeT>(Range))), |
318 | | PointeeIteratorT(std::end(std::forward<RangeT>(Range)))); |
319 | | } |
320 | | |
321 | | template <typename WrappedIteratorT, |
322 | | typename T = decltype(&*std::declval<WrappedIteratorT>())> |
323 | | class pointer_iterator |
324 | | : public iterator_adaptor_base<pointer_iterator<WrappedIteratorT, T>, |
325 | | WrappedIteratorT, T> { |
326 | | mutable T Ptr; |
327 | | |
328 | | public: |
329 | | pointer_iterator() = default; |
330 | | |
331 | | explicit pointer_iterator(WrappedIteratorT u) |
332 | | : pointer_iterator::iterator_adaptor_base(std::move(u)) {} |
333 | | |
334 | 0 | T &operator*() { return Ptr = &*this->I; } |
335 | | const T &operator*() const { return Ptr = &*this->I; } |
336 | | }; |
337 | | |
338 | | template <typename RangeT, typename WrappedIteratorT = |
339 | | decltype(std::begin(std::declval<RangeT>()))> |
340 | | iterator_range<pointer_iterator<WrappedIteratorT>> |
341 | | make_pointer_range(RangeT &&Range) { |
342 | | using PointerIteratorT = pointer_iterator<WrappedIteratorT>; |
343 | | return make_range(PointerIteratorT(std::begin(std::forward<RangeT>(Range))), |
344 | | PointerIteratorT(std::end(std::forward<RangeT>(Range)))); |
345 | | } |
346 | | |
347 | | // Wrapper iterator over iterator ItType, adding DataRef to the type of ItType, |
348 | | // to create NodeRef = std::pair<InnerTypeOfItType, DataRef>. |
349 | | template <typename ItType, typename NodeRef, typename DataRef> |
350 | | class WrappedPairNodeDataIterator |
351 | | : public iterator_adaptor_base< |
352 | | WrappedPairNodeDataIterator<ItType, NodeRef, DataRef>, ItType, |
353 | | typename std::iterator_traits<ItType>::iterator_category, NodeRef, |
354 | | std::ptrdiff_t, NodeRef *, NodeRef &> { |
355 | | using BaseT = iterator_adaptor_base< |
356 | | WrappedPairNodeDataIterator, ItType, |
357 | | typename std::iterator_traits<ItType>::iterator_category, NodeRef, |
358 | | std::ptrdiff_t, NodeRef *, NodeRef &>; |
359 | | |
360 | | const DataRef DR; |
361 | | mutable NodeRef NR; |
362 | | |
363 | | public: |
364 | | WrappedPairNodeDataIterator(ItType Begin, const DataRef DR) |
365 | | : BaseT(Begin), DR(DR) { |
366 | | NR.first = DR; |
367 | | } |
368 | | |
369 | | NodeRef &operator*() const { |
370 | | NR.second = *this->I; |
371 | | return NR; |
372 | | } |
373 | | }; |
374 | | |
375 | | } // end namespace llvh |
376 | | |
377 | | #endif // LLVM_ADT_ITERATOR_H |