File indexing completed on 2026-05-10 08:36:25
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018 #ifndef LLVM_CLANG_ANALYSIS_SUPPORT_BUMPVECTOR_H
0019 #define LLVM_CLANG_ANALYSIS_SUPPORT_BUMPVECTOR_H
0020
0021 #include "llvm/ADT/PointerIntPair.h"
0022 #include "llvm/Support/Allocator.h"
0023 #include <cassert>
0024 #include <cstddef>
0025 #include <cstring>
0026 #include <iterator>
0027 #include <memory>
0028 #include <type_traits>
0029
0030 namespace clang {
0031
0032 class BumpVectorContext {
0033 llvm::PointerIntPair<llvm::BumpPtrAllocator*, 1> Alloc;
0034
0035 public:
0036
0037
0038 BumpVectorContext() : Alloc(new llvm::BumpPtrAllocator(), 1) {}
0039
0040 BumpVectorContext(BumpVectorContext &&Other) : Alloc(Other.Alloc) {
0041 Other.Alloc.setInt(false);
0042 Other.Alloc.setPointer(nullptr);
0043 }
0044
0045
0046
0047 BumpVectorContext &operator=(BumpVectorContext &&) = delete;
0048
0049
0050
0051 BumpVectorContext(const BumpVectorContext &) = delete;
0052 BumpVectorContext &operator=(const BumpVectorContext &) = delete;
0053
0054
0055
0056
0057 BumpVectorContext(llvm::BumpPtrAllocator &A) : Alloc(&A, 0) {}
0058
0059 ~BumpVectorContext() {
0060 if (Alloc.getInt())
0061 delete Alloc.getPointer();
0062 }
0063
0064 llvm::BumpPtrAllocator &getAllocator() { return *Alloc.getPointer(); }
0065 };
0066
0067 template<typename T>
0068 class BumpVector {
0069 T *Begin = nullptr;
0070 T *End = nullptr;
0071 T *Capacity = nullptr;
0072
0073 public:
0074
0075 explicit BumpVector(BumpVectorContext &C, unsigned N) {
0076 reserve(C, N);
0077 }
0078
0079 ~BumpVector() {
0080 if (std::is_class<T>::value) {
0081
0082 destroy_range(Begin, End);
0083 }
0084 }
0085
0086 using size_type = size_t;
0087 using difference_type = ptrdiff_t;
0088 using value_type = T;
0089 using iterator = T *;
0090 using const_iterator = const T *;
0091
0092 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
0093 using reverse_iterator = std::reverse_iterator<iterator>;
0094
0095 using reference = T &;
0096 using const_reference = const T &;
0097 using pointer = T *;
0098 using const_pointer = const T *;
0099
0100
0101 iterator begin() { return Begin; }
0102 const_iterator begin() const { return Begin; }
0103 iterator end() { return End; }
0104 const_iterator end() const { return End; }
0105
0106
0107 reverse_iterator rbegin() { return reverse_iterator(end()); }
0108 const_reverse_iterator rbegin() const{ return const_reverse_iterator(end()); }
0109 reverse_iterator rend() { return reverse_iterator(begin()); }
0110 const_reverse_iterator rend() const {
0111 return const_reverse_iterator(begin());
0112 }
0113
0114 bool empty() const { return Begin == End; }
0115 size_type size() const { return End-Begin; }
0116
0117 reference operator[](unsigned idx) {
0118 assert(Begin + idx < End);
0119 return Begin[idx];
0120 }
0121 const_reference operator[](unsigned idx) const {
0122 assert(Begin + idx < End);
0123 return Begin[idx];
0124 }
0125
0126 reference front() {
0127 return begin()[0];
0128 }
0129 const_reference front() const {
0130 return begin()[0];
0131 }
0132
0133 reference back() {
0134 return end()[-1];
0135 }
0136 const_reference back() const {
0137 return end()[-1];
0138 }
0139
0140 void pop_back() {
0141 --End;
0142 End->~T();
0143 }
0144
0145 T pop_back_val() {
0146 T Result = back();
0147 pop_back();
0148 return Result;
0149 }
0150
0151 void clear() {
0152 if (std::is_class<T>::value) {
0153 destroy_range(Begin, End);
0154 }
0155 End = Begin;
0156 }
0157
0158
0159 pointer data() {
0160 return pointer(Begin);
0161 }
0162
0163
0164 const_pointer data() const {
0165 return const_pointer(Begin);
0166 }
0167
0168 void push_back(const_reference Elt, BumpVectorContext &C) {
0169 if (End < Capacity) {
0170 Retry:
0171 new (End) T(Elt);
0172 ++End;
0173 return;
0174 }
0175 grow(C);
0176 goto Retry;
0177 }
0178
0179
0180
0181 iterator insert(iterator I, size_t Cnt, const_reference E,
0182 BumpVectorContext &C) {
0183 assert(I >= Begin && I <= End && "Iterator out of bounds.");
0184 if (End + Cnt <= Capacity) {
0185 Retry:
0186 move_range_right(I, End, Cnt);
0187 construct_range(I, I + Cnt, E);
0188 End += Cnt;
0189 return I + Cnt;
0190 }
0191 ptrdiff_t D = I - Begin;
0192 grow(C, size() + Cnt);
0193 I = Begin + D;
0194 goto Retry;
0195 }
0196
0197 void reserve(BumpVectorContext &C, unsigned N) {
0198 if (unsigned(Capacity-Begin) < N)
0199 grow(C, N);
0200 }
0201
0202
0203
0204 size_t capacity() const { return Capacity - Begin; }
0205
0206 private:
0207
0208
0209 void grow(BumpVectorContext &C, size_type MinSize = 1);
0210
0211 void construct_range(T *S, T *E, const T &Elt) {
0212 for (; S != E; ++S)
0213 new (S) T(Elt);
0214 }
0215
0216 void destroy_range(T *S, T *E) {
0217 while (S != E) {
0218 --E;
0219 E->~T();
0220 }
0221 }
0222
0223 void move_range_right(T *S, T *E, size_t D) {
0224 for (T *I = E + D - 1, *IL = S + D - 1; I != IL; --I) {
0225 --E;
0226 new (I) T(*E);
0227 E->~T();
0228 }
0229 }
0230 };
0231
0232
0233 template <typename T>
0234 void BumpVector<T>::grow(BumpVectorContext &C, size_t MinSize) {
0235 size_t CurCapacity = Capacity-Begin;
0236 size_t CurSize = size();
0237 size_t NewCapacity = 2*CurCapacity;
0238 if (NewCapacity < MinSize)
0239 NewCapacity = MinSize;
0240
0241
0242 T *NewElts = C.getAllocator().template Allocate<T>(NewCapacity);
0243
0244
0245 if (Begin != End) {
0246 if (std::is_class<T>::value) {
0247 std::uninitialized_copy(Begin, End, NewElts);
0248
0249 destroy_range(Begin, End);
0250 } else {
0251
0252 memcpy(NewElts, Begin, CurSize * sizeof(T));
0253 }
0254 }
0255
0256
0257
0258 Begin = NewElts;
0259 End = NewElts+CurSize;
0260 Capacity = Begin+NewCapacity;
0261 }
0262
0263 }
0264
0265 #endif