From 3d549e7932f5f7b0ca447248e8bc061243036137 Mon Sep 17 00:00:00 2001 From: dick Date: Sun, 25 Sep 1988 17:29:37 +0000 Subject: [PATCH] reorganisation of lint code --- lang/cem/cemcom/Makefile | 6 +- lang/cem/cemcom/ch7bin.c | 29 ++- lang/cem/cemcom/declar.g | 1 - lang/cem/cemcom/expression.g | 5 - lang/cem/cemcom/l_dummy.c | 10 +- lang/cem/cemcom/l_lint.c | 412 ++++++++++++++++++----------------- lang/cem/cemcom/l_states.c | 44 ++-- lang/cem/cemcom/statement.g | 20 +- 8 files changed, 292 insertions(+), 235 deletions(-) diff --git a/lang/cem/cemcom/Makefile b/lang/cem/cemcom/Makefile index eb3bc2ba8..ac234296e 100644 --- a/lang/cem/cemcom/Makefile +++ b/lang/cem/cemcom/Makefile @@ -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 diff --git a/lang/cem/cemcom/ch7bin.c b/lang/cem/cemcom/ch7bin.c index b34957749..a24bee9ac 100644 --- a/lang/cem/cemcom/ch7bin.c +++ b/lang/cem/cemcom/ch7bin.c @@ -8,6 +8,7 @@ #include "botch_free.h" #include #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; diff --git a/lang/cem/cemcom/declar.g b/lang/cem/cemcom/declar.g index 718b673f5..92a501ea0 100644 --- a/lang/cem/cemcom/declar.g +++ b/lang/cem/cemcom/declar.g @@ -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); } diff --git a/lang/cem/cemcom/expression.g b/lang/cem/cemcom/expression.g index a22c18797..d26ed5f87 100644 --- a/lang/cem/cemcom/expression.g +++ b/lang/cem/cemcom/expression.g @@ -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); } ]? diff --git a/lang/cem/cemcom/l_dummy.c b/lang/cem/cemcom/l_dummy.c index f82c24ef0..f0633a615 100644 --- a/lang/cem/cemcom/l_dummy.c +++ b/lang/cem/cemcom/l_dummy.c @@ -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 diff --git a/lang/cem/cemcom/l_lint.c b/lang/cem/cemcom/l_lint.c index 6f6be686c..3cbc27252 100644 --- a/lang/cem/cemcom/l_lint.c +++ b/lang/cem/cemcom/l_lint.c @@ -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; + + 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; + } - 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); + default: + crash("(lint_expr) bad value class\n"); + /* NOTREACHED */ + } +} - 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); +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); - 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 + } + 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 ) { - 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); + esp2 = lint_expr(ex->OP_RIGHT, RVAL, + USED); check_and_merge(&esp1, esp2, oper); + ex = ex->OP_LEFT; } - 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 + 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 ); - /*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 */ + 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); + 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; } diff --git a/lang/cem/cemcom/l_states.c b/lang/cem/cemcom/l_states.c index e9d445221..50c66caac 100644 --- a/lang/cem/cemcom/l_states.c +++ b/lang/cem/cemcom/l_states.c @@ -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; diff --git a/lang/cem/cemcom/statement.g b/lang/cem/cemcom/statement.g index 601473615..4fc91efb3 100644 --- a/lang/cem/cemcom/statement.g +++ b/lang/cem/cemcom/statement.g @@ -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); - } - free_expression(expr); #ifdef LINT - start_if_part(); + start_if_part(0); #endif LINT + } + free_expression(expr); } ')' 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 } ')' -- 2.34.1