The attached patch "solves" the problem reported by Peter Tummeltshammer
about spatch being slow when removing a single statement from a function 
containing many complex switch statements.

The problem is in the code that checks for inconsistent paths, ie a node 
that is reachable from the nodes matched by the semantic patch, but also 
reachable from nodes not matched by the semantic patch.  When the 
control-flow structure of the function is very complicated, this test 
turns out to be very very complicated.

The "solution" was just to drop the test in the case that one one node is 
matched at a time, in which case there is no possible inconsistent path 
problem.  But this means that it will not be possible to apply a more 
complicated pattern, ie including ... to such code.  The only solution 
would be to use the option -allow_inconsistent_paths, in which case one 
should check the result very carefully to be sure that there are no such 
inconsistent paths.  The other solution, if working on a whole directory, 
is to use the option -timeout for some reasonable number of seconds.  That 
way, a file containing such a complicated function will time out and have 
to be treated by hand, but the treatment of other files will benefit from 
the inconsistent paths check.

julia

diff -u -p a/engine/check_reachability.ml b/engine/check_reachability.ml 
--- a/engine/check_reachability.ml      2010-03-12 16:34:04.000000000 +0100
+++ b/engine/check_reachability.ml      2010-03-13 08:47:36.000000000 +0100
@@ -91,19 +91,24 @@ let create_formulas _ =
          let match_roots =
            List.map (function n -> Ast_ctl.Pred(Node(n)))
              (List.sort compare !roots) in
-         let roots =
+         let or_roots =
            List.fold_left
              (function prev -> function cur -> Ast_ctl.Or(prev,cur))
              (List.hd match_roots) (List.tl match_roots) in
-         (node,
-          Ast_ctl.AF(Ast_ctl.BACKWARD,Ast_ctl.NONSTRICT,
-                     Ast_ctl.Or(roots,Ast_ctl.Pred(After))),
-          Ast_ctl.And
-            (Ast_ctl.NONSTRICT,
-             Ast_ctl.Not(roots),
-             Ast_ctl.EX
-               (Ast_ctl.BACKWARD,
-                Ast_ctl.EU(Ast_ctl.BACKWARD,roots,match_node))))
+         (* no point to search if no path, and the presence of after
+            in the AF formula can make things slow *)
+         if List.mem node !roots
+         then acc
+         else
+           (node,
+            Ast_ctl.AF(Ast_ctl.BACKWARD,Ast_ctl.NONSTRICT,
+                       Ast_ctl.Or(or_roots,Ast_ctl.Pred(After))),
+            Ast_ctl.And
+              (Ast_ctl.NONSTRICT,
+               Ast_ctl.Not(or_roots),
+               Ast_ctl.EX
+                 (Ast_ctl.BACKWARD,
+                  Ast_ctl.EU(Ast_ctl.BACKWARD,or_roots,match_node))))
           (*exef
              (wrap(Ast_ctl.And(Ast_ctl.NONSTRICT,match_node,exef(roots))))*)
          :: acc)
_______________________________________________
Cocci mailing list
[email protected]
http://lists.diku.dk/mailman/listinfo/cocci
(Web access from inside DIKUs LAN only)

Reply via email to