update checkpatch.pl to version 0.15

This version brings a number of minor fixes updating the type detector and
the unary tracker.  It also brings a few small fixes for false positives.
It also reverts the --file warning.  Of note:

 - limit CVS checks to added lines
 - improved type detections
 - fixes to the unary tracker

Andy Whitcroft (13):
      Version: 0.15
      EXPORT_SYMBOL checks need to accept array variables
      export checks must match DECLARE_foo and LIST_HEAD
      possible types: cleanup debugging missing line
      values: track values through preprocessor conditional paths
      typeof is actually a type
      possible types: detect definitions which cross lines
      values: include line numbers on value debug information
      values: ensure we find correctly record pending brackets
      values: simplify the brace history stack
      CVS keyword checks should only apply to added lines
      loosen spacing for comments
      allow braces for single statement blocks with multiline conditionals

Harvey Harrison (1):
      checkpatch: remove fastcall

Ingo Molnar (1):
      checkpatch.pl: revert wrong --file message

Uwe Kleine-Koenig (1):
      fix typo "goot" -> "good"

Signed-off-by: Andy Whitcroft <apw@shadowen.org>
Cc: Randy Dunlap <rdunlap@xenotime.net>
Cc: Joel Schopp <jschopp@austin.ibm.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Andi Kleen <ak@suse.de>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
Andy Whitcroft 2008-03-04 14:28:20 -08:00 committed by Linus Torvalds
parent b6abdb0e6c
commit cf655043d4
1 changed files with 204 additions and 115 deletions

View File

