aboutsummaryrefslogtreecommitdiff
path: root/gcc/gimplify.c
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2017-12-01 08:17:06 +0000
committerJakub Jelinek <jakub@redhat.com>2017-12-01 08:17:06 +0000
commit1801e86e34926f53eee8d6e7a37e6984cac9540e (patch)
treeac4410022984e739592923e1b337810b9569c9aa /gcc/gimplify.c
parent8bd2db3726d9e82165802b7c481c3d537a417913 (diff)
PR c/79153
* tree.h (SWITCH_BREAK_LABEL_P): Define. * gimplify.c (collect_fallthrough_labels): Handle GIMPLE_BIND starting with a GIMPLE_SWITCH and ending with GIMPLE_LABEL with SWITCH_BREAK_LABEL_P set on the label. (gimplify_switch_expr): Set SWITCH_BREAK_LABEL_P on the label added for default case if it was missing and not all cases covered. Wrap GIMPLE_SWITCH and the switch_body_seq into a GIMPLE_BIND if switch_body_seq ends with a GIMPLE_LABEL with SWITCH_BREAK_LABEL_P set on the label. * tree-chrec.c (evolution_function_is_univariate_p): Add return true; to avoid -Wimplicit-fallthrough warning. * config/i386/i386.c (ix86_expand_special_args_builtin): Add FALLTHRU comment to avoid -Wimplicit-fallthrough warning. c/ * c-parser.c: Include tree-iterator.h. (c_parser_switch_statement): Emit LABEL_EXPR for the break label into SWITCH_BODY instead of after it and set SWITCH_BREAK_LABEL_P on it. cp/ * cp-gimplify.c (genericize_switch_stmt): Emit LABEL_EXPR for the break label into SWITCH_BODY instead of after it and set SWITCH_BREAK_LABEL_P on it. * parser.c (cp_parser_objc_expression): Add FALLTHRU comment to avoid -Wimplicit-fallthrough warning. fortran/ * match.c (gfc_match): Add FALLTHRU comment to avoid -Wimplicit-fallthrough warning. testsuite/ * c-c++-common/Wimplicit-fallthrough-7.c: Adjust expected warning line. * c-c++-common/Wimplicit-fallthrough-36.c: New test. git-svn-id: https://gcc.gnu.org/svn/gcc/trunk@255298 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/gimplify.c')
-rw-r--r--gcc/gimplify.c60
1 files changed, 57 insertions, 3 deletions
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index 2c2abd76c08..16a86ce70f0 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -1897,6 +1897,27 @@ collect_fallthrough_labels (gimple_stmt_iterator *gsi_p,
do
{
+ if (gimple_code (gsi_stmt (*gsi_p)) == GIMPLE_BIND)
+ {
+ /* Recognize the special GIMPLE_BIND added by gimplify_switch_expr,
+ which starts on a GIMPLE_SWITCH and ends with a break label.
+ Handle that as a single statement that can fall through. */
+ gbind *bind = as_a <gbind *> (gsi_stmt (*gsi_p));
+ gimple *first = gimple_seq_first_stmt (gimple_bind_body (bind));
+ gimple *last = gimple_seq_last_stmt (gimple_bind_body (bind));
+ if (last
+ && gimple_code (first) == GIMPLE_SWITCH
+ && gimple_code (last) == GIMPLE_LABEL)
+ {
+ tree label = gimple_label_label (as_a <glabel *> (last));
+ if (SWITCH_BREAK_LABEL_P (label))
+ {
+ prev = bind;
+ gsi_next (gsi_p);
+ continue;
+ }
+ }
+ }
if (gimple_code (gsi_stmt (*gsi_p)) == GIMPLE_BIND
|| gimple_code (gsi_stmt (*gsi_p)) == GIMPLE_TRY)
{
@@ -2315,6 +2336,7 @@ gimplify_switch_expr (tree *expr_p, gimple_seq *pre_p)
preprocess_case_label_vec_for_gimple (labels, index_type,
&default_case);
+ bool add_bind = false;
if (!default_case)
{
glabel *new_default;
@@ -2322,14 +2344,46 @@ gimplify_switch_expr (tree *expr_p, gimple_seq *pre_p)
default_case
= build_case_label (NULL_TREE, NULL_TREE,
create_artificial_label (UNKNOWN_LOCATION));
+ if (old_in_switch_expr)
+ {
+ SWITCH_BREAK_LABEL_P (CASE_LABEL (default_case)) = 1;
+ add_bind = true;
+ }
new_default = gimple_build_label (CASE_LABEL (default_case));
gimplify_seq_add_stmt (&switch_body_seq, new_default);
}
+ else if (old_in_switch_expr)
+ {
+ gimple *last = gimple_seq_last_stmt (switch_body_seq);
+ if (last && gimple_code (last) == GIMPLE_LABEL)
+ {
+ tree label = gimple_label_label (as_a <glabel *> (last));
+ if (SWITCH_BREAK_LABEL_P (label))
+ add_bind = true;
+ }
+ }
switch_stmt = gimple_build_switch (SWITCH_COND (switch_expr),
- default_case, labels);
- gimplify_seq_add_stmt (pre_p, switch_stmt);
- gimplify_seq_add_seq (pre_p, switch_body_seq);
+ default_case, labels);
+ /* For the benefit of -Wimplicit-fallthrough, if switch_body_seq
+ ends with a GIMPLE_LABEL holding SWITCH_BREAK_LABEL_P LABEL_DECL,
+ wrap the GIMPLE_SWITCH up to that GIMPLE_LABEL into a GIMPLE_BIND,
+ so that we can easily find the start and end of the switch
+ statement. */
+ if (add_bind)
+ {
+ gimple_seq bind_body = NULL;
+ gimplify_seq_add_stmt (&bind_body, switch_stmt);
+ gimple_seq_add_seq (&bind_body, switch_body_seq);
+ gbind *bind = gimple_build_bind (NULL_TREE, bind_body, NULL_TREE);
+ gimple_set_location (bind, EXPR_LOCATION (switch_expr));
+ gimplify_seq_add_stmt (pre_p, bind);
+ }
+ else
+ {
+ gimplify_seq_add_stmt (pre_p, switch_stmt);
+ gimplify_seq_add_seq (pre_p, switch_body_seq);
+ }
labels.release ();
}
else