public inbox for libstdc++@gcc.gnu.org
 help / color / mirror / Atom feed
* [committed] libstdc++: Simplify noexcept-specifiers for move constructors
@ 2021-04-08 16:50 Jonathan Wakely
  2021-04-09 12:06 ` Jonathan Wakely
  0 siblings, 1 reply; 2+ messages in thread
From: Jonathan Wakely @ 2021-04-08 16:50 UTC (permalink / raw)
  To: libstdc++, gcc-patches

[-- Attachment #1: Type: text/plain, Size: 917 bytes --]

This puts the logic for the noexcept-specifier in one place, and then
reuses it elsewhere. This means checking whether the move constructor
can throw doesn't need to do overload resolution and then check whether
some other constructor can throw, we just get the answer directly.

libstdc++-v3/ChangeLog:

	* include/bits/hashtable.h (_Hashtable::_S_nothrow_move()):
	New function to determine noexcept-specifier for move
	constructors.
	(_Hashtable): Use _S_nothrow_move() on move constructors.
	* testsuite/23_containers/unordered_map/cons/noexcept_move_construct.cc:
	Correct static assertion message.
	* testsuite/23_containers/unordered_multimap/cons/noexcept_move_construct.cc:
	Likewise.
	* testsuite/23_containers/unordered_multiset/cons/noexcept_move_construct.cc:
	Likewise.
	* testsuite/23_containers/unordered_set/cons/noexcept_move_construct.cc:
	Likewise.

Tested powerpc64le-linux. Committed to trunk.


[-- Attachment #2: patch.txt --]
[-- Type: text/plain, Size: 8754 bytes --]

commit 1cbba49e3417d9b0661e70301d6fb7a7f52fd360
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Thu Apr 8 16:29:11 2021

    libstdc++: Simplify noexcept-specifiers for move constructors
    
    This puts the logic for the noexcept-specifier in one place, and then
    reuses it elsewhere. This means checking whether the move constructor
    can throw doesn't need to do overload resolution and then check whether
    some other constructor can throw, we just get the answer directly.
    
    libstdc++-v3/ChangeLog:
    
            * include/bits/hashtable.h (_Hashtable::_S_nothrow_move()):
            New function to determine noexcept-specifier for move
            constructors.
            (_Hashtable): Use _S_nothrow_move() on move constructors.
            * testsuite/23_containers/unordered_map/cons/noexcept_move_construct.cc:
            Correct static assertion message.
            * testsuite/23_containers/unordered_multimap/cons/noexcept_move_construct.cc:
            Likewise.
            * testsuite/23_containers/unordered_multiset/cons/noexcept_move_construct.cc:
            Likewise.
            * testsuite/23_containers/unordered_set/cons/noexcept_move_construct.cc:
            Likewise.

diff --git a/libstdc++-v3/include/bits/hashtable.h b/libstdc++-v3/include/bits/hashtable.h
index fa80675ad91..39872ce5342 100644
--- a/libstdc++-v3/include/bits/hashtable.h
+++ b/libstdc++-v3/include/bits/hashtable.h
@@ -472,10 +472,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	__hashtable_alloc(__node_alloc_type(__a))
       { }
 
+      template<bool _No_realloc = true>
+	static constexpr bool
+	_S_nothrow_move()
+	{
+	  if _GLIBCXX17_CONSTEXPR (_No_realloc)
+	    if _GLIBCXX17_CONSTEXPR (is_nothrow_copy_constructible<_Hash>())
+	      return is_nothrow_copy_constructible<_Equal>();
+	  return false;
+	}
+
       _Hashtable(_Hashtable&& __ht, __node_alloc_type&& __a,
 		 true_type /* alloc always equal */)
-	noexcept(std::is_nothrow_copy_constructible<_Hash>::value &&
-		 std::is_nothrow_copy_constructible<_Equal>::value);
+	noexcept(_S_nothrow_move());
 
       _Hashtable(_Hashtable&&, __node_alloc_type&&,
 		 false_type /* alloc always equal */);
@@ -508,19 +517,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
       // Use delegating constructors.
       _Hashtable(_Hashtable&& __ht)
-	noexcept( noexcept(
-	  _Hashtable(std::declval<_Hashtable>(),
-		     std::declval<__node_alloc_type>(),
-		     true_type{})) )
+	noexcept(_S_nothrow_move())
       : _Hashtable(std::move(__ht), std::move(__ht._M_node_allocator()),
 		   true_type{})
       { }
 
       _Hashtable(_Hashtable&& __ht, const allocator_type& __a)
-	noexcept( noexcept(
-	  _Hashtable(std::declval<_Hashtable>(),
-		     std::declval<__node_alloc_type>(),
-		     typename __node_alloc_traits::is_always_equal{})) )
+	noexcept(_S_nothrow_move<__node_alloc_traits::_S_always_equal()>())
       : _Hashtable(std::move(__ht), __node_alloc_type(__a),
 		   typename __node_alloc_traits::is_always_equal{})
       { }
@@ -1400,8 +1403,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	       _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
     _Hashtable(_Hashtable&& __ht, __node_alloc_type&& __a,
 	       true_type /* alloc always equal */)
-    noexcept(std::is_nothrow_copy_constructible<_Hash>::value &&
-	     std::is_nothrow_copy_constructible<_Equal>::value)
+    noexcept(_S_nothrow_move())
     : __hashtable_base(__ht),
       __map_base(__ht),
       __rehash_base(__ht),
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_map/cons/noexcept_move_construct.cc b/libstdc++-v3/testsuite/23_containers/unordered_map/cons/noexcept_move_construct.cc
index 96245aa4c88..015646adf23 100644
--- a/libstdc++-v3/testsuite/23_containers/unordered_map/cons/noexcept_move_construct.cc
+++ b/libstdc++-v3/testsuite/23_containers/unordered_map/cons/noexcept_move_construct.cc
@@ -40,7 +40,7 @@ struct not_noexcept_copy_cons_hash
 using type2 = std::unordered_map<int, int, not_noexcept_copy_cons_hash>;
 
 static_assert( !std::is_nothrow_move_constructible<type2>::value,
-	       "noexcept move constructor" );
+	       "not noexcept move constructor" );
 static_assert( !std::is_nothrow_constructible<type2, type2&&,
 	       const typename type2::allocator_type&>::value,
 	       "not noexcept move constructor with allocator" );
@@ -59,7 +59,7 @@ using type3 = std::unordered_map<int, int, std::hash<int>,
 				  not_noexcept_copy_cons_equal_to>;
 
 static_assert( !std::is_nothrow_move_constructible<type3>::value,
-	       "noexcept move constructor" );
+	       "not noexcept move constructor" );
 static_assert( !std::is_nothrow_constructible<type3, type3&&,
 	       const typename type3::allocator_type&>::value,
 	       "not noexcept move constructor with allocator" );
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_multimap/cons/noexcept_move_construct.cc b/libstdc++-v3/testsuite/23_containers/unordered_multimap/cons/noexcept_move_construct.cc
index efc8d337e7e..1e0b1059d7d 100644
--- a/libstdc++-v3/testsuite/23_containers/unordered_multimap/cons/noexcept_move_construct.cc
+++ b/libstdc++-v3/testsuite/23_containers/unordered_multimap/cons/noexcept_move_construct.cc
@@ -40,7 +40,7 @@ struct not_noexcept_copy_cons_hash
 using type2 = std::unordered_multimap<int, int, not_noexcept_copy_cons_hash>;
 
 static_assert( !std::is_nothrow_move_constructible<type2>::value,
-	       "noexcept move constructor" );
+	       "not not noexcept move constructor" );
 static_assert( !std::is_nothrow_constructible<type2, type2&&,
 	       const typename type2::allocator_type&>::value,
 	       "not noexcept move constructor with allocator" );
@@ -59,7 +59,7 @@ using type3 = std::unordered_multimap<int, int, std::hash<int>,
 				       not_noexcept_copy_cons_equal_to>;
 
 static_assert( !std::is_nothrow_move_constructible<type3>::value,
-	       "noexcept move constructor" );
+	       "not not noexcept move constructor" );
 static_assert( !std::is_nothrow_constructible<type3, type3&&,
 	       const typename type3::allocator_type&>::value,
 	       "not noexcept move constructor with allocator" );
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_multiset/cons/noexcept_move_construct.cc b/libstdc++-v3/testsuite/23_containers/unordered_multiset/cons/noexcept_move_construct.cc
index cc2a8e31051..3e603802f13 100644
--- a/libstdc++-v3/testsuite/23_containers/unordered_multiset/cons/noexcept_move_construct.cc
+++ b/libstdc++-v3/testsuite/23_containers/unordered_multiset/cons/noexcept_move_construct.cc
@@ -40,7 +40,7 @@ struct not_noexcept_copy_cons_hash
 using type2 = std::unordered_multiset<int, not_noexcept_copy_cons_hash>;
 
 static_assert( !std::is_nothrow_move_constructible<type2>::value,
-	       "noexcept move constructor" );
+	       "not noexcept move constructor" );
 static_assert( !std::is_nothrow_constructible<type2, type2&&,
 	       const typename type2::allocator_type&>::value,
 	       "not noexcept move constructor with allocator" );
@@ -59,7 +59,7 @@ using type3 = std::unordered_multiset<int, std::hash<int>,
 				      not_noexcept_copy_cons_equal_to>;
 
 static_assert( !std::is_nothrow_move_constructible<type3>::value,
-	       "noexcept move constructor" );
+	       "not noexcept move constructor" );
 static_assert( !std::is_nothrow_constructible<type3, type3&&,
 	       const typename type3::allocator_type&>::value,
 	       "not noexcept move constructor with allocator" );
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_set/cons/noexcept_move_construct.cc b/libstdc++-v3/testsuite/23_containers/unordered_set/cons/noexcept_move_construct.cc
index f68095302d5..28cb539e9f5 100644
--- a/libstdc++-v3/testsuite/23_containers/unordered_set/cons/noexcept_move_construct.cc
+++ b/libstdc++-v3/testsuite/23_containers/unordered_set/cons/noexcept_move_construct.cc
@@ -40,7 +40,7 @@ struct not_noexcept_copy_cons_hash
 using type2 = std::unordered_set<int, not_noexcept_copy_cons_hash>;
 
 static_assert( !std::is_nothrow_move_constructible<type2>::value,
-	       "noexcept move constructor" );
+	       "not noexcept move constructor" );
 static_assert( !std::is_nothrow_constructible<type2, type2&&,
 	       const typename type2::allocator_type&>::value,
 	       "not noexcept move constructor with allocator" );
@@ -59,7 +59,7 @@ using type3 = std::unordered_set<int, std::hash<int>,
 				  not_noexcept_copy_cons_equal_to>;
 
 static_assert( !std::is_nothrow_move_constructible<type3>::value,
-	       "noexcept move constructor" );
+	       "not noexcept move constructor" );
 static_assert( !std::is_nothrow_constructible<type3, type3&&,
 	       const typename type3::allocator_type&>::value,
 	       "not noexcept move constructor with allocator" );

^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: [committed] libstdc++: Simplify noexcept-specifiers for move constructors
  2021-04-08 16:50 [committed] libstdc++: Simplify noexcept-specifiers for move constructors Jonathan Wakely
@ 2021-04-09 12:06 ` Jonathan Wakely
  0 siblings, 0 replies; 2+ messages in thread
