@@ -148,6 +148,11 @@ class java_object_factoryt
148
148
const pointer_typet &substitute_pointer_type,
149
149
size_t depth,
150
150
const source_locationt &location);
151
+
152
+ void gen_method_call_if_present (
153
+ code_blockt &assignments,
154
+ const exprt &instance_expr,
155
+ const irep_idt &method_name);
151
156
};
152
157
153
158
// / Generates code for allocating a dynamic object. This is used in
@@ -764,6 +769,24 @@ void java_object_factoryt::gen_nondet_pointer_init(
764
769
}
765
770
}
766
771
772
+ // If this is a void* we *must* initialise with null:
773
+ // (This can currently happen for some cases of #exception_value)
774
+ bool must_be_null = subtype == empty_typet ();
775
+
776
+ // If we may be about to initialize a non-null object, always run the
777
+ // clinit_wrapper of its class first.
778
+ // Note that it would be more consistent with the behaviour of the JVM to only
779
+ // run clinit_wrapper if we are about to initialize an object of which we know
780
+ // for sure that it is not null on any following branch. However, adding this
781
+ // case in gen_nondet_struct_init would slow symex down too much.
782
+ if (!must_be_null)
783
+ {
784
+ const java_class_typet &class_type = to_java_class_type (subtype);
785
+ const irep_idt &class_name = class_type.get_name ();
786
+ const irep_idt class_clinit = clinit_wrapper_name (class_name);
787
+ gen_method_call_if_present (assignments, expr, class_clinit);
788
+ }
789
+
767
790
code_blockt new_object_assignments;
768
791
code_blockt update_in_place_assignments;
769
792
@@ -810,10 +833,6 @@ void java_object_factoryt::gen_nondet_pointer_init(
810
833
const bool allow_null =
811
834
depth > object_factory_parameters.max_nonnull_tree_depth ;
812
835
813
- // Alternatively, if this is a void* we *must* initialise with null:
814
- // (This can currently happen for some cases of #exception_value)
815
- bool must_be_null = subtype == empty_typet ();
816
-
817
836
if (must_be_null)
818
837
{
819
838
// Add the following code to assignments:
@@ -1081,17 +1100,7 @@ void java_object_factoryt::gen_nondet_struct_init(
1081
1100
1082
1101
const irep_idt init_method_name =
1083
1102
" java::" + id2string (struct_tag) + " .cproverNondetInitialize:()V" ;
1084
-
1085
- if (const auto func = symbol_table.lookup (init_method_name))
1086
- {
1087
- const code_typet &type = to_code_type (func->type );
1088
- code_function_callt fun_call;
1089
- fun_call.function () = func->symbol_expr ();
1090
- if (type.has_this ())
1091
- fun_call.arguments ().push_back (address_of_exprt (expr));
1092
-
1093
- assignments.add (fun_call);
1094
- }
1103
+ gen_method_call_if_present (assignments, expr, init_method_name);
1095
1104
}
1096
1105
1097
1106
// / Initializes a primitive-typed or reference-typed object tree rooted at
@@ -1619,3 +1628,25 @@ void gen_nondet_init(
1619
1628
pointer_type_selector,
1620
1629
update_in_place);
1621
1630
}
1631
+
1632
+ // / Adds a call for the given method to the end of `assignments` if the method
1633
+ // / exists in the symbol table. Does nothing if the method does not exist.
1634
+ // / \param assignments: A code block that the method call will be appended to.
1635
+ // / \param instance_expr: The instance to call the method on. This argument is
1636
+ // / ignored if the method is static.
1637
+ // / \param method_name: The name of the method to be called.
1638
+ void java_object_factoryt::gen_method_call_if_present (
1639
+ code_blockt &assignments,
1640
+ const exprt &instance_expr,
1641
+ const irep_idt &method_name)
1642
+ {
1643
+ if (const auto func = symbol_table.lookup (method_name))
1644
+ {
1645
+ const code_typet &type = to_code_type (func->type );
1646
+ code_function_callt fun_call;
1647
+ fun_call.function () = func->symbol_expr ();
1648
+ if (type.has_this ())
1649
+ fun_call.arguments ().push_back (address_of_exprt (instance_expr));
1650
+ assignments.add (fun_call);
1651
+ }
1652
+ }
0 commit comments