aboutsummaryrefslogtreecommitdiff
path: root/gcc/c-decl.c
diff options
context:
space:
mode:
authorZack Weinberg <zack@rabi.columbia.edu>2000-01-05 19:26:23 +0000
committerZack Weinberg <zack@gcc.gnu.org>2000-01-05 19:26:23 +0000
commitcb3ca04ee18428f3c08b36f97ee0184449bcb6c6 (patch)
tree2f5f1a4333cfc525d0e30c2fc974ac8bf2621783 /gcc/c-decl.c
parent28b487d7fe96ff2475bd8de4f86d9bc3da040e85 (diff)
downloadgcc-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.c95
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);