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
This commit is contained in:
parent
e4f36438a9
commit
fedfecef5e
15 changed files with 200 additions and 14 deletions
|
@ -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.
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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)
|
||||
;
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
108
gcc/testsuite/c-c++-common/pr60439.c
Normal file
108
gcc/testsuite/c-c++-common/pr60439.c
Normal file
|
@ -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;
|
||||
}
|
|
@ -31,7 +31,7 @@ void f3 ()
|
|||
|
||||
void f4 ()
|
||||
{
|
||||
switch (C br = C())
|
||||
switch (C br = C()) /* { dg-warning "switch condition has" } */
|
||||
{
|
||||
default:
|
||||
abort ();
|
||||
|
|
Loading…
Add table
Reference in a new issue