reorganisation of lint code

This commit is contained in:
dick 1988-09-25 17:29:37 +00:00
parent fb854c82ff
commit 3d549e7932
8 changed files with 296 additions and 239 deletions

View file

@ -418,6 +418,7 @@ ch7bin.o: botch_free.h
ch7bin.o: expr.h
ch7bin.o: idf.h
ch7bin.o: label.h
ch7bin.o: lint.h
ch7bin.o: noRoption.h
ch7bin.o: nobitfield.h
ch7bin.o: nofloat.h
@ -891,6 +892,10 @@ l_comment.o: arith.h
l_comment.o: l_state.h
l_comment.o: lint.h
l_comment.o: spec_arith.h
l_dummy.o: arith.h
l_dummy.o: label.h
l_dummy.o: lint.h
l_dummy.o: spec_arith.h
tokenfile.o: Lpars.h
declar.o: LLlex.h
declar.o: Lpars.h
@ -946,7 +951,6 @@ expression.o: expr.h
expression.o: file_info.h
expression.o: idf.h
expression.o: label.h
expression.o: lint.h
expression.o: noRoption.h
expression.o: nobitfield.h
expression.o: nofloat.h

View file

@ -8,6 +8,7 @@
#include "botch_free.h"
#include <alloc.h>
#include "nofloat.h"
#include "lint.h"
#include "idf.h"
#include "arith.h"
#include "type.h"
@ -65,6 +66,7 @@ ch7bin(expp, oper, expr)
ch7bin(expp, '+', expr);
ch7mon('*', expp);
break;
case '(': /* RM 7.1 */
if ( (*expp)->ex_type->tp_fund == POINTER &&
(*expp)->ex_type->tp_up->tp_fund == FUNCTION
@ -86,11 +88,13 @@ ch7bin(expp, oper, expr)
*expp, '(', expr);
(*expp)->ex_flags |= EX_SIDEEFFECTS;
break;
case PARCOMMA: /* RM 7.1 */
if ((*expp)->ex_type->tp_fund == FUNCTION)
function2pointer(*expp);
*expp = new_oper(expr->ex_type, *expp, PARCOMMA, expr);
break;
case '%':
case MODAB:
case ANDAB:
@ -105,6 +109,7 @@ ch7bin(expp, oper, expr)
arithbalance(expp, oper, &expr);
non_commutative_binop(expp, oper, expr);
break;
case '&':
case '^':
case '|':
@ -115,6 +120,7 @@ ch7bin(expp, oper, expr)
arithbalance(expp, oper, &expr);
commutative_binop(expp, oper, expr);
break;
case '+':
if (expr->ex_type->tp_fund == POINTER) { /* swap operands */
struct expr *etmp = expr;
@ -139,6 +145,7 @@ ch7bin(expp, oper, expr)
non_commutative_binop(expp, oper, expr);
}
break;
case '-':
case MINAB:
case POSTDECR:
@ -156,6 +163,7 @@ ch7bin(expp, oper, expr)
non_commutative_binop(expp, oper, expr);
}
break;
case LEFT:
case RIGHT:
case LEFTAB:
@ -166,6 +174,7 @@ ch7bin(expp, oper, expr)
ch7cast(&expr, oper, int_type); /* cvt. rightop to int */
non_commutative_binop(expp, oper, expr);
break;
case '<':
case '>':
case LESSEQ:
@ -176,6 +185,7 @@ ch7bin(expp, oper, expr)
non_commutative_binop(expp, oper, expr);
(*expp)->ex_type = int_type;
break;
case AND:
case OR:
opnd2test(expp, oper);
@ -220,6 +230,7 @@ ch7bin(expp, oper, expr)
*expp = new_oper(int_type, *expp, oper, expr);
(*expp)->ex_flags |= EX_LOGICAL;
break;
case ':':
if ( is_struct_or_union((*expp)->ex_type->tp_fund)
|| is_struct_or_union(expr->ex_type->tp_fund)
@ -229,16 +240,30 @@ ch7bin(expp, oper, expr)
}
else
relbalance(expp, oper, &expr);
#ifdef LINT
if ( (is_cp_cst(*expp) && is_cp_cst(expr))
&& (*expp)->VL_VALUE == expr->VL_VALUE
) {
hwarning("operands of : are constant and equal");
}
#endif LINT
*expp = new_oper((*expp)->ex_type, *expp, oper, expr);
break;
case '?':
opnd2logical(expp, oper);
if (is_cp_cst(*expp))
if (is_cp_cst(*expp)) {
#ifdef LINT
hwarning("condition in ?: expression is constant");
#endif LINT
*expp = (*expp)->VL_VALUE ?
expr->OP_LEFT : expr->OP_RIGHT;
else
}
else {
*expp = new_oper(expr->ex_type, *expp, oper, expr);
}
break;
case ',':
if (is_cp_cst(*expp))
*expp = expr;

View file

@ -225,7 +225,6 @@ initializer(struct idf *idf; int sc;)
#endif DEBUG
#ifdef LINT
change_state(idf, SET);
pre_lint_expr(expr, RVAL, USED);
#endif LINT
code_declaration(idf, expr, level, sc);
}

View file

@ -6,7 +6,6 @@
/* EXPRESSION SYNTAX PARSER */
{
#include "lint.h"
#include "arith.h"
#include "LLlex.h"
#include "type.h"
@ -208,10 +207,6 @@ conditional_expression(struct expr **expp;)
#endif
ch7bin(&e1, ':', e2);
opnd2test(expp, '?');
#ifdef LINT
if (is_cp_cst(*expp))
hwarning("condition in ?: is constant");
#endif LINT
ch7bin(expp, '?', e1);
}
]?

View file

@ -1,10 +1,16 @@
/*
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
* See the copyright notice in the ACK home directory, in the file "Copyright".
*/
/* $Header$ */
/*
*The following functions are hacked to null-functions (i.e. they
* do nothing). This needs another solution in the future.
*/
#include "lint.h"
#ifdef LINT
#ifdef LINT
#include "arith.h"
#include "label.h"
@ -65,4 +71,4 @@ CC_psdnam(ps_xxx,s) char *s; {}
CC_pspnam(ps_xxx,s) char *s; {}
/* ARGSUSED */
CC_scon(v,s) char *s; {}
#endif LINT
#endif LINT

View file

