572d14eb016c77d72a956e9974dae5165f151f20
[bpt/coccinelle.git] / parsing_cocci / safe_for_multi_decls.ml
1 (*
2 * Copyright 2010, INRIA, University of Copenhagen
3 * Julia Lawall, Rene Rydhof Hansen, Gilles Muller, Nicolas Palix
4 * Copyright 2005-2009, Ecole des Mines de Nantes, University of Copenhagen
5 * Yoann Padioleau, Julia Lawall, Rene Rydhof Hansen, Henrik Stuart, Gilles Muller, Nicolas Palix
6 * This file is part of Coccinelle.
7 *
8 * Coccinelle is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, according to version 2 of the License.
11 *
12 * Coccinelle is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with Coccinelle. If not, see <http://www.gnu.org/licenses/>.
19 *
20 * The authors reserve the right to distribute this or future versions of
21 * Coccinelle under other licenses.
22 *)
23
24
25 (* This phase sets the safe_for_multi_decls field, which is normally false,
26 to true for transformations on declarations where the only change is on the
27 declared variable. This is the only kind of change on such a declaration
28 that can safely be done without splitting the declaration. *)
29
30 module Ast = Ast_cocci
31 module V = Visitor_ast
32
33 let mcode _ (_,_,kind,_) =
34 match kind with
35 Ast.MINUS(_,_,_,_) -> true
36 | Ast.PLUS _ -> failwith "not possible"
37 | Ast.CONTEXT(_,info) -> not (info = Ast.NOTHING)
38
39 let contains_modif =
40 let bind x y = x or y in
41 let option_default = false in
42 let do_nothing r k e = k e in
43 let rule_elem r k re =
44 let res = k re in
45 match Ast.unwrap re with
46 Ast.FunHeader(bef,_,fninfo,name,lp,params,rp) ->
47 bind (mcode r ((),(),bef,[])) res
48 | Ast.Decl(bef,_,decl) -> bind (mcode r ((),(),bef,[])) res
49 | _ -> res in
50 let init r k i =
51 let res = k i in
52 match Ast.unwrap i with
53 Ast.StrInitList(allminus,_,_,_,_) -> allminus or res
54 | _ -> res in
55 let recursor =
56 V.combiner bind option_default
57 mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode
58 do_nothing do_nothing do_nothing do_nothing do_nothing
59 do_nothing do_nothing do_nothing do_nothing init do_nothing
60 do_nothing rule_elem do_nothing do_nothing do_nothing do_nothing in
61 recursor.V.combiner_fullType
62
63 let decl r k e =
64 let e = k e in
65 match Ast.unwrap e with
66 Ast.Init(stg,ty,_,_,_,sem)
67 | Ast.UnInit(stg,ty,_,sem) ->
68 let stg_modif =
69 match stg with
70 Some stg -> mcode () stg
71 | None -> false in
72 let ft_modif = contains_modif ty in
73 let sem_modif = mcode () sem in
74 if not(stg_modif or ft_modif or sem_modif)
75 then {e with Ast.safe_for_multi_decls = true}
76 else e
77 | _ -> e
78 let mcode e = e
79 let donothing r k e = k e
80
81 let process =
82 let fn = V.rebuilder
83 mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode
84 donothing donothing donothing donothing donothing
85 donothing donothing donothing donothing
86 donothing donothing decl donothing
87 donothing donothing donothing donothing in
88 List.map fn.V.rebuilder_top_level
89
90 let safe_for_multi_decls rules =
91 List.map
92 (function (mv,r) ->
93 (mv,
94 match r with
95 Ast.ScriptRule _
96 | Ast.InitialScriptRule _ | Ast.FinalScriptRule _ -> r
97 | Ast.CocciRule (nm, rule_info, r, is_exp,ruletype) ->
98 Ast.CocciRule(nm, rule_info,process r,is_exp,ruletype)))
99 rules