-
Notifications
You must be signed in to change notification settings - Fork 284
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| public enum Color { | ||
| RED, | ||
| GREEN, | ||
| BLUE | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,54 @@ | ||
| public class NondetEnumOpaqueReturn { | ||
|
|
||
| public static void canChooseSomeConstant() { | ||
| Opaque o = new Opaque(); | ||
| Color c = o.getC(); | ||
| if (c == null) | ||
| return; | ||
| assert c != null; | ||
| boolean isRed = c.name().startsWith("RED") && c.name().length() == 3 | ||
| && c.ordinal() == 0; | ||
| boolean isGreen = c.name().startsWith("GREEN") && c.name().length() == 5 | ||
| && c.ordinal() == 1; | ||
| boolean isBlue = c.name().startsWith("BLUE") && c.name().length() == 4 | ||
| && c.ordinal() == 2; | ||
| assert (isRed || isGreen || isBlue); | ||
| } | ||
|
|
||
| public static void canChooseRed() { | ||
| Opaque o = new Opaque(); | ||
| Color c = o.getC(); | ||
| if (c == null) | ||
| return; | ||
| boolean isGreen = c.name().startsWith("GREEN") && c.name().length() == 5 | ||
| && c.ordinal() == 1; | ||
| boolean isBlue = c.name().startsWith("BLUE") && c.name().length() == 4 | ||
| && c.ordinal() == 2; | ||
| assert (isGreen || isBlue); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why are these negative assertions but canChooseSomeConstant is a positive assertion?
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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).
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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). |
||
| } | ||
|
|
||
| public static void canChooseGreen() { | ||
| Opaque o = new Opaque(); | ||
| Color c = o.getC(); | ||
| if (c == null) | ||
| return; | ||
| boolean isRed = c.name().startsWith("RED") && c.name().length() == 3 | ||
| && c.ordinal() == 0; | ||
| boolean isBlue = c.name().startsWith("BLUE") && c.name().length() == 4 | ||
| && c.ordinal() == 2; | ||
| assert (isRed || isBlue); | ||
| } | ||
|
|
||
| public static void canChooseBlue() { | ||
| Opaque o = new Opaque(); | ||
| Color c = o.getC(); | ||
| if (c == null) | ||
| return; | ||
| boolean isRed = c.name().startsWith("RED") && c.name().length() == 3 | ||
| && c.ordinal() == 0; | ||
| boolean isGreen = c.name().startsWith("GREEN") && c.name().length() == 5 | ||
| && c.ordinal() == 1; | ||
| assert (isRed || isGreen); | ||
| } | ||
|
|
||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| public class Opaque { | ||
|
|
||
| Color c; | ||
|
|
||
| public Color getC() { | ||
| return c; | ||
| } | ||
|
|
||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| CORE | ||
| NondetEnumOpaqueReturn.class | ||
| --function NondetEnumOpaqueReturn.canChooseSomeConstant --cp `../../../../scripts/format_classpath.sh . ../../../src/java_bytecode/library/core-models.jar` | ||
| ^VERIFICATION SUCCESSFUL$ | ||
| ^EXIT=0$ | ||
| ^SIGNAL=0$ | ||
| -- | ||
| -- | ||
| The test checks that the name and ordinal fields of nondet-initialized enums | ||
| which have been returned by an opaque method correspond to those of an enum | ||
| constant of the same type. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| CORE | ||
| NondetEnumOpaqueReturn.class | ||
| --function NondetEnumOpaqueReturn.canChooseRed --cp `../../../../scripts/format_classpath.sh . ../../../src/java_bytecode/library/core-models.jar` | ||
| ^VERIFICATION FAILED$ | ||
| -- | ||
| -- | ||
| Test 1 of 3 to check that any of the enum constants can be chosen. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| CORE | ||
| NondetEnumOpaqueReturn.class | ||
| --function NondetEnumOpaqueReturn.canChooseGreen --cp `../../../../scripts/format_classpath.sh . ../../../src/java_bytecode/library/core-models.jar` | ||
| ^VERIFICATION FAILED$ | ||
| -- | ||
| -- | ||
| Test 2 of 3 to check that any of the enum constants can be chosen. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| CORE | ||
| NondetEnumOpaqueReturn.class | ||
| --function NondetEnumOpaqueReturn.canChooseBlue --cp `../../../../scripts/format_classpath.sh . ../../../src/java_bytecode/library/core-models.jar` | ||
| ^VERIFICATION FAILED$ | ||
| -- | ||
| -- | ||
| Test 3 of 3 to check that any of the enum constants can be chosen. |
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 withequalsbecause it's defined inObjectand 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.
equalsalso 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
equalsin my original enum tests but @romainbrenguier suggested that I usestartsWithandlengthinstead because it's quicker, and we don't want these tests to take too long.equalswould 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
equalsworks 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.