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);
+}

Reply via email to