safety commit

This commit is contained in:
ceriel
1986-04-09 18:14:49 +00:00
parent 6ef38e3483
commit 6ca5eb658d
13 changed files with 365 additions and 130 deletions

View File

@@ -7,6 +7,7 @@ static char *RcsId = "$Header$";
#include <em_arith.h>
#include <em_label.h>
#include <assert.h>
#include <alloc.h>
#include "idf.h"
#include "type.h"
#include "def.h"
@@ -14,6 +15,8 @@ static char *RcsId = "$Header$";
#include "node.h"
#include "Lpars.h"
#include "scope.h"
#include "const.h"
#include "standards.h"
int
chk_expr(expp, const)
@@ -60,10 +63,13 @@ int
chk_set(expp, const)
register struct node *expp;
{
/* Check the legality of a SET aggregate, and try to evaluate it
compile time. Unfortunately this is all rather complicated.
*/
struct type *tp;
struct def *df;
register struct node *nd;
extern struct def *findname();
arith *set;
assert(expp->nd_symb == SET);
@@ -72,7 +78,9 @@ chk_set(expp, const)
if (expp->nd_left) {
/* A type was given. Check it out
*/
df = findname(expp->nd_left);
(void) findname(expp->nd_left);
assert(expp->nd_left->nd_class == Def);
df = expp->nd_left->nd_def;
if ((df->df_kind != D_TYPE && df->df_kind != D_ERROR) ||
(df->df_type->tp_fund != SET)) {
node_error(expp, "Illegal set type");
@@ -82,48 +90,79 @@ chk_set(expp, const)
}
else tp = bitset_type;
/* Now check the elements given
/* Now check the elements given, and try to compute a constant set.
*/
set = (arith *) Malloc(tp->tp_size * sizeof(arith) / wrd_size);
nd = expp->nd_right;
while (nd) {
assert(nd->nd_class == Link && nd->nd_symb == ',');
if (!chk_el(nd->nd_left, const, tp->next, 0)) return 0;
if (!chk_el(nd->nd_left, const, tp->next, &set)) return 0;
nd = nd->nd_right;
}
expp->nd_type = tp;
assert(!const || set);
if (set) {
/* Yes, in was a constant set, and we managed to compute it!
*/
expp->nd_class = Set;
expp->nd_set = set;
FreeNode(expp->nd_left);
FreeNode(expp->nd_right);
expp->nd_left = expp->nd_right = 0;
}
return 1;
}
int
chk_el(expp, const, tp, level)
struct node *expp;
chk_el(expp, const, tp, set)
register struct node *expp;
struct type *tp;
arith **set;
{
/* Check elements of a set. This routine may call itself
recursively, but only once.
recursively.
Also try to compute the set!
*/
if (expp->nd_class == Link && expp->nd_symb == UPTO) {
/* { ... , expr1 .. expr2, ... } */
if (level) {
node_error(expp, "Illegal set element");
return 0;
}
if (!chk_el(expp->nd_left, const, tp, 1) ||
!chk_el(expp->nd_right, const, tp, 1)) {
/* { ... , expr1 .. expr2, ... }
First check expr1 and expr2, and try to compute them.
*/
if (!chk_el(expp->nd_left, const, tp, set) ||
!chk_el(expp->nd_right, const, tp, set)) {
return 0;
}
if (expp->nd_left->nd_class == Value &&
expp->nd_right->nd_class == Value) {
/* We have a constant range. Put all elements in the
set
*/
register int i;
if (expp->nd_left->nd_INT > expp->nd_right->nd_INT) {
node_error(expp, "Lower bound exceeds upper bound in range");
return 0;
return rem_set(set);
}
if (*set) for (i = expp->nd_left->nd_INT + 1;
i < expp->nd_right->nd_INT; i++) {
(*set)[i/wrd_bits] |= (1 << (i % wrd_bits));
}
}
else if (*set) {
free(*set);
*set = 0;
}
return 1;
}
if (!chk_expr(expp, const)) return 0;
/* Here, a single element is checked
*/
if (!chk_expr(expp, const)) {
return rem_set(set);
}
if (!TstCompat(tp, expp->nd_type)) {
node_error(expp, "Set element has incompatible type");
return 0;
return rem_set(set);
}
if (expp->nd_class == Value) {
if ((tp->tp_fund != ENUMERATION &&
@@ -133,24 +172,104 @@ node_error(expp, "Lower bound exceeds upper bound in range");
(expp->nd_INT < 0 || expp->nd_INT > tp->enm_ncst))
) {
node_error(expp, "Set element out of range");
#ifdef DEBUG
debug("%d (%d, %d)", (int) expp->nd_INT, (int) tp->sub_lb, (int) tp->sub_ub);
#endif
return 0;
return rem_set(set);
}
if (*set) (*set)[expp->nd_INT/wrd_bits] |= (1 << (expp->nd_INT%wrd_bits));
}
return 1;
}
int
rem_set(set)
arith **set;
{
/* This routine is only used for error exits of chk_el.
It frees the set indicated by "set", and returns 0.
*/
if (*set) {
free((char *) *set);
*set = 0;
}
return 0;
}
int
chk_call(expp, const)
register struct node *expp;
{
/* ??? */
return 1;
register struct type *tp;
register struct node *left;
expp->nd_type = error_type;
(void) findname(expp->nd_left);
left = expp->nd_left;
tp = left->nd_type;
if (tp == error_type) return 0;
if (left->nd_class == Def &&
(left->nd_def->df_kind & (D_HTYPE|D_TYPE|D_HIDDEN))) {
/* A type cast. This is of course not portable.
No runtime action. Remove it.
*/
if (!expp->nd_right ||
(expp->nd_right->nd_symb == ',')) {
node_error(expp, "Only one parameter expected in type cast");
return 0;
}
if (! chk_expr(expp->nd_right, const)) return 0;
if (expp->nd_right->nd_type->tp_size !=
left->nd_type->tp_size) {
node_error(expp, "Size of type in type cast does not match size of operand");
return 0;
}
expp->nd_right->nd_type = left->nd_type;
left = expp->nd_right;
FreeNode(expp->nd_left);
*expp = *(expp->nd_right);
left->nd_left = left->nd_right = 0;
FreeNode(left);
return 1;
}
if ((left->nd_class == Def && left->nd_def->df_kind == D_PROCEDURE) ||
tp->tp_fund == PROCVAR) {
/* A procedure call. it may also be a call to a
standard procedure
*/
if (tp == std_type) {
assert(left->nd_class == Def);
switch(left->nd_def->df_value.df_stdname) {
case S_ABS:
case S_CAP:
case S_CHR:
case S_FLOAT:
case S_HIGH:
case S_MAX:
case S_MIN:
case S_ODD:
case S_ORD:
case S_SIZE:
case S_TRUNC:
case S_VAL:
break;
case S_DEC:
case S_INC:
case S_HALT:
case S_EXCL:
case S_INCL:
expp->nd_type = 0;
break;
default:
assert(0);
}
return 1;
}
return 1;
}
node_error(expp->nd_left, "procedure, type, or function expected");
return 0;
}
struct def *
findname(expp)
register struct node *expp;
{
@@ -159,41 +278,66 @@ findname(expp)
*/
register struct def *df;
struct def *lookfor();
register struct node *nd;
register struct type *tp;
int scope;
int module;
expp->nd_type = error_type;
if (expp->nd_class == Name) {
return lookfor(expp, CurrentScope, 1);
expp->nd_def = lookfor(expp, CurrentScope, 1);
expp->nd_class = Def;
expp->nd_type = expp->nd_def->df_type;
return;
}
assert(expp->nd_class == Link && expp->nd_symb == '.');
assert(expp->nd_left->nd_class == Name);
df = lookfor(expp->nd_left, CurrentScope, 1);
if (df->df_kind == D_ERROR) return df;
nd = expp;
while (nd->nd_class == Link) {
struct node *nd1;
if (!(scope = has_selectors(df))) {
node_error(nd, "identifier \"%s\" has no selectors",
df->df_idf->id_text);
return ill_df;
if (expp->nd_class == Link) {
assert(expp->nd_symb == '.');
assert(expp->nd_right->nd_class == Name);
findname(expp->nd_left);
tp = expp->nd_left->nd_type;
if (tp == error_type) {
df = ill_df;
}
nd = nd->nd_right;
if (nd->nd_class == Name) nd1 = nd;
else nd1 = nd->nd_left;
module = (df->df_kind == D_MODULE);
df = lookup(nd1->nd_IDF, scope);
else if (tp->tp_fund != RECORD) {
/* This is also true for modules */
node_error(expp,"Illegal selection");
df = ill_df;
}
else df = lookup(expp->nd_right->nd_IDF, tp->rec_scope);
if (!df) {
id_not_declared(nd1);
return ill_df;
df = ill_df;
id_not_declared(expp->nd_right);
}
if (module && !(df->df_flags&(D_EXPORTED|D_QEXPORTED))) {
node_error(nd1, "identifier \"%s\" not exprted from qualifying module",
else if (df != ill_df) {
expp->nd_type = df->df_type;
if (!(df->df_flags & (D_EXPORTED|D_QEXPORTED))) {
node_error(expp->nd_right,
"identifier \"%s\" not exprted from qualifying module",
df->df_idf->id_text);
}
}
if (expp->nd_left->nd_class == Def) {
expp->nd_class = Def;
expp->nd_def = df;
FreeNode(expp->nd_left);
FreeNode(expp->nd_right);
expp->nd_left = expp->nd_right = 0;
}
return;
}
return df;
if (expp->nd_class == Oper) {
assert(expp->nd_symb == '[');
(void) findname(expp->nd_left);
if (chk_expr(expp->nd_right, 0) &&
expp->nd_left->nd_type != error_type &&
chk_oper(expp)) /* ??? */ ;
return 1;
}
if (expp->nd_class == Uoper && expp->nd_symb == '^') {
(void) findname(expp->nd_right);
if (expp->nd_right->nd_type != error_type &&
chk_uoper(expp)) /* ??? */ ;
}
return 0;
}
int
@@ -203,16 +347,14 @@ chk_name(expp, const)
register struct def *df;
int retval = 1;
df = findname(expp);
(void) findname(expp);
assert(expp->nd_class == Def);
df = expp->nd_def;
if (df->df_kind == D_ERROR) {
retval = 0;
}
expp->nd_type = df->df_type;
if (df->df_kind == D_ENUM || df->df_kind == D_CONST) {
if (expp->nd_left) FreeNode(expp->nd_left);
if (expp->nd_right) FreeNode(expp->nd_right);
if (df->df_kind & (D_ENUM | D_CONST)) {
if (df->df_kind == D_ENUM) {
expp->nd_left = expp->nd_right = 0;
expp->nd_class = Value;
expp->nd_INT = df->enm_val;
expp->nd_symb = INTEGER;
@@ -251,10 +393,11 @@ chk_oper(expp, const)
expp->nd_right->nd_type = tpr = tpl;
}
}
expp->nd_type = error_type;
if (expp->nd_symb == IN) {
/* Handle this one specially */
expp->nd_type == bool_type;
expp->nd_type = bool_type;
if (tpr->tp_fund != SET) {
node_error(expp, "RHS of IN operator not a SET type");
return 0;
@@ -266,6 +409,21 @@ node_error(expp, "IN operator: type of LHS not compatible with element type of R
return 1;
}
if (expp->nd_symb == '[') {
/* Handle ARRAY selection specially too! */
if (tpl->tp_fund != ARRAY) {
node_error(expp, "array index not belonging to an ARRAY");
return 0;
}
if (!TstCompat(tpl->next, tpr)) {
node_error(expp, "incompatible index type");
return 0;
}
expp->nd_type = tpl->arr_elem;
if (const) return 0;
return 1;
}
if (tpl->tp_fund == SUBRANGE) tpl = tpl->next;
expp->nd_type = tpl;
@@ -450,6 +608,11 @@ chk_uoper(expp, const)
return 1;
}
break;
case '^':
if (tpr->tp_fund != POINTER) break;
expp->nd_type = tpr->next;
if (const) return 0;
return 1;
default:
assert(0);
}