aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp
diff options
context:
space:
mode:
authorIain Sandoe <iain@sandoe.co.uk>2021-02-15 16:13:36 +0000
committerIain Sandoe <iain@sandoe.co.uk>2021-02-25 19:24:52 +0000
commitb8ff3f8efeda02a6bedebfaf20b93645ae3bb5b8 (patch)
tree87d97f7bc9458a6334c8431af597e447d591de48 /gcc/cp
parent7005a50d0121954031a223ea5a6c57aaa7e3efd3 (diff)
downloadgcc-b8ff3f8efeda02a6bedebfaf20b93645ae3bb5b8.zip
gcc-b8ff3f8efeda02a6bedebfaf20b93645ae3bb5b8.tar.gz
gcc-b8ff3f8efeda02a6bedebfaf20b93645ae3bb5b8.tar.bz2
coroutines : Call promise CTOR with parm copies [PR97587].
As the PR notes, we were calling the promise CTOR with the original function parameters, not the copy (as pointed, a previous wording of the section was unambiguous). Fixed thus. gcc/cp/ChangeLog: PR c++/97587 * coroutines.cc (struct param_info): Track rvalue refs. (morph_fn_to_coro): Track rvalue refs, and call the promise CTOR with the frame copy of passed parms. gcc/testsuite/ChangeLog: PR c++/97587 * g++.dg/coroutines/coro1-refs-and-ctors.h: Add a CTOR with two reference parms, to distinguish the rvalue ref. variant. * g++.dg/coroutines/pr97587.C: New test.
Diffstat (limited to 'gcc/cp')
-rw-r--r--gcc/cp/coroutines.cc25
1 files changed, 17 insertions, 8 deletions
diff --git a/gcc/cp/coroutines.cc b/gcc/cp/coroutines.cc
index 19d2ca3..0b63914 100644
--- a/gcc/cp/coroutines.cc
+++ b/gcc/cp/coroutines.cc
@@ -1817,6 +1817,7 @@ struct param_info
tree orig_type; /* The original type of the parm (not as passed). */
bool by_ref; /* Was passed by reference. */
bool pt_ref; /* Was a pointer to object. */
+ bool rv_ref; /* Was an rvalue ref. */
bool trivial_dtor; /* The frame type has a trivial DTOR. */
bool this_ptr; /* Is 'this' */
bool lambda_cobj; /* Lambda capture object */
@@ -4121,7 +4122,7 @@ morph_fn_to_coro (tree orig, tree *resumer, tree *destroyer)
if (actual_type == NULL_TREE)
actual_type = error_mark_node;
parm.orig_type = actual_type;
- parm.by_ref = parm.pt_ref = false;
+ parm.by_ref = parm.pt_ref = parm.rv_ref = false;
if (TREE_CODE (actual_type) == REFERENCE_TYPE)
{
/* If the user passes by reference, then we will save the
@@ -4129,8 +4130,10 @@ morph_fn_to_coro (tree orig, tree *resumer, tree *destroyer)
[dcl.fct.def.coroutine] / 13, if the lifetime of the
referenced item ends and then the coroutine is resumed,
we have UB; well, the user asked for it. */
- actual_type = build_pointer_type (TREE_TYPE (actual_type));
- parm.pt_ref = true;
+ if (TYPE_REF_IS_RVALUE (actual_type))
+ parm.rv_ref = true;
+ else
+ parm.pt_ref = true;
}
else if (TYPE_REF_P (DECL_ARG_TYPE (arg)))
parm.by_ref = true;
@@ -4498,16 +4501,22 @@ morph_fn_to_coro (tree orig, tree *resumer, tree *destroyer)
tree this_ref = build1 (INDIRECT_REF, ct, arg);
tree rt = cp_build_reference_type (ct, false);
this_ref = convert_to_reference (rt, this_ref, CONV_STATIC,
- LOOKUP_NORMAL , NULL_TREE,
+ LOOKUP_NORMAL, NULL_TREE,
tf_warning_or_error);
vec_safe_push (promise_args, this_ref);
}
- else if (parm.by_ref)
- vec_safe_push (promise_args, fld_idx);
+ else if (parm.rv_ref)
+ vec_safe_push (promise_args, rvalue(fld_idx));
else
- vec_safe_push (promise_args, arg);
+ vec_safe_push (promise_args, fld_idx);
- if (TYPE_NEEDS_CONSTRUCTING (parm.frame_type))
+ if (parm.rv_ref || parm.pt_ref)
+ /* Initialise the frame reference field directly. */
+ r = build_modify_expr (fn_start, TREE_OPERAND (fld_idx, 0),
+ parm.frame_type, INIT_EXPR,
+ DECL_SOURCE_LOCATION (arg), arg,
+ DECL_ARG_TYPE (arg));
+ else if (TYPE_NEEDS_CONSTRUCTING (parm.frame_type))
{
vec<tree, va_gc> *p_in;
if (CLASS_TYPE_P (parm.frame_type)