Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

No Warning for Assignment in Boolean Expression

246 views
Skip to first unread message

CyberSimian

unread,
Jun 19, 2004, 7:31:19 PM6/19/04
to
I am not sure what the current thinking is about Open Watcom producing
warning messages for legal C, but Watcom currently generates a warning for
an assignment in a boolean expression. I think that that is useful, as
today I inadvertently coded THREE assignments in boolean expressions, but
only two of them gave rise to messages from Watcom. The following testcase
shows the one that didn't. I am using Open Watcom 1.2 on Win2K SP3.

-- from Cy in the UK


/* Test case for lack of warning msg in boolean expression */
void myfunc(int,char);
void another_func(char);

void myfunc(int mode, char type)
{
if (type='A') another_func(type); /* get warning here */

if (type='B' && mode==0) /* oops! no warning here */
{
type='C';
another_func(type);
}
return;
}


Jorge Hodge

unread,
Jun 19, 2004, 9:41:33 PM6/19/04
to
"CyberSimian" <CyberS...@BeeTeeInternet.com> wrote in message
news:cb2es4$jvo$1...@www1.scitechsoft.com...
<snip>

> /* Test case for lack of warning msg in boolean expression */
> void myfunc(int,char);
> void another_func(char);
>
> void myfunc(int mode, char type)
> {
> if (type='A') another_func(type); /* get warning here */
>
> if (type='B' && mode==0) /* oops! no warning here */
<snip>

The line in question is equivalent to:

if(type = ('B' && mode == 0))

So I think it looks to the compiler as if you're assigning the result of a
conditional expression to the var "type". I don't think the compiler should
generate a warning for this code, since if it was legitimate it would force
me to move the assignment out of the "if".


Steve Fábián

unread,
Jun 20, 2004, 7:41:44 AM6/20/04
to
"Jorge Hodge" <ho...@freenet.fsu.edu> wrote in message
news:cb2puv$sp1$1...@www1.scitechsoft.com...
: "CyberSimian" <CyberS...@BeeTeeInternet.com> wrote in message

Both statements combine multiple operations:

1) evaluate an expression

2) assign its value to an operand

3) use the value to make a decision

The only difference is the simplicity or complexity of the expression to
be evaluated in 1) above. Hence either both or neither should have
warnings.

--
Steve Fábián


Hans-Bernhard Broeker

unread,
Jun 20, 2004, 2:21:12 PM6/20/04
to
CyberSimian <CyberS...@beeteeinternet.com> wrote:

> if (type='B' && mode==0) /* oops! no warning here */

This is right at the borderline where warnings can turn from useful
information to harmful "compiler noise". The use of spaces
to isolate operators is actually deceptive. That line actually
gets parsed as:

if (type = ('B' && (mode == 0)))

As such, it should probably still trigger the compiler's "assignment
used as a truth value" warning. If it doesn't, that may count as a
bug. And just FYI: GCC does manage to pick up that flaw and warn
about it.

--
Hans-Bernhard Broeker (bro...@physik.rwth-aachen.de)
Even if all the snow were burnt, ashes would remain.

Michal Necasek

unread,
Jun 20, 2004, 5:11:09 PM6/20/04
to
CyberSimian wrote:
> I am not sure what the current thinking is about Open Watcom producing
> warning messages for legal C, but Watcom currently generates a warning for
> an assignment in a boolean expression. I think that that is useful, as
> today I inadvertently coded THREE assignments in boolean expressions, but
> only two of them gave rise to messages from Watcom. The following testcase
> shows the one that didn't. I am using Open Watcom 1.2 on Win2K SP3.
>
The warning message is slightly misleading. The explanation in the manual
is not:

'An assignment of a constant has been detected in a boolean expression.
For example: "if( var = 0 )". It is most likely that you want to use
"==" for testing for equality.'

Note the "assignment of a constant" phrase.

That said, I'm not against warning in other cases as well. The problem
is how to stop the compiler from warning on perfectly good code, like

while( *p++ = *q++ )
;

There is a very fine line between the warnings being helpful and getting
in the way.

I'd be curious to know what warnings other compilers give on the
following example:

------------------------boolwrn.c-------------------------
#include <stdio.h>

/* Test case for lack of warning msg in boolean expression */

void foo( int, char );
void bar( char );

