From ec8465a533a6effe46dd5d38fb7dbf387b49070c Mon Sep 17 00:00:00 2001 From: Richard Kenner Date: Wed, 1 Sep 2004 16:09:16 -0400 Subject: [PATCH] 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 --- gcc/c-common.c | 18 ++++++++++++++++++ gcc/c-decl.c | 13 ++++++++++++- 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/gcc/c-common.c b/gcc/c-common.c index a47385b2e05..499829bd0e3 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 a649c43fa13..48f9813f22b 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) -- 2.30.2