From b1558368bee2236c098f53e03e94e3845af3ca5c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?David=20B=C3=BChler?= <david.buhler@cea.fr>
Date: Tue, 9 Apr 2019 15:40:27 +0200
Subject: [PATCH] [Eva] Simplifies split_return in partition.

---
 src/plugins/value/engine/partition.ml         | 80 +++++++------------
 .../value/engine/trace_partitioning.ml        |  5 +-
 2 files changed, 31 insertions(+), 54 deletions(-)

diff --git a/src/plugins/value/engine/partition.ml b/src/plugins/value/engine/partition.ml
index 8b7c530a1aa..83d8771f275 100644
--- a/src/plugins/value/engine/partition.ml
+++ b/src/plugins/value/engine/partition.ml
@@ -308,19 +308,16 @@ struct
     | Failure _ ->
       fail ~exp "this partitioning parameter is too big"
 
-  (* Sorts a list of states by the evaluation of an expression, according to
-     a list of expected integer values.
-     [split_by_evaluation expr expected_values states] returns two list
-     (matched, tail) such as:
-     - for each element (i, states, mess) of the first list [matched],
-       i was in the list of integer [expected_values], [states] is the list of
-       input states where [expr] evaluates to exactly [i], and [mess] is true
-       if there was some other input state on which [expr] evaluates to a value
-       including [i] (but not equal to [i]).
-     - tail are the states on which [expr] does not evaluate to none of the
-       [expected_values]. *)
-  let split_by_evaluation = match Abstract.Val.get Main_values.cvalue_key with
-    | None -> fun _ _ states -> [], states
+  let smash_states acc = function
+    | [] -> acc
+    | v1 :: l -> List.fold_left Abstract.Dom.join v1 l :: acc
+
+  (* In a list of states, join the states in which the given expression
+     evaluates to:
+     - exactly the integer i from the list expected_values;
+     - anything else. *)
+  let merge_by_value = match Abstract.Val.get Main_values.cvalue_key with
+    | None -> fun _ _ states -> states
     | Some get -> fun expr expected_values states ->
       let typ = Cil.typeOf expr in
       let eval acc state =
@@ -331,53 +328,30 @@ struct
           (state, `Value value, zero_or_one) :: acc
       in
       let eval_states = List.fold_left eval [] states in
-      let match_expected_value expected_value states =
-        let process_one_state (eq, mess, neq) (s, v, zero_or_one as current) =
-          if Bottom.is_included Abstract.Val.is_included expected_value v then
-            (* The integer on which we split is part of the result *)
-            if zero_or_one then
-              (s :: eq, mess, neq) (* Clean split *)
-            else
-              (eq, true, current :: neq) (* v is not exact: mess, i.e. no split *)
-          else
-            (eq, mess, current :: neq) (* Integer not in the result at all *)
+      let is_included = Bottom.is_included Abstract.Val.is_included in
+      let match_expected_value i states =
+        let expected_value = `Value Abstract.Val.(reduce (inject_int typ i)) in
+        let process_one_state (eq, neq) (s, v, zero_or_one as current) =
+          let included = is_included expected_value v in
+          if included && not zero_or_one
+          then
+            Value_parameters.result ~once:true ~current:true
+              "cannot properly split on \\result == %a"
+              Abstract_interp.Int.pretty i;
+          if included && zero_or_one
+          then s :: eq, neq
+          else eq, current :: neq
         in
-        List.fold_left process_one_state ([], false, []) states
+        List.fold_left process_one_state ([], []) states
       in
       let process_one_value (acc, states) i =
-        let value = `Value Abstract.Val.(reduce (inject_int typ i)) in
-        let eq, mess, neq = match_expected_value value states in
-        (i, eq, mess) :: acc, neq
+        let eq, neq = match_expected_value i states in
+        smash_states acc eq, neq
       in
       let matched, tail =
         List.fold_left process_one_value ([], eval_states) expected_values
       in
-      matched, List.map (fun (s, _, _) -> s) tail
-
-  let smash_states = function
-    | [] -> []
-    | v1 :: l -> [ List.fold_left Abstract.Dom.join v1 l ]
-
-  (* In the list of [states], join states in which [expr] evaluates to the
-     same exact value in [expected_values] or to any other value. *)
-  let merge_by_value expr expected_values states =
-    let states =
-      if Cil.isIntegralOrPointerType (Cil.typeOf expr)
-      then
-        let matched, tail =
-          split_by_evaluation expr expected_values states
-        in
-        let process (i, states, mess) =
-          if mess then
-            Value_parameters.result ~once:true ~current:true
-              "cannot properly split on \\result == %a"
-              Abstract_interp.Int.pretty i;
-          states
-        in
-        tail :: List.map process matched
-      else [states]
-    in
-    List.flatten (List.map smash_states states)
+      smash_states matched (List.map (fun (s, _, _) -> s) tail)
 
   (* --- Applying partitioning actions onto flows --------------------------- *)
 
diff --git a/src/plugins/value/engine/trace_partitioning.ml b/src/plugins/value/engine/trace_partitioning.ml
index c4bb0eb2bb2..48379890f7f 100644
--- a/src/plugins/value/engine/trace_partitioning.ml
+++ b/src/plugins/value/engine/trace_partitioning.ml
@@ -181,7 +181,10 @@ struct
       | Split_strategy.SplitEqList i ->
         match return_exp with
         | None -> smash ()
-        | Some return_exp -> transfer_action flow (Restrict (return_exp, i))
+        | Some return_exp ->
+          if Cil.isIntegralOrPointerType (Cil.typeOf return_exp)
+          then transfer_action flow (Restrict (return_exp, i))
+          else smash ()
 
   (* Reset state (for hierchical convergence) *)
 
-- 
GitLab