This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Relocation (= move+destroy)


On Sun, 2 Sep 2018, Jonathan Wakely wrote:

On 01/09/18 21:56 +0200, Marc Glisse wrote:
On Sat, 1 Sep 2018, Marc Glisse wrote:

this patch passed bootstrap+regtest on powerpc64le-unknown-linux-gnu.

I realized afterwards that for a C++17-only feature, that's not testing much... So I changed it to apply in C++14 and fixed a minor issue. There is now a single regression:

23_containers/vector/modifiers/push_back/49836.cc

The PR was about not using assignment for an operation that should only use construction, and that's fine. But we ended up with a stricter testcase using CopyConsOnlyType, where the type has a deleted move constructor which, as far as I understand the standard, makes it an invalid type for use in vector::push_back. Is that something we want to keep supporting, or may I break it? What is happening is that

I think you can break it. I'll look back over the history of the test
case, but I don't think supporting deleted moves is intended.

Here is a version where I adapt the test. Bootstrap+testsuite on gcc112.

2018-10-15  Marc Glisse  <marc.glisse@inria.fr>

	PR libstdc++/87106
	* include/bits/alloc_traits.h (_S_construct, _S_destroy, construct,
	destroy): Add noexcept specification.
	* include/bits/allocator.h (construct, destroy): Likewise.
	* include/ext/alloc_traits.h (construct, destroy): Likewise.
	* include/ext/malloc_allocator.h (construct, destroy): Likewise.
	* include/ext/new_allocator.h (construct, destroy): Likewise.
	* include/bits/stl_uninitialized.h (__relocate, __relocate_a,
	__relocate_a_1): New functions.
	(__is_trivially_relocatable): New class.
	* include/bits/stl_vector.h (__use_relocate): New static member.
	* include/bits/vector.tcc (reserve, _M_realloc_insert,
	_M_default_append): Use __relocate_a.
	(reserve, _M_assign_aux, _M_realloc_insert, _M_fill_insert,
	_M_default_append, _M_range_insert): Move _GLIBCXX_ASAN_ANNOTATE_REINIT
	after _Destroy.
	* testsuite/23_containers/vector/modifiers/push_back/49836.cc:
	Replace CopyConsOnlyType with DelAnyAssign.

--
Marc Glisse
Index: libstdc++-v3/include/bits/alloc_traits.h
===================================================================
--- libstdc++-v3/include/bits/alloc_traits.h	(revision 265131)
+++ libstdc++-v3/include/bits/alloc_traits.h	(working copy)
@@ -233,38 +233,43 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	  using type = decltype(__test<_Alloc>(0));
 	};
 
       template<typename _Tp, typename... _Args>
 	using __has_construct
 	  = typename __construct_helper<_Tp, _Args...>::type;
 
       template<typename _Tp, typename... _Args>
 	static _Require<__has_construct<_Tp, _Args...>>
 	_S_construct(_Alloc& __a, _Tp* __p, _Args&&... __args)
+	noexcept(noexcept(__a.construct(__p, std::forward<_Args>(__args)...)))
 	{ __a.construct(__p, std::forward<_Args>(__args)...); }
 
       template<typename _Tp, typename... _Args>
 	static
 	_Require<__and_<__not_<__has_construct<_Tp, _Args...>>,
 			       is_constructible<_Tp, _Args...>>>
 	_S_construct(_Alloc&, _Tp* __p, _Args&&... __args)
+	noexcept(noexcept(::new((void*)__p)
+			  _Tp(std::forward<_Args>(__args)...)))
 	{ ::new((void*)__p) _Tp(std::forward<_Args>(__args)...); }
 
       template<typename _Alloc2, typename _Tp>
 	static auto
 	_S_destroy(_Alloc2& __a, _Tp* __p, int)
+	noexcept(noexcept(__a.destroy(__p)))
 	-> decltype(__a.destroy(__p))
 	{ __a.destroy(__p); }
 
       template<typename _Alloc2, typename _Tp>
 	static void
 	_S_destroy(_Alloc2&, _Tp* __p, ...)
