@@ -20,6 +20,18 @@ Author: Thomas Kiley, thomas.kiley@diffblue.com
20
20
#include < iostream>
21
21
#endif
22
22
23
+ /* *
24
+ * \brief Explicit copy-constructor to make it clear that the shared_map
25
+ * used to store the values of fields is copy-constructed as well
26
+ * to ensure it shares as much data as possible.
27
+ */
28
+ full_struct_abstract_objectt::full_struct_abstract_objectt (
29
+ const full_struct_abstract_objectt &ao):
30
+ struct_abstract_objectt(ao), map(ao.map)
31
+ {
32
+ DATA_INVARIANT (verify (), " Structural invariants maintained" );
33
+ }
34
+
23
35
/* ******************************************************************\
24
36
25
37
Function: full_struct_abstract_objectt::struct_abstract_objectt
@@ -124,13 +136,13 @@ abstract_object_pointert full_struct_abstract_objectt::read_component(
124
136
{
125
137
PRECONDITION (!is_bottom ());
126
138
127
- irep_idt c=member_expr.get_component_name ();
139
+ const irep_idt c=member_expr.get_component_name ();
128
140
129
- struct_mapt::const_iterator it =map.find (c);
141
+ shared_struct_mapt::const_find_type value =map.find (c);
130
142
131
- if (it!=map. cend () )
143
+ if (value. second )
132
144
{
133
- return it-> second ;
145
+ return value. first ;
134
146
}
135
147
else
136
148
{
@@ -182,29 +194,31 @@ sharing_ptrt<struct_abstract_objectt>
182
194
member_expr.compound ().type (), false , true ));
183
195
}
184
196
185
- internal_sharing_ptrt<full_struct_abstract_objectt> copy (
186
- new full_struct_abstract_objectt (* this ));
197
+ const auto &result=
198
+ std::dynamic_pointer_cast< full_struct_abstract_objectt>( mutable_clone ( ));
187
199
188
200
if (!stack.empty ())
189
201
{
190
202
abstract_object_pointert starting_value;
191
- irep_idt c=member_expr.get_component_name ();
192
- if (map.find (c)==map.cend ())
203
+ const irep_idt c=member_expr.get_component_name ();
204
+ shared_struct_mapt::const_find_type old_value = map.find (c);
205
+ if (!old_value.second )
193
206
{
194
207
starting_value=
195
208
environment.abstract_object_factory (
196
209
member_expr.type (), ns, true , false );
197
210
}
198
211
else
199
212
{
200
- starting_value=map. at (c) ;
213
+ starting_value=old_value. first ;
201
214
}
202
215
203
- copy ->map [c]=
216
+ result ->map [c] =
204
217
environment.write (starting_value, value, stack, ns, merging_write);
205
- copy->clear_top ();
206
- DATA_INVARIANT (copy->verify (), " Structural invariants maintained" );;
207
- return copy;
218
+
219
+ result->clear_top ();
220
+ DATA_INVARIANT (result->verify (), " Structural invariants maintained" );
221
+ return result;
208
222
}
209
223
else
210
224
{
@@ -213,41 +227,40 @@ sharing_ptrt<struct_abstract_objectt>
213
227
std::cout << " Setting component" << std::endl;
214
228
#endif
215
229
216
- irep_idt c=member_expr.get_component_name ();
230
+ const irep_idt c=member_expr.get_component_name ();
217
231
218
232
if (merging_write)
219
233
{
220
234
if (is_top ()) // struct is top
221
235
{
222
- DATA_INVARIANT (copy ->verify (), " Structural invariants maintained" ); ;
223
- return copy ;
236
+ DATA_INVARIANT (result ->verify (), " Structural invariants maintained" );
237
+ return result ;
224
238
}
225
239
226
- INVARIANT (!copy ->map .empty (), " If not top, map cannot be empty" );
240
+ INVARIANT (!result ->map .empty (), " If not top, map cannot be empty" );
227
241
228
- struct_mapt &m=copy ->map ;
242
+ shared_struct_mapt::const_find_type old_value=result ->map . find (c) ;
229
243
230
- struct_mapt::iterator it=m.find (c);
231
-
232
- if (it==m.end ()) // component is top
244
+ if (!old_value.second ) // component is top
233
245
{
234
- DATA_INVARIANT (copy ->verify (), " Structural invariants maintained" ); ;
235
- return copy ;
246
+ DATA_INVARIANT (result ->verify (), " Structural invariants maintained" );
247
+ return result ;
236
248
}
237
249
238
250
bool dummy;
239
251
240
- it-> second = abstract_objectt::merge (it-> second , value, dummy);
252
+ result-> map [c] = abstract_objectt::merge (old_value. first , value, dummy);
241
253
}
242
254
else
243
255
{
244
- copy ->map [c]= value;
245
- copy ->clear_top ();
246
- INVARIANT (!copy ->is_bottom (), " top != bottom" );
256
+ result ->map [c] = value;
257
+ result ->clear_top ();
258
+ INVARIANT (!result ->is_bottom (), " top != bottom" );
247
259
}
248
260
249
- DATA_INVARIANT (copy->verify (), " Structural invariants maintained" );;
250
- return copy;
261
+ DATA_INVARIANT (result->verify (), " Structural invariants maintained" );
262
+
263
+ return result;
251
264
}
252
265
}
253
266
@@ -272,15 +285,27 @@ Function: full_struct_abstract_objectt::output
272
285
void full_struct_abstract_objectt::output (
273
286
std::ostream &out, const ai_baset &ai, const namespacet &ns) const
274
287
{
288
+ // To ensure that a consistent ordering of fields is output, use
289
+ // the underlying type declaration for this struct to determine
290
+ // the ordering
291
+ struct_union_typet type_decl = to_struct_union_type (ns.follow (type ()));
292
+
293
+ bool first = true ;
294
+
275
295
out << " {" ;
276
- for (const auto &entry : map )
296
+ for (const auto field : type_decl. components () )
277
297
{
278
- if (entry.first !=map.cbegin ()->first )
298
+ auto value = map.find (field.get_name ());
299
+ if (value.second )
279
300
{
280
- out << " , " ;
301
+ if (!first)
302
+ {
303
+ out << " , " ;
304
+ }
305
+ out << ' .' << field.get_name () << ' =' ;
306
+ value.first ->output (out, ai, ns);
307
+ first = false ;
281
308
}
282
- out << " ." << entry.first << " =" ;
283
- entry.second ->output (out, ai, ns);
284
309
}
285
310
out << " }" ;
286
311
}
@@ -362,22 +387,19 @@ abstract_object_pointert full_struct_abstract_objectt::merge_constant_structs(
362
387
}
363
388
else
364
389
{
365
- struct_mapt merged_map;
366
- bool modified=
367
- abstract_objectt::merge_maps<irep_idt>(map, other->map , merged_map);
390
+ const auto &result=
391
+ std::dynamic_pointer_cast<full_struct_abstract_objectt>(mutable_clone ());
392
+
393
+ bool modified = abstract_objectt::merge_shared_maps<irep_idt>(
394
+ map, other->map , result->map );
395
+
368
396
if (!modified)
369
397
{
370
398
DATA_INVARIANT (verify (), " Structural invariants maintained" );
371
399
return shared_from_this ();
372
400
}
373
401
else
374
402
{
375
- const auto &result=
376
- std::dynamic_pointer_cast<full_struct_abstract_objectt>(
377
- mutable_clone ());
378
-
379
- result->map =merged_map;
380
-
381
403
INVARIANT (!result->is_top (), " Merge of maps will not generate top" );
382
404
INVARIANT (!result->is_bottom (), " Merge of maps will not generate bottom" );
383
405
DATA_INVARIANT (result->verify (), " Structural invariants maintained" );
@@ -397,18 +419,33 @@ abstract_object_pointert full_struct_abstract_objectt::merge_constant_structs(
397
419
* \return A new abstract_object if it's contents is modifed, or this if
398
420
* no modification is needed
399
421
*/
400
- abstract_object_pointert
401
- full_struct_abstract_objectt::visit_sub_elements (
422
+ abstract_object_pointert full_struct_abstract_objectt::visit_sub_elements (
402
423
const abstract_object_visitort &visitor) const
403
424
{
404
425
const auto &result=
405
- std::dynamic_pointer_cast<full_struct_abstract_objectt>(
406
- mutable_clone ());
426
+ std::dynamic_pointer_cast<full_struct_abstract_objectt>(mutable_clone ());
427
+
428
+ bool modified = false ;
429
+
430
+ shared_struct_mapt::viewt view;
431
+ result->map .get_view (view);
407
432
408
- for (auto &item : result-> map )
433
+ for (auto &item : view )
409
434
{
410
- item.second =visitor.visit (item.second );
435
+ auto newval = visitor.visit (item.second );
436
+ if (newval != item.second )
437
+ {
438
+ result->map [item.first ] = visitor.visit (item.second );
439
+ modified = true ;
440
+ }
411
441
}
412
442
413
- return result;
443
+ if (modified)
444
+ {
445
+ return result;
446
+ }
447
+ else
448
+ {
449
+ return shared_from_this ();
450
+ }
414
451
}
0 commit comments