Sunday, May 20, 2007

"-Wall" is misleading

So, what happens when we compile this code "-Wall"?

Not the answer you'd expect --

$ gcc -Wall test.c
$ ./a.exe
Whoops!
$

However, there are quite a few warnings in the gcc documentation that are marked as not being controlled by -Wall -- so let's turn on a bunch of them:

$ gcc -Wall -W -Wshadow -Wpointer-arith -Wcast-qual -Wcast-align -Wwrite-strings -Wconversion -Waggregate-return -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations -Wredundant-decls -Wnested-externs -Werror -ansi test.c
test.c: In function `main':
test.c:8: warning: comparison between signed and unsigned
test.c: At top level:
test.c:3: warning: unused parameter 'argc'
test.c:3: warning: unused parameter 'argv'

Ah!  That's better.

By contrast

C:\temp\unsign>cl test.c /W2
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 14.00.50727.42 for 80x86
Copyright (C) Microsoft Corporation.  All rights reserved.

test.c
Microsoft (R) Incremental Linker Version 8.00.50727.42
Copyright (C) Microsoft Corporation.  All rights reserved.

/out:test.exe
test.obj

C:\temp\unsign>cl test.c /W3
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 14.00.50727.42 for 80x86
Copyright (C) Microsoft Corporation.  All rights reserved.

test.c
test.c(8) : warning C4018: '<' : signed/unsigned mismatch
Microsoft (R) Incremental Linker Version 8.00.50727.42
Copyright (C) Microsoft Corporation.  All rights reserved.

/out:test.exe
test.obj

C:\temp\unsign>cl test.c /W4


Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 14.00.50727.42 for 80x86
Copyright (C) Microsoft Corporation.  All rights reserved.

test.c
test.c(8) : warning C4018: '<' : signed/unsigned mismatch
test.c(3) : warning C4100: 'argv' : unreferenced formal parameter
test.c(3) : warning C4100: 'argc' : unreferenced formal parameter
Microsoft (R) Incremental Linker Version 8.00.50727.42
Copyright (C) Microsoft Corporation.  All rights reserved.

/out:test.exe
test.obj

The Microsoft compiler takes the unsigned comparison as a level 3 warning, and that's what you get by default from DevStudio, with the unused argument warning at level 4.

So what's going on here?

Well in the comparison, the unsigned int is a "larger" type so a is promoted; but unsigned int is not actually any larger in terms of bits, so the bit value is preserved, and so a is interpreted as 2^32-1. Which is slightly larger than 1.

No comments :