+	noexcept(noexcept(__p->~_Tp()))
 	{ __p->~_Tp(); }
 
       template<typename _Alloc2>
 	static auto
 	_S_max_size(_Alloc2& __a, int)
 	-> decltype(__a.max_size())
 	{ return __a.max_size(); }
 
       template<typename _Alloc2>
 	static size_type
@@ -333,33 +338,36 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
        *  @param  __p  Pointer to memory of suitable size and alignment for Tp
        *  @param  __args Constructor arguments.
        *
        *  Calls <tt> __a.construct(__p, std::forward<Args>(__args)...) </tt>
        *  if that expression is well-formed, otherwise uses placement-new
        *  to construct an object of type @a _Tp at location @a __p from the
        *  arguments @a __args...
       */
       template<typename _Tp, typename... _Args>
 	static auto construct(_Alloc& __a, _Tp* __p, _Args&&... __args)
+	noexcept(noexcept(_S_construct(__a, __p,
+				       std::forward<_Args>(__args)...)))
 	-> decltype(_S_construct(__a, __p, std::forward<_Args>(__args)...))
 	{ _S_construct(__a, __p, std::forward<_Args>(__args)...); }
 
       /**
        *  @brief  Destroy an object of type @a _Tp
        *  @param  __a  An allocator.
        *  @param  __p  Pointer to the object to destroy
        *
        *  Calls @c __a.destroy(__p) if that expression is well-formed,
        *  otherwise calls @c __p->~_Tp()
       */
       template<typename _Tp>
 	static void destroy(_Alloc& __a, _Tp* __p)
+	noexcept(noexcept(_S_destroy(__a, __p, 0)))
 	{ _S_destroy(__a, __p, 0); }
 
       /**
        *  @brief  The maximum supported allocation size
        *  @param  __a  An allocator.
        *  @return @c __a.max_size() or @c numeric_limits<size_type>::max()
        *
        *  Returns @c __a.max_size() if that expression is well-formed,
        *  otherwise returns @c numeric_limits<size_type>::max()
       */
@@ -465,32 +473,34 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
        *  @brief  Construct an object of type @a _Up
        *  @param  __a  An allocator.
        *  @param  __p  Pointer to memory of suitable size and alignment for Tp
        *  @param  __args Constructor arguments.
        *
        *  Calls <tt> __a.construct(__p, std::forward<Args>(__args)...) </tt>
       */
       template<typename _Up, typename... _Args>
 	static void
 	construct(allocator_type& __a, _Up* __p, _Args&&... __args)
+	noexcept(noexcept(__a.construct(__p, std::forward<_Args>(__args)...)))
 	{ __a.construct(__p, std::forward<_Args>(__args)...); }
 
       /**
        *  @brief  Destroy an object of type @a _Up
        *  @param  __a  An allocator.
        *  @param  __p  Pointer to the object to destroy
        *
        *  Calls @c __a.destroy(__p).
       */
       template<typename _Up>
 	static void
 	destroy(allocator_type& __a, _Up* __p)
+	noexcept(noexcept(__a.destroy(__p)))
 	{ __a.destroy(__p); }
 
       /**
        *  @brief  The maximum supported allocation size
        *  @param  __a  An allocator.
        *  @return @c __a.max_size()
       */
       static size_type
       max_size(const allocator_type& __a) noexcept
       { return __a.max_size(); }
Index: libstdc++-v3/include/bits/allocator.h
===================================================================
--- libstdc++-v3/include/bits/allocator.h	(revision 265131)
+++ libstdc++-v3/include/bits/allocator.h	(working copy)
@@ -81,25 +81,29 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 #if __cplusplus >= 201103L
       // _GLIBCXX_RESOLVE_LIB_DEFECTS
       // 2103. std::allocator propagate_on_container_move_assignment
       typedef true_type propagate_on_container_move_assignment;
 
       typedef true_type is_always_equal;
 
       template<typename _Up, typename... _Args>
 	void
 	construct(_Up* __p, _Args&&... __args)
