better evaluation order checking in expressions
authordick <none@none>
Thu, 2 Feb 1989 13:57:07 +0000 (13:57 +0000)
committerdick <none@none>
Thu, 2 Feb 1989 13:57:07 +0000 (13:57 +0000)
16 files changed:
lang/cem/cemcom/Makefile
lang/cem/cemcom/ch7.c
lang/cem/cemcom/ch7mon.c
lang/cem/cemcom/code.c
lang/cem/cemcom/eval.c
lang/cem/cemcom/expr.str
lang/cem/cemcom/interface.h
lang/cem/cemcom/ival.g
lang/cem/cemcom/l_comment.c
lang/cem/cemcom/l_ev_ord.c
lang/cem/cemcom/l_lint.c
lang/cem/cemcom/l_lint.h
lang/cem/cemcom/l_misc.c
lang/cem/cemcom/l_outdef.c
lang/cem/cemcom/l_state.str
lang/cem/cemcom/l_states.c

index 8cd000f..b964ac1 100644 (file)
@@ -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
index b231f26..cbe52a1 100644 (file)
@@ -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 */
index cff0b80..acdf50e 100644 (file)
@@ -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 ?
index f13b17c..157f76f 100644 (file)
@@ -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
 }
 
index aa32e84..c782518 100644 (file)
@@ -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
index 3865ab2..3cc2327 100644 (file)
@@ -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)
index 6c90379..e75dd77 100644 (file)
@@ -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
index 3d78418..79a64e0 100644 (file)
@@ -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);
index 64e8ed7..a2a74af 100644 (file)
@@ -12,6 +12,7 @@
 #ifdef LINT
 
 #include       <alloc.h>
+#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;
index 182f40f..c0cfe4c 100644 (file)
@@ -10,6 +10,7 @@
 #ifdef LINT
 
 #include       <alloc.h>       /* for st_free */
+#include       "interface.h"
 #include       "assert.h"
 #include       "arith.h"       /* definition arith */
 #include       "label.h"       /* definition label */
 
 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
index f28e47f..b591e11 100644 (file)
@@ -10,6 +10,8 @@
 #ifdef LINT
 
 #include       <alloc.h>       /* for st_free */
+#include       "debug.h"
+#include       "interface.h"
 #include       "assert.h"
 #include       "arith.h"       /* definition arith */
 #include       "label.h"       /* definition label */
 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
index 3a59bfa..0bdffde 100644 (file)
@@ -9,6 +9,7 @@
 #define        IGNORED         1
 #define        SET             2
 #define        VOIDED          3
+#define        REFERRED        4
 
 /* for od_valreturned */
 #define        NOVALRETURNED   0
index beca5ca..6117832 100644 (file)
@@ -10,6 +10,7 @@
 #ifdef LINT
 
 #include       <alloc.h>       /* for st_free */
+#include       "interface.h"
 #include       "arith.h"       /* definition arith */
 #include       "label.h"       /* definition label */
 #include       "expr.h"
 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) {
index eba9c38..ef31a1a 100644 (file)
@@ -10,6 +10,7 @@
 #ifdef LINT
 
 #include       <alloc.h>
+#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;
 {
index 8263325..2ef9191 100644 (file)
@@ -66,6 +66,7 @@ struct expr_state {
        struct idf *es_idf;
        arith es_offset;
        int es_used;
+       int es_referred;
        int es_set;
 };
 
index 0c6df51..ad47b97 100644 (file)
@@ -10,7 +10,9 @@
 #ifdef LINT
 
 #include       <alloc.h>       /* 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