@ -29,7 +29,9 @@
extern char options[128];
extern char *symbol2str();
struct expr_state *lint_expr();
static struct expr_state *lint_expr();
static struct expr_state *lint_value();
static struct expr_state *lint_oper();
lint_init()
{
@ -44,6 +46,8 @@ lint_init()
pre_lint_expr(expr, val, used)
struct expr *expr;
int val; /* LVAL or RVAL */
int used;
{
/* Introduced to dispose the returned expression states */
@ -65,9 +69,11 @@ free_expr_states(esp)
}
}
struct expr_state *
static struct expr_state *
lint_expr(expr, val, used)
register struct expr *expr;
int val;
int used;
{
/* Main function to process an expression tree.
* It returns a structure containing information about which variables
@ -77,217 +83,232 @@ lint_expr(expr, val, used)
* If the value of an operation without side-effects is not used,
* a warning is given.
*/
struct expr_state *esp1 = 0, *esp2 = 0;
if (used == IGNORED) {
expr_ignored(expr);
}
switch (expr->ex_class) {
case Value:
switch (expr->VL_CLASS) {
case Const:
case Label:
return(0);
case Name:
{
register struct idf *idf = expr->VL_IDF;
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) {
change_state(idf, USED);
add_expr_state(expr->EX_VALUE, USED, &esp1);
}
return(esp1);
}
default:
crash("(lint_expr) bad value class\n");
/* NOTREACHED */
}
return lint_value(expr, val);
case Oper:
return lint_oper(expr, val, used);
default: /* String Float Type */
return 0;
}
}
static struct expr_state *
lint_value(expr, val)
register struct expr *expr;
{
switch (expr->VL_CLASS) {
case Const:
case Label:
return 0;
case Name:
{
register int oper = expr->OP_OPER;
register struct expr *left = expr->OP_LEFT;
register struct expr *right = expr->OP_RIGHT;
register struct idf *idf = expr->VL_IDF;
struct expr_state *esp1 = 0;
switch (oper) {
case '=':
case PLUSAB:
case MINAB:
case TIMESAB:
case DIVAB:
case MODAB:
case LEFTAB:
case RIGHTAB:
case ANDAB:
case XORAB:
case ORAB:
lint_conversion(oper, right->ex_type, left->ex_type);
/* 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);
}
return(esp1);
if (!idf || !idf->id_def)
return 0;
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);
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);
case '(':
if (right != 0) {
/* function call with parameters */
register struct expr *ex = right;
while ( ex->ex_class == Oper
&& ex->OP_OPER == PARCOMMA
) {
esp2 = lint_expr(ex->OP_RIGHT, RVAL,
USED);
check_and_merge(&esp1, esp2, oper);
ex = ex->OP_LEFT;
}
esp2 = lint_expr(ex, RVAL, USED);
check_and_merge(&esp1, esp2, oper);
}
if ( left->ex_class == Value
&& left->VL_CLASS == Name
) {
fill_outcall(expr,
expr->ex_type->tp_fund == VOID ?
VOIDED : used
);
outcall();
left->VL_IDF->id_def->df_used = 1;
}
else {
esp2 = lint_expr(left, val, USED);
check_and_merge(&esp1, esp2, oper);
}
return(esp1);
case '.':
return(lint_expr(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);
case INT2INT:
case INT2FLOAT:
case FLOAT2INT:
case FLOAT2FLOAT:
lint_conversion(oper, right->ex_type, left->ex_type);
return(lint_expr(right, RVAL, USED));
case '<':
case '>':
case LESSEQ:
case GREATEREQ:
case EQUAL:
case NOTEQUAL:
lint_relop(left, right, oper);
lint_relop(right, left,
oper == '<' ? '>' :
oper == '>' ? '<' :
oper == LESSEQ ? GREATEREQ :
oper == GREATEREQ ? LESSEQ :
oper
);
/*FALLTHROUGH*/
case '+':
case '/':
case '%':
case ',':
case LEFT:
case RIGHT:
case '&':
case '|':
case '^':
case OR:
case AND:
esp1 = lint_expr(left, RVAL,
oper == ',' ? IGNORED : USED);
esp2 = lint_expr(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);
default:
return(0); /* for initcomma */
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) {
change_state(idf, USED);
add_expr_state(expr->EX_VALUE, USED, &esp1);
}
return esp1;
}
default:
return(0);
crash("(lint_expr) bad value class\n");
/* NOTREACHED */
}
}
static struct expr_state *
lint_oper(expr, val, used)
struct expr *expr;
int val;
int used;
{
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;
switch (oper) {
case '=':
case PLUSAB:
case MINAB:
case TIMESAB:
case DIVAB:
case MODAB:
case LEFTAB:
case RIGHTAB:
case ANDAB:
case XORAB:
case ORAB:
lint_conversion(oper, right->ex_type, left->ex_type);
/* 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);
}
return esp1;
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;
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;
case '(':
if (right != 0) {
/* function call with parameters */
register struct expr *ex = right;
while ( ex->ex_class == Oper
&& ex->OP_OPER == PARCOMMA
) {
esp2 = lint_expr(ex->OP_RIGHT, RVAL,
USED);
check_and_merge(&esp1, esp2, oper);
ex = ex->OP_LEFT;
}
esp2 = lint_expr(ex, RVAL, USED);
check_and_merge(&esp1, esp2, oper);
}
if ( left->ex_class == Value
&& left->VL_CLASS == Name
) {
fill_outcall(expr,
expr->ex_type->tp_fund == VOID ?
VOIDED : used
);
outcall();
left->VL_IDF->id_def->df_used = 1;
}
else {
esp2 = lint_expr(left, val, USED);
check_and_merge(&esp1, esp2, oper);
}
return esp1;
case '.':
return lint_expr(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;
case INT2INT:
case INT2FLOAT:
case FLOAT2INT:
case FLOAT2FLOAT:
lint_conversion(oper, right->ex_type, left->ex_type);
return lint_expr(right, RVAL, USED);
case '<':
case '>':
case LESSEQ:
case GREATEREQ:
case EQUAL:
case NOTEQUAL:
lint_relop(left, right, oper);
lint_relop(right, left,
oper == '<' ? '>' :
oper == '>' ? '<' :
oper == LESSEQ ? GREATEREQ :
oper == GREATEREQ ? LESSEQ :
oper
);
/*FALLTHROUGH*/
case '+':
case '/':
case '%':
case ',':
case LEFT:
case RIGHT:
case '&':
case '|':
case '^':
case OR:
case AND:
esp1 = lint_expr(left, RVAL,
oper == ',' ? IGNORED : USED);
esp2 = lint_expr(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;
default:
return 0; /* for initcomma */
}
}
@ -340,8 +361,7 @@ expr_ignored(expr)
hwarning("identifier as statement");
break;
case String:
case Float:
default: /* String Float */
hwarning("constant as statement");
break;
}

