EricWF created this revision.
EricWF added reviewers: mclow.lists, howard.hinnant, STL_MSFT.
EricWF added a subscriber: cfe-commits.

To quote STL the problems with stack allocator are"

> "stack_allocator<T, N> is seriously nonconformant to N4582 17.6.3.5 
> [allocator.requirements].
>  First, it lacks a rebinding constructor. (The nested "struct rebind" isn't 
> sufficient.)
>  Second, it lacks templated equality/inequality.
>  Third, it completely ignores alignment.
>  Finally, and most severely, the Standard forbids its existence. Allocators 
> are forbidden from returning memory "inside themselves". This requirement is 
> implied by the Standard's requirements for rebinding and equality. It's 
> permitted to return memory from a separate buffer object on the stack, 
> though."

This patch attempts to address all of those issues.

First, instead of storing the buffer inside the allocator I've change 
`stack_allocator` to accept the buffer as an argument.

Second, in order to fix rebinding I changed the parameter list from `<class T, 
size_t NumElements>` to `<class T, size_t NumBytes>`. This allows allocator 
rebinding
between types that have different sizes.

Third, I added copy and rebinding constructors and assignment operators.

And finally I fixed the allocation logic to always return properly aligned 
storage.


https://reviews.llvm.org/D25154

Files:
  
test/std/containers/container.adaptors/priority.queue/priqueue.cons/ctor_comp.pass.cpp
  
test/std/containers/container.adaptors/priority.queue/priqueue.cons/ctor_default.pass.cpp
  test/std/containers/container.adaptors/queue/queue.cons/ctor_default.pass.cpp
  test/std/containers/container.adaptors/stack/stack.cons/ctor_default.pass.cpp
  test/std/containers/sequences/deque/deque.cons/alloc.pass.cpp
  test/std/containers/sequences/deque/deque.cons/default.pass.cpp
  test/std/containers/sequences/deque/deque.cons/iter_iter.pass.cpp
  test/std/containers/sequences/deque/deque.cons/size.pass.cpp
  test/std/containers/sequences/deque/deque.cons/size_value.pass.cpp
  test/std/containers/sequences/deque/deque.cons/size_value_alloc.pass.cpp
  test/std/containers/sequences/deque/deque.modifiers/insert_iter_iter.pass.cpp
  test/std/containers/sequences/list/list.cons/default_stack_alloc.pass.cpp
  test/std/containers/sequences/list/list.cons/input_iterator.pass.cpp
  test/std/containers/sequences/list/list.cons/size_type.pass.cpp
  test/std/containers/sequences/list/list.cons/size_value_alloc.pass.cpp
  test/std/containers/sequences/vector/vector.capacity/reserve.pass.cpp
  test/std/containers/sequences/vector/vector.capacity/resize_size.pass.cpp
  
test/std/containers/sequences/vector/vector.capacity/resize_size_value.pass.cpp
  test/std/containers/sequences/vector/vector.capacity/shrink_to_fit.pass.cpp
  test/std/containers/sequences/vector/vector.cons/construct_default.pass.cpp
  test/std/containers/sequences/vector/vector.cons/construct_iter_iter.pass.cpp
  
test/std/containers/sequences/vector/vector.cons/construct_iter_iter_alloc.pass.cpp
  test/std/containers/sequences/vector/vector.cons/construct_size_value.pass.cpp
  
test/std/containers/sequences/vector/vector.cons/construct_size_value_alloc.pass.cpp
  test/std/containers/sequences/vector/vector.modifiers/emplace.pass.cpp
  test/std/containers/sequences/vector/vector.modifiers/emplace_back.pass.cpp
  
test/std/containers/sequences/vector/vector.modifiers/insert_iter_iter_iter.pass.cpp
  
test/std/containers/sequences/vector/vector.modifiers/insert_iter_rvalue.pass.cpp
  
test/std/containers/sequences/vector/vector.modifiers/insert_iter_size_value.pass.cpp
  
test/std/containers/sequences/vector/vector.modifiers/insert_iter_value.pass.cpp
  test/std/containers/sequences/vector/vector.modifiers/pop_back.pass.cpp
  test/std/containers/sequences/vector/vector.modifiers/push_back.pass.cpp
  
test/std/containers/sequences/vector/vector.modifiers/push_back_rvalue.pass.cpp
  test/std/containers/stack_allocator.h
  test/support/stack_allocator.h
  test/support/test.support/test_stack_allocator.pass.cpp
  test/support/test_macros.h

Index: test/support/test_macros.h
===================================================================
--- test/support/test_macros.h
+++ test/support/test_macros.h
@@ -62,6 +62,24 @@
 #endif
 #endif
 
+#if TEST_STD_VER < 11
+#ifdef __clang__
+#define TEST_ALIGNOF(X) __alignof(X)
+#define TEST_ALIGNAS(X) __attribute__((__aligned__(X)))
+#elif defined(__GNUC__)
+#define TEST_ALIGNOF(X) __alignof(X)
+#define TEST_ALIGNAS(X) __attribute__((__aligned__(X)))
+#elif defined(_MSC_VER)
+#define TEST_ALIGNOF(X) __alignof__(X)
+#define TEST_ALIGNAS(X) __declspec(align(X))
+#else
+#error Unsupported compiler
+#endif
+#else // TEST_STD_VER >= 11
+#define TEST_ALIGNOF(X) alignof(X)
+#define TEST_ALIGNAS(X) alignas(X)
+#endif
+
 // Attempt to deduce GCC version
 #if defined(_LIBCPP_VERSION) && __has_include(<features.h>)
 #include <features.h>
