diff --git a/src/kernel_internals/parsing/cparser.mly b/src/kernel_internals/parsing/cparser.mly
index 6f2547db91ff1ebf4e193024ad1158e06428e887..4ad71347daf28a3cdee1d158fdb8911b02d5ca3a 100644
--- a/src/kernel_internals/parsing/cparser.mly
+++ b/src/kernel_internals/parsing/cparser.mly
@@ -109,7 +109,7 @@ let check_funspec_abrupt_clauses fname spec =
 	(function
 	| (Cil_types.Normal | Cil_types.Exits),_ -> ()
 	| (Cil_types.Breaks | Cil_types.Continues | Cil_types.Returns),
-          {Logic_ptree.lexpr_loc = (loc,_)} ->
+          { Logic_ptree.tp_statement = { lexpr_loc = (loc,_)}} ->
           Errorloc.parse_error ~source:loc
             "Specification of function %s can only contain ensures or \
                  exits post-conditions" fname)
diff --git a/src/kernel_internals/parsing/logic_lexer.mll b/src/kernel_internals/parsing/logic_lexer.mll
index ca329de4aef0f70a65206da351f27f04d235e13c..b86e9200489ea822f2dfb2315a2d5134b2bfd3b3 100644
--- a/src/kernel_internals/parsing/logic_lexer.mll
+++ b/src/kernel_internals/parsing/logic_lexer.mll
@@ -297,6 +297,18 @@
 
   let accept_c_comments_into_acsl_spec = ref false
 
+  let hack_merge_tokens current next =
+    match (current,next) with
+    | CHECK, REQUIRES -> true, CHECK_REQUIRES
+    | CHECK, ENSURES -> true, CHECK_ENSURES
+    | CHECK, EXITS -> true, CHECK_EXITS
+    | CHECK, RETURNS -> true, CHECK_RETURNS
+    | CHECK, BREAKS -> true, CHECK_BREAKS
+    | CHECK, CONTINUES -> true, CHECK_CONTINUES
+    | CHECK, LOOP -> true, CHECK_LOOP
+    | CHECK, INVARIANT -> true, CHECK_INVARIANT
+    | CHECK, LEMMA -> true, CHECK_LEMMA
+    | _ -> false, current
 }
 
 let space = [' ' '\t' '\012' '\r' '@' ]
@@ -339,7 +351,15 @@ rule token = parse
       let loc = Lexing.(lexeme_start_p lexbuf, lexeme_end_p lexbuf) in
       let cabsloc = Cil_datatype.Location.of_lexing_loc loc in
       let s = lexeme lexbuf in
-      identifier s cabsloc
+      let curr_tok = identifier s cabsloc in
+      if curr_tok = CHECK then begin
+        let next_tok =
+          token { lexbuf with refill_buff = lexbuf.refill_buff }
+        in
+        let (eat_next, tok) = hack_merge_tokens curr_tok next_tok in
+        if eat_next then ignore (token lexbuf);
+        tok
+      end else curr_tok
     }
 
   | '0'['x''X'] rH+ rIS?    { CONSTANT (IntConstant (lexeme lexbuf)) }
diff --git a/src/kernel_internals/parsing/logic_parser.mly b/src/kernel_internals/parsing/logic_parser.mly
index cc86b0d9c1da06ba1beb012a70be1036e51dfff4..38d5b09db50efc5c67c3e204aa83669652d7c1a1 100644
--- a/src/kernel_internals/parsing/logic_parser.mly
+++ b/src/kernel_internals/parsing/logic_parser.mly
@@ -225,6 +225,7 @@
   let cv_const = Attr ("const", [])
   let cv_volatile = Attr ("volatile", [])
 
+  let toplevel_pred tp_only_check tp_statement = { tp_only_check; tp_statement }
 %}
 
 /*****************************************************************************/
@@ -250,6 +251,8 @@
 %token DOLLAR QUESTION MINUS PLUS STAR AMP SLASH PERCENT LSQUARE RSQUARE EOF
 %token GLOBAL INVARIANT VARIANT DECREASES FOR LABEL ASSERT CHECK SEMICOLON NULL EMPTY
 %token REQUIRES ENSURES ALLOCATES FREES ASSIGNS LOOP NOTHING SLICE IMPACT PRAGMA FROM
+%token CHECK_REQUIRES CHECK_LOOP CHECK_INVARIANT CHECK_LEMMA
+%token CHECK_ENSURES CHECK_EXITS CHECK_CONTINUES CHECK_BREAKS CHECK_RETURNS
 %token <string> EXT_CODE_ANNOT EXT_GLOBAL EXT_CONTRACT
 %token EXITS BREAKS CONTINUES RETURNS
 %token VOLATILE READS WRITES
@@ -1098,6 +1101,7 @@ contract:
 
 // use that to detect potentially missing ';' at end of clause
 clause_kw:
+| CHECK_REQUIRES { "check requires" }
 | REQUIRES { "requires" }
 | ASSUMES {"assumes"}
 | ASSIGNS { "assigns" }
@@ -1121,8 +1125,10 @@ requires:
 ;
 
 ne_requires:
-| REQUIRES full_lexpr SEMICOLON requires { $2::$4 }
-| REQUIRES full_lexpr clause_kw { missing 2 ";" $3}
+| REQUIRES full_lexpr SEMICOLON requires { toplevel_pred false $2::$4 }
+| CHECK_REQUIRES full_lexpr SEMICOLON requires { toplevel_pred true $2 :: $4 }
+| REQUIRES full_lexpr clause_kw { missing 2 ";" $3 }
+| CHECK_REQUIRES full_lexpr clause_kw { missing 2 ";" $3 }
 ;
 
 terminates:
@@ -1161,7 +1167,10 @@ allocation:
 
 ne_simple_clauses:
 | post_cond_kind full_lexpr SEMICOLON simple_clauses
-    { let allocation,assigns,post_cond,extended = $4 in allocation,assigns,(($1,$2)::post_cond),extended }
+    { let only_check, kind = $1 in
+      let allocation,assigns,post_cond,extended = $4 in
+      allocation,assigns,
+      ((kind,toplevel_pred only_check $2)::post_cond),extended }
 | allocation SEMICOLON simple_clauses
     { let allocation,assigns,post_cond,extended = $3 in
       let a = concat_allocation allocation $1 in
@@ -1388,7 +1397,8 @@ loop_allocation:
 ;
 
 loop_invariant:
-| LOOP INVARIANT full_lexpr SEMICOLON { $3 }
+| LOOP INVARIANT full_lexpr SEMICOLON { toplevel_pred false $3 }
+| CHECK_LOOP INVARIANT full_lexpr SEMICOLON { toplevel_pred true $3 }
 ;
 
 loop_variant:
@@ -1439,6 +1449,7 @@ beg_pragma_or_code_annotation:
 | ASSERT {}
 | CHECK {}
 | INVARIANT {}
+| CHECK_INVARIANT {}
 | EXT_CODE_ANNOT {}
 ;
 
@@ -1450,10 +1461,13 @@ pragma_or_code_annotation:
 
 code_annotation:
 | ASSERT full_lexpr SEMICOLON
-      { fun bhvs -> AAssert (bhvs,Assert,$2) }
+  { fun bhvs -> AAssert (bhvs,toplevel_pred false $2) }
 | CHECK full_lexpr SEMICOLON
-      { fun bhvs -> AAssert (bhvs,Check,$2) }
-| INVARIANT full_lexpr SEMICOLON { fun bhvs -> AInvariant (bhvs,false,$2) }
+  { fun bhvs -> AAssert (bhvs,toplevel_pred true $2) }
+| INVARIANT full_lexpr SEMICOLON
+  { fun bhvs -> AInvariant (bhvs,false,toplevel_pred false $2) }
+| CHECK_INVARIANT full_lexpr SEMICOLON
+  { fun bhvs -> AInvariant (bhvs,false,toplevel_pred true $2) }
 | EXT_CODE_ANNOT grammar_extension SEMICOLON
   { fun bhvs ->
     let open Cil_types in
@@ -1601,7 +1615,11 @@ logic_def:
 | LEMMA poly_id COLON full_lexpr SEMICOLON
     { let (id,labels,tvars) = $2 in
       exit_type_variables_scope ();
-      LDlemma (id, false, labels, tvars, $4) }
+      LDlemma (id, false, labels, tvars, toplevel_pred false $4) }
+| CHECK_LEMMA poly_id COLON full_lexpr SEMICOLON
+    { let (id,labels,tvars) = $2 in
+      exit_type_variables_scope ();
+      LDlemma (id, false, labels, tvars, toplevel_pred true $4) }
 | AXIOMATIC any_identifier LBRACE logic_decls RBRACE
     { LDaxiomatic($2,$4) }
 | TYPE poly_id_type_add_typename EQUAL typedef SEMICOLON
@@ -1674,7 +1692,7 @@ logic_decl:
 | AXIOM poly_id COLON full_lexpr SEMICOLON
     { let (id,labels,tvars) = $2 in
       exit_type_variables_scope ();
-      LDlemma (id, true, labels, tvars, $4) }
+      LDlemma (id, true, labels, tvars, toplevel_pred false $4) }
 ;
 
 logic_decl_loc:
@@ -1836,11 +1854,16 @@ acsl_c_keyword:
 ;
 
 post_cond:
-| ENSURES { Normal, "ensures" }
-| EXITS   { Exits, "exits" }
-| BREAKS  { Breaks, "breaks" }
-| CONTINUES { Continues, "continues" }
-| RETURNS { Returns, "returns" }
+| ENSURES { (false,Normal), "ensures" }
+| EXITS   { (false,Exits), "exits" }
+| BREAKS  { (false,Breaks), "breaks" }
+| CONTINUES { (false,Continues), "continues" }
+| RETURNS { (false,Returns), "returns" }
+| CHECK_ENSURES { (true,Normal), "check ensures" }
+| CHECK_EXITS   { (true,Exits), "check exits" }
+| CHECK_BREAKS  { (true,Breaks), "check breaks" }
+| CHECK_CONTINUES { (true,Continues), "check continues" }
+| CHECK_RETURNS { (true,Returns), "check returns" }
 ;
 
 is_acsl_spec:
@@ -1851,6 +1874,7 @@ is_acsl_spec:
 | FREES      { "frees" }
 | BEHAVIOR   { "behavior" }
 | REQUIRES   { "requires" }
+| CHECK_REQUIRES { "check requires" }
 | TERMINATES { "terminates" }
 | COMPLETE   { "complete" }
 | DECREASES  { "decreases" }
diff --git a/src/kernel_internals/typing/cabs2cil.ml b/src/kernel_internals/typing/cabs2cil.ml
index de0e67072492daa5af65815d4cff643da90a7455..6c2f452b6c5abfa7196cba938b0215a74a1dd61f 100644
--- a/src/kernel_internals/typing/cabs2cil.ml
+++ b/src/kernel_internals/typing/cabs2cil.ml
@@ -8876,9 +8876,14 @@ and createLocal ghost ((_, sto, _, _) as specs)
                 Logic_const.prel ~loc:castloc (Rle, talloca_size, max_bound)
               in
               let alloca_bounds = Logic_const.pand ~loc:castloc (pos_size, max_size) in
-              let alloca_bounds = { alloca_bounds with pred_name = ["alloca_bounds"] } in
+              let alloca_bounds =
+                { alloca_bounds with pred_name = ["alloca_bounds"] }
+              in
+              let alloca_bounds =
+                Logic_const.toplevel_predicate alloca_bounds
+              in
               let annot =
-                Logic_const.new_code_annotation (AAssert ([], Assert, alloca_bounds))
+                Logic_const.new_code_annotation (AAssert ([], alloca_bounds))
               in
               (mkStmtOneInstr ~ghost ~valid_sid
                  (Code_annot (annot, castloc)),
@@ -9395,9 +9400,10 @@ and doDecl local_env (isglobal: bool) : A.definition -> chunk = function
              [\assert \false]*)
           let pfalse = Logic_const.unamed ~loc Pfalse in
           let pfalse = { pfalse with pred_name = ["missing_return"] } in
+          let pfalse = Logic_const.toplevel_predicate pfalse in
           let assert_false () =
             let annot =
-              Logic_const.new_code_annotation (AAssert ([], Assert, pfalse))
+              Logic_const.new_code_annotation (AAssert ([], pfalse))
             in
             Cil.mkStmt ~ghost ~valid_sid (Instr(Code_annot(annot,loc)))
           in
diff --git a/src/kernel_internals/typing/cfg.ml b/src/kernel_internals/typing/cfg.ml
index 1ffc5c6b32b0e4bfa3fff39766b17671e172ba3d..3438e59ff51819ce28c437e4f00287ca463da39e 100644
--- a/src/kernel_internals/typing/cfg.ml
+++ b/src/kernel_internals/typing/cfg.ml
@@ -360,7 +360,8 @@ let xform_switch_block ?(keepSwitch=false) b =
   let () = Stack.push (Stack.create()) continues_stack in
   let assert_of_clause f ca =
     match ca.annot_content with
-    | AAssert _ | AInvariant _ | AVariant _ | AAssigns _ | AAllocation _ | APragma _ | AExtended _ -> Logic_const.ptrue
+    | AAssert _ | AInvariant _ | AVariant _
+    | AAssigns _ | AAllocation _ | APragma _ | AExtended _ -> Logic_const.ptrue
     | AStmtSpec (_bhv,s) ->
       let open Logic_const in
       List.fold_left
