From 28b2ccccedd3245686e2e9a4728c425819de1620 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Loi=CC=88c=20Correnson?= <loic.correnson@cea.fr>
Date: Mon, 18 Jan 2021 14:10:37 +0100
Subject: [PATCH] [wp] fix use/verify predicate kinds

---
 .../ast_queries/logic_utils.ml                |  3 +
 .../ast_queries/logic_utils.mli               |  9 +++
 src/plugins/wp/wpAnnot.ml                     | 58 +++++++++++--------
 src/plugins/wp/wpReached.ml                   |  2 +-
 src/plugins/wp/wpStrategy.ml                  | 43 ++++++++------
 5 files changed, 72 insertions(+), 43 deletions(-)

diff --git a/src/kernel_services/ast_queries/logic_utils.ml b/src/kernel_services/ast_queries/logic_utils.ml
index 13faf94caec..e6b2f808798 100644
--- a/src/kernel_services/ast_queries/logic_utils.ml
+++ b/src/kernel_services/ast_queries/logic_utils.ml
@@ -2229,6 +2229,9 @@ let lhost_c_type thost =
      | _ -> assert false)
   | TResult ty -> ty
 
+let use_predicate = function Assert | Admit -> true | Check -> false
+let verify_predicate = function Assert | Check -> true | Admit -> false
+
 let is_assert ca =
   match ca.annot_content with AAssert (_, p) -> p.tp_kind = Assert | _ -> false
 
diff --git a/src/kernel_services/ast_queries/logic_utils.mli b/src/kernel_services/ast_queries/logic_utils.mli
index 71579a36bf0..1e0ddf5ad41 100644
--- a/src/kernel_services/ast_queries/logic_utils.mli
+++ b/src/kernel_services/ast_queries/logic_utils.mli
@@ -444,6 +444,15 @@ val merge_funspec :
 val clear_funspec: funspec -> unit
 
 (** {2 Discriminating code_annotations} *)
+
+(** Checks if a predicate kind can be used as an hypothesis or requirement.
+    It is true for `Admit` and `Assert`, and false for `Check`. *)
+val use_predicate : predicate_kind -> bool
+
+(** Checks if a predicate kind shall be put under verification.
+    It is true for `Assert` and `Check`, and false for `Admit`. *)
+val verify_predicate : predicate_kind -> bool
+
 (** Functions below allows to test a special kind of code_annotation.
     Use them in conjunction with {!Annotations.get_filter} to retrieve
     a particular kind of annotations associated to a statement. *)
diff --git a/src/plugins/wp/wpAnnot.ml b/src/plugins/wp/wpAnnot.ml
index a64dbebde90..c6ff88f1a14 100644
--- a/src/plugins/wp/wpAnnot.ml
+++ b/src/plugins/wp/wpAnnot.ml
@@ -28,6 +28,7 @@ let debug fmt = Wp_parameters.debug ~dkey fmt
 
 open Cil_types
 open Cil_datatype
+open Logic_utils
 
 (* -------------------------------------------------------------------------- *)
 (* --- Selection of relevant assigns and postconditions                   --- *)
@@ -761,7 +762,7 @@ let add_called_post called_kf termination_kind acc =
     let kind = WpStrategy.AcallHyp called_kf in
     let assumes = (Ast_info.behavior_assumes b) in
     let add_post acc (tk, p) =
-      if tk = termination_kind && p.ip_content.tp_kind <> Check
+      if tk = termination_kind && use_predicate p.ip_content.tp_kind
       then WpStrategy.add_prop_call_post acc kind called_kf b tk ~assumes p
       else acc
     in List.fold_left add_post acc b.b_post_cond
@@ -838,7 +839,8 @@ let add_variant_annot config s ca var_exp loop_entry loop_back =
   in loop_entry, loop_back
 
 let add_loop_invariant_annot config vloop s ca b_list inv acc =
