sonar-dotnet
sonar-dotnet copied to clipboard
SE: Improve arithmetic handling in loops
Follow-up to #8474 Specification
Currently, the SE engine is not conducting any calculations for arithmetic operations in loops. The following assumptions are approximations for calculations in a loop and can be added one by one:
- Addition:
- [x]
positive + positive
=>[left.Min + right.Min, null]
- [ ]
negative + negative
=>[null, left.Max + right.Max]
(partial implementation exists but does not handle 0) - [ ]
number + positive constant
=>[left.Min + right, null]
- [ ]
number + negative constant
=>[null, left.Max + right]
- [ ]
number + 0 constant
=>[left.Min, left.Max]
- [x]
- Subtraction:
- [ ]
number - positive constant
=>[null, left.Max - right]
- [ ]
number - negative constant
=>[left.Min - right, null]
- [ ]
number - 0 constant
=>[left.Min, left.Max]
- [ ]
- Multiplication:
- [ ]
number * 0
=>[0, 0]
- [ ]
positive * positive
=>[left.Min * right.Min, null]
- [ ]
negative * positive constant
=>[null, left.Max * right]
- [ ]
- Division:
- [ ]
positive / positive constant
=>[0, left.Max / right]
- [ ]
negative / positive constant
=>[left.Min / right, 0]
- [ ]
number / positive constant
=>[-left.Min / right, left.Max / right]
- [ ]
number / negative constant
=>[Max(|left.Min|, |left.Max|) / right, Max(|left.Min|, |left.Max|) / -right]
- [ ]
- Remainder
- [ ]
number % constant
=> same logic as outside a loop
- [ ]
- Bitwise And
- [ ]
number & number
=> same logic as outside a loop
- [ ]
- Bitwise Or
- [ ]
number | number
=> same logic as outside a loop
- [ ]
- Bitwise XOR
- [ ]
number ^ 0 constant
=>[left.Min, left.Max]
- [ ]
positive ^ positive
=>[0, null]
- [ ]
negative ^ positive constant
=>[null, -1]
- [ ]
Addition: What about positive+negative? Is that intended to implicitly fall back to "we don't know" scenario?
We should be able to do multiplication for negative*negative too?
Why do the multiplication and division needs to work with constants only, and not positive/negative?
@pavel-mikula-sonarsource Generally speaking, my idea is, "Let's assume that the result is assigned to one of the operands and thus reused in this calculation in later iterations."
What about positive+negative? Is that intended to implicitly fall back to "we don't know" scenario? Yes. We should be able to do multiplication for negative*negative too? This would always be positive. But if it is assigned to one of the two operands, its signage would flip, and future iterations would give different results. Why do the multiplication and division needs to work with constants only, and not positive/negative? I want to avoid cases where the signage would flip. If the second operand is a constant, the result can only be assigned to the left operand, which would not result in a flipped signage.
I want to avoid cases where the signage would flip. If the second operand is a constant, the result can only be assigned to the left operand, which would not result in a flipped signage.
That's the gap I'm asking about. If we do it with number (not constants) and we know if they are positive/negative, we never flip the signage.
We don't, because we don't know what the result will be assigned to:
var negative = -1;
var positive = 5;
while (condition)
{
positive = positive * negative;
}