Skip to content

Commit 95f5db1

Browse files
Merge pull request #7763 from remi-delmas-3000/contracts-fix-loop-assigns-function-parameter
CONTRACTS: track function parameters explicitly
2 parents 2830a3b + 1beaa58 commit 95f5db1

File tree

4 files changed

+56
-0
lines changed

4 files changed

+56
-0
lines changed
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
#include <stdlib.h>
2+
3+
void decr(size_t n)
4+
{
5+
for(; n--;)
6+
// clang-format off
7+
__CPROVER_assigns(n)
8+
__CPROVER_decreases(n)
9+
// clang-format on
10+
{
11+
}
12+
}
13+
14+
int main()
15+
{
16+
size_t n;
17+
decr(n);
18+
return 0;
19+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
CORE dfcc-only
2+
main.c
3+
--dfcc main --apply-loop-contracts --enforce-contract decr
4+
^\[decr.loop_assigns.\d+] line \d+ Check assigns clause inclusion for loop decr.0: SUCCESS$
5+
^VERIFICATION SUCCESSFUL$
6+
^EXIT=0$
7+
^SIGNAL=0$
8+
--
9+
--
10+
This test checks that function parameters are automatically added to the function
11+
write set when they are assigned from the body of a loop.

src/goto-instrument/contracts/dynamic-frames/dfcc_cfg_info.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,13 @@ class dfcc_cfg_infot
291291
return top_level_write_set;
292292
}
293293

294+
/// Returns the set of top level symbols that must be tracked explicitly in
295+
/// the top level write set of the function.
296+
const std::unordered_set<irep_idt> &get_top_level_tracked()
297+
{
298+
return top_level_tracked;
299+
}
300+
294301
private:
295302
const irep_idt &function_id;
296303
goto_functiont &goto_function;

src/goto-instrument/contracts/dynamic-frames/dfcc_instrument.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -490,6 +490,25 @@ void dfcc_instrumentt::instrument_goto_function(
490490
insert_record_dead_call(function_id, write_set, local_static, end, body);
491491
}
492492

493+
const code_typet &code_type = to_code_type(
494+
dfcc_utilst::get_function_symbol(goto_model.symbol_table, function_id)
495+
.type);
496+
const auto &top_level_tracked = cfg_info.get_top_level_tracked();
497+
498+
// automatically add/remove function parameters that must be tracked in the
499+
// function write set (they must be explicitly tracked if they are assigned
500+
// in the body of a loop)
501+
for(const auto &param : code_type.parameters())
502+
{
503+
const irep_idt &param_id = param.get_identifier();
504+
if(top_level_tracked.find(param_id) != top_level_tracked.end())
505+
{
506+
symbol_exprt param_symbol{param.get_identifier(), param.type()};
507+
insert_add_decl_call(function_id, write_set, param_symbol, begin, body);
508+
insert_record_dead_call(function_id, write_set, param_symbol, end, body);
509+
}
510+
}
511+
493512
remove_skip(body);
494513

495514
// recalculate numbers, etc.

0 commit comments

Comments
 (0)