[cfe-commits] [libcxx] r172250 - in /libcxx/trunk: include/ test/containers/sequences/deque/deque.modifiers/ test/containers/sequences/forwardlist/forwardlist.modifiers/ test/containers/sequences/list/list.modifiers/ test/containers/sequences/vector/vector.modifiers/

Howard Hinnant hhinnant at apple.com
Fri Jan 11 12:36:59 PST 2013


Author: hhinnant
Date: Fri Jan 11 14:36:59 2013
New Revision: 172250

URL: http://llvm.org/viewvc/llvm-project?rev=172250&view=rev
Log:
Fix exception safety bug in vector::push_back

Added:
    libcxx/trunk/test/containers/sequences/deque/deque.modifiers/push_back_exception_safety.pass.cpp
    libcxx/trunk/test/containers/sequences/deque/deque.modifiers/push_front_exception_safety.pass.cpp
    libcxx/trunk/test/containers/sequences/forwardlist/forwardlist.modifiers/push_front_exception_safety.pass.cpp
    libcxx/trunk/test/containers/sequences/list/list.modifiers/push_back_exception_safety.pass.cpp
    libcxx/trunk/test/containers/sequences/list/list.modifiers/push_front_exception_safety.pass.cpp
    libcxx/trunk/test/containers/sequences/vector/vector.modifiers/push_back_exception_safety.pass.cpp
Modified:
    libcxx/trunk/include/memory
    libcxx/trunk/include/vector

Modified: libcxx/trunk/include/memory
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/memory?rev=172250&r1=172249&r2=172250&view=diff
==============================================================================
--- libcxx/trunk/include/memory (original)
+++ libcxx/trunk/include/memory Fri Jan 11 14:36:59 2013
@@ -1571,7 +1571,10 @@
         __construct_backward(allocator_type& __a, _Ptr __begin1, _Ptr __end1, _Ptr& __end2)
         {
             while (__end1 != __begin1)
-                construct(__a, _VSTD::__to_raw_pointer(--__end2), _VSTD::move_if_noexcept(*--__end1));
+            {
+                construct(__a, _VSTD::__to_raw_pointer(__end2-1), _VSTD::move_if_noexcept(*--__end1));
+                --__end2;
+            }
         }
 
     template <class _Tp>

Modified: libcxx/trunk/include/vector
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/vector?rev=172250&r1=172249&r2=172250&view=diff
==============================================================================
--- libcxx/trunk/include/vector (original)
+++ libcxx/trunk/include/vector Fri Jan 11 14:36:59 2013
@@ -1458,7 +1458,8 @@
     allocator_type& __a = this->__alloc();
     __split_buffer<value_type, allocator_type&> __v(__recommend(size() + 1), size(), __a);
     // __v.push_back(_VSTD::forward<_Up>(__x));
-    __alloc_traits::construct(__a, _VSTD::__to_raw_pointer(__v.__end_++), _VSTD::forward<_Up>(__x));
+    __alloc_traits::construct(__a, _VSTD::__to_raw_pointer(__v.__end_), _VSTD::forward<_Up>(__x));
+    __v.__end_++;
     __swap_out_circular_buffer(__v);
 }
 
@@ -1505,7 +1506,8 @@
     allocator_type& __a = this->__alloc();
     __split_buffer<value_type, allocator_type&> __v(__recommend(size() + 1), size(), __a);
 //    __v.emplace_back(_VSTD::forward<_Args>(__args)...);
-    __alloc_traits::construct(__a, _VSTD::__to_raw_pointer(__v.__end_++), _VSTD::forward<_Args>(__args)...);
+    __alloc_traits::construct(__a, _VSTD::__to_raw_pointer(__v.__end_), _VSTD::forward<_Args>(__args)...);
+    __v.__end_++;
     __swap_out_circular_buffer(__v);
 }
 