+	noexcept(noexcept(::new((void *)__p)
+			    _Up(std::forward<_Args>(__args)...)))
 	{ ::new((void *)__p) _Up(std::forward<_Args>(__args)...); }
 
       template<typename _Up>
 	void
-	destroy(_Up* __p) { __p->~_Up(); }
+	destroy(_Up* __p)
+	noexcept(noexcept(__p->~_Up()))
+	{ __p->~_Up(); }
 #endif
     };
 
   /**
    * @brief  The @a standard allocator, as per [20.4].
    *
    *  See https://gcc.gnu.org/onlinedocs/libstdc++/manual/memory.html#std.util.memory.allocator
    *  for further details.
    *
    *  @tparam  _Tp  Type of allocated object.
Index: libstdc++-v3/include/bits/stl_uninitialized.h
===================================================================
--- libstdc++-v3/include/bits/stl_uninitialized.h	(revision 265131)
+++ libstdc++-v3/include/bits/stl_uninitialized.h	(working copy)
@@ -872,14 +872,84 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     uninitialized_move_n(_InputIterator __first, _Size __count,
 			 _ForwardIterator __result)
     {
       auto __res = std::__uninitialized_copy_n_pair
 	(_GLIBCXX_MAKE_MOVE_ITERATOR(__first),
 	 __count, __result);
       return {__res.first.base(), __res.second};
     }
 #endif
 
+#if __cplusplus >= 201402L
+  template<typename _Tp, typename _Up>
+    inline void
+    __relocate(_Tp* __dest, _Up* __orig)
+    noexcept(is_nothrow_constructible<_Tp, _Up&&>::value)
+    {
+      ::new((void*)__dest) _Tp(std::move(*__orig));
+      __orig->~_Up();
+    }
+
+  template<typename _Tp, typename _Up, typename _Allocator>
+    inline void
+    __relocate_a(_Tp* __dest, _Up* __orig, _Allocator& __alloc)
+    noexcept(noexcept(__gnu_cxx::__alloc_traits<_Allocator>::construct(__alloc,
+			 __dest, std::move(*__orig)))
+	     && noexcept(__gnu_cxx::__alloc_traits<_Allocator>::destroy(
+			    __alloc, std::__addressof(*__orig))))
+    {
+      typedef __gnu_cxx::__alloc_traits<_Allocator> __traits;
+      __traits::construct(__alloc, __dest, std::move(*__orig));
+      __traits::destroy(__alloc, std::__addressof(*__orig));
+    }
+
+  template<typename _Tp>
+    struct __is_trivially_relocatable
+    : is_trivially_move_constructible<_Tp> { };
+
+  template <typename _Tp, typename _Up>
+    inline std::enable_if_t<std::__is_trivially_relocatable<_Tp>::value, _Tp*>
+    __relocate_a_1(_Tp* __first, _Tp* __last,
+		   _Tp* __result, allocator<_Up>& __alloc)
+    {
+      ptrdiff_t __count = __last - __first;
+      __builtin_memmove(__result, __first, __count * sizeof(_Tp));
+      return __result + __count;
+    }
+
+  template <typename _InputIterator, typename _ForwardIterator,
+	    typename _Allocator>
+    inline _ForwardIterator
+    __relocate_a_1(_InputIterator __first, _InputIterator __last,
+		   _ForwardIterator __result, _Allocator& __alloc)
+    {
+      typedef typename iterator_traits<_InputIterator>::value_type
+	_ValueType;
+      typedef typename iterator_traits<_ForwardIterator>::value_type
+	_ValueType2;
+      static_assert(std::is_same<_ValueType, _ValueType2>::value);
+      static_assert(noexcept(std::__relocate_a(std::addressof(*__result),
+					       std::addressof(*__first),
+					       __alloc)));
+      _ForwardIterator __cur = __result;
+      for (; __first != __last; ++__first, (void)++__cur)
+	std::__relocate_a(std::__addressof(*__cur),
+			  std::__addressof(*__first), __alloc);
+      return __cur;
+    }
+
+  template <typename _InputIterator, typename _ForwardIterator,
+	    typename _Allocator>
+    inline _ForwardIterator
+    __relocate_a(_InputIterator __first, _InputIterator __last,
+		 _ForwardIterator __result, _Allocator& __alloc)
+    {
+      return __relocate_a_1(std::__niter_base(__first),
+			    std::__niter_base(__last),
+			    std::__niter_base(__result), __alloc);
+    }
+#endif
+
 _GLIBCXX_END_NAMESPACE_VERSION
 } // namespace
 
 #endif /* _STL_UNINITIALIZED_H */
