[libcxx] r231672 - Fix an exception-safety bug in <deque>. Reference: PR#22650. Not closing the bug because there's more work to do here

Marshall Clow mclow.lists at gmail.com
Mon Mar 9 10:08:51 PDT 2015


Author: marshall
Date: Mon Mar  9 12:08:51 2015
New Revision: 231672

URL: http://llvm.org/viewvc/llvm-project?rev=231672&view=rev
Log:
Fix an exception-safety bug in <deque>. Reference: PR#22650. Not closing the bug because there's more work to do here

Modified:
    libcxx/trunk/include/deque
    libcxx/trunk/test/std/containers/sequences/deque/deque.modifiers/push_back_exception_safety.pass.cpp
    libcxx/trunk/test/std/containers/sequences/deque/deque.modifiers/push_front_exception_safety.pass.cpp

Modified: libcxx/trunk/include/deque
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/deque?rev=231672&r1=231671&r2=231672&view=diff
==============================================================================
--- libcxx/trunk/include/deque (original)
+++ libcxx/trunk/include/deque Mon Mar  9 12:08:51 2015
@@ -2288,19 +2288,14 @@ deque<_Tp, _Allocator>::__add_front_capa
         __split_buffer<pointer, typename __base::__pointer_allocator&>
             __buf(max<size_type>(2 * __base::__map_.capacity(), 1),
                   0, __base::__map_.__alloc());
-#ifndef _LIBCPP_NO_EXCEPTIONS
-        try
-        {
-#endif  // _LIBCPP_NO_EXCEPTIONS
-            __buf.push_back(__alloc_traits::allocate(__a, __base::__block_size));
-#ifndef _LIBCPP_NO_EXCEPTIONS
-        }
-        catch (...)
-        {
-            __alloc_traits::deallocate(__a, __buf.front(), __base::__block_size);
-            throw;
-        }
-#endif  // _LIBCPP_NO_EXCEPTIONS
+
+		typedef __allocator_destructor<_Allocator> _Dp;
+		unique_ptr<pointer, _Dp> __hold(
+			__alloc_traits::allocate(__a, __base::__block_size),
+				_Dp(__a, __base::__block_size));
+		__buf.push_back(__hold.get());
+		__hold.release();
+	
         for (typename __base::__map_pointer __i = __base::__map_.begin();
                 __i != __base::__map_.end(); ++__i)
             __buf.push_back(*__i);
@@ -2436,19 +2431,14 @@ deque<_Tp, _Allocator>::__add_back_capac
             __buf(max<size_type>(2* __base::__map_.capacity(), 1),
                   __base::__map_.size(),
                   __base::__map_.__alloc());
-#ifndef _LIBCPP_NO_EXCEPTIONS
-        try
-        {
-#endif  // _LIBCPP_NO_EXCEPTIONS
-            __buf.push_back(__alloc_traits::allocate(__a, __base::__block_size));
-#ifndef _LIBCPP_NO_EXCEPTIONS
-        }
-        catch (...)
-        {
-            __alloc_traits::deallocate(__a, __buf.back(), __base::__block_size);
-            throw;
-        }
-#endif  // _LIBCPP_NO_EXCEPTIONS
+
+		typedef __allocator_destructor<_Allocator> _Dp;
+		unique_ptr<pointer, _Dp> __hold(
+			__alloc_traits::allocate(__a, __base::__block_size),
+				_Dp(__a, __base::__block_size));
+		__buf.push_back(__hold.get());
+		__hold.release();
+
         for (typename __base::__map_pointer __i = __base::__map_.end();
                 __i != __base::__map_.begin();)
             __buf.push_front(*--__i);

Modified: libcxx/trunk/test/std/containers/sequences/deque/deque.modifiers/push_back_exception_safety.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/containers/sequences/deque/deque.modifiers/push_back_exception_safety.pass.cpp?rev=231672&r1=231671&r2=231672&view=diff
==============================================================================
--- libcxx/trunk/test/std/containers/sequences/deque/deque.modifiers/push_back_exception_safety.pass.cpp (original)
+++ libcxx/trunk/test/std/containers/sequences/deque/deque.modifiers/push_back_exception_safety.pass.cpp Mon Mar  9 12:08:51 2015
@@ -12,12 +12,12 @@
 // void push_back(const value_type& x);
 
 #include <deque>
+#include "test_allocator.h"
 #include <cassert>
 
 // Flag that makes the copy constructor for CMyClass throw an exception
 static bool gCopyConstructorShouldThow = false;
 
-
 class CMyClass {
     public: CMyClass(int tag);
     public: CMyClass(const CMyClass& iOther);
@@ -25,6 +25,7 @@ class CMyClass {
 
     bool equal(const CMyClass &rhs) const
         { return fTag == rhs.fTag && fMagicValue == rhs.fMagicValue; }
+        
     private:
         int fMagicValue;
         int fTag;
@@ -66,6 +67,7 @@ bool operator==(const CMyClass &lhs, con
 int main()
 {
     CMyClass instance(42);
+    {
     std::deque<CMyClass> vec;
 
     vec.push_back(instance);
@@ -74,8 +76,26 @@ int main()
     gCopyConstructorShouldThow = true;
     try {
         vec.push_back(instance);
+        assert(false);
+    }
+    catch (...) {
+	    gCopyConstructorShouldThow = false;
+        assert(vec==vec2);
+    }
+	}
+	
+	{
+	typedef std::deque<CMyClass, test_allocator<CMyClass> > C;
+    C vec;
+    C vec2(vec);
+
+	C::allocator_type::throw_after = 1;
+    try {
+        vec.push_back(instance);
+        assert(false);
     }
     catch (...) {
         assert(vec==vec2);
     }
+    }
 }

Modified: libcxx/trunk/test/std/containers/sequences/deque/deque.modifiers/push_front_exception_safety.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/containers/sequences/deque/deque.modifiers/push_front_exception_safety.pass.cpp?rev=231672&r1=231671&r2=231672&view=diff
==============================================================================
--- libcxx/trunk/test/std/containers/sequences/deque/deque.modifiers/push_front_exception_safety.pass.cpp (original)
+++ libcxx/trunk/test/std/containers/sequences/deque/deque.modifiers/push_front_exception_safety.pass.cpp Mon Mar  9 12:08:51 2015
@@ -13,6 +13,7 @@
 
 #include <deque>
 #include <cassert>
+#include "test_allocator.h"
 
 // Flag that makes the copy constructor for CMyClass throw an exception
 static bool gCopyConstructorShouldThow = false;
@@ -66,6 +67,7 @@ bool operator==(const CMyClass &lhs, con
 int main()
 {
     CMyClass instance(42);
+    {
     std::deque<CMyClass> vec;
 
     vec.push_front(instance);
@@ -74,8 +76,26 @@ int main()
     gCopyConstructorShouldThow = true;
     try {
         vec.push_front(instance);
+        assert(false);
     }
     catch (...) {
+	    gCopyConstructorShouldThow = false;
         assert(vec==vec2);
     }
+	}
+	
+	{
+	typedef std::deque<CMyClass, test_allocator<CMyClass> > C;
+    C vec;
+    C vec2(vec);
+
+	C::allocator_type::throw_after = 1;
+    try {
+        vec.push_front(instance);
+        assert(false);
+    }
+    catch (...) {
+        assert(vec==vec2);
+    }
+    }
 }





More information about the cfe-commits mailing list