Bounds context: update after assignments [3/n]#836
Conversation
…icit casts of rvalue casts
…eck to GetOriginalValue
…ility check to GetOriginalValue" This reverts commit 2dba020.
…into equiv-expr-fixes
…into equiv-expr-fixes
…into bounds-context-assignments
…into bounds-context-assignments
…into bounds-context-assignments
…into bounds-context-assignments
dtarditi
left a comment
There was a problem hiding this comment.
Overall, looks good. I have some suggestions for comments and a few questions.
clang/lib/Sema/SemaBounds.cpp
Outdated
| // Record expression equality implied by initialization. | ||
| SmallVector<SmallVector <Expr *, 4>, 4> EquivExprs; | ||
| SmallVector<Expr *, 4> EqualExpr; | ||
| // EquivExprs may not already contain equality implied by initialization |
There was a problem hiding this comment.
Instead of duplicating the explanation in the comment from CheckBoundsDeclAtAssignment, could you just reference back to the explanation in that comment?
| // CHECK-NEXT: IntegerLiteral {{.*}} 1 | ||
| // CHECK-NEXT: } | ||
|
|
||
| // Observed bounds context before declaration: { a => bounds(a, a + 1), arr => bounds(arr, arr + 0), buf => bounds(buf, buf + 2) } |
There was a problem hiding this comment.
Should buf be in the observed bound context before the declaration?
clang/lib/Sema/SemaBounds.cpp
Outdated
| // CreateIntegerLiteral returns an integer literal with Ty type. | ||
| // If Ty denotes a pointer to an integer type (char *, ptr<int>, etc.), | ||
| // CreateIntegerLiteral returns an integer literal with Ty's pointee type. | ||
| // If Ty denotes a pointer to a non-integer type (float *, ptr<double>, |
There was a problem hiding this comment.
I found this comment and code confusing. Are you overloading creation of the integer literal to account for the different bitwidth of integer literals required for integer arithmetic vs. pointer arithmetic involving a literal. For pointer arithmetic, if the pointee type is an integer type, why would you make the type of the integer literal match the pointee type? An example, for "char *", it is valid to add an integer larger than a char to the pointer.
…into bounds-context-assignments
…into bounds-context-assignments
There was a problem hiding this comment.
Overall, this change looks great! Thank you.
There is a follow-up issue that can be addressed in a future change. I believe the observed bounds for local/global array variables aren't correct right now. It is based on the declared bounds. The observed bounds should be based on the (complete) type of the array variable. Could you open an issue about this?
| // If statement, redeclared variable | ||
| void declared2(int flag, int x, int y) { | ||
| // Observed bounds context: { a => bounds(a, a + x) } | ||
| int a checked[] : count(x) = (int checked[]){ 0 }; |
There was a problem hiding this comment.
The observed bounds declaration for an array variable should be based on the declared type of the array variable. It seems to be based on the declared bounds declaration here, which is incorrect. I checked the code in SemaBounds.cpp. Handling of this case seems to be missing, and there is a even a "TODO" that hints at this.
Could you open a new issue for this case? I think this should be handled as a separate change. You should not try to fix it in this PR. There's no reason for this to block further.
| @@ -3288,7 +3351,7 @@ namespace { | |||
| } else { | |||
| BoundsExpr *NormalizedDeclaredBounds = ExpandToRange(D, DeclaredBounds); | |||
There was a problem hiding this comment.
I believe the observed bounds need to be set in this case. Please open an issue to track this, as a separate follow-up. Addressing this case I believe will handled the TODO that is just above (at line 3273).
This PR updates the context mapping variable declarations to their current known bounds after an assignment to a variable.
Context:
This work is part of the soundness of bounds declaration checking. After this PR is merged, the next step is to validate that each variable declaration's observed bounds implies the variable's declared bounds after checking a top-level CFG statement.
Notable changes:
p = p + 2, ifphas declared bounds(p, p + 1)will be (p - 2, p - 2 + 1), since the original value ofpisp - 2.phas declared bounds(p, p + 1), afterp++, check that the updated result bounds(p - 1, p - 1 + 1)imply the declared bounds(p, p + 1).Implications for pointer arithmetic:
One important change in this PR is that the source bounds used to check an assignment are the updated observed bounds. This means that pointer arithmetic on variables with declared bounds will frequently result in bounds warnings or errors.
For example, these assignments will all result in a warning:
These assignments will all result in an error:
Testing: