aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp
diff options
context:
space:
mode:
authorMark Mitchell <mark@codesourcery.com>2000-09-10 21:34:41 +0000
committerMark Mitchell <mmitchel@gcc.gnu.org>2000-09-10 21:34:41 +0000
commit56cb97339bc91ec1b4df74a8bb4a31d4c363aee2 (patch)
treee6b472ea3504de9f1d42acce2241fe0cbaf55dcf /gcc/cp
parent2c9f4db73acfb821ad776df950e908daac642530 (diff)
downloadgcc-56cb97339bc91ec1b4df74a8bb4a31d4c363aee2.zip
gcc-56cb97339bc91ec1b4df74a8bb4a31d4c363aee2.tar.gz
gcc-56cb97339bc91ec1b4df74a8bb4a31d4c363aee2.tar.bz2
c-common.h (add_stmt): Change prototype.
* c-common.h (add_stmt): Change prototype. (RECHAIN_STMTS): New macro. (CASE_LABEL_DECL): Likewise. (genrtl_case_label): Change prototype. (c_expand_start_case): Remove prototype. (build_case_label): Change prototype. (decl_constant_value): Declare. * c-common.c (check_case_value): Handle C++'s extensions to C semantics. * c-commnon.def (CASE_LABEL): Add room for the CASE_LABEL_DECL field. * c-parse.in (stmt): Adjust handling of return statements and case laels. * c-semantics.c (add_stmt): Return the new statement. (genrtl_return_stmt): Take the RETURN_STMT as input, not the returned expression. Directly generate RTL, rather than calling c_expand_return. (genrtl_switch_stmt): Don't call c_expand_start_case. (build_case_label): Take the LABEL_DECL as input, too. (genrtl_case_label): Just call add_case_node. (expand_stmt): Adjust calls to genrtl_return_stmt and genrtl_case_label. * c-tree.h (c_expand_start_case): Declare. * c-typeck.c (decl_constant_value): Give it external linkage. (c_expand_return): Don't call expand_return or expand_null_return; use genrtl_return_stmt instead. * stmt.c (struct nesting): Remove num_ranges field. (add_case_node): Give it external linkage. (expand_start_case): Don't set num_ranges. (expand_start_case_dummy): Don't clear it. (pushcase): Rely on add_case_node to handle `default' labels. (add_case_node): Handle `default' labels. * tree.c (tree_int_cst_compare): New function. * tree.h (tree_int_cst_compare): Declare. (add_case_node): Likewise. * cp-tree.h (push_switch): Change prototype. (check_cp_case_value): Remove declaration. (decl_constant_value): Likewise. * decl.c (struct cp_switch): Add switch_stmt and cases. (case_compare): New function. (push_switch): Set switch_stmt. Initialize cases. (pop_switch): Clean up cases. (define_case_label): Rename to ... (finish_case_label): ... this. Do semantic analysis for case labels here. (start_function): Correct comment. * decl2.c (check_cp_case_value): Remove. * expr.c (do_case): Remove. * pt.c (tsubst_expr): Adjust call to finish_case_label. * semantics.c (genrtl_do_poplevel): Remove declaration. (RECHAIN_STMTS): Remove. (finish_break_stmt): Use build_break_stmt. (finish_continue_stmt): Use build_continue_stmt. (finish_switch_cond): Adjust condition here, rater than in c_expand_start_case. (finish_case_label): Remove. * typeck.c (c_expand_return): Remove. (c_expand_start_case): Likewise. From-SVN: r36305
Diffstat (limited to 'gcc/cp')
-rw-r--r--gcc/cp/ChangeLog26
-rw-r--r--gcc/cp/cp-tree.h4
-rw-r--r--gcc/cp/decl.c194
-rw-r--r--gcc/cp/decl2.c29
-rw-r--r--gcc/cp/expr.c79
-rw-r--r--gcc/cp/pt.c3
-rw-r--r--gcc/cp/semantics.c48
-rw-r--r--gcc/cp/typeck.c49
8 files changed, 233 insertions, 199 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 537e57a..1ba64f0 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,29 @@
+2000-09-09 Mark Mitchell <mark@codesourcery.com>
+
+ * cp-tree.h (push_switch): Change prototype.
+ (check_cp_case_value): Remove declaration.
+ (decl_constant_value): Likewise.
+ * decl.c (struct cp_switch): Add switch_stmt and cases.
+ (case_compare): New function.
+ (push_switch): Set switch_stmt. Initialize cases.
+ (pop_switch): Clean up cases.
+ (define_case_label): Rename to ...
+ (finish_case_label): ... this. Do semantic analysis for case
+ labels here.
+ (start_function): Correct comment.
+ * decl2.c (check_cp_case_value): Remove.
+ * expr.c (do_case): Remove.
+ * pt.c (tsubst_expr): Adjust call to finish_case_label.
+ * semantics.c (genrtl_do_poplevel): Remove declaration.
+ (RECHAIN_STMTS): Remove.
+ (finish_break_stmt): Use build_break_stmt.
+ (finish_continue_stmt): Use build_continue_stmt.
+ (finish_switch_cond): Adjust condition here, rater than in
+ c_expand_start_case.
+ (finish_case_label): Remove.
+ * typeck.c (c_expand_return): Remove.
+ (c_expand_start_case): Likewise.
+
2000-09-07 Gabriel Dos Reis <gdr@codesourcery.com>
* ir.texi: Document type nodes.
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index f29b04b..8dbb82e 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -3829,7 +3829,7 @@ extern void pop_nested_namespace PARAMS ((tree));
extern void maybe_push_to_top_level PARAMS ((int));
extern void push_to_top_level PARAMS ((void));
extern void pop_from_top_level PARAMS ((void));
-extern void push_switch PARAMS ((void));
+extern void push_switch PARAMS ((tree));
extern void pop_switch PARAMS ((void));
extern tree identifier_type_value PARAMS ((tree));
extern void set_identifier_type_value PARAMS ((tree, tree));
@@ -3990,7 +3990,6 @@ extern tree reparse_absdcl_as_casts PARAMS ((tree, tree));
extern tree build_expr_from_tree PARAMS ((tree));
extern tree reparse_decl_as_expr PARAMS ((tree, tree));
extern tree finish_decl_parsing PARAMS ((tree));
-extern tree check_cp_case_value PARAMS ((tree));
extern void set_decl_namespace PARAMS ((tree, tree, int));
extern tree current_decl_namespace PARAMS ((void));
extern void push_decl_namespace PARAMS ((tree));
@@ -4075,7 +4074,6 @@ extern tree get_type_value PARAMS ((tree));
extern tree build_member_call PARAMS ((tree, tree, tree));
extern tree build_offset_ref PARAMS ((tree, tree));
extern tree resolve_offset_ref PARAMS ((tree));
-extern tree decl_constant_value PARAMS ((tree));
extern tree build_new PARAMS ((tree, tree, tree, int));
extern tree build_vec_init PARAMS ((tree, tree, tree, tree, int));
extern tree build_x_delete PARAMS ((tree, int, tree));
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 640deb2..9ac30e4 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -187,6 +187,7 @@ static tree check_special_function_return_type
PARAMS ((special_function_kind, tree, tree, tree));
static tree push_cp_library_fn PARAMS ((enum tree_code, tree));
static tree build_cp_library_fn PARAMS ((tree, enum tree_code, tree));
+static int case_compare PARAMS ((splay_tree_key, splay_tree_key));
#if defined (DEBUG_CP_BINDING_LEVELS)
static void indent PARAMS ((void));
@@ -5176,17 +5177,52 @@ struct cp_switch
{
struct binding_level *level;
struct cp_switch *next;
+ /* The SWITCH_STMT being built. */
+ tree switch_stmt;
+ /* A splay-tree mapping the low element of a case range to the high
+ element, or NULL_TREE if there is no high element. Used to
+ determine whether or not a new case label duplicates an old case
+ label. We need a tree, rather than simply a hash table, because
+ of the GNU case range extension. */
+ splay_tree cases;
};
+/* A stack of the currently active switch statements. The innermost
+ switch statement is on the top of the stack. There is no need to
+ mark the stack for garbage collection because it is only active
+ during the processing of the body of a function, and we never
+ collect at that point. */
+
static struct cp_switch *switch_stack;
+static int
+case_compare (k1, k2)
+ splay_tree_key k1;
+ splay_tree_key k2;
+{
+ /* Consider a NULL key (such as arises with a `default' label) to be
+ smaller than anything else. */
+ if (!k1)
+ return k2 ? -1 : 0;
+ else if (!k2)
+ return k1 ? 1 : 0;
+
+ return tree_int_cst_compare ((tree) k1, (tree) k2);
+}
+
+/* Called right after a switch-statement condition is parsed.
+ SWITCH_STMT is the switch statement being parsed. */
+
void
-push_switch ()
+push_switch (switch_stmt)
+ tree switch_stmt;
{
struct cp_switch *p
= (struct cp_switch *) xmalloc (sizeof (struct cp_switch));
p->level = current_binding_level;
p->next = switch_stack;
+ p->switch_stmt = switch_stmt;
+ p->cases = splay_tree_new (case_compare, NULL, NULL);
switch_stack = p;
}
@@ -5196,6 +5232,7 @@ pop_switch ()
struct cp_switch *cs;
cs = switch_stack;
+ splay_tree_delete (cs->cases);
switch_stack = switch_stack->next;
free (cs);
}
@@ -5204,14 +5241,150 @@ pop_switch ()
is a bad place for one. */
void
-define_case_label ()
+finish_case_label (low_value, high_value)
+ tree low_value;
+ tree high_value;
{
- tree cleanup = last_cleanup_this_contour ();
+ tree label;
+ tree cleanup;
+ tree type;
+ tree cond;
+ tree case_label;
+ splay_tree_node node;
if (! switch_stack)
- /* Don't crash; we'll complain in do_case. */
+ {
+ if (high_value)
+ error ("case label not within a switch statement");
+ else if (low_value)
+ cp_error ("case label `%E' not within a switch statement",
+ low_value);
+ else
+ error ("`default' label not within a switch statement");
+ return;
+ }
+
+ label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
+
+ if (processing_template_decl)
+ {
+ /* For templates, just add the case label; we'll do semantic
+ analysis at instantiation-time. */
+ add_stmt (build_case_label (low_value, high_value, label));
+ return;
+ }
+
+ /* Find the condition on which this switch statement depends. */
+ cond = SWITCH_COND (switch_stack->switch_stmt);
+ if (cond && TREE_CODE (cond) == TREE_LIST)
+ cond = TREE_VALUE (cond);
+ /* If there was an error processing the switch condition, bail now
+ before we get more confused. */
+ if (!cond || cond == error_mark_node)
return;
+ type = TREE_TYPE (cond);
+ if ((low_value && TREE_TYPE (low_value)
+ && POINTER_TYPE_P (TREE_TYPE (low_value)))
+ || (high_value && TREE_TYPE (high_value)
+ && POINTER_TYPE_P (TREE_TYPE (high_value))))
+ error ("pointers are not permitted as case values");
+
+ /* Case ranges are a GNU extension. */
+ if (high_value && pedantic)
+ pedwarn ("ISO C++ forbids range expressions in switch statement");
+
+ if (low_value)
+ {
+ low_value = check_case_value (low_value);
+ low_value = convert_and_check (type, low_value);
+ }
+ if (high_value)
+ {
+ high_value = check_case_value (high_value);
+ high_value = convert_and_check (type, high_value);
+ }
+
+ /* If an error has occurred, bail out now. */
+ if (low_value == error_mark_node || high_value == error_mark_node)
+ return;
+
+ /* If the LOW_VALUE and HIGH_VALUE are the same, then this isn't
+ really a case range, even though it was written that way. Remove
+ the HIGH_VALUE to simplify later processing. */
+ if (tree_int_cst_equal (low_value, high_value))
+ high_value = NULL_TREE;
+ if (low_value && high_value
+ && !tree_int_cst_lt (low_value, high_value))
+ warning ("empty range specified");
+
+ /* Look up the LOW_VALUE in the table of case labels we already
+ have. */
+ node = splay_tree_lookup (switch_stack->cases, (splay_tree_key) low_value);
+ /* If there was not an exact match, check for overlapping ranges.
+ There's no need to do this if there's no LOW_VALUE or HIGH_VALUE;
+ that's a `default' label and the only overlap is an exact match. */
+ if (!node && (low_value || high_value))
+ {
+ splay_tree_node low_bound;
+ splay_tree_node high_bound;
+
+ /* Even though there wasn't an exact match, there might be an
+ overlap between this case range and another case range.
+ Since we've (inductively) not allowed any overlapping case
+ ranges, we simply need to find the greatest low case label
+ that is smaller that LOW_VALUE, and the smallest low case
+ label that is greater than LOW_VALUE. If there is an overlap
+ it will occur in one of these two ranges. */
+ low_bound = splay_tree_predecessor (switch_stack->cases,
+ (splay_tree_key) low_value);
+ high_bound = splay_tree_successor (switch_stack->cases,
+ (splay_tree_key) low_value);
+
+ /* Check to see if the LOW_BOUND overlaps. It is smaller than
+ the LOW_VALUE, so there is no need to check unless the
+ LOW_BOUND is in fact itself a case range. */
+ if (low_bound
+ && CASE_HIGH ((tree) low_bound->value)
+ && tree_int_cst_compare (CASE_HIGH ((tree) low_bound->value),
+ low_value) >= 0)
+ node = low_bound;
+ /* Check to see if the HIGH_BOUND overlaps. The low end of that
+ range is bigger than the low end of the current range, so we
+ are only interested if the current range is a real range, and
+ not an ordinary case label. */
+ else if (high_bound
+ && high_value
+ && (tree_int_cst_compare ((tree) high_bound->key,
+ high_value)
+ <= 0))
+ node = high_bound;
+ }
+ /* If there was an overlap, issue an error. */
+ if (node)
+ {
+ tree duplicate = CASE_LABEL_DECL ((tree) node->value);
+
+ if (high_value)
+ {
+ error ("duplicate (or overlapping) case value");
+ cp_error_at ("this is the first entry overlapping that value",
+ duplicate);
+ }
+ else if (low_value)
+ {
+ cp_error ("duplicate case value `%E'", low_value) ;
+ cp_error_at ("previously used here", duplicate);
+ }
+ else
+ {
+ error ("multiple default labels in one switch");
+ cp_error_at ("this is the first default label", duplicate);
+ }
+ return;
+ }
+
+ cleanup = last_cleanup_this_contour ();
if (cleanup)
{
static int explained = 0;
@@ -5228,9 +5401,18 @@ define_case_label ()
/* After labels, make any new cleanups go into their
own new (temporary) binding contour. */
-
current_binding_level->more_cleanups_ok = 0;
current_function_return_value = NULL_TREE;
+
+ /* Add a representation for the case label to the statement
+ tree. */
+ case_label = build_case_label (low_value, high_value, label);
+ add_stmt (case_label);
+
+ /* Register this case label in the splay tree. */
+ splay_tree_insert (switch_stack->cases,
+ (splay_tree_key) low_value,
+ (splay_tree_value) case_label);
}
/* Return the list of declarations of the current level.
@@ -13601,7 +13783,7 @@ start_function (declspecs, declarator, attrs, flags)
if (flags & SF_INCLASS_INLINE)
maybe_begin_member_template_processing (decl1);
- /* Effective C++ rule 15. See also c_expand_return. */
+ /* Effective C++ rule 15. */
if (warn_ecpp
&& DECL_OVERLOADED_OPERATOR_P (decl1) == NOP_EXPR
&& TREE_CODE (TREE_TYPE (fntype)) == VOID_TYPE)
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index 7bbd998..e97d525 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -4329,35 +4329,6 @@ finish_decl_parsing (decl)
}
}
-tree
-check_cp_case_value (value)
- tree value;
-{
- if (value == NULL_TREE)
- return value;
-
- /* Strip NON_LVALUE_EXPRs since we aren't using as an lvalue. */
- STRIP_TYPE_NOPS (value);
- value = decl_constant_value (value);
- STRIP_TYPE_NOPS (value);
- value = fold (value);
-
- if (TREE_CODE (value) != INTEGER_CST
- && value != error_mark_node)
- {
- cp_error ("case label `%E' does not reduce to an integer constant",
- value);
- value = error_mark_node;
- }
- else
- /* Promote char or short to int. */
- value = default_conversion (value);
-
- constant_expression_warning (value);
-
- return value;
-}
-
/* Return 1 if root encloses child. */
static int
diff --git a/gcc/cp/expr.c b/gcc/cp/expr.c
index 42a5390..39095ec 100644
--- a/gcc/cp/expr.c
+++ b/gcc/cp/expr.c
@@ -205,82 +205,3 @@ extract_init (decl, init)
return 0;
}
-void
-do_case (start, end)
- tree start, end;
-{
- tree value1 = NULL_TREE, value2 = NULL_TREE, label;
-
- if (start != NULL_TREE && TREE_TYPE (start) != NULL_TREE
- && POINTER_TYPE_P (TREE_TYPE (start)))
- error ("pointers are not permitted as case values");
-
- if (end && pedantic)
- pedwarn ("ISO C++ forbids range expressions in switch statement");
-
- if (start)
- value1 = check_cp_case_value (start);
- if (end)
- value2 = check_cp_case_value (end);
-
- label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
-
- if (value1 != error_mark_node
- && value2 != error_mark_node)
- {
- tree duplicate;
- int success;
-
- if (end)
- success = pushcase_range (value1, value2, convert_and_check,
- label, &duplicate);
- else if (start)
- success = pushcase (value1, convert_and_check, label, &duplicate);
- else
- success = pushcase (NULL_TREE, 0, label, &duplicate);
-
- if (success == 1)
- {
- if (end)
- error ("case label not within a switch statement");
- else if (start)
- cp_error ("case label `%E' not within a switch statement", start);
- else
- error ("default label not within a switch statement");
- }
- else if (success == 2)
- {
- if (end)
- {
- error ("duplicate (or overlapping) case value");
- cp_error_at ("this is the first entry overlapping that value",
- duplicate);
- }
- else if (start)
- {
- cp_error ("duplicate case value `%E'", start);
- cp_error_at ("previously used here", duplicate);
- }
- else
- {
- error ("multiple default labels in one switch");
- cp_error_at ("this is the first default label", duplicate);
- }
- }
- else if (success == 3)
- warning ("case value out of range");
- else if (success == 4)
- warning ("empty range specified");
- else if (success == 5)
- {
- if (end)
- error ("case label within scope of cleanup or variable array");
- else if (! start)
- error ("`default' label within scope of cleanup or variable array");
- else
- cp_error ("case label `%E' within scope of cleanup or variable array", start);
- }
- }
-
- current_function_return_value = NULL_TREE;
-}
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 51421fd..dc6f00f 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -7269,7 +7269,8 @@ tsubst_expr (t, args, complain, in_decl)
case CASE_LABEL:
prep_stmt (t);
finish_case_label (tsubst_expr (CASE_LOW (t), args, complain, in_decl),
- tsubst_expr (CASE_HIGH (t), args, complain, in_decl));
+ tsubst_expr (CASE_HIGH (t), args, complain,
+ in_decl));
break;
case LABEL_STMT:
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index e1a73ce..b7abff2 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -55,23 +55,9 @@ static void genrtl_handler PARAMS ((tree));
static void genrtl_catch_block PARAMS ((tree));
static void genrtl_ctor_stmt PARAMS ((tree));
static void genrtl_subobject PARAMS ((tree));
-static tree genrtl_do_poplevel PARAMS ((void));
static void genrtl_named_return_value PARAMS ((void));
static void cp_expand_stmt PARAMS ((tree));
-/* When parsing a template, LAST_TREE contains the last statement
- parsed. These are chained together through the TREE_CHAIN field,
- but often need to be re-organized since the parse is performed
- bottom-up. This macro makes LAST_TREE the indicated SUBSTMT of
- STMT. */
-
-#define RECHAIN_STMTS(stmt, substmt) \
- do { \
- substmt = TREE_CHAIN (stmt); \
- TREE_CHAIN (stmt) = NULL_TREE; \
- last_tree = stmt; \
- } while (0)
-
/* Finish processing the COND, the SUBSTMT condition for STMT. */
#define FINISH_COND(cond, stmt, substmt) \
@@ -520,7 +506,7 @@ finish_for_stmt (for_stmt)
void
finish_break_stmt ()
{
- add_stmt (build_stmt (BREAK_STMT));
+ add_stmt (build_break_stmt ());
}
/* Finish a continue-statement. */
@@ -528,7 +514,7 @@ finish_break_stmt ()
void
finish_continue_stmt ()
{
- add_stmt (build_stmt (CONTINUE_STMT));
+ add_stmt (build_continue_stmt ());
}
/* Begin a switch-statement. Returns a new SWITCH_STMT if
@@ -553,6 +539,9 @@ finish_switch_cond (cond, switch_stmt)
{
if (!processing_template_decl)
{
+ tree type;
+ tree index;
+
/* Convert the condition to an integer or enumeration type. */
cond = build_expr_type_conversion (WANT_INT | WANT_ENUM, cond, 1);
if (cond == NULL_TREE)
@@ -565,9 +554,19 @@ finish_switch_cond (cond, switch_stmt)
cond = default_conversion (cond);
cond = fold (build1 (CLEANUP_POINT_EXPR, TREE_TYPE (cond), cond));
}
+
+ type = TREE_TYPE (cond);
+ index = get_unwidened (cond, NULL_TREE);
+ /* We can't strip a conversion from a signed type to an unsigned,
+ because if we did, int_fits_type_p would do the wrong thing
+ when checking case values for being in range,
+ and it's too hard to do the right thing. */
+ if (TREE_UNSIGNED (TREE_TYPE (cond))
+ == TREE_UNSIGNED (TREE_TYPE (index)))
+ cond = index;
}
FINISH_COND (cond, switch_stmt, SWITCH_COND (switch_stmt));
- push_switch ();
+ push_switch (switch_stmt);
}
/* Finish the body of a switch-statement, which may be given by
@@ -583,21 +582,6 @@ finish_switch_stmt (switch_stmt)
finish_stmt ();
}
-/* Finish a case-label. */
-
-void
-finish_case_label (low_value, high_value)
- tree low_value;
- tree high_value;
-{
- /* Add a representation for the case label to the statement
- tree. */
- add_stmt (build_stmt (CASE_LABEL, low_value, high_value));
- /* And warn about crossing initializations, etc. */
- if (!processing_template_decl)
- define_case_label ();
-}
-
/* Generate the RTL for T, which is a TRY_BLOCK. */
static void
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index bff019d..e15a724 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -6839,56 +6839,7 @@ check_return_expr (retval)
return retval;
}
-/* Expand a C `return' statement.
- RETVAL is the expression for what to return,
- or a null pointer for `return;' with no value.
-
- C++: upon seeing a `return', we must call destructors on all
- variables in scope which had constructors called on them.
- This means that if in a destructor, the base class destructors
- must be called before returning.
-
- The RETURN statement in C++ has initialization semantics. */
-
-void
-c_expand_return (retval)
- tree retval;
-{
- if (!retval)
- expand_null_return ();
- else
- {
- expand_start_target_temps ();
- expand_return (retval);
- expand_end_target_temps ();
- }
-}
-/* Start a C switch statement, testing expression EXP.
- Return EXP if it is valid, an error node otherwise. */
-
-tree
-c_expand_start_case (exp)
- tree exp;
-{
- tree type;
- tree index;
-
- type = TREE_TYPE (exp);
- index = get_unwidened (exp, NULL_TREE);
- /* We can't strip a conversion from a signed type to an unsigned,
- because if we did, int_fits_type_p would do the wrong thing
- when checking case values for being in range,
- and it's too hard to do the right thing. */
- if (TREE_UNSIGNED (TREE_TYPE (exp))
- == TREE_UNSIGNED (TREE_TYPE (index)))
- exp = index;
-
- expand_start_case (1, exp, type, "switch statement");
-
- return exp;
-}
-
/* Returns non-zero if the pointer-type FROM can be converted to the
pointer-type TO via a qualification conversion. If CONSTP is -1,
then we return non-zero if the pointers are similar, and the