coroutines: Only set parm copy guard vars if we have exceptions [PR 102454].
For coroutines, we make copies of the original function arguments into the coroutine frame. Normally, these are destroyed on the proper exit from the coroutine when the frame is destroyed. However, if an exception is thrown before the first suspend point is reached, the cleanup has to happen in the ramp function. These cleanups are guarded such that they are only applied to any param copies actually made. The ICE is caused by an attempt to set the guard variable when there are no exceptions enabled (the guard var is not created in this case). Fixed by checking for flag_exceptions in this case too. While touching this code paths, also clean up the synthetic names used when a function parm is unnamed. Signed-off-by: Iain Sandoe <iain@sandoe.co.uk> PR c++/102454 gcc/cp/ChangeLog: * coroutines.cc (analyze_fn_parms): Clean up synthetic names for unnamed function params. (morph_fn_to_coro): Do not try to set a guard variable for param DTORs in the ramp, unless we have exceptions active. gcc/testsuite/ChangeLog: * g++.dg/coroutines/pr102454.C: New test.
This commit is contained in:
parent
a11052d98d
commit
fae627162d
2 changed files with 52 additions and 11 deletions
|
@ -3829,13 +3829,13 @@ analyze_fn_parms (tree orig)
|
|||
|
||||
if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (parm.frame_type))
|
||||
{
|
||||
char *buf = xasprintf ("_Coro_%s_live", IDENTIFIER_POINTER (name));
|
||||
parm.guard_var = build_lang_decl (VAR_DECL, get_identifier (buf),
|
||||
boolean_type_node);
|
||||
char *buf = xasprintf ("%s%s_live", DECL_NAME (arg) ? "_Coro_" : "",
|
||||
IDENTIFIER_POINTER (name));
|
||||
parm.guard_var
|
||||
= coro_build_artificial_var (UNKNOWN_LOCATION, get_identifier (buf),
|
||||
boolean_type_node, orig,
|
||||
boolean_false_node);
|
||||
free (buf);
|
||||
DECL_ARTIFICIAL (parm.guard_var) = true;
|
||||
DECL_CONTEXT (parm.guard_var) = orig;
|
||||
DECL_INITIAL (parm.guard_var) = boolean_false_node;
|
||||
parm.trivial_dtor = false;
|
||||
}
|
||||
else
|
||||
|
@ -4843,11 +4843,14 @@ morph_fn_to_coro (tree orig, tree *resumer, tree *destroyer)
|
|||
NULL, parm.frame_type,
|
||||
LOOKUP_NORMAL,
|
||||
tf_warning_or_error);
|
||||
/* This var is now live. */
|
||||
r = build_modify_expr (fn_start, parm.guard_var,
|
||||
boolean_type_node, INIT_EXPR, fn_start,
|
||||
boolean_true_node, boolean_type_node);
|
||||
finish_expr_stmt (r);
|
||||
if (flag_exceptions)
|
||||
{
|
||||
/* This var is now live. */
|
||||
r = build_modify_expr (fn_start, parm.guard_var,
|
||||
boolean_type_node, INIT_EXPR, fn_start,
|
||||
boolean_true_node, boolean_type_node);
|
||||
finish_expr_stmt (r);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
38
gcc/testsuite/g++.dg/coroutines/pr102454.C
Normal file
38
gcc/testsuite/g++.dg/coroutines/pr102454.C
Normal file
|
@ -0,0 +1,38 @@
|
|||
// { dg-additional-options "-fno-exceptions" }
|
||||
|
||||
#include <coroutine>
|
||||
#include <string>
|
||||
|
||||
template <typename T>
|
||||
struct looper {
|
||||
struct promise_type {
|
||||
auto get_return_object () { return handle_type::from_promise (*this); }
|
||||
auto initial_suspend () { return suspend_always_prt {}; }
|
||||
auto final_suspend () noexcept { return suspend_always_prt {}; }
|
||||
void return_value (T);
|
||||
void unhandled_exception ();
|
||||
};
|
||||
|
||||
using handle_type = std::coroutine_handle<promise_type>;
|
||||
|
||||
looper (handle_type);
|
||||
|
||||
struct suspend_always_prt {
|
||||
bool await_ready () noexcept;
|
||||
void await_suspend (handle_type) noexcept;
|
||||
void await_resume () noexcept;
|
||||
};
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
looper<T>
|
||||
with_ctorable_state (T)
|
||||
{
|
||||
co_return T ();
|
||||
}
|
||||
|
||||
auto
|
||||
foo ()
|
||||
{
|
||||
return with_ctorable_state<std::string>;
|
||||
}
|
Loading…
Add table
Reference in a new issue