File indexing completed on 2026-05-10 08:36:29
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017 #ifndef LLVM_CLANG_AST_ASTVECTOR_H
0018 #define LLVM_CLANG_AST_ASTVECTOR_H
0019
0020 #include "clang/AST/ASTContextAllocate.h"
0021 #include "llvm/ADT/PointerIntPair.h"
0022 #include <algorithm>
0023 #include <cassert>
0024 #include <cstddef>
0025 #include <cstring>
0026 #include <iterator>
0027 #include <memory>
0028 #include <type_traits>
0029 #include <utility>
0030
0031 namespace clang {
0032
0033 class ASTContext;
0034
0035 template<typename T>
0036 class ASTVector {
0037 private:
0038 T *Begin = nullptr;
0039 T *End = nullptr;
0040 llvm::PointerIntPair<T *, 1, bool> Capacity;
0041
0042 void setEnd(T *P) { this->End = P; }
0043
0044 protected:
0045
0046
0047 bool getTag() const { return Capacity.getInt(); }
0048 void setTag(bool B) { Capacity.setInt(B); }
0049
0050 public:
0051
0052 ASTVector() : Capacity(nullptr, false) {}
0053
0054 ASTVector(ASTVector &&O) : Begin(O.Begin), End(O.End), Capacity(O.Capacity) {
0055 O.Begin = O.End = nullptr;
0056 O.Capacity.setPointer(nullptr);
0057 O.Capacity.setInt(false);
0058 }
0059
0060 ASTVector(const ASTContext &C, unsigned N) : Capacity(nullptr, false) {
0061 reserve(C, N);
0062 }
0063
0064 ASTVector &operator=(ASTVector &&RHS) {
0065 ASTVector O(std::move(RHS));
0066
0067 using std::swap;
0068
0069 swap(Begin, O.Begin);
0070 swap(End, O.End);
0071 swap(Capacity, O.Capacity);
0072 return *this;
0073 }
0074
0075 ~ASTVector() {
0076 if (std::is_class<T>::value) {
0077
0078 destroy_range(Begin, End);
0079 }
0080 }
0081
0082 using size_type = size_t;
0083 using difference_type = ptrdiff_t;
0084 using value_type = T;
0085 using iterator = T *;
0086 using const_iterator = const T *;
0087
0088 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
0089 using reverse_iterator = std::reverse_iterator<iterator>;
0090
0091 using reference = T &;
0092 using const_reference = const T &;
0093 using pointer = T *;
0094 using const_pointer = const T *;
0095
0096
0097 iterator begin() { return Begin; }
0098 const_iterator begin() const { return Begin; }
0099 iterator end() { return End; }
0100 const_iterator end() const { return End; }
0101
0102
0103 reverse_iterator rbegin() { return reverse_iterator(end()); }
0104 const_reverse_iterator rbegin() const{ return const_reverse_iterator(end()); }
0105 reverse_iterator rend() { return reverse_iterator(begin()); }
0106 const_reverse_iterator rend() const { return const_reverse_iterator(begin());}
0107
0108 bool empty() const { return Begin == End; }
0109 size_type size() const { return End-Begin; }
0110
0111 reference operator[](unsigned idx) {
0112 assert(Begin + idx < End);
0113 return Begin[idx];
0114 }
0115 const_reference operator[](unsigned idx) const {
0116 assert(Begin + idx < End);
0117 return Begin[idx];
0118 }
0119
0120 reference front() {
0121 return begin()[0];
0122 }
0123 const_reference front() const {
0124 return begin()[0];
0125 }
0126
0127 reference back() {
0128 return end()[-1];
0129 }
0130 const_reference back() const {
0131 return end()[-1];
0132 }
0133
0134 void pop_back() {
0135 --End;
0136 End->~T();
0137 }
0138
0139 T pop_back_val() {
0140 T Result = back();
0141 pop_back();
0142 return Result;
0143 }
0144
0145 void clear() {
0146 if (std::is_class<T>::value) {
0147 destroy_range(Begin, End);
0148 }
0149 End = Begin;
0150 }
0151
0152
0153 pointer data() {
0154 return pointer(Begin);
0155 }
0156
0157
0158 const_pointer data() const {
0159 return const_pointer(Begin);
0160 }
0161
0162 void push_back(const_reference Elt, const ASTContext &C) {
0163 if (End < this->capacity_ptr()) {
0164 Retry:
0165 new (End) T(Elt);
0166 ++End;
0167 return;
0168 }
0169 grow(C);
0170 goto Retry;
0171 }
0172
0173 void reserve(const ASTContext &C, unsigned N) {
0174 if (unsigned(this->capacity_ptr()-Begin) < N)
0175 grow(C, N);
0176 }
0177
0178
0179
0180 size_t capacity() const { return this->capacity_ptr() - Begin; }
0181
0182
0183 template<typename in_iter>
0184 void append(const ASTContext &C, in_iter in_start, in_iter in_end) {
0185 size_type NumInputs = std::distance(in_start, in_end);
0186
0187 if (NumInputs == 0)
0188 return;
0189
0190
0191 if (NumInputs > size_type(this->capacity_ptr()-this->end()))
0192 this->grow(C, this->size()+NumInputs);
0193
0194
0195
0196
0197 std::uninitialized_copy(in_start, in_end, this->end());
0198 this->setEnd(this->end() + NumInputs);
0199 }
0200
0201
0202 void append(const ASTContext &C, size_type NumInputs, const T &Elt) {
0203
0204 if (NumInputs > size_type(this->capacity_ptr()-this->end()))
0205 this->grow(C, this->size()+NumInputs);
0206
0207
0208 std::uninitialized_fill_n(this->end(), NumInputs, Elt);
0209 this->setEnd(this->end() + NumInputs);
0210 }
0211
0212
0213
0214 template<typename It1, typename It2>
0215 static void uninitialized_copy(It1 I, It1 E, It2 Dest) {
0216 std::uninitialized_copy(I, E, Dest);
0217 }
0218
0219 iterator insert(const ASTContext &C, iterator I, const T &Elt) {
0220 if (I == this->end()) {
0221 push_back(Elt, C);
0222 return this->end()-1;
0223 }
0224
0225 if (this->End < this->capacity_ptr()) {
0226 Retry:
0227 new (this->end()) T(this->back());
0228 this->setEnd(this->end()+1);
0229
0230 std::copy_backward(I, this->end()-1, this->end());
0231 *I = Elt;
0232 return I;
0233 }
0234 size_t EltNo = I-this->begin();
0235 this->grow(C);
0236 I = this->begin()+EltNo;
0237 goto Retry;
0238 }
0239
0240 iterator insert(const ASTContext &C, iterator I, size_type NumToInsert,
0241 const T &Elt) {
0242
0243 size_t InsertElt = I - this->begin();
0244
0245 if (I == this->end()) {
0246 append(C, NumToInsert, Elt);
0247 return this->begin() + InsertElt;
0248 }
0249
0250
0251 reserve(C, static_cast<unsigned>(this->size() + NumToInsert));
0252
0253
0254 I = this->begin()+InsertElt;
0255
0256
0257
0258
0259
0260 if (size_t(this->end()-I) >= NumToInsert) {
0261 T *OldEnd = this->end();
0262 append(C, this->end()-NumToInsert, this->end());
0263
0264
0265 std::copy_backward(I, OldEnd-NumToInsert, OldEnd);
0266
0267 std::fill_n(I, NumToInsert, Elt);
0268 return I;
0269 }
0270
0271
0272
0273
0274
0275 T *OldEnd = this->end();
0276 this->setEnd(this->end() + NumToInsert);
0277 size_t NumOverwritten = OldEnd-I;
0278 this->uninitialized_copy(I, OldEnd, this->end()-NumOverwritten);
0279
0280
0281 std::fill_n(I, NumOverwritten, Elt);
0282
0283
0284 std::uninitialized_fill_n(OldEnd, NumToInsert-NumOverwritten, Elt);
0285 return I;
0286 }
0287
0288 template<typename ItTy>
0289 iterator insert(const ASTContext &C, iterator I, ItTy From, ItTy To) {
0290
0291 size_t InsertElt = I - this->begin();
0292
0293 if (I == this->end()) {
0294 append(C, From, To);
0295 return this->begin() + InsertElt;
0296 }
0297
0298 size_t NumToInsert = std::distance(From, To);
0299
0300
0301 reserve(C, static_cast<unsigned>(this->size() + NumToInsert));
0302
0303
0304 I = this->begin()+InsertElt;
0305
0306
0307
0308
0309
0310 if (size_t(this->end()-I) >= NumToInsert) {
0311 T *OldEnd = this->end();
0312 append(C, this->end()-NumToInsert, this->end());
0313
0314
0315 std::copy_backward(I, OldEnd-NumToInsert, OldEnd);
0316
0317 std::copy(From, To, I);
0318 return I;
0319 }
0320
0321
0322
0323
0324
0325 T *OldEnd = this->end();
0326 this->setEnd(this->end() + NumToInsert);
0327 size_t NumOverwritten = OldEnd-I;
0328 this->uninitialized_copy(I, OldEnd, this->end()-NumOverwritten);
0329
0330
0331 for (; NumOverwritten > 0; --NumOverwritten) {
0332 *I = *From;
0333 ++I; ++From;
0334 }
0335
0336
0337 this->uninitialized_copy(From, To, OldEnd);
0338 return I;
0339 }
0340
0341 void resize(const ASTContext &C, unsigned N, const T &NV) {
0342 if (N < this->size()) {
0343 this->destroy_range(this->begin()+N, this->end());
0344 this->setEnd(this->begin()+N);
0345 } else if (N > this->size()) {
0346 if (this->capacity() < N)
0347 this->grow(C, N);
0348 construct_range(this->end(), this->begin()+N, NV);
0349 this->setEnd(this->begin()+N);
0350 }
0351 }
0352
0353 private:
0354
0355
0356 void grow(const ASTContext &C, size_type MinSize = 1);
0357
0358 void construct_range(T *S, T *E, const T &Elt) {
0359 for (; S != E; ++S)
0360 new (S) T(Elt);
0361 }
0362
0363 void destroy_range(T *S, T *E) {
0364 while (S != E) {
0365 --E;
0366 E->~T();
0367 }
0368 }
0369
0370 protected:
0371 const_iterator capacity_ptr() const {
0372 return (iterator) Capacity.getPointer();
0373 }
0374
0375 iterator capacity_ptr() { return (iterator)Capacity.getPointer(); }
0376 };
0377
0378
0379 template <typename T>
0380 void ASTVector<T>::grow(const ASTContext &C, size_t MinSize) {
0381 size_t CurCapacity = this->capacity();
0382 size_t CurSize = size();
0383 size_t NewCapacity = 2*CurCapacity;
0384 if (NewCapacity < MinSize)
0385 NewCapacity = MinSize;
0386
0387
0388 T *NewElts = new (C, alignof(T)) T[NewCapacity];
0389
0390
0391 if (Begin != End) {
0392 if (std::is_class<T>::value) {
0393 std::uninitialized_copy(Begin, End, NewElts);
0394
0395 destroy_range(Begin, End);
0396 } else {
0397
0398 memcpy(NewElts, Begin, CurSize * sizeof(T));
0399 }
0400 }
0401
0402
0403 Begin = NewElts;
0404 End = NewElts+CurSize;
0405 Capacity.setPointer(Begin+NewCapacity);
0406 }
0407
0408 }
0409
0410 #endif