File indexing completed on 2026-05-10 08:43:02
0001
0002
0003
0004
0005
0006
0007
0008
0009 #ifndef LLVM_ADT_ARRAYREF_H
0010 #define LLVM_ADT_ARRAYREF_H
0011
0012 #include "llvm/ADT/Hashing.h"
0013 #include "llvm/ADT/SmallVector.h"
0014 #include "llvm/ADT/STLExtras.h"
0015 #include "llvm/Support/Compiler.h"
0016 #include <algorithm>
0017 #include <array>
0018 #include <cassert>
0019 #include <cstddef>
0020 #include <initializer_list>
0021 #include <iterator>
0022 #include <memory>
0023 #include <type_traits>
0024 #include <vector>
0025
0026 namespace llvm {
0027 template<typename T> class [[nodiscard]] MutableArrayRef;
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040 template<typename T>
0041 class LLVM_GSL_POINTER [[nodiscard]] ArrayRef {
0042 public:
0043 using value_type = T;
0044 using pointer = value_type *;
0045 using const_pointer = const value_type *;
0046 using reference = value_type &;
0047 using const_reference = const value_type &;
0048 using iterator = const_pointer;
0049 using const_iterator = const_pointer;
0050 using reverse_iterator = std::reverse_iterator<iterator>;
0051 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
0052 using size_type = size_t;
0053 using difference_type = ptrdiff_t;
0054
0055 private:
0056
0057 const T *Data = nullptr;
0058
0059
0060 size_type Length = 0;
0061
0062 public:
0063
0064
0065
0066
0067 ArrayRef() = default;
0068
0069
0070 ArrayRef(std::nullopt_t) {}
0071
0072
0073 ArrayRef(const T &OneElt LLVM_LIFETIME_BOUND)
0074 : Data(&OneElt), Length(1) {}
0075
0076
0077 constexpr ArrayRef(const T *data LLVM_LIFETIME_BOUND,
0078 size_t length)
0079 : Data(data), Length(length) {}
0080
0081
0082 constexpr ArrayRef(const T *begin LLVM_LIFETIME_BOUND, const T *end)
0083 : Data(begin), Length(end - begin) {
0084 assert(begin <= end);
0085 }
0086
0087
0088
0089
0090 template<typename U>
0091 ArrayRef(const SmallVectorTemplateCommon<T, U> &Vec)
0092 : Data(Vec.data()), Length(Vec.size()) {
0093 }
0094
0095
0096 template<typename A>
0097 ArrayRef(const std::vector<T, A> &Vec)
0098 : Data(Vec.data()), Length(Vec.size()) {}
0099
0100
0101 template <size_t N>
0102 constexpr ArrayRef(const std::array<T, N> &Arr)
0103 : Data(Arr.data()), Length(N) {}
0104
0105
0106 template <size_t N>
0107 constexpr ArrayRef(const T (&Arr LLVM_LIFETIME_BOUND)[N])
0108 : Data(Arr), Length(N) {}
0109
0110
0111 #if LLVM_GNUC_PREREQ(9, 0, 0)
0112
0113
0114
0115 #pragma GCC diagnostic push
0116 #pragma GCC diagnostic ignored "-Winit-list-lifetime"
0117 #endif
0118 constexpr ArrayRef(
0119 std::initializer_list<T> Vec LLVM_LIFETIME_BOUND)
0120 : Data(Vec.begin() == Vec.end() ? (T *)nullptr : Vec.begin()),
0121 Length(Vec.size()) {}
0122 #if LLVM_GNUC_PREREQ(9, 0, 0)
0123 #pragma GCC diagnostic pop
0124 #endif
0125
0126
0127
0128 template <typename U>
0129 ArrayRef(const ArrayRef<U *> &A,
0130 std::enable_if_t<std::is_convertible<U *const *, T const *>::value>
0131 * = nullptr)
0132 : Data(A.data()), Length(A.size()) {}
0133
0134
0135
0136
0137 template <typename U, typename DummyT>
0138 ArrayRef(
0139 const SmallVectorTemplateCommon<U *, DummyT> &Vec,
0140 std::enable_if_t<std::is_convertible<U *const *, T const *>::value> * =
0141 nullptr)
0142 : Data(Vec.data()), Length(Vec.size()) {}
0143
0144
0145
0146 template <typename U, typename A>
0147 ArrayRef(const std::vector<U *, A> &Vec,
0148 std::enable_if_t<std::is_convertible<U *const *, T const *>::value>
0149 * = nullptr)
0150 : Data(Vec.data()), Length(Vec.size()) {}
0151
0152
0153
0154
0155
0156 iterator begin() const { return Data; }
0157 iterator end() const { return Data + Length; }
0158
0159 reverse_iterator rbegin() const { return reverse_iterator(end()); }
0160 reverse_iterator rend() const { return reverse_iterator(begin()); }
0161
0162
0163 bool empty() const { return Length == 0; }
0164
0165 const T *data() const { return Data; }
0166
0167
0168 size_t size() const { return Length; }
0169
0170
0171 const T &front() const {
0172 assert(!empty());
0173 return Data[0];
0174 }
0175
0176
0177 const T &back() const {
0178 assert(!empty());
0179 return Data[Length-1];
0180 }
0181
0182
0183 template <typename Allocator> MutableArrayRef<T> copy(Allocator &A) {
0184 T *Buff = A.template Allocate<T>(Length);
0185 std::uninitialized_copy(begin(), end(), Buff);
0186 return MutableArrayRef<T>(Buff, Length);
0187 }
0188
0189
0190 bool equals(ArrayRef RHS) const {
0191 if (Length != RHS.Length)
0192 return false;
0193 return std::equal(begin(), end(), RHS.begin());
0194 }
0195
0196
0197
0198 ArrayRef<T> slice(size_t N, size_t M) const {
0199 assert(N+M <= size() && "Invalid specifier");
0200 return ArrayRef<T>(data()+N, M);
0201 }
0202
0203
0204 ArrayRef<T> slice(size_t N) const { return drop_front(N); }
0205
0206
0207 ArrayRef<T> drop_front(size_t N = 1) const {
0208 assert(size() >= N && "Dropping more elements than exist");
0209 return slice(N, size() - N);
0210 }
0211
0212
0213 ArrayRef<T> drop_back(size_t N = 1) const {
0214 assert(size() >= N && "Dropping more elements than exist");
0215 return slice(0, size() - N);
0216 }
0217
0218
0219
0220 template <class PredicateT> ArrayRef<T> drop_while(PredicateT Pred) const {
0221 return ArrayRef<T>(find_if_not(*this, Pred), end());
0222 }
0223
0224
0225
0226 template <class PredicateT> ArrayRef<T> drop_until(PredicateT Pred) const {
0227 return ArrayRef<T>(find_if(*this, Pred), end());
0228 }
0229
0230
0231 ArrayRef<T> take_front(size_t N = 1) const {
0232 if (N >= size())
0233 return *this;
0234 return drop_back(size() - N);
0235 }
0236
0237
0238 ArrayRef<T> take_back(size_t N = 1) const {
0239 if (N >= size())
0240 return *this;
0241 return drop_front(size() - N);
0242 }
0243
0244
0245
0246 template <class PredicateT> ArrayRef<T> take_while(PredicateT Pred) const {
0247 return ArrayRef<T>(begin(), find_if_not(*this, Pred));
0248 }
0249
0250
0251
0252 template <class PredicateT> ArrayRef<T> take_until(PredicateT Pred) const {
0253 return ArrayRef<T>(begin(), find_if(*this, Pred));
0254 }
0255
0256
0257
0258
0259 const T &operator[](size_t Index) const {
0260 assert(Index < Length && "Invalid index!");
0261 return Data[Index];
0262 }
0263
0264
0265
0266
0267
0268 template <typename U>
0269 std::enable_if_t<std::is_same<U, T>::value, ArrayRef<T>> &
0270 operator=(U &&Temporary) = delete;
0271
0272
0273
0274
0275
0276 template <typename U>
0277 std::enable_if_t<std::is_same<U, T>::value, ArrayRef<T>> &
0278 operator=(std::initializer_list<U>) = delete;
0279
0280
0281
0282
0283 std::vector<T> vec() const {
0284 return std::vector<T>(Data, Data+Length);
0285 }
0286
0287
0288
0289
0290 operator std::vector<T>() const {
0291 return std::vector<T>(Data, Data+Length);
0292 }
0293
0294
0295 };
0296
0297
0298
0299
0300
0301
0302
0303
0304
0305
0306
0307
0308
0309 template<typename T>
0310 class [[nodiscard]] MutableArrayRef : public ArrayRef<T> {
0311 public:
0312 using value_type = T;
0313 using pointer = value_type *;
0314 using const_pointer = const value_type *;
0315 using reference = value_type &;
0316 using const_reference = const value_type &;
0317 using iterator = pointer;
0318 using const_iterator = const_pointer;
0319 using reverse_iterator = std::reverse_iterator<iterator>;
0320 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
0321 using size_type = size_t;
0322 using difference_type = ptrdiff_t;
0323
0324
0325 MutableArrayRef() = default;
0326
0327
0328 MutableArrayRef(std::nullopt_t) : ArrayRef<T>() {}
0329
0330
0331 MutableArrayRef(T &OneElt) : ArrayRef<T>(OneElt) {}
0332
0333
0334 MutableArrayRef(T *data, size_t length)
0335 : ArrayRef<T>(data, length) {}
0336
0337
0338 MutableArrayRef(T *begin, T *end) : ArrayRef<T>(begin, end) {}
0339
0340
0341 MutableArrayRef(SmallVectorImpl<T> &Vec)
0342 : ArrayRef<T>(Vec) {}
0343
0344
0345 MutableArrayRef(std::vector<T> &Vec)
0346 : ArrayRef<T>(Vec) {}
0347
0348
0349 template <size_t N>
0350 constexpr MutableArrayRef(std::array<T, N> &Arr)
0351 : ArrayRef<T>(Arr) {}
0352
0353
0354 template <size_t N>
0355 constexpr MutableArrayRef(T (&Arr)[N]) : ArrayRef<T>(Arr) {}
0356
0357 T *data() const { return const_cast<T*>(ArrayRef<T>::data()); }
0358
0359 iterator begin() const { return data(); }
0360 iterator end() const { return data() + this->size(); }
0361
0362 reverse_iterator rbegin() const { return reverse_iterator(end()); }
0363 reverse_iterator rend() const { return reverse_iterator(begin()); }
0364
0365
0366 T &front() const {
0367 assert(!this->empty());
0368 return data()[0];
0369 }
0370
0371
0372 T &back() const {
0373 assert(!this->empty());
0374 return data()[this->size()-1];
0375 }
0376
0377
0378
0379 MutableArrayRef<T> slice(size_t N, size_t M) const {
0380 assert(N + M <= this->size() && "Invalid specifier");
0381 return MutableArrayRef<T>(this->data() + N, M);
0382 }
0383
0384
0385 MutableArrayRef<T> slice(size_t N) const {
0386 return slice(N, this->size() - N);
0387 }
0388
0389
0390 MutableArrayRef<T> drop_front(size_t N = 1) const {
0391 assert(this->size() >= N && "Dropping more elements than exist");
0392 return slice(N, this->size() - N);
0393 }
0394
0395 MutableArrayRef<T> drop_back(size_t N = 1) const {
0396 assert(this->size() >= N && "Dropping more elements than exist");
0397 return slice(0, this->size() - N);
0398 }
0399
0400
0401
0402 template <class PredicateT>
0403 MutableArrayRef<T> drop_while(PredicateT Pred) const {
0404 return MutableArrayRef<T>(find_if_not(*this, Pred), end());
0405 }
0406
0407
0408
0409 template <class PredicateT>
0410 MutableArrayRef<T> drop_until(PredicateT Pred) const {
0411 return MutableArrayRef<T>(find_if(*this, Pred), end());
0412 }
0413
0414
0415 MutableArrayRef<T> take_front(size_t N = 1) const {
0416 if (N >= this->size())
0417 return *this;
0418 return drop_back(this->size() - N);
0419 }
0420
0421
0422 MutableArrayRef<T> take_back(size_t N = 1) const {
0423 if (N >= this->size())
0424 return *this;
0425 return drop_front(this->size() - N);
0426 }
0427
0428
0429
0430 template <class PredicateT>
0431 MutableArrayRef<T> take_while(PredicateT Pred) const {
0432 return MutableArrayRef<T>(begin(), find_if_not(*this, Pred));
0433 }
0434
0435
0436
0437 template <class PredicateT>
0438 MutableArrayRef<T> take_until(PredicateT Pred) const {
0439 return MutableArrayRef<T>(begin(), find_if(*this, Pred));
0440 }
0441
0442
0443
0444
0445 T &operator[](size_t Index) const {
0446 assert(Index < this->size() && "Invalid index!");
0447 return data()[Index];
0448 }
0449 };
0450
0451
0452 template <typename T> class OwningArrayRef : public MutableArrayRef<T> {
0453 public:
0454 OwningArrayRef() = default;
0455 OwningArrayRef(size_t Size) : MutableArrayRef<T>(new T[Size], Size) {}
0456
0457 OwningArrayRef(ArrayRef<T> Data)
0458 : MutableArrayRef<T>(new T[Data.size()], Data.size()) {
0459 std::copy(Data.begin(), Data.end(), this->begin());
0460 }
0461
0462 OwningArrayRef(OwningArrayRef &&Other) { *this = std::move(Other); }
0463
0464 OwningArrayRef &operator=(OwningArrayRef &&Other) {
0465 delete[] this->data();
0466 this->MutableArrayRef<T>::operator=(Other);
0467 Other.MutableArrayRef<T>::operator=(MutableArrayRef<T>());
0468 return *this;
0469 }
0470
0471 ~OwningArrayRef() { delete[] this->data(); }
0472 };
0473
0474
0475
0476
0477 template <typename T> ArrayRef(const T &OneElt) -> ArrayRef<T>;
0478
0479
0480 template <typename T> ArrayRef(const T *data, size_t length) -> ArrayRef<T>;
0481
0482
0483 template <typename T> ArrayRef(const T *data, const T *end) -> ArrayRef<T>;
0484
0485
0486 template <typename T> ArrayRef(const SmallVectorImpl<T> &Vec) -> ArrayRef<T>;
0487
0488
0489 template <typename T, unsigned N>
0490 ArrayRef(const SmallVector<T, N> &Vec) -> ArrayRef<T>;
0491
0492
0493 template <typename T> ArrayRef(const std::vector<T> &Vec) -> ArrayRef<T>;
0494
0495
0496 template <typename T, std::size_t N>
0497 ArrayRef(const std::array<T, N> &Vec) -> ArrayRef<T>;
0498
0499
0500 template <typename T> ArrayRef(const ArrayRef<T> &Vec) -> ArrayRef<T>;
0501
0502
0503 template <typename T> ArrayRef(ArrayRef<T> &Vec) -> ArrayRef<T>;
0504
0505
0506 template <typename T, size_t N> ArrayRef(const T (&Arr)[N]) -> ArrayRef<T>;
0507
0508
0509
0510
0511
0512
0513 template <class T> MutableArrayRef(T &OneElt) -> MutableArrayRef<T>;
0514
0515
0516
0517 template <class T>
0518 MutableArrayRef(T *data, size_t length) -> MutableArrayRef<T>;
0519
0520
0521 template <class T>
0522 MutableArrayRef(SmallVectorImpl<T> &Vec) -> MutableArrayRef<T>;
0523
0524 template <class T, unsigned N>
0525 MutableArrayRef(SmallVector<T, N> &Vec) -> MutableArrayRef<T>;
0526
0527
0528 template <class T> MutableArrayRef(std::vector<T> &Vec) -> MutableArrayRef<T>;
0529
0530
0531 template <class T, std::size_t N>
0532 MutableArrayRef(std::array<T, N> &Vec) -> MutableArrayRef<T>;
0533
0534
0535 template <typename T, size_t N>
0536 MutableArrayRef(T (&Arr)[N]) -> MutableArrayRef<T>;
0537
0538
0539
0540
0541
0542 template<typename T>
0543 inline bool operator==(ArrayRef<T> LHS, ArrayRef<T> RHS) {
0544 return LHS.equals(RHS);
0545 }
0546
0547 template <typename T>
0548 inline bool operator==(SmallVectorImpl<T> &LHS, ArrayRef<T> RHS) {
0549 return ArrayRef<T>(LHS).equals(RHS);
0550 }
0551
0552 template <typename T>
0553 inline bool operator!=(ArrayRef<T> LHS, ArrayRef<T> RHS) {
0554 return !(LHS == RHS);
0555 }
0556
0557 template <typename T>
0558 inline bool operator!=(SmallVectorImpl<T> &LHS, ArrayRef<T> RHS) {
0559 return !(LHS == RHS);
0560 }
0561
0562
0563
0564 template <typename T> hash_code hash_value(ArrayRef<T> S) {
0565 return hash_combine_range(S.begin(), S.end());
0566 }
0567
0568
0569 template <typename T> struct DenseMapInfo<ArrayRef<T>, void> {
0570 static inline ArrayRef<T> getEmptyKey() {
0571 return ArrayRef<T>(
0572 reinterpret_cast<const T *>(~static_cast<uintptr_t>(0)), size_t(0));
0573 }
0574
0575 static inline ArrayRef<T> getTombstoneKey() {
0576 return ArrayRef<T>(
0577 reinterpret_cast<const T *>(~static_cast<uintptr_t>(1)), size_t(0));
0578 }
0579
0580 static unsigned getHashValue(ArrayRef<T> Val) {
0581 assert(Val.data() != getEmptyKey().data() &&
0582 "Cannot hash the empty key!");
0583 assert(Val.data() != getTombstoneKey().data() &&
0584 "Cannot hash the tombstone key!");
0585 return (unsigned)(hash_value(Val));
0586 }
0587
0588 static bool isEqual(ArrayRef<T> LHS, ArrayRef<T> RHS) {
0589 if (RHS.data() == getEmptyKey().data())
0590 return LHS.data() == getEmptyKey().data();
0591 if (RHS.data() == getTombstoneKey().data())
0592 return LHS.data() == getTombstoneKey().data();
0593 return LHS == RHS;
0594 }
0595 };
0596
0597 }
0598
0599 #endif