Hello!
Currently, the "hicpp/signed-bitwise" check returns the beginning of the binary/unary operator as location, which sometimes confuses users in the IDE due to incorrect highlighting.
Yes, the offset from Ranges can be used for this particular check, but i suppose better solution is to return begin location of the problematic operand instead of operator.
Details
Diff Detail
- Repository
- rG LLVM Github Monorepo
Event Timeline
clang-tools-extra/clang-tidy/hicpp/SignedBitwiseCheck.cpp | ||
---|---|---|
98–100 | Seems pretty useless to pass the begin location of the Unary/Binary operator here. |
Hi @vladimir.plyashkun !
I looked at the screenshot in the link you posted. What is the type of value?
Consider that if value is an uint8_t, as per the integer promotion rules, it will be promoted to (signed) int before running the bitwise operation. Therefore clang-tidy is right to point out the problem with value. Check it out:
https://godbolt.org/z/8EMcPd6rd
`-DeclStmt <line:6:5, col:22> `-VarDecl <col:5, col:18> col:10 y 'int':'int' cinit `-BinaryOperator <col:14, col:18> 'int' '&' |-ImplicitCastExpr <col:14> 'int' <IntegralCast> | `-ImplicitCastExpr <col:14> 'std::uint8_t':'unsigned char' <LValueToRValue> | `-DeclRefExpr <col:14> 'std::uint8_t':'unsigned char' lvalue Var 0x55db629e40e8 'x' 'std::uint8_t':'unsigned char' `-IntegerLiteral <col:18> 'int' 255
On the other hand, if the 0xFF becomes 0xFFu, then Clang performs an integer promotion to unsigned int instead of int, and that's why clang-tidy no longer complains.
I'm not sure that's correct behavior, however:
If int can represent the entire range of values of the original type (or the range of values of the original bit field), the value is converted to type int. Otherwise the value is converted to unsigned int.
https://en.cppreference.com/w/c/language/conversion
In this case, an int can represent fully all values of an uint8_t.
Hi @carlosgalvezp
Yes, sorry, maybe screenshot and example from issue in our bugtracker is not the best one.
You can check it on this sample from clang-tidy tests:
The "hicpp-signed-bitwise" will point to
URes = UValue & -1;
[UValue] instead of -1, which looks confusing.
clang-tools-extra/clang-tidy/hicpp/SignedBitwiseCheck.cpp | ||
---|---|---|
98–100 | My initial point was to preserve current behaviour as much as possible, but i agree that (BinaryOp|UnaryOp)->getOperatorLoc() is much better in this case. |
The pre-merge bot is failing because clang-format hasn't been run. Can you please update the diff by running git clang-format first.
clang-tools-extra/clang-tidy/hicpp/SignedBitwiseCheck.cpp | ||
---|---|---|
100 | We still need the source range of the operand [build] Value <<= diagTest(1, 2, 3); [build] ~~~ ^ Vs [build] Value <<= diagTest(1, 2, 3); [build] ~~~ ^~~~~~~~~~~~~~~~~ |
Seems pretty useless to pass the begin location of the Unary/Binary operator here.
The only source locations that are of interest is the operator location and the whole range of the SignedOperand.
Based on the issues with jetbrains rendering, I also imagine clangd would have the same issue, We'd likely want to have the diag locations as the SignedOperand begin(like this patch). Then pass the whole source range of the signed operand(like it currently is).
I'm either way on whether we would need to pass the location of the operator (BinaryOp|UnaryOp)->getOperatorLoc()