Skip to content

Commit aea7a32

Browse files
author
owen-jones-diffblue
authored
Merge pull request diffblue#316 from diffblue/owen-jones-diffblue/pull-out-recency-demotion-to-avoid-duplication
Remove duplicated code to demote most recent DOs
2 parents 69dac0f + 3c27084 commit aea7a32

File tree

4 files changed

+89
-147
lines changed

4 files changed

+89
-147
lines changed

regression/LVSA/recent_alloc_clear_from_callees/test_recent_alloc_clear_from_callees.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,6 @@ def test_should_not_be_most_recent_caller_1(tmpdir):
168168
value_set_expectation.check_contains_dynamic_object(1, False)
169169

170170

171-
@pytest.mark.xfail(strict=True)
172171
def test_should_not_be_most_recent_caller_2(tmpdir):
173172
"""
174173
[13] Checks whether 'is_most_recent_allocation' flag is cleared when

src/pointer-analysis/local_value_set.cpp

Lines changed: 80 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -338,92 +338,99 @@ void local_value_sett::apply_assign_side_effects(
338338
const exprt &rhs,
339339
const namespacet &ns)
340340
{
341-
if(rhs.id()==ID_side_effect &&
342-
rhs.get(ID_statement)==ID_allocate)
341+
if(rhs.id() == ID_side_effect && rhs.get(ID_statement) == ID_allocate)
342+
demote_most_recent_dynamic_objects(location_number);
343+
}
344+
345+
void local_value_sett::demote_most_recent_dynamic_objects(
346+
const unsigned loc_number)
347+
{
348+
// Replace all the current most-recent-allocation dynamic-objects
349+
// with the corresponding any-allocation ones
350+
for(auto &value : values)
343351
{
344-
const typet &dynamic_type=
345-
static_cast<const typet &>(rhs.find(ID_C_cxx_alloc_type));
352+
entryt &entry = value.second;
353+
object_map_dt &object_map = entry.object_map.write();
346354

347-
// Replace all the current most-recent-allocation dynamic-objects
348-
// with the corresponding any-allocation ones
349-
for(auto &value : values)
350-
{
351-
entryt &entry=value.second;
352-
object_map_dt &object_map=entry.object_map.write();
353-
354-
// Look-up for the first appearance of the current
355-
// most-recent dynamic-object in the current object-map
356-
object_map_dt::iterator it=boost::range::find_if(
357-
object_map,
358-
[this] (const object_map_dt::value_type &object)
359-
{
360-
const exprt &o=object_numbering[object.first];
361-
if(o.id()!=ID_dynamic_object)
362-
return false;
355+
// Look-up for the first appearance of the current
356+
// most-recent dynamic-object in the current object-map
357+
object_map_dt::iterator it = boost::range::find_if(
358+
object_map, [this, loc_number](const object_map_dt::value_type &object) {
359+
const exprt &o = object_numbering[object.first];
360+
if(o.id() != ID_dynamic_object)
361+
return false;
363362

364-
const dynamic_object_exprt &dynamic_object=to_dynamic_object_expr(o);
363+
const dynamic_object_exprt &dynamic_object = to_dynamic_object_expr(o);
365364

366-
return dynamic_object.get_instance()==location_number &&
367-
dynamic_object.get_recency()==
368-
dynamic_object_exprt::recencyt::MOST_RECENT_ALLOCATION;
369-
});
365+
return dynamic_object.get_instance() == loc_number &&
366+
dynamic_object.get_recency() ==
367+
dynamic_object_exprt::recencyt::MOST_RECENT_ALLOCATION;
368+
});
370369

371-
if(it==object_map.end())
372-
continue;
370+
if(it == object_map.end())
371+
continue;
373372

374-
// Delete the most-recent dynamic-object from the current object_map
375-
object_map.erase(it);
373+
// Delete the most-recent dynamic-object from the current object_map
374+
object_map.erase(it);
376375

377-
int index_dynamic_object_recent=it->first;
376+
const int index_dynamic_object_recent = it->first;
378377

379-
// Create the any-allocation dynamic-object
380-
// by copying the existing most-recent one and adjusting the recency flag
381-
dynamic_object_exprt dynamic_object_any_allocation=
382-
to_dynamic_object_expr(object_numbering[index_dynamic_object_recent]);
383-
dynamic_object_any_allocation.set_recency(false);
378+
// Create the any-allocation dynamic-object
379+
// by copying the existing most-recent one and adjusting the recency flag
380+
dynamic_object_exprt dynamic_object_any_allocation =
381+
to_dynamic_object_expr(object_numbering[index_dynamic_object_recent]);
382+
dynamic_object_any_allocation.set_recency(false);
384383

385-
// Add the newly created any-allocation dynamic-object
386-
// in the current rhs' object_map
387-
insert(entry.object_map, dynamic_object_any_allocation, 0);
388-
}
384+
// Add the newly created any-allocation dynamic-object
385+
// in the current rhs' object_map
386+
insert(entry.object_map, dynamic_object_any_allocation, 0);
387+
}
389388

390-
const std::string name_most_recent=
391-
prefix_dynamic_object+
392-
std::to_string(location_number)+
393-
id2string(ID_most_recent_allocation);
394-
const std::string name_any_allocation=
395-
prefix_dynamic_object+
396-
std::to_string(location_number)+
397-
id2string(ID_any_allocation);
398-
399-
// Iterates over the domain's entries and when we find the current
400-
// most-recent-allocation dynamic-object, add its object-map
401-
// to its correspondent any-allocation dynamic-object's object-map
402-
for(auto &value : values)
403-
{
404-
entryt &entry=value.second;
389+
const std::string name_most_recent = prefix_dynamic_object +
390+
std::to_string(loc_number) +
391+
id2string(ID_most_recent_allocation);
392+
const std::string name_any_allocation = prefix_dynamic_object +
393+
std::to_string(loc_number) +
394+
id2string(ID_any_allocation);
395+
396+
// Iterates over the domain's entries and when we find the current
397+
// most-recent-allocation dynamic-object, add its object-map to the
398+
// corresponding any-allocation dynamic-object's object-map and remove it
399+
// from the domain
400+
std::vector<valuest::iterator> to_remove;
401+
for(auto it = values.begin(); it != values.end(); ++it)
402+
{
403+
auto &value = *it;
404+
entryt &entry = value.second;
405405

406-
if(entry.identifier==name_most_recent)
407-
{
408-
DATA_INVARIANT(
409-
can_cast_expr<dynamic_object_exprt>(entry.structured_lhs),
410-
"If identifier of entryt begins with dynamic object prefix then its "
411-
"structured_lhs should be castable to a dynamic_object_exprt");
412-
dynamic_object_exprt expr_any_allocation =
413-
to_dynamic_object_expr(entry.structured_lhs);
414-
expr_any_allocation.set_recency(false);
415-
416-
entryt &entry_any_allocation = get_entry(
417-
entryt(name_any_allocation, entry.suffix, expr_any_allocation),
418-
dynamic_type,
419-
ns);
420-
421-
// Add into the any-allocation dynamic-object's object_map
422-
// the most-recent-allocation dynamic-object's object_map
423-
make_union(entry_any_allocation.object_map, entry.object_map);
424-
}
406+
if(entry.identifier == name_most_recent)
407+
{
408+
DATA_INVARIANT(
409+
can_cast_expr<dynamic_object_exprt>(entry.structured_lhs),
410+
"If identifier of entryt begins with dynamic object prefix then its "
411+
"structured_lhs should be castable to a dynamic_object_exprt");
412+
dynamic_object_exprt expr_any_allocation =
413+
to_dynamic_object_expr(entry.structured_lhs);
414+
expr_any_allocation.set_recency(false);
415+
416+
/// The second and third arguments to get_entry() are only used for
417+
/// field_sensitive(), and that will always returns true without using
418+
/// them because name_any_allocation starts with the prefix for a
419+
/// dynamic object, so we can use an empty type and namespace.
420+
entryt &entry_any_allocation = get_entry(
421+
entryt(name_any_allocation, entry.suffix, expr_any_allocation),
422+
nil_typet(),
423+
namespacet(symbol_tablet()));
424+
425+
// Add into the any-allocation dynamic-object's object_map
426+
// the most-recent-allocation dynamic-object's object_map
427+
make_union(entry_any_allocation.object_map, entry.object_map);
428+
to_remove.push_back(it);
425429
}
426430
}
431+
432+
for(auto it : to_remove)
433+
values.erase(it);
427434
}
428435

429436
void local_value_sett::demote_initializers(object_mapt &values_rhs) const

src/pointer-analysis/local_value_set.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,12 @@ class local_value_sett:public value_sett
139139
const exprt &lhs,
140140
const exprt &rhs,
141141
const namespacet &ns) override;
142+
143+
/// Replace most recent dynamic objects allocated at a given location with
144+
/// any allocation dynamic objects allocated at the given location.
145+
/// \param loc_number: the location number for the dynamic objects we are
146+
/// looking for
147+
void demote_most_recent_dynamic_objects(const unsigned loc_number);
142148
};
143149

144150
#endif

src/pointer-analysis/local_value_set_analysis.cpp

Lines changed: 3 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -339,79 +339,9 @@ void local_value_set_analysist::transform_function_stub(
339339
const auto rhs_num=valuesets.object_numbering.get_number(rhs_expr);
340340
if(can_cast_expr<dynamic_object_exprt>(rhs_expr) && rhs_num)
341341
{
342-
// Replace all the current most-recent-allocation dynamic-objects
343-
// with the corresponding any-allocation ones
344-
for(auto &value : valuesets.values)
345-
{
346-
local_value_sett::entryt &entry=value.second;
347-
local_value_sett::object_map_dt &object_map=entry.object_map.write();
348-
349-
// Look-up for the first appearance of the current
350-
// most-recent dynamic-object in the current object-map
351-
const auto it=object_map.find(*rhs_num);
352-
if(it==object_map.end())
353-
continue;
354-
355-
const int index_dynamic_object_recent=it->first;
356-
357-
// Delete the most-recent dynamic-object from the current object_map
358-
object_map.erase(it);
359-
360-
// Create the any-allocation dynamic-object by copying
361-
// the existing most-recent one and adjusting the recency flag
362-
dynamic_object_exprt dynamic_object_any_allocation=
363-
to_dynamic_object_expr(
364-
valuesets.object_numbering[index_dynamic_object_recent]);
365-
dynamic_object_any_allocation.set_recency(false);
366-
367-
// Add the newly created any-allocation dynamic-object
368-
// in the current rhs' object_map
369-
valuesets.insert(entry.object_map, dynamic_object_any_allocation, 0);
370-
}
371-
372-
const std::string name_most_recent=
373-
prefix_dynamic_object+
374-
std::to_string(
375-
expr_try_dynamic_cast<dynamic_object_exprt>(rhs_expr)
376-
->get_instance())+
377-
id2string(ID_most_recent_allocation);
378-
const std::string name_any_allocation=
379-
prefix_dynamic_object+
380-
std::to_string(
381-
expr_try_dynamic_cast<dynamic_object_exprt>(rhs_expr)
382-
->get_instance())+
383-
id2string(ID_any_allocation);
384-
const typet &dynamic_type=
385-
static_cast<const typet &>(rhs_expr.find(ID_C_cxx_alloc_type));
386-
387-
std::vector<local_value_sett::valuest::iterator> to_remove;
388-
for(auto it=valuesets.values.begin(); it!=valuesets.values.end(); ++it)
389-
{
390-
auto &value=*it;
391-
local_value_sett::entryt &entry=value.second;
392-
393-
if(entry.identifier==name_most_recent)
394-
{
395-
DATA_INVARIANT(
396-
can_cast_expr<dynamic_object_exprt>(entry.structured_lhs),
397-
"If identifier of entryt begins with dynamic object prefix then "
398-
"its structured_lhs should be castable to a "
399-
"dynamic_object_exprt");
400-
dynamic_object_exprt expr_any_allocation =
401-
to_dynamic_object_expr(entry.structured_lhs);
402-
expr_any_allocation.set_recency(false);
403-
local_value_sett::entryt &entry_any_allocation =
404-
valuesets.get_entry(
405-
local_value_sett::entryt(
406-
name_any_allocation, entry.suffix, expr_any_allocation),
407-
dynamic_type,
408-
ns);
409-
valuesets.make_union(entry_any_allocation.object_map, entry.object_map);
410-
to_remove.push_back(it);
411-
}
412-
}
413-
for(auto it : to_remove)
414-
valuesets.values.erase(it);
342+
unsigned loc_number =
343+
expr_try_dynamic_cast<dynamic_object_exprt>(rhs_expr)->get_instance();
344+
valuesets.demote_most_recent_dynamic_objects(loc_number);
415345
}
416346

417347
valuesets.insert(rhs_map, rhs_expr);

0 commit comments

Comments
 (0)