Commit 6866c6e8 by Ian Lance Taylor Committed by Ian Lance Taylor

c.opt (Wenum-compare): Enable for C and Objc.

gcc/:
	* c.opt (Wenum-compare): Enable for C and Objc.  Initialize to -1.
	* c-opts.c (c_common_handle_option): For C, set warn_enum_compare
	for -Wall and for -Wc++-compat.
	(c_common_post_options): For C++, set warn_enum_compare if not
	already set.
	* c-tree.h (struct c_expr): Add field original_type.
	(build_external_ref): Update declaration.
	* c-parser.c (c_parser_braced_init): Set original_type.
	(c_parser_initelt): Likewise.
	(c_parser_expr_no_commas): Likewise.
	(c_parser_conditional_expression): Likewise.
	(c_parser_cast_expression): Likewise.
	(c_parser_unary_expression): Likewise.  Pull setting of
	original_code to top of function.
	(c_parser_sizeof_expression): Set original_type.
	(c_parser_alignof_expression): Likewise.
	(c_parser_postfix_expression): Likewise.  Pull setting of
	original_code to top of function.
	(c_parser_postfix_expression_after_paren_type): Set
	original_type.
	(c_parser_postfix_expression_after_primary): Likewise.
	(c_parser_expression): Likewise.
	* c-typeck.c (build_external_ref): Add type parameter.  Change all
	callers.
	(c_expr_sizeof_expr): Set original_type field.
	(parser_build_unary_op): Likewise.
	(parser_build_binary_op): Likewise.  Optionally warn about
	comparisons of enums of different types.
	(digest_init): Set original_type field.
	(really_start_incremental_init): Likewise.
	(push_init_level, pop_init_level): Likewise.
	* doc/invoke.texi (Warning Options): -Wenum-compare now
	supported in C.
gcc/testsuite/:
	* gcc.dg/Wenum-compare-1.c: New testcase.

