Skip to content

Commit bb66937

Browse files
authored
Merge pull request #1176 from smowton/smowton/fix/restore_object_factory_recursion_set
Object factory: remove type from recursion set on leaving scope
2 parents bcbb6fa + 7121d4c commit bb66937

File tree

9 files changed

+118
-1
lines changed

9 files changed

+118
-1
lines changed
199 Bytes
Binary file not shown.
570 Bytes
Binary file not shown.
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
CORE
2+
test.class
3+
--function test.main
4+
^EXIT=10$
5+
^SIGNAL=0$
6+
VERIFICATION FAILED
7+
assertion at file test\.java line 10 .* FAILURE
8+
--
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
2+
public class test {
3+
4+
public Other o1;
5+
public Other o2;
6+
7+
public void main() {
8+
if(o1 == null || o2 == null)
9+
return;
10+
assert(false);
11+
}
12+
13+
}
14+
15+
class Other {
16+
int x;
17+
}
224 Bytes
Binary file not shown.
820 Bytes
Binary file not shown.
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
CORE
2+
test.class
3+
--function test.main
4+
^EXIT=10$
5+
^SIGNAL=0$
6+
VERIFICATION FAILED
7+
assertion at file test.java line 23 function java::test\.toplevel_pointers_not_null.*: FAILURE
8+
assertion at file test.java line 18 function java::test\.next_pointers_not_null.*: SUCCESS
9+
--
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
2+
public class test {
3+
4+
public Other o1;
5+
public Other o2;
6+
7+
public void main() {
8+
if(o1 != null && o2 != null) {
9+
if(o1.next != null && o2.next != null) {
10+
next_pointers_not_null();
11+
}
12+
toplevel_pointers_not_null();
13+
}
14+
}
15+
16+
public void next_pointers_not_null() {
17+
// Not currently achievable due to recursive types
18+
assert(false);
19+
}
20+
21+
public void toplevel_pointers_not_null() {
22+
// Should be possible to hit
23+
assert(false);
24+
}
25+
26+
}
27+
28+
class Other {
29+
int x;
30+
Other next;
31+
}

src/java_bytecode/java_object_factory.cpp

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -389,6 +389,54 @@ void java_object_factoryt::gen_pointer_target_init(
389389
}
390390
}
391391

392+
/// Recursion-set entry owner class. If a recursion-set entry is added
393+
/// in a particular scope, ensures that it is erased on leaving
394+
/// that scope.
395+
class recursion_set_entryt
396+
{
397+
/// Recursion set to modify
398+
std::unordered_set<irep_idt, irep_id_hash> &recursion_set;
399+
/// Entry to erase on destruction, if non-empty
400+
irep_idt erase_entry;
401+
402+
public:
403+
/// Initialise a recursion-set entry owner operating on a given set.
404+
/// Initially it does not own any set entry.
405+
/// \param _recursion_set: set to operate on.
406+
recursion_set_entryt(std::unordered_set<irep_idt, irep_id_hash> &_recursion_set):
407+
recursion_set(_recursion_set)
408+
{ }
409+
410+
/// Removes erase_entry (if set) from the controlled set.
411+
~recursion_set_entryt()
412+
{
413+
if(erase_entry!=irep_idt())
414+
recursion_set.erase(erase_entry);
415+
}
416+
417+
recursion_set_entryt(const recursion_set_entryt &)=delete;
418+
recursion_set_entryt &operator=(const recursion_set_entryt &)=delete;
419+
420+
/// Try to add an entry to the controlled set. If it is added, own that
421+
/// entry and erase it on destruction; otherwise do nothing.
422+
/// \param entry: entry to add
423+
/// \return true if added to the set (and therefore owned by this object)
424+
bool insert_entry(const irep_idt &entry)
425+
{
426+
INVARIANT(
427+
erase_entry==irep_idt(),
428+
"insert_entry should only be called once");
429+
INVARIANT(entry!=irep_idt(), "entry should be a struct tag");
430+
bool ret=recursion_set.insert(entry).second;
431+
if(ret)
432+
{
433+
// We added something, so erase it when this is destroyed:
434+
erase_entry=entry;
435+
}
436+
return ret;
437+
}
438+
};
439+
392440
/// Initialises a primitive or object tree rooted at `expr`, of type pointer. It
393441
/// allocates child objects as necessary and nondet-initialising their members,
394442
/// or if MUST_UPDATE_IN_PLACE is set, re-initialising already-allocated
@@ -431,14 +479,18 @@ void java_object_factoryt::gen_nondet_pointer_init(
431479
return;
432480
}
433481

482+
// This deletes the recursion set entry on leaving this function scope,
483+
// if one is set below.
484+
recursion_set_entryt recursion_set_entry(recursion_set);
485+
434486
const typet &subtype=ns.follow(pointer_type.subtype());
435487
if(subtype.id()==ID_struct)
436488
{
437489
const struct_typet &struct_type=to_struct_type(subtype);
438490
const irep_idt &struct_tag=struct_type.get_tag();
439491

440492
// If this is a recursive type of some kind, set null.
441-
if(!recursion_set.insert(struct_tag).second)
493+
if(!recursion_set_entry.insert_entry(struct_tag))
442494
{
443495
if(update_in_place==update_in_placet::NO_UPDATE_IN_PLACE)
444496
{

0 commit comments

Comments
 (0)