-
Notifications
You must be signed in to change notification settings - Fork 79
Equivalent expressions: assignments [3/n] #802
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
Conversation
…tions of predecessor block states
…signment to a non-variable
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 have suggestions for comment improvements and some issues to address in follow-up pull requests.
clang/lib/Sema/SemaBounds.cpp
Outdated
// Create the RHS of the implied assignment `e1 = e1 @ e2`. | ||
Src = ExprCreatorUtil::CreateBinaryOperator(S, Target, RHS, Op); | ||
|
||
// Update the set of expressions that produce the same value as `e1`. |
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 this comment could be clarified to explain why we are doing this. Given that the compound assignment modifies e1, we need to choose an expression equal to the value of e1 before the assignment.
clang/lib/Sema/SemaBounds.cpp
Outdated
SubExprGs[Src] = State.G; | ||
} | ||
|
||
// Update UEQ and G for assignments to a variable `e1`. |
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.
In the comment, I think you should change variable
to expression
.
clang/lib/Sema/SemaBounds.cpp
Outdated
// Update State.G using the the target of the inc/dec operator for | ||
// expressions where the integer constant 1 could not be constructed | ||
// (e.g. floating point expressions). State.UEQ remains unchanged. | ||
if (CheckIsNonModifying(Target) && CanBeInEqualExprSet(Target)) |
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 doesn't seem right. What if the expression is a pre-increment expression, such as ++e1? Target is not the correct value of the entire expression ++e1. I think in case where the increment/decrement literal does not have an integer type, it is fine to set G to the empty set.
clang/lib/Sema/SemaBounds.cpp
Outdated
@@ -3238,6 +3520,71 @@ namespace { | |||
RValueBounds = Check(E, CSS, State); | |||
} | |||
|
|||
// Methods to update sets of equivalent expressions. |
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 indentation is off.
clang/lib/Sema/SemaBounds.cpp
Outdated
return EqualValue(S.Context, V, Var, nullptr); | ||
} | ||
|
||
// CanBeInEqualExprSet returns true if the expression e can be added to |
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 this method name is confusing. It should either be more descriptive, or also exclude non-modifying expressions.
@@ -2327,8 +2518,50 @@ namespace { | |||
} | |||
} | |||
|
|||
// Update State.UEQ and State.G. |
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 didn't see this comment addressed in your most recent change. It would have been helpful to have a clarifying response here about why it wasn't addressed.
I looked into this and see that UpdateG is screening out non-modifying expressions in the S_i. I am pretty concerned about this. Expression equivalence checking assumes that expressions are non-modifying expressions and may produce incorrect results if they are modifying expressions.
For this reason, I think we should have an invariant that none of the subexpressions G_i containy modifying expression. This change is already large and I'd rather land it now, then have it continune onward. @kkjeer could you file an issue about this, and follow-up in a subsequent check-in.
// BinaryOperator: compound assignment to a variable | ||
void f3(unsigned i) { | ||
// Updated UEQ: { { (i - 2) + 2, i } } | ||
i += 2; |
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 equality implied by the UEQ set is a tautology. (i-2)+2
is equivalent to i
(ignoring overflow). So we are saying i == i
. When updating UEQ information, we should screen out equality facts implied by assignments to variables where the variable also appears on the right-hand side of the assignments. It's fine to flag this as a follow-up issue. This is already a large pull request.
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 created issue #814 to track this work.
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.
Overall, looks great.
I have one last change regarding pre/post-increment expressions. We are trying to compute the non-modifying expression that is equivalent to the value produced by the pre/post-increment expression in the program state after the pre/post-increment expression has executed. The logic that you have reversed. In the state after executing ++x, x produces a value equivalent to the value produced by ++x.
clang/lib/Sema/SemaBounds.cpp
Outdated
|
||
// Update the set G of expressions that produce the same value as e. | ||
if (RHS) { | ||
// For post-inc/dec operators, use the rvalue for `e1` to update G. |
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 is reversed. In the state after the expression ++x has executed, the non-modifying expression equivalent to the value produced by ++x is x. For x++, the non-modifying expression is x - 1..
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.
Looks good! Thank you for the effort that you put into this change!
This PR updates the sets UEQ and G of equivalent expressions while checking expressions that involve assignments. This is done with the following changes:
Testing:
if
statements.