nitsaf: add intraprocedural analysis
authorAlexandre Terrasa <alexandre@moz-code.org>
Sat, 19 Dec 2015 08:44:37 +0000 (03:44 -0500)
committerAlexandre Terrasa <alexandre@moz-code.org>
Sat, 19 Dec 2015 08:44:37 +0000 (03:44 -0500)
Signed-off-by: Alexandre Terrasa <alexandre@moz-code.org>

src/saf/reaching_defs.nit
src/saf/saf_base.nit
tests/nitsaf.args
tests/sav/nitsaf_args10.res [new file with mode: 0644]
tests/sav/nitsaf_args9.res [new file with mode: 0644]
tests/test_saf/flow_fun1.nit [new file with mode: 0644]
tests/test_saf/flow_fun2.nit [new file with mode: 0644]

index bb4ee2a..70c853e 100644 (file)
@@ -26,6 +26,19 @@ class ReachingDefsAnalysis
        # New initial flows are empty (conservative analysis).
        redef fun new_initial_flow do return new FlowHashSet[VarDef]
 
+       # New initial flows for methods contains the parameters.
+       redef fun new_initial_method_flow(n) do
+               var flow = new_initial_flow
+               var n_signature = n.n_signature
+               if n_signature == null then return flow
+               for n_param in n_signature.n_params do
+                       var variable = n_param.variable
+                       if variable == null then continue
+                       flow.add(new VarDef(variable, n_param.location))
+               end
+               return flow
+       end
+
        # Perform set union (used for **some path** analysis).
        redef fun merge(s1, s2) do return s1.flow_union(s2)
 
index 26d55ba..fcc409e 100644 (file)
@@ -56,6 +56,13 @@ abstract class StaticAnalysis
        # implementation of this method is the responsability the subclass.
        fun new_initial_flow: FLOW is abstract
 
+       # Initial flow set to use within methods.
+       #
+       # Returns `new_initial_flow` by default.
+       # Redefine this method to inject things in the inset like parameters from
+       # the signature.
+       fun new_initial_method_flow(v: AMethPropdef): FLOW do return new_initial_flow
+
        # The merge operation on sets for confluence.
        #
        # Depends on the analysis performed.
@@ -227,3 +234,13 @@ redef class AForExpr
                accept_loop_forward_analysis(v)
        end
 end
+
+redef class AMethPropdef
+       redef fun accept_forward_analysis(v) do
+               v.current_inset = v.new_initial_method_flow(self)
+               v.current_outset = v.current_inset.clone
+               v.insets[self] = v.current_inset
+               visit_all(v)
+               v.outsets[self] = v.current_outset
+       end
+end
index 03db9f4..c99a22b 100644 (file)
@@ -6,3 +6,5 @@
 --analysis reaching-defs test_saf/flow_loop1.nit
 --analysis reaching-defs test_saf/flow_loop2.nit
 --analysis reaching-defs test_saf/flow_loop3.nit
