@@ -368,6 +368,20 @@ void goto_symext::dereference_rec(exprt &expr, statet &state, bool write)
368368 }
369369}
370370
371+ static exprt
372+ apply_to_objects_in_dereference (exprt e, const std::function<exprt(exprt)> &f)
373+ {
374+ if (auto deref = expr_try_dynamic_cast<dereference_exprt>(e))
375+ {
376+ deref->op () = f (std::move (deref->op ()));
377+ return *deref;
378+ }
379+
380+ for (auto &sub : e.operands ())
381+ sub = apply_to_objects_in_dereference (std::move (sub), f);
382+ return e;
383+ }
384+
371385// / Replace all dereference operations within \p expr with explicit references
372386// / to the objects they may refer to. For example, the expression `*p1 + *p2`
373387// / might be rewritten to `obj1 + (p2 == &obj2 ? obj2 : obj3)` in the case where
@@ -407,19 +421,21 @@ void goto_symext::dereference_rec(exprt &expr, statet &state, bool write)
407421// / See \ref auto_objects.cpp for details.
408422void goto_symext::dereference (exprt &expr, statet &state, bool write)
409423{
410- // The expression needs to be renamed to level 1
411- // in order to distinguish addresses of local variables
412- // from different frames. Would be enough to rename
413- // symbols whose address is taken.
414424 PRECONDITION (!state.call_stack ().empty ());
415- exprt l1_expr = state.field_sensitivity .apply (
416- ns, state, state.rename <L1>(expr, ns).get (), write);
425+
426+ // Symbols whose address is taken need to be renamed to level 1
427+ // in order to distinguish addresses of local variables
428+ // from different frames.
429+ expr = apply_to_objects_in_dereference (std::move (expr), [&](exprt e) {
430+ return state.field_sensitivity .apply (
431+ ns, state, state.rename <L1>(std::move (e), ns).get (), false );
432+ });
417433
418434 // start the recursion!
419- dereference_rec (l1_expr , state, write);
435+ dereference_rec (expr , state, write);
420436 // dereferencing may introduce new symbol_exprt
421437 // (like __CPROVER_memory)
422- expr = state.rename <L1>(std::move (l1_expr ), ns).get ();
438+ expr = state.rename <L1>(std::move (expr ), ns).get ();
423439
424440 // Dereferencing is likely to introduce new member-of-if constructs --
425441 // for example, "x->field" may have become "(x == &o1 ? o1 : o2).field."
0 commit comments