View file

@ -365,7 +365,7 @@ copy_st_auto_list(from_al, lvl)
from_al = from_al->next;
}
return(start);
return start;
}
free_st_auto_list(au)
@ -392,7 +392,7 @@ copy_state(from_st, lvl)
st->st_auto_list = copy_st_auto_list(from_st->st_auto_list, lvl);
st->st_notreached = from_st->st_notreached;
st->st_warned = from_st->st_warned;
return(st);
return st;
}
static
@ -497,7 +497,7 @@ merge_autos(a1, a2, lvl, mode)
crash("(merge_autos) a2 longer than a1");
/*NOTREACHED*/
}
return(a);
return a;
}
merge_states(st1, st2, lvl, mode)
@ -547,14 +547,15 @@ find_wdf()
register struct lint_stack_entry *lse = top_ls;
while (lse != &stack_bottom) {
switch (lse->ls_class)
switch (lse->ls_class) {
case WHILE:
case DO:
case FOR:
return(lse);
return lse;
}
lse = lse->ls_previous;
}
return(0);
return 0;
}
struct lint_stack_entry *
@ -563,15 +564,16 @@ find_wdfc()
register struct lint_stack_entry *lse = top_ls;
while (lse != &stack_bottom) {
switch (lse->ls_class)
switch (lse->ls_class) {
case WHILE:
case DO:
case FOR:
case CASE:
return(lse);
return lse;
}
lse = lse->ls_previous;
}
return(0);
return 0;
}
struct lint_stack_entry *
@ -580,24 +582,28 @@ find_cs()
register struct lint_stack_entry *lse = top_ls;
while (lse != &stack_bottom) {
switch (lse->ls_class)
switch (lse->ls_class) {
case CASE:
case SWITCH:
return(lse);
return lse;
}
lse = lse->ls_previous;
}
return(0);
return 0;
}
/******** A C T I O N S ********/
start_if_part()
start_if_part(const)
{
/* Push a new stack entry on the lint_stack with class == IF
* copy the ls_current to the top of this stack
*/
register struct lint_stack_entry *lse = new_lint_stack_entry();
if (const)
hwarning("condition in if statement is constant");
lse->ls_class = IF;
lse->ls_current = copy_state(top_ls->ls_current, level);
lse->ls_level = level;
@ -685,7 +691,7 @@ end_do_stmt(const, cond)
{
end_loop_stmt();
if (const)
hwarning("constant do condition");
hwarning("condition in do-while statement is constant");
if (const && cond && top_ls->ls_current->st_notreached) {
/* no break met; this is really an endless loop */
}
@ -718,7 +724,8 @@ lint_continue_stmt()
top_ls->ls_current->st_notreached = 1;
}
start_switch_part()
start_switch_part(expr)
struct expr *expr;
{
/* ls_current of a SWITCH entry has different meaning from ls_current of
* other entries. It keeps track of which variables are used in all
@ -727,6 +734,13 @@ start_switch_part()
*/
register struct lint_stack_entry *lse = new_lint_stack_entry();
/* the following is a trick to detect a constant
* expression in a switch
*/
opnd2test(&expr, SWITCH);
if (is_cp_cst(expr))
hwarning("value in switch statement is constant");
lse->ls_class = SWITCH;
lse->ls_current = copy_state(top_ls->ls_current, level);
lse->ls_level = level;

View file

@ -144,22 +144,22 @@ if_statement
/* The comparison has been optimized
to a 0 or 1.
*/
#ifdef LINT
hwarning("condition in if is constant");
#endif LINT
if (expr->VL_VALUE == (arith)0) {
C_bra(l_false);
}
/* else fall through */
#ifdef LINT
start_if_part(1);
#endif LINT
}
else {
code_expr(expr, RVAL, TRUE, l_true, l_false);
C_df_ilb(l_true);
#ifdef LINT
start_if_part(0);
#endif LINT
}
free_expression(expr);
#ifdef LINT
start_if_part();
#endif LINT
}
')'
statement
@ -363,13 +363,7 @@ switch_statement
{
code_startswitch(&expr);
#ifdef LINT
start_switch_part();
/* the following is a trick to detect a constant
* expression in a switch
*/
opnd2test(&expr, SWITCH);
if (is_cp_cst(expr))
hwarning("switch value is constant");
start_switch_part(expr);
#endif LINT
}
')'