diff options
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 (...) { + } +} |

