[RFC] Compiler warning -Wparentheses for code : while (c = *str++)

Hello!

This is a RFC.

I wonder what you think about trying to avoid a compiler warning for such code:

        while (c = *str++) {
                *p++ = (c >= 'A' && c <= 'Z') ? (c - 'A' + 'a') : c;
        }

Output:

a.c:3:11: warning: using the result of an assignment as a condition without parentheses [-Wparentheses]
        while (c = *str++) {
               ~~^~~~~~~~
a.c:3:11: note: place parentheses around the assignment to silence this warning
        while (c = *str++) {
                 ^
               ( )
a.c:3:11: note: use '==' to turn this assignment into an equality comparison
        while (c = *str++) {
                 ^

Daniel Marjamäki <Daniel.Marjamaki@evidente.se> writes:

Hello!

This is a RFC.

I wonder what you think about trying to avoid a compiler warning for
such code:

        while (c = *str++) {
                *p++ = (c >= 'A' && c <= 'Z') ? (c - 'A' + 'a') : c;
        }

Output:

a.c:3:11: warning: using the result of an assignment as a condition without parentheses [-Wparentheses]
        while (c = *str++) {
               ~~^~~~~~~~
a.c:3:11: note: place parentheses around the assignment to silence this warning
        while (c = *str++) {
                 ^
               ( )

This tells you what to do to avoid the warning, spell this like so:

  while ((c = *str++)) {
    *p++ = (c >= 'A' && c <= 'Z') ? (c - 'A' + 'a') : c;
  }

a.c:3:11: note: use '==' to turn this assignment into an equality comparison
        while (c = *str++) {
                 ^
                 ==
1 warning generated.

I would personally recommend that it is avoided in while if there is
just an assignment and rhs is a nonconstant expression.

The trade off here is between the programmer overhead of adding an extra
set of parentheses vs the likelihood of accidentally typing "=" when you
mean "==". In real code we've seen that this warning finds enough errors
that burdening the programmer to be more explicit when they really want
an assignment is worth it.

To illustrate why a side-effectful RHS isn't sufficient to turn off this
warning, consider:

  char end = lastline ? '\0' : '\n';
  while (end == *str++) { /* do something with *str */ }

This is a bit contrived, but it hints at the complexity of turning off
-Wparentheses for particular cases - it's both easier to get right and
easier to explain if we just say "put extra parens around assignments in
conditions to make it obvious that they're intentional".

Thanks!

In real code we've seen that this warning finds enough errors
that burdening the programmer to be more explicit when they really want
an assignment is worth it.

hmm.. I could put together a list with such warnings in real code.

so far I only looked at a few such warnings. All of them were FP so I thought the FP ratio was not very good.

Best regards,
Daniel Marjamäki

..................................................................................................................
Daniel Marjamäki Senior Engineer
Evidente ES East AB Warfvinges väg 34 SE-112 51 Stockholm Sweden

Mobile: +46 (0)709 12 42 62
E-mail: Daniel.Marjamaki@evidente.se

www.evidente.se

Alternatively, you can declare c in the loop as well:

while (char c = *str++) ...

Joerg

while (a = foo()) is often a typo for while (a == foo()). Having a warning for this is useful, and it’s a pretty established pattern to use duplicate parens if the assignment is in fact intended (while ((a = foo()))). In fact, clang even warns in the reverse case if you use the double parens with a comparison: while ((a == foo())) warns as well.

If you don’t like this warning, can’t you just build with -Wno-parentheses?