aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorRichard Kenner <kenner@gcc.gnu.org>2004-09-01 16:09:16 -0400
committerRichard Kenner <kenner@gcc.gnu.org>2004-09-01 16:09:16 -0400
commitec8465a533a6effe46dd5d38fb7dbf387b49070c (patch)
treebdb6b395dfaadacd9548f86bc3c6b1b0d26c4d91 /gcc
parent938e234bf9b4cccdf687338243b690938c0aa795 (diff)
downloadgcc-ec8465a533a6effe46dd5d38fb7dbf387b49070c.zip
gcc-ec8465a533a6effe46dd5d38fb7dbf387b49070c.tar.gz
gcc-ec8465a533a6effe46dd5d38fb7dbf387b49070c.tar.bz2
re PR c/15224 (Attribute mode causes ICE when applied to enums)
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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/c-common.c18
-rw-r--r--gcc/c-decl.c13
2 files changed, 30 insertions, 1 deletions
diff --git a/gcc/c-common.c b/gcc/c-common.c
index a47385b..499829b 100644
--- a/gcc/c-common.c
+++ b/gcc/c-common.c
@@ -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. */
diff --git a/gcc/c-decl.c b/gcc/c-decl.c
index a649c43..48f9813 100644
--- a/gcc/c-decl.c
+++ b/gcc/c-decl.c
@@ -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)