[PATCH] D21094: [libcxx] [test] In test/support/test_allocator.h, fix construct() to avoid moving immovable types.

Stephan T. Lavavej via cfe-commits cfe-commits at lists.llvm.org
Tue Jun 7 12:29:24 PDT 2016


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

In test/support/test_allocator.h, fix construct() to avoid moving immovable types.

This improves the allocator's conformance, and fixes compiler errors with MSVC's STL. The scenario is when the allocator is asked to construct an object of type X that's immovable (deleted copy/move ctors), but implicitly constructible from an argument type A. When perfectly forwarded, X can be (explicitly) constructed from A, and everything is fine. That's std::allocator's behavior, and the Standard's default when a user allocator's construct() doesn't exist. The previous implementation of construct() here mishandled this scenario. Passing A to this construct() would implicitly construct an X temporary, bound to (non-templated) T&&. Then construct() would attempt to move-construct X from that X temporary, but X is immovable, boom.

http://reviews.llvm.org/D21094

Files:
  test/support/test_allocator.h

Index: test/support/test_allocator.h
===================================================================
--- test/support/test_allocator.h
+++ test/support/test_allocator.h
@@ -80,11 +80,12 @@
         {assert(data_ >= 0); --alloc_count; ::operator delete((void*)p);}
     size_type max_size() const throw()
         {return UINT_MAX / sizeof(T);}
+#ifdef _LIBCPP_HAS_NO_RVALUE_REFERENCES
     void construct(pointer p, const T& val)
         {::new(p) T(val);}
-#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
-    void construct(pointer p, T&& val)
-        {::new(p) T(std::move(val));}
+#else  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
+    template <class U> void construct(pointer p, U&& val)
+        {::new(p) T(std::forward<U>(val));}
 #endif  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
     void destroy(pointer p) {p->~T();}
 
@@ -140,11 +141,12 @@
         {assert(data_ >= 0); --alloc_count; ::operator delete((void*)p); }
     size_type max_size() const throw()
         {return UINT_MAX / sizeof(T);}
+#ifdef _LIBCPP_HAS_NO_RVALUE_REFERENCES
     void construct(pointer p, const T& val)
         {::new(p) T(val);}
-#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
-    void construct(pointer p, T&& val)
-        {::new(p) T(std::move(val));}
+#else  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
+    template <class U> void construct(pointer p, U&& val)
+        {::new(p) T(std::forward<U>(val));}
 #endif  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
     void destroy(pointer p) {p->~T();}
 


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D21094.59934.patch
Type: text/x-patch
Size: 1466 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20160607/b73e11dd/attachment.bin>


More information about the cfe-commits mailing list