This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
wider-than-int enums broken in C++
- From: Alexandre Oliva <aoliva at redhat dot com>
- To: mark at codesourcery dot com
- Cc: rsandifo at redhat dot com, gcc-patches at gcc dot gnu dot org
- Date: 23 Jul 2003 23:50:15 -0300
- Subject: wider-than-int enums broken in C++
- Organization: GCC Team, Red Hat
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