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

update checkpatch.pl to version 0.19

This version is a bit of a whopper.  This version brings a few new checks,
improvements to a number of checks mostly through modifications to the
way types are parsed, several fixes to quote/comment handling, as well as
the usual slew of fixes for false positives.

Of note:
 - return is not a function and is now reported,
 - preprocessor directive detection is loosened to match C99 standard,
 - we now intuit new type modifiers, and
 - comment handling is much improved

Andy Whitcroft (18):
      Version: 0.19
      fix up a couple of missing newlines in reports
      colon to parenthesis spacing varies on asm
      values: #include is a preprocessor statement
      quotes: fix single character quotes at line end
      add typedef exception for the non-pointer "function types"
      kerneldoc parameters must be on one line, relax line length
      types: word boundary is not always required
      improved #define bracketing reports
      uninitialized_var is an annotation not a function name
      possible types: add possible modifier handling
      possible types: fastcall is a type modifier
      types: unsigned is not a modifier on all types
      static/external initialisation to zero should allow modifiers
      checkpatch: fix recognition of preprocessor directives -- part 2
      comments: fix inter-hunk comment tracking
      return is not a function
      do not report include/asm/foo.h use in include/linux/foo.h
      return is not a function -- tighten test

[jengelh@computergmbh.de: fix recognition of preprocessor directives]
Signed-off-by: default avatarAndy Whitcroft <apw@shadowen.org>
Cc: Jan Engelhardt <jengelh@computergmbh.de>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 4feead71
...@@ -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.18'; my $V = '0.19';
use Getopt::Long qw(:config no_auto_abbrev); use Getopt::Long qw(:config no_auto_abbrev);
...@@ -115,6 +115,7 @@ our $Attribute = qr{ ...@@ -115,6 +115,7 @@ our $Attribute = qr{
__kprobes| __kprobes|
__(?:mem|cpu|dev|)(?:initdata|init) __(?:mem|cpu|dev|)(?:initdata|init)
}x; }x;
our $Modifier;
our $Inline = qr{inline|__always_inline|noinline}; our $Inline = qr{inline|__always_inline|noinline};
our $Member = qr{->$Ident|\.$Ident|\[[^]]*\]}; our $Member = qr{->$Ident|\.$Ident|\[[^]]*\]};
our $Lval = qr{$Ident(?:$Member)*}; our $Lval = qr{$Ident(?:$Member)*};
...@@ -144,17 +145,17 @@ our $UTF8 = qr { ...@@ -144,17 +145,17 @@ our $UTF8 = qr {
our @typeList = ( our @typeList = (
qr{void}, qr{void},
qr{char}, qr{(?:unsigned\s+)?char},
qr{short}, qr{(?:unsigned\s+)?short},
qr{int}, qr{(?:unsigned\s+)?int},
qr{long}, qr{(?:unsigned\s+)?long},
qr{(?:unsigned\s+)?long\s+int},
qr{(?:unsigned\s+)?long\s+long},
qr{(?:unsigned\s+)?long\s+long\s+int},
qr{unsigned}, qr{unsigned},
qr{float}, qr{float},
qr{double}, qr{double},
qr{bool}, qr{bool},
qr{long\s+int},
qr{long\s+long},
qr{long\s+long\s+int},
qr{(?:__)?(?:u|s|be|le)(?:8|16|32|64)}, qr{(?:__)?(?:u|s|be|le)(?:8|16|32|64)},
qr{struct\s+$Ident}, qr{struct\s+$Ident},
qr{union\s+$Ident}, qr{union\s+$Ident},
...@@ -163,26 +164,29 @@ our @typeList = ( ...@@ -163,26 +164,29 @@ our @typeList = (
qr{${Ident}_handler}, qr{${Ident}_handler},
qr{${Ident}_handler_fn}, qr{${Ident}_handler_fn},
); );
our @modifierList = (
qr{fastcall},
);
sub build_types { sub build_types {
my $mods = "(?: \n" . join("|\n ", @modifierList) . "\n)";
my $all = "(?: \n" . join("|\n ", @typeList) . "\n)"; my $all = "(?: \n" . join("|\n ", @typeList) . "\n)";
$NonptrType = qr{ $NonptrType = qr{
\b
(?:const\s+)? (?:const\s+)?
(?:unsigned\s+)? (?:$mods\s+)?
(?: (?:
$all| (?:typeof|__typeof__)\s*\(\s*\**\s*$Ident\s*\)|
(?:typeof|__typeof__)\s*\(\s*\**\s*$Ident\s*\) (?:${all}\b)
) )
(?:\s+$Sparse|\s+const)* (?:\s+$Sparse|\s+const)*
\b
}x; }x;
$Type = qr{ $Type = qr{
\b$NonptrType\b $NonptrType
(?:\s*\*+\s*const|\s*\*+|(?:\s*\[\s*\])+)? (?:\s*\*+\s*const|\s*\*+|(?:\s*\[\s*\])+)?
(?:\s+$Inline|\s+$Sparse|\s+$Attribute)* (?:\s+$Inline|\s+$Sparse|\s+$Attribute|\s+$mods)*
}x; }x;
$Declare = qr{(?:$Storage\s+)?$Type}; $Declare = qr{(?:$Storage\s+)?$Type};
$Modifier = qr{(?:$Attribute|$Sparse|$mods)};
} }
build_types(); build_types();
...@@ -329,7 +333,7 @@ sub sanitise_line { ...@@ -329,7 +333,7 @@ sub sanitise_line {
$off++; $off++;
next; next;
} }
if (substr($line, $off, 2) eq $sanitise_quote) { if (substr($line, $off, 2) eq '*/') {
$sanitise_quote = ''; $sanitise_quote = '';
substr($res, $off, 2, "$;$;"); substr($res, $off, 2, "$;$;");
$off++; $off++;
...@@ -366,14 +370,14 @@ sub sanitise_line { ...@@ -366,14 +370,14 @@ sub sanitise_line {
} }
# The pathname on a #include may be surrounded by '<' and '>'. # The pathname on a #include may be surrounded by '<' and '>'.
if ($res =~ /^.#\s*include\s+\<(.*)\>/) { if ($res =~ /^.\s*\#\s*include\s+\<(.*)\>/) {
my $clean = 'X' x length($1); my $clean = 'X' x length($1);
$res =~ s@\<.*\>@<$clean>@; $res =~ s@\<.*\>@<$clean>@;
# The whole of a #error is a string. # The whole of a #error is a string.
} elsif ($res =~ /^.#\s*(?:error|warning)\s+(.*)\b/) { } elsif ($res =~ /^.\s*\#\s*(?:error|warning)\s+(.*)\b/) {
my $clean = 'X' x length($1); my $clean = 'X' x length($1);
$res =~ s@(#\s*(?:error|warning)\s+).*@$1$clean@; $res =~ s@(\#\s*(?:error|warning)\s+).*@$1$clean@;
} }
return $res; return $res;
...@@ -715,7 +719,7 @@ sub annotate_values { ...@@ -715,7 +719,7 @@ sub annotate_values {
print "DECLARE($1)\n" if ($dbg_values > 1); print "DECLARE($1)\n" if ($dbg_values > 1);
$type = 'T'; $type = 'T';
} elsif ($cur =~ /^(#\s*define\s*$Ident)(\(?)/o) { } elsif ($cur =~ /^(\#\s*define\s*$Ident)(\(?)/o) {
print "DEFINE($1,$2)\n" if ($dbg_values > 1); print "DEFINE($1,$2)\n" if ($dbg_values > 1);
$av_preprocessor = 1; $av_preprocessor = 1;
push(@av_paren_type, $type); push(@av_paren_type, $type);
...@@ -724,12 +728,12 @@ sub annotate_values { ...@@ -724,12 +728,12 @@ sub annotate_values {
} }
$type = 'E'; $type = 'E';
} elsif ($cur =~ /^(#\s*undef\s*$Ident)/o) { } elsif ($cur =~ /^(\#\s*(?:undef\s*$Ident|include\b))/o) {
print "UNDEF($1)\n" if ($dbg_values > 1); print "UNDEF($1)\n" if ($dbg_values > 1);
$av_preprocessor = 1; $av_preprocessor = 1;
push(@av_paren_type, $type); push(@av_paren_type, $type);
} elsif ($cur =~ /^(#\s*(?:ifdef|ifndef|if))/o) { } elsif ($cur =~ /^(\#\s*(?:ifdef|ifndef|if))/o) {
print "PRE_START($1)\n" if ($dbg_values > 1); print "PRE_START($1)\n" if ($dbg_values > 1);
$av_preprocessor = 1; $av_preprocessor = 1;
...@@ -737,7 +741,7 @@ sub annotate_values { ...@@ -737,7 +741,7 @@ sub annotate_values {
push(@av_paren_type, $type); push(@av_paren_type, $type);
$type = 'E'; $type = 'E';
} elsif ($cur =~ /^(#\s*(?:else|elif))/o) { } elsif ($cur =~ /^(\#\s*(?:else|elif))/o) {
print "PRE_RESTART($1)\n" if ($dbg_values > 1); print "PRE_RESTART($1)\n" if ($dbg_values > 1);
$av_preprocessor = 1; $av_preprocessor = 1;
...@@ -745,7 +749,7 @@ sub annotate_values { ...@@ -745,7 +749,7 @@ sub annotate_values {
$type = 'E'; $type = 'E';
} elsif ($cur =~ /^(#\s*(?:endif))/o) { } elsif ($cur =~ /^(\#\s*(?:endif))/o) {
print "PRE_END($1)\n" if ($dbg_values > 1); print "PRE_END($1)\n" if ($dbg_values > 1);
$av_preprocessor = 1; $av_preprocessor = 1;
...@@ -837,14 +841,26 @@ sub annotate_values { ...@@ -837,14 +841,26 @@ sub annotate_values {
sub possible { sub possible {
my ($possible, $line) = @_; my ($possible, $line) = @_;
#print "CHECK<$possible>\n"; print "CHECK<$possible> ($line)\n" if ($dbg_possible > 1);
if ($possible !~ /^(?:$Storage|$Type|DEFINE_\S+)$/ && if ($possible !~ /^(?:$Storage|$Type|DEFINE_\S+)$/ &&
$possible ne 'goto' && $possible ne 'return' && $possible ne 'goto' && $possible ne 'return' &&
$possible ne 'struct' && $possible ne 'enum' &&
$possible ne 'case' && $possible ne 'else' && $possible ne 'case' && $possible ne 'else' &&
$possible ne 'typedef') { $possible ne 'asm' &&
$possible !~ /^(typedef|struct|enum)\b/) {
# Check for modifiers.
$possible =~ s/\s*$Storage\s*//g;
$possible =~ s/\s*$Sparse\s*//g;
if ($possible =~ /^\s*$/) {
} elsif ($possible =~ /\s/) {
$possible =~ s/\s*$Type\s*//g;
warn "MODIFIER: $possible ($line)\n" if ($dbg_possible);
push(@modifierList, $possible);
} else {
warn "POSSIBLE: $possible ($line)\n" if ($dbg_possible); warn "POSSIBLE: $possible ($line)\n" if ($dbg_possible);
push(@typeList, $possible); push(@typeList, $possible);
}
build_types(); build_types();
} }
} }
...@@ -949,6 +965,7 @@ sub process { ...@@ -949,6 +965,7 @@ sub process {
} else { } else {
$realcnt=1+1; $realcnt=1+1;
} }
$in_comment = 0;
# Guestimate if this is a continuing comment. Run # Guestimate if this is a continuing comment. Run
# the context looking for a comment "edge". If this # the context looking for a comment "edge". If this
...@@ -1117,7 +1134,9 @@ sub process { ...@@ -1117,7 +1134,9 @@ sub process {
ERROR("trailing whitespace\n" . $herevet); ERROR("trailing whitespace\n" . $herevet);
} }
#80 column limit #80 column limit
if ($line =~ /^\+/ && !($prevrawline=~/\/\*\*/) && $length > 80) { if ($line =~ /^\+/ && $prevrawline !~ /\/\*\*/ &&
$rawline !~ /^.\s*\*\s*\@$Ident\s/ && $length > 80)
{
WARN("line over 80 characters\n" . $herecurr); WARN("line over 80 characters\n" . $herecurr);
} }
...@@ -1159,18 +1178,20 @@ sub process { ...@@ -1159,18 +1178,20 @@ sub process {
# Ignore functions being called # Ignore functions being called
} elsif ($s =~ /^.\s*$Ident\s*\(/s) { } elsif ($s =~ /^.\s*$Ident\s*\(/s) {
# declarations always start with types
} elsif ($prev_values eq 'E' && $s =~ /^.\s*(?:$Storage\s+)?(?:$Inline\s+)?(?:const\s+)?((?:\s*$Ident)+)\b(?:\s+$Sparse)?\s*\**\s*(?:$Ident|\(\*[^\)]*\))\s*(?:;|=|,|\()/s) {
my $type = $1;
$type =~ s/\s+/ /g;
possible($type, "A:" . $s);
# definitions in global scope can only start with types # definitions in global scope can only start with types
} elsif ($s =~ /^.(?:$Storage\s+)?(?:$Inline\s+)?(?:const\s+)?($Ident)\b/s) { } elsif ($s =~ /^.(?:$Storage\s+)?(?:$Inline\s+)?(?:const\s+)?($Ident)\b/s) {
possible($1, $s); possible($1, "B:" . $s);
# declarations always start with types
} elsif ($prev_values eq 'E' && $s =~ /^.\s*(?:$Storage\s+)?(?:const\s+)?($Ident)\b(:?\s+$Sparse)?\s*\**\s*$Ident\s*(?:;|=|,)/s) {
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 ($s =~ /\(($Ident)(?:\s+$Sparse)*\s*\*+\s*\)/sg) { while ($s =~ /\(($Ident)(?:\s+$Sparse)*\s*\*+\s*\)/sg) {
possible($1, $s); possible($1, "C:" . $s);
} }
# Check for any sort of function declaration. # Check for any sort of function declaration.
...@@ -1184,9 +1205,9 @@ sub process { ...@@ -1184,9 +1205,9 @@ sub process {
$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)?$/s || $arg =~ /^($Ident)$/s) {
possible($1, $s); possible($1, "D:" . $s);
} }
} }
} }
...@@ -1221,7 +1242,7 @@ sub process { ...@@ -1221,7 +1242,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 !~ /^.\s*\#/) {
my $pre_ctx = "$1$2"; my $pre_ctx = "$1$2";
my ($level, @ctx) = ctx_statement_level($linenr, $realcnt, 0); my ($level, @ctx) = ctx_statement_level($linenr, $realcnt, 0);
...@@ -1239,7 +1260,7 @@ sub process { ...@@ -1239,7 +1260,7 @@ sub process {
if ($ctx !~ /{\s*/ && defined($lines[$ctx_ln -1]) && $lines[$ctx_ln - 1] =~ /^\+\s*{/) { if ($ctx !~ /{\s*/ && defined($lines[$ctx_ln -1]) && $lines[$ctx_ln - 1] =~ /^\+\s*{/) {
ERROR("that open brace { 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]\n");
} }
if ($level == 0 && $pre_ctx !~ /}\s*while\s*\($/ && if ($level == 0 && $pre_ctx !~ /}\s*while\s*\($/ &&
$ctx =~ /\)\s*\;\s*$/ && $ctx =~ /\)\s*\;\s*$/ &&
...@@ -1248,7 +1269,7 @@ sub process { ...@@ -1248,7 +1269,7 @@ sub process {
my ($nlength, $nindent) = line_stats($lines[$ctx_ln - 1]); my ($nlength, $nindent) = line_stats($lines[$ctx_ln - 1]);
if ($nindent > $indent) { if ($nindent > $indent) {
WARN("trailing semicolon indicates no statements, indent implies otherwise\n" . WARN("trailing semicolon indicates no statements, indent implies otherwise\n" .
"$here\n$ctx\n$lines[$ctx_ln - 1]"); "$here\n$ctx\n$lines[$ctx_ln - 1]\n");
} }
} }
} }
...@@ -1284,7 +1305,7 @@ sub process { ...@@ -1284,7 +1305,7 @@ sub process {
# #
# check for malformed paths in #include statements (uses RAW line) # check for malformed paths in #include statements (uses RAW line)
if ($rawline =~ m{^.#\s*include\s+[<"](.*)[">]}) { if ($rawline =~ m{^.\s*\#\s*include\s+[<"](.*)[">]}) {
my $path = $1; my $path = $1;
if ($path =~ m{//}) { if ($path =~ m{//}) {
ERROR("malformed #include filename\n" . ERROR("malformed #include filename\n" .
...@@ -1316,7 +1337,7 @@ sub process { ...@@ -1316,7 +1337,7 @@ sub process {
} }
# check for external initialisers. # check for external initialisers.
if ($line =~ /^.$Type\s*$Ident\s*=\s*(0|NULL|false)\s*;/) { if ($line =~ /^.$Type\s*$Ident\s*(?:\s+$Modifier)*\s*=\s*(0|NULL|false)\s*;/) {
ERROR("do not initialise externals to 0 or NULL\n" . ERROR("do not initialise externals to 0 or NULL\n" .
$herecurr); $herecurr);
} }
...@@ -1330,6 +1351,7 @@ sub process { ...@@ -1330,6 +1351,7 @@ sub process {
# make sense. # make sense.
if ($line =~ /\btypedef\s/ && if ($line =~ /\btypedef\s/ &&
$line !~ /\btypedef\s+$Type\s+\(\s*\*?$Ident\s*\)\s*\(/ && $line !~ /\btypedef\s+$Type\s+\(\s*\*?$Ident\s*\)\s*\(/ &&
$line !~ /\btypedef\s+$Type\s+$Ident\s*\(/ &&
$line !~ /\b__bitwise(?:__|)\b/) { $line !~ /\b__bitwise(?:__|)\b/) {
WARN("do not add new typedefs\n" . $herecurr); WARN("do not add new typedefs\n" . $herecurr);
} }
...@@ -1388,8 +1410,8 @@ sub process { ...@@ -1388,8 +1410,8 @@ sub process {
# function brace can't be on same line, except for #defines of do while, # function brace can't be on same line, except for #defines of do while,
# or if closed on same line # or if closed on same line
if (($line=~/$Type\s*[A-Za-z\d_]+\(.*\).*\s{/) and if (($line=~/$Type\s*$Ident\(.*\).*\s{/) and
!($line=~/\#define.*do\s{/) and !($line=~/}/)) { !($line=~/\#\s*define.*do\s{/) and !($line=~/}/)) {
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);
} }
...@@ -1416,10 +1438,10 @@ sub process { ...@@ -1416,10 +1438,10 @@ sub process {
# cpp #define statements have non-optional spaces, ie # cpp #define statements have non-optional spaces, ie
# if there is a space between the name and the open # if there is a space between the name and the open
# parenthesis it is simply not a parameter group. # parenthesis it is simply not a parameter group.
} elsif ($ctx_before =~ /^.\#\s*define\s*$/) { } elsif ($ctx_before =~ /^.\s*\#\s*define\s*$/) {
# cpp #elif statement condition may start with a ( # cpp #elif statement condition may start with a (
} elsif ($ctx =~ /^.\#\s*elif\s*$/) { } elsif ($ctx =~ /^.\s*\#\s*elif\s*$/) {
# If this whole things ends with a type its most # If this whole things ends with a type its most
# likely a typedef for a function. # likely a typedef for a function.
...@@ -1625,13 +1647,14 @@ sub process { ...@@ -1625,13 +1647,14 @@ sub process {
ERROR("space prohibited before that close square bracket ']'\n" . $herecurr); ERROR("space prohibited before that close square bracket ']'\n" . $herecurr);
} }
# check spacing on paretheses # check spacing on parentheses
if ($line =~ /\(\s/ && $line !~ /\(\s*(?:\\)?$/ && if ($line =~ /\(\s/ && $line !~ /\(\s*(?:\\)?$/ &&
$line !~ /for\s*\(\s+;/) { $line !~ /for\s*\(\s+;/) {
ERROR("space prohibited after that open parenthesis '('\n" . $herecurr); ERROR("space prohibited after that open parenthesis '('\n" . $herecurr);
} }
if ($line =~ /(\s+)\)/ && $line !~ /^.\s*\)/ && if ($line =~ /(\s+)\)/ && $line !~ /^.\s*\)/ &&
$line !~ /for\s*\(.*;\s+\)/) { $line !~ /for\s*\(.*;\s+\)/ &&
$line !~ /:\s+\)/) {
ERROR("space prohibited before that close parenthesis ')'\n" . $herecurr); ERROR("space prohibited before that close parenthesis ')'\n" . $herecurr);
} }
...@@ -1641,6 +1664,23 @@ sub process { ...@@ -1641,6 +1664,23 @@ sub process {
WARN("labels should not be indented\n" . $herecurr); WARN("labels should not be indented\n" . $herecurr);
} }
# Return is not a function.
if (defined($stat) && $stat =~ /^.\s*return(\s*)(\(.*);/s) {
my $spacing = $1;
my $value = $2;
# Flatten any parentheses and braces
while ($value =~ s/\([^\(\)]*\)/1/) {
}
if ($value =~ /^(?:$Ident|-?$Constant)$/) {
ERROR("return is not a function, parentheses are not required\n" . $herecurr);
} elsif ($spacing !~ /\s+/) {
ERROR("space required before the open parenthesis '('\n" . $herecurr);
}
}
# Need a space before open parenthesis after if, while etc # Need a space before open parenthesis after if, while etc
if ($line=~/\b(if|while|for|switch)\(/) { if ($line=~/\b(if|while|for|switch)\(/) {
ERROR("space required before the open parenthesis '('\n" . $herecurr); ERROR("space required before the open parenthesis '('\n" . $herecurr);
...@@ -1660,7 +1700,7 @@ sub process { ...@@ -1660,7 +1700,7 @@ sub process {
$s =~ s/\n.*//g; $s =~ s/\n.*//g;
$s =~ s/$;//g; # Remove any comments $s =~ s/$;//g; # Remove any comments
if (length($c) && $s !~ /^\s*({|;|)\s*\\*\s*$/ && if (length($c) && $s !~ /^\s*({|;|)\s*\\*\s*$/ &&
$c !~ /^.\#\s*if/) $c !~ /^.\s*\#\s*if/)
{ {
ERROR("trailing statements should be on next line\n" . $herecurr); ERROR("trailing statements should be on next line\n" . $herecurr);
} }
...@@ -1719,14 +1759,16 @@ sub process { ...@@ -1719,14 +1759,16 @@ sub process {
# } # }
#no spaces allowed after \ in define #no spaces allowed after \ in define
if ($line=~/\#define.*\\\s$/) { if ($line=~/\#\s*define.*\\\s$/) {
WARN("Whitepspace after \\ makes next lines useless\n" . $herecurr); WARN("Whitepspace after \\ makes next lines useless\n" . $herecurr);
} }
#warn if <asm/foo.h> is #included and <linux/foo.h> is available (uses RAW line) #warn if <asm/foo.h> is #included and <linux/foo.h> is available (uses RAW line)
if ($tree && $rawline =~ m{^.\#\s*include\s*\<asm\/(.*)\.h\>}) { if ($tree && $rawline =~ m{^.\s*\#\s*include\s*\<asm\/(.*)\.h\>}) {
my $checkfile = "$root/include/linux/$1.h"; my $checkfile = "include/linux/$1.h";
if (-f $checkfile && $1 ne 'irq') { if (-f "$root/$checkfile" && $realfile ne $checkfile &&
$1 ne 'irq')
{
WARN("Use #include <linux/$1.h> instead of <asm/$1.h>\n" . WARN("Use #include <linux/$1.h> instead of <asm/$1.h>\n" .
$herecurr); $herecurr);
} }
...@@ -1735,45 +1777,87 @@ sub process { ...@@ -1735,45 +1777,87 @@ 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 good container # in a known good container
if ($prevline =~ /\#define.*\\/ && if ($line =~ /^.\s*\#\s*define\s*$Ident(\()?/) {
$prevline !~/(?:do\s+{|\(\{|\{)/ &&
$line !~ /(?:do\s+{|\(\{|\{)/ &&
$line !~ /^.\s*$Declare\s/) {
# Grab the first statement, if that is the entire macro
# its ok. This may start either on the #define line
# or the one below.
my $ln = $linenr; my $ln = $linenr;
my $cnt = $realcnt; my $cnt = $realcnt;
my $off = 0; my ($off, $dstat, $dcond, $rest);
my $ctx = '';
# If the macro starts on the define line start my $args = defined($1);
# grabbing the statement after the identifier
$prevline =~ m{^(.#\s*define\s*$Ident(?:\([^\)]*\))?\s*)(.*)\\\s*$};
##print "1<$1> 2<$2>\n";
if (defined $2 && $2 ne '') {
$off = length($1);
$ln--;
$cnt++;
while ($lines[$ln - 1] =~ /^-/) {
$ln--;
$cnt++;
}
}
my @ctx = ctx_statement($ln, $cnt, $off);
my $ctx_ln = $ln + $#ctx + 1;
my $ctx = join("\n", @ctx);
# Pull in any empty extension lines. # Find the end of the macro and limit our statement
while ($ctx =~ /\\$/ && # search to that.
$lines[$ctx_ln - 1] =~ /^.\s*(?:\\)?$/) { while ($cnt > 0 && defined $lines[$ln - 1] &&
$ctx .= $lines[$ctx_ln - 1]; $lines[$ln - 1] =~ /^(?:-|..*\\$)/)
$ctx_ln++; {
$ctx .= $rawlines[$ln - 1] . "\n";
$ln++;
$cnt--;
}
$ctx .= $rawlines[$ln - 1];
($dstat, $dcond, $ln, $cnt, $off) =
ctx_statement_block($linenr, $ln - $linenr + 1, 0);
#print "dstat<$dstat> dcond<$dcond> cnt<$cnt> off<$off>\n";
#print "LINE<$lines[$ln]> len<" . length($lines[$ln]) . "\n";
# Extract the remainder of the define (if any) and
# rip off surrounding spaces, and trailing \'s.
$rest = '';
if (defined $lines[$ln - 1] &&
$off > length($lines[$ln - 1]))
{
$ln++;
$cnt--;
$off = 0;
}
while ($cnt > 0) {
$rest .= substr($lines[$ln - 1], $off) . "\n";
$ln++;
$cnt--;
$off = 0;
}
$rest =~ s/\\\n.//g;
$rest =~ s/^\s*//s;
$rest =~ s/\s*$//s;
# Clean up the original statement.
if ($args) {
substr($dstat, 0, length($dcond), '');
} else {
$dstat =~ s/^.\s*\#\s*define\s+$Ident\s*//;
} }
$dstat =~ s/\\\n.//g;
$dstat =~ s/^\s*//s;
$dstat =~ s/\s*$//s;
if ($ctx =~ /\\$/) { # Flatten any parentheses and braces
if ($ctx =~ /;/) { while ($dstat =~ s/\([^\(\)]*\)/1/) {
}
while ($dstat =~ s/\{[^\{\}]*\}/1/) {
}
my $exceptions = qr{
$Declare|
module_param_named|
MODULE_PARAM_DESC|
DECLARE_PER_CPU|
DEFINE_PER_CPU|
__typeof__\(
}x;
if ($rest ne '') {
if ($rest !~ /while\s*\(/ &&
$dstat !~ /$exceptions/)
{
ERROR("Macros with multiple statements should be enclosed in a do - while loop\n" . "$here\n$ctx\n"); ERROR("Macros with multiple statements should be enclosed in a do - while loop\n" . "$here\n$ctx\n");
} else { }
} elsif ($ctx !~ /;/) {
if ($dstat ne '' &&
$dstat !~ /^(?:$Ident|-?$Constant)$/ &&
$dstat !~ /$exceptions/ &&
$dstat =~ /$Operators/)
{
ERROR("Macros with complex values should be enclosed in parenthesis\n" . "$here\n$ctx\n"); ERROR("Macros with complex values should be enclosed in parenthesis\n" . "$here\n$ctx\n");
} }
} }
...@@ -1884,7 +1968,7 @@ sub process { ...@@ -1884,7 +1968,7 @@ sub process {
# 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*\#\s*include\s*\<$inc>@) {
ERROR("Don't use <$inc>: see Documentation/feature-removal-schedule.txt\n" . $herecurr); ERROR("Don't use <$inc>: see Documentation/feature-removal-schedule.txt\n" . $herecurr);
} }
} }
...@@ -1908,7 +1992,7 @@ sub process { ...@@ -1908,7 +1992,7 @@ sub process {
} }
# warn about #if 0 # warn about #if 0
if ($line =~ /^.#\s*if\s+0\b/) { if ($line =~ /^.\s*\#\s*if\s+0\b/) {
CHK("if this code is redundant consider removing it\n" . CHK("if this code is redundant consider removing it\n" .
$herecurr); $herecurr);
} }
...@@ -1920,23 +2004,16 @@ sub process { ...@@ -1920,23 +2004,16 @@ sub process {
WARN("kfree(NULL) is safe this check is probabally not required\n" . $hereprev); WARN("kfree(NULL) is safe this check is probabally not required\n" . $hereprev);
} }
} }
# check for needless usb_free_urb() checks
if ($prevline =~ /\bif\s*\(([^\)]*)\)/) {
my $expr = $1;
if ($line =~ /\busb_free_urb\(\Q$expr\E\);/) {
WARN("usb_free_urb(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*\#\s*if(|n)def/ && ($realfile =~ /\.c$/)) {
# print "#ifdef in C files should be avoided\n"; # print "#ifdef in C files should be avoided\n";
# print "$herecurr"; # print "$herecurr";
# $clean = 0; # $clean = 0;
# } # }
# warn about spacing in #ifdefs # warn about spacing in #ifdefs
if ($line =~ /^.#\s*(ifdef|ifndef|elif)\s\s+/) { if ($line =~ /^.\s*\#\s*(ifdef|ifndef|elif)\s\s+/) {
ERROR("exactly one space required after that #$1\n" . $herecurr); ERROR("exactly one space required after that #$1\n" . $herecurr);
} }
...@@ -1955,7 +2032,7 @@ sub process { ...@@ -1955,7 +2032,7 @@ sub process {
} }
} }
# check of hardware specific defines # check of hardware specific defines
if ($line =~ m@^.#\s*if.*\b(__i386__|__powerpc64__|__sun__|__s390x__)\b@ && $realfile !~ m@include/asm-@) { if ($line =~ m@^.\s*\#\s*if.*\b(__i386__|__powerpc64__|__sun__|__s390x__)\b@ && $realfile !~ m@include/asm-@) {
CHK("architecture specific defines should be avoided\n" . $herecurr); CHK("architecture specific defines should be avoided\n" . $herecurr);
} }
...@@ -1973,15 +2050,18 @@ sub process { ...@@ -1973,15 +2050,18 @@ sub process {
# check for new externs in .c files. # check for new externs in .c files.
if ($realfile =~ /\.c$/ && defined $stat && if ($realfile =~ /\.c$/ && defined $stat &&
$stat =~ /^.\s*(?:extern\s+)?$Type\s+$Ident(\s*)\(/s) $stat =~ /^.\s*(?:extern\s+)?$Type\s+($Ident)(\s*)\(/s)
{ {
my $paren_space = $1; my $function_name = $1;
my $paren_space = $2;
my $s = $stat; my $s = $stat;
if (defined $cond) { if (defined $cond) {
substr($s, 0, length($cond), ''); substr($s, 0, length($cond), '');
} }
if ($s =~ /^\s*;/) { if ($s =~ /^\s*;/ &&
$function_name ne 'uninitialized_var')
{
WARN("externs should be avoided in .c files\n" . $herecurr); WARN("externs should be avoided in .c files\n" . $herecurr);
} }
...@@ -2030,8 +2110,8 @@ sub process { ...@@ -2030,8 +2110,8 @@ sub process {
# use of NR_CPUS is usually wrong # use of NR_CPUS is usually wrong
# ignore definitions of NR_CPUS and usage to define arrays as likely right # ignore definitions of NR_CPUS and usage to define arrays as likely right
if ($line =~ /\bNR_CPUS\b/ && if ($line =~ /\bNR_CPUS\b/ &&
$line !~ /^.#\s*if\b.*\bNR_CPUS\b/ && $line !~ /^.\s*\s*#\s*if\b.*\bNR_CPUS\b/ &&
$line !~ /^.#\s*define\b.*\bNR_CPUS\b/ && $line !~ /^.\s*\s*#\s*define\b.*\bNR_CPUS\b/ &&
$line !~ /^.\s*$Declare\s.*\[[^\]]*NR_CPUS[^\]]*\]/ && $line !~ /^.\s*$Declare\s.*\[[^\]]*NR_CPUS[^\]]*\]/ &&
$line !~ /\[[^\]]*\.\.\.[^\]]*NR_CPUS[^\]]*\]/ && $line !~ /\[[^\]]*\.\.\.[^\]]*NR_CPUS[^\]]*\]/ &&
$line !~ /\[[^\]]*NR_CPUS[^\]]*\.\.\.[^\]]*\]/) $line !~ /\[[^\]]*NR_CPUS[^\]]*\.\.\.[^\]]*\]/)
......
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