Patchwork C++ PATCH for c++/46497 (is_convertible failure with defaulted move ctor)

login
register
mail settings
Submitter Jason Merrill
Date Nov. 17, 2010, 1:40 a.m.
Message ID <4CE33283.5070500@redhat.com>
Download mbox | patch
Permalink /patch/71502/
State New
Headers show

Comments

Jason Merrill - Nov. 17, 2010, 1:40 a.m.
This bug was hard to track down; it took me a long time to figure out 
what could have been the difference between cases that worked and cases 
that didn't.  Finally I realized that we were rejecting a deleted 
trivial move constructor in SFINAE context, but allowing it in normal 
context.  Fixed so we reject it consistently.

The second patch is a related case I noticed: It seems we would 
(incorrectly) reject copy-list-initialization involving a trivial 
deleted constructor in SFINAE context but (correctly) accept it in 
normal context.  Fixed by moving the special handling into 
convert_like_real.  The error handling change fixes a wrong "incomplete 
type" error for a class that is currently being defined.

Tested x86_64-pc-linux-gnu, applied to trunk.
commit 3441224d830415e3d7b907340addde2c2efcf123
Author: Jason Merrill <jason@redhat.com>
Date:   Tue Nov 16 14:47:49 2010 -0500

    	PR c++/46497
    	* call.c (build_over_call): Check for =delete even when trivial.
commit 4796a6c672241f2887369e758e8ebc24a3a1ade5
Author: Jason Merrill <jason@redhat.com>
Date:   Tue Nov 16 19:56:52 2010 -0500

    	* call.c (convert_like_real): Don't make a temp for copy-list-init.
    	(build_over_call): Don't handle that here.
    	(build_new_method_call): Use COMPLETE_OR_OPEN_TYPE_P for error.

diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 7fa1cf6..5e74bd2 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -5290,6 +5290,10 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
 	   conversion (i.e. the second step of copy-initialization), so
 	   don't allow any more.  */
 	flags |= LOOKUP_NO_CONVERSION;
+      if (TREE_CODE (expr) == TARGET_EXPR
+	  && TARGET_EXPR_LIST_INIT_P (expr))
+	/* Copy-list-initialization doesn't actually involve a copy.  */
+	return expr;
       expr = build_temp (expr, totype, flags, &diag_kind, complain);
       if (diag_kind && fn)
 	{
@@ -6049,15 +6053,9 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
       else
 	arg = cp_build_indirect_ref (arg, RO_NULL, complain);
 
-      if (TREE_CODE (arg) == TARGET_EXPR
-	  && TARGET_EXPR_LIST_INIT_P (arg))
-	{
-	  /* Copy-list-initialization doesn't require the constructor
-	     to be defined.  */
-	}
       /* [class.copy]: the copy constructor is implicitly defined even if
 	 the implementation elided its use.  */
-      else if (!trivial || DECL_DELETED_FN (fn))
+      if (!trivial || DECL_DELETED_FN (fn))
 	{
 	  mark_used (fn);
 	  already_used = true;
@@ -6641,7 +6639,7 @@ build_new_method_call (tree instance, tree fns, VEC(tree,gc) **args,
     {
       if (complain & tf_error)
 	{
-	  if (!COMPLETE_TYPE_P (basetype))
+	  if (!COMPLETE_OR_OPEN_TYPE_P (basetype))
 	    cxx_incomplete_type_error (instance_ptr, basetype);
 	  else if (optype)
 	    error ("no matching function for call to %<%T::operator %T(%A)%#V%>",

Patch

diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index eb7247d..7fa1cf6 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -6057,7 +6057,7 @@  build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
 	}
       /* [class.copy]: the copy constructor is implicitly defined even if
 	 the implementation elided its use.  */
-      else if (!trivial)
+      else if (!trivial || DECL_DELETED_FN (fn))
 	{
 	  mark_used (fn);
 	  already_used = true;
@@ -6086,7 +6086,8 @@  build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
 	}
     }
   else if (DECL_OVERLOADED_OPERATOR_P (fn) == NOP_EXPR
-	   && trivial_fn_p (fn))
+	   && trivial_fn_p (fn)
+	   && !DECL_DELETED_FN (fn))
     {
       tree to = stabilize_reference
 	(cp_build_indirect_ref (argarray[0], RO_NULL, complain));
diff --git a/gcc/testsuite/g++.dg/cpp0x/defaulted20.C b/gcc/testsuite/g++.dg/cpp0x/defaulted20.C
new file mode 100644
index 0000000..d9ad04f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/defaulted20.C
@@ -0,0 +1,19 @@ 
+// PR c++/46497
+// { dg-options -std=c++0x }
+
+struct A {
+  A(A&&) = default;		// { dg-message "A::A" }
+};
+struct B {
+  const A a;
+  B(const B&) = default;
+  B(B&&) = default;		// { dg-error "implicitly deleted|no match" }
+};
+
+void g(B);			// { dg-error "argument 1" }
+B&& f();
+
+int main()
+{
+  g(f());			// { dg-error "deleted" }
+}