-
Notifications
You must be signed in to change notification settings - Fork 273
Finished applying fixes for jbmc for assignment consistency #3822
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
thk123
commented
Jan 16, 2019
- Each commit message has a non-empty body, explaining why the change was made.
- Methods or procedures I have added are documented, following the guidelines provided in CODING_STANDARD.md.
- [n/a] The feature or user visible behaviour I have added or modified has been documented in the User Guide in doc/cprover-manual/
- Regression or unit tests are included, or existing tests cover the modified code (in this case I have detailed which ones those are in the commit message). TODO
- [na] My commit message includes data points confirming performance improvements (if claimed).
- My PR is restricted to a single feature or bugfix.
- White-space or formatting changes outside the feature-related changed lines are in commits of their own.
"those arguments must be pointer-typed"); | ||
} | ||
|
||
call_args[i].make_typecast(need_type); |
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 seems pointless - given the above type_eq
the difference could now only be tag/symbol vs non-tag/symbol types.
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.
Not so, that only checked that the types are either type_eq
or are pointers
@@ -1531,7 +1550,7 @@ code_blockt java_bytecode_convert_methodt::convert_instructions( | |||
else if(statement=="getfield") | |||
{ | |||
PRECONDITION(op.size() == 1 && results.size() == 1); | |||
results[0]=java_bytecode_promotion(to_member(op[0], arg0)); | |||
results[0]=java_bytecode_promotion(to_member(op[0], arg0, ns)); |
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 will need per-commit clang-format cleanup.
Oops, missed the do-not-review label. |
@@ -642,20 +642,39 @@ static irep_idt get_if_cmp_operator(const irep_idt &stmt) | |||
throw "unhandled java comparison instruction"; | |||
} | |||
|
|||
static member_exprt to_member(const exprt &pointer, const exprt &fieldref) | |||
static member_exprt to_member( |
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.
documentation here would help
@@ -642,20 +642,39 @@ static irep_idt get_if_cmp_operator(const irep_idt &stmt) | |||
throw "unhandled java comparison instruction"; | |||
} | |||
|
|||
static member_exprt to_member(const exprt &pointer, const exprt &fieldref) | |||
static member_exprt to_member( | |||
const exprt &pointer, const exprt &fieldref, const namespacet &ns) |
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.
⛏️ fieldref is not a good name
|
||
dereference_exprt obj_deref=checked_dereference(pointer2, class_type); | ||
const irep_idt &component_name = fieldref.get(ID_component_name); |
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 fieldref assumed to be a member_exprt
? It would be better to make that explicit.
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.
It isn't member_exprt
, but rather the nameless expression that describes a getfield
or setfield
operand produced by the Java bytecode parser
to_struct_type(ns.follow(accessed_object.type())); | ||
auto component = object_type.get_component(component_name); | ||
|
||
if(component.is_not_nil()) |
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 would prefer if the loop was expressed as while(component.is_nil())
rather than while(1)
"infer_opaque_type_fields should guarantee that a member access has a " | ||
"corresponding field"); | ||
|
||
accessed_object = member_exprt(accessed_object, components.front()); |
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.
💡 ideally there should be a function giving the parent class from a java class type, that would make this piece of code clearer.
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.
Dumb question: what is it that assures us that we always need to look at the first component? I get that because of Java not permitting multiple inheritance if anything, it must be the first one. Is it because everything inherits at least from java.lang.object
that we know that this first component must be a struct type?
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.
Yep, invariant of Java object layout: every class has at least one member, and the first one is either @class_identifier
(java.lang.Object, or any stub class whose position in the class hierarchy is unknown) or its single superclass.
9adfb23
to
c9dea6b
Compare
So I couldn't reproduce the failure locally, seemingly because I don't understand this change, so if someone does and wants to PR it, that would have my approval. Otherwise, I will PR it after I've got this working. |
@tautschnig thanks for the tip @smowton just pointed me towards that - now got the failure locally. It is to do with an invalid pop and only with symex driven lazy loading so will keep digging. |
Tracked down the problem with the malformed pop (remove returns had already run on a function, so swapping out the type for the type in the symbol table meant no returns). Just checking locally that passes all the tests, then will push up here to verify on CI and then will create a TG bump since plausible it will break things there too. |
c9dea6b
to
8366f3b
Compare
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: 8366f3b).
Build URL: https://travis-ci.com/diffblue/test-gen/builds/97821114
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).
The incompatibility may have been introduced by an earlier PR. In that case merging this
PR should be avoided unless it fixes the current incompatibility.
Even when the compile errors are fixed, this fails in TG for non-equal types in symex - this looks to be to do with the custom stubbing - manual bump incoming. |
{ | ||
struct_tag_typet class_type(fieldref.get(ID_class)); | ||
|
||
const exprt typed_pointer = typecast_exprt::conditional_cast( | ||
pointer, java_reference_type(class_type)); | ||
const exprt typed_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.
This commit contains format fixups that ought to be squashed into a previous commit
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.
8366f3b
to
050dbec
Compare
TG bump looks to be passing - will address existing comments and tidy up, then should be ready for a final review from @tautschnig |
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.
✔️
Passed Diffblue compatibility checks (cbmc commit: 050dbec).
Build URL: https://travis-ci.com/diffblue/test-gen/builds/98066474
@thk123 Just send a ping when you're done with cleanup work. |
@thk123 Actually there isn't anything new that I hadn't looked at in the meantime, so just do the cleanup, merge, and update TG accordingly. Thanks! |
050dbec
to
fabeae2
Compare
|
||
// Component not present: check the immediate parent type. | ||
|
||
const auto &components = object_type.components(); |
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.
⛏️ Looks like resolve_inherited_componentt
can be adapted to do this search
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.
That said - this is just moving code from the typecheck so will clean up in a follow up PR/commit
fabeae2
to
dca461a
Compare
@thk123 re |
// may in fact belong to any ancestor type. | ||
while(1) | ||
{ | ||
struct_typet object_type = |
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'd use const struct_typet &object_type = ...
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.
This code is in fact simply moved - I'd prefer to follow this PR up with a clean up PR as this whole block I think can be replaced by resolve_inherited_componentt
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.
Sounds good!
"infer_opaque_type_fields should guarantee that a member access has a " | ||
"corresponding field"); | ||
|
||
accessed_object = member_exprt(accessed_object, components.front()); |
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.
Dumb question: what is it that assures us that we always need to look at the first component? I get that because of Java not permitting multiple inheritance if anything, it must be the first one. Is it because everything inherits at least from java.lang.object
that we know that this first component must be a struct type?
call_args[i].type().id() == ID_pointer, | ||
"where overriding function argument types differ, " | ||
"those arguments must be pointer-typed"); | ||
call_args[i].make_typecast(need_type); |
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.
Avoid using make_typecast
(it's now deprecated), do call_args[i] = typecast_exprt(call_args[i], need_type);
instead.
#include <goto-programs/goto_functions.h> | ||
#include <goto-programs/show_goto_functions.h> | ||
#include <iostream> |
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 that a debugging left-over?
/// by skipping over type casts and removing balanced dereference/address_of | ||
/// operations | ||
optionalt<symbol_exprt> | ||
root_object(const exprt &lhs_expr, const symbol_tablet &symbol_table) |
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.
As said in the comment, there is object_descriptor_exprt
. I think it may be necessary to extend object_descriptor_exprt::build_object_descriptor_rec
with code handling paired dereference_exprt/address_of_exprt
, but then it should do the trick for you. I believe all the code that this needs in addition is (some variant of):
else if(expr.id() == ID_dereference)
{
const dereference_exprt &deref = to_dereference_expr(expr);
if(deref.pointer().id() == ID_address_of)
{
const address_of_exprt &address_of = to_address_of_expr(deref.pointer());
dest.object() = address_of.object();
build_object_descriptor_rec(ns, address_of.object(), dest);
}
}
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 I saw the object_descriptor_exprt
and saw that it didn't handle the ref/deref. In the interest of not wanting to break anything else that uses this, I will attempt this refactor in a follow up PR too if that is acceptable to you.
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.
Sure!
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'll post a PR in a few minutes.
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.
See #3898.
#include <algorithm> | ||
#include <functional> | ||
#include <unordered_set> | ||
#include <goto-programs/remove_returns.h> |
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'd prefer not mixing our headers with STL includes.
It probably isn't a great assumption - it is true because in |
Previously we created the expression with the partial type given at the access site (i.e. as part of the get/setfield bytecode), but this lacked any generic type information, which the actual component *did* have. The member expression could therefore be type-inconsistent with the object is addressed. Since it's no longer necessary to make the expression approximately and later fix it up in typecheck_expr, let's just get it right the first time, including giving it the right type.
…le add operations This is generally illegal (but is tricky to trigger, hence no test)
…calls This both ensures that the reference to the callee precisely matches the callee's symbol type, and that parameters match. For example, previously the callee could specifically take a List<Integer>, but the type given at the callsite might just be `callee(List)`, omitting the generic type information, leading to a pointer changing type without a cast.
…ase type This is necessary because a generic qualifier is recorded on the pointer, while the direct member has an unqualified type.
For example, when List<E> extends the Collection<E> interface, its overrides of methods accepting an element, such as add(E), are given in terms of its own E, not that of Collection. Therefore we must cast from Collection::E* to List::E* when using that particular override. Only typecast if the parameter types are distinct
It already tried to do this, but doesn't take account for pointers that encode generic information: in such cases the underlying object type can be equal but the pointers differ, and a cast is necessary.
Once all the cases are fixed, this can be returned to a regular equality
dca461a
to
5a9bf1a
Compare
Seem to have done enough rebases to make clang-format go away... |
Specifically - be impartial to deref/cast/address of combinations on the lhs. Be impartial to direct assignments without casts Be impartial to casts before assigning to address of another variable
5a9bf1a
to
f0c520e
Compare
@tautschnig addressed minor comments, larger changes I would like to address in a follow up PR. If that's OK with you, this looks good to merge once CI passes. |
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: 5a9bf1a).
Build URL: https://travis-ci.com/diffblue/test-gen/builds/98303689
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).
The incompatibility may have been introduced by an earlier PR. In that case merging this
PR should be avoided unless it fixes the current incompatibility.
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.
✔️
Passed Diffblue compatibility checks (cbmc commit: f0c520e).
Build URL: https://travis-ci.com/diffblue/test-gen/builds/98304937