From patchwork Mon Apr 18 14:02:03 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Iain Sandoe X-Patchwork-Id: 53011 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id B91E23858C50 for ; Mon, 18 Apr 2022 14:02:51 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org B91E23858C50 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1650290571; bh=8XrOjbz9k9LkgK5UCQIH17LV8qJ0ilTEa9DPGOrqBP4=; h=To:Subject:Date:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:List-Subscribe:From:Reply-To:Cc:From; b=nlaBsrEpAJ0+X+UvBle5SVUDHj+lELbcYrjxpEGcpjwAf/RWzF1TyCdjdy3WC30tK 31pT1YGXVRF384G8GBe6flpRldH41ik2YnSQ9mL/kYMOeJJXNx8/LikNCOqigGEqMn 9kMoUyWu+qwkkcUexAJFIEW50KopxWTbhWaFDF1w= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mail-wr1-x42d.google.com (mail-wr1-x42d.google.com [IPv6:2a00:1450:4864:20::42d]) by sourceware.org (Postfix) with ESMTPS id 59F803858413 for ; Mon, 18 Apr 2022 14:02:12 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 59F803858413 Received: by mail-wr1-x42d.google.com with SMTP id p18so17846130wru.5 for ; Mon, 18 Apr 2022 07:02:12 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :mime-version:content-transfer-encoding; bh=8XrOjbz9k9LkgK5UCQIH17LV8qJ0ilTEa9DPGOrqBP4=; b=ygG+aT314OmSz8ow9/3mnf5SAO/kfVSIVCi5HzjEjas2SjE0TdieDxzPmUhTwA0lTY k8/zvLCqKYWfxWOJv3m8E1tIsTKyWMH7q4xJmUsHyMZo+qZa7blfehxFDvUx+YErgwwO VvV8XZowYelBKwh1E9FdDIMFmkk3Qqhx8aiXrz8Nt/bJuJHPPu6CP6nnRZkMvSnlN/Nl TacTh+wPE0m0D4UouheQlwoEHYPMm7XkPdZl2M80PJL35A4LPld52POwejW3emv01pgJ eucwloP1jGClEEGX9xpnV4CzT7oGXUkDWRKkJpOf1mAX0vsVzOq3IdnJwl99eL5NGSQn +Qsg== X-Gm-Message-State: AOAM532BoW7hSqyx5bOixjTy6oOV2EHWBE/GYNSlZZ8iZcKaYucJ7DLw 43LNjaV6rO+o48zD6h0balj10rtxR9E= X-Google-Smtp-Source: ABdhPJwVB8FjZPbJoxvP16/c7s79xnbHdq/wlQeDSHsmSU6TcVbz+/UVUkHdvJgo6q0wAGHDEB8mSw== X-Received: by 2002:a05:6000:1687:b0:20a:7c1a:afd1 with SMTP id y7-20020a056000168700b0020a7c1aafd1mr8544914wrd.326.1650290530777; Mon, 18 Apr 2022 07:02:10 -0700 (PDT) Received: from localhost.localdomain (host81-138-1-83.in-addr.btopenworld.com. [81.138.1.83]) by smtp.gmail.com with ESMTPSA id s17-20020adfdb11000000b001f02d5fea43sm10604243wri.98.2022.04.18.07.02.10 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Mon, 18 Apr 2022 07:02:10 -0700 (PDT) X-Google-Original-From: Iain Sandoe To: gcc-patches@gcc.gnu.org Subject: [PATCH] c++, coroutines: Make sure our temporaries are in a bind expr [PR105287] Date: Mon, 18 Apr 2022 15:02:03 +0100 Message-Id: <20220418140203.25488-1-iain@sandoe.co.uk> X-Mailer: git-send-email 2.24.3 (Apple Git-128) MIME-Version: 1.0 X-Spam-Status: No, score=-8.3 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FREEMAIL_FROM, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Iain Sandoe via Gcc-patches From: Iain Sandoe Reply-To: iain@sandoe.co.uk Cc: Iain Sandoe Errors-To: gcc-patches-bounces+patchwork=sourceware.org@gcc.gnu.org Sender: "Gcc-patches" 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 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. Signed-off-by: Iain Sandoe --- 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); 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) { + 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 struct coroutine_traits : _Result {}; +template 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); + + }