[comp.bugs.4bsd] lint fails to be my friend

das@eplunix.UUCP (David Steffens) (04/04/91)

When beginning maintenance activities on code that someone else has written,
the first thing I do is to run lint on the code to see what pops out.
This time, lint failed to find something that I think it should have.

Try the following on your favorite flavor of lint.  The first four if's
generate "variable may be used before set" complains as expected.
The fifth if statement does not.  I think it should.  If not, why not??
Tested on 4.2bsd, 4.3bsd, SunOS4.0.3, SunOS4.1 and RTU5.0 (SysV variant).

main()
{
	int foo;
	int *bar, *blap, *flap;
	int baz[10];

	if (foo == 0)
		printf("Yikes!\n");
	if (bar == 0)
		printf("Egads!\n");
	if (*blap == 0)
		printf("Gadzooks!\n");
	if (flap[2] == 0)
		printf("Ack!\n");
	if (baz[2] == 0)
		printf("Eh?\n");
	exit(0);
}
-- 
David Allan Steffens       | I believe in learning from past mistakes...
Eaton-Peabody Laboratory   | ...but does a good education require so many?
Mass. Eye & Ear Infirmary, 243 Charles Street, Boston, MA 02114
{harvard,mit-eddie,think}!eplunix!das      (617) 573-3748 (1400-1900h EST)

michi@ptcburp.ptcbu.oz.au (Michael Henning) (04/04/91)

das@eplunix.UUCP (David Steffens) writes:

>Try the following on your favorite flavor of lint.  The first four if's
>generate "variable may be used before set" complains as expected.
>The fifth if statement does not.  I think it should.  If not, why not??
>Tested on 4.2bsd, 4.3bsd, SunOS4.0.3, SunOS4.1 and RTU5.0 (SysV variant).

>main()
>{
>	int foo;
>	int *bar, *blap, *flap;
>	int baz[10];

>	if (foo == 0)
>		printf("Yikes!\n");
>	if (bar == 0)
>		printf("Egads!\n");
>	if (*blap == 0)
>		printf("Gadzooks!\n");
>	if (flap[2] == 0)
>		printf("Ack!\n");
>	if (baz[2] == 0)
>		printf("Eh?\n");
>	exit(0);
>}

The reason is that 'baz' is an array, and lint cannot check whether an
individual array element has been initialized, since that cannot always
be figured out at compile time. The net effect is that you *never* get
a warning if you use an array element that is not initialized.

In contrast, 'flap' is pointer which is not initialized at the time
it is first used, so you *do* get a warning. The fact that you are indexing
of the pointer has nothing to do with it, you get the same warning if you
replace the fourth test with

	if (flap == 0)
		printf("Ack!\n");
		
							Michi.
-- 
      -m------- Michael Henning			+61 75 950255
    ---mmm----- Pyramid Technology		+61 75 522475 FAX
  -----mmmmm--- Research Park, Bond University	michi@ptcburp.ptcbu.oz.au
-------mmmmmmm- Gold Coast, Q 4229, AUSTRALIA	uunet!munnari!ptcburp.oz!michi

suitti@ima.isc.com (Stephen Uitti) (04/05/91)

In article <380@ptcburp.ptcbu.oz.au> michi@ptcburp.ptcbu.oz.au (Michael Henning) writes:
>das@eplunix.UUCP (David Steffens) writes:
>
>>Try the following on your favorite flavor of lint.
>>main()
>>{
>>	int baz[10];
>>	if (baz[2] == 0)
>>		printf("Eh?\n");
>>	exit(0);
>>}
>
>The reason is that 'baz' is an array, and lint cannot check whether an
>individual array element has been initialized, since that cannot always
>be figured out at compile time. The net effect is that you *never* get
>a warning if you use an array element that is not initialized.

It could try, and in this case, it sure can.  The 'baz' array is
a stack variable, with local scope.  If baz[] wasn't initialized
within the curly braces, it wasn't initialized.

SysV lint (maybe others) complain that main() may return a random
value to the environment - so maybe "return 0;" would be better.
With ANSI C, exit() is essentially part of the language, so maybe
lint could be better.

Traditional 'lint' uses the 'pcc' parser.  Great.  If 'pcc'
didn't care, then 'lint' can't derive the information.  What have
you saved?  Many C compilers, 'pcc' included, have poor exception
handling.  How often have you gotten "Syntax error" when the
compiler should have known that it got "foo" when expecting one
of a small number of tokens?  I've worked with compilers that
tell you what they expected.  Once you get used to it, it is
extraordinarily helpful.  Our friend 'lint', says "Syntax error"
too.

Lint belongs in the compiler, anyway.  Turbo C generates
considerably more complete checking during compilation than
'lint' ever did, at over 3,000 lines per minute on a 7 MHz 8088 Pc/xt.

Stephen.
suitti@ima.isc.com
"We Americans want peace, and it is now evident that we must be
prepared to demand it.  For other peoples have wanted peace, and
the peace they received was the peace of death." - the Most Rev.
Francis J. Spellman, Archbishop of New York.  22 September, 1940

