summaryrefslogtreecommitdiff
path: root/gcc/cp/call.c
diff options
context:
space:
mode:
authorjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>2014-08-13 18:25:06 +0000
committerjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>2014-08-13 18:25:06 +0000
commit7dab9307f1670e455f9c3f06034c857710c93d5d (patch)
tree5e22cf22a1c702b54fc7df06c5a5de3bb7039526 /gcc/cp/call.c
parentf50214f368949c9b317998ad1af88ad8fb50f9c1 (diff)
downloadgcc-7dab9307f1670e455f9c3f06034c857710c93d5d.tar.gz
* call.c (build_x_va_arg): Support passing non-POD through ....
(convert_arg_to_ellipsis): Likewise. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@213921 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/cp/call.c')
-rw-r--r--gcc/cp/call.c48
1 files changed, 30 insertions, 18 deletions
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 64cab453ae0..43bfe504d21 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -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);