diff --git a/src/kernel_services/ast_queries/acsl_extension.mli b/src/kernel_services/ast_queries/acsl_extension.mli
index a4b99bcf14208e8356fbed6097670c7f890a3edb..df0e7f6d07d88fe124247fbaeb2be5f62bb8994a 100644
--- a/src/kernel_services/ast_queries/acsl_extension.mli
+++ b/src/kernel_services/ast_queries/acsl_extension.mli
@@ -80,7 +80,7 @@ type extension_printer =
     Here is a basic example:
     [
     let count = ref 0
-    let foo_typer ~typing_context ~loc = function
+    let foo_typer typing_context loc = function
       | p :: [] ->
         Ext_preds
         [ (typing_context.type_predicate
diff --git a/src/kernel_services/ast_queries/cil.mli b/src/kernel_services/ast_queries/cil.mli
index 5bdb0939b7a617338d8b221ca8cffe24fad7c7a3..df4e0e12389593b8b0423c1bf6d46e91dd878bc5 100644
--- a/src/kernel_services/ast_queries/cil.mli
+++ b/src/kernel_services/ast_queries/cil.mli
@@ -1223,7 +1223,7 @@ val partitionAttributes:  default:attributeClass ->
                 attribute list   (* AttrType *)
 
 (** Add an attribute. Maintains the attributes in sorted order of the second
-    argument *)
+    argument. The attribute is not added if it is already there. *)
 val addAttribute: attribute -> attributes -> attributes
 
 (** Add a list of attributes. Maintains the attributes in sorted order. The
diff --git a/src/plugins/wp/Factory.ml b/src/plugins/wp/Factory.ml
index cdb4593efb4ac2c9aa6813f5dab05f961a3730df..668610d8cfccda532eb16e76f332df7ef6875d5a 100644
--- a/src/plugins/wp/Factory.ml
+++ b/src/plugins/wp/Factory.ml
@@ -104,6 +104,9 @@ let describe s =
 (* --- Variable Proxy                                                     --- *)
 (* -------------------------------------------------------------------------- *)
 
+let validity x =
+  if RefUsage.is_nullable x then MemoryContext.Nullable else Valid
+
 module type Proxy = sig
   val datatype : string
   val param : Cil_types.varinfo -> MemoryContext.param
@@ -124,7 +127,7 @@ struct
     let module S = Datatype.String.Set in
     let open MemoryContext in
     if S.mem x.vname (get_addr ()) then ByAddr else
-    if S.mem x.vname (get_ctxt ()) then InContext else
+    if S.mem x.vname (get_ctxt ()) then InContext (validity x) else
     if S.mem x.vname (get_refs ()) then ByRef else
     if S.mem x.vname (get_vars ()) then ByValue else
       V.param x
@@ -182,16 +185,19 @@ let refusage_param ~byref ~context x =
   | RefUsage.NoAccess -> MemoryContext.NotUsed
   | RefUsage.ByAddr -> MemoryContext.ByAddr
   | RefUsage.ByValue ->
-      if context && is_formal_ptr x then MemoryContext.InContext
+      if context && is_formal_ptr x then MemoryContext.InContext (validity x)
       else if is_ptr x && not (is_fun_ptr x) then MemoryContext.ByShift
       else MemoryContext.ByValue
   | RefUsage.ByRef ->
       if byref
-      then MemoryContext.ByRef
+      then
+        if RefUsage.is_nullable x
+        then MemoryContext.InContext Nullable
+        else MemoryContext.ByRef
       else MemoryContext.ByValue
   | RefUsage.ByArray ->
       if context && is_formal_ptr x
-      then MemoryContext.InArray
+      then MemoryContext.InArray (validity x)
       else MemoryContext.ByShift
 
 let refusage_iter ?kf ~init f = RefUsage.iter ?kf ~init (fun x _usage -> f x)
diff --git a/src/plugins/wp/Generator.ml b/src/plugins/wp/Generator.ml
index 4b5d51804c65821460d0d5ee8397f6c39468e130..425a2b4ca9bab6bf6e494abd77b7d5321d3c1a69 100644
--- a/src/plugins/wp/Generator.ml
+++ b/src/plugins/wp/Generator.ml
@@ -50,7 +50,19 @@ let user_setup () : Factory.setup =
           cint = Cint.Natural ;
           cfloat = Cfloat.Real ;
         }
-    | spec -> Factory.parse spec
+    | spec ->
+        let setup = Factory.parse spec in
+        let mref = match setup.mvar with
+          | Caveat -> "caveat" | Ref -> "ref" | Raw | Var -> "" in
+        if mref <> ""
+        && RefUsage.has_nullable ()
+        && not (Wp_parameters.RTE.is_set ())
+        then
+          Wp_parameters.warning ~current:false ~once:true
+            "In %s model with nullable arguments, \
+             -wp-(no)-rte shall be explicitly positioned."
+            mref ;
+        setup
   end
 
 (* -------------------------------------------------------------------------- *)
diff --git a/src/plugins/wp/MemVar.ml b/src/plugins/wp/MemVar.ml
index e373bd541e29e52019abce940537424ab03ff533..45cc5514fc77bf7cf02ef169a228cbabfc8f9311 100644
--- a/src/plugins/wp/MemVar.ml
+++ b/src/plugins/wp/MemVar.ml
@@ -104,7 +104,7 @@ struct
       match V.param x with
       | ByRef ->
           "ra_" ^ LogicUsage.basename x
-      | NotUsed | ByValue | ByShift | ByAddr | InContext | InArray ->
+      | NotUsed | ByValue | ByShift | ByAddr | InContext _ | InArray _ ->
           "ta_" ^ LogicUsage.basename x
     let is_framed = is_framed_var
   end
@@ -517,8 +517,8 @@ struct
   type mem =
     | CVAL (* By-Value variable *)
     | CREF (* By-Ref variable *)
-    | CTXT (* In-context pointer *)
-    | CARR (* In-context array *)
+    | CTXT of MemoryContext.validity (* In-context pointer *)
+    | CARR of MemoryContext.validity (* In-context array *)
     | HEAP (* In-heap variable *)
 
   type loc =
@@ -563,8 +563,8 @@ struct
   let vtype m x =
     match m with
     | CVAL | HEAP -> x.vtype
-    | CTXT | CREF -> Cil.typeOf_pointed x.vtype
-    | CARR -> Ast_info.array_type (Cil.typeOf_pointed x.vtype)
+    | CTXT _ | CREF -> Cil.typeOf_pointed x.vtype
+    | CARR _ -> Ast_info.array_type (Cil.typeOf_pointed x.vtype)
 
   let vobject m x = Ctypes.object_of (vtype m x)
 
@@ -593,15 +593,15 @@ struct
   let pp_mem fmt = function
     | CVAL -> Format.pp_print_string fmt "var"
     | CREF -> Format.pp_print_string fmt "ref"
-    | CTXT -> Format.pp_print_string fmt "ptr"
-    | CARR -> Format.pp_print_string fmt "arr"
+    | CTXT _ -> Format.pp_print_string fmt "ptr"
+    | CARR _ -> Format.pp_print_string fmt "arr"
     | HEAP -> Format.pp_print_string fmt "mem"
 
   (* re-uses strings that are used into the description of -wp-xxx-vars *)
   let pp_var_model fmt = function
     | ByValue | ByShift | NotUsed -> Format.pp_print_string fmt "non-aliased" (* cf.  -wp-unalias-vars *)
     | ByRef -> Format.pp_print_string fmt "by reference" (* cf. -wp-ref-vars *)
-    | InContext | InArray -> Format.pp_print_string fmt "in an isolated context" (* cf. -wp-context-vars *)
+    | InContext _ | InArray _ -> Format.pp_print_string fmt "in an isolated context" (* cf. -wp-context-vars *)
     | ByAddr -> Format.pp_print_string fmt "aliased" (* cf. -wp-alias-vars *)
 
   let pretty fmt = function
@@ -632,7 +632,36 @@ struct
   let cvar x = match V.param x with
     | NotUsed | ByValue | ByShift -> Val(CVAL,x,[])
     | ByAddr -> Val(HEAP,x,[])
-    | InContext | InArray | ByRef -> Ref x
+    | InContext _ | InArray _ | ByRef -> Ref x
+
+  (* -------------------------------------------------------------------------- *)
+  (* ---  Nullable locations                                                --- *)
+  (* -------------------------------------------------------------------------- *)
+
+  module Nullable = WpContext.Generator(Varinfo)
+      (struct
+        let name = "MemVar.Nullable"
+        type key = varinfo
+        type data = lfun
+
+        let compile v =
+          let result = t_addr () in
+          let lfun = Lang.generated_f ~result "pointer_%s" v.vname in
+          let cluster =
+            Definitions.cluster ~id:"Globals" ~title:"Context pointers" ()
+          in
+          Definitions.define_symbol {
+            d_lfun = lfun ;
+            d_types = 0 ;
+            d_params = [] ;
+            d_definition = Definitions.Logic result ;
+            d_cluster = cluster
+          } ;
+          lfun
+      end)
+
+  let nullable_address v =
+    Lang.F.e_fun (Nullable.get v) []
 
   (* -------------------------------------------------------------------------- *)
   (* ---  Lifting                                                           --- *)
@@ -645,7 +674,11 @@ struct
   let mseq_of_seq seq = { pre = seq.pre.mem ; post = seq.post.mem }
 
   let mloc_of_path m x ofs =
-    List.fold_left moffset (M.cvar (vbase m x)) ofs
+    let l = match m with
+      | CTXT Nullable | CARR Nullable -> M.pointer_loc @@ nullable_address x
+      | _ -> M.cvar (vbase m x)
+    in
+    List.fold_left moffset l ofs
 
   let mloc_of_loc = function
     | Loc l -> l
@@ -731,9 +764,9 @@ struct
   let load sigma obj = function
     | Ref x ->
         begin match V.param x with
-          | ByRef     -> Sigs.Loc(Val(CREF,x,[]))
-          | InContext -> Sigs.Loc(Val(CTXT,x,[]))
-          | InArray   -> Sigs.Loc(Val(CARR,x,[]))
+          | ByRef       -> Sigs.Loc(Val(CREF,x,[]))
+          | InContext n -> Sigs.Loc(Val(CTXT n,x,[]))
+          | InArray n   -> Sigs.Loc(Val(CARR n,x,[]))
           | NotUsed | ByAddr | ByValue | ByShift -> assert false
         end
     | Val((CREF|CVAL),x,ofs) ->
@@ -742,7 +775,7 @@ struct
         Cvalues.map_value
           (fun l -> Loc l)
           (M.load sigma.mem obj l)
-    | Val((CTXT|CARR|HEAP) as m,x,ofs) ->
+    | Val((CTXT _|CARR _|HEAP) as m,x,ofs) ->
         Cvalues.map_value
           (fun l -> Loc l)
           (M.load sigma.mem obj (mloc_of_path m x ofs))
@@ -773,7 +806,7 @@ struct
     | Val((CREF|CVAL),x,ofs) ->
         let init = Cvalues.initialized_obj obj in
         (memvar_stored seq obj l v) :: (memvar_set_init seq x ofs init)
-    | Val((CTXT|CARR|HEAP) as m,x,ofs) ->
+    | Val((CTXT _|CARR _|HEAP) as m,x,ofs) ->
         M.stored (mseq_of_seq seq) obj (mloc_of_path m x ofs) v
     | Loc l ->
         M.stored (mseq_of_seq seq) obj l v
@@ -790,6 +823,8 @@ struct
 
   let is_null = function
     | Loc l -> M.is_null l
+    | Val ((CTXT Nullable|CARR Nullable)as m,x,ofs) ->
+        M.is_null (mloc_of_path m x ofs)
     | Ref _ | Val _ -> F.p_false
 
   let rec offset = function
@@ -831,7 +866,7 @@ struct
   exception ShiftMismatch
 
   let is_heap_allocated = function
-    | CREF | CVAL -> false | HEAP | CTXT | CARR -> true
+    | CREF | CVAL -> false | HEAP | CTXT _ | CARR _ -> true
 
   let shift_mismatch l =
     Wp_parameters.fatal "Invalid shift : %a" pretty l
@@ -939,7 +974,9 @@ struct
     else
       match mem with
       | CVAL | HEAP -> p_bool (ALLOC.value sigma.alloc x)
-      | CREF | CTXT | CARR -> p_true
+      | CREF | CTXT Valid | CARR Valid -> p_true
+      | CTXT Nullable | CARR Nullable ->
+          p_not @@ M.is_null (mloc_of_path mem x [])
 
   (* segment *)
 
@@ -1181,7 +1218,7 @@ struct
 
   let is_mvar_alloc x =
     match V.param x with
-    | ByRef | InContext | InArray | NotUsed -> false
+    | ByRef | InContext _ | InArray _ | NotUsed -> false
     | ByValue | ByShift | ByAddr -> true
 
   let alloc sigma xs =
@@ -1221,6 +1258,17 @@ struct
         in
         List.map uninitialized xs
 
+  let is_nullable m v =
+    let addr = nullable_address v in
+    p_or
+      (M.is_null @@ M.pointer_loc addr)
+      (p_equal (M.pointer_val @@ M.cvar (vbase m v)) addr)
+
+  let nullable_scope v =
+    match V.param v with
+    | InContext Nullable -> Some (is_nullable (CTXT Nullable) v)
+    | InArray Nullable -> Some (is_nullable (CARR Nullable) v)
+    | _ -> None
 
   let scope seq scope xs =
     let xm = List.filter is_mem xs in
@@ -1228,7 +1276,8 @@ struct
     let hmem = M.scope smem scope xm in
     let hvars = scope_vars seq scope xs in
     let hinit = scope_init seq scope xs in
-    hvars @ hinit @ hmem
+    let hcontext = List.filter_map nullable_scope xs in
+    hvars @ hinit @ hmem @ hcontext
 
   let global sigma p = M.global sigma.mem p
 
@@ -1365,7 +1414,7 @@ struct
     | Val((CVAL|CREF),_,_) as vloc ->
         let v = Lang.freshvar ~basename:"v" (Lang.tau_of_object obj) in
         memvar_assigned seq obj vloc (e_var v)
-    | Val((HEAP|CTXT|CARR) as m,x,ofs) ->
+    | Val((HEAP|CTXT _|CARR _) as m,x,ofs) ->
         M.assigned (mseq_of_seq seq) obj (Sloc (mloc_of_path m x ofs))
     | Loc l ->
         M.assigned (mseq_of_seq seq) obj (Sloc l)
@@ -1387,7 +1436,7 @@ struct
         in
         let obj = get_obj (Ctypes.object_of x.vtype) ofs in
         memvar_assigned seq obj vloc (e_var v)
-    | Val((HEAP|CTXT|CARR) as m,x,ofs) ->
+    | Val((HEAP|CTXT _|CARR _) as m,x,ofs) ->
         let l = mloc_of_path m x ofs in
         M.assigned (mseq_of_seq seq) obj (Sarray(l,elt,n))
     | Loc l ->
@@ -1398,7 +1447,7 @@ struct
     | Ref x -> noref ~op:"assigns to" x
     | Loc l ->
         M.assigned (mseq_of_seq seq) obj (Srange(l,elt,a,b))
-    | Val((HEAP|CTXT|CARR) as m,x,ofs) ->
+    | Val((HEAP|CTXT _|CARR _) as m,x,ofs) ->
         M.assigned (mseq_of_seq seq) obj (Srange(mloc_of_path m x ofs,elt,a,b))
     | Val((CVAL|CREF) as m,x,ofs) ->
         let k = Lang.freshvar ~basename:"k" Qed.Logic.Int in
@@ -1412,7 +1461,7 @@ struct
     | Ref x -> noref ~op:"assigns to" x
     | Loc l ->
         M.assigned (mseq_of_seq seq) obj (Sdescr(xs,l,p))
-    | Val((HEAP|CTXT|CARR) as m,x,ofs) ->
+    | Val((HEAP|CTXT _|CARR _) as m,x,ofs) ->
         M.assigned (mseq_of_seq seq) obj (Sdescr(xs,mloc_of_path m x ofs,p))
     | Val((CVAL|CREF) as m,x,ofs) ->
         (* (monotonic_initialized_genset seq xs m x ofs p) @ *)
@@ -1481,10 +1530,16 @@ struct
     | Rrange(Val((CVAL|CREF),x,ofs),obj,a,b) ->
         Fseg(x,range ofs obj a b)
 
-    (* in M: *)
-    | Rloc(obj,Val((CTXT|CARR|HEAP) as m,x,ofs)) ->
+    (* Nullable: force M without symbolic access *)
+    | Rloc(obj,Val((CTXT Nullable|CARR Nullable) as m,x,ofs)) ->
+        Lseg(Rloc(obj, mloc_of_path m x ofs))
+    | Rrange(Val((CTXT Nullable|CARR Nullable) as m,x,ofs),obj,a,b) ->
+        Lseg(Rrange(mloc_of_path m x ofs, obj, a, b))
+
+    (* Otherwise: use M with symbolic access *)
+    | Rloc(obj,Val((CTXT Valid|CARR Valid|HEAP) as m,x,ofs)) ->
         Mseg(Rloc(obj,mloc_of_path m x ofs),x,delta obj x ofs)
-    | Rrange(Val((CTXT|CARR|HEAP) as m,x,ofs),obj,a,b) ->
+    | Rrange(Val((CTXT Valid|CARR Valid|HEAP) as m,x,ofs),obj,a,b) ->
         Mseg(Rrange(mloc_of_path m x ofs,obj,a,b),x,range ofs obj a b)
 
   (* -------------------------------------------------------------------------- *)
@@ -1559,7 +1614,7 @@ struct
           else []
         in
         Heap.Set.of_list ((Var x) :: init)
-    | Loc _ | Val((CTXT|CARR|HEAP),_,_) ->
+    | Loc _ | Val((CTXT _|CARR _|HEAP),_,_) ->
         M.Heap.Set.fold
           (fun m s -> Heap.Set.add (Mem m) s)
           (M.domain obj (mloc_of_loc l)) Heap.Set.empty
diff --git a/src/plugins/wp/MemoryContext.ml b/src/plugins/wp/MemoryContext.ml
index e337a19633147beae582c55553e6e252bbd5da89..1b1066105cb0354d9d327f72617a2a2d9b911fbf 100644
--- a/src/plugins/wp/MemoryContext.ml
+++ b/src/plugins/wp/MemoryContext.ml
@@ -24,16 +24,23 @@
 (* --- Variable Partitionning                                             --- *)
 (* -------------------------------------------------------------------------- *)
 
-type param = NotUsed | ByAddr | ByValue | ByShift | ByRef | InContext | InArray
+type validity = Valid | Nullable
+type param =
+  | NotUsed | ByAddr | ByValue | ByShift | ByRef
+  | InContext of validity | InArray of validity
+
+let pp_nullable fmt = function
+  | Valid -> ()
+  | Nullable -> Format.pp_print_string fmt " (nullable)"
 
 let pp_param fmt = function
   | NotUsed -> Format.pp_print_string fmt "not used"
   | ByAddr -> Format.pp_print_string fmt "in heap"
   | ByValue -> Format.pp_print_string fmt "by value"
   | ByShift -> Format.pp_print_string fmt "by value with shift"
-  | ByRef -> Format.pp_print_string fmt "by ref."
-  | InContext -> Format.pp_print_string fmt "in context"
-  | InArray -> Format.pp_print_string fmt "in array"
+  | ByRef -> Format.pp_print_string fmt "by ref"
+  | InContext n -> Format.fprintf fmt "in context%a" pp_nullable n
+  | InArray n -> Format.fprintf fmt "in array%a" pp_nullable n
 
 (* -------------------------------------------------------------------------- *)
 (* --- Separation Hypotheses                                              --- *)
@@ -47,10 +54,11 @@ type zone =
   | Arr of varinfo   (* p+(..) - the cell and its neighbors pointed by p *)
 
 type partition = {
-  globals : zone list ; (* [ &G , G[...], ... ] *)
-  to_heap : zone list ; (* [ p, ... ] *)
-  context : zone list ; (* [ p+(..), ... ] *)
-  by_addr : zone list ; (* [ &(x + ..), ... ] *)
+  globals : zone list ;  (* [ &G , G[...], ... ] *)
+  to_heap : zone list ;  (* [ p, ... ] *)
+  context : zone list ;  (* [ p+(..), ... ] *)
+  nullable : zone list ; (* [ p+(..), ... ] but can be NULL *)
+  by_addr : zone list ;  (* [ &(x + ..), ... ] *)
 }
 
 (* -------------------------------------------------------------------------- *)
@@ -60,6 +68,7 @@ type partition = {
 let empty = {
   globals = [] ;
   context = [] ;
+  nullable = [] ;
   to_heap = [] ;
   by_addr = [] ;
 }
@@ -68,12 +77,21 @@ let set x p w =
   match p with
   | NotUsed -> w
   | ByAddr -> { w with by_addr = Var x :: w.by_addr }
-  | ByRef | InContext ->
+  | ByRef ->
       if Cil.isFunctionType x.vtype then w else
         { w with context = Ptr x :: w.context }
-  | InArray ->
+  | InContext v ->
+      if Cil.isFunctionType x.vtype then w else
+        begin match v with
+          | Nullable -> { w with nullable = Ptr x :: w.nullable }
+          | Valid -> { w with context = Ptr x :: w.context }
+        end
+  | InArray v ->
       if Cil.isFunctionType x.vtype then w else
-        { w with context = Arr x :: w.context }
+        begin match v with
+          | Nullable -> { w with nullable = Arr x :: w.nullable }
+          | Valid -> { w with context = Arr x :: w.context }
+        end
   | ByValue | ByShift ->
       if x.vghost then w else
       if Cil.isFunctionType x.vtype then w else
@@ -187,9 +205,25 @@ let valid_region loc r =
   let t = region_to_term loc r in
   pvalid ~loc (here_label, t)
 
-let simplify ps =
-  List.sort_uniq Logic_utils.compare_predicate
-    (List.filter (fun p -> not(Logic_utils.is_trivially_true p)) ps)
+let valid_or_null_region loc r =
+  let t = region_to_term loc r in
+  let null = term ~loc Tnull t.term_type in
+  por (valid_region loc r, prel ~loc (Req, t, null))
+
+let rec rank p = match p.pred_content with
+  | Pvalid _ -> 1
+  | Pseparated _ -> 2
+  | Pimplies(_,p) -> rank p
+  | Por(p,q) | Pand(p,q) -> max (rank p) (rank q)
+  | _ -> 0
+
+let compare p q =
+  let r = rank p - rank q in
+  if r <> 0 then r else Logic_utils.compare_predicate p q
+
+let normalize ps =
+  List.sort_uniq compare @@
+  List.filter (fun p -> not(Logic_utils.is_trivially_true p)) ps
 
 let ptrset { term_type = t } =
   let open Logic_typing in
@@ -221,6 +255,9 @@ let global_zones partition =
 let context_zones partition =
   List.map (fun z -> [z]) partition.context
 
+let nullable_zones partition =
+  List.map (fun z -> [z]) partition.nullable
+
 let heaps partition = welltyped partition.to_heap
 let addr_of_vars partition = welltyped partition.by_addr
 
@@ -229,20 +266,42 @@ let addr_of_vars partition = welltyped partition.by_addr
 (* -------------------------------------------------------------------------- *)
 
 (* Memory regions shall be separated with each others *)
-let main_separation loc globals context heaps =
-  match heaps, context with
-  | [], [] ->
-      (* In this case, separation is completely trivial *)
-      [ ptrue ]
-  | [], context ->
-      let zones = globals @ context in
-      [ separated_list ~loc (List.map (region_to_term loc) zones) ]
-  | heaps, context ->
-      let for_typed_heap h =
-        let zones = h :: globals @ context in
-        separated_list ~loc (List.map (region_to_term loc) zones)
+let main_separation loc globals context nullable heaps =
+  if context = [] && nullable = [] && heaps = [] then []
+  else
+    let l_zones = match heaps with
+      | [] -> [globals @ context]
+      | heaps -> List.map (fun h -> h :: (globals @ context)) heaps
+    in
+    let regions_to_terms = List.map (region_to_term loc) in
+    let guard_nullable tn sep =
+      pimplies ~loc (prel ~loc (Rneq, tn, term ~loc Tnull tn.term_type), sep)
+    in
+    let acc_with_nullable tn zones =
+      List.cons @@
+      guard_nullable tn (separated_list ~loc (tn :: regions_to_terms zones))
+    in
+    let no_nullable zones = separated_list ~loc @@ regions_to_terms zones in
+    let nullable_inter nullable =
+      let separated_nullable (p, q) =
+        guard_nullable p @@ guard_nullable q @@ pseparated ~loc [ p ; q ]
       in
-      List.map for_typed_heap heaps
+      let rec collect_pairs = function
+        (* trivial cases *)
+        | [] -> [] | [_] -> []
+        | p :: l ->
+            let acc_sep q = List.cons @@ separated_nullable (p, q) in
+            List.fold_right acc_sep l @@ collect_pairs l
+      in
+      collect_pairs nullable
+    in
+    match nullable with
+    | [] -> List.map no_nullable l_zones
+    | nullable ->
+        let t_nullable = regions_to_terms nullable in
+        let sep_nullable = nullable_inter t_nullable in
+        let fold n = List.fold_right (acc_with_nullable n) l_zones in
+        List.fold_right fold t_nullable sep_nullable
 
 (* Filter assigns *)
 let assigned_locations kf filter =
@@ -301,12 +360,15 @@ let assigned_separation kf loc globals =
 (* Computes conditions from partition *)
 let clauses_of_partition kf loc p =
   let globals = global_zones p in
-  let main_sep = main_separation loc globals (context_zones p) (heaps p) in
+  let main_sep =
+    main_separation loc globals (context_zones p) (nullable_zones p) (heaps p)
+  in
   let assigns_sep_req, assigns_sep_ens = assigned_separation kf loc globals in
-  let context_validity = List.map (valid_region loc) (context_zones p) in
-  let reqs = main_sep @ assigns_sep_req @ context_validity in
-  let reqs = simplify reqs in
-  let ens = simplify assigns_sep_ens in
+  let context_valid = List.map (valid_region loc) (context_zones p) in
+  let nullable_valid = List.map (valid_or_null_region loc) (nullable_zones p) in
+  let reqs = main_sep @ assigns_sep_req @ context_valid @ nullable_valid in
+  let reqs = normalize reqs in
+  let ens = normalize assigns_sep_ens in
   reqs, ens
 
 (* Computes conditions from return *)
@@ -335,7 +397,7 @@ let out_pointers_separation kf loc p =
     let globals = global_zones p in
     List.map (fun t -> term_separated_from_regions loc t globals) asgnd_ptrs
   in
-  simplify (formals_separation @ globals_separation)
+  normalize (formals_separation @ globals_separation)
 
 (* Computes all conditions from behavior *)
 let compute_behavior kf name hypotheses_computer =
diff --git a/src/plugins/wp/MemoryContext.mli b/src/plugins/wp/MemoryContext.mli
index c0698fa9ea1d38761283b3d675fb82ca29cc1375..9cf4ea56bfc5f17b74a9b9b6d94ba2bbb878ac8e 100644
--- a/src/plugins/wp/MemoryContext.mli
+++ b/src/plugins/wp/MemoryContext.mli
@@ -22,7 +22,9 @@
 
 open Cil_types
 
-type param = NotUsed | ByAddr | ByValue | ByShift | ByRef | InContext | InArray
+type validity = Valid | Nullable
+type param = NotUsed | ByAddr | ByValue | ByShift | ByRef
+           | InContext of validity | InArray of validity
 
 val pp_param: Format.formatter -> param -> unit
 
diff --git a/src/plugins/wp/RefUsage.ml b/src/plugins/wp/RefUsage.ml
index 4413187be9efce693afa69a5795f59bdbcb68288..7e485e323bef5d461e2985706f00e47022059611 100644
--- a/src/plugins/wp/RefUsage.ml
+++ b/src/plugins/wp/RefUsage.ml
@@ -827,6 +827,61 @@ module S = State_builder.Option_ref(D)
 let usage () = S.memo compute_usage
 let is_computed () = S.is_computed ()
 
+(* ---------------------------------------------------------------------- *)
+(* --- Nullable variables                                             --- *)
+(* ---------------------------------------------------------------------- *)
+
+module Nullable =
+struct
+  let attribute_name = "wp_nullable"
+
+  let is_nullable vi =
+    vi.vformal && Cil.hasAttribute attribute_name vi.vattr
+
+  let make_nullable vi =
+    vi.vattr <- Cil.addAttribute (AttrAnnot attribute_name) vi.vattr
+
+  module Nullable_extension =
+  struct
+    let type_term typing_context loc e =
+      match e.Logic_ptree.lexpr_node with
+      | Logic_ptree.PLvar s ->
+          let lv = typing_context.Logic_typing.find_var s in
+          begin match lv.lv_origin with
+            | Some vi when Cil.isPointerType vi.vtype && vi.vformal ->
+                make_nullable vi ;
+                Logic_const.tvar ~loc lv
+            | _ ->
+                typing_context.error loc "No pointer: %s" s
+          end
+      | _  ->
+          typing_context.error loc "Illegal expression %a"
+            Logic_print.print_lexpr e
+
+    let typer typing_context loc l =
+      Ext_terms (List.map (type_term typing_context loc) l)
+  end
+
+  let () =
+    Acsl_extension.register_behavior
+      "wp_nullable_args" Nullable_extension.typer false
+
+  module HasNullable =
+    State_builder.Option_ref(Datatype.Bool)
+      (struct
+        let name = "Wp.RefUsage.HasNullable"
+        let dependencies = [Ast.self]
+      end)
+
+  let compute_nullable () =
+    let module F = Globals.Functions in
+    F.fold (fun f b ->
+        b || List.fold_left (fun b v -> b || is_nullable v) b (F.get_params f)
+      ) false
+
+  let has_nullable () = HasNullable.memo compute_nullable
+end
+
 (* ---------------------------------------------------------------------- *)
 (* --- API                                                            --- *)
 (* ---------------------------------------------------------------------- *)
@@ -854,6 +909,9 @@ let get ?kf ?(init=false) vi =
 
 let compute () = ignore (usage ())
 
+let is_nullable = Nullable.is_nullable
+let has_nullable = Nullable.has_nullable
+
 let print x m fmt = Access.pretty x fmt m
 
 let dump () =
diff --git a/src/plugins/wp/RefUsage.mli b/src/plugins/wp/RefUsage.mli
index 988103efebfd6817de6320945e69f06d9194cc12..2290ad05f69084646ce2514260e4cb88db7ec965 100644
--- a/src/plugins/wp/RefUsage.mli
+++ b/src/plugins/wp/RefUsage.mli
@@ -38,6 +38,14 @@ val get : ?kf:kernel_function -> ?init:bool -> varinfo -> access
 
 val iter: ?kf:kernel_function -> ?init:bool -> (varinfo -> access -> unit) -> unit
 
+val is_nullable : varinfo -> bool
+(** [is_nullable vi] returns true
+    iff [vi] is a formal and has an attribute 'nullable' *)
+
+val has_nullable : unit -> bool
+(** [has_nullable ()] return true
+    iff there exists a variable that satisfies [is_nullable] *)
+
 val print : varinfo -> access -> Format.formatter -> unit
 val dump : unit -> unit
 val compute : unit -> unit
diff --git a/src/plugins/wp/doc/manual/nullable.c b/src/plugins/wp/doc/manual/nullable.c
new file mode 100644
index 0000000000000000000000000000000000000000..9b403ffe91cb9148bcff3b461de90cec89c09cb1
--- /dev/null
+++ b/src/plugins/wp/doc/manual/nullable.c
@@ -0,0 +1,9 @@
+void foo(int* p /*@ wp_nullable */, int* q /*@ wp_nullable */){
+
+}
+
+// or equivalently:
+//@ wp_nullable_args p, q ;
+void foo(int* p, int* q){
+
+}
diff --git a/src/plugins/wp/doc/manual/wp_caveat.tex b/src/plugins/wp/doc/manual/wp_caveat.tex
index 6e7afa77c066bb52273da98252d093d08b6980f3..4a49fd03c2be8622dc6700db76484395853348bf 100644
--- a/src/plugins/wp/doc/manual/wp_caveat.tex
+++ b/src/plugins/wp/doc/manual/wp_caveat.tex
@@ -21,7 +21,14 @@ global ones).
 
 Additionally, the \texttt{Caveat} memory model of \textsf{Frama-C}
 performs a local allocation of formal parameters with pointer
-types that cannot be treated as \textit{reference parameters}. 
+types that cannot be treated as \textit{reference parameters}.
+Note that it means that the pointer is considered valid. If one needs
+to accept \texttt{NULL} for this pointer, a \texttt{wp\_nullable} ghost
+annotation or the clause \texttt{wp\_nullage\_args} can be used to bring
+this information to WP:
+
+\listingname{nullable.c}
+\cinput{nullable.c}
 
 This makes explicit the separation hypothesis of memory regions
 pointed by formals in the \textsf{Caveat} tool. The major benefit of
@@ -29,7 +36,7 @@ the \textsf{WP} version is that aliases are taken into account by the
 \texttt{Typed} memory model, hence, there are no more suspicious
 \textit{aliasing} warnings.
 
-\paragraph{Warning:} using the \texttt{Caveat} memory model, 
+\paragraph{Warning:} using the \texttt{Caveat} memory model,
 the user \emph{must} check by manual code review that no aliases are
 introduced \emph{via} pointers passed to formal parameters at call sites.
 
diff --git a/src/plugins/wp/tests/wp_bts/oracle/bts_1828.1.res.oracle b/src/plugins/wp/tests/wp_bts/oracle/bts_1828.1.res.oracle
index 1f183b1d30a1530c5c404f9a38f7ed12fec5d9ff..9c383998a35a6db6956fd0e37c775bc07059fa59 100644
--- a/src/plugins/wp/tests/wp_bts/oracle/bts_1828.1.res.oracle
+++ b/src/plugins/wp/tests/wp_bts/oracle/bts_1828.1.res.oracle
@@ -48,8 +48,8 @@ Prove: global(L_two_24) != one_0.
   Memory model hypotheses for function 'global_frame':
   /*@
      behavior wp_typed_ref:
-       requires \separated(zero, one);
        requires \valid(one);
        requires \valid(zero);
+       requires \separated(zero, one);
      */
   void global_frame(int *one, int arg);
diff --git a/src/plugins/wp/tests/wp_bts/oracle_qualif/bts_1828.1.res.oracle b/src/plugins/wp/tests/wp_bts/oracle_qualif/bts_1828.1.res.oracle
index 43305903b452ccabf5e96e46b022d2bfe3c1ffce..e9a2a01d9a210f37acaaa53be63d723f7baf2541 100644
--- a/src/plugins/wp/tests/wp_bts/oracle_qualif/bts_1828.1.res.oracle
+++ b/src/plugins/wp/tests/wp_bts/oracle_qualif/bts_1828.1.res.oracle
@@ -21,8 +21,8 @@
   Memory model hypotheses for function 'global_frame':
   /*@
      behavior wp_typed_ref:
-       requires \separated(zero, one);
        requires \valid(one);
        requires \valid(zero);
+       requires \separated(zero, one);
      */
   void global_frame(int *one, int arg);
diff --git a/src/plugins/wp/tests/wp_gallery/oracle/frama_c_exo3_solved.old.res.oracle b/src/plugins/wp/tests/wp_gallery/oracle/frama_c_exo3_solved.old.res.oracle
index 56bb306558b56d74141556fc1b026d735ef9cfe9..5508bc1831913be6943b2cc4f680f7b4d23fcbd7 100644
--- a/src/plugins/wp/tests/wp_gallery/oracle/frama_c_exo3_solved.old.res.oracle
+++ b/src/plugins/wp/tests/wp_gallery/oracle/frama_c_exo3_solved.old.res.oracle
@@ -56,8 +56,8 @@
   Memory model hypotheses for function 'equal_elements':
   /*@
      behavior wp_typed_ref:
-       requires \separated(v1, v2, a + (..));
        requires \valid(v1);
        requires \valid(v2);
+       requires \separated(v1, v2, a + (..));
      */
   void equal_elements(int *a, int *v1, int *v2);
diff --git a/src/plugins/wp/tests/wp_gallery/oracle/frama_c_exo3_solved.old.v2.res.oracle b/src/plugins/wp/tests/wp_gallery/oracle/frama_c_exo3_solved.old.v2.res.oracle
index 53078f53cb88bbc0681c1ce463aef6b08bf1de0e..87430ad4b3c1a897ffe57842d2ad079a105b7649 100644
--- a/src/plugins/wp/tests/wp_gallery/oracle/frama_c_exo3_solved.old.v2.res.oracle
+++ b/src/plugins/wp/tests/wp_gallery/oracle/frama_c_exo3_solved.old.v2.res.oracle
@@ -57,8 +57,8 @@
   Memory model hypotheses for function 'equal_elements':
   /*@
      behavior wp_typed_ref:
-       requires \separated(v1, v2, a + (..));
        requires \valid(v1);
        requires \valid(v2);
+       requires \separated(v1, v2, a + (..));
      */
   void equal_elements(int *a, int *v1, int *v2);
diff --git a/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_exo3_solved.old.res.oracle b/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_exo3_solved.old.res.oracle
index 3903ba3a3a32a691f6e6e2bce73a83b71362f378..174cfa7521504fd213dc75ca4404ea89dddb4faa 100644
--- a/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_exo3_solved.old.res.oracle
+++ b/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_exo3_solved.old.res.oracle
@@ -48,9 +48,9 @@
   Memory model hypotheses for function 'equal_elements':
   /*@
      behavior wp_typed_ref:
-       requires \separated(v1, v2, a + (..));
        requires \valid(v1);
        requires \valid(v2);
+       requires \separated(v1, v2, a + (..));
      */
   void equal_elements(int *a, int *v1, int *v2);
 [wp] Running WP plugin...
diff --git a/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_exo3_solved.old.v2.res.oracle b/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_exo3_solved.old.v2.res.oracle
index 1dfeafb91d559189ced438c76169d59f9f36c303..cfbc31146758fcdad382bd59ca15be2c53d18327 100644
--- a/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_exo3_solved.old.v2.res.oracle
+++ b/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_exo3_solved.old.v2.res.oracle
@@ -49,9 +49,9 @@
   Memory model hypotheses for function 'equal_elements':
   /*@
      behavior wp_typed_ref:
-       requires \separated(v1, v2, a + (..));
        requires \valid(v1);
        requires \valid(v2);
+       requires \separated(v1, v2, a + (..));
      */
   void equal_elements(int *a, int *v1, int *v2);
 [wp] Running WP plugin...
diff --git a/src/plugins/wp/tests/wp_hoare/oracle/dispatch_var.res.oracle b/src/plugins/wp/tests/wp_hoare/oracle/dispatch_var.res.oracle
index 03056370c4a6760b6e4e1e2f3662a4c7bf5753a0..30d6f05c1f7c75c51330593d503e43a92237da15 100644
--- a/src/plugins/wp/tests/wp_hoare/oracle/dispatch_var.res.oracle
+++ b/src/plugins/wp/tests/wp_hoare/oracle/dispatch_var.res.oracle
@@ -515,10 +515,10 @@ Prove: true.
   Memory model hypotheses for function 'ref_ctr_nr':
   /*@
      behavior wp_typed_ref:
-       requires \separated(ref, ref1, ref2);
        requires \valid(ref);
        requires \valid(ref1);
        requires \valid(ref2);
+       requires \separated(ref, ref1, ref2);
      */
   int ref_ctr_nr(int *ref, int *ref1, int *ref2);
 [wp] tests/wp_hoare/dispatch_var.i:158: Warning: 
diff --git a/src/plugins/wp/tests/wp_hoare/oracle/memory_hypotheses_checking.res.oracle b/src/plugins/wp/tests/wp_hoare/oracle/memory_hypotheses_checking.res.oracle
index 380a7e0cc8ace27dc70721782cf090990ab2631b..142b8eba2461dd41529943de1b117ebcb619649d 100644
--- a/src/plugins/wp/tests/wp_hoare/oracle/memory_hypotheses_checking.res.oracle
+++ b/src/plugins/wp/tests/wp_hoare/oracle/memory_hypotheses_checking.res.oracle
@@ -142,13 +142,13 @@ Prove: true.
 
 Goal Instance of 'Pre-condition for 'wp_typed_ref' (file tests/wp_hoare/memory_hypotheses_checking.i, line 58) in 'assigns_ptr'' in 'call_assigns_ptr_bad' at call 'assigns_ptr' (file tests/wp_hoare/memory_hypotheses_checking.i, line 70)
 :
-Prove: false.
+Prove: true.
 
 ------------------------------------------------------------
 
 Goal Instance of 'Pre-condition for 'wp_typed_ref' (file tests/wp_hoare/memory_hypotheses_checking.i, line 58) in 'assigns_ptr'' in 'call_assigns_ptr_bad' at call 'assigns_ptr' (file tests/wp_hoare/memory_hypotheses_checking.i, line 70)
 :
-Prove: true.
+Prove: false.
 
 ------------------------------------------------------------
 ------------------------------------------------------------
@@ -194,14 +194,14 @@ Prove: true.
 
 Goal Instance of 'Pre-condition for 'wp_typed_ref' (file tests/wp_hoare/memory_hypotheses_checking.i, line 39) in 'gptr_sep'' in 'call_gptr_sep_bad' at call 'gptr_sep' (file tests/wp_hoare/memory_hypotheses_checking.i, line 53)
 :
-Prove: false.
+Assume { (* Heap *) Type: linked(Malloc_0). }
+Prove: valid_rw(Malloc_0, global(G_g_20), 1).
 
 ------------------------------------------------------------
 
 Goal Instance of 'Pre-condition for 'wp_typed_ref' (file tests/wp_hoare/memory_hypotheses_checking.i, line 39) in 'gptr_sep'' in 'call_gptr_sep_bad' at call 'gptr_sep' (file tests/wp_hoare/memory_hypotheses_checking.i, line 53)
 :
-Assume { (* Heap *) Type: linked(Malloc_0). }
-Prove: valid_rw(Malloc_0, global(G_g_20), 1).
+Prove: false.
 
 ------------------------------------------------------------
 ------------------------------------------------------------
@@ -220,14 +220,14 @@ Prove: true.
 
 Goal Instance of 'Pre-condition for 'wp_typed_ref' (file tests/wp_hoare/memory_hypotheses_checking.i, line 39) in 'gptr_sep'' in 'call_gptr_sep_ok' at call 'gptr_sep' (file tests/wp_hoare/memory_hypotheses_checking.i, line 47)
 :
-Prove: true.
+Assume { (* Heap *) Type: linked(Malloc_0). }
+Prove: valid_rw(Malloc_0[L_l_46 <- 1], global(L_l_46), 1).
 
 ------------------------------------------------------------
 
 Goal Instance of 'Pre-condition for 'wp_typed_ref' (file tests/wp_hoare/memory_hypotheses_checking.i, line 39) in 'gptr_sep'' in 'call_gptr_sep_ok' at call 'gptr_sep' (file tests/wp_hoare/memory_hypotheses_checking.i, line 47)
 :
-Assume { (* Heap *) Type: linked(Malloc_0). }
-Prove: valid_rw(Malloc_0[L_l_46 <- 1], global(L_l_46), 1).
+Prove: true.
 
 ------------------------------------------------------------
 ------------------------------------------------------------
@@ -246,13 +246,13 @@ Prove: true.
 
 Goal Instance of 'Pre-condition for 'wp_typed_ref' (file tests/wp_hoare/memory_hypotheses_checking.i, line 12) in 'sep'' in 'call_sep_bad_sep' at call 'sep' (file tests/wp_hoare/memory_hypotheses_checking.i, line 24)
 :
-Prove: false.
+Prove: true.
 
 ------------------------------------------------------------
 
 Goal Instance of 'Pre-condition for 'wp_typed_ref' (file tests/wp_hoare/memory_hypotheses_checking.i, line 12) in 'sep'' in 'call_sep_bad_sep' at call 'sep' (file tests/wp_hoare/memory_hypotheses_checking.i, line 24)
 :
-Prove: true.
+Prove: false.
 
 ------------------------------------------------------------
 ------------------------------------------------------------
@@ -283,14 +283,14 @@ Prove: true.
 
 Goal Instance of 'Pre-condition for 'wp_typed_ref' (file tests/wp_hoare/memory_hypotheses_checking.i, line 12) in 'sep'' in 'call_sep_bad_valid' at call 'sep' (file tests/wp_hoare/memory_hypotheses_checking.i, line 34)
 :
-Prove: true.
+Assume { (* Heap *) Type: linked(Malloc_0). }
+Prove: valid_rw(Malloc_0[L_l_37 <- 0], global(L_l_37), 1).
 
 ------------------------------------------------------------
 
 Goal Instance of 'Pre-condition for 'wp_typed_ref' (file tests/wp_hoare/memory_hypotheses_checking.i, line 12) in 'sep'' in 'call_sep_bad_valid' at call 'sep' (file tests/wp_hoare/memory_hypotheses_checking.i, line 34)
 :
-Assume { (* Heap *) Type: linked(Malloc_0). }
-Prove: valid_rw(Malloc_0[L_l_37 <- 0], global(L_l_37), 1).
+Prove: true.
 
 ------------------------------------------------------------
 ------------------------------------------------------------
@@ -341,8 +341,8 @@ int g;
 /*@ assigns \nothing;
     
     behavior wp_typed_ref:
-      requires \separated(p_0, &g);
       requires \valid(p_0);
+      requires \separated(p_0, &g);
  */
 int sep(int *p_0)
 {
@@ -382,8 +382,8 @@ int *p;
 /*@ assigns \nothing;
     
     behavior wp_typed_ref:
-      requires \separated(p, &g);
       requires \valid(p);
+      requires \separated(p, &g);
  */
 int gptr_sep(void)
 {
@@ -414,8 +414,8 @@ void call_gptr_sep_bad(void)
 /*@ assigns *p_0;
     
     behavior wp_typed_ref:
-      requires \separated(p_0, &g);
       requires \valid(p_0);
+      requires \separated(p_0, &g);
  */
 void assigns_ptr(int *p_0)
 {
diff --git a/src/plugins/wp/tests/wp_hoare/oracle/reference.res.oracle b/src/plugins/wp/tests/wp_hoare/oracle/reference.res.oracle
index bf4453996e1f0c3f7c0390b232a6c5e86e4608d0..3d3946ce97f51a2657303d810fb22191ebf65aec 100644
--- a/src/plugins/wp/tests/wp_hoare/oracle/reference.res.oracle
+++ b/src/plugins/wp/tests/wp_hoare/oracle/reference.res.oracle
@@ -150,9 +150,9 @@ Prove: true.
   Memory model hypotheses for function 'f2':
   /*@
      behavior wp_typed_ref:
-       requires \separated(p2, q);
        requires \valid(p2);
        requires \valid(q);
+       requires \separated(p2, q);
      */
   int f2(int *p2, int *q);
 [wp] tests/wp_hoare/reference.i:37: Warning: 
diff --git a/src/plugins/wp/tests/wp_hoare/oracle/refguards.res.oracle b/src/plugins/wp/tests/wp_hoare/oracle/refguards.res.oracle
index b99e101310280266d0fc3cf756af8bf32fabd5d8..535d8556ba56a0e495dfbb31d6796d3bee7b3636 100644
--- a/src/plugins/wp/tests/wp_hoare/oracle/refguards.res.oracle
+++ b/src/plugins/wp/tests/wp_hoare/oracle/refguards.res.oracle
@@ -72,26 +72,26 @@ Prove: d != c.
   Memory model hypotheses for function 'f':
   /*@
      behavior wp_typed_ref:
-       requires \separated(c, d, {a + (..), b + (..)});
        requires \valid(c);
        requires \valid(d);
+       requires \separated(c, d, {a + (..), b + (..)});
      */
   void f(int *a, int *b, int *c, int *d, int k);
 [wp] tests/wp_hoare/refguards.i:25: Warning: 
   Memory model hypotheses for function 'h':
   /*@
      behavior wp_typed_ref:
-       requires \separated(c, d);
        requires \valid(c);
        requires \valid(d);
+       requires \separated(c, d);
      */
   void h(int *c, int *d, int k);
 [wp] tests/wp_hoare/refguards.i:39: Warning: 
   Memory model hypotheses for function 's':
   /*@
      behavior wp_typed_ref:
-       requires \separated(c, d);
        requires \valid(c);
        requires \valid(d);
+       requires \separated(c, d);
      */
   void s(int **c, int **d, int k);
diff --git a/src/plugins/wp/tests/wp_hoare/oracle_qualif/dispatch_var.res.oracle b/src/plugins/wp/tests/wp_hoare/oracle_qualif/dispatch_var.res.oracle
index ab588be9a5c14dfaecd979bc01834341e6c05cef..66bc5879f093902b5614de36af3cbf81025e4f34 100644
--- a/src/plugins/wp/tests/wp_hoare/oracle_qualif/dispatch_var.res.oracle
+++ b/src/plugins/wp/tests/wp_hoare/oracle_qualif/dispatch_var.res.oracle
@@ -118,10 +118,10 @@
   Memory model hypotheses for function 'ref_ctr_nr':
   /*@
      behavior wp_typed_ref:
-       requires \separated(ref, ref1, ref2);
        requires \valid(ref);
        requires \valid(ref1);
        requires \valid(ref2);
+       requires \separated(ref, ref1, ref2);
      */
   int ref_ctr_nr(int *ref, int *ref1, int *ref2);
 [wp] tests/wp_hoare/dispatch_var.i:158: Warning: 
diff --git a/src/plugins/wp/tests/wp_hoare/oracle_qualif/memory_hypotheses_checking.res.oracle b/src/plugins/wp/tests/wp_hoare/oracle_qualif/memory_hypotheses_checking.res.oracle
index 6a5957ad9bc912905cd60d35a230bb32192e39ea..da1d58667029622f44e24d74f24031b12720acb4 100644
--- a/src/plugins/wp/tests/wp_hoare/oracle_qualif/memory_hypotheses_checking.res.oracle
+++ b/src/plugins/wp/tests/wp_hoare/oracle_qualif/memory_hypotheses_checking.res.oracle
@@ -10,23 +10,23 @@
 [wp] [Qed] Goal typed_ref_call_sep_ok_call_sep_wp_typed_ref_requires_2 : Valid
 [wp] [Qed] Goal typed_ref_call_sep_bad_sep_assigns_exit : Valid
 [wp] [Qed] Goal typed_ref_call_sep_bad_sep_assigns_normal : Valid
-[wp] [Alt-Ergo] Goal typed_ref_call_sep_bad_sep_call_sep_wp_typed_ref_requires : Unsuccess
-[wp] [Qed] Goal typed_ref_call_sep_bad_sep_call_sep_wp_typed_ref_requires_2 : Valid
+[wp] [Qed] Goal typed_ref_call_sep_bad_sep_call_sep_wp_typed_ref_requires : Valid
+[wp] [Alt-Ergo] Goal typed_ref_call_sep_bad_sep_call_sep_wp_typed_ref_requires_2 : Unsuccess
 [wp] [Qed] Goal typed_ref_call_sep_bad_valid_assigns_exit_part1 : Valid
 [wp] [Qed] Goal typed_ref_call_sep_bad_valid_assigns_exit_part2 : Valid
 [wp] [Qed] Goal typed_ref_call_sep_bad_valid_assigns_normal_part1 : Valid
 [wp] [Qed] Goal typed_ref_call_sep_bad_valid_assigns_normal_part2 : Valid
-[wp] [Qed] Goal typed_ref_call_sep_bad_valid_call_sep_wp_typed_ref_requires : Valid
-[wp] [Alt-Ergo] Goal typed_ref_call_sep_bad_valid_call_sep_wp_typed_ref_requires_2 : Unsuccess
+[wp] [Alt-Ergo] Goal typed_ref_call_sep_bad_valid_call_sep_wp_typed_ref_requires : Unsuccess
+[wp] [Qed] Goal typed_ref_call_sep_bad_valid_call_sep_wp_typed_ref_requires_2 : Valid
 [wp] [Qed] Goal typed_ref_gptr_sep_assigns : Valid
 [wp] [Qed] Goal typed_ref_call_gptr_sep_ok_assigns_exit : Valid
 [wp] [Qed] Goal typed_ref_call_gptr_sep_ok_assigns_normal : Valid
-[wp] [Qed] Goal typed_ref_call_gptr_sep_ok_call_gptr_sep_wp_typed_ref_requires : Valid
-[wp] [Alt-Ergo] Goal typed_ref_call_gptr_sep_ok_call_gptr_sep_wp_typed_ref_requires_2 : Valid
+[wp] [Alt-Ergo] Goal typed_ref_call_gptr_sep_ok_call_gptr_sep_wp_typed_ref_requires : Valid
+[wp] [Qed] Goal typed_ref_call_gptr_sep_ok_call_gptr_sep_wp_typed_ref_requires_2 : Valid
 [wp] [Qed] Goal typed_ref_call_gptr_sep_bad_assigns_exit : Valid
 [wp] [Qed] Goal typed_ref_call_gptr_sep_bad_assigns_normal : Valid
-[wp] [Alt-Ergo] Goal typed_ref_call_gptr_sep_bad_call_gptr_sep_wp_typed_ref_requires : Unsuccess
-[wp] [Alt-Ergo] Goal typed_ref_call_gptr_sep_bad_call_gptr_sep_wp_typed_ref_requires_2 : Valid
+[wp] [Alt-Ergo] Goal typed_ref_call_gptr_sep_bad_call_gptr_sep_wp_typed_ref_requires : Valid
+[wp] [Alt-Ergo] Goal typed_ref_call_gptr_sep_bad_call_gptr_sep_wp_typed_ref_requires_2 : Unsuccess
 [wp] [Qed] Goal typed_ref_assigns_ptr_assigns : Valid
 [wp] [Qed] Goal typed_ref_call_assigns_ptr_ok_assigns_exit : Valid
 [wp] [Qed] Goal typed_ref_call_assigns_ptr_ok_assigns_normal : Valid
@@ -34,8 +34,8 @@
 [wp] [Qed] Goal typed_ref_call_assigns_ptr_ok_call_assigns_ptr_wp_typed_ref_requires_2 : Valid
 [wp] [Qed] Goal typed_ref_call_assigns_ptr_bad_assigns_exit : Valid
 [wp] [Qed] Goal typed_ref_call_assigns_ptr_bad_assigns_normal : Valid
-[wp] [Alt-Ergo] Goal typed_ref_call_assigns_ptr_bad_call_assigns_ptr_wp_typed_ref_requires : Unsuccess
-[wp] [Qed] Goal typed_ref_call_assigns_ptr_bad_call_assigns_ptr_wp_typed_ref_requires_2 : Valid
+[wp] [Qed] Goal typed_ref_call_assigns_ptr_bad_call_assigns_ptr_wp_typed_ref_requires : Valid
+[wp] [Alt-Ergo] Goal typed_ref_call_assigns_ptr_bad_call_assigns_ptr_wp_typed_ref_requires_2 : Unsuccess
 [wp] [Qed] Goal typed_ref_add_return_ok_ensures : Valid
 [wp] [Qed] Goal typed_ref_add_return_ok_assigns : Valid
 [wp] [Qed] Goal typed_ref_add_return_ok_wp_typed_ref_ensures : Valid
diff --git a/src/plugins/wp/tests/wp_hoare/oracle_qualif/reference.res.oracle b/src/plugins/wp/tests/wp_hoare/oracle_qualif/reference.res.oracle
index 6fa2c547d939685057c4e3ce840a76ab810eb7e8..c94049ea06d84693c16c54c4dc50a3e5083ea89c 100644
--- a/src/plugins/wp/tests/wp_hoare/oracle_qualif/reference.res.oracle
+++ b/src/plugins/wp/tests/wp_hoare/oracle_qualif/reference.res.oracle
@@ -45,9 +45,9 @@
   Memory model hypotheses for function 'f2':
   /*@
      behavior wp_typed_ref:
-       requires \separated(p2, q);
        requires \valid(p2);
        requires \valid(q);
+       requires \separated(p2, q);
      */
   int f2(int *p2, int *q);
 [wp] tests/wp_hoare/reference.i:37: Warning: 
diff --git a/src/plugins/wp/tests/wp_hoare/oracle_qualif/refguards.res.oracle b/src/plugins/wp/tests/wp_hoare/oracle_qualif/refguards.res.oracle
index 3fba6a750b4f8d97faebe8f14aca0aa61237fea0..549d47287ee22c85592ea76b95d7b7032aca6afa 100644
--- a/src/plugins/wp/tests/wp_hoare/oracle_qualif/refguards.res.oracle
+++ b/src/plugins/wp/tests/wp_hoare/oracle_qualif/refguards.res.oracle
@@ -26,26 +26,26 @@
   Memory model hypotheses for function 'f':
   /*@
      behavior wp_typed_ref:
-       requires \separated(c, d, {a + (..), b + (..)});
        requires \valid(c);
        requires \valid(d);
+       requires \separated(c, d, {a + (..), b + (..)});
      */
   void f(int *a, int *b, int *c, int *d, int k);
 [wp] tests/wp_hoare/refguards.i:25: Warning: 
   Memory model hypotheses for function 'h':
   /*@
      behavior wp_typed_ref:
-       requires \separated(c, d);
        requires \valid(c);
        requires \valid(d);
+       requires \separated(c, d);
      */
   void h(int *c, int *d, int k);
 [wp] tests/wp_hoare/refguards.i:39: Warning: 
   Memory model hypotheses for function 's':
   /*@
      behavior wp_typed_ref:
-       requires \separated(c, d);
        requires \valid(c);
        requires \valid(d);
+       requires \separated(c, d);
      */
   void s(int **c, int **d, int k);
diff --git a/src/plugins/wp/tests/wp_plugin/nullable.i b/src/plugins/wp/tests/wp_plugin/nullable.i
new file mode 100644
index 0000000000000000000000000000000000000000..ff08ead486c94dfc77c8b34d2a9a7553b6cec248
--- /dev/null
+++ b/src/plugins/wp/tests/wp_plugin/nullable.i
@@ -0,0 +1,34 @@
+/* run.config
+   OPT: -wp-model Caveat
+*/
+/* run.config_qualif
+   OPT: -wp-model Caveat
+*/
+
+int x ;
+int *g ;
+
+/*@ assigns *g, *p, x ; */
+void nullable_coherence(int* p /*@ wp_nullable */){
+  if(p == (void*)0){
+    //@ check must_fail: \false ;
+    return;
+  }
+  //@ check \valid(p);
+  *p = 42;
+  *g = 24;
+  x = 1;
+}
+
+//@ assigns *p, *q, *r, *s, *t ;
+void nullable_in_context
+(int* p /*@ wp_nullable */,
+ int* q /*@ wp_nullable */,
+ int* r /*@ wp_nullable */,
+ int* s, int* t)
+{
+  *p = 42;
+  *q = 42;
+  *r = 42;
+  *s = *t = 0;
+}
diff --git a/src/plugins/wp/tests/wp_plugin/nullable_ext.i b/src/plugins/wp/tests/wp_plugin/nullable_ext.i
new file mode 100644
index 0000000000000000000000000000000000000000..7225aa000f21516ce9c2596b9ff62f4e7245e7ca
--- /dev/null
+++ b/src/plugins/wp/tests/wp_plugin/nullable_ext.i
@@ -0,0 +1,33 @@
+/* run.config
+   OPT: -wp-model Caveat
+*/
+/* run.config_qualif
+   OPT: -wp-model Caveat
+*/
+
+int x ;
+int *g ;
+
+/*@ assigns *g, *p, x ;
+    wp_nullable_args p ;
+*/
+void nullable_coherence(int* p){
+  if(p == (void*)0){
+    //@ check must_fail: \false ;
+    return;
+  }
+  //@ check \valid(p);
+  *p = 42;
+  *g = 24;
+  x = 1;
+}
+
+/*@ assigns *p, *q, *r, *s, *t ;
+    wp_nullable_args p, q, r ;
+*/
+void nullable_in_context(int* p, int* q, int* r, int* s, int* t){
+  *p = 42;
+  *q = 42;
+  *r = 42;
+  *s = *t = 0;
+}
diff --git a/src/plugins/wp/tests/wp_plugin/oracle/nullable.res.oracle b/src/plugins/wp/tests/wp_plugin/oracle/nullable.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..1fe84b7fa72fb41c754482abcee25af6e247c822
--- /dev/null
+++ b/src/plugins/wp/tests/wp_plugin/oracle/nullable.res.oracle
@@ -0,0 +1,68 @@
+# frama-c -wp -wp-model 'Typed (Caveat)' [...]
+[kernel] Parsing tests/wp_plugin/nullable.i (no preprocessing)
+[wp] Running WP plugin...
+[wp] Warning: In caveat model with nullable arguments, -wp-(no)-rte shall be explicitly positioned.
+[wp] Warning: Missing RTE guards
+------------------------------------------------------------
+  Function nullable_coherence
+------------------------------------------------------------
+
+Goal Check 'must_fail' (file tests/wp_plugin/nullable.i, line 14):
+Assume { (* Then *) Have: null = pointer_p. }
+Prove: false.
+
+------------------------------------------------------------
+
+Goal Check (file tests/wp_plugin/nullable.i, line 17):
+Prove: true.
+
+------------------------------------------------------------
+
+Goal Assigns (file tests/wp_plugin/nullable.i, line 11) in 'nullable_coherence':
+Prove: true.
+
+------------------------------------------------------------
+------------------------------------------------------------
+  Function nullable_in_context
+------------------------------------------------------------
+
+Goal Assigns (file tests/wp_plugin/nullable.i, line 23) in 'nullable_in_context' (1/2):
+Prove: true.
+
+------------------------------------------------------------
+
+Goal Assigns (file tests/wp_plugin/nullable.i, line 23) in 'nullable_in_context' (2/2):
+Effect at line 33
+Prove: true.
+
+------------------------------------------------------------
+[wp] tests/wp_plugin/nullable.i:12: Warning: 
+  Memory model hypotheses for function 'nullable_coherence':
+  /*@
+     behavior wp_typed_caveat:
+       requires \valid(g);
+       requires \valid(p) ∨ p ≡ \null;
+       requires \separated(g, &x);
+       requires \separated(p, &x);
+       requires p ≢ \null ⇒ \separated(g, p, &x);
+     */
+  void nullable_coherence(int *p /*@ wp_nullable */);
+[wp] tests/wp_plugin/nullable.i:24: Warning: 
+  Memory model hypotheses for function 'nullable_in_context':
+  /*@
+     behavior wp_typed_caveat:
+       requires \valid(s);
+       requires \valid(t);
+       requires \valid(p) ∨ p ≡ \null;
+       requires \valid(q) ∨ q ≡ \null;
+       requires \valid(r) ∨ r ≡ \null;
+       requires p ≢ \null ⇒ \separated(p, s, t);
+       requires q ≢ \null ⇒ \separated(q, s, t);
+       requires q ≢ \null ⇒ p ≢ \null ⇒ \separated(q, p);
+       requires r ≢ \null ⇒ \separated(r, s, t);
+       requires r ≢ \null ⇒ p ≢ \null ⇒ \separated(r, p);
+       requires r ≢ \null ⇒ q ≢ \null ⇒ \separated(r, q);
+     */
+  void nullable_in_context(int *p /*@ wp_nullable */,
+                           int *q /*@ wp_nullable */,
+                           int *r /*@ wp_nullable */, int *s, int *t);
diff --git a/src/plugins/wp/tests/wp_plugin/oracle/nullable_ext.res.oracle b/src/plugins/wp/tests/wp_plugin/oracle/nullable_ext.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..b4246e6986ee28aa5501e570f37ff31edc9d1282
--- /dev/null
+++ b/src/plugins/wp/tests/wp_plugin/oracle/nullable_ext.res.oracle
@@ -0,0 +1,68 @@
+# frama-c -wp -wp-model 'Typed (Caveat)' [...]
+[kernel] Parsing tests/wp_plugin/nullable_ext.i (no preprocessing)
+[wp] Running WP plugin...
+[wp] Warning: In caveat model with nullable arguments, -wp-(no)-rte shall be explicitly positioned.
+[wp] Warning: Missing RTE guards
+------------------------------------------------------------
+  Function nullable_coherence
+------------------------------------------------------------
+
+Goal Check 'must_fail' (file tests/wp_plugin/nullable_ext.i, line 16):
+Assume { (* Then *) Have: null = pointer_p. }
+Prove: false.
+
+------------------------------------------------------------
+
+Goal Check (file tests/wp_plugin/nullable_ext.i, line 19):
+Prove: true.
+
+------------------------------------------------------------
+
+Goal Assigns (file tests/wp_plugin/nullable_ext.i, line 11) in 'nullable_coherence':
+Prove: true.
+
+------------------------------------------------------------
+------------------------------------------------------------
+  Function nullable_in_context
+------------------------------------------------------------
+
+Goal Assigns (file tests/wp_plugin/nullable_ext.i, line 25) in 'nullable_in_context' (1/2):
+Prove: true.
+
+------------------------------------------------------------
+
+Goal Assigns (file tests/wp_plugin/nullable_ext.i, line 25) in 'nullable_in_context' (2/2):
+Effect at line 32
+Prove: true.
+
+------------------------------------------------------------
+[wp] tests/wp_plugin/nullable_ext.i:14: Warning: 
+  Memory model hypotheses for function 'nullable_coherence':
+  /*@
+     behavior wp_typed_caveat:
+       requires \valid(g);
+       requires \valid(p) ∨ p ≡ \null;
+       requires \separated(g, &x);
+       requires \separated(p, &x);
+       requires p ≢ \null ⇒ \separated(g, p, &x);
+     */
+  void nullable_coherence(int *p /*@ wp_nullable */);
+[wp] tests/wp_plugin/nullable_ext.i:28: Warning: 
+  Memory model hypotheses for function 'nullable_in_context':
+  /*@
+     behavior wp_typed_caveat:
+       requires \valid(s);
+       requires \valid(t);
+       requires \valid(p) ∨ p ≡ \null;
+       requires \valid(q) ∨ q ≡ \null;
+       requires \valid(r) ∨ r ≡ \null;
+       requires p ≢ \null ⇒ \separated(p, s, t);
+       requires q ≢ \null ⇒ \separated(q, s, t);
+       requires q ≢ \null ⇒ p ≢ \null ⇒ \separated(q, p);
+       requires r ≢ \null ⇒ \separated(r, s, t);
+       requires r ≢ \null ⇒ p ≢ \null ⇒ \separated(r, p);
+       requires r ≢ \null ⇒ q ≢ \null ⇒ \separated(r, q);
+     */
+  void nullable_in_context(int *p /*@ wp_nullable */,
+                           int *q /*@ wp_nullable */,
+                           int *r /*@ wp_nullable */, int *s, int *t);
diff --git a/src/plugins/wp/tests/wp_plugin/oracle/sep.res.oracle b/src/plugins/wp/tests/wp_plugin/oracle/sep.res.oracle
index e5d8aa84c061c2c39a06fe1f5257ffadeaea8003..24c245a193b32ecbb0357aa353d2e21d9bce3995 100644
--- a/src/plugins/wp/tests/wp_plugin/oracle/sep.res.oracle
+++ b/src/plugins/wp/tests/wp_plugin/oracle/sep.res.oracle
@@ -69,58 +69,58 @@ Prove: true.
 [wp] tests/wp_plugin/sep.i:18: Warning: 
   Memory model hypotheses for function 'f2_p_a':
   /*@ behavior wp_typed_caveat:
-        requires \separated(p, &a);
-        requires \valid(p); */
+        requires \valid(p);
+        requires \separated(p, &a); */
   void f2_p_a(int *p);
 [wp] tests/wp_plugin/sep.i:22: Warning: 
   Memory model hypotheses for function 'f3_p_ab':
   /*@
      behavior wp_typed_caveat:
-       requires \separated(p, &a, &b);
        requires \valid(p);
+       requires \separated(p, &a, &b);
      */
   void f3_p_ab(int *p);
 [wp] tests/wp_plugin/sep.i:26: Warning: 
   Memory model hypotheses for function 'f4_pq_ab':
   /*@
      behavior wp_typed_caveat:
-       requires \separated(p, q, &a, &b);
        requires \valid(p);
        requires \valid(q);
+       requires \separated(p, q, &a, &b);
      */
   void f4_pq_ab(int *p, int *q);
 [wp] tests/wp_plugin/sep.i:30: Warning: 
   Memory model hypotheses for function 'f5_pq':
   /*@
      behavior wp_typed_caveat:
-       requires \separated(p, q);
        requires \valid(p);
        requires \valid(q);
+       requires \separated(p, q);
      */
   void f5_pq(int *p, int *q);
 [wp] tests/wp_plugin/sep.i:34: Warning: 
   Memory model hypotheses for function 'f6_Pa':
   /*@
      behavior wp_typed_caveat:
-       requires \separated(p + (..), &a);
        requires \valid(p + (..));
+       requires \separated(p + (..), &a);
      */
   void f6_Pa(int *p, int k);
 [wp] tests/wp_plugin/sep.i:43: Warning: 
   Memory model hypotheses for function 'f7_pq_ad':
   /*@
      behavior wp_typed_caveat:
-       requires \separated(p, q, &a, &d);
        requires \valid(p);
        requires \valid(q);
+       requires \separated(p, q, &a, &d);
      */
   void f7_pq_ad(int *p, int *q);
 [wp] tests/wp_plugin/sep.i:49: Warning: 
   Memory model hypotheses for function 'f8_pq_a':
   /*@
      behavior wp_typed_caveat:
-       requires \separated(p, q, &a);
        requires \valid(p);
        requires \valid(q);
+       requires \separated(p, q, &a);
      */
   void f8_pq_a(int *p, int *q);
diff --git a/src/plugins/wp/tests/wp_plugin/oracle_qualif/nullable.res.oracle b/src/plugins/wp/tests/wp_plugin/oracle_qualif/nullable.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..a63862b2bf46f677cdb87a010e4272ceff395884
--- /dev/null
+++ b/src/plugins/wp/tests/wp_plugin/oracle_qualif/nullable.res.oracle
@@ -0,0 +1,49 @@
+# frama-c -wp -wp-model 'Typed (Caveat)' [...]
+[kernel] Parsing tests/wp_plugin/nullable.i (no preprocessing)
+[wp] Running WP plugin...
+[wp] Warning: In caveat model with nullable arguments, -wp-(no)-rte shall be explicitly positioned.
+[wp] Warning: Missing RTE guards
+[wp] 5 goals scheduled
+[wp] [Alt-Ergo] Goal typed_caveat_nullable_coherence_check_must_fail : Unsuccess
+[wp] [Qed] Goal typed_caveat_nullable_coherence_check : Valid
+[wp] [Qed] Goal typed_caveat_nullable_coherence_assigns : Valid
+[wp] [Qed] Goal typed_caveat_nullable_in_context_assigns_part1 : Valid
+[wp] [Qed] Goal typed_caveat_nullable_in_context_assigns_part2 : Valid
+[wp] Proved goals:    4 / 5
+  Qed:             4 
+  Alt-Ergo:        0  (unsuccess: 1)
+------------------------------------------------------------
+ Functions                 WP     Alt-Ergo  Total   Success
+  nullable_coherence        2        -        3      66.7%
+  nullable_in_context       2        -        2       100%
+------------------------------------------------------------
+[wp] tests/wp_plugin/nullable.i:12: Warning: 
+  Memory model hypotheses for function 'nullable_coherence':
+  /*@
+     behavior wp_typed_caveat:
+       requires \valid(g);
+       requires \valid(p) ∨ p ≡ \null;
+       requires \separated(g, &x);
+       requires \separated(p, &x);
+       requires p ≢ \null ⇒ \separated(g, p, &x);
+     */
+  void nullable_coherence(int *p /*@ wp_nullable */);
+[wp] tests/wp_plugin/nullable.i:24: Warning: 
+  Memory model hypotheses for function 'nullable_in_context':
+  /*@
+     behavior wp_typed_caveat:
+       requires \valid(s);
+       requires \valid(t);
+       requires \valid(p) ∨ p ≡ \null;
+       requires \valid(q) ∨ q ≡ \null;
+       requires \valid(r) ∨ r ≡ \null;
+       requires p ≢ \null ⇒ \separated(p, s, t);
+       requires q ≢ \null ⇒ \separated(q, s, t);
+       requires q ≢ \null ⇒ p ≢ \null ⇒ \separated(q, p);
+       requires r ≢ \null ⇒ \separated(r, s, t);
+       requires r ≢ \null ⇒ p ≢ \null ⇒ \separated(r, p);
+       requires r ≢ \null ⇒ q ≢ \null ⇒ \separated(r, q);
+     */
+  void nullable_in_context(int *p /*@ wp_nullable */,
+                           int *q /*@ wp_nullable */,
+                           int *r /*@ wp_nullable */, int *s, int *t);
diff --git a/src/plugins/wp/tests/wp_plugin/oracle_qualif/nullable_ext.res.oracle b/src/plugins/wp/tests/wp_plugin/oracle_qualif/nullable_ext.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..1f2fed4938befc5db60a585320ff3e63bce02d74
--- /dev/null
+++ b/src/plugins/wp/tests/wp_plugin/oracle_qualif/nullable_ext.res.oracle
@@ -0,0 +1,49 @@
+# frama-c -wp -wp-model 'Typed (Caveat)' [...]
+[kernel] Parsing tests/wp_plugin/nullable_ext.i (no preprocessing)
+[wp] Running WP plugin...
+[wp] Warning: In caveat model with nullable arguments, -wp-(no)-rte shall be explicitly positioned.
+[wp] Warning: Missing RTE guards
+[wp] 5 goals scheduled
+[wp] [Alt-Ergo] Goal typed_caveat_nullable_coherence_check_must_fail : Unsuccess
+[wp] [Qed] Goal typed_caveat_nullable_coherence_check : Valid
+[wp] [Qed] Goal typed_caveat_nullable_coherence_assigns : Valid
+[wp] [Qed] Goal typed_caveat_nullable_in_context_assigns_part1 : Valid
+[wp] [Qed] Goal typed_caveat_nullable_in_context_assigns_part2 : Valid
+[wp] Proved goals:    4 / 5
+  Qed:             4 
+  Alt-Ergo:        0  (unsuccess: 1)
+------------------------------------------------------------
+ Functions                 WP     Alt-Ergo  Total   Success
+  nullable_coherence        2        -        3      66.7%
+  nullable_in_context       2        -        2       100%
+------------------------------------------------------------
+[wp] tests/wp_plugin/nullable_ext.i:14: Warning: 
+  Memory model hypotheses for function 'nullable_coherence':
+  /*@
+     behavior wp_typed_caveat:
+       requires \valid(g);
+       requires \valid(p) ∨ p ≡ \null;
+       requires \separated(g, &x);
+       requires \separated(p, &x);
+       requires p ≢ \null ⇒ \separated(g, p, &x);
+     */
+  void nullable_coherence(int *p /*@ wp_nullable */);
+[wp] tests/wp_plugin/nullable_ext.i:28: Warning: 
+  Memory model hypotheses for function 'nullable_in_context':
+  /*@
+     behavior wp_typed_caveat:
+       requires \valid(s);
+       requires \valid(t);
+       requires \valid(p) ∨ p ≡ \null;
+       requires \valid(q) ∨ q ≡ \null;
+       requires \valid(r) ∨ r ≡ \null;
+       requires p ≢ \null ⇒ \separated(p, s, t);
+       requires q ≢ \null ⇒ \separated(q, s, t);
+       requires q ≢ \null ⇒ p ≢ \null ⇒ \separated(q, p);
+       requires r ≢ \null ⇒ \separated(r, s, t);
+       requires r ≢ \null ⇒ p ≢ \null ⇒ \separated(r, p);
+       requires r ≢ \null ⇒ q ≢ \null ⇒ \separated(r, q);
+     */
+  void nullable_in_context(int *p /*@ wp_nullable */,
+                           int *q /*@ wp_nullable */,
+                           int *r /*@ wp_nullable */, int *s, int *t);
diff --git a/src/plugins/wp/tests/wp_typed/oracle/unit_labels.1.res.oracle b/src/plugins/wp/tests/wp_typed/oracle/unit_labels.1.res.oracle
index 7a7b1b25d56460d9600a2462fbc1f0b38cc49dd2..24ac613e94a8d5f7e266beeee05e591a8c77d78e 100644
--- a/src/plugins/wp/tests/wp_typed/oracle/unit_labels.1.res.oracle
+++ b/src/plugins/wp/tests/wp_typed/oracle/unit_labels.1.res.oracle
@@ -30,8 +30,8 @@ Prove: true.
   Memory model hypotheses for function 'duplet':
   /*@
      behavior wp_typed_ref:
-       requires \separated(pi, pj, a + (..));
        requires \valid(pi);
        requires \valid(pj);
+       requires \separated(pi, pj, a + (..));
      */
   void duplet(int *a, int *pi, int *pj);
diff --git a/src/plugins/wp/tests/wp_typed/oracle/user_swap.1.res.oracle b/src/plugins/wp/tests/wp_typed/oracle/user_swap.1.res.oracle
index e571b4fc2cce83e61a9d3f99da28c56e0219ce79..26c949f5c0cd9122a79829c5f595a18b0ad69a14 100644
--- a/src/plugins/wp/tests/wp_typed/oracle/user_swap.1.res.oracle
+++ b/src/plugins/wp/tests/wp_typed/oracle/user_swap.1.res.oracle
@@ -44,8 +44,8 @@ Prove: true.
   Memory model hypotheses for function 'swap':
   /*@
      behavior wp_typed_ref:
-       requires \separated(a, b);
        requires \valid(a);
        requires \valid(b);
+       requires \separated(a, b);
      */
   void swap(int *a, int *b);
diff --git a/src/plugins/wp/tests/wp_typed/oracle_qualif/user_injector.1.res.oracle b/src/plugins/wp/tests/wp_typed/oracle_qualif/user_injector.1.res.oracle
index ad44942e79c58b466fce26436dad805a9512eab4..5d5ce1185b2e1c7d41d297886f473249cfc9c7df 100644
--- a/src/plugins/wp/tests/wp_typed/oracle_qualif/user_injector.1.res.oracle
+++ b/src/plugins/wp/tests/wp_typed/oracle_qualif/user_injector.1.res.oracle
@@ -29,11 +29,11 @@
   Memory model hypotheses for function 'job':
   /*@
      behavior wp_typed_ref:
+       requires \valid(error);
        requires
          \separated(
            error, (int *)service_id + (..), (int *)service_result + (..), &seq,
            &service_cpt
            );
-       requires \valid(error);
      */
   int job(int a, int b, int *error);
diff --git a/src/plugins/wp/tests/wp_typed/oracle_qualif/user_swap.1.res.oracle b/src/plugins/wp/tests/wp_typed/oracle_qualif/user_swap.1.res.oracle
index d37ff58f250004ef4d1fb0e0262f230040f9f336..18eff921deab26414b4b24426d59fa1a2bb7d5e1 100644
--- a/src/plugins/wp/tests/wp_typed/oracle_qualif/user_swap.1.res.oracle
+++ b/src/plugins/wp/tests/wp_typed/oracle_qualif/user_swap.1.res.oracle
@@ -20,8 +20,8 @@
   Memory model hypotheses for function 'swap':
   /*@
      behavior wp_typed_ref:
-       requires \separated(a, b);
        requires \valid(a);
        requires \valid(b);
+       requires \separated(a, b);
      */
   void swap(int *a, int *b);
diff --git a/src/plugins/wp/tests/wp_usage/oracle/caveat.1.res.oracle b/src/plugins/wp/tests/wp_usage/oracle/caveat.1.res.oracle
index 7f6f4e1316280036e5df8c8d578bbb2b5e487f1b..0141c03ea9ff5368e80b619ad7ce64c3253d72c0 100644
--- a/src/plugins/wp/tests/wp_usage/oracle/caveat.1.res.oracle
+++ b/src/plugins/wp/tests/wp_usage/oracle/caveat.1.res.oracle
@@ -72,26 +72,26 @@ Prove: P_OBS(x_2, x_3, x_4).
   Memory model hypotheses for function 'implicit':
   /*@
      behavior wp_typed_caveat:
-       requires \separated(a, r);
        requires \valid(a);
        requires \valid(r);
+       requires \separated(a, r);
      */
   void implicit(struct S *a, int *r);
 [wp] tests/wp_usage/caveat.i:32: Warning: 
   Memory model hypotheses for function 'explicit':
   /*@
      behavior wp_typed_caveat:
-       requires \separated(a, r);
        requires \valid(a);
        requires \valid(r);
+       requires \separated(a, r);
      */
   void explicit(struct S *a, int *r);
 [wp] tests/wp_usage/caveat.i:47: Warning: 
   Memory model hypotheses for function 'observer':
   /*@
      behavior wp_typed_caveat:
-       requires \separated(a, r);
        requires \valid(a);
        requires \valid(r);
+       requires \separated(a, r);
      */
   void observer(struct S *a, int *r);
diff --git a/src/plugins/wp/tests/wp_usage/oracle/caveat2.res.oracle b/src/plugins/wp/tests/wp_usage/oracle/caveat2.res.oracle
index bd126749ac28da329e21c30afd6113528bb91909..7ec4d49d41a9cc9cf35cc6aa9ab3dd2c08c11c9d 100644
--- a/src/plugins/wp/tests/wp_usage/oracle/caveat2.res.oracle
+++ b/src/plugins/wp/tests/wp_usage/oracle/caveat2.res.oracle
@@ -101,8 +101,8 @@ Prove: true.
   Memory model hypotheses for function 'job':
   /*@
      behavior wp_typed_caveat:
-       requires \separated(p, b + (..));
        requires \valid(b + (..));
        requires \valid(p);
+       requires \separated(p, b + (..));
      */
   void job(struct S *p, int n, int *b);
diff --git a/src/plugins/wp/tests/wp_usage/oracle/global.2.res.oracle b/src/plugins/wp/tests/wp_usage/oracle/global.2.res.oracle
index 3489aa287459e7a28ac2466a765b8a28f44a3e89..7bb8969a653815ed38f4c1d7a8033b3de5e92220 100644
--- a/src/plugins/wp/tests/wp_usage/oracle/global.2.res.oracle
+++ b/src/plugins/wp/tests/wp_usage/oracle/global.2.res.oracle
@@ -23,7 +23,7 @@ Prove: true.
   Memory model hypotheses for function 'foo':
   /*@
      behavior wp_typed_ref:
-       requires \separated(a, &GLOBAL);
        requires \valid(a);
+       requires \separated(a, &GLOBAL);
      */
   void foo(int *a);
diff --git a/src/plugins/wp/tests/wp_usage/oracle/issue-189-bis.1.res.oracle b/src/plugins/wp/tests/wp_usage/oracle/issue-189-bis.1.res.oracle
index c15cbee10c3bd49b6bdb5e70c103a1ebac5cb9ff..0fb3ea0ed2e6643f287e6cedf372596e6086c6f1 100644
--- a/src/plugins/wp/tests/wp_usage/oracle/issue-189-bis.1.res.oracle
+++ b/src/plugins/wp/tests/wp_usage/oracle/issue-189-bis.1.res.oracle
@@ -171,8 +171,8 @@ Prove: true.
   Memory model hypotheses for function 'memcpy_context_vars':
   /*@
      behavior wp_typed:
-       requires \separated(src, dst);
        requires \valid(dst);
        requires \valid(src);
+       requires \separated(src, dst);
      */
   void memcpy_context_vars(unsigned char *src, unsigned char *dst, int len);
diff --git a/src/plugins/wp/tests/wp_usage/oracle/issue-189.2.res.oracle b/src/plugins/wp/tests/wp_usage/oracle/issue-189.2.res.oracle
index 5cd9f57c585ba881735715218f8d80be0aab2e2d..0114ddb64681e6f4636f2d82a07fdb25b9f291b4 100644
--- a/src/plugins/wp/tests/wp_usage/oracle/issue-189.2.res.oracle
+++ b/src/plugins/wp/tests/wp_usage/oracle/issue-189.2.res.oracle
@@ -26,7 +26,7 @@ Prove: true.
   Memory model hypotheses for function 'f':
   /*@
      behavior wp_typed_caveat:
-       requires \separated(ptr, src);
        requires \valid(ptr);
+       requires \separated(ptr, src);
      */
   void f(char *ptr, char const *src, unsigned int idx);
diff --git a/src/plugins/wp/tests/wp_usage/oracle_qualif/caveat2.res.oracle b/src/plugins/wp/tests/wp_usage/oracle_qualif/caveat2.res.oracle
index 86f77567c02d0caf7aab6020ddf1b5cb07631098..5ebef0000b8e36cb669571dd841f5ee001c4a791 100644
--- a/src/plugins/wp/tests/wp_usage/oracle_qualif/caveat2.res.oracle
+++ b/src/plugins/wp/tests/wp_usage/oracle_qualif/caveat2.res.oracle
@@ -24,8 +24,8 @@
   Memory model hypotheses for function 'job':
   /*@
      behavior wp_typed_caveat:
-       requires \separated(p, b + (..));
        requires \valid(b + (..));
        requires \valid(p);
+       requires \separated(p, b + (..));
      */
   void job(struct S *p, int n, int *b);
diff --git a/src/plugins/wp/tests/wp_usage/oracle_qualif/issue-189-bis.1.res.oracle b/src/plugins/wp/tests/wp_usage/oracle_qualif/issue-189-bis.1.res.oracle
index e73a38c074fdf04dbda90f7e6ef41eaca850a587..4a5c45145f618785311b2456d1172e1cdfc203e2 100644
--- a/src/plugins/wp/tests/wp_usage/oracle_qualif/issue-189-bis.1.res.oracle
+++ b/src/plugins/wp/tests/wp_usage/oracle_qualif/issue-189-bis.1.res.oracle
@@ -24,8 +24,8 @@
   Memory model hypotheses for function 'memcpy_context_vars':
   /*@
      behavior wp_typed:
-       requires \separated(src, dst);
        requires \valid(dst);
        requires \valid(src);
+       requires \separated(src, dst);
      */
   void memcpy_context_vars(unsigned char *src, unsigned char *dst, int len);