improved error reporting for initialization expressions

miscellaneous changes
This commit is contained in:
dick 1986-03-14 16:15:16 +00:00
parent 6e53274b6a
commit c80f2c0817
15 changed files with 197 additions and 136 deletions

View file

@ -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;
}
}

View file

@ -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",

View file

@ -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"),

View file

@ -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;
}
}

View file

@ -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:

View file

@ -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) {

View file

@ -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

View file

@ -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;
{

View file

@ -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.
*/

View file

@ -231,7 +231,7 @@ conditional_expression(struct expr **expp;)
{check_conditional(e2, '=', "after :");}
{
ch7bin(&e1, ':', e2);
opnd2test(expp, NOTEQUAL);
opnd2test(expp, '?');
ch7bin(expp, '?', e1);
}
]?

View file

@ -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;
}

View file

@ -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);

View file

@ -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();
}
]
';'

View file

@ -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;

View file

@ -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) {