From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 48) id A88293855143; Fri, 25 Nov 2022 11:50:54 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org A88293855143 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1669377054; bh=9PLT72WH0NZi2CTejjSKKH0tt1gPHyBBCMxFqutnX9g=; h=From:To:Subject:Date:In-Reply-To:References:From; b=odWn6r/T95AyNxdaMnpJslXcIBQlu3Wt95gSsANaFlGVyqlUzI3BDPJSvRRqewnOm FCi9iQ66Gnr4fuY/ABxMlpdIzaFUe6AAT4AcB+6ELvHdM8y9XT2CsDLmICGyqLKRBF oW8ichhsCXFGVlzUyg4I8QqxNkkAGGmQe7YYiaPI= From: "adrian.perl at web dot de" To: gcc-bugs@gcc.gnu.org Subject: [Bug c++/99576] [coroutines] destructor of a temporary called too early within co_await expression Date: Fri, 25 Nov 2022 11:50:54 +0000 X-Bugzilla-Reason: CC X-Bugzilla-Type: changed X-Bugzilla-Watch-Reason: None X-Bugzilla-Product: gcc X-Bugzilla-Component: c++ X-Bugzilla-Version: 10.2.1 X-Bugzilla-Keywords: C++-coroutines, wrong-code X-Bugzilla-Severity: normal X-Bugzilla-Who: adrian.perl at web dot de X-Bugzilla-Status: NEW X-Bugzilla-Resolution: X-Bugzilla-Priority: P3 X-Bugzilla-Assigned-To: unassigned at gcc dot gnu.org X-Bugzilla-Target-Milestone: --- X-Bugzilla-Flags: X-Bugzilla-Changed-Fields: cc attachments.created Message-ID: In-Reply-To: References: Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable X-Bugzilla-URL: http://gcc.gnu.org/bugzilla/ Auto-Submitted: auto-generated MIME-Version: 1.0 List-Id: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=3D99576 Adrian Perl changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |adrian.perl at web dot de --- Comment #5 from Adrian Perl --- Created attachment 53963 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=3D53963&action=3Dedit Test applications I also noticed this behaviour in gcc 11.2 and could reproduce it in all ver= sion since 10.2 (even in the current trunk). Since this issues has existed for some time now, I had a look at the code myself and possibly found a fix. Please be aware that I am a complete novic= e in regards to the gcc-sourcecode. As the example posted by David Ledger (https://godbolt.org/z/8r8oGG4z5) was= the simplest one I could find, I used it to debug the issue. Having a look at the generated tree using -fdump-tree-all-graph I found out that the destructor of A gets indeed called twice, first by the destructor = of class Awaitable and then once more in a finally-clause. ... resume.4:; <>>>>; } finally { Awaitable::~Awaitable (&Aw0); } } finally { A::~A (&D.58267); } ... The finally clauses are generated by the maybe_promote_temps-function in coroutines.cc, which modifies the lifetime-management of temporaries in co_await statements in order to keep them alive across a suspension point. = For this purpose it recursivly searches all initializers to the right of the co_await expression, using the helper functions flatten_await_stmt and find_interesting_subtree. In this recursion it finds the initialization of the Awaitable and also the initialization of its member. So both the temporary Awaitable-instance and = its member get promoted, which leads to the generation of a (correct) destructor call for the Awaitable and the (incorrect) call for its member. So the error seems to be in the recursion, which also finds and promotes initializations in sub-scopes like the constructor.=20 Therefore I modified the check for relevant subexpressions to exclude trees below constructor calls, as can be seen in this patch: Patch: diff --git a/gcc/cp/coroutines.cc b/gcc/cp/coroutines.cc index 01a3e831ee5..349b68ea239 100644 --- a/gcc/cp/coroutines.cc +++ b/gcc/cp/coroutines.cc @@ -2684,6 +2684,10 @@ find_interesting_subtree (tree *expr_p, int *dosub, = void *d) return expr; } } + else if (TREE_CODE(expr) =3D=3D CONSTRUCTOR) + { + *dosub =3D 0; /* We don't need to consider this any further. */ + } else if (tmp_target_expr_p (expr) && !p->temps_used->contains (expr)) { --=20 2.34.1 I checked the results of the patched compiler using most of the examples po= sted in this and related bug reports (99576, 100611, 102217, 101244, 101976) and always got the correct results, also matching the output of clang. I have attached these test applications. I also noticed that the incorrect behaviour is gone as soon as the Awaitable has a user defined constructor. This likely moves the initalization of the Awaitable to a seperate tree which does not get evaluated by find_interesting_subtree. I checked the .dot-files and there was indeed an additional tree for the constructor when it is defined by the user. It would be great if someone could have a look at the patch, as I am unsure= if it could have any unforseen sideeffects. Another (better?) fix for this issue could be to always generate the constructor-tree.=