Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SE: Improve arithmetic handling in loops #8695

Open
1 of 21 tasks
Tim-Pohlmann opened this issue Feb 6, 2024 · 6 comments
Open
1 of 21 tasks

SE: Improve arithmetic handling in loops #8695

Tim-Pohlmann opened this issue Feb 6, 2024 · 6 comments
Labels
Area: C# C# rules related issues. Area: CFG/SE CFG and SE related issues. Area: VB.NET VB.NET rules related issues. Type: SE Improve SE engine

Comments

@Tim-Pohlmann
Copy link
Contributor

Tim-Pohlmann commented Feb 6, 2024

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:
    • 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]
  • 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]
@Tim-Pohlmann Tim-Pohlmann added Type: New Feature Area: CFG/SE CFG and SE related issues. Area: VB.NET VB.NET rules related issues. Area: C# C# rules related issues. labels Feb 6, 2024
@Tim-Pohlmann Tim-Pohlmann added this to the 9.20 milestone Feb 6, 2024
@pavel-mikula-sonarsource
Copy link
Contributor

pavel-mikula-sonarsource commented Feb 7, 2024

Addition: What about positive+negative? Is that intended to implicitly fall back to "we don't know" scenario?

@pavel-mikula-sonarsource
Copy link
Contributor

pavel-mikula-sonarsource commented Feb 7, 2024

We should be able to do multiplication for negative*negative too?

@pavel-mikula-sonarsource
Copy link
Contributor

Why do the multiplication and division needs to work with constants only, and not positive/negative?

@Tim-Pohlmann
Copy link
Contributor Author

@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.

@pavel-mikula-sonarsource
Copy link
Contributor

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.

@Tim-Pohlmann
Copy link
Contributor Author

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;    
}

@Tim-Pohlmann Tim-Pohlmann removed this from the 9.20 milestone Feb 14, 2024
@pavel-mikula-sonarsource pavel-mikula-sonarsource added Type: SE Improve SE engine and removed Type: New Feature labels Jun 13, 2024
@Tim-Pohlmann Tim-Pohlmann removed their assignment Jul 16, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area: C# C# rules related issues. Area: CFG/SE CFG and SE related issues. Area: VB.NET VB.NET rules related issues. Type: SE Improve SE engine
Projects
None yet
Development

No branches or pull requests

2 participants