@@ -371,8 +372,8 @@ let xform_switch_block ?(keepSwitch=false) b =
                 (pands
                    (List.map
                       (fun p ->
-                         pold ~loc:p.ip_content.pred_loc
-                           (Logic_const.pred_of_id_pred p))
+                         let p = Logic_const.pred_of_id_pred p in
+                         pold ~loc:p.pred_loc p)
                       bhv.b_assumes),
                  pands
                    (List.fold_left
@@ -478,8 +479,9 @@ let xform_switch_block ?(keepSwitch=false) b =
              xform_switch_stmt
                rest break_dest cont_dest label_index 0
            | p ->
+             let p = Logic_const.toplevel_predicate p in
              let a =
-               Logic_const.new_code_annotation (AAssert ([], Assert, p))
+               Logic_const.new_code_annotation (AAssert ([], p))
              in
              let assertion = mkStmt (Instr(Code_annot(a,l))) in
              popn popstack;
@@ -501,9 +503,8 @@ let xform_switch_block ?(keepSwitch=false) b =
              xform_switch_stmt
                rest break_dest cont_dest label_index 0
            | p ->
-             let a =
-               Logic_const.new_code_annotation (AAssert ([], Assert, p))
-             in
+             let p = Logic_const.toplevel_predicate p in
+             let a = Logic_const.new_code_annotation (AAssert ([], p)) in
              let assertion = mkStmt (Instr(Code_annot(a,l))) in
              popn popstack;
              assertion :: s ::
diff --git a/src/kernel_internals/typing/oneret.ml b/src/kernel_internals/typing/oneret.ml
index f41401c9a7e8d91360f8f91a7498ff38f48feee4..164f5b48e7887784a264e4c55beaaaa74421f352 100644
--- a/src/kernel_internals/typing/oneret.ml
+++ b/src/kernel_internals/typing/oneret.ml
@@ -235,8 +235,8 @@ let oneret ?(callback: callback option) (f: fundec) : unit =
                   (pands
                      (List.map
                         (fun p ->
-                           pold ~loc:p.ip_content.pred_loc
-                             (Logic_const.pred_of_id_pred p))
+                           let p = Logic_const.pred_of_id_pred p in
+                           pold ~loc:p.pred_loc p)
                         bhv.b_assumes),
                    pands
                      (List.fold_left
@@ -381,7 +381,8 @@ let oneret ?(callback: callback option) (f: fundec) : unit =
           match !returns_assert with
           | { pred_content = Ptrue } -> [s; sg]
           | p ->
-            let a = Logic_const.new_code_annotation (AAssert ([],Assert,p)) in
+            let p = Logic_const.toplevel_predicate p in
+            let a = Logic_const.new_code_annotation (AAssert ([],p)) in
             let sta = mkStmt (Instr (Code_annot (a,loc))) in
             if callback<>None then
               ( let gclause = sta , a in
diff --git a/src/kernel_internals/typing/unroll_loops.ml b/src/kernel_internals/typing/unroll_loops.ml
index fc2af50b9c1c20573594c2f62d30c6b4575d36e6..e73b70a19d740f53d7b2e2c390297b7473f4d1fd 100644
--- a/src/kernel_internals/typing/unroll_loops.ml
+++ b/src/kernel_internals/typing/unroll_loops.ml
@@ -684,7 +684,7 @@ class do_it global_find_init ((force:bool),(times:int)) = object(self)
         | Some emitter ->
           let annot =
             Logic_const.new_code_annotation
-              (AInvariant ([],true,Logic_const.pfalse))
+              (AInvariant ([],true,Logic_const.(toplevel_predicate pfalse)))
           in
           Annotations.add_code_annot
 	    emitter ~kf:(Extlib.the self#current_kf) sloop annot;
diff --git a/src/kernel_services/analysis/exn_flow.ml b/src/kernel_services/analysis/exn_flow.ml
index a75151352f640348731a343532d6cfa4da1a5646..45859e0a17ce45666c024f5e9085369c1656130f 100644
--- a/src/kernel_services/analysis/exn_flow.ml
+++ b/src/kernel_services/analysis/exn_flow.ml
@@ -660,7 +660,7 @@ object(self)
            we haven't seen an uncaught exception anyway. *)
       | Exits | Breaks | Continues -> orig
       | Returns | Normal ->
-          let loc = pred.ip_content.pred_loc in
+          let loc = (Logic_const.pred_of_id_pred pred).pred_loc in
           let p = self#pred_uncaught_flag loc false in
           let pred' = Logic_const.pred_of_id_pred pred in
           (kind,
diff --git a/src/kernel_services/analysis/interpreted_automata.ml b/src/kernel_services/analysis/interpreted_automata.ml
index ae1d5a4f3cff63f0f6562dde13fa0a9eec6c3b25..32a98309ead70a015f9269dbe4c382f2abc97e72 100644
--- a/src/kernel_services/analysis/interpreted_automata.ml
+++ b/src/kernel_services/analysis/interpreted_automata.ml
@@ -204,7 +204,7 @@ let variant_predicate stmt v =
   Logic_const.pand ~loc (pred1, pred2)
 
 let supported_annotation annot = match annot.annot_content with
-  | AAssert ([], _, _)
+  | AAssert ([], _)
   | AInvariant ([], _, _)
   | AVariant (_, None) -> true
   | _ -> false (* TODO *)
@@ -214,9 +214,9 @@ let code_annot = Annotations.code_annot ~filter:supported_annotation
 let make_annotation kf stmt annot labels =
   let kind, pred =
     match annot.annot_content with
-    | AAssert ([], Cil_types.Assert, pred) -> Assert, pred
-    | AAssert ([], Cil_types.Check, pred) -> Check, pred
-    | AInvariant ([], _, pred) -> Invariant, pred
+    | AAssert ([], {tp_only_check = false; tp_statement = pred}) -> Assert, pred
+    | AAssert ([], {tp_only_check = true; tp_statement = pred}) -> Check, pred
+    | AInvariant ([], _, pred) -> Invariant, pred.tp_statement
     | AVariant (v, None) -> Assert, variant_predicate stmt v
     | _ -> assert false
   in
@@ -552,7 +552,10 @@ let build_automaton ~annotations kf =
   let bind_labels (v1, edge, v2) =
     match edge.edge_transition with
     | Prop (annot, stmt) ->
-      let l = Cil.extract_labels_from_pred annot.predicate.ip_content in
+      let l =
+        Cil.extract_labels_from_pred
+          (Logic_const.pred_of_id_pred annot.predicate)
+      in
       let bind label map =
         try
           let vertex = match label with
diff --git a/src/kernel_services/analysis/logic_interp.ml b/src/kernel_services/analysis/logic_interp.ml
index ca8044ead8db1d5b6bb9cfb3459f5aca44692aa4..5235e6aec142f3c85c6363fc58002714829453ec 100644
--- a/src/kernel_services/analysis/logic_interp.ml
+++ b/src/kernel_services/analysis/logic_interp.ml
@@ -947,17 +947,17 @@ to function contracts."
         (* to preserve the effect of the statement *)
         pragmas :=
           { !pragmas with stmt = Stmt.Set.add ki !pragmas.stmt}
-      | AAssert (_behav,_,pred) ->
+      | AAssert (_behav,pred) ->
         (* to preserve the interpretation of the assertion *)
-        get_zone_from_pred ki pred;
+        get_zone_from_pred ki pred.tp_statement;
       | AInvariant (_behav,true,pred) -> (* loop invariant *)
         (* WARNING this is obsolete *)
         (* [JS 2010/09/02] TODO: so what is the right way to do? *)
         (* to preserve the interpretation of the loop invariant *)
-        get_zone_from_pred (Extlib.the loop_body_opt) pred;
+        get_zone_from_pred (Extlib.the loop_body_opt) pred.tp_statement;
       | AInvariant (_behav,false,pred) -> (* code invariant *)
         (* to preserve the interpretation of the code invariant *)
-        get_zone_from_pred ki pred;
+        get_zone_from_pred ki pred.tp_statement;
       | AVariant (term,_) ->
         (* to preserve the interpretation of the variant *)
         get_zone_from_term (Extlib.the loop_body_opt) term;
diff --git a/src/kernel_services/ast_data/alarms.ml b/src/kernel_services/ast_data/alarms.ml
index a0845e815040b754587d15eca7cf150ba0911b25..0138ec1f79086c159276d18b5c0ef6fac9cbdb78 100644
--- a/src/kernel_services/ast_data/alarms.ml
+++ b/src/kernel_services/ast_data/alarms.ml
@@ -705,7 +705,8 @@ let to_annot_aux kinstr ?(loc=Kinstr.loc kinstr) alarm =
   (*  Kernel.debug "registering alarm %a" D.pretty alarm;*)
   let add alarm =
     let pred = create_predicate ~loc alarm in
-    Logic_const.new_code_annotation (AAssert([], Assert, pred))
+    let pred = Logic_const.toplevel_predicate pred in
+    Logic_const.new_code_annotation (AAssert([], pred))
   in
   try
     let by_emitter = State.find kinstr in
diff --git a/src/kernel_services/ast_data/annotations.ml b/src/kernel_services/ast_data/annotations.ml
index 056d57d7a3eff673eadf2da8c7bd9adb4f3f9809..4febe26e5fb3c67fdd1eae0311b100785a480a34 100644
--- a/src/kernel_services/ast_data/annotations.ml
+++ b/src/kernel_services/ast_data/annotations.ml
@@ -717,13 +717,16 @@ let extend_name e pred =
   if Emitter.equal e Emitter.end_user || Emitter.equal e Emitter.kernel
   then pred
   else
-    let names = pred.pred_name in
+    let names = pred.tp_statement.pred_name in
     let s = Emitter.get_name e in
     if (List.mem s names) ||
        let acsl_identifier_regexp =
          Str.regexp "^\\([\\][_a-zA-Z]\\|[_a-zA-Z]\\)[0-9_a-zA-Z]*$"
        in not (Str.string_match acsl_identifier_regexp s 0)
-    then pred else { pred with pred_name = s :: names }
+    then pred
+    else
+      { pred with
+        tp_statement = { pred.tp_statement with pred_name = s :: names }}
 
 (** {3 Adding subparts of a function contract} *)
 
@@ -1072,8 +1075,8 @@ let add_code_annot emitter ?kf stmt ca =
   let kf = find_englobing_kf ?kf stmt in
   let convert a =
     match a.annot_content with
-    | AAssert(l, kind, p) ->
-      let a = { a with annot_content=AAssert(l,kind,extend_name emitter p) } in
+    | AAssert(l, p) ->
+      let a = { a with annot_content=AAssert(l,extend_name emitter p) } in
       a, Property.ip_of_code_annot kf stmt a
     | AInvariant(l, b, p) ->
       let a={a with annot_content=AInvariant(l,b,extend_name emitter p)} in
@@ -1270,11 +1273,13 @@ let add_code_annot emitter ?kf stmt ca =
     Code_annots.add stmt tbl
 
 let add_assert e ?kf stmt a =
-  let a = Logic_const.new_code_annotation (AAssert ([],Assert,a)) in
+  let a = Logic_const.toplevel_predicate ~only_check:false a in
+  let a = Logic_const.new_code_annotation (AAssert ([],a)) in
   add_code_annot e ?kf stmt a
 
 let add_check e ?kf stmt a =
-  let a = Logic_const.new_code_annotation (AAssert ([],Check,a)) in
+  let a = Logic_const.toplevel_predicate ~only_check:true a in
+  let a = Logic_const.new_code_annotation (AAssert ([],a)) in
   add_code_annot e ?kf stmt a
 
 (** {3 Adding globals} *)
diff --git a/src/kernel_services/ast_data/cil_types.mli b/src/kernel_services/ast_data/cil_types.mli
index 9ad9fdb7a7684514813a0b79fee5116fcd7ab814..53a410ee52c920a514dc2cfe38a15e149b96959d 100644
--- a/src/kernel_services/ast_data/cil_types.mli
+++ b/src/kernel_services/ast_data/cil_types.mli
@@ -1590,7 +1590,17 @@ and predicate_node =
     create fresh predicates *)
 and identified_predicate = {
   ip_id: int; (** identifier *)
-  ip_content: predicate; (** the predicate itself*)
+  ip_content: toplevel_predicate; (** the predicate itself*)
+}
+
+(** main statement of an annotation. *)
+and toplevel_predicate = {
+  tp_only_check: bool;
+  (** whether the annotation is only used to check that [ip_content] holds, but
+      stays invisible for other verification tasks (see description of ACSL's
+      check keyword).
+  *)
+  tp_statement: predicate;
 }
 
 (** predicates with a location and an optional list of names *)
@@ -1745,17 +1755,11 @@ and pragma =
   | Slice_pragma of slice_pragma
   | Impact_pragma of impact_pragma
 
-(** Kind of an assertion:
-    - an assert is both evaluated and used as hypothesis afterwards;
-    - a check is only evaluated, but is not used as an hypothesis: it does not
-      affect the analyses. *)
-and assertion_kind = Assert | Check
-
 (** all annotations that can be found in the code.
     This type shares the name of its constructors with
     {!Logic_ptree.code_annot}. *)
 and code_annotation_node =
-  | AAssert of string list * assertion_kind * predicate
+  | AAssert of string list * toplevel_predicate
   (** assertion to be checked. The list of strings is the list of
       behaviors to which this assertion applies. *)
 
@@ -1763,7 +1767,7 @@ and code_annotation_node =
   (** statement contract
       (potentially restricted to some enclosing behaviors). *)
 
-  | AInvariant of string list * bool * predicate
+  | AInvariant of string list * bool * toplevel_predicate
   (** loop/code invariant. The list of strings is the list of behaviors to which
       this invariant applies.  The boolean flag is true for normal loop
       invariants and false for invariant-as-assertions. *)
@@ -1814,7 +1818,7 @@ and global_annotation =
   | Dtype of logic_type_info * location (** declaration of a logic type. *)
   | Dlemma of
       string * bool * logic_label list * string list *
-      predicate * attributes * location
+      toplevel_predicate * attributes * location
   (** definition of a lemma. The boolean flag is [true] if the property should
       be taken as an axiom and [false] if it must be proved.  *)
   | Dinvariant of logic_info * location
diff --git a/src/kernel_services/ast_data/property.ml b/src/kernel_services/ast_data/property.ml
index a4720657054383c60c52711a697cf07ba7c7d144..04e98b3d88abb2cfcc90ae5f5686a8af6c494185 100644
--- a/src/kernel_services/ast_data/property.ml
+++ b/src/kernel_services/ast_data/property.ml
@@ -126,7 +126,7 @@ and identified_lemma = {
   il_name : string;
   il_labels : logic_label list;
   il_args : string list;
-  il_pred : predicate;
+  il_pred : toplevel_predicate;
   il_loc : location
 }
 
@@ -281,7 +281,7 @@ let loc_of_loc_o = function
   | OLGlob loc -> loc
 
 let rec location = function
-  | IPPredicate {ip_pred} -> ip_pred.ip_content.pred_loc
+  | IPPredicate {ip_pred} -> (Logic_const.pred_of_id_pred ip_pred).pred_loc
   | IPBehavior {ib_kf=kf; ib_kinstr=ki}
   | IPComplete {ic_kf=kf; ic_kinstr=ki}
   | IPDisjoint {ic_kf=kf; ic_kinstr=ki}
@@ -397,8 +397,13 @@ include Datatype.Make_with_collections
 
       type t = identified_property
       let name = "Property.t"
-      let reprs = [IPAxiom {il_name="";il_labels=[];il_args=[];
-                            il_pred=Logic_const.ptrue;il_loc=Location.unknown}]
+      let reprs = [
+        IPAxiom {
+          il_name="";il_labels=[];il_args=[];
+          il_pred=Logic_const.(toplevel_predicate ptrue);
+          il_loc=Location.unknown
+        }]
+
       let mem_project = Datatype.never_any_project
 
       let pp_active fmt active =
@@ -688,9 +693,10 @@ include Datatype.Make_with_collections
     end)
 
 let rec short_pretty fmt p = match p with
-  | IPPredicate {ip_pred={ip_content={pred_name=name::_}}} ->
-    Format.pp_print_string fmt name
-  | IPPredicate _ -> pretty fmt p
+  | IPPredicate {ip_pred} ->
+    (match (Logic_const.pred_of_id_pred ip_pred).pred_name with
+     | name :: _ -> Format.pp_print_string fmt name
+     | [] -> pretty fmt p)
   | IPExtended {ie_ext={ext_name}} -> Format.pp_print_string fmt ext_name
   | IPAxiom {il_name=n} | IPLemma {il_name=n}
   | IPTypeInvariant {iti_name=n} | IPGlobalInvariant {igi_name=n}
@@ -704,9 +710,11 @@ let rec short_pretty fmt p = match p with
   | IPDisjoint {ic_kf} ->
     Format.fprintf fmt "disjoint clause in function %a"
       Kernel_function.pretty ic_kf
-  | IPCodeAnnot {ica_ca={annot_content=AAssert (_, _, {pred_name=name::_})}}
-  | IPCodeAnnot {ica_ca={annot_content=AInvariant (_, _, {pred_name=name::_})}} ->
-    Format.pp_print_string fmt name
+  | IPCodeAnnot {ica_ca={annot_content=AAssert (_, {tp_statement})}}
+  | IPCodeAnnot {ica_ca={annot_content=AInvariant (_, _, {tp_statement})}} ->
+    (match tp_statement.pred_name with
+     | name :: _ -> Format.pp_print_string fmt name
+     | [] -> pretty fmt p)
   | IPCodeAnnot _ -> pretty fmt p
   | IPAllocation {ial_kf} ->
     Format.fprintf fmt "allocates/frees clause in function %a"
@@ -813,7 +821,7 @@ let rec pretty_debug fmt = function
       Cil_types_debug.pp_string il_name
       (Cil_types_debug.pp_list Cil_types_debug.pp_logic_label) il_labels
       (Cil_types_debug.pp_list Cil_types_debug.pp_string) il_args
-      Cil_types_debug.pp_predicate il_pred
+      Cil_types_debug.pp_toplevel_predicate il_pred
       Cil_types_debug.pp_location il_loc
   | IPAxiomatic {iax_name; iax_props} ->
     Format.fprintf fmt "IPAxiomatic(%a,%a)"
@@ -824,7 +832,7 @@ let rec pretty_debug fmt = function
       Cil_types_debug.pp_string il_name
       (Cil_types_debug.pp_list Cil_types_debug.pp_logic_label) il_labels
       (Cil_types_debug.pp_list Cil_types_debug.pp_string) il_args
-      Cil_types_debug.pp_predicate il_pred
+      Cil_types_debug.pp_toplevel_predicate il_pred
       Cil_types_debug.pp_location il_loc
   | IPTypeInvariant {iti_name; iti_type; iti_pred; iti_loc} ->
     Format.fprintf fmt "IPTypeInvariant(%a,%a,%a,%a)"
@@ -919,7 +927,8 @@ struct
 
   let pp_code_annot_names fmt ca =
     match ca.annot_content with
-    | AAssert(for_bhv,_,named_pred) | AInvariant(for_bhv,_,named_pred) ->
+    | AAssert(for_bhv,pred) | AInvariant(for_bhv,_,pred) ->
+      let named_pred = pred.tp_statement in
       let pp_for_bhv fmt l =
         match l with
         | [] -> ()
@@ -976,13 +985,13 @@ struct
     | IPPredicate {ip_kind=pk;ip_kf=kf;ip_kinstr=ki;ip_pred=idp} ->
       Format.asprintf "%s%s%a"
         (kf_prefix kf) (predicate_kind_txt pk ki)
-        pp_names idp.ip_content.pred_name
+        pp_names (Logic_const.pred_of_id_pred idp).pred_name
     | IPExtended {ie_ext={ext_name};ie_loc=le} ->
       Format.asprintf  "%sextended%a" (extended_loc_prefix le) pp_names [ext_name]
     | IPCodeAnnot {ica_kf=kf; ica_ca=ca} ->
       let name = match ca.annot_content with
-        | AAssert (_, Assert, _) -> "assert"
-        | AAssert (_, Check, _) -> "check"
+        | AAssert (_, {tp_only_check = false }) -> "assert"
+        | AAssert (_, {tp_only_check = true }) -> "check"
         | AInvariant (_,true,_) -> "loop_inv"
         | AInvariant _ -> "inv"
         | APragma _ -> "pragma"
@@ -1003,10 +1012,10 @@ struct
     | IPDecrease {id_kf=kf; id_variant=variant} ->
       (kf_prefix kf) ^ "loop_term" ^ (variant_suffix variant)
     | IPAxiom {il_name=name; il_pred} ->
-      Format.asprintf "axiom_%s%a" name pp_names il_pred.pred_name
+      Format.asprintf "axiom_%s%a" name pp_names il_pred.tp_statement.pred_name
     | IPAxiomatic {iax_name} -> "axiomatic_" ^ iax_name
     | IPLemma {il_name=name; il_pred} ->
-      Format.asprintf "lemma_%s%a" name pp_names il_pred.pred_name
+      Format.asprintf "lemma_%s%a" name pp_names il_pred.tp_statement.pred_name
     | IPTypeInvariant {iti_name; iti_pred} ->
       Format.asprintf "type_invariant_%s%a"
         iti_name pp_names iti_pred.pred_name
@@ -1106,7 +1115,7 @@ struct
     | K kf -> Sanitizer.add_string buffer (Kernel_function.get_name kf)
     | A msg -> Sanitizer.add_string buffer msg
     | S stmt -> Sanitizer.add_string buffer (Printf.sprintf "s%d" stmt.sid)
-    | I { ip_content = { pred_name = a } }
+    | I { ip_content = { tp_statement = { pred_name = a } } }
     | P { pred_name = a } | T { term_name = a } -> Sanitizer.add_list buffer a
 
   let rec add_parts buffer = function
@@ -1125,17 +1134,35 @@ struct
     | IPPredicate {ip_kind=PKAssumes bhv; ip_kf=kf; ip_pred=ip} ->
       [ K kf ; B bhv ; A "assumes" ; I ip ]
     | IPPredicate {ip_kind=PKRequires bhv; ip_kf=kf; ip_pred=ip} ->
-      [ K kf ; B bhv ; A "requires" ; I ip ]
+      let a =
+        if ip.ip_content.tp_only_check then "check_requires" else "requires"
+      in
+      [ K kf ; B bhv ; A a ; I ip ]
     | IPPredicate {ip_kind=PKEnsures (bhv, Normal); ip_kf=kf; ip_pred=ip} ->
-      [ K kf ; B bhv ; A "ensures" ; I ip ]
+      let a =
+        if ip.ip_content.tp_only_check then "check_ensures" else "ensures"
+      in
+      [ K kf ; B bhv ; A a ; I ip ]
     | IPPredicate {ip_kind=PKEnsures (bhv, Exits); ip_kf=kf; ip_pred=ip} ->
-      [ K kf ; B bhv ; A "exits" ; I ip ]
+      let a =
+        if ip.ip_content.tp_only_check then "check_exits" else "exits"
+      in
+      [ K kf ; B bhv ; A a ; I ip ]
     | IPPredicate {ip_kind=PKEnsures (bhv, Breaks); ip_kf=kf; ip_pred=ip} ->
-      [ K kf ; B bhv ; A "breaks" ; I ip ]
+      let a =
+        if ip.ip_content.tp_only_check then "check_breaks" else "breaks"
+      in
+      [ K kf ; B bhv ; A a ; I ip ]
     | IPPredicate {ip_kind=PKEnsures (bhv, Continues); ip_kf=kf; ip_pred=ip} ->
-      [ K kf ; B bhv ; A "continues" ; I ip ]
+      let a =
+        if ip.ip_content.tp_only_check then "check_continues" else "continues"
+      in
+      [ K kf ; B bhv ; A a ; I ip ]
     | IPPredicate {ip_kind=PKEnsures (bhv, Returns); ip_kf=kf; ip_pred=ip} ->
-      [ K kf ; B bhv ; A "returns" ; I ip ]
+      let a =
+        if ip.ip_content.tp_only_check then "check_returns" else "returns"
+      in
+      [ K kf ; B bhv ; A a ; I ip ]
     | IPPredicate {ip_kind=PKTerminates; ip_kf=kf; ip_pred=ip} ->
       [ K kf ; A "terminates" ; I ip ]
 
@@ -1166,14 +1193,19 @@ struct
     | IPCodeAnnot {ica_kf=kf; ica_stmt=stmt;
                    ica_ca={annot_content=AExtended (_, _, {ext_name})}} ->
       [ K kf ; A ext_name ; S stmt ]
-    | IPCodeAnnot {ica_kf=kf; ica_ca={annot_content=AAssert (_, Assert,p)}} ->
-      [K kf ; A "assert" ; P p ]
-    | IPCodeAnnot {ica_kf=kf; ica_ca={annot_content=AAssert (_, Check,p)}} ->
-      [K kf ; A "check" ; P p ]
+    | IPCodeAnnot {ica_kf=kf; ica_ca={annot_content=AAssert (_,p)}} ->
+      let a = if p.tp_only_check then "check" else "assert" in
+      [K kf ; A a ; P p.tp_statement ]
     | IPCodeAnnot {ica_kf=kf; ica_ca={annot_content=AInvariant (_, true, p)}} ->
-      [K kf ; A "loop_invariant" ; P p ]
-    | IPCodeAnnot {ica_kf=kf; ica_ca={annot_content=AInvariant (_, false, p)}} ->
-      [K kf ; A "invariant" ; P p ]
+      let a =
+        if p.tp_only_check then "check_loop_invariant" else "loop_invariant"
+      in
+      [K kf ; A a ; P p.tp_statement ]
+    | IPCodeAnnot {ica_kf=kf; ica_ca={annot_content=AInvariant (_,false, p)}} ->
+      let a =
+        if p.tp_only_check then "check_invariant" else "invariant"
+      in
+      [K kf ; A a ; P p.tp_statement ]
     | IPCodeAnnot {ica_kf=kf; ica_ca={annot_content=AVariant (e, _)}} ->
       [K kf ; A "loop_variant" ; T e ]
     | IPCodeAnnot {ica_kf=kf; ica_ca={annot_content=AAssigns _}} ->
@@ -1199,7 +1231,8 @@ struct
     | IPAxiomatic _
     | IPAxiom _ -> []
     | IPLemma {il_name=name; il_pred=p} ->
-      [ A "lemma" ; A name ; P p ]
+      let a = if p.tp_only_check then "check_lemma" else "lemma" in
+      [ A a ; A name ; P p.tp_statement ]
 
     | IPTypeInvariant {iti_name=name}
     | IPGlobalInvariant {igi_name=name} ->
diff --git a/src/kernel_services/ast_data/property.mli b/src/kernel_services/ast_data/property.mli
index 02db66a05b03a21a453f145017b482ed89717c85..068d8a76fc1eecd8fcb0b31051f62a78e2024008 100644
--- a/src/kernel_services/ast_data/property.mli
+++ b/src/kernel_services/ast_data/property.mli
@@ -156,7 +156,7 @@ and identified_lemma = {
   il_name : string;
   il_labels : logic_label list;
   il_args : string list;
-  il_pred : predicate;
+  il_pred : toplevel_predicate;
   il_loc : location
 }
 
diff --git a/src/kernel_services/ast_printing/cil_printer.ml b/src/kernel_services/ast_printing/cil_printer.ml
index fbfc904dc2a8963412e321eaa01982d36048325e..a95db1207b8feca44ff8871dbcaab4fc81cc8378 100644
--- a/src/kernel_services/ast_printing/cil_printer.ml
+++ b/src/kernel_services/ast_printing/cil_printer.ml
@@ -2828,13 +2828,17 @@ class cil_printer () = object (self)
   method decreases fmt v = self#decrement "decreases" fmt v
   method variant fmt v = self#decrement "loop variant" fmt v
 
+  method private pp_only_check fmt p =
+    if p.tp_only_check then fprintf fmt "%a " self#pp_acsl_keyword "check"
+
   method assumes fmt p =
     fprintf fmt "@[<hov 2>%a@ %a;@]"
       self#pp_acsl_keyword "assumes"
       self#identified_predicate p
 
   method requires fmt p =
-    fprintf fmt "@[<hov 2>%a@ %a;@]"
+    fprintf fmt "@[<hov 2>%a%a@ %a;@]"
+      self#pp_only_check p.ip_content
       self#pp_acsl_keyword "requires"
       self#identified_predicate p
 
@@ -2846,7 +2850,8 @@ class cil_printer () = object (self)
 
   method post_cond fmt (k,p) =
     let kw = get_termination_kind_name k in
-    fprintf fmt "@[<hov 2>%a@ %a;@]"
+    fprintf fmt "@[<hov 2>%a%a@ %a;@]"
+      self#pp_only_check p.ip_content
       self#pp_acsl_keyword kw
       self#identified_predicate p
 
@@ -3053,16 +3058,12 @@ class cil_printer () = object (self)
           (Pretty_utils.pp_list ~sep:",@ " pp_print_string) l
     in
     match ca.annot_content with
-    | AAssert (behav,Assert,p) ->
+    | AAssert (behav,p) ->
+      let kw = if p.tp_only_check then "check" else "assert" in
       fprintf fmt "@[%a%a@ %a;@]"
         pp_for_behavs behav
-        self#pp_acsl_keyword "assert"
-        self#predicate p
-    | AAssert (behav,Check,p) ->
-      fprintf fmt "@[%a%a@ %a;@]"
-        pp_for_behavs behav
-        self#pp_acsl_keyword "check"
-        self#predicate p
+        self#pp_acsl_keyword kw
+        self#predicate p.tp_statement
     | APragma (Slice_pragma sp) ->
       fprintf fmt "@[%a@ %a;@]"
         self#pp_acsl_keyword "slice pragma"
@@ -3088,15 +3089,17 @@ class cil_printer () = object (self)
         pp_for_behavs behav
         (self#allocation ~isloop:true) af
     | AInvariant(behav,true, i) ->
-      fprintf fmt "@[<2>%a%a@ %a;@]"
+      fprintf fmt "@[<2>%a%a%a@ %a;@]"
         pp_for_behavs behav
+        self#pp_only_check i
         self#pp_acsl_keyword "loop invariant"
-        self#predicate i
+        self#predicate i.tp_statement
     | AInvariant(behav,false,i) ->
-      fprintf fmt "@[<2>%a%a@ %a;@]"
+      fprintf fmt "@[<2>%a%a%a@ %a;@]"
         pp_for_behavs behav
+        self#pp_only_check i
         self#pp_acsl_keyword "invariant"
-        self#predicate i
+        self#predicate i.tp_statement
     | AVariant v ->
       self#variant fmt v
     | AExtended (behav, is_loop, e) ->
@@ -3186,7 +3189,8 @@ class cil_printer () = object (self)
     | Dlemma(name, is_axiom, labels, tvars, pred, _attr, _) ->
       (* attributes are meant to be purely internal for now. *)
       let old_lab = current_label in
-      fprintf fmt "@[<hv 2>@[<hov 1>%a %a%a%a:@]@ %t%a;@]@\n"
+      fprintf fmt "@[<hv 2>@[<hov 1>%a%a %a%a%a:@]@ %t%a;@]@\n"
+        self#pp_only_check pred
         self#pp_acsl_keyword (if is_axiom then "axiom" else "lemma")
         self#varname name
         self#labels labels
@@ -3197,7 +3201,7 @@ class cil_printer () = object (self)
            the pretty-printing of labels, and before pretty-printing predicate
         *)
         (fun _ -> (match labels with [l] -> current_label <- l | _ -> ()))
-        self#predicate pred;
+        self#predicate pred.tp_statement;
       current_label <- old_lab
     | Dtype (ti,_) ->
       fprintf fmt "@[<hv 2>@[%a %a%a%a;@]@\n"
diff --git a/src/kernel_services/ast_printing/cil_types_debug.ml b/src/kernel_services/ast_printing/cil_types_debug.ml
index 0b4be0a9ac93ec2a8d93fb8a07047eaf2ff7a62e..cca0b496be8e8135493306671bf2202391f9ba2c 100644
--- a/src/kernel_services/ast_printing/cil_types_debug.ml
+++ b/src/kernel_services/ast_printing/cil_types_debug.ml
@@ -881,7 +881,13 @@ and pp_predicate_node fmt = function
 
 and pp_identified_predicate fmt identified_predicate =
   Format.fprintf fmt "{ip_id=%d;ip_content=%a}"
-    identified_predicate.ip_id pp_predicate identified_predicate.ip_content
+    identified_predicate.ip_id
+    pp_toplevel_predicate identified_predicate.ip_content
+
+and pp_toplevel_predicate fmt toplevel_predicate =
+  Format.fprintf fmt "{tp_only_check=%B;tp_statement=%a}"
+    toplevel_predicate.tp_only_check
+    pp_predicate toplevel_predicate.tp_statement
 
 and pp_predicate fmt predicate = Format.fprintf fmt "{%a%apred_content=%a}"
     (pp_if_list_not_empty "pred_name=" ";" (pp_list pp_string)) predicate.pred_name
@@ -960,17 +966,16 @@ and pp_pragma fmt = function
   | Impact_pragma(term) ->
     Format.fprintf fmt "Impact_pragma(%a)" pp_impact_pragma term
 
-and pp_assertion_kind fmt = function
-  | Assert -> Format.pp_print_string fmt "Assert"
-  | Check -> Format.pp_print_string fmt "Check"
-
 and pp_code_annotation_node fmt = function
-  | AAssert(string_list,kind,predicate) ->
-    Format.fprintf fmt "AAssert(%a,%a,%a)"  (pp_list pp_string) string_list pp_assertion_kind kind pp_predicate predicate
+  | AAssert(string_list,p) ->
+    Format.fprintf fmt "AAssert(%a,%a)"
+      (pp_list pp_string) string_list
+      pp_toplevel_predicate p
   | AStmtSpec(string_list,spec) ->
     Format.fprintf fmt "AStmtSpec(%a,%a)"  (pp_list pp_string) string_list  pp_spec spec
-  | AInvariant(string_list,bool,predicate) ->
-    Format.fprintf fmt "AInvariant(%a,%a,%a)"  (pp_list pp_string) string_list  pp_bool bool  pp_predicate predicate
+  | AInvariant(string_list,bool,p) ->
+    Format.fprintf fmt "AInvariant(%a,%a,%a)"
+      (pp_list pp_string) string_list  pp_bool bool  pp_toplevel_predicate p
   | AVariant(term_variant) ->
     Format.fprintf fmt "AVariant(%a)" pp_variant term_variant
   | AAssigns(string_list,assigns) ->
@@ -1010,7 +1015,8 @@ and pp_global_annotation fmt = function
   | Dlemma(string,bool,logic_label_list,string_list,predicate,attributes,location) ->
     Format.fprintf fmt "Dlemma(%a,%a,%a,%a,%a,%a,%a)"  pp_string string  pp_bool bool
       (pp_list pp_logic_label) logic_label_list (pp_list pp_string) string_list
-      pp_predicate predicate  pp_attributes attributes  pp_location location
+      pp_toplevel_predicate predicate
+      pp_attributes attributes  pp_location location
   | Dinvariant(logic_info,location) ->
     Format.fprintf fmt "Dinvariant(%a,%a)"  pp_logic_info logic_info  pp_location location
   | Dtype_annot(logic_info,location) ->
diff --git a/src/kernel_services/ast_printing/cil_types_debug.mli b/src/kernel_services/ast_printing/cil_types_debug.mli
index c9f1318b512cc8430d085f7c53b4fb8392bcb099..b64e8fbfebde6a2bb71a95224180bbcdb9f135ac 100644
--- a/src/kernel_services/ast_printing/cil_types_debug.mli
+++ b/src/kernel_services/ast_printing/cil_types_debug.mli
@@ -135,6 +135,7 @@ val pp_quantifiers : Format.formatter -> Cil_types.quantifiers -> unit
 val pp_relation : Format.formatter -> Cil_types.relation -> unit
 val pp_predicate_node : Format.formatter -> Cil_types.predicate_node -> unit
 val pp_identified_predicate : Format.formatter -> Cil_types.identified_predicate -> unit
+val pp_toplevel_predicate: Format.formatter -> Cil_types.toplevel_predicate -> unit
 val pp_predicate : Cil_types.predicate Pretty_utils.formatter
 val pp_spec : Format.formatter -> Cil_types.spec -> unit
 val pp_acsl_extension : Format.formatter -> Cil_types.acsl_extension -> unit
diff --git a/src/kernel_services/ast_printing/description.ml b/src/kernel_services/ast_printing/description.ml
index 47add398d3dbb5684c85af5f42351c50b8090032..4f152488f0b06c8f5ec161379b09408d0bb47bda 100644
--- a/src/kernel_services/ast_printing/description.ml
+++ b/src/kernel_services/ast_printing/description.ml
@@ -54,7 +54,7 @@ let pp_labels fmt stmt =
   | ls -> Format.fprintf fmt " '%s'" (String.concat "," ls)
 
 let pp_idpred kloc fmt idpred =
-  let np = idpred.ip_content in
+  let np = Logic_const.pred_of_id_pred idpred in
   if np.pred_name <> []
   then Format.fprintf fmt " '%s'" (String.concat "," np.pred_name)
   else pp_kloc kloc fmt np.pred_loc
@@ -110,14 +110,16 @@ let pp_named fmt nx =
   if nx.pred_name <> [] then
     Format.fprintf fmt " '%s'" (String.concat "," nx.pred_name)
 
+let pp_top fmt tp = pp_named fmt tp.tp_statement
+
 let pp_code_annot fmt ca =
   match ca.annot_content with
-  | AAssert(bs,Assert,np) ->
-    Format.fprintf fmt "assertion%a%a" pp_for bs pp_named np
-  | AAssert(bs,Check,np) ->
-    Format.fprintf fmt "check%a%a" pp_for bs pp_named np
-  | AInvariant(bs,_,np) ->
-    Format.fprintf fmt "invariant%a%a" pp_for bs pp_named np
+  | AAssert(bs,tp) when not tp.tp_only_check ->
+    Format.fprintf fmt "assertion%a%a" pp_for bs pp_top tp
+  | AAssert(bs,tp) ->
+    Format.fprintf fmt "check%a%a" pp_for bs pp_top tp
+  | AInvariant(bs,_,tp) ->
+    Format.fprintf fmt "invariant%a%a" pp_for bs pp_top tp
   | AAssigns(bs,_) -> Format.fprintf fmt "assigns%a" pp_for bs
   | AAllocation(bs,_) -> Format.fprintf fmt "allocates_frees%a" pp_for bs
   | APragma _ -> Format.pp_print_string fmt "pragma"
@@ -253,21 +255,22 @@ let rec pp_prop kfopt kiopt kloc fmt = function
       pp_bhvs ic_bhvs
       (pp_opt kiopt (pp_kinstr kloc)) ic_kinstr
       (pp_opt kiopt pp_active) ic_active
-  | IPCodeAnnot {ica_ca={annot_content=AAssert(bs,Assert,np)}} ->
+  | IPCodeAnnot {ica_ca={annot_content=AAssert(bs,tp)}}
+    when not tp.tp_only_check ->
     Format.fprintf fmt "Assertion%a%a%a"
       pp_for bs
-      pp_named np
-      (pp_kloc kloc) np.pred_loc
-  | IPCodeAnnot {ica_ca={annot_content=AAssert(bs,Check,np)}} ->
+      pp_top tp
+      (pp_kloc kloc) tp.tp_statement.pred_loc
+  | IPCodeAnnot {ica_ca={annot_content=AAssert(bs,tp)}} ->
     Format.fprintf fmt "Check%a%a%a"
       pp_for bs
-      pp_named np
-      (pp_kloc kloc) np.pred_loc
-  | IPCodeAnnot {ica_ca={annot_content=AInvariant(bs,_,np)}} ->
+      pp_top tp
+      (pp_kloc kloc) tp.tp_statement.pred_loc
+  | IPCodeAnnot {ica_ca={annot_content=AInvariant(bs,_,tp)}} ->
     Format.fprintf fmt "Invariant%a%a%a"
       pp_for bs
-      pp_named np
-      (pp_kloc kloc) np.pred_loc
+      pp_top tp
+      (pp_kloc kloc) tp.tp_statement.pred_loc
   | IPCodeAnnot {ica_ca={annot_content=AExtended(bs,_,{ext_name})};ica_stmt} ->
     Format.fprintf fmt "%a%a %a"
       pp_capitalize ext_name pp_for bs (pp_stmt kloc) ica_stmt
@@ -360,18 +363,16 @@ let to_string pp elt =
   Buffer.contents b
 
 let code_annot_kind_and_node code_annot = match code_annot.annot_content with
-  | AAssert (_, kind, {pred_content; pred_name}) ->
+  | AAssert (_, {tp_only_check; tp_statement = {pred_content; pred_name}}) ->
     let kind = match Alarms.find code_annot with
       | Some alarm -> Alarms.get_name alarm
       | None ->
-        if List.exists ((=) "missing_return") pred_name
-        then "missing_return"
-        else match kind with
-          | Assert -> "user assertion"
-          | Check -> "user check"
+        if List.exists ((=) "missing_return") pred_name then "missing_return"
+        else if tp_only_check then "user check"
+        else "user assertion"
     in
     Some (kind, to_string Printer.pp_predicate_node pred_content)
-  | AInvariant (_, _, {pred_content}) ->
+  | AInvariant (_, _, {tp_statement = {pred_content}}) ->
     Some ("loop invariant", to_string Printer.pp_predicate_node pred_content)
   | _ -> None
 
@@ -471,12 +472,12 @@ let for_order k = function
   | [] -> [I k]
   | bs -> I (succ k) :: named_order bs
 let annot_order = function
-  | {annot_content=AAssert(bs,Check,np)} ->
-    for_order 0 bs @ named_order np.pred_name
-  | {annot_content=AAssert(bs,Assert,np)} ->
-    for_order 2 bs @ named_order np.pred_name
-  | {annot_content=AInvariant(bs,_,np)} ->
-    for_order 4 bs @ named_order np.pred_name
+  | {annot_content=AAssert(bs,tp)} when tp.tp_only_check ->
+    for_order 0 bs @ named_order tp.tp_statement.pred_name
+  | {annot_content=AAssert(bs,tp)} ->
+    for_order 2 bs @ named_order tp.tp_statement.pred_name
+  | {annot_content=AInvariant(bs,_,tp)} ->
+    for_order 4 bs @ named_order tp.tp_statement.pred_name
   | _ -> [I 6]
 let loop_order = function
   | Id_contract (active,b) -> [B b; A active]
diff --git a/src/kernel_services/ast_printing/logic_print.ml b/src/kernel_services/ast_printing/logic_print.ml
index fca0da4953174ea419fd0fe96a21a520e7a80f18..1b3c0544fc39e38fce56da4f47fe2a8dae606f60 100644
--- a/src/kernel_services/ast_printing/logic_print.ml
+++ b/src/kernel_services/ast_printing/logic_print.ml
@@ -356,11 +356,12 @@ let rec print_decl fmt d =
       (pp_list ~sep:",@ " print_typed_ident) prms
       (pp_list ~sep:"@\n" print_case) cases
   | LDlemma(name,is_axiom,labels,tvar,body) ->
-    fprintf fmt "@[<2>%a@ %s%a%a:@ %a;@]"
+    fprintf fmt "@[<2>%s%a@ %s%a%a:@ %a;@]"
+      (if body.tp_only_check then "check " else "")
       (pp_cond ~pr_false:"lemma" is_axiom) "axiom" name
       (pp_list ~pre:"{@[" ~sep:",@ " ~suf:"@]}" pp_print_string) labels
       (pp_list ~pre:"<@[" ~sep:",@ " ~suf:"@>}" pp_print_string) tvar
-      print_lexpr body
+      print_lexpr body.tp_statement
   | LDaxiomatic (s,d) ->
     fprintf fmt "@[<2>axiomatic@ %s@ {@\n%a@]@\n}" s
       (pp_list ~sep:"@\n" print_decl) d
@@ -409,14 +410,18 @@ let print_allocation ~isloop fmt fa =
 
 let print_clause name fmt e = fprintf fmt "@\n%s@ %a;" name print_lexpr e
 
+let print_tp_clause name fmt e =
+  let name = if e.tp_only_check then "check " ^ name else name in
+  print_clause name fmt e.tp_statement
+
 let print_post fmt (k,e) =
-  print_clause (Cil_printer.get_termination_kind_name k) fmt e
+  print_tp_clause (Cil_printer.get_termination_kind_name k) fmt e
 
 let print_behavior fmt bhv =
   fprintf fmt "@[<2>behavior@ %s:%a%a%a%a%a@]"
     bhv.b_name
     (pp_list ~pre:"" ~suf:"" (print_clause "assumes")) bhv.b_assumes
-    (pp_list ~pre:"" ~suf:"" (print_clause "requires")) bhv.b_requires
+    (pp_list ~pre:"" ~suf:"" (print_tp_clause "requires")) bhv.b_requires
     (pp_list ~pre:"" ~suf:"" print_post) bhv.b_post_cond
     (print_allocation ~isloop:false) bhv.b_allocation
     print_assigns bhv.b_assigns
@@ -463,10 +468,6 @@ let print_pragma fmt p =
   | Slice_pragma p -> fprintf fmt "slice@ pragma@ %a;" print_slice_pragma p
   | Impact_pragma p -> fprintf fmt "impact@ pragma@ %a;" print_impact_pragma p
 
-let print_assertion_kind fmt = function
-  | Assert -> pp_print_string fmt "assert"
-  | Check -> pp_print_string fmt "check"
-
 let print_extension fmt (name, ext) =
   fprintf fmt "%s %a" name (pp_list ~sep:",@ " print_lexpr) ext
 
@@ -475,16 +476,21 @@ let print_code_annot fmt ca =
     (pp_list ~pre:"for@ " ~sep:",@ " ~suf:":@ " pp_print_string) fmt bhvs
   in
   match ca with
-    AAssert(bhvs,kind,e) ->
-    fprintf fmt "%a%a@ %a;"
-      print_behaviors bhvs print_assertion_kind kind print_lexpr e
+    AAssert(bhvs,e) ->
+    fprintf fmt "%a%s@ %a;"
+      print_behaviors bhvs
+      (if e.tp_only_check then "check" else "assert")
+      print_lexpr e.tp_statement
   | AStmtSpec (bhvs,s) ->
     fprintf fmt "%a%a"
       print_behaviors bhvs
       print_spec s
   | AInvariant (bhvs,loop,e) ->
-    fprintf fmt "%a%ainvariant@ %a;"
-      print_behaviors bhvs (pp_cond loop) "loop@ " print_lexpr e
+    fprintf fmt "%a%a%ainvariant@ %a;"
+      print_behaviors bhvs
+      (pp_cond e.tp_only_check) "check @"
+      (pp_cond loop) "loop@ "
+      print_lexpr e.tp_statement
   | AVariant e -> fprintf fmt "loop@ variant@ %a;" print_variant e
   | AAssigns (bhvs,a) ->
     fprintf fmt "%aloop@ %a" print_behaviors bhvs print_assigns a
diff --git a/src/kernel_services/ast_printing/printer.ml b/src/kernel_services/ast_printing/printer.ml
index 336d08c7b428d42fdadd796b4ff037804b02f3d0..aaaf74c2fd22f90d4cffa88e0bb00867fa28f71d 100644
--- a/src/kernel_services/ast_printing/printer.ml
+++ b/src/kernel_services/ast_printing/printer.ml
@@ -288,6 +288,7 @@ let () = Cil_datatype.Logic_label.pretty_ref := pp_logic_label
 let () = Cil_datatype.Global_annotation.pretty_ref := pp_global_annotation
 let () = Cil_datatype.Global.pretty_ref := pp_global
 let () = Cil_datatype.Predicate.pretty_ref := pp_predicate
+let () = Cil_datatype.Toplevel_predicate.pretty_ref := pp_toplevel_predicate
 let () = Cil_datatype.Identified_predicate.pretty_ref := pp_identified_predicate
 let () = Cil_datatype.Fundec.pretty_ref := pp_fundec
 
diff --git a/src/kernel_services/ast_printing/printer_api.mli b/src/kernel_services/ast_printing/printer_api.mli
index 428ff0df997022496c722540f5228eb284e5f2dd..566723c11c7ea5cc3fe179211b78ce2716e687ae 100644
--- a/src/kernel_services/ast_printing/printer_api.mli
+++ b/src/kernel_services/ast_printing/printer_api.mli
@@ -451,6 +451,8 @@ module type S_pp = sig
   (** @since 21.0-Scandium *)
   val pp_predicate_node: Format.formatter -> predicate_node -> unit
   val pp_predicate: Format.formatter -> predicate -> unit
+  val pp_toplevel_predicate: Format.formatter -> toplevel_predicate -> unit
+  (** @since Frama-C+dev *)
   val pp_identified_predicate: Format.formatter -> identified_predicate -> unit
   val pp_code_annotation: Format.formatter -> code_annotation -> unit
   val pp_funspec: Format.formatter -> funspec -> unit
diff --git a/src/kernel_services/ast_printing/printer_builder.ml b/src/kernel_services/ast_printing/printer_builder.ml
index beb17790e42b8bf9968b5368d8831d6edda3297b..94ef3b64e1f6d32232daf0ac0ef9174300f5b942 100644
--- a/src/kernel_services/ast_printing/printer_builder.ml
+++ b/src/kernel_services/ast_printing/printer_builder.ml
@@ -65,6 +65,8 @@ struct
   let pp_term_offset fmt x = (printer ())#term_offset fmt x
   let pp_predicate_node fmt x = (printer ())#predicate_node fmt x
   let pp_predicate fmt x = (printer ())#predicate fmt x
+  let pp_toplevel_predicate fmt x =
+    (printer())#predicate fmt x.Cil_types.tp_statement
   let pp_identified_predicate fmt x = (printer ())#identified_predicate fmt x
   let pp_code_annotation fmt x = (printer ())#code_annotation fmt x
   let pp_funspec fmt x = (printer ())#funspec fmt x
diff --git a/src/kernel_services/ast_queries/cil.ml b/src/kernel_services/ast_queries/cil.ml
index 544e912ca692472f847d2aa060ffd96c604f2c19..2ca9b6460174ddb4e2a31eaa05cb845814feaaec 100644
--- a/src/kernel_services/ast_queries/cil.ml
+++ b/src/kernel_services/ast_queries/cil.ml
@@ -1769,9 +1769,14 @@ and visitCilPredicate vis p =
   doVisitCil vis
     id vis#vpredicate childrenPredicate p
 
+and visitCilToplevel_predicate vis p =
+  let s = p.tp_statement in
+  let s' = visitCilPredicate vis s in
+  if s != s' then { p with tp_statement = s' } else p
+
 and childrenIdentified_predicate vis ip =
   let p = ip.ip_content in
-  let p' = visitCilPredicate vis p in
+  let p' = visitCilToplevel_predicate vis p in
   if p != p' then { ip with ip_content = p' }
   else ip
 
@@ -2089,7 +2094,7 @@ and childrenAnnotation vis a =
         vis#get_filling_actions;
     if ti' != ti then Dtype (ti',loc) else a
   | Dlemma(s,is_axiom,labels,tvars,p,attr,loc) ->
