https://gcc.gnu.org/bugzilla/show_bug.cgi?id=123597
--- Comment #6 from Tobias Burnus <burnus at gcc dot gnu.org> ---
The problem seems to be related to 'pushdecl' (called during template
substitution in pt.cc) putting 'sum' into the same scope as the
'long int j' iteration variable.
Only the
'<<cleanup_point int sum = 99;>>;'
remains at the original place.
I bet the problem occurs due to the following in parser.cc's
cp_parser_omp_for_loop
/* Do the substitution from the inside out. */
for (unsigned int i = count - 1; i > 0; i--)
if (data.init_placeholderv[i])
for (unsigned int j = i; j > 0; j--)
if (data.body_blockv[j - 1])
{
substitute_in_tree (&data.body_blockv[j - 1],
data.init_placeholderv[i],
data.body_blockv[i], false);
/*...*/ break;
}
Which moves the body of the inner omp-for loop (body_blockv[1]) to
the outermost nest-for loop.
My feeling - which might be wrong - is that the 'sum' variable is
originally created with a binding in the inner omp-for loop and that's
saved in IDENTIFIER_BINDING (decl) = ...
As the code is now moved, the code is no longer in that binding - and
find_local_binding - invoked via 'pushdecl' during the t-expr substitution
cannot find it anymore and then adds it to the current_binding_level which is
the one of OMP_FOR (i.e. before the for loops) instead of in the binding of the
body.
This would also explain why 'collapse(1)' works as the scope is already OK -
and I guess, without dependent type, the binding does not matter as no
'pushdecl' is called for it again.
Disclaimer: My suspicion might be also wrong as I have not fully understood how
current_binding_level is handled nor have I fully dug through the code nor
walked it properly in 'gdb'.