On 9/1/26 4:20 AM, Jakub Jelinek wrote:
Hi!The following testcase is incorrectly rejected with error: accessing '<anonymous>' outside its lifetime where <anonymous> is the TARGET_EXPR_SLOT of get_internal_target_expr returned TARGET_EXPR created in cp_finish_decomp. The problem is we create <<cleanup_point <<< Unknown tree: expr_stmt D.2723.a = v >>>; <<< Unknown tree: expr_stmt D.2723.b = v * 2 >>>; <<< Unknown tree: expr_stmt D.2723.c = v != 0 >>>; D.2758 = 1; TARGET_EXPR <D.2759, A::operator bool (&D.2723)>; const type & a; <<cleanup_point <<< Unknown tree: expr_stmt (void) (a = (const type &) A::get<0> (&D.2723)) >>>>>; const type & b; <<cleanup_point <<< Unknown tree: expr_stmt (void) (b = (const type &) A::get<1> (&D.2723)) >>>>>;>>; if (D.2759) { return <retval> = (int) *a + (int) *b; } where because of CWG2867 the first CLEANUP_POINT_EXPR wraps the whole structured binding initialization. The <anonymous> var is D.2759 above, we need to remember the return value from operator bool, but it is then used in the if condition after the initialization.
Why do we call operator bool so soon? The comment says
/* For structured bindings used in conditions we need to evaluate the conversion of decl (aka e in the standard) to bool or integral/enumeral type (the latter for switch conditions) before the get methods. */
but doesn't say why. I'd expect the conversion to happen after the whole initialization is complete: we do the whole structured binding declaration, and then once it's done we take e as the decision variable, which means converting it to bool at that point. There's no need to introduce a bool temporary at all.
Jason
