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