| 1 | (* This phase sets the safe_for_multi_decls field, which is normally false, |
| 2 | to true for transformations on declarations where the only change is on the |
| 3 | declared variable. This is the only kind of change on such a declaration |
| 4 | that can safely be done without splitting the declaration. *) |
| 5 | |
| 6 | module Ast = Ast_cocci |
| 7 | module V = Visitor_ast |
| 8 | |
| 9 | let mcode _ (_,_,kind,_) = |
| 10 | match kind with |
| 11 | Ast.MINUS(_,_,_,_) -> true |
| 12 | | Ast.PLUS _ -> failwith "not possible" |
| 13 | | Ast.CONTEXT(_,info) -> not (info = Ast.NOTHING) |
| 14 | |
| 15 | let contains_modif = |
| 16 | let bind x y = x or y in |
| 17 | let option_default = false in |
| 18 | let do_nothing r k e = k e in |
| 19 | let rule_elem r k re = |
| 20 | let res = k re in |
| 21 | match Ast.unwrap re with |
| 22 | Ast.FunHeader(bef,_,fninfo,name,lp,params,rp) -> |
| 23 | bind (mcode r ((),(),bef,Ast.NoMetaPos)) res |
| 24 | | Ast.Decl(bef,_,decl) -> bind (mcode r ((),(),bef,Ast.NoMetaPos)) res |
| 25 | | _ -> res in |
| 26 | let init r k i = |
| 27 | let res = k i in |
| 28 | match Ast.unwrap i with |
| 29 | Ast.StrInitList(allminus,_,_,_,_) -> allminus or res |
| 30 | | _ -> res in |
| 31 | let recursor = |
| 32 | V.combiner bind option_default |
| 33 | mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode |
| 34 | do_nothing do_nothing do_nothing do_nothing do_nothing |
| 35 | do_nothing do_nothing do_nothing do_nothing init do_nothing |
| 36 | do_nothing rule_elem do_nothing do_nothing do_nothing do_nothing in |
| 37 | recursor.V.combiner_fullType |
| 38 | |
| 39 | let decl r k e = |
| 40 | let e = k e in |
| 41 | match Ast.unwrap e with |
| 42 | Ast.Init(stg,ty,_,_,_,sem) |
| 43 | | Ast.UnInit(stg,ty,_,sem) -> |
| 44 | let stg_modif = |
| 45 | match stg with |
| 46 | Some stg -> mcode () stg |
| 47 | | None -> false in |
| 48 | let ft_modif = contains_modif ty in |
| 49 | let sem_modif = mcode () sem in |
| 50 | if not(stg_modif or ft_modif or sem_modif) |
| 51 | then {e with Ast.safe_for_multi_decls = true} |
| 52 | else e |
| 53 | | _ -> e |
| 54 | let mcode e = e |
| 55 | let donothing r k e = k e |
| 56 | |
| 57 | let process = |
| 58 | let fn = V.rebuilder |
| 59 | mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode |
| 60 | donothing donothing donothing donothing donothing |
| 61 | donothing donothing donothing donothing |
| 62 | donothing donothing decl donothing |
| 63 | donothing donothing donothing donothing in |
| 64 | List.map fn.V.rebuilder_top_level |
| 65 | |
| 66 | let safe_for_multi_decls rules = |
| 67 | List.map |
| 68 | (function (mv,r) -> |
| 69 | (mv, |
| 70 | match r with |
| 71 | Ast.ScriptRule _ |
| 72 | | Ast.InitialScriptRule _ | Ast.FinalScriptRule _ -> r |
| 73 | | Ast.CocciRule (nm, rule_info, r, is_exp,ruletype) -> |
| 74 | Ast.CocciRule(nm, rule_info,process r,is_exp,ruletype))) |
| 75 | rules |