Skip to content

Commit 8a60dfd

Browse files
committed
L1 renaming at each declaration
This was done up until c8f0f7b. The (observable) problem tackled here is that objects declared in loops got the same L1 name, which implies they had the same address. Thus objects were spuriously reported as dead when their address was taken, because a pointer to the latest (live) object would be the same as one to an earlier (genuinely dead) object. A problem not yet fully fixed is regression/cbmc/vla3, which still fails despite the work here.
1 parent 1ab989f commit 8a60dfd

File tree

9 files changed

+88
-66
lines changed

9 files changed

+88
-66
lines changed
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
int g;
2+
3+
int main()
4+
{
5+
for(int i = 0; i < 4; ++i)
6+
{
7+
int *x;
8+
*&x = &g;
9+
}
10+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
CORE
2+
main.c
3+
--pointer-check
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
^VERIFICATION SUCCESSFUL$
7+
--
8+
^warning: ignoring

src/goto-programs/goto_clean_expr.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,8 @@ symbol_exprt goto_convertt::make_compound_literal(
4545

4646
// The lifetime of compound literals is really that of
4747
// the block they are in.
48-
copy(code_declt(result), DECL, dest);
48+
if(!new_symbol.is_static_lifetime)
49+
copy(code_declt(result), DECL, dest);
4950

5051
code_assignt code_assign(result, expr);
5152
code_assign.add_source_location()=source_location;

src/goto-symex/goto_symex_state.cpp

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -785,3 +785,34 @@ void goto_symex_statet::output_propagation_map(std::ostream &out)
785785
out << name_value.first << " <- " << format(name_value.second) << "\n";
786786
}
787787
}
788+
789+
void goto_symex_statet::add_object(
790+
ssa_exprt &ssa,
791+
std::size_t l1_index,
792+
const namespacet &ns)
793+
{
794+
framet &frame = top();
795+
796+
const irep_idt l0_name = ssa.get_identifier();
797+
798+
// save old L1 name, if any
799+
auto c_it = level1.current_names.find(l0_name);
800+
801+
if(c_it != level1.current_names.end())
802+
{
803+
frame.old_level1.emplace(l0_name, c_it->second);
804+
c_it->second = std::make_pair(ssa, l1_index);
805+
}
806+
else
807+
{
808+
c_it = level1.current_names.emplace(l0_name, std::make_pair(ssa, l1_index))
809+
.first;
810+
}
811+
812+
rename(ssa, ns, goto_symex_statet::L1);
813+
const irep_idt &l1_name = ssa.get_identifier();
814+
815+
// unique -- store
816+
if(!frame.local_objects.insert(l1_name).second)
817+
PRECONDITION(false);
818+
}

src/goto-symex/goto_symex_state.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,9 +58,6 @@ class goto_symex_statet final
5858
symex_targett::sourcet source;
5959
symex_target_equationt *symex_target;
6060

61-
// we remember all L1 renamings
62-
std::set<irep_idt> l1_history;
63-
6461
symex_level0t level0;
6562
symex_level1t level1;
6663
symex_level2t level2;
@@ -239,6 +236,10 @@ class goto_symex_statet final
239236

240237
const framet &previous_frame() { return *(--(--call_stack().end())); }
241238

239+
/// Turn L0-renamed \p ssa into an L1-renamed SSA expression with an L1 index
240+
/// \p l1_index that must not have previously been used.
241+
void add_object(ssa_exprt &ssa, std::size_t l1_index, const namespacet &ns);
242+
242243
void print_backtrace(std::ostream &) const;
243244

244245
// threads

src/goto-symex/path_storage.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,11 +85,24 @@ class path_storaget
8585
return size() == 0;
8686
};
8787

88+
/// Provide a unique index for a given \p id, starting from \p minimum_index.
89+
std::size_t get_unique_index(const irep_idt &id, std::size_t minimum_index)
90+
{
91+
auto entry = unique_index_map.emplace(id, minimum_index);
92+
93+
if(!entry.second)
94+
entry.first->second = std::max(entry.first->second + 1, minimum_index);
95+
96+
return entry.first->second;
97+
}
98+
8899
private:
89100
// Derived classes should override these methods, allowing the base class to
90101
// enforce preconditions.
91102
virtual patht &private_peek() = 0;
92103
virtual void private_pop() = 0;
104+
105+
std::unordered_map<irep_idt, std::size_t> unique_index_map;
93106
};
94107

95108
/// \brief LIFO save queue: depth-first search, try to finish paths

src/goto-symex/symex_decl.cpp

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,14 @@ void goto_symext::symex_decl(statet &state)
3434

