From f70dfe4d00678d184413aaa12fb00f702ef3577b Mon Sep 17 00:00:00 2001 From: dick Date: Thu, 2 Feb 1989 13:57:07 +0000 Subject: [PATCH] better evaluation order checking in expressions --- lang/cem/cemcom/Makefile | 11 +- lang/cem/cemcom/ch7.c | 2 +- lang/cem/cemcom/ch7mon.c | 9 +- lang/cem/cemcom/code.c | 2 +- lang/cem/cemcom/eval.c | 6 +- lang/cem/cemcom/expr.str | 5 +- lang/cem/cemcom/interface.h | 4 +- lang/cem/cemcom/ival.g | 3 +- lang/cem/cemcom/l_comment.c | 22 ++- lang/cem/cemcom/l_ev_ord.c | 69 ++++---- lang/cem/cemcom/l_lint.c | 332 ++++++++++++++++++++++-------------- lang/cem/cemcom/l_lint.h | 1 + lang/cem/cemcom/l_misc.c | 11 +- lang/cem/cemcom/l_outdef.c | 22 ++- lang/cem/cemcom/l_state.str | 1 + lang/cem/cemcom/l_states.c | 94 ++++++---- 16 files changed, 367 insertions(+), 227 deletions(-) diff --git a/lang/cem/cemcom/Makefile b/lang/cem/cemcom/Makefile index 8cd000fa5..b964ac109 100644 --- a/lang/cem/cemcom/Makefile +++ b/lang/cem/cemcom/Makefile @@ -126,7 +126,7 @@ LINT = /usr/bin/lint LINTFLAGS = MYLINT = ../lpass2/lint -MYLINTFLAGS = #-xh +MYLINTFLAGS = -xh #EXCLEXCLEXCLEXCL @@ -800,6 +800,7 @@ l_lint.o: def.h l_lint.o: expr.h l_lint.o: file_info.h l_lint.o: idf.h +l_lint.o: interface.h l_lint.o: l_lint.h l_lint.o: l_outdef.h l_lint.o: l_state.h @@ -822,6 +823,7 @@ l_states.o: def.h l_states.o: expr.h l_states.o: file_info.h l_states.o: idf.h +l_states.o: interface.h l_states.o: l_brace.h l_states.o: l_comment.h l_states.o: l_lint.h @@ -844,6 +846,7 @@ l_misc.o: def.h l_misc.o: expr.h l_misc.o: file_info.h l_misc.o: idf.h +l_misc.o: interface.h l_misc.o: l_state.h l_misc.o: label.h l_misc.o: level.h @@ -864,6 +867,7 @@ l_ev_ord.o: def.h l_ev_ord.o: expr.h l_ev_ord.o: file_info.h l_ev_ord.o: idf.h +l_ev_ord.o: interface.h l_ev_ord.o: l_lint.h l_ev_ord.o: l_state.h l_ev_ord.o: label.h @@ -879,12 +883,14 @@ l_outdef.o: LLlex.h l_outdef.o: Lpars.h l_outdef.o: arith.h l_outdef.o: assert.h +l_outdef.o: code.h l_outdef.o: debug.h l_outdef.o: def.h l_outdef.o: expr.h l_outdef.o: field.h l_outdef.o: file_info.h l_outdef.o: idf.h +l_outdef.o: interface.h l_outdef.o: l_class.h l_outdef.o: l_comment.h l_outdef.o: l_lint.h @@ -900,6 +906,8 @@ l_outdef.o: stack.h l_outdef.o: struct.h l_outdef.o: type.h l_comment.o: arith.h +l_comment.o: interface.h +l_comment.o: l_comment.h l_comment.o: l_state.h l_comment.o: lint.h l_comment.o: spec_arith.h @@ -991,7 +999,6 @@ ival.o: LLlex.h ival.o: Lpars.h ival.o: arith.h ival.o: assert.h -ival.o: code.h ival.o: debug.h ival.o: def.h ival.o: estack.h diff --git a/lang/cem/cemcom/ch7.c b/lang/cem/cemcom/ch7.c index b231f2664..cbe52a115 100644 --- a/lang/cem/cemcom/ch7.c +++ b/lang/cem/cemcom/ch7.c @@ -258,7 +258,7 @@ ch7cast(expp, oper, tp) expr_warning(*expp, "incompatible pointers in %s", symbol2str(oper)); #ifdef LINT - if (oper == CAST) + if (oper != CAST) lint_ptr_conv(oldtp->tp_up->tp_fund, tp->tp_up->tp_fund); #endif LINT (*expp)->ex_type = tp; /* free conversion */ diff --git a/lang/cem/cemcom/ch7mon.c b/lang/cem/cemcom/ch7mon.c index cff0b8053..acdf50e93 100644 --- a/lang/cem/cemcom/ch7mon.c +++ b/lang/cem/cemcom/ch7mon.c @@ -71,9 +71,7 @@ ch7mon(oper, expp) expr_error(*expp, "& applied to non-lvalue"); else { /* assume that enums are already filtered out */ - if ( (*expp)->ex_class == Value - && (*expp)->VL_CLASS == Name - ) { + if (ISNAME(*expp)) { register struct def *def = (*expp)->VL_IDF->id_def; @@ -147,10 +145,7 @@ ch7mon(oper, expp) ch7incr(expp, oper); break; case SIZEOF: - if ( (*expp)->ex_class == Value - && (*expp)->VL_CLASS == Name - && (*expp)->VL_IDF->id_def->df_formal_array - ) + if (ISNAME(*expp) && (*expp)->VL_IDF->id_def->df_formal_array) warning("sizeof formal array %s is sizeof pointer!", (*expp)->VL_IDF->id_text); expr = intexpr((*expp)->ex_type == string_type ? diff --git a/lang/cem/cemcom/code.c b/lang/cem/cemcom/code.c index f13b17c81..157f76f4d 100644 --- a/lang/cem/cemcom/code.c +++ b/lang/cem/cemcom/code.c @@ -559,7 +559,7 @@ code_expr(expr, val, code, tlbl, flbl) C_lin((arith)(expr->ex_line)); EVAL(expr, val, code, tlbl, flbl); #else LINT - pre_lint_expr(expr, RVAL, code ? USED : IGNORED); + lint_expr(expr, code ? USED : IGNORED); #endif LINT } diff --git a/lang/cem/cemcom/eval.c b/lang/cem/cemcom/eval.c index aa32e8464..c782518d6 100644 --- a/lang/cem/cemcom/eval.c +++ b/lang/cem/cemcom/eval.c @@ -453,7 +453,7 @@ EVAL(expr, val, code, true_label, false_label) arith ParSize = (arith)0; label setjmp_label = 0; - if (left->ex_class == Value && left->VL_CLASS == Name) { + if (ISNAME(left)) { if (left->VL_IDF->id_special == SP_SETJMP) { label addr_label = data_label(); @@ -480,7 +480,7 @@ EVAL(expr, val, code, true_label, false_label) NO_LABEL, NO_LABEL); ParSize += ATW(ex->ex_type->tp_size); } - if (left->ex_class == Value && left->VL_CLASS == Name) { + if (ISNAME(left)) { /* e.g., main() { (*((int (*)())0))(); } */ C_cal(left->VL_IDF->id_text); if (setjmp_label) { @@ -913,7 +913,7 @@ load_val(expr, rlval) register struct idf *id = expr->VL_IDF; register struct def *df = id->id_def; - ASSERT(expr->VL_CLASS == Name); + ASSERT(ISNAME(expr)); if (df->df_type->tp_fund == FUNCTION) { /* the previous statement tried to catch a function identifier, which may be cast to a pointer to a diff --git a/lang/cem/cemcom/expr.str b/lang/cem/cemcom/expr.str index 3865ab28f..3cc232707 100644 --- a/lang/cem/cemcom/expr.str +++ b/lang/cem/cemcom/expr.str @@ -104,8 +104,11 @@ struct expr { #define NILEXPR ((struct expr *)0) +/* some useful tests */ +#define ISNAME(e) ((e)->ex_class == Value && (e)->VL_CLASS == Name) +#define ISCOMMA(e) ((e)->ex_class == Oper && (e)->OP_OPER == INITCOMMA) + extern struct expr *intexpr(), *new_oper(); /* ALLOCDEF "expr" 20 */ -#define ISCOMMA(e) ((e)->ex_class == Oper && (e)->OP_OPER == INITCOMMA) diff --git a/lang/cem/cemcom/interface.h b/lang/cem/cemcom/interface.h index 6c9037991..e75dd7749 100644 --- a/lang/cem/cemcom/interface.h +++ b/lang/cem/cemcom/interface.h @@ -3,6 +3,6 @@ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands. * See the copyright notice in the ACK home directory, in the file "Copyright". */ -#define PRIVATE -#define IMPORT extern +#define PRIVATE /*static /* or not */ +#define IMPORT extern #define EXPORT diff --git a/lang/cem/cemcom/ival.g b/lang/cem/cemcom/ival.g index 3d78418a3..79a64e0c8 100644 --- a/lang/cem/cemcom/ival.g +++ b/lang/cem/cemcom/ival.g @@ -27,7 +27,6 @@ #include "LLlex.h" #include "noRoption.h" #include "estack.h" -#include "code.h" #ifdef LINT #include "l_lint.h" #endif LINT @@ -54,7 +53,7 @@ initial_value(register struct type **tpp; register struct expr **expp;) : assignment_expression(expp) { #ifdef LINT - pre_lint_expr(*expp, RVAL, USED); + lint_expr(*expp, USED); #endif LINT if ((*expp)->ex_type->tp_fund == ARRAY) array2pointer(*expp); diff --git a/lang/cem/cemcom/l_comment.c b/lang/cem/cemcom/l_comment.c index 64e8ed753..a2a74afc4 100644 --- a/lang/cem/cemcom/l_comment.c +++ b/lang/cem/cemcom/l_comment.c @@ -12,6 +12,7 @@ #ifdef LINT #include +#include "interface.h" #include "arith.h" #include "l_state.h" #include "l_comment.h" @@ -24,13 +25,15 @@ extern char loptions[]; one token later. */ -static int notreached; -static int varargsN = -1; -static int argsused; -static int formatN; -static int formatVAR; -static char *format; -static char *prev_format; +PRIVATE int notreached; +PRIVATE int varargsN = -1; +PRIVATE int argsused; +PRIVATE int formatN; +PRIVATE int formatVAR; +PRIVATE char *format; +PRIVATE char *prev_format; + +PRIVATE make_format(); int LINTLIB; /* file is lint library */ int s_NOTREACHED; /* statement not reached */ @@ -71,8 +74,8 @@ lint_comment_function() formatVAR = 0; } -static char buf[1000]; -static char *bufpos; /* next free position in buf */ +PRIVATE char buf[1000]; +PRIVATE char *bufpos; /* next free position in buf */ lint_start_comment() { @@ -139,6 +142,7 @@ lint_end_comment() #define LETGIT 1 #define LETGITSPACE 2 +PRIVATE make_format(argn, oldf) int argn; char *oldf; diff --git a/lang/cem/cemcom/l_ev_ord.c b/lang/cem/cemcom/l_ev_ord.c index 182f40f64..c0cfe4c49 100644 --- a/lang/cem/cemcom/l_ev_ord.c +++ b/lang/cem/cemcom/l_ev_ord.c @@ -10,6 +10,7 @@ #ifdef LINT #include /* for st_free */ +#include "interface.h" #include "assert.h" #include "arith.h" /* definition arith */ #include "label.h" /* definition label */ @@ -28,42 +29,56 @@ extern char *symbol2str(); -check_and_merge(espp, esp, com_oper) +PRIVATE check_ev_order(); + +check_and_merge(expr, espp, esp) + struct expr *expr; struct expr_state **espp, *esp; { -/* Checks for undefined evaluation orders in case of a commutative operator. +/* Checks for undefined evaluation orders in case of a non-sequencing operator. * In addition the sets of used and set variables of both expressions are * united. * *espp will be pointing to this new list. esp is used for this list. */ register struct expr_state **pp, *p1, *p2; + int oper = expr->OP_OPER; + int is_sequencer = + (oper == '?' || oper == OR || oper == AND || oper ==','); for (p1 = *espp; p1; p1 = p1->next) { + /* scan the list esp for the same variable */ p2 = esp; pp = &esp; while (p2) { - if ( /* p1 and p2 are the same */ + if ( /* p1 and p2 refer to the same location */ p1->es_idf == p2->es_idf && p1->es_offset == p2->es_offset ) { - if (com_oper) - check_ev_order(p1, p2, com_oper); + /* check */ + if (!is_sequencer) + check_ev_order(p1, p2, expr); + + /* merge the info */ p1->es_used |= p2->es_used; + p1->es_referred |= p2->es_referred; p1->es_set |= p2->es_set; + + /* and remove the entry from esp */ *pp = p2->next; free_expr_state(p2); p2 = *pp; } else { + /* skip over the entry in esp */ pp = &p2->next; p2 = p2->next; } } } - /* The rest of the list esp is pointing to, is put in front of the list - * *espp is now pointing to. - * *espp will be pointing to this new list. - */ + /* If there is anything left in the list esp, this is put in + front of the list *espp is now pointing to, and *espp will be + left pointing to this new list. + */ if (!esp) return; p1 = *espp; @@ -73,44 +88,20 @@ check_and_merge(espp, esp, com_oper) esp->next = p1; } -check_ev_order(esp1, esp2, com_oper) +PRIVATE +check_ev_order(esp1, esp2, expr) struct expr_state *esp1, *esp2; + struct expr *expr; { if ( (esp1->es_used && esp2->es_set) || (esp1->es_set && esp2->es_used) || (esp1->es_set && esp2->es_set) ) { - warning("result of %s depends on evaluation order on %s", - symbol2str(com_oper), + expr_warning(expr, + "result of %s depends on evaluation order on %s", + symbol2str(expr->OP_OPER), esp1->es_idf->id_text); } } -add_expr_state(value, to_state, espp) - struct value value; - struct expr_state **espp; -{ - register struct expr_state *esp = *espp; - - ASSERT(value.vl_class == Name); - while ( esp - && !( esp->es_idf == value.vl_data.vl_idf - && esp->es_offset == value.vl_value - ) - ) { - esp = esp->next; - } - if (!esp) { /* create new expr_state */ - esp = new_expr_state(); - esp->es_idf = value.vl_data.vl_idf; - esp->es_offset = value.vl_value; - esp->next = *espp; - *espp = esp; - } - if (to_state == SET) - esp->es_set = 1; - else /* USED */ - esp->es_used = 1; -} - #endif LINT diff --git a/lang/cem/cemcom/l_lint.c b/lang/cem/cemcom/l_lint.c index f28e47f64..b591e11f3 100644 --- a/lang/cem/cemcom/l_lint.c +++ b/lang/cem/cemcom/l_lint.c @@ -10,6 +10,8 @@ #ifdef LINT #include /* for st_free */ +#include "debug.h" +#include "interface.h" #include "assert.h" #include "arith.h" /* definition arith */ #include "label.h" /* definition label */ @@ -30,9 +32,13 @@ extern char options[128]; extern char *symbol2str(); -static struct expr_state *lint_expr(); -static struct expr_state *lint_value(); -static struct expr_state *lint_oper(); +PRIVATE struct expr_state *expr2state(); +PRIVATE struct expr_state *value2state(); +PRIVATE struct expr_state *oper2state(); +PRIVATE expr_ignored(); +PRIVATE add_expr_state(); +PRIVATE referred_esp(); +PRIVATE free_expr_states(); lint_init() { @@ -40,36 +46,22 @@ lint_init() lint_init_stack(); } -pre_lint_expr(expr, val, used) +lint_expr(expr, used) struct expr *expr; - int val; /* LVAL or RVAL */ - int used; + int used; /* USED or IGNORED */ { -/* Introduced to dispose the returned expression states */ - register struct expr_state *esp; - esp = lint_expr(expr, val, used); + esp = expr2state(expr, RVAL, used); + referred_esp(esp); free_expr_states(esp); } -free_expr_states(esp) - register struct expr_state *esp; -{ - register struct expr_state *esp2; - - while (esp) { - esp2 = esp; - esp = esp->next; - free_expr_state(esp2); - } -} - -static struct expr_state * -lint_expr(expr, val, used) +PRIVATE struct expr_state * +expr2state(expr, val, used) register struct expr *expr; - int val; - int used; + int val; /* RVAL or LVAL */ + int used; /* USED or IGNORED */ { /* Main function to process an expression tree. * It returns a structure containing information about which variables @@ -85,19 +77,20 @@ lint_expr(expr, val, used) switch (expr->ex_class) { case Value: - return lint_value(expr, val); + return value2state(expr, val); case Oper: - return lint_oper(expr, val, used); + return oper2state(expr, val, used); - default: /* String Float Type */ + default: /* String, Float, Type */ return 0; } } -static struct expr_state * -lint_value(expr, val) - register struct expr *expr; +PRIVATE struct expr_state * +value2state(expr, val) + struct expr *expr; + int val; /* RVAL or LVAL */ { switch (expr->VL_CLASS) { case Const: @@ -107,28 +100,21 @@ lint_value(expr, val) case Name: { register struct idf *idf = expr->VL_IDF; - struct expr_state *esp1 = 0; + struct expr_state *esp = 0; if (!idf || !idf->id_def) return 0; - if ( val == LVAL - || ( val == RVAL - && expr->ex_type->tp_fund == POINTER - && !expr->ex_lvalue - ) - ) { - change_state(idf, SET); - idf->id_def->df_file = - Salloc(dot.tk_file, - strlen(dot.tk_file) + 1); - idf->id_def->df_line = dot.tk_line; - } - if (val == RVAL) { + if (val == RVAL && expr->ex_lvalue == 1) { + /* value of identifier used */ change_state(idf, USED); - add_expr_state(expr->EX_VALUE, USED, &esp1); + add_expr_state(expr->EX_VALUE, USED, &esp); + } + if (val == RVAL && expr->ex_lvalue == 0) { + /* address of identifier used */ + add_expr_state(expr->EX_VALUE, REFERRED, &esp); } - return esp1; + return esp; } default: @@ -137,19 +123,31 @@ lint_value(expr, val) } } -static struct expr_state * -lint_oper(expr, val, used) +/* Let's get this straight. + An assignment is performed by elaborating the LHS and the RHS + collaterally, to use the A68 terminology, and then serially do the + actual assignment. This means: + 1. evaluate the LHS as an LVAL, + 2. evaluate the RHS as an RVAL, + 3. merge them checking for interference, + 4. set the result of the LHS to SET, if it is a named variable +*/ + +PRIVATE struct expr_state * +oper2state(expr, val, used) struct expr *expr; - int val; - int used; + int val; /* RVAL or LVAL */ + int used; /* USED or IGNORED */ { register int oper = expr->OP_OPER; register struct expr *left = expr->OP_LEFT; register struct expr *right = expr->OP_RIGHT; - struct expr_state *esp1 = 0; - struct expr_state *esp2 = 0; + struct expr_state *esp_l = 0; + struct expr_state *esp_r = 0; switch (oper) { + + /* assignments */ case '=': case PLUSAB: case MINAB: @@ -161,53 +159,42 @@ lint_oper(expr, val, used) case ANDAB: case XORAB: case ORAB: - /* for cases like i += l; */ - esp1 = lint_expr(right, RVAL, USED); - if (oper != '=') { - /* i += 1; is interpreted as i = i + 1; */ - esp2 = lint_expr(left, RVAL, USED); - check_and_merge(&esp1, esp2, oper); - } - esp2 = lint_expr(left, LVAL, USED); - /* for cases like i = i + 1; and i not set, this - ** order is essential - */ - check_and_merge(&esp1, esp2, oper); - if ( left->ex_class == Value - && left->VL_CLASS == Name - ) { - add_expr_state(left->EX_VALUE, SET, &esp1); + /* evaluate the LHS, only once; see RM 7.14 */ + esp_l = expr2state(left, (oper == '=' ? LVAL : RVAL), USED); + + /* evaluate the RHS as an RVAL and merge */ + esp_r = expr2state(right, RVAL, USED); + check_and_merge(expr, &esp_l, esp_r); + + /* set resulting variable, if any */ + if (ISNAME(left)) { + change_state(left->VL_IDF, SET); + add_expr_state(left->EX_VALUE, SET, &esp_l); } - return esp1; + + return esp_l; case POSTINCR: case POSTDECR: case PLUSPLUS: case MINMIN: - /* i++; is parsed as i = i + 1; - * This isn't quite correct : - * The first statement doesn't USE i, - * the second does. - */ - esp1 = lint_expr(left, RVAL, USED); - esp2 = lint_expr(left, LVAL, USED); - check_and_merge(&esp1, esp2, oper); - if ( left->ex_class == Value - && left->VL_CLASS == Name - ) { - add_expr_state(left->EX_VALUE, SET, &esp1); - add_expr_state(left->EX_VALUE, USED, &esp1); + esp_l = expr2state(left, RVAL, USED); + + /* set resulting variable, if any */ + if (ISNAME(left)) { + change_state(left->VL_IDF, SET); + add_expr_state(left->EX_VALUE, SET, &esp_l); } - return esp1; - case '-': - case '*': - if (left == 0) /* unary */ - return lint_expr(right, RVAL, USED); - esp1 = lint_expr(left, RVAL, USED); - esp2 = lint_expr(right, RVAL, USED); - check_and_merge(&esp1, esp2, oper); - return esp1; + return esp_l; + + case '?': + esp_l = expr2state(left, RVAL, USED); + esp_r = expr2state(right->OP_LEFT, RVAL, USED); + check_and_merge(expr, &esp_l, esp_r); + esp_r = expr2state(right->OP_RIGHT, RVAL, USED); + check_and_merge(expr, &esp_l, esp_r); + return esp_l; case '(': if (right != 0) { @@ -217,17 +204,15 @@ lint_oper(expr, val, used) while ( ex->ex_class == Oper && ex->OP_OPER == PARCOMMA ) { - esp2 = lint_expr(ex->OP_RIGHT, RVAL, - USED); - check_and_merge(&esp1, esp2, oper); + esp_r = expr2state(ex->OP_RIGHT, RVAL, USED); + check_and_merge(expr, &esp_l, esp_r); ex = ex->OP_LEFT; } - esp2 = lint_expr(ex, RVAL, USED); - check_and_merge(&esp1, esp2, oper); + esp_r = expr2state(ex, RVAL, USED); + check_and_merge(expr, &esp_l, esp_r); } - if ( left->ex_class == Value - && left->VL_CLASS == Name - ) { + + if (ISNAME(left)) { fill_outcall(expr, expr->ex_type->tp_fund == VOID ? VOIDED : used @@ -236,35 +221,34 @@ lint_oper(expr, val, used) left->VL_IDF->id_def->df_used = 1; } else { - esp2 = lint_expr(left, val, USED); - check_and_merge(&esp1, esp2, oper); + esp_r = expr2state(left, RVAL, USED); + check_and_merge(expr, &esp_l, esp_r); } - return esp1; + referred_esp(esp_l); + return esp_l; case '.': - return lint_expr(left, val, USED); + return expr2state(left, val, USED); case ARROW: - return lint_expr(left, RVAL, USED); - - case '~': - case '!': - return lint_expr(right, RVAL, USED); - - case '?': - esp1 = lint_expr(left, RVAL, USED); - esp2 = lint_expr(right->OP_LEFT, RVAL, USED); - check_and_merge(&esp1, esp2, 0); - esp2 = lint_expr(right->OP_RIGHT, RVAL, USED); - check_and_merge(&esp1, esp2, 0); - return esp1; + return expr2state(left, RVAL, USED); case INT2INT: case INT2FLOAT: case FLOAT2INT: case FLOAT2FLOAT: - return lint_expr(right, RVAL, USED); + return expr2state(right, RVAL, USED); + + /* monadic operators */ + case '-': + case '*': + if (left) + goto dyadic; + case '~': + case '!': + return expr2state(right, RVAL, USED); + /* relational operators */ case '<': case '>': case LESSEQ: @@ -279,7 +263,10 @@ lint_oper(expr, val, used) oper == GREATEREQ ? LESSEQ : oper ); - /*FALLTHROUGH*/ + goto dyadic; + + /* dyadic operators */ + dyadic: case '+': case '/': case '%': @@ -291,21 +278,20 @@ lint_oper(expr, val, used) case '^': case OR: case AND: - esp1 = lint_expr(left, RVAL, + esp_l = expr2state(left, RVAL, oper == ',' ? IGNORED : USED); - esp2 = lint_expr(right, RVAL, + esp_r = expr2state(right, RVAL, oper == ',' ? used : USED); - if (oper == OR || oper == AND || oper == ',') - check_and_merge(&esp1, esp2, 0); - else - check_and_merge(&esp1, esp2, oper); - return esp1; + check_and_merge(expr, &esp_l, esp_r); + + return esp_l; default: return 0; /* for initcomma */ } } +PRIVATE expr_ignored(expr) struct expr *expr; { @@ -334,7 +320,7 @@ expr_ignored(expr) case POSTDECR: case PLUSPLUS: case MINMIN: - /* may hide the operator * */ + /* may hide the operator '*' */ if ( /* operation on a pointer */ expr->OP_TYPE->tp_fund == POINTER && /* the result is dereferenced, e.g. *p++; */ @@ -361,4 +347,96 @@ expr_ignored(expr) } } +PRIVATE +add_expr_state(value, to_state, espp) + struct value value; + struct expr_state **espp; +{ + register struct expr_state *esp = *espp; + + ASSERT(value.vl_class == Name); + + /* try to find the esp */ + while ( esp + && !( esp->es_idf == value.vl_data.vl_idf + && esp->es_offset == value.vl_value + ) + ) { + esp = esp->next; + } + + /* if not found, add it */ + if (!esp) { + esp = new_expr_state(); + esp->es_idf = value.vl_data.vl_idf; + esp->es_offset = value.vl_value; + esp->next = *espp; + *espp = esp; + } + + /* set state */ + switch (to_state) { + case USED: + esp->es_used = 1; + break; + case REFERRED: + esp->es_referred = 1; + break; + case SET: + esp->es_set = 1; + break; + default: + NOTREACHED(); + /* NOTREACHED */ + } +} + +PRIVATE +referred_esp(esp) + struct expr_state *esp; +{ + /* raises all REFERRED items to SET and USED status */ + while (esp) { + if (esp->es_referred) { + esp->es_set = 1; + change_state(esp->es_idf, SET); + esp->es_used = 1; + change_state(esp->es_idf, USED); + esp->es_referred = 0; + } + esp = esp->next; + } +} + +PRIVATE +free_expr_states(esp) + register struct expr_state *esp; +{ + while (esp) { + register struct expr_state *esp2 = esp; + + esp = esp->next; + free_expr_state(esp2); + } +} + +#ifdef DEBUG +print_esp(msg, esp) + char *msg; + struct expr_state *esp; +{ + print("%s: <", msg); + while (esp) { + print(" %s[%d]%c%c%c ", + esp->es_idf->id_text, esp->es_offset, + (esp->es_used ? 'U' : ' '), + (esp->es_referred ? 'R' : ' '), + (esp->es_set ? 'S' : ' ') + ); + esp = esp->next; + } + print(">\n"); +} +#endif DEBUG + #endif LINT diff --git a/lang/cem/cemcom/l_lint.h b/lang/cem/cemcom/l_lint.h index 3a59bfac4..0bdffde22 100644 --- a/lang/cem/cemcom/l_lint.h +++ b/lang/cem/cemcom/l_lint.h @@ -9,6 +9,7 @@ #define IGNORED 1 #define SET 2 #define VOIDED 3 +#define REFERRED 4 /* for od_valreturned */ #define NOVALRETURNED 0 diff --git a/lang/cem/cemcom/l_misc.c b/lang/cem/cemcom/l_misc.c index beca5ca91..6117832b3 100644 --- a/lang/cem/cemcom/l_misc.c +++ b/lang/cem/cemcom/l_misc.c @@ -10,6 +10,7 @@ #ifdef LINT #include /* for st_free */ +#include "interface.h" #include "arith.h" /* definition arith */ #include "label.h" /* definition label */ #include "expr.h" @@ -27,6 +28,10 @@ extern char *symbol2str(); extern struct type *func_type; +PRIVATE lint_enum_arith(); +PRIVATE lint_conversion(); +PRIVATE int numsize(); + lint_new_oper(expr) struct expr *expr; { @@ -210,6 +215,7 @@ lint_new_oper(expr) } } +PRIVATE lint_enum_arith(l_fund, oper, r_fund) int l_fund, oper, r_fund; { @@ -228,10 +234,11 @@ lint_enum_arith(l_fund, oper, r_fund) && l_fund != INT ) { warning("%s on %s and enum", - symbol2str(oper), symbol2str(r_fund)); + symbol2str(oper), symbol2str(l_fund)); } } +PRIVATE lint_conversion(from_expr, to_fund) struct expr *from_expr; int to_fund; @@ -267,7 +274,7 @@ lint_conversion(from_expr, to_fund) } } -int +PRIVATE int numsize(fund) { switch (fund) { diff --git a/lang/cem/cemcom/l_outdef.c b/lang/cem/cemcom/l_outdef.c index eba9c38b1..ef31a1a89 100644 --- a/lang/cem/cemcom/l_outdef.c +++ b/lang/cem/cemcom/l_outdef.c @@ -10,6 +10,7 @@ #ifdef LINT #include +#include "interface.h" #include "arith.h" #include "assert.h" #include "type.h" @@ -33,7 +34,18 @@ extern char *bts2str(); extern char *symbol2str(); int stat_number = 9999; /* static scope number */ -struct outdef OutDef, OutCall; +struct outdef OutDef; + +PRIVATE struct outdef OutCall; + +PRIVATE local_EFDC(); +PRIVATE output_def(); +PRIVATE outargs(); +PRIVATE outarg(); +PRIVATE outargstring(); +PRIVATE outargtype(); +PRIVATE implicit_func_decl(); +PRIVATE fill_arg(); lint_declare_idf(idf, sc) struct idf *idf; @@ -111,6 +123,7 @@ set_od_valreturned(n) OutDef.od_valreturned = n; } +PRIVATE local_EFDC(idf) struct idf *idf; { @@ -251,6 +264,7 @@ outcall() output_def(&OutCall); } +PRIVATE output_def(od) struct outdef *od; { @@ -319,6 +333,7 @@ output_def(od) printf(":%u:%s\n", od->od_line, od->od_file); } +PRIVATE outargs(arg, n) struct argument *arg; { @@ -341,6 +356,7 @@ outargs(arg, n) } } +PRIVATE outarg(arg) struct argument *arg; { @@ -379,6 +395,7 @@ outarg(arg) } } +PRIVATE outargstring(arg) struct argument *arg; { @@ -393,6 +410,7 @@ outargstring(arg) printf("\"%s\"", buff); } +PRIVATE outargtype(tp) struct type *tp; { @@ -436,6 +454,7 @@ outargtype(tp) } } +PRIVATE implicit_func_decl(idf, file, line) struct idf *idf; char *file; @@ -485,6 +504,7 @@ fill_outcall(ex, used) OutCall.od_valused = used; /* USED, IGNORED or VOIDED */ } +PRIVATE fill_arg(e) struct expr *e; { diff --git a/lang/cem/cemcom/l_state.str b/lang/cem/cemcom/l_state.str index 82633253d..2ef91912b 100644 --- a/lang/cem/cemcom/l_state.str +++ b/lang/cem/cemcom/l_state.str @@ -66,6 +66,7 @@ struct expr_state { struct idf *es_idf; arith es_offset; int es_used; + int es_referred; int es_set; }; diff --git a/lang/cem/cemcom/l_states.c b/lang/cem/cemcom/l_states.c index 0c6df5147..ad47b97fa 100644 --- a/lang/cem/cemcom/l_states.c +++ b/lang/cem/cemcom/l_states.c @@ -10,7 +10,9 @@ #ifdef LINT #include /* for st_free */ +#include "interface.h" #include "assert.h" +#include "debug.h" #include "arith.h" /* definition arith */ #include "label.h" /* definition label */ #include "expr.h" @@ -38,15 +40,29 @@ extern int func_notypegiven; extern char loptions[]; /* global variables for the lint_stack */ -struct lint_stack_entry stack_bottom; -struct lint_stack_entry *top_ls = &stack_bottom; +PRIVATE struct lint_stack_entry stack_bottom; +PRIVATE struct lint_stack_entry *top_ls = &stack_bottom; /* global variables for the brace stack */ -int brace_count; -struct brace brace_bottom; -struct brace *top_br = &brace_bottom; - -static print_autos(); +PRIVATE int brace_count; +PRIVATE struct brace brace_bottom; +PRIVATE struct brace *top_br = &brace_bottom; + +PRIVATE end_brace(); +PRIVATE lint_1_local(); +PRIVATE lint_1_global(); +PRIVATE check_autos(); +PRIVATE struct auto_def *copy_st_auto_list(); +PRIVATE free_st_auto_list(); +PRIVATE struct state *copy_state(); +PRIVATE Free_state(); +PRIVATE remove_settings(); +PRIVATE struct auto_def *merge_autos(); +PRIVATE merge_states(); +PRIVATE struct lint_stack_entry *find_wdf(), *find_wdfc(), *find_cs(); +PRIVATE cont_break_merge(); +PRIVATE lint_push(); +PRIVATE lint_pop(); lint_init_stack() { @@ -90,6 +106,7 @@ lint_local_level(stl) end_brace(stl); } +PRIVATE end_brace(stl) struct stack_level *stl; { @@ -113,6 +130,7 @@ end_brace(stl) free_brace(br); } +PRIVATE lint_1_local(idf, def) struct idf *idf; struct def *def; @@ -158,6 +176,7 @@ lint_global_level(stl) } } +PRIVATE lint_1_global(idf, def) struct idf *idf; struct def *def; @@ -219,6 +238,7 @@ lint_1_global(idf, def) change_state(idf, to_state) struct idf *idf; + int to_state; /* SET or USED */ { /* Changes the state of the variable identified by idf in the current state * on top of the stack. @@ -228,10 +248,14 @@ change_state(idf, to_state) register struct auto_def *a = top_ls->ls_current->st_auto_list; if (def) { - if (to_state == SET) + switch (to_state) { + case SET: def->df_set = 1; - else + break; + case USED: def->df_used = 1; + break; + } if (def->df_firstbrace == 0) { def->df_firstbrace = brace_count; @@ -256,20 +280,22 @@ change_state(idf, to_state) if (a == 0) /* identifier not in list */ return; - if (to_state == SET) { + switch (to_state) { + case SET: a->ad_maybe_set = 0; a->ad_set = 1; - return; - } - /* else to_state == USED */ - if (!a->ad_set) { - warning("%s%s uninitialized", idf->id_text, - (a->ad_maybe_set ? " possibly" : "") - ); - a->ad_maybe_set = 0; - a->ad_set = 1; /* one warning */ + break; + case USED: + if (!a->ad_set) { + warning("%s%s uninitialized", idf->id_text, + (a->ad_maybe_set ? " possibly" : "") + ); + a->ad_maybe_set = 0; + a->ad_set = 1; /* one warning */ + } + a->ad_used = 1; + break; } - a->ad_used = 1; } extern struct stack_level *local_level; @@ -301,6 +327,7 @@ add_auto(idf) /* to current state on top of lint_stack */ } } +PRIVATE check_autos() { /* Before leaving a block remove the auto_defs of the automatic @@ -348,7 +375,7 @@ check_args_used() } } -struct auto_def * +PRIVATE struct auto_def * copy_st_auto_list(from_al, lvl) struct auto_def *from_al; { @@ -370,6 +397,7 @@ copy_st_auto_list(from_al, lvl) return start; } +PRIVATE free_st_auto_list(au) register struct auto_def *au; { @@ -382,7 +410,7 @@ free_st_auto_list(au) } } -struct state * +PRIVATE struct state * copy_state(from_st, lvl) struct state *from_st; { @@ -397,7 +425,7 @@ copy_state(from_st, lvl) return st; } -static +PRIVATE Free_state(stp) struct state **stp; { @@ -408,6 +436,7 @@ Free_state(stp) *stp = 0; } +PRIVATE remove_settings(state, lvl) struct state *state; { @@ -430,7 +459,7 @@ remove_settings(state, lvl) #define CASE_BREAK 1 #define USE_ONLY 2 -struct auto_def * +PRIVATE struct auto_def * merge_autos(a1, a2, lvl, mode) struct auto_def *a1, *a2; int mode; @@ -491,6 +520,7 @@ merge_autos(a1, a2, lvl, mode) return a; } +PRIVATE merge_states(st1, st2, lvl, mode) struct state *st1, *st2; int mode; @@ -532,7 +562,7 @@ merge_states(st1, st2, lvl, mode) * The letters mean : w: WHILE; d: DO; f: FOR; s: SWITCH; c: CASE. */ -struct lint_stack_entry * +PRIVATE struct lint_stack_entry * find_wdf() { register struct lint_stack_entry *lse = top_ls; @@ -549,7 +579,7 @@ find_wdf() return 0; } -struct lint_stack_entry * +PRIVATE struct lint_stack_entry * find_wdfc() { register struct lint_stack_entry *lse = top_ls; @@ -567,7 +597,7 @@ find_wdfc() return 0; } -struct lint_stack_entry * +PRIVATE struct lint_stack_entry * find_cs() { register struct lint_stack_entry *lse = top_ls; @@ -691,6 +721,7 @@ end_do_stmt(const, cond) } } +PRIVATE cont_break_merge(lse) struct lint_stack_entry *lse; { @@ -988,7 +1019,7 @@ lint_statement() return; if (top_ls->ls_current->st_notreached) { if (DOT != CASE && DOT != DEFAULT && AHEAD != ':') { - if (DOT != BREAK || !loptions['b']) + if (DOT != BREAK || loptions['b']) warning("statement cannot be reached"); top_ls->ls_current->st_warned = 1; } @@ -999,6 +1030,7 @@ lint_statement() } } +PRIVATE lint_push(lse) struct lint_stack_entry *lse; { @@ -1007,13 +1039,14 @@ lint_push(lse) top_ls = lse; } +PRIVATE lint_pop() { top_ls = top_ls->ls_previous; free_lint_stack_entry(top_ls->next); } - +#ifdef DEBUG /* FOR DEBUGGING */ print_lint_stack() @@ -1082,7 +1115,6 @@ print_lint_stack() print(" |--------------\n\n"); } -static print_autos(a) register struct auto_def *a; { @@ -1094,4 +1126,6 @@ print_autos(a) } print("\n"); } +#endif DEBUG + #endif LINT -- 2.34.1