|
@@ -0,0 +1,241 @@
|
|
|
+/// Compare pointer-typed values to NULL rather than 0
|
|
|
+///
|
|
|
+//# This makes an effort to choose between !x and x == NULL. !x is used
|
|
|
+//# if it has previously been used with the function used to initialize x.
|
|
|
+//# This relies on type information. More type information can be obtained
|
|
|
+//# using the option -all_includes and the option -I to specify an
|
|
|
+//# include path.
|
|
|
+//
|
|
|
+// Confidence: High
|
|
|
+// Copyright: (C) 2012 Julia Lawall, INRIA/LIP6. GPLv2.
|
|
|
+// Copyright: (C) 2012 Gilles Muller, INRIA/LiP6. GPLv2.
|
|
|
+// URL: http://coccinelle.lip6.fr/
|
|
|
+// Requires: 1.0.0
|
|
|
+// Options:
|
|
|
+//
|
|
|
+// SPDX-License-Identifier: GPL-2.0
|
|
|
+//
|
|
|
+
|
|
|
+virtual patch
|
|
|
+virtual context
|
|
|
+virtual org
|
|
|
+virtual report
|
|
|
+
|
|
|
+@initialize:ocaml@
|
|
|
+@@
|
|
|
+let negtable = Hashtbl.create 101
|
|
|
+
|
|
|
+@depends on patch@
|
|
|
+expression *E;
|
|
|
+identifier f;
|
|
|
+@@
|
|
|
+
|
|
|
+(
|
|
|
+ (E = f(...)) ==
|
|
|
+- 0
|
|
|
++ NULL
|
|
|
+|
|
|
|
+ (E = f(...)) !=
|
|
|
+- 0
|
|
|
++ NULL
|
|
|
+|
|
|
|
+- 0
|
|
|
++ NULL
|
|
|
+ == (E = f(...))
|
|
|
+|
|
|
|
+- 0
|
|
|
++ NULL
|
|
|
+ != (E = f(...))
|
|
|
+)
|
|
|
+
|
|
|
+
|
|
|
+@t1 depends on !patch@
|
|
|
+expression *E;
|
|
|
+identifier f;
|
|
|
+position p;
|
|
|
+@@
|
|
|
+
|
|
|
+(
|
|
|
+ (E = f(...)) ==
|
|
|
+* 0@p
|
|
|
+|
|
|
|
+ (E = f(...)) !=
|
|
|
+* 0@p
|
|
|
+|
|
|
|
+* 0@p
|
|
|
+ == (E = f(...))
|
|
|
+|
|
|
|
+* 0@p
|
|
|
+ != (E = f(...))
|
|
|
+)
|
|
|
+
|
|
|
+@script:python depends on org@
|
|
|
+p << t1.p;
|
|
|
+@@
|
|
|
+
|
|
|
+coccilib.org.print_todo(p[0], "WARNING comparing pointer to 0")
|
|
|
+
|
|
|
+@script:python depends on report@
|
|
|
+p << t1.p;
|
|
|
+@@
|
|
|
+
|
|
|
+coccilib.report.print_report(p[0], "WARNING comparing pointer to 0")
|
|
|
+
|
|
|
+// Tests of returned values
|
|
|
+
|
|
|
+@s@
|
|
|
+identifier f;
|
|
|
+expression E,E1;
|
|
|
+@@
|
|
|
+
|
|
|
+ E = f(...)
|
|
|
+ ... when != E = E1
|
|
|
+ !E
|
|
|
+
|
|
|
+@script:ocaml depends on s@
|
|
|
+f << s.f;
|
|
|
+@@
|
|
|
+
|
|
|
+try let _ = Hashtbl.find negtable f in ()
|
|
|
+with Not_found -> Hashtbl.add negtable f ()
|
|
|
+
|
|
|
+@ r disable is_zero,isnt_zero exists @
|
|
|
+expression *E;
|
|
|
+identifier f;
|
|
|
+@@
|
|
|
+
|
|
|
+E = f(...)
|
|
|
+...
|
|
|
+(E == 0
|
|
|
+|E != 0
|
|
|
+|0 == E
|
|
|
+|0 != E
|
|
|
+)
|
|
|
+
|
|
|
+@script:ocaml@
|
|
|
+f << r.f;
|
|
|
+@@
|
|
|
+
|
|
|
+try let _ = Hashtbl.find negtable f in ()
|
|
|
+with Not_found -> include_match false
|
|
|
+
|
|
|
+// This rule may lead to inconsistent path problems, if E is defined in two
|
|
|
+// places
|
|
|
+@ depends on patch disable is_zero,isnt_zero @
|
|
|
+expression *E;
|
|
|
+expression E1;
|
|
|
+identifier r.f;
|
|
|
+@@
|
|
|
+
|
|
|
+E = f(...)
|
|
|
+<...
|
|
|
+(
|
|
|
+- E == 0
|
|
|
++ !E
|
|
|
+|
|
|
|
+- E != 0
|
|
|
++ E
|
|
|
+|
|
|
|
+- 0 == E
|
|
|
++ !E
|
|
|
+|
|
|
|
+- 0 != E
|
|
|
++ E
|
|
|
+)
|
|
|
+...>
|
|
|
+?E = E1
|
|
|
+
|
|
|
+@t2 depends on !patch disable is_zero,isnt_zero @
|
|
|
+expression *E;
|
|
|
+expression E1;
|
|
|
+identifier r.f;
|
|
|
+position p1;
|
|
|
+position p2;
|
|
|
+@@
|
|
|
+
|
|
|
+E = f(...)
|
|
|
+<...
|
|
|
+(
|
|
|
+* E == 0@p1
|
|
|
+|
|
|
|
+* E != 0@p2
|
|
|
+|
|
|
|
+* 0@p1 == E
|
|
|
+|
|
|
|
+* 0@p1 != E
|
|
|
+)
|
|
|
+...>
|
|
|
+?E = E1
|
|
|
+
|
|
|
+@script:python depends on org@
|
|
|
+p << t2.p1;
|
|
|
+@@
|
|
|
+
|
|
|
+coccilib.org.print_todo(p[0], "WARNING comparing pointer to 0, suggest !E")
|
|
|
+
|
|
|
+@script:python depends on org@
|
|
|
+p << t2.p2;
|
|
|
+@@
|
|
|
+
|
|
|
+coccilib.org.print_todo(p[0], "WARNING comparing pointer to 0")
|
|
|
+
|
|
|
+@script:python depends on report@
|
|
|
+p << t2.p1;
|
|
|
+@@
|
|
|
+
|
|
|
+coccilib.report.print_report(p[0], "WARNING comparing pointer to 0, suggest !E")
|
|
|
+
|
|
|
+@script:python depends on report@
|
|
|
+p << t2.p2;
|
|
|
+@@
|
|
|
+
|
|
|
+coccilib.report.print_report(p[0], "WARNING comparing pointer to 0")
|
|
|
+
|
|
|
+@ depends on patch disable is_zero,isnt_zero @
|
|
|
+expression *E;
|
|
|
+@@
|
|
|
+
|
|
|
+(
|
|
|
+ E ==
|
|
|
+- 0
|
|
|
++ NULL
|
|
|
+|
|
|
|
+ E !=
|
|
|
+- 0
|
|
|
++ NULL
|
|
|
+|
|
|
|
+- 0
|
|
|
++ NULL
|
|
|
+ == E
|
|
|
+|
|
|
|
+- 0
|
|
|
++ NULL
|
|
|
+ != E
|
|
|
+)
|
|
|
+
|
|
|
+@ t3 depends on !patch disable is_zero,isnt_zero @
|
|
|
+expression *E;
|
|
|
+position p;
|
|
|
+@@
|
|
|
+
|
|
|
+(
|
|
|
+* E == 0@p
|
|
|
+|
|
|
|
+* E != 0@p
|
|
|
+|
|
|
|
+* 0@p == E
|
|
|
+|
|
|
|
+* 0@p != E
|
|
|
+)
|
|
|
+
|
|
|
+@script:python depends on org@
|
|
|
+p << t3.p;
|
|
|
+@@
|
|
|
+
|
|
|
+coccilib.org.print_todo(p[0], "WARNING comparing pointer to 0")
|
|
|
+
|
|
|
+@script:python depends on report@
|
|
|
+p << t3.p;
|
|
|
+@@
|
|
|
+
|
|
|
+coccilib.report.print_report(p[0], "WARNING comparing pointer to 0")
|