https://gcc.gnu.org/bugzilla/show_bug.cgi?id=123597

--- Comment #20 from GCC Commits <cvs-commit at gcc dot gnu.org> ---
The releases/gcc-15 branch has been updated by Jakub Jelinek
<[email protected]>:

https://gcc.gnu.org/g:786def4bda52096c50b4294d402c33bc41da9807

commit r15-10729-g786def4bda52096c50b4294d402c33bc41da9807
Author: Jakub Jelinek <[email protected]>
Date:   Fri Jan 23 08:37:36 2026 +0100

    openmp: Fix up OpenMP loop parsing in templates [PR123597]

    The following testcase is miscompiled, because since r14-3490
    because in this case the sum variable is moved out of the loop's
    body into an outer BIND_EXPR and becomes shared, so from what
    has been previously private can result in data races.

    In the C++ FE, BIND_EXPRs are mostly created for 2 reasons.
    One is when something calls c_build_bind_expr and that function
    creates a BIND_EXPR because there are decls to attach to it,
    this happens for !processing_template_decl e.g. from do_poplevel
    or poplevel (the latter for sk_cleanup which I think don't appear
    if processing_template_decl).  And the other case are BIND_EXPRs
    created by begin_compound_stmt if processing_template_decl, those
    don't stand for the need to collect decls inside of it, but to
    say the source had {} at this point, take it into account when
    instantiating the template.

    Now, on the testcase when parsing the body of the inner collapsed
    loop we call cp_parser_statement -> cp_parser_compound_statement
    -> begin_compound_statement because the body is surrounded by {}s
    and that returns a BIND_EXPR with the processing_template_decl
    meaning, the source had {} here.
    But the r14-3490 code then calls substitute_in_tree in a loop, trying
    to replace placeholders it created with the parsed bodies.  And while
    doing that, considers all BIND_EXPRs with !BIND_EXPR_VARS redundant
    and just throws them away.
    They are redundant when !processing_template_decl, but when
    processing_template_decl they I think always have !BIND_EXPR_VARS,
    the vars inside of such bodies aren't pushed into any BIND_EXPR yet,
    they just have a DECL_EXPR somewhere, and the pushing of the instantiated
    copies of those will be done only during instantiation.

    The following patch fixes it by not treating BIND_EXPRs with
!BIND_EXPR_VARS
    as redundant if processing_template_decl, it is fine to merge two
    BIND_EXPRs with nothing in between them.

    2026-01-23  Jakub Jelinek  <[email protected]>

            PR c++/123597
            * parser.cc (substitute_in_tree_walker, substitute_in_tree): Don't
            consider BIND_EXPRs with !BIND_EXPR_VARS redundant if
            processing_template_decl.

            * g++.dg/gomp/pr123597.C: New test.

    (cherry picked from commit 1ae53b20c2474c28da13835719cceeee0702c966)

Reply via email to