-
Notifications
You must be signed in to change notification settings - Fork 273
Load static initializers for enum types returned by opaque methods #3124
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.
This PR failed Diffblue compatibility checks (cbmc commit: 5bad705).
Build URL: https://travis-ci.com/diffblue/test-gen/builds/87232902
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).
@antlechner, Looks good. Do you have a TG bump? |
OK, found it: https://github.com/diffblue/test-gen/pull/2361 |
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.
Couple of questions to check, generally lgtm
if (c == null) | ||
return; | ||
assert c != null; | ||
boolean isRed = c.name().startsWith("RED") && c.name().length() == 3 |
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.
startsWith -> equals?
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's equivalent, yes, (and you wouldn't need c.name().length() == 3
) but pointer analysis doesn't cope very well with equals
because it's defined in Object
and overridden almost everywhere.
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 looks like a workaround.equals
also has to work...
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.
@smowton @peterschrammel I originally had equals
in my original enum tests but @romainbrenguier suggested that I use startsWith
and length
instead because it's quicker, and we don't want these tests to take too long. equals
would work as well, it would just take a bit longer I think.
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'm fine with that as long as we are sure that equals works as well (but takes a bit longer).
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 checked locally just to be sure, and using equals
works too, all the tests would pass with that. I'll leave the tests as they are, since they are testing properties of the returned enums, not String methods, and it's better to save a bit of time here.
&& c.ordinal() == 1; | ||
boolean isBlue = c.name().startsWith("BLUE") && c.name().length() == 4 | ||
&& c.ordinal() == 2; | ||
assert (isGreen || isBlue); |
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.
Why are these negative assertions but canChooseSomeConstant is a positive assertion?
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.
Positive assertions check for correctness whereas negative assertions check for reachability (as unreachable assertions cannot be violated by cbmc).
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, the positive assertion checks that jbmc will always choose something in the set of the three constants, and the negative assertions check that for any two given constants, there is something else that it can choose (namely, the third constant).
if (c == null) | ||
return; | ||
assert c != null; | ||
boolean isRed = c.name().startsWith("RED") && c.name().length() == 3 |
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 looks like a workaround.equals
also has to work...
@@ -42,6 +61,14 @@ bool ci_lazy_methods_neededt::add_needed_class( | |||
if(symbol_table.symbols.count(cprover_validate)) | |||
add_needed_method(cprover_validate); | |||
|
|||
// Special case for enums. We may want to generalise this, see TG-4689 | |||
// and the comment in java_object_factoryt::gen_nondet_pointer_init. | |||
namespacet ns{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.
Why {}?
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.
Copy-pasted from another function in this file, but ()
is probably better so I changed it to that, thanks.
@@ -42,6 +61,14 @@ bool ci_lazy_methods_neededt::add_needed_class( | |||
if(symbol_table.symbols.count(cprover_validate)) | |||
add_needed_method(cprover_validate); | |||
|
|||
// Special case for enums. We may want to generalise this, see TG-4689 |
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.
Generalise in what way? Since this is in JBMC, the TG reference is not very helpful.
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.
There is a link to java_object_factoryt::gen_nondet_pointer_init
, which has more details. I slightly rephrased this comment, putting the link first and the ticket number only afterwards in brackets so it's clearer that you don't actually need access to the ticket to work on this.
5bad705
to
06b2f80
Compare
Previously static initializers for enum types were only loaded for those types that are reachable from the arguments to the entry method. This would lead to an invariant violation when an opaque method returned an enum type (which needs to be nondet-initialized just like arguments to the entry method). This commit solves this problem by moving the code for marking the static initializers of enums as loaded from ci_lazy_methods to ci_lazy_methods_needed, and applying it to all deterministic and nondeterministic enums that are reachable in some way from the entry method. Including deterministic enums is not a problem, since we load static initializers for all types (enums and others) whose constructor we use anyway.
The tests were copied from jbmc/regression/jbmc/NondetEnumArg and adapted for the case where the enum is returned by an opaque method (Opaque.class has been deleted).
06b2f80
to
f9da0bd
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: 06b2f80).
Build URL: https://travis-ci.com/diffblue/test-gen/builds/87335833
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).
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: f9da0bd).
Build URL: https://travis-ci.com/diffblue/test-gen/builds/87344796
Previously static initializers for enum types were only loaded for those types that are reachable from the arguments to the entry method.
This would lead to an invariant violation when an opaque method returned an enum type (which needs to be nondet-initialized just like arguments to the entry method).
This PR solves this problem by moving the code for marking the static initializers of enums as loaded from ci_lazy_methods to ci_lazy_methods_needed, and applying it to all deterministic and
nondeterministic enums that are reachable in some way from the entry method.
Including deterministic enums is not a problem, since we load static initializers for all types (enums and others) whose constructor we use anyway.