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]>

Reply via email to