@@ -298,4 +298,138 @@ SCENARIO(
298298 }
299299 }
300300 }
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+ }
301435}
0 commit comments