views:

135

answers:

6

Can't a compiler warn (even better if it throws errors) when it notices a statement with undefined/unspecified/implementation-defined behaviour?

Probably to flag a statement as error, the standard should say so, but it can warn the coder at least. Is there any technical difficulties in implementing such an option? Or is it merely impossible?

Reason I got this question is, in statements like a[i] = ++i; won't it be knowing that the code is trying to reference a variable and modifying it in the same statement, before a sequence point is reached.

+2  A: 

gcc does warn in that situation (at least with -Wall):

#include <stdio.h>

int main(int argc, char *argv[])
{
  int a[5];
  int i = 0;

  a[i] = ++i;

  printf("%d\n", a[0]);

  return 0;
}

Gives:

$ make
gcc -Wall main.c -o app
main.c: In function ‘main’:
main.c:8: warning: operation on ‘i’ may be undefined

Edit:

A quick read of the man page shows that -Wsequence-point will do it, if you don't want -Wall for some reason.

Carl Norum
Any specific option is to be passed when invoking the compiler for it to warn? Invoking it normally didn't give any errors or warnings.
legends2k
`-Wsequence-point` will do it, I used `-Wall` which is probably a good idea.
Carl Norum
I didn't know that GCC warns of these behaviours, in my experience with GCC and VC++ I haven't seen any; I always use `-Wall` in GCC and Warning Level 3 in VC++, but probably I've not compiled some code which has an undefined behaviour; but I didn't know about the `-Wsequence-point`. Thanks anyway :)
legends2k
@legends2k@ Why only \W3 for VC++? Use \W4 \WX, and -Wall -Werror for GCC. Regarding not knowing about specific warning options: http://gcc.gnu.org/onlinedocs/ (they are all there).
Clifford
A: 

GCC warns as much as it can when you do something out of the norms of the language while still being syntactically correct, but beyond the certain point one must be informed enough.

You can call GCC with the -Wall flag to see more of that.

Xorlev
+1  A: 

Contrarily, compilers are not required to make any sort of diagnosis for undefined behavior:

§1.4.1:
The set of diagnosable rules consists of all syntactic and semantic rules in this International Standard except for those rules containing an explicit notation that “no diagnostic is required” or which are described as resulting in “undefined behavior.”

Emphasis mine. While I agree it may be nice, the compiler's have enough problem trying to be standards compliant, let alone teach the programmer how to program.

GMan
+4  A: 
Alok
Don't forget *"a compiler can't determine undefined behaviour as soon as calls to outside of the compiled sources are involved"*
Georg Fritzsche
@gf: good point. I was thinking about it when writing my answer, but then forgot. Thanks!
Alok
Accepted for demonstrating possible scenario where it's not always deterministic to the compiler and for giving elaborate reasoning.
legends2k
One thing that makes the "export" template feature difficult to implement is that things that the ODR forbids affecting multiple translation unit must actually be checked: If two calls to a single template definition is made from two TUs, then you are confronted with name-lookup into two TUs, that *should* lookup to the same declarations. The compiler can't simply ignore inconsistencies here (according to the EDG members), because such inconsistency will directly affect its behavior resolving these dependent names (and the compiler doesn't really want to segfault on this).
Johannes Schaub - litb
+1  A: 

Different compilers trap different conditions; most compilers have warning level options, GCC specifically has many, but -Wall -Werror will switch on most of the useful ones, and coerce them to errors. Use \W4 \WX for similar protection in VC++.

In GCC You could use -ansi -pedantic, but pedantic is what it says, and will throw up many irrelevant issues and make it hard to use much third party code.

Either way, because compilers catch different errors, or produce different messages for the same error, it is therefore useful to use multiple compilers, not necessarily for deployment, but as a poor-man's static analysis. Another approach for C code is to attempt to compile it as C++; the stronger type checking of C++ generally results in better C code; but be sure that if you want C compilation to work, don't use the C++ compilation exclusively; you are likely to introduce C++ specific features. Again this need not be deployed as C++, but just used as an additional check.

Finally, compilers are generally built with a balance of performance and error checking; to check exhaustively would take time that many developers would not accept. For this reason static analysers exist, for C there is the traditional lint, and the open-source splint. C++ is more complex to statically analyse, and tools are often very expensive. One of the best I have used is QAC++ from Programming Research. I am not aware of any free or open source C++ analysers of any repute.

Clifford
Thanks for the explanation and suggestions; I shall see what split does (+1).
legends2k
A: 

If your compiler won't warn of this, you can try a Linter.

Splint is free, but only checks C http://www.splint.org/

Gimpel Lint supports C++ but costs US $389 - maybe your company c an be persuaded to buy a copy? http://www.gimpel.com/

Mawg