+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.
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)
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.
--- /dev/null
+/* 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;
+}