@@ -419,23 +419,23 @@ void local_value_set_analysist::transform_function_stub(
419
419
// avoid unnecessary recalculations
420
420
const auto &rhs_expr = assignment.second ;
421
421
if (!pre_call_rhs_value_sets.count (rhs_expr))
422
- {
423
- value_sett::object_mapt &rhs_values = pre_call_rhs_value_sets[rhs_expr];
424
- if (rhs_expr.id () == ID_external_value_set)
425
422
{
426
- // The RHS expression is an external value set. Expand this to read from
427
- // local objects that match it too.
428
- const auto &evse = to_external_value_set (rhs_expr);
429
- const std::string &evse_label =
430
- id2string (to_constant_expr (evse.label ()).get_value ());
423
+ value_sett::object_mapt &rhs_values = pre_call_rhs_value_sets[rhs_expr];
424
+ if (rhs_expr.id () == ID_external_value_set)
425
+ {
426
+ // The RHS expression is an external value set. Expand this to read from
427
+ // local objects that match it too.
428
+ const auto &evse = to_external_value_set (rhs_expr);
429
+ const std::string &evse_label =
430
+ id2string (to_constant_expr (evse.label ()).get_value ());
431
431
432
432
if (has_prefix (evse_label, PER_FIELD_EVS_PREFIX))
433
433
{
434
434
PRECONDITION (evse.access_path_entries ().size () == 1 );
435
435
436
436
// This external value set denotes either all pointers stored in a
437
437
// particular field (e.g. TypeA.fieldb), or all arrays (in which case
438
- // declared_on_type() is nil the the field name is "[]")
438
+ // declared_on_type() is nil and the field name is "[]")
439
439
std::vector<irep_idt> key_list;
440
440
const auto &apback = evse.access_path_entries ().back ();
441
441
if (!evse.is_initializer ())
@@ -454,33 +454,33 @@ void local_value_set_analysist::transform_function_stub(
454
454
local_value_sett::entryt &entry = valuesets.values .at (key);
455
455
valuesets.make_union_adjusting_types (
456
456
rhs_values, entry.object_map , evse.type (), ns);
457
+ }
458
+ // Also add the external set itself,
459
+ // representing the possibility that the read
460
+ // comes from outside *this* function as well:
461
+ valuesets.insert (rhs_values, evse);
457
462
}
458
- // Also add the external set itself,
459
- // representing the possibility that the read
460
- // comes from outside *this* function as well:
461
- valuesets.insert (rhs_values, evse);
462
- }
463
- else if (has_prefix (evse_label, PRECISE_EVS_PREFIX))
464
- {
465
- // Precise EVS
466
- PRECONDITION (!evse.access_path_entries ().empty ());
467
- exprt precise_access_path_expr =
468
- get_expr_from_precise_evs (evse, function_symbol, fcall, ns, *this );
463
+ else if (has_prefix (evse_label, PRECISE_EVS_PREFIX))
464
+ {
465
+ // Precise EVS
466
+ PRECONDITION (!evse.access_path_entries ().empty ());
467
+ exprt precise_access_path_expr =
468
+ get_expr_from_precise_evs (evse, function_symbol, fcall, ns, *this );
469
469
470
- valuesets.get_value_set (
471
- precise_access_path_expr, rhs_values, ns, false );
472
- }
473
- else
474
- {
475
- // This should be an external value set of type ROOT_OBJECT. It denotes
476
- // the pointers that may be stored in a particular argument or global
477
- // pre-call.
478
- PRECONDITION (evse.access_path_entries ().empty ());
479
- exprt root_object_expr = get_expr_from_root_object_evs (
480
- evse, function_symbol, fcall, ns, *this );
481
-
482
- valuesets.get_value_set (root_object_expr, rhs_values, ns, false );
483
- }
470
+ valuesets.get_value_set (
471
+ precise_access_path_expr, rhs_values, ns, false );
472
+ }
473
+ else
474
+ {
475
+ // This should be an external value set of type ROOT_OBJECT. It denotes
476
+ // the pointers that may be stored in a particular argument or global
477
+ // pre-call.
478
+ PRECONDITION (evse.access_path_entries ().empty ());
479
+ exprt root_object_expr = get_expr_from_root_object_evs (
480
+ evse, function_symbol, fcall, ns, *this );
481
+
482
+ valuesets.get_value_set (root_object_expr, rhs_values, ns, false );
483
+ }
484
484
}
485
485
else
486
486
{
@@ -535,15 +535,14 @@ void local_value_set_analysist::transform_function_stub(
535
535
lhs_fieldname.declared_on_type ,
536
536
lhs_fieldname.structured_lhs );
537
537
irep_idt objkey = evse_entry.get_key (ns);
538
- valuesets.values .insert ( std::make_pair ( objkey, evse_entry) );
539
- key_list.emplace_back ( objkey);
538
+ valuesets.values .emplace ( objkey, evse_entry);
539
+ key_list.push_back ( std::move ( objkey) );
540
540
541
541
// Store the write to `weak_updates`:
542
542
for (const irep_idt &key : key_list)
543
543
{
544
- auto insert_it =
545
- weak_updates.insert (std::make_pair (key, valuesets.values .at (key)));
546
- valuesets.make_union (insert_it.first ->second .object_map , rhs_values);
544
+ auto result = weak_updates.emplace (key, valuesets.values .at (key));
545
+ valuesets.make_union (result.first ->second .object_map , rhs_values);
547
546
}
548
547
}
549
548
else if (has_prefix (lhs_fieldname.base_name , PRECISE_EVS_PREFIX))
@@ -570,8 +569,7 @@ void local_value_set_analysist::transform_function_stub(
570
569
lhs_fieldname.field_name ,
571
570
lhs_fieldname.declared_on_type ,
572
571
lhs_fieldname.structured_lhs );
573
- auto insertit =
574
- weak_updates.insert (std::make_pair (objkey, dynobj_entry_name));
572
+ auto insertit = weak_updates.emplace (objkey, dynobj_entry_name);
575
573
valuesets.make_union (insertit.first ->second .object_map , rhs_values);
576
574
}
577
575
else
@@ -585,19 +583,22 @@ void local_value_set_analysist::transform_function_stub(
585
583
lhs_fieldname.field_name ,
586
584
lhs_fieldname.declared_on_type ,
587
585
lhs_fieldname.structured_lhs );
588
- auto insert_it = weak_updates. insert (
589
- std::make_pair (global_entry.get_key (ns), global_entry) );
586
+ auto result =
587
+ weak_updates. emplace (global_entry.get_key (ns), global_entry);
590
588
591
- valuesets.make_union (insert_it .first ->second .object_map , rhs_values);
589
+ valuesets.make_union (result .first ->second .object_map , rhs_values);
592
590
}
593
591
}
594
592
595
- // Now apply the updates. We have to be careful that parameters might alias,
596
- // so we have to deal with strong updates in a slightly roundabout way. We
597
- // first write an empty object map to expr which got a strong update. If the
598
- // expr is singular then this will erase the object map. Then we write the
599
- // intended object map with `add_to_sets` false, so the write is weak. Then we
600
- // apply the weak updates.
593
+ // Now apply the updates. We can't implement strong updates in the naive way
594
+ // because if two parameters alias and both get strong updates then the first
595
+ // one will get overwritten by the second one, whereas we want to end up with
596
+ // the union of the two (but pre-existing entries in the value set should be
597
+ // cleared).
598
+
599
+ // First go through all expressions that get strong updates and try to do a
600
+ // strong write of an empty object map. If a strong write is possible then
601
+ // this will clear the value set. Otherwise it will do nothing.
601
602
value_sett::object_mapt empty_object_map;
602
603
for (auto &strong_update : strong_updates)
603
604
{
@@ -606,13 +607,16 @@ void local_value_set_analysist::transform_function_stub(
606
607
strong_update.first , empty_object_map, ns, add_to_sets);
607
608
}
608
609
610
+ // Now go through all strong updates doing a weak write of the desired object
611
+ // map
609
612
for (auto &strong_update : strong_updates)
610
613
{
611
614
const bool add_to_sets = true ;
612
615
valuesets.assign_valueset (
613
616
strong_update.first , strong_update.second , ns, add_to_sets);
614
617
}
615
618
619
+ // Finally do all weak updates
616
620
valuesets.make_union (weak_updates);
617
621
}
618
622
0 commit comments