File indexing completed on 2026-05-10 08:43:07
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080 #ifndef LLVM_ADT_SEQUENCE_H
0081 #define LLVM_ADT_SEQUENCE_H
0082
0083 #include <cassert> // assert
0084 #include <iterator> // std::random_access_iterator_tag
0085 #include <limits> // std::numeric_limits
0086 #include <type_traits> // std::is_integral, std::is_enum, std::underlying_type,
0087
0088
0089 #include "llvm/Support/MathExtras.h" // AddOverflow / SubOverflow
0090
0091 namespace llvm {
0092
0093
0094
0095
0096
0097
0098
0099 template <typename EnumT> struct enum_iteration_traits {
0100 static constexpr bool is_iterable = false;
0101 };
0102
0103 struct force_iteration_on_noniterable_enum_t {
0104 explicit force_iteration_on_noniterable_enum_t() = default;
0105 };
0106
0107 inline constexpr force_iteration_on_noniterable_enum_t
0108 force_iteration_on_noniterable_enum;
0109
0110 namespace detail {
0111
0112
0113 template <typename T, typename U> bool canTypeFitValue(const U Value) {
0114 const intmax_t BotT = intmax_t(std::numeric_limits<T>::min());
0115 const intmax_t BotU = intmax_t(std::numeric_limits<U>::min());
0116 const uintmax_t TopT = uintmax_t(std::numeric_limits<T>::max());
0117 const uintmax_t TopU = uintmax_t(std::numeric_limits<U>::max());
0118 return !((BotT > BotU && Value < static_cast<U>(BotT)) ||
0119 (TopT < TopU && Value > static_cast<U>(TopT)));
0120 }
0121
0122
0123
0124
0125
0126 struct CheckedInt {
0127
0128 template <typename Integral,
0129 std::enable_if_t<std::is_integral<Integral>::value, bool> = 0>
0130 static CheckedInt from(Integral FromValue) {
0131 if (!canTypeFitValue<intmax_t>(FromValue))
0132 assertOutOfBounds();
0133 CheckedInt Result;
0134 Result.Value = static_cast<intmax_t>(FromValue);
0135 return Result;
0136 }
0137
0138
0139 template <typename Enum,
0140 std::enable_if_t<std::is_enum<Enum>::value, bool> = 0>
0141 static CheckedInt from(Enum FromValue) {
0142 using type = std::underlying_type_t<Enum>;
0143 return from<type>(static_cast<type>(FromValue));
0144 }
0145
0146
0147 bool operator==(const CheckedInt &O) const { return Value == O.Value; }
0148 bool operator!=(const CheckedInt &O) const { return Value != O.Value; }
0149
0150 CheckedInt operator+(intmax_t Offset) const {
0151 CheckedInt Result;
0152 if (AddOverflow(Value, Offset, Result.Value))
0153 assertOutOfBounds();
0154 return Result;
0155 }
0156
0157 intmax_t operator-(CheckedInt Other) const {
0158 intmax_t Result;
0159 if (SubOverflow(Value, Other.Value, Result))
0160 assertOutOfBounds();
0161 return Result;
0162 }
0163
0164
0165 template <typename Integral,
0166 std::enable_if_t<std::is_integral<Integral>::value, bool> = 0>
0167 Integral to() const {
0168 if (!canTypeFitValue<Integral>(Value))
0169 assertOutOfBounds();
0170 return static_cast<Integral>(Value);
0171 }
0172
0173
0174
0175 template <typename Enum,
0176 std::enable_if_t<std::is_enum<Enum>::value, bool> = 0>
0177 Enum to() const {
0178 using type = std::underlying_type_t<Enum>;
0179 return Enum(to<type>());
0180 }
0181
0182 private:
0183 static void assertOutOfBounds() { assert(false && "Out of bounds"); }
0184
0185 intmax_t Value;
0186 };
0187
0188 template <typename T, bool IsReverse> struct SafeIntIterator {
0189 using iterator_category = std::random_access_iterator_tag;
0190 using value_type = T;
0191 using difference_type = intmax_t;
0192 using pointer = T *;
0193 using reference = value_type;
0194
0195
0196 explicit SafeIntIterator(T Value) : SI(CheckedInt::from<T>(Value)) {}
0197
0198 SafeIntIterator(const SafeIntIterator<T, !IsReverse> &O) : SI(O.SI) {}
0199
0200
0201 reference operator*() const { return SI.to<T>(); }
0202
0203 reference operator[](intmax_t Offset) const { return *(*this + Offset); }
0204
0205
0206 bool operator==(const SafeIntIterator &O) const { return SI == O.SI; }
0207 bool operator!=(const SafeIntIterator &O) const { return SI != O.SI; }
0208
0209 bool operator<(const SafeIntIterator &O) const { return (*this - O) < 0; }
0210 bool operator>(const SafeIntIterator &O) const { return (*this - O) > 0; }
0211 bool operator<=(const SafeIntIterator &O) const { return (*this - O) <= 0; }
0212 bool operator>=(const SafeIntIterator &O) const { return (*this - O) >= 0; }
0213
0214
0215 void operator++() { offset(1); }
0216 void operator--() { offset(-1); }
0217
0218
0219 SafeIntIterator operator++(int) {
0220 const auto Copy = *this;
0221 ++*this;
0222 return Copy;
0223 }
0224 SafeIntIterator operator--(int) {
0225 const auto Copy = *this;
0226 --*this;
0227 return Copy;
0228 }
0229
0230
0231 void operator+=(intmax_t Offset) { offset(Offset); }
0232 void operator-=(intmax_t Offset) { offset(-Offset); }
0233
0234
0235 SafeIntIterator operator+(intmax_t Offset) const { return add(Offset); }
0236 SafeIntIterator operator-(intmax_t Offset) const { return add(-Offset); }
0237
0238
0239 intmax_t operator-(const SafeIntIterator &O) const {
0240 return IsReverse ? O.SI - SI : SI - O.SI;
0241 }
0242
0243 private:
0244 SafeIntIterator(const CheckedInt &SI) : SI(SI) {}
0245
0246 static intmax_t getOffset(intmax_t Offset) {
0247 return IsReverse ? -Offset : Offset;
0248 }
0249
0250 CheckedInt add(intmax_t Offset) const { return SI + getOffset(Offset); }
0251
0252 void offset(intmax_t Offset) { SI = SI + getOffset(Offset); }
0253
0254 CheckedInt SI;
0255
0256
0257 template <typename, bool> friend struct SafeIntIterator;
0258 };
0259
0260 }
0261
0262 template <typename T> struct iota_range {
0263 using value_type = T;
0264 using reference = T &;
0265 using const_reference = const T &;
0266 using iterator = detail::SafeIntIterator<value_type, false>;
0267 using const_iterator = iterator;
0268 using reverse_iterator = detail::SafeIntIterator<value_type, true>;
0269 using const_reverse_iterator = reverse_iterator;
0270 using difference_type = intmax_t;
0271 using size_type = std::size_t;
0272
0273 explicit iota_range(T Begin, T End, bool Inclusive)
0274 : BeginValue(Begin), PastEndValue(End) {
0275 assert(Begin <= End && "Begin must be less or equal to End.");
0276 if (Inclusive)
0277 ++PastEndValue;
0278 }
0279
0280 size_t size() const { return PastEndValue - BeginValue; }
0281 bool empty() const { return BeginValue == PastEndValue; }
0282
0283 auto begin() const { return const_iterator(BeginValue); }
0284 auto end() const { return const_iterator(PastEndValue); }
0285
0286 auto rbegin() const { return const_reverse_iterator(PastEndValue - 1); }
0287 auto rend() const { return const_reverse_iterator(BeginValue - 1); }
0288
0289 private:
0290 static_assert(std::is_integral<T>::value || std::is_enum<T>::value,
0291 "T must be an integral or enum type");
0292 static_assert(std::is_same<T, std::remove_cv_t<T>>::value,
0293 "T must not be const nor volatile");
0294
0295 iterator BeginValue;
0296 iterator PastEndValue;
0297 };
0298
0299
0300
0301
0302
0303 template <typename T, typename = std::enable_if_t<std::is_integral<T>::value &&
0304 !std::is_enum<T>::value>>
0305 auto seq(T Begin, T End) {
0306 return iota_range<T>(Begin, End, false);
0307 }
0308
0309
0310
0311
0312
0313 template <typename T, typename = std::enable_if_t<std::is_integral<T>::value &&
0314 !std::is_enum<T>::value>>
0315 auto seq(T Size) {
0316 return seq<T>(0, Size);
0317 }
0318
0319
0320
0321
0322
0323 template <typename T, typename = std::enable_if_t<std::is_integral<T>::value &&
0324 !std::is_enum<T>::value>>
0325 auto seq_inclusive(T Begin, T End) {
0326 return iota_range<T>(Begin, End, true);
0327 }
0328
0329
0330
0331
0332
0333
0334
0335 template <typename EnumT,
0336 typename = std::enable_if_t<std::is_enum<EnumT>::value>>
0337 auto enum_seq(EnumT Begin, EnumT End) {
0338 static_assert(enum_iteration_traits<EnumT>::is_iterable,
0339 "Enum type is not marked as iterable.");
0340 return iota_range<EnumT>(Begin, End, false);
0341 }
0342
0343
0344
0345
0346
0347
0348
0349
0350 template <typename EnumT,
0351 typename = std::enable_if_t<std::is_enum<EnumT>::value>>
0352 auto enum_seq(EnumT Begin, EnumT End, force_iteration_on_noniterable_enum_t) {
0353 return iota_range<EnumT>(Begin, End, false);
0354 }
0355
0356
0357
0358
0359
0360
0361
0362 template <typename EnumT,
0363 typename = std::enable_if_t<std::is_enum<EnumT>::value>>
0364 auto enum_seq_inclusive(EnumT Begin, EnumT End) {
0365 static_assert(enum_iteration_traits<EnumT>::is_iterable,
0366 "Enum type is not marked as iterable.");
0367 return iota_range<EnumT>(Begin, End, true);
0368 }
0369
0370
0371
0372
0373
0374
0375
0376
0377 template <typename EnumT,
0378 typename = std::enable_if_t<std::is_enum<EnumT>::value>>
0379 auto enum_seq_inclusive(EnumT Begin, EnumT End,
0380 force_iteration_on_noniterable_enum_t) {
0381 return iota_range<EnumT>(Begin, End, true);
0382 }
0383
0384 }
0385
0386 #endif