dhesi%cirrusl@oliveb.ATC.olivetti.com (Rahul Dhesi) (04/05/91)

In <1991Apr04.212837.13505@ima.isc.com> suitti@ima.isc.com (Stephen
Uitti) writes:

     Lint belongs in the compiler, anyway.  Turbo C generates
     considerably more complete checking during compilation than 'lint'
     ever did, at over 3,000 lines per minute on a 7 MHz 8088 Pc/xt.

Turbo C does good intrafile checking.  However, lint really shines when
it does interfile checking.  Until we get smarter (and slower) linkers,
we will have to rely upon lint and similar programs for this.  A
compiler that did interfile checking would essentially be a linker.

Properly created headers can help the compiler do some of what lint
does, but then who checks the headers?  Lint, of course.
--
Rahul Dhesi <dhesi@cirrus.COM>
UUCP:  oliveb!cirrusl!dhesi

gwyn@smoke.brl.mil (Doug Gwyn) (04/06/91)

In article <1991Apr04.212837.13505@ima.isc.com> suitti@ima.isc.com (Stephen Uitti) writes:
>With ANSI C, exit() is essentially part of the language, so maybe
>lint could be better.

And indeed some versions of "lint" ARE better.

>Traditional 'lint' uses the 'pcc' parser.  Great.  If 'pcc'
>didn't care, then 'lint' can't derive the information.

That's not entirely accurate, even for pre-ANSI C "lint".
There are several utilities within the "software generation system"
that share source code, but each of them tends to have its own
special pieces of support within the shared code.

(I think it was "ctrace" that I decided to also bring into the fold
rather than giving it its own slightly edited version of the SGS
sources as it was shipped with SVR2.)

>I've worked with compilers that tell you what they expected.
>Once you get used to it, it is extraordinarily helpful.  Our
>friend 'lint', says "Syntax error" too.

Yes, such diagnostics as you mentioned are nice.  The generic
"syntax error" style of message is often due to the use of a
parser generator (such as "yacc") with insufficient care given
to its error-reporting and -recovery capabilities.  At least
the SVR2 "lint" and PCC recover from syntax errors considerably
better than some other implementations I've seen, wherein the
least little typo produces literally hundreds of spurious
subsequent diagnostics.  (Might as well make the first diagnostic
fatal in such a case!)

>Lint belongs in the compiler, anyway.

No, I disagree.  SYNTAX CHECKING is perhaps best done by a genuine
compiler, but that is NOT the only task that "lint" performs.  In
particular, "lint" is used to check for nonportabilities, possible
unintended but valid C usage, intermodule linkage compatibility,
and so forth, none of which would I WANT a C compiler to do.  The
compiler should correctly and SILENTLY translate a correct program
to efficient code, not try to second-guess the programmer.

harrison@necssd.NEC.COM (Mark Harrison) (04/07/91)

In article <1059@eplunix.UUCP>, das@eplunix.UUCP (David Steffens) writes:
> When beginning maintenance activities on code that someone else has written,
> the first thing I do is to run lint on the code to see what pops out.
> This time, lint failed to find something that I think it should have.

Gimpel's Flexelint catches it.  I *LIKE* flexelint.

} FlexeLint (U32) Ver. 4.00h, Copyright Gimpel Software 1985-1990
} foo.c  7  Warning 530: foo (line 3) not initialized
} foo.c  9  Warning 530: bar (line 4) not initialized
} foo.c  11  Warning 530: blap (line 4) not initialized
} foo.c  13  Warning 530: flap (line 4) not initialized
} foo.c  15  Warning 530: baz (line 5) not initialized
} foo.c  18  Warning 533: Return mode of main inconsistent with line 1

PS, you forgot to return a value from main(). :-) :-) :-)
-- 
Mark Harrison             harrison@ssd.dl.nec.com
(214)518-5050             {necntc, cs.utexas.edu}!necssd!harrison
standard disclaimers apply...

das@eplunix.UUCP (David Steffens) (04/13/91)

In article <755@necssd.NEC.COM>,
harrison@necssd.NEC.COM (Mark Harrison) says:
> Gimpel's Flexelint catches it.
Of course the _line numbers_ in your sample bear little resemblance
to reality (picky, picky).  Did you alter the code?  Or the output sample?
Snide Aside: Just what I need... another "awk: bailing out near line 1" :-)

> I *LIKE* flexelint.
So might I... assuming the line numbers it produces are _correct_ !
Where can I get it and approximately how much does it cost?
-- 
David Allan Steffens       | I believe in learning from past mistakes...
Eaton-Peabody Laboratory   | ...but does a good education require so many?
Mass. Eye & Ear Infirmary, 243 Charles Street, Boston, MA 02114
{harvard,mit-eddie,think}!eplunix!das      (617) 573-3748 (1400-1900h EST)