void foo( int mode, char type )
{
float g;
FILE *f;
char *p = NULL, *q = NULL;

if( type = 't' ) {
bar( type );
}

while( *p++ = *q++ )
;

if((g = mode))
bar( type );

if( (f = fopen( "foo", "r" )) == NULL )
foo( 1, type );

if((g = 3.0))
bar( type );

if( type = 'A') bar( type );

if( type = 'B' && mode == 0 ) {
type = 'C';
bar( type );
}
return;
}
----------------------------------------------------------

Here's what wcc386 -wx says:

boolwrn.c(13): Warning! W105: Assignment found in boolean expression
boolwrn.c(29): Warning! W105: Assignment found in boolean expression

(It's a bug that it doesn't warn on the float assignment)

Here's wpp386 -wx:

boolwrn.c(13): Warning! W001: col(14) assignment of constant found in
boolean expression
boolwrn.c(17): Warning! W391: col(17) assignment found in boolean expression
boolwrn.c(20): Warning! W391: col(11) assignment found in boolean expression
boolwrn.c(26): Warning! W391: col(11) assignment found in boolean expression
boolwrn.c(29): Warning! W001: col(14) assignment of constant found in
boolean expression
boolwrn.c(31): Warning! W391: col(14) assignment found in boolean expression

Here's Borland C++ 4.11:

Warning boolwrn.c 13: Possibly incorrect assignment in function foo
Warning boolwrn.c 18: Possibly incorrect assignment in function foo
Warning boolwrn.c 20: Possibly incorrect assignment in function foo
Warning boolwrn.c 26: Possibly incorrect assignment in function foo
Warning boolwrn.c 29: Possibly incorrect assignment in function foo
Warning boolwrn.c 31: Possibly incorrect assignment in function foo
Warning boolwrn.c 36: 'f' is assigned a value that is never used in
function foo
Warning boolwrn.c 36: 'g' is assigned a value that is never used in
function foo

Here's IBM VisualAge C++ 3.08 with default warning level:

boolwrn.c(13:14) : informational EDC0426: An assignment expression is
used as a condition. An equality comparison (==) may have been intended.
boolwrn.c(20:8) : informational EDC0426: An assignment expression is
used as a condition. An equality comparison (==) may have been intended.
boolwrn.c(26:8) : informational EDC0426: An assignment expression is
used as a condition. An equality comparison (==) may have been intended.
boolwrn.c(29:14) : informational EDC0426: An assignment expression is
used as a condition. An equality comparison (==) may have been intended.
boolwrn.c(31:16) : informational EDC0424: The condition is always true.
boolwrn.c(31:14) : informational EDC0426: An assignment expression is
used as a condition. An equality comparison (==) may have been intended.

Note that for some reason there's no warning on line 17.

Here's IBM VisualAge C++ 3.08 again, with -Wall:

boolwrn.c(1) : informational EDC0743: Processing include file
J:\C\IBMC30\INCLUDE\stdio.h
J:\C\IBMC30\INCLUDE\stdio.h(1:2) : informational EDC0460: if nesting
level is 1.
J:\C\IBMC30\INCLUDE\stdio.h(1:2) : informational EDC0454: if condition
evaluates to 1.
J:\C\IBMC30\INCLUDE\stdio.h(332:2) : informational EDC0460: endif
nesting level is 1.
boolwrn.c(13:14) : informational EDC0426: An assignment expression is
used as a condition. An equality comparison (==) may have been intended.
boolwrn.c(17:5) : informational EDC0473: An unintended semi-colon may
have created an empty loop body.
boolwrn.c(20:8) : informational EDC0426: An assignment expression is
used as a condition. An equality comparison (==) may have been intended.
boolwrn.c(26:8) : informational EDC0453: Assigning a floating point type
to another floating point type with less precision.
boolwrn.c(26:8) : informational EDC0426: An assignment expression is
used as a condition. An equality comparison (==) may have been intended.
boolwrn.c(29:14) : informational EDC0426: An assignment expression is
used as a condition. An equality comparison (==) may have been intended.
boolwrn.c(31:16) : informational EDC0424: The condition is always true.
boolwrn.c(31:14) : informational EDC0451: The target integral type
cannot hold all possible values of the source integral type.
boolwrn.c(31:14) : informational EDC0426: An assignment expression is
used as a condition. An equality comparison (==) may have been intended.
boolwrn.c(36:1) : informational EDC0412: The variable 'f' is referenced
before being initialized.
boolwrn.c(36:1) : informational EDC0412: The variable 'g' is referenced
before being initialized.

