diff options
author | Marek Polacek <polacek@redhat.com> | 2015-06-29 13:12:44 +0000 |
---|---|---|
committer | Marek Polacek <mpolacek@gcc.gnu.org> | 2015-06-29 13:12:44 +0000 |
commit | b155cfd9288996f3a1044fb2463c7ac7e757a0df (patch) | |
tree | 8bc44969367937690b20314e2432d485c707678f /gcc/c | |
parent | 99e943a2be4bb7ec0d51b5a68e44d0d42dd9347a (diff) | |
download | gcc-b155cfd9288996f3a1044fb2463c7ac7e757a0df.zip gcc-b155cfd9288996f3a1044fb2463c7ac7e757a0df.tar.gz gcc-b155cfd9288996f3a1044fb2463c7ac7e757a0df.tar.bz2 |
re PR c/66322 (Linus Torvalds: -Wswitch-bool produces dubious warnings, fails to notice really bad things)
PR c/66322
* c-common.c (check_case_bounds): Add bool * parameter. Set
OUTSIDE_RANGE_P.
(c_add_case_label): Add bool * parameter. Pass it down to
check_case_bounds.
(c_do_switch_warnings): Add bool parameters. Implement -Wswitch-bool
warning here.
* c-common.h (c_add_case_label, c_do_switch_warnings): Update
declarations.
* c-typeck.c (struct c_switch): Add BOOL_COND_P and OUTSIDE_RANGE_P.
(c_start_case): Set BOOL_COND_P and OUTSIDE_RANGE_P. Don't warn
about -Wswitch-bool here.
(do_case): Update c_add_case_label call.
(c_finish_case): Update c_do_switch_warnings call.
* decl.c (struct cp_switch): Add OUTSIDE_RANGE_P.
(push_switch): Set OUTSIDE_RANGE_P.
(pop_switch): Update c_do_switch_warnings call.
(finish_case_label): Update c_add_case_label call.
* semantics.c (finish_switch_cond): Don't warn about -Wswitch-bool
here.
* function.c (stack_protect_epilogue): Remove a cast to int.
* doc/invoke.texi: Update -Wswitch-bool description.
* c-c++-common/pr60439.c: Add dg-prune-output and add switch cases.
* c-c++-common/pr66322.c: New test.
* g++.dg/eh/scope1.C: Remove dg-warning.
From-SVN: r225116
Diffstat (limited to 'gcc/c')
-rw-r--r-- | gcc/c/ChangeLog | 9 | ||||
-rw-r--r-- | gcc/c/c-typeck.c | 22 |
2 files changed, 26 insertions, 5 deletions
diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog index edba3f1..2c5ba6d 100644 --- a/gcc/c/ChangeLog +++ b/gcc/c/ChangeLog @@ -1,3 +1,12 @@ +2015-06-29 Marek Polacek <polacek@redhat.com> + + PR c/66322 + * c-typeck.c (struct c_switch): Add BOOL_COND_P and OUTSIDE_RANGE_P. + (c_start_case): Set BOOL_COND_P and OUTSIDE_RANGE_P. Don't warn + about -Wswitch-bool here. + (do_case): Update c_add_case_label call. + (c_finish_case): Update c_do_switch_warnings call. + 2015-06-27 Marek Polacek <polacek@redhat.com> * c-typeck.c: Use VECTOR_TYPE_P throughout. diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c index 8e2696a..6ea3513 100644 --- a/gcc/c/c-typeck.c +++ b/gcc/c/c-typeck.c @@ -9525,6 +9525,14 @@ struct c_switch { /* The next node on the stack. */ struct c_switch *next; + + /* Remember whether the controlling expression had boolean type + before integer promotions for the sake of -Wswitch-bool. */ + bool bool_cond_p; + + /* Remember whether there was a case value that is outside the + range of the ORIG_TYPE. */ + bool outside_range_p; }; /* A stack of the currently active switch statements. The innermost @@ -9538,7 +9546,7 @@ struct c_switch *c_switch_stack; /* Start a C switch statement, testing expression EXP. Return the new SWITCH_EXPR. SWITCH_LOC is the location of the `switch'. SWITCH_COND_LOC is the location of the switch's condition. - EXPLICIT_CAST_P is true if the expression EXP has explicit cast. */ + EXPLICIT_CAST_P is true if the expression EXP has an explicit cast. */ tree c_start_case (location_t switch_loc, @@ -9546,6 +9554,7 @@ c_start_case (location_t switch_loc, tree exp, bool explicit_cast_p) { tree orig_type = error_mark_node; + bool bool_cond_p = false; struct c_switch *cs; if (exp != error_mark_node) @@ -9575,8 +9584,7 @@ c_start_case (location_t switch_loc, /* Explicit cast to int suppresses this warning. */ && !(TREE_CODE (type) == INTEGER_TYPE && explicit_cast_p)) - warning_at (switch_cond_loc, OPT_Wswitch_bool, - "switch condition has boolean value"); + bool_cond_p = true; if (!in_system_header_at (input_location) && (type == long_integer_type_node @@ -9600,6 +9608,8 @@ c_start_case (location_t switch_loc, cs->orig_type = orig_type; cs->cases = splay_tree_new (case_compare, NULL, NULL); cs->bindings = c_get_switch_bindings (); + cs->bool_cond_p = bool_cond_p; + cs->outside_range_p = false; cs->next = c_switch_stack; c_switch_stack = cs; @@ -9646,7 +9656,8 @@ do_case (location_t loc, tree low_value, tree high_value) label = c_add_case_label (loc, c_switch_stack->cases, SWITCH_COND (c_switch_stack->switch_expr), c_switch_stack->orig_type, - low_value, high_value); + low_value, high_value, + &c_switch_stack->outside_range_p); if (label == error_mark_node) label = NULL_TREE; return label; @@ -9667,7 +9678,8 @@ c_finish_case (tree body, tree type) switch_location = EXPR_LOCATION (cs->switch_expr); c_do_switch_warnings (cs->cases, switch_location, type ? type : TREE_TYPE (cs->switch_expr), - SWITCH_COND (cs->switch_expr)); + SWITCH_COND (cs->switch_expr), + cs->bool_cond_p, cs->outside_range_p); /* Pop the stack. */ c_switch_stack = cs->next; |