[comp.lang.c] 2 lint questions

boyd@ingr.com (Boyd Nation) (07/28/89)

I have two questions bout lint:

1)  How does one prevent lint from issuing a warning message about possible
pointer alignment problems given the following line of code:

	x = (blivet *)malloc(sizeof(blivet));

given that everything is declared and defined correctly?


2)  Is there any way to get lint to detect a closed loop of code which can
never be called?  For example:

	void func1()
	{
	    if (some_condition)
		func2();
	    some_action();
	}

	void func2()
	{
	    some_other_action();
	    func1();
	}

where there are no other calls to func1 or func2.

-- 
I propose that the software be modified so that anyone posting angrily to
defend a group which may have been insulted must type the word "wolf" 1000
times before posting.  It would also be nice if real life worked this way. 
Boyd Nation      ...!uunet!ingr!boyd      boyd@ingr.com      Stress kills.

chris@mimsy.UUCP (Chris Torek) (07/28/89)

In article <5967@ingr.com> boyd@ingr.com (Boyd Nation) writes:
>1)  How does one prevent lint from issuing a warning message about possible
>pointer alignment problems given the following line of code:
>
>	x = (blivet *)malloc(sizeof(blivet));
>
>given that everything is declared and defined correctly?

As the `BUGS' section of any whole% lint(1) manual page says, `There
are some things you just *can't* get lint to shut up about.'
/*NOSTRICT*/ was supposed to keep it quiet in this particular case; but
NOSTRICT is not implemented in many (all?) lints, and in any case it is
the wrong solution.
-----
% Some vendors remove or rename the `BUGS' sections from manuals.
-----

There is a solution, albeit an ugly one:

	#ifdef lint
	/* keep lint quiet about malloc() */
	static void _lint_malloc(x) unsigned x; { x = x; }
	#define malloc(x) (_lint_malloc(x), 0)
	#endif /* lint */

Then your call changes from

	x = (blivet *)malloc(sizeof(blivet));

to

	x = (blivet *)(_lint_malloc(sizeof(blivet)),0);

which puts a nil pointer of type `pointer to blivet' into x.
Since lint is fairly stupid,

	if (x == NULL)

does not cause warnings about constants in conditional contexts,
even if you wrote

	if ((x = (blivet *)malloc(sizeof(blivet))) == NULL)

It would be nice if compiler vendors included something like the
`#ifdef' code above in <stddef.h> (the _lint_malloc function would
have to move to the regular lint library).

>2)  Is there any way to get lint to detect a closed loop of code which can
>never be called?

Lint would need to do call graph analysis to find these; I have never
seen one that does.
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163)
Domain:	chris@mimsy.umd.edu	Path:	uunet!mimsy!chris

gwyn@smoke.BRL.MIL (Doug Gwyn) (07/29/89)

In article <5967@ingr.com> boyd@ingr.com (Boyd Nation) writes:
-1)  How does one prevent lint from issuing a warning message about possible
-pointer alignment problems given the following line of code:
-	x = (blivet *)malloc(sizeof(blivet));

The only way is to substitute different code under "#ifdef lint" control.
If you actually plan on doing that, I recommend using a nice macro wrapper
defined to implement the actual malloc() call with casts etc. normally but
defined with a lint-free substitute under "#ifdef lint" conditions.

-2)  Is there any way to get lint to detect a closed loop of code which can
-never be called?  For example:
-	void func1()
-	{
-		func2();
-	}
-	void func2()
-	{
-	    func1();
-	}
-where there are no other calls to func1 or func2.

Nope.

paul@moncam.co.uk (Paul Hudson) (07/31/89)

In article <18796@mimsy.UUCP> chris@mimsy.UUCP (Chris Torek) writes:


   >2)  Is there any way to get lint to detect a closed loop of code which can
   >never be called?

   Lint would need to do call graph analysis to find these; I have never
   seen one that does.
   -- 
   In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163)
   Domain:	chris@mimsy.umd.edu	Path:	uunet!mimsy!chris

Don't hold your breath - determining whether code is reachable is
equivalent to the halting problem. Lint takes long enough already -
infinite time seems a little over-the-top.
--
Paul Hudson	 MAIL: Monotype ADG, Science Park, Cambridge, CB4 4FQ, UK.
		PHONE: +44 (223) 420018	  EMAIL: paul@moncam.co.uk,
	;"	  FAX: +44 (223) 420911		 ...!ukc!acorn!moncam!paul
 `"";";"        These opinions void where prohibited by law.

hascall@atanasoff.cs.iastate.edu (John Hascall) (08/01/89)

In article <PAUL.89Jul31124616> paul@moncam.co.uk (Paul Hudson) writes:
>In article <18796@mimsy.UUCP> chris@mimsy.UUCP (Chris Torek) writes:
 
>   Lint would need to do call graph analysis to find these; I have never
>   seen one that does.
 
>Don't hold your breath - determining whether code is reachable is
>equivalent to the halting problem. Lint takes long enough already -
>infinite time seems a little over-the-top.

    Yes, but if you ignore conditionals (i.e., assume that all branches
    will be taken at some time) the problem of becomes much simpler--and
    I believe this is the problem the original poster has in mind.

    It parallels a check for variables declared but never used.

