From: dick Date: Fri, 7 Dec 1990 14:42:26 +0000 (+0000) Subject: lint update (merge from C compiler) X-Git-Tag: release-5-5~1356 X-Git-Url: https://git.ndcode.org/public/gitweb.cgi?a=commitdiff_plain;h=495a0377148641ef21c3fe46cd09acd9ee3fedb1;p=ack.git lint update (merge from C compiler) --- diff --git a/lang/cem/cemcom.ansi/.distr b/lang/cem/cemcom.ansi/.distr index a922449f8..f13181741 100644 --- a/lang/cem/cemcom.ansi/.distr +++ b/lang/cem/cemcom.ansi/.distr @@ -56,7 +56,7 @@ l_brace.str l_class.h l_comment.h l_comment.c -l_dummy.c +l_em.h l_ev_ord.c l_lint.c l_lint.h diff --git a/lang/cem/cemcom.ansi/LintPars b/lang/cem/cemcom.ansi/LintPars index 27f6151c5..46f66e2a8 100644 --- a/lang/cem/cemcom.ansi/LintPars +++ b/lang/cem/cemcom.ansi/LintPars @@ -1,5 +1,6 @@ !File: lint.h #define LINT 1 /* if defined, 'lint' is produced */ +#define ANSI 1 /* tell l_* files it's ANSI */ !File: pathlength.h @@ -22,7 +23,8 @@ !File: nparams.h -#define NPARAMS 32 /* maximum number of parameters of macros */ +#define NPARAMS 32 /* maximum number of parameters */ +#define STDC_NPARAMS 31 /* ANSI limit on number of parameters */ !File: ifdepth.h @@ -33,14 +35,15 @@ #define DENSITY 2 /* see switch.[ch] for an explanation */ -!File: lapbuf.h -#define LAPBUF 4096 /* size of macro actual parameter buffer */ +!File: macbuf.h +#define LAPBUF 128 /* initial size of macro replacement buffer */ +#define ARGBUF 128 /* initial size of macro parameter buffer(s) */ !File: strsize.h #define ISTRSIZE 32 /* minimum number of bytes allocated for storing a string */ -#define RSTRSIZE 8 /* step size in enlarging the memory for +#define RSTRSIZE 16 /* step size in enlarging the memory for the storage of a string */ @@ -56,6 +59,7 @@ #define SZ_FLOAT 4 #define SZ_DOUBLE 8 #define SZ_POINTER 4 +#define SZ_LNGDBL 8 /* for now */ /* target machine alignment requirements */ #define AL_CHAR 1 @@ -65,6 +69,7 @@ #define AL_LONG SZ_WORD #define AL_FLOAT SZ_WORD #define AL_DOUBLE SZ_WORD +#define AL_LNGDBL SZ_WORD #define AL_POINTER SZ_WORD #define AL_STRUCT 1 #define AL_UNION 1 @@ -99,7 +104,7 @@ !File: textsize.h -#define ITEXTSIZE 16 /* 1st piece of memory for repl. text */ +#define ITEXTSIZE 32 /* 1st piece of memory for repl. text */ !File: inputtype.h @@ -117,6 +122,7 @@ !File: spec_arith.h /* describes internal compiler arithmetics */ #undef SPECIAL_ARITHMETICS /* something different from native long */ +#undef UNSIGNED_ARITH unsigned arith !File: static.h diff --git a/lang/cem/cemcom.ansi/Makefile b/lang/cem/cemcom.ansi/Makefile index df5dda2ef..7dea883fd 100644 --- a/lang/cem/cemcom.ansi/Makefile +++ b/lang/cem/cemcom.ansi/Makefile @@ -84,7 +84,7 @@ CSRC = main.c idf.c declarator.c decspecs.c struct.c \ skip.c stack.c type.c ch3mon.c label.c eval.c \ switch.c conversion.c util.c proto.c \ pragma.c blocks.c dataflow.c Version.c stab.c\ - l_lint.c l_states.c l_misc.c l_ev_ord.c l_outdef.c l_comment.c l_dummy.c + l_lint.c l_states.c l_misc.c l_ev_ord.c l_outdef.c l_comment.c COBJ = main.o idf.o declarator.o decspecs.o struct.o \ expr.o ch3.o ch3bin.o cstoper.o fltcstoper.o arith.o \ code.o dumpidf.o error.o field.o\ @@ -93,7 +93,7 @@ COBJ = main.o idf.o declarator.o decspecs.o struct.o \ skip.o stack.o type.o ch3mon.o label.o eval.o \ switch.o conversion.o util.o proto.o \ pragma.o blocks.o dataflow.o Version.o stab.o \ - l_lint.o l_states.o l_misc.o l_ev_ord.o l_outdef.o l_comment.o l_dummy.o + l_lint.o l_states.o l_misc.o l_ev_ord.o l_outdef.o l_comment.o # Objects of other generated C files GCSRC = char.c symbol2str.c next.c @@ -123,8 +123,8 @@ GHSRC = botch_free.h dataflow.h debug.h density.h errout.h \ regcount.h HSRC = LLlex.h align.h arith.h assert.h atw.h class.h \ - input.h label.h level.h mes.h sizes.h specials.h \ - file_info.h tokenname.h l_lint.h + input.h interface.h label.h level.h mes.h sizes.h specials.h \ + file_info.h tokenname.h l_em.h l_lint.h HFILES = $(HSRC) $(GHSRC) $(GHSTRSRC) @@ -496,6 +496,7 @@ arith.o: sizes.h arith.o: spec_arith.h arith.o: trgt_sizes.h arith.o: type.h +code.o: LLlex.h code.o: Lpars.h code.o: arith.h code.o: assert.h @@ -508,6 +509,7 @@ code.o: debug.h code.o: declar.h code.o: decspecs.h code.o: def.h +code.o: l_em.h code.o: expr.h code.o: file_info.h code.o: idf.h @@ -549,6 +551,7 @@ error.o: LLlex.h error.o: arith.h error.o: debug.h error.o: def.h +error.o: l_em.h error.o: errout.h error.o: expr.h error.o: file_info.h @@ -611,6 +614,7 @@ LLmessage.o: file_info.h LLmessage.o: idf.h LLmessage.o: nopp.h LLmessage.o: spec_arith.h +input.o: dbsymtab.h input.o: file_info.h input.o: input.h input.o: inputtype.h @@ -621,6 +625,7 @@ domacro.o: arith.h domacro.o: assert.h domacro.o: botch_free.h domacro.o: class.h +domacro.o: dbsymtab.h domacro.o: debug.h domacro.o: file_info.h domacro.o: idf.h @@ -688,6 +693,7 @@ stack.o: botch_free.h stack.o: dbsymtab.h stack.o: debug.h stack.o: def.h +stack.o: l_em.h stack.o: idf.h stack.o: level.h stack.o: lint.h @@ -778,9 +784,11 @@ switch.o: code.h switch.o: dbsymtab.h switch.o: debug.h switch.o: density.h +switch.o: l_em.h switch.o: expr.h switch.o: idf.h switch.o: label.h +switch.o: lint.h switch.o: nobitfield.h switch.o: nocross.h switch.o: nopp.h @@ -803,6 +811,7 @@ util.o: Lpars.h util.o: align.h util.o: debug.h util.o: def.h +util.o: l_em.h util.o: lint.h util.o: nocross.h util.o: regcount.h @@ -919,7 +928,6 @@ l_misc.o: Lpars.h l_misc.o: arith.h l_misc.o: code.h l_misc.o: dbsymtab.h -l_misc.o: debug.h l_misc.o: def.h l_misc.o: expr.h l_misc.o: file_info.h @@ -963,6 +971,8 @@ l_outdef.o: assert.h l_outdef.o: code.h l_outdef.o: dbsymtab.h l_outdef.o: debug.h +l_outdef.o: declar.h +l_outdef.o: decspecs.h l_outdef.o: def.h l_outdef.o: expr.h l_outdef.o: field.h @@ -988,10 +998,6 @@ l_comment.o: l_comment.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 @@ -1007,7 +1013,6 @@ declar.o: field.h declar.o: file_info.h declar.o: idf.h declar.o: l_lint.h -declar.o: l_state.h declar.o: label.h declar.o: level.h declar.o: lint.h @@ -1028,11 +1033,11 @@ statement.o: code.h statement.o: dbsymtab.h statement.o: debug.h statement.o: def.h +statement.o: l_em.h statement.o: expr.h statement.o: file_info.h statement.o: idf.h statement.o: l_lint.h -statement.o: l_state.h statement.o: label.h statement.o: lint.h statement.o: nobitfield.h @@ -1070,7 +1075,7 @@ program.o: def.h program.o: expr.h program.o: file_info.h program.o: idf.h -program.o: l_state.h +program.o: l_lint.h program.o: label.h program.o: lint.h program.o: nobitfield.h @@ -1085,6 +1090,7 @@ ival.o: assert.h ival.o: dbsymtab.h ival.o: debug.h ival.o: def.h +ival.o: l_em.h ival.o: estack.h ival.o: expr.h ival.o: field.h diff --git a/lang/cem/cemcom.ansi/ch3bin.c b/lang/cem/cemcom.ansi/ch3bin.c index 0c4fe07df..ce78205ad 100644 --- a/lang/cem/cemcom.ansi/ch3bin.c +++ b/lang/cem/cemcom.ansi/ch3bin.c @@ -270,10 +270,15 @@ ch3bin(expp, oper, expr) break; case ',': - if (is_cp_cst(*expp)) + if (is_cp_cst(*expp)) { +#ifdef LINT + hwarning("constant expression ignored"); +#endif LINT *expp = expr; - else + } + else { *expp = new_oper(expr->ex_type, *expp, oper, expr); + } (*expp)->ex_flags |= EX_COMMA; break; } diff --git a/lang/cem/cemcom.ansi/code.c b/lang/cem/cemcom.ansi/code.c index 962873c24..b8724ea73 100644 --- a/lang/cem/cemcom.ansi/code.c +++ b/lang/cem/cemcom.ansi/code.c @@ -8,7 +8,12 @@ #include "lint.h" #include "debug.h" #include "dbsymtab.h" -#include +#ifndef LINT +#include +#else +#include "l_em.h" +#include "l_lint.h" +#endif LINT #include "botch_free.h" #include #include "dataflow.h" @@ -135,6 +140,7 @@ flush_strings() { } } +#ifndef LINT end_code() { /* end_code() performs the actions to be taken when closing @@ -147,6 +153,7 @@ end_code() C_ms_src((int)(LineNumber - 2), FileName); C_close(); } +#endif LINT #ifdef PREPEND_SCOPES prepend_scopes() @@ -592,7 +599,7 @@ loc_init(expr, id) store_val(&vl, tp); } #else LINT - df->df_set = 1; + id->id_def->df_set = 1; #endif LINT free_expression(expr); } @@ -644,7 +651,9 @@ formal_cvt(hasproto,df) && tp->tp_fund == FLOAT && !hasproto) { LoadLocal(df->df_address, double_size); +#ifndef LINT conversion(double_type, float_type); +#endif LINT StoreLocal(df->df_address, tp->tp_size); } } @@ -666,7 +675,6 @@ code_expr(expr, val, code, tlbl, flbl) #ifdef DBSYMTAB if (options['g']) db_line(expr->ex_file, (unsigned int)expr->ex_line); #endif - EVAL(expr, val, code, tlbl, flbl); #else LINT lint_expr(expr, code ? USED : IGNORED); diff --git a/lang/cem/cemcom.ansi/declar.g b/lang/cem/cemcom.ansi/declar.g index fd398b0be..4cd60900e 100644 --- a/lang/cem/cemcom.ansi/declar.g +++ b/lang/cem/cemcom.ansi/declar.g @@ -30,7 +30,6 @@ #include "level.h" #ifdef LINT #include "l_lint.h" -#include "l_state.h" #endif LINT extern char options[]; @@ -643,7 +642,7 @@ parameter_decl(struct proto **plp;) /* This is weird. Due to the LR structure of the ANSI C grammar we have to duplicate the actions of 'declarator' and - 'abstract_declarator'. Calling these separate, as in + 'abstract_declarator'. Calling these separately, as in parameter_decl: decl_specifiers diff --git a/lang/cem/cemcom.ansi/def.str b/lang/cem/cemcom.ansi/def.str index 222917c29..b023f4d8d 100644 --- a/lang/cem/cemcom.ansi/def.str +++ b/lang/cem/cemcom.ansi/def.str @@ -12,7 +12,7 @@ struct def { /* for ordinary tags */ int df_level; struct type *df_type; int df_sc; /* may be: - GLOBAL, STATIC, EXTERN + GLOBAL, STATIC, EXTERN, TYPEDEF, FORMAL, AUTO, ENUM, LABEL @@ -20,7 +20,6 @@ struct def { /* for ordinary tags */ char df_initialized; /* an initialization has been generated */ char df_alloc; /* 0, ALLOC_SEEN or ALLOC_DONE */ char df_used; /* set if idf is used */ - char df_formal_array; /* to warn if sizeof is taken */ char *df_file; /* file containing the definition */ unsigned int df_line; /* line number of the definition */ #ifdef LINT @@ -28,6 +27,7 @@ struct def { /* for ordinary tags */ int df_firstbrace; /* brace number of its first occurrence */ int df_minlevel; /* the lowest level needed for this def */ #endif LINT + char df_formal_array; /* to warn if sizeof is taken */ arith df_address; }; diff --git a/lang/cem/cemcom.ansi/error.c b/lang/cem/cemcom.ansi/error.c index 797da2f84..619989130 100644 --- a/lang/cem/cemcom.ansi/error.c +++ b/lang/cem/cemcom.ansi/error.c @@ -5,9 +5,14 @@ /* $Header$ */ /* E R R O R A N D D I A G N O S T I C R O U T I N E S */ +#include "lint.h" #include #include +#ifndef LINT #include +#else +#include "l_em.h" +#endif LINT #include "debug.h" #include "lint.h" diff --git a/lang/cem/cemcom.ansi/idf.c b/lang/cem/cemcom.ansi/idf.c index 305d819bf..1e0639ce5 100644 --- a/lang/cem/cemcom.ansi/idf.c +++ b/lang/cem/cemcom.ansi/idf.c @@ -266,23 +266,7 @@ declare_idf(ds, dc, lvl) : AUTO; #ifdef LINT - if ( def && def->df_level < lvl - && !( lvl == L_FORMAL2 - || def->df_level == L_UNIVERSAL - || sc == GLOBAL - || sc == EXTERN - ) - ) { - /* there is already a definition for this non-extern name - on a more global level - */ - warning("%s is already defined as a %s", - idf->id_text, - def->df_level == L_GLOBAL ? "global" : - def->df_level == L_FORMAL2 ? "formal" : - "more global local" - ); - } + check_hiding(idf, lvl, sc); /* of some idf by this idf */ #endif LINT if ((def && @@ -332,8 +316,8 @@ declare_idf(ds, dc, lvl) newdef->df_file = idf->id_file; newdef->df_line = idf->id_line; #ifdef LINT - newdef->df_set = (type->tp_fund == ARRAY); - /* newdef->df_firstbrace = 0; */ + newdef->df_set = 0; + newdef->df_firstbrace = 0; #endif LINT /* link it into the name list in the proper place */ idf->id_def = newdef; diff --git a/lang/cem/cemcom.ansi/ival.g b/lang/cem/cemcom.ansi/ival.g index 5111bc01a..9126095b6 100644 --- a/lang/cem/cemcom.ansi/ival.g +++ b/lang/cem/cemcom.ansi/ival.g @@ -7,7 +7,12 @@ { #include "lint.h" +#ifndef LINT #include +#else +#include "l_em.h" +#include "l_lint.h" +#endif LINT #include "debug.h" #include #include @@ -28,9 +33,6 @@ #include "def.h" #include "LLlex.h" #include "estack.h" -#ifdef LINT -#include "l_lint.h" -#endif LINT #define con_nullbyte() C_con_ucon("0", (arith)1) #define aggregate_type(tp) ((tp)->tp_fund == ARRAY || (tp)->tp_fund == STRUCT) diff --git a/lang/cem/cemcom.ansi/l_em.h b/lang/cem/cemcom.ansi/l_em.h new file mode 100644 index 000000000..f59e21876 --- /dev/null +++ b/lang/cem/cemcom.ansi/l_em.h @@ -0,0 +1,75 @@ +/* + * (c) copyright 1990 by the Vrije Universiteit, Amsterdam, The Netherlands. + * See the copyright notice in the ACK home directory, in the file "Copyright". + */ +/* $Header$ */ + +/* + * This file can be considered the em_code.h file of lint. + * Those code generating functions that are used by cem and that have not + * been defined away by #ifdef LINT, are defined away here. Note that this a + * fairly random collection. E.g. it does not include C_open(), since the + * standard C-open() C_close() sequence is protected by #ifdef LINT, but it + * does include C_close() since the latter is also called in other places, + * to terminate the compilation process. + */ + +#define store_block(sz, al) +#define load_block(sz, al) + +#define C_asp(c) +#define C_bra(b) +#define C_cal(p) +#define C_csa(w) +#define C_csb(w) +#define C_fil_dlb(g,o) +#define C_lae_dlb(g,o) +#define C_lal(c) +#define C_lin(c) +#define C_loi(c) +#define C_lol(c) +#define C_sdl(c) +#define C_sti(c) +#define C_stl(c) + +#define C_busy() 0 +#define C_close() + +#define C_df_dlb(l) +#define C_df_dnam(s) +#define C_df_ilb(l) + +#define C_pro_narg(s) +#define C_end(l) + +#define C_exa_dnam(s) +#define C_ina_dnam(s) +#define C_ina_dlb(l) +#define C_exp(s) +#define C_inp(s) + +#define C_bss_cst(n,w,i) + +#define C_con_cst(v) +#define C_con_icon(v,s) +#define C_con_ucon(v,s) +#define C_con_fcon(v,s) +#define C_con_scon(v,s) +#define C_con_dnam(v,s) +#define C_con_dlb(v,s) +#define C_con_pnam(v) + +#define C_rom_cst(v) +#define C_rom_icon(v,s) +#define C_rom_scon(v,s) +#define C_rom_ilb(v) + +#define C_ldl(l) + +#define C_mes_begin(ms) +#define C_mes_end() + +#define C_ms_gto() +#define C_ms_par(b) +#define C_ms_reg(o,s,t,c) + diff --git a/lang/cem/cemcom.ansi/l_ev_ord.c b/lang/cem/cemcom.ansi/l_ev_ord.c index 5cdda08a3..be44675c8 100644 --- a/lang/cem/cemcom.ansi/l_ev_ord.c +++ b/lang/cem/cemcom.ansi/l_ev_ord.c @@ -12,7 +12,9 @@ #include /* for st_free */ #include "interface.h" #include "assert.h" +#ifdef ANSI #include +#endif ANSI #include "arith.h" /* definition arith */ #include "label.h" /* definition label */ #include "expr.h" diff --git a/lang/cem/cemcom.ansi/l_lint.c b/lang/cem/cemcom.ansi/l_lint.c index e2629dfe9..73adf197f 100644 --- a/lang/cem/cemcom.ansi/l_lint.c +++ b/lang/cem/cemcom.ansi/l_lint.c @@ -13,7 +13,9 @@ #include "debug.h" #include "interface.h" #include "assert.h" +#ifdef ANSI #include +#endif ANSI #include "arith.h" /* definition arith */ #include "label.h" /* definition label */ #include "expr.h" @@ -255,14 +257,6 @@ oper2state(expr, val, used) case GREATEREQ: case EQUAL: case NOTEQUAL: - lint_relop(left, right, oper); - lint_relop(right, left, - oper == '<' ? '>' : - oper == '>' ? '<' : - oper == LESSEQ ? GREATEREQ : - oper == GREATEREQ ? LESSEQ : - oper - ); goto dyadic; /* dyadic operators */ @@ -296,8 +290,10 @@ expr_ignored(expr) struct expr *expr; { switch (expr->ex_class) { + int oper; case Oper: - switch (expr->OP_OPER) { + oper = expr->OP_OPER; + switch (oper) { case '=': case TIMESAB: case DIVAB: @@ -312,6 +308,7 @@ expr_ignored(expr) case '(': case '?': case ',': + oper = 0; /* ignore the ignoring */ break; case PLUSAB: @@ -320,29 +317,45 @@ expr_ignored(expr) case POSTDECR: case PLUSPLUS: case MINMIN: - /* may hide the operator '*' */ + oper = 0; /* ignore in priciple */ + /* may, however, hide the operator '*' */ if ( /* operation on a pointer */ expr->OP_TYPE->tp_fund == POINTER && /* the result is dereferenced, e.g. *p++; */ expr->ex_type == expr->OP_TYPE->tp_up ) { - hwarning("result of * ignored"); + oper = '*'; } break; - default: - hwarning("result of %s ignored", - symbol2str(expr->OP_OPER)); + case '/': + /* this is a specially weird case: the '/' may + result from pointer subtraction + */ + if ( expr->OP_TYPE->tp_fund == INT + && expr->OP_LEFT->OP_OPER == '-' + && expr->OP_LEFT->OP_TYPE->tp_fund == POINTER + ) { + oper = '-'; + } break; } + if (oper) { + hwarning("result of %s ignored", symbol2str(oper)); + } break; case Value: - hwarning("value as statement"); + if (expr->VL_CLASS == Const) { + hwarning("constant expression ignored"); + } + else { + hwarning("value ignored"); + } break; default: /* String Float */ - hwarning("constant as statement"); + hwarning("constant ignored"); break; } } diff --git a/lang/cem/cemcom.ansi/l_misc.c b/lang/cem/cemcom.ansi/l_misc.c index e558e530f..d0213ca1b 100644 --- a/lang/cem/cemcom.ansi/l_misc.c +++ b/lang/cem/cemcom.ansi/l_misc.c @@ -10,9 +10,10 @@ #ifdef LINT #include /* for st_free */ -#include "debug.h" #include "interface.h" +#ifdef ANSI #include +#endif ANSI #include "arith.h" /* definition arith */ #include "label.h" /* definition label */ #include "expr.h" @@ -33,6 +34,32 @@ PRIVATE lint_enum_arith(); PRIVATE lint_conversion(); PRIVATE int numsize(); +check_hiding(idf, lvl, sc) + struct idf *idf; + int lvl; + int sc; +{ + /* Checks if there is already a definition for this non-extern + name on a more global level. + */ + struct def *def = idf->id_def; + + if ( def && def->df_level < lvl + && ! ( lvl == L_FORMAL2 + || def->df_level == L_UNIVERSAL + || sc == GLOBAL + || sc == EXTERN + ) + ) { + warning("%s is already defined as a %s", + idf->id_text, + def->df_level == L_GLOBAL ? "global" : + def->df_level == L_FORMAL2 ? "formal" : + "more global local" + ); + } +} + lint_new_oper(expr) struct expr *expr; { @@ -53,14 +80,14 @@ lint_new_oper(expr) right == 0 ? 0 : /* for ( without parameters */ right->ex_type->tp_fund; - /* In ch3.c, in ch3asgn(), a combined operator/assignment + /* In ch7.c, in ch7asgn(), a combined operator/assignment is hammered into correctness by repeated application of - ch3bin(), which calls new_oper(), which calls lint_new_oper(). + ch7bin(), which calls new_oper(), which calls lint_new_oper(). These spurious calls understandably cause spurious error messages, which we don't like. So we try to suppress these wierd calls here. This refers to the code marked this is really $#@&*%$# ! - in ch3asgn(). + in ch7asgn(). */ switch (oper) { case PLUSAB: @@ -104,7 +131,7 @@ lint_new_oper(expr) else { /* binary */ if (l_fund == ENUM && r_fund == ENUM) { - if (!equal_type(left->ex_type, right->ex_type, 0)) + if (left->ex_type != right->ex_type) warning("subtracting enums of different type"); /* update the type, cem does not do it */ expr->ex_type = int_type; @@ -141,8 +168,7 @@ lint_new_oper(expr) break; case '~': - if (r_fund == ENUM || r_fund == FLOAT || r_fund == DOUBLE - /* ??? || r_fund == LNGDBL */ ) + if (r_fund == ENUM || r_fund == FLOAT || r_fund == DOUBLE) warning("~ on %s", symbol2str(r_fund)); break; @@ -165,7 +191,7 @@ lint_new_oper(expr) case EQUAL: case NOTEQUAL: if ( (l_fund == ENUM || r_fund == ENUM) - && !equal_type(left->ex_type, right->ex_type, 0) + && left->ex_type != right->ex_type ) { warning("comparing enum with non-enum"); } @@ -287,7 +313,6 @@ numsize(fund) case LONG: return 4; case FLOAT: return 5; case DOUBLE: return 6; - case LNGDBL: return 7; default: return 0; } } @@ -303,8 +328,8 @@ lint_ptr_conv(from, to) { /* X -> X ok -- this includes struct -> struct, of any size * X -> CHAR ok - * LNGDBL -> X ok - * DOUBLE -> FLOAT -> LONG -> INT -> SHORT ok + * DOUBLE -> X ok + * FLOAT -> LONG -> INT -> SHORT ok */ if (from == to) return; @@ -312,18 +337,10 @@ lint_ptr_conv(from, to) if (to == CHAR) return; - if (from == LNGDBL) + if (from == DOUBLE) return; switch (from) { - case DOUBLE: - switch(to) { - case FLOAT: - case INT: - case SHORT: - return; - } - break; case FLOAT: switch (to) { case LONG: @@ -373,7 +390,7 @@ lint_relop(left, right, oper) && right->ex_class == Value && right->VL_CLASS == Const ) { - if (right->VL_VALUE < 0) { + if (!right->ex_type->tp_unsigned && right->VL_VALUE < 0) { warning("unsigned compared to negative constant"); } if (right->VL_VALUE == 0) { diff --git a/lang/cem/cemcom.ansi/l_outdef.c b/lang/cem/cemcom.ansi/l_outdef.c index b29b6140b..fd3a31aef 100644 --- a/lang/cem/cemcom.ansi/l_outdef.c +++ b/lang/cem/cemcom.ansi/l_outdef.c @@ -10,12 +10,15 @@ #ifdef LINT #include -#include "debug.h" #include "interface.h" +#ifdef ANSI #include +#endif ANSI #include "arith.h" #include "assert.h" #include "type.h" +#include "declar.h" +#include "decspecs.h" #include "LLlex.h" #include "Lpars.h" #include "stack.h" @@ -34,6 +37,7 @@ extern char *bts2str(); extern char *symbol2str(); +extern char *strindex(); int stat_number = 9999; /* static scope number */ struct outdef OutDef; @@ -46,7 +50,6 @@ PRIVATE outargs(); PRIVATE outarg(); PRIVATE outargstring(); PRIVATE outargtype(); -PRIVATE implicit_func_decl(); PRIVATE fill_arg(); lint_declare_idf(idf, sc) @@ -69,10 +72,23 @@ lint_declare_idf(idf, sc) } } +lint_non_function_decl(ds, dc) + struct decspecs *ds; + struct declarator *dc; +{ + register struct def *def = dc->dc_idf->id_def; + register int is_function = def->df_type->tp_fund == FUNCTION; + + if (is_function) + def2decl(ds->ds_sc); + if (def->df_sc != TYPEDEF) + outdef(); +} + lint_ext_def(idf, sc) struct idf *idf; { -/* At this place the following fields of the outputdefinition can be +/* At this place the following fields of the output definition can be * filled: * name, stat_number, class, file, line, type. * For variable definitions and declarations this will be all. @@ -165,7 +181,7 @@ lint_formals() switch (type->tp_fund) { case CHAR: case SHORT: - type = int_type; + type = (type->tp_unsigned ? uint_type : int_type); break; case FLOAT: type = double_type; @@ -273,7 +289,7 @@ output_def(od) /* As the types are output the tp_entries are removed, because they * are then not needed anymore. */ - if (od->od_class == XXDF) + if (od->od_class == XXDF || !od->od_name || od->od_name[0] == '#') return; if (LINTLIB) { @@ -435,7 +451,18 @@ outargtype(tp) case STRUCT: case UNION: case ENUM: - printf("%s %s", symbol2str(tp->tp_fund), tp->tp_idf->id_text); + /* watch out for anonymous identifiers; the count field does + not have to be the same for all compilation units. + Remove it, so that pass 2 does not see it. The only + problem with this is that pass2 will not see a difference + between two non-tagged types declared on the same line. + */ + printf("%s ", symbol2str(tp->tp_fund)); + if (is_anon_idf(tp->tp_idf)) { + /* skip the #, replace it by '#anonymous id' */ + printf("#anonymous id%s", strindex(tp->tp_idf->id_text, ' ')); + } + else printf(tp->tp_idf->id_text); break; case CHAR: @@ -444,7 +471,6 @@ outargtype(tp) case LONG: case FLOAT: case DOUBLE: - case LNGDBL: case VOID: case ERRONEOUS: if (tp->tp_unsigned) @@ -457,6 +483,7 @@ outargtype(tp) } } +#ifdef IMPLICIT PRIVATE implicit_func_decl(idf, file, line) struct idf *idf; @@ -474,6 +501,7 @@ implicit_func_decl(idf, file, line) output_def(&od); /* The other fields are not used for this class. */ } +#endif IMPLICIT fill_outcall(ex, used) struct expr *ex; @@ -482,10 +510,12 @@ fill_outcall(ex, used) register struct idf *idf = ex->OP_LEFT->VL_IDF; register struct def *def = idf->id_def; +#ifdef IMPLICIT if (def->df_sc == IMPLICIT && !idf->id_def->df_used) { /* IFDC, first time */ implicit_func_decl(idf, ex->ex_file, ex->ex_line); } +#endif IMPLICIT OutCall.od_type = def->df_type->tp_up; OutCall.od_statnr = (def->df_sc == STATIC ? stat_number : 0); @@ -519,7 +549,10 @@ fill_arg(e) arg->ar_class = ArgConst; arg->CAA_VALUE = e->VL_VALUE; } - else if (e->ex_class == Value && e->VL_CLASS == Label) { + else if ( e->ex_type == string_type + && e->ex_class == Value + && e->VL_CLASS == Label + ) { /* it may be a string; let's look it up */ register struct string_cst *sc = str_list; diff --git a/lang/cem/cemcom.ansi/l_state.str b/lang/cem/cemcom.ansi/l_state.str index 2ef91912b..5f8f1b281 100644 --- a/lang/cem/cemcom.ansi/l_state.str +++ b/lang/cem/cemcom.ansi/l_state.str @@ -12,35 +12,52 @@ * control of the program. */ +#define TEST_VAR 0 /* not a constant */ +#define TEST_TRUE 1 /* always true */ +#define TEST_FALSE 2 /* always false */ -struct switch_states { +struct loop_state { /* used in lint_end_state only */ + int lps_test; /* is the test a constant? */ + struct state *lps_body; + struct state *lps_loop; +}; + +struct switch_state { /* used in lint_end_state only */ struct state *sws_case; struct state *sws_break; int sws_default_met; }; +/* This union describes the (possibly incomplete) state at the end of the + mentioned construct. +*/ +union lint_end_state { /* used in lint_stack_entry only */ + struct state *ule_if; + struct loop_state ule_loop; + struct switch_state ule_switch; +}; + struct lint_stack_entry { struct lint_stack_entry *next; struct lint_stack_entry *ls_previous; - short ls_class; /* IF, WHILE, DO, FOR, SWITCH, CASE */ int ls_level; - struct state *ls_current; /* used by all classes */ - union { - struct state *u_if_state; /* used for IF-class */ - struct state *u_end; /* used for loop-classes */ - struct switch_states u_switch; - } ls_states; /* not used for CASE-class */ + struct state *ls_current; /* used by all classes */ + short ls_class; /* IF, WHILE, DO, FOR, SWITCH, CASE */ + union lint_end_state ls_end; }; -/* macros to access the union */ -#define LS_IF_STATE ls_states.u_if_state -#define LS_END ls_states.u_end -#define LS_CASE ls_states.u_switch.sws_case -#define LS_BREAK ls_states.u_switch.sws_break -#define LS_DEFAULT_MET ls_states.u_switch.sws_default_met - /* ALLOCDEF "lint_stack_entry" 10 */ +/* macros to access the union */ +#define LS_IF ls_end.ule_if +#define LS_TEST ls_end.ule_loop.lps_test +#define LS_BODY ls_end.ule_loop.lps_body +#define LS_LOOP ls_end.ule_loop.lps_loop +#define LS_CASE ls_end.ule_switch.sws_case +#define LS_BREAK ls_end.ule_switch.sws_break +#define LS_DEFAULT_MET ls_end.ule_switch.sws_default_met + +/* describes a branch in the program, with its local idfs */ struct state { struct state *next; /* only used by memory allocator */ struct auto_def *st_auto_list; @@ -50,6 +67,7 @@ struct state { /* ALLOCDEF "state" 15 */ +/* describes the state of a local idf in a given branch of the program */ struct auto_def { struct auto_def *next; struct idf *ad_idf; @@ -61,13 +79,14 @@ struct auto_def { /* ALLOCDEF "auto_def" 20 */ -struct expr_state { +/* describes the state of an idf during expression evaluation */ +struct expr_state { /*actually concerns idfs only */ struct expr_state *next; - struct idf *es_idf; + struct idf *es_idf; /* the idf with its offset */ arith es_offset; - int es_used; - int es_referred; - int es_set; + int es_used; /* value has been used */ + int es_referred; /* address has been taken */ + int es_set; /* has been assigned to */ }; /* ALLOCDEF "expr_state" 20 */ diff --git a/lang/cem/cemcom.ansi/l_states.c b/lang/cem/cemcom.ansi/l_states.c index 463276ada..b7f87fb9c 100644 --- a/lang/cem/cemcom.ansi/l_states.c +++ b/lang/cem/cemcom.ansi/l_states.c @@ -10,12 +10,14 @@ #ifdef LINT #include /* for st_free */ -#include "debug.h" #include "interface.h" #include "assert.h" +#include "debug.h" +#ifdef ANSI #include -#include "arith.h" /* definition arith */ -#include "label.h" /* definition label */ +#endif ANSI +#include "arith.h" +#include "label.h" #include "expr.h" #include "idf.h" #include "def.h" @@ -31,50 +33,62 @@ #include "l_comment.h" #include "l_outdef.h" -#define min(a, b) ((a) < (b) ? (a) : (b)) +#ifdef DEBUG +#define dbg_lint_stack(m) /*print_lint_stack(m) /* or not */ +#else +#define dbg_lint_stack(m) +#endif DEBUG extern char *symbol2str(); extern char *func_name; extern struct type *func_type; extern int func_notypegiven; extern char loptions[]; +extern struct stack_level *local_level; /* global variables for the lint_stack */ -PRIVATE struct lint_stack_entry stack_bottom; -PRIVATE struct lint_stack_entry *top_ls = &stack_bottom; +PRIVATE struct lint_stack_entry *top_ls; /* global variables for the brace stack */ PRIVATE int brace_count; -PRIVATE struct brace brace_bottom; -PRIVATE struct brace *top_br = &brace_bottom; +PRIVATE struct brace *top_br; + +/* global variables for the function return */ +PRIVATE int valreturned; /* see l_lint.h */ +PRIVATE int return_warned; PRIVATE end_brace(); PRIVATE lint_1_local(); PRIVATE lint_1_global(); +PRIVATE start_loop_stmt(); PRIVATE check_autos(); -PRIVATE struct auto_def *copy_st_auto_list(); -PRIVATE free_st_auto_list(); +PRIVATE struct auto_def *copy_auto_list(); +PRIVATE free_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 cont_merge(); +PRIVATE break_merge(); +PRIVATE struct lint_stack_entry *mk_lint_stack_entry(); PRIVATE lint_push(); PRIVATE lint_pop(); lint_init_stack() { -/* Allocate some memory for the global stack_bottom - */ - stack_bottom.ls_current = new_state(); +/* Allocate memory for the global lint-stack elements. +*/ + top_ls = new_lint_stack_entry(); + top_ls->ls_current = new_state(); } lint_start_local() { register struct brace *br = new_brace(); + dbg_lint_stack("lint_start_local"); brace_count++; br->br_count = brace_count; br->br_level = level; @@ -82,24 +96,20 @@ lint_start_local() top_br = br; } -lint_local_level(stl) +lint_end_local(stl) struct stack_level *stl; { + + dbg_lint_stack("lint_end_local"); if (s_NOTREACHED) { top_ls->ls_current->st_notreached = 1; + top_ls->ls_current->st_warned = 0; s_NOTREACHED = 0; } if (top_ls->ls_class == CASE && level == top_ls->ls_level) { + /* supply missing break; at end of switch */ lint_break_stmt(); - /* To prevent a warning for the case - * switch (cond) { - * int i; - * case 0: - * i = 0; - * use(i); - * } - */ } check_autos(); @@ -111,6 +121,7 @@ end_brace(stl) struct stack_level *stl; { /* Check if static variables and labels are used and/or set. + Automatic vars have already been checked by check_autos(). */ register struct stack_entry *se = stl->sl_entry; register struct brace *br; @@ -125,6 +136,7 @@ end_brace(stl) se = se->next; } + /* remove entry from brace stack */ br = top_br; top_br = br->next; free_brace(br); @@ -139,8 +151,9 @@ lint_1_local(idf, def) if ( (sc == STATIC || sc == LABEL) && !def->df_used + && !is_anon_idf(idf) ) { - def_warning(def, "%s %s declared but not used in function %s", + def_warning(def, "%s %s not applied anywhere in function %s", symbol2str(sc), idf->id_text, func_name); } @@ -149,6 +162,7 @@ lint_1_local(idf, def) && !def->df_initialized && def->df_firstbrace != 0 && def->df_minlevel != level + && !is_anon_idf(idf) ) { register int diff = def->df_minlevel - level; @@ -159,11 +173,12 @@ lint_1_local(idf, def) } } -lint_global_level(stl) +lint_end_global(stl) struct stack_level *stl; { register struct stack_entry *se = stl->sl_entry; + dbg_lint_stack("lint_end_global"); ASSERT(level == L_GLOBAL); while (se) { register struct idf *idf = se->se_idf; @@ -188,7 +203,9 @@ lint_1_global(idf, def) case STATIC: case EXTERN: case GLOBAL: +#ifdef IMPLICIT case IMPLICIT: +#endif IMPLICIT if (fund == ERRONEOUS) break; @@ -198,32 +215,19 @@ lint_1_global(idf, def) */ output_use(idf); } - else { - if (sc == STATIC) { - if (def->df_set) { + + if (sc == STATIC && !def->df_used) { + if (def->df_set) { + if (!is_anon_idf(idf) && fund != ERRONEOUS) { def_warning(def, "%s %s %s set but not used", symbol2str(sc), symbol2str(fund), idf->id_text); } - else { - def_warning(def, - "%s %s %s not used anywhere", - symbol2str(sc), - symbol2str(fund), - idf->id_text); - } } - if (loptions['x']) { - register char *fn = def->df_file; - - if ( (sc == EXTERN || sc == GLOBAL) - && def->df_alloc == 0 - && !def->df_set - && !def->df_initialized - && strcmp(&fn[strlen(fn)-2], ".c") == 0 - ) { + else { + if (!is_anon_idf(idf) && fund != ERRONEOUS) { def_warning(def, "%s %s %s not used anywhere", symbol2str(sc), @@ -232,6 +236,25 @@ lint_1_global(idf, def) } } } + if (loptions['x']) { + register char *fn = def->df_file; + + if ( (sc == EXTERN || sc == GLOBAL) + && def->df_alloc == 0 + && !def->df_set + && !def->df_initialized + && !def->df_used + && strcmp(&fn[strlen(fn)-2], ".c") == 0 + && !is_anon_idf(idf) + && fund != ERRONEOUS + ) { + def_warning(def, + "%s %s %s not used anywhere", + symbol2str(sc), + symbol2str(fund), + idf->id_text); + } + } break; } } @@ -242,42 +265,44 @@ change_state(idf, to_state) { /* Changes the state of the variable identified by idf in the current state * on top of the stack. - * For non-automatic variables, the fields in the def-descriptor are set too. + * The fields in the def-descriptor are set too. */ register struct def *def = idf->id_def; register struct auto_def *a = top_ls->ls_current->st_auto_list; - if (def) { - switch (to_state) { - case SET: - def->df_set = 1; - break; - case USED: - def->df_used = 1; - break; - } + ASSERT(def); - if (def->df_firstbrace == 0) { - def->df_firstbrace = brace_count; - def->df_minlevel = level; - } - else { - register struct brace *br = top_br; + switch (to_state) { + case SET: + def->df_set = 1; + break; + case USED: + def->df_used = 1; + break; + } - /* find the smallest brace range from which - firstbrace is visible - */ - while (br && br->br_count > def->df_firstbrace) { - br = br->next; - } - ASSERT(br && def->df_minlevel >= br->br_level); - def->df_minlevel = br->br_level; + /* adjust minimum required brace level */ + if (def->df_firstbrace == 0) { + def->df_firstbrace = brace_count; + def->df_minlevel = level; + } + else { + register struct brace *br = top_br; + + /* find the smallest brace range from which + firstbrace is visible + */ + while (br && br->br_count > def->df_firstbrace) { + br = br->next; } + ASSERT(br && def->df_minlevel >= br->br_level); + def->df_minlevel = br->br_level; } + /* search auto_list */ while(a && a->ad_idf != idf) a = a->next; - if (a == 0) /* identifier not in list */ + if (a == 0) /* identifier not in list, global definition */ return; switch (to_state) { @@ -287,9 +312,12 @@ change_state(idf, to_state) break; case USED: if (!a->ad_set) { - warning("%s%s uninitialized", idf->id_text, - (a->ad_maybe_set ? " possibly" : "") - ); + if (!is_anon_idf(idf)) { + warning("variable %s%s uninitialized", + idf->id_text, + (a->ad_maybe_set ? " possibly" : "") + ); + } a->ad_maybe_set = 0; a->ad_set = 1; /* one warning */ } @@ -298,30 +326,31 @@ change_state(idf, to_state) } } -extern struct stack_level *local_level; - add_auto(idf) /* to current state on top of lint_stack */ struct idf *idf; { /* Check if idf's definition is really an auto (or register). * It could be a static or extern too. - * Watch out for register formal parameters. + * Watch out for formal parameters. */ register struct def *def = idf->id_def; - register struct auto_def *a; - if (!def) - return; + ASSERT(def); + switch (def->df_sc) { + register struct auto_def *a; case AUTO: case REGISTER: if (def->df_level < L_LOCAL) - return; /* a register formal */ + return; /* a formal */ + a = new_auto_def(); + a->ad_idf = idf; - a->ad_def = idf->id_def; + a->ad_def = def; a->ad_used = def->df_used; a->ad_set = def->df_set; + a->next = top_ls->ls_current->st_auto_list; top_ls->ls_current->st_auto_list = a; } @@ -330,43 +359,50 @@ 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 +/* Before leaving a block, remove the auto_defs of the automatic * variables on this level and check if they are used */ - register struct auto_def *a1 = top_ls->ls_current->st_auto_list; - register struct auto_def *a2; + register struct auto_def *a = top_ls->ls_current->st_auto_list; - ASSERT(!(a1 && a1->ad_def->df_level > level)); - while (a1 && a1->ad_def->df_level == level) { - a2 = a1; - a1 = a1->next; - if (!a2->ad_used) { - if (a2->ad_set || a2->ad_maybe_set) { - def_warning(a2->ad_def, + ASSERT(!(a && a->ad_def->df_level > level)); + while (a && a->ad_def->df_level == level) { + struct idf *idf = a->ad_idf; + struct def *def = idf->id_def; + + if (!def->df_used && !is_anon_idf(idf)) { + if (def->df_set || a->ad_maybe_set) { + def_warning(def, "%s set but not used in function %s", - a2->ad_idf->id_text, func_name); + idf->id_text, func_name); } else { - def_warning(a2->ad_def, - "%s neither set nor used in function %s", - a2->ad_idf->id_text, func_name); + def_warning(def, + "%s not used anywhere in function %s", + idf->id_text, func_name); } } - free_auto_def(a2); + + { /* free a */ + register struct auto_def *aux = a; + a = a->next; + free_auto_def(aux); + } } - top_ls->ls_current->st_auto_list = a1; + top_ls->ls_current->st_auto_list = a; } -check_args_used() +lint_end_formals() { register struct stack_entry *se = local_level->sl_entry; + dbg_lint_stack("lint_end_formals"); ASSERT(level == L_FORMAL1); while (se) { register struct def *def = se->se_idf->id_def; if ( (def && !def->df_used) && !(f_ARGSUSED || LINTLIB) + && !is_anon_idf(se->se_idf) ) { def_warning(def, "argument %s not used in function %s", se->se_idf->id_text, func_name); @@ -376,15 +412,18 @@ check_args_used() } PRIVATE struct auto_def * -copy_st_auto_list(from_al, lvl) +copy_auto_list(from_al, lvl) struct auto_def *from_al; + int lvl; { struct auto_def *start = 0; register struct auto_def **hook = &start; + /* skip too high levels */ while (from_al && from_al->ad_def->df_level > lvl) { from_al = from_al->next; } + while (from_al) { register struct auto_def *a = new_auto_def(); @@ -398,28 +437,27 @@ copy_st_auto_list(from_al, lvl) } PRIVATE -free_st_auto_list(au) - register struct auto_def *au; -{ +free_auto_list(a) register struct auto_def *a; - - while (au) { - a = au; - au = au->next; - free_auto_def(a); +{ + while (a) { + register struct auto_def *aux = a; + a = a->next; + free_auto_def(aux); } } PRIVATE struct state * copy_state(from_st, lvl) struct state *from_st; + int lvl; { /* Memory for the struct state and the struct auto_defs is allocated * by this function */ register struct state *st = new_state(); - st->st_auto_list = copy_st_auto_list(from_st->st_auto_list, lvl); + st->st_auto_list = copy_auto_list(from_st->st_auto_list, lvl); st->st_notreached = from_st->st_notreached; st->st_warned = from_st->st_warned; return st; @@ -431,19 +469,20 @@ Free_state(stp) { /* This function also frees the list of auto_defs */ - free_st_auto_list((*stp)->st_auto_list); + free_auto_list((*stp)->st_auto_list); free_state(*stp); *stp = 0; } PRIVATE -remove_settings(state, lvl) - struct state *state; +remove_settings(st, lvl) + struct state *st; + int lvl; { -/* The state of all variables on this level are set to 'not set' and +/* The states of all variables on this level are set to 'not set' and * 'not maybe set'. (I think you have to read this twice.) */ - register struct auto_def *a = state->st_auto_list; + register struct auto_def *a = st->st_auto_list; while (a && a->ad_def->df_level == lvl) { a->ad_set = a->ad_maybe_set = 0; @@ -459,9 +498,48 @@ remove_settings(state, lvl) #define CASE_BREAK 1 #define USE_ONLY 2 +PRIVATE +merge_states(st1, st2, lvl, mode) + struct state *st1, *st2; + int lvl; + int mode; /* NORMAL or CASE_BREAK */ +{ +/* st2 becomes the result. + * st1 is left unchanged. + * The resulting state is the state the program gets in if st1 OR st2 + * becomes the state. (E.g. the states at the end of an if-part and an + * end-part are merged by this function.) + */ + if (st1->st_notreached) { + if (mode == NORMAL || st2->st_notreached) { + st2->st_auto_list = + merge_autos(st1->st_auto_list, + st2->st_auto_list, lvl, USE_ONLY); + } + } + else + if (st2->st_notreached) { + register struct auto_def *tmp = st2->st_auto_list; + + st2->st_auto_list = copy_auto_list(st1->st_auto_list, lvl); + st2->st_notreached = 0; + st2->st_warned = 0; + st2->st_auto_list = merge_autos(tmp, st2->st_auto_list, + lvl, USE_ONLY); + free_auto_list(tmp); + } + else { + /* both st1 and st2 reached */ + st2->st_auto_list = + merge_autos(st1->st_auto_list, st2->st_auto_list, + lvl, mode); + } +} + PRIVATE struct auto_def * merge_autos(a1, a2, lvl, mode) struct auto_def *a1, *a2; + int lvl; int mode; { /* Returns a pointer to the result. @@ -484,17 +562,23 @@ merge_autos(a1, a2, lvl, mode) */ register struct auto_def *a; + /* skip too local entries */ while (a1 && a1->ad_def->df_level > lvl) { a1 = a1->next; } + + /* discard too local entries */ while (a2 && a2->ad_def->df_level > lvl) { - a = a2; + register struct auto_def *aux = a2; a2 = a2->next; - free_auto_def(a); + free_auto_def(aux); } + a = a2; /* pointer to the result */ while (a1) { ASSERT(a2); + + /* merge the auto_defs for one idf */ ASSERT(a1->ad_idf == a2->ad_idf); if (a1->ad_used) a2->ad_used = 1; @@ -520,41 +604,6 @@ merge_autos(a1, a2, lvl, mode) return a; } -PRIVATE -merge_states(st1, st2, lvl, mode) - struct state *st1, *st2; - int mode; -{ -/* st2 becomes the result. - * st1 is left unchanged. - * The resulting state is the state the program gets in if st1 OR st2 - * becomes the state. (E.g. the states at the end of an if-part and an - * end-part are merged by this function.) - */ - if (st1->st_notreached) { - if (mode == NORMAL || st2->st_notreached) { - st2->st_auto_list = - merge_autos(st1->st_auto_list, - st2->st_auto_list, lvl, USE_ONLY); - } - } - else if (st2->st_notreached) { - register struct auto_def *tmp = st2->st_auto_list; - - st2->st_auto_list = copy_st_auto_list(st1->st_auto_list, lvl); - st2->st_notreached = 0; - st2->st_warned = 0; - st2->st_auto_list = merge_autos(tmp, st2->st_auto_list, - lvl, USE_ONLY); - free_st_auto_list(tmp); - } - else { - st2->st_auto_list = - merge_autos(st1->st_auto_list, st2->st_auto_list, - lvl, mode); - } -} - /******** L I N T S T A C K S E A R C H I N G ********/ @@ -567,7 +616,7 @@ find_wdf() { register struct lint_stack_entry *lse = top_ls; - while (lse != &stack_bottom) { + while (lse) { switch (lse->ls_class) { case WHILE: case DO: @@ -584,7 +633,7 @@ find_wdfc() { register struct lint_stack_entry *lse = top_ls; - while (lse != &stack_bottom) { + while (lse) { switch (lse->ls_class) { case WHILE: case DO: @@ -602,7 +651,7 @@ find_cs() { register struct lint_stack_entry *lse = top_ls; - while (lse != &stack_bottom) { + while (lse) { switch (lse->ls_class) { case CASE: case SWITCH: @@ -613,163 +662,227 @@ find_cs() return 0; } -/******** A C T I O N S ********/ +/******** A C T I O N S : I F ********/ 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(); + register struct lint_stack_entry *new = mk_lint_stack_entry(IF); + dbg_lint_stack("start_if_part"); 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; - lint_push(lse); + lint_push(new); +/* ls_current: the state at the start of the if-part +*/ } start_else_part() { -/* Move ls_current to LS_IF_STATE - * ls_current of the stack entry one below is copied to ls_current. - */ +/* ls_current: the state at the end of the if-part + ls_previous->ls_current: the state before the if-part +*/ + + dbg_lint_stack("start_else_part"); if (s_NOTREACHED) { top_ls->ls_current->st_notreached = 1; + top_ls->ls_current->st_warned = 0; s_NOTREACHED = 0; } - top_ls->LS_IF_STATE = top_ls->ls_current; + top_ls->LS_IF = top_ls->ls_current; /* this is the reason why ls_current is a pointer */ - top_ls->ls_current = copy_state(top_ls->ls_previous->ls_current, - level); + top_ls->ls_current = + copy_state(top_ls->ls_previous->ls_current, level); top_ls->ls_level = level; +/* ls_current: the state before the if-part and the else-part + LS_IF: the state at the end of the if-part +*/ } end_if_else_stmt() { - Free_state(&top_ls->ls_previous->ls_current); - merge_states(top_ls->LS_IF_STATE, top_ls->ls_current, +/* ls_current: state at the end of the else-part + LS_IF: state at the end of the if-part +*/ + + dbg_lint_stack("end_if_else_stmt"); + merge_states(top_ls->LS_IF, top_ls->ls_current, top_ls->ls_level, NORMAL); - Free_state(&top_ls->LS_IF_STATE); + Free_state(&top_ls->LS_IF); + Free_state(&top_ls->ls_previous->ls_current); top_ls->ls_previous->ls_current = top_ls->ls_current; lint_pop(); } end_if_stmt() { -/* No else-part met; merge ls_current with ls_current of previous - * stack entry - */ +/* No else-part met. + ls_current: state at the end of the if-part +*/ + + dbg_lint_stack("end_if_stmt"); merge_states(top_ls->ls_current, top_ls->ls_previous->ls_current, top_ls->ls_level, NORMAL); Free_state(&top_ls->ls_current); lint_pop(); } +/******** A C T I O N S : L O O P S ********/ + +start_while_stmt(expr) + struct expr *expr; +{ + if (is_cp_cst(expr)) { + start_loop_stmt(WHILE, 1, expr->VL_VALUE != (arith)0); + } + else { + start_loop_stmt(WHILE, 0, 0); + } +} + +start_do_stmt() +{ + start_loop_stmt(DO, 1, 1); +} + +start_for_stmt(expr) + struct expr *expr; +{ + if (!expr) { + start_loop_stmt(FOR, 1, 1); + } + else + if (is_cp_cst(expr)) { + start_loop_stmt(FOR, 1, expr->VL_VALUE != (arith)0); + } + else { + start_loop_stmt(FOR, 0, 0); + } +} + +PRIVATE start_loop_stmt(looptype, const, cond) { -/* If const, the condition is constant and given in cond */ - register struct lint_stack_entry *lse = new_lint_stack_entry(); +/* If const, the condition is a constant and its value is cond +*/ + register struct lint_stack_entry *new = mk_lint_stack_entry(looptype); - lse->ls_class = looptype; - lse->ls_current = copy_state(top_ls->ls_current, level); - lse->ls_level = level; + dbg_lint_stack("start_loop_stmt"); if (const && !cond) { /* while (0) | for (;0;) */ - hwarning("condition in %s statement is constant", + hwarning("condition in %s statement is always false", symbol2str(looptype)); - lse->ls_current->st_notreached = 1; + new->ls_current->st_notreached = 1; } if (const && cond) { /* while (1) | for (;;) | do */ - /* omitting the copy for LS_END will force this loop + /* omitting the copy for LS_LOOP will force this loop to be treated as a do loop */ top_ls->ls_current->st_notreached = 1; + top_ls->ls_current->st_warned = 0; } else { - lse->LS_END = copy_state(top_ls->ls_current, level); + new->LS_LOOP = copy_state(top_ls->ls_current, level); } - lint_push(lse); + new->LS_TEST = (!const ? TEST_VAR : cond ? TEST_TRUE : TEST_FALSE); + lint_push(new); + +/* ls_current: the state at the start of the body + LS_TEST: info about the loop test + LS_BODY: 0, the state at the end of the body + LS_LOOP: the state at the end of the loop, or 0 if the loop + does not end +*/ } -end_loop_stmt() +end_loop_body() { - register struct lint_stack_entry *prev_ls = top_ls->ls_previous; + register struct lint_stack_entry *lse = find_wdf(); - lint_continue_stmt(); - top_ls->LS_END->st_notreached = prev_ls->ls_current->st_notreached; - top_ls->LS_END->st_warned = prev_ls->ls_current->st_warned; - Free_state(&top_ls->ls_current); - Free_state(&prev_ls->ls_current); - prev_ls->ls_current = top_ls->LS_END; - lint_pop(); + dbg_lint_stack("end_loop_body"); + ASSERT(lse == top_ls); + if (!lse->ls_current->st_notreached) + cont_merge(lse); } -end_do_stmt(const, cond) +end_loop_stmt() { - end_loop_stmt(); - if (const) - hwarning("condition in do-while statement is constant"); - if (const && cond && top_ls->ls_current->st_notreached) { + register struct lint_stack_entry *lse = find_wdf(); + + dbg_lint_stack("end_loop_stmt"); + ASSERT(lse == top_ls); + if (lse->LS_TEST != TEST_TRUE) + break_merge(lse); + + dbg_lint_stack("end_loop_stmt after break_merge"); + if (!top_ls->LS_LOOP) { /* no break met; this is really an endless loop */ + hwarning("endless %s loop", symbol2str(top_ls->ls_class)); + Free_state(&top_ls->ls_current); } else { - top_ls->ls_current->st_notreached = 0; + Free_state(&top_ls->ls_current); + Free_state(&top_ls->ls_previous->ls_current); + top_ls->ls_previous->ls_current = top_ls->LS_LOOP; } + lint_pop(); } -PRIVATE -cont_break_merge(lse) - struct lint_stack_entry *lse; +end_do_stmt(const, cond) { - /* merge for continue and break statements */ - if (lse->LS_END) { - merge_states(top_ls->ls_current, lse->LS_END, - lse->ls_level, NORMAL); - } - else { - lse->LS_END = copy_state(top_ls->ls_current, lse->ls_level); + register struct lint_stack_entry *lse = find_wdf(); + + dbg_lint_stack("end_do_stmt"); + if (const && !cond) { + /* do ... while (0) */ + hwarning("condition in do statement is always false"); } + lse->LS_TEST = (!const ? TEST_VAR : cond ? TEST_TRUE : TEST_FALSE); + end_loop_stmt(); + } lint_continue_stmt() { register struct lint_stack_entry *lse = find_wdf(); + dbg_lint_stack("lint_continue_stmt"); if (!lse) return; /* not inside a loop statement */ - cont_break_merge(lse); + cont_merge(lse); top_ls->ls_current->st_notreached = 1; + top_ls->ls_current->st_warned = 0; } -start_switch_part(expr) - struct expr *expr; +/******** A C T I O N S : S W I T C H ********/ + +start_switch_part(const) { /* 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 * following case parts. (Needed for variables declared in a compound * switch-block.) */ - register struct lint_stack_entry *lse = new_lint_stack_entry(); + register struct lint_stack_entry *new = mk_lint_stack_entry(SWITCH); - if (is_cp_cst(expr)) + dbg_lint_stack("start_switch_part"); + if (const) 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; - lse->LS_CASE = copy_state(top_ls->ls_current, level); - lse->ls_current->st_notreached = 1; + new->LS_CASE = copy_state(top_ls->ls_current, level); + new->ls_current->st_notreached = 1; + new->ls_current->st_warned = 0; top_ls->ls_current->st_notreached = 1; - lint_push(lse); + top_ls->ls_current->st_warned = 0; + lint_push(new); } end_switch_stmt() { + + dbg_lint_stack("end_switch_stmt"); if (top_ls->ls_class == CASE) { /* no break after last case or default */ lint_break_stmt(); /* introduce break */ @@ -814,30 +927,33 @@ end_switch_stmt() lint_case_stmt(dflt) { /* A default statement is just a special case statement */ - - register struct lint_stack_entry *lse; register struct lint_stack_entry *cs_entry = find_cs(); + dbg_lint_stack("lint_case_stmt"); if (!cs_entry) return; /* not inside switch */ + if (cs_entry != top_ls) { warning("%s statement in strange context", dflt ? "default" : "case"); return; } - if (cs_entry->ls_class == SWITCH) { + + switch (cs_entry->ls_class) { + register struct lint_stack_entry *new; + + case SWITCH: if (dflt) { cs_entry->LS_DEFAULT_MET = 1; } - lse = new_lint_stack_entry(); - lse->ls_class = CASE; - lse->ls_current = copy_state(top_ls->ls_current, level); - remove_settings(lse->ls_current, level); - lse->ls_level = level; - lint_push(lse); - } - else { - ASSERT(cs_entry->ls_class == CASE); + + new = mk_lint_stack_entry(CASE); + remove_settings(new->ls_current, level); + lint_push(new); + break; + + case CASE: + ASSERT(top_ls->ls_previous->ls_class == SWITCH); if (dflt) { cs_entry->ls_previous->LS_DEFAULT_MET = 1; } @@ -851,6 +967,11 @@ lint_case_stmt(dflt) copy_state(top_ls->ls_previous->ls_current, top_ls->ls_previous->ls_level); remove_settings(top_ls->ls_current, top_ls->ls_level); + break; + + default: + NOTREACHED(); + /*NOTREACHED*/ } } @@ -858,6 +979,7 @@ lint_break_stmt() { register struct lint_stack_entry *lse = find_wdfc(); + dbg_lint_stack("lint_break_stmt"); if (!lse) return; @@ -867,7 +989,7 @@ lint_break_stmt() case DO: /* loop break */ lse->ls_previous->ls_current->st_notreached = 0; - cont_break_merge(lse); + break_merge(lse); break; case CASE: @@ -878,115 +1000,146 @@ lint_break_stmt() merge_states(lse->ls_current, lse->ls_previous->ls_current, lse->ls_previous->ls_level, NORMAL); if (lse->ls_previous->LS_BREAK) { - merge_states(top_ls->ls_current, lse->ls_previous->LS_BREAK, - lse->ls_previous->ls_level, NORMAL); + merge_states(top_ls->ls_current, + lse->ls_previous->LS_BREAK, + lse->ls_previous->ls_level, NORMAL); } else { - lse->ls_previous->LS_BREAK = copy_state(top_ls->ls_current, - lse->ls_previous->ls_level); + lse->ls_previous->LS_BREAK = + copy_state(top_ls->ls_current, + lse->ls_previous->ls_level); } if (lse == top_ls) { Free_state(&lse->ls_current); lint_pop(); } break; + default: NOTREACHED(); /*NOTREACHED*/ } top_ls->ls_current->st_notreached = 1; + top_ls->ls_current->st_warned = 0; } +PRIVATE +cont_merge(lse) + struct lint_stack_entry *lse; +{ + /* merge for continue statements */ + if (lse->LS_BODY) { + merge_states(top_ls->ls_current, lse->LS_BODY, + lse->ls_level, NORMAL); + } + else { + lse->LS_BODY = copy_state(top_ls->ls_current, lse->ls_level); + } +} + +PRIVATE +break_merge(lse) + struct lint_stack_entry *lse; +{ + /* merge for break statements */ + if (lse->LS_LOOP) { + merge_states(top_ls->ls_current, lse->LS_LOOP, + lse->ls_level, NORMAL); + } + else { + lse->LS_LOOP = copy_state(top_ls->ls_current, lse->ls_level); + } +} + +/******** A C T I O N S : R E T U R N ********/ + lint_start_function() { - lint_return_stmt(-1); /* initialization */ + + dbg_lint_stack("lint_start_function"); + valreturned = NORETURN; /* initialization */ + return_warned = 0; lint_comment_function(); } lint_end_function() { - extern struct outdef OutDef; - register int fund = func_type->tp_fund; - if ( OutDef.od_valreturned == NOVALRETURNED - && !func_notypegiven - && fund != VOID - ) { - warning("function %s declared %s%s but no value returned", - func_name, - (func_type->tp_unsigned && fund != POINTER) ? - "unsigned " : "", - symbol2str(fund) - ); - } + dbg_lint_stack("lint_end_function"); /* write the function definition record */ outdef(); - /* At this stage it is possible that stack_bottom.ls_current is + /* At this stage it is possible that top_ls->ls_current is * pointing to a state with a list of auto_defs. * These auto_defs must be freed and the state must be filled * with zeros. */ - ASSERT(top_ls == &stack_bottom); - if (top_ls->ls_current->st_auto_list != 0) - free_st_auto_list(top_ls->ls_current->st_auto_list); + ASSERT(!top_ls->ls_previous); + free_auto_list(top_ls->ls_current->st_auto_list); top_ls->ls_current->st_auto_list = 0; top_ls->ls_current->st_notreached = 0; top_ls->ls_current->st_warned = 0; } +lint_implicit_return() +{ + + dbg_lint_stack("lint_implicit_return"); + if (!top_ls->ls_current->st_notreached) { + lint_return_stmt(NOVALRETURNED); + } +} + lint_return_stmt(e) int e; { -/* The statics of this function are initialized by calling it with e = -1. */ - - static int ret_e; - /*-1 no return met yet - * 0 return; met - * 1 return with expression met - */ - static int warned; - - switch (e) { - case -1: - ret_e = -1; - warned = 0; - return; - case 0: - if (top_ls->ls_current->st_notreached) - break; - if (ret_e == 1 && !warned) { - warning("function %s does not always return a value", - func_name); - warned = 1; - } - else - ret_e = 0; - break; - case 1: - if (top_ls->ls_current->st_notreached) - break; - if (ret_e == 0 && !warned) { - warning("function %s does not always return a value", - func_name); - warned = 1; + + dbg_lint_stack("lint_return_stmt"); + if (valreturned == NORETURN) { + /* first return met */ + register int fund = func_type->tp_fund; + + if ( e == NOVALRETURNED + && !func_notypegiven + && fund != VOID + && fund != ERRONEOUS + ) { + warning("function %s declared %s%s but no value returned", + func_name, + (func_type->tp_unsigned && fund != POINTER) ? + "unsigned " : "", + symbol2str(fund) + ); + /* adjust */ + e = VALRETURNED; } - else - ret_e = 1; - break; + valreturned = e; + } + else + if (valreturned != e && !return_warned) { + warning("function %s does not always return a value", + func_name); + return_warned = 1; + } + + if (!top_ls->ls_current->st_notreached) { + set_od_valreturned(valreturned); } - if (!top_ls->ls_current->st_notreached) - set_od_valreturned(e); top_ls->ls_current->st_notreached = 1; + top_ls->ls_current->st_warned = 0; } +/******** A C T I O N S : J U M P ********/ + lint_jump_stmt(idf) struct idf *idf; { + + dbg_lint_stack("lint_jump_stmt"); top_ls->ls_current->st_notreached = 1; - if (!idf->id_def) - return; - idf->id_def->df_used = 1; + top_ls->ls_current->st_warned = 0; + if (idf->id_def) + idf->id_def->df_used = 1; } lint_label() @@ -998,6 +1151,7 @@ lint_label() */ register struct auto_def *a = top_ls->ls_current->st_auto_list; + dbg_lint_stack("lint_label"); while (a) { a->ad_maybe_set = 0; a->ad_set = 1; @@ -1005,12 +1159,17 @@ lint_label() } } +/******** A C T I O N S : S T A T E M E N T ********/ + lint_statement() { -/* Check if this statement can be reached - */ +/* Check if this statement can be reached +*/ + + dbg_lint_stack("lint_statement"); if (s_NOTREACHED) { top_ls->ls_current->st_notreached = 1; + top_ls->ls_current->st_warned = 0; s_NOTREACHED = 0; } if (DOT == '{' || DOT == ';') @@ -1030,6 +1189,22 @@ lint_statement() } } +PRIVATE struct lint_stack_entry * +mk_lint_stack_entry(cl) + int cl; +{ +/* Prepare a new stack entry for the lint_stack with class cl. + Copy the top ls_current to this entry and set its level. +*/ + register struct lint_stack_entry *new = new_lint_stack_entry(); + + new->ls_class = cl; + new->ls_current = copy_state(top_ls->ls_current, level); + new->ls_level = level; + + return new; +} + PRIVATE lint_push(lse) struct lint_stack_entry *lse; @@ -1049,64 +1224,77 @@ lint_pop() #ifdef DEBUG /* FOR DEBUGGING */ -print_lint_stack() +PRIVATE +print_autos(a) + struct auto_def *a; +{ + while (a) { + struct idf *idf = a->ad_idf; + struct def *def = idf->id_def; + + print("%s", idf->id_text); + print("(lvl=%d)", a->ad_def->df_level); + print("(u%ds%dm%d U%dS%d) ", + a->ad_used, a->ad_set, a->ad_maybe_set, + def->df_used, def->df_set + ); + a = a->next; + } +} + +PRIVATE +pr_lint_state(nm, st) + char *nm; + struct state *st; +{ + print("%s: ", nm); + if (st) { + print("notreached == %d ", st->st_notreached); + print_autos(st->st_auto_list); + } + else { + print("NULL"); + } + print("\n"); +} + +print_lint_stack(msg) + char *msg; { register struct lint_stack_entry *lse = top_ls; + print("Lint stack: %s(level=%d)\n", msg, level); while (lse) { print(" |-------------- level %d ------------\n", lse->ls_level); - print(" |cur: "); - if (lse->ls_current) { - print_autos(lse->ls_current->st_auto_list); - print(" |st_notreached == %d\n", - lse->ls_current->st_notreached); - } - else - print("\n"); + pr_lint_state(" |current", lse->ls_current); + print(" |class == %s\n", lse->ls_class ? symbol2str(lse->ls_class) : "{"); + switch (lse->ls_class) { case SWITCH: - print(" |LS_BREAK: "); - if (lse->LS_BREAK) { - print_autos(lse->LS_BREAK->st_auto_list); - print(" |st_notreached == %d\n", - lse->LS_BREAK->st_notreached); - } - else - print("\n"); - print(" |LS_CASE: "); - if (lse->LS_CASE) { - print_autos(lse->LS_CASE->st_auto_list); - print(" |st_notreached == %d\n", - lse->LS_CASE->st_notreached); - } - else - print("\n"); + pr_lint_state(" |LS_BREAK", lse->LS_BREAK); + pr_lint_state(" |LS_CASE", lse->LS_CASE); break; + case DO: case WHILE: case FOR: - print(" |LS_END: "); - if (lse->LS_END) { - print_autos(lse->LS_END->st_auto_list); - print(" |st_notreached == %d\n", - lse->LS_END->st_notreached); - } - else - print("\n"); + print(" |LS_TEST == %s\n", + lse->LS_TEST == TEST_VAR ? "TEST_VAR" : + lse->LS_TEST == TEST_TRUE ? "TEST_TRUE" : + lse->LS_TEST == TEST_FALSE ? "TEST_FALSE" : + "<>" + ); + pr_lint_state(" |LS_BODY", lse->LS_BODY); + pr_lint_state(" |LS_LOOP", lse->LS_LOOP); break; + case IF: - print(" |LS_IF_STATE: "); - if (lse->LS_IF_STATE) { - print_autos(lse->LS_IF_STATE->st_auto_list); - print(" |st_notreached == %d\n", - lse->LS_IF_STATE->st_notreached); - } - else - print("\n"); + pr_lint_state(" |LS_IF", lse->LS_IF); break; + default: break; } @@ -1115,17 +1303,6 @@ print_lint_stack() print(" |--------------\n\n"); } -print_autos(a) - register struct auto_def *a; -{ - while (a) { - print("%s", a->ad_idf->id_text); - print("(l=%d)", a->ad_def->df_level); - print("(U%dS%dM%d) ", a->ad_used, a->ad_set, a->ad_maybe_set); - a = a->next; - } - print("\n"); -} #endif DEBUG #endif LINT diff --git a/lang/cem/cemcom.ansi/main.c b/lang/cem/cemcom.ansi/main.c index 2d7f64734..7e42daead 100644 --- a/lang/cem/cemcom.ansi/main.c +++ b/lang/cem/cemcom.ansi/main.c @@ -298,7 +298,10 @@ compile(argc, argv) #ifdef PREPEND_SCOPES prepend_scopes(); #endif PREPEND_SCOPES + +#ifndef LINT end_code(); +#endif LINT #ifdef DEBUG if (options['u']) { diff --git a/lang/cem/cemcom.ansi/program.g b/lang/cem/cemcom.ansi/program.g index cd7adfb82..f361d3f8c 100644 --- a/lang/cem/cemcom.ansi/program.g +++ b/lang/cem/cemcom.ansi/program.g @@ -60,7 +60,7 @@ #include "expr.h" #include "def.h" #ifdef LINT -#include "l_state.h" +#include "l_lint.h" #endif LINT #ifndef NOPP @@ -182,10 +182,7 @@ non_function(register struct decspecs *ds; register struct declarator *dc;) ] { #ifdef LINT - if (dc->dc_idf->id_def->df_type->tp_fund == FUNCTION) - def2decl(ds->ds_sc); - if (dc->dc_idf->id_def->df_sc != TYPEDEF) - outdef(); + lint_non_function_decl(ds, dc); #endif LINT } [ @@ -225,11 +222,11 @@ function(struct decspecs *ds; struct declarator *dc;) { end_proc(fbytes); #ifdef LINT - lint_return_stmt(0); /* implicit return at end of function */ + lint_implicit_return(); #endif LINT unstack_level(); /* L_FORMAL2 declarations */ #ifdef LINT - check_args_used(); + lint_end_formals(); #endif LINT unstack_level(); /* L_FORMAL1 declarations */ #ifdef LINT diff --git a/lang/cem/cemcom.ansi/stack.c b/lang/cem/cemcom.ansi/stack.c index ba7716c18..827d6cb6b 100644 --- a/lang/cem/cemcom.ansi/stack.c +++ b/lang/cem/cemcom.ansi/stack.c @@ -7,7 +7,11 @@ #include "lint.h" #include +#ifndef LINT #include +#else +#include "l_em.h" +#endif LINT #include "debug.h" #include "botch_free.h" #include @@ -109,7 +113,7 @@ unstack_level() #endif DEBUG #ifdef LINT - lint_local_level(local_level); + lint_end_local(local_level); #endif LINT /* The implementation below is more careful than strictly @@ -185,7 +189,7 @@ unstack_world() register struct stack_entry *se = local_level->sl_entry; #ifdef LINT - lint_global_level(local_level); + lint_end_global(local_level); #endif LINT #ifdef GEN_NM_LIST diff --git a/lang/cem/cemcom.ansi/statement.g b/lang/cem/cemcom.ansi/statement.g index ecdb74720..873dd9779 100644 --- a/lang/cem/cemcom.ansi/statement.g +++ b/lang/cem/cemcom.ansi/statement.g @@ -6,9 +6,14 @@ /* STATEMENT SYNTAX PARSER */ { -#include - #include "lint.h" +#ifndef LINT +#include +#else +#include "l_em.h" +#include "l_lint.h" +#endif LINT + #include "debug.h" #include "botch_free.h" #include "dbsymtab.h" @@ -23,10 +28,6 @@ #include "code.h" #include "stack.h" #include "def.h" -#ifdef LINT -#include "l_lint.h" -#include "l_state.h" -#endif LINT #ifdef DBSYMTAB #include #endif /* DBSYMTAB */ @@ -215,18 +216,14 @@ while_statement if (expr->VL_VALUE == (arith)0) { C_bra(l_break); } -#ifdef LINT - start_loop_stmt(WHILE, 1, - expr->VL_VALUE != (arith)0); -#endif LINT } else { code_expr(expr, RVAL, TRUE, l_body, l_break); C_df_ilb(l_body); + } #ifdef LINT - start_loop_stmt(WHILE, 0, 0); + start_while_stmt(expr); #endif LINT - } } ')' statement @@ -236,6 +233,7 @@ while_statement unstack_stmt(); free_expression(expr); #ifdef LINT + end_loop_body(); end_loop_stmt(); #endif LINT } @@ -253,13 +251,17 @@ do_statement { C_df_ilb(l_body); stack_stmt(l_break, l_continue); #ifdef LINT - start_loop_stmt(DO, 1, 1); + start_do_stmt(); #endif LINT } statement WHILE '(' - { C_df_ilb(l_continue); + { +#ifdef LINT + end_loop_body(); +#endif LINT + C_df_ilb(l_continue); } expression(&expr) { @@ -295,9 +297,6 @@ for_statement label l_continue = text_label(); label l_body = text_label(); label l_test = text_label(); -#ifdef LINT - int const = 1, cond = 1; /* the default case */ -#endif LINT } : FOR @@ -320,17 +319,10 @@ for_statement if (e_test->VL_VALUE == (arith)0) { C_bra(l_break); } -#ifdef LINT - const = 1, - cond = e_test->VL_VALUE != (arith)0; -#endif LINT } else { code_expr(e_test, RVAL, TRUE, l_body, l_break); C_df_ilb(l_body); -#ifdef LINT - const = 0, cond = 0; -#endif LINT } } ]? @@ -339,13 +331,13 @@ for_statement ')' { #ifdef LINT - start_loop_stmt(FOR, const, cond); + start_for_stmt(e_test); #endif LINT } statement { #ifdef LINT - end_loop_stmt(); + end_loop_body(); #endif LINT C_df_ilb(l_continue); if (e_incr) @@ -357,6 +349,9 @@ for_statement free_expression(e_init); free_expression(e_test); free_expression(e_incr); +#ifdef LINT + end_loop_stmt(); +#endif LINT } ; @@ -372,7 +367,7 @@ switch_statement { code_startswitch(&expr); #ifdef LINT - start_switch_part(expr); + start_switch_part(is_cp_cst(expr)); #endif LINT } ')' @@ -435,7 +430,7 @@ return_statement do_return_expr(expr); free_expression(expr); #ifdef LINT - lint_return_stmt(1); + lint_return_stmt(VALRETURNED); #endif LINT } | @@ -443,7 +438,7 @@ return_statement { do_return(); #ifdef LINT - lint_return_stmt(0); + lint_return_stmt(NOVALRETURNED); #endif LINT } ] diff --git a/lang/cem/cemcom.ansi/switch.c b/lang/cem/cemcom.ansi/switch.c index 94271078c..124c1e33b 100644 --- a/lang/cem/cemcom.ansi/switch.c +++ b/lang/cem/cemcom.ansi/switch.c @@ -5,7 +5,12 @@ /* $Header$ */ /* S W I T C H - S T A T E M E N T A D M I N I S T R A T I O N */ +#include "lint.h" +#ifndef LINT #include +#else +#include "l_em.h" +#endif LINT #include "debug.h" #include "botch_free.h" #include @@ -73,6 +78,9 @@ code_startswitch(expp) sh->sh_type = (*expp)->ex_type; /* the expression switched */ /* sh->sh_entries = (struct case_entry *) 0; /* case-entry list */ sh->sh_expr = *expp; +#ifdef LINT + code_expr(sh->sh_expr, RVAL, TRUE, NO_LABEL, NO_LABEL); +#endif sh->next = switch_stack; /* push onto switch-stack */ switch_stack = sh; C_bra(l_table); /* goto start of switch_table */ @@ -92,7 +100,9 @@ code_endswitch() C_bra(sh->sh_break); /* skip the switch table now */ C_df_ilb(sh->sh_table); /* switch table entry */ /* evaluate the switch expr. */ +#ifndef LINT code_expr(sh->sh_expr, RVAL, TRUE, NO_LABEL, NO_LABEL); +#endif tablabel = data_label(); /* the rom must have a label */ C_df_dlb(tablabel); C_rom_ilb(sh->sh_default); diff --git a/lang/cem/cemcom.ansi/util.c b/lang/cem/cemcom.ansi/util.c index 495e1abb1..4ffe7ed53 100644 --- a/lang/cem/cemcom.ansi/util.c +++ b/lang/cem/cemcom.ansi/util.c @@ -11,12 +11,17 @@ allowing re-use. */ +#include "lint.h" +#ifndef LINT #include +#else +#include "l_em.h" +#endif LINT +#include #include #include #include -#include "lint.h" #include "debug.h" #include "util.h" #include "use_tmp.h"