-
Notifications
You must be signed in to change notification settings - Fork 42
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
ACSL: Improve handling of dereferences #703
base: dev
Are you sure you want to change the base?
Conversation
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.
👍 Thanks.
I'm not deeply familiar with the ACSL translation, so unfortunately I can only offer some superficial comments (see below).
Could you also add some test cases here?
final CType type = CEnum.replaceEnumWithInt(expr.getLrValue().getCType().getUnderlyingType()); | ||
// Perform a custom switch to RValue without any read calls | ||
// This allows us to use also dereferences inside ACSL expressions that have to be side-effect-free | ||
// (e.g., loop invariant or contracts) |
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.
But this will now also be used for ACSL asserts, right?
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.
Yes, it will be used for any ACSL expression.
final Expression memoryAccess = ExpressionFactory.constructNestedArrayAccessExpression(loc, | ||
mCHandler.getMemoryArrayForType(type), new Expression[] { heapValue.getAddress() }); | ||
return new ExpressionResultBuilder(expr).resetLrValue(new RValue(memoryAccess, type)).build(); | ||
} |
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.
Do I understand correctly that this code replaces the calls to mExprResultTransformer.switchToRValue
(and related methods) that were previously made?
If so, I am a bit unsure if this is a good place to have this. For instance, it could easily get out-of-sync with changes in switchToRValue
. Would it be possible to make this a specialized method e.g. mExprResultTransformer.switchToRValueWithoutSideEffects
?
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.
Do I understand correctly that this code replaces the calls to
mExprResultTransformer.switchToRValue
(and related methods) that were previously made?
Yes, any call to mExprResultTransformer.switchToRValue
in ACSLHandler
was replaced with a call to this method.
If so, I am a bit unsure if this is a good place to have this. For instance, it could easily get out-of-sync with changes in
switchToRValue
. Would it be possible to make this a specialized method e.g.mExprResultTransformer.switchToRValueWithoutSideEffects
?
We cannot get completely out-of-sync, this method still has the call to mExprResultTransformer.switchToRValue
as a base case (which does currently nothing, but if this changes, it will also be visible in this method).
We could also make it a public method in ExpressionResultTransformer
, but this switchToRValue
does not have any memsafety-checks (even if the setting is enabled). Therefore I am not sure, if it is a good idea to have such a public method in ExpressionResultTransformer
.
I just added two test cases. The should actually pass, since the |
Perform the switch to RValue only in the internal method dispatchSwitch
97e14cd
to
4915880
Compare
In our C translation, we translate dereferences to calls to Boogie procedures, e.g.,
x = a[i];
is translated to:where
read~int
has the following signature (for memsafety we have a stronger contract):This read-call is produced by
ExpressionResultTransformer::switchToRValue
.For ACSL, we attempted to handle this the same way as for C. There were however two problems:
ArrayAccessExpression
, the call toswitchToRValue
was missing, which led to a crash (fixed in 07b75aa)//@ assert x == a[i];
looks similar to above). There are however other ACSL statements / expressions, the translation with calls does not work, as it produces not only an expression, but also auxiliary statements (e.g., function contracts, loop invariants, quantifiers in the future). Therefore I replaced the read-call by an array-access in the corresponding memory-array (e.g.,#memory_int
) when handling ACSL. This was implemented through a customswitchToRValue
method inACSLHandler
(see d0b8165).Note: Before this change, every dereference was translated to a read/write-call in Boogie, where the
MemorySlicer
relied on. Therefore, we now crash, on programs with ACSL dereferences, whenMemorySlicer
is used (We probably have to replace#memory_int
everywhere, not only in the contracts of the read/write-procedures). @Heizmann can you have a look at this issue?