3

Is there any way to have gcc or g++ emit a warning when an implicit conversion within an if, something like if(25.0), is used?

This question is inspired by a bug I recently observed where a parenthesis was mis-placed, and the if statement has the unexpected behavior illustrated in the example below. I understand from this discussion on the comma operator that this is valid (although ugly) code, but I would like to get a warning. I tried -Wconversion -Wall -pedantic with g++ (GCC) 4.1.2 and g++ (GCC) 4.6.3 without any luck.

#include <cstdio>

bool passMin(float val, float minval=10.) {return minval<val;}

int main () {
  float val(20.0), minval(25.0);
  if(passMin(val), minval) printf(" pass (p( ), )"); else printf(" fail (p( ), )");
  printf("\n");
  if(passMin(val, minval)) printf(" pass (p( , ))"); else printf(" fail (p( , ))");
  printf("\n");
}

This produces:

 pass (p( ), )
 fail (p( , ))
miken32
  • 42,008
  • 16
  • 111
  • 154
user2148414
  • 312
  • 3
  • 14
  • Not sure that's easy to do, since there are (probably) cases where this is used to acheive (something). Not using default values is a good idea... ;) – Mats Petersson Aug 09 '13 at 13:54
  • Have you tried Wextra ? – Vincent Aug 09 '13 at 14:32
  • @Vincent Yes, without any luck :-( – user2148414 Aug 09 '13 at 14:39
  • You could customize GCC e.g. with [MELT](http://gcc-melt.org/) or with a plugin painfully coded in *C* to achieve your goal. However, I also think that quite a lot of code use `if` on non boolean values... – Basile Starynkevitch Aug 09 '13 at 19:37
  • 1
    `clang` will give you a nice warning for this, see it [live](http://coliru.stacked-crooked.com/a/8dfbfed12d28d375), so if using `clang` is an option then you may be in luck. – Shafik Yaghmour Dec 20 '13 at 04:59
  • @ShafikYaghmour I haven't played much with `clang` yet, but it looks very promising. Thank you! – user2148414 Dec 21 '13 at 10:33
  • 1
    In this specific case, the GCC warning `-Wfloat-equal` would have covered it. That warning is about an exact comparison, where one of the operands is a floating-point type. The use of a floating-point value in an `if` statement performs an exact comparison to zero. –  Apr 19 '14 at 09:06

1 Answers1

1

In C and C++ all expressions are essentially evaluated down to a logical expression: true or false? true is any non-zero value while false is zero.

What's happening is that your expression

if(passMin(val), minval)

is falling foul of the , operator, which evaluates the expression on the left side and discards the result, then proceeds to evaluate the expression on the right and return that value.

The comma operator has the lowest precedence of any operator and is left associative.

Essentially, the code above means

void(passMin(val));
if (minVal)

It's very unlikely that any current compiler provides an option to restrict this pattern, because it is very widely used for things like pointer and zero checks:

for (Node* node = list->head; node; node = node->next)
    ...

void func(const char* str) {
    assert(str);
    ...

So if you did have an option you would probably cripple most libraries, STL, boost, etc.

That said, you could probably use a static analyzer to enforce a code practice that prohibits it within your own code.

Visual studio: http://msdn.microsoft.com/en-us/library/dd380660.aspx

Clang static analyzer: http://clang-analyzer.llvm.org/ (the page is not all that helpful, the analyzer seems to come with 3.5 so additional searches will be required to find better documentation)

kfsone
  • 23,617
  • 2
  • 42
  • 74