checkpatch: whine about ACCESS_ONCE
authorJoe Perches <joe@perches.com>
Sat, 21 May 2016 00:04:08 +0000 (17:04 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sat, 21 May 2016 00:58:30 +0000 (17:58 -0700)
Add a test for use of ACCESS_ONCE that could be written using READ_ONCE or
WRITE_ONCE.

--fix it too if desired.

The WRITE_ONCE fixes are less correct than the coccinelle script below as
checkpatch cannot have a completely correct "expression" mechanism because
checkpatch works on patches and not complete files.

$ cat access_once.cocci
@@
expression e1;
expression e2;
@@

-       ACCESS_ONCE(e1) = e2
+       WRITE_ONCE(e1, e2)

@@
expression e1;
@@

-       ACCESS_ONCE(e1)
+       READ_ONCE(e1)

Signed-off-by: Joe Perches <joe@perches.com>
Cc: Julia Lawall <julia.lawall@lip6.fr>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
scripts/checkpatch.pl

index 6c1213c..1048672 100755 (executable)
@@ -5850,6 +5850,28 @@ sub process {
                        }
                }
 
+# whine about ACCESS_ONCE
+               if ($^V && $^V ge 5.10.0 &&
+                   $line =~ /\bACCESS_ONCE\s*$balanced_parens\s*(=(?!=))?\s*($FuncArg)?/) {
+                       my $par = $1;
+                       my $eq = $2;
+                       my $fun = $3;
+                       $par =~ s/^\(\s*(.*)\s*\)$/$1/;
+                       if (defined($eq)) {
+                               if (WARN("PREFER_WRITE_ONCE",
+                                        "Prefer WRITE_ONCE(<FOO>, <BAR>) over ACCESS_ONCE(<FOO>) = <BAR>\n" . $herecurr) &&
+                                   $fix) {
+                                       $fixed[$fixlinenr] =~ s/\bACCESS_ONCE\s*\(\s*\Q$par\E\s*\)\s*$eq\s*\Q$fun\E/WRITE_ONCE($par, $fun)/;
+                               }
+                       } else {
+                               if (WARN("PREFER_READ_ONCE",
+                                        "Prefer READ_ONCE(<FOO>) over ACCESS_ONCE(<FOO>)\n" . $herecurr) &&
+                                   $fix) {
+                                       $fixed[$fixlinenr] =~ s/\bACCESS_ONCE\s*\(\s*\Q$par\E\s*\)/READ_ONCE($par)/;
+                               }
+                       }
+               }
+
 # check for lockdep_set_novalidate_class
                if ($line =~ /^.\s*lockdep_set_novalidate_class\s*\(/ ||
                    $line =~ /__lockdep_no_validate__\s*\)/ ) {