John Hascall

chris@mimsy.UUCP (Chris Torek) (08/01/89)

In some article someone asked:
>>Is there any way to get lint to detect a closed loop of code which can
>>never be called?

>In article <18796@mimsy.UUCP> I suggested that
>Lint would need to do call graph analysis to find these; I have never
>seen one that does.

In article <PAUL.89Jul31124616@marvin.moncam.co.uk> paul@moncam.co.uk
(Paul Hudson) replies:
>Don't hold your breath - determining whether code is reachable is
>equivalent to the halting problem. Lint takes long enough already -
>infinite time seems a little over-the-top.

This is true.  The problem of discovering that some code is not
reachable is, however, simpler.  That is, there exist code sequences
that are easy to prove unreachable.  Although there are some sequences
that are unsolvable---for instance,

	if (other_program_halts())
		fn();
	else
		exit(0);

---there are plenty of sequences that *are* solvable, such as

	int main() { return 0; }
	void a() { b(); }
	void b() { a(); }

and it would certainly be `in the spirit of lint' to find such.

Note that this problem is essentially the same as discovering that

	f()
	{
		goto skip;
	loop:
		notused();
		goto loop;
	skip:
		used();

	}

contains unreachable code, except that the scope over which one
must analyse is greater.  Of course, lint does not catch this last
example either.
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163)
Domain:	chris@mimsy.umd.edu	Path:	uunet!mimsy!chris

jeffrey@algor2.uu.net (Jeffrey Kegler) (08/16/89)

In article <5967@ingr.com> boyd@ingr.com (Boyd Nation) writes:
>1)  How does one prevent lint from issuing a warning message about possible
>pointer alignment problems given the following line of code:
>
>	x = (blivet *)malloc(sizeof(blivet));

#ifdef lint
#define NOSTRICT(type, exp) ((exp)?(type)0:(type)0)
#else
#define NOSTRICT(type, exp) ((type)(exp))
#endif

so that the expression above becomes
       x = NOSTRICT(blivet *,malloc(sizeof(blivet)));

This solves all complaints about casts, possible loss of precision,
etc.  Note the expression exp is still type-checked by lint, so you
are turning lint off only on the cast.

I believe in making lint absolutely silent, that is, lint returns nothing
but another shell prompt.  Otherwise, lint messages pile up and it
becomes impossible to sort out that there are now 16 "possible loss of
precision" messages instead of 15 and the new one ain't just crying
wolf, either.  This is particularly true is you are not the only one
who worked on the code.
-- 

Jeffrey Kegler, Independent UNIX Consultant, Algorists, Inc.
jeffrey@algor2.ALGORISTS.COM or uunet!algor2!jeffrey
1762 Wainwright DR, Reston VA 22090

jac@paul.rutgers.edu (Jonathan A. Chandross) (08/17/89)

boyd@ingr.com (Boyd Nation) writes:
>1)  How does one prevent lint from issuing a warning message about possible
>pointer alignment problems given the following line of code:
>	x = (blivet *)malloc(sizeof(blivet));

jeffrey@algor2.uu.net (Jeffrey Kegler)
> #ifdef lint
> #define NOSTRICT(type, exp) ((exp)?(type)0:(type)0)
> #else
> #define NOSTRICT(type, exp) ((type)(exp))
> #endif
> so that the expression above becomes
>       x = NOSTRICT(blivet *,malloc(sizeof(blivet)));

I use an entirely different approach.  I declare a fake malloc:

	void *my_malloc(size)
	unsigned int	size;
	{
	extern	char	*malloc();

		return((void *)malloc(size));
	}

and then whenever I use it I say something like:

	....
	extern	void	*my_malloc()
	ZAP		*zap_pntr = (ZAP *)my_malloc((U_INT)sizeof(ZAP));	

This shuts up lint except for the line in my_malloc where I cast from
char * to void *.  I figure that 1 ignorable complaint is better than
hundreds of them.


Jonathan A. Chandross
Internet: jac@paul.rutgers.edu
UUCP: rutgers!paul.rutgers.edu!jac

karl@haddock.ima.isc.com (Karl Heuer) (08/17/89)

In article <1989Aug16.152316.24402@algor2.uu.net> jeffrey@algor2.UUCP (Jeffrey Kegler) writes:
>I believe in making lint absolutely silent, that is, lint returns nothing
>but another shell prompt.

I believe this is a worthy goal, but I refuse to add that much clutter to my
code just to work around a lint bug.

>In article <5967@ingr.com> boyd@ingr.com (Boyd Nation) writes:
>>1)  How does one prevent lint from issuing a warning message about possible
>>pointer alignment problems given the following line of code:
>>	x = (blivet *)malloc(sizeof(blivet));

The best long-term solution is to pester your vendor to fix lint.  A simple
lintpragma /*ALIGNED*/, attached to the declarations (*not* the invocations!)
of malloc(), calloc(), and realloc() would be a nice general solution.

You might also ask them to add a lintpragma /*NONRETURNING*/ that can be
attached to the declarations of exit() and longjmp(), which would obsolete the
/*NOTREACHED*/ hack.

Karl W. Z. Heuer (ima!haddock!karl or karl@haddock.isc.com), The Walking Lint