3535
void goto_symext::symex_decl(statet &state, const symbol_exprt &expr)
3636
{
37-
// We increase the L2 renaming to make these non-deterministic.
38-
// We also prevent propagation of old values.
37+
// each declaration introduces a new object, which we record as a fresh L1
38+
// index
3939

4040
ssa_exprt ssa(expr);
41-
state.rename(ssa, ns, goto_symex_statet::L1);
41+
state.rename(ssa, ns, goto_symex_statet::L0);
42+
const std::size_t fresh_l1_index =
43+
path_storage.get_unique_index(ssa.get_identifier(), 1);
44+
state.add_object(ssa, fresh_l1_index, ns);
4245
const irep_idt &l1_identifier=ssa.get_identifier();
4346

4447
// rename type to L2
@@ -62,16 +65,11 @@ void goto_symext::symex_decl(statet &state, const symbol_exprt &expr)
6265
state.value_set.assign(ssa, rhs, ns, true, false);
6366
}
6467

65-
// prevent propagation
66-
state.propagation.erase(l1_identifier);
67-
6868
// L2 renaming
69-
// inlining may yield multiple declarations of the same identifier
70-
// within the same L1 context
71-
const auto level2_it =
72-
state.level2.current_names.emplace(l1_identifier, std::make_pair(ssa, 0))
73-
.first;
74-
symex_renaming_levelt::increase_counter(level2_it);
69+
bool is_new =
70+
state.level2.current_names.emplace(l1_identifier, std::make_pair(ssa, 1))
71+
.second;
72+
CHECK_RETURN(is_new);
7573
const bool record_events=state.record_events;
7674
state.record_events=false;
7775
state.rename(ssa, ns);

src/goto-symex/symex_function_call.cpp

Lines changed: 7 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -376,8 +376,8 @@ void goto_symext::symex_end_of_function(statet &state)
376376
pop_frame(state);
377377
}
378378

379-
/// preserves locality of local variables of a given function by applying L1
380-
/// renaming to the local identifiers
379+
/// preserves locality of parameters of a given function by applying L1
380+
/// renaming to them
381381
void goto_symext::locality(
382382
const irep_idt &function_identifier,
383383
statet &state,
@@ -387,57 +387,15 @@ void goto_symext::locality(
387387
state.threads[state.source.thread_nr].function_frame[function_identifier];
388388
frame_nr++;
389389

390-
std::set<irep_idt> local_identifiers;
391-
392-
get_local_identifiers(goto_function, local_identifiers);
393-
394-
statet::framet &frame=state.top();
395-
396-
for(std::set<irep_idt>::const_iterator
397-
it=local_identifiers.begin();
398-
it!=local_identifiers.end();
399-
it++)
390+
for(const auto &param : goto_function.type.parameters())
400391
{
401392
// get L0 name
402-
ssa_exprt ssa(ns.lookup(*it).symbol_expr());
393+
ssa_exprt ssa(ns.lookup(param.get_identifier()).symbol_expr());
403394
state.rename(ssa, ns, goto_symex_statet::L0);
404-
const irep_idt l0_name=ssa.get_identifier();
405-
406-
// save old L1 name for popping the frame
407-
auto c_it = state.level1.current_names.find(l0_name);
408-
409-
if(c_it != state.level1.current_names.end())
410-
{
411-
frame.old_level1.emplace(l0_name, c_it->second);
412-
c_it->second = std::make_pair(ssa, frame_nr);
413-
}
414-
else
415-
{
416-
c_it = state.level1.current_names
417-
.emplace(l0_name, std::make_pair(ssa, frame_nr))
418-
.first;
419-
}
420-
421-
// do L1 renaming -- these need not be unique, as
422-
// identifiers may be shared among functions
423-
// (e.g., due to inlining or other code restructuring)
424-
425-
state.rename(ssa, ns, goto_symex_statet::L1);
426-
427-
irep_idt l1_name=ssa.get_identifier();
428-
unsigned offset=0;
429-
430-
while(state.l1_history.find(l1_name)!=state.l1_history.end())
431-
{
432-
symex_renaming_levelt::increase_counter(c_it);
433-
++offset;
434-
ssa.set_level_1(frame_nr+offset);
435-
l1_name=ssa.get_identifier();
436-
}
437395

438-
// now unique -- store
439-
frame.local_objects.insert(l1_name);
440-
state.l1_history.insert(l1_name);
396+
const std::size_t fresh_l1_index =
397+
path_storage.get_unique_index(ssa.get_identifier(), frame_nr);
398+
state.add_object(ssa, fresh_l1_index, ns);
441399
}
442400
}
443401

src/goto-symex/symex_start_thread.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,9 @@ void goto_symext::symex_start_thread(statet &state)
6666

6767
// get L0 name for current thread
6868
lhs.set_level_0(t);
69+
const irep_idt &l0_name = lhs.get_identifier();
70+
std::size_t l1_index = path_storage.get_unique_index(l0_name, 0);
71+
CHECK_RETURN(l1_index == 0);
6972

7073
// set up L1 name
7174
if(!state.level1.current_names.insert(
@@ -75,7 +78,6 @@ void goto_symext::symex_start_thread(statet &state)
7578
state.rename(lhs, ns, goto_symex_statet::L1);
7679
const irep_idt l1_name=lhs.get_l1_object_identifier();
7780
// store it
78-
state.l1_history.insert(l1_name);
7981
new_thread.call_stack.back().local_objects.insert(l1_name);
8082

8183
// make copy

0 commit comments

Comments
 (0)