Skip to content

Commit 0040862

Browse files
committed
Extend to clusters of equal parameters
Specified by a semi-colon separated list of comma separated names.
1 parent 9db8bd4 commit 0040862

File tree

6 files changed

+115
-60
lines changed

6 files changed

+115
-60
lines changed
Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,27 @@
11
#include <assert.h>
22
#include <stdlib.h>
33

4-
typedef struct st
4+
typedef struct st1
55
{
66
struct st *next;
77
int data;
8-
} st_t;
8+
} st1_t;
99

10-
void func(st_t *p, st_t *q)
10+
typedef struct st2
11+
{
12+
struct st *next;
13+
int data;
14+
} st2_t;
15+
16+
void func(st1_t *p, st1_t *q, st2_t *r, st2_t *s, st2_t *t)
1117
{
1218
assert(p != NULL);
1319
assert(p->next != NULL);
1420

1521
assert(p == q);
22+
23+
assert((void *)p != (void *)r);
24+
25+
assert(r == s);
26+
assert(r == t);
1627
}

regression/goto-harness/pointer-function-parameters-equal-simple/test.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
CORE
22
main.c
3-
--function func --min-null-tree-depth 10 --max-nondet-tree-depth 3 --harness-type call-function --treat-pointers-equal p,q
3+
--function func --min-null-tree-depth 10 --max-nondet-tree-depth 3 --harness-type call-function --treat-pointers-equal 'p,q;r,s,t'
44
^EXIT=0$
55
^SIGNAL=0$
66
VERIFICATION SUCCESSFUL

src/goto-harness/function_call_harness_generator.cpp

Lines changed: 53 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,8 @@ 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;
51+
std::vector<std::set<irep_idt>> function_parameters_to_treat_equal;
52+
std::vector<std::set<irep_idt>> function_arguments_to_treat_equal;
5353

5454
std::set<irep_idt> function_parameters_to_treat_as_cstrings;
5555
std::set<irep_idt> function_arguments_to_treat_as_cstrings;
@@ -119,9 +119,14 @@ void function_call_harness_generatort::handle_option(
119119
{
120120
for(auto const &value : values)
121121
{
122-
for(auto const &param_id : split_string(value, ','))
122+
for(auto const &param_cluster : split_string(value, ';'))
123123
{
124-
p_impl->function_parameters_to_treat_equal.insert(param_id);
124+
std::set<irep_idt> equal_param_set;
125+
for(auto const &param_id : split_string(param_cluster, ','))
126+
{
127+
equal_param_set.insert(param_id);
128+
}
129+
p_impl->function_parameters_to_treat_equal.push_back(equal_param_set);
125130
}
126131
}
127132
}
@@ -276,41 +281,44 @@ void function_call_harness_generatort::validate_options(
276281

277282
auto function_to_call = goto_model.symbol_table.lookup_ref(p_impl->function);
278283
auto ftype = to_code_type(function_to_call.type);
279-
for(auto const &pointer_id : p_impl->function_parameters_to_treat_equal)
284+
for(auto const &equal_cluster : p_impl->function_parameters_to_treat_equal)
280285
{
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+
for(auto const &pointer_id : equal_cluster)
286287
{
287-
if(formal_param.get_identifier() == decorated_pointer_id)
288+
std::string decorated_pointer_id =
289+
id2string(p_impl->function) + "::" + id2string(pointer_id);
290+
bool is_a_param = false;
291+
typet common_type = empty_typet{};
292+
for(auto const &formal_param : ftype.parameters())
288293
{
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)
294+
if(formal_param.get_identifier() == decorated_pointer_id)
297295
{
298-
if(common_type != formal_param.type())
296+
is_a_param = true;
297+
if(formal_param.type().id() != ID_pointer)
299298
{
300299
throw invalid_command_line_argument_exceptiont{
301-
"pointer arguments of conflicting type",
300+
id2string(pointer_id) + " is not a pointer parameter",
302301
"--" FUNCTION_HARNESS_GENERATOR_TREAT_POINTERS_EQUAL_OPT};
303302
}
303+
if(common_type.id() != ID_empty)
304+
{
305+
if(common_type != formal_param.type())
306+
{
307+
throw invalid_command_line_argument_exceptiont{
308+
"pointer arguments of conflicting type",
309+
"--" FUNCTION_HARNESS_GENERATOR_TREAT_POINTERS_EQUAL_OPT};
310+
}
311+
}
312+
else
313+
common_type = formal_param.type();
304314
}
305-
else
306-
common_type = formal_param.type();
307315
}
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};
316+
if(!is_a_param)
317+
{
318+
throw invalid_command_line_argument_exceptiont{
319+
id2string(pointer_id) + " is not a parameter",
320+
"--" FUNCTION_HARNESS_GENERATOR_TREAT_POINTERS_EQUAL_OPT};
321+
}
314322
}
315323
}
316324
}
@@ -403,11 +411,6 @@ function_call_harness_generatort::implt::declare_arguments(
403411
function_arguments_to_treat_as_cstrings.insert(argument_name);
404412
}
405413

