Theory Reference: Separation Logic ¶
cvc5 supports a syntax for separation logic as an extension of the SMT-LIB 2.6 language.
Signature ¶
Given a (decidable) base theory \(T\) , cvc5 implements a decision procedure for quantifier-free \(SL(T)_{Loc,Data}\) formulas [ RISK16 ] , where \(Loc\) and \(Data\) are any sort belonging to \(T\) .
A \(SL(T)_{Loc,Data}\) formula is one from the following grammar:
F : L | sep.emp | (pto t u) | (sep F1 ... Fn) | (wand F1 F2) | ~F1 | F1 op ... op Fn
where
op
is any classical Boolean connective,
t
and
u
are terms
built from symbols in the signature of
\(T\)
of sort
\(Loc\)
and
\(Data\)
respectively, and
\(L\)
is a
\(T\)
-literal.
The operator
sep.emp
denotes the empty heap constraint, the operator
pto
denotes the points-to predicate, the operator
sep
denotes separation start
and is variadic, and the operator
wand
denote magic wand.
Semantics ¶
A satisfiability relation \(I,h \models_{SL} \varphi\) is defined for \(SL(T)_{Loc,Data}\) formulas \(\varphi\) , where \(I\) is an interpretation, and \(h\) is a heap.
The semantics of separation logic operators are as follows:
\(I,h \models_{SL} L\) |
Iff |
\(I \models L\) , if \(L\) is a \(T\) -literal |
\(I,h \models_{SL}\) (emp \(t \ u\) ) |
Iff |
\(h = \emptyset\) |
\(I,h \models_{SL}\) (pto \(t \ u\) ) |
Iff |
\(h = \{(t^I,u^I)\} \text{ and } t^I\not=nil^I\) |
\(I,h \models_{SL}\) (sep \(\phi_1 \ldots \phi_n)\) |
Iff |
there exist heaps \(h_1,\ldots,h_n\) s.t. \(h=h_1\uplus \ldots \uplus h_n\) and \(I,h_i \models_{SL} \phi_i, i = 1,\ldots,n\) |
\(I,h \models_{SL}\) (wand \(\phi_1 \ \phi_2\) ) |
Iff |
for all heaps \(h'\) if \(h'\#h\) and \(I,h' \models_{SL} \phi_1\) then \(I,h'\uplus h \models_{SL} \phi_2\) |
where \(h_1 \uplus \ldots \uplus h_n\) denotes the disjoint union of heaps \(h_1, \ldots, h_n\) and \(h'\#h\) denotes that heaps \(h'\) and \(h\) are disjoint, and \(nil\) is a distinguished variable of sort \(Loc\) . All classical Boolean connectives are interpreted as expected.
Syntax ¶
Separation logic in cvc5 requires the
QF_ALL
logic, and for the types of the heap to be declared via the
declare-heap
command:
(declare-heap (T1 T2))
This command must be executed when the solver is in its Start mode (see page 52 of the SMT-LIB 2.6 standard [ BFT17 ] ). This command sets the location type of the heap \(Loc\) to \(T1\) and the data type \(Data\) to \(T2\) , where \(T1\) and \(T2\) are any defined types. This command can only be executed once in any context, and is reset only via a reset command.
The syntax for the operators of separation logic is summarized in the following
table. For the C++ API examples in this table, we assume that we have created
a
cvc5::Solver
object.
SMTLIB language |
C++ API |
|
Logic String |
|
|
Empty Heap |
|
where
|
Points-To |
|
|
Separation Star |
|
|
Magic Wand |
|
|
Nil Element |
|
|
Examples ¶
The following input on heaps
Int
->
Int
is unsatisfiable:
(set-logic QF_ALL)
(declare-heap (Int Int))
(set-info :status unsat)
(declare-const x Int)
(declare-const a Int)
(declare-const b Int)
(assert (and (pto x a) (pto x b)))
(assert (not (= a b)))
(check-sat)
The following input on heaps
U
->
Int
is satisfiable. Notice that the
formula
(not
sep.emp)
is satisfied by heaps
U
->
Int
whose domain is
non-empty.
(set-logic QF_ALL)
(set-info :status sat)
(declare-sort U 0)
(declare-heap (U Int))
(declare-const x U)
(declare-const a Int)
(assert (and (not sep.emp) (pto x a)))
(check-sat)
The following input on heaps
Int
->
Node
is satisfiable, where
Node
denotes a user-defined inductive
Theory Reference: Datatypes
.
(set-logic QF_ALL)
(set-info :status sat)
(declare-const x Int)
(declare-const y Int)
(declare-const z Int)
(declare-datatype Node ((node (data Int) (left Int) (right Int))))
(declare-heap (Int Node))
(assert (pto x (node 0 y z)))
(check-sat)
Note
Given a separation logic input, the sorts \(Loc\) and \(Data\) declared via the declare-heap command must match all separation logic predicates in the input. cvc5 does not accept an input such as:
(set-logic QF_ALL)
(declare-sort U 0)
(declare-heap (U Int))
(declare-const x U)
(assert (and (pto x 0) (pto 1 2)))
(check-sat)
since the second points-to predicate uses Int for its location type.