This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: In C, enum types may be unsigned, but enum constants may not
- To: gcc-patches at gcc dot gnu dot org
- Subject: Re: In C, enum types may be unsigned, but enum constants may not
- From: Alexandre Oliva <aoliva at redhat dot com>
- Date: 24 Jul 2000 14:47:20 -0300
- Organization: GCC Team, Red Hat
- References: <orem4p4ffm.fsf@guarana.lsd.ic.unicamp.br>
Here's a patch that fixes the test case. Full bootstrap and no
regressions on i686-pc-linux-gnu. Ok to install?
Index: gcc/testsuite/ChangeLog
from Alexandre Oliva <aoliva@redhat.com>
* gcc.c-torture/execute/enum-2.c: New test.
Index: gcc/testsuite/gcc.c-torture/execute/enum-2.c
===================================================================
RCS file: enum-2.c
diff -N enum-2.c
--- gcc/testsuite/gcc.c-torture/execute/enum-2.c Tue May 5 13:32:27 1998
+++ gcc/testsuite/gcc.c-torture/execute/enum-2.c Mon Jul 24 10:45:46 2000
@@ -0,0 +1,22 @@
+/* Copyright (C) 2000 Free Software Foundation */
+/* by Alexandre Oliva <aoliva@redhat.com> */
+
+enum foo { FOO, BAR };
+
+/* Even though the underlying type of an enum is unspecified, the type
+ of enumeration constants is explicitly defined as int (6.4.4.3/2 in
+ the C99 Standard). Therefore, `i' must not be promoted to
+ `unsigned' in the comparison below; we must exit the loop when it
+ becomes negative. */
+
+int
+main ()
+{
+ int i;
+ for (i = BAR; i >= FOO; --i)
+ if (i == -1)
+ abort ();
+
+ exit (0);
+}
+
Index: gcc/ChangeLog
from Alexandre Oliva <aoliva@redhat.com>
* c-decl.c (finish_enum): Convert enumerations that fit in an
`int' to `int'.
(build_enumerator): In pedantic mode, cast to `int' those that
don't.
Index: gcc/c-decl.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/c-decl.c,v
retrieving revision 1.132
diff -u -r1.132 c-decl.c
--- gcc/c-decl.c 2000/07/18 17:53:35 1.132
+++ gcc/c-decl.c 2000/07/24 17:46:03
@@ -5562,7 +5562,7 @@
tree attributes;
{
register tree pair, tem;
- tree minnode = 0, maxnode = 0;
+ tree minnode = 0, maxnode = 0, enum_value_type;
int precision, unsign;
int toplevel = (global_binding_level == current_binding_level);
@@ -5603,6 +5603,11 @@
precision = TYPE_PRECISION (long_long_integer_type_node);
}
+ if (precision == TYPE_PRECISION (integer_type_node))
+ enum_value_type = type_for_size (precision, 0);
+ else
+ enum_value_type = enumtype;
+
TYPE_MIN_VALUE (enumtype) = minnode;
TYPE_MAX_VALUE (enumtype) = maxnode;
TYPE_PRECISION (enumtype) = precision;
@@ -5629,7 +5634,18 @@
DECL_ALIGN (enu) = TYPE_ALIGN (enumtype);
DECL_USER_ALIGN (enu) = TYPE_USER_ALIGN (enumtype);
DECL_MODE (enu) = TYPE_MODE (enumtype);
- DECL_INITIAL (enu) = convert (enumtype, DECL_INITIAL (enu));
+
+ /* The ISO C Standard mandates enumerators to have type int,
+ even though the underlying type of an enum type is
+ unspecified. Here we convert any enumerators that fit in
+ an int to type int, to avoid promotions to unsigned types
+ when comparing integers with enumerators that fit in the
+ int range. When -pedantic is given, build_enumerator()
+ would have already taken care of those that don't fit. */
+ if (int_fits_type_p (DECL_INITIAL (enu), enum_value_type))
+ DECL_INITIAL (enu) = convert (enum_value_type, DECL_INITIAL (enu));
+ else
+ DECL_INITIAL (enu) = convert (enumtype, DECL_INITIAL (enu));
TREE_PURPOSE (pair) = DECL_NAME (enu);
TREE_VALUE (pair) = DECL_INITIAL (enu);
@@ -5706,7 +5722,7 @@
if (pedantic && ! int_fits_type_p (value, integer_type_node))
{
pedwarn ("ANSI C restricts enumerator values to range of `int'");
- value = integer_zero_node;
+ value = convert (integer_type_node, value);
}
/* Set basis for default for next value. */
--
Alexandre Oliva Enjoy Guarana', see http://www.ic.unicamp.br/~oliva/
Red Hat GCC Developer aoliva@{cygnus.com, redhat.com}
CS PhD student at IC-Unicamp oliva@{lsd.ic.unicamp.br, gnu.org}
Free Software Evangelist *Please* write to mailing lists, not to me