[comp.lang.c] turbo-C and lint ?

alanf@bruce.OZ (Alan Grant Finlay) (03/20/90)

I was surprised to discover that the Turbo-C package does not come with a lint
program.  Specifically I want to have the ability to automatically check for
procedure argument type consistency.  When in the past I have complained to
C advocates that C compilers don't check for consistent use of parameters they
have usually replied "that's what lint is for!".  Is it really acceptable for
a commercial compiler package to come supplied without an essential part or
have I missed something in the package that does the same job?

Also does anyone know if there are any public domain lints available that will
work with Turbo-C source?

reino@cs.eur.nl (Reino de Boer) (03/20/90)

alanf@bruce.OZ (Alan Grant Finlay) writes:

>I was surprised to discover that the Turbo-C package does not come with a lint
>program.  Specifically I want to have the ability to automatically check for
>procedure argument type consistency.  When in the past I have complained to

Doesn't Turbo-C have a built-in checking mechanism ?

Reino
-- 
Reino R. A. de Boer
Erasmus University Rotterdam ( Informatica )
e-mail: reino@cs.eur.nl

noren@dinl.uucp (Charles Noren) (03/21/90)

In article <1964@bruce.OZ> alanf@bruce.OZ (Alan Grant Finlay) writes:
>I was surprised to discover that the Turbo-C package does not come with a lint
>program....

Turbo C combines the lint checking with its compiler, thus you can optionally
turn on all the lint diagnostics when you compile.  The manual provides
details on how to do this.
-- 
Chuck Noren
NET:     ncar!dinl!noren
US-MAIL: Martin Marietta I&CS, MS XL8058, P.O. Box 1260,
         Denver, CO 80201-1260
Phone:   (303) 971-7930

dms@cs.arizona.edu (David Michael Shackelford) (03/21/90)

In article <1964@bruce.OZ>, alanf@bruce.OZ (Alan Grant Finlay) writes:
> I was surprised to discover that the Turbo-C package does not come with a lint
> program.  Specifically I want to have the ability to automatically check for
> procedure argument type consistency.  When in the past I have complained to
> C advocates that C compilers don't check for consistent use of parameters they
> have usually replied "that's what lint is for!".  Is it really acceptable for
> a commercial compiler package to come supplied without an essential part or
> have I missed something in the package that does the same job?
> 
> Also does anyone know if there are any public domain lints available that will
> work with Turbo-C source?

I use Turbo-C's extended function prototype syntax and it checks for parameter
type compatibility at the function calls.  There might be an option in the   
compiler/warnings menu to cause it to give the message when types dont match.
I compile with all error and warning messages enabled.

As for the lint package, I don't know of any.  Maybe someone else has an idea..

There might be a portability problem with using Turbo's extended prototypes,
so if you're planning on porting, beware...

alanf@bruce.OZ (Alan Grant Finlay) (03/21/90)

In article <1990Mar20.130947.16583@cs.eur.nl>, reino@cs.eur.nl (Reino de Boer) writes:
> 
> Doesn't Turbo-C have a built-in checking mechanism ?
> 

In article <1555@dinl.mmc.UUCP>, noren@dinl.uucp (Charles Noren) writes:
> Turbo C combines the lint checking with its compiler, thus you can optionally
> turn on all the lint diagnostics when you compile.  The manual provides
> details on how to do this.
> -- 

Both of these were in reponse to my original query which may not have been
specific enough.  Consider the following correct program:

check(x,y)
long x;
char *y;
{
printf("%10.10s ",y);
}
main()
{
check(10l,"testing");
}

If you now remove the l after the 10 in the procedure call the compiler
issues no relevant warnings and the program misbehaves.  Can Turbo-C 
generate a warning for this kind of error?

bobmon@iuvax.cs.indiana.edu (RAMontante) (03/21/90)

alanf@bruce.OZ (Alan Grant Finlay) <1966@bruce.OZ> :
-main()
-{
-check(10l,"testing");
-}
-
-If you now remove the l after the 10 in the procedure call the compiler
-issues no relevant warnings and the program misbehaves.  Can Turbo-C 
-generate a warning for this kind of error?

