From: Jason Merrill <jason@redhat.com>
To: Iain Sandoe <iain@sandoe.co.uk>
Cc: GCC Patches <gcc-patches@gcc.gnu.org>
Subject: Re: [PATCH] c++, coroutines: Make sure our temporaries are in a bind expr [PR105287]
Date: Thu, 28 Apr 2022 07:44:04 -0400 [thread overview]
Message-ID: <b04563c6-4018-0abf-bca9-36a7ca9ff9aa@redhat.com> (raw)
In-Reply-To: <53609151-4693-4B73-91D5-28F8B4438714@sandoe.co.uk>
On 4/28/22 04:28, Iain Sandoe wrote:
> Hi Jason,
>
>> On 20 Apr 2022, at 03:14, Jason Merrill <jason@redhat.com> wrote:
>>
>> On 4/18/22 10:02, Iain Sandoe wrote:
>>> There are a few cases where we can generate a temporary that does not need
>>> to be added to the coroutine frame (i.e. these are genuinely ephemeral). The
>>> intent was that unnamed temporaries should not be 'promoted' to coroutine
>>> frame entries. However there was a thinko and these were not actually ever
>>> added to the bind expressions being generated for the expanded awaits. This
>>> meant that they were showing in the global namspace, leading to an empty
>>> DECL_CONTEXT and the ICE reported.
>>> tested on x86_64-darwin, OK for mainline? / Backports? (when?)
>>> thanks,
>>> Iain
>>> Signed-off-by: Iain Sandoe <iain@sandoe.co.uk>
>>> PR c++/105287
>>> gcc/cp/ChangeLog:
>>> * coroutines.cc (maybe_promote_temps): Ensure generated temporaries
>>> are added to the bind expr.
>>> (add_var_to_bind): Fix local var naming to use portable punctuation.
>>> (register_local_var_uses): Do not add synthetic names to unnamed
>>> temporaries.
>>> gcc/testsuite/ChangeLog:
>>> * g++.dg/coroutines/pr105287.C: New test.
>>> ---
>>> gcc/cp/coroutines.cc | 17 ++++----
>>> gcc/testsuite/g++.dg/coroutines/pr105287.C | 48 ++++++++++++++++++++++
>>> 2 files changed, 56 insertions(+), 9 deletions(-)
>>> create mode 100644 gcc/testsuite/g++.dg/coroutines/pr105287.C
>>> diff --git a/gcc/cp/coroutines.cc b/gcc/cp/coroutines.cc
>>> index a9ce6e050dd..dcc2284171b 100644
>>> --- a/gcc/cp/coroutines.cc
>>> +++ b/gcc/cp/coroutines.cc
>>> @@ -3103,7 +3103,7 @@ maybe_promote_temps (tree *stmt, void *d)
>>> If the initializer is a conditional expression, we need to collect
>>> and declare any promoted variables nested within it. DTORs for such
>>> variables must be run conditionally too. */
>>> - if (t->var && DECL_NAME (t->var))
>>> + if (t->var)
>>> {
>>> tree var = t->var;
>>> DECL_CHAIN (var) = vlist;
>>> @@ -3304,7 +3304,7 @@ add_var_to_bind (tree& bind, tree var_type,
>>> tree b_vars = BIND_EXPR_VARS (bind);
>>> /* Build a variable to hold the condition, this will be included in the
>>> frame as a local var. */
>>> - char *nam = xasprintf ("%s.%d", nam_root, nam_vers);
>>> + char *nam = xasprintf ("`__%s_%d", nam_root, nam_vers);
>>
>> ` is portable?
>
> nope, it’s a typo - apparently accepted by GAS and Darwin’s assembler tho…
> thanks for catching that.
>
>>> tree newvar = build_lang_decl (VAR_DECL, get_identifier (nam), var_type);
>>> free (nam);
>>> DECL_CHAIN (newvar) = b_vars;
>>> @@ -3949,7 +3949,7 @@ register_local_var_uses (tree *stmt, int *do_subtree, void *d)
>>> scopes with identically named locals and still be able to
>>> identify them in the coroutine frame. */
>>> tree lvname = DECL_NAME (lvar);
>>> - char *buf;
>>> + char *buf = NULL;
>>> /* The outermost bind scope contains the artificial variables that
>>> we inject to implement the coro state machine. We want to be able
>>> @@ -3959,14 +3959,13 @@ register_local_var_uses (tree *stmt, int *do_subtree, void *d)
>>> else if (lvname != NULL_TREE)
>>> buf = xasprintf ("%s_%u_%u", IDENTIFIER_POINTER (lvname),
>>> lvd->nest_depth, lvd->bind_indx);
>>> - else
>>> - buf = xasprintf ("_D%u_%u_%u", DECL_UID (lvar), lvd->nest_depth,
>>> - lvd->bind_indx);
>>> /* TODO: Figure out if we should build a local type that has any
>>> excess alignment or size from the original decl. */
>>> - local_var.field_id
>>> - = coro_make_frame_entry (lvd->field_list, buf, lvtype, lvd->loc);
>>> - free (buf);
>>> + if (buf) {
>>
>> Brace should be on the next line.
>
> that was careless, too much rushing, fixed as below,
> OK now?
OK.
> -----
>
> [PATCH] c++, coroutines: Make sure our temporaries are in a bind expr
> [PR105287]
>
> There are a few cases where we can generate a temporary that does not need
> to be added to the coroutine frame (i.e. these are genuinely ephemeral). The
> intent was that unnamed temporaries should not be 'promoted' to coroutine
> frame entries. However there was a thinko and these were not actually ever
> added to the bind expressions being generated for the expanded awaits. This
> meant that they were showing in the global namspace, leading to an empty
> DECL_CONTEXT and the ICE reported.
>
> Signed-off-by: Iain Sandoe <iain@sandoe.co.uk>
>
> PR c++/105287
>
> gcc/cp/ChangeLog:
>
> * coroutines.cc (maybe_promote_temps): Ensure generated temporaries
> are added to the bind expr.
> (add_var_to_bind): Fix local var naming to use portable punctuation.
> (register_local_var_uses): Do not add synthetic names to unnamed
> temporaries.
>
> gcc/testsuite/ChangeLog:
>
> * g++.dg/coroutines/pr105287.C: New test.
> ---
> gcc/cp/coroutines.cc | 18 ++++----
> gcc/testsuite/g++.dg/coroutines/pr105287.C | 48 ++++++++++++++++++++++
> 2 files changed, 57 insertions(+), 9 deletions(-)
> create mode 100644 gcc/testsuite/g++.dg/coroutines/pr105287.C
>
> diff --git a/gcc/cp/coroutines.cc b/gcc/cp/coroutines.cc
> index a9ce6e050dd..7e9ff69ae35 100644
> --- a/gcc/cp/coroutines.cc
> +++ b/gcc/cp/coroutines.cc
> @@ -3103,7 +3103,7 @@ maybe_promote_temps (tree *stmt, void *d)
> If the initializer is a conditional expression, we need to collect
> and declare any promoted variables nested within it. DTORs for such
> variables must be run conditionally too. */
> - if (t->var && DECL_NAME (t->var))
> + if (t->var)
> {
> tree var = t->var;
> DECL_CHAIN (var) = vlist;
> @@ -3304,7 +3304,7 @@ add_var_to_bind (tree& bind, tree var_type,
> tree b_vars = BIND_EXPR_VARS (bind);
> /* Build a variable to hold the condition, this will be included in the
> frame as a local var. */
> - char *nam = xasprintf ("%s.%d", nam_root, nam_vers);
> + char *nam = xasprintf ("__%s_%d", nam_root, nam_vers);
> tree newvar = build_lang_decl (VAR_DECL, get_identifier (nam), var_type);
> free (nam);
> DECL_CHAIN (newvar) = b_vars;
> @@ -3949,7 +3949,7 @@ register_local_var_uses (tree *stmt, int *do_subtree, void *d)
> scopes with identically named locals and still be able to
> identify them in the coroutine frame. */
> tree lvname = DECL_NAME (lvar);
> - char *buf;
> + char *buf = NULL;
>
> /* The outermost bind scope contains the artificial variables that
> we inject to implement the coro state machine. We want to be able
> @@ -3959,14 +3959,14 @@ register_local_var_uses (tree *stmt, int *do_subtree, void *d)
> else if (lvname != NULL_TREE)
> buf = xasprintf ("%s_%u_%u", IDENTIFIER_POINTER (lvname),
> lvd->nest_depth, lvd->bind_indx);
> - else
> - buf = xasprintf ("_D%u_%u_%u", DECL_UID (lvar), lvd->nest_depth,
> - lvd->bind_indx);
> /* TODO: Figure out if we should build a local type that has any
> excess alignment or size from the original decl. */
> - local_var.field_id
> - = coro_make_frame_entry (lvd->field_list, buf, lvtype, lvd->loc);
> - free (buf);
> + if (buf)
> + {
> + local_var.field_id = coro_make_frame_entry (lvd->field_list, buf,
> + lvtype, lvd->loc);
> + free (buf);
> + }
> /* We don't walk any of the local var sub-trees, they won't contain
> any bind exprs. */
> }
> diff --git a/gcc/testsuite/g++.dg/coroutines/pr105287.C b/gcc/testsuite/g++.dg/coroutines/pr105287.C
> new file mode 100644
> index 00000000000..9790945287d
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/coroutines/pr105287.C
> @@ -0,0 +1,48 @@
> +// { dg-additional-options "-fanalyzer" }
> +// { dg-excess-errors "lots of analyzer output, but no ICE" }
> +namespace std {
> +template <typename _Result> struct coroutine_traits : _Result {};
> +template <typename = void> struct coroutine_handle {
> + operator coroutine_handle<>();
> +};
> +}
> +struct coro1 {
> + using handle_type = std::coroutine_handle<>;
> + coro1(handle_type);
> + struct suspend_always_prt {
> + bool await_ready() noexcept;
> + void await_suspend(handle_type) noexcept;
> + void await_resume() noexcept;
> + };
> + struct promise_type {
> + std::coroutine_handle<> ch_;
> + auto get_return_object() { return ch_; }
> + auto initial_suspend() { return suspend_always_prt{}; }
> + auto final_suspend() noexcept { return suspend_always_prt{}; }
> + void unhandled_exception();
> + };
> +};
> +struct BoolAwaiter {
> + BoolAwaiter(bool);
> + bool await_ready();
> + void await_suspend(std::coroutine_handle<>);
> + bool await_resume();
> +};
> +struct IntAwaiter {
> + IntAwaiter(int);
> + bool await_ready();
> + void await_suspend(std::coroutine_handle<>);
> + int await_resume();
> +};
> +coro1 my_coro() {
> + int a = 1;
> + if (a == 0) {
> + int b = 5;
> +
> + }
> + {
> + int c = 10;
> + }
> + co_await BoolAwaiter(true) && co_await IntAwaiter(a);
> +
> + }
prev parent reply other threads:[~2022-04-28 11:44 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-04-18 14:02 Iain Sandoe
2022-04-20 2:14 ` Jason Merrill
2022-04-28 8:28 ` Iain Sandoe
2022-04-28 11:44 ` Jason Merrill [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=b04563c6-4018-0abf-bca9-36a7ca9ff9aa@redhat.com \
--to=jason@redhat.com \
--cc=gcc-patches@gcc.gnu.org \
--cc=iain@sandoe.co.uk \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).