re PR c++/10796 (ICE (segfault) when defining an enum with two values: -1 and MAX_INT...
authorMark Mitchell <mark@codesourcery.com>
Fri, 27 Jun 2003 21:21:08 +0000 (21:21 +0000)
committerMark Mitchell <mmitchel@gcc.gnu.org>
Fri, 27 Jun 2003 21:21:08 +0000 (21:21 +0000)
PR c++/10796
* decl.c (finish_enum): Implement DR377.

* decl.c (cp_finish_decl): Don't make variables with reference
type readonly while they are being initialized.

PR c++/10796
* g++.dg/init/enum1.C: New test.

From-SVN: r68610

gcc/cp/ChangeLog
gcc/cp/decl.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/init/enum1.C [new file with mode: 0644]

index d0ecbdb..3e1fa5d 100644 (file)
@@ -1,3 +1,11 @@
+2003-06-27  Mark Mitchell  <mark@codesourcery.com>
+
+       PR c++/10796
+       * decl.c (finish_enum): Implement DR377.
+
+       * decl.c (cp_finish_decl): Don't make variables with reference
+       type readonly while they are being initialized.
+
 2003-06-26  Mark Mitchell  <mark@codesourcery.com>
 
        PR c++/11332
index b9c59af..66257c0 100644 (file)
@@ -8101,7 +8101,8 @@ cp_finish_decl (tree decl, tree init, tree asmspec_tree, int flags)
     ttype = target_type (type);
 
   if (! DECL_EXTERNAL (decl) && TREE_READONLY (decl)
-      && TYPE_NEEDS_CONSTRUCTING (type))
+      && (TYPE_NEEDS_CONSTRUCTING (type) 
+         || TREE_CODE (type) == REFERENCE_TYPE))
     {
       /* Currently, GNU C++ puts constants in text space, making them
         impossible to initialize.  In the future, one would hope for
@@ -13106,24 +13107,36 @@ finish_enum (tree enumtype)
   highprec = min_precision (maxnode, unsignedp);
   precision = MAX (lowprec, highprec);
 
-  /* Set TYPE_MIN_VALUE and TYPE_MAX_VALUE according to `precision'.  */
-  TYPE_SIZE (enumtype) = NULL_TREE;
+  /* DR 377
+       
+     IF no integral type can represent all the enumerator values, the
+     enumeration is ill-formed.  */
+  if (precision > TYPE_PRECISION (long_long_integer_type_node))
+    {
+      error ("no integral type can represent all of the enumerator values "
+            "for `%T'", enumtype);
+      precision = TYPE_PRECISION (long_long_integer_type_node);
+    }
+
+  /* Compute the minium and maximum values for the type, the size of
+     the type, and so forth.  */
   TYPE_PRECISION (enumtype) = precision;
+  TYPE_SIZE (enumtype) = NULL_TREE;
   if (unsignedp)
     fixup_unsigned_type (enumtype);
   else
     fixup_signed_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);
+  /* 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);
+    }
 
   /* Fix up all variant types of this enum type.  */
   for (t = TYPE_MAIN_VARIANT (enumtype); t; t = TYPE_NEXT_VARIANT (t))
index 930031b..b407402 100644 (file)
@@ -1,3 +1,8 @@
+2003-06-27  Mark Mitchell  <mark@codesourcery.com>
+
+       PR c++/10796
+       * g++.dg/init/enum1.C: New test.
+
 2003-06-27  Ulrich Weigand  <uweigand@de.ibm.com>
 
        * gcc.dg/20030627-1.c: New test.
diff --git a/gcc/testsuite/g++.dg/init/enum1.C b/gcc/testsuite/g++.dg/init/enum1.C
new file mode 100644 (file)
index 0000000..f74a5ad
--- /dev/null
@@ -0,0 +1,10 @@
+enum test {
+  acceptable = -1,
+  unacceptable = 0xffffffffffffffffLL
+}; // { dg-error "" }
+
+enum test t = acceptable, u = unacceptable;
+
+int main() {
+    return 0;
+}