-    let p' = visitCilPredicate vis p in
+    let p' = visitCilToplevel_predicate vis p in
     let attr' = visitCilAttributes vis attr in
     if p' != p || attr != attr' then
       Dlemma(s,is_axiom,labels,tvars,p',attr',loc)
@@ -2142,14 +2147,14 @@ and visitCilCodeAnnotation vis ca =
     vis (Visitor_behavior.ccode_annotation vis#behavior) vis#vcode_annot childrenCodeAnnot ca
 
 and childrenCodeAnnot vis ca =
-  let vPred p = visitCilPredicate vis p in
+  let vPred p = visitCilToplevel_predicate vis p in
   let vTerm t = visitCilTerm vis t in
   let vSpec s = visitCilFunspec vis s in
   let change_content annot = { ca with annot_content = annot } in
   match ca.annot_content with
-    AAssert (behav,kind,p) ->
+    AAssert (behav,p) ->
     let p' = vPred p in if p' != p then
-      change_content (AAssert (behav,kind,p'))
+      change_content (AAssert (behav,p'))
     else ca
   | APragma (Impact_pragma t) ->
     let t' = visitCilImpactPragma vis t in
diff --git a/src/kernel_services/ast_queries/cil_datatype.ml b/src/kernel_services/ast_queries/cil_datatype.ml
index c9f743a32f6e55252fbed085583b467a45c07492..cd957175947d1393dee11370e9ebb96f9d4cea10 100644
--- a/src/kernel_services/ast_queries/cil_datatype.ml
+++ b/src/kernel_services/ast_queries/cil_datatype.ml
@@ -2235,8 +2235,8 @@ module Code_annotation = struct
       end)
 
   let loc ca = match ca.annot_content with
-    | AAssert(_,_,{pred_loc=loc})
-    | AInvariant(_,_,{pred_loc=loc})
+    | AAssert(_,{ tp_statement = {pred_loc=loc}})
+    | AInvariant(_,_,{tp_statement = {pred_loc=loc}})
     | AVariant({term_loc=loc},_) -> Some loc
     | AAssigns _ | AAllocation _ | APragma _ | AExtended _
     | AStmtSpec _ -> None
@@ -2259,6 +2259,20 @@ module Predicate = struct
       end)
 end
 
+module Toplevel_predicate = struct
+  let pretty_ref = ref (fun _ _ -> assert false)
+  include Make
+      (struct
+        type t = toplevel_predicate
+        let name = "Toplevel_predicate"
+        let reprs =
+          [ { tp_statement = List.hd Predicate.reprs; tp_only_check = false }]
+        let internal_pretty_code = Datatype.undefined
+        let pretty fmt x = !pretty_ref fmt x
+        let varname _ = "p"
+      end)
+end
+
 module Identified_predicate = struct
   let pretty_ref = ref (fun _ _ -> assert false)
   include Make_with_collections
@@ -2266,7 +2280,7 @@ module Identified_predicate = struct
         type t = identified_predicate
         let name = "Identified_predicate"
         let reprs =
-          [ { ip_content = List.hd Predicate.reprs; ip_id = -1} ]
+          [ { ip_content = List.hd Toplevel_predicate.reprs; ip_id = -1} ]
         let compare x y = Extlib.compare_basic x.ip_id y.ip_id
         let equal x y = x.ip_id = y.ip_id
         let copy = Datatype.undefined
diff --git a/src/kernel_services/ast_queries/cil_datatype.mli b/src/kernel_services/ast_queries/cil_datatype.mli
index 52f914d8ebe394785d5d998afbe9cf7e640a7e0b..34041802d4ba1afa79f34415c0e9c707818f0331 100644
--- a/src/kernel_services/ast_queries/cil_datatype.mli
+++ b/src/kernel_services/ast_queries/cil_datatype.mli
@@ -293,6 +293,7 @@ module Term_lval: S_with_collections_pretty with type t = term_lval
 module Logic_real: S_with_collections_pretty with type t = logic_real
 
 module Predicate: S_with_pretty with type t = predicate
+module Toplevel_predicate: S_with_pretty with type t = toplevel_predicate
 module Identified_predicate: 
   S_with_collections_pretty with type t = identified_predicate
 (** @since Neon-20140301 *)
diff --git a/src/kernel_services/ast_queries/filecheck.ml b/src/kernel_services/ast_queries/filecheck.ml
index c6214a4461ba9731be1ba117c42aa38093129d4c..2eb9c7560b2bd1dd8164cb4cffc039614fca390a 100644
--- a/src/kernel_services/ast_queries/filecheck.ml
+++ b/src/kernel_services/ast_queries/filecheck.ml
@@ -650,7 +650,7 @@ module Base_checker = struct
            names of statement contracts. *)
         if is_normalized then begin
           match ca.annot_content with
-          | AAssert(bhvs,_,_) | AStmtSpec(bhvs,_) | AInvariant (bhvs,_,_)
+          | AAssert(bhvs,_) | AStmtSpec(bhvs,_) | AInvariant (bhvs,_,_)
           | AAssigns(bhvs,_) | AAllocation(bhvs,_) | AExtended (bhvs,_,_) ->
             List.iter
               (fun b ->
diff --git a/src/kernel_services/ast_queries/logic_const.ml b/src/kernel_services/ast_queries/logic_const.ml
index 8ee64b0b36651d60f18a87251d73e9db53d5a161..861d64099492abe32e3cc6026ce0eee7beba3c1f 100644
--- a/src/kernel_services/ast_queries/logic_const.ml
+++ b/src/kernel_services/ast_queries/logic_const.ml
@@ -43,12 +43,15 @@ let new_code_annotation annot =
 
 let fresh_code_annotation = AnnotId.next
 
-let new_predicate p =
-  { ip_id = PredicateId.next (); ip_content = p }
+let toplevel_predicate ?(only_check=false) p =
+  { tp_only_check = only_check; tp_statement = p }
+
+let new_predicate ?only_check p =
+  { ip_id = PredicateId.next (); ip_content = toplevel_predicate ?only_check p }
 
 let fresh_predicate_id = PredicateId.next
 
-let pred_of_id_pred p = p.ip_content
+let pred_of_id_pred p = p.ip_content.tp_statement
 
 let refresh_predicate p = { p with ip_id = PredicateId.next () }
 
diff --git a/src/kernel_services/ast_queries/logic_const.mli b/src/kernel_services/ast_queries/logic_const.mli
index 51759d05c132490f56e7b7a7644677cc944c9fac..9079513585804f3b4d54d1c4052eb7b30f392675 100644
--- a/src/kernel_services/ast_queries/logic_const.mli
+++ b/src/kernel_services/ast_queries/logic_const.mli
@@ -46,8 +46,19 @@ val refresh_code_annotation: code_annotation -> code_annotation
 *)
 val refresh_spec: funspec -> funspec
 
-(** creates a new identified predicate with a fresh id. *)
-val new_predicate: predicate -> identified_predicate
+(** creates a new toplevel predicate.
+    [only_check] is true if the corresponding predicate should only be used
+    to check a property, without adding it as hypothesis for the rest of the
+    verification. See {!Cil_types.toplevel_predicate} for more information.
+    Default is [false], i.e. use standard ACSL semantics.
+    @since Frama-C+dev
+*)
+val toplevel_predicate: ?only_check:bool -> predicate -> toplevel_predicate
+
+(** creates a new identified predicate with a fresh id.
+    @modify Frama-C+dev add [only_check] optional parameter
+ *)
+val new_predicate: ?only_check:bool -> predicate -> identified_predicate
 
 (** creates a new acsl_extension with a fresh id.
     @plugin development guide
diff --git a/src/kernel_services/ast_queries/logic_typing.ml b/src/kernel_services/ast_queries/logic_typing.ml
index d0298228e25e382a6a140398d4a14ec0fd524f7b..70e213f6bdc137f92f134cfdfb75dee1e8cedf71 100644
--- a/src/kernel_services/ast_queries/logic_typing.ml
+++ b/src/kernel_services/ast_queries/logic_typing.ml
@@ -3513,6 +3513,10 @@ struct
 
   let id_predicate env pred = Logic_const.new_predicate (predicate env pred)
 
+  let id_predicate_top env pred =
+    let { tp_only_check = only_check; tp_statement = pred } = pred in
+    Logic_const.new_predicate ~only_check (predicate env pred)
+
   let id_term_ptr env t =
     let loc = t.lexpr_loc in
     let t = term env t in
@@ -3675,11 +3679,12 @@ struct
               ~type_assigns:type_assign
           in
           let b_assumes = List.map (id_predicate env) bas in
-          let b_requires= List.map (id_predicate env) br in
+          let b_requires= List.map (id_predicate_top env) br in
           let b_post_cond =
             List.map
               (fun (k,p)->
-                 let p' = id_predicate (post_state_env k) p in (k,p')) be
+                 let p' = id_predicate_top (post_state_env k) p in (k,p'))
+              be
           in
           let b_assigns =
             type_assign typing_context ~accept_formal:is_stmt_contract assigns_env ba