From: Jonathan Wakely @ 2021-04-09 12:06 UTC (permalink / raw)
  To: libstdc++, gcc-patches

[-- Attachment #1: Type: text/plain, Size: 1163 bytes --]

On 08/04/21 17:50 +0100, Jonathan Wakely wrote:
>This puts the logic for the noexcept-specifier in one place, and then
>reuses it elsewhere. This means checking whether the move constructor
>can throw doesn't need to do overload resolution and then check whether
>some other constructor can throw, we just get the answer directly.
>
>libstdc++-v3/ChangeLog:
>
>	* include/bits/hashtable.h (_Hashtable::_S_nothrow_move()):
>	New function to determine noexcept-specifier for move
>	constructors.
>	(_Hashtable): Use _S_nothrow_move() on move constructors.
>	* testsuite/23_containers/unordered_map/cons/noexcept_move_construct.cc:
>	Correct static assertion message.
>	* testsuite/23_containers/unordered_multimap/cons/noexcept_move_construct.cc:
>	Likewise.
>	* testsuite/23_containers/unordered_multiset/cons/noexcept_move_construct.cc:
>	Likewise.
>	* testsuite/23_containers/unordered_set/cons/noexcept_move_construct.cc:
>	Likewise.
>

I keep forgetting that a constexpr function in C++11 has to be a single
return statement.

I'm testing this patch now and will push to trunk and backport to the
branches where I already backported the breakage (facepalm).



[-- Attachment #2: patch.txt --]
[-- Type: text/x-patch, Size: 3307 bytes --]

commit ea14e090ebfa8bb52583ccc1a78db06a759a63ef
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Fri Apr 9 12:05:39 2021

    libstdc++: Fix invalid constexpr function in C++11 mode [PR 99985]
    
    I keep forgetting that a constexpr function in C++11 has to be a single
    return statement.
    
    libstdc++-v3/ChangeLog:
    
            PR libstdc++/99985
            * include/bits/hashtable.h (_Hashtable::_S_nothrow_move()): Fix
            to be a valid constexpr function in C++11.
            * testsuite/23_containers/unordered_set/cons/99985.cc: New test.

diff --git a/libstdc++-v3/include/bits/hashtable.h b/libstdc++-v3/include/bits/hashtable.h
index 39872ce5342..6711d08e6b8 100644
--- a/libstdc++-v3/include/bits/hashtable.h
+++ b/libstdc++-v3/include/bits/hashtable.h
@@ -476,10 +476,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	static constexpr bool
 	_S_nothrow_move()
 	{
-	  if _GLIBCXX17_CONSTEXPR (_No_realloc)
-	    if _GLIBCXX17_CONSTEXPR (is_nothrow_copy_constructible<_Hash>())
+#if __cplusplus <= 201402L
+	  return __and_<__bool_constant<_No_realloc>,
+			is_nothrow_copy_constructible<_Hash>,
+			is_nothrow_copy_constructible<_Equal>>::value;
+#else
+	  if constexpr (_No_realloc)
+	    if constexpr (is_nothrow_copy_constructible<_Hash>())
 	      return is_nothrow_copy_constructible<_Equal>();
 	  return false;
+#endif
 	}
 
       _Hashtable(_Hashtable&& __ht, __node_alloc_type&& __a,
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_set/cons/99985.cc b/libstdc++-v3/testsuite/23_containers/unordered_set/cons/99985.cc
new file mode 100644
index 00000000000..b209f7627f5
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/unordered_set/cons/99985.cc
@@ -0,0 +1,47 @@
+// Copyright (C) 2021 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-options "-std=gnu++11" }
+// { dg-do compile { target c++11 } }
+
+#include <unordered_set>
+#include <testsuite_allocator.h>
+
+template<typename Alloc, typename T = typename Alloc::value_type>
+  using Set = std::unordered_set<T, std::hash<T>, std::equal_to<T>, Alloc>;
+
+// PR libstdc++/99985 - invalid constexpr function in C++11 mode
+
+void
+test01()
+{
+  using A = std::allocator<int>;
+  A a;
+  Set<A> s;
+  static_assert( noexcept( Set<A>(std::move(s)) ), "non-throwing" );
+  static_assert( noexcept( Set<A>(std::move(s), a) ), "non-throwing" );
+}
+
+void
+test02()
+{
+  using A = __gnu_test::uneq_allocator<long>;
+  A a;
+  Set<A> s;
+  static_assert( noexcept( Set<A>(std::move(s)) ), "non-throwing" );
+  static_assert( ! noexcept( Set<A>(std::move(s), a) ), "throwing" );
+}

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2021-04-09 12:06 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-04-08 16:50 [committed] libstdc++: Simplify noexcept-specifiers for move constructors Jonathan Wakely
2021-04-09 12:06 ` Jonathan Wakely

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).