In the following code:
#include <iostream>
int main()
{
const long l = 4294967296;
int i = l;
return i; //just to silence the compiler
}
the compiler warns about implicit conversion (using -Wall and -std=c++14) as following:
warning: implicit conversion from 'const long' to 'int' changes value from 4294967296 to 0 [-Wconstant-conversion]
which is ok. But there is no warning if the conversion is from double to int, as in the following code:
#include <iostream>
int main()
{
const double d = 4294967296.0;
int i = d;
return i; //just to silence the compiler
}
Why the compiler reacts differently in these situations?
Note 1: clang version is 3.6.2-svn240577-1~exp1
Note 2: I've tested it with many others versions of gcc, clang and icc thanks to Compiler Explorer (gcc.godbolt.org). So all tested versions of gcc (with exception of 5.x) and icc threw the warning. No clang version did it.
Well, by reading this great article named "What Every C Programmer Should Know About Undefined Behavior", specially part #3/3, at LLVM Project Blog, written by Chris Lattner - the main author of LLVM - I could understand better the Clang's Approach to Handling Undefined Behavior.
So, in order to guarantee your strong appeal for optimization and time economy - "ultimate performance" -
Keep in mind though that the compiler is limited by not having dynamic information and by being limited to what it can without burning lots of compile time.
Clang doesn't run all related undefined behavior checks by default,
Clang generates warnings for many classes of undefined behavior (including dereference of null, oversized shifts, etc) that are obvious in the code to catch some common mistakes.
instead of this, Clang and LLVM provides tools like Clang Static Analyzer, Klee project, and the -fcatch-undefined-behavior
(now UndefinedBehaviorSanitizer - UBSan - ) to avoid these possible bugs.
By running UBSan in the presented code, clang++
with the following argument -fsanitize=undefined
the bug will be catched as following:
runtime error: value 4.29497e+09 is outside the range of representable values of type 'int'