checkpatch: make extern in .h prototypes quieter
[sfrench/cifs-2.6.git] / scripts / checkpatch.pl
index 9185883f5885b9c24d939781288534a67483fc85..66cad506b8a2a944f2873856ef0078445f673b8b 100755 (executable)
@@ -31,8 +31,10 @@ my $show_types = 0;
 my $fix = 0;
 my $root;
 my %debug;
-my %ignore_type = ();
 my %camelcase = ();
+my %use_type = ();
+my @use = ();
+my %ignore_type = ();
 my @ignore = ();
 my $help = 0;
 my $configuration_file = ".checkpatch.conf";
@@ -56,6 +58,7 @@ Options:
   --terse                    one line per report
   -f, --file                 treat FILE as regular source file
   --subjective, --strict     enable more subjective tests
+  --types TYPE(,TYPE2...)    show only these comma separated message types
   --ignore TYPE(,TYPE2...)   ignore various comma separated message types
   --max-line-length=n        set the maximum line length, if exceeded, warn
   --show-types               show the message "types" in the output
@@ -120,6 +123,7 @@ GetOptions(
        'subjective!'   => \$check,
        'strict!'       => \$check,
        'ignore=s'      => \@ignore,
+       'types=s'       => \@use,
        'show-types!'   => \$show_types,
        'max-line-length=i' => \$max_line_length,
        'root=s'        => \$root,
@@ -150,19 +154,38 @@ if ($#ARGV < 0) {
        exit(1);
 }
 
-@ignore = split(/,/, join(',',@ignore));
-foreach my $word (@ignore) {
-       $word =~ s/\s*\n?$//g;
-       $word =~ s/^\s*//g;
-       $word =~ s/\s+/ /g;
-       $word =~ tr/[a-z]/[A-Z]/;
+sub hash_save_array_words {
+       my ($hashRef, $arrayRef) = @_;
 
-       next if ($word =~ m/^\s*#/);
-       next if ($word =~ m/^\s*$/);
+       my @array = split(/,/, join(',', @$arrayRef));
+       foreach my $word (@array) {
+               $word =~ s/\s*\n?$//g;
+               $word =~ s/^\s*//g;
+               $word =~ s/\s+/ /g;
+               $word =~ tr/[a-z]/[A-Z]/;
 
-       $ignore_type{$word}++;
+               next if ($word =~ m/^\s*#/);
+               next if ($word =~ m/^\s*$/);
+
+               $hashRef->{$word}++;
+       }
 }
 
+sub hash_show_words {
+       my ($hashRef, $prefix) = @_;
+
+       if ($quiet == 0 && keys %$hashRef) {
+               print "NOTE: $prefix message types:";
+               foreach my $word (sort keys %$hashRef) {
+                       print " $word";
+               }
+               print "\n\n";
+       }
+}
+
+hash_save_array_words(\%ignore_type, \@ignore);
+hash_save_array_words(\%use_type, \@use);
+
 my $dbg_values = 0;
 my $dbg_possible = 0;
 my $dbg_type = 0;
@@ -219,6 +242,8 @@ our $Sparse = qr{
                        __rcu
                }x;
 
+our $InitAttribute = qr{__(?:mem|cpu|dev|net_|)(?:initdata|initconst|init\b)};
+
 # Notes to $Attribute:
 # We need \b after 'init' otherwise 'initconst' will cause a false positive in a check
 our $Attribute = qr{
@@ -239,7 +264,7 @@ our $Attribute      = qr{
                        __deprecated|
                        __read_mostly|
                        __kprobes|
-                       __(?:mem|cpu|dev|)(?:initdata|initconst|init\b)|
+                       $InitAttribute|
                        ____cacheline_aligned|
                        ____cacheline_aligned_in_smp|
                        ____cacheline_internodealigned_in_smp|
@@ -269,6 +294,7 @@ our $Operators      = qr{
                  }x;
 
 our $NonptrType;
+our $NonptrTypeWithAttr;
 our $Type;
 our $Declare;
 
@@ -331,6 +357,12 @@ our @typeList = (
        qr{${Ident}_handler},
        qr{${Ident}_handler_fn},
 );
+our @typeListWithAttr = (
+       @typeList,
+       qr{struct\s+$InitAttribute\s+$Ident},
+       qr{union\s+$InitAttribute\s+$Ident},
+);
+
 our @modifierList = (
        qr{fastcall},
 );
@@ -344,6 +376,7 @@ our $allowed_asm_includes = qr{(?x:
 sub build_types {
        my $mods = "(?x:  \n" . join("|\n  ", @modifierList) . "\n)";
        my $all = "(?x:  \n" . join("|\n  ", @typeList) . "\n)";
+       my $allWithAttr = "(?x:  \n" . join("|\n  ", @typeListWithAttr) . "\n)";
        $Modifier       = qr{(?:$Attribute|$Sparse|$mods)};
        $NonptrType     = qr{
                        (?:$Modifier\s+|const\s+)*
@@ -354,6 +387,15 @@ sub build_types {
                        )
                        (?:\s+$Modifier|\s+const)*
                  }x;
+       $NonptrTypeWithAttr     = qr{
+                       (?:$Modifier\s+|const\s+)*
+                       (?:
+                               (?:typeof|__typeof__)\s*\([^\)]*\)|
+                               (?:$typeTypedefs\b)|
+                               (?:${allWithAttr}\b)
+                       )
+                       (?:\s+$Modifier|\s+const)*
+                 }x;
        $Type   = qr{
                        $NonptrType
                        (?:(?:\s|\*|\[\])+\s*const|(?:\s|\*|\[\])+|(?:\s*\[\s*\])+)?
@@ -1367,7 +1409,9 @@ sub possible {
 my $prefix = '';
 
 sub show_type {
-       return !defined $ignore_type{$_[0]};
+       return defined $use_type{$_[0]} if (scalar keys %use_type > 0);
+
+       return !defined $ignore_type{$_[0]};
 }
 
 sub report {
@@ -1447,7 +1491,23 @@ sub check_absolute_file {
 sub trim {
        my ($string) = @_;
 
-       $string =~ s/(^\s+|\s+$)//g;
+       $string =~ s/^\s+|\s+$//g;
+
+       return $string;
+}
+
+sub ltrim {
+       my ($string) = @_;
+
+       $string =~ s/^\s+//;
+
+       return $string;
+}
+
+sub rtrim {
+       my ($string) = @_;
+
+       $string =~ s/\s+$//;
 
        return $string;
 }
@@ -1637,6 +1697,8 @@ sub process {
        $linenr = 0;
        foreach my $line (@lines) {
                $linenr++;
+               my $sline = $line;      #copy of $line
+               $sline =~ s/$;/ /g;     #with comments as spaces
 
                my $rawline = $rawlines[$linenr - 1];
 
@@ -2153,7 +2215,7 @@ sub process {
                    $realline_next);
 #print "LINE<$line>\n";
                if ($linenr >= $suppress_statement &&
-                   $realcnt && $line =~ /.\s*\S/) {
+                   $realcnt && $sline =~ /.\s*\S/) {
                        ($stat, $cond, $line_nr_next, $remain_next, $off_next) =
                                ctx_statement_block($linenr, $realcnt, 0);
                        $stat =~ s/\n./\n /g;
@@ -2796,6 +2858,7 @@ sub process {
                        $off = 0;
 
                        my $blank = copy_spacing($opline);
+                       my $last_after = -1;
 
                        for (my $n = 0; $n < $#elements; $n += 2) {
 
@@ -2861,7 +2924,7 @@ sub process {
                                            $cc !~ /^\\/ && $cc !~ /^;/) {
                                                if (ERROR("SPACING",
                                                          "space required after that '$op' $at\n" . $hereptr)) {
-                                                       $good = trim($fix_elements[$n]) . " " . trim($fix_elements[$n + 1]) . " ";
+                                                       $good = $fix_elements[$n] . trim($fix_elements[$n + 1]) . " ";
                                                        $line_fixed = 1;
                                                }
                                        }
@@ -2876,11 +2939,11 @@ sub process {
                                        if ($ctx =~ /Wx.|.xW/) {
                                                if (ERROR("SPACING",
                                                          "spaces prohibited around that '$op' $at\n" . $hereptr)) {
-                                                       $good = trim($fix_elements[$n]) . trim($fix_elements[$n + 1]);
-                                                       $line_fixed = 1;
+                                                       $good = rtrim($fix_elements[$n]) . trim($fix_elements[$n + 1]);
                                                        if (defined $fix_elements[$n + 2]) {
                                                                $fix_elements[$n + 2] =~ s/^\s+//;
                                                        }
+                                                       $line_fixed = 1;
                                                }
                                        }
 
@@ -2889,8 +2952,9 @@ sub process {
                                        if ($ctx !~ /.x[WEC]/ && $cc !~ /^}/) {
                                                if (ERROR("SPACING",
                                                          "space required after that '$op' $at\n" . $hereptr)) {
-                                                       $good = trim($fix_elements[$n]) . trim($fix_elements[$n + 1]) . " ";
+                                                       $good = $fix_elements[$n] . trim($fix_elements[$n + 1]) . " ";
                                                        $line_fixed = 1;
+                                                       $last_after = $n;
                                                }
                                        }
 
@@ -2907,8 +2971,10 @@ sub process {
                                        if ($ctx !~ /[WEBC]x./ && $ca !~ /(?:\)|!|~|\*|-|\&|\||\+\+|\-\-|\{)$/) {
                                                if (ERROR("SPACING",
                                                          "space required before that '$op' $at\n" . $hereptr)) {
-                                                       $good = trim($fix_elements[$n]) . " " . trim($fix_elements[$n + 1]);
-                                                       $line_fixed = 1;
+                                                       if ($n != $last_after + 2) {
+                                                               $good = $fix_elements[$n] . " " . ltrim($fix_elements[$n + 1]);
+                                                               $line_fixed = 1;
+                                                       }
                                                }
                                        }
                                        if ($op eq '*' && $cc =~/\s*$Modifier\b/) {
@@ -2917,12 +2983,11 @@ sub process {
                                        } elsif ($ctx =~ /.xW/) {
                                                if (ERROR("SPACING",
                                                          "space prohibited after that '$op' $at\n" . $hereptr)) {
-                                                       $fixed_line =~ s/\s+$//;
-                                                       $good = trim($fix_elements[$n]) . trim($fix_elements[$n + 1]);
-                                                       $line_fixed = 1;
+                                                       $good = $fix_elements[$n] . rtrim($fix_elements[$n + 1]);
                                                        if (defined $fix_elements[$n + 2]) {
                                                                $fix_elements[$n + 2] =~ s/^\s+//;
                                                        }
+                                                       $line_fixed = 1;
                                                }
                                        }
 
@@ -2931,8 +2996,7 @@ sub process {
                                        if ($ctx !~ /[WEOBC]x[^W]/ && $ctx !~ /[^W]x[WOBEC]/) {
                                                if (ERROR("SPACING",
                                                          "space required one side of that '$op' $at\n" . $hereptr)) {
-                                                       $fixed_line =~ s/\s+$//;
-                                                       $good = trim($fix_elements[$n]) . trim($fix_elements[$n + 1]) . " ";
+                                                       $good = $fix_elements[$n] . trim($fix_elements[$n + 1]) . " ";
                                                        $line_fixed = 1;
                                                }
                                        }
@@ -2940,20 +3004,18 @@ sub process {
                                            ($ctx =~ /Wx./ && $cc =~ /^;/)) {
                                                if (ERROR("SPACING",
                                                          "space prohibited before that '$op' $at\n" . $hereptr)) {
-                                                       $fixed_line =~ s/\s+$//;
-                                                       $good = trim($fix_elements[$n]) . trim($fix_elements[$n + 1]);
+                                                       $good = rtrim($fix_elements[$n]) . trim($fix_elements[$n + 1]);
                                                        $line_fixed = 1;
                                                }
                                        }
                                        if ($ctx =~ /ExW/) {
                                                if (ERROR("SPACING",
                                                          "space prohibited after that '$op' $at\n" . $hereptr)) {
-                                                       $fixed_line =~ s/\s+$//;
-                                                       $good = trim($fix_elements[$n]) . trim($fix_elements[$n + 1]);
-                                                       $line_fixed = 1;
+                                                       $good = $fix_elements[$n] . trim($fix_elements[$n + 1]);
                                                        if (defined $fix_elements[$n + 2]) {
                                                                $fix_elements[$n + 2] =~ s/^\s+//;
                                                        }
+                                                       $line_fixed = 1;
                                                }
                                        }
 
@@ -2967,8 +3029,10 @@ sub process {
                                        if ($ctx =~ /Wx[^WCE]|[^WCE]xW/) {
                                                if (ERROR("SPACING",
                                                          "need consistent spacing around '$op' $at\n" . $hereptr)) {
-                                                       $fixed_line =~ s/\s+$//;
-                                                       $good = trim($fix_elements[$n]) . " " . trim($fix_elements[$n + 1]) . " ";
+                                                       $good = rtrim($fix_elements[$n]) . " " . trim($fix_elements[$n + 1]) . " ";
+                                                       if (defined $fix_elements[$n + 2]) {
+                                                               $fix_elements[$n + 2] =~ s/^\s+//;
+                                                       }
                                                        $line_fixed = 1;
                                                }
                                        }
@@ -2979,7 +3043,7 @@ sub process {
                                        if ($ctx =~ /Wx./) {
                                                if (ERROR("SPACING",
                                                          "space prohibited before that '$op' $at\n" . $hereptr)) {
-                                                       $good = trim($fix_elements[$n]) . trim($fix_elements[$n + 1]);
+                                                       $good = rtrim($fix_elements[$n]) . trim($fix_elements[$n + 1]);
                                                        $line_fixed = 1;
                                                }
                                        }
@@ -3006,8 +3070,10 @@ sub process {
                                        if ($ok == 0) {
                                                if (ERROR("SPACING",
                                                          "spaces required around that '$op' $at\n" . $hereptr)) {
-                                                       $good = trim($fix_elements[$n]) . " " . trim($fix_elements[$n + 1]) . " ";
-                                                       $good = $fix_elements[$n] . " " . trim($fix_elements[$n + 1]) . " ";
+                                                       $good = rtrim($fix_elements[$n]) . " " . trim($fix_elements[$n + 1]) . " ";
+                                                       if (defined $fix_elements[$n + 2]) {
+                                                               $fix_elements[$n + 2] =~ s/^\s+//;
+                                                       }
                                                        $line_fixed = 1;
                                                }
                                        }
@@ -3426,7 +3492,8 @@ sub process {
                            $dstat !~ /^for\s*$Constant$/ &&                            # for (...)
                            $dstat !~ /^for\s*$Constant\s+(?:$Ident|-?$Constant)$/ &&   # for (...) bar()
                            $dstat !~ /^do\s*{/ &&                                      # do {...
-                           $dstat !~ /^\({/)                                           # ({...
+                           $dstat !~ /^\({/ &&                                         # ({...
+                           $ctx !~ /^.\s*#\s*define\s+TRACE_(?:SYSTEM|INCLUDE_FILE|INCLUDE_PATH)\b/)
                        {
                                $ctx =~ s/\n*$//;
                                my $herectx = $here . "\n";
@@ -3658,6 +3725,32 @@ sub process {
                        }
                }
 
+sub string_find_replace {
+       my ($string, $find, $replace) = @_;
+
+       $string =~ s/$find/$replace/g;
+
+       return $string;
+}
+
+# check for bad placement of section $InitAttribute (e.g.: __initdata)
+               if ($line =~ /(\b$InitAttribute\b)/) {
+                       my $attr = $1;
+                       if ($line =~ /^\+\s*static\s+(?:const\s+)?(?:$attr\s+)?($NonptrTypeWithAttr)\s+(?:$attr\s+)?($Ident(?:\[[^]]*\])?)\s*[=;]/) {
+                               my $ptr = $1;
+                               my $var = $2;
+                               if ((($ptr =~ /\b(union|struct)\s+$attr\b/ &&
+                                     ERROR("MISPLACED_INIT",
+                                           "$attr should be placed after $var\n" . $herecurr)) ||
+                                    ($ptr !~ /\b(union|struct)\s+$attr\b/ &&
+                                     WARN("MISPLACED_INIT",
+                                          "$attr should be placed after $var\n" . $herecurr))) &&
+                                   $fix) {
+                                       $fixed[$linenr - 1] =~ s/(\bstatic\s+(?:const\s+)?)(?:$attr\s+)?($NonptrTypeWithAttr)\s+(?:$attr\s+)?($Ident(?:\[[^]]*\])?)\s*([=;])\s*/"$1" . trim(string_find_replace($2, "\\s*$attr\\s*", " ")) . " " . trim(string_find_replace($3, "\\s*$attr\\s*", "")) . " $attr" . ("$4" eq ";" ? ";" : " = ")/e;
+                               }
+                       }
+               }
+
 # prefer usleep_range over udelay
                if ($line =~ /\budelay\s*\(\s*(\d+)\s*\)/) {
                        # ignore udelay's < 10, however
@@ -3882,8 +3975,8 @@ sub process {
 # check for new externs in .h files.
                if ($realfile =~ /\.h$/ &&
                    $line =~ /^\+\s*(extern\s+)$Type\s*$Ident\s*\(/s) {
-                       if (WARN("AVOID_EXTERNS",
-                                "extern prototypes should be avoided in .h files\n" . $herecurr) &&
+                       if (CHK("AVOID_EXTERNS",
+                               "extern prototypes should be avoided in .h files\n" . $herecurr) &&
                            $fix) {
                                $fixed[$linenr - 1] =~ s/(.*)\bextern\b\s*(.*)/$1$2/;
                        }
@@ -4190,13 +4283,8 @@ sub process {
                }
        }
 
-       if ($quiet == 0 && keys %ignore_type) {
-           print "NOTE: Ignored message types:";
-           foreach my $ignore (sort keys %ignore_type) {
-               print " $ignore";
-           }
-           print "\n\n";
-       }
+       hash_show_words(\%use_type, "Used");
+       hash_show_words(\%ignore_type, "Ignored");
 
        if ($clean == 0 && $fix && "@rawlines" ne "@fixed") {
                my $newfile = $filename . ".EXPERIMENTAL-checkpatch-fixes";