@@ -3773,15 +3778,14 @@ struct
     append_loop_labels (append_here_label (append_pre_label (append_init_label
                                                                (Lenv.empty()))))
 
-  let assertion_kind =
-    function Assert -> Cil_types.Assert | Check -> Cil_types.Check
-
   let code_annot loc current_behaviors current_return_type ca =
     let source = fst loc in
     let annot = match ca with
-      | AAssert (behav,k,p) ->
+      | AAssert (behav,{tp_only_check=only_check; tp_statement = p}) ->
         check_behavior_names loc current_behaviors behav;
-        Cil_types.AAssert(behav,assertion_kind k,predicate (code_annot_env()) p)
+        let p = predicate (code_annot_env()) p in
+        let p = Logic_const.toplevel_predicate ~only_check p in
+        Cil_types.AAssert(behav,p)
       | APragma (Impact_pragma sp) ->
         Cil_types.APragma
           (Cil_types.Impact_pragma (impact_pragma (code_annot_env()) sp))
@@ -3807,10 +3811,11 @@ struct
         Cil_types.AStmtSpec (behav,my_spec)
       | AVariant v ->
         Cil_types.AVariant (type_variant (loop_annot_env ()) v)
-      | AInvariant (behav,f,i) ->
+      | AInvariant (behav,f,{ tp_only_check = only_check; tp_statement = i}) ->
         let env = if f then loop_annot_env () else code_annot_env () in
         check_behavior_names loc current_behaviors behav;
-        Cil_types.AInvariant (behav,f,predicate env i)
+        let p = Logic_const.toplevel_predicate ~only_check (predicate env i) in
+        Cil_types.AInvariant (behav,f,p)
       | AAllocation (behav,fa) ->
         check_behavior_names loc current_behaviors behav;
         Cil_types.AAllocation(behav,
@@ -4116,7 +4121,8 @@ struct
         C.error loc "Definition of %s is cyclic" s;
       my_info.lt_def <- tdef;
       Dtype (my_info,loc)
-    | LDlemma (x,is_axiom, labels, poly, e) ->
+    | LDlemma (x,is_axiom, labels, poly,
+               { tp_only_check = only_check; tp_statement = e}) ->
       if Logic_env.Lemmas.mem x then begin
         let old_def = Logic_env.Lemmas.find x in
         let old_loc = Cil_datatype.Global_annotation.loc old_def in
@@ -4132,7 +4138,7 @@ struct
           Cil_datatype.Location.pretty old_loc
       end;
       let labels,env = annot_env loc labels poly in
-      let p = predicate env e in
+      let p = Logic_const.toplevel_predicate ~only_check (predicate env e) in
       let labels = match !Lenv.default_label with
         | None -> labels
         | Some lab -> [lab]
diff --git a/src/kernel_services/ast_queries/logic_utils.ml b/src/kernel_services/ast_queries/logic_utils.ml
index 242feb6c6a054e09f4016d0168be57a3e4a9c38f..019913fdd973d36c15460410bd7cbe9669db5220 100644
--- a/src/kernel_services/ast_queries/logic_utils.ml
+++ b/src/kernel_services/ast_queries/logic_utils.ml
@@ -129,7 +129,7 @@ let coerce_type typ =
   else if Cil.isFloatingType ty then Lreal
   else Ctype typ
 
-let predicate_of_identified_predicate ip = ip.ip_content
+let predicate_of_identified_predicate ip = ip.ip_content.tp_statement
 
 let translate_old_label s p =
   let get_label () =
@@ -1025,8 +1025,13 @@ and is_same_predicate pred1 pred2 =
   is_same_list Datatype.String.equal pred1.pred_name pred2.pred_name &&
   is_same_predicate_node pred1.pred_content pred2.pred_content
 
+
+and is_same_toplevel_predicate p1 p2 =
+  p1.tp_only_check = p2.tp_only_check &&
+  is_same_predicate p1.tp_statement p2.tp_statement
+
 and is_same_identified_predicate p1 p2 =
-  is_same_predicate p1.ip_content p2.ip_content
+  is_same_toplevel_predicate p1.ip_content p2.ip_content
 
 and is_same_identified_term l1 l2 =
   is_same_term l1.it_content l2.it_content
@@ -1130,12 +1135,12 @@ let is_same_extension x1 x2 =
 
 let is_same_code_annotation (ca1:code_annotation) (ca2:code_annotation) =
   match ca1.annot_content, ca2.annot_content with
-  | AAssert(l1,k1,p1), AAssert(l2,k2,p2) ->
-    is_same_list (=) l1 l2 && k1 = k2 && is_same_predicate p1 p2
+  | AAssert(l1,p1), AAssert(l2,p2) ->
+    is_same_list (=) l1 l2 && is_same_toplevel_predicate p1 p2
   | AStmtSpec (l1,s1), AStmtSpec (l2,s2) ->
     is_same_list (=) l1 l2 && is_same_spec s1 s2
   | AInvariant(l1,b1,p1), AInvariant(l2,b2,p2) ->
-    is_same_list (=) l1 l2 && b1 = b2 && is_same_predicate p1 p2
+    is_same_list (=) l1 l2 && b1 = b2 && is_same_toplevel_predicate p1 p2
   | AVariant v1, AVariant v2 -> is_same_variant v1 v2
   | AAssigns(l1,a1), AAssigns(l2,a2) ->
     is_same_list (=) l1 l2 && is_same_assigns a1 a2
@@ -1165,7 +1170,7 @@ let rec is_same_global_annotation ga1 ga2 =
     Dlemma(n2,ax2,labs2,typs2,st2,attr2,_) ->
     is_same_string n1 n2 && ax1 = ax2 &&
     is_same_list is_same_logic_label labs1 labs2 &&
-    is_same_list (=) typs1 typs2 && is_same_predicate st1 st2 &&
+    is_same_list (=) typs1 typs2 && is_same_toplevel_predicate st1 st2 &&
     is_same_attributes attr1 attr2
   | Dinvariant (li1,_), Dinvariant (li2,_) -> is_same_logic_info li1 li2
   | Dtype_annot (li1,_), Dtype_annot (li2,_) -> is_same_logic_info li1 li2
@@ -2158,10 +2163,10 @@ let lhost_c_type thost =
   | TResult ty -> ty
 
 let is_assert ca =
-  match ca.annot_content with AAssert (_, Assert, _) -> true | _ -> false
+  match ca.annot_content with AAssert (_, p) -> not p.tp_only_check | _ -> false
 
 let is_check ca =
-  match ca.annot_content with AAssert (_, Check, _) -> true | _ -> false
+  match ca.annot_content with AAssert (_, p) -> p.tp_only_check | _ -> false
 
 let is_contract ca =
   match ca.annot_content with AStmtSpec _ -> true | _ -> false
@@ -2205,7 +2210,7 @@ let is_loop_annot s =
 
 let is_trivial_annotation a =
   match a.annot_content with
-  | AAssert (_,_,a) -> is_trivially_true a
+  | AAssert (_,a) -> is_trivially_true a.tp_statement
   | APragma _ | AStmtSpec _ | AInvariant _ | AVariant _
   | AAssigns _| AAllocation _ | AExtended _
     -> false
diff --git a/src/kernel_services/ast_transformations/filter.ml b/src/kernel_services/ast_transformations/filter.ml
index caff6cef46efa2b4fe32181dfc5868163ff6509d..d36b2cf000fee0b47bff693060a297d72a290f9f 100644
--- a/src/kernel_services/ast_transformations/filter.ml
+++ b/src/kernel_services/ast_transformations/filter.ml
@@ -448,9 +448,12 @@ end = struct
           Printer.pp_code_annotation v;
         ChangeTo
           (Logic_const.new_code_annotation
-             (AAssert ([], Assert,
-                       { pred_name = []; pred_loc = Cil_datatype.Location.unknown;
-                         pred_content = Ptrue})))
+             (AAssert
+                ([],
+                 Logic_const.toplevel_predicate
+                   { pred_name = [];
+                     pred_loc = Cil_datatype.Location.unknown;
+                     pred_content = Ptrue})))
       end
 
     method private process_call is_init_call call_stmt lval _f args loc =
@@ -714,7 +717,8 @@ end = struct
 
     method private visit_pred p =
       Logic_const.new_predicate
-        (visitCilPredicate (self:>Cil.cilVisitor) p.ip_content)
+        (visitCilPredicate (self:>Cil.cilVisitor)
+           (Logic_const.pred_of_id_pred p))
 
     method private visit_identified_term t =
       let t' = visitCilTerm (self:>Cil.cilVisitor) t.it_content in
@@ -733,11 +737,15 @@ end = struct
     method! vbehavior b =
       let finfo = self#get_finfo () in
 
-      let pre_visible p =  Info.fun_precond_visible finfo p.ip_content in
+      let pre_visible p =
+        Info.fun_precond_visible finfo (Logic_const.pred_of_id_pred p)
+      in
       b.b_assumes <- filter_list pre_visible self#visit_pred b.b_assumes;
       b.b_requires <- filter_list pre_visible self#visit_pred b.b_requires;
 
