diff options
author | Zack Weinberg <zack@rabi.columbia.edu> | 2000-01-05 19:26:23 +0000 |
---|---|---|
committer | Zack Weinberg <zack@gcc.gnu.org> | 2000-01-05 19:26:23 +0000 |
commit | cb3ca04ee18428f3c08b36f97ee0184449bcb6c6 (patch) | |
tree | 2f5f1a4333cfc525d0e30c2fc974ac8bf2621783 /gcc/c-decl.c | |
parent | 28b487d7fe96ff2475bd8de4f86d9bc3da040e85 (diff) | |
download | gcc-cb3ca04ee18428f3c08b36f97ee0184449bcb6c6.zip gcc-cb3ca04ee18428f3c08b36f97ee0184449bcb6c6.tar.gz gcc-cb3ca04ee18428f3c08b36f97ee0184449bcb6c6.tar.bz2 |
c-decl.c (finish_enum): Simplify code to determine minimum and maximum values of the enum...
2000-01-05 11:25 -0800 Zack Weinberg <zack@rabi.columbia.edu>
* c-decl.c (finish_enum): Simplify code to determine minimum and
maximum values of the enum, and calculate the type. Remove check
for FUNCTION_DECLs in the values list, which cannot happen. Replace
the DECL_INITIAL of each enumeration constant with a copy converted
to the enumeration type. When updating variant types, don't bother
updating the type itself.
* c-typeck.c (build_binary_op): Simplify conditional expressions
when weeding out spurious signed-unsigned warnings. Add new
spurious warning category: if the unsigned quantity is an enum
and its maximum value fits in signed_type(result_type). Update
commentary.
(build_conditional_expr): Warn here if one alternative is signed
and the other is unsigned.
From-SVN: r31244
Diffstat (limited to 'gcc/c-decl.c')
-rw-r--r-- | gcc/c-decl.c | 95 |
1 files changed, 46 insertions, 49 deletions
diff --git a/gcc/c-decl.c b/gcc/c-decl.c index 2eba0e4..850ac6d 100644 --- a/gcc/c-decl.c +++ b/gcc/c-decl.c @@ -5664,8 +5664,8 @@ finish_enum (enumtype, values, attributes) { register tree pair, tem; tree minnode = 0, maxnode = 0; - int lowprec, highprec, precision; - int toplevel = global_binding_level == current_binding_level; + int precision, unsign; + int toplevel = (global_binding_level == current_binding_level); if (in_parm_level_p ()) warning ("enum defined inside parms"); @@ -5677,67 +5677,62 @@ finish_enum (enumtype, values, attributes) if (values == error_mark_node) minnode = maxnode = integer_zero_node; else - for (pair = values; pair; pair = TREE_CHAIN (pair)) - { - tree value = TREE_VALUE (pair); - if (pair == values) - minnode = maxnode = TREE_VALUE (pair); - else - { - if (tree_int_cst_lt (maxnode, value)) - maxnode = value; - if (tree_int_cst_lt (value, minnode)) - minnode = value; - } - } - - TYPE_MIN_VALUE (enumtype) = minnode; - TYPE_MAX_VALUE (enumtype) = maxnode; - - /* An enum can have some negative values; then it is signed. */ - TREE_UNSIGNED (enumtype) = tree_int_cst_sgn (minnode) >= 0; - - /* Determine the precision this type needs. */ - - lowprec = min_precision (minnode, TREE_UNSIGNED (enumtype)); - highprec = min_precision (maxnode, TREE_UNSIGNED (enumtype)); - precision = MAX (lowprec, highprec); - - if (TYPE_PACKED (enumtype) || precision > TYPE_PRECISION (integer_type_node)) { - tree narrowest = type_for_size (precision, 1); - if (narrowest == 0) + minnode = maxnode = TREE_VALUE (values); + for (pair = TREE_CHAIN (values); pair; pair = TREE_CHAIN (pair)) { - warning ("enumeration values exceed range of largest integer"); - narrowest = long_long_integer_type_node; + tree value = TREE_VALUE (pair); + if (tree_int_cst_lt (maxnode, value)) + maxnode = value; + if (tree_int_cst_lt (value, minnode)) + minnode = value; } + } - TYPE_PRECISION (enumtype) = TYPE_PRECISION (narrowest); + /* Construct the final type of this enumeration. It is the same + as one of the integral types - the narrowest one that fits, except + that normally we only go as narrow as int - and signed iff any of + the values are negative. */ + unsign = (tree_int_cst_sgn (minnode) >= 0); + precision = MAX (min_precision (minnode, unsign), + min_precision (maxnode, unsign)); + if (!TYPE_PACKED (enumtype)) + precision = MAX (precision, TYPE_PRECISION (integer_type_node)); + if (type_for_size (precision, unsign) == 0) + { + warning ("enumeration values exceed range of largest integer"); + precision = TYPE_PRECISION (long_long_integer_type_node); } - else - TYPE_PRECISION (enumtype) = TYPE_PRECISION (integer_type_node); + TYPE_MIN_VALUE (enumtype) = minnode; + TYPE_MAX_VALUE (enumtype) = maxnode; + TYPE_PRECISION (enumtype) = precision; + TREE_UNSIGNED (enumtype) = unsign; TYPE_SIZE (enumtype) = 0; layout_type (enumtype); if (values != error_mark_node) { - /* Change the type of the enumerators to be the enum type. - Formerly this was done only for enums that fit in an int, - but the comment said it was done only for enums wider than int. - It seems necessary to do this for wide enums, - and best not to change what's done for ordinary narrower ones. */ + /* Change the type of the enumerators to be the enum type. We + need to do this irrespective of the size of the enum, for + proper type checking. Replace the DECL_INITIALs of the + enumerators, and the value slots of the list, with copies + that have the enum type; they cannot be modified in place + because they may be shared (e.g. integer_zero_node) Finally, + change the purpose slots to point to the names of the decls. */ for (pair = values; pair; pair = TREE_CHAIN (pair)) { - TREE_TYPE (TREE_PURPOSE (pair)) = enumtype; - DECL_SIZE (TREE_PURPOSE (pair)) = TYPE_SIZE (enumtype); - if (TREE_CODE (TREE_PURPOSE (pair)) != FUNCTION_DECL) - DECL_ALIGN (TREE_PURPOSE (pair)) = TYPE_ALIGN (enumtype); - } + tree enu = TREE_PURPOSE (pair); - /* Replace the decl nodes in VALUES with their names. */ - for (pair = values; pair; pair = TREE_CHAIN (pair)) - TREE_PURPOSE (pair) = DECL_NAME (TREE_PURPOSE (pair)); + TREE_TYPE (enu) = enumtype; + DECL_SIZE (enu) = TYPE_SIZE (enumtype); + DECL_ALIGN (enu) = TYPE_ALIGN (enumtype); + DECL_MODE (enu) = TYPE_MODE (enumtype); + DECL_INITIAL (enu) = convert (enumtype, DECL_INITIAL (enu)); + + TREE_PURPOSE (pair) = DECL_NAME (enu); + TREE_VALUE (pair) = DECL_INITIAL (enu); + } TYPE_VALUES (enumtype) = values; } @@ -5745,6 +5740,8 @@ finish_enum (enumtype, values, attributes) /* Fix up all variant types of this enum type. */ for (tem = TYPE_MAIN_VARIANT (enumtype); tem; tem = TYPE_NEXT_VARIANT (tem)) { + if (tem == enumtype) + continue; TYPE_VALUES (tem) = TYPE_VALUES (enumtype); TYPE_MIN_VALUE (tem) = TYPE_MIN_VALUE (enumtype); TYPE_MAX_VALUE (tem) = TYPE_MAX_VALUE (enumtype); |