@@ -263,15 +263,40 @@ goto_symex_statet::rename(exprt expr, const namespacet &ns)
263
263
*it = rename<level>(std::move (*it), ns).get ();
264
264
265
265
const exprt &c_expr = as_const (expr);
266
+
267
+ // It may happen that the `old` subexpression of a `with_exprt` expression
268
+ // is propagated with a value that has an array type with a size that is a
269
+ // symbol with an L2 index that is different. In this case the type of the
270
+ // `with_exprt` will not match with the type of the `old` subexpression
271
+ // anymore.
272
+ // To address this issue we re-canonicalize the `with_exprt` by propagating
273
+ // the type of the `old` subexpression to the type of the `with_exprt`.
274
+ const auto *c_with_expr = expr_try_dynamic_cast<with_exprt>(c_expr);
275
+ if (
276
+ c_with_expr && can_cast_type<array_typet>(c_with_expr->type ()) &&
277
+ can_cast_type<array_typet>(c_with_expr->old ().type ()) &&
278
+ c_with_expr->type () != c_with_expr->old ().type ())
279
+ {
280
+ expr.type () = to_with_expr (expr).old ().type ();
281
+ }
282
+ INVARIANT_WITH_DIAGNOSTICS (
283
+ expr.id () != ID_with ||
284
+ c_expr.type () == to_with_expr (c_expr).old ().type (),
285
+ " Type of renamed expr should be the same as operands for with_exprt" ,
286
+ c_expr.type ().pretty (),
287
+ to_with_expr (c_expr).old ().type ().pretty ());
288
+ INVARIANT_WITH_DIAGNOSTICS (
289
+ expr.id () != ID_if ||
290
+ c_expr.type () == to_if_expr (c_expr).true_case ().type (),
291
+ " Type of renamed expr should be the same as operands for if_exprt" ,
292
+ c_expr.type ().pretty (),
293
+ to_if_expr (c_expr).true_case ().type ().pretty ());
266
294
INVARIANT_WITH_DIAGNOSTICS (
267
- (expr.id () != ID_with ||
268
- c_expr.type () == to_with_expr (c_expr).old ().type ()) &&
269
- (expr.id () != ID_if ||
270
- (c_expr.type () == to_if_expr (c_expr).true_case ().type () &&
271
- c_expr.type () == to_if_expr (c_expr).false_case ().type ())),
272
- " Type of renamed expr should be the same as operands for with_exprt and "
273
- " if_exprt" ,
274
- irep_pretty_diagnosticst{expr});
295
+ expr.id () != ID_if ||
296
+ c_expr.type () == to_if_expr (c_expr).false_case ().type (),
297
+ " Type of renamed expr should be the same as operands for if_exprt" ,
298
+ c_expr.type ().pretty (),
299
+ to_if_expr (c_expr).false_case ().type ().pretty ());
275
300
276
301
if (level == L2)
277
302
expr = field_sensitivity.apply (ns, *this , std::move (expr), false );
0 commit comments