checkpatch: update with latest checkpatch from the linux kernel
Update with commit 577f12c07e4edd54730dc559a9c7bc44d22bf7dc from the Linux kernel. Change-Id: Ie2cabbfea415d26ffacef340d9497342b496dc29 Signed-off-by: Anas Nashif <anas.nashif@intel.com>
This commit is contained in:
parent
302d23d1a6
commit
0f3d5478a8
|
@ -27,12 +27,15 @@ my $emacs = 0;
|
|||
my $terse = 0;
|
||||
my $showfile = 0;
|
||||
my $file = 0;
|
||||
my $git = 0;
|
||||
my %git_commits = ();
|
||||
my $check = 0;
|
||||
my $check_orig = 0;
|
||||
my $summary = 1;
|
||||
my $mailback = 0;
|
||||
my $summary_file = 0;
|
||||
my $show_types = 0;
|
||||
my $list_types = 0;
|
||||
my $fix = 0;
|
||||
my $fix_inplace = 0;
|
||||
my $root;
|
||||
|
@ -42,8 +45,8 @@ my %use_type = ();
|
|||
my @use = ();
|
||||
my %ignore_type = ();
|
||||
my @ignore = ();
|
||||
my @exclude = ();
|
||||
my $help = 0;
|
||||
my @exclude = ();
|
||||
my $configuration_file = ".checkpatch.conf";
|
||||
my $max_line_length = 80;
|
||||
my $ignore_perl_version = 0;
|
||||
|
@ -52,7 +55,9 @@ my $min_conf_desc_length = 4;
|
|||
my $spelling_file = "$D/spelling.txt";
|
||||
my $codespell = 0;
|
||||
my $codespellfile = "/usr/share/codespell/dictionary.txt";
|
||||
my $conststructsfile = "$D/const_structs.checkpatch";
|
||||
my $color = 1;
|
||||
my $allow_c99_comments = 1;
|
||||
|
||||
sub help {
|
||||
my ($exitcode) = @_;
|
||||
|
@ -69,14 +74,25 @@ Options:
|
|||
--emacs emacs compile window format
|
||||
--terse one line per report
|
||||
--showfile emit diffed file position, not input file position
|
||||
-g, --git treat FILE as a single commit or git revision range
|
||||
single git commit with:
|
||||
<rev>
|
||||
<rev>^
|
||||
<rev>~n
|
||||
multiple git commits with:
|
||||
<rev1>..<rev2>
|
||||
<rev1>...<rev2>
|
||||
<rev>-<count>
|
||||
git merges are ignored
|
||||
-f, --file treat FILE as regular source file
|
||||
--subjective, --strict enable more subjective tests
|
||||
--list-types list the possible message types
|
||||
--types TYPE(,TYPE2...) show only these comma separated message types
|
||||
--ignore TYPE(,TYPE2...) ignore various comma separated message types
|
||||
--show-types show the specific message type in the output
|
||||
--exclude DIR(,DIR22...) exclude directories
|
||||
--max-line-length=n set the maximum line length, if exceeded, warn
|
||||
--min-conf-desc-length=n set the min description length, if shorter, warn
|
||||
--show-types show the message "types" in the output
|
||||
--root=PATH PATH to the kernel tree root
|
||||
--no-summary suppress the per-file summary
|
||||
--mailback only produce a report in case of warnings/errors
|
||||
|
@ -108,6 +124,37 @@ EOM
|
|||
exit($exitcode);
|
||||
}
|
||||
|
||||
sub uniq {
|
||||
my %seen;
|
||||
return grep { !$seen{$_}++ } @_;
|
||||
}
|
||||
|
||||
sub list_types {
|
||||
my ($exitcode) = @_;
|
||||
|
||||
my $count = 0;
|
||||
|
||||
local $/ = undef;
|
||||
|
||||
open(my $script, '<', abs_path($P)) or
|
||||
die "$P: Can't read '$P' $!\n";
|
||||
|
||||
my $text = <$script>;
|
||||
close($script);
|
||||
|
||||
my @types = ();
|
||||
for ($text =~ /\b(?:(?:CHK|WARN|ERROR)\s*\(\s*"([^"]+)")/g) {
|
||||
push (@types, $_);
|
||||
}
|
||||
@types = sort(uniq(@types));
|
||||
print("#\tMessage type\n\n");
|
||||
foreach my $type (@types) {
|
||||
print(++$count . "\t" . $type . "\n");
|
||||
}
|
||||
|
||||
exit($exitcode);
|
||||
}
|
||||
|
||||
my $conf = which_conf($configuration_file);
|
||||
if (-f $conf) {
|
||||
my @conf_args;
|
||||
|
@ -143,12 +190,14 @@ GetOptions(
|
|||
'terse!' => \$terse,
|
||||
'showfile!' => \$showfile,
|
||||
'f|file!' => \$file,
|
||||
'g|git!' => \$git,
|
||||
'subjective!' => \$check,
|
||||
'strict!' => \$check,
|
||||
'ignore=s' => \@ignore,
|
||||
'exclude=s' => \@exclude,
|
||||
'exclude=s' => \@exclude,
|
||||
'types=s' => \@use,
|
||||
'show-types!' => \$show_types,
|
||||
'list-types!' => \$list_types,
|
||||
'max-line-length=i' => \$max_line_length,
|
||||
'min-conf-desc-length=i' => \$min_conf_desc_length,
|
||||
'root=s' => \$root,
|
||||
|
@ -169,6 +218,8 @@ GetOptions(
|
|||
|
||||
help(0) if ($help);
|
||||
|
||||
list_types(0) if ($list_types);
|
||||
|
||||
$fix = 1 if ($fix_inplace);
|
||||
$check_orig = $check;
|
||||
|
||||
|
@ -181,9 +232,9 @@ if ($^V && $^V lt $minimum_perl_version) {
|
|||
}
|
||||
}
|
||||
|
||||
#if no filenames are given, push '-' to read patch from stdin
|
||||
if ($#ARGV < 0) {
|
||||
print "$P: no input files\n";
|
||||
exit(1);
|
||||
push(@ARGV, '-');
|
||||
}
|
||||
|
||||
sub hash_save_array_words {
|
||||
|
@ -267,12 +318,12 @@ our $Sparse = qr{
|
|||
__kernel|
|
||||
__force|
|
||||
__iomem|
|
||||
__pmem|
|
||||
__must_check|
|
||||
__init_refok|
|
||||
__kprobes|
|
||||
__ref|
|
||||
__rcu
|
||||
__rcu|
|
||||
__private
|
||||
}x;
|
||||
our $InitAttributePrefix = qr{__(?:mem|cpu|dev|net_|)};
|
||||
our $InitAttributeData = qr{$InitAttributePrefix(?:initdata\b)};
|
||||
|
@ -476,7 +527,11 @@ our @mode_permission_funcs = (
|
|||
["module_param_array_named", 5],
|
||||
["debugfs_create_(?:file|u8|u16|u32|u64|x8|x16|x32|x64|size_t|atomic_t|bool|blob|regset32|u32_array)", 2],
|
||||
["proc_create(?:_data|)", 2],
|
||||
["(?:CLASS|DEVICE|SENSOR)_ATTR", 2],
|
||||
["(?:CLASS|DEVICE|SENSOR|SENSOR_DEVICE|IIO_DEVICE)_ATTR", 2],
|
||||
["IIO_DEV_ATTR_[A-Z_]+", 1],
|
||||
["SENSOR_(?:DEVICE_|)ATTR_2", 2],
|
||||
["SENSOR_TEMPLATE(?:_2|)", 3],
|
||||
["__ATTR", 2],
|
||||
);
|
||||
|
||||
#Create a search pattern for all these functions to speed up a loop below
|
||||
|
@ -494,6 +549,32 @@ our $mode_perms_world_writable = qr{
|
|||
0[0-7][0-7][2367]
|
||||
}x;
|
||||
|
||||
our %mode_permission_string_types = (
|
||||
"S_IRWXU" => 0700,
|
||||
"S_IRUSR" => 0400,
|
||||
"S_IWUSR" => 0200,
|
||||
"S_IXUSR" => 0100,
|
||||
"S_IRWXG" => 0070,
|
||||
"S_IRGRP" => 0040,
|
||||
"S_IWGRP" => 0020,
|
||||
"S_IXGRP" => 0010,
|
||||
"S_IRWXO" => 0007,
|
||||
"S_IROTH" => 0004,
|
||||
"S_IWOTH" => 0002,
|
||||
"S_IXOTH" => 0001,
|
||||
"S_IRWXUGO" => 0777,
|
||||
"S_IRUGO" => 0444,
|
||||
"S_IWUGO" => 0222,
|
||||
"S_IXUGO" => 0111,
|
||||
);
|
||||
|
||||
#Create a search pattern for all these strings to speed up a loop below
|
||||
our $mode_perms_string_search = "";
|
||||
foreach my $entry (keys %mode_permission_string_types) {
|
||||
$mode_perms_string_search .= '|' if ($mode_perms_string_search ne "");
|
||||
$mode_perms_string_search .= $entry;
|
||||
}
|
||||
|
||||
our $allowed_asm_includes = qr{(?x:
|
||||
irq|
|
||||
memory|
|
||||
|
@ -551,6 +632,29 @@ if ($codespell) {
|
|||
|
||||
$misspellings = join("|", sort keys %spelling_fix) if keys %spelling_fix;
|
||||
|
||||
my $const_structs = "";
|
||||
if (open(my $conststructs, '<', $conststructsfile)) {
|
||||
while (<$conststructs>) {
|
||||
my $line = $_;
|
||||
|
||||
$line =~ s/\s*\n?$//g;
|
||||
$line =~ s/^\s*//g;
|
||||
|
||||
next if ($line =~ m/^\s*#/);
|
||||
next if ($line =~ m/^\s*$/);
|
||||
if ($line =~ /\s/) {
|
||||
print("$conststructsfile: '$line' invalid - ignored\n");
|
||||
next;
|
||||
}
|
||||
|
||||
$const_structs .= '|' if ($const_structs ne "");
|
||||
$const_structs .= $line;
|
||||
}
|
||||
close($conststructsfile);
|
||||
#} else {
|
||||
# warn "No structs that should be const will be found - file '$conststructsfile': $!\n";
|
||||
}
|
||||
|
||||
sub build_types {
|
||||
my $mods = "(?x: \n" . join("|\n ", (@modifierList, @modifierListFile)) . "\n)";
|
||||
my $all = "(?x: \n" . join("|\n ", (@typeList, @typeListFile)) . "\n)";
|
||||
|
@ -754,10 +858,42 @@ my @fixed_inserted = ();
|
|||
my @fixed_deleted = ();
|
||||
my $fixlinenr = -1;
|
||||
|
||||
# If input is git commits, extract all commits from the commit expressions.
|
||||
# For example, HEAD-3 means we need check 'HEAD, HEAD~1, HEAD~2'.
|
||||
die "$P: No git repository found\n" if ($git && !-e ".git");
|
||||
|
||||
if ($git) {
|
||||
my @commits = ();
|
||||
foreach my $commit_expr (@ARGV) {
|
||||
my $git_range;
|
||||
if ($commit_expr =~ m/^(.*)-(\d+)$/) {
|
||||
$git_range = "-$2 $1";
|
||||
} elsif ($commit_expr =~ m/\.\./) {
|
||||
$git_range = "$commit_expr";
|
||||
} else {
|
||||
$git_range = "-1 $commit_expr";
|
||||
}
|
||||
my $lines = `git log --no-color --no-merges --pretty=format:'%H %s' $git_range`;
|
||||
foreach my $line (split(/\n/, $lines)) {
|
||||
$line =~ /^([0-9a-fA-F]{40,40}) (.*)$/;
|
||||
next if (!defined($1) || !defined($2));
|
||||
my $sha1 = $1;
|
||||
my $subject = $2;
|
||||
unshift(@commits, $sha1);
|
||||
$git_commits{$sha1} = $subject;
|
||||
}
|
||||
}
|
||||
die "$P: no git commits after extraction!\n" if (@commits == 0);
|
||||
@ARGV = @commits;
|
||||
}
|
||||
|
||||
my $vname;
|
||||
for my $filename (@ARGV) {
|
||||
my $FILE;
|
||||
if ($file) {
|
||||
if ($git) {
|
||||
open($FILE, '-|', "git format-patch -M --stdout -1 $filename") ||
|
||||
die "$P: $filename: git format-patch failed - $!\n";
|
||||
} elsif ($file) {
|
||||
open($FILE, '-|', "diff -u /dev/null $filename") ||
|
||||
die "$P: $filename: diff failed - $!\n";
|
||||
} elsif ($filename eq '-') {
|
||||
|
@ -768,6 +904,8 @@ for my $filename (@ARGV) {
|
|||
}
|
||||
if ($filename eq '-') {
|
||||
$vname = 'Your patch';
|
||||
} elsif ($git) {
|
||||
$vname = "Commit " . substr($filename, 0, 12) . ' ("' . $git_commits{$filename} . '")';
|
||||
} else {
|
||||
$vname = $filename;
|
||||
}
|
||||
|
@ -812,7 +950,7 @@ EOM
|
|||
print << "EOM"
|
||||
|
||||
NOTE: If any of the errors are false positives, please report
|
||||
them to the maintainer.
|
||||
them to the maintainer, see CHECKPATCH in MAINTAINERS.
|
||||
EOM
|
||||
}
|
||||
}
|
||||
|
@ -1064,6 +1202,11 @@ sub sanitise_line {
|
|||
$res =~ s@(\#\s*(?:error|warning)\s+).*@$1$clean@;
|
||||
}
|
||||
|
||||
if ($allow_c99_comments && $res =~ m@(//.*$)@) {
|
||||
my $match = $1;
|
||||
$res =~ s/\Q$match\E/"$;" x length($match)/e;
|
||||
}
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
||||
|
@ -1983,6 +2126,7 @@ sub process {
|
|||
my $is_patch = 0;
|
||||
my $in_header_lines = $file ? 0 : 1;
|
||||
my $in_commit_log = 0; #Scanning lines before patch
|
||||
my $has_commit_log = 0; #Encountered lines before patch
|
||||
my $commit_log_possible_stack_dump = 0;
|
||||
my $commit_log_long_line = 0;
|
||||
my $commit_log_has_diff = 0;
|
||||
|
@ -2256,7 +2400,7 @@ sub process {
|
|||
|
||||
# Check if MAINTAINERS is being updated. If so, there's probably no need to
|
||||
# emit the "does MAINTAINERS need updating?" message on file add/move/delete
|
||||
if ($realfile =~ /MAINTAINERS/) {
|
||||
if ($line =~ /^\s*MAINTAINERS\s*\|/) {
|
||||
$reported_maintainer_file = 1;
|
||||
}
|
||||
|
||||
|
@ -2376,8 +2520,9 @@ sub process {
|
|||
|
||||
# Check for git id commit length and improperly formed commit descriptions
|
||||
if ($in_commit_log && !$commit_log_possible_stack_dump &&
|
||||
$line !~ /^\s*(?:Link|Patchwork|http|https|BugLink):/i &&
|
||||
($line =~ /\bcommit\s+[0-9a-f]{5,}\b/i ||
|
||||
($line =~ /\b[0-9a-f]{12,40}\b/i &&
|
||||
($line =~ /(?:\s|^)[0-9a-f]{12,40}(?:[\s"'\(\[]|$)/i &&
|
||||
$line !~ /[\<\[][0-9a-f]{12,40}[\>\]]/i &&
|
||||
$line !~ /\bfixes:\s*[0-9a-f]{12,40}/i))) {
|
||||
my $init_char = "c";
|
||||
|
@ -2482,6 +2627,7 @@ sub process {
|
|||
$rawline =~ /^(commit\b|from\b|[\w-]+:).*$/i)) {
|
||||
$in_header_lines = 0;
|
||||
$in_commit_log = 1;
|
||||
$has_commit_log = 1;
|
||||
}
|
||||
|
||||
# Check if there is UTF-8 in a commit log when a mail header has explicitly
|
||||
|
@ -2691,6 +2837,10 @@ sub process {
|
|||
$line =~ /^\+\s*#\s*define\s+\w+\s+$String$/) {
|
||||
$msg_type = "";
|
||||
|
||||
# EFI_GUID is another special case
|
||||
} elsif ($line =~ /^\+.*\bEFI_GUID\s*\(/) {
|
||||
$msg_type = "";
|
||||
|
||||
# Otherwise set the alternate message types
|
||||
|
||||
# a comment starts before $max_line_length
|
||||
|
@ -2766,6 +2916,19 @@ sub process {
|
|||
"Logical continuations should be on the previous line\n" . $hereprev);
|
||||
}
|
||||
|
||||
# check indentation starts on a tab stop
|
||||
if ($^V && $^V ge 5.10.0 &&
|
||||
$sline =~ /^\+\t+( +)(?:$c90_Keywords\b|\{\s*$|\}\s*(?:else\b|while\b|\s*$))/) {
|
||||
my $indent = length($1);
|
||||
if ($indent % 8) {
|
||||
if (WARN("TABSTOP",
|
||||
"Statements should start on a tabstop\n" . $herecurr) &&
|
||||
$fix) {
|
||||
$fixed[$fixlinenr] =~ s@(^\+\t+) +@$1 . "\t" x ($indent/8)@e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# check multi-line statement indentation matches previous line
|
||||
if ($^V && $^V ge 5.10.0 &&
|
||||
$prevline =~ /^\+([ \t]*)((?:$c90_Keywords(?:\s+if)\s*)|(?:$Declare\s*)?(?:$Ident|\(\s*\*\s*$Ident\s*\))\s*|$Ident\s*=\s*$Ident\s*)\(.*(\&\&|\|\||,)\s*$/) {
|
||||
|
@ -2842,6 +3005,30 @@ sub process {
|
|||
"Block comments use a trailing */ on a separate line\n" . $herecurr);
|
||||
}
|
||||
|
||||
# Block comment * alignment
|
||||
if ($prevline =~ /$;[ \t]*$/ && #ends in comment
|
||||
$line =~ /^\+[ \t]*$;/ && #leading comment
|
||||
$rawline =~ /^\+[ \t]*\*/ && #leading *
|
||||
(($prevrawline =~ /^\+.*?\/\*/ && #leading /*
|
||||
$prevrawline !~ /\*\/[ \t]*$/) || #no trailing */
|
||||
$prevrawline =~ /^\+[ \t]*\*/)) { #leading *
|
||||
my $oldindent;
|
||||
$prevrawline =~ m@^\+([ \t]*/?)\*@;
|
||||
if (defined($1)) {
|
||||
$oldindent = expand_tabs($1);
|
||||
} else {
|
||||
$prevrawline =~ m@^\+(.*/?)\*@;
|
||||
$oldindent = expand_tabs($1);
|
||||
}
|
||||
$rawline =~ m@^\+([ \t]*)\*@;
|
||||
my $newindent = $1;
|
||||
$newindent = expand_tabs($newindent);
|
||||
if (length($oldindent) ne length($newindent)) {
|
||||
WARN("BLOCK_COMMENT_STYLE",
|
||||
"Block comments should align the * on each line\n" . $hereprev);
|
||||
}
|
||||
}
|
||||
|
||||
# check for missing blank lines after struct/union declarations
|
||||
# with exceptions for various attributes and macros
|
||||
if ($prevline =~ /^[\+ ]};?\s*$/ &&
|
||||
|
@ -3251,6 +3438,30 @@ sub process {
|
|||
#ignore lines not being added
|
||||
next if ($line =~ /^[^\+]/);
|
||||
|
||||
# check for declarations of signed or unsigned without int
|
||||
while ($line =~ m{\b($Declare)\s*(?!char\b|short\b|int\b|long\b)\s*($Ident)?\s*[=,;\[\)\(]}g) {
|
||||
my $type = $1;
|
||||
my $var = $2;
|
||||
$var = "" if (!defined $var);
|
||||
if ($type =~ /^(?:(?:$Storage|$Inline|$Attribute)\s+)*((?:un)?signed)((?:\s*\*)*)\s*$/) {
|
||||
my $sign = $1;
|
||||
my $pointer = $2;
|
||||
|
||||
$pointer = "" if (!defined $pointer);
|
||||
|
||||
if (WARN("UNSPECIFIED_INT",
|
||||
"Prefer '" . trim($sign) . " int" . rtrim($pointer) . "' to bare use of '$sign" . rtrim($pointer) . "'\n" . $herecurr) &&
|
||||
$fix) {
|
||||
my $decl = trim($sign) . " int ";
|
||||
my $comp_pointer = $pointer;
|
||||
$comp_pointer =~ s/\s//g;
|
||||
$decl .= $comp_pointer;
|
||||
$decl = rtrim($decl) if ($var eq "");
|
||||
$fixed[$fixlinenr] =~ s@\b$sign\s*\Q$pointer\E\s*$var\b@$decl$var@;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# TEST: allow direct testing of the type matcher.
|
||||
if ($dbg_type) {
|
||||
if ($line =~ /^.\s*$Declare\s*$/) {
|
||||
|
@ -3449,15 +3660,6 @@ sub process {
|
|||
}
|
||||
}
|
||||
|
||||
# check for uses of DEFINE_PCI_DEVICE_TABLE
|
||||
if ($line =~ /\bDEFINE_PCI_DEVICE_TABLE\s*\(\s*(\w+)\s*\)\s*=/) {
|
||||
if (WARN("DEFINE_PCI_DEVICE_TABLE",
|
||||
"Prefer struct pci_device_id over deprecated DEFINE_PCI_DEVICE_TABLE\n" . $herecurr) &&
|
||||
$fix) {
|
||||
$fixed[$fixlinenr] =~ s/\b(?:static\s+|)DEFINE_PCI_DEVICE_TABLE\s*\(\s*(\w+)\s*\)\s*=\s*/static const struct pci_device_id $1\[\] = /;
|
||||
}
|
||||
}
|
||||
|
||||
# check for new typedefs, only function parameters and sparse annotations
|
||||
# make sense.
|
||||
if ($line =~ /\btypedef\s/ &&
|
||||
|
@ -4121,7 +4323,7 @@ sub process {
|
|||
## }
|
||||
|
||||
#need space before brace following if, while, etc
|
||||
if (($line =~ /\(.*\)\{/ && $line !~ /\($Type\){/) ||
|
||||
if (($line =~ /\(.*\)\{/ && $line !~ /\($Type\)\{/) ||
|
||||
$line =~ /do\{/) {
|
||||
if (ERROR("SPACING",
|
||||
"space required before the open brace '{'\n" . $herecurr) &&
|
||||
|
@ -4279,7 +4481,7 @@ sub process {
|
|||
my $comp = $3;
|
||||
my $to = $4;
|
||||
my $newcomp = $comp;
|
||||
if ($lead !~ /$Operators\s*$/ &&
|
||||
if ($lead !~ /(?:$Operators|\.)\s*$/ &&
|
||||
$to !~ /^(?:Constant|[A-Z_][A-Z0-9_]*)$/ &&
|
||||
WARN("CONSTANT_COMPARISON",
|
||||
"Comparisons should place the constant on the right side of the test\n" . $herecurr) &&
|
||||
|
@ -4554,7 +4756,17 @@ sub process {
|
|||
$has_flow_statement = 1 if ($ctx =~ /\b(goto|return)\b/);
|
||||
$has_arg_concat = 1 if ($ctx =~ /\#\#/ && $ctx !~ /\#\#\s*(?:__VA_ARGS__|args)\b/);
|
||||
|
||||
$dstat =~ s/^.\s*\#\s*define\s+$Ident(?:\([^\)]*\))?\s*//;
|
||||
$dstat =~ s/^.\s*\#\s*define\s+$Ident(\([^\)]*\))?\s*//;
|
||||
my $define_args = $1;
|
||||
my $define_stmt = $dstat;
|
||||
my @def_args = ();
|
||||
|
||||
if (defined $define_args && $define_args ne "") {
|
||||
$define_args = substr($define_args, 1, length($define_args) - 2);
|
||||
$define_args =~ s/\s*//g;
|
||||
@def_args = split(",", $define_args);
|
||||
}
|
||||
|
||||
$dstat =~ s/$;//g;
|
||||
$dstat =~ s/\\\n.//g;
|
||||
$dstat =~ s/^\s*//s;
|
||||
|
@ -4573,6 +4785,9 @@ sub process {
|
|||
{
|
||||
}
|
||||
|
||||
# Make asm volatile uses seem like a generic function
|
||||
$dstat =~ s/\b_*asm_*\s+_*volatile_*\b/asm_volatile/g;
|
||||
|
||||
my $exceptions = qr{
|
||||
$Declare|
|
||||
module_param_named|
|
||||
|
@ -4587,6 +4802,15 @@ sub process {
|
|||
^\[
|
||||
}x;
|
||||
#print "REST<$rest> dstat<$dstat> ctx<$ctx>\n";
|
||||
|
||||
$ctx =~ s/\n*$//;
|
||||
my $herectx = $here . "\n";
|
||||
my $stmt_cnt = statement_rawlines($ctx);
|
||||
|
||||
for (my $n = 0; $n < $stmt_cnt; $n++) {
|
||||
$herectx .= raw_line($linenr, $n) . "\n";
|
||||
}
|
||||
|
||||
if ($dstat ne '' &&
|
||||
$dstat !~ /^(?:$Ident|-?$Constant),$/ && # 10, // foo(),
|
||||
$dstat !~ /^(?:$Ident|-?$Constant);$/ && # foo();
|
||||
|
@ -4602,13 +4826,6 @@ sub process {
|
|||
$dstat !~ /^\(\{/ && # ({...
|
||||
$ctx !~ /^.\s*#\s*define\s+TRACE_(?:SYSTEM|INCLUDE_FILE|INCLUDE_PATH)\b/)
|
||||
{
|
||||
$ctx =~ s/\n*$//;
|
||||
my $herectx = $here . "\n";
|
||||
my $cnt = statement_rawlines($ctx);
|
||||
|
||||
for (my $n = 0; $n < $cnt; $n++) {
|
||||
$herectx .= raw_line($linenr, $n) . "\n";
|
||||
}
|
||||
|
||||
if ($dstat =~ /;/) {
|
||||
WARN("MULTISTATEMENT_MACRO_USE_DO_WHILE",
|
||||
|
@ -4617,6 +4834,46 @@ sub process {
|
|||
WARN("COMPLEX_MACRO",
|
||||
"Macros with complex values should be enclosed in parentheses\n" . "$herectx");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
# Make $define_stmt single line, comment-free, etc
|
||||
my @stmt_array = split('\n', $define_stmt);
|
||||
my $first = 1;
|
||||
$define_stmt = "";
|
||||
foreach my $l (@stmt_array) {
|
||||
$l =~ s/\\$//;
|
||||
if ($first) {
|
||||
$define_stmt = $l;
|
||||
$first = 0;
|
||||
} elsif ($l =~ /^[\+ ]/) {
|
||||
$define_stmt .= substr($l, 1);
|
||||
}
|
||||
}
|
||||
$define_stmt =~ s/$;//g;
|
||||
$define_stmt =~ s/\s+/ /g;
|
||||
$define_stmt = trim($define_stmt);
|
||||
|
||||
# check if any macro arguments are reused (ignore '...' and 'type')
|
||||
foreach my $arg (@def_args) {
|
||||
next if ($arg =~ /\.\.\./);
|
||||
next if ($arg =~ /^type$/i);
|
||||
my $tmp = $define_stmt;
|
||||
$tmp =~ s/\b(typeof|__typeof__|__builtin\w+|typecheck\s*\(\s*$Type\s*,|\#+)\s*\(*\s*$arg\s*\)*\b//g;
|
||||
$tmp =~ s/\#+\s*$arg\b//g;
|
||||
$tmp =~ s/\b$arg\s*\#\#//g;
|
||||
my $use_cnt = $tmp =~ s/\b$arg\b//g;
|
||||
if ($use_cnt > 1) {
|
||||
CHK("MACRO_ARG_REUSE",
|
||||
"Macro argument reuse '$arg' - possible side-effects?\n" . "$herectx");
|
||||
}
|
||||
# check if any macro arguments may have other precedence issues
|
||||
if ($define_stmt =~ m/($Operators)?\s*\b$arg\b\s*($Operators)?/m &&
|
||||
((defined($1) && $1 ne ',') ||
|
||||
(defined($2) && $2 ne ','))) {
|
||||
CHK("MACRO_ARG_PRECEDENCE",
|
||||
"Macro argument '$arg' may be better as '($arg)' to avoid precedence issues\n" . "$herectx");
|
||||
}
|
||||
}
|
||||
|
||||
# check for macros with flow control, but without ## concatenation
|
||||
|
@ -5381,46 +5638,46 @@ sub process {
|
|||
}
|
||||
|
||||
# Check for memcpy(foo, bar, ETH_ALEN) that could be ether_addr_copy(foo, bar)
|
||||
if ($^V && $^V ge 5.10.0 &&
|
||||
defined $stat &&
|
||||
$stat =~ /^\+(?:.*?)\bmemcpy\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\,\s*ETH_ALEN\s*\)/) {
|
||||
if (WARN("PREFER_ETHER_ADDR_COPY",
|
||||
"Prefer ether_addr_copy() over memcpy() if the Ethernet addresses are __aligned(2)\n" . "$here\n$stat\n") &&
|
||||
$fix) {
|
||||
$fixed[$fixlinenr] =~ s/\bmemcpy\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\,\s*ETH_ALEN\s*\)/ether_addr_copy($2, $7)/;
|
||||
}
|
||||
}
|
||||
# if ($^V && $^V ge 5.10.0 &&
|
||||
# defined $stat &&
|
||||
# $stat =~ /^\+(?:.*?)\bmemcpy\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\,\s*ETH_ALEN\s*\)/) {
|
||||
# if (WARN("PREFER_ETHER_ADDR_COPY",
|
||||
# "Prefer ether_addr_copy() over memcpy() if the Ethernet addresses are __aligned(2)\n" . "$here\n$stat\n") &&
|
||||
# $fix) {
|
||||
# $fixed[$fixlinenr] =~ s/\bmemcpy\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\,\s*ETH_ALEN\s*\)/ether_addr_copy($2, $7)/;
|
||||
# }
|
||||
# }
|
||||
|
||||
# Check for memcmp(foo, bar, ETH_ALEN) that could be ether_addr_equal*(foo, bar)
|
||||
if ($^V && $^V ge 5.10.0 &&
|
||||
defined $stat &&
|
||||
$stat =~ /^\+(?:.*?)\bmemcmp\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\,\s*ETH_ALEN\s*\)/) {
|
||||
WARN("PREFER_ETHER_ADDR_EQUAL",
|
||||
"Prefer ether_addr_equal() or ether_addr_equal_unaligned() over memcmp()\n" . "$here\n$stat\n")
|
||||
}
|
||||
# if ($^V && $^V ge 5.10.0 &&
|
||||
# defined $stat &&
|
||||
# $stat =~ /^\+(?:.*?)\bmemcmp\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\,\s*ETH_ALEN\s*\)/) {
|
||||
# WARN("PREFER_ETHER_ADDR_EQUAL",
|
||||
# "Prefer ether_addr_equal() or ether_addr_equal_unaligned() over memcmp()\n" . "$here\n$stat\n")
|
||||
# }
|
||||
|
||||
# check for memset(foo, 0x0, ETH_ALEN) that could be eth_zero_addr
|
||||
# check for memset(foo, 0xFF, ETH_ALEN) that could be eth_broadcast_addr
|
||||
if ($^V && $^V ge 5.10.0 &&
|
||||
defined $stat &&
|
||||
$stat =~ /^\+(?:.*?)\bmemset\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\,\s*ETH_ALEN\s*\)/) {
|
||||
|
||||
my $ms_val = $7;
|
||||
|
||||
if ($ms_val =~ /^(?:0x|)0+$/i) {
|
||||
if (WARN("PREFER_ETH_ZERO_ADDR",
|
||||
"Prefer eth_zero_addr over memset()\n" . "$here\n$stat\n") &&
|
||||
$fix) {
|
||||
$fixed[$fixlinenr] =~ s/\bmemset\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*,\s*ETH_ALEN\s*\)/eth_zero_addr($2)/;
|
||||
}
|
||||
} elsif ($ms_val =~ /^(?:0xff|255)$/i) {
|
||||
if (WARN("PREFER_ETH_BROADCAST_ADDR",
|
||||
"Prefer eth_broadcast_addr() over memset()\n" . "$here\n$stat\n") &&
|
||||
$fix) {
|
||||
$fixed[$fixlinenr] =~ s/\bmemset\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*,\s*ETH_ALEN\s*\)/eth_broadcast_addr($2)/;
|
||||
}
|
||||
}
|
||||
}
|
||||
# if ($^V && $^V ge 5.10.0 &&
|
||||
# defined $stat &&
|
||||
# $stat =~ /^\+(?:.*?)\bmemset\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\,\s*ETH_ALEN\s*\)/) {
|
||||
#
|
||||
# my $ms_val = $7;
|
||||
#
|
||||
# if ($ms_val =~ /^(?:0x|)0+$/i) {
|
||||
# if (WARN("PREFER_ETH_ZERO_ADDR",
|
||||
# "Prefer eth_zero_addr over memset()\n" . "$here\n$stat\n") &&
|
||||
# $fix) {
|
||||
# $fixed[$fixlinenr] =~ s/\bmemset\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*,\s*ETH_ALEN\s*\)/eth_zero_addr($2)/;
|
||||
# }
|
||||
# } elsif ($ms_val =~ /^(?:0xff|255)$/i) {
|
||||
# if (WARN("PREFER_ETH_BROADCAST_ADDR",
|
||||
# "Prefer eth_broadcast_addr() over memset()\n" . "$here\n$stat\n") &&
|
||||
# $fix) {
|
||||
# $fixed[$fixlinenr] =~ s/\bmemset\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*,\s*ETH_ALEN\s*\)/eth_broadcast_addr($2)/;
|
||||
# }
|
||||
# }
|
||||
# }
|
||||
|
||||
# typecasts on min/max could be min_t/max_t
|
||||
if ($^V && $^V ge 5.10.0 &&
|
||||
|
@ -5540,6 +5797,19 @@ sub process {
|
|||
"externs should be avoided in .c files\n" . $herecurr);
|
||||
}
|
||||
|
||||
if ($realfile =~ /\.[ch]$/ && defined $stat &&
|
||||
$stat =~ /^.\s*(?:extern\s+)?$Type\s*$Ident\s*\(\s*([^{]+)\s*\)\s*;/s &&
|
||||
$1 ne "void") {
|
||||
my $args = trim($1);
|
||||
while ($args =~ m/\s*($Type\s*(?:$Ident|\(\s*\*\s*$Ident?\s*\)\s*$balanced_parens)?)/g) {
|
||||
my $arg = trim($1);
|
||||
if ($arg =~ /^$Type$/ && $arg !~ /enum\s+$Ident$/) {
|
||||
WARN("FUNCTION_ARGUMENTS",
|
||||
"function definition argument '$arg' should also have an identifier name\n" . $herecurr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# checks for new __setup's
|
||||
if ($rawline =~ /\b__setup\("([^"]*)"/) {
|
||||
my $name = $1;
|
||||
|
@ -5611,8 +5881,9 @@ sub process {
|
|||
}
|
||||
}
|
||||
|
||||
# check for #defines like: 1 << <digit> that could be BIT(digit)
|
||||
if ($line =~ /#\s*define\s+\w+\s+\(?\s*1\s*([ulUL]*)\s*\<\<\s*(?:\d+|$Ident)\s*\)?/) {
|
||||
# check for #defines like: 1 << <digit> that could be BIT(digit), it is not exported to uapi
|
||||
if ($realfile !~ m@^include/uapi/@ &&
|
||||
$line =~ /#\s*define\s+\w+\s+\(?\s*1\s*([ulUL]*)\s*\<\<\s*(?:\d+|$Ident)\s*\)?/) {
|
||||
my $ull = "";
|
||||
$ull = "_ULL" if (defined($1) && $1 =~ /ll/i);
|
||||
if (CHK("BIT_MACRO",
|
||||
|
@ -5622,6 +5893,16 @@ sub process {
|
|||
}
|
||||
}
|
||||
|
||||
# check for #if defined CONFIG_<FOO> || defined CONFIG_<FOO>_MODULE
|
||||
if ($line =~ /^\+\s*#\s*if\s+defined(?:\s*\(?\s*|\s+)(CONFIG_[A-Z_]+)\s*\)?\s*\|\|\s*defined(?:\s*\(?\s*|\s+)\1_MODULE\s*\)?\s*$/) {
|
||||
my $config = $1;
|
||||
if (WARN("PREFER_IS_ENABLED",
|
||||
"Prefer IS_ENABLED(<FOO>) to CONFIG_<FOO> || CONFIG_<FOO>_MODULE\n" . $herecurr) &&
|
||||
$fix) {
|
||||
$fixed[$fixlinenr] = "\+#if IS_ENABLED($config)";
|
||||
}
|
||||
}
|
||||
|
||||
# check for case / default statements not preceded by break/fallthrough/switch
|
||||
if ($line =~ /^.\s*(?:case\s+(?:$Ident|$Constant)\s*|default):/) {
|
||||
my $has_break = 0;
|
||||
|
@ -5728,46 +6009,6 @@ sub process {
|
|||
}
|
||||
|
||||
# check for various structs that are normally const (ops, kgdb, device_tree)
|
||||
my $const_structs = qr{
|
||||
acpi_dock_ops|
|
||||
address_space_operations|
|
||||
backlight_ops|
|
||||
block_device_operations|
|
||||
dentry_operations|
|
||||
dev_pm_ops|
|
||||
dma_map_ops|
|
||||
extent_io_ops|
|
||||
file_lock_operations|
|
||||
file_operations|
|
||||
hv_ops|
|
||||
ide_dma_ops|
|
||||
intel_dvo_dev_ops|
|
||||
item_operations|
|
||||
iwl_ops|
|
||||
kgdb_arch|
|
||||
kgdb_io|
|
||||
kset_uevent_ops|
|
||||
lock_manager_operations|
|
||||
microcode_ops|
|
||||
mtrr_ops|
|
||||
neigh_ops|
|
||||
nlmsvc_binding|
|
||||
of_device_id|
|
||||
pci_raw_ops|
|
||||
pipe_buf_operations|
|
||||
platform_hibernation_ops|
|
||||
platform_suspend_ops|
|
||||
proto_ops|
|
||||
rpc_pipe_ops|
|
||||
seq_operations|
|
||||
snd_ac97_build_ops|
|
||||
soc_pcmcia_socket_ops|
|
||||
stacktrace_ops|
|
||||
sysfs_ops|
|
||||
tty_operations|
|
||||
uart_ops|
|
||||
usb_mon_operations|
|
||||
wd_ops}x;
|
||||
if ($line !~ /\bconst\b/ &&
|
||||
$line =~ /\bstruct\s+($const_structs)\b/) {
|
||||
WARN("CONST_STRUCT",
|
||||
|
@ -5812,6 +6053,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*\)/ ) {
|
||||
|
@ -5832,34 +6095,69 @@ sub process {
|
|||
# Mode permission misuses where it seems decimal should be octal
|
||||
# This uses a shortcut match to avoid unnecessary uses of a slow foreach loop
|
||||
if ($^V && $^V ge 5.10.0 &&
|
||||
defined $stat &&
|
||||
$line =~ /$mode_perms_search/) {
|
||||
foreach my $entry (@mode_permission_funcs) {
|
||||
my $func = $entry->[0];
|
||||
my $arg_pos = $entry->[1];
|
||||
|
||||
my $lc = $stat =~ tr@\n@@;
|
||||
$lc = $lc + $linenr;
|
||||
my $stat_real = raw_line($linenr, 0);
|
||||
for (my $count = $linenr + 1; $count <= $lc; $count++) {
|
||||
$stat_real = $stat_real . "\n" . raw_line($count, 0);
|
||||
}
|
||||
|
||||
my $skip_args = "";
|
||||
if ($arg_pos > 1) {
|
||||
$arg_pos--;
|
||||
$skip_args = "(?:\\s*$FuncArg\\s*,\\s*){$arg_pos,$arg_pos}";
|
||||
}
|
||||
my $test = "\\b$func\\s*\\(${skip_args}([\\d]+)\\s*[,\\)]";
|
||||
if ($line =~ /$test/) {
|
||||
my $test = "\\b$func\\s*\\(${skip_args}($FuncArg(?:\\|\\s*$FuncArg)*)\\s*[,\\)]";
|
||||
if ($stat =~ /$test/) {
|
||||
my $val = $1;
|
||||
$val = $6 if ($skip_args ne "");
|
||||
|
||||
if ($val !~ /^0$/ &&
|
||||
(($val =~ /^$Int$/ && $val !~ /^$Octal$/) ||
|
||||
length($val) ne 4)) {
|
||||
if (($val =~ /^$Int$/ && $val !~ /^$Octal$/) ||
|
||||
($val =~ /^$Octal$/ && length($val) ne 4)) {
|
||||
ERROR("NON_OCTAL_PERMISSIONS",
|
||||
"Use 4 digit octal (0777) not decimal permissions\n" . $herecurr);
|
||||
} elsif ($val =~ /^$Octal$/ && (oct($val) & 02)) {
|
||||
"Use 4 digit octal (0777) not decimal permissions\n" . "$here\n" . $stat_real);
|
||||
}
|
||||
if ($val =~ /^$Octal$/ && (oct($val) & 02)) {
|
||||
ERROR("EXPORTED_WORLD_WRITABLE",
|
||||
"Exporting writable files is usually an error. Consider more restrictive permissions.\n" . $herecurr);
|
||||
"Exporting writable files is usually an error. Consider more restrictive permissions.\n" . "$here\n" . $stat_real);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# check for uses of S_<PERMS> that could be octal for readability
|
||||
if ($line =~ /\b$mode_perms_string_search\b/) {
|
||||
my $val = "";
|
||||
my $oval = "";
|
||||
my $to = 0;
|
||||
my $curpos = 0;
|
||||
my $lastpos = 0;
|
||||
while ($line =~ /\b(($mode_perms_string_search)\b(?:\s*\|\s*)?\s*)/g) {
|
||||
$curpos = pos($line);
|
||||
my $match = $2;
|
||||
my $omatch = $1;
|
||||
last if ($lastpos > 0 && ($curpos - length($omatch) != $lastpos));
|
||||
$lastpos = $curpos;
|
||||
$to |= $mode_permission_string_types{$match};
|
||||
$val .= '\s*\|\s*' if ($val ne "");
|
||||
$val .= $match;
|
||||
$oval .= $omatch;
|
||||
}
|
||||
$oval =~ s/^\s*\|\s*//;
|
||||
$oval =~ s/\s*\|\s*$//;
|
||||
my $octal = sprintf("%04o", $to);
|
||||
if (WARN("SYMBOLIC_PERMS",
|
||||
"Symbolic permissions '$oval' are not preferred. Consider using octal permissions '$octal'.\n" . $herecurr) &&
|
||||
$fix) {
|
||||
$fixed[$fixlinenr] =~ s/$val/$octal/;
|
||||
}
|
||||
}
|
||||
|
||||
# validate content of MODULE_LICENSE against list from include/linux/module.h
|
||||
if ($line =~ /\bMODULE_LICENSE\s*\(\s*($String)\s*\)/) {
|
||||
my $extracted_string = get_quoted_string($line, $rawline);
|
||||
|
@ -5901,7 +6199,7 @@ sub process {
|
|||
ERROR("NOT_UNIFIED_DIFF",
|
||||
"Does not appear to be a unified-diff format patch\n");
|
||||
}
|
||||
if ($is_patch && $filename ne '-' && $chk_signoff && $signoff == 0) {
|
||||
if ($is_patch && $has_commit_log && $chk_signoff && $signoff == 0) {
|
||||
ERROR("MISSING_SIGN_OFF",
|
||||
"Missing Signed-off-by: line(s)\n");
|
||||
}
|
||||
|
@ -5915,14 +6213,12 @@ sub process {
|
|||
}
|
||||
|
||||
if ($quiet == 0) {
|
||||
# If there were whitespace errors which cleanpatch can fix
|
||||
# then suggest that.
|
||||
if ($rpt_cleaners) {
|
||||
$rpt_cleaners = 0;
|
||||
# If there were any defects found and not already fixing them
|
||||
if (!$clean and !$fix) {
|
||||
print << "EOM"
|
||||
|
||||
NOTE: Whitespace errors detected.
|
||||
You may wish to use scripts/cleanpatch or scripts/cleanfile
|
||||
NOTE: For some of the reported defects, checkpatch may be able to
|
||||
mechanically convert to the typical style using --fix or --fix-inplace.
|
||||
EOM
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue