Commit d2f2e467 by Jason Merrill Committed by Jason Merrill

call.c (build_x_va_arg): Support passing non-POD through ....

	* call.c (build_x_va_arg): Support passing non-POD through ....
	(convert_arg_to_ellipsis): Likewise.

From-SVN: r213921
parent f9089781
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
......
......@@ -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);
......
......@@ -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
......
// 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();
}
// 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" }
}
// 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" }
......@@ -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" } */
}
......@@ -13,4 +13,4 @@ class UnitList
UnitList (...);
};
UnitList unit_list (String("keV")); // { dg-error "" } cannot pass non-pod
UnitList unit_list (String("keV"));
// { 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 }
}
// { 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;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment