Skip to content

Commit ebbed91

Browse files
committed
Make sure free symbols are declared in SMT2_conv after quantifier rewriting
1 parent 7e5d539 commit ebbed91

File tree

4 files changed

+53
-35
lines changed

4 files changed

+53
-35
lines changed
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
#include <assert.h>
2+
#include <stdbool.h>
3+
#include <stddef.h>
4+
5+
#define N 16
6+
7+
void main()
8+
{
9+
int a[N];
10+
a[10] = 0;
11+
bool flag = true;
12+
for(size_t j = 0; j < N; ++j)
13+
// clang-format off
14+
__CPROVER_assigns(j, __CPROVER_object_whole(a))
15+
__CPROVER_loop_invariant(j <= N)
16+
__CPROVER_loop_invariant((j != 0) ==> __CPROVER_forall {
17+
int k;
18+
(0 <= k && k < N) ==> (a[k] == 1)
19+
})
20+
// clang-format on
21+
{
22+
for(size_t i = 0; i < N; ++i)
23+
// clang-format off
24+
__CPROVER_assigns(i, __CPROVER_object_whole(a))
25+
__CPROVER_loop_invariant(0 <= i && i <= N)
26+
__CPROVER_loop_invariant(__CPROVER_forall { int k; k < i ==> a[k] == 1 })
27+
28+
// clang-format on
29+
{
30+
a[i] = 1;
31+
}
32+
}
33+
assert(a[10] == 1);
34+
}

regression/contracts-dfcc/quantifiers-loop-fail/test.desc renamed to regression/contracts-dfcc/quantifiers-loop-05/test.desc

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
11
CORE dfcc-only
22
main.c
33
--dfcc main --apply-loop-contracts _ --smt2
4-
^EXIT=6$
4+
^EXIT=0$
55
^SIGNAL=0$
6-
^SMT2 solver returned error message:$
7-
^.*\"line \d+ column \d+: unknown constant .*$
8-
^VERIFICATION ERROR$
6+
^VERIFICATION SUCCESSFUL$
97
--
108
^warning: ignoring
119
--

regression/contracts-dfcc/quantifiers-loop-fail/main.c

Lines changed: 0 additions & 27 deletions
This file was deleted.

src/solvers/smt2/smt2_conv.cpp

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4908,17 +4908,30 @@ void smt2_convt::find_symbols(const exprt &expr)
49084908

49094909
if(expr.id() == ID_exists || expr.id() == ID_forall)
49104910
{
4911+
std::unordered_map<irep_idt, std::optional<identifiert>> hidden_syms;
4912+
49114913
// do not declare the quantified symbol, but record
49124914
// as 'bound symbol'
49134915
const auto &q_expr = to_quantifier_expr(expr);
49144916
for(const auto &symbol : q_expr.variables())
49154917
{
49164918
const auto identifier = symbol.get_identifier();
4917-
identifiert &id = identifier_map[identifier];
4918-
id.type = symbol.type();
4919-
id.is_bound = true;
4919+
auto id_entry = identifier_map.insert({identifier, identifiert{}});
4920+
hidden_syms.insert(
4921+
{identifier,
4922+
id_entry.second ? std::nullopt
4923+
: std::optional{id_entry.first->second}});
4924+
id_entry.first->second.is_bound = true;
49204925
}
49214926
find_symbols(q_expr.where());
4927+
for(const auto &[id, hidden_val] : hidden_syms)
4928+
{
4929+
auto previous_entry = identifier_map.find(id);
4930+
if(!hidden_val.has_value())
4931+
identifier_map.erase(previous_entry);
4932+
else
4933+
previous_entry->second = std::move(*hidden_val);
4934+
}
49224935
return;
49234936
}
49244937

@@ -4943,7 +4956,7 @@ void smt2_convt::find_symbols(const exprt &expr)
49434956

49444957
identifiert &id=identifier_map[identifier];
49454958

4946-
if(id.type.is_nil())
4959+
if(!id.is_bound && id.type.is_nil())
49474960
{
49484961
id.type=expr.type();
49494962

0 commit comments

Comments
 (0)