[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