[PATCH] libstdc++/89130 and libstdc++/89090 fixes for vector relocation

Jonathan Wakely jwakely@redhat.com
Tue Feb 26 20:35:00 GMT 2019


On 24/02/19 15:46 +0000, Jonathan Wakely wrote:
>On 21/02/19 20:47 +0000, Jonathan Wakely wrote:
>>On 05/02/19 14:45 +0000, Jonathan Wakely wrote:
>>>This fixes two PRs, one trivial (don't use C++17 features in C++11
>>>mode) and one more serious (don't require MoveInsertable when we
>>>should only need CopyInsertable).
>>>
>>>It would be nice to rely on if-constexpr in C++11 mode, but it causes
>>>clang warnings, complicates testcase bisection/reduction, and causes
>>>users to file bogus bug reports. So let's just avoid it.
>>>
>>>Tested powerpc64le-linux, committed to trunk.
>>>
>>>
>>
>>>commit 51908e56bd32b5f89bc909193c3da957de01c3e0
>>>Author: Jonathan Wakely <jwakely@redhat.com>
>>>Date:   Tue Feb 5 11:50:18 2019 +0000
>>>
>>>  PR libstdc++/89130 restore support for non-MoveConstructible types
>>>  The changes to "relocate" std::vector elements can lead to new errors
>>>  outside the immediate context, because moving the elements to new
>>>  storage no longer makes use of the move-if-noexcept utilities. This
>>>  means that types with deleted moves no longer degenerate to copies, but
>>>  are just ill-formed. The errors happen while instantiating the
>>>  noexcept-specifier for __relocate_object_a, when deciding whether to try
>>>  to relocate.
>>>  This patch introduces indirections to avoid the ill-formed
>>>  instantiations of std::__relocate_object_a. In order to avoid using
>>>  if-constexpr prior to C++17 this is done by tag dispatching. After this
>>>  patch all uses of std::__relocate_a are guarded by checks that will
>>>  support sensible code (i.e. code not using custom allocators that fool
>>>  the new checks).
>>>          PR libstdc++/89130
>>>          * include/bits/alloc_traits.h (__is_copy_insertable_impl): Rename to
>>>          __is_alloc_insertable_impl. Replace single type member with two
>>>          members, one for each of copy and move insertable.
>>>          (__is_move_insertable): New trait for internal use.
>>>          * include/bits/stl_vector.h (vector::_S_nothrow_relocate(true_type))
>>>          (vector::_S_nothrow_relocate(true_type)): New functions to
>>>          conditionally check if __relocate_a can throw.
>>>          (vector::_S_use_relocate()): Dispatch to _S_nothrow_relocate based
>>>          on __is_move_insertable.
>>>          (vector::_S_do_relocate): New overloaded functions to conditionally
>>>          call __relocate_a.
>>>          (vector::_S_relocate): New function that dispatches to _S_do_relocate
>>>          based on _S_use_relocate.
>>>          * include/bits/vector.tcc (vector::reserve, vector::_M_realloc_insert)
>>>          (vector::_M_default_append): Call _S_relocate instead of __relocate_a.
>>>          * testsuite/23_containers/vector/modifiers/push_back/89130.cc: New.
>>>
>>>diff --git a/libstdc++-v3/include/bits/alloc_traits.h b/libstdc++-v3/include/bits/alloc_traits.h
>>>index ed61ce845f8..3b0c16fbf64 100644
>>>--- a/libstdc++-v3/include/bits/alloc_traits.h
>>>+++ b/libstdc++-v3/include/bits/alloc_traits.h
>>>@@ -577,14 +577,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>>>   }
>>>
>>> template<typename _Alloc>
>>>-    class __is_copy_insertable_impl
>>>+    class __is_alloc_insertable_impl
>>>   {
>>>-      typedef allocator_traits<_Alloc> _Traits;
>>>+      using _Traits = allocator_traits<_Alloc>;
>>>+      using value_type = typename _Traits::value_type;
>>>
>>>-      template<typename _Up, typename
>>>+      template<typename _Up, typename _Tp = __remove_cvref_t<_Up>,
>>>+	       typename
>>>	       = decltype(_Traits::construct(std::declval<_Alloc&>(),
>>>-					     std::declval<_Up*>(),
>>>-					     std::declval<const _Up&>()))>
>>>+					     std::declval<_Tp*>(),
>>>+					     std::declval<_Up>()))>
>>>	static true_type
>>>	_M_select(int);
>>>
>>>@@ -593,13 +595,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>>>	_M_select(...);
>>>
>>>   public:
>>>-      typedef decltype(_M_select<typename _Alloc::value_type>(0)) type;
>>>+      using copy = decltype(_M_select<const value_type&>(0));
>>>+      using move = decltype(_M_select<value_type>(0));
>>
>>This caused another regression, fixed by the attached patch.
>
>That patch doesn't work with Clang because I made the members
>protected and forgot to make them public again (and GCC doesn't cre,
>only Clang notices).

Aaaand another patch for Clang, because my test using Clang was flawed
and only tested std::allocator, which is handled by the partial
specialization. These problems are not found using G++ because of the
numerous bugs with access control in templates.

Tested powerpc64le-linux, committed to trunk.


-------------- next part --------------
A non-text attachment was scrubbed...
Name: patch.txt
Type: text/x-patch
Size: 3091 bytes
Desc: not available
URL: <http://gcc.gnu.org/pipermail/libstdc++/attachments/20190226/a7ea1b91/attachment.bin>


More information about the Libstdc++ mailing list