summaryrefslogtreecommitdiff
path: root/gcc/c
diff options
context:
space:
mode:
authormpolacek <mpolacek@138bc75d-0d04-0410-961f-82ee72b054a4>2014-06-03 17:35:34 +0000
committermpolacek <mpolacek@138bc75d-0d04-0410-961f-82ee72b054a4>2014-06-03 17:35:34 +0000
commitc69ec07da595081a3bc476bebe4729049b6254d8 (patch)
tree91bf428ee9f7a6bf677d0b5faa7d6cf778b29135 /gcc/c
parentb4b0f2cac267ff11c64bc6448218a96b66fc6ac3 (diff)
downloadgcc-c69ec07da595081a3bc476bebe4729049b6254d8.tar.gz
PR c/60439
* doc/invoke.texi: Document -Wswitch-bool. * function.c (stack_protect_epilogue): Cast controlling expression of the switch to int. * gengtype.c (walk_type): Generate switch expression with its controlling expression cast to int. c/ * c-parser.c (c_parser_switch_statement): Pass explicit_cast_p to c_start_case. * c-tree.h (c_start_case): Update. * c-typeck.c (c_start_case): Add new boolean parameter. Warn if switch condition has boolean value. cp/ * semantics.c (finish_switch_cond): Warn if switch condition has boolean value. c-family/ * c.opt (Wswitch-bool): New option. testsuite/ * c-c++-common/pr60439.c: New test. * g++.dg/eh/scope1.C (f4): Add dg-warning. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@211194 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/c')
-rw-r--r--gcc/c/ChangeLog9
-rw-r--r--gcc/c/c-parser.c6
-rw-r--r--gcc/c/c-tree.h2
-rw-r--r--gcc/c/c-typeck.c18
4 files changed, 31 insertions, 4 deletions
diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog
index 536e07e38d9..1047a65b636 100644
--- a/gcc/c/ChangeLog
+++ b/gcc/c/ChangeLog
@@ -1,3 +1,12 @@
+2014-06-03 Marek Polacek <polacek@redhat.com>
+
+ PR c/60439
+ * c-parser.c (c_parser_switch_statement): Pass explicit_cast_p to
+ c_start_case.
+ * c-tree.h (c_start_case): Update.
+ * c-typeck.c (c_start_case): Add new boolean parameter. Warn if
+ switch condition has boolean value.
+
2014-06-02 Andrew MacLeod <amacleod@redhat.com>
* c-decl.c: Include builtins.h.
diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
index 1d9780edf4e..abd636c5436 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -5197,9 +5197,13 @@ c_parser_switch_statement (c_parser *parser)
gcc_assert (c_parser_next_token_is_keyword (parser, RID_SWITCH));
c_parser_consume_token (parser);
block = c_begin_compound_stmt (flag_isoc99);
+ bool explicit_cast_p = false;
if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
{
switch_cond_loc = c_parser_peek_token (parser)->location;
+ if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)
+ && c_token_starts_typename (c_parser_peek_2nd_token (parser)))
+ explicit_cast_p = true;
ce = c_parser_expression (parser);
ce = convert_lvalue_to_rvalue (switch_cond_loc, ce, true, false);
expr = ce.value;
@@ -5217,7 +5221,7 @@ c_parser_switch_statement (c_parser *parser)
switch_cond_loc = UNKNOWN_LOCATION;
expr = error_mark_node;
}
- c_start_case (switch_loc, switch_cond_loc, expr);
+ c_start_case (switch_loc, switch_cond_loc, expr, explicit_cast_p);
save_break = c_break_label;
c_break_label = NULL_TREE;
body = c_parser_c99_block_statement (parser);
diff --git a/gcc/c/c-tree.h b/gcc/c/c-tree.h
index e7dcb355e9c..133930f4a09 100644
--- a/gcc/c/c-tree.h
+++ b/gcc/c/c-tree.h
@@ -614,7 +614,7 @@ extern void process_init_element (location_t, struct c_expr, bool,
struct obstack *);
extern tree build_compound_literal (location_t, tree, tree, bool);
extern void check_compound_literal_type (location_t, struct c_type_name *);
-extern tree c_start_case (location_t, location_t, tree);
+extern tree c_start_case (location_t, location_t, tree, bool);
extern void c_finish_case (tree);
extern tree build_asm_expr (location_t, tree, tree, tree, tree, tree, bool);
extern tree build_asm_stmt (tree, tree);
diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c
index 6ca584bf38c..a98ce0786f3 100644
--- a/gcc/c/c-typeck.c
+++ b/gcc/c/c-typeck.c
@@ -9361,12 +9361,13 @@ 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. */
+ SWITCH_COND_LOC is the location of the switch's condition.
+ EXPLICIT_CAST_P is true if the expression EXP has explicit cast. */
tree
c_start_case (location_t switch_loc,
location_t switch_cond_loc,
- tree exp)
+ tree exp, bool explicit_cast_p)
{
tree orig_type = error_mark_node;
struct c_switch *cs;
@@ -9387,6 +9388,19 @@ c_start_case (location_t switch_loc,
else
{
tree type = TYPE_MAIN_VARIANT (orig_type);
+ tree e = exp;
+
+ /* Warn if the condition has boolean value. */
+ while (TREE_CODE (e) == COMPOUND_EXPR)
+ e = TREE_OPERAND (e, 1);
+
+ if ((TREE_CODE (type) == BOOLEAN_TYPE
+ || truth_value_p (TREE_CODE (e)))
+ /* 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");
if (!in_system_header_at (input_location)
&& (type == long_integer_type_node