From: jakub Date: Wed, 23 Jan 2019 14:41:16 +0000 (+0000) Subject: PR c/44715 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=8090d51ce27a5f35a643b0dbd7773a748c18aa3b;p=thirdparty%2Fgcc.git 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@268188 138bc75d-0d04-0410-961f-82ee72b054a4 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index bbbacebf4cbe..401b81d75c7a 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2019-01-23 Jakub Jelinek + + PR c/44715 + * doc/extend.texi: Document break and continue behavior in + statement expressions. + 2019-01-23 Richard Biener PR tree-optimization/89008 diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 363dff135cfb..a36fe31ca23d 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,9 @@ 2019-01-23 Jakub Jelinek + 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. diff --git a/gcc/cp/cp-gimplify.c b/gcc/cp/cp-gimplify.c index e476b8f53ec1..33111bd14bff 100644 --- a/gcc/cp/cp-gimplify.c +++ b/gcc/cp/cp-gimplify.c @@ -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) diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index 2f3f10b911ec..4044fba753e3 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -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, diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index c6006e0655b1..38fec831cb88 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,8 @@ 2019-01-23 Jakub Jelinek + PR c/44715 + * c-c++-common/pr44715.c: New test. + PR c++/88984 * c-c++-common/pr88984.c: New test. diff --git a/gcc/testsuite/c-c++-common/pr44715.c b/gcc/testsuite/c-c++-common/pr44715.c new file mode 100644 index 000000000000..f20a14688fa6 --- /dev/null +++ b/gcc/testsuite/c-c++-common/pr44715.c @@ -0,0 +1,171 @@ +/* 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; +}