better evaluation order checking in expressions

This commit is contained in:
dick 1989-02-02 13:57:07 +00:00
parent f7df668450
commit f70dfe4d00
16 changed files with 367 additions and 227 deletions

View 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

View 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 */

View 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 ?

View 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
}

View 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

View 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)

View 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

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

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

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

View 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 */
@ -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);
}
return esp1;
if (val == RVAL && expr->ex_lvalue == 0) {
/* address of identifier used */
add_expr_state(expr->EX_VALUE, REFERRED, &esp);
}
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);
/* 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);
}
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);
}
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);
}
return esp1;
esp_l = expr2state(left, RVAL, USED);
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;
/* set resulting variable, if any */
if (ISNAME(left)) {
change_state(left->VL_IDF, SET);
add_expr_state(left->EX_VALUE, SET, &esp_l);
}
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

View file

@ -9,6 +9,7 @@
#define IGNORED 1
#define SET 2
#define VOIDED 3
#define REFERRED 4
/* for od_valreturned */
#define NOVALRETURNED 0

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

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

View file

@ -66,6 +66,7 @@ struct expr_state {
struct idf *es_idf;
arith es_offset;
int es_used;
int es_referred;
int es_set;
};

View 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;
PRIVATE int brace_count;
PRIVATE struct brace brace_bottom;
PRIVATE struct brace *top_br = &brace_bottom;
static print_autos();
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;
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;
}
/* 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 */
}
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