[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