Index: libstdc++-v3/include/bits/stl_vector.h
===================================================================
--- libstdc++-v3/include/bits/stl_vector.h	(revision 265131)
+++ libstdc++-v3/include/bits/stl_vector.h	(working copy)
@@ -414,20 +414,28 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
       typedef typename _Alloc_traits::const_reference	const_reference;
       typedef __gnu_cxx::__normal_iterator<pointer, vector> iterator;
       typedef __gnu_cxx::__normal_iterator<const_pointer, vector>
       const_iterator;
       typedef std::reverse_iterator<const_iterator>	const_reverse_iterator;
       typedef std::reverse_iterator<iterator>		reverse_iterator;
       typedef size_t					size_type;
       typedef ptrdiff_t					difference_type;
       typedef _Alloc					allocator_type;
 
+    private:
+#if __cplusplus >= 201402L
+      static constexpr bool __use_relocate =
+	noexcept(std::__relocate_a(std::addressof(*std::declval<pointer>()),
+				   std::addressof(*std::declval<pointer>()),
+				   std::declval<_Tp_alloc_type&>()));
+#endif
+
     protected:
       using _Base::_M_allocate;
       using _Base::_M_deallocate;
       using _Base::_M_impl;
       using _Base::_M_get_Tp_allocator;
 
     public:
       // [23.2.4.1] construct/copy/destroy
       // (assign() and get_allocator() are also listed in this section)
 
Index: libstdc++-v3/include/bits/vector.tcc
===================================================================
--- libstdc++-v3/include/bits/vector.tcc	(revision 265131)
+++ libstdc++-v3/include/bits/vector.tcc	(working copy)
@@ -64,26 +64,39 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
   template<typename _Tp, typename _Alloc>
     void
     vector<_Tp, _Alloc>::
     reserve(size_type __n)
     {
       if (__n > this->max_size())
 	__throw_length_error(__N("vector::reserve"));
       if (this->capacity() < __n)
 	{
 	  const size_type __old_size = size();
-	  pointer __tmp = _M_allocate_and_copy(__n,
-	    _GLIBCXX_MAKE_MOVE_IF_NOEXCEPT_ITERATOR(this->_M_impl._M_start),
-	    _GLIBCXX_MAKE_MOVE_IF_NOEXCEPT_ITERATOR(this->_M_impl._M_finish));
+	  pointer __tmp;
+#if __cplusplus >= 201402L
+	  if constexpr (__use_relocate)
+	    {
+	      __tmp = this->_M_allocate(__n);
+	      std::__relocate_a(this->_M_impl._M_start,
+				this->_M_impl._M_finish,
+				__tmp, _M_get_Tp_allocator());
+	    }
+	  else
+#endif
+	    {
+	      __tmp = _M_allocate_and_copy(__n,
+		_GLIBCXX_MAKE_MOVE_IF_NOEXCEPT_ITERATOR(this->_M_impl._M_start),
+		_GLIBCXX_MAKE_MOVE_IF_NOEXCEPT_ITERATOR(this->_M_impl._M_finish));
+	      std::_Destroy(this->_M_impl._M_start, this->_M_impl._M_finish,
+			    _M_get_Tp_allocator());
+	    }
 	  _GLIBCXX_ASAN_ANNOTATE_REINIT;
-	  std::_Destroy(this->_M_impl._M_start, this->_M_impl._M_finish,
-			_M_get_Tp_allocator());
 	  _M_deallocate(this->_M_impl._M_start,
 			this->_M_impl._M_end_of_storage
 			- this->_M_impl._M_start);
 	  this->_M_impl._M_start = __tmp;
 	  this->_M_impl._M_finish = __tmp + __old_size;
 	  this->_M_impl._M_end_of_storage = this->_M_impl._M_start + __n;
 	}
     }
 
 #if __cplusplus >= 201103L