406-
if(function_parameters_to_treat_equal.count(parameter_name) != 0)
407-
{
408-
function_arguments_to_treat_equal.insert(argument_name);
409-
}
410-
411414
auto it = function_parameter_to_associated_array_size.find(parameter_name);
412415
if(it != function_parameter_to_associated_array_size.end())
413416
{
@@ -425,6 +428,22 @@ function_call_harness_generatort::implt::declare_arguments(
425428
{argument_name, associated_array_size_argument->second});
426429
}
427430
}
431+
432+
// translate the parameter to argument also in the equality clusters
433+
for(auto const &equal_cluster : function_parameters_to_treat_equal)
434+
{
435+
std::set<irep_idt> cluster_argument_names;
436+
for(auto const &parameter_name : equal_cluster)
437+
{
438+
INVARIANT(
439+
parameter_name_to_argument_name.count(parameter_name) != 0,
440+
id2string(parameter_name) + " is not a parameter");
441+
cluster_argument_names.insert(
442+
parameter_name_to_argument_name[parameter_name]);
443+
}
444+
function_arguments_to_treat_equal.push_back(cluster_argument_names);
445+
}
446+
428447
allocate_objects.declare_created_symbols(function_body);
429448
return arguments;
430449
}

src/goto-harness/function_harness_generator_options.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,8 @@ Author: Diffblue Ltd.
4747
" p treat the function parameter with the name `p' as\n" \
4848
" an array\n" \
4949
"--" 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" \
50+
" p,q,r[;s,t] treat the function parameters `q,r' equal\n" \
51+
" to parameter `p'; `s` to `t` and so on\n" \
5252
"--" FUNCTION_HARNESS_GENERATOR_ASSOCIATED_ARRAY_SIZE_OPT \
5353
" array_name:size_name\n" \
5454
" set the parameter <size_name> to the size" \

src/goto-harness/recursive_initialization.cpp

Lines changed: 42 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -93,24 +93,32 @@ recursive_initializationt::recursive_initializationt(
9393
initialization_config.min_null_tree_depth,
9494
signed_int_type())))
9595
{
96+
common_arguments_origins.resize(
97+
this->initialization_config.pointers_to_treat_equal.size());
9698
}
9799

