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
This commit is contained in:
parent
f116fecf89
commit
6866c6e8ff
@ -1,3 +1,39 @@
|
||||
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>
|
||||
|
||||
* tree-ssa-pre.c (eliminate): When replacing a PHI node carry
|
||||
|
19
gcc/c-opts.c
19
gcc/c-opts.c
@ -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. */
|
||||
if (warn_main == -1)
|
||||
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
|
||||
{
|
||||
@ -438,6 +444,13 @@ c_common_handle_option (size_t scode, const char *arg, int value)
|
||||
cpp_opts->warn_comments = value;
|
||||
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:
|
||||
cpp_opts->warn_deprecated = value;
|
||||
break;
|
||||
@ -1099,6 +1112,12 @@ c_common_post_options (const char **pfilename)
|
||||
if (warn_sign_conversion == -1)
|
||||
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
|
||||
warning is issued in stor-layout.c which is not part of the front-end so
|
||||
we need to selectively turn it on here. */
|
||||
|
107
gcc/c-parser.c
107
gcc/c-parser.c
@ -3044,6 +3044,7 @@ c_parser_braced_init (c_parser *parser, tree type, bool nested_p)
|
||||
struct c_expr ret;
|
||||
ret.value = error_mark_node;
|
||||
ret.original_code = ERROR_MARK;
|
||||
ret.original_type = NULL;
|
||||
c_parser_skip_until_found (parser, CPP_CLOSE_BRACE, "expected %<}%>");
|
||||
pop_init_level (0);
|
||||
return ret;
|
||||
@ -3100,6 +3101,7 @@ c_parser_initelt (c_parser *parser)
|
||||
struct c_expr init;
|
||||
init.value = error_mark_node;
|
||||
init.original_code = ERROR_MARK;
|
||||
init.original_type = NULL;
|
||||
c_parser_error (parser, "expected identifier");
|
||||
c_parser_skip_until_found (parser, CPP_COMMA, NULL);
|
||||
process_init_element (init, false);
|
||||
@ -3174,6 +3176,7 @@ c_parser_initelt (c_parser *parser)
|
||||
mexpr.value
|
||||
= objc_build_message_expr (build_tree_list (rec, args));
|
||||
mexpr.original_code = ERROR_MARK;
|
||||
mexpr.original_type = NULL;
|
||||
/* Now parse and process the remainder of the
|
||||
initializer, starting with this message
|
||||
expression as a primary-expression. */
|
||||
@ -3223,6 +3226,7 @@ c_parser_initelt (c_parser *parser)
|
||||
struct c_expr init;
|
||||
init.value = error_mark_node;
|
||||
init.original_code = ERROR_MARK;
|
||||
init.original_type = NULL;
|
||||
c_parser_error (parser, "expected %<=%>");
|
||||
c_parser_skip_until_found (parser, CPP_COMMA, NULL);
|
||||
process_init_element (init, false);
|
||||
@ -4438,6 +4442,7 @@ c_parser_expr_no_commas (c_parser *parser, struct c_expr *after)
|
||||
TREE_NO_WARNING (ret.value) = 1;
|
||||
ret.original_code = ERROR_MARK;
|
||||
}
|
||||
ret.original_type = NULL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -4485,6 +4490,7 @@ c_parser_conditional_expression (c_parser *parser, struct c_expr *after)
|
||||
exp1.value = c_save_expr (default_conversion (cond.value));
|
||||
if (eptype)
|
||||
exp1.value = build1 (EXCESS_PRECISION_EXPR, eptype, exp1.value);
|
||||
exp1.original_type = NULL;
|
||||
cond.value = c_objc_common_truthvalue_conversion (cond_loc, exp1.value);
|
||||
skip_evaluation += cond.value == truthvalue_true_node;
|
||||
}
|
||||
@ -4503,6 +4509,7 @@ c_parser_conditional_expression (c_parser *parser, struct c_expr *after)
|
||||
skip_evaluation -= cond.value == truthvalue_true_node;
|
||||
ret.value = error_mark_node;
|
||||
ret.original_code = ERROR_MARK;
|
||||
ret.original_type = NULL;
|
||||
return ret;
|
||||
}
|
||||
exp2 = c_parser_conditional_expression (parser, NULL);
|
||||
@ -4512,6 +4519,24 @@ c_parser_conditional_expression (c_parser *parser, struct c_expr *after)
|
||||
cond.original_code == C_MAYBE_CONST_EXPR,
|
||||
exp1.value, exp2.value);
|
||||
ret.original_code = ERROR_MARK;
|
||||
if (exp1.value == error_mark_node || exp2.value == error_mark_node)
|
||||
ret.original_type = NULL;
|
||||
else
|
||||
{
|
||||
tree t1, t2;
|
||||
|
||||
/* If both sides are enum type, the default conversion will have
|
||||
made the type of the result be an integer type. We want to
|
||||
remember the enum types we started with. */
|
||||
t1 = exp1.original_type ? exp1.original_type : TREE_TYPE (exp1.value);
|
||||
t2 = exp2.original_type ? exp2.original_type : TREE_TYPE (exp2.value);
|
||||
ret.original_type = ((t1 != error_mark_node
|
||||
&& t2 != error_mark_node
|
||||
&& (TYPE_MAIN_VARIANT (t1)
|
||||
== TYPE_MAIN_VARIANT (t2)))
|
||||
? t1
|
||||
: NULL);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -4800,6 +4825,7 @@ c_parser_cast_expression (c_parser *parser, struct c_expr *after)
|
||||
{
|
||||
ret.value = error_mark_node;
|
||||
ret.original_code = ERROR_MARK;
|
||||
ret.original_type = NULL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -4813,6 +4839,7 @@ c_parser_cast_expression (c_parser *parser, struct c_expr *after)
|
||||
expr = default_function_array_conversion (expr);
|
||||
ret.value = c_cast_expr (type_name, expr.value);
|
||||
ret.original_code = ERROR_MARK;
|
||||
ret.original_type = NULL;
|
||||
return ret;
|
||||
}
|
||||
else
|
||||
@ -4852,6 +4879,8 @@ c_parser_unary_expression (c_parser *parser)
|
||||
int ext;
|
||||
struct c_expr ret, op;
|
||||
location_t loc = c_parser_peek_token (parser)->location;
|
||||
ret.original_code = ERROR_MARK;
|
||||
ret.original_type = NULL;
|
||||
switch (c_parser_peek_token (parser)->type)
|
||||
{
|
||||
case CPP_PLUS_PLUS:
|
||||
@ -4874,7 +4903,6 @@ c_parser_unary_expression (c_parser *parser)
|
||||
op = c_parser_cast_expression (parser, NULL);
|
||||
op = default_function_array_conversion (op);
|
||||
ret.value = build_indirect_ref (loc, op.value, "unary *");
|
||||
ret.original_code = ERROR_MARK;
|
||||
return ret;
|
||||
case CPP_PLUS:
|
||||
if (!c_dialect_objc () && !in_system_header)
|
||||
@ -4914,7 +4942,6 @@ c_parser_unary_expression (c_parser *parser)
|
||||
c_parser_error (parser, "expected identifier");
|
||||
ret.value = error_mark_node;
|
||||
}
|
||||
ret.original_code = ERROR_MARK;
|
||||
return ret;
|
||||
case CPP_KEYWORD:
|
||||
switch (c_parser_peek_token (parser)->keyword)
|
||||
@ -4975,6 +5002,7 @@ c_parser_sizeof_expression (c_parser *parser)
|
||||
in_sizeof--;
|
||||
ret.value = error_mark_node;
|
||||
ret.original_code = ERROR_MARK;
|
||||
ret.original_type = NULL;
|
||||
return ret;
|
||||
}
|
||||
if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
|
||||
@ -5029,6 +5057,7 @@ c_parser_alignof_expression (c_parser *parser)
|
||||
in_alignof--;
|
||||
ret.value = error_mark_node;
|
||||
ret.original_code = ERROR_MARK;
|
||||
ret.original_type = NULL;
|
||||
return ret;
|
||||
}
|
||||
if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
|
||||
@ -5042,6 +5071,7 @@ c_parser_alignof_expression (c_parser *parser)
|
||||
in_alignof--;
|
||||
ret.value = c_alignof (groktypename (type_name, NULL, NULL));
|
||||
ret.original_code = ERROR_MARK;
|
||||
ret.original_type = NULL;
|
||||
return ret;
|
||||
}
|
||||
else
|
||||
@ -5053,6 +5083,7 @@ c_parser_alignof_expression (c_parser *parser)
|
||||
in_alignof--;
|
||||
ret.value = c_alignof_expr (expr.value);
|
||||
ret.original_code = ERROR_MARK;
|
||||
ret.original_type = NULL;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
@ -5116,11 +5147,12 @@ c_parser_postfix_expression (c_parser *parser)
|
||||
struct c_expr expr, e1, e2, e3;
|
||||
struct c_type_name *t1, *t2;
|
||||
location_t loc;
|
||||
expr.original_code = ERROR_MARK;
|
||||
expr.original_type = NULL;
|
||||
switch (c_parser_peek_token (parser)->type)
|
||||
{
|
||||
case CPP_NUMBER:
|
||||
expr.value = c_parser_peek_token (parser)->value;
|
||||
expr.original_code = ERROR_MARK;
|
||||
loc = c_parser_peek_token (parser)->location;
|
||||
c_parser_consume_token (parser);
|
||||
if (TREE_CODE (expr.value) == FIXED_CST
|
||||
@ -5135,7 +5167,6 @@ c_parser_postfix_expression (c_parser *parser)
|
||||
case CPP_CHAR32:
|
||||
case CPP_WCHAR:
|
||||
expr.value = c_parser_peek_token (parser)->value;
|
||||
expr.original_code = ERROR_MARK;
|
||||
c_parser_consume_token (parser);
|
||||
break;
|
||||
case CPP_STRING:
|
||||
@ -5150,7 +5181,6 @@ c_parser_postfix_expression (c_parser *parser)
|
||||
gcc_assert (c_dialect_objc ());
|
||||
expr.value
|
||||
= objc_build_string_object (c_parser_peek_token (parser)->value);
|
||||
expr.original_code = ERROR_MARK;
|
||||
c_parser_consume_token (parser);
|
||||
break;
|
||||
case CPP_NAME:
|
||||
@ -5158,7 +5188,6 @@ c_parser_postfix_expression (c_parser *parser)
|
||||
{
|
||||
c_parser_error (parser, "expected expression");
|
||||
expr.value = error_mark_node;
|
||||
expr.original_code = ERROR_MARK;
|
||||
break;
|
||||
}
|
||||
{
|
||||
@ -5167,8 +5196,8 @@ c_parser_postfix_expression (c_parser *parser)
|
||||
c_parser_consume_token (parser);
|
||||
expr.value = build_external_ref (id,
|
||||
(c_parser_peek_token (parser)->type
|
||||
== CPP_OPEN_PAREN), loc);
|
||||
expr.original_code = ERROR_MARK;
|
||||
== CPP_OPEN_PAREN), loc,
|
||||
&expr.original_type);
|
||||
}
|
||||
break;
|
||||
case CPP_OPEN_PAREN:
|
||||
@ -5189,7 +5218,6 @@ c_parser_postfix_expression (c_parser *parser)
|
||||
c_parser_skip_until_found (parser, CPP_CLOSE_BRACE, NULL);
|
||||
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
|
||||
expr.value = error_mark_node;
|
||||
expr.original_code = ERROR_MARK;
|
||||
break;
|
||||
}
|
||||
stmt = c_begin_stmt_expr ();
|
||||
@ -5199,7 +5227,6 @@ c_parser_postfix_expression (c_parser *parser)
|
||||
pedwarn (here, OPT_pedantic,
|
||||
"ISO C forbids braced-groups within expressions");
|
||||
expr.value = c_finish_stmt_expr (stmt);
|
||||
expr.original_code = ERROR_MARK;
|
||||
}
|
||||
else if (c_token_starts_typename (c_parser_peek_2nd_token (parser)))
|
||||
{
|
||||
@ -5215,7 +5242,6 @@ c_parser_postfix_expression (c_parser *parser)
|
||||
if (type_name == NULL)
|
||||
{
|
||||
expr.value = error_mark_node;
|
||||
expr.original_code = ERROR_MARK;
|
||||
}
|
||||
else
|
||||
expr = c_parser_postfix_expression_after_paren_type (parser,
|
||||
@ -5230,6 +5256,7 @@ c_parser_postfix_expression (c_parser *parser)
|
||||
TREE_NO_WARNING (expr.value) = 1;
|
||||
if (expr.original_code != C_MAYBE_CONST_EXPR)
|
||||
expr.original_code = ERROR_MARK;
|
||||
/* Don't change EXPR.ORIGINAL_TYPE. */
|
||||
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
|
||||
"expected %<)%>");
|
||||
}
|
||||
@ -5243,7 +5270,6 @@ c_parser_postfix_expression (c_parser *parser)
|
||||
expr.value = fname_decl (c_parser_peek_token (parser)->location,
|
||||
c_parser_peek_token (parser)->keyword,
|
||||
c_parser_peek_token (parser)->value);
|
||||
expr.original_code = ERROR_MARK;
|
||||
c_parser_consume_token (parser);
|
||||
break;
|
||||
case RID_VA_ARG:
|
||||
@ -5251,7 +5277,6 @@ c_parser_postfix_expression (c_parser *parser)
|
||||
if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
|
||||
{
|
||||
expr.value = error_mark_node;
|
||||
expr.original_code = ERROR_MARK;
|
||||
break;
|
||||
}
|
||||
e1 = c_parser_expr_no_commas (parser, NULL);
|
||||
@ -5260,7 +5285,6 @@ c_parser_postfix_expression (c_parser *parser)
|
||||
{
|
||||
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
|
||||
expr.value = error_mark_node;
|
||||
expr.original_code = ERROR_MARK;
|
||||
break;
|
||||
}
|
||||
t1 = c_parser_type_name (parser);
|
||||
@ -5269,7 +5293,6 @@ c_parser_postfix_expression (c_parser *parser)
|
||||
if (t1 == NULL)
|
||||
{
|
||||
expr.value = error_mark_node;
|
||||
expr.original_code = ERROR_MARK;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -5284,7 +5307,6 @@ c_parser_postfix_expression (c_parser *parser)
|
||||
expr.value);
|
||||
C_MAYBE_CONST_EXPR_NON_CONST (expr.value) = true;
|
||||
}
|
||||
expr.original_code = ERROR_MARK;
|
||||
}
|
||||
break;
|
||||
case RID_OFFSETOF:
|
||||
@ -5292,21 +5314,18 @@ c_parser_postfix_expression (c_parser *parser)
|
||||
if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
|
||||
{
|
||||
expr.value = error_mark_node;
|
||||
expr.original_code = ERROR_MARK;
|
||||
break;
|
||||
}
|
||||
t1 = c_parser_type_name (parser);
|
||||
if (t1 == NULL)
|
||||
{
|
||||
expr.value = error_mark_node;
|
||||
expr.original_code = ERROR_MARK;
|
||||
break;
|
||||
}
|
||||
if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>"))
|
||||
{
|
||||
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
|
||||
expr.value = error_mark_node;
|
||||
expr.original_code = ERROR_MARK;
|
||||
break;
|
||||
}
|
||||
{
|
||||
@ -5371,7 +5390,6 @@ c_parser_postfix_expression (c_parser *parser)
|
||||
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
|
||||
"expected %<)%>");
|
||||
expr.value = fold_offsetof (offsetof_ref, NULL_TREE);
|
||||
expr.original_code = ERROR_MARK;
|
||||
}
|
||||
break;
|
||||
case RID_CHOOSE_EXPR:
|
||||
@ -5379,7 +5397,6 @@ c_parser_postfix_expression (c_parser *parser)
|
||||
if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
|
||||
{
|
||||
expr.value = error_mark_node;
|
||||
expr.original_code = ERROR_MARK;
|
||||
break;
|
||||
}
|
||||
loc = c_parser_peek_token (parser)->location;
|
||||
@ -5388,7 +5405,6 @@ c_parser_postfix_expression (c_parser *parser)
|
||||
{
|
||||
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
|
||||
expr.value = error_mark_node;
|
||||
expr.original_code = ERROR_MARK;
|
||||
break;
|
||||
}
|
||||
e2 = c_parser_expr_no_commas (parser, NULL);
|
||||
@ -5396,7 +5412,6 @@ c_parser_postfix_expression (c_parser *parser)
|
||||
{
|
||||
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
|
||||
expr.value = error_mark_node;
|
||||
expr.original_code = ERROR_MARK;
|
||||
break;
|
||||
}
|
||||
e3 = c_parser_expr_no_commas (parser, NULL);
|
||||
@ -5420,28 +5435,24 @@ c_parser_postfix_expression (c_parser *parser)
|
||||
if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
|
||||
{
|
||||
expr.value = error_mark_node;
|
||||
expr.original_code = ERROR_MARK;
|
||||
break;
|
||||
}
|
||||
t1 = c_parser_type_name (parser);
|
||||
if (t1 == NULL)
|
||||
{
|
||||
expr.value = error_mark_node;
|
||||
expr.original_code = ERROR_MARK;
|
||||
break;
|
||||
}
|
||||
if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>"))
|
||||
{
|
||||
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
|
||||
expr.value = error_mark_node;
|
||||
expr.original_code = ERROR_MARK;
|
||||
break;
|
||||
}
|
||||
t2 = c_parser_type_name (parser);
|
||||
if (t2 == NULL)
|
||||
{
|
||||
expr.value = error_mark_node;
|
||||
expr.original_code = ERROR_MARK;
|
||||
break;
|
||||
}
|
||||
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
|
||||
@ -5455,7 +5466,6 @@ c_parser_postfix_expression (c_parser *parser)
|
||||
expr.value = comptypes (e1, e2)
|
||||
? build_int_cst (NULL_TREE, 1)
|
||||
: build_int_cst (NULL_TREE, 0);
|
||||
expr.original_code = ERROR_MARK;
|
||||
}
|
||||
break;
|
||||
case RID_AT_SELECTOR:
|
||||
@ -5464,7 +5474,6 @@ c_parser_postfix_expression (c_parser *parser)
|
||||
if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
|
||||
{
|
||||
expr.value = error_mark_node;
|
||||
expr.original_code = ERROR_MARK;
|
||||
break;
|
||||
}
|
||||
{
|
||||
@ -5472,7 +5481,6 @@ c_parser_postfix_expression (c_parser *parser)
|
||||
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
|
||||
"expected %<)%>");
|
||||
expr.value = objc_build_selector_expr (sel);
|
||||
expr.original_code = ERROR_MARK;
|
||||
}
|
||||
break;
|
||||
case RID_AT_PROTOCOL:
|
||||
@ -5481,7 +5489,6 @@ c_parser_postfix_expression (c_parser *parser)
|
||||
if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
|
||||
{
|
||||
expr.value = error_mark_node;
|
||||
expr.original_code = ERROR_MARK;
|
||||
break;
|
||||
}
|
||||
if (c_parser_next_token_is_not (parser, CPP_NAME))
|
||||
@ -5489,7 +5496,6 @@ c_parser_postfix_expression (c_parser *parser)
|
||||
c_parser_error (parser, "expected identifier");
|
||||
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
|
||||
expr.value = error_mark_node;
|
||||
expr.original_code = ERROR_MARK;
|
||||
break;
|
||||
}
|
||||
{
|
||||
@ -5498,7 +5504,6 @@ c_parser_postfix_expression (c_parser *parser)
|
||||
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
|
||||
"expected %<)%>");
|
||||
expr.value = objc_build_protocol_expr (id);
|
||||
expr.original_code = ERROR_MARK;
|
||||
}
|
||||
break;
|
||||
case RID_AT_ENCODE:
|
||||
@ -5508,14 +5513,12 @@ c_parser_postfix_expression (c_parser *parser)
|
||||
if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
|
||||
{
|
||||
expr.value = error_mark_node;
|
||||
expr.original_code = ERROR_MARK;
|
||||
break;
|
||||
}
|
||||
t1 = c_parser_type_name (parser);
|
||||
if (t1 == NULL)
|
||||
{
|
||||
expr.value = error_mark_node;
|
||||
expr.original_code = ERROR_MARK;
|
||||
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
|
||||
break;
|
||||
}
|
||||
@ -5524,13 +5527,11 @@ c_parser_postfix_expression (c_parser *parser)
|
||||
{
|
||||
tree type = groktypename (t1, NULL, NULL);
|
||||
expr.value = objc_build_encode_expr (type);
|
||||
expr.original_code = ERROR_MARK;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
c_parser_error (parser, "expected expression");
|
||||
expr.value = error_mark_node;
|
||||
expr.original_code = ERROR_MARK;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
@ -5545,14 +5546,12 @@ c_parser_postfix_expression (c_parser *parser)
|
||||
"expected %<]%>");
|
||||
expr.value = objc_build_message_expr (build_tree_list (receiver,
|
||||
args));
|
||||
expr.original_code = ERROR_MARK;
|
||||
break;
|
||||
}
|
||||
/* Else fall through to report error. */
|
||||
default:
|
||||
c_parser_error (parser, "expected expression");
|
||||
expr.value = error_mark_node;
|
||||
expr.original_code = ERROR_MARK;
|
||||
break;
|
||||
}
|
||||
return c_parser_postfix_expression_after_primary (parser, expr);
|
||||
@ -5597,6 +5596,7 @@ c_parser_postfix_expression_after_paren_type (c_parser *parser,
|
||||
non_const |= !type_expr_const;
|
||||
expr.value = build_compound_literal (type, init.value, non_const);
|
||||
expr.original_code = ERROR_MARK;
|
||||
expr.original_type = NULL;
|
||||
if (type_expr)
|
||||
{
|
||||
if (TREE_CODE (expr.value) == C_MAYBE_CONST_EXPR)
|
||||
@ -5637,6 +5637,7 @@ c_parser_postfix_expression_after_primary (c_parser *parser,
|
||||
"expected %<]%>");
|
||||
expr.value = build_array_ref (expr.value, idx, loc);
|
||||
expr.original_code = ERROR_MARK;
|
||||
expr.original_type = NULL;
|
||||
break;
|
||||
case CPP_OPEN_PAREN:
|
||||
/* Function call. */
|
||||
@ -5655,6 +5656,7 @@ c_parser_postfix_expression_after_primary (c_parser *parser,
|
||||
&& DECL_BUILT_IN_CLASS (orig_expr.value) == BUILT_IN_NORMAL
|
||||
&& DECL_FUNCTION_CODE (orig_expr.value) == BUILT_IN_CONSTANT_P)
|
||||
expr.original_code = C_MAYBE_CONST_EXPR;
|
||||
expr.original_type = NULL;
|
||||
break;
|
||||
case CPP_DOT:
|
||||
/* Structure element reference. */
|
||||
@ -5667,11 +5669,23 @@ c_parser_postfix_expression_after_primary (c_parser *parser,
|
||||
c_parser_error (parser, "expected identifier");
|
||||
expr.value = error_mark_node;
|
||||
expr.original_code = ERROR_MARK;
|
||||
expr.original_type = NULL;
|
||||
return expr;
|
||||
}
|
||||
c_parser_consume_token (parser);
|
||||
expr.value = build_component_ref (expr.value, ident);
|
||||
expr.original_code = ERROR_MARK;
|
||||
if (TREE_CODE (expr.value) != COMPONENT_REF)
|
||||
expr.original_type = NULL;
|
||||
else
|
||||
{
|
||||
/* Remember the original type of a bitfield. */
|
||||
tree field = TREE_OPERAND (expr.value, 1);
|
||||
if (TREE_CODE (field) != FIELD_DECL)
|
||||
expr.original_type = NULL;
|
||||
else
|
||||
expr.original_type = DECL_BIT_FIELD_TYPE (field);
|
||||
}
|
||||
break;
|
||||
case CPP_DEREF:
|
||||
/* Structure element reference. */
|
||||
@ -5684,6 +5698,7 @@ c_parser_postfix_expression_after_primary (c_parser *parser,
|
||||
c_parser_error (parser, "expected identifier");
|
||||
expr.value = error_mark_node;
|
||||
expr.original_code = ERROR_MARK;
|
||||
expr.original_type = NULL;
|
||||
return expr;
|
||||
}
|
||||
c_parser_consume_token (parser);
|
||||
@ -5692,6 +5707,17 @@ c_parser_postfix_expression_after_primary (c_parser *parser,
|
||||
"->"),
|
||||
ident);
|
||||
expr.original_code = ERROR_MARK;
|
||||
if (TREE_CODE (expr.value) != COMPONENT_REF)
|
||||
expr.original_type = NULL;
|
||||
else
|
||||
{
|
||||
/* Remember the original type of a bitfield. */
|
||||
tree field = TREE_OPERAND (expr.value, 1);
|
||||
if (TREE_CODE (field) != FIELD_DECL)
|
||||
expr.original_type = NULL;
|
||||
else
|
||||
expr.original_type = DECL_BIT_FIELD_TYPE (field);
|
||||
}
|
||||
break;
|
||||
case CPP_PLUS_PLUS:
|
||||
/* Postincrement. */
|
||||
@ -5700,6 +5726,7 @@ c_parser_postfix_expression_after_primary (c_parser *parser,
|
||||
expr.value = build_unary_op (loc,
|
||||
POSTINCREMENT_EXPR, expr.value, 0);
|
||||
expr.original_code = ERROR_MARK;
|
||||
expr.original_type = NULL;
|
||||
break;
|
||||
case CPP_MINUS_MINUS:
|
||||
/* Postdecrement. */
|
||||
@ -5708,6 +5735,7 @@ c_parser_postfix_expression_after_primary (c_parser *parser,
|
||||
expr.value = build_unary_op (loc,
|
||||
POSTDECREMENT_EXPR, expr.value, 0);
|
||||
expr.original_code = ERROR_MARK;
|
||||
expr.original_type = NULL;
|
||||
break;
|
||||
default:
|
||||
return expr;
|
||||
@ -5735,6 +5763,7 @@ c_parser_expression (c_parser *parser)
|
||||
next = default_function_array_conversion (next);
|
||||
expr.value = build_compound_expr (expr.value, next.value);
|
||||
expr.original_code = COMPOUND_EXPR;
|
||||
expr.original_type = NULL;
|
||||
}
|
||||
return expr;
|
||||
}
|
||||
|
@ -163,6 +163,11 @@ struct c_expr
|
||||
initializers, or ERROR_MARK for other expressions (including
|
||||
parenthesized expressions). */
|
||||
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
|
||||
@ -577,7 +582,7 @@ extern struct c_expr default_function_array_conversion (struct c_expr);
|
||||
extern tree composite_type (tree, tree);
|
||||
extern tree build_component_ref (tree, tree);
|
||||
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 struct c_expr c_expr_sizeof_expr (struct c_expr);
|
||||
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)
|
||||
|
||||
/* Build an external reference to identifier ID. FUN indicates
|
||||
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
|
||||
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 decl = lookup_name (id);
|
||||
@ -2213,8 +2216,12 @@ build_external_ref (tree id, int fun, location_t loc)
|
||||
whatever lookup_name() found. */
|
||||
decl = objc_lookup_ivar (decl, id);
|
||||
|
||||
*type = NULL;
|
||||
if (decl && decl != error_mark_node)
|
||||
ref = decl;
|
||||
{
|
||||
ref = decl;
|
||||
*type = TREE_TYPE (ref);
|
||||
}
|
||||
else if (fun)
|
||||
/* Implicit function declaration. */
|
||||
ref = implicitly_declare (id);
|
||||
@ -2346,6 +2353,7 @@ c_expr_sizeof_expr (struct c_expr expr)
|
||||
{
|
||||
ret.value = error_mark_node;
|
||||
ret.original_code = ERROR_MARK;
|
||||
ret.original_type = NULL;
|
||||
pop_maybe_used (false);
|
||||
}
|
||||
else
|
||||
@ -2355,6 +2363,7 @@ c_expr_sizeof_expr (struct c_expr expr)
|
||||
&expr_const_operands);
|
||||
ret.value = c_sizeof (TREE_TYPE (folded_expr));
|
||||
ret.original_code = ERROR_MARK;
|
||||
ret.original_type = NULL;
|
||||
if (c_vla_type_p (TREE_TYPE (folded_expr)))
|
||||
{
|
||||
/* 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)
|
||||
type = groktypename (t, &type_expr, &type_expr_const);
|
||||
ret.value = c_sizeof (type);
|
||||
ret.original_code = ERROR_MARK;
|
||||
ret.original_type = NULL;
|
||||
if (type_expr && c_vla_type_p (type))
|
||||
{
|
||||
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)
|
||||
|
||||
result.value = build_unary_op (loc, code, arg.value, 0);
|
||||
result.original_code = code;
|
||||
|
||||
result.original_type = NULL;
|
||||
|
||||
if (TREE_OVERFLOW_P (result.value) && !TREE_OVERFLOW_P (arg.value))
|
||||
overflow_warning (result.value);
|
||||
|
||||
@ -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 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,
|
||||
arg1.value, arg2.value, 1);
|
||||
result.original_code = code;
|
||||
result.original_type = NULL;
|
||||
|
||||
if (TREE_CODE (result.value) == ERROR_MARK)
|
||||
return result;
|
||||
@ -2915,6 +2933,16 @@ parser_build_binary_op (location_t location, enum tree_code code,
|
||||
&& !TREE_OVERFLOW_P (arg2.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;
|
||||
}
|
||||
|
||||
@ -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)));
|
||||
expr.value = inside_init;
|
||||
expr.original_code = (strict_string ? STRING_CST : ERROR_MARK);
|
||||
expr.original_type = NULL;
|
||||
maybe_warn_string_init (type, expr);
|
||||
|
||||
if (comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (inside_init)),
|
||||
@ -5690,6 +5719,7 @@ really_start_incremental_init (tree type)
|
||||
p->depth = constructor_depth;
|
||||
p->replacement_value.value = 0;
|
||||
p->replacement_value.original_code = ERROR_MARK;
|
||||
p->replacement_value.original_type = NULL;
|
||||
p->implicit = 0;
|
||||
p->range_stack = 0;
|
||||
p->outer = 0;
|
||||
@ -5833,6 +5863,7 @@ push_init_level (int implicit)
|
||||
p->depth = constructor_depth;
|
||||
p->replacement_value.value = 0;
|
||||
p->replacement_value.original_code = ERROR_MARK;
|
||||
p->replacement_value.original_type = NULL;
|
||||
p->implicit = implicit;
|
||||
p->outer = 0;
|
||||
p->incremental = constructor_incremental;
|
||||
@ -5989,6 +6020,7 @@ pop_init_level (int implicit)
|
||||
struct c_expr ret;
|
||||
ret.value = 0;
|
||||
ret.original_code = ERROR_MARK;
|
||||
ret.original_type = NULL;
|
||||
|
||||
if (implicit == 0)
|
||||
{
|
||||
|
@ -204,7 +204,7 @@ C ObjC C++ ObjC++ Warning
|
||||
Warn about stray tokens after #elif and #endif
|
||||
|
||||
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
|
||||
|
||||
Werror
|
||||
|
@ -2758,6 +2758,7 @@ Options} and @ref{Objective-C and Objective-C++ Dialect Options}.
|
||||
-Warray-bounds @r{(only with} @option{-O2}@r{)} @gol
|
||||
-Wc++0x-compat @gol
|
||||
-Wchar-subscripts @gol
|
||||
-Wenum-compare @r{(in C/Objc; this is on by default in C++)} @gol
|
||||
-Wimplicit-int @gol
|
||||
-Wimplicit-function-declaration @gol
|
||||
-Wcomment @gol
|
||||
@ -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
|
||||
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 Wno-enum-compare
|
||||
Warn about a comparison between values of different enum types. This
|
||||
warning is enabled by default.
|
||||
Warn about a comparison between values of different enum types. In C++
|
||||
this warning is enabled by default. In C this warning is enabled by
|
||||
@option{-Wall}.
|
||||
|
||||
@item -Wsign-compare
|
||||
@opindex Wsign-compare
|
||||
|
@ -1,3 +1,7 @@
|
||||
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>
|
||||
|
||||
PR tree-optimization/39764
|
||||
|
33
gcc/testsuite/gcc.dg/Wenum-compare-1.c
Normal file
33
gcc/testsuite/gcc.dg/Wenum-compare-1.c
Normal file
@ -0,0 +1,33 @@
|
||||
/* { 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 ();
|
||||
}
|
Loading…
Reference in New Issue
Block a user