@@ -288,23 +301,23 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
       vector<_Tp, _Alloc>::
       _M_assign_aux(_ForwardIterator __first, _ForwardIterator __last,
 		    std::forward_iterator_tag)
       {
 	const size_type __len = std::distance(__first, __last);
 
 	if (__len > capacity())
 	  {
 	    _S_check_init_len(__len, _M_get_Tp_allocator());
 	    pointer __tmp(_M_allocate_and_copy(__len, __first, __last));
-	    _GLIBCXX_ASAN_ANNOTATE_REINIT;
 	    std::_Destroy(this->_M_impl._M_start, this->_M_impl._M_finish,
 			  _M_get_Tp_allocator());
+	    _GLIBCXX_ASAN_ANNOTATE_REINIT;
 	    _M_deallocate(this->_M_impl._M_start,
 			  this->_M_impl._M_end_of_storage
 			  - this->_M_impl._M_start);
 	    this->_M_impl._M_start = __tmp;
 	    this->_M_impl._M_finish = this->_M_impl._M_start + __len;
 	    this->_M_impl._M_end_of_storage = this->_M_impl._M_finish;
 	  }
 	else if (size() >= __len)
 	  _M_erase_at_end(std::copy(__first, __last, this->_M_impl._M_start));
 	else
@@ -436,44 +449,66 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 	  // [res.on.arguments]).
 	  _Alloc_traits::construct(this->_M_impl,
 				   __new_start + __elems_before,
 #if __cplusplus >= 201103L
 				   std::forward<_Args>(__args)...);
 #else
 				   __x);
 #endif
 	  __new_finish = pointer();
 
-	  __new_finish
-	    = std::__uninitialized_move_if_noexcept_a
-	    (__old_start, __position.base(),
-	     __new_start, _M_get_Tp_allocator());
-
-	  ++__new_finish;
-
-	  __new_finish
-	    = std::__uninitialized_move_if_noexcept_a
-	    (__position.base(), __old_finish,
-	     __new_finish, _M_get_Tp_allocator());
+#if __cplusplus >= 201402L
+	  if constexpr (__use_relocate)
+	    {
+	      __new_finish
+		= std::__relocate_a
+		(__old_start, __position.base(),
+		 __new_start, _M_get_Tp_allocator());
+
+	      ++__new_finish;
+
+	      __new_finish
+		= std::__relocate_a
+		(__position.base(), __old_finish,
+		 __new_finish, _M_get_Tp_allocator());
+	    }
+	  else
+#endif
+	    {
+	      __new_finish
+		= std::__uninitialized_move_if_noexcept_a
+		(__old_start, __position.base(),
+		 __new_start, _M_get_Tp_allocator());
+
+	      ++__new_finish;
+
+	      __new_finish
+		= std::__uninitialized_move_if_noexcept_a
+		(__position.base(), __old_finish,
+		 __new_finish, _M_get_Tp_allocator());
+	    }
 	}
       __catch(...)
 	{
 	  if (!__new_finish)
 	    _Alloc_traits::destroy(this->_M_impl,
 				   __new_start + __elems_before);
 	  else
 	    std::_Destroy(__new_start, __new_finish, _M_get_Tp_allocator());
 	  _M_deallocate(__new_start, __len);
 	  __throw_exception_again;
 	}
