From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-il1-x133.google.com (mail-il1-x133.google.com [IPv6:2607:f8b0:4864:20::133]) by sourceware.org (Postfix) with ESMTPS id 3CF5D3858D3C for ; Wed, 30 Mar 2022 13:06:22 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 3CF5D3858D3C Received: by mail-il1-x133.google.com with SMTP id z10so1444653iln.0 for ; Wed, 30 Mar 2022 06:06:22 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:mime-version:from:date:message-id:subject:to; bh=hORtl6CesvMcHjntfOcsKCtr6aFWmk1Z7EBMzFacIYQ=; b=8KL26+6NyW7r/nmamlpjlLLfRZEIjmJ0DQkbsZT5OcXLDJ2r0WjV8m1dz+H9UmlJ47 B1q6kh3WEa7FlNitfdlSas121AqX6sefvmUcdQxl6IU1/MoSG77NTnSMOwDZ5LVakgkm MugBNk6n4d53hpdz6pk+w6zozpIbv0/MmLC+Ktt1SAe/drvpLbZXkqDqhyNrXcJlCYMh IKkIU2YniikT3PkubpauY3ikgytNbCObKZC6xoKS3k1qU23TnDW5tw2MNBBnTtTKhwoO cDgQPJ5DmMJk0YTlwm+vxXFvaA2pSoY5HCP+FSjeAOshBSij8MbvPiOEaqFRAuwLsq8D a9lA== X-Gm-Message-State: AOAM533wgmV+99J7NS4MHG2tWmKGa0AiUYMO3AwnAchhBs0dEmLHwDjx q49xP4CiseNfcsJMWezWjjmSAzkQyOzpHlrI3mzERB8cwDA= X-Google-Smtp-Source: ABdhPJx2TWzQRK0oRKxpHN/tRdkThq4TpBmyuqij0KMTzwe+LgwL9pMek0eWbnCnKQptC8TA+Q4hgO1PSMSIYg76hGs= X-Received: by 2002:a05:6e02:1caa:b0:2c9:8eaa:72e0 with SMTP id x10-20020a056e021caa00b002c98eaa72e0mr11121657ill.146.1648645581353; Wed, 30 Mar 2022 06:06:21 -0700 (PDT) MIME-Version: 1.0 From: Benno Evers Date: Wed, 30 Mar 2022 15:06:10 +0200 Message-ID: Subject: [PATCH] c++: Fix ICE due to shared BLOCK node in coroutine generation [PR103328] To: gcc-patches@gcc.gnu.org Content-Type: text/plain; charset="UTF-8" X-Spam-Status: No, score=-10.5 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-List-Received-Date: Wed, 30 Mar 2022 13:06:24 -0000 From: Benno Evers When finishing a function that is a coroutine, the function is transformed into a "ramp" function, and the original user-provided function body gets moved into a newly created "actor" function. In this case `current_function_decl` points to the ramp function, but `current_binding_level->blocks` would still point to the scope block of the user-provided function body in the actor function, so when the ramp function was finished during `poplevel()` in decl.cc, we could end up with that block being reused as the `DECL_INITIAL()` of the ramp function: subblocks = functionbody >= 0 ? current_binding_level->blocks : 0; // [...] DECL_INITIAL (current_function_decl) = block ? block : subblocks; This block would then be independently modified by subsequent passes touching either the ramp or the actor function, potentially causing an ICE depending on the order and function of these passes. gcc/cp/ChangeLog: PR c++/103328 * coroutines.cc (morph_fn_to_coro): Reset current_binding_level->blocks. gcc/testsuite/ChangeLog: PR c++/103328 * g++.dg/coroutines/pr103328.C: New test. Co-Authored-By: Iain Sandoe --- gcc/cp/coroutines.cc | 3 ++ gcc/testsuite/g++.dg/coroutines/pr103328.C | 32 ++++++++++++++++++++++ 2 files changed, 35 insertions(+) create mode 100644 gcc/testsuite/g++.dg/coroutines/pr103328.C diff --git a/gcc/cp/coroutines.cc b/gcc/cp/coroutines.cc index 23dc28271a4..ece30c905e8 100644 --- a/gcc/cp/coroutines.cc +++ b/gcc/cp/coroutines.cc @@ -4541,6 +4541,9 @@ morph_fn_to_coro (tree orig, tree *resumer, tree *destroyer) BLOCK_VARS (top_block) = BIND_EXPR_VARS (ramp_bind); BLOCK_SUBBLOCKS (top_block) = NULL_TREE; + /* Reset the current binding level to the ramp function */ + current_binding_level->blocks = top_block; + /* The decl_expr for the coro frame pointer, initialize to zero so that we can pass it to the IFN_CO_FRAME (since there's no way to pass a type, directly apparently). This avoids a "used uninitialized" warning. */ diff --git a/gcc/testsuite/g++.dg/coroutines/pr103328.C b/gcc/testsuite/g++.dg/coroutines/pr103328.C new file mode 100644 index 00000000000..56fb54ab316 --- /dev/null +++ b/gcc/testsuite/g++.dg/coroutines/pr103328.C @@ -0,0 +1,32 @@ +// { dg-additional-options "-g" } + +#include + +struct task { + struct promise_type { + task get_return_object() { return {}; } + std::suspend_never initial_suspend() { return {}; } + std::suspend_never final_suspend() noexcept { return {}; } + void unhandled_exception() {} + }; + bool await_ready() { return false; } + void await_suspend(std::coroutine_handle<> h) {} + void await_resume() {} +}; + +template +void call(Func func) { func(); } + +class foo { + void f(); + task g(); +}; + +void foo::f() { + auto lambda = [this]() noexcept -> task { + co_await g(); + }; + (void)call; +} + +int main() {} -- 2.32.0