* call.c (build_x_va_arg): Support passing non-POD through ....
authorjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 13 Aug 2014 18:25:06 +0000 (18:25 +0000)
committerjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 13 Aug 2014 18:25:06 +0000 (18:25 +0000)
(convert_arg_to_ellipsis): Likewise.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@213921 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/cp/ChangeLog
gcc/cp/call.c
gcc/doc/implement-cxx.texi
gcc/testsuite/g++.dg/ext/varargs1.C [new file with mode: 0644]
gcc/testsuite/g++.dg/overload/ellipsis1.C
gcc/testsuite/g++.dg/overload/ellipsis2.C
gcc/testsuite/g++.dg/warn/var-args1.C
gcc/testsuite/g++.old-deja/g++.brendan/crash63.C
gcc/testsuite/g++.old-deja/g++.other/vaarg3.C
gcc/testsuite/g++.old-deja/g++.pt/vaarg3.C

index 0889ea6..d4163b0 100644 (file)
@@ -1,3 +1,8 @@
+2014-08-13  Jason Merrill  <jason@redhat.com>
+
+       * call.c (build_x_va_arg): Support passing non-POD through ....
+       (convert_arg_to_ellipsis): Likewise.
+
 2014-08-13  Andrew Sutton  <andrew.n.sutton@gmail.com>
 
        * pt.c (lookup_template_variable): Make dependent variable templates 
index 64cab45..43bfe50 100644 (file)
@@ -6570,8 +6570,8 @@ convert_arg_to_ellipsis (tree arg, tsubst_flags_t complain)
         with no corresponding parameter is conditionally-supported, with
         implementation-defined semantics.
 
-        We used to just warn here and do a bitwise copy, but now
-        cp_expr_size will abort if we try to do that.
+        We support it as pass-by-invisible-reference, just like a normal
+        value parameter.
 
         If the call appears in the context of a sizeof expression,
         it is not potentially-evaluated.  */
@@ -6579,10 +6579,12 @@ convert_arg_to_ellipsis (tree arg, tsubst_flags_t complain)
          && (type_has_nontrivial_copy_init (arg_type)
              || TYPE_HAS_NONTRIVIAL_DESTRUCTOR (arg_type)))
        {
-         if (complain & tf_error)
-           error_at (loc, "cannot pass objects of non-trivially-copyable "
-                     "type %q#T through %<...%>", arg_type);
-         return error_mark_node;
+         if (complain & tf_warning)
+           warning (OPT_Wconditionally_supported,
+                    "passing objects of non-trivially-copyable "
+                    "type %q#T through %<...%> is conditionally supported",
+                    arg_type);
+         return cp_build_addr_expr (arg, complain);
        }
     }
 
@@ -6595,7 +6597,11 @@ tree
 build_x_va_arg (source_location loc, tree expr, tree type)
 {
   if (processing_template_decl)
-    return build_min (VA_ARG_EXPR, type, expr);
+    {
+      tree r = build_min (VA_ARG_EXPR, type, expr);
+      SET_EXPR_LOCATION (r, loc);
+      return r;
+    }
 
   type = complete_type_or_else (type, NULL_TREE);
 
@@ -6604,18 +6610,24 @@ build_x_va_arg (source_location loc, tree expr, tree type)
 
   expr = mark_lvalue_use (expr);
 
+  if (TREE_CODE (type) == REFERENCE_TYPE)
+    {
+      error ("cannot receive reference type %qT through %<...%>", type);
+      return error_mark_node;
+    }
+
   if (type_has_nontrivial_copy_init (type)
-      || TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type)
-      || TREE_CODE (type) == REFERENCE_TYPE)
-    {
-      /* Remove reference types so we don't ICE later on.  */
-      tree type1 = non_reference (type);
-      /* conditionally-supported behavior [expr.call] 5.2.2/7.  */
-      error ("cannot receive objects of non-trivially-copyable type %q#T "
-            "through %<...%>; ", type);
-      expr = convert (build_pointer_type (type1), null_node);
-      expr = cp_build_indirect_ref (expr, RO_NULL, tf_warning_or_error);
-      return expr;
+      || TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type))
+    {
+      /* conditionally-supported behavior [expr.call] 5.2.2/7.  Let's treat
+        it as pass by invisible reference.  */
+      warning_at (loc, OPT_Wconditionally_supported,
+                "receiving objects of non-trivially-copyable type %q#T "
+                "through %<...%> is conditionally-supported", type);
+
+      tree ref = cp_build_reference_type (type, false);
+      expr = build_va_arg (loc, expr, ref);
+      return convert_from_reference (expr);
     }
 
   return build_va_arg (loc, expr, type);
index 50efcc3..5802311 100644 (file)
@@ -42,7 +42,9 @@ all conditionally-supported constructs that it does not support (C++0x
 @cite{Whether an argument of class type with a non-trivial copy
 constructor or destructor can be passed to ... (C++0x 5.2.2).}
 
-Such argument passing is not supported.
+Such argument passing is supported, using the same
+pass-by-invisible-reference approach used for normal function
+arguments of such types.
 
 @end itemize
 
diff --git a/gcc/testsuite/g++.dg/ext/varargs1.C b/gcc/testsuite/g++.dg/ext/varargs1.C
new file mode 100644 (file)
index 0000000..b67d788
--- /dev/null
@@ -0,0 +1,34 @@
+// Test that passing an object with non-trivial copy constructor and
+// destructor is (conditionally) supported and has sensible semantics.
+
+#include <stdarg.h>
+extern "C" void abort();
+
+void *as[5];
+int i;
+
+struct A {
+  A() { as[i++] = this; }
+  A(const A& a) {
+    if (&a != as[i-1])
+      abort();
+    as[i++] = this;
+  }
+  ~A() {
+    if (this != as[--i])
+      abort();
+  }
+};
+
+void f(int i, ...) {
+  va_list ap;
+  va_start (ap, i);
+  A ar = va_arg (ap, A);
+}
+
+int main()
+{
+  f(42,A());
+  if (i != 0)
+    abort();
+}
index 3dedaa6..1dde2bc 100644 (file)
@@ -1,5 +1,6 @@
 // PR c++/15142
 // Bug: We were aborting after giving a warning about passing a non-POD.
+// { dg-options "-Wconditionally-supported" }
 
 struct B { 
     B() throw() { } 
@@ -14,5 +15,5 @@ struct X {
 struct S { S(...); }; 
  
 void SillyFunc() { 
-  throw S(X());                // { dg-error "copy" }
+  throw S(X());                // { dg-message "copy" }
 } 
index d9118ba..c226e1c 100644 (file)
@@ -1,4 +1,5 @@
 // PR c++/60253
+// { dg-options "-Wconditionally-supported" }
 
 struct A
 {
@@ -10,4 +11,4 @@ struct B
   B(...);
 };
 
-B b(0, A());  // { dg-error "cannot pass" }
+B b(0, A());  // { dg-message "pass" }
index 9bd84a7..35deb09 100644 (file)
@@ -6,6 +6,6 @@ void foo(int, ...)
 {
     va_list va;
     int i;
-    i = va_arg(va, int&); /* { dg-error "cannot receive objects" } */
+    i = va_arg(va, int&); /* { dg-error "cannot receive" } */
 }
 
index 89685fc..badd926 100644 (file)
@@ -13,4 +13,4 @@ class UnitList
    UnitList (...);
    };
 
-UnitList unit_list (String("keV")); // { dg-error "" } cannot pass non-pod
+UnitList unit_list (String("keV"));
index 134a89c..98f7877 100644 (file)
@@ -1,5 +1,6 @@
 // { dg-do assemble  }
-// { dg-options "-Wno-abi" { target arm_eabi } }
+// { dg-options "-Wconditionally-supported" }
+// { dg-options "-Wno-abi -Wconditionally-supported" { target arm_eabi } }
 
 // Copyright (C) 1999 Free Software Foundation, Inc.
 // Contributed by Nathan Sidwell 4 Oct 1999 <nathan@acm.org>
@@ -14,19 +15,19 @@ struct Z;   // { dg-message "forward decl" }
 void fn1(va_list args)
 {
   int i = va_arg (args, int);
-  Y x = va_arg (args, Y);         // { dg-error "cannot receive" }
-  Y y = va_arg (args, struct Y);  // { dg-error "cannot receive" }
+  Y x = va_arg (args, Y);         // { dg-message "receiv" }
+  Y y = va_arg (args, struct Y);  // { dg-message "receiv" }
   int &r = va_arg (args, int &);  // { dg-error "cannot receive" }
   
   Z z1 = va_arg (args, Z);        // { dg-error "incomplete" } 
   const Z &z2 = va_arg (args, Z);       // { dg-error "incomplete" } 
 
   va_arg (args, char);    // { dg-warning "promote" } 
-  // { dg-message "should pass" "pass" { target *-*-* } 24 }
-  // { dg-message "abort" "abort" { target *-*-* } 24 }
+  // { dg-message "should pass" "pass" { target *-*-* } 25 }
+  // { dg-message "abort" "abort" { target *-*-* } 25 }
   va_arg (args, int []);  // { dg-error "array with unspecified bounds" } promote
   va_arg (args, int ());  // { dg-warning "promoted" } promote
-  // { dg-message "abort" "abort" { target *-*-* } 28 }
+  // { dg-message "abort" "abort" { target *-*-* } 29 }
   va_arg (args, bool);    // { dg-warning "promote" "promote" } 
-  // { dg-message "abort" "abort" { target *-*-* } 30 }
+  // { dg-message "abort" "abort" { target *-*-* } 31 }
 }
index e880119..ee84db9 100644 (file)
@@ -1,4 +1,5 @@
 // { dg-do assemble  }
+// { dg-options "-Wconditionally-supported" }
 // Copyright (C) 2000 Free Software Foundation
 // Contributed by Nathan Sidwell 22 June 2000 <nathan@codesourcery.com>
 
@@ -14,14 +15,14 @@ void PrintArgs (Type somearg, ...)
 va_list argp;
 va_start (argp, somearg);
 Type value;
-value = va_arg (argp, Type); // { dg-error "cannot receive" } cannot pass non-POD
+value = va_arg (argp, Type); // { dg-message "receiv" } cannot pass non-POD
 va_end (argp);
 }
 
 int main (void)
 {
 A dummy;
-PrintArgs (dummy, dummy); // { dg-error "cannot pass" } cannot pass non-POD
-// { dg-message "required" "inst" { target *-*-* } 24 }
+PrintArgs (dummy, dummy); // { dg-message "pass" } cannot pass non-POD
+// { dg-message "required" "inst" { target *-*-* } 25 }
 return 0;
 }