_LIBCPP_INLINE_VISIBILITY
static
void
- __construct_forward(allocator_type& __a, _Ptr __begin1, _Ptr __end1, _Ptr& __begin2)
+ __construct_forward_with_exception_guarantees(allocator_type& __a, _Ptr __begin1, _Ptr __end1, _Ptr& __begin2)
{
for (; __begin1 != __end1; ++__begin1, (void) ++__begin2)
- construct(__a, _VSTD::__to_raw_pointer(__begin2), _VSTD::move_if_noexcept(*__begin1));
+ construct(__a, _VSTD::__to_raw_pointer(__begin2),
+#ifdef _LIBCPP_NO_EXCEPTIONS
+ _VSTD::move(*__begin1)
+#else
+ _VSTD::move_if_noexcept(*__begin1)
+#endif
+ );
}
template <class _Tp>
is_trivially_move_constructible<_Tp>::value,
void
>::type
- __construct_forward(allocator_type&, _Tp* __begin1, _Tp* __end1, _Tp*& __begin2)
+ __construct_forward_with_exception_guarantees(allocator_type&, _Tp* __begin1, _Tp* __end1, _Tp*& __begin2)
{
ptrdiff_t _Np = __end1 - __begin1;
if (_Np > 0)
_LIBCPP_INLINE_VISIBILITY
static
void
- __construct_backward(allocator_type& __a, _Ptr __begin1, _Ptr __end1, _Ptr& __end2)
+ __construct_backward_with_exception_guarantees(allocator_type& __a, _Ptr __begin1, _Ptr __end1, _Ptr& __end2)
{
while (__end1 != __begin1)
{
- construct(__a, _VSTD::__to_raw_pointer(__end2-1), _VSTD::move_if_noexcept(*--__end1));
- --__end2;
+ construct(__a, _VSTD::__to_raw_pointer(__end2 - 1),
+#ifdef _LIBCPP_NO_EXCEPTIONS
+ _VSTD::move(*--__end1)
+#else
+ _VSTD::move_if_noexcept(*--__end1)
+#endif
+ );
+ --__end2;
}
}
is_trivially_move_constructible<_Tp>::value,
void
>::type
- __construct_backward(allocator_type&, _Tp* __begin1, _Tp* __end1, _Tp*& __end2)
+ __construct_backward_with_exception_guarantees(allocator_type&, _Tp* __begin1, _Tp* __end1, _Tp*& __end2)
{
ptrdiff_t _Np = __end1 - __begin1;
__end2 -= _Np;
vector<_Tp, _Allocator>::__swap_out_circular_buffer(__split_buffer<value_type, allocator_type&>& __v)
{
__annotate_delete();
- __alloc_traits::__construct_backward(this->__alloc(), this->__begin_, this->__end_, __v.__begin_);
+ __alloc_traits::__construct_backward_with_exception_guarantees(
+ this->__alloc(), this->__begin_, this->__end_, __v.__begin_);
_VSTD::swap(this->__begin_, __v.__begin_);
_VSTD::swap(this->__end_, __v.__end_);
_VSTD::swap(this->__end_cap(), __v.__end_cap());
{
__annotate_delete();
pointer __r = __v.__begin_;
- __alloc_traits::__construct_backward(this->__alloc(), this->__begin_, __p, __v.__begin_);
- __alloc_traits::__construct_forward(this->__alloc(), __p, this->__end_, __v.__end_);
+ __alloc_traits::__construct_backward_with_exception_guarantees(
+ this->__alloc(), this->__begin_, __p, __v.__begin_);
+ __alloc_traits::__construct_forward_with_exception_guarantees(
+ this->__alloc(), __p, this->__end_, __v.__end_);
_VSTD::swap(this->__begin_, __v.__begin_);
_VSTD::swap(this->__end_, __v.__end_);
_VSTD::swap(this->__end_cap(), __v.__end_cap());
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// RUN: %build -fno-exceptions
+// RUN: %run
+
+// UNSUPPORTED: c++98, c++03
+
+// <vector>
+
+// Test that vector always moves elements when exceptions are disabled.
+// vector is allowed to move or copy elements while resizing, so long as
+// it still provides the strong exception safety guarantee.
+
+#include <vector>
+#include <cassert>
+
+#include "test_macros.h"
+
+#ifndef TEST_HAS_NO_EXCEPTIONS
+#error exceptions should be disabled.
+#endif
+
+bool allow_moves = false;
+
+class A {
+public:
+ A() {}
+ A(A&&) { assert(allow_moves); }
+ explicit A(int) {}
+ A(A const&) { assert(false); }
+};
+
+int main(int, char**) {
+ std::vector<A> v;
+
+ // Create a vector containing some number of elements that will
+ // have to be moved when it is resized.
+ v.reserve(10);
+ size_t old_cap = v.capacity();
+ for (int i = 0; i < v.capacity(); ++i) {
+ v.emplace_back(42);
+ }
+ assert(v.capacity() == old_cap);
+ assert(v.size() == v.capacity());
+
+ // The next emplace back should resize.
+ allow_moves = true;
+ v.emplace_back(42);
+
+ return 0;
+}