diff options
author | Jakub Jelinek <jakub@redhat.com> | 2017-12-01 08:17:06 +0000 |
---|---|---|
committer | Jakub Jelinek <jakub@redhat.com> | 2017-12-01 08:17:06 +0000 |
commit | 1801e86e34926f53eee8d6e7a37e6984cac9540e (patch) | |
tree | ac4410022984e739592923e1b337810b9569c9aa /gcc/gimplify.c | |
parent | 8bd2db3726d9e82165802b7c481c3d537a417913 (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.c | 60 |
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 |