Re: Fwd: Fix std::pair std::is_copy_assignable behavior

2013-04-13 Thread Paolo Carlini

On 04/13/2013 09:21 PM, François Dumont wrote:
Does DR 1402 resolution generalization need a Standard committee 
validation first ?
In my opinion, it's much more clear to send the C++ front-end patch 
*separately* together with a simple C++-only (no library) testcase. I 
would also CC Jason.


Paolo.


Fwd: Fix std::pair std::is_copy_assignable behavior

2013-04-13 Thread François Dumont


Hider

Here is a patch already posted to libstdc++ mailing but I am 
resending following libstdc++ maintainers advises to add gcc-patches 
mailing list.


This patch proposal is to fix the behavior of std::pair regarding 
the std::is_*_assignable meta programming functions.


As announced it is requiring a compiler patch to extend DR 1402 
resolution to all defaulted methods.


2013-04-12 François Dumont 

* call.c (joust): Extend DR 1402 to all defaulted methods.

This modification is mandatory so that pair& operator=(const pair&) 
can be defaulted whereas leaving gcc consider the other operator= in 
some situations like std::pair. This way, with usage of 
std::enable_if on the template operator=, we can control when p1= p2 is 
a valid expression resulting in a correct behavior of 
std::is_copy_assignable.


For the moment I preferred to add a dg-require-normal-mode option 
in the single test that fail to compile because of the compiler 
modification.


Does DR 1402 resolution generalization need a Standard committee 
validation first ?


2013-04-13  François Dumont  

* include/bits/stl_pair.h (operator=(const pair&)): Defaulted.
(operator=(pair&&)): Likewise.
(template<> operator=(const pair&)): Add noexcept
qualification. Enable if is_assignable true for both
parameters.
(template<> operator=(pair<>&&)): Add noexcept
qualification. Enable if is_assignable true for both
parameters.
* testsuite/23_containers/unordered_set/55043.cc: Add
dg-require-normal-mode.
* testsuite/20_util/pair/is_move_assignable.cc: New.
* testsuite/20_util/pair/is_copy_assignable.cc: Likewise.
* testsuite/20_util/pair/is_assignable.cc: Likewise.
* testsuite/20_util/pair/is_nothrow_move_assignable.cc: Likewise.
* testsuite/20_util/pair/assign_neg.cc: Likewise.
* testsuite/20_util/pair/is_nothrow_copy_assignable.cc: Likewise.
* testsuite/20_util/pair/assign.cc: Likewise.

François

Index: call.c
===
--- call.c	(revision 197829)
+++ call.c	(working copy)
@@ -8377,19 +8377,20 @@
   && (IS_TYPE_OR_DECL_P (cand1->fn)))
 return 1;
 
-  /* Prefer a non-deleted function over an implicitly deleted move
- constructor or assignment operator.  This differs slightly from the
- wording for issue 1402 (which says the move op is ignored by overload
- resolution), but this way produces better error messages.  */
+  /* Prefer a non-deleted function over an implicitly deleted one. This
+ differs slightly from the wording for issue 1402 because:
+ - it is extended to all defaulted functions, not only the ones with
+ move semantic
+ - it says the op is ignored by overload resolution while we are
+ only making it a worst candidate, but this way produces better error
+ messages.  */
   if (TREE_CODE (cand1->fn) == FUNCTION_DECL
   && TREE_CODE (cand2->fn) == FUNCTION_DECL
   && DECL_DELETED_FN (cand1->fn) != DECL_DELETED_FN (cand2->fn))
 {
-  if (DECL_DELETED_FN (cand1->fn) && DECL_DEFAULTED_FN (cand1->fn)
-	  && move_fn_p (cand1->fn))
+  if (DECL_DELETED_FN (cand1->fn) && DECL_DEFAULTED_FN (cand1->fn))
 	return -1;
-  if (DECL_DELETED_FN (cand2->fn) && DECL_DEFAULTED_FN (cand2->fn)
-	  && move_fn_p (cand2->fn))
+  if (DECL_DELETED_FN (cand2->fn) && DECL_DEFAULTED_FN (cand2->fn))
 	return 1;
 }
 

Index: include/bits/stl_pair.h
===
--- include/bits/stl_pair.h	(revision 197829)
+++ include/bits/stl_pair.h	(working copy)
@@ -155,26 +155,18 @@
 pair(piecewise_construct_t, tuple<_Args1...>, tuple<_Args2...>);
 
   pair&
-  operator=(const pair& __p)
-  {
-	first = __p.first;
-	second = __p.second;
-	return *this;
-  }
+  operator=(const pair&) = default;
 
   pair&
-  operator=(pair&& __p)
-  noexcept(__and_,
-	  is_nothrow_move_assignable<_T2>>::value)
-  {
-	first = std::forward(__p.first);
-	second = std::forward(__p.second);
-	return *this;
-  }
+  operator=(pair&&) = default;
 
   template
-	pair&
+	typename enable_if<__and_,
+  is_assignable<_T2&, const _U2&>>::value,
+			   pair&>::type
 	operator=(const pair<_U1, _U2>& __p)
+	noexcept(__and_,
+			is_nothrow_assignable<_T2&, const _U2&>>::value)
 	{
 	  first = __p.first;
 	  second = __p.second;
@@ -182,8 +174,12 @@
 	}
 
   template
-	pair&
+  	typename enable_if<__and_,
+    is_assignable<_T2&, _U2&&>>::value,
+  			   pair&>::type
 	operator=(pair<_U1, _U2>&& __p)
+	noexcept(__and_,
+			is_nothrow_assignable<_T2&, _U2&&>>::value)
 	{
 	  first = std::forward<_U1>(__p.first);
 	  second = std::forward<_U2>(__p.second);
Index: testsuite/23_containers/unordered_set/55043.cc
===
--- testsuite/23_containers/unordered_set/55043.cc	(revision 197829)
+++ test