+--analysis reaching-defs test_saf/flow_fun1.nit
+--analysis reaching-defs test_saf/flow_fun2.nit
diff --git a/tests/sav/nitsaf_args10.res b/tests/sav/nitsaf_args10.res
new file mode 100644 (file)
index 0000000..8061f96
--- /dev/null
@@ -0,0 +1,88 @@
+15: {a: 15}, {b: 15} out of APublicVisibility
+15: {a: 15}, {b: 15} out of TKwmeth
+15: {a: 15}, {b: 15} out of TId
+15: {a: 15}, {b: 15} out of AIdMethid
+15: {a: 15}, {b: 15} out of TOpar
+15: {a: 15}, {b: 15} out of TId
+15: {a: 15}, {b: 15} out of AParam
+15: {a: 15}, {b: 15} out of TId
+15: {a: 15}, {b: 15} out of TClassid
+15: {a: 15}, {b: 15} out of AQclassid
+15: {a: 15}, {b: 15} out of AType
+15: {a: 15}, {b: 15} out of AParam
+15: {a: 15}, {b: 15} out of TCpar
+15: {a: 15}, {b: 15} out of TClassid
+15: {a: 15}, {b: 15} out of AQclassid
+15: {a: 15}, {b: 15} out of AType
+15: {a: 15}, {b: 15} out of ASignature
+15: {a: 15}, {b: 15} out of TKwdo
+16: {a: 15}, {b: 15} out of TId
+16: {a: 15}, {b: 15} out of AVarExpr
+16: {a: 15}, {b: 15} out of TEq
+16: {a: 15}, {b: 15} out of TId
+16: {a: 15}, {b: 15} out of AVarExpr
+16: {a: 15}, {b: 15} out of AEqExpr
+17: {a: 15}, {b: 15} out of TKwvar
+17: {a: 15}, {b: 15} out of TId
+17: {a: 15}, {b: 15} out of TAssign
+17: {a: 15}, {b: 15}, {c: 17} out of TInteger
+17: {a: 15}, {b: 15}, {c: 17} out of AIntegerExpr
+17: {a: 15}, {b: 15}, {c: 17} out of AVardeclExpr
+18: {a: 15}, {b: 15}, {c: 17} out of TId
+18: {a: 15}, {b: 15}, {c: 17} out of TAssign
+18: {a: 15}, {b: 18}, {c: 17} out of TId
+18: {a: 15}, {b: 18}, {c: 17} out of AVarExpr
+18: {a: 15}, {b: 18}, {c: 17} out of AVarAssignExpr
+18: {a: 15}, {b: 18}, {c: 17} out of ABlockExpr
+19: {a: 15}, {b: 15} out of TKwend
+19: {a: 15}, {b: 15} out of ABlockExpr
+20: {a: 15}, {b: 15}, {b: 18}, {c: 17} out of TKwreturn
+20: {a: 15}, {b: 15}, {b: 18}, {c: 17} out of TId
+20: {a: 15}, {b: 15}, {b: 18}, {c: 17} out of AVarExpr
+20: {a: 15}, {b: 15}, {b: 18}, {c: 17} out of AReturnExpr
+21: {a: 15}, {b: 15}, {b: 18}, {c: 17} out of TKwend
+21: {a: 15}, {b: 15}, {b: 18}, {c: 17} out of ABlockExpr
+21: {a: 15}, {b: 15}, {b: 18}, {c: 17} out of AMethPropdef
+21: {a: 15}, {b: 15}, {b: 18}, {c: 17} out of ATopClassdef
+23: {i: 23} out of AListExprs
+23: {i: 23} out of ACallExpr
+23: {i: 23} out of AVardeclExpr
+24: {i: 23} out of TKwvar
+24: {i: 23} out of TId
+24: {i: 23} out of TAssign
+24: {i: 23} out of AImplicitSelfExpr
+24: {i: 23} out of TId
+24: {i: 23} out of AQid
+24: {i: 23} out of AListExprs
+24: {i: 23} out of ACallExpr
+24: {i: 23} out of TId
+24: {i: 23} out of AQid
+24: {i: 23}, {j: 24} out of AListExprs
+24: {i: 23}, {j: 24} out of ACallExpr
+24: {i: 23}, {j: 24} out of AVardeclExpr
+25: {i: 23}, {j: 24} out of TKwvar
+25: {i: 23}, {j: 24} out of TId
+25: {i: 23}, {j: 24} out of TAssign
+25: {i: 23}, {j: 24} out of AImplicitSelfExpr
+25: {i: 23}, {j: 24} out of TId
+25: {i: 23}, {j: 24} out of AQid
+25: {i: 23}, {j: 24} out of TOpar
+25: {i: 23}, {j: 24} out of TId
+25: {i: 23}, {j: 24} out of AVarExpr
+25: {i: 23}, {j: 24} out of TId
+25: {i: 23}, {j: 24} out of AVarExpr
+25: {i: 23}, {j: 24}, {z: 25} out of TCpar
+25: {i: 23}, {j: 24}, {z: 25} out of AParExprs
+25: {i: 23}, {j: 24}, {z: 25} out of ACallExpr
+25: {i: 23}, {j: 24}, {z: 25} out of AVardeclExpr
+26: {i: 23}, {j: 24}, {z: 25} out of AImplicitSelfExpr
+26: {i: 23}, {j: 24}, {z: 25} out of TId
+26: {i: 23}, {j: 24}, {z: 25} out of AQid
+26: {i: 23}, {j: 24}, {z: 25} out of TId
+26: {i: 23}, {j: 24}, {z: 25} out of AVarExpr
+26: {i: 23}, {j: 24}, {z: 25} out of AListExprs
+26: {i: 23}, {j: 24}, {z: 25} out of ACallExpr
+26: {i: 23}, {j: 24}, {z: 25} out of ABlockExpr
+26: {i: 23}, {j: 24}, {z: 25} out of AMainMethPropdef
+26: {i: 23}, {j: 24}, {z: 25} out of AMainClassdef
+26: {i: 23}, {j: 24}, {z: 25} out of AModule
diff --git a/tests/sav/nitsaf_args9.res b/tests/sav/nitsaf_args9.res
new file mode 100644 (file)
index 0000000..cfeedae
--- /dev/null
@@ -0,0 +1,79 @@
+16: {a: 16} out of TInteger
+16: {a: 16} out of AIntegerExpr
+16: {a: 16} out of AVardeclExpr
+17: {a: 16} out of TId
+17: {a: 16} out of TAssign
+17: {a: 17} out of TInteger
+17: {a: 17} out of AIntegerExpr
+17: {a: 17} out of AVarAssignExpr
+18: {a: 17} out of AImplicitSelfExpr
+18: {a: 17} out of TId
+18: {a: 17} out of AQid
+18: {a: 17} out of TId
+18: {a: 17} out of AVarExpr
+18: {a: 17} out of AListExprs
+18: {a: 17} out of ACallExpr
+19: {a: 17} out of TKwend
+19: {a: 17} out of ABlockExpr
+19: {a: 17} out of AMethPropdef
+19: {a: 17} out of ATopClassdef
+21: {a: 21}, {b: 21} out of APublicVisibility
+21: {a: 21}, {b: 21} out of TKwmeth
+21: {a: 21}, {b: 21} out of TId
+21: {a: 21}, {b: 21} out of AIdMethid
+21: {a: 21}, {b: 21} out of TOpar
+21: {a: 21}, {b: 21} out of TId
+21: {a: 21}, {b: 21} out of AParam
+21: {a: 21}, {b: 21} out of TId
+21: {a: 21}, {b: 21} out of TClassid
+21: {a: 21}, {b: 21} out of AQclassid
+21: {a: 21}, {b: 21} out of AType
+21: {a: 21}, {b: 21} out of AParam
+21: {a: 21}, {b: 21} out of TCpar
+21: {a: 21}, {b: 21} out of ASignature
+21: {a: 21}, {b: 21} out of TKwdo
+22: {a: 21}, {b: 21} out of TId
+22: {a: 21}, {b: 21} out of AVarExpr
+22: {a: 21}, {b: 21} out of TEq
+22: {a: 21}, {b: 21} out of TId
+22: {a: 21}, {b: 21} out of AVarExpr
+22: {a: 21}, {b: 21} out of AEqExpr
+23: {a: 21}, {b: 21} out of TKwvar
+23: {a: 21}, {b: 21} out of TId
+23: {a: 21}, {b: 21} out of TAssign
+23: {a: 21}, {b: 21}, {c: 23} out of TInteger
+23: {a: 21}, {b: 21}, {c: 23} out of AIntegerExpr
+23: {a: 21}, {b: 21}, {c: 23} out of AVardeclExpr
+24: {a: 21}, {b: 21}, {c: 23} out of TId
+24: {a: 21}, {b: 21}, {c: 23} out of TAssign
+24: {a: 21}, {b: 24}, {c: 23} out of TId
+24: {a: 21}, {b: 24}, {c: 23} out of AVarExpr
+24: {a: 21}, {b: 24}, {c: 23} out of AVarAssignExpr
+24: {a: 21}, {b: 24}, {c: 23} out of ABlockExpr
+25: {a: 21}, {b: 21} out of TKwend
+25: {a: 21}, {b: 21} out of ABlockExpr
+26: {a: 21}, {b: 21}, {b: 24}, {c: 23} out of AImplicitSelfExpr
+26: {a: 21}, {b: 21}, {b: 24}, {c: 23} out of TId
+26: {a: 21}, {b: 21}, {b: 24}, {c: 23} out of AQid
+26: {a: 21}, {b: 21}, {b: 24}, {c: 23} out of TId
+26: {a: 21}, {b: 21}, {b: 24}, {c: 23} out of AVarExpr
+26: {a: 21}, {b: 21}, {b: 24}, {c: 23} out of AListExprs
+26: {a: 21}, {b: 21}, {b: 24}, {c: 23} out of ACallExpr
+27: {a: 21}, {b: 21}, {b: 24}, {c: 23} out of TKwend
+27: {a: 21}, {b: 21}, {b: 24}, {c: 23} out of ABlockExpr
+27: {a: 21}, {b: 21}, {b: 24}, {c: 23} out of AMethPropdef
+27: {a: 21}, {b: 21}, {b: 24}, {c: 23} out of ATopClassdef
+32: {z: 32} out of AListExprs
+32: {z: 32} out of ACallExpr
+32: {z: 32} out of AVardeclExpr
+33: {z: 32} out of AImplicitSelfExpr
+33: {z: 32} out of TId
+33: {z: 32} out of AQid
+33: {z: 32} out of TId
+33: {z: 32} out of AVarExpr
+33: {z: 32} out of AListExprs
+33: {z: 32} out of ACallExpr
+33: {z: 32} out of ABlockExpr
+33: {z: 32} out of AMainMethPropdef
+33: {z: 32} out of AMainClassdef
+33: {z: 32} out of AModule
diff --git a/tests/test_saf/flow_fun1.nit b/tests/test_saf/flow_fun1.nit
new file mode 100644 (file)
index 0000000..8ecca1c
--- /dev/null
@@ -0,0 +1,33 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+fun foo do
+       var a = 1
+       a = 2
+       print a
+end
+
+fun bar(a, b: Int) do
+       if a == b then
+               var c = 0
+               b = c
+       end
+       print b
+end
+
+foo
+bar(1, 2)
+
+var z = gets.to_i
+print z
diff --git a/tests/test_saf/flow_fun2.nit b/tests/test_saf/flow_fun2.nit
new file mode 100644 (file)
index 0000000..958d740
--- /dev/null
@@ -0,0 +1,26 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+fun bar(a, b: Int): Int do
+       if a == b then
+               var c = 0
+               b = c
+       end
+       return a
+end
+
+var i = gets.to_i
+var j = gets.to_i
+var z = bar(i, j)
+print z