@@ -66,6 +66,8 @@ void local_value_set_analysist::initialize(const goto_programt &fun)
66
66
external_symbols.end ());
67
67
68
68
auto &initial_state=(*this )[fun.instructions .begin ()].value_set ;
69
+ const external_value_set_typet
70
+ default_mode_for_new_evs=external_value_set_typet::ROOT_OBJECT;
69
71
70
72
// Now insert fresh symbols for each external symbol,
71
73
// indicating an unknown external points-to set.
@@ -83,7 +85,7 @@ void local_value_set_analysist::initialize(const goto_programt &fun)
83
85
external_value_set_exprt extsym_var (
84
86
extsym.type ().subtype (),
85
87
constant_exprt (extsym_name, string_typet ()),
86
- external_value_set_typet::ROOT_OBJECT ,
88
+ default_mode_for_new_evs ,
87
89
true );
88
90
initial_state.insert (extsym_entry.object_map , extsym_var);
89
91
}
@@ -129,44 +131,41 @@ void local_value_set_analysist::transform_function_stub(
129
131
const symbolt &function_symbol=ns.lookup (fname);
130
132
const code_function_callt &fcall=to_code_function_call (l_call->code );
131
133
132
- std::shared_ptr<lvsaa_single_external_set_summaryt> call_summary =
133
- summarydb.at (fname);
134
+ const auto &assignments=summarydb.at (fname)->field_assignments ;
134
135
135
136
// The summary gives a list of inclusions, in the form symbol1 <- symbol2,
136
137
// indicating that values reachable before the call from symbol2
137
- // may now be reachable from symbol1. The assignments are simeltaneous .
138
+ // may now be reachable from symbol1. The assignments are simultaneous .
138
139
// Thus start by reading all RHS values, before any changes are made:
139
140
140
141
auto &valuesets=static_cast <domaint&>(state).value_set ;
141
142
std::map<exprt, local_value_sett::object_mapt> pre_call_rhs_value_sets;
142
- const std::string external_objects_basename_prefix =" external_objects" ;
143
+ const std::string per_field_evs_prefix =" external_objects" ;
143
144
144
145
std::set<std::pair<std::string, std::string> > lhs_written;
145
146
146
- for (const auto &assignment : call_summary-> field_assignments )
147
+ for (const auto &assignment : assignments )
147
148
{
148
149
++nstub_assignments;
150
+ const auto &lhs_fieldname=assignment.first ;
149
151
const auto &rhs_expr=assignment.second ;
150
152
if (pre_call_rhs_value_sets.count (rhs_expr))
151
153
continue ;
152
154
auto &rhs_map=pre_call_rhs_value_sets[rhs_expr];
153
- if (assignment. second .id ()==ID_external_value_set)
155
+ if (rhs_expr .id ()==ID_external_value_set)
154
156
{
155
- auto &evse=to_external_value_set (assignment.second );
157
+ const auto &evse=to_external_value_set (rhs_expr);
158
+ const std::string &evse_label=
159
+ id2string (to_constant_expr (evse.label ()).get_value ());
160
+
156
161
// Differentiate external-set entries that only contain
157
162
// their initialiser from ones that have been written:
158
163
if (!evse.is_initializer ())
159
- {
160
- lhs_written.insert ({
161
- assignment.first .base_name ,
162
- assignment.first .field_name });
163
- }
164
- if (has_prefix (
165
- id2string (to_constant_expr (evse.label ()).get_value ()),
166
- " external_objects" ))
164
+ lhs_written.insert ({lhs_fieldname.base_name , lhs_fieldname.field_name });
165
+
166
+ if (has_prefix (evse_label, per_field_evs_prefix))
167
167
{
168
168
std::vector<local_value_sett::entryt*> rhs_entries;
169
- const auto &evse=to_external_value_set (assignment.second );
170
169
PRECONDITION (!evse.access_path_entries ().empty ());
171
170
const auto &apback=evse.access_path_entries ().back ();
172
171
if (!evse.is_initializer ())
@@ -179,20 +178,21 @@ void local_value_set_analysist::transform_function_stub(
179
178
}
180
179
181
180
for (const auto &rhs_entry : rhs_entries)
181
+ {
182
182
valuesets.make_union_adjusting_evs_types (
183
183
rhs_map,
184
184
rhs_entry->object_map ,
185
185
evse.type ());
186
+ }
186
187
// Also add the external set itself,
187
188
// representing the possibility that the read
188
189
// comes from outside *this* function as well:
189
190
valuesets.insert (rhs_map, evse);
190
191
}
191
192
else
192
193
{
193
- // This should be an external value set assigned
194
- // to initialise some global or parameter.
195
- assert (evse.access_path_entries ().empty ());
194
+ // This should be an external value set of type ROOT_OBJECT.
195
+ PRECONDITION (evse.access_path_entries ().empty ());
196
196
const symbolt &inflow_symbol=
197
197
ns.lookup (to_constant_expr (evse.label ()).get_value ());
198
198
exprt inflow_expr;
@@ -222,7 +222,7 @@ void local_value_set_analysist::transform_function_stub(
222
222
<< to_constant_expr (evse.label ()).get_value ()
223
223
<< eom;
224
224
}
225
- assert (paramidx!=(size_t )-1 && " Unknown parameter symbol?" );
225
+ INVARIANT (paramidx!=(size_t )-1 , " Unknown parameter symbol?" );
226
226
inflow_expr=fcall.arguments ()[paramidx];
227
227
}
228
228
pointer_typet expect_type=pointer_type (evse.type ());
@@ -234,49 +234,48 @@ void local_value_set_analysist::transform_function_stub(
234
234
else
235
235
{
236
236
// Ordinary value set member; just add to the RHS map.
237
- valuesets.insert (rhs_map, assignment.second );
238
- lhs_written.insert ({
239
- assignment.first .base_name ,
240
- assignment.first .field_name });
237
+ valuesets.insert (rhs_map, rhs_expr);
238
+ lhs_written.insert ({lhs_fieldname.base_name , lhs_fieldname.field_name });
241
239
}
242
240
}
243
241
244
242
// OK, read all the RHS sets, now assign to the LHS symbols:
245
243
246
- for (const auto &assignment : call_summary-> field_assignments )
244
+ for (const auto &assignment : assignments )
247
245
{
246
+ const auto &lhs_fieldname=assignment.first ;
248
247
const auto &rhs_values=pre_call_rhs_value_sets.at (assignment.second );
249
248
250
- if (has_prefix (assignment. first . base_name , external_objects_basename_prefix ))
249
+ if (has_prefix (lhs_fieldname. base_name , per_field_evs_prefix ))
251
250
{
252
251
std::vector<local_value_sett::entryt*> lhs_entries;
253
252
const auto find_pair=std::make_pair (
254
- assignment. first .base_name ,
255
- assignment. first .field_name );
253
+ lhs_fieldname .base_name ,
254
+ lhs_fieldname .field_name );
256
255
if (lhs_written.count (find_pair))
257
256
get_all_field_value_sets (
258
- assignment. first .field_name ,
259
- assignment. first .declared_on_type ,
257
+ lhs_fieldname .field_name ,
258
+ lhs_fieldname .declared_on_type ,
260
259
valuesets,
261
260
lhs_entries);
262
261
// Also write to the external value set itself:
263
262
local_value_sett::entryt evse_entry (
264
- assignment. first .base_name ,
265
- assignment. first .field_name ,
266
- assignment. first .declared_on_type );
267
- std::string objkey=assignment. first . base_name +assignment. first .field_name ;
263
+ lhs_fieldname .base_name ,
264
+ lhs_fieldname .field_name ,
265
+ lhs_fieldname .declared_on_type );
266
+ std::string objkey=lhs_fieldname. base_name +lhs_fieldname .field_name ;
268
267
auto insertit=valuesets.values .insert (std::make_pair (objkey, evse_entry));
269
268
lhs_entries.push_back (&insertit.first ->second );
270
269
for (auto lhs_entry : lhs_entries)
271
270
valuesets.make_union (lhs_entry->object_map , rhs_values);
272
271
}
273
- else if (has_prefix (assignment. first .base_name , prefix_dynamic_object))
272
+ else if (has_prefix (lhs_fieldname .base_name , prefix_dynamic_object))
274
273
{
275
- std::string objkey=assignment. first . base_name +assignment. first .field_name ;
274
+ std::string objkey=lhs_fieldname. base_name +lhs_fieldname .field_name ;
276
275
local_value_sett::entryt dynobj_entry_name (
277
- assignment. first .base_name ,
278
- assignment. first .field_name ,
279
- assignment. first .declared_on_type );
276
+ lhs_fieldname .base_name ,
277
+ lhs_fieldname .field_name ,
278
+ lhs_fieldname .declared_on_type );
280
279
auto insertit=
281
280
valuesets.values .insert (std::make_pair (objkey, dynobj_entry_name));
282
281
valuesets.make_union (insertit.first ->second .object_map , rhs_values);
@@ -285,12 +284,14 @@ void local_value_set_analysist::transform_function_stub(
285
284
{
286
285
// The only other kind of symbols mentioned
287
286
// in summary LHS are global variables.
288
- assert (assignment.first .field_name ==" " );
289
- const auto &global_sym=ns.lookup (assignment.first .base_name );
287
+ INVARIANT (
288
+ lhs_fieldname.field_name ==" " ,
289
+ " unexpected lhs entry in call summary assignments" );
290
+ const auto &global_sym=ns.lookup (lhs_fieldname.base_name );
290
291
local_value_sett::entryt global_entry_name (
291
- assignment. first .base_name ,
292
+ lhs_fieldname .base_name ,
292
293
" " ,
293
- assignment. first .declared_on_type );
294
+ lhs_fieldname .declared_on_type );
294
295
auto &global_entry=
295
296
valuesets.get_entry (global_entry_name, global_sym.type , ns);
296
297
valuesets.make_union (global_entry.object_map , rhs_values);
@@ -409,17 +410,20 @@ void lvsaa_single_external_set_summaryt::from_final_state(
409
410
// by this function, and the values they may be assigned.
410
411
411
412
std::vector<local_value_sett::valuest::const_iterator> to_export;
413
+ const std::string per_field_evs_prefix=" external_objects" ;
412
414
413
- for (auto it=final_state.values .begin (), itend=final_state. values . end () ;
414
- it!=itend ;
415
+ for (auto it=final_state.values .begin ();
416
+ it!=final_state. values . end () ;
415
417
++it)
416
418
{
417
419
const auto &entry=*it;
418
- const std::string prefix= " external_objects " ;
420
+
419
421
const std::string entryname=id2string (entry.first );
420
422
bool export_this_entry=false ;
421
- if (has_prefix (entryname, prefix))
423
+ if (has_prefix (entryname, per_field_evs_prefix))
424
+ {
422
425
export_this_entry=true ;
426
+ }
423
427
if ((!export_this_entry) &&
424
428
has_prefix (entryname, prefix_dynamic_object))
425
429
{
@@ -482,7 +486,7 @@ void lvsaa_single_external_set_summaryt::from_final_state(
482
486
id2string (entry.second.identifier),
483
487
entry.second.suffix,
484
488
entry.second.declared_on_type);
485
- field_assignments.push_back(std::make_pair( thisname, *toexport) );
489
+ field_assignments.emplace_back( thisname, *toexport);
486
490
}
487
491
}
488
492
}
0 commit comments