Skip to content

Commit 9ce6a06

Browse files
authored
Merge pull request #3124 from antlechner/stub-return-enum
Load static initializers for enum types returned by opaque methods
2 parents d63fb7a + f9da0bd commit 9ce6a06

13 files changed

+130
-41
lines changed
Binary file not shown.
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
public enum Color {
2+
RED,
3+
GREEN,
4+
BLUE
5+
}
Binary file not shown.
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
public class NondetEnumOpaqueReturn {
2+
3+
public static void canChooseSomeConstant() {
4+
Opaque o = new Opaque();
5+
Color c = o.getC();
6+
if (c == null)
7+
return;
8+
assert c != null;
9+
boolean isRed = c.name().startsWith("RED") && c.name().length() == 3
10+
&& c.ordinal() == 0;
11+
boolean isGreen = c.name().startsWith("GREEN") && c.name().length() == 5
12+
&& c.ordinal() == 1;
13+
boolean isBlue = c.name().startsWith("BLUE") && c.name().length() == 4
14+
&& c.ordinal() == 2;
15+
assert (isRed || isGreen || isBlue);
16+
}
17+
18+
public static void canChooseRed() {
19+
Opaque o = new Opaque();
20+
Color c = o.getC();
21+
if (c == null)
22+
return;
23+
boolean isGreen = c.name().startsWith("GREEN") && c.name().length() == 5
24+
&& c.ordinal() == 1;
25+
boolean isBlue = c.name().startsWith("BLUE") && c.name().length() == 4
26+
&& c.ordinal() == 2;
27+
assert (isGreen || isBlue);
28+
}
29+
30+
public static void canChooseGreen() {
31+
Opaque o = new Opaque();
32+
Color c = o.getC();
33+
if (c == null)
34+
return;
35+
boolean isRed = c.name().startsWith("RED") && c.name().length() == 3
36+
&& c.ordinal() == 0;
37+
boolean isBlue = c.name().startsWith("BLUE") && c.name().length() == 4
38+
&& c.ordinal() == 2;
39+
assert (isRed || isBlue);
40+
}
41+
42+
public static void canChooseBlue() {
43+
Opaque o = new Opaque();
44+
Color c = o.getC();
45+
if (c == null)
46+
return;
47+
boolean isRed = c.name().startsWith("RED") && c.name().length() == 3
48+
&& c.ordinal() == 0;
49+
boolean isGreen = c.name().startsWith("GREEN") && c.name().length() == 5
50+
&& c.ordinal() == 1;
51+
assert (isRed || isGreen);
52+
}
53+
54+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
public class Opaque {
2+
3+
Color c;
4+
5+
public Color getC() {
6+
return c;
7+
}
8+
9+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
CORE
2+
NondetEnumOpaqueReturn.class
3+
--function NondetEnumOpaqueReturn.canChooseSomeConstant --cp `../../../../scripts/format_classpath.sh . ../../../src/java_bytecode/library/core-models.jar`
4+
^VERIFICATION SUCCESSFUL$
5+
^EXIT=0$
6+
^SIGNAL=0$
7+
--
8+
--
9+
The test checks that the name and ordinal fields of nondet-initialized enums
10+
which have been returned by an opaque method correspond to those of an enum
11+
constant of the same type.
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
CORE
2+
NondetEnumOpaqueReturn.class
3+
--function NondetEnumOpaqueReturn.canChooseRed --cp `../../../../scripts/format_classpath.sh . ../../../src/java_bytecode/library/core-models.jar`
4+
^VERIFICATION FAILED$
5+
--
6+
--
7+
Test 1 of 3 to check that any of the enum constants can be chosen.
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
CORE
2+
NondetEnumOpaqueReturn.class
3+
--function NondetEnumOpaqueReturn.canChooseGreen --cp `../../../../scripts/format_classpath.sh . ../../../src/java_bytecode/library/core-models.jar`
4+
^VERIFICATION FAILED$
5+
--
6+
--
7+
Test 2 of 3 to check that any of the enum constants can be chosen.
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
CORE
2+
NondetEnumOpaqueReturn.class
3+
--function NondetEnumOpaqueReturn.canChooseBlue --cp `../../../../scripts/format_classpath.sh . ../../../src/java_bytecode/library/core-models.jar`
4+
^VERIFICATION FAILED$
5+
--
6+
--
7+
Test 3 of 3 to check that any of the enum constants can be chosen.

jbmc/src/java_bytecode/ci_lazy_methods.cpp

Lines changed: 0 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -392,37 +392,6 @@ void ci_lazy_methodst::initialize_instantiated_classes(
392392
// As in class_loader, ensure these classes stay available
393393
for(const auto &id : extra_instantiated_classes)
394394
needed_lazy_methods.add_needed_class("java::" + id2string(id));
395-
396-
// Special case for enums. We may want to generalise this, see TG-4689
397-
// and the comment in java_object_factoryt::gen_nondet_pointer_init.
398-
for(const auto &found_class : needed_lazy_methods.get_instantiated_classes())
399-
{
400-
const auto &class_type = to_java_class_type(ns.lookup(found_class).type);
401-
if(class_type.get_base("java::java.lang.Enum"))
402-
add_clinit_call(found_class, ns.get_symbol_table(), needed_lazy_methods);
403-
}
404-
}
405-
406-
/// Helper function for `initialize_instantiated_classes`.
407-
/// For a given class id that is being noted as needed in `needed_lazy_methods`,
408-
/// notes that its static initializer is also needed.
409-
/// This applies the same logic to the given class that
410-
/// `java_bytecode_convert_methodt::get_clinit_call` applies e.g. to classes
411-
/// whose constructor we call in a method body. This duplication is unavoidable
412-
/// due to the fact that ci_lazy_methods essentially has to go through the same
413-
/// logic as __CPROVER_start in its initial setup.
414-
/// \param class_id: The given class id
415-
/// \param symbol_table: Used to look up occurrences of static initializers
416-
/// \param [out] needed_lazy_methods: Gets notified of any static initializers
417-
/// that need to be loaded
418-
void ci_lazy_methodst::add_clinit_call(
419-
const irep_idt &class_id,
420-
const symbol_tablet &symbol_table,
421-
ci_lazy_methods_neededt &needed_lazy_methods)
422-
{
423-
const irep_idt &clinit_wrapper = clinit_wrapper_name(class_id);
424-
if(symbol_table.symbols.count(clinit_wrapper))
425-
needed_lazy_methods.add_needed_method(clinit_wrapper);
426395
}
427396

428397
/// Get places where virtual functions are called.

0 commit comments

Comments
 (0)