aboutsummaryrefslogtreecommitdiff
path: root/gcc/c-decl.c
diff options
context:
space:
mode:
authorkenner <kenner@138bc75d-0d04-0410-961f-82ee72b054a4>1994-06-14 21:55:38 +0000
committerkenner <kenner@138bc75d-0d04-0410-961f-82ee72b054a4>1994-06-14 21:55:38 +0000
commitba19d940e36d1b7503352247286a7ee91e45202e (patch)
tree3eda82c90eedb1671f261ada97220ea214cdc83b /gcc/c-decl.c
parent8cb81425743091dd88e9683359809f0beae9b86f (diff)
(min_precision): New function.
(finish_enum): Rewrite code to determine precision required for enumeral type. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@7471 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/c-decl.c')
-rw-r--r--gcc/c-decl.c70
1 files changed, 38 insertions, 32 deletions
diff --git a/gcc/c-decl.c b/gcc/c-decl.c
index bdbbb5fd4f5..44face4730b 100644
--- a/gcc/c-decl.c
+++ b/gcc/c-decl.c
@@ -5621,6 +5621,37 @@ start_enum (name)
return enumtype;
}
+/* Return the minimum number of bits needed to represent VALUE in a
+ signed or unsigned type, UNSIGNEDP says which. */
+
+static int
+min_precision (value, unsignedp)
+ tree value;
+ int unsignedp;
+{
+ int log;
+
+ /* If the value is negative, compute its negative minus 1. The latter
+ adjustment is because the absolute value of the largest negative value
+ is one larger than the largest positive value. This is equivalent to
+ a bit-wise negation, so use that operation instead. */
+
+ if (tree_int_cst_sgn (value) < 0)
+ value = fold (build1 (BIT_NOT_EXPR, TREE_TYPE (value), value));
+
+ /* Return the number of bits needed, taking into account the fact
+ that we need one more bit for a signed than unsigned type. */
+
+ if (integer_zerop (value))
+ log = 0;
+ else if (TREE_INT_CST_HIGH (value) != 0)
+ log = HOST_BITS_PER_WIDE_INT + floor_log2 (TREE_INT_CST_HIGH (value));
+ else
+ log = floor_log2 (TREE_INT_CST_LOW (value));
+
+ return log + 1 + ! unsignedp;
+}
+
/* After processing and defining all the values of an enumeration type,
install their decls in the enumeration type and finish it off.
ENUMTYPE is the type object and VALUES a list of decl-value pairs.
@@ -5632,9 +5663,7 @@ finish_enum (enumtype, values)
{
register tree pair, tem;
tree minnode = 0, maxnode = 0;
- register HOST_WIDE_INT maxvalue = 0;
- register HOST_WIDE_INT minvalue = 0;
- unsigned precision = 0;
+ int lowprec, highprec, precision;
int toplevel = global_binding_level == current_binding_level;
if (in_parm_level_p ())
@@ -5662,34 +5691,14 @@ finish_enum (enumtype, values)
TYPE_MIN_VALUE (enumtype) = minnode;
TYPE_MAX_VALUE (enumtype) = maxnode;
- /* Determine the precision this type needs. */
-
- if (TREE_INT_CST_HIGH (minnode) >= 0
- ? tree_int_cst_lt (TYPE_MAX_VALUE (unsigned_type_node), maxnode)
- : (tree_int_cst_lt (minnode, TYPE_MIN_VALUE (integer_type_node))
- || tree_int_cst_lt (TYPE_MAX_VALUE (integer_type_node), maxnode)))
- precision = TYPE_PRECISION (long_long_integer_type_node);
- else
- {
- maxvalue = TREE_INT_CST_LOW (maxnode);
- minvalue = TREE_INT_CST_LOW (minnode);
+ /* An enum can have some negative values; then it is signed. */
+ TREE_UNSIGNED (enumtype) = tree_int_cst_sgn (minnode) >= 0;
- if (maxvalue > 0)
- precision = floor_log2 (maxvalue) + 1;
- if (minvalue < 0)
- {
- /* Compute number of bits to represent magnitude of a negative value.
- Add one to MINVALUE since range of negative numbers
- includes the power of two. */
- unsigned negprecision = floor_log2 (-minvalue - 1) + 1;
- if (negprecision > precision)
- precision = negprecision;
- precision += 1; /* room for sign bit */
- }
+ /* Determine the precision this type needs. */
- if (!precision)
- precision = 1;
- }
+ lowprec = min_precision (minnode, TREE_UNSIGNED (enumtype));
+ highprec = min_precision (maxnode, TREE_UNSIGNED (enumtype));
+ precision = MAX (lowprec, highprec);
if (flag_short_enums || precision > TYPE_PRECISION (integer_type_node))
/* Use the width of the narrowest normal C type which is wide enough. */
@@ -5700,9 +5709,6 @@ finish_enum (enumtype, values)
TYPE_SIZE (enumtype) = 0;
layout_type (enumtype);
- /* An enum can have some negative values; then it is signed. */
- TREE_UNSIGNED (enumtype) = tree_int_cst_sgn (minnode) >= 0;
-
if (values != error_mark_node)
{
/* Change the type of the enumerators to be the enum type.