Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[CONTRACTS] DFCC loop assigns infererence with functions inlined #8490

Open
wants to merge 1 commit into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions regression/contracts-dfcc/loop_assigns_inference-04/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
struct hole
{
int pos;
};

void set_len(struct hole *h, unsigned long int new_len)
{
h->pos = new_len;
}

int main()
{
int i = 0;
struct hole h;
h.pos = 0;
for(i = 0; i < 5; i++)
// __CPROVER_assigns(h.pos, i)
__CPROVER_loop_invariant(h.pos == i)
{
set_len(&h, h.pos + 1);
}
}
14 changes: 14 additions & 0 deletions regression/contracts-dfcc/loop_assigns_inference-04/test.desc
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
CORE dfcc-only
main.c
--dfcc main --apply-loop-contracts
^EXIT=0$
^SIGNAL=0$
^\[main.loop_invariant_base.\d+\] line \d+ Check invariant before entry for loop .*: SUCCESS$
^\[main.loop_invariant_base.\d+\] line \d+ Check invariant before entry for loop .*: SUCCESS$
^\[main.loop_invariant_step.\d+\] line \d+ Check invariant after step for loop .*: SUCCESS$
^\[main.loop_step_unwinding.\d+\] line \d+ Check step was unwound for loop .*: SUCCESS$
^\[set_len.assigns.\d+\] line \d+ Check that h\-\>pos is assignable: SUCCESS
^VERIFICATION SUCCESSFUL$
--
--
This test checks assigns h->pos is inferred correctly.
22 changes: 22 additions & 0 deletions regression/contracts/loop_assigns_inference-04/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
struct hole
{
int pos;
};

void set_len(struct hole *h, unsigned long int new_len)
{
h->pos = new_len;
}

int main()
{
int i = 0;
struct hole h;
h.pos = 0;
for(i = 0; i < 5; i++)
// __CPROVER_assigns(h.pos, i)
__CPROVER_loop_invariant(h.pos == i)
{
set_len(&h, h.pos + 1);
}
}
10 changes: 10 additions & 0 deletions regression/contracts/loop_assigns_inference-04/test.desc
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
CORE
main.c
--apply-loop-contracts
^EXIT=0$
^SIGNAL=0$
^\[main.\d+\] .* Check loop invariant before entry: SUCCESS$
^VERIFICATION SUCCESSFUL$
--
--
This test checks assigns h->pos is inferred correctly.
39 changes: 29 additions & 10 deletions src/goto-instrument/contracts/dynamic-frames/dfcc_cfg_info.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -329,7 +329,7 @@
const dfcc_loop_nesting_grapht &loop_nesting_graph,
const std::size_t loop_id,
const irep_idt &function_id,
local_may_aliast &local_may_alias,
const assignst &inferred_assigns,
const bool check_side_effect,
message_handlert &message_handler,
const namespacet &ns)
Expand Down Expand Up @@ -380,13 +380,11 @@
else
{
// infer assigns clause targets if none given
auto inferred = dfcc_infer_loop_assigns(
local_may_alias, loop.instructions, loop.head->source_location(), ns);
log.warning() << "No assigns clause provided for loop " << function_id
<< "." << loop.latch->loop_number << " at "
<< loop.head->source_location() << ". The inferred set {";
bool first = true;
for(const auto &expr : inferred)
for(const auto &expr : inferred_assigns)
{
if(!first)
{
Expand All @@ -398,7 +396,7 @@
log.warning() << "} might be incomplete or imprecise, please provide an "
"assigns clause if the analysis fails."
<< messaget::eom;
result.assigns.swap(inferred);
result.assigns = inferred_assigns;
}

if(result.decreases_clauses.empty())
Expand All @@ -416,14 +414,16 @@
const dfcc_loop_nesting_grapht &loop_nesting_graph,
const std::size_t loop_id,
const irep_idt &function_id,
goto_functiont &goto_function,
const std::map<std::size_t, dfcc_loop_infot> &loop_info_map,
dirtyt &dirty,
local_may_aliast &local_may_alias,
const assignst &inferred_assigns,
const bool check_side_effect,
message_handlert &message_handler,
dfcc_libraryt &library,
symbol_table_baset &symbol_table)
{
const namespacet ns(symbol_table);
std::unordered_set<irep_idt> loop_locals =
gen_loop_locals_set(loop_nesting_graph, loop_id);

Expand All @@ -433,12 +433,11 @@
dirty,
loop_info_map);

const namespacet ns(symbol_table);
struct contract_clausest contract_clauses = default_loop_contract_clauses(
loop_nesting_graph,
loop_id,
function_id,
local_may_alias,
inferred_assigns,
check_side_effect,
message_handler,
ns);
Expand Down Expand Up @@ -489,6 +488,7 @@
}

