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]

wider-than-int enums broken in C++


Mark,

Your patch for PR 10796, that implemented C++ DR377, also contained a
code clean-up that was actually wrong.  The underlying type of an enum
must be an integral type, but, after your patch, we end up with a type
whose precision is given by the min and max values of the enumeration,
that doesn't necessarily match the precision of any of the integral
types.

Richard Sandiford found out we were miscompiling libstdc++ because of
this, and I turned the code snippet he extracted from libstdc++ into
the attached testcase.  Richard also analyzed the problem in detail,
but it turned out that he didn't know for sure what had been decided
for DR377, so I ended up taking the issue over and found out the exact
bits of Mark's patch that introduced the problem but didn't contribute
to the implementation of the DR or the fix to the PR.

Tested on i686-pc-linux-gnu.  Ok to install?  Ok for 3.3?

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

	PR c++/10796
	* decl.c (finish_enum): Make sure the underlying integer type has
	the same precision as some full integer type.  Reverts part
	2003-06-27's patch that didn't play any role in fixing the PR.

Index: gcc/cp/decl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/decl.c,v
retrieving revision 1.1096
diff -u -p -r1.1096 decl.c
--- gcc/cp/decl.c 22 Jul 2003 23:30:14 -0000 1.1096
+++ gcc/cp/decl.c 24 Jul 2003 02:39:48 -0000
@@ -13140,16 +13140,16 @@ finish_enum (tree enumtype)
   else
     fixup_signed_type (enumtype);
 
-  /* We use "int" or "unsigned int" as the underlying type, unless all
-     the values will not fit or the user has requested that we try to
-     use shorter types where possible.  */
-  if (precision < TYPE_PRECISION (integer_type_node)
-      && !flag_short_enums)
-    {
-      TYPE_PRECISION (enumtype) = TYPE_PRECISION (integer_type_node);
-      TYPE_SIZE (enumtype) = NULL_TREE;
-      layout_type (enumtype);
-    }
+  if (flag_short_enums || (precision > TYPE_PRECISION (integer_type_node)))
+    /* Use the width of the narrowest normal C type which is wide
+       enough.  */
+    TYPE_PRECISION (enumtype) = TYPE_PRECISION (c_common_type_for_size
+						(precision, 1));
+  else
+    TYPE_PRECISION (enumtype) = TYPE_PRECISION (integer_type_node);
+
+  TYPE_SIZE (enumtype) = NULL_TREE;
+  layout_type (enumtype);
 
   /* Fix up all variant types of this enum type.  */
   for (t = TYPE_MAIN_VARIANT (enumtype); t; t = TYPE_NEXT_VARIANT (t))
Index: gcc/testsuite/ChangeLog
from  Alexandre Oliva  <aoliva@redhat.com>

	* g++.dg/init/enum2.C: New.

Index: gcc/testsuite/g++.dg/init/enum2.C
===================================================================
RCS file: gcc/testsuite/g++.dg/init/enum2.C
diff -N gcc/testsuite/g++.dg/init/enum2.C
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gcc/testsuite/g++.dg/init/enum2.C 24 Jul 2003 02:39:57 -0000
@@ -0,0 +1,8 @@
+#include <limits.h>
+enum test {
+  z = 0,
+  c = UINT_MAX + 1LL
+} x = z;
+int main() {
+  return x != z;
+}
-- 
Alexandre Oliva   Enjoy Guarana', see http://www.ic.unicamp.br/~oliva/
Red Hat GCC Developer                 aoliva@{redhat.com, gcc.gnu.org}
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]