File indexing completed on 2026-05-10 08:43:01
0001
0002
0003
0004
0005
0006
0007
0008
0009 #ifndef LLVM_ADT_ALLOCATORLIST_H
0010 #define LLVM_ADT_ALLOCATORLIST_H
0011
0012 #include "llvm/ADT/ilist_node.h"
0013 #include "llvm/ADT/iterator.h"
0014 #include "llvm/ADT/simple_ilist.h"
0015 #include "llvm/Support/Allocator.h"
0016 #include <cassert>
0017 #include <cstddef>
0018 #include <iterator>
0019 #include <type_traits>
0020 #include <utility>
0021
0022 namespace llvm {
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033 template <class T, class AllocatorT> class AllocatorList : AllocatorT {
0034 struct Node : ilist_node<Node> {
0035 Node(Node &&) = delete;
0036 Node(const Node &) = delete;
0037 Node &operator=(Node &&) = delete;
0038 Node &operator=(const Node &) = delete;
0039
0040 Node(T &&V) : V(std::move(V)) {}
0041 Node(const T &V) : V(V) {}
0042 template <class... Ts> Node(Ts &&... Vs) : V(std::forward<Ts>(Vs)...) {}
0043 T V;
0044 };
0045
0046 using list_type = simple_ilist<Node>;
0047
0048 list_type List;
0049
0050 AllocatorT &getAlloc() { return *this; }
0051 const AllocatorT &getAlloc() const { return *this; }
0052
0053 template <class... ArgTs> Node *create(ArgTs &&... Args) {
0054 return new (getAlloc()) Node(std::forward<ArgTs>(Args)...);
0055 }
0056
0057 struct Cloner {
0058 AllocatorList &AL;
0059
0060 Cloner(AllocatorList &AL) : AL(AL) {}
0061
0062 Node *operator()(const Node &N) const { return AL.create(N.V); }
0063 };
0064
0065 struct Disposer {
0066 AllocatorList &AL;
0067
0068 Disposer(AllocatorList &AL) : AL(AL) {}
0069
0070 void operator()(Node *N) const {
0071 N->~Node();
0072 AL.getAlloc().Deallocate(N);
0073 }
0074 };
0075
0076 public:
0077 using value_type = T;
0078 using pointer = T *;
0079 using reference = T &;
0080 using const_pointer = const T *;
0081 using const_reference = const T &;
0082 using size_type = typename list_type::size_type;
0083 using difference_type = typename list_type::difference_type;
0084
0085 private:
0086 template <class ValueT, class IteratorBase>
0087 class IteratorImpl
0088 : public iterator_adaptor_base<IteratorImpl<ValueT, IteratorBase>,
0089 IteratorBase,
0090 std::bidirectional_iterator_tag, ValueT> {
0091 template <class OtherValueT, class OtherIteratorBase>
0092 friend class IteratorImpl;
0093 friend AllocatorList;
0094
0095 using base_type =
0096 iterator_adaptor_base<IteratorImpl<ValueT, IteratorBase>, IteratorBase,
0097 std::bidirectional_iterator_tag, ValueT>;
0098
0099 public:
0100 using value_type = ValueT;
0101 using pointer = ValueT *;
0102 using reference = ValueT &;
0103
0104 IteratorImpl() = default;
0105 IteratorImpl(const IteratorImpl &) = default;
0106 IteratorImpl &operator=(const IteratorImpl &) = default;
0107
0108 explicit IteratorImpl(const IteratorBase &I) : base_type(I) {}
0109
0110 template <class OtherValueT, class OtherIteratorBase>
0111 IteratorImpl(const IteratorImpl<OtherValueT, OtherIteratorBase> &X,
0112 std::enable_if_t<std::is_convertible<
0113 OtherIteratorBase, IteratorBase>::value> * = nullptr)
0114 : base_type(X.wrapped()) {}
0115
0116 ~IteratorImpl() = default;
0117
0118 reference operator*() const { return base_type::wrapped()->V; }
0119 pointer operator->() const { return &operator*(); }
0120 };
0121
0122 public:
0123 using iterator = IteratorImpl<T, typename list_type::iterator>;
0124 using reverse_iterator =
0125 IteratorImpl<T, typename list_type::reverse_iterator>;
0126 using const_iterator =
0127 IteratorImpl<const T, typename list_type::const_iterator>;
0128 using const_reverse_iterator =
0129 IteratorImpl<const T, typename list_type::const_reverse_iterator>;
0130
0131 AllocatorList() = default;
0132 AllocatorList(AllocatorList &&X)
0133 : AllocatorT(std::move(X.getAlloc())), List(std::move(X.List)) {}
0134
0135 AllocatorList(const AllocatorList &X) {
0136 List.cloneFrom(X.List, Cloner(*this), Disposer(*this));
0137 }
0138
0139 AllocatorList &operator=(AllocatorList &&X) {
0140 clear();
0141 List = std::move(X.List);
0142 getAlloc() = std::move(X.getAlloc());
0143 return *this;
0144 }
0145
0146 AllocatorList &operator=(const AllocatorList &X) {
0147 List.cloneFrom(X.List, Cloner(*this), Disposer(*this));
0148 return *this;
0149 }
0150
0151 ~AllocatorList() { clear(); }
0152
0153 void swap(AllocatorList &RHS) {
0154 List.swap(RHS.List);
0155 std::swap(getAlloc(), RHS.getAlloc());
0156 }
0157
0158 bool empty() { return List.empty(); }
0159 size_t size() { return List.size(); }
0160
0161 iterator begin() { return iterator(List.begin()); }
0162 iterator end() { return iterator(List.end()); }
0163 const_iterator begin() const { return const_iterator(List.begin()); }
0164 const_iterator end() const { return const_iterator(List.end()); }
0165 reverse_iterator rbegin() { return reverse_iterator(List.rbegin()); }
0166 reverse_iterator rend() { return reverse_iterator(List.rend()); }
0167 const_reverse_iterator rbegin() const {
0168 return const_reverse_iterator(List.rbegin());
0169 }
0170 const_reverse_iterator rend() const {
0171 return const_reverse_iterator(List.rend());
0172 }
0173
0174 T &back() { return List.back().V; }
0175 T &front() { return List.front().V; }
0176 const T &back() const { return List.back().V; }
0177 const T &front() const { return List.front().V; }
0178
0179 template <class... Ts> iterator emplace(iterator I, Ts &&... Vs) {
0180 return iterator(List.insert(I.wrapped(), *create(std::forward<Ts>(Vs)...)));
0181 }
0182
0183 iterator insert(iterator I, T &&V) {
0184 return iterator(List.insert(I.wrapped(), *create(std::move(V))));
0185 }
0186 iterator insert(iterator I, const T &V) {
0187 return iterator(List.insert(I.wrapped(), *create(V)));
0188 }
0189
0190 template <class Iterator>
0191 void insert(iterator I, Iterator First, Iterator Last) {
0192 for (; First != Last; ++First)
0193 List.insert(I.wrapped(), *create(*First));
0194 }
0195
0196 iterator erase(iterator I) {
0197 return iterator(List.eraseAndDispose(I.wrapped(), Disposer(*this)));
0198 }
0199
0200 iterator erase(iterator First, iterator Last) {
0201 return iterator(
0202 List.eraseAndDispose(First.wrapped(), Last.wrapped(), Disposer(*this)));
0203 }
0204
0205 void clear() { List.clearAndDispose(Disposer(*this)); }
0206 void pop_back() { List.eraseAndDispose(--List.end(), Disposer(*this)); }
0207 void pop_front() { List.eraseAndDispose(List.begin(), Disposer(*this)); }
0208 void push_back(T &&V) { insert(end(), std::move(V)); }
0209 void push_front(T &&V) { insert(begin(), std::move(V)); }
0210 void push_back(const T &V) { insert(end(), V); }
0211 void push_front(const T &V) { insert(begin(), V); }
0212 template <class... Ts> void emplace_back(Ts &&... Vs) {
0213 emplace(end(), std::forward<Ts>(Vs)...);
0214 }
0215 template <class... Ts> void emplace_front(Ts &&... Vs) {
0216 emplace(begin(), std::forward<Ts>(Vs)...);
0217 }
0218
0219
0220
0221
0222 void resetAlloc() {
0223 assert(empty() && "Cannot reset allocator if not empty");
0224 getAlloc().Reset();
0225 }
0226 };
0227
0228 template <class T> using BumpPtrList = AllocatorList<T, BumpPtrAllocator>;
0229
0230 }
0231
0232 #endif