+#if __cplusplus >= 201402L
+      if constexpr (!__use_relocate)
+#endif
+	std::_Destroy(__old_start, __old_finish, _M_get_Tp_allocator());
       _GLIBCXX_ASAN_ANNOTATE_REINIT;
-      std::_Destroy(__old_start, __old_finish, _M_get_Tp_allocator());
       _M_deallocate(__old_start,
 		    this->_M_impl._M_end_of_storage - __old_start);
       this->_M_impl._M_start = __new_start;
       this->_M_impl._M_finish = __new_finish;
       this->_M_impl._M_end_of_storage = __new_start + __len;
     }
 
   template<typename _Tp, typename _Alloc>
     void
     vector<_Tp, _Alloc>::
@@ -555,23 +590,23 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 		  if (!__new_finish)
 		    std::_Destroy(__new_start + __elems_before,
 				  __new_start + __elems_before + __n,
 				  _M_get_Tp_allocator());
 		  else
 		    std::_Destroy(__new_start, __new_finish,
 				  _M_get_Tp_allocator());
 		  _M_deallocate(__new_start, __len);
 		  __throw_exception_again;
 		}
-	      _GLIBCXX_ASAN_ANNOTATE_REINIT;
 	      std::_Destroy(this->_M_impl._M_start, this->_M_impl._M_finish,
 			    _M_get_Tp_allocator());
+	      _GLIBCXX_ASAN_ANNOTATE_REINIT;
 	      _M_deallocate(this->_M_impl._M_start,
 			    this->_M_impl._M_end_of_storage
 			    - this->_M_impl._M_start);
 	      this->_M_impl._M_start = __new_start;
 	      this->_M_impl._M_finish = __new_finish;
 	      this->_M_impl._M_end_of_storage = __new_start + __len;
 	    }
 	}
     }
 
@@ -596,41 +631,62 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 	      this->_M_impl._M_finish =
 		std::__uninitialized_default_n_a(this->_M_impl._M_finish,
 						 __n, _M_get_Tp_allocator());
 	      _GLIBCXX_ASAN_ANNOTATE_GREW(__n);
 	    }
 	  else
 	    {
 	      const size_type __len =
 		_M_check_len(__n, "vector::_M_default_append");
 	      pointer __new_start(this->_M_allocate(__len));
-	      pointer __destroy_from = pointer();
-	      __try
+#if __cplusplus >= 201402L
+	      if constexpr (__use_relocate)
 		{
-		  std::__uninitialized_default_n_a(__new_start + __size,
-						   __n, _M_get_Tp_allocator());
-		  __destroy_from = __new_start + __size;
-		  std::__uninitialized_move_if_noexcept_a(
-		      this->_M_impl._M_start, this->_M_impl._M_finish,
-		      __new_start, _M_get_Tp_allocator());
+		  __try
+		    {
+		      std::__uninitialized_default_n_a(__new_start + __size,
+			      __n, _M_get_Tp_allocator());
+		    }
+		  __catch(...)
+		    {
+		      _M_deallocate(__new_start, __len);
+		      __throw_exception_again;
+		    }
+		  std::__relocate_a(this->_M_impl._M_start,
+				    this->_M_impl._M_finish,
+				    __new_start, _M_get_Tp_allocator());
 		}
-	      __catch(...)
+	      else
+#endif
 		{
-		  if (__destroy_from)
-		    std::_Destroy(__destroy_from, __destroy_from + __n,
-				  _M_get_Tp_allocator());
-		  _M_deallocate(__new_start, __len);
-		  __throw_exception_again;
+		  pointer __destroy_from = pointer();
+		  __try
+		    {
+		      std::__uninitialized_default_n_a(__new_start + __size,
+			      __n, _M_get_Tp_allocator());
+		      __destroy_from = __new_start + __size;
+		      std::__uninitialized_move_if_noexcept_a(
+			      this->_M_impl._M_start, this->_M_impl._M_finish,
+			      __new_start, _M_get_Tp_allocator());
+		    }
+		  __catch(...)
+		    {
+		      if (__destroy_from)
+			std::_Destroy(__destroy_from, __destroy_from + __n,
+				      _M_get_Tp_allocator());
+		      _M_deallocate(__new_start, __len);
+		      __throw_exception_again;
+		    }
+		  std::_Destroy(this->_M_impl._M_start, this->_M_impl._M_finish,
+				_M_get_Tp_allocator());
 		}
 	      _GLIBCXX_ASAN_ANNOTATE_REINIT;
-	      std::_Destroy(this->_M_impl._M_start, this->_M_impl._M_finish,
-			    _M_get_Tp_allocator());
 	      _M_deallocate(this->_M_impl._M_start,
 			    this->_M_impl._M_end_of_storage
 			    - this->_M_impl._M_start);
 	      this->_M_impl._M_start = __new_start;
 	      this->_M_impl._M_finish = __new_start + __size + __n;
 	      this->_M_impl._M_end_of_storage = __new_start + __len;
 	    }
 	}
     }
 
