From patchwork Wed Aug 21 19:10:01 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Iain Sandoe X-Patchwork-Id: 1975084 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20230601 header.b=AfK/cLqZ; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=8.43.85.97; helo=server2.sourceware.org; envelope-from=gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=patchwork.ozlabs.org) Received: from server2.sourceware.org (server2.sourceware.org [8.43.85.97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4Wpwtf1WLbz1yXf for ; Thu, 22 Aug 2024 05:11:54 +1000 (AEST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 6804D38708E4 for ; Wed, 21 Aug 2024 19:11:52 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mail-ej1-x62b.google.com (mail-ej1-x62b.google.com [IPv6:2a00:1450:4864:20::62b]) by sourceware.org (Postfix) with ESMTPS id DCE9C3857000 for ; Wed, 21 Aug 2024 19:10:12 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org DCE9C3857000 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=gmail.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org DCE9C3857000 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2a00:1450:4864:20::62b ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1724267414; cv=none; b=G9/bMfpkncfzhuEGBJRowpUZAcZ+zdmCs+FuVbMCJLJGFsRbZAtzy7jTKnr7bWj0v8NlcrwkRQsHWeD94Osb6SxrMgbplw3tTb8rvNZqmWxZpCIu6pKiWg/I/PjR6PtonEvVOqDQAl1m8pVT6MjtevDfu807lhW9CcT93K/SoIo= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1724267414; c=relaxed/simple; bh=YdF/eQ8zi+5Pmr+FnddgXZHN7lhxNUEkWwKEMRQpMvQ=; h=DKIM-Signature:From:To:Subject:Date:Message-Id:MIME-Version; b=vw4nTltmOwIPNHHzjkU74ISJDLbfMgxIBBl5fp+ioqu5QZVpv/GMT5pPi8VVVyJ7CDa/ZfnB1tis/0xS/olHCCxYamma4iFr7jr0bzl8/EOi+23G76xh0pDipUN9qu2NapEyI87DqzsYYmb00JTDsIM0p+IqiUoWZezJCfuxjHk= ARC-Authentication-Results: i=1; server2.sourceware.org Received: by mail-ej1-x62b.google.com with SMTP id a640c23a62f3a-a83597ce5beso1422966b.1 for ; Wed, 21 Aug 2024 12:10:12 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1724267411; x=1724872211; darn=gcc.gnu.org; h=content-transfer-encoding:mime-version:reply-to:references :in-reply-to:message-id:date:subject:cc:to:from:from:to:cc:subject :date:message-id:reply-to; bh=Zy/4CuG1c1nrRLvnkgQ7F1yRTvWwkXnB6Xc+68mOsh4=; b=AfK/cLqZA5o9n0TiL/RVAGBB2O/HIPyyXNf2jtKtaLOx+in0HncJcTMLdcfL/ivK/F WV+QThQmDp7l668biMhVaRUnLDvB0exS42hoY30gJaPjHZ0A5djivaPpcRxRHK60wyMJ kncSjd2xOMW/RDbrg04ZNOxf1C+rNPotxzVFFwQBiLtLwi5ARxvKNDWg6/Z0p8+dhDl3 0wK30uMuGwe7NtHlVDsGSrB4QiNugviHTGABlYx0j0RDPWJzTeYjCVTdj3DHxhsSRhZq 2138Wh8KVdTc+vOmx+wdnI9ZZtmJJdx0smsK8yUetD0k0Cbqsc66dUB1x2A2R9LCKD75 sfpA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1724267411; x=1724872211; h=content-transfer-encoding:mime-version:reply-to:references :in-reply-to:message-id:date:subject:cc:to:from:x-gm-message-state :from:to:cc:subject:date:message-id:reply-to; bh=Zy/4CuG1c1nrRLvnkgQ7F1yRTvWwkXnB6Xc+68mOsh4=; b=wN3PGwCcyA1DB81XOepk6kiprFyfPVVcJC1es4X3Y1m+G1vzMbD99VfGoZV3hdXDCC bGCQqjSQqJ5NHsHGHSh8QJ9sItHnbhCe9HhCVYV4HYqH57TrwKGBn9w+JEnfMtUeRsQm CT3jaeY64ziGN2pQxVEwOe6Gl3I/vpwoi9LDOFZOUneQ/fVEfv1ozeNmp+y8eYDu+5cu WK1zDbk5Xy8vu14n1b2ZeDDVAyca+qgL/Q+XSGSJlmWNUcDTtIi4xAuFJGZQTVtS3RP+ //N01ZhAstQld8mcoaGNPUbkx0N/h1LWz7Vna+HEAmCP/0pviRVs0rImmYcMhbOXyAQ/ Q1lg== X-Gm-Message-State: AOJu0YwjEB6/dJ+INNHQNJIKIibGOqisocwgsdQCUnHrt3pf0j+h43Tb 9erqCi9vizaM2JG8GCU0vDPUtTWIo4CjIwXdowTH396yxOGp61PF79SK3b8g X-Google-Smtp-Source: AGHT+IFF+ToVbkOssbWOtckcoiuAxz+UivMV0+QcWFGzRv42bH3pEYn8m/1Wapri7nnY4uULPCNQlQ== X-Received: by 2002:a17:907:9451:b0:a7a:b26d:fb5 with SMTP id a640c23a62f3a-a868a7b4800mr46452366b.19.1724267411114; Wed, 21 Aug 2024 12:10:11 -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 a640c23a62f3a-a83838c6c07sm941222566b.43.2024.08.21.12.10.10 (version=TLS1_3 cipher=TLS_CHACHA20_POLY1305_SHA256 bits=256/256); Wed, 21 Aug 2024 12:10:10 -0700 (PDT) From: Iain Sandoe X-Google-Original-From: Iain Sandoe To: gcc-patches@gcc.gnu.org Cc: jason@redhat.com Subject: [PATCH 4/9] c++, coroutines: Fix handling of early exceptions [PR113773]. Date: Wed, 21 Aug 2024 20:10:01 +0100 Message-Id: <1d01b29247e0ab540787a5790dc9990994575b06.1724267239.git.iain@sandoe.co.uk> X-Mailer: git-send-email 2.39.2 (Apple Git-143) In-Reply-To: References: 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.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: iain@sandoe.co.uk Errors-To: gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org The responsibility for destroying part of the frame content (promise, arg copies and the frame itself) transitions from the ramp to the body of the coroutine once we reach the await_resume () for the initial suspend. We added the variable that flags the transition, but failed to act on it. This corrects that so that the ramp only tries to run DTORs for objects when an exception occurs before the initial suspend await resume has started. PR c++/113773 gcc/cp/ChangeLog: * coroutines.cc (cp_coroutine_transform::build_ramp_function): Only cleanup the frame state on exceptions that occur before the initial await resume has begun. gcc/testsuite/ChangeLog: * g++.dg/coroutines/torture/pr113773.C: New test. Signed-off-by: Iain Sandoe --- gcc/cp/coroutines.cc | 23 +++++++ .../g++.dg/coroutines/torture/pr113773.C | 66 +++++++++++++++++++ 2 files changed, 89 insertions(+) create mode 100644 gcc/testsuite/g++.dg/coroutines/torture/pr113773.C diff --git a/gcc/cp/coroutines.cc b/gcc/cp/coroutines.cc index f9f0bf40ed7..2faf198c206 100644 --- a/gcc/cp/coroutines.cc +++ b/gcc/cp/coroutines.cc @@ -5183,6 +5183,17 @@ cp_coroutine_transform::build_ramp_function () add_stmt (gro_d_if); } + /* Before initial resume is called, the responsibility for cleanup on + exception falls to the ramp. After that, the coroutine body code + should do the cleanup. */ + tree iarc_m = lookup_member (frame_type, coro_frame_i_a_r_c_id, + 1, 0, tf_warning_or_error); + tree iarc_x = build_class_member_access_expr (deref_fp, iarc_m, NULL_TREE, + false, tf_warning_or_error); + tree not_iarc + = build1_loc (loc, TRUTH_NOT_EXPR, boolean_type_node, iarc_x); + tree cleanup_if = begin_if_stmt (); + finish_if_stmt_cond (not_iarc, cleanup_if); /* If the promise is live, then run its dtor if that's available. */ if (promise_dtor && promise_dtor != error_mark_node) { @@ -5225,7 +5236,19 @@ cp_coroutine_transform::build_ramp_function () } /* We always expect to delete the frame. */ + tree fnf_if = begin_if_stmt (); + finish_if_stmt_cond (fnf_x, fnf_if); finish_expr_stmt (delete_frame_call); + finish_then_clause (fnf_if); + tree fnf_if_scope = IF_SCOPE (fnf_if); + IF_SCOPE (fnf_if) = NULL; + fnf_if = do_poplevel (fnf_if_scope); + add_stmt (fnf_if); + finish_then_clause (cleanup_if); + tree cleanup_if_scope = IF_SCOPE (cleanup_if); + IF_SCOPE (cleanup_if) = NULL; + cleanup_if = do_poplevel (cleanup_if_scope); + add_stmt (cleanup_if); tree rethrow = build_throw (loc, NULL_TREE, tf_warning_or_error); suppress_warning (rethrow); finish_expr_stmt (rethrow); diff --git a/gcc/testsuite/g++.dg/coroutines/torture/pr113773.C b/gcc/testsuite/g++.dg/coroutines/torture/pr113773.C new file mode 100644 index 00000000000..b048b0d63f4 --- /dev/null +++ b/gcc/testsuite/g++.dg/coroutines/torture/pr113773.C @@ -0,0 +1,66 @@ +// { dg-do run } +#include +#ifdef OUTPUT +#include +#endif + +struct result { + operator int() { + throw 42; + } +}; + +static int p_dtor_count = 0; +class promise { +public: + result get_return_object() { return {}; } + std::suspend_never initial_suspend() { +#ifdef OUTPUT + std::cout << "initial suspend" << std::endl; +#endif + return {}; + } + void unhandled_exception() { +#ifdef OUTPUT + std::cout << "unhandled exception" << std::endl; +#endif + } + std::suspend_never final_suspend() noexcept { +#ifdef OUTPUT + std::cout << "final suspend" << std::endl; +#endif + return {}; + } + void return_void() {} + ~promise() { + p_dtor_count++; +#ifdef OUTPUT + std::cout << "~promise()" << std::endl; +#endif + } +}; + +template +struct std::coroutine_traits { + using promise_type = promise; +}; + +int f() { + co_return; +} + +int main() { + try { + f(); + } + catch (int i) { + if (i != 42) + __builtin_abort (); +#ifdef OUTPUT + std::cout << "caught 42" << std::endl; +#endif + } + if (p_dtor_count != 1) + __builtin_abort (); + return 0; +}