re PR c/15224 (Attribute mode causes ICE when applied to enums)
authorRichard Kenner <kenner@gcc.gnu.org>
Wed, 1 Sep 2004 20:09:16 +0000 (16:09 -0400)
committerRichard Kenner <kenner@gcc.gnu.org>
Wed, 1 Sep 2004 20:09:16 +0000 (16:09 -0400)
PR c/15224
* c-common.c (handle_mode_attribute): Handle ENUMERAL_TYPE.
* c-decl.c (finish_enum): Check for user-specified precision too small.

From-SVN: r86926

gcc/c-common.c
gcc/c-decl.c

index a47385b2e059eacb61c719379f3330b64395ce7a..499829bd0e38c46670a4f1cae0dcd891601a16bc 100644 (file)
@@ -4351,11 +4351,29 @@ handle_mode_attribute (tree *node, tree name, tree args,
        }
       else
         typefm = lang_hooks.types.type_for_mode (mode, TYPE_UNSIGNED (type));
+
       if (typefm == NULL_TREE)
        {
          error ("no data type for mode %<%s%>", p);
          return NULL_TREE;
        }
+      else if (TREE_CODE (type) == ENUMERAL_TYPE)
+       {
+         /* For enumeral types, copy the precision from the integer
+            type returned above.  If not an INTEGER_TYPE, we can't use
+            this mode for this type.  */
+         if (TREE_CODE (typefm) != INTEGER_TYPE)
+           {
+             error ("cannot use mode '%s' for enumeral types",
+                    GET_MODE_NAME (mode));
+             return NULL_TREE;
+           }
+
+         if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
+           type = build_variant_type_copy (type);
+         TYPE_PRECISION (type) = TYPE_PRECISION (typefm);
+         typefm = type;
+       }
       *node = typefm;
 
       /* No need to layout the type here.  The caller should do this.  */
index a649c43fa13a152bec9c9f67145b6c7fc8657c3a..48f9813f22bb142cdf533df7d435ab3d4fd972e5 100644 (file)
@@ -5760,6 +5760,7 @@ finish_enum (tree enumtype, tree values, tree attributes)
   unsign = (tree_int_cst_sgn (minnode) >= 0);
   precision = MAX (min_precision (minnode, unsign),
                   min_precision (maxnode, unsign));
+
   if (TYPE_PACKED (enumtype) || precision > TYPE_PRECISION (integer_type_node))
     {
       tem = c_common_type_for_size (precision, unsign);
@@ -5774,9 +5775,19 @@ finish_enum (tree enumtype, tree values, tree attributes)
 
   TYPE_MIN_VALUE (enumtype) = TYPE_MIN_VALUE (tem);
   TYPE_MAX_VALUE (enumtype) = TYPE_MAX_VALUE (tem);
-  TYPE_PRECISION (enumtype) = TYPE_PRECISION (tem);
   TYPE_UNSIGNED (enumtype) = TYPE_UNSIGNED (tem);
   TYPE_SIZE (enumtype) = 0;
+
+  /* If the precision of the type was specific with an attribute and it
+     was too small, give an error.  Otherwise, use it.  */
+  if (TYPE_PRECISION (enumtype))
+    {
+      if (precision > TYPE_PRECISION (enumtype))
+       error ("specified mode too small for enumeral values");
+    }
+  else
+    TYPE_PRECISION (enumtype) = TYPE_PRECISION (tem);
+
   layout_type (enumtype);
 
   if (values != error_mark_node)