@@ -735,23 +791,23 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 		      (__position.base(), this->_M_impl._M_finish,
 		       __new_finish, _M_get_Tp_allocator());
 		  }
 		__catch(...)
 		  {
 		    std::_Destroy(__new_start, __new_finish,
 				  _M_get_Tp_allocator());
 		    _M_deallocate(__new_start, __len);
 		    __throw_exception_again;
 		  }
-		_GLIBCXX_ASAN_ANNOTATE_REINIT;
 		std::_Destroy(this->_M_impl._M_start, this->_M_impl._M_finish,
 			      _M_get_Tp_allocator());
+		_GLIBCXX_ASAN_ANNOTATE_REINIT;
 		_M_deallocate(this->_M_impl._M_start,
 			      this->_M_impl._M_end_of_storage
 			      - this->_M_impl._M_start);
 		this->_M_impl._M_start = __new_start;
 		this->_M_impl._M_finish = __new_finish;
 		this->_M_impl._M_end_of_storage = __new_start + __len;
 	      }
 	  }
       }
 
Index: libstdc++-v3/include/ext/alloc_traits.h
===================================================================
--- libstdc++-v3/include/ext/alloc_traits.h	(revision 265131)
+++ libstdc++-v3/include/ext/alloc_traits.h	(working copy)
@@ -73,29 +73,32 @@ template<typename _Alloc, typename = typ
     template<typename _Ptr>
       using __is_custom_pointer
 	= std::__and_<std::is_same<pointer, _Ptr>,
 		      std::__not_<std::is_pointer<_Ptr>>>;
 
   public:
     // overload construct for non-standard pointer types
     template<typename _Ptr, typename... _Args>
       static typename std::enable_if<__is_custom_pointer<_Ptr>::value>::type
       construct(_Alloc& __a, _Ptr __p, _Args&&... __args)
+      noexcept(noexcept(_Base_type::construct(__a, std::__to_address(__p),
+					      std::forward<_Args>(__args)...)))
       {
 	_Base_type::construct(__a, std::__to_address(__p),
 			      std::forward<_Args>(__args)...);
       }
 
     // overload destroy for non-standard pointer types
     template<typename _Ptr>
       static typename std::enable_if<__is_custom_pointer<_Ptr>::value>::type
       destroy(_Alloc& __a, _Ptr __p)
+      noexcept(noexcept(_Base_type::destroy(__a, std::__to_address(__p))))
       { _Base_type::destroy(__a, std::__to_address(__p)); }
 
     static _Alloc _S_select_on_copy(const _Alloc& __a)
     { return _Base_type::select_on_container_copy_construction(__a); }
 
     static void _S_on_swap(_Alloc& __a, _Alloc& __b)
     { std::__alloc_on_swap(__a, __b); }
 
     static constexpr bool _S_propagate_on_copy_assign()
     { return _Base_type::propagate_on_container_copy_assignment::value; }