-  let only_check = inv.tp_kind = Check in
+  let hyp = use_predicate inv.tp_kind in
+  let goal = verify_predicate inv.tp_kind in
   let inv = inv.tp_statement in
   let assigns, loop_entry, loop_back , loop_core = acc in
   (* we have to prove that inv is true for each edge that goes
@@ -849,22 +851,29 @@ let add_loop_invariant_annot config vloop s ca b_list inv acc =
   | TBRpart (* TODO: PKPartial *)
     ->
       begin
-        let loop_entry = add_prop_loop_inv ~established:true config loop_entry
-            WpStrategy.Agoal s ca inv in
-        let loop_back = add_prop_loop_inv ~established:false config loop_back
-            WpStrategy.Agoal s ca inv in
+        let loop_entry =
+          if goal then
+            add_prop_loop_inv ~established:true config loop_entry
+              WpStrategy.Agoal s ca inv
+          else loop_entry in
+        let loop_back =
+          if goal then
+            add_prop_loop_inv ~established:false config loop_back
+              WpStrategy.Agoal s ca inv
+          else loop_back in
         let loop_core =
-          if only_check then loop_core
-          else
+          if hyp then
             add_prop_inv_fixpoint config loop_core WpStrategy.Ahyp s ca inv
-        in
+          else loop_core in
         assigns, loop_entry , loop_back , loop_core
       end
-  | TBRhyp when not only_check ->
-      let kind = WpStrategy.Ahyp in
-      let loop_core = add_prop_inv_fixpoint config loop_core kind s ca inv
-      in assigns, loop_entry , loop_back , loop_core
-  | TBRhyp | TBRno -> acc
+  | TBRhyp ->
+      if hyp then
+        let kind = WpStrategy.Ahyp in
+        let loop_core = add_prop_inv_fixpoint config loop_core kind s ca inv
+        in assigns, loop_entry , loop_back , loop_core
+      else acc
+  | TBRno -> acc
 
 (** Returns the annotations for the three edges of the loop node:
  * - loop_entry : goals for the edge entering in the loop
@@ -952,24 +961,25 @@ let get_stmt_annots config v s =
         let acc = match is_annot_for_config config v s b_list with
           | TBRno -> acc
           | TBRhyp ->
-              if p.tp_kind = Check then acc
-              else
+              if use_predicate p.tp_kind then
                 let b_acc =
                   WpStrategy.add_prop_assert
                     b_acc WpStrategy.Ahyp kf s a p.tp_statement
                 in (b_acc, (a_acc, e_acc))
+              else acc
           | TBRok | TBRpart ->
               let id = WpPropId.mk_assert_id config.kf s a in
               let goal = goal_to_select config id in
-              if p.tp_kind = Check && not goal then acc
-              else
-                let kind =
-                  WpStrategy.(if p.tp_kind = Check then Agoal else Aboth goal)
-                in
+              let add, kind =
+                match p.tp_kind with
+                | Admit -> true, WpStrategy.Ahyp
+                | Assert -> true, Aboth goal
+                | Check -> goal, Agoal
+              in if add then
                 let b_acc =
                   WpStrategy.add_prop_assert b_acc kind kf s a p.tp_statement
-                in
-                (b_acc, (a_acc, e_acc))
+                in (b_acc, (a_acc, e_acc))
+              else acc
         in acc
     | AAllocation (_b_list, _frees_allocates) ->
         (* [PB] TODO *) acc
@@ -1136,7 +1146,7 @@ let add_global_annotations annots =
           linfo.l_var_info.lv_name;
         ()
     | Dlemma (name,_,_,_,p,_,_) ->
-        if p.tp_kind <> Check then
+        if use_predicate p.tp_kind then
           WpStrategy.add_axiom annots (LogicUsage.logic_lemma name)
 
   and do_globals gs = List.iter do_global gs in
diff --git a/src/plugins/wp/wpReached.ml b/src/plugins/wp/wpReached.ml
index af993718983..549725d8cf1 100644
--- a/src/plugins/wp/wpReached.ml
+++ b/src/plugins/wp/wpReached.ml
@@ -92,7 +92,7 @@ let is_dead_annot ca =
       is_unrolled_completely spec
   | AAssert([],p)
   | AInvariant([],_,p) ->
-      p.tp_kind <> Check && is_predicate false p.tp_statement
+      Logic_utils.use_predicate p.tp_kind && is_predicate false p.tp_statement
   | _ -> false
 
 let is_dead_code stmt =
diff --git a/src/plugins/wp/wpStrategy.ml b/src/plugins/wp/wpStrategy.ml
index 2488ade0d3f..bace35e939a 100644
--- a/src/plugins/wp/wpStrategy.ml
+++ b/src/plugins/wp/wpStrategy.ml
@@ -24,6 +24,7 @@ let dkey = Wp_parameters.register_category "strategy" (* debugging key *)
 let debug fmt = Wp_parameters.debug ~dkey fmt
 
 open Cil_types
+open Logic_utils
 open LogicUsage
 
 (* -------------------------------------------------------------------------- *)
@@ -171,7 +172,7 @@ let add_prop_fct_pre_bhv acc kind kf bhv =
     Logic_const.(pat (p,pre_label))
   in
   let requires =
-    List.filter (fun x -> x.ip_content.tp_kind <> Check) bhv.b_requires
+    List.filter (fun x -> use_predicate x.ip_content.tp_kind) bhv.b_requires
   in
   let requires = Logic_const.pands (List.map norm_pred requires) in
   let assumes = Logic_const.pands (List.map norm_pred bhv.b_assumes) in
@@ -183,21 +184,23 @@ let add_prop_fct_pre_bhv acc kind kf bhv =
   add_prop acc kind id p
 
 let add_prop_fct_pre acc kind kf bhv ~assumes pre =
-  if pre.ip_content.tp_kind = Check then acc else begin
+  if use_predicate pre.ip_content.tp_kind then begin
     let id = WpPropId.mk_pre_id kf Kglobal bhv pre in
     let labels = NormAtLabels.labels_fct_pre in
     let p = Logic_const.pred_of_id_pred pre in
     let p = Logic_const.(pat (p,pre_label)) in
     let p = normalize id ?assumes labels p in
     add_prop acc kind id p
-  end
+  end else acc
 
 let add_prop_fct_post acc kind kf  bhv tkind post =
-  let id = WpPropId.mk_fct_post_id kf bhv (tkind, post) in
-  let labels = NormAtLabels.labels_fct_post in
-  let p = Logic_const.pred_of_id_pred post in
-  let p = normalize id labels p in
-  add_prop acc kind id p
+  if verify_predicate post.ip_content.tp_kind then begin
+    let id = WpPropId.mk_fct_post_id kf bhv (tkind, post) in
+    let labels = NormAtLabels.labels_fct_post in
+    let p = Logic_const.pred_of_id_pred post in
+    let p = normalize id labels p in
+    add_prop acc kind id p
+  end else acc
 
 let add_prop_fct_bhv_pre acc kind kf bhv =
   let assumes = None in
@@ -206,11 +209,13 @@ let add_prop_fct_bhv_pre acc kind kf bhv =
   List.fold_left add acc bhv.b_assumes
 
 let add_prop_stmt_pre acc kind kf s bhv ~assumes pre =
-  let id = WpPropId.mk_pre_id kf (Kstmt s) bhv pre in
-  let labels = NormAtLabels.labels_stmt_pre ~kf s in
-  let p = Logic_const.pred_of_id_pred pre in
-  let p = normalize id labels ?assumes p in
-  add_prop acc kind id p
+  if use_predicate pre.ip_content.tp_kind then begin
+    let id = WpPropId.mk_pre_id kf (Kstmt s) bhv pre in
+    let labels = NormAtLabels.labels_stmt_pre ~kf s in
+    let p = Logic_const.pred_of_id_pred pre in
+    let p = normalize id labels ?assumes p in
+    add_prop acc kind id p
+  end else acc
 
 let add_prop_stmt_bhv_requires acc kind kf s bhv ~with_assumes =
   let assumes =
@@ -227,11 +232,13 @@ let add_prop_stmt_spec_pre acc kind kf s spec =
   in List.fold_left add_bhv_pre acc spec.spec_behavior
 
 let add_prop_stmt_post acc kind kf s bhv tkind l_post ~assumes post =
-  let id = WpPropId.mk_stmt_post_id kf s bhv (tkind, post) in
-  let labels = NormAtLabels.labels_stmt_post ~kf s l_post in
-  let p = Logic_const.pred_of_id_pred post in
-  let p = normalize id labels ?assumes p in
-  add_prop acc kind id p
+  if verify_predicate post.ip_content.tp_kind then begin
+    let id = WpPropId.mk_stmt_post_id kf s bhv (tkind, post) in
+    let labels = NormAtLabels.labels_stmt_post ~kf s l_post in
+    let p = Logic_const.pred_of_id_pred post in
+    let p = normalize id labels ?assumes p in
+    add_prop acc kind id p
+  end else acc
 
 let update_kind kind pre =
   if pre.ip_content.tp_kind = Check then begin
-- 
GitLab