-
Notifications
You must be signed in to change notification settings - Fork 273
Make goto_rw slightly less conservative [depends-on: #3769, blocks: #2677, #2694] #2646
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
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.
is_dynamic_object
seems like a good change to me -- though invalid_pointer_exprt
for example should then also become is_invalid_pointer_exprt
? Also suggest if you're introducing such an expression to give it an exprt
-derived helper class (inheriting from unary_predicate_exprt
I would imagine).
I don't know enough about goto_rw
to comment whether the change will have unintended consequences unfortunately, so must practically defer to @tautschnig or @peterschrammel here.
@@ -175,7 +175,9 @@ void dep_graph_domaint::data_dependencies( | |||
{ | |||
bool found=false; | |||
for(const auto &wr : w_range.second) | |||
{ |
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.
Give simple re-styles like this their own commit
src/analyses/goto_rw.cpp
Outdated
else if(expr.id()==ID_dynamic_object) | ||
{ | ||
// Dynamic object expressions should always have two operands. | ||
PRECONDITION(expr.operands().size() == 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.
Redundant with to_dynamic_object_expr
src/analyses/goto_rw.cpp
Outdated
// Dynamic object expressions should always have two operands. | ||
PRECONDITION(expr.operands().size() == 2); | ||
const auto obj_instance = to_dynamic_object_expr(expr).get_instance(); | ||
add(mode, "dynamic_object-" + std::to_string(obj_instance), 0, -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.
Any risk of name clash? Most analyses seem to namespace dynamic objects to avoid this
const symbolt *symbol_ptr; | ||
if(ns.lookup(identifier, symbol_ptr)) | ||
const symbolt *symbol_ptr = nullptr; | ||
if(ns.lookup(identifier, symbol_ptr) && |
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.
Move the ns.lookup()
out of the test?
src/ansi-c/expr2c.cpp
Outdated
@@ -3574,7 +3574,7 @@ std::string expr2ct::convert_with_precedence( | |||
else if(src.id()==ID_invalid_pointer) | |||
return convert_function(src, "__CPROVER_invalid_pointer", precedence=16); | |||
|
|||
else if(src.id()==ID_dynamic_object) | |||
else if(src.id()==ID_is_dynamic_object) | |||
return convert_function(src, "DYNAMIC_OBJECT", precedence=16); |
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.
Consider the same improvement to the pretty-printed code too? (i.e. "DYNAMIC_OBJECT" -> "IS_DYNAMIC_OBJECT")
I agree that, for example, I've addressed the other comments in the next version of this PR. |
@@ -45,7 +45,7 @@ literalt bv_pointerst::convert_rest(const exprt &expr) | |||
} | |||
} | |||
} | |||
else if(expr.id()==ID_dynamic_object) | |||
else if(expr.id()==ID_is_dynamic_object) | |||
{ | |||
if(operands.size()==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.
These should probably become DATA_INVARIANTS but this is a clean up and not vital for 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.
These being the condition operands.size() == 1 && operands[0].type().id() == ID_pointer
?
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. They should be enforced on exprt creation with PRECONDITION, on conversion with DATA_INVARIANT (as you have done in std_expr) and then referenced / checked with DATA_INVARIANT when they are relevant for the usage (for example here).
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 so. Can people who care about the full slicer and have test suites for it ( @polgreen @tautschnig @danpoe @chrisr-diffblue ) have a quick run with this PR.
src/util/simplify_expr_pointer.cpp
Outdated
if(expr.operands().size()!=1) | ||
return true; | ||
// This should hold as a result of the expr ID being is_dynamic_object. | ||
PRECONDITION(expr.operands().size() == 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.
Pedantry! DATA_INVARIANT because it is something that should always be true for think kind of exprt.
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 PR failed Diffblue compatibility checks (cbmc commit: 45b5508).
Build URL: https://travis-ci.com/diffblue/test-gen/builds/80810785
Status will be re-evaluated on next push.
Please contact @peterschrammel, @thk123, or @allredj for support.
Common spurious failures:
- the cbmc commit has disappeared in the mean time (e.g. in a force-push)
- the author is not in the list of contributors (e.g. first-time contributors).
I did a quick run of this PR, rebased against develop, and with PR #2642 cherry-picked on top of it. I don't think it's introduced any new bugs for me. The full slicer does terminate with "identifier not found", but develop does too. |
This commit resolves an issue where ID_dynamic_object was used to label two semantically distinct exprts. One, with a single operand, was a boolean expression meaning that the operand is a pointer to a dynamic object. This has been renamed to ID_is_dynamic_object. The second, with two operands, is an exprt representing a dynamic object itself. This has stayed ID_dynamic_object. Disambiguating which meaning was intended in each case was relatively easy, as uses of these exprts frequently come with assertions about the number of operands, and so this was used to inform which instances of ID_dynamic_object should be changed and which should be left the same.
When handling the case of pointers, goto_rw would mark both the object pointed to and the pointer itself as written. For example, if x = &i, the line `*x = 1' would yield a write set containing both x and i, instead of just i. This resolves that issue by ensuring that value_set_dereference always gives at least one object that the dereference can refer to. This also resolves a bug wherein &a is marked as reading from a by removing the ID_symbol special case from get_objects_address_of.A
This branch is not taken by symex but it is taken by the slicer. The code I've removed has no effect, as far as I can tell, and may have been left over from an old implementation from before the beginning of the git history. Note, there is a commit that splits ID_dynamic_object into two different ids. See diffblue#2646 and diffblue#3769 for more details.
I've pulled out the commit "Disambiguates two exprts with the same ID." as #4479, and added a related change. |
Closing due to age (no further comment on PR content), please reopen with rebase on develop if you intent to continue this work. |
This addresses the issues mentioned in #748 using a slightly different approach.
The issue that arose previously was that value_set_dereference failed to translate dereferences of pointers to dynamic objects into accesses of objects, and so
*x = 1
would write tox
but not to*x
. This change ensures that an object access is always generated, and so*x = 1
can be made to no longer write tox
without influencing the correctness of analyses such as dependence_graph. This change is contained in f095e43.In order to resolve this issue, we first had to disambiguate two different
exprt
s which were using the same ID but were semantically distinct. This is done in 87e8ab1, and more description of how it was possible to determine which meaning was intended in each case is provided in the commit message.The final commit (a6db625) includes a test case that was introduced by #748. This pull request does not make that test case work, but since it does resolve most of the other issues resolved by #748, it made sense to introduce the test here as well.