Skip to content

Conversation

@kkjeer
Copy link
Contributor

@kkjeer kkjeer commented Oct 11, 2019

This PR adds a temporary binding expression when building a BoundsCastExpr. This helps enable dynamic and assume bounds casts expressions to be treated as non-value-preserving in CanonBounds::CompareExpr (see issue #691).

Changes

  • Introduce temporary binding expression to bounds casts.
  • Adjust bounds inference and visiting cast expressions to reflect the temporary bindings.
  • Account for BoundsCastExprs when getting the temporary binding of an expression.
  • Account for whether the expression is in a checked scope or not in PruneTemporaryBindings. (A follow-up issue Differentiate between Memory and Bounds checked scopes in SemaBounds #698 is opened to use the CheckedScopeSpecifier enum rather than a boolean here.)
  • Consider BoundsCastExprs to be value-preserving in CheckBoundsDeclarations::EqualValue. Note: this assumes that the expressions E1 and E2 have been successfully evaluated. This change has been removed. This affects the Checked C static_check_bounds_cast.c test (modified in Add tests for bounds cast expression temporary bindings checkedc#385 - opened Improve memory access detection for bounds casts #695 to track remaining work).
  • Treat bounds cast expressions as non-value-preserving.
  • Consider an expression e to be lexicographically equal to the usage of a temporary binding of e.
  • Remove the llvm_unreachable call if a dynamic cast fails in CanonBounds::Compare. Since bounds casts are no longer considered value-preserving, it is possible to compare, e.g. a BoundsCastExpr and an ImplicitCastExpr. An ImplicitCastExpr cannot be dynamically cast to a BoundsCastExpr.
  • Account for the cast kind when profiling a BoundsCastExpr.

Tests

  • Remove the function call test from bounds-decl-challenges. With the introduction of temporaries to bounds cast expressions, this test no longer produces an error.
  • Add AST tests to verify that bounds cast expressions include a temporary binding expression.
  • Other tests are added to checked-c (Add tests for bounds cast expression temporary bindings checkedc#385).

Copy link
Member

@dtarditi dtarditi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have a few formatting suggestions. I think that the check in EqualValue needs to be pushed into the lexicographic comparison class.

if (BoundsValueExpr *BV1 = dyn_cast<BoundsValueExpr>(E1))
if (BV1->getTemporaryBinding() == E2)
if (BoundsValueExpr *BV1 = dyn_cast<BoundsValueExpr>(E1)) {
CHKCBindTemporaryExpr *Binding = BV1->getTemporaryBinding();
Copy link
Member

@dtarditi dtarditi Oct 11, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stylisitc issues: I believe the indentation of the declaration of Binding is off by one-space.

Clang/LLVM developers don't put single statements in blocks. So:

if (Binding == E2) {
 return Result::Equal;
}

should be

if (Binding == E2) 
  return Result::Equal
 #Resolved

if (Binding == E1) {
return Result::Equal;
}
if (Binding) {
Copy link
Member

@dtarditi dtarditi Oct 11, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The indentation seems off here.
#Resolved

CHKCBindTemporaryExpr *GetTempBinding(Expr *E) {
// Bounds casts should always have a temporary binding.
if (BoundsCastExpr *BCE = dyn_cast<BoundsCastExpr>(E)) {
CHKCBindTemporaryExpr *Result = dyn_cast<CHKCBindTemporaryExpr>(BCE->getSubExpr());
Copy link
Member

@dtarditi dtarditi Oct 11, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The indentation should be 2 characters.
#Resolved


static bool EqualValue(ASTContext &Ctx, Expr *E1, Expr *E2, EquivExprSets *EquivExprs) {
Lexicographic::Result R = Lexicographic(Ctx, EquivExprs).CompareExpr(E1, E2);
// It is assumed that E1 and E2 have been successfully evaluated, so that dynamic and assume bounds casts can be treated as value preserving here.
Copy link
Member

@dtarditi dtarditi Oct 11, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you need to push this check into Lexicographic expression comparison. There should be a special mode that answer the questions: if e1 and e2 evaluate to values, are the values guaranteed to be equal? We can assume there that any evaluations of dynamic_bounds_cast in subexpressions of e1 (or 32) will succeed and any bounds checks that depend on bounds changed by *_cast operation will also succeed.

#Resolved

Copy link
Member

@dtarditi dtarditi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great - nice to see code be deleted and become simpler! I have one suggested comment update. Please run automated testing before committing this,.

Cmp = CompareTypeIgnoreCheckedness(E1ChildExpr->getType(),
E2ChildExpr->getType());

if (!isa<BoundsExpr>(E1ChildExpr))
Copy link
Member

@dtarditi dtarditi Oct 11, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It'd be helpful to add a comment "Bounds expressions don't have types".
#Resolved

@kkjeer
Copy link
Contributor Author

kkjeer commented Oct 18, 2019

Looks great - nice to see code be deleted and become simpler! I have one suggested comment update. Please run automated testing before committing this,.

The automated testing has passed.

Copy link
Member

@dtarditi dtarditi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the methods in the BoundsInference class, can you make InCheckedScope a field, instead of passing it as an additional argument? An expression is always in the same checked scope, I believe.

@dtarditi
Copy link
Member

If we were to add support for statement expressions in GCC (https://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html) , an expression might not always be in the same checked scope.

@kkjeer kkjeer merged commit 82f665e into master Oct 19, 2019
@kkjeer kkjeer deleted the issue691-bounds-casts-temp-binding branch October 19, 2019 00:16
mgrang pushed a commit that referenced this pull request Oct 25, 2019
Cherry-picked from commit 82f665e
Author: Katherine Kjeer <[email protected]>
Commit: GitHub <[email protected]>

    Introduce temporary bindings to BoundsCastExprs (#694)

    * Account for cast kind in StmtProfiler::VisitBoundsCastExpr and CanonBounds::CompareImpl

    * Don't treat dynamic and assume bounds casts as value preserving; don't compare types on bounds expressions

    * Introduce a temporary binding expression for all bounds cast expressions

    * Use the temporary bindings introduced in bounds cast expressions to infer bounds

    * Remove unused PruneTemporaryBindings

    * Treat e and the usage of a temporary binding of e as equal

    * Remove llvm_unreachable from CanonBounds::Compare

    * Account for bounds cast expressions in GetTempBinding

    * Treat bounds casts as value preserving in CheckBoundsDelarations::EqualValue (introducing the assumption that E1 and E2 have been evaluated)

    * Remove function call test from bounds-decl-challenges

    * Add AST dump tests for bounds cast expression temporaries

    * Fix indentation

    * More formatting fixes

    * Revert treating bounds casts as value preserving in EqualValue

    * Add comment about lack of bounds expression types

    * Prune temporary bindings from member expression bounds

    * Account for checked scope information in PruneTemporaryBindings
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants