diff --git a/src/plugins/eva/engine/transfer_logic.ml b/src/plugins/eva/engine/transfer_logic.ml index 5dc4ddfdc11bc4fd0ba6a5465fa363f9a5e852e9..41aa1bc0dcc998b4bc84eaf8866910479fe1784f 100644 --- a/src/plugins/eva/engine/transfer_logic.ml +++ b/src/plugins/eva/engine/transfer_logic.ml @@ -27,7 +27,26 @@ open Eval let ignore_predicate named_pred = List.exists (fun tag -> tag = "no_eva") named_pred.Cil_types.pred_name -(* -------------------------- Message emission ------------------------------ *) +let create_conjunction l= + let loc = match l with + | [] -> None + | p :: _ -> Some (Logic_const.pred_of_id_pred p).pred_loc + in + Logic_const.(List.fold_right (fun p1 p2 -> pand ?loc (p1, p2)) (List.map pred_of_id_pred l) ptrue) + +let ip_from_precondition kf call_ki b pre = + let ip_precondition = Property.ip_of_requires kf Kglobal b pre in + match call_ki with + | Kglobal -> (* status of the main function. We update the global + status, and pray that there is no recursion. + TODO: check what the WP does.*) + ip_precondition + | Kstmt stmt -> + (* choose the copy of the precondition on the call point [stmt]. *) + Statuses_by_call.setup_precondition_proxy kf ip_precondition; + Statuses_by_call.precondition_at_call kf ip_precondition stmt + +(* --------------------- Message and status emission ------------------------ *) (* The function that puts statuses on pre- and post-conditions is essentially agnostic as to which kind of property it operates on. However, the messages @@ -60,15 +79,15 @@ let post_kind kf = else PostLeaf else PostBody -let conv_status = function - | Alarmset.False -> Property_status.False_if_reachable; - | Alarmset.True -> Property_status.True; - | Alarmset.Unknown -> Property_status.Dont_know - let emit_status ppt status = - if status = Property_status.False_if_reachable then begin + let status = + match status with + | Alarmset.False -> Property_status.False_if_reachable; + | Alarmset.True -> Property_status.True; + | Alarmset.Unknown -> Property_status.Dont_know + in + if status = Property_status.False_if_reachable then Red_statuses.add_red_property (Property.get_kinstr ppt) ppt; - end; Property_status.emit ~distinct:true Eva_utils.emitter ~hyps:[] ppt status (* Display the message as result/warning depending on [status] *) @@ -111,7 +130,7 @@ let pp_predicate behavior kind fmt named_pred = in Format.fprintf fmt "%a%a" pp_p_kind kind pp_predicate named_pred -let emit_message_and_status kind kf behavior ~active ~empty property named_pred status = +let emit_contract_status kind kf behavior ~active ~empty property named_pred status = let pp_predicate = pp_predicate behavior kind in let source = fst (Property.location property) in match kind with @@ -124,34 +143,51 @@ let emit_message_and_status kind kf behavior ~active ~empty property named_pred Alarmset.Status.pretty status (if active then (fun _ -> ()) else behavior_inactive) Eva_utils.pp_callstack; - emit_status property (conv_status status); + emit_status property status; | Postcondition postk -> (* Do not emit a status for leaf functions or builtins. Otherwise, we would overwrite the "considered valid" status of the kernel. *) if emit_postcond_status postk - then emit_status property (conv_status status) + then emit_status property status | Assumes -> (* No statuses are emitted for 'assumes' clauses, and for the moment we do not emit text either *) () -let create_conjunction l= - let loc = match l with - | [] -> None - | p :: _ -> Some (Logic_const.pred_of_id_pred p).pred_loc +let pp_code_annot fmt ca = + match ca.annot_content with + | AAssert (_,{ tp_kind; tp_statement }) -> + let kind = Cil_printer.name_of_assert tp_kind in + Format.fprintf fmt "%s%a" kind Description.pp_named tp_statement + | AInvariant (_, _, { tp_statement }) -> + Format.fprintf fmt "loop invariant%a" Description.pp_named tp_statement + | AExtended (_, _, extension) -> + Format.fprintf fmt "%s annotation" extension.ext_name; + | APragma _ | AVariant _ | AAssigns _ | AAllocation _ | AStmtSpec _ -> + assert false (* currently not treated by Eva *) + +(* location of the given code annotation. If unknown, use the location of the + statement instead. *) +let code_annotation_loc stmt code_annot = + match Cil_datatype.Code_annotation.loc code_annot with + | Some loc when not (Cil_datatype.Location.(equal loc unknown)) -> loc + | _ -> Cil_datatype.Stmt.loc stmt + +let emit_code_annot_status ~reduce ~empty kf stmt code_annot status = + let source, _ = code_annotation_loc stmt code_annot in + let ips = Property.ip_of_code_annot kf stmt code_annot in + List.iter (fun p -> emit_status p status) ips; + let message = + match status with + | Alarmset.Unknown -> "unknown" + | Alarmset.True -> "valid" + | Alarmset.False -> + "invalid" ^ (if reduce then " (stopping propagation)" else "") in - Logic_const.(List.fold_right (fun p1 p2 -> pand ?loc (p1, p2)) (List.map pred_of_id_pred l) ptrue) + let prefix = if empty then "no state left, " else "" in + msg_status status ~once:true ~source + "%s%a got status %s." prefix pp_code_annot code_annot message -let ip_from_precondition kf call_ki b pre = - let ip_precondition = Property.ip_of_requires kf Kglobal b pre in - match call_ki with - | Kglobal -> (* status of the main function. We update the global - status, and pray that there is no recursion. - TODO: check what the WP does.*) - ip_precondition - | Kstmt stmt -> - (* choose the copy of the precondition on the call point [stmt]. *) - Statuses_by_call.setup_precondition_proxy kf ip_precondition; - Statuses_by_call.precondition_at_call kf ip_precondition stmt +(* --------------------- Process inactive behaviors ------------------------- *) (* Emits informative messages about inactive behaviors, and emits a valid status for requires and ensures that have not been evaluated. *) @@ -163,14 +199,14 @@ let process_inactive_behavior kf call_ki behavior = emitted := true; if emit_postcond_status (post_kind kf) then let ip = Property.ip_of_ensures kf Kglobal behavior post in - emit_status ip Property_status.True; + emit_status ip Alarmset.True; end ) behavior.b_post_cond; List.iter (fun pre -> if pre.ip_content.tp_kind <> Admit then begin emitted := true; let ip = ip_from_precondition kf call_ki behavior pre in - emit_status ip Property_status.True; + emit_status ip Alarmset.True; end ) behavior.b_requires; if !emitted then @@ -192,7 +228,7 @@ let process_inactive_postconds kf inactive_bhvs = emitted := true; if emit_postcond_status (post_kind kf) then let ip = Property.ip_of_ensures kf Kglobal b post in - emit_status ip Property_status.True; + emit_status ip Alarmset.True; end ) b.b_post_cond; if !emitted then @@ -201,6 +237,57 @@ let process_inactive_postconds kf inactive_bhvs = (pp_header kf) b Eva_utils.pp_callstack; ) inactive_bhvs + +(* ---------------- Evaluation of "calls" ACSL extension ------------------- *) + +let get_call term = + match term.term_node with + | TLval (TVar { lv_origin = Some v }, TNoOffset ) -> Globals.Functions.get v + | _ -> raise Not_found + +(* Returns the list of kernel functions referred to by a "calls" annotation, + or raise exception Not_found if it is not a proper "calls" annotation. *) +let get_calls_kf code_annot = + match code_annot.annot_content with + | AExtended (_, _, { ext_kind = Ext_terms terms }) -> List.map get_call terms + | _ -> raise Not_found + +(* Returns the "calls" annotations at statement [stmt]. *) +let get_calls_annotations stmt = + let filter code_annot = + match code_annot.annot_content with + | AExtended (_, _, e) -> e.ext_name = "calls" && e.ext_has_status + | _ -> false + in + Annotations.code_annot ~filter stmt + +(* Checks one "calls" annotation [code_annot] at statement [stmt]. *) +let check_calls_annotation stmt called_functions code_annot = + match get_calls_kf code_annot with + | exception Not_found -> + Self.warning ~current:true ~once:true + "Ignoring invalid calls annotation: %a" + Printer.pp_code_annotation code_annot; + called_functions + | kfs -> + let length = List.length called_functions in + let kfs = Kernel_function.Set.of_list kfs in + let is_call (kf, _) = Kernel_function.Set.mem kf kfs in + let called_functions = List.filter is_call called_functions in + let status = + match List.length called_functions with + | 0 -> Alarmset.False + | l when l = length -> Alarmset.True + | _ -> Alarmset.Unknown + in + let kf = Kernel_function.find_englobing_kf stmt in + emit_code_annot_status ~reduce:true ~empty:false kf stmt code_annot status; + called_functions + +let check_calls_annotations stmt called_functions = + let calls = get_calls_annotations stmt in + List.fold_left (check_calls_annotation stmt) called_functions calls + (* -------------------------------- Functor --------------------------------- *) module type S = sig @@ -392,7 +479,7 @@ module Make the pre- and post-states. *) let eval_and_reduce kf behavior active kind ips states build_prop build_env = let limit = Eva_utils.get_slevel kf in - let emit = emit_message_and_status kind kf behavior ~active in + let emit = emit_contract_status kind kf behavior ~active in let aux_pred states pred = let pr = Logic_const.pred_of_id_pred pred in let record = pred.ip_content.tp_kind <> Admit in @@ -534,30 +621,12 @@ module Make let assumes = create_conjunction behavior.b_assumes in Domain.evaluate_predicate pre_env state assumes - let code_annotation_text ca = - match ca.annot_content with - | AAssert (_,{tp_kind}) -> Cil_printer.name_of_assert tp_kind - | AInvariant _ -> "loop invariant" - | APragma _ | AVariant _ | AAssigns _ | AAllocation _ | AStmtSpec _ - | AExtended _ -> - assert false (* currently not treated by Value *) - - (* location of the given code annotation. If unknown, use the location of the - statement instead. *) - let code_annotation_loc ca stmt = - match Cil_datatype.Code_annotation.loc ca with - | Some loc when not (Cil_datatype.Location.(equal loc unknown)) -> loc - | _ -> Cil_datatype.Stmt.loc stmt - (* Reduce the given states according to the given code annotations. If [record] is true, update the proof state of the code annotation. DO NOT PASS record=false unless you know what your are doing *) let interp_annot ~limit ~record kf ab stmt code_annot ~initial_state states = - let ips = Property.ip_of_code_annot kf stmt code_annot in - let source, _ = code_annotation_loc code_annot stmt in let aux_interp ~record ~reduce code_annot behav p = - let text = code_annotation_text code_annot in let in_behavior = match behav with | [] -> `True @@ -573,36 +642,13 @@ module Make match in_behavior with | `False -> states | `True | `Unknown as in_behavior -> - let emit status = - let change_status st = List.iter (fun p -> emit_status p st) ips in - let message = - match status, in_behavior with - | Alarmset.Unknown, _ -> - change_status Property_status.Dont_know; - "unknown" - | Alarmset.True, _ -> - change_status Property_status.True; - "valid" - | Alarmset.False, `True -> - change_status Property_status.False_if_reachable; - "invalid" ^ (if reduce then " (stopping propagation)" else "") - | Alarmset.False, `Unknown -> - change_status Property_status.False_if_reachable; - "invalid" - in - msg_status status ~once:true ~source - "%s%a got status %s." text Description.pp_named p message - in + (* No reduction if the behavior might be inactive. *) + let reduce = reduce && in_behavior = `True in + let emit = emit_code_annot_status ~reduce ~empty:false kf stmt in let reduce_state here res accstateset = - match res, in_behavior with - | _, `Unknown -> - (* Cannot conclude because behavior might be inactive *) - States.add here accstateset - - | Alarmset.False, `True -> (* Dead/invalid branch *) - accstateset - - | (Alarmset.Unknown | Alarmset.True), `True -> + match res with + | Alarmset.False -> accstateset (* Dead/invalid branch *) + | Alarmset.Unknown | Alarmset.True -> let env = here_env ~pre:initial_state ~here in (* Reduce by p if it is a disjunction, or if it did not evaluate to True *) @@ -618,7 +664,7 @@ module Make let env = here_env ~pre:initial_state ~here in let res = Domain.evaluate_predicate env here p in (* if [record] holds, emit kernel status and print a message *) - if record then emit res; + if record then emit code_annot res; (* if [reduce] holds, reduce the state. *) if reduce then reduce_state here res accstateset else accstateset) states States.empty @@ -631,13 +677,9 @@ module Make if ignore_predicate p then states else if States.is_empty states then ( - if record then begin - let text = code_annotation_text code_annot in - List.iter (fun p -> emit_status p Property_status.True) ips; - msg_status Alarmset.True ~once:true ~source - "no state left, %s%a got status valid." - text Description.pp_named p; - end; + if record then + emit_code_annot_status ~reduce:true ~empty:true + kf stmt code_annot Alarmset.True; states ) else aux_interp ~record ~reduce code_annot behav p diff --git a/src/plugins/eva/engine/transfer_logic.mli b/src/plugins/eva/engine/transfer_logic.mli index 38969a61a1fc9c5be16db705370f437549f8f2ae..5cce864ef90908be7a9c194f25e93d63da904c6b 100644 --- a/src/plugins/eva/engine/transfer_logic.mli +++ b/src/plugins/eva/engine/transfer_logic.mli @@ -27,6 +27,12 @@ open Eval val process_inactive_behaviors: kinstr -> kernel_function -> behavior list -> unit +(* Checks "calls" annotations at the given statement according to the inferred + list of functions at this point. Reduces the given list to the functions + referred to by "calls" annotations. *) +val check_calls_annotations: + stmt -> (kernel_function * 'a) list -> (kernel_function * 'a) list + module type S = sig type state type states diff --git a/src/plugins/eva/engine/transfer_stmt.ml b/src/plugins/eva/engine/transfer_stmt.ml index 33fc8fc4c3abc07ded45489725070c179790d20e..f9e0d865b6134bdc577b419c581cd1b986b022d3 100644 --- a/src/plugins/eva/engine/transfer_stmt.ml +++ b/src/plugins/eva/engine/transfer_stmt.ml @@ -735,6 +735,8 @@ module Make (Abstract: Abstractions.S_with_evaluation) = struct let cacheable = ref Cacheable in let eval = let+ functions = functions in + (* Check "calls" annotations, and reduce called functions accordingly. *) + let functions = Transfer_logic.check_calls_annotations stmt functions in let process_one_function kf valuation = (* The special Frama_C_ functions to print states are handled here. *) if apply_special_directives ~subdivnb kf args state diff --git a/tests/value/calls_annotation.i b/tests/value/calls_annotation.i new file mode 100644 index 0000000000000000000000000000000000000000..3a9b799aa1dcca30aebad979fb7ff4e956b437a7 --- /dev/null +++ b/tests/value/calls_annotation.i @@ -0,0 +1,101 @@ +/* run.config* + STDOPT: +*/ + +/* This file tests the evaluation of the logical status of "calls" annotations, + and the reduction of called functions accordingly. */ + +volatile unsigned int nondet; + +int incr(int x) { + return x+1; +} + +int decr(int x) { + return x-1; +} + +int square(int x) { + return x*x; +} + +/* Should be never called according to "calls" annotations. */ +int error(int x) { + return x / 0; +} + +int unreachable(int x) { + return 0; +} + +typedef int (*fptr)(int); + +fptr funs[4] = { &incr, &decr, &square, &error }; + +int apply(fptr fp, int a) { + int x; + //@ calls incr, decr, square; // unknown: error could also be called + x = (*fp)(a); + //@ calls incr, decr, square; // valid as consequence of the previous one + x = (*fp)(x); + return x; +} + +void main(void) { + int a = 1, i = 0; + + /* Valid "calls" annotations. */ + //@ calls decr; // valid singleton + a = (*funs[1])(a); + i = nondet % 3; + //@ calls incr, decr, square; // valid + a = (*funs[i])(a); + //@ calls incr, decr, square, unreachable; // valid but contains unreachable + a = (*funs[i])(a); + + /* Unknown "calls" annotations: Eva can reduce the called functions. */ + i = nondet % 4; + //@ calls incr, decr; // unknown: square and error could also be called + a = (*funs[i])(a); + Frama_C_show_each_0_1(i); // i can be reduced to {0; 1} + + /* Invalid "calls" annotations. */ + if (nondet) { + //@ calls incr; // invalid + a = (*funs[1])(a); + Frama_C_show_each_UNREACHABLE(); + } + if (nondet) { + i = nondet % 2; + //@ calls square, unreachable; // invalid + a = (*funs[i])(a); + Frama_C_show_each_UNREACHABLE(i); + } + + /* "calls" annotations evaluated in multiple states. */ + //@ loop unroll 4; + for (int j = 0; j < 4; j++) { + a = 0; + //@ calls incr; // valid at each iteration + a = (*funs[0])(a); + //@ calls incr, decr; // valid at each iteration + a = (*funs[j % 2])(a); + i = nondet % (j+1); + //@ calls incr, decr, square; // valid then unknown at the last iteration + a = (*funs[i])(a); + if (nondet) { + //@ calls incr, decr, square; // invalid at the last iteration + a = (*funs[j])(a); + if (j == 3) Frama_C_show_each_UNREACHABLE(j); // j == 3 is impossible here. + } + if (nondet) { + a = apply(funs[j], a); // invalid at the last iteration + if (j == 3) Frama_C_show_each_UNREACHABLE(j); // j == 3 is impossible here. + } + if (nondet) { + //@ calls unreachable; // invalid at each iteration + a = (*funs[j])(a); + Frama_C_show_each_UNREACHABLE(a); + } + } +} diff --git a/tests/value/oracle/calls_annotation.res.oracle b/tests/value/oracle/calls_annotation.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..e22c92eeaa06b83e9ad93056ae0a1ba807bfda18 --- /dev/null +++ b/tests/value/oracle/calls_annotation.res.oracle @@ -0,0 +1,209 @@ +[kernel] Parsing calls_annotation.i (no preprocessing) +[eva] Analyzing a complete application starting at main +[eva] Computing initial state +[eva] Initial state computed +[eva:initial-state] Values of globals at initialization + nondet ∈ [--..--] + funs[0] ∈ {{ &incr }} + [1] ∈ {{ &decr }} + [2] ∈ {{ &square }} + [3] ∈ {{ &error }} +[eva] calls_annotation.i:49: calls annotation got status valid. +[eva] computing for function decr <- main. + Called from calls_annotation.i:49. +[eva] Recording results for decr +[eva] Done for function decr +[eva] calls_annotation.i:52: calls annotation got status valid. +[eva] computing for function square <- main. + Called from calls_annotation.i:52. +[eva] Recording results for square +[eva] Done for function square +[eva] computing for function decr <- main. + Called from calls_annotation.i:52. +[eva] Recording results for decr +[eva] Done for function decr +[eva] computing for function incr <- main. + Called from calls_annotation.i:52. +[eva] Recording results for incr +[eva] Done for function incr +[eva] calls_annotation.i:54: calls annotation got status valid. +[eva] computing for function square <- main. + Called from calls_annotation.i:54. +[eva] Recording results for square +[eva] Done for function square +[eva] computing for function decr <- main. + Called from calls_annotation.i:54. +[eva] Recording results for decr +[eva] Done for function decr +[eva] computing for function incr <- main. + Called from calls_annotation.i:54. +[eva] Recording results for incr +[eva] Done for function incr +[eva:alarm] calls_annotation.i:59: Warning: calls annotation got status unknown. +[eva] computing for function decr <- main. + Called from calls_annotation.i:59. +[eva] Recording results for decr +[eva] Done for function decr +[eva] computing for function incr <- main. + Called from calls_annotation.i:59. +[eva] Recording results for incr +[eva] Done for function incr +[eva] calls_annotation.i:60: Frama_C_show_each_0_1: {0; 1} +[eva:alarm] calls_annotation.i:65: Warning: + calls annotation got status invalid (stopping propagation). +[eva:alarm] calls_annotation.i:71: Warning: + calls annotation got status invalid (stopping propagation). +[eva] calls_annotation.i:80: calls annotation got status valid. +[eva] calls_annotation.i:80: Reusing old results for call to incr +[eva] calls_annotation.i:82: calls annotation got status valid. +[eva] computing for function incr <- main. + Called from calls_annotation.i:82. +[eva] Recording results for incr +[eva] Done for function incr +[eva] calls_annotation.i:85: calls annotation got status valid. +[eva] computing for function incr <- main. + Called from calls_annotation.i:85. +[eva] Recording results for incr +[eva] Done for function incr +[eva] calls_annotation.i:88: calls annotation got status valid. +[eva] computing for function incr <- main. + Called from calls_annotation.i:88. +[eva] Recording results for incr +[eva] Done for function incr +[eva] computing for function apply <- main. + Called from calls_annotation.i:92. +[eva] calls_annotation.i:38: calls annotation got status valid. +[eva] computing for function incr <- apply <- main. + Called from calls_annotation.i:38. +[eva] Recording results for incr +[eva] Done for function incr +[eva] calls_annotation.i:40: calls annotation got status valid. +[eva] computing for function incr <- apply <- main. + Called from calls_annotation.i:40. +[eva] Recording results for incr +[eva] Done for function incr +[eva] Recording results for apply +[eva] Done for function apply +[eva:alarm] calls_annotation.i:97: Warning: + calls annotation got status invalid (stopping propagation). +[eva] calls_annotation.i:80: Reusing old results for call to incr +[eva] calls_annotation.i:82: Reusing old results for call to decr +[eva] calls_annotation.i:85: Reusing old results for call to decr +[eva] calls_annotation.i:85: Reusing old results for call to incr +[eva] computing for function decr <- main. + Called from calls_annotation.i:88. +[eva] Recording results for decr +[eva] Done for function decr +[eva] computing for function apply <- main. + Called from calls_annotation.i:92. +[eva] computing for function decr <- apply <- main. + Called from calls_annotation.i:38. +[eva] Recording results for decr +[eva] Done for function decr +[eva] computing for function decr <- apply <- main. + Called from calls_annotation.i:40. +[eva] Recording results for decr +[eva] Done for function decr +[eva] Recording results for apply +[eva] Done for function apply +[eva] calls_annotation.i:80: Reusing old results for call to incr +[eva] calls_annotation.i:82: Reusing old results for call to incr +[eva] computing for function square <- main. + Called from calls_annotation.i:85. +[eva] Recording results for square +[eva] Done for function square +[eva] computing for function decr <- main. + Called from calls_annotation.i:85. +[eva] Recording results for decr +[eva] Done for function decr +[eva] calls_annotation.i:85: Reusing old results for call to incr +[eva] computing for function square <- main. + Called from calls_annotation.i:88. +[eva] Recording results for square +[eva] Done for function square +[eva] computing for function apply <- main. + Called from calls_annotation.i:92. +[eva] computing for function square <- apply <- main. + Called from calls_annotation.i:38. +[eva] Recording results for square +[eva] Done for function square +[eva] computing for function square <- apply <- main. + Called from calls_annotation.i:40. +[eva] Recording results for square +[eva] Done for function square +[eva] Recording results for apply +[eva] Done for function apply +[eva] calls_annotation.i:80: Reusing old results for call to incr +[eva] calls_annotation.i:82: Reusing old results for call to decr +[eva:alarm] calls_annotation.i:85: Warning: calls annotation got status unknown. +[eva] calls_annotation.i:85: Reusing old results for call to square +[eva] calls_annotation.i:85: Reusing old results for call to decr +[eva] calls_annotation.i:85: Reusing old results for call to incr +[eva:alarm] calls_annotation.i:88: Warning: + calls annotation got status invalid (stopping propagation). +[eva] computing for function apply <- main. + Called from calls_annotation.i:92. +[eva:alarm] calls_annotation.i:38: Warning: + calls annotation got status invalid (stopping propagation). +[eva] Recording results for apply +[eva] Done for function apply +[eva] Recording results for main +[eva] Done for function main +[eva] ====== VALUES COMPUTED ====== +[eva:final-states] Values at end of function decr: + __retres ∈ {-4; -3; -2; -1; 0; 1} +[eva:final-states] Values at end of function incr: + __retres ∈ {-1; 0; 1; 2; 3; 4; 5; 6} +[eva:final-states] Values at end of function square: + __retres ∈ [-1..65536] +[eva:final-states] Values at end of function apply: + x ∈ [-4..65536] +[eva:final-states] Values at end of function main: + a ∈ {-1; 0; 1} + i ∈ {0; 1; 2} +[from] Computing for function decr +[from] Done for function decr +[from] Computing for function incr +[from] Done for function incr +[from] Computing for function square +[from] Done for function square +[from] Computing for function apply +[from] Computing for function error <-apply +[from] Non-terminating function error (no dependencies) +[from] Done for function error +[from] Done for function apply +[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 decr: + \result FROM x +[from] Function incr: + \result FROM x +[from] Function square: + \result FROM x +[from] Function apply: + \result FROM fp; a +[from] Function main: + NO EFFECTS +[from] ====== END OF DEPENDENCIES ====== +[inout] Out (internal) for function decr: + __retres +[inout] Inputs for function decr: + \nothing +[inout] Out (internal) for function incr: + __retres +[inout] Inputs for function incr: + \nothing +[inout] Out (internal) for function square: + __retres +[inout] Inputs for function square: + \nothing +[inout] Out (internal) for function apply: + x +[inout] Inputs for function apply: + \nothing +[inout] Out (internal) for function main: + a; i; j +[inout] Inputs for function main: + nondet; funs[0..3] diff --git a/tests/value/oracle_apron/calls_annotation.res.oracle b/tests/value/oracle_apron/calls_annotation.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..2b7f3f96a5e0decd5fd44facaedf808dd051fd07 --- /dev/null +++ b/tests/value/oracle_apron/calls_annotation.res.oracle @@ -0,0 +1,81 @@ +57c57,60 +< [eva] calls_annotation.i:80: Reusing old results for call to incr +--- +> [eva] computing for function incr <- main. +> Called from calls_annotation.i:80. +> [eva] Recording results for incr +> [eva] Done for function incr +89,92c92,107 +< [eva] calls_annotation.i:80: Reusing old results for call to incr +< [eva] calls_annotation.i:82: Reusing old results for call to decr +< [eva] calls_annotation.i:85: Reusing old results for call to decr +< [eva] calls_annotation.i:85: Reusing old results for call to incr +--- +> [eva] computing for function incr <- main. +> Called from calls_annotation.i:80. +> [eva] Recording results for incr +> [eva] Done for function incr +> [eva] computing for function decr <- main. +> Called from calls_annotation.i:82. +> [eva] Recording results for decr +> [eva] Done for function decr +> [eva] computing for function decr <- main. +> Called from calls_annotation.i:85. +> [eva] Recording results for decr +> [eva] Done for function decr +> [eva] computing for function incr <- main. +> Called from calls_annotation.i:85. +> [eva] Recording results for incr +> [eva] Done for function incr +109,110c124,131 +< [eva] calls_annotation.i:80: Reusing old results for call to incr +< [eva] calls_annotation.i:82: Reusing old results for call to incr +--- +> [eva] computing for function incr <- main. +> Called from calls_annotation.i:80. +> [eva] Recording results for incr +> [eva] Done for function incr +> [eva] computing for function incr <- main. +> Called from calls_annotation.i:82. +> [eva] Recording results for incr +> [eva] Done for function incr +119c140,143 +< [eva] calls_annotation.i:85: Reusing old results for call to incr +--- +> [eva] computing for function incr <- main. +> Called from calls_annotation.i:85. +> [eva] Recording results for incr +> [eva] Done for function incr +136,137c160,167 +< [eva] calls_annotation.i:80: Reusing old results for call to incr +< [eva] calls_annotation.i:82: Reusing old results for call to decr +--- +> [eva] computing for function incr <- main. +> Called from calls_annotation.i:80. +> [eva] Recording results for incr +> [eva] Done for function incr +> [eva] computing for function decr <- main. +> Called from calls_annotation.i:82. +> [eva] Recording results for decr +> [eva] Done for function decr +139,141c169,180 +< [eva] calls_annotation.i:85: Reusing old results for call to square +< [eva] calls_annotation.i:85: Reusing old results for call to decr +< [eva] calls_annotation.i:85: Reusing old results for call to incr +--- +> [eva] computing for function square <- main. +> Called from calls_annotation.i:85. +> [eva] Recording results for square +> [eva] Done for function square +> [eva] computing for function decr <- main. +> Called from calls_annotation.i:85. +> [eva] Recording results for decr +> [eva] Done for function decr +> [eva] computing for function incr <- main. +> Called from calls_annotation.i:85. +> [eva] Recording results for incr +> [eva] Done for function incr +158c197 +< __retres ∈ [-1..65536] +--- +> __retres ∈ [0..65536]