98100
void recursive_initializationt::initialize(
99101
const exprt &lhs,
100102
const exprt &depth,
101103
code_blockt &body)
102104
{
103-
if(
104-
lhs.id() == ID_symbol &&
105-
should_be_treated_equal(to_symbol_expr(lhs).get_identifier()))
105+
if(lhs.id() == ID_symbol)
106106
{
107-
if(common_arguments_origin.has_value())
107+
const auto maybe_cluster_index =
108+
find_equal_cluster(to_symbol_expr(lhs).get_identifier());
109+
if(maybe_cluster_index.has_value())
108110
{
109-
body.add(code_assignt{lhs, *common_arguments_origin});
110-
return;
111+
if(common_arguments_origins[*maybe_cluster_index].has_value())
112+
{
113+
body.add(
114+
code_assignt{lhs, *common_arguments_origins[*maybe_cluster_index]});
115+
return;
116+
}
117+
else
118+
{
119+
common_arguments_origins[*maybe_cluster_index] = lhs;
120+
}
111121
}
112-
else
113-
common_arguments_origin = lhs;
114122
}
115123

116124
const irep_idt &fun_name = build_constructor(lhs);
@@ -293,11 +301,17 @@ bool recursive_initializationt::should_be_treated_as_array(
293301
initialization_config.pointers_to_treat_as_arrays.end();
294302
}
295303

296-
bool recursive_initializationt::should_be_treated_equal(
297-
const irep_idt &pointer_name) const
304+
optionalt<std::size_t>
305+
recursive_initializationt::find_equal_cluster(const irep_idt &name) const
298306
{
299-
return initialization_config.pointers_to_treat_equal.find(pointer_name) !=
300-
initialization_config.pointers_to_treat_equal.end();
307+
for(size_t index = 0;
308+
index != initialization_config.pointers_to_treat_equal.size();
309+
++index)
310+
{
311+
if(initialization_config.pointers_to_treat_equal[index].count(name) != 0)
312+
return index;
313+
}
314+
return {};
301315
}
302316

303317
bool recursive_initializationt::is_array_size_parameter(
@@ -786,14 +800,25 @@ code_blockt recursive_initializationt::build_dynamic_array_constructor(
786800

787801
bool recursive_initializationt::needs_freeing(const exprt &expr) const
788802
{
789-
if(expr.type().id() != ID_pointer)
803+
if(expr.type().id() != ID_pointer || expr.type().id() == ID_code)
790804
return false;
791-
if(common_arguments_origin.has_value() && expr.id() == ID_symbol)
805+
if(expr.id() == ID_symbol)
792806
{
793-
auto origin_name =
794-
to_symbol_expr(*common_arguments_origin).get_identifier();
795807
auto expr_name = to_symbol_expr(expr).get_identifier();
796-
return origin_name == expr_name;
808+
if(find_equal_cluster(expr_name).has_value())
809+
{
810+
for(auto const &origin_expr : common_arguments_origins)
811+
{
812+
if(!origin_expr.has_value())
813+
continue;
814+
INVARIANT(
815+
origin_expr->id() == ID_symbol, "common origin is not a symbol");
816+
auto origin_name = to_symbol_expr(*origin_expr).get_identifier();
817+
if(origin_name == expr_name)
818+
return true;
819+
}
820+
return false;
821+
}
797822
}
798823
return true;
799824
}

src/goto-harness/recursive_initialization.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +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;
40+
std::vector<std::set<irep_idt>> pointers_to_treat_equal;
4141

4242
std::string to_string() const; // for debugging purposes
4343

@@ -90,15 +90,15 @@ class recursive_initializationt
9090
irep_idt max_depth_var_name;
9191
irep_idt min_depth_var_name;
9292
type_constructor_namest type_constructor_names;
93-
optionalt<exprt> common_arguments_origin;
93+
std::vector<optionalt<exprt>> common_arguments_origins;
9494

9595
/// Get the malloc function as symbol exprt,
9696
/// and inserts it into the goto-model if it doesn't
9797
/// exist already.
9898
symbol_exprt get_malloc_function();
9999

100100
bool should_be_treated_as_array(const irep_idt &pointer_name) const;
101-
bool should_be_treated_equal(const irep_idt &pointer_name) const;
101+
optionalt<std::size_t> find_equal_cluster(const irep_idt &name) const;
102102
bool is_array_size_parameter(const irep_idt &cmdline_arg) const;
103103
optionalt<irep_idt>
104104
get_associated_size_variable(const irep_idt &array_name) const;

0 commit comments

Comments
 (0)