Skip to content

Commit 1f2fd5a

Browse files
committed
Additional unit tests for value_sett
Several branches cannot easily be tested by regression tests as existing front-ends will never create some of the expressions.
1 parent 2ce536c commit 1f2fd5a

File tree

1 file changed

+134
-0
lines changed

1 file changed

+134
-0
lines changed

unit/pointer-analysis/value_set.cpp

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)