Index: libstdc++-v3/include/ext/malloc_allocator.h
===================================================================
--- libstdc++-v3/include/ext/malloc_allocator.h	(revision 265131)
+++ libstdc++-v3/include/ext/malloc_allocator.h	(working copy)
@@ -144,25 +144,29 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	return size_t(__PTRDIFF_MAX__) / sizeof(_Tp);
 #else
 	return size_t(-1) / sizeof(_Tp);
 #endif
       }
 
 #if __cplusplus >= 201103L
       template<typename _Up, typename... _Args>
         void
         construct(_Up* __p, _Args&&... __args)
+	noexcept(noexcept(::new((void *)__p)
+			  _Up(std::forward<_Args>(__args)...)))
 	{ ::new((void *)__p) _Up(std::forward<_Args>(__args)...); }
 
       template<typename _Up>
         void 
-        destroy(_Up* __p) { __p->~_Up(); }
+        destroy(_Up* __p)
+	noexcept(noexcept(__p->~_Up()))
+	{ __p->~_Up(); }
 #else
       // _GLIBCXX_RESOLVE_LIB_DEFECTS
       // 402. wrong new expression in [some_] allocator::construct
       void 
       construct(pointer __p, const _Tp& __val) 
       { ::new((void *)__p) value_type(__val); }
 
       void 
       destroy(pointer __p) { __p->~_Tp(); }
 #endif
Index: libstdc++-v3/include/ext/new_allocator.h
===================================================================
--- libstdc++-v3/include/ext/new_allocator.h	(revision 265131)
+++ libstdc++-v3/include/ext/new_allocator.h	(working copy)
@@ -135,25 +135,29 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	return size_t(__PTRDIFF_MAX__) / sizeof(_Tp);
 #else
 	return size_t(-1) / sizeof(_Tp);
 #endif
       }
 
 #if __cplusplus >= 201103L
       template<typename _Up, typename... _Args>
 	void
 	construct(_Up* __p, _Args&&... __args)
+	noexcept(noexcept(::new((void *)__p)
+			    _Up(std::forward<_Args>(__args)...)))
 	{ ::new((void *)__p) _Up(std::forward<_Args>(__args)...); }
 
       template<typename _Up>
 	void
-	destroy(_Up* __p) { __p->~_Up(); }
+	destroy(_Up* __p)
+	noexcept(noexcept( __p->~_Up()))
+	{ __p->~_Up(); }
 #else
       // _GLIBCXX_RESOLVE_LIB_DEFECTS
       // 402. wrong new expression in [some_] allocator::construct
       void
       construct(pointer __p, const _Tp& __val)
       { ::new((void *)__p) _Tp(__val); }
 
       void
       destroy(pointer __p) { __p->~_Tp(); }
 #endif
Index: libstdc++-v3/testsuite/23_containers/vector/modifiers/push_back/49836.cc
===================================================================
--- libstdc++-v3/testsuite/23_containers/vector/modifiers/push_back/49836.cc	(revision 265131)
+++ libstdc++-v3/testsuite/23_containers/vector/modifiers/push_back/49836.cc	(working copy)
@@ -17,25 +17,25 @@
 // with this library; see the file COPYING3.  If not see
 // <http://www.gnu.org/licenses/>.
 
 #include <vector>
 #include <testsuite_hooks.h>
 #include <testsuite_tr1.h>
 
 // libstdc++/49836
 void test01()
 {
-  using __gnu_test::CopyConsOnlyType;
+  using __gnu_test::assign::DelAnyAssign;
   using __gnu_test::MoveConsOnlyType;
 
-  std::vector<CopyConsOnlyType> v1;
-  CopyConsOnlyType t1(1);
+  std::vector<DelAnyAssign> v1;
+  DelAnyAssign t1;
   v1.push_back(t1);
   v1.push_back(t1);
   v1.push_back(t1);
   VERIFY( v1.size() == 3 );
 
   std::vector<MoveConsOnlyType> v2;
   MoveConsOnlyType t2(1);
   v2.push_back(std::move(t2));
   v2.push_back(std::move(t2));
   v2.push_back(std::move(t2));

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]