aboutsummaryrefslogtreecommitdiff
path: root/gcc/c
diff options
context:
space:
mode:
authorMarek Polacek <polacek@redhat.com>2015-06-29 13:12:44 +0000
committerMarek Polacek <mpolacek@gcc.gnu.org>2015-06-29 13:12:44 +0000
commitb155cfd9288996f3a1044fb2463c7ac7e757a0df (patch)
tree8bc44969367937690b20314e2432d485c707678f /gcc/c
parent99e943a2be4bb7ec0d51b5a68e44d0d42dd9347a (diff)
downloadgcc-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/ChangeLog9
-rw-r--r--gcc/c/c-typeck.c22
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;