Unit-test try_evaluate_pointer_comparison and bugfix#4774
Conversation
This is so that we can unit-test this function.
b74ba9d to
4bf2cd5
Compare
get_l1_object suggests we are comparing the address of the object, but the actually should interpret the symbol itself as a pointer. A unit test for the case of the issue that is fixed will be added in a following commit.
Field sensitivity the value set to keep track of pointers in individal fields, making it possible to evaluate equalities such as the one in the example. This is a case which would not work if try_evaluate_pointer_comparisons was using get_l1_object_identifier instead of getting the identifier of the whole l1 expression (not the underlying object). fixup! Check pointer evaluation in the array case
4bf2cd5 to
017cd09
Compare
src/pointer-analysis/value_set.cpp
Outdated
| output(ns, std::cout); | ||
| #endif | ||
|
|
||
| PRECONDITION(is_l1_renamed(lhs)); |
There was a problem hiding this comment.
This is only true when used in symex-- otherwise we expect to operate on plain un-renamed expressions. Therefore these invariants should move to symex_dereference or to some wrapper function in goto_statet.
There was a problem hiding this comment.
I defined a wrapper class for value_sett (a wrapper function wouldn't ensure we didn't continue to use the unchecked one)
owen-mc-diffblue
left a comment
There was a problem hiding this comment.
Great unit tests. Some other edge cases you might want to consider testing: if the value-set contains ID_unknown, ID_invalid or a failed symbol then try_evaluate_pointer_comparison should not be able to determine anything.
b056982 to
2253cbd
Compare
|
@owen-jones-diffblue I added some cases in the unit test, in particular some with unknown in the value set. |
|
Btw failed symbols are covered by the regression test that was merged in #4659, I believe. |
src/goto-symex/symex_value_set.h
Outdated
|
|
||
| /// Wrapper for value_sett which ensures we access it in a consistent way. | ||
| /// In particular level 1 names should be used. | ||
| class symex_value_sett : value_sett |
There was a problem hiding this comment.
Generally prefer composition to inheritence
| ssa_exprt l1_lhs(lhs); | ||
| l1_lhs.remove_level_2(); | ||
|
|
||
| if(run_validation_checks) |
There was a problem hiding this comment.
These should still be guarded by if(run_validation_checks)
tautschnig
left a comment
There was a problem hiding this comment.
This PR appears to be doing at least 3 different things (and some of them I believe are wrong, see detailed comments).
src/goto-symex/renamed.cpp
Outdated
| bool is_l1_renamed(const exprt &expr) | ||
| { | ||
| if(!is_l2_renamed(expr.type())) | ||
| return false; |
There was a problem hiding this comment.
The claim made in the commit message seems wrong: the type may well be renamed to L2 even when the object itself is only L1. On the contrary, it actually makes no sense for the type to be renamed to L1 ever.
There was a problem hiding this comment.
Ok I didn't know that the type could be L2 while the object L1. But is it true that L1 object always have L2 types? It sounds wrong to me. It seems that when an ssa_exprt is renamed to L1, its type is also renamed to L1.
There was a problem hiding this comment.
Renaming to L1 effectively is instantiation/determines which instance of a named object we are using. At that point the type must be complete, i.e., must be L2.
There was a problem hiding this comment.
It seems to be the case in symex_decl but not in symex_dereference and the other places where L1 renaming is used. Should we make rename<L1> apply L2 renaming on the type to ensure this is consistent?
src/pointer-analysis/value_set.cpp
Outdated
| #include <langapi/language_util.h> | ||
| #include <util/range.h> | ||
| #include <util/format_expr.h> | ||
| #include <util/format_type.h> |
There was a problem hiding this comment.
But then #include <langapi/language_util.h> better be removed as well (and hopefully also the corresponding entry in module_dependencies.txt).
src/pointer-analysis/value_set.cpp
Outdated
| #include <util/prefix.h> | ||
| #include <util/simplify_expr.h> | ||
|
|
||
| #include <goto-symex/renamed.h> |
There was a problem hiding this comment.
I don't think a dependency from pointer-analysis towards goto-symex is right.
ded9716 to
e26f4cd
Compare
Yes you are right, I extracted what comes after the unit tests and bugfix into a new pull request |
allredj
left a comment
There was a problem hiding this comment.
✔️
Passed Diffblue compatibility checks (cbmc commit: e26f4cd).
Build URL: https://travis-ci.com/diffblue/test-gen/builds/115206278
Codecov Report
@@ Coverage Diff @@
## develop #4774 +/- ##
==========================================
Coverage ? 68.62%
==========================================
Files ? 1276
Lines ? 105155
Branches ? 0
==========================================
Hits ? 72162
Misses ? 32993
Partials ? 0
Continue to review full report at Codecov.
|
This test the case where ptr1 can point to value1 or value2 and we evaluate `ptr1 != &value1`
This check the case where ptr1 is either &value1 or &value2 and we compare it to null.
This adds a unit test for the case where the value set contains unknown. In that case no comparison can be decided.
6f1891d to
767d8f0
Compare
allredj
left a comment
There was a problem hiding this comment.
✔️
Passed Diffblue compatibility checks (cbmc commit: 767d8f0).
Build URL: https://travis-ci.com/diffblue/test-gen/builds/115226966
This adds some unit test for
try_evaluate_pointer_comparison, then fix a small bug, and add an unit-test for the case that was buggy, then add some checks for an implicit invariant that I noticed while unit testing, and make value_sett::output more usable in particular for debugging unit tests.