From-SVN: r146127
parent f116fecf
2009-04-15 Ian Lance Taylor <iant@google.com>
* c.opt (Wenum-compare): Enable for C and Objc. Initialize to -1.
* c-opts.c (c_common_handle_option): For C, set warn_enum_compare
for -Wall and for -Wc++-compat.
(c_common_post_options): For C++, set warn_enum_compare if not
already set.
* c-tree.h (struct c_expr): Add field original_type.
(build_external_ref): Update declaration.
* c-parser.c (c_parser_braced_init): Set original_type.
(c_parser_initelt): Likewise.
(c_parser_expr_no_commas): Likewise.
(c_parser_conditional_expression): Likewise.
(c_parser_cast_expression): Likewise.
(c_parser_unary_expression): Likewise. Pull setting of
original_code to top of function.
(c_parser_sizeof_expression): Set original_type.
(c_parser_alignof_expression): Likewise.
(c_parser_postfix_expression): Likewise. Pull setting of
original_code to top of function.
(c_parser_postfix_expression_after_paren_type): Set
original_type.
(c_parser_postfix_expression_after_primary): Likewise.
(c_parser_expression): Likewise.
* c-typeck.c (build_external_ref): Add type parameter. Change all
callers.
(c_expr_sizeof_expr): Set original_type field.
(parser_build_unary_op): Likewise.
(parser_build_binary_op): Likewise. Optionally warn about
comparisons of enums of different types.
(digest_init): Set original_type field.
(really_start_incremental_init): Likewise.
(push_init_level, pop_init_level): Likewise.
* doc/invoke.texi (Warning Options): -Wenum-compare now
supported in C.
2009-04-15 Richard Guenther <rguenther@suse.de> 2009-04-15 Richard Guenther <rguenther@suse.de>
* tree-ssa-pre.c (eliminate): When replacing a PHI node carry * tree-ssa-pre.c (eliminate): When replacing a PHI node carry
......
...@@ -412,6 +412,12 @@ c_common_handle_option (size_t scode, const char *arg, int value) ...@@ -412,6 +412,12 @@ c_common_handle_option (size_t scode, const char *arg, int value)
can turn it off only if it's not explicit. */ can turn it off only if it's not explicit. */
if (warn_main == -1) if (warn_main == -1)
warn_main = (value ? 2 : 0); warn_main = (value ? 2 : 0);
/* In C, -Wall turns on -Wenum-compare, which we do here.
In C++ it is on by default, which is done in
c_common_post_options. */
if (warn_enum_compare == -1)
warn_enum_compare = value;
} }
else else
{ {
...@@ -438,6 +444,13 @@ c_common_handle_option (size_t scode, const char *arg, int value) ...@@ -438,6 +444,13 @@ c_common_handle_option (size_t scode, const char *arg, int value)
cpp_opts->warn_comments = value; cpp_opts->warn_comments = value;
break; break;
case OPT_Wc___compat:
/* Because -Wenum-compare is the default in C++, -Wc++-compat
implies -Wenum-compare. */
if (warn_enum_compare == -1 && value)
warn_enum_compare = value;
break;
case OPT_Wdeprecated: case OPT_Wdeprecated:
cpp_opts->warn_deprecated = value; cpp_opts->warn_deprecated = value;
break; break;
...@@ -1099,6 +1112,12 @@ c_common_post_options (const char **pfilename) ...@@ -1099,6 +1112,12 @@ c_common_post_options (const char **pfilename)
if (warn_sign_conversion == -1) if (warn_sign_conversion == -1)
warn_sign_conversion = (c_dialect_cxx ()) ? 0 : warn_conversion; warn_sign_conversion = (c_dialect_cxx ()) ? 0 : warn_conversion;
/* In C, -Wall and -Wc++-compat enable -Wenum-compare, which we do
in c_common_handle_option; if it has not yet been set, it is
disabled by default. In C++, it is enabled by default. */
if (warn_enum_compare == -1)
warn_enum_compare = c_dialect_cxx () ? 1 : 0;
/* -Wpacked-bitfield-compat is on by default for the C languages. The /* -Wpacked-bitfield-compat is on by default for the C languages. The
warning is issued in stor-layout.c which is not part of the front-end so warning is issued in stor-layout.c which is not part of the front-end so
we need to selectively turn it on here. */ we need to selectively turn it on here. */
......
...@@ -163,6 +163,11 @@ struct c_expr ...@@ -163,6 +163,11 @@ struct c_expr
initializers, or ERROR_MARK for other expressions (including initializers, or ERROR_MARK for other expressions (including
parenthesized expressions). */ parenthesized expressions). */
enum tree_code original_code; enum tree_code original_code;
/* If not NULL, the original type of an expression. This will
differ from the type of the value field for an enum constant.
The type of an enum constant is a plain integer type, but this
field will be the enum type. */
tree original_type;
}; };
/* A kind of type specifier. Note that this information is currently /* A kind of type specifier. Note that this information is currently
...@@ -577,7 +582,7 @@ extern struct c_expr default_function_array_conversion (struct c_expr); ...@@ -577,7 +582,7 @@ extern struct c_expr default_function_array_conversion (struct c_expr);
extern tree composite_type (tree, tree); extern tree composite_type (tree, tree);
extern tree build_component_ref (tree, tree); extern tree build_component_ref (tree, tree);
extern tree build_array_ref (tree, tree, location_t); extern tree build_array_ref (tree, tree, location_t);
extern tree build_external_ref (tree, int, location_t); extern tree build_external_ref (tree, int, location_t, tree *);
extern void pop_maybe_used (bool); extern void pop_maybe_used (bool);
extern struct c_expr c_expr_sizeof_expr (struct c_expr); extern struct c_expr c_expr_sizeof_expr (struct c_expr);
extern struct c_expr c_expr_sizeof_type (struct c_type_name *); extern struct c_expr c_expr_sizeof_type (struct c_type_name *);
......
...@@ -2202,9 +2202,12 @@ build_array_ref (tree array, tree index, location_t loc) ...@@ -2202,9 +2202,12 @@ build_array_ref (tree array, tree index, location_t loc)
/* Build an external reference to identifier ID. FUN indicates /* Build an external reference to identifier ID. FUN indicates
whether this will be used for a function call. LOC is the source whether this will be used for a function call. LOC is the source
location of the identifier. */ location of the identifier. This sets *TYPE to the type of the
identifier, which is not the same as the type of the returned value
for CONST_DECLs defined as enum constants. If the type of the
identifier is not available, *TYPE is set to NULL. */
tree tree
build_external_ref (tree id, int fun, location_t loc) build_external_ref (tree id, int fun, location_t loc, tree *type)
{ {
tree ref; tree ref;
tree decl = lookup_name (id); tree decl = lookup_name (id);
...@@ -2213,8 +2216,12 @@ build_external_ref (tree id, int fun, location_t loc) ...@@ -2213,8 +2216,12 @@ build_external_ref (tree id, int fun, location_t loc)
whatever lookup_name() found. */ whatever lookup_name() found. */
decl = objc_lookup_ivar (decl, id); decl = objc_lookup_ivar (decl, id);
*type = NULL;
if (decl && decl != error_mark_node) if (decl && decl != error_mark_node)
ref = decl; {
ref = decl;
*type = TREE_TYPE (ref);
}
else if (fun) else if (fun)
/* Implicit function declaration. */ /* Implicit function declaration. */
ref = implicitly_declare (id); ref = implicitly_declare (id);
...@@ -2346,6 +2353,7 @@ c_expr_sizeof_expr (struct c_expr expr) ...@@ -2346,6 +2353,7 @@ c_expr_sizeof_expr (struct c_expr expr)
{ {
ret.value = error_mark_node; ret.value = error_mark_node;
ret.original_code = ERROR_MARK; ret.original_code = ERROR_MARK;
ret.original_type = NULL;
pop_maybe_used (false); pop_maybe_used (false);
} }
else else
...@@ -2355,6 +2363,7 @@ c_expr_sizeof_expr (struct c_expr expr) ...@@ -2355,6 +2363,7 @@ c_expr_sizeof_expr (struct c_expr expr)
&expr_const_operands); &expr_const_operands);
ret.value = c_sizeof (TREE_TYPE (folded_expr)); ret.value = c_sizeof (TREE_TYPE (folded_expr));
ret.original_code = ERROR_MARK; ret.original_code = ERROR_MARK;
ret.original_type = NULL;
if (c_vla_type_p (TREE_TYPE (folded_expr))) if (c_vla_type_p (TREE_TYPE (folded_expr)))
{ {
/* sizeof is evaluated when given a vla (C99 6.5.3.4p2). */ /* sizeof is evaluated when given a vla (C99 6.5.3.4p2). */
...@@ -2380,6 +2389,7 @@ c_expr_sizeof_type (struct c_type_name *t) ...@@ -2380,6 +2389,7 @@ c_expr_sizeof_type (struct c_type_name *t)
type = groktypename (t, &type_expr, &type_expr_const); type = groktypename (t, &type_expr, &type_expr_const);
ret.value = c_sizeof (type); ret.value = c_sizeof (type);
ret.original_code = ERROR_MARK; ret.original_code = ERROR_MARK;
ret.original_type = NULL;
if (type_expr && c_vla_type_p (type)) if (type_expr && c_vla_type_p (type))
{ {
ret.value = build2 (C_MAYBE_CONST_EXPR, TREE_TYPE (ret.value), ret.value = build2 (C_MAYBE_CONST_EXPR, TREE_TYPE (ret.value),
...@@ -2856,7 +2866,8 @@ parser_build_unary_op (enum tree_code code, struct c_expr arg, location_t loc) ...@@ -2856,7 +2866,8 @@ parser_build_unary_op (enum tree_code code, struct c_expr arg, location_t loc)
result.value = build_unary_op (loc, code, arg.value, 0); result.value = build_unary_op (loc, code, arg.value, 0);
result.original_code = code; result.original_code = code;
result.original_type = NULL;
if (TREE_OVERFLOW_P (result.value) && !TREE_OVERFLOW_P (arg.value)) if (TREE_OVERFLOW_P (result.value) && !TREE_OVERFLOW_P (arg.value))
overflow_warning (result.value); overflow_warning (result.value);
...@@ -2879,10 +2890,17 @@ parser_build_binary_op (location_t location, enum tree_code code, ...@@ -2879,10 +2890,17 @@ parser_build_binary_op (location_t location, enum tree_code code,
enum tree_code code1 = arg1.original_code; enum tree_code code1 = arg1.original_code;
enum tree_code code2 = arg2.original_code; enum tree_code code2 = arg2.original_code;
tree type1 = (arg1.original_type
? arg1.original_type
: TREE_TYPE (arg1.value));
tree type2 = (arg2.original_type
? arg2.original_type
: TREE_TYPE (arg2.value));
result.value = build_binary_op (location, code, result.value = build_binary_op (location, code,
arg1.value, arg2.value, 1); arg1.value, arg2.value, 1);
result.original_code = code; result.original_code = code;
result.original_type = NULL;
if (TREE_CODE (result.value) == ERROR_MARK) if (TREE_CODE (result.value) == ERROR_MARK)
return result; return result;
...@@ -2915,6 +2933,16 @@ parser_build_binary_op (location_t location, enum tree_code code, ...@@ -2915,6 +2933,16 @@ parser_build_binary_op (location_t location, enum tree_code code,
&& !TREE_OVERFLOW_P (arg2.value)) && !TREE_OVERFLOW_P (arg2.value))
overflow_warning (result.value); overflow_warning (result.value);
/* Warn about comparisons of different enum types. */
if (warn_enum_compare
&& TREE_CODE_CLASS (code) == tcc_comparison
&& TREE_CODE (type1) == ENUMERAL_TYPE
&& TREE_CODE (type2) == ENUMERAL_TYPE
&& TYPE_MAIN_VARIANT (type1) != TYPE_MAIN_VARIANT (type2))
warning_at (location, OPT_Wenum_compare,
"comparison between %qT and %qT",
type1, type2);
return result; return result;
} }
...@@ -5171,6 +5199,7 @@ digest_init (tree type, tree init, bool null_pointer_constant, ...@@ -5171,6 +5199,7 @@ digest_init (tree type, tree init, bool null_pointer_constant,
tree typ2 = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (inside_init))); tree typ2 = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (inside_init)));
expr.value = inside_init; expr.value = inside_init;
expr.original_code = (strict_string ? STRING_CST : ERROR_MARK); expr.original_code = (strict_string ? STRING_CST : ERROR_MARK);
expr.original_type = NULL;
maybe_warn_string_init (type, expr); maybe_warn_string_init (type, expr);
if (comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (inside_init)), if (comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (inside_init)),
...@@ -5690,6 +5719,7 @@ really_start_incremental_init (tree type) ...@@ -5690,6 +5719,7 @@ really_start_incremental_init (tree type)
p->depth = constructor_depth; p->depth = constructor_depth;
p->replacement_value.value = 0; p->replacement_value.value = 0;
p->replacement_value.original_code = ERROR_MARK; p->replacement_value.original_code = ERROR_MARK;
p->replacement_value.original_type = NULL;
p->implicit = 0; p->implicit = 0;
p->range_stack = 0; p->range_stack = 0;
p->outer = 0; p->outer = 0;
...@@ -5833,6 +5863,7 @@ push_init_level (int implicit) ...@@ -5833,6 +5863,7 @@ push_init_level (int implicit)
p->depth = constructor_depth; p->depth = constructor_depth;
p->replacement_value.value = 0; p->replacement_value.value = 0;
p->replacement_value.original_code = ERROR_MARK; p->replacement_value.original_code = ERROR_MARK;
p->replacement_value.original_type = NULL;
p->implicit = implicit; p->implicit = implicit;
p->outer = 0; p->outer = 0;
p->incremental = constructor_incremental; p->incremental = constructor_incremental;
...@@ -5989,6 +6020,7 @@ pop_init_level (int implicit) ...@@ -5989,6 +6020,7 @@ pop_init_level (int implicit)
struct c_expr ret; struct c_expr ret;
ret.value = 0; ret.value = 0;
ret.original_code = ERROR_MARK; ret.original_code = ERROR_MARK;
ret.original_type = NULL;
if (implicit == 0) if (implicit == 0)
{ {
......
...@@ -204,7 +204,7 @@ C ObjC C++ ObjC++ Warning ...@@ -204,7 +204,7 @@ C ObjC C++ ObjC++ Warning
Warn about stray tokens after #elif and #endif Warn about stray tokens after #elif and #endif
Wenum-compare Wenum-compare
C++ ObjC++ Var(warn_enum_compare) Init(1) Warning C ObjC C++ ObjC++ Var(warn_enum_compare) Init(-1) Warning
Warn about comparison of different enum types Warn about comparison of different enum types
Werror Werror
......
...@@ -2758,6 +2758,7 @@ Options} and @ref{Objective-C and Objective-C++ Dialect Options}. ...@@ -2758,6 +2758,7 @@ Options} and @ref{Objective-C and Objective-C++ Dialect Options}.
-Warray-bounds @r{(only with} @option{-O2}@r{)} @gol -Warray-bounds @r{(only with} @option{-O2}@r{)} @gol
-Wc++0x-compat @gol -Wc++0x-compat @gol
-Wchar-subscripts @gol -Wchar-subscripts @gol
-Wenum-compare @r{(in C/Objc; this is on by default in C++)} @gol
-Wimplicit-int @gol -Wimplicit-int @gol
-Wimplicit-function-declaration @gol -Wimplicit-function-declaration @gol
-Wcomment @gol -Wcomment @gol
...@@ -3743,11 +3744,12 @@ integers are disabled by default in C++ unless ...@@ -3743,11 +3744,12 @@ integers are disabled by default in C++ unless
Warn if an empty body occurs in an @samp{if}, @samp{else} or @samp{do Warn if an empty body occurs in an @samp{if}, @samp{else} or @samp{do
while} statement. This warning is also enabled by @option{-Wextra}. while} statement. This warning is also enabled by @option{-Wextra}.
@item -Wenum-compare @r{(C++ and Objective-C++ only)} @item -Wenum-compare
@opindex Wenum-compare @opindex Wenum-compare
@opindex Wno-enum-compare @opindex Wno-enum-compare
Warn about a comparison between values of different enum types. This Warn about a comparison between values of different enum types. In C++
warning is enabled by default. this warning is enabled by default. In C this warning is enabled by
@option{-Wall}.
@item -Wsign-compare @item -Wsign-compare
@opindex Wsign-compare @opindex Wsign-compare
......
2009-04-15 Ian Lance Taylor <iant@google.com>
* gcc.dg/Wenum-compare-1.c: New testcase.
2009-04-15 Richard Guenther <rguenther@suse.de> 2009-04-15 Richard Guenther <rguenther@suse.de>
PR tree-optimization/39764 PR tree-optimization/39764
......
/* { dg-do compile } */
/* { dg-options "-Wenum-compare" } */
enum E1 { A, B, C };
enum E2 { D, E, F };
extern void f2 ();
void
f1 ()
{
int a = A;
int d = D;
enum E1 e1 = A;
enum E2 e2 = D;
if (A > D) /* { dg-warning "comparison between .enum E1. and .enum E2." } */
f2 ();
if (e1 > e2) /* { dg-warning "comparison between .enum E1. and .enum E2." } */
f2 ();
if (e1 > e2 + 1)
f2 ();
if (A > 0)
f2 ();
if (e1 > 0)
f2 ();
if (A + D > 0)
f2 ();
if (e1 > 0)
f2 ();
if (A + D > 0)
f2 ();
if ((int) A > D)
f2 ();
if ((int) e1 > e2)
f2 ();
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment