I tried the list example (Example 2.23 on page 37, in Section "Function Contracts") from the ACSL manual, but I hid the implementation of incr_list
and changed the return type. Full source below.
struct list {
int hd;
struct list *next;
};
/*@ inductive reachable{L} (struct list *root,struct list *to) {
@ case empty{L}: \forall struct list *l; reachable(l,l) ;
@ case non_empty{L}:\forall struct list *l1,*l2;
@ \valid(l1) && reachable(l1->next,l2) ==> reachable(l1,l2) ;
@ }
*/
// The requires clause forbids giving a circular list
/*@ requires reachable(p,\null);
@ assigns \result \from { q->hd | struct list *q ; reachable(p,q) } ;
@
*/
int incr_list(struct list *p);
int main() {
struct list l = {.hd=0, .next=0};
struct list l2 = {.hd=1, .next=&l};
return incr_list(&l2);
}
I am running this with the slicer frama-c test-1.c -slice-calls incr_list -then-last -print
. The output seems fine, but I worry about the warnings that are generated when running this command:
[inout] test-1.c:23: Warning:
failed to interpret inputs in assigns clause 'assigns \result
\from {q->hd |
struct list *q
; reachable{Old}(p, q)};'
[eva:alarm] test-1.c:23: Warning:
function incr_list: precondition got status unknown.
[eva] test-1.c:23: Warning:
cannot interpret 'from'
clause 'assigns \result \from {q->hd | struct list *q; reachable{Old}(p, q)};'
(error in AST: non-lval term {q->hd | struct list *q; reachable{Old}(p, q)}; please report)
In particular the first and third one. It seems like something unexpected is happening? I don't quite understand what exact issue the tool is having here.