diff --git a/Makefile b/Makefile index 531ba1bf1fad242d50b3b824c728c376210b5a35..8a1d9897659a5a16bf966df630a839a416c2f6d5 100644 --- a/Makefile +++ b/Makefile @@ -899,7 +899,7 @@ PLUGIN_CMO:= partitioning/split_strategy domains/domain_mode self parameters \ domains/cvalue/builtins_watchpoint \ domains/cvalue/builtins_float domains/cvalue/builtins_split \ domains/inout_domain \ - legacy/eval_terms legacy/eval_annots \ + legacy/eval_terms \ domains/cvalue/cvalue_transfer domains/cvalue/cvalue_init \ domains/cvalue/cvalue_specification \ domains/cvalue/cvalue_domain \ @@ -908,7 +908,7 @@ PLUGIN_CMO:= partitioning/split_strategy domains/domain_mode self parameters \ partitioning/auto_loop_unroll \ partitioning/partition partitioning/partitioning_parameters \ partitioning/partitioning_index partitioning/trace_partitioning \ - engine/recursion engine/function_calls \ + engine/recursion engine/function_calls legacy/eval_annots \ engine/subdivided_evaluation engine/evaluation engine/abstractions \ engine/transfer_logic engine/transfer_stmt engine/transfer_specification \ engine/mem_exec engine/iterator engine/initialization \ diff --git a/src/plugins/value/engine/function_calls.ml b/src/plugins/value/engine/function_calls.ml index eff7dbc77a5f6901692fb0970623833be131f5d1..7c368ffcbae75ebe3692dc56160438b35fbe1548 100644 --- a/src/plugins/value/engine/function_calls.ml +++ b/src/plugins/value/engine/function_calls.ml @@ -123,6 +123,14 @@ let analysis_status kf = with Not_found -> Unreachable +(* Must be consistent with the choice made by [analysis_target] below. *) +let use_spec_instead_of_definition ?(recursion_depth = -1) kf = + Ast_info.is_frama_c_builtin (Kernel_function.get_name kf) || + Builtins.is_builtin_overridden kf || + recursion_depth >= Parameters.RecursiveUnroll.get () || + not (Kernel_function.is_definition kf) || + Kernel_function.Set.mem kf (Parameters.UsePrototype.get ()) + let analysis_target ~recursion_depth callsite kf = match Builtins.find_builtin_override kf with | Some (name, builtin, cache, spec) -> diff --git a/src/plugins/value/engine/function_calls.mli b/src/plugins/value/engine/function_calls.mli index 698b62406e5db83c76b697e55acfe2d9f5169b62..c7efe940d8855a9e75c262d02d27a52fcf2f103e 100644 --- a/src/plugins/value/engine/function_calls.mli +++ b/src/plugins/value/engine/function_calls.mli @@ -40,6 +40,11 @@ type analysis_target = val define_analysis_target: ?recursion_depth:int -> kinstr -> kernel_function -> analysis_target +(** Returns true if the Eva analysis use the specification of the given + function instead of its body to interpret its calls. *) +val use_spec_instead_of_definition: + ?recursion_depth:int -> kernel_function -> bool + (** Returns true if the function has been analyzed. *) val is_called: kernel_function -> bool diff --git a/src/plugins/value/engine/transfer_logic.ml b/src/plugins/value/engine/transfer_logic.ml index d56f52ae0bb0ea56cd3eacb2d6132902c6c4c731..634021c6eccb088daea3311546445e8d09afb663 100644 --- a/src/plugins/value/engine/transfer_logic.ml +++ b/src/plugins/value/engine/transfer_logic.ml @@ -54,7 +54,7 @@ let pp_p_kind fmt = function let post_kind kf = if Builtins.is_builtin_overridden kf then PostBuiltin - else if !Db.Value.use_spec_instead_of_definition kf then + else if Function_calls.use_spec_instead_of_definition kf then if Kernel_function.is_definition kf then PostUseSpec else PostLeaf diff --git a/src/plugins/value/engine/transfer_stmt.ml b/src/plugins/value/engine/transfer_stmt.ml index 8e3c04f6d31f20deb9bbaf4aa09966db3482974d..205ad005015a33b60aa4b9434cd0831b7ee4f963 100644 --- a/src/plugins/value/engine/transfer_stmt.ml +++ b/src/plugins/value/engine/transfer_stmt.ml @@ -85,7 +85,7 @@ let do_copy_at = function on functions whose body is analyzed. *) let is_determinate kf = let name = Kernel_function.get_name kf in - (warn_indeterminate kf || !Db.Value.use_spec_instead_of_definition kf) + (warn_indeterminate kf || Function_calls.use_spec_instead_of_definition kf) && not (Ast_info.is_frama_c_builtin name) let subdivide_stmt = Eva_utils.get_subdivision diff --git a/src/plugins/value/gui_files/gui_eval.ml b/src/plugins/value/gui_files/gui_eval.ml index 05ca7822f598f6266d533fc24a0ec3495b52da7a..691ec61e3e21054da275d86deaf89cf264b1147a 100644 --- a/src/plugins/value/gui_files/gui_eval.ml +++ b/src/plugins/value/gui_files/gui_eval.ml @@ -343,7 +343,7 @@ module Make (X: Analysis.S) = struct let pre = pre_kf kf callstack in let post = X.Dom.get_cvalue_or_top post in let result = - if !Db.Value.use_spec_instead_of_definition kf then + if Function_calls.use_spec_instead_of_definition kf then None else let ret_stmt = Kernel_function.find_return kf in @@ -395,7 +395,8 @@ module Make (X: Analysis.S) = struct normal termination, and only when the function is called. After states are not available. *) let callstacks_at_post kf = - if not (!Db.Value.use_spec_instead_of_definition kf) && results_kf_computed kf + if not (Function_calls.use_spec_instead_of_definition kf) + && results_kf_computed kf then let ret = Kernel_function.find_return kf in let states_before = X.get_stmt_state_by_callstack ~after:true ret in diff --git a/src/plugins/value/legacy/eval_annots.ml b/src/plugins/value/legacy/eval_annots.ml index 8c83557fd2a766d1dde996152ae20a256e009ece..4bf4155529115dd9930da1dc8a5f579a32f3e1c4 100644 --- a/src/plugins/value/legacy/eval_annots.ml +++ b/src/plugins/value/legacy/eval_annots.ml @@ -109,7 +109,7 @@ let mark_unreachable () = Visitor.visitFramacFileFunctions unreach (Ast.get ()) let c_labels kf cs = - if !Db.Value.use_spec_instead_of_definition kf then + if Function_calls.use_spec_instead_of_definition kf then Cil_datatype.Logic_label.Map.empty else let fdec = Kernel_function.get_definition kf in diff --git a/src/plugins/value/register.ml b/src/plugins/value/register.ml index c1e1695ae85b438899b4c2d4199c034d24a20eae..8732d620e1aca7f1c02075cfd2cb79d35ea9e81b 100644 --- a/src/plugins/value/register.ml +++ b/src/plugins/value/register.ml @@ -124,14 +124,6 @@ let find_deps_term_no_transitivity_state state t = r.Eval_terms.ldeps with Eval_terms.LogicEvalError _ -> raise Db.From.Not_lval -(* If the function is a builtin, or if the user has requested it, use - \assigns and \from clauses, that give an approximation of the result *) -let use_spec_instead_of_definition kf = - not (Kernel_function.is_definition kf) || - Ast_info.is_frama_c_builtin (Kernel_function.get_name kf) || - Builtins.is_builtin_overridden kf || - Kernel_function.Set.mem kf (Parameters.UsePrototype.get ()) - let eval_predicate ~pre ~here p = let open Eval_terms in let env = env_annot ~pre ~here () in @@ -153,7 +145,8 @@ let valid_behaviors kf state = let () = (* Pretty-printing *) - Db.Value.use_spec_instead_of_definition := use_spec_instead_of_definition; + Db.Value.use_spec_instead_of_definition := + Function_calls.use_spec_instead_of_definition; Db.Value.assigns_outputs_to_zone := assigns_outputs_to_zone; Db.Value.assigns_outputs_to_locations := assigns_outputs_to_locations; Db.Value.assigns_inputs_to_zone := assigns_inputs_to_zone;