22
22
// update_exprt.
23
23
// #define USE_UPDATE
24
24
25
+ constexpr bool use_update ()
26
+ {
27
+ #ifdef USE_UPDATE
28
+ return true ;
29
+ #else
30
+ return false ;
31
+ #endif
32
+ }
33
+
25
34
// / Store the \p what expression by recursively descending into the operands
26
35
// / of \p lhs until the first operand \c op0 is _nil_: this _nil_ operand
27
36
// / is then replaced with \p what.
@@ -71,12 +80,15 @@ void symex_assignt::assign_rec(
71
80
assign_symbol (to_ssa_expr (lhs), full_lhs, rhs, guard);
72
81
}
73
82
else if (lhs.id () == ID_index)
74
- assign_array (to_index_expr (lhs), full_lhs, rhs, guard);
83
+ assign_array< use_update ()> (to_index_expr (lhs), full_lhs, rhs, guard);
75
84
else if (lhs.id ()==ID_member)
76
85
{
77
86
const typet &type = to_member_expr (lhs).struct_op ().type ();
78
87
if (type.id () == ID_struct || type.id () == ID_struct_tag)
79
- assign_struct_member (to_member_expr (lhs), full_lhs, rhs, guard);
88
+ {
89
+ assign_struct_member<use_update ()>(
90
+ to_member_expr (lhs), full_lhs, rhs, guard);
91
+ }
80
92
else if (type.id () == ID_union || type.id () == ID_union_tag)
81
93
{
82
94
// should have been replaced by byte_extract
@@ -147,92 +159,102 @@ struct assignmentt final
147
159
// / \ref symex_assignt::assign_struct_member have done, but now making use
148
160
// / of the index/member that may only be known after renaming to L2 has taken
149
161
// / place.
162
+ // / \tparam use_update: use update_exprt instead of with_exprt when building
163
+ // / expressions that modify components of an array or a struct
150
164
// / \param [in, out] state: symbolic execution state to perform renaming
151
165
// / \param assignment: an assignment to rewrite
152
166
// / \param ns: namespace
153
167
// / \return the updated assignment
168
+ template <bool use_update>
154
169
static assignmentt rewrite_with_to_field_symbols (
155
170
goto_symext::statet &state,
156
171
assignmentt assignment,
157
172
const namespacet &ns)
158
173
{
159
174
exprt &ssa_rhs = assignment.rhs ;
160
175
ssa_exprt &lhs_mod = assignment.lhs ;
161
- #ifdef USE_UPDATE
162
- while (ssa_rhs.id () == ID_update &&
163
- to_update_expr (ssa_rhs).designator ().size () == 1 &&
164
- (lhs_mod.type ().id () == ID_array || lhs_mod.type ().id () == ID_struct ||
165
- lhs_mod.type ().id () == ID_struct_tag))
176
+ if (use_update)
166
177
{
167
- exprt field_sensitive_lhs;
168
- const update_exprt &update = to_update_expr (ssa_rhs);
169
- PRECONDITION (update.designator ().size () == 1 );
170
- const exprt &designator = update.designator ().front ();
171
-
172
- if (lhs_mod.type ().id () == ID_array)
178
+ while (ssa_rhs.id () == ID_update &&
179
+ to_update_expr (ssa_rhs).designator ().size () == 1 &&
180
+ (lhs_mod.type ().id () == ID_array ||
181
+ lhs_mod.type ().id () == ID_struct ||
182
+ lhs_mod.type ().id () == ID_struct_tag))
173
183
{
174
- field_sensitive_lhs =
175
- index_exprt (lhs_mod, to_index_designator (designator).index ());
176
- }
177
- else
178
- {
179
- field_sensitive_lhs = member_exprt (
180
- lhs_mod,
181
- to_member_designator (designator).get_component_name (),
182
- update.new_value ().type ());
183
- }
184
+ exprt field_sensitive_lhs;
185
+ const update_exprt &update = to_update_expr (ssa_rhs);
186
+ PRECONDITION (update.designator ().size () == 1 );
187
+ const exprt &designator = update.designator ().front ();
184
188
185
- state.field_sensitivity .apply (state, field_sensitive_lhs, true );
189
+ if (lhs_mod.type ().id () == ID_array)
190
+ {
191
+ field_sensitive_lhs =
192
+ index_exprt (lhs_mod, to_index_designator (designator).index ());
193
+ }
194
+ else
195
+ {
196
+ field_sensitive_lhs = member_exprt (
197
+ lhs_mod,
198
+ to_member_designator (designator).get_component_name (),
199
+ update.new_value ().type ());
200
+ }
186
201
187
- if (field_sensitive_lhs.id () != ID_symbol)
188
- break ;
202
+ state.field_sensitivity .apply (ns, state, field_sensitive_lhs, true );
189
203
190
- ssa_rhs = update.new_value ();
191
- lhs_mod = to_ssa_expr (field_sensitive_lhs);
192
- }
193
- #else
194
- while (ssa_rhs.id () == ID_with &&
195
- to_with_expr (ssa_rhs).operands ().size () == 3 &&
196
- (lhs_mod.type ().id () == ID_array || lhs_mod.type ().id () == ID_struct ||
197
- lhs_mod.type ().id () == ID_struct_tag))
198
- {
199
- exprt field_sensitive_lhs;
200
- const with_exprt &with_expr = to_with_expr (ssa_rhs);
204
+ if (field_sensitive_lhs.id () != ID_symbol)
205
+ break ;
201
206
202
- if (lhs_mod.type ().id () == ID_array)
203
- {
204
- field_sensitive_lhs = index_exprt (lhs_mod, with_expr.where ());
207
+ ssa_rhs = update.new_value ();
208
+ lhs_mod = to_ssa_expr (field_sensitive_lhs);
205
209
}
206
- else
210
+ }
211
+ else
212
+ {
213
+ while (
214
+ ssa_rhs.id () == ID_with && to_with_expr (ssa_rhs).operands ().size () == 3 &&
215
+ (lhs_mod.type ().id () == ID_array || lhs_mod.type ().id () == ID_struct ||
216
+ lhs_mod.type ().id () == ID_struct_tag))
207
217
{
208
- field_sensitive_lhs = member_exprt (
209
- lhs_mod,
210
- with_expr.where ().get (ID_component_name),
211
- with_expr.new_value ().type ());
212
- }
218
+ exprt field_sensitive_lhs;
219
+ const with_exprt &with_expr = to_with_expr (ssa_rhs);
213
220
214
- field_sensitive_lhs = state.field_sensitivity .apply (
215
- ns, state, std::move (field_sensitive_lhs), true );
221
+ if (lhs_mod.type ().id () == ID_array)
222
+ {
223
+ field_sensitive_lhs = index_exprt (lhs_mod, with_expr.where ());
224
+ }
225
+ else
226
+ {
227
+ field_sensitive_lhs = member_exprt (
228
+ lhs_mod,
229
+ with_expr.where ().get (ID_component_name),
230
+ with_expr.new_value ().type ());
231
+ }
216
232
217
- if ( field_sensitive_lhs. id () != ID_symbol)
218
- break ;
233
+ field_sensitive_lhs = state. field_sensitivity . apply (
234
+ ns, state, std::move (field_sensitive_lhs), true ) ;
219
235
220
- ssa_rhs = with_expr.new_value ();
221
- lhs_mod = to_ssa_expr (field_sensitive_lhs);
236
+ if (field_sensitive_lhs.id () != ID_symbol)
237
+ break ;
238
+
239
+ ssa_rhs = with_expr.new_value ();
240
+ lhs_mod = to_ssa_expr (field_sensitive_lhs);
241
+ }
222
242
}
223
- #endif
224
243
return assignment;
225
244
}
226
245
227
246
// / Replace byte-update operations that only affect individual fields of an
228
247
// / expression by assignments to just those fields. May generate "with" (or
229
248
// / "update") expressions, which \ref rewrite_with_to_field_symbols will then
230
249
// / take care of.
250
+ // / \tparam use_update: use update_exprt instead of with_exprt when building
251
+ // / expressions that modify components of an array or a struct
231
252
// / \param [in, out] state: symbolic execution state to perform renaming
232
253
// / \param assignment: assignment to transform
233
254
// / \param ns: namespace
234
255
// / \param do_simplify: set to true if, and only if, simplification is enabled
235
256
// / \return updated assignment
257
+ template <bool use_update>
236
258
static assignmentt shift_indexed_access_to_lhs (
237
259
goto_symext::statet &state,
238
260
assignmentt assignment,
@@ -269,31 +291,38 @@ static assignmentt shift_indexed_access_to_lhs(
269
291
if (byte_extract.id () == ID_index)
270
292
{
271
293
index_exprt &idx = to_index_expr (byte_extract);
272
-
273
- #ifdef USE_UPDATE
274
- update_exprt new_rhs{idx.array (), exprt{}, ssa_rhs};
275
- new_rhs.designator ().push_back (index_designatort{idx.index ()});
276
- #else
277
- with_exprt new_rhs{idx.array (), idx.index (), ssa_rhs};
278
- #endif
279
-
280
- ssa_rhs = new_rhs;
294
+ ssa_rhs = [&]() -> exprt {
295
+ if (use_update)
296
+ {
297
+ update_exprt new_rhs{idx.array (), exprt{}, ssa_rhs};
298
+ new_rhs.designator ().push_back (index_designatort{idx.index ()});
299
+ return std::move (new_rhs);
300
+ }
301
+ else
302
+ return with_exprt{idx.array (), idx.index (), ssa_rhs};
303
+ }();
281
304
byte_extract = idx.array ();
282
305
}
283
306
else
284
307
{
285
308
member_exprt &member = to_member_expr (byte_extract);
286
309
const irep_idt &component_name = member.get_component_name ();
287
-
288
- #ifdef USE_UPDATE
289
- update_exprt new_rhs{member.compound (), exprt{}, ssa_rhs};
290
- new_rhs.designator ().push_back (member_designatort{component_name});
291
- #else
292
- with_exprt new_rhs (member.compound (), exprt (ID_member_name), ssa_rhs);
293
- new_rhs.where ().set (ID_component_name, component_name);
294
- #endif
295
-
296
- ssa_rhs = new_rhs;
310
+ ssa_rhs = [&]() -> exprt {
311
+ if (use_update)
312
+ {
313
+ update_exprt new_rhs{member.compound (), exprt{}, ssa_rhs};
314
+ new_rhs.designator ().push_back (
315
+ member_designatort{component_name});
316
+ return std::move (new_rhs);
317
+ }
318
+ else
319
+ {
320
+ with_exprt new_rhs (
321
+ member.compound (), exprt (ID_member_name), ssa_rhs);
322
+ new_rhs.where ().set (ID_component_name, component_name);
323
+ return std::move (new_rhs);
324
+ }
325
+ }();
297
326
byte_extract = member.compound ();
298
327
}
299
328
}
@@ -361,9 +390,10 @@ void symex_assignt::assign_non_struct_symbol(
361
390
// introduced by assign_struct_member, are transformed into member
362
391
// expressions on the LHS. If we add an option to disable field-sensitivity
363
392
// in the future these should be omitted.
364
- auto assignment = shift_indexed_access_to_lhs (
393
+ auto assignment = shift_indexed_access_to_lhs< use_update ()> (
365
394
state, assignmentt{lhs, std::move (l2_rhs)}, ns, symex_config.simplify_opt );
366
- assignment = rewrite_with_to_field_symbols (state, std::move (assignment), ns);
395
+ assignment = rewrite_with_to_field_symbols<use_update ()>(
396
+ state, std::move (assignment), ns);
367
397
368
398
if (symex_config.simplify_opt )
369
399
assignment.rhs = simplify_expr (std::move (assignment.rhs ), ns);
@@ -437,6 +467,7 @@ void symex_assignt::assign_typecast(
437
467
assign_rec (lhs.op (), new_full_lhs, rhs_typecasted, guard);
438
468
}
439
469
470
+ template <bool use_update>
440
471
void symex_assignt::assign_array (
441
472
const index_exprt &lhs,
442
473
const exprt &full_lhs,
@@ -449,36 +480,29 @@ void symex_assignt::assign_array(
449
480
450
481
PRECONDITION (lhs_index_type.id () == ID_array);
451
482
452
- #ifdef USE_UPDATE
453
-
454
- // turn
455
- // a[i]=e
456
- // into
457
- // a'==UPDATE(a, [i], e)
458
-
459
- update_exprt new_rhs (lhs_index_type);
460
- new_rhs.old ()=lhs_array;
461
- new_rhs.designator ().push_back (index_designatort (lhs_index));
462
- new_rhs.new_value ()=rhs;
463
-
464
- exprt new_full_lhs=add_to_lhs (full_lhs, lhs);
465
-
466
- symex_assign_rec (
467
- state, lhs_array, new_full_lhs, new_rhs, guard, assignment_type);
468
-
469
- #else
470
- // turn
471
- // a[i]=e
472
- // into
473
- // a'==a WITH [i:=e]
474
-
475
- const with_exprt new_rhs{lhs_array, lhs_index, rhs};
476
- const exprt new_full_lhs = add_to_lhs (full_lhs, lhs);
477
-
478
- assign_rec (lhs_array, new_full_lhs, new_rhs, guard);
479
- #endif
483
+ if (use_update)
484
+ {
485
+ // turn
486
+ // a[i]=e
487
+ // into
488
+ // a'==UPDATE(a, [i], e)
489
+ const update_exprt new_rhs{lhs_array, index_designatort (lhs_index), rhs};
490
+ const exprt new_full_lhs = add_to_lhs (full_lhs, lhs);
491
+ assign_rec (lhs_array, new_full_lhs, new_rhs, guard);
492
+ }
493
+ else
494
+ {
495
+ // turn
496
+ // a[i]=e
497
+ // into
498
+ // a'==a WITH [i:=e]
499
+ const with_exprt new_rhs{lhs_array, lhs_index, rhs};
500
+ const exprt new_full_lhs = add_to_lhs (full_lhs, lhs);
501
+ assign_rec (lhs_array, new_full_lhs, new_rhs, guard);
502
+ }
480
503
}
481
504
505
+ template <bool use_update>
482
506
void symex_assignt::assign_struct_member (
483
507
const member_exprt &lhs,
484
508
const exprt &full_lhs,
@@ -514,35 +538,30 @@ void symex_assignt::assign_struct_member(
514
538
515
539
const irep_idt &component_name=lhs.get_component_name ();
516
540
517
- #ifdef USE_UPDATE
518
-
519
- // turn
520
- // a.c=e
521
- // into
522
- // a'==UPDATE(a, .c, e)
523
-
524
- update_exprt new_rhs (lhs_struct.type ());
525
- new_rhs.old ()=lhs_struct;
526
- new_rhs.designator ().push_back (member_designatort (component_name));
527
- new_rhs.new_value ()=rhs;
528
-
529
- exprt new_full_lhs=add_to_lhs (full_lhs, lhs);
530
-
531
- symex_assign_rec (
532
- state, lhs_struct, new_full_lhs, new_rhs, guard, assignment_type);
533
-
534
- #else
535
- // turn
536
- // a.c=e
537
- // into
538
- // a'==a WITH [c:=e]
541
+ if (use_update)
542
+ {
543
+ // turn
544
+ // a.c=e
545
+ // into
546
+ // a'==UPDATE(a, .c, e)
547
+ const update_exprt new_rhs{
548
+ lhs_struct, member_designatort (component_name), rhs};
549
+ const exprt new_full_lhs = add_to_lhs (full_lhs, lhs);
550
+ assign_rec (lhs_struct, new_full_lhs, new_rhs, guard);
551
+ }
552
+ else
553
+ {
554
+ // turn
555
+ // a.c=e
556
+ // into
557
+ // a'==a WITH [c:=e]
539
558
540
- with_exprt new_rhs (lhs_struct, exprt (ID_member_name), rhs);
541
- new_rhs.where ().set (ID_component_name, component_name);
559
+ with_exprt new_rhs (lhs_struct, exprt (ID_member_name), rhs);
560
+ new_rhs.where ().set (ID_component_name, component_name);
542
561
543
- exprt new_full_lhs= add_to_lhs (full_lhs, lhs);
544
- assign_rec (lhs_struct, new_full_lhs, new_rhs, guard);
545
- # endif
562
+ exprt new_full_lhs = add_to_lhs (full_lhs, lhs);
563
+ assign_rec (lhs_struct, new_full_lhs, new_rhs, guard);
564
+ }
546
565
}
547
566
548
567
void symex_assignt::assign_if (
0 commit comments