This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: In C, enum types may be unsigned, but enum constants may not


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

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]