Index: test/support/test.support/test_stack_allocator.pass.cpp
===================================================================
--- /dev/null
+++ test/support/test.support/test_stack_allocator.pass.cpp
@@ -0,0 +1,84 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+
+// "support/stack_allocator.h"
+
+#include "stack_allocator.h"
+
+#include "test_macros.h"
+
+template <size_t S, size_t A>
+struct TEST_ALIGNAS(A) AlignedType {
+  char buff[S];
+};
+
+static const size_t MA = TEST_ALIGNOF(std::max_align_t);
+
+typedef AlignedType<1, 1>  S1;
+typedef AlignedType<2, 2>  S2;
+typedef AlignedType<17, 1>  S17;
+typedef AlignedType<sizeof(void*), TEST_ALIGNOF(void*)>  SPtr;
+typedef AlignedType<MA, MA>  SMA;
+typedef AlignedType<MA * 2, MA>  SMA2;
+
+template <class T>
+void test_basic() {
+  typedef stack_buffer<T, 10> BuffT;
+  typedef typename BuffT::allocator_type AllocT;
+  BuffT SB;
+  AllocT SA(SB);
+  uintptr_t lastVal = 0;
+  for (size_t i=0; i < SA.max_size(); ++i) {
+    T* ptr = SA.allocate(1);
+    assert(ptr);
+    const uintptr_t PVal = reinterpret_cast<uintptr_t>(ptr);
+    assert(PVal % TEST_ALIGNOF(std::max_align_t) == 0);
+    assert(PVal >= (lastVal + sizeof(T)));
+    lastVal = PVal;
+  }
+#ifndef TEST_HAS_NO_EXCEPTIONS
+  try {
+    SA.allocate(1);
+    assert(false);
+  } catch (std::bad_alloc const&) {}
+#endif
+}
+
+template <class T1, size_t N1, class T2, size_t N2>
+void test_rebind() {
+  typedef stack_buffer<T1, N1> BuffT;
+  typedef typename BuffT::allocator_type AllocT;
+  BuffT SB, SB2;
+  AllocT SA(SB);
+  AllocT SA2(SB2);
+  typedef typename AllocT::template rebind<T2>::other OAllocT;
+  {
+    OAllocT SO(SA);
+    assert(SO == SA);
+    assert(SO != SA2);
+    SO = SA2;
+    assert(SO == SA2);
+    assert(SO != SA);
+  }
+  {
+    typedef typename OAllocT::template rebind<T1>::other BackAllocT;
+    static_assert((std::is_same<BackAllocT, AllocT>::value), "");
+  }
+};
+
+int main() {
+    test_basic<S1>();
+    test_basic<S2>();
+    test_basic<S17>();
+    test_basic<SPtr>();
+    test_basic<SMA>();
+    test_basic<SMA2>();
+    test_rebind<S1, 100, S2, 100>();
+}
Index: test/support/stack_allocator.h
===================================================================
--- /dev/null
+++ test/support/stack_allocator.h
@@ -0,0 +1,195 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef STACK_ALLOCATOR_H
+#define STACK_ALLOCATOR_H
+
+#include <cstddef>
+#include <memory>
+#include <new>
+#include <cassert>
+
+#include "test_macros.h"
+template <class T, std::size_t N> struct stack_allocator;
+
+const size_t MaxAlign = TEST_ALIGNOF(std::max_align_t);
+
+template <size_t S, size_t A = MaxAlign>
+struct AlignedAllocSize : std::integral_constant<size_t, (S + A - 1) & ~(A - 1)> {
+};
+
+inline size_t alignedAllocSize(size_t S, size_t A = MaxAlign) {
+  return (S + A - 1) & ~(A - 1);
+}
+
+struct stack_buffer_base {
+  const size_t size;
+  char* const buff;
+  char* const buff_end;
+  void* ptr;
+  void* last_alloc;
+  std::size_t remaining_size;
+
+  stack_buffer_base(char* buff_imp, size_t buff_size)
+      : size(buff_size), buff(buff_imp), buff_end(buff + size), ptr(buff),
+        last_alloc(nullptr), remaining_size(buff_size)
+  {
+    assert((buff_size % MaxAlign) == 0);
+  }
+
+  void reset() {
+    ptr = buff;
+    last_alloc = nullptr;
+    remaining_size = size;
+  }
+
+  template <class T>
+  void* allocate(size_t S) {
+    const size_t AllocSize = alignedAllocSize(sizeof(T)) * S;
+    if (std::align(MaxAlign, AllocSize, ptr, remaining_size)) {
+      void* ret = ptr;
+      ptr = static_cast<char*>(ptr) + AllocSize;
+      remaining_size -= AllocSize;
+      last_alloc = ret;
+      return ret;
+    }
+    return nullptr;
+  }
+
+  void deallocate(void* P, size_t S = 1) {
+    if (P == last_alloc) {
+      ptr = last_alloc;
+      last_alloc = nullptr;
+      remaining_size = buff_end - static_cast<char*>(ptr);
+    }
+  }
+
+  template <class T>
+  size_t max_size() const {
+    return size / alignedAllocSize(sizeof(T));
+  }
+
+private:
+  stack_buffer_base(stack_buffer_base const&);
+  stack_buffer_base& operator=(stack_buffer_base const&);
+};
+
+template <class T, size_t N>
+struct stack_buffer : stack_buffer_base {
+  static const size_t alloc_size = AlignedAllocSize<sizeof(T)>::value;
+  static const size_t NumBytes = alloc_size * N;
+
+public:
+  typedef stack_allocator<T, NumBytes> allocator_type;
+
+  stack_buffer() : stack_buffer_base(buff_imp, NumBytes) {}
+
+  allocator_type makeAlloc() {
+    allocator_type alloc(this);
+    return alloc;
+  }
+private:
+  TEST_ALIGNAS(MaxAlign) char buff_imp[NumBytes];
+
+  stack_buffer(stack_buffer const&);
+  stack_buffer& operator=(stack_buffer const&);
+};
+
+template <class T, std::size_t NumBytesP>
+class stack_allocator
+{
+    static_assert(AlignedAllocSize<sizeof(T)>::value <= NumBytesP, "");
+    static const size_t NumBytes = NumBytesP;
+    template <class U, std::size_t> friend struct stack_allocator;
+    stack_buffer_base* handle;
+public:
+    typedef T                 value_type;
+    typedef value_type*       pointer;
+    typedef const value_type* const_pointer;
+    typedef value_type&       reference;
+    typedef const value_type& const_reference;
+    typedef std::size_t       size_type;
+    typedef std::ptrdiff_t    difference_type;
+
+    template <class U> struct rebind {
+      typedef stack_allocator<U, NumBytes> other;
+    };
+
+    template <size_t NElem>
+    explicit stack_allocator(stack_buffer<T, NElem>& buff) : handle(&buff) {
+      static_assert((stack_buffer<T, NElem>::NumBytes == NumBytes), "");
+    }
+
+    stack_allocator(const stack_allocator& OA) : handle(OA.handle) {}
+    stack_allocator& operator=(const stack_allocator& OA)
+    { handle = OA.handle; return *this; }
+
+    template <class U>
+    explicit stack_allocator(stack_allocator<U, NumBytesP> const& OAlloc)
+        : handle(OAlloc.handle)
+    {
+    }
+
+    template <class U>
+    stack_allocator& operator=(stack_allocator<U, NumBytesP> const& other) {
+      handle = other.handle;
+      return *this;
+    }
+
+
+    stack_buffer_base* getBase() const { return handle; }
+    void reset() { getBase()->reset(); }
+public:
+    pointer allocate(size_type n, const void* = 0)
+    {
+        void* ptr = handle->allocate<T>(n);
+        if (!ptr) {
+#ifndef _LIBCPP_NO_EXCEPTIONS
+            throw std::bad_alloc();
+#else
+            std::terminate();
+#endif
+        }
+        return static_cast<pointer>(ptr);
+    }
+
+    void deallocate(pointer p, size_type n)
+    {
+        handle->deallocate(p, n);
+    }
+
+    size_type max_size() const {return NumBytes / alignedAllocSize(sizeof(T));}
+};
+
+template <class T, size_t TN, class U, size_t UN>
+inline bool operator==(stack_allocator<T, TN> const& LHS, stack_allocator<U, UN> const& RHS) {
+  return LHS.getBase() == RHS.getBase();
+}
+
+template <class T, size_t TN, class U, size_t UN>
+inline bool operator!=(stack_allocator<T, TN> const& LHS, stack_allocator<U, UN> const& RHS) {
+  return LHS.getBase() != RHS.getBase();
+}
+
+template <class T, std::size_t N>
+inline
+void
+swap(stack_allocator<T, N>& x, stack_allocator<T, N>& y) {}
+
+template <class VT, std::size_t NumElem>
+struct StackAllocTraits {
+  typedef stack_buffer<VT, NumElem> BuffT;
+  typedef typename BuffT::allocator_type AllocT;
+
+  StackAllocTraits() : buff(), alloc(buff) {}
+  BuffT buff;
+  AllocT alloc;
+};
+
+#endif  // STACK_ALLOCATOR_H
Index: test/std/containers/stack_allocator.h
===================================================================
--- test/std/containers/stack_allocator.h
+++ /dev/null
@@ -1,66 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef STACK_ALLOCATOR_H
-#define STACK_ALLOCATOR_H
-
-#include <cstddef>
-#include <new>
-
-template <class T, std::size_t N>
-class stack_allocator
-{
-    char buf_[sizeof(T)*N];
-    char* ptr_;
-public:
-    typedef T                 value_type;
-    typedef value_type*       pointer;
-    typedef const value_type* const_pointer;
-    typedef value_type&       reference;
-    typedef const value_type& const_reference;
-    typedef std::size_t       size_type;
-    typedef std::ptrdiff_t    difference_type;
-
-    template <class U> struct rebind {typedef stack_allocator<U, N> other;};
-
-    stack_allocator() : ptr_(buf_) {}
-
-private:
-    stack_allocator(const stack_allocator&);// = delete;
-    stack_allocator& operator=(const stack_allocator&);// = delete;
-
-public:
-    pointer allocate(size_type n, const void* = 0)
-    {
-        if (n > N - (ptr_ - buf_) / sizeof(value_type)) {
-#ifndef _LIBCPP_NO_EXCEPTIONS
-            throw std::bad_alloc();
-#else
-            std::terminate();
-#endif
-        }
-        pointer r = (T*)ptr_;
-        ptr_ += n * sizeof(T);
-        return r;
-    }
-    void deallocate(pointer p, size_type n)
-    {
-        if ((char*)(p + n) == ptr_)
-            ptr_ = (char*)p;
-    }
-
-    size_type max_size() const {return N;}
-};
-
-template <class T, std::size_t N>
-inline
-void
-swap(stack_allocator<T, N>& x, stack_allocator<T, N>& y) {}
-
-#endif  // STACK_ALLOCATOR_H
Index: test/std/containers/sequences/vector/vector.modifiers/push_back_rvalue.pass.cpp
===================================================================
--- test/std/containers/sequences/vector/vector.modifiers/push_back_rvalue.pass.cpp
+++ test/std/containers/sequences/vector/vector.modifiers/push_back_rvalue.pass.cpp
@@ -7,20 +7,21 @@
 //
 //===----------------------------------------------------------------------===//
 
+// UNSUPPORTED: c++98, c++03
+
 // <vector>
 
 // void push_back(value_type&& x);
 
 #include <vector>
 #include <cassert>
 #include "MoveOnly.h"
-#include "../../../stack_allocator.h"
+#include "stack_allocator.h"
 #include "min_allocator.h"
 #include "asan_testing.h"
 
 int main()
 {
-#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
     {
         std::vector<MoveOnly> c;
         c.push_back(MoveOnly(0));
@@ -50,7 +51,9 @@
             assert(c[j] == MoveOnly(j));
     }
     {
-        std::vector<MoveOnly, stack_allocator<MoveOnly, 15> > c;
+        typedef StackAllocTraits<MoveOnly, 15> Traits;
+        Traits T;
+        std::vector<MoveOnly, Traits::AllocT > c(T.alloc);
         c.push_back(MoveOnly(0));
         assert(c.size() == 1);
         assert(is_contiguous_container_asan_correct(c));
@@ -77,7 +80,6 @@
         for (int j = 0; j < c.size(); ++j)
             assert(c[j] == MoveOnly(j));
     }
-#if TEST_STD_VER >= 11
     {
         std::vector<MoveOnly, min_allocator<MoveOnly>> c;
         c.push_back(MoveOnly(0));
@@ -106,6 +108,4 @@
         for (int j = 0; j < c.size(); ++j)
             assert(c[j] == MoveOnly(j));
     }
-#endif
-#endif  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
 }
Index: test/std/containers/sequences/vector/vector.modifiers/push_back.pass.cpp
===================================================================
--- test/std/containers/sequences/vector/vector.modifiers/push_back.pass.cpp
+++ test/std/containers/sequences/vector/vector.modifiers/push_back.pass.cpp
@@ -13,7 +13,7 @@
 
 #include <vector>
 #include <cassert>
-#include "../../../stack_allocator.h"
+#include "stack_allocator.h"
 #include "min_allocator.h"
 #include "asan_testing.h"
 
