do any compilers notice/warn on always false expressions used as conditions

D

David Resnick

We recently had a bug that was (effectively) something like this

if ( a < 0 && a > someConstantValue )
{
/* do some error handling */
}

The && meant to be ||, somehow slipped through the cracks during code
review and was an error case that never actually got tested. gcc
doesn't object to the above with -Wall -Wextra. I'm wondering if
there are options with gcc or for that matter other compilers that
might notice this sort of always false condition, which they can know
at compile time always true/always false assuming a is not volatile.
I realize that this would need special casing to not warn on the cases
like if (0), while (0), while (1) that are rather heavily used, and
maybe this would conflict with other common usage. gcc does warn on
some comparisons it can notice by static analysis are always false
based on type range, which feels a bit related, such as:

temp(861)$ cat foo.c
#include <stdio.h>
int main(void)
{
const unsigned char a = 5;
if ( a < 0 && a > 255)
{
printf("Absolutely, totally, and in all other ways
inconceivable.\n");
}

return 0;
}
temp(862)$ gcc -o foo -Wall -pedantic -Wextra -O2 foo
foo.c: In function 'main':
foo.c:5: warning: comparison is always false due to limited range of
data type
foo.c:5: warning: comparison is always false due to limited range of
data type

It makes the two warnings the same whether it is && or ||.

gcc also generates the warning here, where the overall condition is in
fact always true, it is based on the individual comparison not the
overall expression...
const unsigned char a = 5;
if ( a < 0 || a == 5)
{
printf("You keep using that word. I do not think it means
what you think it means.\n");
}

Any thoughts? Just too complicated in practice? Worth raising to gcc/
others?
 
B

Bill Davy

David Resnick said:
We recently had a bug that was (effectively) something like this

if ( a < 0 && a > someConstantValue )
{
/* do some error handling */
}

The && meant to be ||, somehow slipped through the cracks during code
review and was an error case that never actually got tested. gcc
doesn't object to the above with -Wall -Wextra. I'm wondering if
there are options with gcc or for that matter other compilers that
might notice this sort of always false condition, which they can know
at compile time always true/always false assuming a is not volatile.
I realize that this would need special casing to not warn on the cases
like if (0), while (0), while (1) that are rather heavily used, and
maybe this would conflict with other common usage. gcc does warn on
some comparisons it can notice by static analysis are always false
based on type range, which feels a bit related, such as:

temp(861)$ cat foo.c
#include <stdio.h>
int main(void)
{
const unsigned char a = 5;
if ( a < 0 && a > 255)
{
printf("Absolutely, totally, and in all other ways
inconceivable.\n");
}

return 0;
}
temp(862)$ gcc -o foo -Wall -pedantic -Wextra -O2 foo
foo.c: In function 'main':
foo.c:5: warning: comparison is always false due to limited range of
data type
foo.c:5: warning: comparison is always false due to limited range of
data type

It makes the two warnings the same whether it is && or ||.

gcc also generates the warning here, where the overall condition is in
fact always true, it is based on the individual comparison not the
overall expression...
const unsigned char a = 5;
if ( a < 0 || a == 5)
{
printf("You keep using that word. I do not think it means
what you think it means.\n");
}

Any thoughts? Just too complicated in practice? Worth raising to gcc/
others?


PC-Lint would certainly point out "(unsigned) < 0" is questionable. Their
user forums are pretty good (http://www.gimpel.com/).
They have reasonable value tracking ideas which help a lot.

Bill
 
I

Ike Naar

const unsigned char a = 5;
if ( a < 0 && a > 255)
[...]
foo.c:5: warning: comparison is always false due to limited range of
data type

Apparently the warning is about the ``a < 0'' part.
``a'' has an unsigned type so it cannot be less than zero.
 
C

Chris H

In message <[email protected]
s.com> said:
We recently had a bug that was (effectively) something like this

if ( a < 0 && a > someConstantValue )
{
/* do some error handling */
}

The && meant to be ||, somehow slipped through the cracks during code
review and was an error case that never actually got tested.

It's not a compiler problem. A compiler is a translator. If the code is
legal syntax the compiler is happy.

What you need is static analysis.
 
D

David Resnick

It's not a compiler problem.  A compiler is a translator. If the code is
legal syntax the compiler is happy.

What you need is static analysis.

Yes, sure. But gcc does notice superficially similar classes of
problems. Just was wondering if there was any precedent (or
specifically gcc way) that the compiler might notice this. For
example, the optimizer might quite reasonably detect this and remove
the branching entirely if the condition at compile time can be
determined to be always false/always true, in which case there COULD
be an associated warning...

-David
 
C

Chris H

In message <[email protected]
s.com> said:
Yes, sure. But gcc does notice superficially similar classes of
problems.

You said it: "superficially similar".

That is why all C code should be statically analysed. It was always
intended that Lint should be part of the compile chain to stop "legal
but dubious constructs"
 
W

Willem

David Resnick wrote:
) The && meant to be ||, somehow slipped through the cracks during code
) review and was an error case that never actually got tested. gcc
) doesn't object to the above with -Wall -Wextra. I'm wondering if

Does -Wextra include -Wunreachable-code ?
Are you using optimization ?


SaSW, Willem
--
Disclaimer: I am in no way responsible for any of the statements
made in the above text. For all I know I might be
drugged or something..
No I'm not paranoid. You all think I'm paranoid, don't you !
#EOT
 
D

David Resnick

David Resnick wrote:

) The && meant to be ||, somehow slipped through the cracks during code
) review and was an error case that never actually got tested.  gcc
) doesn't object to the above with -Wall -Wextra.  I'm wondering if

Does -Wextra include -Wunreachable-code ?
Are you using optimization ?


Just what I was looking for, thanks. That flag makes gcc notice.
example:

temp(926)$ cat foo.c
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int a = rand();
if ( a < 0 && a > 5)
{
printf("inconceivable\n");
}

return 0;
}
temp(927)$ gcc -o foo -Wall -pedantic -Wextra -Wunreachable-code -O2
foo.c
foo.c: In function 'main':
foo.c:8: warning: will never be executed

Note that -Wextra alone doesn't give you that...

-David
 
R

robin

| We recently had a bug that was (effectively) something like this
|
| if ( a < 0 && a > someConstantValue )
| {
| /* do some error handling */
| }
|
| The && meant to be ||, somehow slipped through the cracks during code
| review and was an error case that never actually got tested. gcc
| doesn't object to the above with -Wall -Wextra. I'm wondering if
| there are options with gcc or for that matter other compilers that
| might notice this sort of always false condition, which they can know
| at compile time always true/always false assuming a is not volatile.
| I realize that this would need special casing to not warn on the cases
| like if (0), while (0), while (1) that are rather heavily used, and
| maybe this would conflict with other common usage. gcc does warn on
| some comparisons it can notice by static analysis are always false
| based on type range, which feels a bit related, such as:
|
| temp(861)$ cat foo.c
| #include <stdio.h>
| int main(void)
| {
| const unsigned char a = 5;
| if ( a < 0 && a > 255)

if 'a' is unsigned char, how it is going to be negative?
Greater than 255?
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,995
Messages
2,570,225
Members
46,815
Latest member
treekmostly22

Latest Threads

Top