Skip to content

Commit 825029a

Browse files
committed
Add function pointer nondet initialisation to goto-harness
1 parent 9db8bd4 commit 825029a

File tree

4 files changed

+92
-3
lines changed

4 files changed

+92
-3
lines changed
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#include <assert.h>
2+
3+
typedef int (*fptr)(int a, int b);
4+
5+
int max_normal(int first, int second)
6+
{
7+
return first >= second ? first : second;
8+
}
9+
10+
int max_crazy(int first, int second)
11+
{
12+
return first >= second ? second : first;
13+
}
14+
15+
void use_fptr(fptr max, int first, int second)
16+
{
17+
int m = max(first, second);
18+
assert(m == first || m == second);
19+
assert(m >= first && m >= second);
20+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
CORE
2+
test.c
3+
--harness-type call-function --harness-function-name harness --function use_fptr
4+
^EXIT=10$
5+
^SIGNAL=0$
6+
\[use_fptr.assertion.1\] line \d+ assertion m == first \|\| m == second: SUCCESS
7+
\[use_fptr.assertion.2\] line \d+ assertion m >= first && m >= second: FAILURE
8+
--
9+
^warning: ignoring

src/goto-harness/recursive_initialization.cpp

Lines changed: 57 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,10 @@ code_blockt recursive_initializationt::build_constructor_body(
169169
}
170170
else if(type.id() == ID_pointer)
171171
{
172+
if(type.subtype().id() == ID_code)
173+
{
174+
return build_function_pointer_constructor(result_symbol);
175+
}
172176
if(lhs_name.has_value())
173177
{
174178
if(should_be_treated_as_cstring(*lhs_name) && type == char_type())
@@ -192,7 +196,7 @@ code_blockt recursive_initializationt::build_constructor_body(
192196
}
193197
}
194198

195-
const irep_idt &recursive_initializationt::build_constructor(const exprt &expr)
199+
irep_idt recursive_initializationt::build_constructor(const exprt &expr)
196200
{
197201
// for `expr` of type T builds a declaration of a function:
198202
//
@@ -786,7 +790,7 @@ code_blockt recursive_initializationt::build_dynamic_array_constructor(
786790

787791
bool recursive_initializationt::needs_freeing(const exprt &expr) const
788792
{
789-
if(expr.type().id() != ID_pointer)
793+
if(expr.type().id() != ID_pointer || expr.type().subtype().id() == ID_code)
790794
return false;
791795
if(common_arguments_origin.has_value() && expr.id() == ID_symbol)
792796
{
@@ -797,3 +801,54 @@ bool recursive_initializationt::needs_freeing(const exprt &expr) const
797801
}
798802
return true;
799803
}
804+
805+
code_blockt recursive_initializationt::build_function_pointer_constructor(
806+
const exprt &result)
807+
{
808+
PRECONDITION(can_cast_type<pointer_typet>(result.type()));
809+
const auto &result_type = to_pointer_type(result.type());
810+
PRECONDITION(can_cast_type<pointer_typet>(result_type.subtype()));
811+
const auto &function_pointer_type = to_pointer_type(result_type.subtype());
812+
PRECONDITION(can_cast_type<code_typet>(function_pointer_type.subtype()));
813+
const auto &function_type = to_code_type(function_pointer_type.subtype());
814+
815+
std::vector<symbol_exprt> targets;
816+
817+
for(const auto &sym : goto_model.get_symbol_table())
818+
{
819+
if(sym.second.type == function_type)
820+
{
821+
targets.push_back(sym.second.symbol_expr());
822+
}
823+
}
824+
825+
code_blockt body{};
826+
827+
const auto function_pointer_selector =
828+
get_fresh_local_symexpr("function_pointer_selector");
829+
body.add(
830+
code_assignt{function_pointer_selector,
831+
side_effect_expr_nondett{function_pointer_selector.type()}});
832+
auto function_pointer_index = std::size_t{0};
833+
834+
for(const auto &target : targets)
835+
{
836+
auto const assign =
837+
code_assignt{dereference_exprt{result}, address_of_exprt{target}};
838+
if(function_pointer_index != targets.size() - 1)
839+
{
840+
auto const condition = equal_exprt{
841+
function_pointer_selector,
842+
from_integer(function_pointer_index, function_pointer_selector.type())};
843+
auto const then = code_blockt{{assign, code_returnt{}}};
844+
body.add(code_ifthenelset{condition, then});
845+
}
846+
else
847+
{
848+
body.add(assign);
849+
}
850+
++function_pointer_index;
851+
}
852+
853+
return body;
854+
}

src/goto-harness/recursive_initialization.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,12 @@ class recursive_initializationt
176176
/// it if not.
177177
/// \param expr: the expression to be constructed
178178
/// \return name of the constructor function
179-
const irep_idt &build_constructor(const exprt &expr);
179+
irep_idt build_constructor(const exprt &expr);
180+
181+
/// Constructor for function pointers.
182+
/// \param result: symbol of the result parameter
183+
/// \return the body of the constructor
184+
code_blockt build_function_pointer_constructor(const exprt &result);
180185

181186
/// Generic constructor for all pointers: only builds one pointee (not an
182187
/// array) but may recourse in case the pointee contains more pointers, e.g.

0 commit comments

Comments
 (0)