14
14
#include < util/arith_tools.h>
15
15
#include < util/byte_operators.h>
16
16
#include < util/c_types.h>
17
+ #include < util/expr_iterator.h>
17
18
#include < util/pointer_offset_size.h>
18
19
#include < util/simplify_expr.h>
19
20
@@ -169,6 +170,33 @@ replace_nondet(exprt &expr, symex_nondet_generatort &build_symex_nondet)
169
170
}
170
171
}
171
172
173
+ static void lower_cond_expr (exprt &expr)
174
+ {
175
+ for (auto it = expr.depth_begin (), itend = expr.depth_end (); it != itend; ++it)
176
+ {
177
+ if (it->id () == ID_cond)
178
+ {
179
+ exprt new_expr;
180
+ const auto &cond_expr = to_cond_expr (*it);
181
+ INVARIANT (cond_expr.get_n_cases () >= 1 , " cond_expr should not be empty" );
182
+ for (std::size_t i = cond_expr.get_n_cases () - 1 ; ; --i)
183
+ {
184
+ if (i == cond_expr.get_n_cases () - 1 )
185
+ new_expr = cond_expr.value (i);
186
+ else
187
+ {
188
+ new_expr =
189
+ if_exprt (cond_expr.condition (i), cond_expr.value (i), new_expr);
190
+ }
191
+ if (i == 0 )
192
+ break ;
193
+ }
194
+
195
+ it.mutate () = std::move (new_expr);
196
+ }
197
+ }
198
+ }
199
+
172
200
void goto_symext::clean_expr (
173
201
exprt &expr,
174
202
statet &state,
@@ -177,6 +205,12 @@ void goto_symext::clean_expr(
177
205
replace_nondet (expr, path_storage.build_symex_nondet );
178
206
dereference (expr, state, write );
179
207
208
+ // We know how to handle cond_exprt on the LHS (symex_assign_rec does this),
209
+ // but cond_exprt on the RHS is currently patchily handled, especially by the
210
+ // Java string solver. For now, lower such expressions to nested if_exprts.
211
+ if (!write )
212
+ lower_cond_expr (expr);
213
+
180
214
// make sure all remaining byte extract operations use the root
181
215
// object to avoid nesting of with/update and byte_update when on
182
216
// lhs
0 commit comments