return 0;
}
\f
+/* Returns the number of possible values of TYPE.
+ Returns -1 if the number is unknown or variable.
+ Returns -2 if the number does not fit in a HOST_WIDE_INT.
+ Sets *SPARENESS to 2 if TYPE is an ENUMERAL_TYPE whose values
+ do not increase monotonically (there may be duplicates);
+ to 1 if the values increase monotonically, but not always by 1;
+ otherwise sets it to 0. */
+
+HOST_WIDE_INT
+all_cases_count (type, spareness)
+ tree type;
+ int *spareness;
+{
+ HOST_WIDE_INT count, count_high = 0;
+ *spareness = 0;
+
+ switch (TREE_CODE (type))
+ {
+ tree t;
+ case BOOLEAN_TYPE:
+ count = 2;
+ break;
+ case CHAR_TYPE:
+ count = 1 << BITS_PER_UNIT;
+ break;
+ default:
+ case INTEGER_TYPE:
+ if (TREE_CODE (TYPE_MIN_VALUE (type)) != INTEGER_CST
+ || TREE_CODE (TYPE_MIN_VALUE (type)) != INTEGER_CST)
+ return -1;
+ else
+ {
+ /* count
+ = TREE_INT_CST_LOW (TYPE_MAX_VALUE (type))
+ - TREE_INT_CST_LOW (TYPE_MIN_VALUE (type)) + 1
+ but with overflow checking. */
+ tree mint = TYPE_MIN_VALUE (type);
+ tree maxt = TYPE_MAX_VALUE (type);
+ HOST_WIDE_INT lo, hi;
+ neg_double(TREE_INT_CST_LOW (mint), TREE_INT_CST_HIGH (mint),
+ &lo, &hi);
+ add_double(TREE_INT_CST_LOW (maxt), TREE_INT_CST_HIGH (maxt),
+ lo, hi, &lo, &hi);
+ add_double (lo, hi, 1, 0, &lo, &hi);
+ if (hi != 0 || lo < 0)
+ return -2;
+ count = lo;
+ }
+ break;
+ case ENUMERAL_TYPE:
+ count = 0;
+ for (t = TYPE_VALUES (type); t != NULL_TREE; t = TREE_CHAIN (t))
+ {
+ if (TREE_CODE (TYPE_MIN_VALUE (type)) != INTEGER_CST
+ || TREE_CODE (TREE_VALUE (t)) != INTEGER_CST
+ || TREE_INT_CST_LOW (TYPE_MIN_VALUE (type)) + count
+ != TREE_INT_CST_LOW (TREE_VALUE (t)))
+ *spareness = 1;
+ count++;
+ }
+ if (*spareness == 1)
+ {
+ tree prev = TREE_VALUE (TYPE_VALUES (type));
+ for (t = TYPE_VALUES (type); t = TREE_CHAIN (t), t != NULL_TREE; )
+ {
+ if (! tree_int_cst_lt (prev, TREE_VALUE (t)))
+ {
+ *spareness = 2;
+ break;
+ }
+ prev = TREE_VALUE (t);
+ }
+
+ }
+ }
+ return count;
+}
+
+
+#define BITARRAY_TEST(ARRAY, INDEX) \
+ ((ARRAY)[(unsigned)(INDEX) / HOST_BITS_PER_CHAR]\
+ & (1 << ((unsigned)(INDEX) % HOST_BITS_PER_CHAR)))
+#define BITARRAY_SET(ARRAY, INDEX) \
+ ((ARRAY)[(unsigned)(INDEX) / HOST_BITS_PER_CHAR]\
+ |= 1 << ((unsigned)(INDEX) % HOST_BITS_PER_CHAR))
+
+/* Set the elements of the bitstring CASES_SEEN (which has length COUNT),
+ with the case values we have seen, assuming the case expression
+ has the given TYPE.
+ SPARSENESS is as determined by all_cases_count.
+
+ The time needed is propotional to COUNT, unless
+ SPARSENESS is 2, in which case quadratic time is needed. */
+
+void
+mark_seen_cases (type, cases_seen, count, sparseness)
+ tree type;
+ unsigned char *cases_seen;
+ long count;
+ int sparseness;
+{
+ long i;
+
+ tree next_node_to_try = NULL_TREE;
+ long next_node_offset = 0;
+
+ register struct case_node *n;
+ tree val = make_node (INTEGER_CST);
+ TREE_TYPE (val) = type;
+ for (n = case_stack->data.case_stmt.case_list; n;
+ n = n->right)
+ {
+ TREE_INT_CST_LOW (val) = TREE_INT_CST_LOW (n->low);
+ TREE_INT_CST_HIGH (val) = TREE_INT_CST_HIGH (n->low);
+ while ( ! tree_int_cst_lt (n->high, val))
+ {
+ /* Calculate (into xlo) the "offset" of the integer (val).
+ The element with lowest value has offset 0, the next smallest
+ element has offset 1, etc. */
+
+ HOST_WIDE_INT xlo, xhi;
+ tree t;
+ if (sparseness == 2)
+ {
+ /* This less efficient loop is only needed to handle
+ duplicate case values (multiple enum constants
+ with the same value). */
+ for (t = TYPE_VALUES (type), xlo = 0; t != NULL_TREE;
+ t = TREE_CHAIN (t), xlo++)
+ {
+ if (tree_int_cst_equal (val, TREE_VALUE (t)))
+ BITARRAY_SET (cases_seen, xlo);
+ }
+ }
+ else
+ {
+ if (sparseness && TYPE_VALUES (type) != NULL_TREE)
+ {
+ /* The TYPE_VALUES will be in increasing order, so
+ starting searching where we last ended. */
+ t = next_node_to_try;
+ xlo = next_node_offset;
+ xhi = 0;
+ for (;;)
+ {
+ if (t == NULL_TREE)
+ {
+ t = TYPE_VALUES (type);
+ xlo = 0;
+ }
+ if (tree_int_cst_equal (val, TREE_VALUE (t)))
+ {
+ next_node_to_try = TREE_CHAIN (t);
+ next_node_offset = xlo + 1;
+ break;
+ }
+ xlo++;
+ t = TREE_CHAIN (t);
+ if (t == next_node_to_try)
+ break;
+ }
+ }
+ else
+ {
+ t = TYPE_MIN_VALUE (type);
+ if (t)
+ neg_double (TREE_INT_CST_LOW (t), TREE_INT_CST_HIGH (t),
+ &xlo, &xhi);
+ else
+ xlo = xhi = 0;
+ add_double (xlo, xhi,
+ TREE_INT_CST_LOW (val), TREE_INT_CST_HIGH (val),
+ &xlo, &xhi);
+ }
+
+ if (xhi != 0 || xlo < 0 || xlo >= count)
+ fatal ("internal error - mark_cases_seen");
+ else
+ BITARRAY_SET (cases_seen, xlo);
+ }
+ add_double (TREE_INT_CST_LOW (val), TREE_INT_CST_HIGH (val),
+ 1, 0,
+ &TREE_INT_CST_LOW (val), &TREE_INT_CST_HIGH (val));
+ }
+ }
+}
+
/* Called when the index of a switch statement is an enumerated type
and there is no default label.
register tree chain;
int all_values = 1;
+ /* True iff the selector type is a numbered set mode. */
+ int sparseness = 0;
+
+ /* The number of possible selector values. */
+ HOST_WIDE_INT size;
+
+ /* For each possible selector value. a one iff it has been matched
+ by a case value alternative. */
+ unsigned char *cases_seen;
+
+ /* The allocated size of cases_seen, in chars. */
+ long bytes_needed;
+ tree t;
+
if (output_bytecode)
{
bc_check_for_full_enumeration_handling (type);
return;
}
- /* The time complexity of this loop is currently O(N * M), with
- N being the number of members in the enumerated type, and
- M being the number of case expressions in the switch. */
+ if (! warn_switch)
+ return;
+
+ size = all_cases_count (type, &sparseness);
+ bytes_needed = (size + HOST_BITS_PER_CHAR) / HOST_BITS_PER_CHAR;
- for (chain = TYPE_VALUES (type);
- chain;
- chain = TREE_CHAIN (chain))
+ if (size > 0 && size < 600000
+ /* We deliberately use malloc here - not xmalloc. */
+ && (cases_seen = (char*) malloc (bytes_needed)) != NULL)
{
- /* Find a match between enumeral and case expression, if possible.
- Quit looking when we've gone too far (since case expressions
- are kept sorted in ascending order). Warn about enumerators not
- handled in the switch statement case expression list. */
-
- for (n = case_stack->data.case_stmt.case_list;
- n && tree_int_cst_lt (n->high, TREE_VALUE (chain));
- n = n->right)
- ;
+ long i;
+ tree v = TYPE_VALUES (type);
+ bzero (cases_seen, bytes_needed);
+
+ /* The time complexity of this code is normally O(N), where
+ N being the number of members in the enumerated type.
+ However, if type is a ENUMERAL_TYPE whose values do not
+ increase monotonically, quadratic time may be needed. */
- if (!n || tree_int_cst_lt (TREE_VALUE (chain), n->low))
+ mark_seen_cases (type, cases_seen, size, sparseness);
+
+ for (i = 0; v != NULL_TREE && i < size; i++, v = TREE_CHAIN (v))
{
- if (warn_switch)
+ if (BITARRAY_TEST(cases_seen, i) == 0)
warning ("enumeration value `%s' not handled in switch",
- IDENTIFIER_POINTER (TREE_PURPOSE (chain)));
- all_values = 0;
+ IDENTIFIER_POINTER (TREE_PURPOSE (v)));
}
+
+ free (cases_seen);
}
/* Now we go the other way around; we warn if there are case