[Bug c++/123597] [14/15/16 Regression][OpenMP] Local variable wrongly hoisted (and shared) with templates and collapse(2)
cvs-commit at gcc dot gnu.org
gcc-bugzilla@gcc.gnu.org
Fri Jan 23 07:52:42 GMT 2026
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=123597
--- Comment #18 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:1ae53b20c2474c28da13835719cceeee0702c966
commit r16-6989-g1ae53b20c2474c28da13835719cceeee0702c966
Author: Jakub Jelinek <jakub@redhat.com>
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 <jakub@redhat.com>
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.
More information about the Gcc-bugs
mailing list