Re: Strange behavior of -Wfloat-equal on clang (Xcode 5)
Re: Strange behavior of -Wfloat-equal on clang (Xcode 5)
- Subject: Re: Strange behavior of -Wfloat-equal on clang (Xcode 5)
- From: Fritz Anderson <email@hidden>
- Date: Fri, 03 Jan 2014 11:24:03 -0600
On 3 Jan 2014, at 7:46 AM, Asiga Nael <email@hidden> wrote:
> Hi!
>
> There's something strange with -Wfloat-equal warnings on clang from Xcode 5.
>
> This warning is supposed to be triggered whenever two floating point values are compared for equality.
>
> However, if I compile the following code with cc mytest.c -Wfloat-equal
>
...
> intmain(int argc, char **argv)
> {
> float a=0.357;
> float b=1.782;
// "third test:"
> if(a==2.0)
> {
> printf("This must trigger a warning from -Wfloat-equal as well.\n");
> }
> return EXIT_SUCCESS;
> }
...
>
> I'm getting warnings from just the first and second tests. The third test doesn't trigger a warning.
>
> From more tests I did, it seems -Wfloat-equal doesn't trigger a warning if one operand is a floating point literal that can be casted to a integer exactly without data loss.
>
> However, compiled it with llvm-gcc mytest.c -Wfloat-equal and all three tests generate a warning (which is the behavior I'm used too).
>
> What's happening here?
>
> If it helps, the clang version reported by my Xcode 5 installation is:
>
> cc --version
> Apple LLVM version 5.0 (clang-500.2.79) (based on LLVM 3.3svn)
> Target: x86_64-apple-darwin12.4.0
> Thread model: posix
>
> If anybody knows why is this happening, and how to get all these three warnings from clang, please tell!!
This is the intended behavior. The only way to get the warnings you're used to is to compile your own clang and use that. <http://clang.llvm.org/doxygen/SemaChecking_8cpp-source.html> (you can assume EmitWarning is always true):
// Special case: check for comparisons against literals that can be exactly
// represented by APFloat. In such cases, do not emit a warning. This
// is a heuristic: often comparison against such literals are used to
// detect if a value in a variable has not changed. This clearly can
// lead to false negatives.
if (EmitWarning) {
if (FloatingLiteral* FLL = dyn_cast<FloatingLiteral>(LeftExprSansParen)) {
if (FLL->isExact())
EmitWarning = false;
} else
if (FloatingLiteral* FLR = dyn_cast<FloatingLiteral>(RightExprSansParen)){
if (FLR->isExact())
EmitWarning = false;
}
}
(By the way, I'm in awe of the clarity of this code.)
If the purpose of compilation warnings is to alert the programmer to the potential for _actual_ misbehavior at run time; and not to alert when no potential exists; then clang's behavior is correct.
Comparison to exact representations has no potential for misbehavior. One side of the comparison contains _exactly_ the bits to test for; the other side is found equal only if it has _exactly_ those bits. Possibly the other side's bits were derived by a process that would yield a different number in continuous math. In real life, no matter how you compare the scalars (such as by the usual epsilon bracket), nothing is going to do better at catching that case. If you need a real-number-domain test, derive the variable side algebraically, or build your own numerics that somehow preserve the low-order bits that the scalar loses. (And even then, you're only putting the problem off.)
(Or at least so clang _assumes,_ if I understand the last sentence in the comment. I read it as a hedge that acknowledges the "clear" potential for missing an issue. I don't know the details of the thinking behind this — for all I know, the warning is a sop to contributors who object in principle to behavior that works, but cannot be proved to work.)
---
llvm-gcc doesn't catch that case because:
* The maintainers of the gcc parser made a different tradeoff on the risks; or
* Compared to clang, llvm-gcc isn't very bright,** even if you disagree with a few design decisions.
** (The contributors to gcc are ingenious, learned, and hard-working; many incomparably so. They also are laboring under different priorities in design and resources; must work on a lacework code base that can sensibly be aged in fractions of a century; and are straitjacketed in backward compatibility.)
---
Anyway, llvm-gcc is no longer supported for development for Apple platforms. Objective-C is changing rapidly (that's one of the reasons Apple abandoned gcc). Those developments tend to become mandatory in the Cocoa API, and gcc won't give them to you in time to meet your needs.
---
Which leads to the question:
> However, compiled it with llvm-gcc mytest.c -Wfloat-equal and all three tests generate a warning (which is the behavior I'm used to[]).
Okay, you're used to the gcc behavior (which is least unsophisticated, and arguably incorrect). I praise caution about numerics, but does this really matter to you? Is your objection practical? Or is it just that clang's behavior surprises you? The solution to that may be to stop being surprised.
— F
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Xcode-users mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden