20a99390b2d091ffcdcc67cfac8d0eff7197d1f8
[bpt/coccinelle.git] / parsing_cocci / simple_assignments.ml
1 (*
2 * Copyright 2005-2009, Ecole des Mines de Nantes, University of Copenhagen
3 * Yoann Padioleau, Julia Lawall, Rene Rydhof Hansen, Henrik Stuart, Gilles Muller
4 * This file is part of Coccinelle.
5 *
6 * Coccinelle is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, according to version 2 of the License.
9 *
10 * Coccinelle is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with Coccinelle. If not, see <http://www.gnu.org/licenses/>.
17 *
18 * The authors reserve the right to distribute this or future versions of
19 * Coccinelle under other licenses.
20 *)
21
22
23 module Ast0 = Ast0_cocci
24 module Ast = Ast_cocci
25 module V0 = Visitor_ast0
26
27 (* find assignments that can match an initialization *)
28
29 let pure_mcodekind = function
30 Ast0.CONTEXT(mc) ->
31 (match !mc with
32 (Ast.NOTHING,_,_) -> true
33 | _ -> false)
34 | _ -> false
35
36 let is_simple_assign left op =
37 (match Ast0.unwrap left with
38 Ast0.Ident(_) | Ast0.MetaExpr(_,_,_,_,_) -> true
39 | _ -> false)
40 &&
41 ((Ast0.unwrap_mcode op) = Ast.SimpleAssign)
42
43 let is_simple_ast_assign left op minus_left =
44 (match Ast.unwrap left with
45 Ast.Ident(_) -> true
46 | Ast.MetaExpr(name,_,_,_,_,_) ->
47 (match Ast0.unwrap minus_left with
48 Ast0.MetaExpr(name1,_,_,_,_) ->
49 Ast.unwrap_mcode name = Ast0.unwrap_mcode name1
50 | _ -> false)
51 | _ -> false)
52 &&
53 ((Ast.unwrap_mcode op) = Ast.SimpleAssign)
54
55 let warning e msg =
56 Common.pr2
57 ("the simple assignment expression on line "^
58 (string_of_int (Ast0.get_line e))^
59 " contains transformations\n"^
60 "that prevent it from matching a declaration ("^msg^")\n");
61 e
62
63 let rebuild e1 left right op simple =
64 Ast0.rewrap e1 (Ast0.Assignment(left,op,right,simple))
65
66 let rec exp mc e1 =
67 match Ast0.unwrap e1 with
68 Ast0.Assignment(left,op,right,_) ->
69 if is_simple_assign left op
70 then
71 (if !Flag.sgrep_mode2
72 then rebuild e1 left right op true
73 else
74 match mc with
75 Ast0.MINUS(mc) ->
76 (match !mc with
77 ([[Ast.ExpressionTag(e2)]],_) ->
78 (match Ast.unwrap e2 with
79 Ast.Assignment(left',op',_,_) ->
80 if is_simple_ast_assign left' op' left
81 then rebuild e1 left right op true
82 else warning e1 "replacement is not simple"
83 | _ -> warning e1 "replacement is not an assignment")
84 | _ -> warning e1 "multiple replacements")
85 | m ->
86 let pure =
87 (pure_mcodekind m) &&
88 (pure_mcodekind (Ast0.get_mcodekind left)) &&
89 (pure_mcodekind (Ast0.get_mcode_mcodekind op)) in
90 if not pure
91 then warning e1 "not pure"
92 else rebuild e1 left right op pure)
93 else e1
94 | Ast0.DisjExpr(lp,exps,mids,rp) ->
95 Ast0.rewrap e1
96 (Ast0.DisjExpr
97 (lp,List.map (function x -> exp (Ast0.get_mcodekind x) x) exps,
98 mids,rp))
99 | Ast0.OptExp(e) ->
100 Ast0.rewrap e1 (Ast0.OptExp(exp (Ast0.get_mcodekind e) e))
101 | Ast0.UniqueExp(e) ->
102 Ast0.rewrap e1 (Ast0.UniqueExp(exp (Ast0.get_mcodekind e) e))
103 | _ -> e1
104
105 let simple_assignments l =
106 let mcode x = x in
107 let donothing r k e = k e in
108 let statement r k e =
109 match Ast0.unwrap e with
110 Ast0.Exp(e1) -> Ast0.rewrap e (Ast0.Exp(exp (Ast0.get_mcodekind e) e1))
111 | _ -> k e in
112 let fn =
113 V0.rebuilder
114 mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode
115 donothing donothing donothing donothing donothing donothing
116 donothing donothing donothing donothing donothing donothing statement
117 donothing donothing in
118 List.map fn.V0.rebuilder_top_level l