- //===- llvm/ADT/AllocatorList.h - Custom allocator list ---------*- C++ -*-===// 
- // 
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 
- // See https://llvm.org/LICENSE.txt for license information. 
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 
- // 
- //===----------------------------------------------------------------------===// 
-   
- #ifndef LLVM_ADT_ALLOCATORLIST_H 
- #define LLVM_ADT_ALLOCATORLIST_H 
-   
- #include "llvm/ADT/ilist_node.h" 
- #include "llvm/ADT/iterator.h" 
- #include "llvm/ADT/simple_ilist.h" 
- #include "llvm/Support/Allocator.h" 
- #include <cassert> 
- #include <cstddef> 
- #include <iterator> 
- #include <type_traits> 
- #include <utility> 
-   
- namespace llvm { 
-   
- /// A linked-list with a custom, local allocator. 
- /// 
- /// Expose a std::list-like interface that owns and uses a custom LLVM-style 
- /// allocator (e.g., BumpPtrAllocator), leveraging \a simple_ilist for the 
- /// implementation details. 
- /// 
- /// Because this list owns the allocator, calling \a splice() with a different 
- /// list isn't generally safe.  As such, \a splice has been left out of the 
- /// interface entirely. 
- template <class T, class AllocatorT> class AllocatorList : AllocatorT { 
-   struct Node : ilist_node<Node> { 
-     Node(Node &&) = delete; 
-     Node(const Node &) = delete; 
-     Node &operator=(Node &&) = delete; 
-     Node &operator=(const Node &) = delete; 
-   
-     Node(T &&V) : V(std::move(V)) {} 
-     Node(const T &V) : V(V) {} 
-     template <class... Ts> Node(Ts &&... Vs) : V(std::forward<Ts>(Vs)...) {} 
-     T V; 
-   }; 
-   
-   using list_type = simple_ilist<Node>; 
-   
-   list_type List; 
-   
-   AllocatorT &getAlloc() { return *this; } 
-   const AllocatorT &getAlloc() const { return *this; } 
-   
-   template <class... ArgTs> Node *create(ArgTs &&... Args) { 
-     return new (getAlloc()) Node(std::forward<ArgTs>(Args)...); 
-   } 
-   
-   struct Cloner { 
-     AllocatorList &AL; 
-   
-     Cloner(AllocatorList &AL) : AL(AL) {} 
-   
-     Node *operator()(const Node &N) const { return AL.create(N.V); } 
-   }; 
-   
-   struct Disposer { 
-     AllocatorList &AL; 
-   
-     Disposer(AllocatorList &AL) : AL(AL) {} 
-   
-     void operator()(Node *N) const { 
-       N->~Node(); 
-       AL.getAlloc().Deallocate(N); 
-     } 
-   }; 
-   
- public: 
-   using value_type = T; 
-   using pointer = T *; 
-   using reference = T &; 
-   using const_pointer = const T *; 
-   using const_reference = const T &; 
-   using size_type = typename list_type::size_type; 
-   using difference_type = typename list_type::difference_type; 
-   
- private: 
-   template <class ValueT, class IteratorBase> 
-   class IteratorImpl 
-       : public iterator_adaptor_base<IteratorImpl<ValueT, IteratorBase>, 
-                                      IteratorBase, 
-                                      std::bidirectional_iterator_tag, ValueT> { 
-     template <class OtherValueT, class OtherIteratorBase> 
-     friend class IteratorImpl; 
-     friend AllocatorList; 
-   
-     using base_type = 
-         iterator_adaptor_base<IteratorImpl<ValueT, IteratorBase>, IteratorBase, 
-                               std::bidirectional_iterator_tag, ValueT>; 
-   
-   public: 
-     using value_type = ValueT; 
-     using pointer = ValueT *; 
-     using reference = ValueT &; 
-   
-     IteratorImpl() = default; 
-     IteratorImpl(const IteratorImpl &) = default; 
-     IteratorImpl &operator=(const IteratorImpl &) = default; 
-   
-     explicit IteratorImpl(const IteratorBase &I) : base_type(I) {} 
-   
-     template <class OtherValueT, class OtherIteratorBase> 
-     IteratorImpl(const IteratorImpl<OtherValueT, OtherIteratorBase> &X, 
-                  std::enable_if_t<std::is_convertible< 
-                      OtherIteratorBase, IteratorBase>::value> * = nullptr) 
-         : base_type(X.wrapped()) {} 
-   
-     ~IteratorImpl() = default; 
-   
-     reference operator*() const { return base_type::wrapped()->V; } 
-     pointer operator->() const { return &operator*(); } 
-   }; 
-   
- public: 
-   using iterator = IteratorImpl<T, typename list_type::iterator>; 
-   using reverse_iterator = 
-       IteratorImpl<T, typename list_type::reverse_iterator>; 
-   using const_iterator = 
-       IteratorImpl<const T, typename list_type::const_iterator>; 
-   using const_reverse_iterator = 
-       IteratorImpl<const T, typename list_type::const_reverse_iterator>; 
-   
-   AllocatorList() = default; 
-   AllocatorList(AllocatorList &&X) 
-       : AllocatorT(std::move(X.getAlloc())), List(std::move(X.List)) {} 
-   
-   AllocatorList(const AllocatorList &X) { 
-     List.cloneFrom(X.List, Cloner(*this), Disposer(*this)); 
-   } 
-   
-   AllocatorList &operator=(AllocatorList &&X) { 
-     clear(); // Dispose of current nodes explicitly. 
-     List = std::move(X.List); 
-     getAlloc() = std::move(X.getAlloc()); 
-     return *this; 
-   } 
-   
-   AllocatorList &operator=(const AllocatorList &X) { 
-     List.cloneFrom(X.List, Cloner(*this), Disposer(*this)); 
-     return *this; 
-   } 
-   
-   ~AllocatorList() { clear(); } 
-   
-   void swap(AllocatorList &RHS) { 
-     List.swap(RHS.List); 
-     std::swap(getAlloc(), RHS.getAlloc()); 
-   } 
-   
-   bool empty() { return List.empty(); } 
-   size_t size() { return List.size(); } 
-   
-   iterator begin() { return iterator(List.begin()); } 
-   iterator end() { return iterator(List.end()); } 
-   const_iterator begin() const { return const_iterator(List.begin()); } 
-   const_iterator end() const { return const_iterator(List.end()); } 
-   reverse_iterator rbegin() { return reverse_iterator(List.rbegin()); } 
-   reverse_iterator rend() { return reverse_iterator(List.rend()); } 
-   const_reverse_iterator rbegin() const { 
-     return const_reverse_iterator(List.rbegin()); 
-   } 
-   const_reverse_iterator rend() const { 
-     return const_reverse_iterator(List.rend()); 
-   } 
-   
-   T &back() { return List.back().V; } 
-   T &front() { return List.front().V; } 
-   const T &back() const { return List.back().V; } 
-   const T &front() const { return List.front().V; } 
-   
-   template <class... Ts> iterator emplace(iterator I, Ts &&... Vs) { 
-     return iterator(List.insert(I.wrapped(), *create(std::forward<Ts>(Vs)...))); 
-   } 
-   
-   iterator insert(iterator I, T &&V) { 
-     return iterator(List.insert(I.wrapped(), *create(std::move(V)))); 
-   } 
-   iterator insert(iterator I, const T &V) { 
-     return iterator(List.insert(I.wrapped(), *create(V))); 
-   } 
-   
-   template <class Iterator> 
-   void insert(iterator I, Iterator First, Iterator Last) { 
-     for (; First != Last; ++First) 
-       List.insert(I.wrapped(), *create(*First)); 
-   } 
-   
-   iterator erase(iterator I) { 
-     return iterator(List.eraseAndDispose(I.wrapped(), Disposer(*this))); 
-   } 
-   
-   iterator erase(iterator First, iterator Last) { 
-     return iterator( 
-         List.eraseAndDispose(First.wrapped(), Last.wrapped(), Disposer(*this))); 
-   } 
-   
-   void clear() { List.clearAndDispose(Disposer(*this)); } 
-   void pop_back() { List.eraseAndDispose(--List.end(), Disposer(*this)); } 
-   void pop_front() { List.eraseAndDispose(List.begin(), Disposer(*this)); } 
-   void push_back(T &&V) { insert(end(), std::move(V)); } 
-   void push_front(T &&V) { insert(begin(), std::move(V)); } 
-   void push_back(const T &V) { insert(end(), V); } 
-   void push_front(const T &V) { insert(begin(), V); } 
-   template <class... Ts> void emplace_back(Ts &&... Vs) { 
-     emplace(end(), std::forward<Ts>(Vs)...); 
-   } 
-   template <class... Ts> void emplace_front(Ts &&... Vs) { 
-     emplace(begin(), std::forward<Ts>(Vs)...); 
-   } 
-   
-   /// Reset the underlying allocator. 
-   /// 
-   /// \pre \c empty() 
-   void resetAlloc() { 
-     assert(empty() && "Cannot reset allocator if not empty"); 
-     getAlloc().Reset(); 
-   } 
- }; 
-   
- template <class T> using BumpPtrList = AllocatorList<T, BumpPtrAllocator>; 
-   
- } // end namespace llvm 
-   
- #endif // LLVM_ADT_ALLOCATORLIST_H 
-