-      let ensure_visible (_,p) = Info.fun_postcond_visible finfo p.ip_content in
+      let ensure_visible (_,p) =
+        Info.fun_postcond_visible finfo (Logic_const.pred_of_id_pred p)
+      in
       b.b_post_cond <-
         filter_list ensure_visible (fun (k,p) -> k,self#visit_pred p)
           b.b_post_cond;
@@ -785,7 +793,7 @@ end = struct
       let new_term = match spec.spec_terminates with
         | None -> None
         | Some p ->
-          if Info.fun_precond_visible finfo p.ip_content
+          if Info.fun_precond_visible finfo (Logic_const.pred_of_id_pred p)
           then Some (self#visit_pred p)
           else None
       in
diff --git a/src/kernel_services/parsetree/cabshelper.mli b/src/kernel_services/parsetree/cabshelper.mli
index a4b0498146e4bce7b14fa47a60c7adf8d615981e..458c01febc4a9f2eb6b482b78cd1d48e7dda3ab8 100644
--- a/src/kernel_services/parsetree/cabshelper.mli
+++ b/src/kernel_services/parsetree/cabshelper.mli
@@ -80,8 +80,9 @@ val is_attr_test: unit -> bool
 val mk_behavior :
   ?name:string ->
   ?assumes:Logic_ptree.lexpr list ->
-  ?requires:Logic_ptree.lexpr list ->
-  ?post_cond:(Cil_types.termination_kind * Logic_ptree.lexpr) list ->
+  ?requires:Logic_ptree.toplevel_predicate list ->
+  ?post_cond:
+    (Cil_types.termination_kind * Logic_ptree.toplevel_predicate) list ->
   ?assigns:Logic_ptree.assigns ->
   ?allocation:Logic_ptree.allocation ->
   ?extended:Logic_ptree.extension list ->
diff --git a/src/kernel_services/parsetree/logic_ptree.mli b/src/kernel_services/parsetree/logic_ptree.mli
index adde2634144cb07084ca310b5ea944ea7ed119c8..bff3332bb8dff7075b6aedd448b7caecbfb70469 100644
--- a/src/kernel_services/parsetree/logic_ptree.mli
+++ b/src/kernel_services/parsetree/logic_ptree.mli
@@ -161,6 +161,7 @@ and lexpr_node =
   | PLrepeat of lexpr * lexpr
       (** repeat a list of elements a number of times. *)
 
+type toplevel_predicate = { tp_only_check: bool; tp_statement: lexpr }
 
 type extension = string * lexpr list
 
@@ -231,7 +232,7 @@ and decl_node =
         (** [LDinductive_def(name,labels,type_params, parameters, indcases)]
             represents an inductive definition of a new predicate.
          *)
-  | LDlemma of string * bool * string list * string list * lexpr
+  | LDlemma of string * bool * string list * string list * toplevel_predicate
       (** LDlemma(name,is_axiom,labels,type_params,property) represents
           a lemma or an axiom [name].
           [is_axiom] is true for an axiom and false for a lemma. [labels]
@@ -276,9 +277,11 @@ and variant = lexpr * string option
     with {!Cil_types.behavior}. *)
 type behavior = {
   mutable b_name : string; (** name of the behavior. *)
-  mutable b_requires : lexpr list; (** require clauses. *)
+  mutable b_requires : toplevel_predicate list; (** require clauses. *)
   mutable b_assumes : lexpr list; (** assume clauses. *)
-  mutable b_post_cond : (Cil_types.termination_kind * lexpr) list; (** post-condition. *)
+  mutable b_post_cond :
+    (Cil_types.termination_kind * toplevel_predicate) list;
+  (** post-condition. *)
   mutable b_assigns : assigns; (** assignments. *)
   mutable b_allocation : allocation; (** frees, allocates. *)
   mutable b_extended : extension list (** extensions *)
@@ -329,13 +332,10 @@ and pragma =
   | Slice_pragma of slice_pragma
   | Impact_pragma of impact_pragma
 
-and assertion_kind = Assert | Check
-
-
 (** all annotations that can be found in the code. This type shares the name of
     its constructors with {!Cil_types.code_annotation_node}. *)
 type code_annot =
-  | AAssert of string list * assertion_kind * lexpr
+  | AAssert of string list * toplevel_predicate
   (** assertion to be checked. The list of strings is the list of
       behaviors to which this assertion applies. *)
 
@@ -343,7 +343,7 @@ type code_annot =
   (** statement contract
       (potentially restricted to some enclosing behaviors). *)
 
-  | AInvariant of string list * bool * lexpr
+  | AInvariant of string list * bool * toplevel_predicate
   (** loop/code invariant. The list of strings is the list of behaviors to which
       this invariant applies.  The boolean flag is true for normal loop
       invariants and false for invariant-as-assertions. *)
diff --git a/src/plugins/aorai/aorai_utils.ml b/src/plugins/aorai/aorai_utils.ml
index c4fb25191c1f4b7f166ad3666763e6eff90a1aa1..8ace0513ae632217120f86caaa07cee32e0dd722 100644
--- a/src/plugins/aorai/aorai_utils.ml
+++ b/src/plugins/aorai/aorai_utils.ml
@@ -957,6 +957,7 @@ let mk_deterministic_lemma () =
     in
     let trans = Path_analysis.get_transitions_of_state state automaton in
     let prop = Extlib.product_fold disjoint_guards ptrue trans trans in
+    let prop = Logic_const.toplevel_predicate ~only_check:true prop in
     let name = state.Promelaast.name ^ "_deterministic_trans" in
     let lemma =
       Dlemma (name, false, [label],[],prop,[],Cil_datatype.Location.unknown)
diff --git a/src/plugins/aorai/aorai_visitors.ml b/src/plugins/aorai/aorai_visitors.ml
index 004941db6742cd482c8910fc0e7a1d3f3d0f197a..0bffbd505a4068b3530c5d266d90200595322839 100644
--- a/src/plugins/aorai/aorai_visitors.ml
+++ b/src/plugins/aorai/aorai_visitors.ml
@@ -460,6 +460,7 @@ let get_unchanged_aux_var loc current_state =
 class visit_adding_pre_post_from_buch treatloops =
 
   let predicate_to_invariant kf stmt pred =
+    let pred = Logic_const.toplevel_predicate pred in
     Annotations.add_code_annot
       Aorai_option.emitter
       ~kf
diff --git a/src/plugins/aorai/tests/aorai/oracle/assigns.1.res.oracle b/src/plugins/aorai/tests/aorai/oracle/assigns.1.res.oracle
index 2434556b05d580bac96d12dfa195f2e84cc9ee09..1ae6c45cb17fbe316a8edc9df3ce59f761d38989 100644
--- a/src/plugins/aorai/tests/aorai/oracle/assigns.1.res.oracle
+++ b/src/plugins/aorai/tests/aorai/oracle/assigns.1.res.oracle
@@ -18,15 +18,15 @@ enum aorai_OpStatusList {
     aorai_Terminated = 1,
     aorai_Called = 0
 };
-/*@ lemma in_main_deterministic_trans{L}: \true;
+/*@ check lemma in_main_deterministic_trans{L}: \true;
  */
-/*@ lemma Sf_deterministic_trans{L}: \true;
+/*@ check lemma Sf_deterministic_trans{L}: \true;
  */
-/*@ lemma S_in_f_deterministic_trans{L}: \true;
+/*@ check lemma S_in_f_deterministic_trans{L}: \true;
  */
-/*@ lemma S2_deterministic_trans{L}: \true;
+/*@ check lemma S2_deterministic_trans{L}: \true;
  */
-/*@ lemma S1_deterministic_trans{L}: \true;
+/*@ check lemma S1_deterministic_trans{L}: \true;
  */
 int X;
 /*@ ghost enum aorai_ListOper aorai_CurOperation = op_main; */
diff --git a/src/plugins/aorai/tests/aorai/oracle/declared_function.res.oracle b/src/plugins/aorai/tests/aorai/oracle/declared_function.res.oracle
index f30827619507d6a1d3244f24cb2af9416e749eb3..9d37fe0b6442bed85a03f3b4a22d895bf153f3ca 100644
--- a/src/plugins/aorai/tests/aorai/oracle/declared_function.res.oracle
+++ b/src/plugins/aorai/tests/aorai/oracle/declared_function.res.oracle
@@ -19,7 +19,7 @@ int f(void);
 /*@ ghost enum aorai_ListOper aorai_CurOperation = op_main; */
 /*@ ghost enum aorai_OpStatusList aorai_CurOpStatus = aorai_Called; */
 /*@
-lemma I_deterministic_trans{L}:
+check lemma I_deterministic_trans{L}:
   (∀ int __retres_f;
      ¬(\at(aorai_CurOperation,L) ≡ op_f ∧
         \at(aorai_CurOpStatus,L) ≡ aorai_Terminated ∧
diff --git a/src/plugins/aorai/tests/aorai/oracle/deterministic.res.oracle b/src/plugins/aorai/tests/aorai/oracle/deterministic.res.oracle
index 37d537ca5af54b6e147169cb5a78c9903dc749fb..75acb9204ee5a6aee059455def9e02c64419a037 100644
--- a/src/plugins/aorai/tests/aorai/oracle/deterministic.res.oracle
+++ b/src/plugins/aorai/tests/aorai/oracle/deterministic.res.oracle
@@ -23,22 +23,22 @@ enum aorai_OpStatusList {
     aorai_Terminated = 1,
     aorai_Called = 0
 };
-/*@ lemma Si_deterministic_trans{L}: \true;
+/*@ check lemma Si_deterministic_trans{L}: \true;
  */
-/*@ lemma Sf_deterministic_trans{L}: \true;
+/*@ check lemma Sf_deterministic_trans{L}: \true;
  */
-/*@ lemma S5_deterministic_trans{L}: \true;
+/*@ check lemma S5_deterministic_trans{L}: \true;
  */
-/*@ lemma S4_deterministic_trans{L}: \true;
+/*@ check lemma S4_deterministic_trans{L}: \true;
  */
-/*@ lemma S2_deterministic_trans{L}: \true;
+/*@ check lemma S2_deterministic_trans{L}: \true;
  */
 int X;
 int Y;
 /*@ ghost enum aorai_ListOper aorai_CurOperation = op_main; */
 /*@ ghost enum aorai_OpStatusList aorai_CurOpStatus = aorai_Called; */
 /*@
-lemma S3_deterministic_trans{L}:
+check lemma S3_deterministic_trans{L}:
   ∀ int x;
     ¬(\at(aorai_CurOperation,L) ≡ op_g ∧
        \at(aorai_CurOpStatus,L) ≡ aorai_Called ∧ x ≡ 5 ∧
@@ -46,7 +46,7 @@ lemma S3_deterministic_trans{L}:
        \at(aorai_CurOpStatus,L) ≡ aorai_Called ∧ x ≡ 4);
  */
 /*@
-lemma S1_deterministic_trans{L}:
+check lemma S1_deterministic_trans{L}:
   ∀ int __retres_f, int x;
     ¬(\at(aorai_CurOperation,L) ≡ op_f ∧
        \at(aorai_CurOpStatus,L) ≡ aorai_Terminated ∧ __retres_f ≡ 0 ∧
@@ -54,7 +54,7 @@ lemma S1_deterministic_trans{L}:
        \at(aorai_CurOpStatus,L) ≡ aorai_Called ∧ x ≡ 4);
  */
 /*@
-lemma S0_deterministic_trans{L}:
+check lemma S0_deterministic_trans{L}:
   ∀ int c;
     ¬(\at(aorai_CurOperation,L) ≡ op_real_main ∧
        \at(aorai_CurOpStatus,L) ≡ aorai_Called ∧ c ≢ 0 ∧
diff --git a/src/plugins/aorai/tests/aorai/oracle/formals.res.oracle b/src/plugins/aorai/tests/aorai/oracle/formals.res.oracle
index b850086cbe94dbafa142e58f40a017022d73a22c..f7b7f60952fc0de58218d819587217b5ac8e2cb3 100644
--- a/src/plugins/aorai/tests/aorai/oracle/formals.res.oracle
+++ b/src/plugins/aorai/tests/aorai/oracle/formals.res.oracle
@@ -22,16 +22,16 @@ enum aorai_OpStatusList {
     aorai_Terminated = 1,
     aorai_Called = 0
 };
-/*@ lemma init_deterministic_trans{L}: \true;
+/*@ check lemma init_deterministic_trans{L}: \true;
  */
-/*@ lemma aorai_reject_deterministic_trans{L}: \true;
+/*@ check lemma aorai_reject_deterministic_trans{L}: \true;
  */
-/*@ lemma OK_deterministic_trans{L}: \true;
+/*@ check lemma OK_deterministic_trans{L}: \true;
  */
 /*@ ghost enum aorai_ListOper aorai_CurOperation = op_main; */
 /*@ ghost enum aorai_OpStatusList aorai_CurOpStatus = aorai_Called; */
 /*@
-lemma main_0_deterministic_trans{L}:
+check lemma main_0_deterministic_trans{L}:
   ∀ int x;
     ¬(\at(aorai_CurOperation,L) ≡ op_f ∧
        \at(aorai_CurOpStatus,L) ≡ aorai_Called ∧ x ≡ 3 ∧
@@ -39,7 +39,7 @@ lemma main_0_deterministic_trans{L}:
        \at(aorai_CurOpStatus,L) ≡ aorai_Called ∧ x ≡ 1);
  */
 /*@
-lemma aorai_intermediate_state_0_deterministic_trans{L}:
+check lemma aorai_intermediate_state_0_deterministic_trans{L}:
   ¬(\at(aorai_CurOperation,L) ≡ op_g ∧
      \at(aorai_CurOpStatus,L) ≡ aorai_Called ∧
      ¬(\at(aorai_CurOperation,L) ≡ op_g ∧
@@ -48,7 +48,7 @@ lemma aorai_intermediate_state_0_deterministic_trans{L}:
 /*@ ghost int aorai_CurStates = init; */
 /*@ ghost int aorai_x_0 = 0; */
 /*@
-lemma aorai_intermediate_state_2_deterministic_trans{L}:
+check lemma aorai_intermediate_state_2_deterministic_trans{L}:
   ¬(\at(aorai_CurOperation,L) ≡ op_f ∧
      \at(aorai_CurOpStatus,L) ≡ aorai_Terminated ∧
      \at(aorai_x_0,L) ≡ 3 ∧
@@ -58,7 +58,7 @@ lemma aorai_intermediate_state_2_deterministic_trans{L}:
  */
 /*@ ghost int aorai_y = 0; */
 /*@
-lemma aorai_intermediate_state_1_deterministic_trans{L}:
+check lemma aorai_intermediate_state_1_deterministic_trans{L}:
   ¬(\at(aorai_CurOperation,L) ≡ op_g ∧
      \at(aorai_CurOpStatus,L) ≡ aorai_Terminated ∧
      \at(aorai_y,L) ≡ 2 ∧
@@ -68,7 +68,7 @@ lemma aorai_intermediate_state_1_deterministic_trans{L}:
  */
 /*@ ghost int aorai_x = 0; */
 /*@
-lemma aorai_intermediate_state_deterministic_trans{L}:
+check lemma aorai_intermediate_state_deterministic_trans{L}:
   ¬(\at(aorai_CurOperation,L) ≡ op_f ∧
      \at(aorai_CurOpStatus,L) ≡ aorai_Terminated ∧
      \at(aorai_x,L) ≡ 1 ∧
diff --git a/src/plugins/aorai/tests/aorai/oracle/incorrect.res.oracle b/src/plugins/aorai/tests/aorai/oracle/incorrect.res.oracle
index ebe6f07db4c9567f195bde9895293748e61bd6a4..f0441fa89f01c774e4a8ac2e8e94708bf91e14b0 100644
--- a/src/plugins/aorai/tests/aorai/oracle/incorrect.res.oracle
+++ b/src/plugins/aorai/tests/aorai/oracle/incorrect.res.oracle
@@ -15,7 +15,7 @@ enum aorai_OpStatusList {
     aorai_Terminated = 1,
     aorai_Called = 0
 };
-/*@ lemma s0_deterministic_trans{L}: \true;
+/*@ check lemma s0_deterministic_trans{L}: \true;
  */
 int f(void);
 
diff --git a/src/plugins/aorai/tests/aorai/oracle/monostate.res.oracle b/src/plugins/aorai/tests/aorai/oracle/monostate.res.oracle
index e4e6c64f81a3e62fcd37119fae12ca6dd86062c6..00d9af27024d4c9f1ab797e12c8459678891dfb0 100644
--- a/src/plugins/aorai/tests/aorai/oracle/monostate.res.oracle
+++ b/src/plugins/aorai/tests/aorai/oracle/monostate.res.oracle
@@ -19,19 +19,19 @@ enum aorai_OpStatusList {
     aorai_Terminated = 1,
     aorai_Called = 0
 };
-/*@ lemma aorai_reject_deterministic_trans{L}: \true;
+/*@ check lemma aorai_reject_deterministic_trans{L}: \true;
  */
 /*@ ghost enum aorai_ListOper aorai_CurOperation = op_main; */
 /*@ ghost enum aorai_OpStatusList aorai_CurOpStatus = aorai_Called; */
 /*@
-lemma aorai_intermediate_state_deterministic_trans{L}:
+check lemma aorai_intermediate_state_deterministic_trans{L}:
   ¬(\at(aorai_CurOperation,L) ≡ op_main ∧
      \at(aorai_CurOpStatus,L) ≡ aorai_Terminated ∧
      ¬(\at(aorai_CurOperation,L) ≡ op_main ∧
         \at(aorai_CurOpStatus,L) ≡ aorai_Terminated));
  */
 /*@
-lemma Init_deterministic_trans{L}:
+check lemma Init_deterministic_trans{L}:
   ¬(\at(aorai_CurOperation,L) ≡ op_main ∧
      \at(aorai_CurOpStatus,L) ≡ aorai_Called ∧
      ¬(\at(aorai_CurOperation,L) ≡ op_main ∧
diff --git a/src/plugins/e-acsl/src/code_generator/translate.ml b/src/plugins/e-acsl/src/code_generator/translate.ml
index 6a77b6530dfb5e6fd13a9a96e9878c3b5d48c6c9..018963ff23b879f9279c5d65080f4f9a42346a93 100644
--- a/src/plugins/e-acsl/src/code_generator/translate.ml
+++ b/src/plugins/e-acsl/src/code_generator/translate.ml
@@ -856,13 +856,14 @@ and translate_rte_annots:
   let env =
     List.fold_left
       (fun env a -> match a.annot_content with
-         | AAssert(_, _, p) ->
+         | AAssert(_, p) ->
            handle_error
              (fun env ->
                 Options.feedback ~dkey ~level:4 "prevent RTE from %a" pp elt;
                 (* The logic scope MUST NOT be reset here since we still might
                    be in the middle of the translation of the original
                    predicate. *)
+                let p = p.tp_statement in
                 let lscope_reset_old = Env.Logic_scope.get_reset env in
                 let env = Env.Logic_scope.set_reset env false in
                 let env = translate_named_predicate kf (Env.rte env false) p in
@@ -958,10 +959,11 @@ let term_to_exp typ t =
 let assumes_predicate bhv =
   List.fold_left
     (fun acc p ->
-       let loc = p.ip_content.pred_loc in
+       let pred = p.ip_content.tp_statement in
+       let loc = pred.pred_loc in
        Logic_const.pand ~loc
          (acc,
-          Logic_const.unamed ~loc p.ip_content.pred_content))
+          Logic_const.unamed ~loc pred.pred_content))
     Logic_const.ptrue
     bhv.b_assumes
 
@@ -971,14 +973,15 @@ let translate_preconditions kf env behaviors =
     let assumes_pred = assumes_predicate b in
     List.fold_left
       (fun env p ->
+         let pred = p.ip_content.tp_statement in
          let do_it env =
            if Keep_status.must_translate kf Keep_status.K_Requires then
-             let loc = p.ip_content.pred_loc in
+             let loc = pred.pred_loc in
              let p =
                Logic_const.pimplies
                  ~loc
                  (assumes_pred,
-                  Logic_const.unamed ~loc p.ip_content.pred_content)
+                  Logic_const.unamed ~loc pred.pred_content)
              in
              translate_named_predicate kf env p
            else
@@ -1012,8 +1015,8 @@ let translate_postconditions kf env behaviors =
            let do_it env =
              match t with
              | Normal ->
-               let loc = p.ip_content.pred_loc in
-               let p = p.ip_content in
+               let p = p.ip_content.tp_statement in
+               let loc = p.pred_loc in
                let p =
                  Logic_const.pimplies
                    ~loc
@@ -1083,12 +1086,12 @@ let translate_post_spec kf env spec =
 
 let translate_pre_code_annotation kf env annot =
   let convert env = match annot.annot_content with
-    | AAssert(l, _, p) ->
+    | AAssert(l, p) ->
       if Keep_status.must_translate kf Keep_status.K_Assert then
         let env = Env.set_annotation_kind env Constructor.Assertion in
         if l <> [] then
           not_yet env "@[assertion applied only on some behaviors@]";
-        translate_named_predicate kf env p
+        translate_named_predicate kf env p.tp_statement
       else
         env
     | AStmtSpec(l, spec) ->
@@ -1100,8 +1103,10 @@ let translate_pre_code_annotation kf env annot =
         let env = Env.set_annotation_kind env Constructor.Invariant in
         if l <> [] then
           not_yet env "@[invariant applied only on some behaviors@]";
-        let env = translate_named_predicate kf env p in
-        if loop_invariant then Env.add_loop_invariant env p else env
+        let env = translate_named_predicate kf env p.tp_statement in
+        if loop_invariant then
+          Env.add_loop_invariant env p.tp_statement
+        else env
       else
         env
     | AVariant _ ->
diff --git a/src/plugins/gui/property_navigator.ml b/src/plugins/gui/property_navigator.ml
index cc6b91fad051562f7170a891918d900a29429f23..e2f62844d00d39aac3e2c09cc96e44f7b8138d3e 100644
--- a/src/plugins/gui/property_navigator.ml
+++ b/src/plugins/gui/property_navigator.ml
@@ -636,14 +636,12 @@ let make_panel (main_ui:main_window_extension_points) =
     | IPLemma _ -> lemmas.get ()
     | IPComplete _ -> complete_disjoint.get ()
     | IPDisjoint _ -> complete_disjoint.get ()
-    | IPCodeAnnot {ica_ca={annot_content = AAssert (_, kind, _)} as ca} ->
+    | IPCodeAnnot {ica_ca={annot_content=AAssert(_, {tp_only_check})} as ca} ->
       begin
         match Alarms.find ca with
         | Some a -> rte.get () && active_alarm a
         | None ->
-          match kind with
-          | Assert -> user_assertions.get ()
-          | Check -> user_checks.get ()
+          if tp_only_check then user_checks.get() else  user_assertions.get ()
       end
     | IPCodeAnnot {ica_ca={annot_content = AInvariant _}} ->
       invariant.get ()
diff --git a/src/plugins/inout/operational_inputs.ml b/src/plugins/inout/operational_inputs.ml
index 777c7ce0892b7a680201d7920f83d8fca3b58014..0215a63e3161bf2e3b3c60fc6ed78d6d9b9a9706 100644
--- a/src/plugins/inout/operational_inputs.ml
+++ b/src/plugins/inout/operational_inputs.ml
@@ -373,7 +373,7 @@ end) = struct
     Annotations.iter_code_annot
       (fun _ ca ->
          match ca.annot_content with
-         | AAssert (_, _, p)
+         | AAssert (_, p)
          | AInvariant (_, true, p) ->
            begin
              let env =
@@ -382,7 +382,7 @@ end) = struct
                  ~here:(X.stmt_state stmt)
                  ()
              in
-             match Eva.Eval_terms.predicate_deps env p with
+             match Eva.Eval_terms.predicate_deps env p.tp_statement with
              | None ->
                (* To be sound, we should perform a join with the top zone here.
                   We do nothing instead because the latter behavior would
diff --git a/src/plugins/instantiate/stdlib/basic_alloc.ml b/src/plugins/instantiate/stdlib/basic_alloc.ml
index a35a97b53e37d96e97149e0bb851c4db758cac6c..42142cc28c44a5064df718b6d0499850aff7bca7 100644
--- a/src/plugins/instantiate/stdlib/basic_alloc.ml
+++ b/src/plugins/instantiate/stdlib/basic_alloc.ml
@@ -82,6 +82,7 @@ let make_axiomatic_is_allocable loc () =
   let cond = pand (prel (Rlt, t_i, zero), prel (Rgt, t_i, max)) in
   let app = pnot (papp (is_allocable,[label],[t_i])) in
   let prop = pforall ([lv_i], pimplies (cond, app)) in
+  let prop = Logic_const.toplevel_predicate prop in
   let gfun = Dfun_or_pred(is_allocable, loc) in
   let axiom = Dlemma("never_allocable", true, [label],[],prop,[], loc) in
   ("dynamic_allocation", [gfun ; axiom]), [is_allocable]
diff --git a/src/plugins/obfuscator/obfuscate.ml b/src/plugins/obfuscator/obfuscate.ml
index 5cf8be87e632f5db30d2b4cce7477fb4e65dfde6..adbe1215a838a78ebd76bbfc1f087e3aa716e9be 100644
--- a/src/plugins/obfuscator/obfuscate.ml
+++ b/src/plugins/obfuscator/obfuscate.ml
@@ -150,11 +150,14 @@ class visitor = object
       Cil.SkipChildren
     else begin
       Identified_predicate.Hashtbl.add id_pred_visited p ();
-      let names = p.ip_content.pred_name in
+      let { tp_only_check = only_check; tp_statement = pred } = p.ip_content in
+      let names = pred.pred_name in
       let names' =
         List.map (Dictionary.fresh Obfuscator_kind.Predicate) names
       in
-      let p' = { p with ip_content = { p.ip_content with pred_name = names'}} in
+      let pred' = { pred with pred_name = names' } in
+      let ip_content = Logic_const.toplevel_predicate ~only_check pred' in
+      let p' = { p with ip_content } in
       Cil.ChangeDoChildrenPost (p', Extlib.id)
     end
 
diff --git a/src/plugins/scope/datascope.ml b/src/plugins/scope/datascope.ml
index 6c190670c612e36b26f3bf757832171056c6de0d..1fb31afa260c5dd460f811a9024fede3e1ee27cb 100644
--- a/src/plugins/scope/datascope.ml
+++ b/src/plugins/scope/datascope.ml
@@ -488,15 +488,17 @@ let add_proven_annot (ca, stmt_ca) (ca_because, stmt_because) acc =
 let check_stmt_annots (ca, stmt_ca) stmt acc =
   let check _ annot acc =
     match ca.annot_content, annot.annot_content with
-    | AAssert (_, Assert, p'), AAssert (_, _, p) ->
-        if Logic_utils.is_same_predicate_node p.pred_content p'.pred_content then
-          let acc, added = add_proven_annot (annot, stmt) (ca, stmt_ca) acc in
-          if added then
-            R.debug "annot at stmt %d could be removed: %a"
-              stmt.sid Printer.pp_code_annotation annot;
-          acc
-        else
-          acc
+    | AAssert (_, p'), AAssert (_, p) when not p'.tp_only_check ->
+      let p = p.tp_statement.pred_content in
+      let p' = p'.tp_statement.pred_content in
+      if Logic_utils.is_same_predicate_node p p' then
+        let acc, added = add_proven_annot (annot, stmt) (ca, stmt_ca) acc in
+        if added then
+          R.debug "annot at stmt %d could be removed: %a"
+            stmt.sid Printer.pp_code_annotation annot;
+        acc
+      else
+        acc
     | _ -> acc
   in
   Annotations.fold_code_annot check stmt acc
diff --git a/src/plugins/value/alarmset.ml b/src/plugins/value/alarmset.ml
index 21475b79a7a7d523304ec22c16b5d8ed8b76e2d5..c0577e7c88ff21791d2b2be88d0f40430129ee30 100644
--- a/src/plugins/value/alarmset.ml
+++ b/src/plugins/value/alarmset.ml
@@ -216,9 +216,10 @@ let local_printer: Printer.extensible_printer =
     method! code_annotation fmt ca =
       temporaries <- Cil_datatype.Varinfo.Set.empty;
       match ca.annot_content with
-      | AAssert (_, _, p) ->
+      | AAssert (_, p) ->
         (* ignore the ACSL name *)
-        Format.fprintf fmt "@[<v>@[assert@ %a;@]" self#predicate_node p.pred_content;
+        let p = p.tp_statement.pred_content in
+        Format.fprintf fmt "@[<v>@[assert@ %a;@]" self#predicate_node p;
         (* print temporary variables information *)
         if not (Cil_datatype.Varinfo.Set.is_empty temporaries) then begin
           Format.fprintf fmt "@ @[(%t)@]" self#pp_temporaries
diff --git a/src/plugins/value/domains/traces_domain.ml b/src/plugins/value/domains/traces_domain.ml
index c7cb5f5219d7ce702517e27cfac0d85b2b665b05..f10b631cfe65a596c50cbf3f6706cae73b02709e 100644
--- a/src/plugins/value/domains/traces_domain.ml
+++ b/src/plugins/value/domains/traces_domain.ml
@@ -1082,7 +1082,8 @@ let rec stmts_of_cfg cfg current var_map locals return_exp acc =
         let exp = subst_in_exp var_map exp in
         let predicate = Logic_utils.expr_to_predicate exp in
         let predicate = if b then predicate else Logic_const.pnot predicate in
-        let code_node = Cil_types.AAssert([],Assert,predicate) in
+        let predicate = Logic_const.toplevel_predicate predicate in
+        let code_node = Cil_types.AAssert([],predicate) in
         let code_annot = Logic_const.new_code_annotation code_node in
         let stmt_kind = Cil_types.Code_annot(code_annot,exp.eloc) in
         let stmt = Cil.mkStmtOneInstr ~valid_sid stmt_kind in
diff --git a/src/plugins/value/engine/transfer_logic.ml b/src/plugins/value/engine/transfer_logic.ml
index 294b81b7245753a7e05e23047eb3aa8c25ecbd54..a6efdf17d21b8abfa3ff22fabffb1155fd11ecfe 100644
--- a/src/plugins/value/engine/transfer_logic.ml
+++ b/src/plugins/value/engine/transfer_logic.ml
@@ -137,7 +137,7 @@ let emit_message_and_status kind kf behavior ~active ~empty property named_pred
 let create_conjunction l=
   let loc = match l with
     | [] -> None
-    | p :: _ -> Some p.ip_content.pred_loc
+    | p :: _ -> Some (Logic_const.pred_of_id_pred p).pred_loc
   in
   Logic_const.(List.fold_right (fun p1 p2 -> pand ?loc (p1, p2)) (List.map pred_of_id_pred l) ptrue)
 
@@ -384,11 +384,11 @@ module Make
     else (* Not enough slevel to split, and reduction not required *)
       States.singleton state
 
-  let eval_split_and_reduce limit active pred build_env state =
+  let eval_split_and_reduce limit ~reduce pred build_env state =
     let env = build_env state in
     let status = Domain.evaluate_predicate env state pred in
     let  reduced_states =
-      if active then
+      if reduce then
         match status with
         | Alarmset.False   -> States.empty
         | Alarmset.True    ->
@@ -453,6 +453,7 @@ module Make
     let emit = emit_message_and_status kind kf behavior ~active in
     let aux_pred states pred =
       let pr = Logic_const.pred_of_id_pred pred in
+      let reduce = active && not pred.ip_content.tp_only_check in
       let ip = build_prop pred in
       if ignore_predicate pr then
         states
@@ -465,7 +466,7 @@ module Make
           States.fold
             (fun state (acc_status, acc_states) ->
                let status, reduced_states =
-                 eval_split_and_reduce limit active pr build_env state
+                 eval_split_and_reduce limit ~reduce pr build_env state
                in
                (status :: acc_status,
                 fst (States.merge ~into:acc_states reduced_states)))
@@ -580,8 +581,8 @@ module Make
 
   let code_annotation_text ca =
     match ca.annot_content with
-    | AAssert (_, Assert, _) ->  "assertion"
-    | AAssert (_, Check, _) -> "check"
+    | AAssert (_,{tp_only_check = false}) ->  "assertion"
+    | AAssert (_,{tp_only_check = true}) -> "check"
     | AInvariant _ ->  "loop invariant"
     | APragma _  | AVariant _ | AAssigns _ | AAllocation _ | AStmtSpec _
     | AExtended _ ->
@@ -687,9 +688,9 @@ module Make
         aux_interp ~reduce code_annot behav p
     in
     match code_annot.annot_content with
-    | AAssert (behav, Check, p) -> aux ~reduce:false code_annot behav p
-    | AAssert (behav, Assert, p)
-    | AInvariant (behav, true, p) -> aux ~reduce:true code_annot behav p
+    | AAssert (behav, p)
+    | AInvariant (behav, true, p) ->
+      aux ~reduce:(not p.tp_only_check) code_annot behav p.tp_statement
     | APragma _
     | AInvariant (_, false, _)
     | AVariant _ | AAssigns _ | AAllocation _ | AExtended _
diff --git a/src/plugins/value/gui_files/gui_red.ml b/src/plugins/value/gui_files/gui_red.ml
index 8671ed982494460661e53c88939c4ae85d6b9e5e..fdd4ce7ec5dfe2549bdd6f4ec86c5133e4ea584b 100644
--- a/src/plugins/value/gui_files/gui_red.ml
+++ b/src/plugins/value/gui_files/gui_red.ml
@@ -69,7 +69,8 @@ type red_alarm = {
 
 let get_predicate ca =
   match ca.annot_content with
-  | AAssert (_, _, p) -> { p with pred_name = [] }
+  | AAssert (_, p) ->
+    { p with tp_statement = { p.tp_statement with pred_name = [] }}
   | _ -> assert false
 
 let make_red_alarm function_name ki alarm callstacks =
@@ -84,7 +85,9 @@ let make_red_alarm function_name ki alarm callstacks =
   let ip = Property.ip_of_code_annot_single kf stmt ca in
   let kind = String.capitalize_ascii (Alarms.get_name alarm) in
   let p = get_predicate ca in
-  let acsl = Format.asprintf "@[<hov>%a@]" Cil_datatype.Predicate.pretty p in
+  let acsl =
+    Format.asprintf "@[<hov>%a@]" Cil_datatype.Toplevel_predicate.pretty p
+  in
   let alarm_or_prop = Red_statuses.Alarm alarm in
   { function_name; ip; kind; alarm_or_prop; acsl; callstacks }
 
diff --git a/src/plugins/value/gui_files/register_gui.ml b/src/plugins/value/gui_files/register_gui.ml
index dc46ee11e7e5528f14f49c0d9ca4d2cc4861ff30..19d46c75109c13781b61f0069a2258aa9b916ec6 100644
--- a/src/plugins/value/gui_files/register_gui.ml
+++ b/src/plugins/value/gui_files/register_gui.ml
@@ -461,13 +461,17 @@ module Select (Eval: Eval) = struct
       | PVDecl (Some kf, Kstmt stmt, vi) ->
         let lv = (Var vi, NoOffset) in
         select_lv main_ui (GL_Stmt (kf, stmt)) lv
-      | PIP (IPCodeAnnot {ica_kf = kf; ica_stmt = stmt;
-                          ica_ca = {annot_content =
-                                      AAssert (_, _, p)
-                                    | AInvariant (_, true, p)} as ca
-                         } as ip) ->
+      | PIP (
+          IPCodeAnnot {
+            ica_kf = kf; ica_stmt = stmt;
+            ica_ca = {
+              annot_content =
+                AAssert (_, p) | AInvariant (_, true, p)
+            } as ca
+          } as ip) ->
         begin
           let loc = GL_Stmt (kf, stmt) in
+          let p = p.tp_statement in
           let alarm_or_property =
             match Alarms.find ca with
             | None -> Red_statuses.Prop ip
diff --git a/src/plugins/value/legacy/eval_annots.ml b/src/plugins/value/legacy/eval_annots.ml
index e043c43a0b809b5727ee35e0d7868ac84dc8a94d..978309b89bba0f5296392d41e793d4783e1be46f 100644
--- a/src/plugins/value/legacy/eval_annots.ml
+++ b/src/plugins/value/legacy/eval_annots.ml
@@ -29,8 +29,8 @@ let has_requires spec =
 
 let code_annotation_text ca =
   match ca.annot_content with
-  | AAssert (_, Assert, _) ->  "assertion"
-  | AAssert (_, Check, _) -> "check"
+  | AAssert (_, {tp_only_check=false}) ->  "assertion"
+  | AAssert (_, {tp_only_check=true}) -> "check"
   | AInvariant _ ->  "loop invariant"
   | APragma _  | AVariant _ | AAssigns _ | AAllocation _ | AStmtSpec _
   | AExtended _  ->
@@ -203,7 +203,8 @@ let mark_green_and_red () =
        currently skipped during evaluation. *)
     if contains_c_at ca || (Alarms.find ca <> None) then
       match ca.annot_content with
-      | AAssert (_, _, p) | AInvariant (_, true, p) ->
+      | AAssert (_, p) | AInvariant (_, true, p) ->
+        let p = p.tp_statement in
         let loc = code_annotation_loc ca stmt in
         Cil.CurrentLoc.set loc;
         let kf = Kernel_function.find_englobing_kf stmt in
@@ -246,7 +247,8 @@ let mark_invalid_initializers () =
     | None -> ()
     | Some _ ->
       match ca.annot_content with
-      | AAssert (_, _, p) ->
+      | AAssert (_, p) ->
+        let p = p.tp_statement in
         let ip = Property.ip_of_code_annot_single kf first_stmt ca in
         (* Evaluate in a fully empty state. Only predicates that do not
            depend on the memory will result in 'False' *)
diff --git a/src/plugins/wp/Changelog b/src/plugins/wp/Changelog
index bdfeb67ae5865b23b198d32b88d71b4a01a126df..5d908195357178785cda176070da7a0a96635a29 100644
--- a/src/plugins/wp/Changelog
+++ b/src/plugins/wp/Changelog
@@ -20,6 +20,8 @@
 #   <Prover>: prover
 ###############################################################################
 
+- Wp          [2020-09-09] Support for generalized @check ACSL annotations
+
 #########################
 Plugin WP 21.1 (Scandium)
 #########################
diff --git a/src/plugins/wp/Cstring.ml b/src/plugins/wp/Cstring.ml
index 7705498957b67213b63c2dc7142c5bd396f6b3f7..826350e8a6739e7b6e3de05a70bf97dded252a81 100644
--- a/src/plugins/wp/Cstring.ml
+++ b/src/plugins/wp/Cstring.ml
@@ -76,7 +76,7 @@ module LIT = WpContext.Generator(STR)
         define_lemma {
           l_name = prefix ^ "_literal" ;
           l_cluster = cluster () ;
-          l_assumed = true ;
+          l_kind = `Axiom ;
           l_types = 0 ;
           l_forall = [] ;
           l_triggers = [] ;
diff --git a/src/plugins/wp/Definitions.ml b/src/plugins/wp/Definitions.ml
index 6a55329e78dc75a7ab03e577f4e79e17529a68b3..7fa51bc9552b65ef190faf123100abd1970c0519 100644
--- a/src/plugins/wp/Definitions.ml
+++ b/src/plugins/wp/Definitions.ml
@@ -53,7 +53,7 @@ type cluster = {
 and dlemma = {
   l_name  : string ;
   l_cluster : cluster ;
-  l_assumed : bool ;
+  l_kind : lkind ;
   l_types : int ;
   l_forall : var list ;
   l_triggers : trigger list list (* OR of AND triggers *) ;
diff --git a/src/plugins/wp/Definitions.mli b/src/plugins/wp/Definitions.mli
index 7bc141a15b431d8af5c1f741c15317cbe8241486..8adf448cde8cdbf8bc28b94d564081dc68c3017b 100644
--- a/src/plugins/wp/Definitions.mli
+++ b/src/plugins/wp/Definitions.mli
@@ -49,7 +49,7 @@ type typedef = (tau,field,lfun) Qed.Engine.ftypedef
 type dlemma = {
   l_name  : string ;
   l_cluster : cluster ;
-  l_assumed : bool ;
+  l_kind : lkind ;
   l_types : int ;
   l_forall : var list ;
   l_triggers : trigger list list ; (** OR of AND-triggers *)
diff --git a/src/plugins/wp/LogicCompiler.ml b/src/plugins/wp/LogicCompiler.ml
index 8c88a3af10b1598c786be81e67386363fd551c2a..69019743d70d1b3ae649826081996e4f618fa102 100644
--- a/src/plugins/wp/LogicCompiler.ml
+++ b/src/plugins/wp/LogicCompiler.ml
@@ -498,7 +498,7 @@ struct
     | Pforall(qs,q) -> strip_forall (xs @ qs) q
     | _ -> xs , p
 
-  let compile_lemma cluster name ~assumed types labels lemma =
+  let compile_lemma cluster name ~kind types labels lemma =
     let qs,prop = strip_forall [] lemma in
     let xs,tgs,domain,prop,_ =
       let cc_pred = pred `Positive in
@@ -508,7 +508,7 @@ struct
     {
       l_name = name ;
       l_types = List.length types ;
-      l_assumed = assumed ;
+      l_kind = kind ;
       l_triggers = [tgs] ;
       l_forall = xs ;
       l_cluster = cluster ;
@@ -539,7 +539,7 @@ struct
             let trigger = Trigger.of_term result in
             Definitions.define_lemma {
               l_name = name ;
-              l_assumed = true ;
+              l_kind = `Axiom ;
               l_types = ldef.d_types ;
               l_forall = ldef.d_params ;
               l_triggers = [[trigger]] ;
@@ -721,7 +721,7 @@ struct
     (* Re-compile final cases *)
     let cases = List.map
         (fun (case,labels,types,lemma) ->
-           compile_lemma cluster ~assumed:true case types labels lemma)
+           compile_lemma cluster ~kind:`Axiom case types labels lemma)
         cases in
     Definitions.update_symbol { ldef with d_definition = Inductive cases } ;
     type_for_signature l ldef sigp (* sufficient *) ; SIG sigm
@@ -770,7 +770,7 @@ struct
                     {
                       l_name ;
                       l_types = 0 ;
-                      l_assumed = true ;
+                      l_kind = `Axiom ;
                       l_triggers = [frame.triggers] ;
                       l_forall = vs ;
                       l_cluster = cluster ;
@@ -802,7 +802,7 @@ struct
         "Lemma '%s' has labels, consider using global invariant instead."
         l.lem_name ;
     Definitions.define_lemma
-      (compile_lemma c ~assumed:l.lem_axiom
+      (compile_lemma c ~kind:l.lem_kind
          l.lem_name l.lem_types l.lem_labels l.lem_property)
 
   let define_axiomatic cluster ax =
diff --git a/src/plugins/wp/LogicUsage.ml b/src/plugins/wp/LogicUsage.ml
index 953d1c9b92b14b94f18577e6653c22df5c06e345..1058d7ffa962fa3063fd853fc8039e5a8aa9450c 100644
--- a/src/plugins/wp/LogicUsage.ml
+++ b/src/plugins/wp/LogicUsage.ml
@@ -57,10 +57,12 @@ let trim name =
 (* --- Definition Blocks                                                  --- *)
 (* -------------------------------------------------------------------------- *)
 
+type lkind = [ `Axiom | `Check | `Lemma ]
+
 type logic_lemma = {
   lem_name : string ;
+  lem_kind : lkind ;
   lem_position : Filepath.position ;
-  lem_axiom : bool ;
   lem_types : string list ;
   lem_labels : logic_label list ;
   lem_property : predicate ;
@@ -192,27 +194,36 @@ let pp_profile fmt l =
 
 let ip_lemma l =
   let open Property in
-  (if l.lem_axiom then Property.ip_axiom else Property.ip_lemma)
+  let mk_prop, only_check =
+    match l.lem_kind with
+    | `Axiom -> Property.ip_axiom, false
+    | `Lemma -> Property.ip_lemma, false
+    | `Check -> Property.ip_lemma, true
+  in
+  mk_prop
     {il_name = l.lem_name; il_labels = l.lem_labels;
      il_args = l.lem_types; il_loc = (l.lem_position, l.lem_position);
-     il_pred = l.lem_property}
-
-let lemma_of_global proof = function
-  | Dlemma(name,axiom,labels,types,pred,_,loc) -> {
-      lem_name = name ;
-      lem_position = fst loc ;
-      lem_types = types ;
-      lem_labels = labels ;
-      lem_axiom = axiom ;
-      lem_property = pred ;
-      lem_depends = proof ;
-    }
+     il_pred = Logic_const.toplevel_predicate ~only_check l.lem_property}
+
+let lemma_of_global ~context = function
+  | Dlemma(name,axiom,labels,types,pred,_,loc) ->
+      let kind = if axiom then `Axiom else
+        if pred.tp_only_check then `Check else `Lemma in
+      {
+        lem_name = name ;
+        lem_position = fst loc ;
+        lem_types = types ;
+        lem_labels = labels ;
+        lem_kind = kind ;
+        lem_property = pred.tp_statement ;
+        lem_depends = context ;
+      }
   | _ -> assert false
 
-let populate a proof = function
+let populate a ~context = function
   | Dfun_or_pred(l,_) -> a.ax_logics <- l :: a.ax_logics
   | Dtype(t,_) -> a.ax_types <- t :: a.ax_types
-  | Dlemma _ as g -> a.ax_lemmas <- lemma_of_global proof g :: a.ax_lemmas
+  | Dlemma _ as g -> a.ax_lemmas <- lemma_of_global ~context g :: a.ax_lemmas
   | _ -> ()
 
 let ip_of_axiomatic g =
@@ -220,7 +231,7 @@ let ip_of_axiomatic g =
   | None -> assert false
   | Some ip -> ip
 
-let axiomatic_of_global proof = function
+let axiomatic_of_global ~context = function
   | Daxiomatic(name,globals,_,loc) as g ->
       let a = {
         ax_name = name ;
@@ -229,7 +240,7 @@ let axiomatic_of_global proof = function
         ax_reads = Varinfo.Set.empty ;
         ax_types = [] ; ax_lemmas = [] ; ax_logics = [] ;
       } in
-      List.iter (populate a proof) globals ;
+      List.iter (populate a ~context) globals ;
       a.ax_types <- List.rev a.ax_types ;
       a.ax_logics <- List.rev a.ax_logics ;
       a.ax_lemmas <- List.rev a.ax_lemmas ;
@@ -402,7 +413,8 @@ class visitor =
       | Dlemma _ ->
           let lem = lemma_of_global database.proofcontext global in
           register_lemma database self#section lem ;
-          database.proofcontext <- lem :: database.proofcontext ;
+          if lem.lem_kind <> `Check then
+            database.proofcontext <- lem :: database.proofcontext ;
           SkipChildren
 
       | Dtype(t,_) ->
@@ -502,9 +514,9 @@ let proof_context () =
 (* --- Dump API                                                           --- *)
 (* -------------------------------------------------------------------------- *)
 
-let dump_type fmt t = Format.fprintf fmt " * type '%s'@\n" t.lt_name
+let pp_type fmt t = Format.fprintf fmt " * type '%s'@\n" t.lt_name
 
-let dump_profile fmt kind l =
+let pp_sig fmt kind l =
   begin
     Format.fprintf fmt " * %s '%s'@\n" kind (compute_logicname l) ;
     if is_overloaded l then
@@ -513,11 +525,11 @@ let dump_profile fmt kind l =
       Format.fprintf fmt "   recursive@\n" ;
   end
 
-let dump_logic fmt d l =
+let pp_decl fmt d l =
   begin
     try
       let cases = LMap.find l d.cases in
-      dump_profile fmt "inductive" l ;
+      pp_sig fmt "inductive" l ;
       List.iter
         (fun ind ->
            Format.fprintf fmt "   @[case %s:" ind.ind_case ;
@@ -532,14 +544,16 @@ let dump_logic fmt d l =
         ) cases ;
     with Not_found ->
       let kind = if l.l_type = None then "predicate" else "function" in
-      dump_profile fmt kind l ;
+      pp_sig fmt kind l ;
   end
 
-let dump_lemma fmt l =
-  if l.lem_axiom then
-    Format.fprintf fmt " * axiom '%s'@\n" l.lem_name
-  else
-    Format.fprintf fmt " * lemma '%s'@\n" l.lem_name
+let pp_kind fmt = function
+  | `Axiom -> Format.pp_print_string fmt "axiom"
+  | `Lemma -> Format.pp_print_string fmt "lemma"
+  | `Check -> Format.pp_print_string fmt "check lemma"
+
+let pp_lemma fmt l =
+  Format.fprintf fmt " * %a '%s'@\n" pp_kind l.lem_kind l.lem_name
 
 let get_name l = compute () ; compute_logicname l
 
@@ -556,9 +570,9 @@ let dump () =
       SMap.iter
         (fun _ a ->
            Format.fprintf fmt "Axiomatic %s {@\n" a.ax_name ;
-           List.iter (dump_type fmt) a.ax_types ;
-           List.iter (dump_logic fmt d) a.ax_logics ;
-           List.iter (dump_lemma fmt) a.ax_lemmas ;
+           List.iter (pp_type fmt) a.ax_types ;
+           List.iter (pp_decl fmt d) a.ax_logics ;
+           List.iter (pp_lemma fmt) a.ax_lemmas ;
            Format.fprintf fmt "}@\n"
         ) d.axiomatics ;
       TMap.iter
@@ -573,8 +587,8 @@ let dump () =
         d.logics ;
       SMap.iter
         (fun l (lem,s) ->
-           Format.fprintf fmt " * %s '%s' in %a@\n"
-             (if lem.lem_axiom then "axiom" else "lemma")
+           Format.fprintf fmt " * %a '%s' in %a@\n"
+             pp_kind lem.lem_kind
              l pp_section s)
         d.lemmas ;
       Format.fprintf fmt "-------------------------------------------------@." ;
diff --git a/src/plugins/wp/LogicUsage.mli b/src/plugins/wp/LogicUsage.mli
index 4ae195a680c70fe9ffa329b0c725dd105417f90d..b36713d5209e66a077ef0a5beb8e8778c7150bf3 100644
--- a/src/plugins/wp/LogicUsage.mli
+++ b/src/plugins/wp/LogicUsage.mli
@@ -30,10 +30,12 @@ open Clabels
 
 val basename : varinfo -> string (** Trims the original name *)
 
+type lkind = [ `Axiom | `Check | `Lemma ]
+
 type logic_lemma = {
   lem_name : string ;
+  lem_kind : lkind ;
   lem_position : Filepath.position ;
-  lem_axiom : bool ;
   lem_types : string list ;
   lem_labels : logic_label list ;
   lem_property : predicate ;
diff --git a/src/plugins/wp/MemLoader.ml b/src/plugins/wp/MemLoader.ml
index 5d940330603ac683267919647abc0ceb32f3e4dc..8edca8a418d8b027ccddc13a879c864b6301d6d5 100644
--- a/src/plugins/wp/MemLoader.ml
+++ b/src/plugins/wp/MemLoader.ml
@@ -141,7 +141,7 @@ struct
                     prefix name Chunk.pretty chunk i in
                 let l_lemma = F.p_hyps conditions (p_equal value1 value2) in
                 Definitions.define_lemma {
-                  l_assumed = true ;
+                  l_kind = `Axiom ;
                   l_name ; l_types = 0 ;
                   l_triggers ;
                   l_forall = F.p_vars l_lemma ;
@@ -226,7 +226,7 @@ struct
           let lfun = Lang.generated_f ~result "Array%a%s_%s" pp_rid r
               (Matrix.id ds) (Matrix.natural_id obj_e) in
           let prefix = Lang.Fun.debug lfun in
-          let axiom = prefix ^ "_access" in
+          let name = prefix ^ "_access" in
           let xmem,chunks,sigma = signature domain in
           let denv = Matrix.denv ds in
           let phi = e_fun lfun (v :: denv.size_val @ List.map e_var xmem) in
@@ -242,8 +242,8 @@ struct
             d_cluster = cluster ;
           } ;
           Definitions.define_lemma {
-            l_assumed = true ;
-            l_name = axiom ; l_types = 0 ;
+            l_kind = `Axiom ;
+            l_name = name ; l_types = 0 ;
             l_forall = F.p_vars lemma ;
             l_triggers = [[Trigger.of_term va]] ;
             l_lemma = lemma ;
diff --git a/src/plugins/wp/MemRegion.ml b/src/plugins/wp/MemRegion.ml
index b717626bea998d91c4a13bdde52727de723ff4f2..4c308904f053b65ad0068ca6316849e9108f53b0 100644
--- a/src/plugins/wp/MemRegion.ml
+++ b/src/plugins/wp/MemRegion.ml
@@ -193,14 +193,14 @@ let constructor ~basename ~params ~index ~addrof ~consistent =
       } ;
       Definitions.define_lemma {
         l_cluster = cluster ;
-        l_assumed = true ;
+        l_kind = `Axiom ;
         l_name = Printf.sprintf "addrof_%s_%d" basename id ;
         l_forall = params ; l_types = 0 ; l_triggers = [] ;
         l_lemma = p_addrof ;
       } ;
       Definitions.define_lemma {
         l_cluster = cluster ;
-        l_assumed = true ;
+        l_kind = `Axiom ;
         l_name = Printf.sprintf "consistent_%s_%d" basename id ;
         l_forall = params ; l_types = 0 ; l_triggers = [] ;
         l_lemma = p_consistent ;
@@ -208,7 +208,7 @@ let constructor ~basename ~params ~index ~addrof ~consistent =
       if p_index != F.p_true then
         Definitions.define_lemma {
           l_cluster = cluster ;
-          l_assumed = true ;
+          l_kind = `Axiom ;
           l_name = Printf.sprintf "index_%s_%d" basename id ;
           l_forall = params @ [k] ; l_types = 0 ; l_triggers = [] ;
           l_lemma = p_index ;
diff --git a/src/plugins/wp/MemTyped.ml b/src/plugins/wp/MemTyped.ml
index 12f4230be78dc3c929fc275951e98918d101e0ab..fd2770c3c3eafe10a024308fcac514e4d4d1ce04 100644
--- a/src/plugins/wp/MemTyped.ml
+++ b/src/plugins/wp/MemTyped.ml
@@ -409,7 +409,7 @@ module STRING = WpContext.Generator(LITERAL)
         let alloc = F.e_get m base in (* The size is alloc-1 *)
         let sized = Cstring.str_len cst (F.e_add alloc F.e_minus_one) in
         Definitions.define_lemma {
-          l_assumed = true ;
+          l_kind = `Axiom ;
           l_name = name ; l_types = 0 ;
           l_triggers = [] ; l_forall = [] ;
           l_lemma = p_forall [a] (p_imply m_linked sized) ;
@@ -420,7 +420,7 @@ module STRING = WpContext.Generator(LITERAL)
         let name = prefix ^ "_region" in
         let re = - Cstring.str_id cst in
         Definitions.define_lemma {
-          l_assumed = true ;
+          l_kind = `Axiom ;
           l_name = name ; l_types = 0 ; l_triggers = [] ; l_forall = [] ;
           l_lemma = p_equal (e_fun f_region [base]) (e_int re) ;
           l_cluster = Cstring.cluster () ;
@@ -437,7 +437,7 @@ module STRING = WpContext.Generator(LITERAL)
         let v = F.e_get (e_var m) addr in
         let read = F.p_equal c v in
         Definitions.define_lemma {
-          l_assumed = true ;
+          l_kind = `Axiom ;
           l_name = name ; l_types = 0 ; l_triggers = [] ;
           l_forall = [m;i] ;
           l_cluster = Cstring.cluster () ;
@@ -461,7 +461,7 @@ module STRING = WpContext.Generator(LITERAL)
         } ;
         Definitions.define_lemma {
           l_name = prefix ^ "_base" ;
-          l_assumed = true ;
+          l_kind = `Axiom ;
           l_types = 0 ; l_triggers = [] ; l_forall = [] ;
           l_lemma = F.p_lt base F.e_zero ;
           l_cluster = Cstring.cluster () ;
@@ -495,7 +495,7 @@ module BASE = WpContext.Generator(Varinfo)
         let name = prefix ^ "_region" in
         let re = if x.vglob then 0 else if x.vformal then 1 else 2 in
         Definitions.define_lemma {
-          l_assumed = true ;
+          l_kind = `Axiom ;
           l_name = name ; l_types = 0 ; l_triggers = [] ; l_forall = [] ;
           l_lemma = p_equal (e_fun f_region [base]) (e_int re) ;
           l_cluster = cluster_globals () ;
@@ -519,7 +519,7 @@ module BASE = WpContext.Generator(Varinfo)
             let m_linked = p_call p_linked [m] in
             let base_size = p_equal (F.e_get m base) (e_int size) in
             Definitions.define_lemma {
-              l_assumed = true ;
+              l_kind = `Axiom ;
               l_name = name ; l_types = 0 ;
               l_triggers = [] ; l_forall = [] ;
               l_lemma = p_forall [a] (p_imply m_linked base_size) ;
diff --git a/src/plugins/wp/ProverWhy3.ml b/src/plugins/wp/ProverWhy3.ml
index 343f4a4affd0f6039e445ee74960ec5c7f284c78..813eda4cf32ee1350d7b6a68c1dd47fb70f1069e 100644
--- a/src/plugins/wp/ProverWhy3.ml
+++ b/src/plugins/wp/ProverWhy3.ml
@@ -911,7 +911,7 @@ class visitor (ctx:context) c =
       id, t
 
     method on_dlemma l =
-      let kind = Why3.Decl.(if l.l_assumed then Paxiom else Plemma) in
+      let kind = Why3.Decl.(if l.l_kind = `Axiom then Paxiom else Plemma) in
       let cnv = empty_cnv ctx in
       let id, t = self#make_lemma cnv l in
       let decl = Why3.Decl.create_prop_decl kind id t in
diff --git a/src/plugins/wp/Splitter.ml b/src/plugins/wp/Splitter.ml
index b5930b40748cf9752bc470ee58ebb5c1eb70baf0..a0707f3bd7ee887c775265ec395ecfefdbf9d4e4 100644
--- a/src/plugins/wp/Splitter.ml
+++ b/src/plugins/wp/Splitter.ml
@@ -50,7 +50,7 @@ let pretty fmt = function
 
 let loc = function
   | THEN s | ELSE s | CASE(s,_) | CALL(s,_) | DEFAULT s -> Stmt.loc s
-  | ASSERT(p,_,_) -> p.ip_content.pred_loc
+  | ASSERT(p,_,_) -> p.ip_content.tp_statement.pred_loc
 
 let compare p q =
   if p == q then 0 else
@@ -103,8 +103,7 @@ and unwrap p =
         (unwrap p)
   | _ -> raise Exit
 
-let predicate ip =
-  ip.ip_content
+let predicate ip = ip.ip_content.tp_statement
 
 let rec enumerate ip k n = function
   | [] -> []
diff --git a/src/plugins/wp/StmtSemantics.ml b/src/plugins/wp/StmtSemantics.ml
index 22b7335e91ecd96befa323fb73703dcab40a81ba..6ba37de4959f4d9e35742cd11d71c5073a11f621 100644
--- a/src/plugins/wp/StmtSemantics.ml
+++ b/src/plugins/wp/StmtSemantics.ml
@@ -297,9 +297,9 @@ struct
       with Not_found -> Wp_parameters.fatal "Error during compilation"
 
   let assert_ env p prop_id =
-    let pos = pred env `Positive p.ip_content in
+    let pos = pred env `Positive p.ip_content.tp_statement in
     let env' = env @* [Clabels.here, env @: Clabels.next ] in
-    let neg = pred env' `Negative p.ip_content in
+    let neg = pred env' `Negative p.ip_content.tp_statement in
     let goal = {
       goal_pred = pos;
       goal_prop = prop_id;
@@ -430,7 +430,7 @@ struct
     in
     let post_cond termination_kind env (tk, ip) =
       if tk = termination_kind then
-        assume_ env `Positive ip.ip_content
+        assume_ env `Positive ip.ip_content.tp_statement
       else nop
     in
     let behavior env b =
@@ -540,7 +540,7 @@ struct
                  let node = get_node nodes vertex in
                  bind c_label node acc
               ) a.labels env in
-          assume (pred env `Negative a.predicate.ip_content) @^
+          assume (pred env `Negative a.predicate.ip_content.tp_statement) @^
           goto (env @: Clabels.here) (env @: Clabels.next)
       | Prop _ ->
           not_yet "[StmtSemantics] Annots other than 'assert'"
@@ -717,7 +717,7 @@ struct
       in
       assume,
       List.fold_left
-        (fun acc ip -> acc @^ pre_cond `Negative env ip.ip_content)
+        (fun acc ip -> acc @^ pre_cond `Negative env ip.ip_content.tp_statement)
         nop b.b_requires
       @^ goto (env @: Clabels.here) (env @: Clabels.next)
     in
diff --git a/src/plugins/wp/cfgWP.ml b/src/plugins/wp/cfgWP.ml
index b8389519cc2b552a62d28100f2ae7c1b8b7ecab1..8a35afd310f5d85c5e14bcfc8effb75ece93956b 100644
--- a/src/plugins/wp/cfgWP.ml
+++ b/src/plugins/wp/cfgWP.ml
@@ -1394,7 +1394,7 @@ struct
   let compile_lemma l = ignore (VCG.lemma l)
 
   let prove_lemma collection l =
-    if not l.lem_axiom then
+    if l.lem_kind <> `Axiom then
       begin
         let id = WpPropId.mk_lemma_id l in
         let def = VCG.lemma l in
diff --git a/src/plugins/wp/tests/README.md b/src/plugins/wp/tests/README.md
index c88b74cb66da4ec06b1b519cc8808a595c96eec8..a4ca41d8419b1182981f16b2c79cac381ac594c8 100644
--- a/src/plugins/wp/tests/README.md
+++ b/src/plugins/wp/tests/README.md
@@ -1,3 +1,9 @@
+# Running qualif tests
+
+- Be sure that you have installed the appropriate versions of
+  alt-ergo and coq _before_ having compiled Frama-C.
+- use `make wp-qualif` in the toplevel Frama-C directory
+
 # How to add a new test
 
 ```
diff --git a/src/plugins/wp/tests/wp/stmtcompiler_test_rela.ml b/src/plugins/wp/tests/wp/stmtcompiler_test_rela.ml
index a474167455ddc2e1c51857f25dcc425304d63b93..2603c8fa245d66ce14db353223f0b2bdcff4979c 100644
--- a/src/plugins/wp/tests/wp/stmtcompiler_test_rela.ml
+++ b/src/plugins/wp/tests/wp/stmtcompiler_test_rela.ml
@@ -54,7 +54,8 @@ let run () =
         pred_content = Cil_types.Ptrue;
       }
     in
-    let annot = Logic_const.new_code_annotation (AAssert ([],Assert,pred)) in
+    let pred = Logic_const.toplevel_predicate pred in
+    let annot = Logic_const.new_code_annotation (AAssert ([],pred)) in
     let po = Wpo.{
         po_gid = "";
         po_leg = "";
diff --git a/src/plugins/wp/tests/wp_acsl/checks.i b/src/plugins/wp/tests/wp_acsl/checks.i
index 1a1174504f7e46923c594d5f5d11049ad5fdd1f0..f3fdcbfcab8f623e1c5393ae7e7b4b977300a6c2 100644
--- a/src/plugins/wp/tests/wp_acsl/checks.i
+++ b/src/plugins/wp/tests/wp_acsl/checks.i
@@ -1,7 +1,7 @@
 /* run.config
    OPT: -eva -load-module scope,eva,report -then -report
    OPT: -wp-prop=@check
-   OPT: -wp-prop=@assert
+   OPT: -wp-prop=-@check
 */
 /* run.config_qualif
    OPT: -load-module report -wp-steps 5 -then -report
diff --git a/src/plugins/wp/tests/wp_acsl/generalized_checks.i b/src/plugins/wp/tests/wp_acsl/generalized_checks.i
new file mode 100644
index 0000000000000000000000000000000000000000..3b34ced34e21bad22ab97aaefd60da416ce909d5
--- /dev/null
+++ b/src/plugins/wp/tests/wp_acsl/generalized_checks.i
@@ -0,0 +1,66 @@
+/* run.config_qualif
+   OPT: -wp-timeout 1
+ */
+
+/*@
+  axiomatic Th {
+
+  predicate P(integer p);
+  predicate Q(integer q);
+  predicate R(integer r);
+
+  axiom       A: \forall integer x; P(x) ==> Q(x);
+  check lemma C: ko: \forall integer x; Q(x) ==> R(x);
+  lemma       L: ko: \forall integer x; P(x) ==> R(x); // C is not used
+
+  }
+ */
+
+/*@
+  axiomatic Cfg {
+  logic integer F(integer x);
+  predicate A(integer x);
+  predicate B(integer x);
+  predicate CA1(integer x);
+  predicate CA2(integer x);
+  predicate CB1(integer x);
+  predicate CB2(integer x);
+
+  axiom AFB: \forall integer x; A(x) ==> B(F(x));
+  axiom ACB1: \forall integer x; A(x) ==> CB1(F(x));
+  axiom CA1B2: \forall integer x; CA1(x) ==> CB2(F(x));
+
+  }
+ */
+
+/*@
+  ensures \result == F(x);
+  assigns \nothing;
+ */
+int f(int x);
+
+/*@
+  requires A:               A(x);
+  check requires CA1:     CA1(x);
+  check requires CA2: ko: CA2(x);
+  ensures B:                B(\result);
+  check ensures CB1:      CB1(\result);
+  check ensures CB2: ko:  CB2(\result); // CA1 is not used
+  assigns \nothing;
+*/
+int job(int x) {
+  return f(x);
+}
+
+/*@
+  requires A(x);
+  requires CA1(x);
+  ensures R: B(\result);
+  ensures R1: ko: CB1(\result); // CB1 is not used from job
+  ensures R2: ko: CA2(x);   // CA2 is not used from job
+  assigns \nothing;
+*/
+int caller(int x)
+{
+  return job(x); // CA2 is not proved
+}
diff --git a/src/plugins/wp/tests/wp_acsl/oracle/generalized_checks.res.oracle b/src/plugins/wp/tests/wp_acsl/oracle/generalized_checks.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..6b7463a9cd6fe372fa0d12a2c30aa428cbe48498
--- /dev/null
+++ b/src/plugins/wp/tests/wp_acsl/oracle/generalized_checks.res.oracle
@@ -0,0 +1,139 @@
+# frama-c -wp [...]
+[kernel] Parsing tests/wp_acsl/generalized_checks.i (no preprocessing)
+[wp] Running WP plugin...
+[wp] Loading driver 'share/wp.driver'
+[wp] Warning: Missing RTE guards
+------------------------------------------------------------
+  Axiomatic 'Th'
+------------------------------------------------------------
+
+Lemma C:
+Assume: 'A'
+Prove: (P_Q x_0) -> (P_R x_0)
+
+------------------------------------------------------------
+
+Lemma L:
+Assume: 'A'
+Prove: (P_P x_0) -> (P_R x_0)
+
+------------------------------------------------------------
+------------------------------------------------------------
+  Function caller
+------------------------------------------------------------
+
+Goal Post-condition 'R' in 'caller':
+Prove: true.
+
+------------------------------------------------------------
+
+Goal Post-condition 'R1,ko' in 'caller':
+Assume {
+  Type: is_sint32(caller_0) /\ is_sint32(x).
+  (* Pre-condition *)
+  Have: P_A(x) /\ P_CA1(x).
+  (* Call 'job' *)
+  Have: P_B(caller_0).
+}
+Prove: P_CB1(caller_0).
+
+------------------------------------------------------------
+
+Goal Post-condition 'R2,ko' in 'caller':
+Assume {
+  Type: is_sint32(caller_0) /\ is_sint32(x).
+  (* Pre-condition *)
+  Have: P_A(x) /\ P_CA1(x).
+  (* Call 'job' *)
+  Have: P_B(caller_0).
+}
+Prove: P_CA2(x).
+
+------------------------------------------------------------
+
+Goal Assigns nothing in 'caller':
+Prove: true.
+
+------------------------------------------------------------
+
+Goal Assigns nothing in 'caller' (1/2):
+Prove: true.
+
+------------------------------------------------------------
+
+Goal Assigns nothing in 'caller' (2/2):
+Call Result at line 65
+Prove: true.
+
+------------------------------------------------------------
+
+Goal Instance of 'Pre-condition 'A' in 'job'' in 'caller' at call 'job' (file tests/wp_acsl/generalized_checks.i, line 65)
+:
+Prove: true.
+
+------------------------------------------------------------
+
+Goal Instance of 'Pre-condition 'CA1' in 'job'' in 'caller' at call 'job' (file tests/wp_acsl/generalized_checks.i, line 65)
+:
+Prove: true.
+
+------------------------------------------------------------
+
+Goal Instance of 'Pre-condition 'CA2,ko' in 'job'' in 'caller' at call 'job' (file tests/wp_acsl/generalized_checks.i, line 65)
+:
+Assume { Type: is_sint32(x). (* Pre-condition *) Have: P_A(x) /\ P_CA1(x). }
+Prove: P_CA2(x).
+
+------------------------------------------------------------
+------------------------------------------------------------
+  Function job
+------------------------------------------------------------
+
+Goal Post-condition 'B' in 'job':
+Let x_1 = L_F(x).
+Assume {
+  Type: is_sint32(x) /\ is_sint32(x_1).
+  (* Pre-condition *)
+  Have: P_A(x).
+}
+Prove: P_B(x_1).
+
+------------------------------------------------------------
+
+Goal Post-condition 'CB1' in 'job':
+Let x_1 = L_F(x).
+Assume {
+  Type: is_sint32(x) /\ is_sint32(x_1).
+  (* Pre-condition *)
+  Have: P_A(x).
+}
+Prove: P_CB1(x_1).
+
+------------------------------------------------------------
+
+Goal Post-condition 'CB2,ko' in 'job':
+Let x_1 = L_F(x).
+Assume {
+  Type: is_sint32(x) /\ is_sint32(x_1).
+  (* Pre-condition *)
+  Have: P_A(x).
+}
+Prove: P_CB2(x_1).
+
+------------------------------------------------------------
+
+Goal Assigns nothing in 'job':
+Prove: true.
+
+------------------------------------------------------------
+
+Goal Assigns nothing in 'job' (1/2):
+Prove: true.
+
+------------------------------------------------------------
+
+Goal Assigns nothing in 'job' (2/2):
+Call Result at line 52
+Prove: true.
+
+------------------------------------------------------------
diff --git a/src/plugins/wp/tests/wp_acsl/oracle_qualif/generalized_checks.res.oracle b/src/plugins/wp/tests/wp_acsl/oracle_qualif/generalized_checks.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..4b3a0044393faa02a60d3f95120b5a17991d3a11
--- /dev/null
+++ b/src/plugins/wp/tests/wp_acsl/oracle_qualif/generalized_checks.res.oracle
@@ -0,0 +1,34 @@
+# frama-c -wp -wp-timeout 1 [...]
+[kernel] Parsing tests/wp_acsl/generalized_checks.i (no preprocessing)
+[wp] Running WP plugin...
+[wp] Loading driver 'share/wp.driver'
+[wp] Warning: Missing RTE guards
+[wp] 17 goals scheduled
+[wp] [Alt-Ergo] Goal typed_check_lemma_C_ko : Unsuccess
+[wp] [Alt-Ergo] Goal typed_lemma_L_ko : Unsuccess
+[wp] [Qed] Goal typed_caller_ensures_R : Valid
+[wp] [Alt-Ergo] Goal typed_caller_ensures_R1_ko : Unsuccess
+[wp] [Alt-Ergo] Goal typed_caller_ensures_R2_ko : Unsuccess
+[wp] [Qed] Goal typed_caller_assigns_exit : Valid
+[wp] [Qed] Goal typed_caller_assigns_normal_part1 : Valid
+[wp] [Qed] Goal typed_caller_assigns_normal_part2 : Valid
+[wp] [Qed] Goal typed_caller_call_job_requires_A : Valid
+[wp] [Qed] Goal typed_caller_call_job_check_requires_CA1 : Valid
+[wp] [Alt-Ergo] Goal typed_caller_call_job_check_requires_CA2_ko : Unsuccess
+[wp] [Alt-Ergo] Goal typed_job_ensures_B : Valid
+[wp] [Alt-Ergo] Goal typed_job_check_ensures_CB1 : Valid
+[wp] [Alt-Ergo] Goal typed_job_check_ensures_CB2_ko : Unsuccess
+[wp] [Qed] Goal typed_job_assigns_exit : Valid
+[wp] [Qed] Goal typed_job_assigns_normal_part1 : Valid
+[wp] [Qed] Goal typed_job_assigns_normal_part2 : Valid
+[wp] Proved goals:   11 / 17
+  Qed:             9 
+  Alt-Ergo:        2  (unsuccess: 6)
+------------------------------------------------------------
+ Axiomatics                WP     Alt-Ergo  Total   Success
+  Axiomatic Th              -        -        2       0.0%
+------------------------------------------------------------
+ Functions                 WP     Alt-Ergo  Total   Success
+  job                       3        2        6      83.3%
+  caller                    6        -        9      66.7%
+------------------------------------------------------------
diff --git a/src/plugins/wp/wpAnnot.ml b/src/plugins/wp/wpAnnot.ml
index b7b5698f643fdcafecc7251c539a7beec9b5ca2d..eaee55511cfafb12924c110f9ab35ad17d8f4b6c 100644
--- a/src/plugins/wp/wpAnnot.ml
+++ b/src/plugins/wp/wpAnnot.ml
@@ -373,6 +373,9 @@ let kind_to_select config kind id = match kind with
   | WpStrategy.AcallPre(goal,fct) ->
       let goal = goal && goal_to_select config id in
       Some (WpStrategy.AcallPre(goal,fct))
+  | WpStrategy.AcallCheck(fct) ->
+      if goal_to_select config id then Some (WpStrategy.AcallCheck fct)
+      else None
   | WpStrategy.AcallPost _ ->
       if goal_to_select config id then Some kind else None
   | WpStrategy.Ahyp | WpStrategy.AcallHyp _ -> Some kind
@@ -753,7 +756,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
+      if tk = termination_kind && not p.ip_content.tp_only_check
       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
@@ -830,6 +833,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_only_check 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
    * in the loop, so we can assume that inv is true for each edge
@@ -843,15 +848,18 @@ let add_loop_invariant_annot config vloop s ca b_list inv acc =
             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_core = add_prop_inv_fixpoint config loop_core
-            WpStrategy.Ahyp s ca inv in
+        let loop_core =
+          if only_check then loop_core
+          else
+            add_prop_inv_fixpoint config loop_core WpStrategy.Ahyp s ca inv
+        in
         assigns, loop_entry , loop_back , loop_core
       end
-  | TBRhyp ->
+  | 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
-  | TBRno -> acc
+  | TBRhyp | TBRno -> acc
 
 (** Returns the annotations for the three edges of the loop node:
  * - loop_entry : goals for the edge entering in the loop
@@ -934,24 +942,28 @@ let get_stmt_annots config v s =
               Printer.pp_code_annotation a;
             acc
           end
-    | AAssert (b_list, kind, p) ->
+    | AAssert (b_list, p) ->
         let kf = config.kf in
         let acc = match is_annot_for_config config v s b_list with
           | TBRno -> acc
           | TBRhyp ->
-              if kind = Check then acc
+              if p.tp_only_check then acc
               else
                 let b_acc =
-                  WpStrategy.add_prop_assert b_acc WpStrategy.Ahyp kf s a p
+                  WpStrategy.add_prop_assert
+                    b_acc WpStrategy.Ahyp kf s a p.tp_statement
                 in (b_acc, (a_acc, e_acc))
           | TBRok | TBRpart ->
               let id = WpPropId.mk_assert_id config.kf s a in
-              let check = kind = Check
-              and goal = goal_to_select config id in
-              if check && not goal then acc
+              let goal = goal_to_select config id in
+              if p.tp_only_check && not goal then acc
               else
-                let kind = WpStrategy.(if check then Agoal else Aboth goal) in
-                let b_acc = WpStrategy.add_prop_assert b_acc kind kf s a p in
+                let kind =
+                  WpStrategy.(if p.tp_only_check then Agoal else Aboth goal)
+                in
+                let b_acc =
+                  WpStrategy.add_prop_assert b_acc kind kf s a p.tp_statement
+                in
                 (b_acc, (a_acc, e_acc))
         in acc
     | AAllocation (_b_list, _frees_allocates) ->
@@ -1118,8 +1130,9 @@ let add_global_annotations annots =
           "Global invariant not handled yet ('%s' ignored)"
           linfo.l_var_info.lv_name;
         ()
-    | Dlemma (name,_,_,_,_,_,_) ->
-        WpStrategy.add_axiom annots (LogicUsage.logic_lemma name)
+    | Dlemma (name,_,_,_,p,_,_) ->
+        if not (p.tp_only_check) then
+          WpStrategy.add_axiom annots (LogicUsage.logic_lemma name)
 
   and do_globals gs = List.iter do_global gs in
   (*[LC]: forcing order of iteration: hash is not the same on 32 and 64 bits *)
@@ -1425,7 +1438,7 @@ let get_id_prop_strategies ~model ?(assigns=WithAssigns) p =
   let open Property in match p with
   | IPCodeAnnot {ica_kf; ica_ca} ->
       let bhvs = match ica_ca.annot_content with
-        | AAssert (l, _, _) | AInvariant (l, _, _) | AAssigns (l, _) -> l
+        | AAssert (l, _) | AInvariant (l, _, _) | AAssigns (l, _) -> l
         | _ -> []
       in get_strategies assigns ica_kf model bhvs None (IdProp p)
   | IPAssigns {ias_kf = kf; ias_bhv = Id_loop _}
diff --git a/src/plugins/wp/wpPropId.ml b/src/plugins/wp/wpPropId.ml
index 9821c657890900dac6b7ba825e5dc6c5f025f2d1..458a2fcf48f0597f432a0cd3f2f236a18127852b 100644
--- a/src/plugins/wp/wpPropId.ml
+++ b/src/plugins/wp/wpPropId.ml
@@ -465,10 +465,13 @@ let ident_names names =
   List.filter (function "" -> true
                       | _ as n -> '\"' <> (String.get n 0) ) names
 
+let pred_names p =
+  let p_names = ident_names p.tp_statement.pred_name in
+  if p.tp_only_check then "@check"::p_names else p_names
+
 let code_annot_names ca = match ca.annot_content with
-  | AAssert (_, Check, named_pred)  -> "@check"::(ident_names named_pred.pred_name)
-  | AAssert (_, Assert, named_pred)  -> "@assert"::(ident_names named_pred.pred_name)
-  | AInvariant (_,_,named_pred) -> "@invariant"::(ident_names named_pred.pred_name)
+  | AAssert (_, pred)  -> "@assert" :: pred_names pred
+  | AInvariant (_,_,pred) -> "@invariant":: pred_names pred
   | AVariant (term, _) -> "@variant"::(ident_names term.term_name)
   | AExtended(_,_,{ext_name}) -> [Printf.sprintf "@%s" ext_name]
   | _ -> [] (* TODO : add some more names ? *)
@@ -479,7 +482,7 @@ let user_prop_names p =
   let open Property in match p with
   | IPPredicate {ip_kind; ip_pred} ->
       Format.asprintf  "@@%a" Property.pretty_predicate_kind ip_kind ::
-      ip_pred.ip_content.pred_name
+      pred_names ip_pred.ip_content
   | IPExtended {ie_ext={ext_name}} -> [ Printf.sprintf "@%s" ext_name ]
   | IPCodeAnnot {ica_ca} -> code_annot_names ica_ca
   | IPComplete {ic_bhvs} ->
@@ -497,8 +500,8 @@ let user_prop_names p =
   | IPDecrease {id_ca=Some ca} -> "@decreases"::code_annot_names ca
   | IPDecrease _ -> [ "@decreases" ]
   | IPLemma {il_name = a; il_pred = l} ->
-      let names = "@lemma"::a::(ident_names l.pred_name)
-      in begin
+      let names = "@lemma"::a::pred_names l in
+      begin
         match LogicUsage.section_of_lemma a with
         | LogicUsage.Toplevel _ -> names
         | LogicUsage.Axiomatic ax -> ax.LogicUsage.ax_name::names
@@ -641,8 +644,8 @@ let assigns_hints hs froms =
   List.iter (fun ({it_content=t},_) -> term_hints hs t) froms
 
 let annot_hints hs = function
-  | AAssert(bs,_,ipred) | AInvariant(bs,_,ipred) ->
-      List.iter (add_hint hs) (ident_names ipred.pred_name) ;
+  | AAssert(bs,ipred) | AInvariant(bs,_,ipred) ->
+      List.iter (add_hint hs) (ident_names ipred.tp_statement.pred_name) ;
       List.iter (add_hint hs) bs
   | AAssigns(bs,Writes froms) ->
       List.iter (add_hint hs) bs ;
@@ -654,12 +657,12 @@ let property_hints hs =
   let open Property in function
     | IPAxiom  {il_name; il_pred}
     | IPLemma  {il_name; il_pred} ->
-        List.iter (add_required hs) (il_name::il_pred.pred_name)
+        List.iter (add_required hs) (il_name::il_pred.tp_statement.pred_name)
     | IPBehavior _ -> ()
     | IPComplete {ic_bhvs} | IPDisjoint {ic_bhvs} ->
         List.iter (add_required hs) ic_bhvs
     | IPPredicate {ip_pred} ->
-        List.iter (add_hint hs) ip_pred.ip_content.pred_name
+        List.iter (add_hint hs) ip_pred.ip_content.tp_statement.pred_name
     | IPExtended {ie_ext={ext_name}} -> List.iter (add_hint hs) [ext_name]
     | IPCodeAnnot {ica_ca} -> annot_hints hs ica_ca.annot_content
     | IPAssigns {ias_froms} -> assigns_hints hs ias_froms
diff --git a/src/plugins/wp/wpReached.ml b/src/plugins/wp/wpReached.ml
index 98acfad8ecbdd9dcf19e600ffe29b1efa795a5b6..f2b7abc13875fb0113053421aace7c796df5eaf7 100644
--- a/src/plugins/wp/wpReached.ml
+++ b/src/plugins/wp/wpReached.ml
@@ -84,8 +84,9 @@ let is_dead_annot ca =
   match ca.annot_content with
   | APragma (Loop_pragma (Unroll_specs [ spec ; _ ])) ->
       false && is_unrolled_completely spec
-  | AAssert([],Assert,p) -> is_predicate false p
-  | AInvariant([],_,p) -> is_predicate false p
+  | AAssert([],p) ->
+      not p.tp_only_check && is_predicate false p.tp_statement
+  | AInvariant([],_,p) -> 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 ee31dab55e746eef3b68c77901182615c54cffce..96f589da256b9329369a41a49b171e172f687230 100644
--- a/src/plugins/wp/wpStrategy.ml
+++ b/src/plugins/wp/wpStrategy.ml
@@ -48,10 +48,15 @@ type annot_kind =
   | AcallPre of bool * kernel_function
   (* annotation is a called function precondition :
      to be considered as hyp, and goal if bool=true *)
+  | AcallCheck of kernel_function
+  (* annotation is a called function check-only precondition.
+     to be considered as goal only. *)
   | AcallPost of kernel_function
   (* annotation is a called function post check :
      to be considered as goal only *)
 
+type call_pre_kind = CPhyp | CPgoal | CPboth
+
 (* -------------------------------------------------------------------------- *)
 (* --- Annotations for one program point.                                 --- *)
 (* -------------------------------------------------------------------------- *)
@@ -68,7 +73,7 @@ type annots = {
   p_both : (bool * WpPropId.pred_info) list;
   p_cut : (bool * WpPropId.pred_info) list;
   call_hyp : WpPropId.pred_info list ForCall.t; (* post and pre *)
-  call_pre : (bool * WpPropId.pred_info) list ForCall.t; (* goal only *)
+  call_pre : (call_pre_kind * WpPropId.pred_info) list ForCall.t;
   call_post : WpPropId.pred_info list ForCall.t; (* post goals only (not hyp) *)
   call_asgn : WpPropId.assigns_full_info ForCall.t;
   a_goal : WpPropId.assigns_full_info;
@@ -112,10 +117,20 @@ let add_prop acc kind id p =
                          | Some p -> Some(WpPropId.mk_pred_info id p) in
   let add_hyp l = match get_p with None -> l | Some p -> p::l in
   let add_goal l = match get_p with None -> l | Some p -> p::l in
+  let add_both_std goal l =
+    match get_p with None -> l | Some p -> (goal,p) :: l
+  in
   let add_both goal l =
     match get_p with
     | None -> l
-    | Some p -> (goal, p)::l
+    | Some p ->
+        let kind = if goal then CPboth else CPhyp in
+        (kind, p)::l
+  in
+  let add_pre l =
+    match get_p with
+    | None -> l
+    | Some p -> (CPgoal, p) :: l
   in
   let add_for_call fct calls =
     let l = try ForCall.find fct calls with Not_found -> [] in
@@ -123,6 +138,10 @@ let add_prop acc kind id p =
   let add_both_call fct goal calls =
     let l = try ForCall.find fct calls with Not_found -> [] in
     ForCall.add fct (add_both goal l) calls in
+  let add_pre_call fct calls =
+    let l = try ForCall.find fct calls with Not_found -> [] in
+    ForCall.add fct (add_pre l) calls
+  in
   let info = acc.info in
   let goal, info = match kind with
     | Ahyp ->
@@ -130,13 +149,15 @@ let add_prop acc kind id p =
     | Agoal ->
         true, { info with p_goal = add_goal info.p_goal }
     | Aboth goal ->
-        goal, { info with p_both = add_both goal info.p_both }
+        goal, { info with p_both = add_both_std goal info.p_both }
     | AcutB goal ->
-        goal, { info with p_cut = add_both goal info.p_cut }
+        goal, { info with p_cut = add_both_std goal info.p_cut }
     | AcallHyp fct ->
         false, { info with call_hyp = add_for_call fct info.call_hyp }
     | AcallPre (goal,fct) ->
         goal, { info with call_pre = add_both_call fct goal info.call_pre }
+    | AcallCheck fct ->
+        true, { info with call_pre = add_pre_call fct info.call_pre }
     | AcallPost fct ->
         true, { info with call_post = add_for_call fct info.call_post }
   in let acc = { acc with info = info } in
@@ -149,7 +170,10 @@ let add_prop_fct_pre_bhv acc kind kf bhv =
     let p = Logic_const.pred_of_id_pred pred in
     Logic_const.(pat (p,pre_label))
   in
-  let requires = Logic_const.pands (List.map norm_pred bhv.b_requires) in
+  let requires =
+    List.filter (fun x -> not x.ip_content.tp_only_check) 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
   let precond = Logic_const.pimplies (assumes, requires) in
   let precond_id = Logic_const.new_predicate precond in
@@ -159,12 +183,14 @@ 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 =
-  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
+  if pre.ip_content.tp_only_check then acc else 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
 
 let add_prop_fct_post acc kind kf  bhv tkind post =
   let id = WpPropId.mk_fct_post_id kf bhv (tkind, post) in
@@ -207,13 +233,24 @@ let add_prop_stmt_post acc kind kf s bhv tkind l_post ~assumes post =
   let p = normalize id labels ?assumes p in
   add_prop acc kind id p
 
+let update_kind kind pre =
+  if pre.ip_content.tp_only_check then begin
+    match kind with
+    | AcallPre(false,_) -> None
+    | AcallPre(true, kf) -> Some (AcallCheck kf)
+    | _ -> Some kind
+  end else Some kind
+
 let add_prop_call_pre acc kind id ~assumes pre =
-  let labels = NormAtLabels.labels_fct_pre in
-  let p = Logic_const.pred_of_id_pred pre in
-  (* assumes can be normalized in the same time *)
-  let p = Logic_const.pimplies (assumes, p) in
-  let p = normalize id labels p in
-  add_prop acc kind id p
+  match update_kind kind pre with
+  | None -> acc
+  | Some kind ->
+      let labels = NormAtLabels.labels_fct_pre in
+      let p = Logic_const.pred_of_id_pred pre in
+      (* assumes can be normalized in the same time *)
+      let p = Logic_const.pimplies (assumes, p) in
+      let p = normalize id labels p in
+      add_prop acc kind id p
 
 let add_prop_call_post acc kind called_kf bhv tkind ~assumes post =
   let id = WpPropId.mk_fct_post_id called_kf bhv (tkind, post) in
@@ -439,6 +476,14 @@ let filter_both l =
     p::h_acc, if goal then p::g_acc else g_acc
   in List.fold_left add ([], []) l
 
+let filter_both_call l =
+  let add (h_acc, g_acc) (goal, p) =
+    match goal with
+    | CPboth -> p :: h_acc, p :: g_acc
+    | CPhyp -> p :: h_acc, g_acc
+    | CPgoal -> h_acc, p :: g_acc
+  in List.fold_left add ([], []) l
+
 let get_both_hyp_goals annots = filter_both annots.info.p_both
 
 let get_call_hyp annots fct =
@@ -446,7 +491,7 @@ let get_call_hyp annots fct =
   with Not_found -> []
 
 let get_call_pre annots fct =
-  try filter_both (ForCall.find fct annots.info.call_pre)
+  try filter_both_call (ForCall.find fct annots.info.call_pre)
   with Not_found -> [],[]
 
 let get_call_post annots fct =
@@ -473,8 +518,14 @@ let pp_annots fmt acc =
     Format.fprintf fmt "%s%s: %a@."
       k (if b then "" else " (h)") WpPropId.pp_pred_of_pred_info p
   in
+  let pp_pred_c k c p =
+    let kind = match c with CPboth -> "(h+g)" | CPgoal -> "g" | CPhyp -> "h" in
+    Format.fprintf fmt "%s%s: %a@."
+      k kind WpPropId.pp_pred_of_pred_info p
+  in
   let pp_pred_list k l = List.iter (fun p -> pp_pred k true p) l in
   let pp_pred_b_list k l = List.iter (fun (b, p) -> pp_pred k b p) l in
+  let pp_pred_c_list k l = List.iter (fun (c, p) -> pp_pred_c k c p) l in
   begin
     pp_pred_list "H" acc.p_hyp;
     pp_pred_list "G" acc.p_goal;
@@ -488,7 +539,7 @@ let pp_annots fmt acc =
     ForCall.iter
       (fun kf bhs ->
          let name = "CallPre:" ^ (Kernel_function.get_name kf) in
-         pp_pred_b_list name bhs)
+         pp_pred_c_list name bhs)
       acc.call_pre;
     ForCall.iter
       (fun kf asgn ->
diff --git a/src/plugins/wp/wpStrategy.mli b/src/plugins/wp/wpStrategy.mli
index 9177f1fe53676af44dc9d2ed1345dd6cbc64234d..8f30ea928ce13ce88e7d6f240dc2f4905fe0df8e 100644
--- a/src/plugins/wp/wpStrategy.mli
+++ b/src/plugins/wp/wpStrategy.mli
@@ -58,6 +58,9 @@ type annot_kind =
   | AcallPre of bool * kernel_function
   (** annotation is a called function precondition :
       to be considered as hyp, and goal if bool=true *)
+  | AcallCheck of kernel_function
+  (** annotation is check-only called function precondition.
+      handled internally by {!add_prop_call_pre} below. *)
   | AcallPost of kernel_function
   (** annotation is a called function post check :
       to be considered as goal only (no hyp) *)
diff --git a/src/plugins/wp/wp_parameters.ml b/src/plugins/wp/wp_parameters.ml
index 51394d3c145b1a8a66650b4ddb7f957a6bac49e4..94bc7d0af63478b4c7a3dff2146d14c708425ca9 100644
--- a/src/plugins/wp/wp_parameters.ml
+++ b/src/plugins/wp/wp_parameters.ml
@@ -84,7 +84,7 @@ module Behaviors =
     (struct
       let option_name = "-wp-bhv"
       let arg_name = "b,..."
-      let help = "Select properties of the given behaviors (defaults to all behaviors) of the selected functions."
+      let help = "Select only properties belonging to listed behaviors."
     end)
 let () = on_reset Behaviors.clear
 
@@ -96,10 +96,14 @@ module Properties =
     (struct
       let option_name = "-wp-prop"
       let arg_name = "p,..."
-      let help = "Select properties having the one of the given tagnames (defaults to all properties).\n\
-                  You may also replace the tagname by '@category' for the selection of all properties of the given category.\n\
-                  Accepted categories are: lemmas, requires, assigns, ensures, exits, complete_behaviors, disjoint_behaviors, assert, check, invariant, variant, breaks, continues, returns.\n\
-                  Starts by a minus character to remove properties from the selection."
+      let help =
+        "Select properties based names and category.\n\
+         Use +name or +category to select properties and -name or -category\n\
+         to remove them from the selection. The '+' sign can be omitted.\n\
+         Categories are: @lemma, @requires, @assigns, @ensures, @exits,\n\
+         @assert, @invariant, @variant, @breaks, @continues, @returns,\n\
+         @complete_behaviors, @disjoint_behaviors and\n\
+         @check (which includes all check clauses)."
     end)
 let () = on_reset Properties.clear
 
diff --git a/src/plugins/wp/wpo.ml b/src/plugins/wp/wpo.ml
index 21f7f3a9fa1b25a40763c3172b6f9f529ac61746..032fa83fa1ee75034d6cfc2df03b5dd75cce06cd 100644
--- a/src/plugins/wp/wpo.ml
+++ b/src/plugins/wp/wpo.ml
@@ -722,7 +722,8 @@ let set_doomed emitter pid =
             let pred_loc = Stmt.loc stmt in
             let pred_name = [ "Wp" ; "SmokeTest" ] in
             let pf = { Logic_const.pfalse with pred_loc ; pred_name } in
-            let ca = Logic_const.new_code_annotation (AAssert ([],Assert,pf)) in
+            let pf = Logic_const.toplevel_predicate pf in
+            let ca = Logic_const.new_code_annotation (AAssert ([],pf)) in
             Annotations.add_code_annot emitter ~kf stmt ca ; ca
       in
       List.iter (set_invalid emitter) (Property.ip_of_code_annot kf stmt ca)
diff --git a/tests/libc/check_const.ml b/tests/libc/check_const.ml
index 60f734a6e459c69be94b71a90bd1faad019d9f25..965f710a3caa345008a615bf2a99d4e4532a2f1c 100644
--- a/tests/libc/check_const.ml
+++ b/tests/libc/check_const.ml
@@ -21,7 +21,7 @@ let warn_if_not_const kf string typ vi loc =
         string Printer.pp_varinfo vi string
 
 let check_annot kf _ (a: identified_predicate) =
-  let p = a.ip_content.pred_content in
+  let p = (Logic_const.pred_of_id_pred a).pred_content in
   match p with
   | Pvalid (_, t) | Pvalid_read (_, t)
   | Papp ({l_var_info={lv_name=("valid_string"|"valid_read_string")}},
diff --git a/tests/libc/check_libc_naming_conventions.ml b/tests/libc/check_libc_naming_conventions.ml
index c7a991504950d391779f9761b7a51b4bb0a0d294..c928b21109bbdf51e6ef14a7d61d59db44b7fd73 100644
--- a/tests/libc/check_libc_naming_conventions.ml
+++ b/tests/libc/check_libc_naming_conventions.ml
@@ -58,21 +58,21 @@ let () =
             if Cil.hasAttribute "fc_stdlib" fun_attrs then begin
               Annotations.iter_behaviors (fun _emitter bhv ->
                   List.iter (fun ip ->
-                      let pred = ip.ip_content in
+                      let pred = Logic_const.pred_of_id_pred ip in
                       warn_if_unnamed "requires" pred;
                       check_initialized pred;
                       check_dangling pred;
                       check_separated pred;
                     ) bhv.b_requires;
                   List.iter (fun ip ->
-                      let pred = ip.ip_content in
+                      let pred = Logic_const.pred_of_id_pred ip in
                       warn_if_unnamed "assumes" pred;
                       check_initialized pred;
                       check_dangling pred;
                       check_separated pred;
                     ) bhv.b_assumes;
                   List.iter (fun (_termination, ip) ->
-                      let pred = ip.ip_content in
+                      let pred = Logic_const.pred_of_id_pred ip in
                       warn_if_unnamed "ensures" pred;
                       check_initialized pred;
                       check_dangling pred;
diff --git a/tests/spec/add_global.ml b/tests/spec/add_global.ml
index 39b169539e4b0cf0ab265c7217223c93ba5b8bcd..0a8f954137c1f7f9ff583f8be0ef3e617fc3e0fc 100644
--- a/tests/spec/add_global.ml
+++ b/tests/spec/add_global.ml
@@ -15,7 +15,8 @@ object(self)
           ("MyAxiomatic",
            [ Dlemma(
                  "myaxiom", true, [], [],
-                 Logic_const.ptrue, [], Cil_datatype.Location.unknown)],
+                 Logic_const.(toplevel_predicate ptrue),
+                 [], Cil_datatype.Location.unknown)],
            [], Cil_datatype.Location.unknown)
       in
       Queue.add (fun () -> Annotations.add_global emitter ax)
diff --git a/tests/spec/bts0578.ml b/tests/spec/bts0578.ml
index df12b588dd1d7888ce952084172349671679de70..594d3b71e4b03b506173990f569c70b3ae21ddcf 100644
--- a/tests/spec/bts0578.ml
+++ b/tests/spec/bts0578.ml
@@ -16,12 +16,12 @@ let main () =
     in
     add s (AStmtSpec ([],contract))
   in
-  add s (AInvariant(["foo"], true, ptrue));
+  add s (AInvariant(["foo"], true, toplevel_predicate ptrue));
   add s (AVariant(tinteger 0, None));
-  add s (AInvariant([], true, ptrue));
-  add s (AInvariant(["foo"], true, ptrue));
+  add s (AInvariant([], true, toplevel_predicate ptrue));
+  add s (AInvariant(["foo"], true, toplevel_predicate ptrue));
   Filecheck.check_ast "after adding invariants";
-  let requires = [Logic_const.new_predicate Logic_const.ptrue] in
+  let requires = [new_predicate ptrue] in
   let bhv = [Cil.mk_behavior ~requires ()] in
   add_behavior !s1 bhv;
   Filecheck.check_ast "after adding contract";
diff --git a/tests/spec/expr_to_term.ml b/tests/spec/expr_to_term.ml
index b6ce6b3ab15e0fab3b0e5eb4f46909816c7b4d8d..450dd0d0235313762e4a527d5b891776c1db0566 100644
--- a/tests/spec/expr_to_term.ml
+++ b/tests/spec/expr_to_term.ml
@@ -11,7 +11,7 @@ let check_expr_term check fct s post =
   in
   let term =
     match post with
-      | (_, { ip_content = { pred_content = Papp(_,_,[l;_]) } }) -> l
+      | (_,{ip_content={tp_statement={pred_content = Papp(_,_,[l;_])}}}) -> l
       | _ -> Kernel.fatal "Unexpected ensures %a" Printer.pp_post_cond post
   in
   let term' = Logic_utils.expr_to_term ~coerce:false exp in
diff --git a/tests/spec/generalized_check.i b/tests/spec/generalized_check.i
new file mode 100644
index 0000000000000000000000000000000000000000..7f7c9748c531a7cb0812633335a4ccbd1a73d558
--- /dev/null
+++ b/tests/spec/generalized_check.i
@@ -0,0 +1,42 @@
+/* run.config
+OPT: -wp -wp-prover qed -wp-msg-key no-cache-info,no-time-info
+OPT: -eva -eva-use-spec f
+OPT: -print
+*/
+/*@ check lemma easy_proof: \false; */ // should not be put in any environment
+
+/*@ check requires f_valid_x: \valid(x);
+    assigns *x;
+    check ensures f_init_x: *x == 0;
+*/
+void f(int* x) {
+  /*@ check f_valid_ko: \valid(x); */
+  *x = 0;
+}
+
+void loop(void);
+
+int main() {
+  int a = 4;
+  volatile int c;
+  int* p = (void*)0;
+  if (c) p = &a;
+  f(p);
+  /*@ check main_valid_ko: \valid(p); */
+  /*@ check main_p_content_ko: *p == 0; */
+  loop();
+}
+
+void loop () {
+  int j = 0;
+  /*@ check loop invariant false_but_preserved: j == 10;
+      loop assigns i;
+   */
+  for (int i = 0; i< 10; i++);
+  /*@ check implied_by_false_invariant: j == 10; */
+ l: /*@ check invariant \true; */ ;
+  if (j >= 10) goto l1;
+  j++;
+  goto l;
+ l1 : ;
+}
diff --git a/tests/spec/oracle/generalized_check.0.res.oracle b/tests/spec/oracle/generalized_check.0.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..7f7128dfa8d7a982a69817b1f63a4e4ef677a02b
--- /dev/null
+++ b/tests/spec/oracle/generalized_check.0.res.oracle
@@ -0,0 +1,23 @@
+[kernel] Parsing tests/spec/generalized_check.i (no preprocessing)
+[wp] Running WP plugin...
+[wp] tests/spec/generalized_check.i:30: Warning: 
+  Unsupported generalized invariant, use loop invariant instead.
+  Ignored invariant 
+  check invariant \true;
+[wp] Warning: Missing RTE guards
+[wp] tests/spec/generalized_check.i:37: Warning: 
+  Missing assigns clause (assigns 'everything' instead)
+[wp] 11 goals scheduled
+[wp] [Qed] Goal typed_f_assigns : Valid
+[wp] [Failed] Goal typed_f_check_f_valid_ko
+[wp] [Qed] Goal typed_f_check_ensures_f_init_x : Valid
+[wp] [Failed] Goal typed_check_lemma_easy_proof
+[wp] [Qed] Goal typed_loop_loop_assigns : Valid
+[wp] [Failed] Goal typed_loop_check_implied_by_false_invariant
+[wp] [Failed] Goal typed_loop_check_loop_invariant_false_but_preserved_established
+[wp] [Failed] Goal typed_loop_check_loop_invariant_false_but_preserved_preserved
+[wp] [Failed] Goal typed_main_call_f_check_requires_f_valid_x
+[wp] [Failed] Goal typed_main_check_main_p_content_ko
+[wp] [Failed] Goal typed_main_check_main_valid_ko
+[wp] Proved goals:    3 / 11
+  Qed:             3
diff --git a/tests/spec/oracle/generalized_check.1.res.oracle b/tests/spec/oracle/generalized_check.1.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..f93e7228b403b708b01b4386186ab29d200d1a5a
--- /dev/null
+++ b/tests/spec/oracle/generalized_check.1.res.oracle
@@ -0,0 +1,47 @@
+[kernel] Parsing tests/spec/generalized_check.i (no preprocessing)
+[eva] Analyzing a complete application starting at main
+[eva] Computing initial state
+[eva] Initial state computed
+[eva:initial-state] Values of globals at initialization
+  
+[eva:alarm] tests/spec/generalized_check.i:23: Warning: 
+  accessing uninitialized left-value. assert \initialized(&c);
+[eva] using specification for function f
+[eva:alarm] tests/spec/generalized_check.i:24: Warning: 
+  function f: precondition 'f_valid_x' got status unknown.
+[eva] tests/spec/generalized_check.i:9: Warning: 
+  no \from part for clause 'assigns *x;'
+[eva:alarm] tests/spec/generalized_check.i:25: Warning: 
+  check 'main_valid_ko' got status unknown.
+[eva:alarm] tests/spec/generalized_check.i:26: Warning: 
+  check 'main_p_content_ko' got status unknown.
+[eva:alarm] tests/spec/generalized_check.i:32: Warning: 
+  loop invariant 'false_but_preserved' got status invalid.
+[eva] tests/spec/generalized_check.i:35: starting to merge loop iterations
+[eva:alarm] tests/spec/generalized_check.i:36: Warning: 
+  check 'implied_by_false_invariant' got status invalid.
+[eva] done for function main
+[eva] ====== VALUES COMPUTED ======
+[eva:final-states] Values at end of function loop:
+  j ∈ {10}
+[eva:final-states] Values at end of function main:
+  a ∈ [--..--]
+  p ∈ {{ NULL ; &a }}
+  __retres ∈ {0}
+[eva:summary] ====== ANALYSIS SUMMARY ======
+  ----------------------------------------------------------------------------
+  3 functions analyzed (out of 3): 100% coverage.
+  In these functions, 25 statements reached (out of 28): 89% coverage.
+  ----------------------------------------------------------------------------
+  Some errors and warnings have been raised during the analysis:
+    by the Eva analyzer:      0 errors    1 warning
+    by the Frama-C kernel:    0 errors    0 warnings
+  ----------------------------------------------------------------------------
+  1 alarm generated by the analysis:
+       1 access to uninitialized left-values
+  ----------------------------------------------------------------------------
+  Evaluation of the logical properties reached by the analysis:
+    Assertions        0 valid     2 unknown     2 invalid      4 total
+    Preconditions     0 valid     1 unknown     0 invalid      1 total
+  0% of the logical properties reached have been proven.
+  ----------------------------------------------------------------------------
diff --git a/tests/spec/oracle/generalized_check.2.res.oracle b/tests/spec/oracle/generalized_check.2.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..dd870d5dc009e1cf2c1e19963f7f6d1bbae27bfb
--- /dev/null
+++ b/tests/spec/oracle/generalized_check.2.res.oracle
@@ -0,0 +1,51 @@
+[kernel] Parsing tests/spec/generalized_check.i (no preprocessing)
+/* Generated by Frama-C */
+/*@ check lemma easy_proof: \false;
+ */
+/*@ check requires f_valid_x: \valid(x);
+    check ensures f_init_x: *\old(x) ≡ 0;
+    assigns *x;
+ */
+void f(int *x)
+{
+  /*@ check f_valid_ko: \valid(x); */ ;
+  *x = 0;
+  return;
+}
+
+void loop(void);
+
+int main(void)
+{
+  int __retres;
+  int volatile c;
+  int a = 4;
+  int *p = (int *)0;
+  if (c) p = & a;
+  f(p);
+  /*@ check main_valid_ko: \valid(p); */ ;
+  /*@ check main_p_content_ko: *p ≡ 0; */ ;
+  loop();
+  __retres = 0;
+  return __retres;
+}
+
+void loop(void)
+{
+  int j = 0;
+  {
+    int i = 0;
+    /*@ check loop invariant false_but_preserved: j ≡ 10;
+        loop assigns i; */
+    while (i < 10) i ++;
+  }
+  /*@ check implied_by_false_invariant: j ≡ 10; */ ;
+  l: /*@ check invariant \true; */ ;
+  if (j >= 10) goto l1;
+  j ++;
+  goto l;
+  l1: ;
+  return;
+}
+
+
diff --git a/tests/syntax/syntactic_hook.ml b/tests/syntax/syntactic_hook.ml
index c6a5d1f3517e261599913c4c0f8f577ece146a2c..5a479278793dbeb6d7f90325d44d63a624fc95d7 100644
--- a/tests/syntax/syntactic_hook.ml
+++ b/tests/syntax/syntactic_hook.ml
@@ -13,10 +13,15 @@ class visit = object
       [{ stmt_ghost = false;
          stmt_node =
            CODE_ANNOT(
-             AAssert([], Assert,
-                     { lexpr_node =
-                         PLat ({ lexpr_node = PLtrue; lexpr_loc = loc},"Pre");
-                       lexpr_loc = loc}), loc)};
+             AAssert(
+               [],
+               { tp_only_check = false;
+                 tp_statement =
+                   { lexpr_node =
+                       PLat ({ lexpr_node = PLtrue; lexpr_loc = loc},"Pre");
+                     lexpr_loc = loc}
+               }),
+             loc)};
        s]
 end