-
Notifications
You must be signed in to change notification settings - Fork 231
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: Add BitXorOperation #7246
SE: Add BitXorOperation #7246
Conversation
8407081
to
9df6079
Compare
NumberConstraint.From(42).IsSingleValue.Should().BeTrue();
NumberConstraint.From(1, 1).IsSingleValue.Should().BeTrue();
NumberConstraint.From(null, 42).IsSingleValue.Should().BeFalse();
NumberConstraint.From(42, null).IsSingleValue.Should().BeFalse();
NumberConstraint.From(1, 100).IsSingleValue.Should().BeFalse(); So the sub-100% coverage seems a glitch of AltCover. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think there are some things wrong. Let me know what you think and then I'll do another review.
...s/src/SonarAnalyzer.Common/SymbolicExecution/Roslyn/OperationProcessors/Binary.Arithmetic.cs
Outdated
Show resolved
Hide resolved
...s/src/SonarAnalyzer.Common/SymbolicExecution/Roslyn/OperationProcessors/Binary.Arithmetic.cs
Outdated
Show resolved
Hide resolved
{ | ||
return left.CanOverlap(right) ? 0 : Min(left.Max - right.Min, right.Max - left.Min); | ||
} | ||
return null; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should also be true, I think:
return null; | |
if (left.Min.HasValue && right.Min.HasValue) | |
{ | |
NegativeMagnitude(BigInteger.Min(left.Min.Value, right.Min.Value)); | |
} | |
return null; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This one breaks multiple cases, and flipping sign either inside and outside NegativeMagnitude
doesn't fix it.
Given how little impactful this case can in practice be, I would not invest more time in supporting it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Try this, it actually fixes two of the existing UTs.
return null; | |
else if ((left.IsPositive || right.IsNegative) && left.Max.HasValue && right.Min.HasValue) | |
{ | |
return NegativeMagnitude(-BigInteger.Max(left.Max.Value, BigInteger.Abs(right.Min.Value))); | |
} | |
else if ((left.IsNegative || right.IsPositive) && left.Min.HasValue && right.Max.HasValue) | |
{ | |
return NegativeMagnitude(-BigInteger.Max(BigInteger.Abs(left.Min.Value), right.Max.Value)); | |
} | |
else if (left.Min.HasValue && left.Max.HasValue && right.Min.HasValue && right.Max.HasValue) | |
{ | |
return NegativeMagnitude(-BigInteger.Max( | |
BigInteger.Max(BigInteger.Abs(left.Min.Value), right.Max.Value), | |
BigInteger.Max(left.Max.Value, BigInteger.Abs(right.Min.Value)))); | |
} | |
else | |
{ | |
return null; | |
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tried and worked for existing use cases. However, after some analysis, I could find a case that breaks your code:
[DataRow("i >= -3 && i <= -1 && j >= -4 && j <=-2", 0, 3)]
// Expected SETestContext.CreateCS(code, "int i, int j").Validator.TagValue("Value")
// to have constraints {NotNull, Number from 0 to 3}, but {Number from 0 to 3} are missing
// and additional {Number from 3 to 7} are present. Actual are {NotNull, Number from 3 to 7}.
Even if I got CalculateXorMax
(see comments below), an issue surely also affects CalculateXorMin
.
So, I am not applying these changes, and only keep basic cases where we have solid understanding of how to calculate lower bounds.
Again, given how little impactful these cases can in practice be, I would not invest more time in supporting them.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The test case is not affected by the code I suggested. When I add my code suggestion to the current implementation it does what I expect: It improves two test cases ("i == 4 && j >= -6" and "i == -4 && j <= 6").
if ((left.IsPositive && right.IsPositive) || (left.IsPositive && right.CanBePositive) || (right.IsPositive && left.CanBeNegative)) | ||
{ | ||
return left.Max.HasValue && right.Max.HasValue ? PositiveMagnitude(left.Max.Value | right.Max.Value) : null; | ||
} | ||
else if ((left.IsPositive && right.IsNegative) || (left.IsNegative && right.IsPositive)) | ||
{ | ||
return -1; | ||
} | ||
return null; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This logic confuses me. Shouldn't it be symmetric? From my understanding the following should be correct:
if ((left.IsPositive && right.IsPositive) || (left.IsPositive && right.CanBePositive) || (right.IsPositive && left.CanBeNegative)) | |
{ | |
return left.Max.HasValue && right.Max.HasValue ? PositiveMagnitude(left.Max.Value | right.Max.Value) : null; | |
} | |
else if ((left.IsPositive && right.IsNegative) || (left.IsNegative && right.IsPositive)) | |
{ | |
return -1; | |
} | |
return null; | |
if ((left.IsPositive && right.IsNegative) || (left.IsNegative && right.IsPositive)) | |
{ | |
return -1; | |
} | |
else if (left.Max.HasValue && right.Max.HasValue) | |
{ | |
return PositiveMagnitude(left.Max.Value | right.Max.Value); | |
} | |
else | |
{ | |
return null; | |
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Try this, it's the opposite to my suggested min:
if ((left.IsPositive && right.IsNegative) || (left.IsNegative && right.IsPositive))
{
return -1;
}
else if ((left.IsPositive || right.IsPositive) && left.Max.HasValue && right.Max.HasValue)
{
return PositiveMagnitude(BigInteger.Max(left.Max.Value, right.Max.Value));
}
else if ((left.IsNegative || right.IsNegative) && left.Min.HasValue && right.Min.HasValue)
{
return PositiveMagnitude(BigInteger.Max(BigInteger.Abs(left.Min.Value), BigInteger.Abs(right.Min.Value)));
}
else if (left.Min.HasValue && left.Max.HasValue && right.Min.HasValue && right.Max.HasValue)
{
return PositiveMagnitude(BigInteger.Max(
BigInteger.Max(left.Max.Value, right.Max.Value),
BigInteger.Max(BigInteger.Abs(left.Min.Value), BigInteger.Abs(right.Min.Value))));
}
else
{
return null;
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tried that too, and it breaks for the following test case:
[DataRow("i == 4 && j >= -6", null, null)] // exact range: -8, null
Expected SETestContext.CreateCS(code, "int i, int j").Validator.TagValue("Value")
to have constraints {NotNull}, but additional {Number from * to 7} are present.
Actual are {NotNull, Number from * to 7}.
Counterexample: i = 4 = 0b00000100 and j = 11 = 0b00001011 => i ^ j = 0b00001111 =15 > 7
There is something wrong in the branch that returns 7:
else if ((left.IsNegative || right.IsNegative) && left.Min.HasValue && right.Min.HasValue)
{
return PositiveMagnitude(BigInteger.Max(BigInteger.Abs(left.Min.Value), BigInteger.Abs(right.Min.Value)));
}
So, for max too, I would revert the code to the one surely working, and not invest more time in trying to support these cases, unless there is proven usefulness in doing so.
Also, I am not sure that return left.Max.HasValue && right.Max.HasValue ? PositiveMagnitude(BigInteger.Max(left.Max.Value, right.Max.Value)) : null;
works correctly for negative numbers, so I am keeping return left.Max.HasValue && right.Max.HasValue ? PositiveMagnitude(left.Max.Value | right.Max.Value) : null;
, for which I have strong intuition than it does and that works on all UTs.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I cannot reproduce the failing test case. Replacing the current implementation with my suggestion improves 5 test cases.
47b41c6
to
72f1b86
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I cannot reproduce the failing test cases. Applying my code suggestions improves multiple existing test cases. Please try once more to integrate the changes.
I may have missed something when trying to validate your suggestion. Since the release is already happening, and this work won't be included in it, I am keeping this PR on hold until your suggestions in #7310 get merged into this PR. I still think we have already hit a diminishing return with this development, and we shouldn't invest more effort to cover more cases. |
Kudos, SonarCloud Quality Gate passed! |
Kudos, SonarCloud Quality Gate passed! |
#7310 has been merged into this PR. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM!
Part of #7267
Based on the property (holding for positive numbers only) that$a - b \leq a \oplus b \leq a + b$