Added: libcxx/trunk/test/containers/sequences/deque/deque.modifiers/push_back_exception_safety.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/containers/sequences/deque/deque.modifiers/push_back_exception_safety.pass.cpp?rev=172250&view=auto
==============================================================================
--- libcxx/trunk/test/containers/sequences/deque/deque.modifiers/push_back_exception_safety.pass.cpp (added)
+++ libcxx/trunk/test/containers/sequences/deque/deque.modifiers/push_back_exception_safety.pass.cpp Fri Jan 11 14:36:59 2013
@@ -0,0 +1,73 @@
+//===----------------------------------------------------------------------===//
+//
+//                     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.
+//
+//===----------------------------------------------------------------------===//
+
+// <deque>
+
+// void push_back(const value_type& x);
+
+#include <deque>
+#include <cassert>
+
+// Flag that makes the copy constructor for CMyClass throw an exception
+static bool gCopyConstructorShouldThow = false;
+
+
+class CMyClass {
+	public: CMyClass();
+	public: CMyClass(const CMyClass& iOther);
+	public: ~CMyClass();
+
+	private: int fMagicValue;
+
+	private: static int kStartedConstructionMagicValue;
+	private: static int kFinishedConstructionMagicValue;
+};
+
+// Value for fMagicValue when the constructor has started running, but not yet finished
+int CMyClass::kStartedConstructionMagicValue = 0;
+// Value for fMagicValue when the constructor has finished running
+int CMyClass::kFinishedConstructionMagicValue = 12345;
+
+CMyClass::CMyClass() :
+	fMagicValue(kStartedConstructionMagicValue)
+{
+	// Signal that the constructor has finished running
+	fMagicValue = kFinishedConstructionMagicValue;
+}
+
+CMyClass::CMyClass(const CMyClass& /*iOther*/) :
+	fMagicValue(kStartedConstructionMagicValue)
+{
+	// If requested, throw an exception _before_ setting fMagicValue to kFinishedConstructionMagicValue
+	if (gCopyConstructorShouldThow) {
+		throw std::exception();
+	}
+	// Signal that the constructor has finished running
+	fMagicValue = kFinishedConstructionMagicValue;
+}
+
+CMyClass::~CMyClass() {
+	// Only instances for which the constructor has finished running should be destructed
+	assert(fMagicValue == kFinishedConstructionMagicValue);
+}
+
+int main()
+{
+	CMyClass instance;
+	std::deque<CMyClass> vec;
+
+	vec.push_back(instance);
+
+	gCopyConstructorShouldThow = true;
+	try {
+		vec.push_back(instance);
+	}
+	catch (...) {
+	}
+}

Added: libcxx/trunk/test/containers/sequences/deque/deque.modifiers/push_front_exception_safety.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/containers/sequences/deque/deque.modifiers/push_front_exception_safety.pass.cpp?rev=172250&view=auto
==============================================================================
--- libcxx/trunk/test/containers/sequences/deque/deque.modifiers/push_front_exception_safety.pass.cpp (added)
+++ libcxx/trunk/test/containers/sequences/deque/deque.modifiers/push_front_exception_safety.pass.cpp Fri Jan 11 14:36:59 2013
@@ -0,0 +1,73 @@
+//===----------------------------------------------------------------------===//
+//
+//                     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.
+//
+//===----------------------------------------------------------------------===//
+
+// <deque>
+
+// void push_front(const value_type& x);
+
+#include <deque>
+#include <cassert>
+
+// Flag that makes the copy constructor for CMyClass throw an exception
+static bool gCopyConstructorShouldThow = false;
+
+
+class CMyClass {
+	public: CMyClass();
+	public: CMyClass(const CMyClass& iOther);
+	public: ~CMyClass();
+
+	private: int fMagicValue;
+
+	private: static int kStartedConstructionMagicValue;
+	private: static int kFinishedConstructionMagicValue;
+};
+
+// Value for fMagicValue when the constructor has started running, but not yet finished
+int CMyClass::kStartedConstructionMagicValue = 0;
+// Value for fMagicValue when the constructor has finished running
+int CMyClass::kFinishedConstructionMagicValue = 12345;
+
+CMyClass::CMyClass() :
+	fMagicValue(kStartedConstructionMagicValue)
+{
+	// Signal that the constructor has finished running
+	fMagicValue = kFinishedConstructionMagicValue;
+}
+
+CMyClass::CMyClass(const CMyClass& /*iOther*/) :
+	fMagicValue(kStartedConstructionMagicValue)
+{
+	// If requested, throw an exception _before_ setting fMagicValue to kFinishedConstructionMagicValue
+	if (gCopyConstructorShouldThow) {
+		throw std::exception();
+	}
+	// Signal that the constructor has finished running
+	fMagicValue = kFinishedConstructionMagicValue;
+}
+
+CMyClass::~CMyClass() {
+	// Only instances for which the constructor has finished running should be destructed
+	assert(fMagicValue == kFinishedConstructionMagicValue);
+}
+
+int main()
+{
+	CMyClass instance;
+	std::deque<CMyClass> vec;
+
+	vec.push_front(instance);
+
+	gCopyConstructorShouldThow = true;
+	try {
+		vec.push_front(instance);
+	}
+	catch (...) {
+	}
+}

