Commit f0a594c1 authored by Andy Whitcroft's avatar Andy Whitcroft Committed by Linus Torvalds

update checkpatch.pl to version 0.08

This version brings a number of new checks, and a number of bug
fixes.  Of note:

  - warnings for multiple assignments per line
  - warnings for multiple declarations per line
  - checks for single statement blocks with braces

This patch includes an update for feature-removal-schedule.txt to
better target checks.

Andy Whitcroft (12):
      Version: 0.08
      only apply printk checks where there is a string literal
      allow suppression of errors for when no patch is found
      warn about multiple assignments
      warn on declaration of multiple variables
      check for kfree() with needless null check
      check for single statement braced blocks
      check for aggregate initialisation on the next line
      handle the => operator
      check for spaces between function name and open parenthesis
      move to explicit Check: entries in feature-removal-schedule.txt
      handle pointer attributes
Signed-off-by: default avatarAndy Whitcroft <apw@shadowen.org>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 4b8a8b81
...@@ -51,6 +51,7 @@ Who: David Miller <davem@davemloft.net> ...@@ -51,6 +51,7 @@ Who: David Miller <davem@davemloft.net>
What: Video4Linux API 1 ioctls and video_decoder.h from Video devices. What: Video4Linux API 1 ioctls and video_decoder.h from Video devices.
When: December 2006 When: December 2006
Files: include/linux/video_decoder.h Files: include/linux/video_decoder.h
Check: include/linux/video_decoder.h
Why: V4L1 AP1 was replaced by V4L2 API. during migration from 2.4 to 2.6 Why: V4L1 AP1 was replaced by V4L2 API. during migration from 2.4 to 2.6
series. The old API have lots of drawbacks and don't provide enough series. The old API have lots of drawbacks and don't provide enough
means to work with all video and audio standards. The newer API is means to work with all video and audio standards. The newer API is
...@@ -84,7 +85,7 @@ Who: Dominik Brodowski <linux@brodo.de> ...@@ -84,7 +85,7 @@ Who: Dominik Brodowski <linux@brodo.de>
What: remove EXPORT_SYMBOL(kernel_thread) What: remove EXPORT_SYMBOL(kernel_thread)
When: August 2006 When: August 2006
Files: arch/*/kernel/*_ksyms.c Files: arch/*/kernel/*_ksyms.c
Funcs: kernel_thread Check: kernel_thread
Why: kernel_thread is a low-level implementation detail. Drivers should Why: kernel_thread is a low-level implementation detail. Drivers should
use the <linux/kthread.h> API instead which shields them from use the <linux/kthread.h> API instead which shields them from
implementation details and provides a higherlevel interface that implementation details and provides a higherlevel interface that
......
...@@ -9,7 +9,7 @@ use strict; ...@@ -9,7 +9,7 @@ use strict;
my $P = $0; my $P = $0;
$P =~ s@.*/@@g; $P =~ s@.*/@@g;
my $V = '0.07'; my $V = '0.08';
use Getopt::Long qw(:config no_auto_abbrev); use Getopt::Long qw(:config no_auto_abbrev);
...@@ -47,16 +47,14 @@ my $removal = 'Documentation/feature-removal-schedule.txt'; ...@@ -47,16 +47,14 @@ my $removal = 'Documentation/feature-removal-schedule.txt';
if ($tree && -f $removal) { if ($tree && -f $removal) {
open(REMOVE, "<$removal") || die "$P: $removal: open failed - $!\n"; open(REMOVE, "<$removal") || die "$P: $removal: open failed - $!\n";
while (<REMOVE>) { while (<REMOVE>) {
if (/^Files:\s+(.*\S)/) { if (/^Check:\s+(.*\S)/) {
for my $file (split(/[, ]+/, $1)) { for my $entry (split(/[, ]+/, $1)) {
if ($file =~ m@include/(.*)@) { if ($entry =~ m@include/(.*)@) {
push(@dep_includes, $1); push(@dep_includes, $1);
}
}
} elsif (/^Funcs:\s+(.*\S)/) { } elsif ($entry !~ m@/@) {
for my $func (split(/[, ]+/, $1)) { push(@dep_functions, $entry);
push(@dep_functions, $func); }
} }
} }
} }
...@@ -153,7 +151,7 @@ sub sanitise_line { ...@@ -153,7 +151,7 @@ sub sanitise_line {
} }
sub ctx_block_get { sub ctx_block_get {
my ($linenr, $remain, $outer, $open, $close) = @_; my ($linenr, $remain, $outer, $open, $close, $off) = @_;
my $line; my $line;
my $start = $linenr - 1; my $start = $linenr - 1;
my $blk = ''; my $blk = '';
...@@ -161,38 +159,58 @@ sub ctx_block_get { ...@@ -161,38 +159,58 @@ sub ctx_block_get {
my @c; my @c;
my @res = (); my @res = ();
my $level = 0;
for ($line = $start; $remain > 0; $line++) { for ($line = $start; $remain > 0; $line++) {
next if ($rawlines[$line] =~ /^-/); next if ($rawlines[$line] =~ /^-/);
$remain--; $remain--;
$blk .= $rawlines[$line]; $blk .= $rawlines[$line];
foreach my $c (split(//, $rawlines[$line])) {
##print "C<$c>L<$level><$open$close>O<$off>\n";
if ($off > 0) {
$off--;
next;
}
@o = ($blk =~ /$open/g); if ($c eq $close && $level > 0) {
@c = ($blk =~ /$close/g); $level--;
last if ($level == 0);
} elsif ($c eq $open) {
$level++;
}
}
if (!$outer || (scalar(@o) - scalar(@c)) == 1) { if (!$outer || $level <= 1) {
push(@res, $rawlines[$line]); push(@res, $rawlines[$line]);
} }
last if (scalar(@o) == scalar(@c)); last if ($level == 0);
} }
return @res; return ($level, @res);
} }
sub ctx_block_outer { sub ctx_block_outer {
my ($linenr, $remain) = @_; my ($linenr, $remain) = @_;
return ctx_block_get($linenr, $remain, 1, '\{', '\}'); my ($level, @r) = ctx_block_get($linenr, $remain, 1, '{', '}', 0);
return @r;
} }
sub ctx_block { sub ctx_block {
my ($linenr, $remain) = @_; my ($linenr, $remain) = @_;
return ctx_block_get($linenr, $remain, 0, '\{', '\}'); my ($level, @r) = ctx_block_get($linenr, $remain, 0, '{', '}', 0);
return @r;
} }
sub ctx_statement { sub ctx_statement {
my ($linenr, $remain, $off) = @_;
my ($level, @r) = ctx_block_get($linenr, $remain, 0, '(', ')', $off);
return @r;
}
sub ctx_block_level {
my ($linenr, $remain) = @_; my ($linenr, $remain) = @_;
return ctx_block_get($linenr, $remain, 0, '\(', '\)'); return ctx_block_get($linenr, $remain, 0, '{', '}', 0);
} }
sub ctx_locate_comment { sub ctx_locate_comment {
...@@ -246,16 +264,23 @@ sub cat_vet { ...@@ -246,16 +264,23 @@ sub cat_vet {
return $vet; return $vet;
} }
my @report = ();
sub report {
push(@report, $_[0]);
}
sub report_dump {
@report;
}
sub ERROR { sub ERROR {
print "ERROR: $_[0]\n"; report("ERROR: $_[0]\n");
our $clean = 0; our $clean = 0;
} }
sub WARN { sub WARN {
print "WARNING: $_[0]\n"; report("WARNING: $_[0]\n");
our $clean = 0; our $clean = 0;
} }
sub CHK { sub CHK {
print "CHECK: $_[0]\n"; report("CHECK: $_[0]\n");
our $clean = 0; our $clean = 0;
} }
...@@ -318,7 +343,10 @@ sub process { ...@@ -318,7 +343,10 @@ sub process {
(?:\s*\*+\s*const|\s*\*+)? (?:\s*\*+\s*const|\s*\*+)?
}x; }x;
my $Declare = qr{(?:$Storage\s+)?$Type}; my $Declare = qr{(?:$Storage\s+)?$Type};
my $Attribute = qr{__read_mostly|__init|__initdata}; my $Attribute = qr{const|__read_mostly|__init|__initdata|__meminit};
my $Member = qr{->$Ident|\.$Ident|\[[^]]*\]};
my $Lval = qr{$Ident(?:$Member)*};
# Pre-scan the patch looking for any __setup documentation. # Pre-scan the patch looking for any __setup documentation.
my @setup_docs = (); my @setup_docs = ();
...@@ -509,7 +537,7 @@ sub process { ...@@ -509,7 +537,7 @@ sub process {
# if/while/etc brace do not go on next line, unless defining a do while loop, # if/while/etc brace do not go on next line, unless defining a do while loop,
# or if that brace on the next line is for something else # or if that brace on the next line is for something else
if ($line =~ /\b(?:(if|while|for|switch)\s*\(|do\b|else\b)/ && $line !~ /^.#/) { if ($line =~ /\b(?:(if|while|for|switch)\s*\(|do\b|else\b)/ && $line !~ /^.#/) {
my @ctx = ctx_statement($linenr, $realcnt); my @ctx = ctx_statement($linenr, $realcnt, 0);
my $ctx_ln = $linenr + $#ctx + 1; my $ctx_ln = $linenr + $#ctx + 1;
my $ctx_cnt = $realcnt - $#ctx - 1; my $ctx_cnt = $realcnt - $#ctx - 1;
my $ctx = join("\n", @ctx); my $ctx = join("\n", @ctx);
...@@ -521,7 +549,7 @@ sub process { ...@@ -521,7 +549,7 @@ sub process {
##warn "line<$line>\nctx<$ctx>\nnext<$lines[$ctx_ln - 1]>"; ##warn "line<$line>\nctx<$ctx>\nnext<$lines[$ctx_ln - 1]>";
if ($ctx !~ /{\s*/ && $ctx_cnt > 0 && $lines[$ctx_ln - 1] =~ /^\+\s*{/) { if ($ctx !~ /{\s*/ && $ctx_cnt > 0 && $lines[$ctx_ln - 1] =~ /^\+\s*{/) {
ERROR("That { should be on the previous line\n" . ERROR("That open brace { should be on the previous line\n" .
"$here\n$ctx\n$lines[$ctx_ln - 1]"); "$here\n$ctx\n$lines[$ctx_ln - 1]");
} }
} }
...@@ -535,6 +563,12 @@ sub process { ...@@ -535,6 +563,12 @@ sub process {
next; next;
} }
# check for initialisation to aggregates open brace on the next line
if ($prevline =~ /$Declare\s*$Ident\s*=\s*$/ &&
$line =~ /^.\s*{/) {
ERROR("That open brace { should be on the previous line\n" . $hereprev);
}
# #
# Checks which are anchored on the added line. # Checks which are anchored on the added line.
# #
...@@ -570,8 +604,13 @@ sub process { ...@@ -570,8 +604,13 @@ sub process {
} }
} }
# check for external initialisers.
if ($line =~ /^.$Type\s*$Ident\s*=\s*(0|NULL);/) {
ERROR("do not initialise externals to 0 or NULL\n" .
$herecurr);
}
# check for static initialisers. # check for static initialisers.
if ($line=~/\s*static\s.*=\s+(0|NULL);/) { if ($line =~ /\s*static\s.*=\s*(0|NULL);/) {
ERROR("do not initialise statics to 0 or NULL\n" . ERROR("do not initialise statics to 0 or NULL\n" .
$herecurr); $herecurr);
} }
...@@ -593,11 +632,11 @@ sub process { ...@@ -593,11 +632,11 @@ sub process {
ERROR("\"(foo $1 )\" should be \"(foo $1)\"\n" . ERROR("\"(foo $1 )\" should be \"(foo $1)\"\n" .
$herecurr); $herecurr);
} elsif ($line =~ m{$NonptrType(\*+)(?:\s+const)?\s+[A-Za-z\d_]+}) { } elsif ($line =~ m{$NonptrType(\*+)(?:\s+$Attribute)?\s+[A-Za-z\d_]+}) {
ERROR("\"foo$1 bar\" should be \"foo $1bar\"\n" . ERROR("\"foo$1 bar\" should be \"foo $1bar\"\n" .
$herecurr); $herecurr);
} elsif ($line =~ m{$NonptrType\s+(\*+)(?!\s+const)\s+[A-Za-z\d_]+}) { } elsif ($line =~ m{$NonptrType\s+(\*+)(?!\s+$Attribute)\s+[A-Za-z\d_]+}) {
ERROR("\"foo $1 bar\" should be \"foo $1bar\"\n" . ERROR("\"foo $1 bar\" should be \"foo $1bar\"\n" .
$herecurr); $herecurr);
} }
...@@ -614,7 +653,7 @@ sub process { ...@@ -614,7 +653,7 @@ sub process {
# to try and find and validate the current printk. In summary the current # to try and find and validate the current printk. In summary the current
# printk includes all preceeding printk's which have no newline on the end. # printk includes all preceeding printk's which have no newline on the end.
# we assume the first bad printk is the one to report. # we assume the first bad printk is the one to report.
if ($line =~ /\bprintk\((?!KERN_)/) { if ($line =~ /\bprintk\((?!KERN_)\s*"/) {
my $ok = 0; my $ok = 0;
for (my $ln = $linenr - 1; $ln >= $first_line; $ln--) { for (my $ln = $linenr - 1; $ln >= $first_line; $ln--) {
#print "CHECK<$lines[$ln - 1]\n"; #print "CHECK<$lines[$ln - 1]\n";
...@@ -639,6 +678,12 @@ sub process { ...@@ -639,6 +678,12 @@ sub process {
ERROR("open brace '{' following function declarations go on the next line\n" . $herecurr); ERROR("open brace '{' following function declarations go on the next line\n" . $herecurr);
} }
# check for spaces between functions and their parentheses.
if ($line =~ /($Ident)\s+\(/ &&
$1 !~ /^(?:if|for|while|switch|return|volatile)$/ &&
$line !~ /$Type\s+\(/ && $line !~ /^.\#\s*define\b/) {
ERROR("no space between function name and open parenthesis '('\n" . $herecurr);
}
# Check operator spacing. # Check operator spacing.
# Note we expand the line with the leading + as the real # Note we expand the line with the leading + as the real
# line will be displayed with the leading + and the tabs # line will be displayed with the leading + and the tabs
...@@ -647,7 +692,7 @@ sub process { ...@@ -647,7 +692,7 @@ sub process {
$opline = expand_tabs($opline); $opline = expand_tabs($opline);
$opline =~ s/^./ /; $opline =~ s/^./ /;
if (!($line=~/\#\s*include/)) { if (!($line=~/\#\s*include/)) {
my @elements = split(/(<<=|>>=|<=|>=|==|!=|\+=|-=|\*=|\/=|%=|\^=|\|=|&=|->|<<|>>|<|>|=|!|~|&&|\|\||,|\^|\+\+|--|;|&|\||\+|-|\*|\/\/|\/)/, $opline); my @elements = split(/(<<=|>>=|<=|>=|==|!=|\+=|-=|\*=|\/=|%=|\^=|\|=|&=|=>|->|<<|>>|<|>|=|!|~|&&|\|\||,|\^|\+\+|--|;|&|\||\+|-|\*|\/\/|\/)/, $opline);
my $off = 0; my $off = 0;
for (my $n = 0; $n < $#elements; $n += 2) { for (my $n = 0; $n < $#elements; $n += 2) {
$off += length($elements[$n]); $off += length($elements[$n]);
...@@ -773,6 +818,18 @@ sub process { ...@@ -773,6 +818,18 @@ sub process {
} }
} }
# check for multiple assignments
if ($line =~ /^.\s*$Lval\s*=\s*$Lval\s*=(?!=)/) {
WARN("multiple assignments should be avoided\n" . $herecurr);
}
# check for multiple declarations, allowing for a function declaration
# continuation.
if ($line =~ /^.\s*$Type\s+$Ident(?:\s*=[^,{]*)?\s*,\s*$Ident.*/ &&
$line !~ /^.\s*$Type\s+$Ident(?:\s*=[^,{]*)?\s*,\s*$Type\s*$Ident.*/) {
WARN("declaring multiple variables together should be avoided\n" . $herecurr);
}
#need space before brace following if, while, etc #need space before brace following if, while, etc
if ($line =~ /\(.*\){/ || $line =~ /do{/) { if ($line =~ /\(.*\){/ || $line =~ /do{/) {
ERROR("need a space before the open brace '{'\n" . $herecurr); ERROR("need a space before the open brace '{'\n" . $herecurr);
...@@ -847,13 +904,18 @@ sub process { ...@@ -847,13 +904,18 @@ sub process {
# or the one below. # or the one below.
my $ln = $linenr; my $ln = $linenr;
my $cnt = $realcnt; my $cnt = $realcnt;
my $off = 0;
# If the macro starts on the define line start there. # If the macro starts on the define line start
if ($prevline !~ m{^.#\s*define\s*$Ident(?:\([^\)]*\))?\s*\\\s*$}) { # grabbing the statement after the identifier
$prevline =~ m{^(.#\s*define\s*$Ident(?:\([^\)]*\))?\s*)(.*)\\\s*$};
##print "1<$1> 2<$2>\n";
if ($2 ne '') {
$off = length($1);
$ln--; $ln--;
$cnt++; $cnt++;
} }
my @ctx = ctx_statement($ln, $cnt); my @ctx = ctx_statement($ln, $cnt, $off);
my $ctx_ln = $ln + $#ctx + 1; my $ctx_ln = $ln + $#ctx + 1;
my $ctx = join("\n", @ctx); my $ctx = join("\n", @ctx);
...@@ -873,6 +935,44 @@ sub process { ...@@ -873,6 +935,44 @@ sub process {
} }
} }
# check for redundant bracing round if etc
if ($line =~ /\b(if|while|for|else)\b/) {
# Locate the end of the opening statement.
my @control = ctx_statement($linenr, $realcnt, 0);
my $nr = $linenr + (scalar(@control) - 1);
my $cnt = $realcnt - (scalar(@control) - 1);
my $off = $realcnt - $cnt;
#print "$off: line<$line>end<" . $lines[$nr - 1] . ">\n";
# If this is is a braced statement group check it
if ($lines[$nr - 1] =~ /{\s*$/) {
my ($lvl, @block) = ctx_block_level($nr, $cnt);
my $stmt = join(' ', @block);
$stmt =~ s/^[^{]*{//;
$stmt =~ s/}[^}]*$//;
#print "block<" . join(' ', @block) . "><" . scalar(@block) . ">\n";
#print "stmt<$stmt>\n\n";
# Count the ;'s if there is fewer than two
# then there can only be one statement,
# if there is a brace inside we cannot
# trivially detect if its one statement.
# Also nested if's often require braces to
# disambiguate the else binding so shhh there.
my @semi = ($stmt =~ /;/g);
##print "semi<" . scalar(@semi) . ">\n";
if ($lvl == 0 && scalar(@semi) < 2 &&
$stmt !~ /{/ && $stmt !~ /\bif\b/) {
my $herectx = "$here\n" . join("\n", @control, @block[1 .. $#block]) . "\n";
shift(@block);
ERROR("braces {} are not necessary for single statement blocks\n" . $herectx);
}
}
}
# don't include deprecated include files (uses RAW line) # don't include deprecated include files (uses RAW line)
for my $inc (@dep_includes) { for my $inc (@dep_includes) {
if ($rawline =~ m@\#\s*include\s*\<$inc>@) { if ($rawline =~ m@\#\s*include\s*\<$inc>@) {
...@@ -898,6 +998,14 @@ sub process { ...@@ -898,6 +998,14 @@ sub process {
$herecurr); $herecurr);
} }
# check for needless kfree() checks
if ($prevline =~ /\bif\s*\(([^\)]*)\)/) {
my $expr = $1;
if ($line =~ /\bkfree\(\Q$expr\E\);/) {
WARN("kfree(NULL) is safe this check is probabally not required\n" . $hereprev);
}
}
# warn about #ifdefs in C files # warn about #ifdefs in C files
# if ($line =~ /^.#\s*if(|n)def/ && ($realfile =~ /\.c$/)) { # if ($line =~ /^.#\s*if(|n)def/ && ($realfile =~ /\.c$/)) {
# print "#ifdef in C files should be avoided\n"; # print "#ifdef in C files should be avoided\n";
...@@ -952,6 +1060,9 @@ sub process { ...@@ -952,6 +1060,9 @@ sub process {
ERROR("Missing Signed-off-by: line(s)\n"); ERROR("Missing Signed-off-by: line(s)\n");
} }
if ($clean == 0 && ($chk_patch || $is_patch)) {
print report_dump();
}
if ($clean == 1 && $quiet == 0) { if ($clean == 1 && $quiet == 0) {
print "Your patch has no obvious style problems and is ready for submission.\n" print "Your patch has no obvious style problems and is ready for submission.\n"
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment