summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--libcxx/include/memory5
-rw-r--r--libcxx/include/vector6
-rw-r--r--libcxx/test/containers/sequences/deque/deque.modifiers/push_back_exception_safety.pass.cpp73
-rw-r--r--libcxx/test/containers/sequences/deque/deque.modifiers/push_front_exception_safety.pass.cpp73
-rw-r--r--libcxx/test/containers/sequences/forwardlist/forwardlist.modifiers/push_front_exception_safety.pass.cpp73
-rw-r--r--libcxx/test/containers/sequences/list/list.modifiers/push_back_exception_safety.pass.cpp73
-rw-r--r--libcxx/test/containers/sequences/list/list.modifiers/push_front_exception_safety.pass.cpp73
-rw-r--r--libcxx/test/containers/sequences/vector/vector.modifiers/push_back_exception_safety.pass.cpp73
8 files changed, 446 insertions, 3 deletions
diff --git a/libcxx/include/memory b/libcxx/include/memory
index 4c12ad93ab8..f80d699fc0d 100644
--- a/libcxx/include/memory
+++ b/libcxx/include/memory
@@ -1571,7 +1571,10 @@ struct _LIBCPP_VISIBLE allocator_traits
__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>
diff --git a/libcxx/include/vector b/libcxx/include/vector
index 0c280682833..876b7e5676b 100644
--- a/libcxx/include/vector
+++ b/libcxx/include/vector
@@ -1458,7 +1458,8 @@ vector<_Tp, _Allocator>::__push_back_slow_path(_Up& __x)
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 @@ vector<_Tp, _Allocator>::__emplace_back_slow_path(_Args&&... __args)
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);
}
diff --git a/libcxx/test/containers/sequences/deque/deque.modifiers/push_back_exception_safety.pass.cpp b/libcxx/test/containers/sequences/deque/deque.modifiers/push_back_exception_safety.pass.cpp
new file mode 100644
index 00000000000..d1aeee61130
--- /dev/null
+++ b/libcxx/test/containers/sequences/deque/deque.modifiers/push_back_exception_safety.pass.cpp
@@ -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 (...) {
+ }
+}
diff --git a/libcxx/test/containers/sequences/deque/deque.modifiers/push_front_exception_safety.pass.cpp b/libcxx/test/containers/sequences/deque/deque.modifiers/push_front_exception_safety.pass.cpp
new file mode 100644
index 00000000000..aa1d35485a2
--- /dev/null
+++ b/libcxx/test/containers/sequences/deque/deque.modifiers/push_front_exception_safety.pass.cpp
@@ -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 (...) {
+ }
+}
diff --git a/libcxx/test/containers/sequences/forwardlist/forwardlist.modifiers/push_front_exception_safety.pass.cpp b/libcxx/test/containers/sequences/forwardlist/forwardlist.modifiers/push_front_exception_safety.pass.cpp
new file mode 100644
index 00000000000..1624ed6e6af
--- /dev/null
+++ b/libcxx/test/containers/sequences/forwardlist/forwardlist.modifiers/push_front_exception_safety.pass.cpp
@@ -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 (...) {
+ }
+}
diff --git a/libcxx/test/containers/sequences/list/list.modifiers/push_back_exception_safety.pass.cpp b/libcxx/test/containers/sequences/list/list.modifiers/push_back_exception_safety.pass.cpp
new file mode 100644
index 00000000000..bdb6af36e51
--- /dev/null
+++ b/libcxx/test/containers/sequences/list/list.modifiers/push_back_exception_safety.pass.cpp
@@ -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 (...) {
+ }
+}
diff --git a/libcxx/test/containers/sequences/list/list.modifiers/push_front_exception_safety.pass.cpp b/libcxx/test/containers/sequences/list/list.modifiers/push_front_exception_safety.pass.cpp
new file mode 100644
index 00000000000..03f8af248fe
--- /dev/null
+++ b/libcxx/test/containers/sequences/list/list.modifiers/push_front_exception_safety.pass.cpp
@@ -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 (...) {
+ }
+}
diff --git a/libcxx/test/containers/sequences/vector/vector.modifiers/push_back_exception_safety.pass.cpp b/libcxx/test/containers/sequences/vector/vector.modifiers/push_back_exception_safety.pass.cpp
new file mode 100644
index 00000000000..17a13a8e86a
--- /dev/null
+++ b/libcxx/test/containers/sequences/vector/vector.modifiers/push_back_exception_safety.pass.cpp
@@ -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 (...) {
+ }
+}
OpenPOWER on IntegriCloud