aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarek Polacek <mpolacek@gcc.gnu.org>2014-06-03 17:35:34 +0000
committerMarek Polacek <mpolacek@gcc.gnu.org>2014-06-03 17:35:34 +0000
commitfedfecef5e3e78daf0d970d8edb4ab33a167535c (patch)
tree91bf428ee9f7a6bf677d0b5faa7d6cf778b29135
parente4f36438a9dd49f88a9fb4006b481aeeda780255 (diff)
downloadgcc-fedfecef5e3e78daf0d970d8edb4ab33a167535c.zip
gcc-fedfecef5e3e78daf0d970d8edb4ab33a167535c.tar.gz
gcc-fedfecef5e3e78daf0d970d8edb4ab33a167535c.tar.bz2
re PR c/60439 (No warning for case overflow in switch statement.)
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. From-SVN: r211194
-rw-r--r--gcc/ChangeLog15
-rw-r--r--gcc/c-family/ChangeLog5
-rw-r--r--gcc/c-family/c.opt4
-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
-rw-r--r--gcc/cp/ChangeLog6
-rw-r--r--gcc/cp/semantics.c5
-rw-r--r--gcc/doc/invoke.texi18
-rw-r--r--gcc/function.c2
-rw-r--r--gcc/gengtype.c8
-rw-r--r--gcc/testsuite/ChangeLog6
-rw-r--r--gcc/testsuite/c-c++-common/pr60439.c108
-rw-r--r--gcc/testsuite/g++.dg/eh/scope1.C2
15 files changed, 200 insertions, 14 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 7866183..406179f 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,4 +1,13 @@
-2014-06-03 Vishnu K S <Vishnu.k_s@atmel.com>
+2014-06-03 Marek Polacek <polacek@redhat.com>
+
+ 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.
+
+2014-06-03 Vishnu K S <Vishnu.k_s@atmel.com>
* config/avr/avr-mcus.def: Add new avr25 devices attiny441, attiny828
and attiny841.
@@ -6,8 +15,8 @@
* config/avr/t-multilib: Regenerate.
* doc/avr-mmcu.texi: Regenerate.
-2014-06-03 Vishnu K S <vishnu.k_s@atmel.com>
- Pitchumani Sivanupandi <pitchumani.s@atmel.com>
+2014-06-03 Vishnu K S <vishnu.k_s@atmel.com>
+ Pitchumani Sivanupandi <pitchumani.s@atmel.com>
* config/avr/avr-mcus.def (ata6616c): Add new avr25 device.
(ata6617c, ata664251): Add new avr35 devices.
diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog
index 675a66e..86267f4 100644
--- a/gcc/c-family/ChangeLog
+++ b/gcc/c-family/ChangeLog
@@ -1,3 +1,8 @@
+2014-06-03 Marek Polacek <polacek@redhat.com>
+
+ PR c/60439
+ * c.opt (Wswitch-bool): New option.
+
2014-05-22 Thomas Schwinge <thomas@codesourcery.com>
* c-common.h (c_omp_sharing_predetermined, c_omp_remap_decl):
diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
index c586e65..5d36a80 100644
--- a/gcc/c-family/c.opt
+++ b/gcc/c-family/c.opt
@@ -534,6 +534,10 @@ Wswitch-enum
C ObjC C++ ObjC++ Var(warn_switch_enum) Warning
Warn about all enumerated switches missing a specific case
+Wswitch-bool
+C ObjC C++ ObjC++ Warning Init(1)
+Warn about switches with boolean controlling expression
+
Wmissing-format-attribute
C ObjC C++ ObjC++ Alias(Wsuggest-attribute=format)
;
diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog
index 536e07e..1047a65 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 1d9780e..abd636c 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 e7dcb35..133930f 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 6ca584b..a98ce07 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
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index f356caa..2fa1549f 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,9 @@
+2014-06-03 Marek Polacek <polacek@redhat.com>
+
+ PR c/60439
+ * semantics.c (finish_switch_cond): Warn if switch condition has
+ boolean value.
+
2014-06-03 Jason Merrill <jason@redhat.com>
PR c++/60992
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 21920b4..c1c16f4 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -1130,6 +1130,11 @@ finish_switch_cond (tree cond, tree switch_stmt)
orig_type = TREE_TYPE (cond);
if (cond != error_mark_node)
{
+ /* Warn if the condition has boolean value. */
+ if (TREE_CODE (orig_type) == BOOLEAN_TYPE)
+ warning_at (input_location, OPT_Wswitch_bool,
+ "switch condition has type bool");
+
/* [stmt.switch]
Integral promotions are performed. */
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 6db0d55..1c2e079 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -271,7 +271,7 @@ Objective-C and Objective-C++ Dialects}.
-Wstrict-aliasing=n @gol -Wstrict-overflow -Wstrict-overflow=@var{n} @gol
-Wsuggest-attribute=@r{[}pure@r{|}const@r{|}noreturn@r{|}format@r{]} @gol
-Wmissing-format-attribute @gol
--Wswitch -Wswitch-default -Wswitch-enum -Wsync-nand @gol
+-Wswitch -Wswitch-default -Wswitch-enum -Wswitch-bool -Wsync-nand @gol
-Wsystem-headers -Wtrampolines -Wtrigraphs -Wtype-limits -Wundef @gol
-Wuninitialized -Wunknown-pragmas -Wno-pragmas @gol
-Wunsuffixed-float-constants -Wunused -Wunused-function @gol
@@ -3846,6 +3846,22 @@ between @option{-Wswitch} and this option is that this option gives a
warning about an omitted enumeration code even if there is a
@code{default} label.
+@item -Wswitch-bool
+@opindex Wswitch-bool
+@opindex Wno-switch-bool
+Warn whenever a @code{switch} statement has an index of boolean type.
+It is possible to suppress this warning by casting the controlling
+expression to a type other than @code{bool}. For example:
+@smallexample
+@group
+switch ((int) (a == 4))
+ @{
+ ...
+ @}
+@end group
+@end smallexample
+This warning is enabled by default for C and C++ programs.
+
@item -Wsync-nand @r{(C and C++ only)}
@opindex Wsync-nand
@opindex Wno-sync-nand
diff --git a/gcc/function.c b/gcc/function.c
index ec2ea26..922f567 100644
--- a/gcc/function.c
+++ b/gcc/function.c
@@ -4649,7 +4649,7 @@ stack_protect_epilogue (void)
/* Allow the target to compare Y with X without leaking either into
a register. */
- switch (HAVE_stack_protect_test != 0)
+ switch ((int) (HAVE_stack_protect_test != 0))
{
case 1:
tmp = gen_stack_protect_test (x, y, label);
diff --git a/gcc/gengtype.c b/gcc/gengtype.c
index bc8f701..ffe3f94 100644
--- a/gcc/gengtype.c
+++ b/gcc/gengtype.c
@@ -3099,9 +3099,9 @@ walk_type (type_p t, struct walk_type_data *d)
t->u.s.tag);
desc = "1";
}
- oprintf (d->of, "%*sswitch (", d->indent, "");
+ oprintf (d->of, "%*sswitch ((int) (", d->indent, "");
output_escaped_param (d, desc, "desc");
- oprintf (d->of, ")\n");
+ oprintf (d->of, "))\n");
d->indent += 2;
oprintf (d->of, "%*s{\n", d->indent, "");
}
@@ -3121,9 +3121,9 @@ walk_type (type_p t, struct walk_type_data *d)
"missing `tag' option for type `%s'",
t->u.s.tag);
}
- oprintf (d->of, "%*sswitch (", d->indent, "");
+ oprintf (d->of, "%*sswitch ((int) (", d->indent, "");
output_escaped_param (d, desc, "desc");
- oprintf (d->of, ")\n");
+ oprintf (d->of, "))\n");
d->indent += 2;
oprintf (d->of, "%*s{\n", d->indent, "");
oprintf (d->of, "%*scase %s:\n", d->indent, "", type_tag);
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 14d79e1..c409d99 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,9 @@
+2014-06-03 Marek Polacek <polacek@redhat.com>
+
+ PR c/60439
+ * c-c++-common/pr60439.c: New test.
+ * g++.dg/eh/scope1.C (f4): Add dg-warning.
+
2014-06-03 Martin Jambor <mjambor@suse.cz>
PR ipa/61160
diff --git a/gcc/testsuite/c-c++-common/pr60439.c b/gcc/testsuite/c-c++-common/pr60439.c
new file mode 100644
index 0000000..3368a0b
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/pr60439.c
@@ -0,0 +1,108 @@
+/* PR c/60439 */
+/* { dg-do compile } */
+
+#ifndef __cplusplus
+# define bool _Bool
+#endif
+
+extern bool foo (void);
+
+void
+f1 (bool b)
+{
+ switch (b) /* { dg-warning "switch condition has" } */
+ break;
+}
+
+void
+f2 (int a, int b)
+{
+ switch (a && b) /* { dg-warning "switch condition has" } */
+ break;
+ switch ((bool) (a && b)) /* { dg-warning "switch condition has" } */
+ break;
+ switch ((a && b) || a) /* { dg-warning "switch condition has" } */
+ break;
+ /* No warnings on following. */
+ switch ((int) (a && b))
+ break;
+ switch ((unsigned int) (a && b))
+ break;
+ switch ((unsigned short int) (a && b))
+ break;
+ switch ((char) (a && b))
+ break;
+}
+
+void
+f3 (int a)
+{
+ switch (!!a) /* { dg-warning "switch condition has" } */
+ break;
+ switch (!a) /* { dg-warning "switch condition has" } */
+ break;
+}
+
+void
+f4 (void)
+{
+ switch (foo ()) /* { dg-warning "switch condition has" } */
+ break;
+}
+
+void
+f5 (int a)
+{
+ switch (a == 3) /* { dg-warning "switch condition has" } */
+ break;
+ switch (a != 3) /* { dg-warning "switch condition has" } */
+ break;
+ switch (a > 3) /* { dg-warning "switch condition has" } */
+ break;
+ switch (a < 3) /* { dg-warning "switch condition has" } */
+ break;
+ switch (a <= 3) /* { dg-warning "switch condition has" } */
+ break;
+ switch (a >= 3) /* { dg-warning "switch condition has" } */
+ break;
+ switch (foo (), foo (), a >= 42) /* { dg-warning "switch condition has" } */
+ break;
+ switch (a == 3, a & 4, a ^ 5, a)
+ break;
+ switch ((int) (a == 3))
+ break;
+ switch ((int) (a != 3))
+ break;
+}
+
+void
+f6 (bool b)
+{
+ switch (b) /* { dg-warning "switch condition has" } */
+ break;
+ switch (!b) /* { dg-warning "switch condition has" } */
+ break;
+ switch (b++) /* { dg-warning "switch condition has" } */
+ break;
+}
+
+void
+f7 (void)
+{
+ bool b;
+ switch (b = 1) /* { dg-warning "switch condition has" } */
+ break;
+}
+
+void
+f8 (int i)
+{
+ switch (i)
+ break;
+ switch ((int) i)
+ break;
+ switch ((unsigned int) i)
+ break;
+ switch ((bool) i) /* { dg-warning "switch condition has" } */
+ break;
+}
diff --git a/gcc/testsuite/g++.dg/eh/scope1.C b/gcc/testsuite/g++.dg/eh/scope1.C
index 276e0d6..8d553d8 100644
--- a/gcc/testsuite/g++.dg/eh/scope1.C
+++ b/gcc/testsuite/g++.dg/eh/scope1.C
@@ -31,7 +31,7 @@ void f3 ()
void f4 ()
{
- switch (C br = C())
+ switch (C br = C()) /* { dg-warning "switch condition has" } */
{
default:
abort ();