@@ -106,6 +106,125 @@ static constant_exprt constant_bool(bool val)
106
106
return from_integer (val ? 1 : 0 , java_boolean_type ());
107
107
}
108
108
109
+ static std::unordered_set<irep_idt> init_symbol (
110
+ const symbolt &sym,
111
+ code_blockt &code_block,
112
+ symbol_table_baset &symbol_table,
113
+ const source_locationt &source_location,
114
+ bool assume_init_pointers_not_null,
115
+ const java_object_factory_parameterst &object_factory_parameters,
116
+ const select_pointer_typet &pointer_type_selector,
117
+ bool string_refinement_enabled,
118
+ message_handlert &message_handler)
119
+ {
120
+ std::unordered_set<irep_idt> additional_symbols;
121
+
122
+ if (
123
+ const symbolt *class_literal_init_method =
124
+ get_class_literal_initializer (sym, symbol_table))
125
+ {
126
+ const std::string &name_str = id2string (sym.name );
127
+ irep_idt class_name =
128
+ name_str.substr (0 , name_str.size () - strlen (JAVA_CLASS_MODEL_SUFFIX));
129
+ const symbolt &class_symbol = symbol_table.lookup_ref (class_name);
130
+
131
+ bool class_is_array = is_java_array_tag (sym.name );
132
+
133
+ journalling_symbol_tablet journalling_table =
134
+ journalling_symbol_tablet::wrap (symbol_table);
135
+
136
+ symbol_exprt class_name_literal = get_or_create_string_literal_symbol (
137
+ to_class_type (class_symbol.type ).get_tag (),
138
+ journalling_table,
139
+ string_refinement_enabled);
140
+
141
+ // If that created any new symbols make sure we initialise those too:
142
+ additional_symbols = journalling_table.get_inserted ();
143
+
144
+ // Call the literal initializer method instead of a nondet initializer:
145
+
146
+ // For arguments we can't parse yet:
147
+ side_effect_expr_nondett nondet_bool (java_boolean_type (), sym.location );
148
+
149
+ const auto &java_class_type = to_java_class_type (class_symbol.type );
150
+
151
+ // Argument order is: name, isAnnotation, isArray, isInterface,
152
+ // isSynthetic, isLocalClass, isMemberClass, isEnum
153
+
154
+ code_function_callt initializer_call (
155
+ class_literal_init_method->symbol_expr (),
156
+ {// this:
157
+ address_of_exprt (sym.symbol_expr ()),
158
+ // name:
159
+ address_of_exprt (class_name_literal),
160
+ // isAnnotation:
161
+ constant_bool (java_class_type.get_is_annotation ()),
162
+ // isArray:
163
+ constant_bool (class_is_array),
164
+ // isInterface:
165
+ constant_bool (java_class_type.get_interface ()),
166
+ // isSynthetic:
167
+ constant_bool (java_class_type.get_synthetic ()),
168
+ // isLocalClass:
169
+ nondet_bool,
170
+ // isMemberClass:
171
+ nondet_bool,
172
+ // isEnum:
173
+ constant_bool (java_class_type.get_is_enumeration ())});
174
+
175
+ // First initialize the object as prior to a constructor:
176
+ namespacet ns (symbol_table);
177
+
178
+ auto zero_object = zero_initializer (sym.type , source_locationt (), ns);
179
+ if (!zero_object.has_value ())
180
+ {
181
+ messaget message (message_handler);
182
+ message.error () << " failed to zero-initialize " << sym.name
183
+ << messaget::eom;
184
+ throw 0 ;
185
+ }
186
+ set_class_identifier (
187
+ to_struct_expr (*zero_object), ns, to_struct_tag_type (sym.type ));
188
+
189
+ code_block.add (
190
+ std::move (code_frontend_assignt (sym.symbol_expr (), *zero_object)));
191
+
192
+ // Then call the init function:
193
+ code_block.add (std::move (initializer_call));
194
+ }
195
+ else if (sym.value .is_nil () && sym.type != java_void_type ())
196
+ {
197
+ const bool is_class_model = has_suffix (id2string (sym.name ), " @class_model" );
198
+ const bool not_allow_null = is_java_string_literal_id (sym.name ) ||
199
+ is_non_null_library_global (sym.name ) ||
200
+ assume_init_pointers_not_null;
201
+
202
+ java_object_factory_parameterst parameters = object_factory_parameters;
203
+ if (not_allow_null && !is_class_model)
204
+ parameters.min_null_tree_depth = 1 ;
205
+
206
+ gen_nondet_init (
207
+ sym.symbol_expr (),
208
+ code_block,
209
+ symbol_table,
210
+ source_location,
211
+ false ,
212
+ lifetimet::STATIC_GLOBAL,
213
+ parameters,
214
+ pointer_type_selector,
215
+ update_in_placet::NO_UPDATE_IN_PLACE,
216
+ message_handler);
217
+ }
218
+ else if (sym.value .is_not_nil ())
219
+ {
220
+ code_frontend_assignt assignment (sym.symbol_expr (), sym.value );
221
+ assignment.add_source_location () = source_location;
222
+ code_block.add (assignment);
223
+ }
224
+
225
+ return additional_symbols;
226
+ }
227
+
109
228
void java_static_lifetime_init (
110
229
symbol_table_baset &symbol_table,
111
230
const source_locationt &source_location,
@@ -142,127 +261,40 @@ void java_static_lifetime_init(
142
261
// external. Iterate over a copy of the symtab, as its iterators are
143
262
// invalidated by object_factory:
144
263
145
- std::list<irep_idt> symbol_names;
264
+ // sort alphabetically for reproducible results
265
+ std::set<std::string> symbol_names;
146
266
for (const auto &entry : symbol_table.symbols )
147
- symbol_names.push_back (entry.first );
148
-
149
- // Don't use a for-each loop here because the loop extends the list, and the
150
- // for-each loop may only read `.end()` once.
151
- for (
152
- auto symbol_it = symbol_names.begin ();
153
- symbol_it != symbol_names.end ();
154
- ++symbol_it)
267
+ symbol_names.insert (id2string (entry.first ));
268
+
269
+ std::set<std::string> additional_symbols;
270
+ while (!symbol_names.empty () || !additional_symbols.empty ())
155
271
{
156
- const auto &symname = *symbol_it;
157
- const symbolt &sym = symbol_table.lookup_ref (symname);
158
- if (should_init_symbol (sym))
272
+ if (!additional_symbols.empty ())
273
+ symbol_names.swap (additional_symbols);
274
+
275
+ for (const auto &symbol_name : symbol_names)
159
276
{
160
- if (const symbolt *class_literal_init_method =
161
- get_class_literal_initializer (sym, symbol_table))
162
- {
163
- const std::string &name_str = id2string (sym.name );
164
- irep_idt class_name =
165
- name_str.substr (0 , name_str.size () - strlen (JAVA_CLASS_MODEL_SUFFIX));
166
- const symbolt &class_symbol = symbol_table.lookup_ref (class_name);
167
-
168
- bool class_is_array = is_java_array_tag (sym.name );
169
-
170
- journalling_symbol_tablet journalling_table =
171
- journalling_symbol_tablet::wrap (symbol_table);
172
-
173
- symbol_exprt class_name_literal = get_or_create_string_literal_symbol (
174
- to_class_type (class_symbol.type ).get_tag (),
175
- journalling_table,
176
- string_refinement_enabled);
177
-
178
- // If that created any new symbols make sure we initialise those too:
179
- const auto &new_symbols = journalling_table.get_inserted ();
180
- symbol_names.insert (
181
- symbol_names.end (), new_symbols.begin (), new_symbols.end ());
182
-
183
- // Call the literal initializer method instead of a nondet initializer:
184
-
185
- // For arguments we can't parse yet:
186
- side_effect_expr_nondett nondet_bool (java_boolean_type (), sym.location );
187
-
188
- const auto &java_class_type = to_java_class_type (class_symbol.type );
189
-
190
- // Argument order is: name, isAnnotation, isArray, isInterface,
191
- // isSynthetic, isLocalClass, isMemberClass, isEnum
192
-
193
- code_function_callt initializer_call (
194
- class_literal_init_method->symbol_expr (),
195
- {// this:
196
- address_of_exprt (sym.symbol_expr ()),
197
- // name:
198
- address_of_exprt (class_name_literal),
199
- // isAnnotation:
200
- constant_bool (java_class_type.get_is_annotation ()),
201
- // isArray:
202
- constant_bool (class_is_array),
203
- // isInterface:
204
- constant_bool (java_class_type.get_interface ()),
205
- // isSynthetic:
206
- constant_bool (java_class_type.get_synthetic ()),
207
- // isLocalClass:
208
- nondet_bool,
209
- // isMemberClass:
210
- nondet_bool,
211
- // isEnum:
212
- constant_bool (java_class_type.get_is_enumeration ())});
213
-
214
- // First initialize the object as prior to a constructor:
215
- namespacet ns (symbol_table);
216
-
217
- auto zero_object = zero_initializer (sym.type , source_locationt (), ns);
218
- if (!zero_object.has_value ())
219
- {
220
- messaget message (message_handler);
221
- message.error () << " failed to zero-initialize " << sym.name
222
- << messaget::eom;
223
- throw 0 ;
224
- }
225
- set_class_identifier (
226
- to_struct_expr (*zero_object), ns, to_struct_tag_type (sym.type ));
227
-
228
- code_block.add (
229
- std::move (code_frontend_assignt (sym.symbol_expr (), *zero_object)));
230
-
231
- // Then call the init function:
232
- code_block.add (std::move (initializer_call));
233
- }
234
- else if (sym.value .is_nil () && sym.type != java_void_type ())
277
+ const symbolt &sym = symbol_table.lookup_ref (symbol_name);
278
+ if (should_init_symbol (sym))
235
279
{
236
- const bool is_class_model =
237
- has_suffix (id2string (sym.name ), " @class_model" );
238
- const bool not_allow_null = is_java_string_literal_id (sym.name ) ||
239
- is_non_null_library_global (sym.name ) ||
240
- assume_init_pointers_not_null;
241
-
242
- java_object_factory_parameterst parameters = object_factory_parameters;
243
- if (not_allow_null && !is_class_model)
244
- parameters.min_null_tree_depth = 1 ;
245
-
246
- gen_nondet_init (
247
- sym.symbol_expr (),
280
+ auto new_symbols = init_symbol (
281
+ sym,
248
282
code_block,
249
283
symbol_table,
250
284
source_location,
251
- false ,
252
- lifetimet::STATIC_GLOBAL,
253
- parameters,
285
+ assume_init_pointers_not_null,
286
+ object_factory_parameters,
254
287
pointer_type_selector,
255
- update_in_placet::NO_UPDATE_IN_PLACE ,
288
+ string_refinement_enabled ,
256
289
message_handler);
257
- }
258
- else if (sym.value .is_not_nil ())
259
- {
260
- code_frontend_assignt assignment (sym.symbol_expr (), sym.value );
261
- assignment.add_source_location ()=source_location;
262
- code_block.add (assignment);
290
+ for (const auto &new_symbol_name : new_symbols)
291
+ additional_symbols.insert (id2string (new_symbol_name));
263
292
}
264
293
}
294
+
295
+ symbol_names.clear ();
265
296
}
297
+
266
298
initialize_symbol.value = std::move (code_block);
267
299
}
268
300
0 commit comments