[clang] Do not diagnose float-equal for 0 and 1 #207288
Conversation
|
Hello @juniorrantila 👋 Thank you for submitting a Pull Request (PR) to the LLVM Project. Since this is your first PR, here are a few useful links covering our main contribution policies and review practices.
Please reply to this message to confirm that you have read these policies, especially the LLVM AI Tool Use Policy, and that any AI tool usage has been noted in the PR description. Frequently asked questionsHow do I add reviewers? This PR will be automatically labeled, and the relevant teams will be notified. For some parts of the project, reviewers may also be added automatically. You can also add reviewers manually using the Reviewers section on this page. If you cannot use that section, it is probably because you do not have write permissions for the repository. In that case, you can request a review by tagging reviewers in a comment using What if there are no comments? If you have not received any comments on your PR after a week, you can request a review by pinging the PR with a comment such as “Ping”. The common courtesy ping rate is once a week. Please remember that you are asking for volunteer time from other developers. Are any special GitHub settings required to contribute to LLVM? We only require contributors to have a public email address associated with their GitHub commits, see this section of LLVM Developer Policy for details. If you have questions, feel free to leave a comment on this PR, or ask on LLVM Discord or LLVM Discourse. Thank you, |
|
@llvm/pr-subscribers-clang Author: Junior Rantila (juniorrantila) ChangesThe values 0 and 1 are commonly used for checking if something is initialized and are both exactly representable as floats. Emitting a diagnostic when comparing with these values seems a bit obtuse. Full diff: https://github.com/llvm/llvm-project/pull/207288.diff 1 Files Affected:
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 01b1f4c26f017..8050d387b0fa3 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -11672,6 +11672,14 @@ void Sema::CheckFloatComparison(SourceLocation Loc, const Expr *LHS,
} else if (const auto *FLR = dyn_cast<FloatingLiteral>(RightExprSansParen))
if (FLR->isExact())
return;
+ if (const auto *ILL = dyn_cast<IntegerLiteral>(LeftExprSansParen)) {
+ if (ILL->getValue() == 0 || ILL->getValue() == 1)
+ return;
+ }
+ if (const auto *ILR = dyn_cast<IntegerLiteral>(RightExprSansParen)) {
+ if (ILR->getValue() == 0 || ILR->getValue() == 1)
+ return;
+ }
// Check for comparisons with builtin types.
if (const auto *CL = dyn_cast<CallExpr>(LeftExprSansParen);
|
These values are commonly used for checking if something is initialized and are both exactly representable as floats. Emitting a diagnostic when comparing with these values seems a bit obtuse.
2c16692 to
80d65be
Compare
Sirraide
left a comment
There was a problem hiding this comment.
Candidly, I don’t think this is a good idea.
The values 0 and 1 are commonly used for checking if something is initialized and are both exactly representable as floats. Emitting a diagnostic when comparing with these values seems a bit obtuse.
Assuming you’re talking about -Wfloat-equal here, I don’t quite agree w/ this notion: the reason we diagnose this is that computations involving floating-point numbers are fundamentally inexact.
A computation that mathematically would result in 0 or 1 may not actually give you 0 or 1 if you’re using floating-point numbers (e.g. .7 + .2 + .1 == 1 evaluates to false because the LHS is actually .9999999999999999), which means that most of the time, == or != are definitely not what you want when you’re working with floating-point numbers.
Whether or not such a comparison happens to involve 1 or 0 doesn’t really make a difference here—if anything not diagnosing a comparison with 0 would be especially bad given that comparisons against 0 are actually quite common (e.g. two vectors are perpendicular if their dot product is 0).
(As an aside, from an implementation perspective, this would still need a test and a release note.)
|
I see we apparently don’t diagnose floating-point literals for some reason... but I don’t think that’s really a good idea either |
|
I am currently on holidays, so will get back to you in a week unless I get a chance to use the computer :p This patch was inspired by one of the safety critical C guidelines, I don't remember which one at the top of my head, will look it up as soon as I get the opportunity, where floating point equality comparison is not allowed. However, 0 and 1 are special cased to be allowed. Reasoning behind this, as I understand it, is that it is common to memset buffers to 0 as to signify not yet initialised for lazy structures. When you compare to 0, you actually are interested in the exact bit pattern to signify that you need to do initialisation of the structure, approximate comparison would be incorrect. It could be argued that the same idea goes for the value 1 or any other exactly representable float value as well, but I haven't personally needed anything other than 0 or 1. I will look up the specific section where the exceptions are mentioned as soon as I have time :) |
That seems surprisingly dangerous given this behavior in the wild: https://godbolt.org/z/dhMxM91n3 (I'm surprised Clang doesn't diagnose that!)
Then you shouldn't be comparing with zero, but instead using I'm not opposed, just some drive-by comments. I added a few floating-point experts for their opinions. |
Yeah, we explicitly don’t diagnose floating-point literals that are exactly representable: llvm-project/clang/lib/Sema/SemaChecking.cpp Lines 11664 to 11674 in fb1de34 I don’t think doing this is a good idea but it’s been there since 2007. |
|
The logic that leads us to suppress the warning for exact floating-point literals could easily be extended to integer literals that can be exactly represented, but I'm also not sure it's a good idea to have ever done that. The reasoning for the warning seems to apply to the exact-literal comparison cases as well as anything else. If there really is demand for not diagnosing in these cases, perhaps a new option to control that behavior specifically is in order. |
|
I did some more digging and can't find the exact PDF I was looking for, but in MISRA 1998, rule 40 states: In MISRA 2004 (Rule 13.3), they removed the comparison to zero exemption. Static analysis tools seem to commonly allow comparisons to for (float v = 0.0f; v != 100.0f, v += 1.0f)
;would be allowed on the grounds that the initializer and the value we increment by are both integer values, so the float will not drift. See Polyspace. In my opinion, |
I think it's useful to find all direct comparisons of floating-point types regardless of value, which is the behavior of |
The values 0 and 1 are commonly used for checking if something is initialized and are both exactly representable as floats. Emitting a diagnostic when comparing with these values seems a bit obtuse.