summaryrefslogtreecommitdiffstats
path: root/libcxx/test/support/test_allocator.h
diff options
context:
space:
mode:
authorMarshall Clow <mclow.lists@gmail.com>2016-07-11 21:38:08 +0000
committerMarshall Clow <mclow.lists@gmail.com>2016-07-11 21:38:08 +0000
commitdc3eb83d08d63d41824d87e64c10021faee44c6e (patch)
tree817e696bbdaaadc91e760d0e08b2fd7f8f554ae2 /libcxx/test/support/test_allocator.h
parent83a25792c5c2fc658736af63b7fc51172642be01 (diff)
downloadbcm5719-llvm-dc3eb83d08d63d41824d87e64c10021faee44c6e.tar.gz
bcm5719-llvm-dc3eb83d08d63d41824d87e64c10021faee44c6e.zip
Always use the allocator to construct/destruct elements of a deque/vector. Fixes PR#28412. Thanks to Jonathan Wakely for the report.
llvm-svn: 275105
Diffstat (limited to 'libcxx/test/support/test_allocator.h')
-rw-r--r--libcxx/test/support/test_allocator.h78
1 files changed, 78 insertions, 0 deletions
diff --git a/libcxx/test/support/test_allocator.h b/libcxx/test/support/test_allocator.h
index 551477119c1..466c7fabc66 100644
--- a/libcxx/test/support/test_allocator.h
+++ b/libcxx/test/support/test_allocator.h
@@ -228,4 +228,82 @@ public:
};
+#if TEST_STD_VER >= 11
+
+struct Ctor_Tag {};
+
+template <typename T> class TaggingAllocator;
+
+struct Tag_X {
+ // All constructors must be passed the Tag type.
+
+ // DefaultInsertable into vector<X, TaggingAllocator<X>>,
+ Tag_X(Ctor_Tag) {}
+ // CopyInsertable into vector<X, TaggingAllocator<X>>,
+ Tag_X(Ctor_Tag, const Tag_X&) {}
+ // MoveInsertable into vector<X, TaggingAllocator<X>>, and
+ Tag_X(Ctor_Tag, Tag_X&&) {}
+
+ // EmplaceConstructible into vector<X, TaggingAllocator<X>> from args.
+ template<typename... Args>
+ Tag_X(Ctor_Tag, Args&&...) { }
+
+ // not DefaultConstructible, CopyConstructible or MoveConstructible.
+ Tag_X() = delete;
+ Tag_X(const Tag_X&) = delete;
+ Tag_X(Tag_X&&) = delete;
+
+ // CopyAssignable.
+ Tag_X& operator=(const Tag_X&) { return *this; }
+
+ // MoveAssignable.
+ Tag_X& operator=(Tag_X&&) { return *this; }
+
+private:
+ // Not Destructible.
+ ~Tag_X() { }
+
+ // Erasable from vector<X, TaggingAllocator<X>>.
+ friend class TaggingAllocator<Tag_X>;
+};
+
+
+template<typename T>
+class TaggingAllocator {
+public:
+ using value_type = T;
+ TaggingAllocator() = default;
+
+ template<typename U>
+ TaggingAllocator(const TaggingAllocator<U>&) { }
+
+ T* allocate(std::size_t n) { return std::allocator<T>{}.allocate(n); }
+
+ void deallocate(T* p, std::size_t n) { std::allocator<T>{}.deallocate(p, n); }
+
+ template<typename... Args>
+ void construct(Tag_X* p, Args&&... args)
+ { ::new((void*)p) Tag_X(Ctor_Tag{}, std::forward<Args>(args)...); }
+
+ template<typename U, typename... Args>
+ void construct(U* p, Args&&... args)
+ { ::new((void*)p) U(std::forward<Args>(args)...); }
+
+ template<typename U, typename... Args>
+ void destroy(U* p)
+ { p->~U(); }
+};
+
+template<typename T, typename U>
+bool
+operator==(const TaggingAllocator<T>&, const TaggingAllocator<U>&)
+{ return true; }
+
+template<typename T, typename U>
+bool
+operator!=(const TaggingAllocator<T>&, const TaggingAllocator<U>&)
+{ return false; }
+#endif
+
+
#endif // TEST_ALLOCATOR_H
OpenPOWER on IntegriCloud