From 62a6836681b47d302c0ef2e8143ab3a59c7e69ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Bobot?= <francois.bobot@cea.fr> Date: Mon, 25 Sep 2017 08:39:04 +0200 Subject: [PATCH] [Eva] prints start call finalize call --- .../value/domains/traces/traces_domain.ml | 89 ++++++++++----- tests/value/traces/oracle/test1.res.oracle | 89 ++++++++------- tests/value/traces/oracle/test2.err.oracle | 0 tests/value/traces/oracle/test2.res.oracle | 108 ++++++++++++++++++ tests/value/traces/test2.i | 22 ++++ 5 files changed, 236 insertions(+), 72 deletions(-) create mode 100644 tests/value/traces/oracle/test2.err.oracle create mode 100644 tests/value/traces/oracle/test2.res.oracle create mode 100644 tests/value/traces/test2.i diff --git a/src/plugins/value/domains/traces/traces_domain.ml b/src/plugins/value/domains/traces/traces_domain.ml index 5bc65500f86..b7d352f791e 100644 --- a/src/plugins/value/domains/traces/traces_domain.ml +++ b/src/plugins/value/domains/traces/traces_domain.ml @@ -207,10 +207,56 @@ module Traces = struct let g = join_graph m c.graph in { start = c.start; current = n; graph = g} + + let is_included c1 c2 = + (* start is the same *) + c1.start = c2.start && + (* there are epsilons transition (Msg) between c1.current and + c2.current *) + let rec epsilon_path current stop g = + Node.equal current stop || + begin + Node.compare current stop <= 0 && + match Graph.find current g with + | exception Not_found -> false + | l -> + let exists = function + | Msg (n,_) -> epsilon_path n stop g + | _ -> false + in + List.exists exists l + end + in + epsilon_path c1.current c2.current c2.graph + && + (* The graph is c1.graph is included into c2.graph *) + let rec decide_both k l1 l2 = + match l1, l2 with + | [], _ -> true + | _, [] -> false + | h1 :: t1, h2 :: t2 -> + let c = Edge.compare h1 h2 in + if c = 0 + then decide_both k t1 t2 + else if c < 0 + then false + else decide_both k l1 t2 + in + Graph.binary_predicate + Hptmap_sig.NoCache + Graph.UniversalPredicate + ~decide_fast:Graph.decide_fast_inclusion + ~decide_fst:(fun _ _ -> false) + ~decide_snd:(fun _ _ -> true) + ~decide_both + c1.graph c2.graph + let join c1 c2 = match view c1, view c2 with | `Top, _ -> c1 | _, `Top -> c2 + | `Other c1, `Other c2 when is_included c1 c2 -> c2 + | `Other c1, `Other c2 when is_included c2 c1 -> c1 | `Other c1, `Other c2 -> if c1.start <> c2.start then assert false else @@ -235,30 +281,6 @@ module Traces = struct {start = c1.start; current = n; graph = g} let narrow _c1 c2 = `Value c2 - - let is_included c1 c2 = - c1.start = c2.start && - (* don't compare current we are at the same place *) - let rec decide_both k l1 l2 = - match l1, l2 with - | [], _ -> true - | _, [] -> false - | h1 :: t1, h2 :: t2 -> - let c = Edge.compare h1 h2 in - if c = 0 - then decide_both k t1 t2 - else if c < 0 - then false - else decide_both k l1 t2 - in - Graph.binary_predicate - Hptmap_sig.NoCache - Graph.UniversalPredicate - ~decide_fast:Graph.decide_fast_inclusion - ~decide_fst:(fun _ _ -> false) - ~decide_snd:(fun _ _ -> true) - ~decide_both - c1.graph c2.graph end let key = Structure.Key_Domain.create_key "traces domain" @@ -299,9 +321,17 @@ module Internal = struct let assume _stmt e pos _valuation state = `Value(Traces.add_edge state (Assume(0,e,pos))) - let start_call _stmt _call _valuation state = `Value state + let start_call _stmt call _valuation state = + let msg = + Format.asprintf "start_call: %a" (Pretty_utils.pp_list ~sep:",@ " + (fun fmt v -> Cil_datatype.Varinfo.pretty fmt v.Eval.formal)) + call.Eval.arguments in + let state = Traces.add_edge state (Msg(0,msg)) in + `Value state - let finalize_call _stmt _call ~pre:_ ~post = `Value post + let finalize_call _stmt call ~pre:_ ~post = + `Value (Traces.add_edge post (Msg(0,Format.asprintf "finalize_call: %a" + (Pretty_utils.pp_opt Cil_datatype.Varinfo.pretty) call.Eval.return))) let update _valuation state = `Value state @@ -320,9 +350,10 @@ module Internal = struct let reuse _kf _bases ~current_input:_ ~previous_output:state = state let empty () = Traces.empty - let introduce_globals _vars state = state - let initialize_variable _ _ ~initialized:_ _ state = state - let initialize_variable_using_type _ _ state = state + let introduce_globals _vars state = Traces.add_edge state (Msg(0,"introduce globals")) + let initialize_variable lv _ ~initialized:_ _ state = + Traces.add_edge state (Msg(0,Format.asprintf "initialize variable: %a" Printer.pp_lval lv )) + let initialize_variable_using_type _ _ state = Traces.add_edge state (Msg(0,"initialize variable using type")) (* TODO *) let logic_assign _assign _location ~pre:_ _state = top diff --git a/tests/value/traces/oracle/test1.res.oracle b/tests/value/traces/oracle/test1.res.oracle index f16e857bb12..47b04471d6d 100644 --- a/tests/value/traces/oracle/test1.res.oracle +++ b/tests/value/traces/oracle/test1.res.oracle @@ -10,50 +10,53 @@ tests/value/traces/test1.i:14:[value] Frama_C_dump_each: tmp ∈ {4; 5} # Value.Traces_domain.Traces.t: start: 0 - {[ 0 -> ([ EnterScope: tmp -> 1 ]) - 1 -> ([ Assign: tmp = 0; -> 2 ]) - 2 -> ([ Assume: c false -> 3; Assume: c true -> 4 ]) - 3 -> ([ Assign: tmp = 2; -> 7 ]) - 4 -> ([ Assign: tmp = 1; -> 6 ]) - 6 -> ([ EnterScope: i -> 11 ]) - 7 -> ([ EnterScope: i -> 9 ]) - 9 -> ([ Assign: int i = 0; -> 10 ]) - 10 -> ([ enter_loop -> 15 ]) + {[ 0 -> ([ initialize variable using type -> 1 ]) + 1 -> ([ EnterScope: tmp -> 2 ]) + 2 -> ([ Assign: tmp = 0; -> 3 ]) + 3 -> ([ Assume: c false -> 4; Assume: c true -> 5 ]) + 4 -> ([ Assign: tmp = 2; -> 8 ]) + 5 -> ([ Assign: tmp = 1; -> 7 ]) + 7 -> ([ EnterScope: i -> 13 ]) + 8 -> ([ EnterScope: i -> 10 ]) + 10 -> ([ initialize variable: i -> 11 ]) 11 -> ([ Assign: int i = 0; -> 12 ]) - 12 -> ([ enter_loop -> 14 ]) - 14 -> ([ Assume: i < 3 true -> 17 ]) - 15 -> ([ Assume: i < 3 true -> 18 ]) - 17 -> ([ Assign: tmp ++; -> 20 ]) - 18 -> ([ Assign: tmp ++; -> 19 ]) - 19 -> ([ Assign: i ++; -> 21 ]) - 20 -> ([ Assign: i ++; -> 22 ]) - 21 -> ([ incr_loop_counter -> 25 ]) - 22 -> ([ incr_loop_counter -> 24 ]) - 24 -> ([ Assume: i < 3 true -> 28 ]) - 25 -> ([ Assume: i < 3 true -> 29 ]) - 28 -> ([ Assign: tmp ++; -> 31 ]) - 29 -> ([ Assign: tmp ++; -> 30 ]) - 30 -> ([ Assign: i ++; -> 33 ]) - 31 -> ([ Assign: i ++; -> 32 ]) - 32 -> ([ incr_loop_counter -> 37 ]) - 33 -> ([ incr_loop_counter -> 36 ]) - 36 -> ([ Assume: i < 3 true -> 40 ]) - 37 -> ([ Assume: i < 3 true -> 41 ]) - 40 -> ([ Assign: tmp ++; -> 43 ]) - 41 -> ([ Assign: tmp ++; -> 42 ]) - 42 -> ([ Assign: i ++; -> 45 ]) - 43 -> ([ Assign: i ++; -> 44 ]) - 44 -> ([ incr_loop_counter -> 49 ]) - 45 -> ([ incr_loop_counter -> 48 ]) - 48 -> ([ Assume: i < 3 false -> 52 ]) - 49 -> ([ Assume: i < 3 false -> 53 ]) - 52 -> ([ leave_loop -> 55 ]) - 53 -> ([ leave_loop -> 54 ]) - 54 -> ([ LeaveScope: i -> 57 ]) - 55 -> ([ LeaveScope: i -> 56 ]) - 56 -> ([ join -> 58 ]) - 57 -> ([ join -> 58 ]) ]} - current: 58] + 12 -> ([ enter_loop -> 18 ]) + 13 -> ([ initialize variable: i -> 14 ]) + 14 -> ([ Assign: int i = 0; -> 15 ]) + 15 -> ([ enter_loop -> 17 ]) + 17 -> ([ Assume: i < 3 true -> 20 ]) + 18 -> ([ Assume: i < 3 true -> 21 ]) + 20 -> ([ Assign: tmp ++; -> 23 ]) + 21 -> ([ Assign: tmp ++; -> 22 ]) + 22 -> ([ Assign: i ++; -> 24 ]) + 23 -> ([ Assign: i ++; -> 25 ]) + 24 -> ([ incr_loop_counter -> 28 ]) + 25 -> ([ incr_loop_counter -> 27 ]) + 27 -> ([ Assume: i < 3 true -> 31 ]) + 28 -> ([ Assume: i < 3 true -> 32 ]) + 31 -> ([ Assign: tmp ++; -> 34 ]) + 32 -> ([ Assign: tmp ++; -> 33 ]) + 33 -> ([ Assign: i ++; -> 36 ]) + 34 -> ([ Assign: i ++; -> 35 ]) + 35 -> ([ incr_loop_counter -> 40 ]) + 36 -> ([ incr_loop_counter -> 39 ]) + 39 -> ([ Assume: i < 3 true -> 43 ]) + 40 -> ([ Assume: i < 3 true -> 44 ]) + 43 -> ([ Assign: tmp ++; -> 46 ]) + 44 -> ([ Assign: tmp ++; -> 45 ]) + 45 -> ([ Assign: i ++; -> 48 ]) + 46 -> ([ Assign: i ++; -> 47 ]) + 47 -> ([ incr_loop_counter -> 52 ]) + 48 -> ([ incr_loop_counter -> 51 ]) + 51 -> ([ Assume: i < 3 false -> 55 ]) + 52 -> ([ Assume: i < 3 false -> 56 ]) + 55 -> ([ leave_loop -> 58 ]) + 56 -> ([ leave_loop -> 57 ]) + 57 -> ([ LeaveScope: i -> 60 ]) + 58 -> ([ LeaveScope: i -> 59 ]) + 59 -> ([ join -> 61 ]) + 60 -> ([ join -> 61 ]) ]} + current: 61] ==END OF DUMP== [value] Recording results for main [value] done for function main diff --git a/tests/value/traces/oracle/test2.err.oracle b/tests/value/traces/oracle/test2.err.oracle new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/value/traces/oracle/test2.res.oracle b/tests/value/traces/oracle/test2.res.oracle new file mode 100644 index 00000000000..a0188abe8a2 --- /dev/null +++ b/tests/value/traces/oracle/test2.res.oracle @@ -0,0 +1,108 @@ +[kernel] Parsing tests/value/traces/test2.i (no preprocessing) +[value] Analyzing a complete application starting at main +[value] Computing initial state +[value] Initial state computed +[value:initial-state] Values of globals at initialization + +[value] computing for function loop <- main. + Called from tests/value/traces/test2.i:18. +[value] Recording results for loop +[value] Done for function loop +[value] computing for function loop <- main. + Called from tests/value/traces/test2.i:18. +[value] Recording results for loop +[value] Done for function loop +tests/value/traces/test2.i:20:[value] Frama_C_dump_each: + # Cvalue domain: + c ∈ [--..--] + tmp ∈ {4; 5} + # Value.Traces_domain.Traces.t: + start: 0 + {[ 0 -> ([ initialize variable using type -> 1 ]) + 1 -> ([ EnterScope: tmp -> 2 ]) + 2 -> ([ Assign: tmp = 0; -> 3 ]) + 3 -> ([ Assume: c false -> 4; Assume: c true -> 5 ]) + 4 -> ([ Assign: tmp = 2; -> 8 ]) + 5 -> ([ Assign: tmp = 1; -> 7 ]) + 7 -> ([ start_call: j -> 9 ]) + 8 -> ([ start_call: j -> 53 ]) + 9 -> ([ EnterScope: i -> 10 ]) + 10 -> ([ initialize variable: i -> 11 ]) + 11 -> ([ Assign: int i = 0; -> 12 ]) + 12 -> ([ enter_loop -> 13 ]) + 13 -> ([ Assume: i < 3 true -> 14 ]) + 14 -> ([ Assign: j ++; -> 15 ]) + 15 -> ([ Assign: i ++; -> 16 ]) + 16 -> ([ incr_loop_counter -> 17 ]) + 17 -> ([ Assume: i < 3 true -> 19 ]) + 19 -> ([ Assign: j ++; -> 20 ]) + 20 -> ([ Assign: i ++; -> 21 ]) + 21 -> ([ incr_loop_counter -> 23 ]) + 23 -> ([ Assume: i < 3 true -> 25 ]) + 25 -> ([ Assign: j ++; -> 26 ]) + 26 -> ([ Assign: i ++; -> 27 ]) + 27 -> ([ incr_loop_counter -> 29 ]) + 29 -> ([ Assume: i < 3 false -> 31 ]) + 31 -> ([ leave_loop -> 32 ]) + 32 -> ([ LeaveScope: i -> 33 ]) + 33 -> ([ EnterScope: \result<loop> -> 34 ]) + 34 -> ([ Assign: return j; -> 35 ]) + 35 -> ([ LeaveScope: j -> 49 ]) + 49 -> ([ finalize_call: \result<loop> -> 50 ]) + 50 -> ([ Assign: tmp = loop(tmp); -> 51 ]) + 51 -> ([ LeaveScope: \result<loop> -> 52 ]) + 52 -> ([ join -> 116 ]) + 53 -> ([ EnterScope: i -> 55 ]) + 55 -> ([ initialize variable: i -> 56 ]) + 56 -> ([ Assign: int i = 0; -> 57 ]) + 57 -> ([ enter_loop -> 58 ]) + 58 -> ([ Assume: i < 3 true -> 59 ]) + 59 -> ([ Assign: j ++; -> 60 ]) + 60 -> ([ Assign: i ++; -> 61 ]) + 61 -> ([ incr_loop_counter -> 62 ]) + 62 -> ([ Assume: i < 3 true -> 64 ]) + 64 -> ([ Assign: j ++; -> 65 ]) + 65 -> ([ Assign: i ++; -> 66 ]) + 66 -> ([ incr_loop_counter -> 68 ]) + 68 -> ([ Assume: i < 3 true -> 70 ]) + 70 -> ([ Assign: j ++; -> 71 ]) + 71 -> ([ Assign: i ++; -> 72 ]) + 72 -> ([ incr_loop_counter -> 74 ]) + 74 -> ([ Assume: i < 3 false -> 76 ]) + 76 -> ([ leave_loop -> 77 ]) + 77 -> ([ LeaveScope: i -> 78 ]) + 78 -> ([ EnterScope: \result<loop> -> 79 ]) + 79 -> ([ Assign: return j; -> 80 ]) + 80 -> ([ LeaveScope: j -> 112 ]) + 112 -> ([ finalize_call: \result<loop> -> 113 ]) + 113 -> ([ Assign: tmp = loop(tmp); -> 114 ]) + 114 -> ([ LeaveScope: \result<loop> -> 115 ]) + 115 -> ([ join -> 116 ]) ]} + current: 116] + ==END OF DUMP== +[value] Recording results for main +[value] done for function main +[value] ====== VALUES COMPUTED ====== +[value:final-states] Values at end of function loop: + j ∈ {4; 5} +[value:final-states] Values at end of function main: + tmp ∈ {4; 5} +[from] Computing for function loop +[from] Done for function loop +[from] Computing for function main +[from] Done for function main +[from] ====== DEPENDENCIES COMPUTED ====== + These dependencies hold at termination for the executions that terminate: +[from] Function loop: + \result FROM j +[from] Function main: + \result FROM c +[from] ====== END OF DEPENDENCIES ====== +[inout] Out (internal) for function loop: + j; i +[inout] Inputs for function loop: + \nothing +[inout] Out (internal) for function main: + tmp +[inout] Inputs for function main: + \nothing diff --git a/tests/value/traces/test2.i b/tests/value/traces/test2.i new file mode 100644 index 00000000000..c04aebeee14 --- /dev/null +++ b/tests/value/traces/test2.i @@ -0,0 +1,22 @@ +/* run.config + STDOPT: #"-eva-traces-domain -value-msg-key d-traces -slevel 10" +*/ + + +int loop(int j){ + for(int i = 0; i < 3; i++){ + j ++; + } + return j; +} + +int main(int c){ + int tmp; + tmp = 0; + if (c) tmp = 1; + else tmp = 2; + tmp = loop(tmp); + //@ slevel merge; + Frama_C_dump_each(); + return c; +} -- GitLab