diff mbox

C++ PATCH for c++/49102 (missing error with private defaulted copy ctor and ellipsis)

Message ID 4DDB2A2C.9050805@redhat.com
State New
Headers show

Commit Message

Jason Merrill May 24, 2011, 3:46 a.m. UTC
In this case, the copy constructor is trivial, so we don't complain 
about having a non-trivial copy constructor.  But we should still be 
doing the lvalue-rvalue conversion, which strictly speaking involves a 
copy constructor call.

Tested x86_64-pc-linux-gnu, applying to trunk.
diff mbox

Patch

commit a3138b14669986fe312a9579e79edcf091026eec
Author: Jason Merrill <jason@redhat.com>
Date:   Mon May 23 13:52:01 2011 -0400

    	PR c++/49102
    	* call.c (convert_arg_to_ellipsis): Call force_rvalue.

diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 8503f5e..ff3dc06 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -5905,10 +5905,13 @@  convert_arg_to_ellipsis (tree arg)
       /* In a template (or ill-formed code), we can have an incomplete type
 	 even after require_complete_type, in which case we don't know
 	 whether it has trivial copy or not.  */
-      && COMPLETE_TYPE_P (arg_type)
-      && (type_has_nontrivial_copy_init (arg_type)
-	  || TYPE_HAS_NONTRIVIAL_DESTRUCTOR (arg_type)))
+      && COMPLETE_TYPE_P (arg_type))
     {
+      /* Build up a real lvalue-to-rvalue conversion in case the
+	 copy constructor is trivial but not callable.  */
+      if (CLASS_TYPE_P (arg_type))
+	force_rvalue (arg, tf_warning_or_error);
+
       /* [expr.call] 5.2.2/7:
 	 Passing a potentially-evaluated argument of class type (Clause 9)
 	 with a non-trivial copy constructor or a non-trivial destructor
@@ -5920,7 +5923,9 @@  convert_arg_to_ellipsis (tree arg)
 
 	 If the call appears in the context of a sizeof expression,
 	 it is not potentially-evaluated.  */
-      if (cp_unevaluated_operand == 0)
+      if (cp_unevaluated_operand == 0
+	  && (type_has_nontrivial_copy_init (arg_type)
+	      || TYPE_HAS_NONTRIVIAL_DESTRUCTOR (arg_type)))
 	error ("cannot pass objects of non-trivially-copyable "
 	       "type %q#T through %<...%>", arg_type);
     }
diff --git a/gcc/testsuite/g++.dg/cpp0x/defaulted28.C b/gcc/testsuite/g++.dg/cpp0x/defaulted28.C
new file mode 100644
index 0000000..15caef6
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/defaulted28.C
@@ -0,0 +1,15 @@ 
+// PR c++/49102
+// { dg-options -std=c++0x }
+
+struct A {
+  A() = default;
+
+private:
+  A(A const&) = default;	// { dg-error "private" }
+};
+
+void f(...) { }
+int main() {
+  A a;
+  f(a); 			// { dg-error "this context" }
+}