@ -9,7 +9,7 @@ use strict;
my $P = $0; my $P = $0;
$P =~ s@.*/@@g; $P =~ s@.*/@@g;
my $V = '0.14'; my $V = '0.15';
use Getopt::Long qw(:config no_auto_abbrev); use Getopt::Long qw(:config no_auto_abbrev);
@ -105,8 +105,7 @@ our $Sparse = qr{
__iomem| __iomem|
__must_check| __must_check|
__init_refok| __init_refok|
__kprobes| __kprobes
fastcall
}x; }x;
our $Attribute = qr{ our $Attribute = qr{
const| const|
@ -158,7 +157,10 @@ sub build_types {
\b \b
(?:const\s+)? (?:const\s+)?
(?:unsigned\s+)? (?:unsigned\s+)?
$all (?:
$all|
(?:typeof|__typeof__)\s*\(\s*\**\s*$Ident\s*\)
)
(?:\s+$Sparse|\s+const)* (?:\s+$Sparse|\s+const)*
\b \b
}x; }x;
@ -362,6 +364,7 @@ sub ctx_statement_block {
my $type = ''; my $type = '';
my $level = 0; my $level = 0;
my $p;
my $c; my $c;
my $len = 0; my $len = 0;
@ -386,6 +389,7 @@ sub ctx_statement_block {
last; last;
} }
} }
$p = $c;
$c = substr($blk, $off, 1); $c = substr($blk, $off, 1);
$remainder = substr($blk, $off); $remainder = substr($blk, $off);
@ -397,8 +401,9 @@ sub ctx_statement_block {
} }
# An else is really a conditional as long as its not else if # An else is really a conditional as long as its not else if
if ($level == 0 && $remainder =~ /(\s+else)(?:\s|{)/ && if ($level == 0 && (!defined($p) || $p =~ /(?:\s|\})/) &&
$remainder !~ /\s+else\s+if\b/) { $remainder =~ /(else)(?:\s|{)/ &&
$remainder !~ /else\s+if\b/) {
$coff = $off + length($1); $coff = $off + length($1);
} }
@ -445,21 +450,73 @@ sub ctx_statement_block {
$line, $remain + 1, $off - $loff + 1, $level); $line, $remain + 1, $off - $loff + 1, $level);
} }
sub statement_lines {
my ($stmt) = @_;
# Strip the diff line prefixes and rip blank lines at start and end.
$stmt =~ s/(^|\n)./$1/g;
$stmt =~ s/^\s*//;
$stmt =~ s/\s*$//;
my @stmt_lines = ($stmt =~ /\n/g);
return $#stmt_lines + 2;
}
sub statement_rawlines {
my ($stmt) = @_;
my @stmt_lines = ($stmt =~ /\n/g);
return $#stmt_lines + 2;
}
sub statement_block_size {
my ($stmt) = @_;
$stmt =~ s/(^|\n)./$1/g;
$stmt =~ s/^\s*{//;
$stmt =~ s/}\s*$//;
$stmt =~ s/^\s*//;
$stmt =~ s/\s*$//;
my @stmt_lines = ($stmt =~ /\n/g);
my @stmt_statements = ($stmt =~ /;/g);
my $stmt_lines = $#stmt_lines + 2;
my $stmt_statements = $#stmt_statements + 1;
if ($stmt_lines > $stmt_statements) {
return $stmt_lines;
} else {
return $stmt_statements;
}
}
sub ctx_statement_full { sub ctx_statement_full {
my ($linenr, $remain, $off) = @_; my ($linenr, $remain, $off) = @_;
my ($statement, $condition, $level); my ($statement, $condition, $level);
my (@chunks); my (@chunks);
# Grab the first conditional/block pair.
($statement, $condition, $linenr, $remain, $off, $level) = ($statement, $condition, $linenr, $remain, $off, $level) =
ctx_statement_block($linenr, $remain, $off); ctx_statement_block($linenr, $remain, $off);
#print "F: c<$condition> s<$statement>\n"; #print "F: c<$condition> s<$statement>\n";
push(@chunks, [ $condition, $statement ]);
if (!($remain > 0 && $condition =~ /^\s*(?:\n[+-])?\s*(?:if|else|do)\b/s)) {
return ($level, $linenr, @chunks);
}
# Pull in the following conditional/block pairs and see if they
# could continue the statement.
for (;;) { for (;;) {
push(@chunks, [ $condition, $statement ]);
last if (!($remain > 0 && $condition =~ /^.\s*(?:if|else|do)/));
($statement, $condition, $linenr, $remain, $off, $level) = ($statement, $condition, $linenr, $remain, $off, $level) =
ctx_statement_block($linenr, $remain, $off); ctx_statement_block($linenr, $remain, $off);
#print "C: c<$condition> s<$statement>\n"; #print "C: c<$condition> s<$statement> remain<$remain>\n";
last if (!($remain > 0 && $condition =~ /^\s*(?:\n[+-])?\s*(?:else|do)\b/s));
#print "C: push\n";
push(@chunks, [ $condition, $statement ]);
} }
return ($level, $linenr, @chunks); return ($level, $linenr, @chunks);
@ -593,13 +650,13 @@ sub cat_vet {
} }
my $av_preprocessor = 0; my $av_preprocessor = 0;
my $av_paren = 0; my $av_pending;
my @av_paren_type; my @av_paren_type;
sub annotate_reset { sub annotate_reset {
$av_preprocessor = 0; $av_preprocessor = 0;
$av_paren = 0; $av_pending = '_';
@av_paren_type = (); @av_paren_type = ('E');
} }
sub annotate_values { sub annotate_values {
@ -611,12 +668,13 @@ sub annotate_values {
print "$stream\n" if ($dbg_values > 1); print "$stream\n" if ($dbg_values > 1);
while (length($cur)) { while (length($cur)) {
print " <$type> " if ($dbg_values > 1); print " <" . join('', @av_paren_type) .
"> <$type> " if ($dbg_values > 1);
if ($cur =~ /^(\s+)/o) { if ($cur =~ /^(\s+)/o) {
print "WS($1)\n" if ($dbg_values > 1); print "WS($1)\n" if ($dbg_values > 1);
if ($1 =~ /\n/ && $av_preprocessor) { if ($1 =~ /\n/ && $av_preprocessor) {
$type = pop(@av_paren_type);
$av_preprocessor = 0; $av_preprocessor = 0;
$type = 'N';
} }
} elsif ($cur =~ /^($Type)/) { } elsif ($cur =~ /^($Type)/) {
@ -626,11 +684,33 @@ sub annotate_values {
} elsif ($cur =~ /^(#\s*define\s*$Ident)(\(?)/o) { } elsif ($cur =~ /^(#\s*define\s*$Ident)(\(?)/o) {
print "DEFINE($1)\n" if ($dbg_values > 1); print "DEFINE($1)\n" if ($dbg_values > 1);
$av_preprocessor = 1; $av_preprocessor = 1;
$av_paren_type[$av_paren] = 'N'; $av_pending = 'N';
} elsif ($cur =~ /^(#\s*(?:ifdef|ifndef|if|else|elif|endif))/o) { } elsif ($cur =~ /^(#\s*(?:ifdef|ifndef|if))/o) {
print "PRE($1)\n" if ($dbg_values > 1); print "PRE_START($1)\n" if ($dbg_values > 1);
$av_preprocessor = 1; $av_preprocessor = 1;
push(@av_paren_type, $type);
push(@av_paren_type, $type);
$type = 'N';
} elsif ($cur =~ /^(#\s*(?:else|elif))/o) {
print "PRE_RESTART($1)\n" if ($dbg_values > 1);
$av_preprocessor = 1;
push(@av_paren_type, $av_paren_type[$#av_paren_type]);
$type = 'N';
} elsif ($cur =~ /^(#\s*(?:endif))/o) {
print "PRE_END($1)\n" if ($dbg_values > 1);
$av_preprocessor = 1;
# Assume all arms of the conditional end as this
# one does, and continue as if the #endif was not here.
pop(@av_paren_type);
push(@av_paren_type, $type);
$type = 'N'; $type = 'N';
} elsif ($cur =~ /^(\\\n)/o) { } elsif ($cur =~ /^(\\\n)/o) {
@ -639,13 +719,13 @@ sub annotate_values {
} elsif ($cur =~ /^(sizeof)\s*(\()?/o) { } elsif ($cur =~ /^(sizeof)\s*(\()?/o) {
print "SIZEOF($1)\n" if ($dbg_values > 1); print "SIZEOF($1)\n" if ($dbg_values > 1);
if (defined $2) { if (defined $2) {
$av_paren_type[$av_paren] = 'V'; $av_pending = 'V';
} }
$type = 'N'; $type = 'N';
} elsif ($cur =~ /^(if|while|typeof|__typeof__|for)\b/o) { } elsif ($cur =~ /^(if|while|typeof|__typeof__|for)\b/o) {
print "COND($1)\n" if ($dbg_values > 1); print "COND($1)\n" if ($dbg_values > 1);
$av_paren_type[$av_paren] = 'N'; $av_pending = 'N';
$type = 'N'; $type = 'N';
} elsif ($cur =~/^(return|case|else)/o) { } elsif ($cur =~/^(return|case|else)/o) {
@ -654,14 +734,14 @@ sub annotate_values {
} elsif ($cur =~ /^(\()/o) { } elsif ($cur =~ /^(\()/o) {
print "PAREN('$1')\n" if ($dbg_values > 1); print "PAREN('$1')\n" if ($dbg_values > 1);
$av_paren++; push(@av_paren_type, $av_pending);
$av_pending = '_';
$type = 'N'; $type = 'N';
} elsif ($cur =~ /^(\))/o) { } elsif ($cur =~ /^(\))/o) {
$av_paren-- if ($av_paren > 0); my $new_type = pop(@av_paren_type);
if (defined $av_paren_type[$av_paren]) { if ($new_type ne '_') {
$type = $av_paren_type[$av_paren]; $type = $new_type;
undef $av_paren_type[$av_paren];
print "PAREN('$1') -> $type\n" print "PAREN('$1') -> $type\n"
if ($dbg_values > 1); if ($dbg_values > 1);
} else { } else {
@ -670,7 +750,7 @@ sub annotate_values {
} elsif ($cur =~ /^($Ident)\(/o) { } elsif ($cur =~ /^($Ident)\(/o) {
print "FUNC($1)\n" if ($dbg_values > 1); print "FUNC($1)\n" if ($dbg_values > 1);
$av_paren_type[$av_paren] = 'V'; $av_pending = 'V';
} elsif ($cur =~ /^($Ident|$Constant)/o) { } elsif ($cur =~ /^($Ident|$Constant)/o) {
print "IDENT($1)\n" if ($dbg_values > 1); print "IDENT($1)\n" if ($dbg_values > 1);
@ -680,11 +760,11 @@ sub annotate_values {
print "ASSIGN($1)\n" if ($dbg_values > 1); print "ASSIGN($1)\n" if ($dbg_values > 1);
$type = 'N'; $type = 'N';
} elsif ($cur =~/^(;)/) { } elsif ($cur =~/^(;|{|})/) {
print "END($1)\n" if ($dbg_values > 1); print "END($1)\n" if ($dbg_values > 1);
$type = 'E'; $type = 'E';
} elsif ($cur =~ /^(;|{|}|\?|:|\[)/o) { } elsif ($cur =~ /^(;|\?|:|\[)/o) {
print "CLOSE($1)\n" if ($dbg_values > 1); print "CLOSE($1)\n" if ($dbg_values > 1);
$type = 'N'; $type = 'N';
@ -988,7 +1068,7 @@ sub process {
} }
# check for RCS/CVS revision markers # check for RCS/CVS revision markers
if ($rawline =~ /\$(Revision|Log|Id)(?:\$|)/) { if ($rawline =~ /^\+.*\$(Revision|Log|Id)(?:\$|)/) {
WARN("CVS style keyword markers, these will _not_ be updated\n". $herecurr); WARN("CVS style keyword markers, these will _not_ be updated\n". $herecurr);
} }
@ -999,41 +1079,44 @@ sub process {
# Check for potential 'bare' types # Check for potential 'bare' types
if ($realcnt) { if ($realcnt) {
my ($s, $c) = ctx_statement_block($linenr, $realcnt, 0);
$s =~ s/\n./ /g;
$s =~ s/{.*$//;
# Ignore goto labels. # Ignore goto labels.
if ($line =~ /$Ident:\*$/) { if ($s =~ /$Ident:\*$/) {
# Ignore functions being called # Ignore functions being called
} elsif ($line =~ /^.\s*$Ident\s*\(/) { } elsif ($s =~ /^.\s*$Ident\s*\(/) {
# definitions in global scope can only start with types # definitions in global scope can only start with types
} elsif ($line =~ /^.(?:$Storage\s+)?(?:$Inline\s+)?(?:const\s+)?($Ident)\b/) { } elsif ($s =~ /^.(?:$Storage\s+)?(?:$Inline\s+)?(?:const\s+)?($Ident)\b/) {
possible($1, $line); possible($1, $s);
# declarations always start with types # declarations always start with types
} elsif ($prev_values eq 'E' && $line =~ /^.\s*(?:$Storage\s+)?(?:const\s+)?($Ident)\b(:?\s+$Sparse)?\s*\**\s*$Ident\s*(?:;|=|,)/) { } elsif ($prev_values eq 'E' && $s =~ /^.\s*(?:$Storage\s+)?(?:const\s+)?($Ident)\b(:?\s+$Sparse)?\s*\**\s*$Ident\s*(?:;|=|,)/) {
possible($1); possible($1, $s);
} }
# any (foo ... *) is a pointer cast, and foo is a type # any (foo ... *) is a pointer cast, and foo is a type
while ($line =~ /\(($Ident)(?:\s+$Sparse)*\s*\*+\s*\)/g) { while ($s =~ /\(($Ident)(?:\s+$Sparse)*\s*\*+\s*\)/g) {
possible($1, $line); possible($1, $s);
} }
# Check for any sort of function declaration. # Check for any sort of function declaration.
# int foo(something bar, other baz); # int foo(something bar, other baz);
# void (*store_gdt)(x86_descr_ptr *); # void (*store_gdt)(x86_descr_ptr *);
if ($prev_values eq 'E' && $line =~ /^(.(?:typedef\s*)?(?:(?:$Storage|$Inline)\s*)*\s*$Type\s*(?:\b$Ident|\(\*\s*$Ident\))\s*)\(/) { if ($prev_values eq 'E' && $s =~ /^(.(?:typedef\s*)?(?:(?:$Storage|$Inline)\s*)*\s*$Type\s*(?:\b$Ident|\(\*\s*$Ident\))\s*)\(/) {
my ($name_len) = length($1); my ($name_len) = length($1);
my ($level, @ctx) = ctx_statement_level($linenr, $realcnt, $name_len);
my $ctx = join("\n", @ctx);
$ctx =~ s/\n.//; my $ctx = $s;
substr($ctx, 0, $name_len + 1) = ''; substr($ctx, 0, $name_len + 1) = '';
$ctx =~ s/\)[^\)]*$//; $ctx =~ s/\)[^\)]*$//;
for my $arg (split(/\s*,\s*/, $ctx)) { for my $arg (split(/\s*,\s*/, $ctx)) {
if ($arg =~ /^(?:const\s+)?($Ident)(?:\s+$Sparse)*\s*\**\s*(:?\b$Ident)?$/ || $arg =~ /^($Ident)$/) { if ($arg =~ /^(?:const\s+)?($Ident)(?:\s+$Sparse)*\s*\**\s*(:?\b$Ident)?$/ || $arg =~ /^($Ident)$/) {
possible($1, $line); possible($1, $s);
} }
} }
} }
@ -1100,8 +1183,8 @@ sub process {
$curr_values = $prev_values . $curr_values; $curr_values = $prev_values . $curr_values;
if ($dbg_values) { if ($dbg_values) {
my $outline = $opline; $outline =~ s/\t/ /g; my $outline = $opline; $outline =~ s/\t/ /g;
warn "--> .$outline\n"; print "$linenr > .$outline\n";
warn "--> $curr_values\n"; print "$linenr > $curr_values\n";
} }
$prev_values = substr($curr_values, -1); $prev_values = substr($curr_values, -1);
@ -1148,7 +1231,9 @@ sub process {
if (($prevline !~ /^}/) && if (($prevline !~ /^}/) &&
($prevline !~ /^\+}/) && ($prevline !~ /^\+}/) &&
($prevline !~ /^ }/) && ($prevline !~ /^ }/) &&
($prevline !~ /\b\Q$name\E(?:\s+$Attribute)?\s*(?:;|=)/)) { ($prevline !~ /^.DECLARE_$Ident\(\Q$name\E\)/) &&
($prevline !~ /^.LIST_HEAD\(\Q$name\E\)/) &&
($prevline !~ /\b\Q$name\E(?:\s+$Attribute)?\s*(?:;|=|\[)/)) {
WARN("EXPORT_SYMBOL(foo); should immediately follow its function/variable\n" . $herecurr); WARN("EXPORT_SYMBOL(foo); should immediately follow its function/variable\n" . $herecurr);
} }
} }
@ -1266,7 +1351,7 @@ sub process {
=>|->|<<|>>|<|>|=|!|~| =>|->|<<|>>|<|>|=|!|~|
&&|\|\||,|\^|\+\+|--|&|\||\+|-|\*|\/|% &&|\|\||,|\^|\+\+|--|&|\||\+|-|\*|\/|%
}x; }x;
my @elements = split(/($;+|$ops|;)/, $opline); my @elements = split(/($ops|;)/, $opline);
my $off = 0; my $off = 0;
my $blank = copy_spacing($opline); my $blank = copy_spacing($opline);
@ -1277,6 +1362,7 @@ sub process {
my $a = ''; my $a = '';
$a = 'V' if ($elements[$n] ne ''); $a = 'V' if ($elements[$n] ne '');
$a = 'W' if ($elements[$n] =~ /\s$/); $a = 'W' if ($elements[$n] =~ /\s$/);
$a = 'C' if ($elements[$n] =~ /$;$/);
$a = 'B' if ($elements[$n] =~ /(\[|\()$/); $a = 'B' if ($elements[$n] =~ /(\[|\()$/);
$a = 'O' if ($elements[$n] eq ''); $a = 'O' if ($elements[$n] eq '');
$a = 'E' if ($elements[$n] eq '' && $n == 0); $a = 'E' if ($elements[$n] eq '' && $n == 0);
@ -1287,6 +1373,7 @@ sub process {
if (defined $elements[$n + 2]) { if (defined $elements[$n + 2]) {
$c = 'V' if ($elements[$n + 2] ne ''); $c = 'V' if ($elements[$n + 2] ne '');
$c = 'W' if ($elements[$n + 2] =~ /^\s/); $c = 'W' if ($elements[$n + 2] =~ /^\s/);
$c = 'C' if ($elements[$n + 2] =~ /^$;/);
$c = 'B' if ($elements[$n + 2] =~ /^(\)|\]|;)/); $c = 'B' if ($elements[$n + 2] =~ /^(\)|\]|;)/);
$c = 'O' if ($elements[$n + 2] eq ''); $c = 'O' if ($elements[$n + 2] eq '');
$c = 'E' if ($elements[$n + 2] =~ /\s*\\$/); $c = 'E' if ($elements[$n + 2] =~ /\s*\\$/);
@ -1330,13 +1417,13 @@ sub process {
if ($op_type ne 'V' && if ($op_type ne 'V' &&
$ca =~ /\s$/ && $cc =~ /^\s*,/) { $ca =~ /\s$/ && $cc =~ /^\s*,/) {
# Ignore comments # # Ignore comments
} elsif ($op =~ /^$;+$/) { # } elsif ($op =~ /^$;+$/) {
# ; should have either the end of line or a space or \ after it # ; should have either the end of line or a space or \ after it
} elsif ($op eq ';') { } elsif ($op eq ';') {
if ($ctx !~ /.x[WEB]/ && $cc !~ /^\\/ && if ($ctx !~ /.x[WEBC]/ &&
$cc !~ /^;/) { $cc !~ /^\\/ && $cc !~ /^;/) {
ERROR("need space after that '$op' $at\n" . $hereptr); ERROR("need space after that '$op' $at\n" . $hereptr);
} }
@ -1351,7 +1438,7 @@ sub process {
# , must have a space on the right. # , must have a space on the right.
} elsif ($op eq ',') { } elsif ($op eq ',') {
if ($ctx !~ /.xW|.xE/ && $cc !~ /^}/) { if ($ctx !~ /.x[WEC]/ && $cc !~ /^}/) {
ERROR("need space after that '$op' $at\n" . $hereptr); ERROR("need space after that '$op' $at\n" . $hereptr);
} }
@ -1364,7 +1451,7 @@ sub process {
# unary operator, or a cast # unary operator, or a cast
} elsif ($op eq '!' || $op eq '~' || } elsif ($op eq '!' || $op eq '~' ||
($is_unary && ($op eq '*' || $op eq '-' || $op eq '&'))) { ($is_unary && ($op eq '*' || $op eq '-' || $op eq '&'))) {
if ($ctx !~ /[WEB]x./ && $ca !~ /(?:\)|!|~|\*|-|\&|\||\+\+|\-\-|\{)$/) { if ($ctx !~ /[WEBC]x./ && $ca !~ /(?:\)|!|~|\*|-|\&|\||\+\+|\-\-|\{)$/) {
ERROR("need space before that '$op' $at\n" . $hereptr); ERROR("need space before that '$op' $at\n" . $hereptr);
} }
if ($ctx =~ /.xW/) { if ($ctx =~ /.xW/) {
@ -1373,7 +1460,7 @@ sub process {
# unary ++ and unary -- are allowed no space on one side. # unary ++ and unary -- are allowed no space on one side.
} elsif ($op eq '++' or $op eq '--') { } elsif ($op eq '++' or $op eq '--') {
if ($ctx !~ /[WOB]x[^W]/ && $ctx !~ /[^W]x[WOBE]/) { if ($ctx !~ /[WOBC]x[^W]/ && $ctx !~ /[^W]x[WOBEC]/) {
ERROR("need space one side of that '$op' $at\n" . $hereptr); ERROR("need space one side of that '$op' $at\n" . $hereptr);
} }
if ($ctx =~ /WxB/ || ($ctx =~ /Wx./ && $cc =~ /^;/)) { if ($ctx =~ /WxB/ || ($ctx =~ /Wx./ && $cc =~ /^;/)) {
@ -1387,13 +1474,13 @@ sub process {
$op eq '*' or $op eq '/' or $op eq '*' or $op eq '/' or
$op eq '%') $op eq '%')
{ {
if ($ctx !~ /VxV|WxW|VxE|WxE|VxO/) { if ($ctx !~ /VxV|WxW|VxE|WxE|VxO|Cx.|.xC/) {
ERROR("need consistent spacing around '$op' $at\n" . ERROR("need consistent spacing around '$op' $at\n" .
$hereptr); $hereptr);
} }
# All the others need spaces both sides. # All the others need spaces both sides.
} elsif ($ctx !~ /[EW]x[WE]/) { } elsif ($ctx !~ /[EWC]x[CWE]/) {
# Ignore email addresses <foo@bar> # Ignore email addresses <foo@bar>
if (!($op eq '<' && $cb =~ /$;\S+\@\S+>/) && if (!($op eq '<' && $cb =~ /$;\S+\@\S+>/) &&
!($op eq '>' && $cb =~ /<\S+\@\S+$;/)) { !($op eq '>' && $cb =~ /<\S+\@\S+$;/)) {
@ -1551,7 +1638,7 @@ sub process {
# multi-statement macros should be enclosed in a do while loop, grab the # multi-statement macros should be enclosed in a do while loop, grab the
# first statement and ensure its the whole macro if its not enclosed # first statement and ensure its the whole macro if its not enclosed
# in a known goot container # in a known good container
if ($prevline =~ /\#define.*\\/ && if ($prevline =~ /\#define.*\\/ &&
$prevline !~/(?:do\s+{|\(\{|\{)/ && $prevline !~/(?:do\s+{|\(\{|\{)/ &&
$line !~ /(?:do\s+{|\(\{|\{)/ && $line !~ /(?:do\s+{|\(\{|\{)/ &&
@ -1599,84 +1686,95 @@ sub process {
# check for redundant bracing round if etc # check for redundant bracing round if etc
if ($line =~ /(^.*)\bif\b/ && $1 !~ /else\s*$/) { if ($line =~ /(^.*)\bif\b/ && $1 !~ /else\s*$/) {
my ($level, $endln, @chunks) = my ($level, $endln, @chunks) =
ctx_statement_full($linenr, $realcnt, 0); ctx_statement_full($linenr, $realcnt, 1);
#print "chunks<$#chunks> linenr<$linenr> endln<$endln> level<$level>\n"; #print "chunks<$#chunks> linenr<$linenr> endln<$endln> level<$level>\n";
if ($#chunks > 1 && $level == 0) { #print "APW: <<$chunks[1][0]>><<$chunks[1][1]>>\n";
if ($#chunks > 0 && $level == 0) {
my $allowed = 0; my $allowed = 0;
my $seen = 0; my $seen = 0;
my $herectx = $here . "\n";;
my $ln = $linenr - 1;
for my $chunk (@chunks) { for my $chunk (@chunks) {
my ($cond, $block) = @{$chunk}; my ($cond, $block) = @{$chunk};
$herectx .= "$rawlines[$ln]\n[...]\n";
$ln += statement_rawlines($block) - 1;
substr($block, 0, length($cond)) = ''; substr($block, 0, length($cond)) = '';
$seen++ if ($block =~ /^\s*{/); $seen++ if ($block =~ /^\s*{/);
$block =~ s/(^|\n)./$1/g; #print "cond<$cond> block<$block> allowed<$allowed>\n";
$block =~ s/^\s*{//; if (statement_lines($cond) > 1) {
$block =~ s/}\s*$//; #print "APW: ALLOWED: cond<$cond>\n";
$block =~ s/^\s*//;
$block =~ s/\s*$//;
my @lines = ($block =~ /\n/g);
my @statements = ($block =~ /;/g);
#print "cond<$cond> block<$block> lines<" . scalar(@lines) . "> statements<" . scalar(@statements) . "> seen<$seen> allowed<$allowed>\n";
if (scalar(@lines) != 0) {
$allowed = 1; $allowed = 1;
} }
if ($block =~/\b(?:if|for|while)\b/) { if ($block =~/\b(?:if|for|while)\b/) {
#print "APW: ALLOWED: block<$block>\n";
$allowed = 1; $allowed = 1;
} }
if (scalar(@statements) > 1) { if (statement_block_size($block) > 1) {
#print "APW: ALLOWED: lines block<$block>\n";
$allowed = 1; $allowed = 1;
} }
} }
if ($seen && !$allowed) { if ($seen && !$allowed) {
WARN("braces {} are not necessary for any arm of this statement\n" . $herecurr); WARN("braces {} are not necessary for any arm of this statement\n" . $herectx);
$suppress_ifbraces = $endln;
} }
# Either way we have looked over this whole
# statement and said what needs to be said.
$suppress_ifbraces = $endln;
} }
} }
if ($linenr > $suppress_ifbraces && if ($linenr > $suppress_ifbraces &&
$line =~ /\b(if|while|for|else)\b/) { $line =~ /\b(if|while|for|else)\b/) {
# Locate the end of the opening statement. my ($level, $endln, @chunks) =
my @control = ctx_statement($linenr, $realcnt, 0); ctx_statement_full($linenr, $realcnt, $-[0]);
my $nr = $linenr + (scalar(@control) - 1);
my $cnt = $realcnt - (scalar(@control) - 1);
my $off = $realcnt - $cnt; my $allowed = 0;
#print "$off: line<$line>end<" . $lines[$nr - 1] . ">\n";
# If this is is a braced statement group check it # Check the pre-context.
if ($lines[$nr - 1] =~ /{\s*$/) { if (substr($line, 0, $-[0]) =~ /(\}\s*)$/) {
my ($lvl, @block) = ctx_block_level($nr, $cnt); #print "APW: ALLOWED: pre<$1>\n";
$allowed = 1;
my $stmt = join("\n", @block); }
# Drop the diff line leader. # Check the condition.
$stmt =~ s/\n./\n/g; my ($cond, $block) = @{$chunks[0]};
# Drop the code outside the block. if (defined $cond) {
$stmt =~ s/(^[^{]*){\s*//; substr($block, 0, length($cond)) = '';
my $before = $1; }
$stmt =~ s/\s*}([^}]*$)//; if (statement_lines($cond) > 1) {
my $after = $1; #print "APW: ALLOWED: cond<$cond>\n";
$allowed = 1;
#print "block<" . join(' ', @block) . "><" . scalar(@block) . ">\n"; }
#print "before<$before> stmt<$stmt> after<$after>\n\n"; if ($block =~/\b(?:if|for|while)\b/) {
#print "APW: ALLOWED: block<$block>\n";
# Count the newlines, if there is only one $allowed = 1;
# then the block should not have {}'s. }
my @lines = ($stmt =~ /\n/g); if (statement_block_size($block) > 1) {
my @statements = ($stmt =~ /;/g); #print "APW: ALLOWED: lines block<$block>\n";
#print "lines<" . scalar(@lines) . ">\n"; $allowed = 1;
#print "statements<" . scalar(@statements) . ">\n"; }
if ($lvl == 0 && scalar(@lines) == 0 && # Check the post-context.
scalar(@statements) < 2 && if (defined $chunks[1]) {
$stmt !~ /{/ && $stmt !~ /\bif\b/ && my ($cond, $block) = @{$chunks[1]};
$before !~ /}/ && $after !~ /{/) { if (defined $cond) {
my $herectx = "$here\n" . join("\n", @control, @block[1 .. $#block]) . "\n"; substr($block, 0, length($cond)) = '';
shift(@block);
WARN("braces {} are not necessary for single statement blocks\n" . $herectx);
} }
if ($block =~ /^\s*\{/) {
#print "APW: ALLOWED: chunk-1 block<$block>\n";
$allowed = 1;
}
}
if ($level == 0 && $block =~ /^\s*\{/ && !$allowed) {
my $herectx = $here . "\n";;
my $end = $linenr + statement_rawlines($block) - 1;
for (my $ln = $linenr - 1; $ln < $end; $ln++) {
$herectx .= $rawlines[$ln] . "\n";;
}
WARN("braces {} are not necessary for single statement blocks\n" . $herectx);
} }
} }
@ -1828,15 +1926,6 @@ sub process {
print "are false positives report them to the maintainer, see\n"; print "are false positives report them to the maintainer, see\n";
print "CHECKPATCH in MAINTAINERS.\n"; print "CHECKPATCH in MAINTAINERS.\n";
} }
print <<EOL if ($file == 1 && $quiet == 0);
WARNING: Using --file mode. Please do not send patches to linux-kernel
that change whole existing files if you did not significantly change most
of the the file for other reasons anyways or just wrote the file newly
from scratch. Pure code style patches have a significant cost in a
quickly changing code base like Linux because they cause rejects
with other changes.
EOL
return $clean; return $clean;
} }