dfcc_cfg_infot::dfcc_cfg_infot(
goto_modelt &goto_model,

Check warning on line 491 in src/goto-instrument/contracts/dynamic-frames/dfcc_cfg_info.cpp

View check run for this annotation

Codecov / codecov/patch

src/goto-instrument/contracts/dynamic-frames/dfcc_cfg_info.cpp#L491

Added line #L491 was not covered by tests
const irep_idt &function_id,
goto_functiont &goto_function,
const exprt &top_level_write_set,
Expand All @@ -507,6 +507,9 @@
// Clean up possible fake loops that are due to do { ... } while(0);
simplify_gotos(goto_program, ns);

// From loop number to the inferred loop assigns.

Check warning on line 510 in src/goto-instrument/contracts/dynamic-frames/dfcc_cfg_info.cpp

View check run for this annotation

Codecov / codecov/patch

src/goto-instrument/contracts/dynamic-frames/dfcc_cfg_info.cpp#L510

Added line #L510 was not covered by tests
std::map<std::size_t, assignst> inferred_loop_assigns_map;

Check warning on line 512 in src/goto-instrument/contracts/dynamic-frames/dfcc_cfg_info.cpp

View check run for this annotation

Codecov / codecov/patch

src/goto-instrument/contracts/dynamic-frames/dfcc_cfg_info.cpp#L512

Added line #L512 was not covered by tests
if(loop_contract_config.apply_loop_contracts)
{
messaget log(message_handler);
Expand All @@ -527,9 +530,23 @@

auto topsorted = loop_nesting_graph.topsort();

bool has_loops_with_contracts = false;
for(const auto idx : topsorted)
{
topsorted_loops.push_back(idx);
has_loops_with_contracts |= has_contract(
loop_nesting_graph[idx].latch, loop_contract_config.check_side_effect);
}

// We infer loop assigns for all loops in the function.

Check warning on line 541 in src/goto-instrument/contracts/dynamic-frames/dfcc_cfg_info.cpp

View check run for this annotation

Codecov / codecov/patch

src/goto-instrument/contracts/dynamic-frames/dfcc_cfg_info.cpp#L541

Added line #L541 was not covered by tests
if(has_loops_with_contracts)
{
dfcc_infer_loop_assigns_for_function(
inferred_loop_assigns_map,
goto_model.goto_functions,
goto_function,
message_handler,

Check warning on line 548 in src/goto-instrument/contracts/dynamic-frames/dfcc_cfg_info.cpp

View check run for this annotation

Codecov / codecov/patch

src/goto-instrument/contracts/dynamic-frames/dfcc_cfg_info.cpp#L548

Added line #L548 was not covered by tests
ns);
}
}

Expand All @@ -549,19 +566,21 @@

// generate dfcc_cfg_loop_info for loops and add to loop_info_map
dirtyt dirty(goto_function);
local_may_aliast local_may_alias(goto_function);

for(const auto &loop_id : topsorted_loops)
{
auto inferred_loop_assigns =
inferred_loop_assigns_map[loop_nesting_graph[loop_id].latch->loop_number];
loop_info_map.insert(
{loop_id,
gen_dfcc_loop_info(
loop_nesting_graph,
loop_id,
function_id,
goto_function,

Check warning on line 580 in src/goto-instrument/contracts/dynamic-frames/dfcc_cfg_info.cpp

View check run for this annotation

Codecov / codecov/patch

src/goto-instrument/contracts/dynamic-frames/dfcc_cfg_info.cpp#L580

Added line #L580 was not covered by tests
loop_info_map,
dirty,
local_may_alias,
inferred_loop_assigns,

Check warning on line 583 in src/goto-instrument/contracts/dynamic-frames/dfcc_cfg_info.cpp

View check run for this annotation

Codecov / codecov/patch

src/goto-instrument/contracts/dynamic-frames/dfcc_cfg_info.cpp#L583

Added line #L583 was not covered by tests
loop_contract_config.check_side_effect,
message_handler,
library,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ Date: March 2023
#include <util/std_expr.h>
#include <util/symbol_table.h>

#include <goto-programs/goto_model.h>
#include <goto-programs/goto_program.h>

#include <goto-instrument/contracts/loop_contract_config.h>
Expand Down Expand Up @@ -242,6 +243,7 @@ class dfcc_cfg_infot
{
public:
dfcc_cfg_infot(
goto_modelt &goto_model,
const irep_idt &function_id,
goto_functiont &goto_function,
const exprt &top_level_write_set,
Expand Down
Loading
Loading