From: Per Bothner Date: Wed, 31 Aug 1994 23:42:28 +0000 (-0700) Subject: stmt.c (all_cases_count, [...]): New functions. X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=94d6511c61decde2c932e8800b4469eeaccd5e62;p=platform%2Fupstream%2Fgcc.git stmt.c (all_cases_count, [...]): New functions. * stmt.c (all_cases_count, mark_seen_cases): New functions. (BITARRAY_TEST, BITARRAY_SET): New macros. Used (mainly by Chill) to check all cases are covered (for enums and ranges). (check_for_full_enumeration_handling): Re-write to use the new functions, now that we have them. From-SVN: r8009 --- diff --git a/gcc/stmt.c b/gcc/stmt.c index 1116f0a..59a6777 100644 --- a/gcc/stmt.c +++ b/gcc/stmt.c @@ -4077,6 +4077,193 @@ bc_pushcase (value, label) return 0; } +/* 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. @@ -4097,37 +4284,55 @@ check_for_full_enumeration_handling (type) 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