re PR c/15236 (pedantic switch modifies treatment of non-ISO compliant enumerations)

2008-08-13  Manuel Lopez-Ibanez  <manu@gcc.gnu.org>

	PR c/15236
	* diagnostic.c (pedwarn_at): New.
	* toplev.h (pedwarn_at): Declare.
	* c-tree.h (build_enumerator): Update declaration.
	* c-decl.c (finish_enum): Update comment.
	(build_enumerator): Take a location parameter. Give a pedwarn but do
	not perform any conversion.
	* c-parser.c (c_parser_enum_specifier): Set correct location for
	enumerator.
testsuite/
	* gcc.dg/pr15236.c: New.
	* gcc.dg/torture/pr25183.c: Update.

From-SVN: r139050
parent 374035cb
2008-08-13 Manuel Lopez-Ibanez <manu@gcc.gnu.org> 2008-08-13 Manuel Lopez-Ibanez <manu@gcc.gnu.org>
PR c/15236
* diagnostic.c (pedwarn_at): New.
* toplev.h (pedwarn_at): Declare.
* c-tree.h (build_enumerator): Update declaration.
* c-decl.c (finish_enum): Update comment.
(build_enumerator): Take a location parameter. Give a pedwarn but do
not perform any conversion.
* c-parser.c (c_parser_enum_specifier): Set correct location for
enumerator.
2008-08-13 Manuel Lopez-Ibanez <manu@gcc.gnu.org>
PR 35635 PR 35635
* c-common.c (conversion_warning): Use a switch. Ignore boolean * c-common.c (conversion_warning): Use a switch. Ignore boolean
expressions except for conversions to signed:1 bitfields. Handle expressions except for conversions to signed:1 bitfields. Handle
......
...@@ -5877,11 +5877,13 @@ finish_enum (tree enumtype, tree values, tree attributes) ...@@ -5877,11 +5877,13 @@ finish_enum (tree enumtype, tree values, tree attributes)
/* The ISO C Standard mandates enumerators to have type int, /* The ISO C Standard mandates enumerators to have type int,
even though the underlying type of an enum type is even though the underlying type of an enum type is
unspecified. Here we convert any enumerators that fit in unspecified. However, GCC allows enumerators of any
an int to type int, to avoid promotions to unsigned types integer type as an extensions. Here we convert any
when comparing integers with enumerators that fit in the enumerators that fit in an int to type int, to avoid
int range. When -pedantic is given, build_enumerator() promotions to unsigned types when comparing integers with
would have already taken care of those that don't fit. */ enumerators that fit in the int range. When -pedantic is
given, build_enumerator() would have already warned about
those that don't fit. */
if (int_fits_type_p (ini, integer_type_node)) if (int_fits_type_p (ini, integer_type_node))
tem = integer_type_node; tem = integer_type_node;
else else
...@@ -5933,7 +5935,8 @@ finish_enum (tree enumtype, tree values, tree attributes) ...@@ -5933,7 +5935,8 @@ finish_enum (tree enumtype, tree values, tree attributes)
Assignment of sequential values by default is handled here. */ Assignment of sequential values by default is handled here. */
tree tree
build_enumerator (struct c_enum_contents *the_enum, tree name, tree value) build_enumerator (struct c_enum_contents *the_enum, tree name, tree value,
location_t value_loc)
{ {
tree decl, type; tree decl, type;
...@@ -5967,14 +5970,13 @@ build_enumerator (struct c_enum_contents *the_enum, tree name, tree value) ...@@ -5967,14 +5970,13 @@ build_enumerator (struct c_enum_contents *the_enum, tree name, tree value)
if (the_enum->enum_overflow) if (the_enum->enum_overflow)
error ("overflow in enumeration values"); error ("overflow in enumeration values");
} }
/* Even though the underlying type of an enum is unspecified, the
if (pedantic && !int_fits_type_p (value, integer_type_node)) type of enumeration constants is explicitly defined as int
{ (6.4.4.3/2 in the C99 Standard). GCC allows any integer type as
pedwarn (OPT_pedantic, "ISO C restricts enumerator values to range of %<int%>"); an extension. */
/* XXX This causes -pedantic to change the meaning of the program. else if (!int_fits_type_p (value, integer_type_node))
Remove? -zw 2004-03-15 */ pedwarn_at (value_loc, OPT_pedantic,
value = convert (integer_type_node, value); "ISO C restricts enumerator values to range of %<int%>");
}
/* Set basis for default for next value. */ /* Set basis for default for next value. */
the_enum->enum_next_value = build_binary_op (PLUS_EXPR, value, the_enum->enum_next_value = build_binary_op (PLUS_EXPR, value,
......
...@@ -1630,6 +1630,7 @@ c_parser_enum_specifier (c_parser *parser) ...@@ -1630,6 +1630,7 @@ c_parser_enum_specifier (c_parser *parser)
bool seen_comma; bool seen_comma;
c_token *token; c_token *token;
location_t comma_loc; location_t comma_loc;
location_t value_loc;
if (c_parser_next_token_is_not (parser, CPP_NAME)) if (c_parser_next_token_is_not (parser, CPP_NAME))
{ {
c_parser_error (parser, "expected identifier"); c_parser_error (parser, "expected identifier");
...@@ -1641,15 +1642,19 @@ c_parser_enum_specifier (c_parser *parser) ...@@ -1641,15 +1642,19 @@ c_parser_enum_specifier (c_parser *parser)
enum_id = token->value; enum_id = token->value;
/* Set the location in case we create a decl now. */ /* Set the location in case we create a decl now. */
c_parser_set_source_position_from_token (token); c_parser_set_source_position_from_token (token);
value_loc = token->location;
c_parser_consume_token (parser); c_parser_consume_token (parser);
if (c_parser_next_token_is (parser, CPP_EQ)) if (c_parser_next_token_is (parser, CPP_EQ))
{ {
c_parser_consume_token (parser); c_parser_consume_token (parser);
value_loc = c_parser_peek_token (parser)->location;
/* This may call cb_line_change and alter the input_location. */
enum_value = c_parser_expr_no_commas (parser, NULL).value; enum_value = c_parser_expr_no_commas (parser, NULL).value;
} }
else else
enum_value = NULL_TREE; enum_value = NULL_TREE;
enum_decl = build_enumerator (&the_enum, enum_id, enum_value); enum_decl = build_enumerator (&the_enum, enum_id, enum_value,
value_loc);
TREE_CHAIN (enum_decl) = values; TREE_CHAIN (enum_decl) = values;
values = enum_decl; values = enum_decl;
seen_comma = false; seen_comma = false;
......
...@@ -462,7 +462,7 @@ extern void c_print_identifier (FILE *, tree, int); ...@@ -462,7 +462,7 @@ extern void c_print_identifier (FILE *, tree, int);
extern int quals_from_declspecs (const struct c_declspecs *); extern int quals_from_declspecs (const struct c_declspecs *);
extern struct c_declarator *build_array_declarator (tree, struct c_declspecs *, extern struct c_declarator *build_array_declarator (tree, struct c_declspecs *,
bool, bool); bool, bool);
extern tree build_enumerator (struct c_enum_contents *, tree, tree); extern tree build_enumerator (struct c_enum_contents *, tree, tree, location_t);
extern tree check_for_loop_decls (void); extern tree check_for_loop_decls (void);
extern void mark_forward_parm_decls (void); extern void mark_forward_parm_decls (void);
extern void declare_parm_level (void); extern void declare_parm_level (void);
......
...@@ -537,10 +537,10 @@ warning_at (location_t location, int opt, const char *gmsgid, ...) ...@@ -537,10 +537,10 @@ warning_at (location_t location, int opt, const char *gmsgid, ...)
return report_diagnostic (&diagnostic); return report_diagnostic (&diagnostic);
} }
/* A "pedantic" warning: issues a warning unless -pedantic-errors was /* A "pedantic" warning at LOCATION: issues a warning unless
given on the command line, in which case it issues an error. Use -pedantic-errors was given on the command line, in which case it
this for diagnostics required by the relevant language standard, issues an error. Use this for diagnostics required by the relevant
if you have chosen not to make them errors. language standard, if you have chosen not to make them errors.
Note that these diagnostics are issued independent of the setting Note that these diagnostics are issued independent of the setting
of the -pedantic command-line switch. To get a warning enabled of the -pedantic command-line switch. To get a warning enabled
...@@ -551,6 +551,21 @@ warning_at (location_t location, int opt, const char *gmsgid, ...) ...@@ -551,6 +551,21 @@ warning_at (location_t location, int opt, const char *gmsgid, ...)
Returns true if the warning was printed, false if it was inhibited. */ Returns true if the warning was printed, false if it was inhibited. */
bool bool
pedwarn_at (location_t location, int opt, const char *gmsgid, ...)
{
diagnostic_info diagnostic;
va_list ap;
va_start (ap, gmsgid);
diagnostic_set_info (&diagnostic, gmsgid, &ap, location, DK_PEDWARN);
diagnostic.option_index = opt;
va_end (ap);
return report_diagnostic (&diagnostic);
}
/* Equivalent to pedwarn_at using INPUT_LOCATION. */
bool
pedwarn (int opt, const char *gmsgid, ...) pedwarn (int opt, const char *gmsgid, ...)
{ {
diagnostic_info diagnostic; diagnostic_info diagnostic;
......
2008-08-13 Manuel Lopez-Ibanez <manu@gcc.gnu.org> 2008-08-13 Manuel Lopez-Ibanez <manu@gcc.gnu.org>
PR c/15236
* gcc.dg/pr15236.c: New.
* gcc.dg/torture/pr25183.c: Update.
2008-08-13 Manuel Lopez-Ibanez <manu@gcc.gnu.org>
PR 35635 PR 35635
* gcc.dg/pr35635.c: New. * gcc.dg/pr35635.c: New.
* gcc.dg/Wconversion-integer.c: Update. * gcc.dg/Wconversion-integer.c: Update.
......
/* PR 15236: pedantic switch modifies treatment of non-ISO compliant
enumerations. */
/* { dg-do compile } */
/* { dg-options "-Wall -Wextra -pedantic-errors -Wconversion" } */
typedef enum OMX_ERRORTYPE
{
OMX_ErrorNone = 0,
OMX_ErrorInsufficientResources = 0x80001000 /* { dg-error "ISO C restricts enumerator values to range of .int." } */
} OMX_ERRORTYPE;
...@@ -12,11 +12,11 @@ static enum err E_; ...@@ -12,11 +12,11 @@ static enum err E_;
int error() int error()
{ {
switch (E_) { switch (E_) {
case err_IO : break; /* { dg-warning "overflow" } */ case err_IO : break;
case err_NM : break; /* { dg-warning "overflow" } */ case err_NM : break;
case err_EOF : break; /* { dg-warning "overflow" } */ case err_EOF : break;
case err_SE : break; /* { dg-warning "overflow" } */ case err_SE : break;
case err_PT : break; /* { dg-warning "overflow" } */ case err_PT : break;
default : return 0; default : return 0;
} }
} }
...@@ -65,6 +65,7 @@ extern void fatal_error (const char *, ...) ATTRIBUTE_GCC_DIAG(1,2) ...@@ -65,6 +65,7 @@ extern void fatal_error (const char *, ...) ATTRIBUTE_GCC_DIAG(1,2)
ATTRIBUTE_NORETURN; ATTRIBUTE_NORETURN;
/* Pass one of the OPT_W* from options.h as the first parameter. */ /* Pass one of the OPT_W* from options.h as the first parameter. */
extern bool pedwarn (int, const char *, ...) ATTRIBUTE_GCC_DIAG(2,3); extern bool pedwarn (int, const char *, ...) ATTRIBUTE_GCC_DIAG(2,3);
extern bool pedwarn_at (location_t, int, const char *, ...)
extern bool permerror (const char *, ...) ATTRIBUTE_GCC_DIAG(1,2); extern bool permerror (const char *, ...) ATTRIBUTE_GCC_DIAG(1,2);
extern bool permerror_at (location_t, const char *, ...) extern bool permerror_at (location_t, const char *, ...)
ATTRIBUTE_GCC_DIAG(2,3); ATTRIBUTE_GCC_DIAG(2,3);
......
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