Added: libcxx/trunk/test/containers/sequences/forwardlist/forwardlist.modifiers/push_front_exception_safety.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/containers/sequences/forwardlist/forwardlist.modifiers/push_front_exception_safety.pass.cpp?rev=172250&view=auto
==============================================================================
--- libcxx/trunk/test/containers/sequences/forwardlist/forwardlist.modifiers/push_front_exception_safety.pass.cpp (added)
+++ libcxx/trunk/test/containers/sequences/forwardlist/forwardlist.modifiers/push_front_exception_safety.pass.cpp Fri Jan 11 14:36:59 2013
@@ -0,0 +1,73 @@
+//===----------------------------------------------------------------------===//
+//
+//                     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.
+//
+//===----------------------------------------------------------------------===//
+
+// <forward_list>
+
+// void push_front(const value_type& x);
+
+#include <forward_list>
+#include <cassert>
+
+// Flag that makes the copy constructor for CMyClass throw an exception
+static bool gCopyConstructorShouldThow = false;
+
+
+class CMyClass {
+	public: CMyClass();
+	public: CMyClass(const CMyClass& iOther);
+	public: ~CMyClass();
+
+	private: int fMagicValue;
+
+	private: static int kStartedConstructionMagicValue;
+	private: static int kFinishedConstructionMagicValue;
+};
+
+// Value for fMagicValue when the constructor has started running, but not yet finished
+int CMyClass::kStartedConstructionMagicValue = 0;
+// Value for fMagicValue when the constructor has finished running
+int CMyClass::kFinishedConstructionMagicValue = 12345;
+
+CMyClass::CMyClass() :
+	fMagicValue(kStartedConstructionMagicValue)
+{
+	// Signal that the constructor has finished running
+	fMagicValue = kFinishedConstructionMagicValue;
+}
+
+CMyClass::CMyClass(const CMyClass& /*iOther*/) :
+	fMagicValue(kStartedConstructionMagicValue)
+{
+	// If requested, throw an exception _before_ setting fMagicValue to kFinishedConstructionMagicValue
+	if (gCopyConstructorShouldThow) {
+		throw std::exception();
+	}
+	// Signal that the constructor has finished running
+	fMagicValue = kFinishedConstructionMagicValue;
+}
+
+CMyClass::~CMyClass() {
+	// Only instances for which the constructor has finished running should be destructed
+	assert(fMagicValue == kFinishedConstructionMagicValue);
+}
+
+int main()
+{
+	CMyClass instance;
+	std::forward_list<CMyClass> vec;
+
+	vec.push_front(instance);
+
+	gCopyConstructorShouldThow = true;
+	try {
+		vec.push_front(instance);
+	}
+	catch (...) {
+	}
+}

Added: libcxx/trunk/test/containers/sequences/list/list.modifiers/push_back_exception_safety.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/containers/sequences/list/list.modifiers/push_back_exception_safety.pass.cpp?rev=172250&view=auto
==============================================================================
--- libcxx/trunk/test/containers/sequences/list/list.modifiers/push_back_exception_safety.pass.cpp (added)
+++ libcxx/trunk/test/containers/sequences/list/list.modifiers/push_back_exception_safety.pass.cpp Fri Jan 11 14:36:59 2013
@@ -0,0 +1,73 @@
+//===----------------------------------------------------------------------===//
+//
+//                     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.
+//
+//===----------------------------------------------------------------------===//
+
+// <list>
+
+// void push_back(const value_type& x);
+
+#include <list>
+#include <cassert>
+
+// Flag that makes the copy constructor for CMyClass throw an exception
+static bool gCopyConstructorShouldThow = false;
+
+
+class CMyClass {
+	public: CMyClass();
+	public: CMyClass(const CMyClass& iOther);
+	public: ~CMyClass();
+
+	private: int fMagicValue;
+
+	private: static int kStartedConstructionMagicValue;
+	private: static int kFinishedConstructionMagicValue;
+};
+
+// Value for fMagicValue when the constructor has started running, but not yet finished
+int CMyClass::kStartedConstructionMagicValue = 0;
+// Value for fMagicValue when the constructor has finished running
+int CMyClass::kFinishedConstructionMagicValue = 12345;
+
+CMyClass::CMyClass() :
+	fMagicValue(kStartedConstructionMagicValue)
+{
+	// Signal that the constructor has finished running
+	fMagicValue = kFinishedConstructionMagicValue;
+}
+
+CMyClass::CMyClass(const CMyClass& /*iOther*/) :
+	fMagicValue(kStartedConstructionMagicValue)
+{
+	// If requested, throw an exception _before_ setting fMagicValue to kFinishedConstructionMagicValue
+	if (gCopyConstructorShouldThow) {
+		throw std::exception();
+	}
+	// Signal that the constructor has finished running
+	fMagicValue = kFinishedConstructionMagicValue;
+}
+
+CMyClass::~CMyClass() {
+	// Only instances for which the constructor has finished running should be destructed
+	assert(fMagicValue == kFinishedConstructionMagicValue);
+}
+
+int main()
+{
+	CMyClass instance;
+	std::list<CMyClass> vec;
+
+	vec.push_back(instance);
+
+	gCopyConstructorShouldThow = true;
+	try {
+		vec.push_back(instance);
+	}
+	catch (...) {
+	}
+}

Added: libcxx/trunk/test/containers/sequences/list/list.modifiers/push_front_exception_safety.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/containers/sequences/list/list.modifiers/push_front_exception_safety.pass.cpp?rev=172250&view=auto
==============================================================================
--- libcxx/trunk/test/containers/sequences/list/list.modifiers/push_front_exception_safety.pass.cpp (added)
+++ libcxx/trunk/test/containers/sequences/list/list.modifiers/push_front_exception_safety.pass.cpp Fri Jan 11 14:36:59 2013
@@ -0,0 +1,73 @@
+//===----------------------------------------------------------------------===//
+//
+//                     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.
+//
+//===----------------------------------------------------------------------===//
+
+// <list>
+
+// void push_front(const value_type& x);
+
+#include <list>
+#include <cassert>
+
+// Flag that makes the copy constructor for CMyClass throw an exception
+static bool gCopyConstructorShouldThow = false;
+
+
+class CMyClass {
+	public: CMyClass();
+	public: CMyClass(const CMyClass& iOther);
+	public: ~CMyClass();
+
+	private: int fMagicValue;
+
+	private: static int kStartedConstructionMagicValue;
+	private: static int kFinishedConstructionMagicValue;
+};
+
+// Value for fMagicValue when the constructor has started running, but not yet finished
+int CMyClass::kStartedConstructionMagicValue = 0;
+// Value for fMagicValue when the constructor has finished running
+int CMyClass::kFinishedConstructionMagicValue = 12345;
+
+CMyClass::CMyClass() :
+	fMagicValue(kStartedConstructionMagicValue)
+{
+	// Signal that the constructor has finished running
+	fMagicValue = kFinishedConstructionMagicValue;
+}
+
+CMyClass::CMyClass(const CMyClass& /*iOther*/) :
+	fMagicValue(kStartedConstructionMagicValue)
+{
+	// If requested, throw an exception _before_ setting fMagicValue to kFinishedConstructionMagicValue
+	if (gCopyConstructorShouldThow) {
+		throw std::exception();
+	}
+	// Signal that the constructor has finished running
+	fMagicValue = kFinishedConstructionMagicValue;
+}
+
+CMyClass::~CMyClass() {
+	// Only instances for which the constructor has finished running should be destructed
+	assert(fMagicValue == kFinishedConstructionMagicValue);
+}
+
+int main()
+{
+	CMyClass instance;
+	std::list<CMyClass> vec;
+
+	vec.push_front(instance);
+
+	gCopyConstructorShouldThow = true;
+	try {
+		vec.push_front(instance);
+	}
+	catch (...) {
+	}
+}

Added: libcxx/trunk/test/containers/sequences/vector/vector.modifiers/push_back_exception_safety.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/containers/sequences/vector/vector.modifiers/push_back_exception_safety.pass.cpp?rev=172250&view=auto
==============================================================================
--- libcxx/trunk/test/containers/sequences/vector/vector.modifiers/push_back_exception_safety.pass.cpp (added)
+++ libcxx/trunk/test/containers/sequences/vector/vector.modifiers/push_back_exception_safety.pass.cpp Fri Jan 11 14:36:59 2013
@@ -0,0 +1,73 @@
+//===----------------------------------------------------------------------===//
+//
+//                     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.
+//
+//===----------------------------------------------------------------------===//
+
+// <vector>
+
+// void push_back(const value_type& x);
+
+#include <vector>
+#include <cassert>
+
+// Flag that makes the copy constructor for CMyClass throw an exception
+static bool gCopyConstructorShouldThow = false;
+
+
+class CMyClass {
+	public: CMyClass();
+	public: CMyClass(const CMyClass& iOther);
+	public: ~CMyClass();
+
+	private: int fMagicValue;
+
+	private: static int kStartedConstructionMagicValue;
+	private: static int kFinishedConstructionMagicValue;
+};
+
+// Value for fMagicValue when the constructor has started running, but not yet finished
+int CMyClass::kStartedConstructionMagicValue = 0;
+// Value for fMagicValue when the constructor has finished running
+int CMyClass::kFinishedConstructionMagicValue = 12345;
+
+CMyClass::CMyClass() :
+	fMagicValue(kStartedConstructionMagicValue)
+{
+	// Signal that the constructor has finished running
+	fMagicValue = kFinishedConstructionMagicValue;
+}
+
+CMyClass::CMyClass(const CMyClass& /*iOther*/) :
+	fMagicValue(kStartedConstructionMagicValue)
+{
+	// If requested, throw an exception _before_ setting fMagicValue to kFinishedConstructionMagicValue
+	if (gCopyConstructorShouldThow) {
+		throw std::exception();
+	}
+	// Signal that the constructor has finished running
+	fMagicValue = kFinishedConstructionMagicValue;
+}
+
+CMyClass::~CMyClass() {
+	// Only instances for which the constructor has finished running should be destructed
+	assert(fMagicValue == kFinishedConstructionMagicValue);
+}
+
+int main()
+{
+	CMyClass instance;
+	std::vector<CMyClass> vec;
+
+	vec.push_back(instance);
+
+	gCopyConstructorShouldThow = true;
+	try {
+		vec.push_back(instance);
+	}
+	catch (...) {
+	}
+}





More information about the cfe-commits mailing list