Commit 81629a4d authored by Allan Blanchard's avatar Allan Blanchard

Merge branch 'feature/wp/post-assigns' into 'master'

[wp] fix assigns with Post labels

See merge request frama-c/frama-c!2931
parents de09f05c d229ab90
...@@ -90,7 +90,7 @@ struct ...@@ -90,7 +90,7 @@ struct
(* Authorized written region from an assigns specification *) (* Authorized written region from an assigns specification *)
type effect = { type effect = {
e_pid : P.t ; (* Assign Property *) e_pid : P.t ; (* Assign Property *)
e_kind : a_kind ; (* Requires post effects (in case of loop-assigns) *) e_post : bool ; (* Requires post effects (loop-assigns or post-assigns) *)
e_label : c_label ; (* scope for collection *) e_label : c_label ; (* scope for collection *)
e_valid : L.sigma ; (* sigma where locations are filtered for validity *) e_valid : L.sigma ; (* sigma where locations are filtered for validity *)
e_region : L.region ; (* expected from spec *) e_region : L.region ; (* expected from spec *)
...@@ -444,21 +444,23 @@ struct ...@@ -444,21 +444,23 @@ struct
ainfo.a_assigns ainfo.a_assigns
in match authorized_region with in match authorized_region with
| None -> None | None -> None
| Some region -> Some { | Some region ->
e_pid = pid ; let post = match ainfo.a_kind with
e_kind = ainfo.a_kind ; | LoopAssigns -> true
e_label = from ; | StmtAssigns -> NormAtLabels.has_postassigns ainfo.a_assigns
e_valid = sigma ; in Some {
e_region = region ; e_pid = pid ;
e_warn = Warning.Set.empty ; e_post = post ;
} e_label = from ;
e_valid = sigma ;
e_region = region ;
e_warn = Warning.Set.empty ;
}
let cc_posteffect e vcs = let cc_posteffect e vcs =
match e.e_kind with if not e.e_post then vcs else
| StmtAssigns -> vcs let vc = { empty_vc with vars = L.vars e.e_region } in
| LoopAssigns -> Gmap.add (Gposteffect e.e_pid) (Splitter.singleton vc) vcs
let vc = { empty_vc with vars = L.vars e.e_region } in
Gmap.add (Gposteffect e.e_pid) (Splitter.singleton vc) vcs
(* -------------------------------------------------------------------------- *) (* -------------------------------------------------------------------------- *)
(* --- WP RULES : adding axioms, hypotheses and goals --- *) (* --- WP RULES : adding axioms, hypotheses and goals --- *)
...@@ -549,14 +551,13 @@ struct ...@@ -549,14 +551,13 @@ struct
vars = xs } vars = xs }
in in
let group = let group =
match e.e_kind with if not e.e_post then
| StmtAssigns -> Splitter.singleton (setup empty_vc)
Splitter.singleton (setup empty_vc) else
| LoopAssigns -> try Splitter.map setup (Gmap.find (Gposteffect e.e_pid) vcs)
try Splitter.map setup (Gmap.find (Gposteffect e.e_pid) vcs) with Not_found ->
with Not_found -> Wp_parameters.fatal "Missing post-effect for %a"
Wp_parameters.fatal "Missing post-effect for %a" WpPropId.pretty e.e_pid
WpPropId.pretty e.e_pid
in in
let target = match sloc with let target = match sloc with
| None -> Gprop e.e_pid | None -> Gprop e.e_pid
......
...@@ -74,6 +74,11 @@ let of_logic = function ...@@ -74,6 +74,11 @@ let of_logic = function
| BuiltinLabel LoopEntry -> loopentry | BuiltinLabel LoopEntry -> loopentry
| StmtLabel s -> stmt !s | StmtLabel s -> stmt !s
let is_post = function
| BuiltinLabel Post -> true
| FormalLabel a -> a = post
| _ -> false
let name = function FormalLabel a -> a | _ -> "" let name = function FormalLabel a -> a | _ -> ""
let lookup labels a = let lookup labels a =
......
...@@ -65,6 +65,9 @@ val of_logic : Cil_types.logic_label -> c_label ...@@ -65,6 +65,9 @@ val of_logic : Cil_types.logic_label -> c_label
labels. Ambiguous labels are: Old, LoopEntry and LoopCurrent, since labels. Ambiguous labels are: Old, LoopEntry and LoopCurrent, since
they points to different program points dependending on the context. *) they points to different program points dependending on the context. *)
val is_post : Cil_types.logic_label -> bool
(** Checks whether the logic-label is [Post] or [to_logic post] *)
val pretty : Format.formatter -> c_label -> unit val pretty : Format.formatter -> c_label -> unit
open Cil_types open Cil_types
......
...@@ -210,9 +210,27 @@ let preproc_assigns labels asgns = ...@@ -210,9 +210,27 @@ let preproc_assigns labels asgns =
let visitor = new norm_at labels in let visitor = new norm_at labels in
List.map (Visitor.visitFramacFrom visitor) asgns List.map (Visitor.visitFramacFrom visitor) asgns
let has_postassigns = function
| WritesAny -> false
| Writes froms ->
let exception HAS_POST in
let visitor = new norm_at (fun l ->
if Clabels.is_post l then raise HAS_POST
else Clabels.of_logic l
) in
try
List.iter
(fun fr -> ignore @@ Visitor.visitFramacFrom visitor fr)
froms ;
false
with HAS_POST ->
true
let catch_label_error ex txt1 txt2 = match ex with let catch_label_error ex txt1 txt2 = match ex with
| LabelError lab -> | LabelError lab ->
Wp_parameters.warning Wp_parameters.warning
"Unexpected label %a in %s : ignored %s" "Unexpected label %a in %s : ignored %s"
Wp_error.pp_logic_label lab txt1 txt2 Wp_error.pp_logic_label lab txt1 txt2
| _ -> raise ex | _ -> raise ex
(* -------------------------------------------------------------------------- *)
...@@ -42,5 +42,5 @@ val labels_predicate : (logic_label * logic_label) list -> label_mapping ...@@ -42,5 +42,5 @@ val labels_predicate : (logic_label * logic_label) list -> label_mapping
val labels_axiom : label_mapping val labels_axiom : label_mapping
val preproc_annot : label_mapping -> predicate -> predicate val preproc_annot : label_mapping -> predicate -> predicate
val preproc_assigns : label_mapping -> from list -> from list val preproc_assigns : label_mapping -> from list -> from list
val has_postassigns : assigns -> bool
# frama-c -wp [...]
[kernel] Parsing tests/wp_acsl/postassigns.c (with preprocessing)
[wp] Running WP plugin...
[wp] Warning: Missing RTE guards
------------------------------------------------------------
Function job1
------------------------------------------------------------
Goal Post-condition (file tests/wp_acsl/postassigns.c, line 4) in 'job1':
Prove: true.
------------------------------------------------------------
Goal Assigns (file tests/wp_acsl/postassigns.c, line 5) in 'job1' (1/9):
Prove: true.
------------------------------------------------------------
Goal Assigns (file tests/wp_acsl/postassigns.c, line 5) in 'job1' (2/9):
Effect at line 10
Prove: true.
------------------------------------------------------------
Goal Assigns (file tests/wp_acsl/postassigns.c, line 5) in 'job1' (3/9):
Effect at line 10
Prove: true.
------------------------------------------------------------
Goal Assigns (file tests/wp_acsl/postassigns.c, line 5) in 'job1' (4/9):
Effect at line 11
Prove: true.
------------------------------------------------------------
Goal Assigns (file tests/wp_acsl/postassigns.c, line 5) in 'job1' (5/9):
Effect at line 11
Prove: true.
------------------------------------------------------------
Goal Assigns (file tests/wp_acsl/postassigns.c, line 5) in 'job1' (6/9):
Effect at line 12
Prove: true.
------------------------------------------------------------
Goal Assigns (file tests/wp_acsl/postassigns.c, line 5) in 'job1' (7/9):
Effect at line 12
Prove: true.
------------------------------------------------------------
Goal Assigns (file tests/wp_acsl/postassigns.c, line 5) in 'job1' (8/9):
Effect at line 13
Prove: true.
------------------------------------------------------------
Goal Assigns (file tests/wp_acsl/postassigns.c, line 5) in 'job1' (9/9):
Effect at line 13
Prove: true.
------------------------------------------------------------
------------------------------------------------------------
Function job2
------------------------------------------------------------
Goal Post-condition (file tests/wp_acsl/postassigns.c, line 19) in 'job2':
Prove: true.
------------------------------------------------------------
Goal Assigns (file tests/wp_acsl/postassigns.c, line 20) in 'job2' (1/9):
Prove: true.
------------------------------------------------------------
Goal Assigns (file tests/wp_acsl/postassigns.c, line 20) in 'job2' (2/9):
Effect at line 25
Prove: true.
------------------------------------------------------------
Goal Assigns (file tests/wp_acsl/postassigns.c, line 20) in 'job2' (3/9):
Effect at line 25
Prove: true.
------------------------------------------------------------
Goal Assigns (file tests/wp_acsl/postassigns.c, line 20) in 'job2' (4/9):
Effect at line 26
Prove: true.
------------------------------------------------------------
Goal Assigns (file tests/wp_acsl/postassigns.c, line 20) in 'job2' (5/9):
Effect at line 26
Let x = A[1].
Assume {
Type: is_sint32(x).
(* Heap *)
Type: (region(p.base) <= 0) /\ IsArray_sint32(A) /\ linked(Malloc_0).
(* Goal *)
When: !invalid(Malloc_0, shift_sint32(p, x), 1).
}
Prove: exists i : Z. (A[i] = x) /\ (0 <= i) /\ (i <= 3).
------------------------------------------------------------
Goal Assigns (file tests/wp_acsl/postassigns.c, line 20) in 'job2' (6/9):
Effect at line 27
Prove: true.
------------------------------------------------------------
Goal Assigns (file tests/wp_acsl/postassigns.c, line 20) in 'job2' (7/9):
Effect at line 27
Let x = A[2].
Assume {
Type: is_sint32(x).
(* Heap *)
Type: (region(p.base) <= 0) /\ IsArray_sint32(A) /\ linked(Malloc_0).
(* Goal *)
When: !invalid(Malloc_0, shift_sint32(p, x), 1).
}
Prove: exists i : Z. (A[i] = x) /\ (0 <= i) /\ (i <= 3).
------------------------------------------------------------
Goal Assigns (file tests/wp_acsl/postassigns.c, line 20) in 'job2' (8/9):
Effect at line 28
Prove: true.
------------------------------------------------------------
Goal Assigns (file tests/wp_acsl/postassigns.c, line 20) in 'job2' (9/9):
Effect at line 28
Prove: true.
------------------------------------------------------------
------------------------------------------------------------
Function job3
------------------------------------------------------------
Goal Preservation of Invariant (file tests/wp_acsl/postassigns.c, line 38):
Assume {
Type: is_sint32(N) /\ is_sint32(i) /\ is_sint32(1 + i).
(* Pre-condition *)
Have: 0 <= N.
(* Invariant *)
Have: (i <= N) /\ (0 <= i).
(* Then *)
Have: i < N.
}
Prove: (-1) <= i.
------------------------------------------------------------
Goal Establishment of Invariant (file tests/wp_acsl/postassigns.c, line 38):
Prove: true.
------------------------------------------------------------
Goal Loop assigns (file tests/wp_acsl/postassigns.c, line 39) (1/3):
Prove: true.
------------------------------------------------------------
Goal Loop assigns (file tests/wp_acsl/postassigns.c, line 39) (2/3):
Effect at line 41
Prove: true.
------------------------------------------------------------
Goal Loop assigns (file tests/wp_acsl/postassigns.c, line 39) (3/3):
Effect at line 42
Let a = shift_sint32(p, i).
Assume {
Type: is_sint32(N) /\ is_sint32(i).
(* Heap *)
Type: (region(p.base) <= 0) /\ linked(Malloc_0).
(* Goal *)
When: !invalid(Malloc_0, a, 1).
(* Pre-condition *)
Have: 0 <= N.
(* Invariant *)
Have: (i <= N) /\ (0 <= i).
(* Then *)
Have: i < N.
}
Prove: included(a, 1, shift_sint32(p, 0), N).
------------------------------------------------------------
Goal Assigns (file tests/wp_acsl/postassigns.c, line 33) in 'job3' (1/2):
Prove: true.
------------------------------------------------------------
Goal Assigns (file tests/wp_acsl/postassigns.c, line 33) in 'job3' (2/2):
Effect at line 41
Prove: true.
------------------------------------------------------------
[wp] tests/wp_acsl/postassigns.c:7: Warning:
Memory model hypotheses for function 'job1':
/*@
behavior wp_typed:
requires \separated(p + (..), &N);
ensures \separated(p + (0 .. \at(N,Post) - 1), &N);
*/
void job1(int *p);
[wp] tests/wp_acsl/postassigns.c:22: Warning:
Memory model hypotheses for function 'job2':
/*@
behavior wp_typed:
requires \separated(p + (..), (int *)A + (..), &N);
ensures \separated(p + A[0 .. \at(N,Post) - 1], (int *)A + (..), &N);
*/
void job2(int *p);
[wp] tests/wp_acsl/postassigns.c:35: Warning:
Memory model hypotheses for function 'job3':
/*@
behavior wp_typed:
requires \separated(p + (..), &N);
ensures \separated(p + (0 .. \at(N,Post)), &N);
*/
void job3(int *p);
# frama-c -wp [...]
[kernel] Parsing tests/wp_acsl/postassigns.c (with preprocessing)
[wp] Running WP plugin...
[wp] Warning: Missing RTE guards
[wp] 27 goals scheduled
[wp] [Qed] Goal typed_job1_ensures : Valid
[wp] [Qed] Goal typed_job1_assigns_part1 : Valid
[wp] [Qed] Goal typed_job1_assigns_part2 : Valid
[wp] [Qed] Goal typed_job1_assigns_part3 : Valid
[wp] [Qed] Goal typed_job1_assigns_part4 : Valid
[wp] [Qed] Goal typed_job1_assigns_part5 : Valid
[wp] [Qed] Goal typed_job1_assigns_part6 : Valid
[wp] [Qed] Goal typed_job1_assigns_part7 : Valid
[wp] [Qed] Goal typed_job1_assigns_part8 : Valid
[wp] [Qed] Goal typed_job1_assigns_part9 : Valid
[wp] [Qed] Goal typed_job2_ensures : Valid
[wp] [Qed] Goal typed_job2_assigns_part1 : Valid
[wp] [Qed] Goal typed_job2_assigns_part2 : Valid
[wp] [Qed] Goal typed_job2_assigns_part3 : Valid
[wp] [Qed] Goal typed_job2_assigns_part4 : Valid
[wp] [Alt-Ergo] Goal typed_job2_assigns_part5 : Valid
[wp] [Qed] Goal typed_job2_assigns_part6 : Valid
[wp] [Alt-Ergo] Goal typed_job2_assigns_part7 : Valid
[wp] [Qed] Goal typed_job2_assigns_part8 : Valid
[wp] [Qed] Goal typed_job2_assigns_part9 : Valid
[wp] [Alt-Ergo] Goal typed_job3_loop_invariant_preserved : Valid
[wp] [Qed] Goal typed_job3_loop_invariant_established : Valid
[wp] [Qed] Goal typed_job3_loop_assigns_part1 : Valid
[wp] [Qed] Goal typed_job3_loop_assigns_part2 : Valid
[wp] [Alt-Ergo] Goal typed_job3_loop_assigns_part3 : Valid
[wp] [Qed] Goal typed_job3_assigns_part1 : Valid
[wp] [Qed] Goal typed_job3_assigns_part2 : Valid
[wp] Proved goals: 27 / 27
Qed: 23
Alt-Ergo: 4
------------------------------------------------------------
Functions WP Alt-Ergo Total Success
job1 10 - 10 100%
job2 8 2 10 100%
job3 5 2 7 100%
------------------------------------------------------------
[wp] tests/wp_acsl/postassigns.c:7: Warning:
Memory model hypotheses for function 'job1':
/*@
behavior wp_typed:
requires \separated(p + (..), &N);
ensures \separated(p + (0 .. \at(N,Post) - 1), &N);
*/
void job1(int *p);
[wp] tests/wp_acsl/postassigns.c:22: Warning:
Memory model hypotheses for function 'job2':
/*@
behavior wp_typed:
requires \separated(p + (..), (int *)A + (..), &N);
ensures \separated(p + A[0 .. \at(N,Post) - 1], (int *)A + (..), &N);
*/
void job2(int *p);
[wp] tests/wp_acsl/postassigns.c:35: Warning:
Memory model hypotheses for function 'job3':
/*@
behavior wp_typed:
requires \separated(p + (..), &N);
ensures \separated(p + (0 .. \at(N,Post)), &N);
*/
void job3(int *p);
int N;
/*@
ensures N == 4;
assigns N, p[0..\at(N,Post)-1];
*/
void job1(int *p)
{
N = 0;
p[N++] = 0;
p[N++] = 0;
p[N++] = 0;
p[N++] = 0;
}
int A[4];
/*@
ensures N == 4;
assigns N, *(p + A[0..\at(N,Post)-1]);
*/
void job2(int *p)
{
N = 0;
p[A[N++]] = 0;
p[A[N++]] = 0;
p[A[N++]] = 0;
p[A[N++]] = 0;
}
/*@
requires 0 <= N;
assigns N, p[0..\at(N,Post)];
*/
void job3(int *p)
{
/*@
loop invariant 0 <= i <= N;
loop assigns i, p[0..N-1];
*/
for (int i = 0; i < N; i++)
p[i] = 0;
N++;
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment