https://gcc.gnu.org/bugzilla/show_bug.cgi?id=127109
--- Comment #4 from GCC Commits <cvs-commit at gcc dot gnu.org> --- The master branch has been updated by Jakub Jelinek <[email protected]>: https://gcc.gnu.org/g:84ec92254bda8e7675dd2b3bfd5c76255568e72e commit r17-3889-g84ec92254bda8e7675dd2b3bfd5c76255568e72e Author: Jakub Jelinek <[email protected]> Date: Thu Sep 3 09:45:58 2026 +0200 c++: Fix up constexpr structured bindings used as condition [PR127109] 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. The CLEANUP_POINT_EXPR around the whole initialization does destruct_value the TARGET_EXPR slot though, so the use in if (D.2759) is then during constant evaluation considered out of lifetime use. This patch stops using TARGET_EXPR for this and instead uses get_temp_regvar with pushdecl, instead of DECL_DECOMP_BASE recorded as NON_LVALUE_EXPR around that temp var to differentiate it from structured binding vars other than the base where the VAR_DECL stands for the base. 2026-09-03 Jakub Jelinek <[email protected]> PR c++/127109 * decl.cc (cp_finish_decomp): Add [dcl.struct.bind]/7 reference to comment. Use get_temp_regvar and pushdecl instead of get_internal_target_expr and add_stmt. Set DECL_DECOMP_BASE to NON_LVALUE_EXPR around the temp regvar. * cp-tree.h (DECL_DECOMP_BASE): Adjust macro comment. * semantics.cc (maybe_convert_cond, switch_finish_cond): Check for NON_LVALUE_EXPR rather than TARGET_EXPR and extract its operand rather than TARGET_EXPR_SLOT. * g++.dg/cpp26/decomp32.C: New test. Reviewed-by: Jason Merrill <[email protected]>
