diff options
author | mpolacek <mpolacek@138bc75d-0d04-0410-961f-82ee72b054a4> | 2014-06-03 17:35:34 +0000 |
---|---|---|
committer | mpolacek <mpolacek@138bc75d-0d04-0410-961f-82ee72b054a4> | 2014-06-03 17:35:34 +0000 |
commit | c69ec07da595081a3bc476bebe4729049b6254d8 (patch) | |
tree | 91bf428ee9f7a6bf677d0b5faa7d6cf778b29135 /gcc/c | |
parent | b4b0f2cac267ff11c64bc6448218a96b66fc6ac3 (diff) | |
download | gcc-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/ChangeLog | 9 | ||||
-rw-r--r-- | gcc/c/c-parser.c | 6 | ||||
-rw-r--r-- | gcc/c/c-tree.h | 2 | ||||
-rw-r--r-- | gcc/c/c-typeck.c | 18 |
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 |