Coverage Report

Created: 2025-12-12 07:27

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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