Commit 372e6e6b by Jakub Jelinek Committed by Jakub Jelinek

re PR c/44715 (Break in increment expression of "for" statement inconsistent with g++)

	PR c/44715
	* cp-gimplify.c (genericize_cp_loop): Call begin_bc_block only
	after genericizing cond and incr expressions.

	* doc/extend.texi: Document break and continue behavior in
	statement expressions.

	* c-c++-common/pr44715.c: New test.

From-SVN: r268188
parent d0f2db23
2019-01-23 Jakub Jelinek <jakub@redhat.com>
PR c/44715
* doc/extend.texi: Document break and continue behavior in
statement expressions.
2019-01-23 Richard Biener <rguenther@suse.de>
PR tree-optimization/89008
......
2019-01-23 Jakub Jelinek <jakub@redhat.com>
PR c/44715
* cp-gimplify.c (genericize_cp_loop): Call begin_bc_block only
after genericizing cond and incr expressions.
PR c++/88984
* cp-gimplify.c (genericize_switch_stmt): Move cond genericization
before the begin_bc_block call.
......
......@@ -242,14 +242,15 @@ genericize_cp_loop (tree *stmt_p, location_t start_locus, tree cond, tree body,
tree exit = NULL;
tree stmt_list = NULL;
blab = begin_bc_block (bc_break, start_locus);
clab = begin_bc_block (bc_continue, start_locus);
protected_set_expr_location (incr, start_locus);
cp_walk_tree (&cond, cp_genericize_r, data, NULL);
cp_walk_tree (&body, cp_genericize_r, data, NULL);
cp_walk_tree (&incr, cp_genericize_r, data, NULL);
blab = begin_bc_block (bc_break, start_locus);
clab = begin_bc_block (bc_continue, start_locus);
cp_walk_tree (&body, cp_genericize_r, data, NULL);
*walk_subtrees = 0;
if (cond && TREE_CODE (cond) != INTEGER_CST)
......
......@@ -213,7 +213,14 @@ statement expression is part of a larger expression then it is
unspecified which other subexpressions of that expression have been
evaluated except where the language definition requires certain
subexpressions to be evaluated before or after the statement
expression. In any case, as with a function call, the evaluation of a
expression. A @code{break} or @code{continue} statement inside of
a statement expression used in @code{while}, @code{do} or @code{for}
loop or @code{switch} statement condition
or @code{for} statement init or increment expressions jumps to an
outer loop or @code{switch} statement if any (otherwise it is an error),
rather than to the loop or @code{switch} statement in whose condition
or init or increment expression it appears.
In any case, as with a function call, the evaluation of a
statement expression is not interleaved with the evaluation of other
parts of the containing expression. For example,
......
2019-01-23 Jakub Jelinek <jakub@redhat.com>
PR c/44715
* c-c++-common/pr44715.c: New test.
PR c++/88984
* c-c++-common/pr88984.c: New test.
......
/* PR c/44715 */
/* { dg-do run } */
/* { dg-options "" } */
void
foo (int x, int y)
{
int z;
switch (x)
{
case 0:
while (({ if (y) break; 0; }))
;
__builtin_abort ();
break;
case 1:
do
;
while (({ if (y) break; 0; }));
__builtin_abort ();
break;
case 2:
for (z = ({ if (y) break; 0; }); z < 5; z++)
;
__builtin_abort ();
break;
case 3:
for (z = 0; z < ({ if (y) break; 5; }); z++)
;
__builtin_abort ();
break;
case 4:
for (z = 0; z < 5; z += ({ if (y) break; 1; }))
;
__builtin_abort ();
break;
case 5:
switch (({ if (y) break; 1; }))
{
default: break;
}
__builtin_abort ();
break;
default:
__builtin_abort ();
break;
}
}
void
bar (int x, int y)
{
int z;
while (x >= 0)
{
if (x == 0)
{
while (({ if (y) break; 0; }))
;
__builtin_abort ();
}
if (x == 1)
{
do
;
while (({ if (y) break; 0; }));
__builtin_abort ();
}
if (x == 2)
{
for (z = ({ if (y) break; 0; }); z < 5; z++)
;
__builtin_abort ();
}
if (x == 3)
{
for (z = 0; z < ({ if (y) break; 5; }); z++)
;
__builtin_abort ();
}
if (x == 4)
{
for (z = 0; z < 5; z += ({ if (y) break; 1; }))
;
__builtin_abort ();
}
if (x == 5)
{
switch (({ if (y) break; 1; }))
{
default: break;
}
__builtin_abort ();
}
}
}
void
baz (int x, int y)
{
int z;
while (x >= 0)
{
if (++y == 2)
return;
if (x == 0)
{
while (({ if (y) continue; 0; }))
;
__builtin_abort ();
}
if (x == 1)
{
do
;
while (({ if (y) continue; 0; }));
__builtin_abort ();
}
if (x == 2)
{
for (z = ({ if (y) continue; 0; }); z < 5; z++)
;
__builtin_abort ();
}
if (x == 3)
{
for (z = 0; z < ({ if (y) continue; 5; }); z++)
;
__builtin_abort ();
}
if (x == 4)
{
for (z = 0; z < 5; z += ({ if (y) continue; 1; }))
;
__builtin_abort ();
}
if (x == 5)
{
switch (({ if (y) continue; 1; }))
{
default: break;
}
__builtin_abort ();
}
}
__builtin_abort ();
}
int
main ()
{
foo (0, 1);
foo (1, 1);
foo (2, 1);
foo (3, 1);
foo (4, 1);
foo (5, 1);
bar (0, 1);
bar (1, 1);
bar (2, 1);
bar (3, 1);
bar (4, 1);
bar (5, 1);
baz (0, 0);
baz (1, 0);
baz (2, 0);
baz (3, 0);
baz (4, 0);
baz (5, 0);
return 0;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment