From: dick Date: Fri, 14 Mar 1986 16:15:16 +0000 (+0000) Subject: improved error reporting for initialization expressions X-Git-Tag: release-5-5~5351 X-Git-Url: https://git.ndcode.org/public/gitweb.cgi?a=commitdiff_plain;h=c80f2c08177243ea517e0e34fa57b5ee953e13ca;p=ack.git improved error reporting for initialization expressions miscellaneous changes --- diff --git a/lang/cem/cemcom/arith.c b/lang/cem/cemcom/arith.c index 04f843a21..3b780bcf6 100644 --- a/lang/cem/cemcom/arith.c +++ b/lang/cem/cemcom/arith.c @@ -164,14 +164,23 @@ any2arith(expp, oper) error("operator %s on non-numerical operand (%s)", symbol2str(oper), symbol2str(fund)); case ERRONEOUS: - free_expression(*expp); - *expp = intexpr((arith)1, INT); + erroneous2int(expp); break; } return (*expp)->ex_type->tp_fund; } +erroneous2int(expp) + struct expr **expp; +{ + /* the (erroneous) expression *expp is replaced by an + int expression + */ + free_expression(*expp); + *expp = intexpr((arith)0, INT); +} + struct expr * arith2arith(tp, oper, expr) struct type *tp; @@ -247,7 +256,7 @@ float2float(expp, tp) */ fp_used = 1; - if ((*expp)->ex_class == Float) { + if (is_fp_cst(*expp)) { (*expp)->ex_type = tp; } else { @@ -285,7 +294,7 @@ opnd2integral(expp, oper) if (fund != ERRONEOUS) error("%s operand to %s", symbol2str(fund), symbol2str(oper)); - *expp = intexpr((arith)1, INT); + erroneous2int(expp); /* fund = INT; */ } } @@ -321,7 +330,7 @@ opnd2logical(expp, oper) error("%s operand to %s", symbol2str(fund), symbol2str(oper)); case ERRONEOUS: - *expp = intexpr((arith)1, INT); + erroneous2int(expp); break; } } diff --git a/lang/cem/cemcom/ch7.c b/lang/cem/cemcom/ch7.c index 38fcbc21b..2a6d564f2 100644 --- a/lang/cem/cemcom/ch7.c +++ b/lang/cem/cemcom/ch7.c @@ -13,10 +13,6 @@ #include "Lpars.h" #include "assert.h" -#define is_zero(ex) \ - ((ex)->ex_class == Value && (ex)->VL_VALUE == (arith)0 && \ - (ex)->VL_IDF == 0) - extern char options[]; extern char *symbol2str(); @@ -262,7 +258,7 @@ ch7cast(expp, oper, tp) case NOTEQUAL: case '=': case RETURN: - if (is_zero(*expp)) + if (is_cp_cst(*expp) && (*expp)->VL_VALUE == (arith)0) break; default: warning("illegal conversion of %s to pointer", diff --git a/lang/cem/cemcom/ch7bin.c b/lang/cem/cemcom/ch7bin.c index ee30b03d5..469a01e6b 100644 --- a/lang/cem/cemcom/ch7bin.c +++ b/lang/cem/cemcom/ch7bin.c @@ -82,7 +82,7 @@ ch7bin(expp, oper, expr) fund = arithbalance(expp, oper, &expr); if (fund == DOUBLE) { error("floating operand to %%"); - *expp = intexpr((arith)1, INT); + erroneous2int(expp); } else non_commutative_binop(expp, oper, expr); @@ -235,8 +235,7 @@ pntminuspnt(expp, oper, expr) if (up_type != expr->ex_type->tp_up) { error("subtracting incompatible pointers"); free_expression(expr); - free_expression(*expp); - *expp = intexpr((arith)0, INT); + erroneous2int(expp); return; } /* we hope the optimizer will eliminate the load-time @@ -285,8 +284,7 @@ pointer_arithmetic(expp1, oper, expp2) if (any2arith(expp2, oper) == DOUBLE) { expr_error(*expp2, "illegal combination of float and pointer"); - free_expression(*expp2); - *expp2 = intexpr((arith)0, INT); + erroneous2int(expp2); } ch7bin( expp2, '*', intexpr(size_of_type((*expp1)->ex_type->tp_up, "object"), diff --git a/lang/cem/cemcom/ch7mon.c b/lang/cem/cemcom/ch7mon.c index 061db8176..3c25f3756 100644 --- a/lang/cem/cemcom/ch7mon.c +++ b/lang/cem/cemcom/ch7mon.c @@ -76,7 +76,7 @@ ch7mon(oper, expp) be used as register anymore */ if (def->df_sc == REGISTER) { - error("'&' on register variable not allowed"); + error("& on register variable not allowed"); (*expp)->ex_type = error_type; break; /* break case '&' */ } @@ -91,8 +91,9 @@ ch7mon(oper, expp) int fund = (*expp)->ex_type->tp_fund; if (fund == FLOAT || fund == DOUBLE) { - error("~ not allowed on %s operands", symbol2str(fund)); - *expp = intexpr((arith)1, INT); + error("~ not allowed on %s operands", + symbol2str(fund)); + erroneous2int(expp); break; } } diff --git a/lang/cem/cemcom/code.c b/lang/cem/cemcom/code.c index 788e4dbd4..1d0df57a1 100644 --- a/lang/cem/cemcom/code.c +++ b/lang/cem/cemcom/code.c @@ -18,7 +18,7 @@ #include "em.h" #include "level.h" #include "decspecs.h" -#include "declar.h" +#include "declarator.h" #include "Lpars.h" #include "mes.h" #include "LLlex.h" @@ -227,6 +227,13 @@ end_proc(fbytes, nbytes) C_end(ATW(nbytes)); } +do_return() +{ + /* do_return generates a direct return */ + /* isn't a jump to the return label smarter ??? */ + C_ret((arith)0); +} + do_return_expr(expr) struct expr *expr; { @@ -303,10 +310,11 @@ code_declaration(idf, expr, lvl, sc) do_ival(&(def->df_type), expr); else { /* produce blank space */ if (size <= 0) { - error("size of \"%s\" unknown", text); + error("size of %s unknown", text); size = (arith)0; } - C_bss_cst(align(size, word_align), (arith)0, 1); + C_bss_cst(align(size, word_align), + (arith)0, 1); } break; case EXTERN: diff --git a/lang/cem/cemcom/cstoper.c b/lang/cem/cemcom/cstoper.c index 414e18d67..9b4e09eb4 100644 --- a/lang/cem/cemcom/cstoper.c +++ b/lang/cem/cemcom/cstoper.c @@ -34,7 +34,7 @@ cstbin(expp, oper, expr) break; case '/': if (o2 == 0) { - error("division by 0"); + expr_error(expr, "division by 0"); break; } if (uns) { @@ -71,7 +71,7 @@ cstbin(expp, oper, expr) break; case '%': if (o2 == 0) { - error("modulo by 0"); + expr_error(expr, "modulo by 0"); break; } if (uns) { diff --git a/lang/cem/cemcom/eval.c b/lang/cem/cemcom/eval.c index d3e38a5eb..094cf6255 100644 --- a/lang/cem/cemcom/eval.c +++ b/lang/cem/cemcom/eval.c @@ -180,7 +180,7 @@ EVAL(expr, val, code, true_label, false_label) C_sbi(tp->tp_size); break; case POINTER: - if (EXPRTYPE(rightop) == POINTER) + if (rightop->ex_type->tp_fund == POINTER) C_sbs(pointer_size); else { C_ngi(rightop->ex_type->tp_size); @@ -645,7 +645,7 @@ EVAL(expr, val, code, true_label, false_label) conversion(rightop->ex_type, leftop->ex_type); break; default: - crash("(EVAL) Bad operator %s\n", symbol2str(oper)); + crash("(EVAL) bad operator %s\n", symbol2str(oper)); } /* If the rvalue of the expression is required but diff --git a/lang/cem/cemcom/expr.c b/lang/cem/cemcom/expr.c index 72c43ef74..12760689a 100644 --- a/lang/cem/cemcom/expr.c +++ b/lang/cem/cemcom/expr.c @@ -12,7 +12,7 @@ #include "LLlex.h" #include "Lpars.h" #include "decspecs.h" -#include "declar.h" +#include "declarator.h" #include "storage.h" #include "sizes.h" @@ -212,21 +212,18 @@ intexpr(ivalue, fund) the size indicated by fund. */ struct expr *expr = new_expr(); - + clear((char *)expr, sizeof(struct expr)); expr->ex_file = dot.tk_file; expr->ex_line = dot.tk_line; - + switch (fund) { - case INT: expr->ex_type = int_type; break; - case LONG: expr->ex_type = long_type; break; - case UNSIGNED: /* We cannot make a test like "ivalue <= max_unsigned" because, if sizeof(long) == int_size holds, max_unsigned @@ -237,17 +234,15 @@ intexpr(ivalue, fund) expr->ex_type = (ivalue & ~max_unsigned) ? long_type : uint_type; break; - case INTEGER: expr->ex_type = (ivalue <= max_int) ? int_type : long_type; break; - default: crash("(intexpr) bad fund %s\n", symbol2str(fund)); } expr->ex_class = Value; expr->VL_VALUE = ivalue; - + cut_size(expr); return expr; } @@ -279,13 +274,26 @@ new_oper(tp, e1, oper, e2) struct oper *op; clear((char *)expr, sizeof(struct expr)); - if (!e1 || !e2) { - expr->ex_file = dot.tk_file; - expr->ex_line = dot.tk_line; + if (e2) { + struct expr *e = e2; + + while (e->ex_class == Oper && e->OP_LEFT) + e = e->OP_LEFT; + expr->ex_file = e->ex_file; + expr->ex_line = e->ex_line; + } + else + if (e1) { + struct expr *e = e1; + + while (e->ex_class == Oper && e->OP_RIGHT) + e = e->OP_RIGHT; + expr->ex_file = e->ex_file; + expr->ex_line = e->ex_line; } else { - expr->ex_file = e2->ex_file; - expr->ex_line = e2->ex_line; + expr->ex_file = dot.tk_file; + expr->ex_line = dot.tk_line; } expr->ex_type = tp; expr->ex_class = Oper; @@ -333,7 +341,7 @@ chk_cst_expr(expp) are cast, logical operators and the expression comma. Special problems (of which there is only one, sizeof in Preprocessor #if) have to be dealt with locally - + Note that according to K&R the negation ! is illegal in constant expressions and is indeed rejected by the Ritchie compiler. @@ -369,7 +377,7 @@ chk_cst_expr(expp) if (err) { free_expression(expr); - *expp = intexpr((arith)1, INT); + erroneous2int(expp); (*expp)->ex_type = error_type; } } @@ -393,6 +401,36 @@ init_expression(eppp, expr) *eppp = &(**eppp)->OP_RIGHT; } +int +is_ld_cst(expr) + register struct expr *expr; +{ + /* An expression is a `load-time constant' if it is of the form + +/- or . + */ + return expr->ex_lvalue == 0 && expr->ex_class == Value; +} + +int +is_cp_cst(expr) + register struct expr *expr; +{ + /* An expression is a `compile-time constant' if it is a + load-time constant, and the idf is not there. + */ + return is_ld_cst(expr) && expr->VL_IDF == 0; +} + +int +is_fp_cst(expr) + register struct expr *expr; +{ + /* An expression is a `floating-point constant' if it consists + of the float only. + */ + return expr->ex_class == Float; +} + free_expression(expr) struct expr *expr; { diff --git a/lang/cem/cemcom/expr.str b/lang/cem/cemcom/expr.str index 87f611420..b322e8998 100644 --- a/lang/cem/cemcom/expr.str +++ b/lang/cem/cemcom/expr.str @@ -63,19 +63,6 @@ struct expr { #define OP_OPER ex_object.ex_oper.op_oper #define OP_RIGHT ex_object.ex_oper.op_right -#define EXPRTYPE(e) ((e)->ex_type->tp_fund) - -/* An expression is a `load-time constant' if it is of the form - +/- or ; - it is a `compile-time constant' if it is an . -*/ -#define is_ld_cst(e) ((e)->ex_lvalue == 0 && (e)->ex_class == Value) -#define is_cp_cst(e) (is_ld_cst(e) && (e)->VL_IDF == 0) - -/* a floating constant expression ? -*/ -#define is_fp_cst(e) ((e)->ex_class == Float) - /* some bits for the ex_flag field, to keep track of various interesting properties of an expression. */ diff --git a/lang/cem/cemcom/expression.g b/lang/cem/cemcom/expression.g index 94976c645..9d9a4fdb8 100644 --- a/lang/cem/cemcom/expression.g +++ b/lang/cem/cemcom/expression.g @@ -231,7 +231,7 @@ conditional_expression(struct expr **expp;) {check_conditional(e2, '=', "after :");} { ch7bin(&e1, ':', e2); - opnd2test(expp, NOTEQUAL); + opnd2test(expp, '?'); ch7bin(expp, '?', e1); } ]? diff --git a/lang/cem/cemcom/idf.c b/lang/cem/cemcom/idf.c index 9739c8a35..14868764d 100644 --- a/lang/cem/cemcom/idf.c +++ b/lang/cem/cemcom/idf.c @@ -16,7 +16,7 @@ #include "def.h" #include "type.h" #include "struct.h" -#include "declar.h" +#include "declarator.h" #include "decspecs.h" #include "sizes.h" #include "Lpars.h" @@ -333,7 +333,7 @@ declare_idf(ds, dc, lvl) case REGISTER: case AUTO: if (type->tp_size == (arith)-1) { - error("size of local \"%s\" unknown", + error("size of local %s unknown", idf->id_text); type = idf->id_def->df_type = int_type; } diff --git a/lang/cem/cemcom/ival.c b/lang/cem/cemcom/ival.c index baf2b5e65..3a5efa363 100644 --- a/lang/cem/cemcom/ival.c +++ b/lang/cem/cemcom/ival.c @@ -84,7 +84,8 @@ IVAL(tpp, expr) register struct type *tp = *tpp; switch (tp->tp_fund) { - case ARRAY: /* array initialisation */ + case ARRAY: + /* array initialisation */ if (valid_type(tp->tp_up, "array element") == 0) return 0; if (ISCOMMA(expr)) { @@ -96,10 +97,13 @@ IVAL(tpp, expr) */ if (tp->tp_up->tp_fund == CHAR && expr->ex_class == String) init_string(tpp, expr); - else /* " int i[24] = 12;" */ + else { + /* " int i[24] = 12;" */ check_and_pad(expr, tpp); + } return 0; /* nothing left */ - case STRUCT: /* struct initialisation */ + case STRUCT: + /* struct initialisation */ if (valid_type(tp, "struct") == 0) return 0; if (ISCOMMA(expr)) { @@ -109,13 +113,16 @@ IVAL(tpp, expr) /* "struct foo f = 12;" */ check_and_pad(expr, tpp); return 0; - case UNION: /* sorry, but .... */ + case UNION: + /* sorry, but .... */ error("union initialisation not allowed"); return 0; case ERRONEOUS: return 0; - default: /* fundamental type */ - if (ISCOMMA(expr)) { /* " int i = {12};" */ + default: + /* fundamental type */ + if (ISCOMMA(expr)) { + /* " int i = {12};" */ if (IVAL(tpp, expr->OP_LEFT) != 0) too_many_initialisers(expr); /* return remainings of the list for the @@ -124,10 +131,9 @@ IVAL(tpp, expr) */ return expr->OP_RIGHT; } - else { /* "int i = 12;" */ - check_ival(expr, tp); - return 0; - } + /* "int i = 12;" */ + check_ival(expr, tp); + return 0; } /* NOTREACHED */ } @@ -149,15 +155,14 @@ do_array(expr, tpp) struct expr *expr; struct type **tpp; { - /* it is certain that ISCOMMA(expr) and tp->tp_fund == ARRAY */ register struct type *tp = *tpp; register arith elem_count; - ASSERT(tp->tp_fund == ARRAY); + ASSERT(tp->tp_fund == ARRAY && ISCOMMA(expr)); /* the following test catches initialisations like char c[] = {"just a string"}; or - char d[] = {{"just another string"}} + char d[] = {{"just another string"}}; The use of the brackets causes this problem. Note: although the implementation of such initialisations is completely foolish, we did it!! (no applause, thank you) @@ -249,12 +254,11 @@ do_struct(expr, tp) struct expr *expr; struct type *tp; { - /* tp is a STRUCT and expr->OP_OPER == INITCOMMA */ - struct sdef *sd = tp->tp_sdef; arith bytes_upto_here = (arith)0; arith last_offset = (arith)-1; - + + ASSERT(tp->tp_fund == STRUCT && ISCOMMA(expr)); /* as long as there are selectors and there is an initialiser.. */ while (sd && expr) { if (ISCOMMA(expr->OP_LEFT)) { /* embraced expression */ @@ -292,7 +296,8 @@ do_struct(expr, tp) bytes_upto_here += zero_bytes(sd); if (last_offset != sd->sd_offset) { /* don't take the field-width more than once */ - bytes_upto_here += size_of_type(sd->sd_type, "selector"); + bytes_upto_here += + size_of_type(sd->sd_type, "selector"); last_offset = sd->sd_offset; } sd = sd->sd_sdef; @@ -308,7 +313,8 @@ do_struct(expr, tp) if (sd->sd_sdef) bytes_upto_here += zero_bytes(sd); /* no field thrown-outs here */ - bytes_upto_here += size_of_type(sd->sd_type, "selector"); + bytes_upto_here += + size_of_type(sd->sd_type, "selector"); } while (sd = sd->sd_sdef); } /* keep on aligning... */ @@ -440,8 +446,8 @@ check_ival(expr, type) { /* The philosophy here is that ch7cast puts an explicit conversion node in front of the expression if the types - are not compatible. In this case, the initialisation is - not legal. ??? + are not compatible. In this case, the initialisation + expression is no longer a constant. */ switch (type->tp_fund) { @@ -449,31 +455,24 @@ check_ival(expr, type) case SHORT: case INT: case LONG: - if (expr->ex_class == Oper || expr->VL_IDF != 0) { + case ENUM: + ch7cast(&expr, '=', type); + if (expr->ex_class != Value || expr->VL_IDF != 0) { illegal_init_cst(expr); break; } - ch7cast(&expr, '=', type); con_int(expr); break; #ifndef NOBITFIELD case FIELD: - if (expr->ex_class == Oper || expr->VL_IDF != 0) { + ch7cast(&expr, '=', type->tp_up); + if (expr->ex_class != Value || expr->VL_IDF != 0) { illegal_init_cst(expr); break; } - ch7cast(&expr, '=', type->tp_up); put_bf(type, expr->VL_VALUE); break; #endif NOBITFIELD - case ENUM: - if (expr->ex_class == Oper) { - illegal_init_cst(expr); - break; - } - ch7cast(&expr, '=', type); - con_int(expr); - break; case FLOAT: case DOUBLE: ch7cast(&expr, '=', type); @@ -482,10 +481,11 @@ check_ival(expr, type) else if (expr->ex_class == Oper && expr->OP_OPER == INT2FLOAT) { expr = expr->OP_RIGHT; - if (expr->ex_class == Value && expr->VL_IDF == 0) - C_con_fcon(itos(expr->VL_VALUE), type->tp_size); - else + if (expr->ex_class != Value || expr->VL_IDF != 0) { illegal_init_cst(expr); + break; + } + C_con_fcon(itos(expr->VL_VALUE), type->tp_size); } else illegal_init_cst(expr); diff --git a/lang/cem/cemcom/statement.g b/lang/cem/cemcom/statement.g index e35ac980b..af127420b 100644 --- a/lang/cem/cemcom/statement.g +++ b/lang/cem/cemcom/statement.g @@ -108,20 +108,19 @@ if_statement '(' expression(&expr) { - opnd2test(&expr, NOTEQUAL); - if (expr->ex_class != Value) { - /* What's happening here? If the - expression consisted of a constant - expression, the comparison has - been optimized to a 0 or 1. + opnd2test(&expr, IF); + if (is_cp_cst(expr)) { + /* The comparison has been optimized + to a 0 or 1. */ - code_expr(expr, RVAL, TRUE, l_true, l_false); - C_df_ilb(l_true); - } - else { if (expr->VL_VALUE == (arith)0) { C_bra(l_false); } + /* else fall through */ + } + else { + code_expr(expr, RVAL, TRUE, l_true, l_false); + C_df_ilb(l_true); } free_expression(expr); } @@ -159,16 +158,16 @@ while_statement '(' expression(&expr) { - opnd2test(&expr, NOTEQUAL); - if (expr->ex_class != Value) { - code_expr(expr, RVAL, TRUE, l_body, l_break); - C_df_ilb(l_body); - } - else { + opnd2test(&expr, WHILE); + if (is_cp_cst(expr)) { if (expr->VL_VALUE == (arith)0) { C_bra(l_break); } } + else { + code_expr(expr, RVAL, TRUE, l_body, l_break); + C_df_ilb(l_body); + } } ')' statement @@ -198,15 +197,15 @@ do_statement } expression(&expr) { - opnd2test(&expr, NOTEQUAL); - if (expr->ex_class != Value) { - code_expr(expr, RVAL, TRUE, l_body, l_break); - } - else { + opnd2test(&expr, WHILE); + if (is_cp_cst(expr)) { if (expr->VL_VALUE == (arith)1) { C_bra(l_body); } } + else { + code_expr(expr, RVAL, TRUE, l_body, l_break); + } C_df_ilb(l_break); } ')' @@ -240,16 +239,16 @@ for_statement [ expression(&e_test) { - opnd2test(&e_test, NOTEQUAL); - if (e_test->ex_class != Value) { - code_expr(e_test, RVAL, TRUE, l_body, l_break); - C_df_ilb(l_body); - } - else { + opnd2test(&e_test, FOR); + if (is_cp_cst(e_test)) { if (e_test->VL_VALUE == (arith)0) { C_bra(l_break); } } + else { + code_expr(e_test, RVAL, TRUE, l_body, l_break); + C_df_ilb(l_body); + } } ]? ';' @@ -276,9 +275,8 @@ switch_statement : SWITCH '(' - expression(&expr) /* this must be an integer expression! */ + expression(&expr) { - ch7cast(&expr, CAST, int_type); code_startswitch(expr); } ')' @@ -297,7 +295,7 @@ case_statement CASE constant_expression(&expr) { - code_case(expr->VL_VALUE); + code_case(expr); free_expression(expr); } ':' @@ -348,7 +346,7 @@ return_statement | empty { - C_ret((arith)0); + do_return(); } ] ';' diff --git a/lang/cem/cemcom/struct.c b/lang/cem/cemcom/struct.c index 752bcdf87..6b1945873 100644 --- a/lang/cem/cemcom/struct.c +++ b/lang/cem/cemcom/struct.c @@ -396,7 +396,7 @@ add_field(szp, fd, pfd_type, idf, stp) case LONG: /* right type; size OK? */ if ((*pfd_type)->tp_size > word_size) { - error("bit field type %s doesn't fit in word", + error("bit field type %s does not fit in a word", symbol2str((*pfd_type)->tp_fund)); *pfd_type = error_type; return field_offset; diff --git a/lang/cem/cemcom/switch.c b/lang/cem/cemcom/switch.c index 8a695de2f..ba0c7458f 100644 --- a/lang/cem/cemcom/switch.c +++ b/lang/cem/cemcom/switch.c @@ -5,6 +5,7 @@ #include "botch_free.h" #include "density.h" +#include "Lpars.h" #include "idf.h" #include "label.h" #include "arith.h" @@ -16,6 +17,8 @@ #include "type.h" #include "em.h" +extern char options[]; + #define compact(nr, low, up) (nr != 0 && (up - low) / nr <= (DENSITY - 1)) static struct switch_hdr *switch_stack = 0; @@ -23,19 +26,32 @@ static struct switch_hdr *switch_stack = 0; code_startswitch(expr) struct expr *expr; { - /* stack a new case header and fill in the necessary fields. + /* Check the expression, stack a new case header and + fill in the necessary fields. */ register label l_table = text_label(); register label l_break = text_label(); register struct switch_hdr *sh = new_switch_hdr(); - + int fund = any2arith(&expr, SWITCH); /* INT, LONG or DOUBLE */ + + switch (fund) { + case LONG: + if (options['R']) + warning("long in switch"); + break; + case DOUBLE: + error("float/double in switch"); + erroneous2int(&expr); + break; + } + stat_stack(l_break, NO_LABEL); sh->sh_break = l_break; sh->sh_default = 0; sh->sh_table = l_table; sh->sh_nrofentries = 0; sh->sh_type = expr->ex_type; /* the expression switched */ - sh->sh_lowerbd = sh->sh_upperbd = (arith)0; /* ??? */ + sh->sh_lowerbd = sh->sh_upperbd = (arith)0; /* immaterial ??? */ sh->sh_entries = (struct case_entry *) 0; /* case-entry list */ sh->next = switch_stack; /* push onto switch-stack */ switch_stack = sh; @@ -48,7 +64,7 @@ code_endswitch() { register struct switch_hdr *sh = switch_stack; register label tablabel; - register struct case_entry *ce, *tmp; + register struct case_entry *ce; if (sh->sh_default == 0) /* no default occurred yet */ sh->sh_default = sh->sh_break; @@ -88,33 +104,42 @@ code_endswitch() } C_df_ilb(sh->sh_break); switch_stack = sh->next; /* unstack the switch descriptor */ + /* free the allocated switch structure */ - for (ce = sh->sh_entries; ce; ce = tmp) { - tmp = ce->next; + ce = sh->sh_entries; + while (ce) { + register struct case_entry *tmp = ce->next; free_case_entry(ce); + ce = tmp; } free_switch_hdr(sh); stat_unstack(); } -code_case(val) - arith val; +code_case(expr) + struct expr *expr; { + register arith val; register struct case_entry *ce; register struct switch_hdr *sh = switch_stack; - + if (sh == 0) { error("case statement not in switch"); return; } + + expr->ex_type = sh->sh_type; + cut_size(expr); + ce = new_case_entry(); C_df_ilb(ce->ce_label = text_label()); - ce->ce_value = val; + ce->ce_value = val = expr->VL_VALUE; + if (sh->sh_entries == 0) { /* first case entry */ ce->next = (struct case_entry *) 0; sh->sh_entries = ce; - sh->sh_lowerbd = sh->sh_upperbd = ce->ce_value; + sh->sh_lowerbd = sh->sh_upperbd = val; sh->sh_nrofentries = 1; } else { @@ -138,7 +163,8 @@ code_case(val) insert ce right after the head 3: c1 == 0 && c2 != 0: append ce to last element - The case c1 == 0 && c2 == 0 cannot occur! + The case c1 == 0 && c2 == 0 cannot occur, since + the list is guaranteed not to be empty. */ if (c1) { if (c1->ce_value == ce->ce_value) {