Skip to content

Commit 9db8bd4

Browse files
committed
Allow function pointer arguments to be equal
for the function-call goto-harness. We add a new command-line option `treat-pointers-equal` that takes a list of formal parameter names and results in a harness that only generates constructor for one of the pointers. The other pointers are simply assigned with the constructed one.
1 parent cb20917 commit 9db8bd4

File tree

6 files changed

+131
-2
lines changed

6 files changed

+131
-2
lines changed
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#include <assert.h>
2+
#include <stdlib.h>
3+
4+
typedef struct st
5+
{
6+
struct st *next;
7+
int data;
8+
} st_t;
9+
10+
void func(st_t *p, st_t *q)
11+
{
12+
assert(p != NULL);
13+
assert(p->next != NULL);
14+
15+
assert(p == q);
16+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
CORE
2+
main.c
3+
--function func --min-null-tree-depth 10 --max-nondet-tree-depth 3 --harness-type call-function --treat-pointers-equal p,q
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
VERIFICATION SUCCESSFUL
7+
--
8+
^warning: ignoring

src/goto-harness/function_call_harness_generator.cpp

Lines changed: 62 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,9 @@ struct function_call_harness_generatort::implt
4848
std::set<irep_idt> function_parameters_to_treat_as_arrays;
4949
std::set<irep_idt> function_arguments_to_treat_as_arrays;
5050

51+
std::set<irep_idt> function_parameters_to_treat_equal;
52+
std::set<irep_idt> function_arguments_to_treat_equal;
53+
5154
std::set<irep_idt> function_parameters_to_treat_as_cstrings;
5255
std::set<irep_idt> function_arguments_to_treat_as_cstrings;
5356

@@ -112,6 +115,16 @@ void function_call_harness_generatort::handle_option(
112115
p_impl->function_parameters_to_treat_as_arrays.insert(
113116
values.begin(), values.end());
114117
}
118+
else if(option == FUNCTION_HARNESS_GENERATOR_TREAT_POINTERS_EQUAL_OPT)
119+
{
120+
for(auto const &value : values)
121+
{
122+
for(auto const &param_id : split_string(value, ','))
123+
{
124+
p_impl->function_parameters_to_treat_equal.insert(param_id);
125+
}
126+
}
127+
}
115128
else if(option == FUNCTION_HARNESS_GENERATOR_ASSOCIATED_ARRAY_SIZE_OPT)
116129
{
117130
for(auto const &array_size_pair : values)
@@ -183,6 +196,8 @@ void function_call_harness_generatort::implt::generate(
183196
recursive_initialization_config.mode = function_to_call.mode;
184197
recursive_initialization_config.pointers_to_treat_as_arrays =
185198
function_arguments_to_treat_as_arrays;
199+
recursive_initialization_config.pointers_to_treat_equal =
200+
function_arguments_to_treat_equal;
186201
recursive_initialization_config.array_name_to_associated_array_size_variable =
187202
function_argument_to_associated_array_size;
188203
for(const auto &pair : function_argument_to_associated_array_size)
@@ -238,7 +253,7 @@ void function_call_harness_generatort::implt::generate_initialisation_code_for(
238253
{
239254
recursive_initialization->initialize(
240255
lhs, from_integer(0, signed_int_type()), block);
241-
if(lhs.type().id() == ID_pointer)
256+
if(recursive_initialization->needs_freeing(lhs))
242257
global_pointers.insert(to_symbol_expr(lhs));
243258
}
244259

@@ -258,6 +273,46 @@ void function_call_harness_generatort::validate_options(
258273
"--" COMMON_HARNESS_GENERATOR_MIN_ARRAY_SIZE_OPT
259274
" --" COMMON_HARNESS_GENERATOR_MAX_ARRAY_SIZE_OPT};
260275
}
276+
277+
auto function_to_call = goto_model.symbol_table.lookup_ref(p_impl->function);
278+
auto ftype = to_code_type(function_to_call.type);
279+
for(auto const &pointer_id : p_impl->function_parameters_to_treat_equal)
280+
{
281+
std::string decorated_pointer_id =
282+
id2string(p_impl->function) + "::" + id2string(pointer_id);
283+
bool is_a_param = false;
284+
typet common_type = empty_typet{};
285+
for(auto const &formal_param : ftype.parameters())
286+
{
287+
if(formal_param.get_identifier() == decorated_pointer_id)
288+
{
289+
is_a_param = true;
290+
if(formal_param.type().id() != ID_pointer)
291+
{
292+
throw invalid_command_line_argument_exceptiont{
293+
id2string(pointer_id) + " is not a pointer parameter",
294+
"--" FUNCTION_HARNESS_GENERATOR_TREAT_POINTERS_EQUAL_OPT};
295+
}
296+
if(common_type.id() != ID_empty)
297+
{
298+
if(common_type != formal_param.type())
299+
{
300+
throw invalid_command_line_argument_exceptiont{
301+
"pointer arguments of conflicting type",
302+
"--" FUNCTION_HARNESS_GENERATOR_TREAT_POINTERS_EQUAL_OPT};
303+
}
304+
}
305+
else
306+
common_type = formal_param.type();
307+
}
308+
}
309+
if(!is_a_param)
310+
{
311+
throw invalid_command_line_argument_exceptiont{
312+
id2string(pointer_id) + " is not a parameter",
313+
"--" FUNCTION_HARNESS_GENERATOR_TREAT_POINTERS_EQUAL_OPT};
314+
}
315+
}
261316
}
262317

263318
const symbolt &
@@ -348,6 +403,11 @@ function_call_harness_generatort::implt::declare_arguments(
348403
function_arguments_to_treat_as_cstrings.insert(argument_name);
349404
}
350405

406+
if(function_parameters_to_treat_equal.count(parameter_name) != 0)
407+
{
408+
function_arguments_to_treat_equal.insert(argument_name);
409+
}
410+
351411
auto it = function_parameter_to_associated_array_size.find(parameter_name);
352412
if(it != function_parameter_to_associated_array_size.end())
353413
{
@@ -377,7 +437,7 @@ void function_call_harness_generatort::implt::call_function(
377437
for(auto const &argument : arguments)
378438
{
379439
generate_initialisation_code_for(function_body, argument);
380-
if(argument.type().id() == ID_pointer)
440+
if(recursive_initialization->needs_freeing(argument))
381441
global_pointers.insert(to_symbol_expr(argument));
382442
}
383443
code_function_callt function_call{function_to_call.symbol_expr(),

src/goto-harness/function_harness_generator_options.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ Author: Diffblue Ltd.
1515
#define FUNCTION_HARNESS_GENERATOR_NONDET_GLOBALS_OPT "nondet-globals"
1616
#define FUNCTION_HARNESS_GENERATOR_TREAT_POINTER_AS_ARRAY_OPT \
1717
"treat-pointer-as-array"
18+
#define FUNCTION_HARNESS_GENERATOR_TREAT_POINTERS_EQUAL_OPT \
19+
"treat-pointers-equal"
1820
#define FUNCTION_HARNESS_GENERATOR_ASSOCIATED_ARRAY_SIZE_OPT \
1921
"associated-array-size"
2022
#define FUNCTION_HARNESS_GENERATOR_TREAT_POINTER_AS_CSTRING \
@@ -25,6 +27,7 @@ Author: Diffblue Ltd.
2527
"(" FUNCTION_HARNESS_GENERATOR_FUNCTION_OPT "):" \
2628
"(" FUNCTION_HARNESS_GENERATOR_NONDET_GLOBALS_OPT ")" \
2729
"(" FUNCTION_HARNESS_GENERATOR_TREAT_POINTER_AS_ARRAY_OPT "):" \
30+
"(" FUNCTION_HARNESS_GENERATOR_TREAT_POINTERS_EQUAL_OPT "):" \
2831
"(" FUNCTION_HARNESS_GENERATOR_ASSOCIATED_ARRAY_SIZE_OPT "):" \
2932
"(" FUNCTION_HARNESS_GENERATOR_TREAT_POINTER_AS_CSTRING "):" \
3033
// FUNCTION_HARNESS_GENERATOR_OPTIONS
@@ -43,6 +46,9 @@ Author: Diffblue Ltd.
4346
"--" FUNCTION_HARNESS_GENERATOR_TREAT_POINTER_AS_ARRAY_OPT \
4447
" p treat the function parameter with the name `p' as\n" \
4548
" an array\n" \
49+
"--" FUNCTION_HARNESS_GENERATOR_TREAT_POINTERS_EQUAL_OPT \
50+
" p,q treat the function parameter with the name `q' equal\n" \
51+
" to parameter `q'\n" \
4652
"--" FUNCTION_HARNESS_GENERATOR_ASSOCIATED_ARRAY_SIZE_OPT \
4753
" array_name:size_name\n" \
4854
" set the parameter <size_name> to the size" \

src/goto-harness/recursive_initialization.cpp

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,19 @@ void recursive_initializationt::initialize(
100100
const exprt &depth,
101101
code_blockt &body)
102102
{
103+
if(
104+
lhs.id() == ID_symbol &&
105+
should_be_treated_equal(to_symbol_expr(lhs).get_identifier()))
106+
{
107+
if(common_arguments_origin.has_value())
108+
{
109+
body.add(code_assignt{lhs, *common_arguments_origin});
110+
return;
111+
}
112+
else
113+
common_arguments_origin = lhs;
114+
}
115+
103116
const irep_idt &fun_name = build_constructor(lhs);
104117
const symbolt &fun_symbol = goto_model.symbol_table.lookup_ref(fun_name);
105118

@@ -280,6 +293,13 @@ bool recursive_initializationt::should_be_treated_as_array(
280293
initialization_config.pointers_to_treat_as_arrays.end();
281294
}
282295

296+
bool recursive_initializationt::should_be_treated_equal(
297+
const irep_idt &pointer_name) const
298+
{
299+
return initialization_config.pointers_to_treat_equal.find(pointer_name) !=
300+
initialization_config.pointers_to_treat_equal.end();
301+
}
302+
283303
bool recursive_initializationt::is_array_size_parameter(
284304
const irep_idt &cmdline_arg) const
285305
{
@@ -763,3 +783,17 @@ code_blockt recursive_initializationt::build_dynamic_array_constructor(
763783

764784
return body;
765785
}
786+
787+
bool recursive_initializationt::needs_freeing(const exprt &expr) const
788+
{
789+
if(expr.type().id() != ID_pointer)
790+
return false;
791+
if(common_arguments_origin.has_value() && expr.id() == ID_symbol)
792+
{
793+
auto origin_name =
794+
to_symbol_expr(*common_arguments_origin).get_identifier();
795+
auto expr_name = to_symbol_expr(expr).get_identifier();
796+
return origin_name == expr_name;
797+
}
798+
return true;
799+
}

src/goto-harness/recursive_initialization.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ struct recursive_initialization_configt
3737
std::map<irep_idt, irep_idt> array_name_to_associated_array_size_variable;
3838

3939
std::set<irep_idt> pointers_to_treat_as_cstrings;
40+
std::set<irep_idt> pointers_to_treat_equal;
4041

4142
std::string to_string() const; // for debugging purposes
4243

@@ -81,19 +82,23 @@ class recursive_initializationt
8182
!has_prefix(id2string(symbol.name), CPROVER_PREFIX));
8283
}
8384

85+
bool needs_freeing(const exprt &expr) const;
86+
8487
private:
8588
const recursive_initialization_configt initialization_config;
8689
goto_modelt &goto_model;
8790
irep_idt max_depth_var_name;
8891
irep_idt min_depth_var_name;
8992
type_constructor_namest type_constructor_names;
93+
optionalt<exprt> common_arguments_origin;
9094

9195
/// Get the malloc function as symbol exprt,
9296
/// and inserts it into the goto-model if it doesn't
9397
/// exist already.
9498
symbol_exprt get_malloc_function();
9599

96100
bool should_be_treated_as_array(const irep_idt &pointer_name) const;
101+
bool should_be_treated_equal(const irep_idt &pointer_name) const;
97102
bool is_array_size_parameter(const irep_idt &cmdline_arg) const;
98103
optionalt<irep_idt>
99104
get_associated_size_variable(const irep_idt &array_name) const;

0 commit comments

Comments
 (0)