Skip to content
Snippets Groups Projects
Commit cfe2a65d authored by Allan Blanchard's avatar Allan Blanchard
Browse files

[wp] Hypotheses to validate at post

parent dda13ade
No related branches found
No related tags found
No related merge requests found
...@@ -50,6 +50,7 @@ type partition = { ...@@ -50,6 +50,7 @@ type partition = {
globals : zone list ; (* [ &G , G[...], ... ] *) globals : zone list ; (* [ &G , G[...], ... ] *)
to_heap : zone list ; (* [ p, ... ] *) to_heap : zone list ; (* [ p, ... ] *)
context : zone list ; (* [ p+(..), ... ] *) context : zone list ; (* [ p+(..), ... ] *)
by_addr : zone list ;
} }
(* -------------------------------------------------------------------------- *) (* -------------------------------------------------------------------------- *)
...@@ -60,12 +61,13 @@ let empty = { ...@@ -60,12 +61,13 @@ let empty = {
globals = [] ; globals = [] ;
context = [] ; context = [] ;
to_heap = [] ; to_heap = [] ;
by_addr = [] ;
} }
let set x p w = let set x p w =
match p with match p with
| NotUsed -> w | NotUsed -> w
| ByAddr -> w | ByAddr -> { w with by_addr = Var x :: w.by_addr }
| ByRef | InContext -> | ByRef | InContext ->
if Cil.isFunctionType x.vtype then w else if Cil.isFunctionType x.vtype then w else
{ w with context = Ptr x :: w.context } { w with context = Ptr x :: w.context }
...@@ -192,6 +194,10 @@ let global_zones partition = ...@@ -192,6 +194,10 @@ let global_zones partition =
let context_zones partition = let context_zones partition =
List.map (fun z -> [z]) partition.context List.map (fun z -> [z]) partition.context
let addr_of_zones partition =
let comp a b = Cil_datatype.Typ.compare (type_of_zone a) (type_of_zone b) in
List.sort comp partition.by_addr
let heap_zones partition = let heap_zones partition =
let comp a b = Cil_datatype.Typ.compare (type_of_zone a) (type_of_zone b) in let comp a b = Cil_datatype.Typ.compare (type_of_zone a) (type_of_zone b) in
List.sort comp partition.to_heap List.sort comp partition.to_heap
...@@ -199,7 +205,7 @@ let heap_zones partition = ...@@ -199,7 +205,7 @@ let heap_zones partition =
(* Note that this function does not return separated zone lists, but well-typed (* Note that this function does not return separated zone lists, but well-typed
zone lists. zone lists.
*) *)
let heaps partition = let well_type_zones zone_function partition =
let rec partition_by_type t acc l = let rec partition_by_type t acc l =
match l, acc with match l, acc with
| [], _ -> | [], _ ->
...@@ -211,7 +217,9 @@ let heaps partition = ...@@ -211,7 +217,9 @@ let heaps partition =
| x :: l, acc -> | x :: l, acc ->
partition_by_type (type_of_zone x) ([x] :: acc) l partition_by_type (type_of_zone x) ([x] :: acc) l
in in
partition_by_type Cil.voidType [] (heap_zones partition) partition_by_type Cil.voidType [] (zone_function partition)
let heaps = well_type_zones heap_zones
let main_separation loc globals context heaps = let main_separation loc globals context heaps =
match heaps, context with match heaps, context with
...@@ -232,16 +240,11 @@ let assigned_locations kf filter = ...@@ -232,16 +240,11 @@ let assigned_locations kf filter =
let add_from l (e, _ds) = let add_from l (e, _ds) =
if filter e.it_content then e :: l else l if filter e.it_content then e :: l else l
in in
let add_assign kf _emitter assigns l = match assigns with let add_assign _emitter assigns l = match assigns with
| WritesAny -> | WritesAny -> l
Wp_parameters.warning
~wkey:Wp_parameters.wkey_imprecise_hypotheses_assigns ~once:true
"No assigns for function '%a', model hypotheses will be imprecise"
Kernel_function.pretty kf ;
l
| Writes froms -> List.fold_left add_from l froms | Writes froms -> List.fold_left add_from l froms
in in
Annotations.fold_assigns (add_assign kf) kf Cil.default_behavior_name [] Annotations.fold_assigns add_assign kf Cil.default_behavior_name []
let assigned_via_pointers kf = let assigned_via_pointers kf =
let rec assigned_via_pointer t = let rec assigned_via_pointer t =
...@@ -260,24 +263,67 @@ let assigned_via_pointers kf = ...@@ -260,24 +263,67 @@ let assigned_via_pointers kf =
in in
assigned_locations kf assigned_via_pointer assigned_locations kf assigned_via_pointer
let post_term t =
let exception Post_value in
let v = object
inherit Cil.nopCilVisitor
method! vlogic_label = function
| BuiltinLabel(Post) -> raise Post_value
| _ -> Cil.SkipChildren
method! vterm_lval = function
| TResult _, _ -> raise Post_value
| _ -> Cil.DoChildren
end in
try ignore (Cil.visitCilTerm v t) ; false
with Post_value -> true
let simpl_pred_list l =
List.sort_uniq Logic_utils.compare_predicate
(List.filter (fun p -> not(Logic_utils.is_trivially_true p)) l)
let clauses_of_partition kf loc p = let clauses_of_partition kf loc p =
let globals = global_zones p in let globals = global_zones p in
let main_sep = let main_sep =
main_separation loc globals (context_zones p) (heaps p) main_separation loc globals (context_zones p) (heaps p)
in in
let assigns_sep = let assigns_sep_req, assigns_sep_ens =
let addr_of t = addr_of_lval ~loc t.it_content in let addr_of t = addr_of_lval ~loc t.it_content in
List.map let folder (req, ens) t =
(fun t -> term_separated_from_regions loc (addr_of t) globals) let sep = term_separated_from_regions loc (addr_of t) globals in
(assigned_via_pointers kf) if post_term t.it_content then (req, sep :: ens) else (sep :: req, ens)
in
List.fold_left folder ([],[]) (assigned_via_pointers kf)
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 = simpl_pred_list reqs in
let ens = simpl_pred_list assigns_sep_ens in
reqs, ens
let addr_of_vars = well_type_zones addr_of_zones
let ptr_or_ptr_set { term_type = t } =
let open Logic_typing in
is_pointer_type t || (is_set_type t && is_pointer_type (type_of_element t))
let escaping_formals kf loc p =
let ret_t = Kernel_function.get_return_type kf in
let addr_of t = addr_of_lval ~loc t.it_content in
let asgnd_ptrs =
Extlib.filter_map
(* Search assigned pointers via a pointer,
e.g. 'assigns *p ;' with '*p' of type pointer or set of pointers *)
(fun t -> ptr_or_ptr_set t.it_content) addr_of (assigned_via_pointers kf)
in in
let context_validity = let asgnd_ptrs =
List.map (valid_region loc) (context_zones p) if Cil.isPointerType ret_t then tresult ~loc ret_t :: asgnd_ptrs
else asgnd_ptrs
in in
let reqs = main_sep @ assigns_sep @ context_validity in let local_zone = function Var v -> v.vformal | _ -> false in
let reqs = List.filter (fun p -> not(Logic_utils.is_trivially_true p)) reqs in let local_partition = { p with by_addr = List.filter local_zone p.by_addr } in
let reqs = List.sort_uniq Logic_utils.compare_predicate reqs in let locals = addr_of_vars local_partition in
reqs simpl_pred_list
(List.map (fun t -> term_separated_from_regions loc t locals) asgnd_ptrs)
module Table = module Table =
State_builder.Hashtbl State_builder.Hashtbl
...@@ -292,16 +338,18 @@ module Table = ...@@ -292,16 +338,18 @@ module Table =
let compute_behavior kf name hypotheses_computer = let compute_behavior kf name hypotheses_computer =
let partition = hypotheses_computer kf in let partition = hypotheses_computer kf in
let loc = Kernel_function.get_location kf in let loc = Kernel_function.get_location kf in
let reqs = clauses_of_partition kf loc partition in let reqs, ens = clauses_of_partition kf loc partition in
let reqs = List.map Logic_const.new_predicate reqs in let ens = escaping_formals kf loc partition @ ens in
match reqs with let reqs = List.map new_predicate reqs in
| [] -> None let ens = List.map (fun p -> Normal, new_predicate p) ens in
| l1 -> match reqs, ens with
| [], [] -> None
| reqs, ens ->
Some { Some {
b_name = name ; b_name = name ;
b_requires = l1 ; b_requires = reqs ;
b_assumes = [] ; b_assumes = [] ;
b_post_cond = [] ; b_post_cond = ens ;
b_assigns = WritesAny ; b_assigns = WritesAny ;
b_allocation = FreeAllocAny ; b_allocation = FreeAllocAny ;
b_extended = [] b_extended = []
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment