As it's set in Bug 32048 at the moment Clang misses a lot of warnings about "possibly problematic" conversions. This patch adds such warnings in places where we have different kinds of assignments.
Alexey, could you have look at OpenMP tests - maybe it's better to change something?
Details
Diff Detail
Event Timeline
Hmm. I think if you're going to push for this, you need to put more time into making sure that the diagnostics are good, and most them seem pretty questionable.
test/OpenMP/teams_distribute_simd_loop_messages.cpp | ||
---|---|---|
48 ↗ | (On Diff #132125) | This, and all the other warnings in these OpenMP tests, is actually really misleading. It happens to be true that the result of this computation is effectively as if the value being added was just 1, but that's not what the diagnostic actually says, and it wouldn't be true for all operations or values. |
test/Sema/constant-conversion.c | ||
76 ↗ | (On Diff #132125) | This doesn't seem like a good warning. The original code masks off the high bit of the value stored in the bit-field, which is a perfectly sensible operation to do. It's actually exactly the expected pattern of code for idiomatic bit manipulation. |
test/Sema/conversion.c | ||
362 | This diagnostic is okay. It would be nice to somehow refer to the fact the the conversion is the conversion done at the end of the compound operation. Although... it's not like it's unreasonable to multiply an integer by a float and then truncate back to an integer. So there needs to be some way of suppressing this warning, and I'm not sure what it would be, because you can't add a cast without changing the meaning of the operation, so you'd have to spell out the LHS twice, which is really unfortunate. We usually don't like to add warnings for code that might be the best way of expressing what it needs to express. | |
test/Sema/shift.c | ||
31 ↗ | (On Diff #132125) | Okay, this is really a bad diagnostic, because the value 999999 is in no way getting truncated. |
test/SemaCXX/conversion.cpp | ||
27 ↗ | (On Diff #132125) | Are you implying that we don't currently warn in these cases? |
test/SemaCXX/null_in_arithmetic_ops.cpp | ||
65 ↗ | (On Diff #132125) | I feel like these don't add much on top of the other warning. |
lib/Sema/SemaChecking.cpp | ||
---|---|---|
9167 | Please can you move this function as an NFC commit and then update this patch so it just shows the change in the code. |
I removed the ambiguity with changes in CheckImplicitConversion (required by rksimon): now it's absolutely clear what was changed.
And I minimized changes in diagnostics(required by rjmccall): the only float-double truncation was changed. As result only two tests were changed. Later we could easily extend the diagnostic updates if it will be necessary (but inside another patch).
Hmm. I'm still torn about this. I feel like at a minimum it's necessary to explain in the diagnostic that the conversion is the final conversion does as part of a compound assignment. I think the right solution is to tell CheckImplicitConversion that it's not just a straight-up conversion, it's a conversion done as part of a compound assignment, and then CheckImplicitConversion can choose to suppress or use different diagnostics based on that information. This will also more reliably avoid duplicate diagnostics.
I think the right solution is to tell CheckImplicitConversion that it's not just a straight-up conversion, it's a conversion done as part of a compound assignment, and then CheckImplicitConversion can choose to suppress or use different diagnostics based on that information. This will also more reliably avoid duplicate diagnostics.
I'm not sure I understand you. There is a special branch in CheckImplicitConversion related to FloatingPoint:
if (SourceBT && SourceBT->isFloatingPoint()) { // ...and the target is floating point... if (TargetBT && TargetBT->isFloatingPoint()) { // ...then warn if we're dropping FP rank.
And that's exactly our case. How can knowledge about "part of a compound assignment" improve the diagnostic here? Please, clarify.
The diagnostic text for this warning is misleading at best when the conversion is actually a truncation of the result of a compound assignment.
OK, at the moment we have:
*b += a; // expected-warning {{implicit conversion loses floating-point precision: 'double' to 'float'}}
But you'd like to see something like:
*b += a; // expected-warning {{truncation of the result of a compound assignment loses floating-point precision: 'double' to 'float'}}
Right? And you'd like to keep the current message at simple assignment, right?
Right. I would suggest something like "implicit conversion when assigning computation result loses floating-point precision", and you should make sure that the source type is the computation result type, and the arrow should point at the operator.
And you'd like to keep the current message at simple assignment, right?
Yeah. Thanks!
I separated analyze of compound assignments from simple ones and created special diagnostic. Hope, now it's OK.
lib/Sema/SemaChecking.cpp | ||
---|---|---|
9199 | This feels likely to cause redundant or inappropriate diagnostics. | |
9203 | E->getComputationResultType()->getType()->getAs<BuiltinType>() | |
9205 | T->getAs<BuiltinType>() | |
9212 | Should we actually do a suppression for constant values here? We suppress them for normal assignments because it's free to coerce a constant double to float, but [fixed]myFloat *= 2.0[/fixed] actually does do a computation in [fixed]double[/fixed] that has to be truncated to [fixed]float[/fixed]. Someone using this warning to find places where unwanted implicit floating-point coercions are being used would surely want to know about this location so that they can make the literal [fixed]2.0f[/fixed]. |
lib/Sema/SemaChecking.cpp | ||
---|---|---|
9152 | Function names should follow coding standard, shouldWarnFloatPrecision. | |
9158 | The names of the variables should start from capital letter, Result | |
9166–9167 | Do you need this check? With or without it you just return true. | |
9196 | Start from small letter function names. | |
9202 | const BuiltinType *->const auto * | |
9204 | const BuiltinType *->const auto * |
lib/Sema/SemaChecking.cpp | |||||
---|---|---|---|---|---|
9203 | Unfortunatelly, it does not work because getComputationResultType() returns 'double': CompoundAssignOperator 0xd2db9a0 'float' '+=' ComputeLHSTy='double' ComputeResultTy='double'
`-ImplicitCastExpr 0xd2db988 'double' <LValueToRValue> `-DeclRefExpr 0xd2db960 'double' lvalue ParmVar 0xd2db6d8 'a' 'double' (gdb) p CAOp->getComputationLHSType()->dump() (gdb) p CAOp->getComputationResultType ()->dump() |
lib/Sema/SemaChecking.cpp | ||
---|---|---|
9203 | Sorry, I mean instead of E->getRHS()->getType(). |
lib/Sema/SemaChecking.cpp | ||
---|---|---|
9203 | OK, in this case we need clear comment about getComputationResultType: I was sure that ResultType is LHS type. Could you add such a comment in Expr.h? |
lib/Sema/SemaChecking.cpp | ||
---|---|---|
9196 | Looking at the other Analyze functions, it looks like you're supposed to recurse on the LHS and RHS in here: this is supposed to diagnose the entire expression tree, not just conversions in the outermost expression. The test case would be to have an unfortunate implicit conversion embedded somewhere in the LHS or RHS, like as an argument to a call that produces a subscript index or something. |
If I understood rjmccall correctly I should do both: recurse in LHS/RHS and check the outermost expression. If it is I fixed the issue.
On the other side in one of my previous versions there was a call to AnalyzeAssignment and this call did exactly the same plus bitfield issue checking. Maybe we should return this call instead 2 explicit calls to AnalyzeImplicitConversions?
It seems I found a new problem here: with vector type it works just now (w/o this patch)
llvm/tools/clang/test/Sema/ext_vector_conversions.c:18:10: warning: implicit conversion loses integer precision: 'long long' to 'short4' (vector of 4 'short' values)
vs4 += ll; // expected-warning {{implicit conversion loses integer precision}} ~~ ^~
Let's wait until I'll find and fix the issue. I'll warn you when it's ready for review.
I've fixed the last minute issues and it works now properly.
On the other hand I'm going to continue the research about vector types: maybe it's possible to extend the current code?
But if it's possible I'd like to commit the current patch and to continue with the new one.
lib/Sema/SemaChecking.cpp | ||
---|---|---|
9200 | It's not obvious that the bit-field special case in that function is appropriate for all compound assignments. For now, let's just leave that function for simple assignments; we can directly call AnalyzeImplicitConversions on the LHS and RHS here. |
lib/Sema/SemaChecking.cpp | ||
---|---|---|
9200 | There is one problem only here: if we don't support the bit-field special case here then we have several additional tests failed. But OK - I'll do it. |
I removed cheking of bit-field case.
And I was wrong about increasing of number of failed tests: it's starnge but I was sure I saw it. OK, now we have one modified test only.
Yeah, the previous behavior is just a simple recursion without any assignment-specific knowledge, so that makes sense.
LGTM.
lib/Sema/SemaChecking.cpp | ||
---|---|---|
9530 | DO you still need ICContext parameter? I don't see where it is used. |
I fixed all issues raised by ABataev and committed the patch as revision 327618. I'll close the review in some hours.
You are aware that you can either use arc patch (best way), or at least manually add Differential revision: https://reviews.llvm.org/Dsomething line to the commit msg, so
- the differential is auto-closed
- the commit msg is taken from differential description
- there is a trivial way to go from commit to differential (and vice versa)
?
If I'm sure in success I'm using "Differential revision" but sometimes I'd prefer to wait until the patch is really accepted by the system and only after that I'm closing it by hand.
But what's about arc patch? Could you point me to any docs about?
Do you really need this declaration here?