checkpatch.pl: update from Linux kernel v5.4-rc3

Update from upstream.

Just minor changes like checking that the author has also done a sign-off.

Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
This commit is contained in:
Heinrich Schuchardt 2019-10-19 09:06:38 +02:00 committed by Tom Rini
parent c9acae3396
commit c261fef51c

View File

@ -1,9 +1,11 @@
#!/usr/bin/env perl
# SPDX-License-Identifier: GPL-2.0
#
# (c) 2001, Dave Jones. (the file handling bit)
# (c) 2005, Joel Schopp <jschopp@austin.ibm.com> (the ugly bit)
# (c) 2007,2008, Andy Whitcroft <apw@uk.ibm.com> (new conditions, test suite)
# (c) 2008-2010 Andy Whitcroft <apw@canonical.com>
# Licensed under the terms of the GNU GPL License version 2
# (c) 2010-2018 Joe Perches <joe@perches.com>
use strict;
use warnings;
@ -11,6 +13,7 @@ use POSIX;
use File::Basename;
use Cwd 'abs_path';
use Term::ANSIColor qw(:constants);
use Encode qw(decode encode);
my $P = $0;
my $D = dirname(abs_path($P));
@ -58,7 +61,9 @@ my $codespellfile = "/usr/share/codespell/dictionary.txt";
my $conststructsfile = "$D/const_structs.checkpatch";
my $typedefsfile = "";
my $color = "auto";
my $allow_c99_comments = 1;
my $allow_c99_comments = 1; # Can be overridden by --ignore C99_COMMENT_TOLERANCE
# git output parsing needs US English output, so first set backtick child process LANGUAGE
my $git_command ='export LANGUAGE=en_US.UTF-8; git';
sub help {
my ($exitcode) = @_;
@ -238,11 +243,11 @@ $check_orig = $check;
my $exit = 0;
my $perl_version_ok = 1;
if ($^V && $^V lt $minimum_perl_version) {
$perl_version_ok = 0;
printf "$P: requires at least perl version %vd\n", $minimum_perl_version;
if (!$ignore_perl_version) {
exit(1);
}
exit(1) if (!$ignore_perl_version);
}
#if no filenames are given, push '-' to read patch from stdin
@ -344,9 +349,10 @@ our $Sparse = qr{
__force|
__iomem|
__must_check|
__init_refok|
__kprobes|
__ref|
__refconst|
__refdata|
__rcu|
__private
}x;
@ -376,6 +382,7 @@ our $Attribute = qr{
__noclone|
__deprecated|
__read_mostly|
__ro_after_init|
__kprobes|
$InitAttribute|
____cacheline_aligned|
@ -461,8 +468,19 @@ our $logFunctions = qr{(?x:
seq_vprintf|seq_printf|seq_puts
)};
our $allocFunctions = qr{(?x:
(?:(?:devm_)?
(?:kv|k|v)[czm]alloc(?:_node|_array)? |
kstrdup(?:_const)? |
kmemdup(?:_nul)?) |
(?:\w+)?alloc_skb(?:ip_align)? |
# dev_alloc_skb/netdev_alloc_skb, et al
dma_alloc_coherent
)};
our $signature_tags = qr{(?xi:
Signed-off-by:|
Co-developed-by:|
Acked-by:|
Tested-by:|
Reviewed-by:|
@ -568,6 +586,27 @@ foreach my $entry (@mode_permission_funcs) {
}
$mode_perms_search = "(?:${mode_perms_search})";
our %deprecated_apis = (
"synchronize_rcu_bh" => "synchronize_rcu",
"synchronize_rcu_bh_expedited" => "synchronize_rcu_expedited",
"call_rcu_bh" => "call_rcu",
"rcu_barrier_bh" => "rcu_barrier",
"synchronize_sched" => "synchronize_rcu",
"synchronize_sched_expedited" => "synchronize_rcu_expedited",
"call_rcu_sched" => "call_rcu",
"rcu_barrier_sched" => "rcu_barrier",
"get_state_synchronize_sched" => "get_state_synchronize_rcu",
"cond_synchronize_sched" => "cond_synchronize_rcu",
);
#Create a search pattern for all these strings to speed up a loop below
our $deprecated_apis_search = "";
foreach my $entry (keys %deprecated_apis) {
$deprecated_apis_search .= '|' if ($deprecated_apis_search ne "");
$deprecated_apis_search .= $entry;
}
$deprecated_apis_search = "(?:${deprecated_apis_search})";
our $mode_perms_world_writable = qr{
S_IWUGO |
S_IWOTH |
@ -845,6 +884,17 @@ sub is_maintained_obsolete {
return $status =~ /obsolete/i;
}
sub is_SPDX_License_valid {
my ($license) = @_;
return 1 if (!$tree || which("python") eq "" || !(-e "$root/scripts/spdxcheck.py") || !(-e "$root/.git"));
my $root_path = abs_path($root);
my $status = `cd "$root_path"; echo "$license" | python scripts/spdxcheck.py -`;
return 0 if ($status ne "");
return 1;
}
my $camelcase_seeded = 0;
sub seed_camelcase_includes {
return if ($camelcase_seeded);
@ -856,7 +906,7 @@ sub seed_camelcase_includes {
$camelcase_seeded = 1;
if (-e ".git") {
my $git_last_include_commit = `git log --no-merges --pretty=format:"%h%n" -1 -- include`;
my $git_last_include_commit = `${git_command} log --no-merges --pretty=format:"%h%n" -1 -- include`;
chomp $git_last_include_commit;
$camelcase_cache = ".checkpatch-camelcase.git.$git_last_include_commit";
} else {
@ -884,7 +934,7 @@ sub seed_camelcase_includes {
}
if (-e ".git") {
$files = `git ls-files "include/*.h"`;
$files = `${git_command} ls-files "include/*.h"`;
@include_files = split('\n', $files);
}
@ -908,13 +958,13 @@ sub git_commit_info {
return ($id, $desc) if ((which("git") eq "") || !(-e ".git"));
my $output = `git log --no-color --format='%H %s' -1 $commit 2>&1`;
my $output = `${git_command} log --no-color --format='%H %s' -1 $commit 2>&1`;
$output =~ s/^\s*//gm;
my @lines = split("\n", $output);
return ($id, $desc) if ($#lines < 0);
if ($lines[0] =~ /^error: short SHA1 $commit is ambiguous\./) {
if ($lines[0] =~ /^error: short SHA1 $commit is ambiguous/) {
# Maybe one day convert this block of bash into something that returns
# all matching commit ids, but it's very slow...
#
@ -958,7 +1008,7 @@ if ($git) {
} else {
$git_range = "-1 $commit_expr";
}
my $lines = `git log --no-color --no-merges --pretty=format:'%H %s' $git_range`;
my $lines = `${git_command} 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));
@ -973,6 +1023,7 @@ if ($git) {
}
my $vname;
$allow_c99_comments = !defined $ignore_type{"C99_COMMENT_TOLERANCE"};
for my $filename (@ARGV) {
my $FILE;
if ($git) {
@ -1024,11 +1075,11 @@ if (!$quiet) {
hash_show_words(\%use_type, "Used");
hash_show_words(\%ignore_type, "Ignored");
if ($^V lt 5.10.0) {
if (!$perl_version_ok) {
print << "EOM"
NOTE: perl $^V is not modern enough to detect all possible issues.
An upgrade to at least perl v5.10.0 is suggested.
An upgrade to at least perl $minimum_perl_version is suggested.
EOM
}
if ($exit) {
@ -2233,10 +2284,14 @@ sub process {
our $clean = 1;
my $signoff = 0;
my $author = '';
my $authorsignoff = 0;
my $is_patch = 0;
my $is_binding_patch = -1;
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_lines = 0; #Number of commit log lines
my $commit_log_possible_stack_dump = 0;
my $commit_log_long_line = 0;
my $commit_log_has_diff = 0;
@ -2375,6 +2430,14 @@ sub process {
my $rawline = $rawlines[$linenr - 1];
# check if it's a mode change, rename or start of a patch
if (!$in_commit_log &&
($line =~ /^ mode change [0-7]+ => [0-7]+ \S+\s*$/ ||
($line =~ /^rename (?:from|to) \S+\s*$/ ||
$line =~ /^diff --git a\/[\w\/\.\_\-]+ b\/\S+\s*$/))) {
$is_patch = 1;
}
#extract the line range in the file after the patch is applied
if (!$in_commit_log &&
$line =~ /^\@\@ -\d+(?:,\d+)? \+(\d+)(,(\d+))? \@\@(.*)/) {
@ -2475,6 +2538,19 @@ sub process {
$check = $check_orig;
}
$checklicenseline = 1;
if ($realfile !~ /^MAINTAINERS/) {
my $last_binding_patch = $is_binding_patch;
$is_binding_patch = () = $realfile =~ m@^(?:Documentation/devicetree/|include/dt-bindings/)@;
if (($last_binding_patch != -1) &&
($last_binding_patch ^ $is_binding_patch)) {
WARN("DT_SPLIT_BINDING_PATCH",
"DT binding docs and includes should be a separate patch. See: Documentation/devicetree/bindings/submitting-patches.txt\n");
}
}
next;
}
@ -2486,6 +2562,18 @@ sub process {
$cnt_lines++ if ($realcnt != 0);
# Verify the existence of a commit log if appropriate
# 2 is used because a $signature is counted in $commit_log_lines
if ($in_commit_log) {
if ($line !~ /^\s*$/) {
$commit_log_lines++; #could be a $signature
}
} elsif ($has_commit_log && $commit_log_lines < 2) {
WARN("COMMIT_MESSAGE",
"Missing commit description - Add an appropriate one\n");
$commit_log_lines = 2; #warn only once
}
# Check if the commit log has what seems like a diff which can confuse patch
if ($in_commit_log && !$commit_log_has_diff &&
(($line =~ m@^\s+diff\b.*a/[\w/]+@ &&
@ -2507,10 +2595,24 @@ sub process {
}
}
# Check the patch for a From:
if (decode("MIME-Header", $line) =~ /^From:\s*(.*)/) {
$author = $1;
$author = encode("utf8", $author) if ($line =~ /=\?utf-8\?/i);
$author =~ s/"//g;
}
# Check the patch for a signoff:
if ($line =~ /^\s*signed-off-by:/i) {
$signoff++;
$in_commit_log = 0;
if ($author ne '') {
my $l = $line;
$l =~ s/"//g;
if ($l =~ /^\s*signed-off-by:\s*\Q$author\E/i) {
$authorsignoff = 1;
}
}
}
# Check if MAINTAINERS is being updated. If so, there's probably no need to
@ -2587,6 +2689,24 @@ sub process {
} else {
$signatures{$sig_nospace} = 1;
}
# Check Co-developed-by: immediately followed by Signed-off-by: with same name and email
if ($sign_off =~ /^co-developed-by:$/i) {
if ($email eq $author) {
WARN("BAD_SIGN_OFF",
"Co-developed-by: should not be used to attribute nominal patch author '$author'\n" . "$here\n" . $rawline);
}
if (!defined $lines[$linenr]) {
WARN("BAD_SIGN_OFF",
"Co-developed-by: must be immediately followed by Signed-off-by:\n" . "$here\n" . $rawline);
} elsif ($rawlines[$linenr] !~ /^\s*signed-off-by:\s*(.*)/i) {
WARN("BAD_SIGN_OFF",
"Co-developed-by: must be immediately followed by Signed-off-by:\n" . "$here\n" . $rawline . "\n" .$rawlines[$linenr]);
} elsif ($1 ne $email) {
WARN("BAD_SIGN_OFF",
"Co-developed-by and Signed-off-by: name/email do not match \n" . "$here\n" . $rawline . "\n" .$rawlines[$linenr]);
}
}
}
# Check email subject for common tools that don't need to be mentioned
@ -2596,12 +2716,6 @@ sub process {
"A patch subject line should describe the change not the tool that found it\n" . $herecurr);
}
# Check for old stable address
if ($line =~ /^\s*cc:\s*.*<?\bstable\@kernel\.org\b>?.*$/i) {
ERROR("STABLE_ADDRESS",
"The 'stable' address should be 'stable\@vger.kernel.org'\n" . $herecurr);
}
# Check for unwanted Gerrit info
if ($in_commit_log && $line =~ /^\s*change-id:/i) {
ERROR("GERRIT_CHANGE_ID",
@ -2613,8 +2727,10 @@ sub process {
($line =~ /^\s*(?:WARNING:|BUG:)/ ||
$line =~ /^\s*\[\s*\d+\.\d{6,6}\s*\]/ ||
# timestamp
$line =~ /^\s*\[\<[0-9a-fA-F]{8,}\>\]/)) {
# stack dump address
$line =~ /^\s*\[\<[0-9a-fA-F]{8,}\>\]/) ||
$line =~ /^(?:\s+\w+:\s+[0-9a-fA-F]+){3,3}/ ||
$line =~ /^\s*\#\d+\s*\[[0-9a-fA-F]+\]\s*\w+ at [0-9a-fA-F]+/) {
# stack dump address styles
$commit_log_possible_stack_dump = 1;
}
@ -2786,6 +2902,17 @@ sub process {
}
}
# check for invalid commit id
if ($in_commit_log && $line =~ /(^fixes:|\bcommit)\s+([0-9a-f]{6,40})\b/i) {
my $id;
my $description;
($id, $description) = git_commit_info($2, undef, undef);
if (!defined($id)) {
WARN("UNKNOWN_COMMIT_ID",
"Unknown commit id '$2', maybe rebased or not pulled?\n" . $herecurr);
}
}
# ignore non-hunk lines and lines being removed
next if (!$hunk_line || $line =~ /^-/);
@ -2915,7 +3042,7 @@ sub process {
my @compats = $rawline =~ /\"([a-zA-Z0-9\-\,\.\+_]+)\"/g;
my $dt_path = $root . "/Documentation/devicetree/bindings/";
my $vp_file = $dt_path . "vendor-prefixes.txt";
my $vp_file = $dt_path . "vendor-prefixes.yaml";
foreach my $compat (@compats) {
my $compat2 = $compat;
@ -2930,7 +3057,7 @@ sub process {
next if $compat !~ /^([a-zA-Z0-9\-]+)\,/;
my $vendor = $1;
`grep -Eq "^$vendor\\b" $vp_file`;
`grep -Eq "\\"\\^\Q$vendor\E,\\.\\*\\":" $vp_file`;
if ( $? >> 8 ) {
WARN("UNDOCUMENTED_DT_STRING",
"DT compatible string vendor \"$vendor\" appears un-documented -- check $vp_file\n" . $herecurr);
@ -2954,10 +3081,24 @@ sub process {
$comment = '..';
}
# check SPDX comment style for .[chsS] files
if ($realfile =~ /\.[chsS]$/ &&
$rawline =~ /SPDX-License-Identifier:/ &&
$rawline !~ m@^\+\s*\Q$comment\E\s*@) {
WARN("SPDX_LICENSE_TAG",
"Improper SPDX comment style for '$realfile', please use '$comment' instead\n" . $herecurr);
}
if ($comment !~ /^$/ &&
$rawline !~ /^\+\Q$comment\E SPDX-License-Identifier: /) {
$rawline !~ m@^\+\Q$comment\E SPDX-License-Identifier: @) {
WARN("SPDX_LICENSE_TAG",
"Missing or malformed SPDX-License-Identifier tag in line $checklicenseline\n" . $herecurr);
} elsif ($rawline =~ /(SPDX-License-Identifier: .*)/) {
my $spdx_license = $1;
if (!is_SPDX_License_valid($spdx_license)) {
WARN("SPDX_LICENSE_TAG",
"'$spdx_license' is not supported in LICENSES/...\n" . $herecurr);
}
}
}
}
@ -2965,6 +3106,14 @@ sub process {
# check we are in a valid source file if not then ignore this hunk
next if ($realfile !~ /\.(h|c|s|S|sh|dtsi|dts)$/);
# check for using SPDX-License-Identifier on the wrong line number
if ($realline != $checklicenseline &&
$rawline =~ /\bSPDX-License-Identifier:/ &&
substr($line, @-, @+ - @-) eq "$;" x (@+ - @-)) {
WARN("SPDX_LICENSE_TAG",
"Misplaced SPDX-License-Identifier tag - use line $checklicenseline instead\n" . $herecurr);
}
# line length limit (with some exclusions)
#
# There are a few types of lines that may extend beyond $max_line_length:
@ -3062,6 +3211,12 @@ sub process {
}
}
# check for assignments on the start of a line
if ($sline =~ /^\+\s+($Assignment)[^=]/) {
CHK("ASSIGNMENT_CONTINUATIONS",
"Assignment operator '$1' should be on the previous line\n" . $hereprev);
}
# check for && or || at the start of a line
if ($rawline =~ /^\+\s*(&&|\|\|)/) {
CHK("LOGICAL_CONTINUATIONS",
@ -3069,7 +3224,7 @@ sub process {
}
# check indentation starts on a tab stop
if ($^V && $^V ge 5.10.0 &&
if ($perl_version_ok &&
$sline =~ /^\+\t+( +)(?:$c90_Keywords\b|\{\s*$|\}\s*(?:else\b|while\b|\s*$)|$Declare\s*$Ident\s*[;=])/) {
my $indent = length($1);
if ($indent % 8) {
@ -3082,7 +3237,7 @@ sub process {
}
# check multi-line statement indentation matches previous line
if ($^V && $^V ge 5.10.0 &&
if ($perl_version_ok &&
$prevline =~ /^\+([ \t]*)((?:$c90_Keywords(?:\s+if)\s*)|(?:$Declare\s*)?(?:$Ident|\(\s*\*\s*$Ident\s*\))\s*|(?:\*\s*)*$Lval\s*=\s*$Ident\s*)\(.*(\&\&|\|\||,)\s*$/) {
$prevline =~ /^\+(\t*)(.*)$/;
my $oldindent = $1;
@ -3239,7 +3394,7 @@ sub process {
# known declaration macros
$sline =~ /^\+\s+$declaration_macros/ ||
# start of struct or union or enum
$sline =~ /^\+\s+(?:union|struct|enum|typedef)\b/ ||
$sline =~ /^\+\s+(?:static\s+)?(?:const\s+)?(?:union|struct|enum|typedef)\b/ ||
# start or end of block or continuation of declaration
$sline =~ /^\+\s+(?:$|[\{\}\.\#\"\?\:\(\[])/ ||
# bitfield continuation
@ -3771,19 +3926,48 @@ sub process {
"type '$tmp' should be specified in [[un]signed] [short|int|long|long long] order\n" . $herecurr);
}
# check for unnecessary <signed> int declarations of short/long/long long
while ($sline =~ m{\b($TypeMisordered(\s*\*)*|$C90_int_types)\b}g) {
my $type = trim($1);
next if ($type !~ /\bint\b/);
next if ($type !~ /\b(?:short|long\s+long|long)\b/);
my $new_type = $type;
$new_type =~ s/\b\s*int\s*\b/ /;
$new_type =~ s/\b\s*(?:un)?signed\b\s*/ /;
$new_type =~ s/^const\s+//;
$new_type = "unsigned $new_type" if ($type =~ /\bunsigned\b/);
$new_type = "const $new_type" if ($type =~ /^const\b/);
$new_type =~ s/\s+/ /g;
$new_type = trim($new_type);
if (WARN("UNNECESSARY_INT",
"Prefer '$new_type' over '$type' as the int is unnecessary\n" . $herecurr) &&
$fix) {
$fixed[$fixlinenr] =~ s/\b\Q$type\E\b/$new_type/;
}
}
# check for static const char * arrays.
if ($line =~ /\bstatic\s+const\s+char\s*\*\s*(\w+)\s*\[\s*\]\s*=\s*/) {
WARN("STATIC_CONST_CHAR_ARRAY",
"static const char * array should probably be static const char * const\n" .
$herecurr);
}
}
# check for initialized const char arrays that should be static const
if ($line =~ /^\+\s*const\s+(char|unsigned\s+char|_*u8|(?:[us]_)?int8_t)\s+\w+\s*\[\s*(?:\w+\s*)?\]\s*=\s*"/) {
if (WARN("STATIC_CONST_CHAR_ARRAY",
"const array should probably be static const\n" . $herecurr) &&
$fix) {
$fixed[$fixlinenr] =~ s/(^.\s*)const\b/${1}static const/;
}
}
# check for static char foo[] = "bar" declarations.
if ($line =~ /\bstatic\s+char\s+(\w+)\s*\[\s*\]\s*=\s*"/) {
WARN("STATIC_CONST_CHAR_ARRAY",
"static char array declaration should probably be static const char\n" .
$herecurr);
}
}
# check for const <foo> const where <foo> is not a pointer or array type
if ($sline =~ /\bconst\s+($BasicType)\s+const\b/) {
@ -3957,7 +4141,7 @@ sub process {
# function brace can't be on same line, except for #defines of do while,
# or if closed on same line
if ($^V && $^V ge 5.10.0 &&
if ($perl_version_ok &&
$sline =~ /$Type\s*$Ident\s*$balanced_parens\s*\{/ &&
$sline !~ /\#\s*define\b.*do\s*\{/ &&
$sline !~ /}/) {
@ -4083,7 +4267,7 @@ sub process {
my ($where, $prefix) = ($-[1], $1);
if ($prefix !~ /$Type\s+$/ &&
($where != 0 || $prefix !~ /^.\s+$/) &&
$prefix !~ /[{,]\s+$/) {
$prefix !~ /[{,:]\s+$/) {
if (ERROR("BRACKET_SPACE",
"space prohibited before open square bracket '['\n" . $herecurr) &&
$fix) {
@ -4473,11 +4657,11 @@ sub process {
#need space before brace following if, while, etc
if (($line =~ /\(.*\)\{/ && $line !~ /\($Type\)\{/) ||
$line =~ /do\{/) {
$line =~ /\b(?:else|do)\{/) {
if (ERROR("SPACING",
"space required before the open brace '{'\n" . $herecurr) &&
$fix) {
$fixed[$fixlinenr] =~ s/^(\+.*(?:do|\)))\{/$1 {/;
$fixed[$fixlinenr] =~ s/^(\+.*(?:do|else|\)))\{/$1 {/;
}
}
@ -4491,7 +4675,7 @@ sub process {
# closing brace should have a space following it when it has anything
# on the line
if ($line =~ /}(?!(?:,|;|\)))\S/) {
if ($line =~ /}(?!(?:,|;|\)|\}))\S/) {
if (ERROR("SPACING",
"space required after that close brace '}'\n" . $herecurr) &&
$fix) {
@ -4568,7 +4752,7 @@ sub process {
# check for unnecessary parentheses around comparisons in if uses
# when !drivers/staging or command-line uses --strict
if (($realfile !~ m@^(?:drivers/staging/)@ || $check_orig) &&
$^V && $^V ge 5.10.0 && defined($stat) &&
$perl_version_ok && defined($stat) &&
$stat =~ /(^.\s*if\s*($balanced_parens))/) {
my $if_stat = $1;
my $test = substr($2, 1, -1);
@ -4605,7 +4789,7 @@ sub process {
# return is not a function
if (defined($stat) && $stat =~ /^.\s*return(\s*)\(/s) {
my $spacing = $1;
if ($^V && $^V ge 5.10.0 &&
if ($perl_version_ok &&
$stat =~ /^.\s*return\s*($balanced_parens)\s*;\s*$/) {
my $value = $1;
$value = deparenthesize($value);
@ -4632,7 +4816,7 @@ sub process {
}
# if statements using unnecessary parentheses - ie: if ((foo == bar))
if ($^V && $^V ge 5.10.0 &&
if ($perl_version_ok &&
$line =~ /\bif\s*((?:\(\s*){2,})/) {
my $openparens = $1;
my $count = $openparens =~ tr@\(@\(@;
@ -4649,7 +4833,7 @@ sub process {
# avoid cases like "foo + BAR < baz"
# only fix matches surrounded by parentheses to avoid incorrect
# conversions like "FOO < baz() + 5" being "misfixed" to "baz() > FOO + 5"
if ($^V && $^V ge 5.10.0 &&
if ($perl_version_ok &&
$line =~ /^\+(.*)\b($Constant|[A-Z_][A-Z0-9_]*)\s*($Compare)\s*($LvalOrFunc)/) {
my $lead = $1;
my $const = $2;
@ -4841,17 +5025,6 @@ sub process {
while ($line =~ m{($Constant|$Lval)}g) {
my $var = $1;
#gcc binary extension
if ($var =~ /^$Binary$/) {
if (WARN("GCC_BINARY_CONSTANT",
"Avoid gcc v4.3+ binary constant extension: <$var>\n" . $herecurr) &&
$fix) {
my $hexval = sprintf("0x%x", oct($var));
$fixed[$fixlinenr] =~
s/\b$var\b/$hexval/;
}
}
#CamelCase
if ($var !~ /^$Constant$/ &&
$var =~ /[A-Z][a-z]|[a-z][A-Z]/ &&
@ -4939,6 +5112,7 @@ sub process {
if (defined $define_args && $define_args ne "") {
$define_args = substr($define_args, 1, length($define_args) - 2);
$define_args =~ s/\s*//g;
$define_args =~ s/\\\+?//g;
@def_args = split(",", $define_args);
}
@ -5032,10 +5206,10 @@ sub process {
next if ($arg =~ /\.\.\./);
next if ($arg =~ /^type$/i);
my $tmp_stmt = $define_stmt;
$tmp_stmt =~ s/\b(typeof|__typeof__|__builtin\w+|typecheck\s*\(\s*$Type\s*,|\#+)\s*\(*\s*$arg\s*\)*\b//g;
$tmp_stmt =~ s/\b(sizeof|typeof|__typeof__|__builtin\w+|typecheck\s*\(\s*$Type\s*,|\#+)\s*\(*\s*$arg\s*\)*\b//g;
$tmp_stmt =~ s/\#+\s*$arg\b//g;
$tmp_stmt =~ s/\b$arg\s*\#\#//g;
my $use_cnt = $tmp_stmt =~ s/\b$arg\b//g;
my $use_cnt = () = $tmp_stmt =~ /\b$arg\b/g;
if ($use_cnt > 1) {
CHK("MACRO_ARG_REUSE",
"Macro argument reuse '$arg' - possible side-effects?\n" . "$herectx");
@ -5074,7 +5248,7 @@ sub process {
# do {} while (0) macro tests:
# single-statement macros do not need to be enclosed in do while (0) loop,
# macro should not end with a semicolon
if ($^V && $^V ge 5.10.0 &&
if ($perl_version_ok &&
$realfile !~ m@/vmlinux.lds.h$@ &&
$line =~ /^.\s*\#\s*define\s+$Ident(\()?/) {
my $ln = $linenr;
@ -5115,16 +5289,6 @@ sub process {
}
}
# make sure symbols are always wrapped with VMLINUX_SYMBOL() ...
# all assignments may have only one of the following with an assignment:
# .
# ALIGN(...)
# VMLINUX_SYMBOL(...)
if ($realfile eq 'vmlinux.lds.h' && $line =~ /(?:(?:^|\s)$Ident\s*=|=\s*$Ident(?:\s|$))/) {
WARN("MISSING_VMLINUX_SYMBOL",
"vmlinux.lds.h needs VMLINUX_SYMBOL() around C-visible symbols\n" . $herecurr);
}
# check for redundant bracing round if etc
if ($line =~ /(^.*)\bif\b/ && $1 !~ /else\s*$/) {
my ($level, $endln, @chunks) =
@ -5330,15 +5494,28 @@ sub process {
}
# concatenated string without spaces between elements
if ($line =~ /$String[A-Z_]/ || $line =~ /[A-Za-z0-9_]$String/) {
CHK("CONCATENATED_STRING",
"Concatenated strings should use spaces between elements\n" . $herecurr);
if ($line =~ /$String[A-Za-z0-9_]/ || $line =~ /[A-Za-z0-9_]$String/) {
if (CHK("CONCATENATED_STRING",
"Concatenated strings should use spaces between elements\n" . $herecurr) &&
$fix) {
while ($line =~ /($String)/g) {
my $extracted_string = substr($rawline, $-[0], $+[0] - $-[0]);
$fixed[$fixlinenr] =~ s/\Q$extracted_string\E([A-Za-z0-9_])/$extracted_string $1/;
$fixed[$fixlinenr] =~ s/([A-Za-z0-9_])\Q$extracted_string\E/$1 $extracted_string/;
}
}
}
# uncoalesced string fragments
if ($line =~ /$String\s*"/) {
WARN("STRING_FRAGMENTS",
"Consecutive strings are generally better as a single string\n" . $herecurr);
if (WARN("STRING_FRAGMENTS",
"Consecutive strings are generally better as a single string\n" . $herecurr) &&
$fix) {
while ($line =~ /($String)(?=\s*")/g) {
my $extracted_string = substr($rawline, $-[0], $+[0] - $-[0]);
$fixed[$fixlinenr] =~ s/\Q$extracted_string\E\s*"/substr($extracted_string, 0, -1)/e;
}
}
}
# check for non-standard and hex prefixed decimal printf formats
@ -5374,9 +5551,14 @@ sub process {
# warn about #if 0
if ($line =~ /^.\s*\#\s*if\s+0\b/) {
CHK("REDUNDANT_CODE",
"if this code is redundant consider removing it\n" .
$herecurr);
WARN("IF_0",
"Consider removing the code enclosed by this #if 0 and its #endif\n" . $herecurr);
}
# warn about #if 1
if ($line =~ /^.\s*\#\s*if\s+1\b/) {
WARN("IF_1",
"Consider removing the #if 1 and its #endif\n" . $herecurr);
}
# check for needless "if (<foo>) fn(<foo>)" uses
@ -5423,7 +5605,8 @@ sub process {
my ($s, $c) = ctx_statement_block($linenr - 3, $realcnt, 0);
# print("line: <$line>\nprevline: <$prevline>\ns: <$s>\nc: <$c>\n\n\n");
if ($s =~ /(?:^|\n)[ \+]\s*(?:$Type\s*)?\Q$testval\E\s*=\s*(?:\([^\)]*\)\s*)?\s*(?:devm_)?(?:[kv][czm]alloc(?:_node|_array)?\b|kstrdup|kmemdup|(?:dev_)?alloc_skb)/) {
if ($s =~ /(?:^|\n)[ \+]\s*(?:$Type\s*)?\Q$testval\E\s*=\s*(?:\([^\)]*\)\s*)?\s*$allocFunctions\s*\(/ &&
$s !~ /\b__GFP_NOWARN\b/ ) {
WARN("OOM_MESSAGE",
"Possible unnecessary 'out of memory' message\n" . $hereprev);
}
@ -5447,7 +5630,7 @@ sub process {
}
# check for mask then right shift without a parentheses
if ($^V && $^V ge 5.10.0 &&
if ($perl_version_ok &&
$line =~ /$LvalOrFunc\s*\&\s*($LvalOrFunc)\s*>>/ &&
$4 !~ /^\&/) { # $LvalOrFunc may be &foo, ignore if so
WARN("MASK_THEN_SHIFT",
@ -5455,7 +5638,7 @@ sub process {
}
# check for pointer comparisons to NULL
if ($^V && $^V ge 5.10.0) {
if ($perl_version_ok) {
while ($line =~ /\b$LvalOrFunc\s*(==|\!=)\s*NULL\b/g) {
my $val = $1;
my $equal = "!";
@ -5544,7 +5727,7 @@ sub process {
# ignore udelay's < 10, however
if (! ($delay < 10) ) {
CHK("USLEEP_RANGE",
"usleep_range is preferred over udelay; see Documentation/timers/timers-howto.txt\n" . $herecurr);
"usleep_range is preferred over udelay; see Documentation/timers/timers-howto.rst\n" . $herecurr);
}
if ($delay > 2000) {
WARN("LONG_UDELAY",
@ -5556,7 +5739,7 @@ sub process {
if ($line =~ /\bmsleep\s*\((\d+)\);/) {
if ($1 < 20) {
WARN("MSLEEP",
"msleep < 20ms can sleep for up to 20ms; see Documentation/timers/timers-howto.txt\n" . $herecurr);
"msleep < 20ms can sleep for up to 20ms; see Documentation/timers/timers-howto.rst\n" . $herecurr);
}
}
@ -5698,13 +5881,6 @@ sub process {
"__packed is preferred over __attribute__((packed))\n" . $herecurr);
}
# Check for new packed members, warn to use care
if ($realfile !~ m@\binclude/uapi/@ &&
$line =~ /\b(__attribute__\s*\(\s*\(.*\bpacked|__packed)\b/) {
WARN("NEW_PACKED",
"Adding new packed members is to be done with care\n" . $herecurr);
}
# Check for __attribute__ aligned, prefer __aligned
if ($realfile !~ m@\binclude/uapi/@ &&
$line =~ /\b__attribute__\s*\(\s*\(.*aligned/) {
@ -5712,6 +5888,18 @@ sub process {
"__aligned(size) is preferred over __attribute__((aligned(size)))\n" . $herecurr);
}
# Check for __attribute__ section, prefer __section
if ($realfile !~ m@\binclude/uapi/@ &&
$line =~ /\b__attribute__\s*\(\s*\(.*_*section_*\s*\(\s*("[^"]*")/) {
my $old = substr($rawline, $-[1], $+[1] - $-[1]);
my $new = substr($old, 1, -1);
if (WARN("PREFER_SECTION",
"__section($new) is preferred over __attribute__((section($old)))\n" . $herecurr) &&
$fix) {
$fixed[$fixlinenr] =~ s/\b__attribute__\s*\(\s*\(\s*_*section_*\s*\(\s*\Q$old\E\s*\)\s*\)\s*\)/__section($new)/;
}
}
# Check for __attribute__ format(printf, prefer __printf
if ($realfile !~ m@\binclude/uapi/@ &&
$line =~ /\b__attribute__\s*\(\s*\(\s*format\s*\(\s*printf/) {
@ -5734,7 +5922,7 @@ sub process {
}
# Check for __attribute__ weak, or __weak declarations (may have link issues)
if ($^V && $^V ge 5.10.0 &&
if ($perl_version_ok &&
$line =~ /(?:$Declare|$DeclareMisordered)\s*$Ident\s*$balanced_parens\s*(?:$Attribute)?\s*;/ &&
($line =~ /\b__attribute__\s*\(\s*\(.*\bweak\b/ ||
$line =~ /\b__weak\b/)) {
@ -5816,25 +6004,25 @@ sub process {
}
# check for vsprintf extension %p<foo> misuses
if ($^V && $^V ge 5.10.0 &&
if ($perl_version_ok &&
defined $stat &&
$stat =~ /^\+(?![^\{]*\{\s*).*\b(\w+)\s*\(.*$String\s*,/s &&
$1 !~ /^_*volatile_*$/) {
my $specifier;
my $extension;
my $bad_specifier = "";
my $stat_real;
my $lc = $stat =~ tr@\n@@;
$lc = $lc + $linenr;
for (my $count = $linenr; $count <= $lc; $count++) {
my $specifier;
my $extension;
my $bad_specifier = "";
my $fmt = get_quoted_string($lines[$count - 1], raw_line($count, 0));
$fmt =~ s/%%//g;
while ($fmt =~ /(\%[\*\d\.]*p(\w))/g) {
$specifier = $1;
$extension = $2;
if ($extension !~ /[SsBKRraEhMmIiUDdgVCbGNOx]/) {
if ($extension !~ /[SsBKRraEhMmIiUDdgVCbGNOxt]/) {
$bad_specifier = $specifier;
last;
}
@ -5863,7 +6051,7 @@ sub process {
}
# Check for misused memsets
if ($^V && $^V ge 5.10.0 &&
if ($perl_version_ok &&
defined $stat &&
$stat =~ /^\+(?:.*?)\bmemset\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\,\s*$FuncArg\s*\)/) {
@ -5881,7 +6069,7 @@ sub process {
}
# Check for memcpy(foo, bar, ETH_ALEN) that could be ether_addr_copy(foo, bar)
# if ($^V && $^V ge 5.10.0 &&
# if ($perl_version_ok &&
# defined $stat &&
# $stat =~ /^\+(?:.*?)\bmemcpy\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\,\s*ETH_ALEN\s*\)/) {
# if (WARN("PREFER_ETHER_ADDR_COPY",
@ -5892,7 +6080,7 @@ sub process {
# }
# Check for memcmp(foo, bar, ETH_ALEN) that could be ether_addr_equal*(foo, bar)
# if ($^V && $^V ge 5.10.0 &&
# if ($perl_version_ok &&
# defined $stat &&
# $stat =~ /^\+(?:.*?)\bmemcmp\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\,\s*ETH_ALEN\s*\)/) {
# WARN("PREFER_ETHER_ADDR_EQUAL",
@ -5901,7 +6089,7 @@ sub process {
# 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 &&
# if ($perl_version_ok &&
# defined $stat &&
# $stat =~ /^\+(?:.*?)\bmemset\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\,\s*ETH_ALEN\s*\)/) {
#
@ -5923,7 +6111,7 @@ sub process {
# }
# typecasts on min/max could be min_t/max_t
if ($^V && $^V ge 5.10.0 &&
if ($perl_version_ok &&
defined $stat &&
$stat =~ /^\+(?:.*?)\b(min|max)\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\)/) {
if (defined $2 || defined $7) {
@ -5947,23 +6135,23 @@ sub process {
}
# check usleep_range arguments
if ($^V && $^V ge 5.10.0 &&
if ($perl_version_ok &&
defined $stat &&
$stat =~ /^\+(?:.*?)\busleep_range\s*\(\s*($FuncArg)\s*,\s*($FuncArg)\s*\)/) {
my $min = $1;
my $max = $7;
if ($min eq $max) {
WARN("USLEEP_RANGE",
"usleep_range should not use min == max args; see Documentation/timers/timers-howto.txt\n" . "$here\n$stat\n");
"usleep_range should not use min == max args; see Documentation/timers/timers-howto.rst\n" . "$here\n$stat\n");
} elsif ($min =~ /^\d+$/ && $max =~ /^\d+$/ &&
$min > $max) {
WARN("USLEEP_RANGE",
"usleep_range args reversed, use min then max; see Documentation/timers/timers-howto.txt\n" . "$here\n$stat\n");
"usleep_range args reversed, use min then max; see Documentation/timers/timers-howto.rst\n" . "$here\n$stat\n");
}
}
# check for naked sscanf
if ($^V && $^V ge 5.10.0 &&
if ($perl_version_ok &&
defined $stat &&
$line =~ /\bsscanf\b/ &&
($stat !~ /$Ident\s*=\s*sscanf\s*$balanced_parens/ &&
@ -5977,7 +6165,7 @@ sub process {
}
# check for simple sscanf that should be kstrto<foo>
if ($^V && $^V ge 5.10.0 &&
if ($perl_version_ok &&
defined $stat &&
$line =~ /\bsscanf\b/) {
my $lc = $stat =~ tr@\n@@;
@ -6049,7 +6237,7 @@ sub process {
}
# check for function definitions
if ($^V && $^V ge 5.10.0 &&
if ($perl_version_ok &&
defined $stat &&
$stat =~ /^.\s*(?:$Storage\s+)?$Type\s*($Ident)\s*$balanced_parens\s*{/s) {
$context_function = $1;
@ -6081,22 +6269,22 @@ sub process {
}
}
# check for pointless casting of kmalloc return
if ($line =~ /\*\s*\)\s*[kv][czm]alloc(_node){0,1}\b/) {
# check for pointless casting of alloc functions
if ($line =~ /\*\s*\)\s*$allocFunctions\b/) {
WARN("UNNECESSARY_CASTS",
"unnecessary cast may hide bugs, see http://c-faq.com/malloc/mallocnocast.html\n" . $herecurr);
}
# alloc style
# p = alloc(sizeof(struct foo), ...) should be p = alloc(sizeof(*p), ...)
if ($^V && $^V ge 5.10.0 &&
$line =~ /\b($Lval)\s*\=\s*(?:$balanced_parens)?\s*([kv][mz]alloc(?:_node)?)\s*\(\s*(sizeof\s*\(\s*struct\s+$Lval\s*\))/) {
if ($perl_version_ok &&
$line =~ /\b($Lval)\s*\=\s*(?:$balanced_parens)?\s*((?:kv|k|v)[mz]alloc(?:_node)?)\s*\(\s*(sizeof\s*\(\s*struct\s+$Lval\s*\))/) {
CHK("ALLOC_SIZEOF_STRUCT",
"Prefer $3(sizeof(*$1)...) over $3($4...)\n" . $herecurr);
}
# check for k[mz]alloc with multiplies that could be kmalloc_array/kcalloc
if ($^V && $^V ge 5.10.0 &&
if ($perl_version_ok &&
defined $stat &&
$stat =~ /^\+\s*($Lval)\s*\=\s*(?:$balanced_parens)?\s*(k[mz]alloc)\s*\(\s*($FuncArg)\s*\*\s*($FuncArg)\s*,/) {
my $oldfunc = $3;
@ -6125,8 +6313,9 @@ sub process {
}
# check for krealloc arg reuse
if ($^V && $^V ge 5.10.0 &&
$line =~ /\b($Lval)\s*\=\s*(?:$balanced_parens)?\s*krealloc\s*\(\s*\1\s*,/) {
if ($perl_version_ok &&
$line =~ /\b($Lval)\s*\=\s*(?:$balanced_parens)?\s*krealloc\s*\(\s*($Lval)\s*,/ &&
$1 eq $3) {
WARN("KREALLOC_ARG_REUSE",
"Reusing the krealloc arg is almost always a bug\n" . $herecurr);
}
@ -6194,7 +6383,7 @@ sub process {
}
# check for switch/default statements without a break;
if ($^V && $^V ge 5.10.0 &&
if ($perl_version_ok &&
defined $stat &&
$stat =~ /^\+[$;\s]*(?:case[$;\s]+\w+[$;\s]*:[$;\s]*|)*[$;\s]*\bdefault[$;\s]*:[$;\s]*;/g) {
my $cnt = statement_rawlines($stat);
@ -6270,6 +6459,20 @@ sub process {
"please use device_initcall() or more appropriate function instead of __initcall() (see include/linux/init.h)\n" . $herecurr);
}
# check for spin_is_locked(), suggest lockdep instead
if ($line =~ /\bspin_is_locked\(/) {
WARN("USE_LOCKDEP",
"Where possible, use lockdep_assert_held instead of assertions based on spin_is_locked\n" . $herecurr);
}
# check for deprecated apis
if ($line =~ /\b($deprecated_apis_search)\b\s*\(/) {
my $deprecated_api = $1;
my $new_api = $deprecated_apis{$deprecated_api};
WARN("DEPRECATED_API",
"Deprecated use of '$deprecated_api', prefer '$new_api' instead\n" . $herecurr);
}
# check for various structs that are normally const (ops, kgdb, device_tree)
# and avoid what seem like struct definitions 'struct foo {'
if ($line !~ /\bconst\b/ &&
@ -6298,12 +6501,18 @@ sub process {
}
# likely/unlikely comparisons similar to "(likely(foo) > 0)"
if ($^V && $^V ge 5.10.0 &&
if ($perl_version_ok &&
$line =~ /\b((?:un)?likely)\s*\(\s*$FuncArg\s*\)\s*$Compare/) {
WARN("LIKELY_MISUSE",
"Using $1 should generally have parentheses around the comparison\n" . $herecurr);
}
# nested likely/unlikely calls
if ($line =~ /\b(?:(?:un)?likely)\s*\(\s*!?\s*(IS_ERR(?:_OR_NULL|_VALUE)?|WARN)/) {
WARN("LIKELY_MISUSE",
"nested (un)?likely() calls, $1 already uses unlikely() internally\n" . $herecurr);
}
# whine mightly about in_atomic
if ($line =~ /\bin_atomic\s*\(/) {
if ($realfile =~ m@^drivers/@) {
@ -6341,7 +6550,7 @@ sub process {
# check for DEVICE_ATTR uses that could be DEVICE_ATTR_<FOO>
# and whether or not function naming is typical and if
# DEVICE_ATTR permissions uses are unusual too
if ($^V && $^V ge 5.10.0 &&
if ($perl_version_ok &&
defined $stat &&
$stat =~ /\bDEVICE_ATTR\s*\(\s*(\w+)\s*,\s*\(?\s*(\s*(?:${multi_mode_perms_string_search}|0[0-7]{3,3})\s*)\s*\)?\s*,\s*(\w+)\s*,\s*(\w+)\s*\)/) {
my $var = $1;
@ -6401,7 +6610,7 @@ sub process {
# specific definition of not visible in sysfs.
# o Ignore proc_create*(...) uses with a decimal 0 permission as that means
# use the default permissions
if ($^V && $^V ge 5.10.0 &&
if ($perl_version_ok &&
defined $stat &&
$line =~ /$mode_perms_search/) {
foreach my $entry (@mode_permission_funcs) {
@ -6463,6 +6672,12 @@ sub process {
"unknown module license " . $extracted_string . "\n" . $herecurr);
}
}
# check for sysctl duplicate constants
if ($line =~ /\.extra[12]\s*=\s*&(zero|one|int_max)\b/) {
WARN("DUPLICATED_SYSCTL_CONST",
"duplicated sysctl range checking value '$1', consider using the shared one in include/linux/sysctl.h\n" . $herecurr);
}
}
# If we have no input at all, then there is nothing to report on
@ -6487,9 +6702,14 @@ sub process {
ERROR("NOT_UNIFIED_DIFF",
"Does not appear to be a unified-diff format patch\n");
}
if ($is_patch && $has_commit_log && $chk_signoff && $signoff == 0) {
ERROR("MISSING_SIGN_OFF",
"Missing Signed-off-by: line(s)\n");
if ($is_patch && $has_commit_log && $chk_signoff) {
if ($signoff == 0) {
ERROR("MISSING_SIGN_OFF",
"Missing Signed-off-by: line(s)\n");
} elsif (!$authorsignoff) {
WARN("NO_AUTHOR_SIGN_OFF",
"Missing Signed-off-by: line by nominal patch author '$author'\n");
}
}
print report_dump();