@@ -298,4 +298,138 @@ SCENARIO(
298
298
}
299
299
}
300
300
}
301
+
302
+ GIVEN (" A value-set containing pointers with offsets" )
303
+ {
304
+ signedbv_typet int_type{sizeof (int ) * CHAR_BIT};
305
+ pointer_typet int_ptr_type{int_type, sizeof (void *) * CHAR_BIT};
306
+
307
+ // Create struct S { int a; char b }
308
+ struct_typet struct_S{{{" a" , int_type}, {" b" , unsignedbv_typet{CHAR_BIT}}}};
309
+ struct_S.set_tag (" S" );
310
+
311
+ auto &S_a = struct_S.components ()[0 ];
312
+ auto &S_b = struct_S.components ()[1 ];
313
+
314
+ S_a.set_base_name (" a" );
315
+ S_a.set_pretty_name (" a" );
316
+
317
+ S_b.set_base_name (" b" );
318
+ S_b.set_pretty_name (" b" );
319
+
320
+ type_symbolt S_symbol{" S" , struct_S, irep_idt{}};
321
+ S_symbol.base_name = " S" ;
322
+ S_symbol.pretty_name = " S" ;
323
+
324
+ symbol_table.add (S_symbol);
325
+
326
+ // Create global symbols struct S s, int *p
327
+
328
+ symbolt s_symbol{" s" , struct_tag_typet{S_symbol.name }, irep_idt{}};
329
+ s_symbol.pretty_name = " s" ;
330
+ s_symbol.is_static_lifetime = true ;
331
+ symbol_table.add (s_symbol);
332
+
333
+ symbolt p1_symbol{" p1" , int_ptr_type, irep_idt{}};
334
+ p1_symbol.pretty_name = " p1" ;
335
+ p1_symbol.is_static_lifetime = true ;
336
+ symbol_table.add (p1_symbol);
337
+
338
+ // Assign p1 = &s + s.a + s.a; (which we cannot easily create via regression
339
+ // tests, because front-ends would turn this into binary expressions)
340
+ member_exprt s_a (s_symbol.symbol_expr (), S_a);
341
+ code_assignt assign_p1{
342
+ p1_symbol.symbol_expr (),
343
+ plus_exprt{
344
+ {typecast_exprt{
345
+ address_of_exprt{s_symbol.symbol_expr ()}, p1_symbol.type },
346
+ s_a,
347
+ s_a},
348
+ int_ptr_type}};
349
+
350
+ value_set.apply_code (assign_p1, ns);
351
+
352
+ WHEN (" We query what p1 points to" )
353
+ {
354
+ const std::vector<exprt> p1_result =
355
+ value_set.get_value_set (p1_symbol.symbol_expr (), ns);
356
+
357
+ THEN (" It should point to 's'" )
358
+ {
359
+ REQUIRE (p1_result.size () == 1 );
360
+ const exprt &result = *p1_result.begin ();
361
+ REQUIRE (object_descriptor_matches (result, s_symbol.symbol_expr ()));
362
+ }
363
+ }
364
+
365
+ symbolt p2_symbol{" p2" , int_ptr_type, irep_idt{}};
366
+ p2_symbol.pretty_name = " p2" ;
367
+ p2_symbol.is_static_lifetime = true ;
368
+ symbol_table.add (p2_symbol);
369
+
370
+ // Assign p2 = &s - s.a; (which the simplifier would always rewrite to &s +
371
+ // -(s.a), so use the value_sett::assign interface to wrongly claim
372
+ // simplification had already taken place)
373
+ value_set.assign (
374
+ p2_symbol.symbol_expr (),
375
+ minus_exprt{
376
+ typecast_exprt{
377
+ address_of_exprt{s_symbol.symbol_expr ()}, p2_symbol.type },
378
+ s_a},
379
+ ns,
380
+ true ,
381
+ true );
382
+
383
+ WHEN (" We query what p2 points to" )
384
+ {
385
+ const std::vector<exprt> p2_result =
386
+ value_set.get_value_set (p2_symbol.symbol_expr (), ns);
387
+
388
+ THEN (" It should point to 's'" )
389
+ {
390
+ REQUIRE (p2_result.size () == 1 );
391
+ const exprt &result = *p2_result.begin ();
392
+ REQUIRE (object_descriptor_matches (result, s_symbol.symbol_expr ()));
393
+ }
394
+ }
395
+
396
+ symbolt A_symbol{
397
+ " A" , array_typet{int_type, from_integer (2 , int_type)}, irep_idt{}};
398
+ A_symbol.pretty_name = " A" ;
399
+ A_symbol.is_static_lifetime = true ;
400
+ symbol_table.add (A_symbol);
401
+
402
+ symbolt p3_symbol{" p3" , int_ptr_type, irep_idt{}};
403
+ p3_symbol.pretty_name = " p3" ;
404
+ p3_symbol.is_static_lifetime = true ;
405
+ symbol_table.add (p3_symbol);
406
+
407
+ // Assign p3 = &A[1]; (which the simplifier would always rewrite to A +
408
+ // sizeof(int), so use the value_sett::assign interface to wrongly claim
409
+ // simplification had already taken place)
410
+ value_set.assign (
411
+ p3_symbol.symbol_expr (),
412
+ address_of_exprt{
413
+ index_exprt{A_symbol.symbol_expr (), from_integer (1 , int_type)}},
414
+ ns,
415
+ true ,
416
+ true );
417
+
418
+ WHEN (" We query what p3 points to" )
419
+ {
420
+ const std::vector<exprt> p3_result =
421
+ value_set.get_value_set (p3_symbol.symbol_expr (), ns);
422
+
423
+ THEN (" It should point to 'A'" )
424
+ {
425
+ REQUIRE (p3_result.size () == 1 );
426
+ const exprt &result = *p3_result.begin ();
427
+ REQUIRE (object_descriptor_matches (
428
+ result,
429
+ index_exprt{
430
+ A_symbol.symbol_expr (),
431
+ from_integer (0 , to_array_type (A_symbol.type ).index_type ())}));
432
+ }
433
+ }
434
+ }
301
435
}
0 commit comments