Now there's a paranoid compiler - some of the messages are trying to
be helpful but are useless (I know about the empty loop body - that's
exactly what I wanted!), some are just plain wrong, like the last two.
I consider this a good example of counterproductive warnings, because it
gets pretty much impossible to write code the compiler doesn't warn on.

I'm curious to know what diagnostics MSVC, gcc or other compilers
produce on this little example.


Michal

Jorge Hodge

unread,
Jun 20, 2004, 5:37:54 PM6/20/04
to
"Steve Fábián" <ESFa...@BellAtlantic.net> wrote in message
news:cb3t7l$g5i$1...@www1.scitechsoft.com...

> Both statements combine multiple operations:
>
> 1) evaluate an expression
>
> 2) assign its value to an operand
>
> 3) use the value to make a decision
>
> The only difference is the simplicity or complexity of the expression to
> be evaluated in 1) above. Hence either both or neither should have
> warnings.

I think OW sees the "==" inside the expression tree and decides not to
generate a warning.

I personally like to use constructs like:

FILE *in;

if(in = fopen(filename,"rb))
{
fputs("File already exists",stderr);
fclose(in);
}

But most compilers will generate a warning. At least on GCC I can use an
extra set of parenthesis to avoid getting the warning, but with OW I have to
append a "!= NULL" in addition to an extra set of parenthesis.

But, of course, it is a useful warning.


Cesar Rabak

unread,
Jun 20, 2004, 5:39:19 PM6/20/04
to
Michal Necasek escreveu:

> CyberSimian wrote:
>
>> I am not sure what the current thinking is about Open Watcom producing
>> warning messages for legal C, but Watcom currently generates a warning
>> for
>> an assignment in a boolean expression. I think that that is useful, as
>> today I inadvertently coded THREE assignments in boolean expressions, but
>> only two of them gave rise to messages from Watcom. The following
>> testcase
>> shows the one that didn't. I am using Open Watcom 1.2 on Win2K SP3.
>>
> The warning message is slightly misleading. The explanation in the manual
> is not:
>
> 'An assignment of a constant has been detected in a boolean expression.
> For example: "if( var = 0 )". It is most likely that you want to use
> "==" for testing for equality.'
>
> Note the "assignment of a constant" phrase.
>
> That said, I'm not against warning in other cases as well. The problem
> is how to stop the compiler from warning on perfectly good code, like
>
> while( *p++ = *q++ )
> ;
>
> There is a very fine line between the warnings being helpful and getting
> in the way.
>
> I'd be curious to know what warnings other compilers give on the
> following example:
[snipped]

> I'm curious to know what diagnostics MSVC, gcc or other compilers
> produce on this little example.
>

Here it is:

D:\users\csrabak\Work\MyProjects>cl /W4 /Zs boolwrn.c
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8804 for 80x86
Copyright (C) Microsoft Corp 1984-1998. All rights reserved.

boolwrn.c
boolwrn.c(20) : warning C4244: '=' : conversion from 'int ' to 'float ',
possible loss of data
boolwrn.c(31) : warning C4244: '=' : conversion from 'int ' to 'char ',
possible loss of data

D:\users\csrabak\Work\MyProjects>gcc -O4 -fsyntax-only boolwrn.c

D:\users\csrabak\Work\MyProjects>gcc -Wall -O4 -fsyntax-only boolwrn.c
boolwrn.c: In function `foo':
boolwrn.c:13: warning: suggest parentheses around assignment used as
truth value

boolwrn.c:17: warning: suggest parentheses around assignment used as
truth value

boolwrn.c:29: warning: suggest parentheses around assignment used as
truth value

boolwrn.c:31: warning: suggest parentheses around assignment used as
truth value


D:\users\csrabak\Work\MyProjects>splint boolwrn.c
Splint 3.1.1 --- 12 April 2003

boolwrn.c: (in function foo)
boolwrn.c(13,9): Test expression for if is assignment expression: type = 't'
The condition test is an assignment expression. Probably, you mean to
use ==
instead of =. If an assignment is intended, add an extra parentheses
nesting
(e.g., if ((a = b)) ...) to suppress this message. (Use -predassign to
inhibit warning)
boolwrn.c(13,9): Test expression for if not boolean, type char: type = 't'
Test expression type is not boolean. (Use -predboolothers to inhibit
warning)
boolwrn.c(17,12): Test expression for while is assignment expression:
*p++ = *q++
boolwrn.c(17,12): Test expression for while not boolean, type char: *p++
= *q++
boolwrn.c(20,9): Assignment of int to float: g = mode
To allow all numeric types to match, use +relaxtypes.
boolwrn.c(20,8): Test expression for if not boolean, type float: (g = mode)
boolwrn.c(26,8): Test expression for if not boolean, type float: (g = 3.0)
boolwrn.c(29,9): Test expression for if is assignment expression: type = 'A'
boolwrn.c(29,9): Test expression for if not boolean, type char: type = 'A'
boolwrn.c(31,16): Left operand of && is non-boolean (char): 'B' && mode == 0
The operand of a boolean operator is not a boolean. Use +ptrnegate to
allow !
to be used on pointers. (Use -boolops to inhibit warning)
boolwrn.c(31,9): Assignment of boolean to char: type = 'B' && mode == 0
Types are incompatible. (Use -type to inhibit warning)
boolwrn.c(31,9): Test expression for if is assignment expression:


type = 'B' && mode == 0

boolwrn.c(31,9): Test expression for if not boolean, type char:


type = 'B' && mode == 0

boolwrn.c(4,6): Function exported but not used outside boolwrn: foo
A declaration is exported, but not used outside this module.
Declaration can
use static qualifier. (Use -exportlocal to inhibit warning)
boolwrn.c(36,1): Definition of foo

Finished checking --- 14 code warnings

HTH

--
Cesar Rabak

Jorge Hodge

unread,
Jun 20, 2004, 5:45:27 PM6/20/04
to
Correction: that was a bad example, because it uses a function call, so
there's really no warnings there.


Walter Briscoe

unread,
Jun 21, 2004, 3:58:21 AM6/21/04
to
In message <cb4ujb$t7b$1...@www1.scitechsoft.com> of Sun, 20 Jun 2004
14:11:09 in openwatcom.users.c_cpp, Michal Necasek
<mic...@prodigy.net> writes
[snip]

> There is a very fine line between the warnings being helpful and getting
>in the way.
>
> I'd be curious to know what warnings other compilers give on the
>following example:
[snip]

> Now there's a paranoid compiler - some of the messages are trying to
>be helpful but are useless (I know about the empty loop body - that's
>exactly what I wanted!), some are just plain wrong, like the last two.
>I consider this a good example of counterproductive warnings, because it
>gets pretty much impossible to write code the compiler doesn't warn on.
>
> I'm curious to know what diagnostics MSVC, gcc or other compilers
>produce on this little example.

For many years, I have had good service from FlexeLint and PC-Lint from
http://www.gimpel.com. I tend to run at a paranoid level on my own code
and at a more relaxed level on others. I hope this will be interesting

C:\WFB) lin -u -e550 -e831 -e954 -e960 boolwrn.c

C:\WFB) c:\lint\lint-nt +v -ic:\lint\ std.lnt c:\wfb\bin\c0-delta.lnt +os(_lint.tmp) -u -e550 -e831 -e954 -e960 boolwrn.c
PC-lint for C/C++ (NT) Ver. 8.00n, Copyright Gimpel Software 1985-2003
--- Module: boolwrn.c

C:\WFB) goto:more
c:\lint\lint-nt +v -ic:\lint\ std.lnt c:\wfb\bin\c0-delta.lnt +os(_lint.tmp) -u -e550 -e831 -e954 -e960 boolwrn.c

--- Module: boolwrn.c


if( type = 't' ) {

^
boolwrn.c(13) : Info 720: Boolean test of assignment
boolwrn.c(13) : Warning 506: Constant value Boolean
boolwrn.c(13) : Info 774: Boolean within 'if' always evaluates to True [Reference: file boolwrn.c: line 13]


while( *p++ = *q++ )

^
boolwrn.c(17) : Info 720: Boolean test of assignment
boolwrn.c(17) : Warning 413: Likely use of null pointer 'q' in argument to operator '++' [Reference: file boolwrn.c: line 11]
boolwrn.c(17) : Warning 413: Likely use of null pointer 'unknown-name' in argument to operator 'unary *' [Reference: file boolwrn.c: line 11
]
boolwrn.c(17) : Warning 413: Likely use of null pointer 'p' in argument to operator '++' [Reference: file boolwrn.c: line 11]
boolwrn.c(17) : Warning 413: Likely use of null pointer 'unknown-name' in argument to operator 'unary *' [Reference: file boolwrn.c: line 11
]
if((g = mode))
^
boolwrn.c(20) : Info 820: Boolean test of a parenthesized assignment
if((g = 3.0))
^
boolwrn.c(26) : Info 820: Boolean test of a parenthesized assignment
boolwrn.c(26) : Warning 506: Constant value Boolean


if( type = 'A') bar( type );

^
boolwrn.c(29) : Info 720: Boolean test of assignment
boolwrn.c(29) : Warning 506: Constant value Boolean
boolwrn.c(29) : Info 774: Boolean within 'if' always evaluates to True [Reference: file boolwrn.c: line 29]


if( type = 'B' && mode == 0 ) {

^
boolwrn.c(31) : Warning 506: Constant value Boolean
boolwrn.c(31) : Info 720: Boolean test of assignment
boolwrn.c(31) : Info 821: Right hand side of assignment not parenthesized

During Specific Walk:
File boolwrn.c line 24: foo(1, 116?)
boolwrn.c(17) : Warning 413: Likely use of null pointer 'q' in argument to operator '++' [Reference: file boolwrn.c: line 11]

During Specific Walk:
File boolwrn.c line 24: foo(1, 116?)
boolwrn.c(17) : Warning 413: Likely use of null pointer 'unknown-name' in argument to operator 'unary *' [Reference: file boolwrn.c: line 11
]

During Specific Walk:
File boolwrn.c line 24: foo(1, 116?)
boolwrn.c(17) : Warning 413: Likely use of null pointer 'p' in argument to operator '++' [Reference: file boolwrn.c: line 11]

During Specific Walk:
File boolwrn.c line 24: foo(1, 116?)
boolwrn.c(17) : Warning 413: Likely use of null pointer 'unknown-name' in argument to operator 'unary *' [Reference: file boolwrn.c: line 11
]

During Specific Walk:
File boolwrn.c line 24: foo(1, 116?)
File boolwrn.c line 24: foo(1, 116)
boolwrn.c(17) : Warning 413: Likely use of null pointer 'q' in argument to operator '++' [Reference: file boolwrn.c: line 11]

During Specific Walk:
File boolwrn.c line 24: foo(1, 116?)
File boolwrn.c line 24: foo(1, 116)
boolwrn.c(17) : Warning 413: Likely use of null pointer 'unknown-name' in argument to operator 'unary *' [Reference: file boolwrn.c: line 11
]

During Specific Walk:
File boolwrn.c line 24: foo(1, 116?)
File boolwrn.c line 24: foo(1, 116)
boolwrn.c(17) : Warning 413: Likely use of null pointer 'p' in argument to operator '++' [Reference: file boolwrn.c: line 11]

During Specific Walk:
File boolwrn.c line 24: foo(1, 116?)
File boolwrn.c line 24: foo(1, 116)
boolwrn.c(17) : Warning 413: Likely use of null pointer 'unknown-name' in argument to operator 'unary *' [Reference: file boolwrn.c: line 11
]
---
PC-lint for C/C++ output placed in _LINT.TMP
C:\WFB)

Let me try some others!

Cesar Rabak covered Visual C++ 6.0 and Splint.

C:\WFB) c:\pf\borland\bc5.51\bin\bcc32 -c -Ic:\pf\borland\bc5.51\include boolwrn.c
Borland C++ 5.5.1 for Win32 Copyright (c) 1993, 2000 Borland
boolwrn.c:
Warning W8060 boolwrn.c 13: Possibly incorrect assignment in function foo
Warning W8060 boolwrn.c 17: Possibly incorrect assignment in function foo
Warning W8060 boolwrn.c 20: Possibly incorrect assignment in function foo
Warning W8060 boolwrn.c 26: Possibly incorrect assignment in function foo
Warning W8060 boolwrn.c 29: Possibly incorrect assignment in function foo
Warning W8060 boolwrn.c 31: Possibly incorrect assignment in function foo
Warning W8004 boolwrn.c 36: 'f' is assigned a value that is never used in function foo
Warning W8004 boolwrn.c 36: 'g' is assigned a value that is never used in function foo

C:\WFB) c:\cygwin\bin\gcc.exe -c -Wall boolwrn.c


boolwrn.c: In function `foo':
boolwrn.c:13: warning: suggest parentheses around assignment used as truth value
boolwrn.c:17: warning: suggest parentheses around assignment used as truth value
boolwrn.c:29: warning: suggest parentheses around assignment used as truth value
boolwrn.c:31: warning: suggest parentheses around assignment used as truth value

--
Walter Briscoe

0 new messages