The "Portability Warnings" sub-sub-sub-menu includes `long constant'
warnings as well as others.  Go through the Options menu and turn on
all the warnings and errors that you care about.  They're all available
in the command-line version as well.  The factory default turns most of
these off, so you may not have known they were there.

martinr@cpqhou.UUCP (Martin Richek) (03/21/90)

In article <1990Mar20.130947.16583@cs.eur.nl>, reino@cs.eur.nl (Reino de Boer) writes:
> alanf@bruce.OZ (Alan Grant Finlay) writes:
> 
> >I was surprised to discover that the Turbo-C package does not come with a lint
> >program.  Specifically I want to have the ability to automatically check for
> >procedure argument type consistency.  When in the past I have complained to
> 
> Doesn't Turbo-C have a built-in checking mechanism ?
> 

Yes, it does.  Use the highest warning level.

reino@cs.eur.nl (Reino de Boer) (03/21/90)

alanf@bruce.OZ (Alan Grant Finlay) writes:

>Both of these were in reponse to my original query which may not have been
>specific enough.  Consider the following correct program:

>check(x,y)
>long x;
>char *y;
>{
>printf("%10.10s ",y);
>}
>main()
>{
>check(10l,"testing");
>}

>If you now remove the l after the 10 in the procedure call the compiler
>issues no relevant warnings and the program misbehaves.  Can Turbo-C 
>generate a warning for this kind of error?

lint (Sun OS 4.0.3):
--------------------
test.c(2): warning: argument x unused in function check
check, arg. 1 used inconsistently	test.c(4)  ::  test.c(9)
printf returns value which is always ignored

Turbo-C:
--------
(Not exactly reproduced)
Parameter x never used in function check
Function should return a value in function check
Function should return a value in function main

We can conclude that Turbo-C's checking mechanism does not detect that
parameter 'x' is used inconsistently,
and
that lint does not complain about the lack of return statements.

Hope this answers your question, 
Reino

P.S. Turbo-C also complains about the lack of prototypes for 'check' and
'printf'.

-- 
Reino R. A. de Boer
Erasmus University Rotterdam ( Informatica )
e-mail: reino@cs.eur.nl

teittinen@cc.helsinki.fi (03/21/90)

In article <1966@bruce.OZ>, alanf@bruce.OZ (Alan Grant Finlay) writes:
> check(x,y)
> long x;
> char *y;
> {
> printf("%10.10s ",y);
> }
> main()
> {
> check(10l,"testing");
> }
> 
> If you now remove the l after the 10 in the procedure call the compiler
> issues no relevant warnings and the program misbehaves.  Can Turbo-C 
> generate a warning for this kind of error?

Why are you using old style function definitions, if you're interested
of getting rid of bugs? If you write the check function again using
ANSI-style function definition (void check(long x, char *y)) the compiler
does automatic type conversion and no errors occur. Why make easy things
difficult?

-- 
E-Mail: teittinen@finuh.bitnet               ! "Studying is the only way
        teittinen@cc.helsinki.fi             !  to do nothing without
Marko Teittinen, student of computer science !  anyone blaming you" -me

noren@dinl.uucp (Charles Noren) (03/22/90)

In article <1966@bruce.OZ> alanf@bruce.OZ (Alan Grant Finlay) writes:
 >In article <1990Mar20.130947.16583@cs.eur.nl>, reino@cs.eur.nl (Reino de Boer) writes:
 >In article <1555@dinl.mmc.UUCP>, noren@dinl.uucp (Charles Noren) writes:
 >Both of these were in reponse to my original query which may not have been
 >specific enough.  Consider the following correct program:
 >
 >check(x,y)
 >long x;
 >char *y;
 >{
 >printf("%10.10s ",y);
 >}
 >main()
 >{
 >check(10l,"testing");
 >}
 >
 >If you now remove the l after the 10 in the procedure call the compiler
 >issues no relevant warnings and the program misbehaves.  Can Turbo-C 
 >generate a warning for this kind of error?

My Turbo C stuff is at home...
but I suggest you use the ANSI C features of the compiler, so your
code would become:

void check(long x, char *y)    /* I always want to explicitly say what the
                                  function returns, in this case nothing
                                  (the previous definition returned an int). */
{
    printf("%10.10s ", y);
}

main()
{
    check(10l, "testing");
}

...now Turbo C, under its default settings, will check the argument
list in the function check().  If the "l" is taken out, Turbo C
will let you know.  Turbo C should also tell you that you did
not use argument x in function check().  These are the "lintish"
features of the compiler.  You can turn off the unused argument
check by using a #pragma statement as documented in the Turbo C
manuals (this corresponds to a same lint capability).

As another poster has mentioned, the default checks on your code
by Turbo C, while more than "standard" C compilers, is rather
limited.  Check the documentation for turning on more of the
checks.


-- 
Chuck Noren
NET:     ncar!dinl!noren
US-MAIL: Martin Marietta I&CS, MS XL8058, P.O. Box 1260,
         Denver, CO 80201-1260
Phone:   (303) 971-7930

alawrenc@sobeco.com (a.lawrence) (03/24/90)

From article <1964@bruce.OZ>, by alanf@bruce.OZ (Alan Grant Finlay):
> I was surprised to discover that the Turbo-C package does not come with a lint
> program.  Specifically I want to have the ability to automatically check for
> procedure argument type consistency.  When in the past I have complained to
> C advocates that C compilers don't check for consistent use of parameters they
> have usually replied "that's what lint is for!".  Is it really acceptable for
> a commercial compiler package to come supplied without an essential part or
> have I missed something in the package that does the same job?

I think you had better take a second look at your compiler.  If you turn on
all the warning levels, it will do a much better job verifying your code than
most lint programs.  Turbo C has often found serious problems in programs 
which compiled and linted corrected on UNIX.

As far as function definitions go, if you use ANSI style function prototypes
Turbo C which check all of you function calls very closely, and even report
a warning when the code you right is acceptable C but probably not what you
wanted (suspicious pointer casts, etc).

If you want the code you are developing to be portable to non-ANSI compilers
use the following macro:

  	#ifdef ansi_style
	#define P(x)  x
	#else
	#define P(x)  ()
	#endif

and code your function prototype as:

	char *function P((int num, har *string));

---
On a clear disk you can seek forever.
-------------------------------------------------------------------------
Andrew Lawrence        |  alawrenc@sobmips.sobeco.UUCP
Informaticien Conseil  |  {attcan,mcgill-vision}!sobeco!sobmips!alawrenc
3462 Jeanne-Mance, #1  |
Montreal, Que  CANADA  |  Voice (514) 281-5196

dfoster@jarthur.Claremont.EDU (Derek R. Foster) (03/25/90)

In article <1990Mar21.110835.29391@cs.eur.nl> reino@cs.eur.nl (Reino de Boer) writes:
>alanf@bruce.OZ (Alan Grant Finlay) writes:

>> Consider the following correct program:

>>check(x,y)
>>long x;
>>char *y;
>>{
>>printf("%10.10s ",y);
>>}
>>main()
>>{
>>check(10l,"testing");
>>}
>
>>If you now remove the l after the 10 in the procedure call the compiler
>>issues no relevant warnings and the program misbehaves.  Can Turbo-C 
>>generate a warning for this kind of error?

>[The output from Turbo C with all warnings turned on is compared to
> that of lint. Turbo C does not comment on the call of check involving
> an int.] 

>We can conclude that Turbo-C's checking mechanism does not detect that
>parameter 'x' is used inconsistently,

>Reino R. A. de Boer
>Erasmus University Rotterdam ( Informatica )
>e-mail: reino@cs.eur.nl

The reason that Turbo-C doesn't report an error for this is that for
Turbo-C, it ISN'T an error. For two reasons:

1) when you prototyped

     check(x,y);

   what were are essentially telling Turbo C is

   "I'm going to declare a function, and it takes two arguments, but
    it's none of your business what type those arguments are. Let me
    deal with it."

   So Turbo C respects that request, and does no type checking other
   than to verify that the correct number of arguments are passed.

2) If you had prototyped

     void check(long x, char * y);

   or declared your function as

     void check(long x, char * y) { ... }

   you would have told Turbo C

   "I'm declaring a function that has no return value and takes two
    arguments: a long value and a character pointer. If I try to pass
                                                     ^^^^^^^^^^^^^^^^
    anything else to it, try to convert what I pass to a long and a
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    character pointer, respectively. If you can't, report an error."

You CAN pass an int value to a function which takes a long
parameter. It will simply be sign-extended if necessary, so that
the value that the function recieves as a long represents the
same number that was passed as an int.

Passing a long value to an function which takes an int
parameter will provoke the warning "Conversion may lose
significant digits", and will essentially chop off the
most significant bytes, still attempting to preserve the
sign.

These automagic conversions of values can take place between
many kinds of VALUES (not pointers), including

    char            <-> int

    signed whatever <-> unsigned whatever

    int <-> float
      (I'm not sure about float->int. I think C just truncates
       after the decimal, but I'm not certain. Rounding is also
       possible, or requiring an explicit cast. This is a tricky
       one even under the best of circumstances.)

      (I'm also not sure about int<->enum or int<->typedef int xxx)

Note that while an attempt to send an int to a function which takes
a long parameter is legal, an attempt to send an (int *) to a function
that takes a (long *) is illegal and will provoke a "non-portable
pointer assignment" warning or somesuch, since the compiler can't
really compile conversion code into every statement that might
use indirection on the pointer.

So you see, the reason that Turbo C doesn't complain about your leaving
off the "l" on the constant is (1) because you haven't prototyped
check() properly, and (2) even if you did, Turbo C would simply
convert the int to a long and then end up passing the same value to
check(). It's not that Turbo C has inadequate error-CHECKING abilities.
Instead, it has greater potential error HANDLING.

Side note:
This is also (I think) a reason why the value NULL should be able to
be passed to functions which take other than (void *) parameters, without
explicit casting. If the function is prototyped properly, the compiler
should recognize that since NULL has type (void *) and the function accepts
a (char *), for instance, that a conversion may be necessary if the
value "NULL" in a (char *) is different from that in a (void *). Or why
you don't need to say memcpy((void *) &x, (void *) &y, len), as someone
has suggested recently. The (void *) cast is implicit in the prototype of
memcpy as "void * memcpy(void * x, void * y, size_t z)" (or something
similar -- this is off the top of my head.), and the compiler shouldn't
even issue a warning for implied casts to and from a (void *). Passing a
(char *) to an (int *) will probably give you a warning message, but it can
STILL technically be handled, even if the representations of the pointers
are different. (I would not suggest you do this, however! It is rather
nonportable! Anything to/from a void * should be OK, however)

BTW, I would like to know how much of this if this is standard behavior for
ANSI C, and how much is Turbo C extensions. What does the standard say?

I hope this clears up some confusion!

Derek Riippa Foster

darcy@druid.uucp (D'Arcy J.M. Cain) (03/26/90)

In article <1964@bruce.OZ> alanf@bruce.OZ (Alan Grant Finlay) writes:
>I was surprised to discover that the Turbo-C package does not come with a lint
>program.  Specifically I want to have the ability to automatically check for
>procedure argument type consistency.  When in the past I have complained to
>C advocates that C compilers don't check for consistent use of parameters they
>have usually replied "that's what lint is for!".  Is it really acceptable for
>a commercial compiler package to come supplied without an essential part or
>have I missed something in the package that does the same job?
>
>Also does anyone know if there are any public domain lints available that will
>work with Turbo-C source?

In Turbo-C (2.0 at least) lint is effectively built in.  As long as the
functions are prototyped (and this is true for all of their library functions
if you include the proper header files) then you can be warned of all these
sorts of things.  You must turn on the warnings with a switch but these
can be turned on as a default in your configuration file.  I think that
this type of checking is true for all compilers that try to be ANSI compliant.
That is the point of prototyping - to be able to check each call for errors.

-- 
D'Arcy J.M. Cain (darcy@druid)     |   Thank goodness we don't get all 
D'Arcy Cain Consulting             |   the government we pay for.
West Hill, Ontario, Canada         |
(416) 281-6094                     |

darcy@druid.uucp (D'Arcy J.M. Cain) (03/26/90)

In article <1966@bruce.OZ> alanf@bruce.OZ (Alan Grant Finlay) writes:
> [...]
>check(x,y)
>long x;
>char *y;
>{
>printf("%10.10s ",y);
>}
>main()
>{
>check(10l,"testing");
>}
>
>If you now remove the l after the 10 in the procedure call the compiler
>issues no relevant warnings and the program misbehaves.  Can Turbo-C 
>generate a warning for this kind of error?

Yes if you code it properly (the ANSI way) as follows:

void check(long x,char *y)
{
printf("%10.10s ",y);
}
main()
{
check(10l,"testing");
}

The 'l' is now no longer necessary.  You won't get a warning message
because it will behave correctly.  The compiler knows when calling
"check" that the first argument is a long and does the promotion.  As
K&R2 says (pp 202):
	"If the function declaration in scope for a call is new-style, then
	the arguments are converted, as if by asignment, to the types of
	the corresponding parameters of the function's prototype."

Of course if the type can't be converted this fails but a suitable
error message will be generated.  This will catch the following error:
	check("testing", 10);

-- 
D'Arcy J.M. Cain (darcy@druid)     |   Thank goodness we don't get all 
D'Arcy Cain Consulting             |   the government we pay for.
West Hill, Ontario, Canada         |
(416) 281-6094                     |

jimp@cognos.UUCP (Jim Patterson) (04/11/90)

In article <90033012502875@masnet.uucp> david.megginson@canremote.uucp (DAVID MEGGINSON) writes:
>alawrenc@sobeco.com writes:
>>If you want the code you are developing to be portable to non-ANSI
>>compilers use the following macro:
>>
>>        #ifdef ANSI_style
>>
>Whoa, let's not get non-standard already. Why use
>
>       #ifdef ANSI_style
>
>instead of the ANSI standard
>
>       #ifdef __STDC__
>
>which all strict ANSI compilers should define automatically?

Using your own symbol instead of __STDC__ isn't non-standard, and
there are good reasons for avoiding scattering #ifdef __STDC__ all
through a large product. Sure, all strict ANSI compilers will define
__STDC__. However, a really strict ANSI compiler won't define __STDC__
if it's compiling in a mode that isn't strictly ANSI (e.g. if stdio.h
defines some externals that aren't in the ANSI standard; that's
namespace polution). What's more, it won't let YOU define __STDC__
(it's reserved). This doesn't mean that it won't support prototypes.
(Yes, there are such compilers).

There is also the converse problem. Some not-fully-ANSI compilers
define __STDC__, but to be some other value e.g. 0. It's conceivable
that a compiler vendor might define __STDC__ but might not support
prototypes, or they might have a bug which prevents their use. After
all, ANSI can't proscribe the actions of compiler venders who don't 
support the ANSI standard (though there's a pretty wide concensus that
such vendors are being quite anti-social).

So, using your own manifest name instead of __STDC__ is a good idea.
If your project has a common #include file as many do, then you can
#define your manifest there based on __STDC__ or whatever else
is appropriate, e.g.

#ifdef __STDC__
#if __STDC__ == 1
#define ANSI_style
#endif
#endif


-- 
Jim Patterson                              Cognos Incorporated
UUCP:decvax!utzoo!dciem!nrcaer!cognos!jimp P.O. BOX 9707    
PHONE:(613)738-1440                        3755 Riverside Drive
                                           Ottawa, Ont  K1G 3Z4

madhyani@ucf-cs.ucf.edu (04/20/90)

/* Written  1:32 am  Mar 20, 1990 by alanf@bruce.UUCP in ucf-cs.ucf.edu:comp.lang.c */
>/* ---------- "turbo-C and lint ?" ---------- */
>I was surprised to discover that the Turbo-C package does not come with a lint
>program.  Specifically I want to have the ability to automatically check for
>procedure argument type consistency.  When in the past I have complained to
>C advocates that C compilers don't check for consistent use of parameters they
>have usually replied "that's what lint is for!".  Is it really acceptable for
>a commercial compiler package to come supplied without an essential part or
>have I missed something in the package that does the same job?
>
>Also does anyone know if there are any public domain lints available that will
>work with Turbo-C source?
>/* End of text from ucf-cs.ucf.edu:comp.lang.c */

Are you using Turbo-C 2.0. If so, then you haven't dig into the menus.
Turbo C provides all the lint features you can find in 'UNIX lint'.


Read the manual, Hack the Main menu.

Good Luck!

--
Bharat madhyani
madhyani@ucf-cs.ucf.edu