[comp.lang.c] lint diagnostic

gae@osupyr.UUCP (Gerald Edgar) (12/26/87)

It seems to me this is weird.  Have I misunderstood something?

112> cat x.c
#include <stdio.h>
void
defmach(lo)
  int lo;
{
printf(" %08x\n",lo);
}
main()
{
  printf("sizeof(int) = %d\n",sizeof(int));
  printf("sizeof(long) = %d\n",sizeof(long));
  defmach(65535);
  exit(0);
}

113> cc x.c
114> a.out
sizeof(int) = 4
sizeof(long) = 4
 0000ffff
115> lint x.c
x.c:
defmach, arg. 1 used inconsistently	x.c(6)  ::  x.c(13)
-- 
  Gerald A. Edgar                               TS1871@OHSTVMA.bitnet
  Department of Mathematics                     gae@osupyr.UUCP
  The Ohio State University  ...{akgua,gatech,ihnp4,ulysses}!cbosgd!osupyr!gae
  Columbus, OH 43210                            70715,1324  CompuServe

bobmon@iuvax.UUCP (Bobmon) (12/28/87)

In article <365@osupyr.UUCP> gae@osupyr.UUCP (Gerald Edgar) writes:
+It seems to me this is weird.  Have I misunderstood something?
+
+112> cat x.c
+#include <stdio.h>
+void defmach(lo)
+  int lo;
+{
+printf(" %08x\n",lo);
+}
+main()
+{
+  printf("sizeof(int) = %d\n",sizeof(int));
+  printf("sizeof(long) = %d\n",sizeof(long));
+  defmach(65535);
+  exit(0);
+}
+
+113> cc x.c
+114> a.out
+sizeof(int) = 4
+sizeof(long) = 4
+ 0000ffff
+115> lint x.c
+x.c:
+defmach, arg. 1 used inconsistently	x.c(6)  ::  x.c(13)
+-- 

After playing a bit with the Ultrix cc, and with my MSDOS TurboC, I think:

1)  int's and long's are both 4 bytes on your machine (they seem to be with
    'my' cc, they differ with TurboC).

2)  The constant 65535 is automagically promoted to type long, which is
    inconsistent with the int-type parameter.  (This is sensible on my TurboC,
    where 65535 is too big for 2 (signed) bytes; I don't know why 'cc' would
    bother to do it unless there's a compatibility issue here.)

Did I get it right, Teacher?

gwyn@brl-smoke.ARPA (Doug Gwyn ) (01/06/88)

In article <365@osupyr.UUCP> gae@osupyr.UUCP (Gerald Edgar) writes:
>void
>defmach(lo)
>  int lo;
[...]
>  defmach(65535);
[...]
>defmach, arg. 1 used inconsistently	x.c(6)  ::  x.c(13)

You passed it a long (65535 on a 16-bit machine) but it expects an int.

am@cl.cam.ac.uk (Alan Mycroft) (01/21/88)

[The last line is a query as to whether a full lint can be written!]

In article <5304@iuvax.UUCP> bobmon@iuvax.UUCP (Bobmon) writes:
>In article <365@osupyr.UUCP> gae@osupyr.UUCP (Gerald Edgar) writes:
>+defmach(lo) int lo; [...]
>+main()
>+{ printf("sizeof(int) = %d\n",sizeof(int));
>+  printf("sizeof(long) = %d\n",sizeof(long));
>+  defmach(65535);
>+  exit(0); }
[Execution]
>+sizeof(int) = 4; sizeof(long) = 4; 0000ffff
[Lint]
>+defmach, arg. 1 used inconsistently	x.c(6)  ::  x.c(13)

Doug Gwyn says..
>You passed it a long (65535 on a 16-bit machine) but it expects an int.

I think a more correct explaination is that you have a non-matching
cc and lint -- lint thinks sizeof(int) == 2 so that
65535 has type (long int) whereas cc thinks sizeof(int)==4 so that
65535 has type (int).
You can test it by trying something like
  int a[256/(sizeof(int)-2)];
and seeing if lint splutters.

Thus it would seem to be very hard indeed to write a lint which tries
hard to find 'strictly conforming' ANSI programs -- each number above
0x7fff would be regarded as having two or more types:
  E.g. int x = 99999;      is dubious if sizeof(int)==2
whereas
       printf("%ld", 99999) is dubious if sizeof(int)==4
(it may not work if sizeof(long)==8).
Things become even harder with size_t/ptrdiff_t...

msb@sq.uucp (Mark Brader) (01/30/88)

> >+defmach(lo) int lo; [...]
> >+main()
> >+{ printf("sizeof(int) = %d\n",sizeof(int));
> >+  printf("sizeof(long) = %d\n",sizeof(long));
> >+  defmach(65535);
> >+  exit(0); }
> [Execution]
> >+sizeof(int) = 4; sizeof(long) = 4; 0000ffff
> [Lint]
> >+defmach, arg. 1 used inconsistently	x.c(6)  ::  x.c(13)

> I think a more correct explaination is that you have a non-matching
> cc and lint -- lint thinks sizeof(int) == 2 so that
> 65535 has type (long int) whereas cc thinks sizeof(int)==4 ...

Maybe, or maybe just a clever lint.

One of the purposes of lint is to detect *portability errors*.
The type of the constant 65535 may be int (on a machine with, say, 18-bit
ints) or long, and it must not be used where EITHER int OR long is
specifically required, as in a pre-ANSI function call.  One should always
write 65535L in such positions, and treat the thing as long.

To paraphrase Alan Mycroft's article, integer constants above 32767 should
be treated by lint as having an unknown one of two different types.

>   E.g. int x = 99999;      is dubious if sizeof(int)==2
>        printf("%ld", 99999) is dubious if sizeof(int)==4

I'd say they're dubious any time, and *wrong* in the cases called "dubious"
above.  Anyway, all this got me wondering, and I constructed the following:

	int a(x) int x; {}
	int b(x) long x; {}
	main() {a(65535); b(65535);}

and ran lint on it here on our Sun (version 3.2).  And, yes, it did NOT
complain about the second 65535.  All the world's a land of 16 or 32 bit ints?

Mark Brader, SoftQuad Inc., Toronto, utzoo!sq!msb, msb@sq.com
#define	MSB(type)	(~(((unsigned type)-1)>>1))