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