Fix switch statements so the work in the new scheme.

Convert case labels to be the same type as the switch expression.
Use alias expressions for the various test expressions.
This commit is contained in:
Bill Currie 2011-03-06 00:29:29 +09:00
parent 8cfa80b5d4
commit 28f4de94d2
2 changed files with 23 additions and 5 deletions

View file

@ -1020,11 +1020,10 @@ statement
{
$$ = case_label_expr (switch_block, 0);
}
| SWITCH break_label switch_block '(' fexpr ')' compound_statement
| SWITCH break_label '(' fexpr switch_block ')' compound_statement
{
switch_block->test = $5;
$$ = switch_expr (switch_block, break_label, $7);
switch_block = $3;
switch_block = $5;
break_label = $2;
}
| IF '(' texpr ')' statement %prec IFX
@ -1090,6 +1089,7 @@ switch_block
{
$$ = switch_block;
switch_block = new_switch_block ();
switch_block->test = $<expr>0;
}
;

View file

@ -125,6 +125,22 @@ case_label_expr (switch_block_t *switch_block, expr_t *value)
free (cl);
return 0;
}
if (!switch_block->test)
internal_error (value, "broken switch block");
if (value) {
type_t *type = get_type (switch_block->test);
type_t *val_type = get_type (value);
if (!type_assignable (type, get_type (value)))
return error (value, "type mismatch in case label");
if (type != val_type) {
//FIXME shorts?
if (type == &type_float)
value->e.value.v.float_val = value->e.value.v.integer_val;
else
value->e.value.v.integer_val = value->e.value.v.float_val;
value->e.value.type = type->type;
}
}
cl->value = value;
if (Hash_FindElement (switch_block->labels, cl)) {
error (value, "duplicate %s", value ? "case" : "default");
@ -289,11 +305,13 @@ build_switch (expr_t *sw, case_node_t *tree, int op, expr_t *sw_val,
append_expr (sw, test);
if (tree->low == tree->high) {
branch = branch_expr ('n', temp, tree->labels[0]);
branch = branch_expr ('n', new_alias_expr (&type_integer, temp),
tree->labels[0]);
append_expr (sw, branch);
if (tree->left) {
branch = branch_expr (IFA, temp, high_label);
branch = branch_expr (IFA, new_alias_expr (&type_integer, temp),
high_label);
append_expr (sw, branch);
build_switch (sw, tree->left, op, sw_val, temp, default_label);