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 <jwak...@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.
Tested powerpc64le-linux, committed to trunk.
commit 802fc355d929152fb2c70e5fc1422d16143eeb10
Author: Jonathan Wakely <jwak...@redhat.com>
Date: Thu Feb 21 02:28:16 2019 +0000
PR libstdc++/89416 fix __is_move_insertable trait
The common base class for __is_move_insertable and __is_copy_insertable
instantiates both the copy and move tests, when only one is needed. The
unneeded one might cause errors outside the immediate context.
The solution used in this patch is to replace them with alias templates,
which will only be instantiated as needed.
PR libstdc++/89416
* include/bits/alloc_traits.h (__is_alloc_insertable_impl): Replace
class template with class. Replace move and copy member types with
member alias templates, so they are only instantiated when needed.
(__is_copy_insertable, __is_move_insertable): Adjust base class.
* testsuite/23_containers/vector/modifiers/push_back/89130.cc: Enable
test for C++11/14/17 as well.
* testsuite/23_containers/vector/modifiers/push_back/89416.cc: New
test.
diff --git a/libstdc++-v3/include/bits/alloc_traits.h b/libstdc++-v3/include/bits/alloc_traits.h
index 3b0c16fbf64..71892cbfaba 100644
--- a/libstdc++-v3/include/bits/alloc_traits.h
+++ b/libstdc++-v3/include/bits/alloc_traits.h
@@ -576,33 +576,32 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__do_alloc_on_swap(__one, __two, __pocs());
}
- template<typename _Alloc>
- class __is_alloc_insertable_impl
- {
- using _Traits = allocator_traits<_Alloc>;
- using value_type = typename _Traits::value_type;
+ class __is_alloc_insertable_impl
+ {
+ template<typename _Alloc, typename _Up,
+ typename _Tp = __remove_cvref_t<_Up>,
+ typename = decltype(allocator_traits<_Alloc>::construct(
+ std::declval<_Alloc&>(), std::declval<_Tp*>(),
+ std::declval<_Up>()))>
+ static true_type
+ _M_select(int);
- template<typename _Up, typename _Tp = __remove_cvref_t<_Up>,
- typename
- = decltype(_Traits::construct(std::declval<_Alloc&>(),
- std::declval<_Tp*>(),
- std::declval<_Up>()))>
- static true_type
- _M_select(int);
+ template<typename, typename>
+ static false_type
+ _M_select(...);
- template<typename _Up>
- static false_type
- _M_select(...);
+ protected:
+ template<typename _Alloc, typename _Tp = typename _Alloc::value_type>
+ using copy = decltype(_M_select<_Alloc, const _Tp&>(0));
- public:
- using copy = decltype(_M_select<const value_type&>(0));
- using move = decltype(_M_select<value_type>(0));
- };
+ template<typename _Alloc, typename _Tp = typename _Alloc::value_type>
+ using move = decltype(_M_select<_Alloc, _Tp>(0));
+ };
// true if _Alloc::value_type is CopyInsertable into containers using _Alloc
template<typename _Alloc>
struct __is_copy_insertable
- : __is_alloc_insertable_impl<_Alloc>::copy
+ : __is_alloc_insertable_impl::template copy<_Alloc>
{ };
// std::allocator<_Tp> just requires CopyConstructible
@@ -614,7 +613,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// true if _Alloc::value_type is MoveInsertable into containers using _Alloc
template<typename _Alloc>
struct __is_move_insertable
- : __is_alloc_insertable_impl<_Alloc>::move
+ : __is_alloc_insertable_impl::template move<_Alloc>
{ };
// std::allocator<_Tp> just requires MoveConstructible
diff --git a/libstdc++-v3/testsuite/23_containers/vector/modifiers/push_back/89130.cc b/libstdc++-v3/testsuite/23_containers/vector/modifiers/push_back/89130.cc
index 54b3f53069b..1a34f3e25d3 100644
--- a/libstdc++-v3/testsuite/23_containers/vector/modifiers/push_back/89130.cc
+++ b/libstdc++-v3/testsuite/23_containers/vector/modifiers/push_back/89130.cc
@@ -15,8 +15,7 @@
// with this library; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>.
-// { dg-options "-std=gnu++2a" }
-// { dg-do compile { target c++2a } }
+// { dg-do compile { target c++11 } }
#include <vector>
diff --git a/libstdc++-v3/testsuite/23_containers/vector/modifiers/push_back/89416.cc b/libstdc++-v3/testsuite/23_containers/vector/modifiers/push_back/89416.cc
new file mode 100644
index 00000000000..b1077611887
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/vector/modifiers/push_back/89416.cc
@@ -0,0 +1,44 @@
+// Copyright (C) 2019 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-do compile { target c++11 } }
+
+// PR libstdc++/89416
+
+#include <vector>
+
+template<typename T>
+ struct Alloc : std::allocator<T>
+ {
+ using std::allocator<T>::allocator;
+
+ template<typename U>
+ struct rebind { using other = Alloc<U>; };
+ };
+
+struct X
+{
+ X(int);
+ X(X&&);
+};
+
+void test01()
+{
+ std::vector<X, Alloc<X>> V;
+ V.push_back(X(1));
+ V.emplace_back(1);
+}