aboutsummaryrefslogtreecommitdiffstats
path: root/scripts
diff options
context:
space:
mode:
Diffstat (limited to 'scripts')
-rwxr-xr-xscripts/checkpatch.pl142
1 files changed, 139 insertions, 3 deletions
diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
index d574d13ba963..6750595bd7b8 100755
--- a/scripts/checkpatch.pl
+++ b/scripts/checkpatch.pl
@@ -27,12 +27,15 @@ my $emacs = 0;
27my $terse = 0; 27my $terse = 0;
28my $showfile = 0; 28my $showfile = 0;
29my $file = 0; 29my $file = 0;
30my $git = 0;
31my %git_commits = ();
30my $check = 0; 32my $check = 0;
31my $check_orig = 0; 33my $check_orig = 0;
32my $summary = 1; 34my $summary = 1;
33my $mailback = 0; 35my $mailback = 0;
34my $summary_file = 0; 36my $summary_file = 0;
35my $show_types = 0; 37my $show_types = 0;
38my $list_types = 0;
36my $fix = 0; 39my $fix = 0;
37my $fix_inplace = 0; 40my $fix_inplace = 0;
38my $root; 41my $root;
@@ -68,13 +71,24 @@ Options:
68 --emacs emacs compile window format 71 --emacs emacs compile window format
69 --terse one line per report 72 --terse one line per report
70 --showfile emit diffed file position, not input file position 73 --showfile emit diffed file position, not input file position
74 -g, --git treat FILE as a single commit or git revision range
75 single git commit with:
76 <rev>
77 <rev>^
78 <rev>~n
79 multiple git commits with:
80 <rev1>..<rev2>
81 <rev1>...<rev2>
82 <rev>-<count>
83 git merges are ignored
71 -f, --file treat FILE as regular source file 84 -f, --file treat FILE as regular source file
72 --subjective, --strict enable more subjective tests 85 --subjective, --strict enable more subjective tests
86 --list-types list the possible message types
73 --types TYPE(,TYPE2...) show only these comma separated message types 87 --types TYPE(,TYPE2...) show only these comma separated message types
74 --ignore TYPE(,TYPE2...) ignore various comma separated message types 88 --ignore TYPE(,TYPE2...) ignore various comma separated message types
89 --show-types show the specific message type in the output
75 --max-line-length=n set the maximum line length, if exceeded, warn 90 --max-line-length=n set the maximum line length, if exceeded, warn
76 --min-conf-desc-length=n set the min description length, if shorter, warn 91 --min-conf-desc-length=n set the min description length, if shorter, warn
77 --show-types show the message "types" in the output
78 --root=PATH PATH to the kernel tree root 92 --root=PATH PATH to the kernel tree root
79 --no-summary suppress the per-file summary 93 --no-summary suppress the per-file summary
80 --mailback only produce a report in case of warnings/errors 94 --mailback only produce a report in case of warnings/errors
@@ -106,6 +120,37 @@ EOM
106 exit($exitcode); 120 exit($exitcode);
107} 121}
108 122
123sub uniq {
124 my %seen;
125 return grep { !$seen{$_}++ } @_;
126}
127
128sub list_types {
129 my ($exitcode) = @_;
130
131 my $count = 0;
132
133 local $/ = undef;
134
135 open(my $script, '<', abs_path($P)) or
136 die "$P: Can't read '$P' $!\n";
137
138 my $text = <$script>;
139 close($script);
140
141 my @types = ();
142 for ($text =~ /\b(?:(?:CHK|WARN|ERROR)\s*\(\s*"([^"]+)")/g) {
143 push (@types, $_);
144 }
145 @types = sort(uniq(@types));
146 print("#\tMessage type\n\n");
147 foreach my $type (@types) {
148 print(++$count . "\t" . $type . "\n");
149 }
150
151 exit($exitcode);
152}
153
109my $conf = which_conf($configuration_file); 154my $conf = which_conf($configuration_file);
110if (-f $conf) { 155if (-f $conf) {
111 my @conf_args; 156 my @conf_args;
@@ -141,11 +186,13 @@ GetOptions(
141 'terse!' => \$terse, 186 'terse!' => \$terse,
142 'showfile!' => \$showfile, 187 'showfile!' => \$showfile,
143 'f|file!' => \$file, 188 'f|file!' => \$file,
189 'g|git!' => \$git,
144 'subjective!' => \$check, 190 'subjective!' => \$check,
145 'strict!' => \$check, 191 'strict!' => \$check,
146 'ignore=s' => \@ignore, 192 'ignore=s' => \@ignore,
147 'types=s' => \@use, 193 'types=s' => \@use,
148 'show-types!' => \$show_types, 194 'show-types!' => \$show_types,
195 'list-types!' => \$list_types,
149 'max-line-length=i' => \$max_line_length, 196 'max-line-length=i' => \$max_line_length,
150 'min-conf-desc-length=i' => \$min_conf_desc_length, 197 'min-conf-desc-length=i' => \$min_conf_desc_length,
151 'root=s' => \$root, 198 'root=s' => \$root,
@@ -166,6 +213,8 @@ GetOptions(
166 213
167help(0) if ($help); 214help(0) if ($help);
168 215
216list_types(0) if ($list_types);
217
169$fix = 1 if ($fix_inplace); 218$fix = 1 if ($fix_inplace);
170$check_orig = $check; 219$check_orig = $check;
171 220
@@ -752,10 +801,42 @@ my @fixed_inserted = ();
752my @fixed_deleted = (); 801my @fixed_deleted = ();
753my $fixlinenr = -1; 802my $fixlinenr = -1;
754 803
804# If input is git commits, extract all commits from the commit expressions.
805# For example, HEAD-3 means we need check 'HEAD, HEAD~1, HEAD~2'.
806die "$P: No git repository found\n" if ($git && !-e ".git");
807
808if ($git) {
809 my @commits = ();
810 foreach my $commit_expr (@ARGV) {
811 my $git_range;
812 if ($commit_expr =~ m/^(.*)-(\d+)$/) {
813 $git_range = "-$2 $1";
814 } elsif ($commit_expr =~ m/\.\./) {
815 $git_range = "$commit_expr";
816 } else {
817 $git_range = "-1 $commit_expr";
818 }
819 my $lines = `git log --no-color --no-merges --pretty=format:'%H %s' $git_range`;
820 foreach my $line (split(/\n/, $lines)) {
821 $line =~ /^([0-9a-fA-F]{40,40}) (.*)$/;
822 next if (!defined($1) || !defined($2));
823 my $sha1 = $1;
824 my $subject = $2;
825 unshift(@commits, $sha1);
826 $git_commits{$sha1} = $subject;
827 }
828 }
829 die "$P: no git commits after extraction!\n" if (@commits == 0);
830 @ARGV = @commits;
831}
832
755my $vname; 833my $vname;
756for my $filename (@ARGV) { 834for my $filename (@ARGV) {
757 my $FILE; 835 my $FILE;
758 if ($file) { 836 if ($git) {
837 open($FILE, '-|', "git format-patch -M --stdout -1 $filename") ||
838 die "$P: $filename: git format-patch failed - $!\n";
839 } elsif ($file) {
759 open($FILE, '-|', "diff -u /dev/null $filename") || 840 open($FILE, '-|', "diff -u /dev/null $filename") ||
760 die "$P: $filename: diff failed - $!\n"; 841 die "$P: $filename: diff failed - $!\n";
761 } elsif ($filename eq '-') { 842 } elsif ($filename eq '-') {
@@ -766,6 +847,8 @@ for my $filename (@ARGV) {
766 } 847 }
767 if ($filename eq '-') { 848 if ($filename eq '-') {
768 $vname = 'Your patch'; 849 $vname = 'Your patch';
850 } elsif ($git) {
851 $vname = "Commit " . substr($filename, 0, 12) . ' ("' . $git_commits{$filename} . '")';
769 } else { 852 } else {
770 $vname = $filename; 853 $vname = $filename;
771 } 854 }
@@ -2755,6 +2838,19 @@ sub process {
2755 "Logical continuations should be on the previous line\n" . $hereprev); 2838 "Logical continuations should be on the previous line\n" . $hereprev);
2756 } 2839 }
2757 2840
2841# check indentation starts on a tab stop
2842 if ($^V && $^V ge 5.10.0 &&
2843 $sline =~ /^\+\t+( +)(?:$c90_Keywords\b|\{\s*$|\}\s*(?:else\b|while\b|\s*$))/) {
2844 my $indent = length($1);
2845 if ($indent % 8) {
2846 if (WARN("TABSTOP",
2847 "Statements should start on a tabstop\n" . $herecurr) &&
2848 $fix) {
2849 $fixed[$fixlinenr] =~ s@(^\+\t+) +@$1 . "\t" x ($indent/8)@e;
2850 }
2851 }
2852 }
2853
2758# check multi-line statement indentation matches previous line 2854# check multi-line statement indentation matches previous line
2759 if ($^V && $^V ge 5.10.0 && 2855 if ($^V && $^V ge 5.10.0 &&
2760 $prevline =~ /^\+([ \t]*)((?:$c90_Keywords(?:\s+if)\s*)|(?:$Declare\s*)?(?:$Ident|\(\s*\*\s*$Ident\s*\))\s*|$Ident\s*=\s*$Ident\s*)\(.*(\&\&|\|\||,)\s*$/) { 2856 $prevline =~ /^\+([ \t]*)((?:$c90_Keywords(?:\s+if)\s*)|(?:$Declare\s*)?(?:$Ident|\(\s*\*\s*$Ident\s*\))\s*|$Ident\s*=\s*$Ident\s*)\(.*(\&\&|\|\||,)\s*$/) {
@@ -4291,7 +4387,7 @@ sub process {
4291 my $comp = $3; 4387 my $comp = $3;
4292 my $to = $4; 4388 my $to = $4;
4293 my $newcomp = $comp; 4389 my $newcomp = $comp;
4294 if ($lead !~ /$Operators\s*$/ && 4390 if ($lead !~ /(?:$Operators|\.)\s*$/ &&
4295 $to !~ /^(?:Constant|[A-Z_][A-Z0-9_]*)$/ && 4391 $to !~ /^(?:Constant|[A-Z_][A-Z0-9_]*)$/ &&
4296 WARN("CONSTANT_COMPARISON", 4392 WARN("CONSTANT_COMPARISON",
4297 "Comparisons should place the constant on the right side of the test\n" . $herecurr) && 4393 "Comparisons should place the constant on the right side of the test\n" . $herecurr) &&
@@ -5637,6 +5733,16 @@ sub process {
5637 } 5733 }
5638 } 5734 }
5639 5735
5736# check for #if defined CONFIG_<FOO> || defined CONFIG_<FOO>_MODULE
5737 if ($line =~ /^\+\s*#\s*if\s+defined(?:\s*\(?\s*|\s+)(CONFIG_[A-Z_]+)\s*\)?\s*\|\|\s*defined(?:\s*\(?\s*|\s+)\1_MODULE\s*\)?\s*$/) {
5738 my $config = $1;
5739 if (WARN("PREFER_IS_ENABLED",
5740 "Prefer IS_ENABLED(<FOO>) to CONFIG_<FOO> || CONFIG_<FOO>_MODULE\n" . $herecurr) &&
5741 $fix) {
5742 $fixed[$fixlinenr] = "\+#if IS_ENABLED($config)";
5743 }
5744 }
5745
5640# check for case / default statements not preceded by break/fallthrough/switch 5746# check for case / default statements not preceded by break/fallthrough/switch
5641 if ($line =~ /^.\s*(?:case\s+(?:$Ident|$Constant)\s*|default):/) { 5747 if ($line =~ /^.\s*(?:case\s+(?:$Ident|$Constant)\s*|default):/) {
5642 my $has_break = 0; 5748 my $has_break = 0;
@@ -5827,6 +5933,28 @@ sub process {
5827 } 5933 }
5828 } 5934 }
5829 5935
5936# whine about ACCESS_ONCE
5937 if ($^V && $^V ge 5.10.0 &&
5938 $line =~ /\bACCESS_ONCE\s*$balanced_parens\s*(=(?!=))?\s*($FuncArg)?/) {
5939 my $par = $1;
5940 my $eq = $2;
5941 my $fun = $3;
5942 $par =~ s/^\(\s*(.*)\s*\)$/$1/;
5943 if (defined($eq)) {
5944 if (WARN("PREFER_WRITE_ONCE",
5945 "Prefer WRITE_ONCE(<FOO>, <BAR>) over ACCESS_ONCE(<FOO>) = <BAR>\n" . $herecurr) &&
5946 $fix) {
5947 $fixed[$fixlinenr] =~ s/\bACCESS_ONCE\s*\(\s*\Q$par\E\s*\)\s*$eq\s*\Q$fun\E/WRITE_ONCE($par, $fun)/;
5948 }
5949 } else {
5950 if (WARN("PREFER_READ_ONCE",
5951 "Prefer READ_ONCE(<FOO>) over ACCESS_ONCE(<FOO>)\n" . $herecurr) &&
5952 $fix) {
5953 $fixed[$fixlinenr] =~ s/\bACCESS_ONCE\s*\(\s*\Q$par\E\s*\)/READ_ONCE($par)/;
5954 }
5955 }
5956 }
5957
5830# check for lockdep_set_novalidate_class 5958# check for lockdep_set_novalidate_class
5831 if ($line =~ /^.\s*lockdep_set_novalidate_class\s*\(/ || 5959 if ($line =~ /^.\s*lockdep_set_novalidate_class\s*\(/ ||
5832 $line =~ /__lockdep_no_validate__\s*\)/ ) { 5960 $line =~ /__lockdep_no_validate__\s*\)/ ) {
@@ -5930,6 +6058,14 @@ sub process {
5930 } 6058 }
5931 6059
5932 if ($quiet == 0) { 6060 if ($quiet == 0) {
6061 # If there were any defects found and not already fixing them
6062 if (!$clean and !$fix) {
6063 print << "EOM"
6064
6065NOTE: For some of the reported defects, checkpatch may be able to
6066 mechanically convert to the typical style using --fix or --fix-inplace.
6067EOM
6068 }
5933 # If there were whitespace errors which cleanpatch can fix 6069 # If there were whitespace errors which cleanpatch can fix
5934 # then suggest that. 6070 # then suggest that.
5935 if ($rpt_cleaners) { 6071 if ($rpt_cleaners) {