[Bug c++/127109] [C++26] P0963 structured binding as a condition rejected during constant evaluation when the type uses the tuple protocol
cvs-commit at gcc dot gnu.org
gcc-bugzilla@gcc.gnu.org
Thu Sep 3 07:52:02 GMT 2026
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 <jakub@gcc.gnu.org>:
https://gcc.gnu.org/g:84ec92254bda8e7675dd2b3bfd5c76255568e72e
commit r17-3889-g84ec92254bda8e7675dd2b3bfd5c76255568e72e
Author: Jakub Jelinek <jakub@redhat.com>
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 <jakub@redhat.com>
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 <jason@redhat.com>
More information about the Gcc-bugs
mailing list