improved error reporting for initialization expressions
miscellaneous changes
This commit is contained in:
parent
6e53274b6a
commit
c80f2c0817
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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"),
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
<idf> +/- <integral> or <integral>.
|
||||
*/
|
||||
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;
|
||||
{
|
||||
|
|
|
@ -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
|
||||
<idf> +/- <integral> or <integral>;
|
||||
it is a `compile-time constant' if it is an <integral>.
|
||||
*/
|
||||
#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.
|
||||
*/
|
||||
|
|
|
@ -231,7 +231,7 @@ conditional_expression(struct expr **expp;)
|
|||
{check_conditional(e2, '=', "after :");}
|
||||
{
|
||||
ch7bin(&e1, ':', e2);
|
||||
opnd2test(expp, NOTEQUAL);
|
||||
opnd2test(expp, '?');
|
||||
ch7bin(expp, '?', e1);
|
||||
}
|
||||
]?
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
]
|
||||
';'
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) {
|
||||
|
|
Loading…
Reference in a new issue