@@ -48,7 +48,9 @@
             assert(c[j] == j);
     }
     {
-        std::vector<int, stack_allocator<int, 15> > c;
+        typedef StackAllocTraits<int, 15> Traits;
+        Traits T;
+        std::vector<int, Traits::AllocT > c(T.alloc);
         c.push_back(0);
         assert(c.size() == 1);
         assert(is_contiguous_container_asan_correct(c));
Index: test/std/containers/sequences/vector/vector.modifiers/pop_back.pass.cpp
===================================================================
--- test/std/containers/sequences/vector/vector.modifiers/pop_back.pass.cpp
+++ test/std/containers/sequences/vector/vector.modifiers/pop_back.pass.cpp
@@ -17,7 +17,6 @@
 
 #include <vector>
 #include <cassert>
-#include "../../../stack_allocator.h"
 #include "min_allocator.h"
 
 #if _LIBCPP_DEBUG >= 1
Index: test/std/containers/sequences/vector/vector.modifiers/insert_iter_value.pass.cpp
===================================================================
--- test/std/containers/sequences/vector/vector.modifiers/insert_iter_value.pass.cpp
+++ test/std/containers/sequences/vector/vector.modifiers/insert_iter_value.pass.cpp
@@ -17,7 +17,7 @@
 
 #include <vector>
 #include <cassert>
-#include "../../../stack_allocator.h"
+#include "stack_allocator.h"
 #include "min_allocator.h"
 #include "asan_testing.h"
 
@@ -68,8 +68,11 @@
             assert(v[j] == 0);
     }
     {
-        std::vector<int, stack_allocator<int, 300> > v(100);
-        std::vector<int, stack_allocator<int, 300> >::iterator i = v.insert(v.cbegin() + 10, 1);
+        typedef StackAllocTraits<int, 300> Traits;
+        typedef Traits::AllocT AllocT;
+        Traits T;
+        std::vector<int, AllocT > v(100, 0, T.alloc);
+        std::vector<int, AllocT >::iterator i = v.insert(v.cbegin() + 10, 1);
         assert(v.size() == 101);
         assert(is_contiguous_container_asan_correct(v));
         assert(i == v.begin() + 10);
Index: test/std/containers/sequences/vector/vector.modifiers/insert_iter_size_value.pass.cpp
===================================================================
--- test/std/containers/sequences/vector/vector.modifiers/insert_iter_size_value.pass.cpp
+++ test/std/containers/sequences/vector/vector.modifiers/insert_iter_size_value.pass.cpp
@@ -17,7 +17,7 @@
 
 #include <vector>
 #include <cassert>
-#include "../../../stack_allocator.h"
+#include "stack_allocator.h"
 #include "min_allocator.h"
 #include "asan_testing.h"
 
@@ -70,8 +70,11 @@
             assert(v[j] == 0);
     }
     {
-        std::vector<int, stack_allocator<int, 300> > v(100);
-        std::vector<int, stack_allocator<int, 300> >::iterator i = v.insert(v.cbegin() + 10, 5, 1);
+        typedef StackAllocTraits<int, 300> Traits;
+        typedef Traits::AllocT AllocT;
+        Traits T;
+        std::vector<int, AllocT > v(100, 0, T.alloc);
+        std::vector<int, AllocT >::iterator i = v.insert(v.cbegin() + 10, 5, 1);
         assert(v.size() == 105);
         assert(is_contiguous_container_asan_correct(v));
         assert(i == v.begin() + 10);
Index: test/std/containers/sequences/vector/vector.modifiers/insert_iter_rvalue.pass.cpp
===================================================================
--- test/std/containers/sequences/vector/vector.modifiers/insert_iter_rvalue.pass.cpp
+++ test/std/containers/sequences/vector/vector.modifiers/insert_iter_rvalue.pass.cpp
@@ -7,6 +7,8 @@
 //
 //===----------------------------------------------------------------------===//
 
+// UNSUPPORTED: c++98, c++03
+
 // <vector>
 
 // iterator insert(const_iterator position, value_type&& x);
@@ -17,14 +19,13 @@
 
 #include <vector>
 #include <cassert>
-#include "../../../stack_allocator.h"
+#include "stack_allocator.h"
 #include "MoveOnly.h"
 #include "min_allocator.h"
 #include "asan_testing.h"
 
 int main()
 {
-#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
     {
         std::vector<MoveOnly> v(100);
         std::vector<MoveOnly>::iterator i = v.insert(v.cbegin() + 10, MoveOnly(3));
@@ -39,8 +40,12 @@
             assert(v[j] == MoveOnly());
     }
     {
-        std::vector<MoveOnly, stack_allocator<MoveOnly, 300> > v(100);
-        std::vector<MoveOnly, stack_allocator<MoveOnly, 300> >::iterator i = v.insert(v.cbegin() + 10, MoveOnly(3));
+        typedef StackAllocTraits<MoveOnly, 300> Traits;
+        typedef Traits::AllocT AllocT;
+        Traits T;
+        std::vector<MoveOnly, AllocT > v(T.alloc);
+        v.resize(100);
+        std::vector<MoveOnly, AllocT >::iterator i = v.insert(v.cbegin() + 10, MoveOnly(3));
         assert(v.size() == 101);
         assert(is_contiguous_container_asan_correct(v));
         assert(i == v.begin() + 10);
@@ -59,7 +64,6 @@
         assert(false);
     }
 #endif
-#if TEST_STD_VER >= 11
     {
         std::vector<MoveOnly, min_allocator<MoveOnly>> v(100);
         std::vector<MoveOnly, min_allocator<MoveOnly>>::iterator i = v.insert(v.cbegin() + 10, MoveOnly(3));
@@ -81,6 +85,4 @@
         assert(false);
     }
 #endif
-#endif
-#endif  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
 }
Index: test/std/containers/sequences/vector/vector.modifiers/insert_iter_iter_iter.pass.cpp
===================================================================
--- test/std/containers/sequences/vector/vector.modifiers/insert_iter_iter_iter.pass.cpp
+++ test/std/containers/sequences/vector/vector.modifiers/insert_iter_iter_iter.pass.cpp
@@ -18,7 +18,7 @@
 
 #include <vector>
 #include <cassert>
-#include "../../../stack_allocator.h"
+#include "stack_allocator.h"
 #include "test_iterators.h"
 #include "min_allocator.h"
 #include "asan_testing.h"
@@ -96,7 +96,10 @@
             assert(v[j] == 0);
     }
     {
-        std::vector<int, stack_allocator<int, 308> > v(100);
+        typedef StackAllocTraits<int, 308> Traits;
+        typedef Traits::AllocT AllocT;
+        Traits T;
+        std::vector<int, AllocT > v(100, 0, T.alloc);
         int a[] = {1, 2, 3, 4, 5};
         const int N = sizeof(a)/sizeof(a[0]);
         std::vector<int>::iterator i = v.insert(v.cbegin() + 10, input_iterator<const int*>(a),
@@ -113,7 +116,10 @@
             assert(v[j] == 0);
     }
     {
-        std::vector<int, stack_allocator<int, 300> > v(100);
+        typedef StackAllocTraits<int, 300> Traits;
+        typedef Traits::AllocT AllocT;
+        Traits T;
+        std::vector<int, AllocT > v(100, 0, T.alloc);
         int a[] = {1, 2, 3, 4, 5};
         const int N = sizeof(a)/sizeof(a[0]);
         std::vector<int>::iterator i = v.insert(v.cbegin() + 10, forward_iterator<const int*>(a),
Index: test/std/containers/sequences/vector/vector.modifiers/emplace_back.pass.cpp
===================================================================
--- test/std/containers/sequences/vector/vector.modifiers/emplace_back.pass.cpp
+++ test/std/containers/sequences/vector/vector.modifiers/emplace_back.pass.cpp
@@ -15,7 +15,7 @@
 
 #include <vector>
 #include <cassert>
-#include "../../../stack_allocator.h"
+#include "stack_allocator.h"
 #include "min_allocator.h"
 #include "test_allocator.h"
 #include "asan_testing.h"
@@ -72,7 +72,9 @@
         assert(is_contiguous_container_asan_correct(c));
     }
     {
-        std::vector<A, stack_allocator<A, 4> > c;
+        typedef StackAllocTraits<A, 4> Traits;
+        Traits T;
+        std::vector<A, Traits::AllocT> c(T.alloc);
         A& r1 = c.emplace_back(2, 3.5);
         assert(c.size() == 1);
         assert(&r1 == &c.back());
Index: test/std/containers/sequences/vector/vector.modifiers/emplace.pass.cpp
===================================================================
--- test/std/containers/sequences/vector/vector.modifiers/emplace.pass.cpp
+++ test/std/containers/sequences/vector/vector.modifiers/emplace.pass.cpp
@@ -7,6 +7,8 @@
 //
 //===----------------------------------------------------------------------===//
 
+// UNSUPPORTED: c++98, c++03
+
 // <vector>
 
 // template <class... Args> iterator emplace(const_iterator pos, Args&&... args);
@@ -17,11 +19,10 @@
 
 #include <vector>
 #include <cassert>
-#include "../../../stack_allocator.h"
+#include "stack_allocator.h"
 #include "min_allocator.h"
 #include "asan_testing.h"
 
-#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
 
 class A
 {
@@ -55,11 +56,8 @@
     double getd() const {return d_;}
 };
 
-#endif  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
-
 int main()
 {
-#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
     {
         std::vector<A> c;
         std::vector<A>::iterator i = c.emplace(c.cbegin(), 2, 3.5);
@@ -88,8 +86,10 @@
         assert(is_contiguous_container_asan_correct(c));
     }
     {
-        std::vector<A, stack_allocator<A, 7> > c;
-        std::vector<A, stack_allocator<A, 7> >::iterator i = c.emplace(c.cbegin(), 2, 3.5);
+        typedef StackAllocTraits<A, 7> Traits;
+        Traits T;
+        std::vector<A, Traits::AllocT > c(T.alloc);
+        std::vector<A, Traits::AllocT >::iterator i = c.emplace(c.cbegin(), 2, 3.5);
         assert(i == c.begin());
         assert(c.size() == 1);
         assert(c.front().geti() == 2);
@@ -122,7 +122,6 @@
         assert(false);
     }
 #endif
-#if TEST_STD_VER >= 11
     {
         std::vector<A, min_allocator<A>> c;
         std::vector<A, min_allocator<A>>::iterator i = c.emplace(c.cbegin(), 2, 3.5);
@@ -155,6 +154,5 @@
         assert(false);
     }
 #endif
-#endif
-#endif  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
+
 }
Index: test/std/containers/sequences/vector/vector.cons/construct_size_value_alloc.pass.cpp
===================================================================
--- test/std/containers/sequences/vector/vector.cons/construct_size_value_alloc.pass.cpp
+++ test/std/containers/sequences/vector/vector.cons/construct_size_value_alloc.pass.cpp
@@ -15,6 +15,7 @@
 #include <cassert>
 
 #include "test_macros.h"
+#include "stack_allocator.h"
 #include "min_allocator.h"
 #include "asan_testing.h"
 
@@ -35,6 +36,12 @@
 int main()
 {
     test<std::vector<int> >(50, 3, std::allocator<int>());
+    {
+        typedef StackAllocTraits<int, 50> Traits;
+        typedef Traits::AllocT AllocT;
+        Traits T;
+        test<std::vector<int, AllocT> >(50, 5, T.alloc);
+    }
 #if TEST_STD_VER >= 11
     test<std::vector<int, min_allocator<int>> >(50, 3, min_allocator<int>());
 #endif
Index: test/std/containers/sequences/vector/vector.cons/construct_size_value.pass.cpp
===================================================================
--- test/std/containers/sequences/vector/vector.cons/construct_size_value.pass.cpp
+++ test/std/containers/sequences/vector/vector.cons/construct_size_value.pass.cpp
@@ -15,7 +15,6 @@
 #include <cassert>
 
 #include "test_macros.h"
-#include "../../../stack_allocator.h"
 #include "min_allocator.h"
 #include "asan_testing.h"
 
@@ -34,7 +33,6 @@
 int main()
 {
     test<std::vector<int> >(50, 3);
-    test<std::vector<int, stack_allocator<int, 50> > >(50, 5);
 #if TEST_STD_VER >= 11
     test<std::vector<int, min_allocator<int>> >(50, 3);
 #endif
Index: test/std/containers/sequences/vector/vector.cons/construct_iter_iter_alloc.pass.cpp
===================================================================
--- test/std/containers/sequences/vector/vector.cons/construct_iter_iter_alloc.pass.cpp
+++ test/std/containers/sequences/vector/vector.cons/construct_iter_iter_alloc.pass.cpp
@@ -17,7 +17,7 @@
 
 #include "test_macros.h"
 #include "test_iterators.h"
-#include "../../../stack_allocator.h"
+#include "stack_allocator.h"
 #include "min_allocator.h"
 #include "asan_testing.h"
 
@@ -47,6 +47,7 @@
 
 #endif
 
+
 int main()
 {
     {
@@ -59,6 +60,21 @@
     test<std::vector<int> >(random_access_iterator<const int*>(a), random_access_iterator<const int*>(an), alloc);
     test<std::vector<int> >(a, an, alloc);
     }
+    {
+    int a[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 8, 7, 6, 5, 4, 3, 1, 0};
+    int* an = a + sizeof(a)/sizeof(a[0]);
+    typedef StackAllocTraits<int, 18> Traits;
+    typedef Traits::AllocT AllocT;
+    Traits T;
+    AllocT& A = T.alloc;
+    test<std::vector<int, AllocT> >(forward_iterator<const int*>(a), forward_iterator<const int*>(an), A);
+    A.reset();
+    test<std::vector<int, AllocT> >(bidirectional_iterator<const int*>(a), bidirectional_iterator<const int*>(an), A);
+    A.reset();
+    test<std::vector<int, AllocT > >(random_access_iterator<const int*>(a), random_access_iterator<const int*>(an), A);
+    A.reset();
+    test<std::vector<int, AllocT > >(a, an, A);
+    }
 #if TEST_STD_VER >= 11
     {
     int a[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 8, 7, 6, 5, 4, 3, 1, 0};
Index: test/std/containers/sequences/vector/vector.cons/construct_iter_iter.pass.cpp
===================================================================
--- test/std/containers/sequences/vector/vector.cons/construct_iter_iter.pass.cpp
+++ test/std/containers/sequences/vector/vector.cons/construct_iter_iter.pass.cpp
@@ -16,7 +16,6 @@
 
 #include "test_macros.h"
 #include "test_iterators.h"
-#include "../../../stack_allocator.h"
 #include "min_allocator.h"
 #include "asan_testing.h"
 
@@ -32,6 +31,7 @@
         assert(*i == *first);
 }
 
+
 int main()
 {
     int a[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 8, 7, 6, 5, 4, 3, 1, 0};
@@ -42,11 +42,6 @@
     test<std::vector<int> >(random_access_iterator<const int*>(a), random_access_iterator<const int*>(an));
     test<std::vector<int> >(a, an);
 
-    test<std::vector<int, stack_allocator<int, 63> > >(input_iterator<const int*>(a), input_iterator<const int*>(an));
-    test<std::vector<int, stack_allocator<int, 18> > >(forward_iterator<const int*>(a), forward_iterator<const int*>(an));
-    test<std::vector<int, stack_allocator<int, 18> > >(bidirectional_iterator<const int*>(a), bidirectional_iterator<const int*>(an));
-    test<std::vector<int, stack_allocator<int, 18> > >(random_access_iterator<const int*>(a), random_access_iterator<const int*>(an));
-    test<std::vector<int, stack_allocator<int, 18> > >(a, an);
 #if TEST_STD_VER >= 11
     test<std::vector<int, min_allocator<int>> >(input_iterator<const int*>(a), input_iterator<const int*>(an));
     test<std::vector<int, min_allocator<int>> >(forward_iterator<const int*>(a), forward_iterator<const int*>(an));
Index: test/std/containers/sequences/vector/vector.cons/construct_default.pass.cpp
===================================================================
--- test/std/containers/sequences/vector/vector.cons/construct_default.pass.cpp
+++ test/std/containers/sequences/vector/vector.cons/construct_default.pass.cpp
@@ -18,7 +18,7 @@
 #include "test_macros.h"
 #include "test_allocator.h"
 #include "../../../NotConstructible.h"
-#include "../../../stack_allocator.h"
+#include "stack_allocator.h"
 #include "min_allocator.h"
 #include "asan_testing.h"
 
@@ -49,10 +49,11 @@
 void
 test1(const typename C::allocator_type& a)
 {
+    typedef typename C::allocator_type AllocT;
 #if TEST_STD_VER > 14
-	static_assert((noexcept(C{typename C::allocator_type{}})), "" );
+	static_assert(noexcept(C(a)), "" );
 #elif TEST_STD_VER >= 11
-	static_assert((noexcept(C(typename C::allocator_type())) == std::is_nothrow_copy_constructible<typename C::allocator_type>::value), "" );
+  static_assert(noexcept(C(a)) == std::is_nothrow_copy_constructible<AllocT>::value, "");
 #endif
     C c(a);
     LIBCPP_ASSERT(c.__invariants());
@@ -71,8 +72,11 @@
         (test_allocator<NotConstructible>(5));
     }
     {
-        std::vector<int, stack_allocator<int, 10> > v;
-        assert(v.empty());
+
+        typedef StackAllocTraits<int, 1> TraitsT;
+        typedef TraitsT::AllocT AllocT;
+        TraitsT T;
+        test1<std::vector<int, AllocT> >(T.alloc);
     }
 #if TEST_STD_VER >= 11
     {
Index: test/std/containers/sequences/vector/vector.capacity/shrink_to_fit.pass.cpp
===================================================================
--- test/std/containers/sequences/vector/vector.capacity/shrink_to_fit.pass.cpp
+++ test/std/containers/sequences/vector/vector.capacity/shrink_to_fit.pass.cpp
@@ -13,9 +13,10 @@
 
 #include <vector>
 #include <cassert>
-#include "../../../stack_allocator.h"
+#include "stack_allocator.h"
 #include "min_allocator.h"
 #include "asan_testing.h"
+#include <iostream>
 
 int main()
 {
@@ -29,17 +30,21 @@
         assert(is_contiguous_container_asan_correct(v));
     }
     {
-        std::vector<int, stack_allocator<int, 401> > v(100);
+        typedef StackAllocTraits<int, 401> Traits;
+        Traits T;
+        std::vector<int, Traits::AllocT > v(100, 0, T.alloc);
         v.push_back(1);
         assert(is_contiguous_container_asan_correct(v));
         v.shrink_to_fit();
         assert(v.capacity() == 101);
         assert(v.size() == 101);
         assert(is_contiguous_container_asan_correct(v));
     }
-#ifndef _LIBCPP_NO_EXCEPTIONS
+#ifndef TEST_HAS_NO_EXCEPTIONS
     {
-        std::vector<int, stack_allocator<int, 400> > v(100);
+        typedef StackAllocTraits<int, 400> Traits;
+        Traits T;
+        std::vector<int, Traits::AllocT > v(100, 0, T.alloc);
         v.push_back(1);
         assert(is_contiguous_container_asan_correct(v));
         v.shrink_to_fit();
Index: test/std/containers/sequences/vector/vector.capacity/resize_size_value.pass.cpp
===================================================================
--- test/std/containers/sequences/vector/vector.capacity/resize_size_value.pass.cpp
+++ test/std/containers/sequences/vector/vector.capacity/resize_size_value.pass.cpp
@@ -13,7 +13,7 @@
 
 #include <vector>
 #include <cassert>
-#include "../../../stack_allocator.h"
+#include "stack_allocator.h"
 #include "min_allocator.h"
 #include "asan_testing.h"
 
@@ -35,7 +35,9 @@
             assert(v[i] == 1);
     }
     {
-        std::vector<int, stack_allocator<int, 300> > v(100);
+        typedef StackAllocTraits<int, 300> Traits;
+        Traits T;
+        std::vector<int, Traits::AllocT > v(100, 0, T.alloc);
         v.resize(50, 1);
         assert(v.size() == 50);
         assert(v.capacity() == 100);
Index: test/std/containers/sequences/vector/vector.capacity/resize_size.pass.cpp
===================================================================
--- test/std/containers/sequences/vector/vector.capacity/resize_size.pass.cpp
+++ test/std/containers/sequences/vector/vector.capacity/resize_size.pass.cpp
@@ -13,14 +13,14 @@
 
 #include <vector>
 #include <cassert>
-#include "../../../stack_allocator.h"
+#include "stack_allocator.h"
 #include "MoveOnly.h"
 #include "min_allocator.h"
 #include "asan_testing.h"
 
 int main()
 {
-#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
+#if TEST_STD_VER >= 11
     {
         std::vector<MoveOnly> v(100);
         v.resize(50);
@@ -33,7 +33,10 @@
         assert(is_contiguous_container_asan_correct(v));
     }
     {
-        std::vector<MoveOnly, stack_allocator<MoveOnly, 300> > v(100);
+        typedef StackAllocTraits<MoveOnly, 300> Traits;
+        Traits T;
+        std::vector<MoveOnly, Traits::AllocT > v(T.alloc);
+        v.resize(100);
         v.resize(50);
         assert(v.size() == 50);
         assert(v.capacity() == 100);
@@ -43,7 +46,7 @@
         assert(v.capacity() >= 200);
         assert(is_contiguous_container_asan_correct(v));
     }
-#else  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
+#endif
     {
         std::vector<int> v(100);
         v.resize(50);
@@ -56,7 +59,10 @@
         assert(is_contiguous_container_asan_correct(v));
     }
     {
-        std::vector<int, stack_allocator<int, 300> > v(100);
+        typedef StackAllocTraits<int, 300> Traits;
+        Traits T;
+        std::vector<int, Traits::AllocT > v(T.alloc);
+        v.resize(100);
         v.resize(50);
         assert(v.size() == 50);
         assert(v.capacity() == 100);
@@ -66,7 +72,6 @@
         assert(v.capacity() >= 200);
         assert(is_contiguous_container_asan_correct(v));
     }
-#endif  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
 #if TEST_STD_VER >= 11
     {
         std::vector<MoveOnly, min_allocator<MoveOnly>> v(100);
Index: test/std/containers/sequences/vector/vector.capacity/reserve.pass.cpp
===================================================================
--- test/std/containers/sequences/vector/vector.capacity/reserve.pass.cpp
+++ test/std/containers/sequences/vector/vector.capacity/reserve.pass.cpp
@@ -13,7 +13,7 @@
 
 #include <vector>
 #include <cassert>
-#include "../../../stack_allocator.h"
+#include "stack_allocator.h"
 #include "min_allocator.h"
 #include "asan_testing.h"
 
@@ -37,7 +37,9 @@
         assert(is_contiguous_container_asan_correct(v));
     }
     {
-        std::vector<int, stack_allocator<int, 250> > v(100);
+        typedef StackAllocTraits<int, 250> Traits;
+        Traits T;
+        std::vector<int, Traits::AllocT > v(100, 0, T.alloc);
         assert(v.capacity() == 100);
         v.reserve(50);
         assert(v.size() == 100);
Index: test/std/containers/sequences/list/list.cons/size_value_alloc.pass.cpp
===================================================================
--- test/std/containers/sequences/list/list.cons/size_value_alloc.pass.cpp
+++ test/std/containers/sequences/list/list.cons/size_value_alloc.pass.cpp
@@ -14,7 +14,7 @@
 #include <list>
 #include <cassert>
 #include "DefaultOnly.h"
-#include "../../../stack_allocator.h"
+#include "stack_allocator.h"
 #include "min_allocator.h"
 
 int main()
@@ -42,7 +42,13 @@
         assert(*i == 2);
     }
     {
-        std::list<int, stack_allocator<int, 3> > l(3, 2);
+        // FIXME The list rebinds the allocator internally and it needs
+        // space for more than 3 elements.
+        typedef StackAllocTraits<int, 100> Traits;
+        typedef Traits::AllocT AllocT;
+        Traits T;
+        std::list<int, AllocT > l(3, 2, T.alloc);
+        assert(l.get_allocator() == T.alloc);
         assert(l.size() == 3);
         assert(std::distance(l.begin(), l.end()) == 3);
         std::list<int>::const_iterator i = l.begin();
Index: test/std/containers/sequences/list/list.cons/size_type.pass.cpp
===================================================================
--- test/std/containers/sequences/list/list.cons/size_type.pass.cpp
+++ test/std/containers/sequences/list/list.cons/size_type.pass.cpp
@@ -14,7 +14,7 @@
 #include <list>
 #include <cassert>
 #include "DefaultOnly.h"
-#include "../../../stack_allocator.h"
+#include "stack_allocator.h"
 #include "min_allocator.h"
 
 template <class T, class Allocator>
@@ -47,8 +47,14 @@
         ++i;
         assert(*i == 0);
     }
+#if TEST_STD_VER >= 14
     {
-        std::list<int, stack_allocator<int, 3> > l(3);
+        // FIXME The list rebinds the allocator internally and it needs
+        // space for more than 3 elements.
+        typedef StackAllocTraits<int, 100> Traits;
+        typedef Traits::AllocT AllocT;
+        Traits T;
+        std::list<int, AllocT > l(3, T.alloc);
         assert(l.size() == 3);
         assert(std::distance(l.begin(), l.end()) == 3);
         std::list<int>::const_iterator i = l.begin();
@@ -58,7 +64,6 @@
         ++i;
         assert(*i == 0);
     }
-#if _LIBCPP_STD_VER > 11
     {
         typedef std::list<int, min_allocator<int> > C;
         C l(3, min_allocator<int> ());
@@ -73,14 +78,12 @@
         test3<int, min_allocator<int>> (3);
     }
 #endif
-#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
+#if TEST_STD_VER >= 11
     {
         std::list<DefaultOnly> l(3);
         assert(l.size() == 3);
         assert(std::distance(l.begin(), l.end()) == 3);
     }
-#endif  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
-#if TEST_STD_VER >= 11
     {
         std::list<int, min_allocator<int>> l(3);
         assert(l.size() == 3);
@@ -92,12 +95,10 @@
         ++i;
         assert(*i == 0);
     }
-#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
     {
         std::list<DefaultOnly, min_allocator<DefaultOnly>> l(3);
         assert(l.size() == 3);
         assert(std::distance(l.begin(), l.end()) == 3);
     }
-#endif  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
 #endif
 }
Index: test/std/containers/sequences/list/list.cons/input_iterator.pass.cpp
===================================================================
--- test/std/containers/sequences/list/list.cons/input_iterator.pass.cpp
+++ test/std/containers/sequences/list/list.cons/input_iterator.pass.cpp
@@ -15,7 +15,7 @@
 #include <list>
 #include <cassert>
 #include "test_iterators.h"
-#include "../../../stack_allocator.h"
+#include "stack_allocator.h"
 #include "min_allocator.h"
 
 int main()
@@ -42,9 +42,14 @@
             assert(*i == j);
     }
     {
+
         int a[] = {0, 1, 2, 3};
-        std::list<int, stack_allocator<int, sizeof(a)/sizeof(a[0])> > l(input_iterator<const int*>(a),
-                         input_iterator<const int*>(a + sizeof(a)/sizeof(a[0])));
+        typedef StackAllocTraits<int, 1000> Traits;
+        typedef Traits::AllocT AllocT;
+        Traits T;
+        std::list<int, AllocT > l(input_iterator<const int*>(a),
+                         input_iterator<const int*>(a + sizeof(a)/sizeof(a[0])),
+                        T.alloc);
         assert(l.size() == sizeof(a)/sizeof(a[0]));
         assert(std::distance(l.begin(), l.end()) == sizeof(a)/sizeof(a[0]));
         int j = 0;
Index: test/std/containers/sequences/list/list.cons/default_stack_alloc.pass.cpp
===================================================================
--- test/std/containers/sequences/list/list.cons/default_stack_alloc.pass.cpp
+++ test/std/containers/sequences/list/list.cons/default_stack_alloc.pass.cpp
@@ -13,7 +13,7 @@
 
 #include <list>
 #include <cassert>
-#include "../../../stack_allocator.h"
+#include "stack_allocator.h"
 #include "min_allocator.h"
 
 int main()
@@ -29,7 +29,11 @@
         assert(std::distance(l.begin(), l.end()) == 0);
     }
     {
-        std::list<int, stack_allocator<int, 4> > l;
+        typedef StackAllocTraits<int, 4> Traits;
+        typedef Traits::AllocT AllocT;
+        Traits T;
+        std::list<int, AllocT> l(T.alloc);
+        assert(l.get_allocator() == T.alloc);
         assert(l.size() == 0);
         assert(std::distance(l.begin(), l.end()) == 0);
     }
Index: test/std/containers/sequences/deque/deque.modifiers/insert_iter_iter.pass.cpp
===================================================================
--- test/std/containers/sequences/deque/deque.modifiers/insert_iter_iter.pass.cpp
+++ test/std/containers/sequences/deque/deque.modifiers/insert_iter_iter.pass.cpp
@@ -20,7 +20,7 @@
 #include "test_macros.h"
 #include "test_iterators.h"
 #include "MoveOnly.h"
-#include "../../../stack_allocator.h"
+#include "stack_allocator.h"
 #include "min_allocator.h"
 
 template <class C>
@@ -233,12 +233,12 @@
     }
 }
 
-template <class C>
+template <class C, class Alloc = typename C::allocator_type>
 void
-test_move()
+test_move(Alloc const& A = Alloc())
 {
 #if TEST_STD_VER >= 11
-    C c;
+    C c(A);
     typedef typename C::const_iterator CI;
     {
         MoveOnly mo(0);
@@ -270,7 +270,12 @@
                 testN<std::deque<int> >(rng[i], rng[j], rng[k]);
     testNI<std::deque<int> >(1500, 2000, 1000);
 #if TEST_STD_VER >= 11
-    test_move<std::deque<MoveOnly, stack_allocator<MoveOnly, 2000> > >();
+    {
+        typedef StackAllocTraits<MoveOnly, 2000> Traits;
+        typedef std::deque<MoveOnly, Traits::AllocT> C;
+        Traits T;
+        test_move<C>(T.alloc);
+    }
 #endif
     }
 #if TEST_STD_VER >= 11
Index: test/std/containers/sequences/deque/deque.cons/size_value_alloc.pass.cpp
===================================================================
--- test/std/containers/sequences/deque/deque.cons/size_value_alloc.pass.cpp
+++ test/std/containers/sequences/deque/deque.cons/size_value_alloc.pass.cpp
@@ -14,6 +14,7 @@
 #include <deque>
 #include <cassert>
 
+#include "stack_allocator.h"
 #include "min_allocator.h"
 
 template <class T, class Allocator>
@@ -47,6 +48,23 @@
     test(4096, 1165, a);
     test(4097, 157, a);
     }
+    {
+        typedef StackAllocTraits<int, 10000> Traits;
+        Traits T;
+        Traits::AllocT& a = T.alloc;
+        test(0, 5, a); a.reset();
+        test(1, 10, a); a.reset();
+        test(10, 11, a); a.reset();
+        test(1023, -11, a); a.reset();
+        test(1024, 25, a); a.reset();
+        test(1025, 0, a); a.reset();
+        test(2047, 110, a); a.reset();
+        test(2048, -500, a); a.reset();
+        test(2049, 654, a); a.reset();
+        test(4095, 78, a); a.reset();
+        test(4096, 1165, a); a.reset();
+        test(4097, 157, a); a.reset();
+    }
 #if TEST_STD_VER >= 11
     {
     min_allocator<int> a;
@@ -63,5 +81,7 @@
     test(4096, 1165, a);
     test(4097, 157, a);
     }
+    {
+    }
 #endif
 }
Index: test/std/containers/sequences/deque/deque.cons/size_value.pass.cpp
===================================================================
--- test/std/containers/sequences/deque/deque.cons/size_value.pass.cpp
+++ test/std/containers/sequences/deque/deque.cons/size_value.pass.cpp
@@ -14,7 +14,7 @@
 #include <deque>
 #include <cassert>
 
-#include "../../../stack_allocator.h"
+#include "stack_allocator.h"
 #include "min_allocator.h"
 
 template <class T, class Allocator>
@@ -44,7 +44,7 @@
     test<int, std::allocator<int> >(4095, 78);
     test<int, std::allocator<int> >(4096, 1165);
     test<int, std::allocator<int> >(4097, 157);
-    test<int, stack_allocator<int, 4096> >(4095, 90);
+
 #if TEST_STD_VER >= 11
     test<int, min_allocator<int> >(4095, 90);
 #endif
Index: test/std/containers/sequences/deque/deque.cons/size.pass.cpp
===================================================================
--- test/std/containers/sequences/deque/deque.cons/size.pass.cpp
+++ test/std/containers/sequences/deque/deque.cons/size.pass.cpp
@@ -14,27 +14,26 @@
 #include <deque>
 #include <cassert>
 
-#include "../../../stack_allocator.h"
+#include "test_macros.h"
+#include "stack_allocator.h"
 #include "DefaultOnly.h"
 #include "min_allocator.h"
 
 template <class T, class Allocator>
 void
 test2(unsigned n)
 {
-#if _LIBCPP_STD_VER > 11
+#if TEST_STD_VER >= 14
     typedef std::deque<T, Allocator> C;
     typedef typename C::const_iterator const_iterator;
     assert(DefaultOnly::count == 0);
     {
     C d(n, Allocator());
     assert(DefaultOnly::count == n);
     assert(d.size() == n);
     assert(distance(d.begin(), d.end()) == d.size());
-#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
     for (const_iterator i = d.begin(), e = d.end(); i != e; ++i)
         assert(*i == T());
-#endif  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
     }
     assert(DefaultOnly::count == 0);
 #endif
@@ -52,19 +51,19 @@
     assert(DefaultOnly::count == n);
     assert(d.size() == n);
     assert(distance(d.begin(), d.end()) == d.size());
-#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
+#if TEST_STD_VER >= 11
     for (const_iterator i = d.begin(), e = d.end(); i != e; ++i)
         assert(*i == T());
-#endif  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
+#endif
     }
     assert(DefaultOnly::count == 0);
 }
 
 template <class T, class Allocator>
 void
 test3(unsigned n, Allocator const &alloc = Allocator())
 {
-#if _LIBCPP_STD_VER > 11
+#if TEST_STD_VER >= 14
     typedef std::deque<T, Allocator> C;
     typedef typename C::const_iterator const_iterator;
     {
@@ -98,16 +97,21 @@
     test<DefaultOnly, std::allocator<DefaultOnly> >(4096);
     test<DefaultOnly, std::allocator<DefaultOnly> >(4097);
 
-    test1<DefaultOnly, stack_allocator<DefaultOnly, 4096> >(4095);
 
 #if TEST_STD_VER >= 11
     test<DefaultOnly, min_allocator<DefaultOnly> >(4095);
 #endif
 
-#if _LIBCPP_STD_VER > 11
+#if TEST_STD_VER >= 14
     test3<DefaultOnly, std::allocator<DefaultOnly>> (1023);
     test3<int, std::allocator<int>>(1);
     test3<int, min_allocator<int>> (3);
+    {
+        // FIXME: The deque only uses 4096 elements but it needs extra room.
+        typedef StackAllocTraits<DefaultOnly, 100000> Traits;
+        Traits T;
+        test3<DefaultOnly>(4095, T.alloc);
+    }
 #endif
 
 }
Index: test/std/containers/sequences/deque/deque.cons/iter_iter.pass.cpp
===================================================================
--- test/std/containers/sequences/deque/deque.cons/iter_iter.pass.cpp
+++ test/std/containers/sequences/deque/deque.cons/iter_iter.pass.cpp
@@ -14,7 +14,7 @@
 #include <deque>
 #include <cassert>
 
-#include "../../../stack_allocator.h"
+#include "stack_allocator.h"
 #include "test_iterators.h"
 #include "min_allocator.h"
 
@@ -33,14 +33,14 @@
         assert(*i == *f);
 }
 
-template <class Allocator, class InputIterator>
+template <class InputIterator, class Alloc>
 void
-test(InputIterator f, InputIterator l)
+test(InputIterator f, InputIterator l, Alloc const& A)
 {
     typedef typename std::iterator_traits<InputIterator>::value_type T;
-    typedef std::deque<T, Allocator> C;
+    typedef std::deque<T, Alloc> C;
     typedef typename C::const_iterator const_iterator;
-    C d(f, l);
+    C d(f, l, A);
     assert(d.size() == std::distance(f, l));
     assert(distance(d.begin(), d.end()) == d.size());
     for (const_iterator i = d.begin(), e = d.end(); i != e; ++i, ++f)
@@ -55,8 +55,15 @@
     test(forward_iterator<const int*>(ab), forward_iterator<const int*>(an));
     test(bidirectional_iterator<const int*>(ab), bidirectional_iterator<const int*>(an));
     test(random_access_iterator<const int*>(ab), random_access_iterator<const int*>(an));
-    test<stack_allocator<int, 4096> >(ab, an);
+    {
+        typedef StackAllocTraits<int, 4096> Traits;
+        Traits T;
+        test(ab, an, T.alloc);
+    }
 #if TEST_STD_VER >= 11
-    test<min_allocator<int> >(ab, an);
+    {
+        min_allocator<int> A;
+        test(ab, an, A);
+    }
 #endif
 }
Index: test/std/containers/sequences/deque/deque.cons/default.pass.cpp
===================================================================
--- test/std/containers/sequences/deque/deque.cons/default.pass.cpp
+++ test/std/containers/sequences/deque/deque.cons/default.pass.cpp
@@ -14,7 +14,6 @@
 #include <deque>
 #include <cassert>
 
-#include "../../../stack_allocator.h"
 #include "../../../NotConstructible.h"
 #include "min_allocator.h"
 
@@ -33,7 +32,6 @@
 int main()
 {
     test<int, std::allocator<int> >();
-    test<NotConstructible, stack_allocator<NotConstructible, 1> >();
 #if TEST_STD_VER >= 11
     test<int, min_allocator<int> >();
     test<NotConstructible, min_allocator<NotConstructible> >();
Index: test/std/containers/sequences/deque/deque.cons/alloc.pass.cpp
===================================================================
--- test/std/containers/sequences/deque/deque.cons/alloc.pass.cpp
+++ test/std/containers/sequences/deque/deque.cons/alloc.pass.cpp
@@ -14,6 +14,7 @@
 #include <deque>
 #include <cassert>
 
+#include "stack_allocator.h"
 #include "test_allocator.h"
 #include "../../../NotConstructible.h"
 #include "min_allocator.h"
@@ -31,6 +32,12 @@
 {
     test<int>(std::allocator<int>());
     test<NotConstructible>(test_allocator<NotConstructible>(3));
+    {
+        typedef StackAllocTraits<NotConstructible, 3> Traits;
+        typedef Traits::AllocT AllocT;
+        Traits T;
+        test<NotConstructible>(T.alloc);
+    }
 #if TEST_STD_VER >= 11
     test<int>(min_allocator<int>());
     test<NotConstructible>(min_allocator<NotConstructible>{});
Index: test/std/containers/container.adaptors/stack/stack.cons/ctor_default.pass.cpp
===================================================================
--- test/std/containers/container.adaptors/stack/stack.cons/ctor_default.pass.cpp
+++ test/std/containers/container.adaptors/stack/stack.cons/ctor_default.pass.cpp
@@ -15,11 +15,9 @@
 #include <vector>
 #include <cassert>
 
-#include "../../../stack_allocator.h"
-
 int main()
 {
-    std::stack<int, std::vector<int, stack_allocator<int, 10> > > q;
+    std::stack<int, std::vector<int> > q;
     assert(q.size() == 0);
     q.push(1);
     q.push(2);
Index: test/std/containers/container.adaptors/queue/queue.cons/ctor_default.pass.cpp
===================================================================
--- test/std/containers/container.adaptors/queue/queue.cons/ctor_default.pass.cpp
+++ test/std/containers/container.adaptors/queue/queue.cons/ctor_default.pass.cpp
@@ -14,11 +14,10 @@
 #include <queue>
 #include <cassert>
 
-#include "../../../stack_allocator.h"
 
 int main()
 {
-    std::queue<int, std::vector<int, stack_allocator<int, 10> > > q;
+    std::queue<int, std::vector<int> > q;
     assert(q.size() == 0);
     q.push(1);
     q.push(2);
Index: test/std/containers/container.adaptors/priority.queue/priqueue.cons/ctor_default.pass.cpp
===================================================================
--- test/std/containers/container.adaptors/priority.queue/priqueue.cons/ctor_default.pass.cpp
+++ test/std/containers/container.adaptors/priority.queue/priqueue.cons/ctor_default.pass.cpp
@@ -14,11 +14,9 @@
 #include <queue>
 #include <cassert>
 
-#include "../../../stack_allocator.h"
-
 int main()
 {
-    std::priority_queue<int, std::vector<int, stack_allocator<int, 10> > > q;
+    std::priority_queue<int, std::vector<int> > q;
     assert(q.size() == 0);
     q.push(1);
     q.push(2);
Index: test/std/containers/container.adaptors/priority.queue/priqueue.cons/ctor_comp.pass.cpp
===================================================================
--- test/std/containers/container.adaptors/priority.queue/priqueue.cons/ctor_comp.pass.cpp
+++ test/std/containers/container.adaptors/priority.queue/priqueue.cons/ctor_comp.pass.cpp
@@ -14,11 +14,9 @@
 #include <queue>
 #include <cassert>
 
-#include "../../../stack_allocator.h"
-
 int main()
 {
-    std::priority_queue<int, std::vector<int, stack_allocator<int, 10> > > q((std::less<int>()));
+    std::priority_queue<int, std::vector<int> > q((std::less<int>()));
     assert(q.size() == 0);
     q.push(1);
     q.push(2);
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to