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]
Other format: [Raw text]

PR c/30260 Enumeration types and enumeration constants erroneously given unsigned types


Second try addressing Joseph comments.

Bootstrapped and regression tested on x86_64-unknown-linux-gnu with
--enable-languages=all,ada with --target_board=\{-m32,-m64\}

OK for trunk?

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

	PR c/30260
	* c-decl.c (finish_enum): Convert non-integer enumerators to enum
	type.
	(build_enumerator): Convert enumerators that fit in integer to
	integer type.
testsuite/
	* gcc.dg/pr30260.c: New.
Index: gcc/testsuite/gcc.dg/pr30260.c
===================================================================
--- gcc/testsuite/gcc.dg/pr30260.c	(revision 0)
+++ gcc/testsuite/gcc.dg/pr30260.c	(revision 0)
@@ -0,0 +1,32 @@
+/* PR 30260  */
+/* { dg-do link } */
+/* { dg-options "-pedantic -O" } */
+#include <limits.h>
+
+enum A {
+  A1 = 0, 
+  A2 = A1 - 1
+};
+enum B {
+  B1 = 0u, 
+  B2 = B1 - 1 /* { dg-bogus "ISO C restricts enumerator values to range of 'int'" } */
+};
+int main(void)
+{
+  enum A a = -1;
+  enum B b = -1;
+
+  if (!(a < 0))
+    link_error ();
+  if (!(A2 < 0))
+    link_error ();
+  if (!(b < 0))
+    link_error ();
+  if (!(B2 < 0))
+    link_error ();
+
+  return 0;
+}
+
+enum E1 { e10 = INT_MAX, e11 }; /* { dg-error "overflow in enumeration values" } */
+enum E2 { e20 = (unsigned) INT_MAX, e21 }; /* { dg-error "overflow in enumeration values" } */
Index: gcc/c-decl.c
===================================================================
--- gcc/c-decl.c	(revision 139749)
+++ gcc/c-decl.c	(working copy)
@@ -5899,21 +5899,19 @@ finish_enum (tree enumtype, tree values,
 	  TREE_TYPE (enu) = enumtype;
 
 	  /* The ISO C Standard mandates enumerators to have type int,
 	     even though the underlying type of an enum type is
 	     unspecified.  However, GCC allows enumerators of any
-	     integer type as an extensions.  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 warned about
-	     those that don't fit.  */
-	  if (int_fits_type_p (ini, integer_type_node))
-	    tem = integer_type_node;
-	  else
-	    tem = enumtype;
-	  ini = convert (tem, ini);
+	     integer type as an extensions.  build_enumerator()
+	     converts 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 warned about those that don't fit. Here we
+	     convert the rest to the enumerator type. */
+	  if (TREE_TYPE (ini) != integer_type_node)
+	    ini = convert (enumtype, ini);
 
 	  DECL_INITIAL (enu) = ini;
 	  TREE_PURPOSE (pair) = DECL_NAME (enu);
 	  TREE_VALUE (pair) = ini;
 	}
@@ -5999,10 +5997,22 @@ build_enumerator (struct c_enum_contents
      an extension.  */
   else if (!int_fits_type_p (value, integer_type_node))
     pedwarn (value_loc, OPT_pedantic, 
 	     "ISO C restricts enumerator values to range of %<int%>");
 
+  /* The ISO C Standard mandates enumerators to have type int, even
+     though the underlying type of an enum type is unspecified.
+     However, GCC allows enumerators of any integer type as an
+     extensions.  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, we would have already warned about those that
+     don't fit. We have to do this here rather than in finish_enum
+     because this value may be used to define more enumerators.  */
+  if (int_fits_type_p (value, integer_type_node))
+    value = convert (integer_type_node, value);
+
   /* Set basis for default for next value.  */
   the_enum->enum_next_value = build_binary_op (PLUS_EXPR, value,
 					       integer_one_node, 0);
   the_enum->enum_overflow = tree_int_cst_lt (the_enum->enum_next_value, value);
 

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