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]

underlying type of C++ enums


The underlying type we choose for the following enum is `int', not
`unsigned [long] long' as one might expect from the Standard C++
requirements.  (Note that the rules for Standard C are different)

 enum foo
 {
    foo1   = 0,
    foo2   = 0xffffffffffffffffULL,
    foo3   = 0xf0fffffffffffffeULL,
 };

The problem is that, when we look for the min and max enumerators, we
use tree_int_cst_lt, that assumes both operands have the same value
for the UNSIGNED flag.  In the case of enum initializers, this
assumption does not hold.

This patch fixes the problem.

I recommend this patch to be considered for GCC 3.1, since it has ABI
affects (it would change sizeof foo from sizeof int to sizeof long
long).

Ok to install?

Index: gcc/cp/ChangeLog
from  Alexandre Oliva  <aoliva@redhat.com>

	* decl.c (finish_enum): Take the sign of each enumerator into
	account when looking for the minimum and maximum values.

Index: gcc/cp/decl.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/decl.c,v
retrieving revision 1.902
diff -u -p -r1.902 decl.c
--- gcc/cp/decl.c 24 Apr 2002 20:41:01 -0000 1.902
+++ gcc/cp/decl.c 25 Apr 2002 22:01:09 -0000
@@ -13210,7 +13210,9 @@ finish_enum (enumtype)
 {
   tree pair;
   tree minnode;
+  int minnode_sgn;
   tree maxnode;
+  int maxnode_sgn;
   tree t;
   bool unsignedp;
   int lowprec;
@@ -13242,35 +13244,57 @@ finish_enum (enumtype)
     }
 
   /* Figure out what the minimum and maximum values of the enumerators
-     are.  */
+     are.  We have to take the sign of each constant into account when
+     comparing with minnode and maxnode, because tree_int_cst_lt
+     assumes both operands have the same value for the UNSIGNED
+     flag.  */
   if (TYPE_VALUES (enumtype))
     {
       minnode = maxnode = NULL_TREE;
+      minnode_sgn = maxnode_sgn = 0;
 
       for (pair = TYPE_VALUES (enumtype);
 	   pair;
 	   pair = TREE_CHAIN (pair))
 	{
 	  tree value;
+	  int value_sgn;
 
 	  value = DECL_INITIAL (TREE_VALUE (pair));
+	  value_sgn = tree_int_cst_sgn (value);
 
 	  if (!minnode)
-	    minnode = maxnode = value;
-	  else if (tree_int_cst_lt (maxnode, value))
-	    maxnode = value;
-	  else if (tree_int_cst_lt (value, minnode))
-	    minnode = value;
+	    {
+	      minnode = maxnode = value;
+	      minnode_sgn = maxnode_sgn = value_sgn;
+	    }
+	  else if (maxnode_sgn < value_sgn
+		   || (maxnode_sgn == value_sgn
+		       && tree_int_cst_lt (maxnode, value)))
+	    {
+	      maxnode = value;
+	      maxnode_sgn = value_sgn;
+	    }
+	  else if (value_sgn < minnode_sgn
+		   || (value_sgn == minnode_sgn
+		       && tree_int_cst_lt (value, minnode)))
+	    {
+	      minnode = value;
+	      minnode_sgn = value_sgn;
+	    }
 	}
     }
   else
-    minnode = maxnode = integer_zero_node;
+    {
+      minnode = maxnode = integer_zero_node;
+      minnode_sgn = maxnode_sgn = 0;
+    }
 
   /* Compute the number of bits require to represent all values of the
      enumeration.  We must do this before the type of MINNODE and
      MAXNODE are transformed, since min_precision relies on the
      TREE_TYPE of the value it is passed.  */
-  unsignedp = tree_int_cst_sgn (minnode) >= 0;
+  unsignedp = minnode_sgn >= 0;
   lowprec = min_precision (minnode, unsignedp);
   highprec = min_precision (maxnode, unsignedp);
   precision = MAX (lowprec, highprec);

-- 
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                Professional serial bug killer

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