Merge tag 'modules-next-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git...
[cascardo/linux.git] / scripts / checkpatch.pl
index 646295c..34eb216 100755 (executable)
@@ -281,7 +281,7 @@ our $Attribute      = qr{
                        __weak
                  }x;
 our $Modifier;
-our $Inline    = qr{inline|__always_inline|noinline};
+our $Inline    = qr{inline|__always_inline|noinline|__inline|__inline__};
 our $Member    = qr{->$Ident|\.$Ident|\[[^]]*\]};
 our $Lval      = qr{$Ident(?:$Member)*};
 
@@ -304,6 +304,8 @@ our $Operators      = qr{
                        &&|\|\||,|\^|\+\+|--|&|\||$Arithmetic
                  }x;
 
+our $c90_Keywords = qr{do|for|while|if|else|return|goto|continue|switch|default|case|break}x;
+
 our $NonptrType;
 our $NonptrTypeWithAttr;
 our $Type;
@@ -388,6 +390,13 @@ our @mode_permission_funcs = (
        ["(?:CLASS|DEVICE|SENSOR)_ATTR", 2],
 );
 
+#Create a search pattern for all these functions to speed up a loop below
+our $mode_perms_search = "";
+foreach my $entry (@mode_permission_funcs) {
+       $mode_perms_search .= '|' if ($mode_perms_search ne "");
+       $mode_perms_search .= $entry->[0];
+}
+
 our $allowed_asm_includes = qr{(?x:
        irq|
        memory
@@ -422,7 +431,7 @@ sub build_types {
                        (?:(?:\s|\*|\[\])+\s*const|(?:\s|\*|\[\])+|(?:\s*\[\s*\])+)?
                        (?:\s+$Inline|\s+$Modifier)*
                  }x;
-       $Declare        = qr{(?:$Storage\s+)?$Type};
+       $Declare        = qr{(?:$Storage\s+(?:$Inline\s+)?)?$Type};
 }
 build_types();
 
@@ -439,9 +448,14 @@ our $FuncArg = qr{$Typecast{0,1}($LvalOrFunc|$Constant)};
 sub deparenthesize {
        my ($string) = @_;
        return "" if (!defined($string));
-       $string =~ s@^\s*\(\s*@@g;
-       $string =~ s@\s*\)\s*$@@g;
+
+       while ($string =~ /^\s*\(.*\)\s*$/) {
+               $string =~ s@^\s*\(\s*@@;
+               $string =~ s@\s*\)\s*$@@;
+       }
+
        $string =~ s@\s+@ @g;
+
        return $string;
 }
 
@@ -1431,21 +1445,25 @@ sub possible {
 my $prefix = '';
 
 sub show_type {
-       return defined $use_type{$_[0]} if (scalar keys %use_type > 0);
+       my ($type) = @_;
+
+       return defined $use_type{$type} if (scalar keys %use_type > 0);
 
-       return !defined $ignore_type{$_[0]};
+       return !defined $ignore_type{$type};
 }
 
 sub report {
-       if (!show_type($_[1]) ||
-           (defined $tst_only && $_[2] !~ /\Q$tst_only\E/)) {
+       my ($level, $type, $msg) = @_;
+
+       if (!show_type($type) ||
+           (defined $tst_only && $msg !~ /\Q$tst_only\E/)) {
                return 0;
        }
        my $line;
        if ($show_types) {
-               $line = "$prefix$_[0]:$_[1]: $_[2]\n";
+               $line = "$prefix$level:$type: $msg\n";
        } else {
-               $line = "$prefix$_[0]: $_[2]\n";
+               $line = "$prefix$level: $msg\n";
        }
        $line = (split('\n', $line))[0] . "\n" if ($terse);
 
@@ -1453,12 +1471,15 @@ sub report {
 
        return 1;
 }
+
 sub report_dump {
        our @report;
 }
 
 sub ERROR {
-       if (report("ERROR", $_[0], $_[1])) {
+       my ($type, $msg) = @_;
+
+       if (report("ERROR", $type, $msg)) {
                our $clean = 0;
                our $cnt_error++;
                return 1;
@@ -1466,7 +1487,9 @@ sub ERROR {
        return 0;
 }
 sub WARN {
-       if (report("WARNING", $_[0], $_[1])) {
+       my ($type, $msg) = @_;
+
+       if (report("WARNING", $type, $msg)) {
                our $clean = 0;
                our $cnt_warn++;
                return 1;
@@ -1474,7 +1497,9 @@ sub WARN {
        return 0;
 }
 sub CHK {
-       if ($check && report("CHECK", $_[0], $_[1])) {
+       my ($type, $msg) = @_;
+
+       if ($check && report("CHECK", $type, $msg)) {
                our $clean = 0;
                our $cnt_chk++;
                return 1;
@@ -1584,7 +1609,7 @@ sub pos_last_openparen {
                }
        }
 
-       return $last_openparen + 1;
+       return length(expand_tabs(substr($line, 0, $last_openparen))) + 1;
 }
 
 sub process {
@@ -1901,6 +1926,12 @@ sub process {
                        }
                }
 
+# Check for unwanted Gerrit info
+               if ($in_commit_log && $line =~ /^\s*change-id:/i) {
+                       ERROR("GERRIT_CHANGE_ID",
+                             "Remove Gerrit Change-Id's before submitting upstream.\n" . $herecurr);
+               }
+
 # Check for wrappage within a valid hunk of the file
                if ($realcnt != 0 && $line !~ m{^(?:\+|-| |\\ No newline|$)}) {
                        ERROR("CORRUPTED_PATCH",
@@ -2051,13 +2082,17 @@ sub process {
                }
 
 # check for DT compatible documentation
-               if (defined $root && $realfile =~ /\.dts/ &&
-                   $rawline =~ /^\+\s*compatible\s*=/) {
+               if (defined $root &&
+                       (($realfile =~ /\.dtsi?$/ && $line =~ /^\+\s*compatible\s*=\s*\"/) ||
+                        ($realfile =~ /\.[ch]$/ && $line =~ /^\+.*\.compatible\s*=\s*\"/))) {
+
                        my @compats = $rawline =~ /\"([a-zA-Z0-9\-\,\.\+_]+)\"/g;
 
+                       my $dt_path = $root . "/Documentation/devicetree/bindings/";
+                       my $vp_file = $dt_path . "vendor-prefixes.txt";
+
                        foreach my $compat (@compats) {
                                my $compat2 = $compat;
-                               my $dt_path =  $root . "/Documentation/devicetree/bindings/";
                                $compat2 =~ s/\,[a-z]*\-/\,<\.\*>\-/;
                                `grep -Erq "$compat|$compat2" $dt_path`;
                                if ( $? >> 8 ) {
@@ -2065,14 +2100,12 @@ sub process {
                                             "DT compatible string \"$compat\" appears un-documented -- check $dt_path\n" . $herecurr);
                                }
 
-                               my $vendor = $compat;
-                               my $vendor_path = $dt_path . "vendor-prefixes.txt";
-                               next if (! -f $vendor_path);
-                               $vendor =~ s/^([a-zA-Z0-9]+)\,.*/$1/;
-                               `grep -Eq "$vendor" $vendor_path`;
+                               next if $compat !~ /^([a-zA-Z0-9\-]+)\,/;
+                               my $vendor = $1;
+                               `grep -Eq "^$vendor\\b" $vp_file`;
                                if ( $? >> 8 ) {
                                        WARN("UNDOCUMENTED_DT_STRING",
-                                            "DT compatible string vendor \"$vendor\" appears un-documented -- check $vendor_path\n" . $herecurr);
+                                            "DT compatible string vendor \"$vendor\" appears un-documented -- check $vp_file\n" . $herecurr);
                                }
                        }
                }
@@ -2169,7 +2202,7 @@ sub process {
 
 # check multi-line statement indentation matches previous line
                if ($^V && $^V ge 5.10.0 &&
-                   $prevline =~ /^\+(\t*)(if \(|$Ident\().*(\&\&|\|\||,)\s*$/) {
+                   $prevline =~ /^\+([ \t]*)((?:$c90_Keywords(?:\s+if)\s*)|(?:$Declare\s*)?(?:$Ident|\(\s*\*\s*$Ident\s*\))\s*|$Ident\s*=\s*$Ident\s*)\(.*(\&\&|\|\||,)\s*$/) {
                        $prevline =~ /^\+(\t*)(.*)$/;
                        my $oldindent = $1;
                        my $rest = $2;
@@ -2208,7 +2241,8 @@ sub process {
 
                if ($realfile =~ m@^(drivers/net/|net/)@ &&
                    $prevrawline =~ /^\+[ \t]*\/\*[ \t]*$/ &&
-                   $rawline =~ /^\+[ \t]*\*/) {
+                   $rawline =~ /^\+[ \t]*\*/ &&
+                   $realline > 2) {
                        WARN("NETWORKING_BLOCK_COMMENT_STYLE",
                             "networking block comments don't use an empty /* line, use /* Comment...\n" . $hereprev);
                }
@@ -2231,6 +2265,21 @@ sub process {
                             "networking block comments put the trailing */ on a separate line\n" . $herecurr);
                }
 
+# check for missing blank lines after declarations
+               if ($realfile =~ m@^(drivers/net/|net/)@ &&
+                   $prevline =~ /^\+\s+$Declare\s+$Ident/ &&
+                   !($prevline =~ /(?:$Compare|$Assignment|$Operators)\s*$/ ||
+                     $prevline =~ /(?:\{\s*|\\)$/) &&          #extended lines
+                   $sline =~ /^\+\s+/ &&                       #Not at char 1
+                   !($sline =~ /^\+\s+$Declare/ ||
+                     $sline =~ /^\+\s+$Ident\s+$Ident/ ||      #eg: typedef foo
+                     $sline =~ /^\+\s+(?:union|struct|enum|typedef)\b/ ||
+                     $sline =~ /^\+\s+(?:$|[\{\}\.\#\"\?\:\(])/ ||
+                     $sline =~ /^\+\s+\(?\s*(?:$Compare|$Assignment|$Operators)/)) {
+                       WARN("SPACING",
+                            "networking uses a blank line after declarations\n" . $hereprev);
+               }
+
 # check for spaces at the beginning of a line.
 # Exceptions:
 #  1) within comments
@@ -2675,6 +2724,13 @@ sub process {
                                $herecurr);
                }
 
+# check for non-global char *foo[] = {"bar", ...} declarations.
+               if ($line =~ /^.\s+(?:static\s+|const\s+)?char\s+\*\s*\w+\s*\[\s*\]\s*=\s*\{/) {
+                       WARN("STATIC_CONST_CHAR_ARRAY",
+                            "char * array declaration might be better as static const\n" .
+                               $herecurr);
+               }
+
 # check for function declarations without arguments like "int foo()"
                if ($line =~ /(\b$Type\s+$Ident)\s*\(\s*\)/) {
                        if (ERROR("FUNCTION_WITHOUT_ARGS",
@@ -2809,7 +2865,7 @@ sub process {
                        my $level2 = $level;
                        $level2 = "dbg" if ($level eq "debug");
                        WARN("PREFER_PR_LEVEL",
-                            "Prefer netdev_$level2(netdev, ... then dev_$level2(dev, ... then pr_$level(...  to printk(KERN_$orig ...\n" . $herecurr);
+                            "Prefer [subsystem eg: netdev]_$level2([subsystem]dev, ... then dev_$level2(dev, ... then pr_$level(...  to printk(KERN_$orig ...\n" . $herecurr);
                }
 
                if ($line =~ /\bpr_warning\s*\(/) {
@@ -3082,10 +3138,13 @@ sub process {
                                # // is a comment
                                } elsif ($op eq '//') {
 
+                               #   :   when part of a bitfield
+                               } elsif ($opv eq ':B') {
+                                       # skip the bitfield test for now
+
                                # No spaces for:
                                #   ->
-                               #   :   when part of a bitfield
-                               } elsif ($op eq '->' || $opv eq ':B') {
+                               } elsif ($op eq '->') {
                                        if ($ctx =~ /Wx.|.xW/) {
                                                if (ERROR("SPACING",
                                                          "spaces prohibited around that '$op' $at\n" . $hereptr)) {
@@ -3355,14 +3414,17 @@ sub process {
                        }
                }
 
-# Return is not a function.
+# return is not a function
                if (defined($stat) && $stat =~ /^.\s*return(\s*)\(/s) {
                        my $spacing = $1;
                        if ($^V && $^V ge 5.10.0 &&
-                           $stat =~ /^.\s*return\s*$balanced_parens\s*;\s*$/) {
-                               ERROR("RETURN_PARENTHESES",
-                                     "return is not a function, parentheses are not required\n" . $herecurr);
-
+                           $stat =~ /^.\s*return\s*($balanced_parens)\s*;\s*$/) {
+                               my $value = $1;
+                               $value = deparenthesize($value);
+                               if ($value =~ m/^\s*$FuncArg\s*(?:\?|$)/) {
+                                       ERROR("RETURN_PARENTHESES",
+                                             "return is not a function, parentheses are not required\n" . $herecurr);
+                               }
                        } elsif ($spacing !~ /\s+/) {
                                ERROR("SPACING",
                                      "space required before the open parenthesis '('\n" . $herecurr);
@@ -4279,12 +4341,6 @@ sub process {
                             "$1 uses number as first arg, sizeof is generally wrong\n" . $herecurr);
                }
 
-# check for GFP_NOWAIT use
-               if ($line =~ /\b__GFP_NOFAIL\b/) {
-                       WARN("__GFP_NOFAIL",
-                            "Use of __GFP_NOFAIL is deprecated, no new users should be added\n" . $herecurr);
-               }
-
 # check for multiple semicolons
                if ($line =~ /;\s*;\s*$/) {
                        if (WARN("ONE_SEMICOLON",
@@ -4497,26 +4553,30 @@ sub process {
                             "Exporting world writable files is usually an error. Consider more restrictive permissions.\n" . $herecurr);
                }
 
-               foreach my $entry (@mode_permission_funcs) {
-                       my $func = $entry->[0];
-                       my $arg_pos = $entry->[1];
-
-                       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 ($^V && $^V ge 5.10.0 &&
-                           $line =~ /$test/) {
-                               my $val = $1;
-                               $val = $6 if ($skip_args ne "");
-
-                               if ($val !~ /^0$/ &&
-                                   (($val =~ /^$Int$/ && $val !~ /^$Octal$/) ||
-                                    length($val) ne 4)) {
-                                       ERROR("NON_OCTAL_PERMISSIONS",
-                                             "Use 4 digit octal (0777) not decimal permissions\n" . $herecurr);
+# 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 &&
+                   $line =~ /$mode_perms_search/) {
+                       foreach my $entry (@mode_permission_funcs) {
+                               my $func = $entry->[0];
+                               my $arg_pos = $entry->[1];
+
+                               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 $val = $1;
+                                       $val = $6 if ($skip_args ne "");
+
+                                       if ($val !~ /^0$/ &&
+                                           (($val =~ /^$Int$/ && $val !~ /^$Octal$/) ||
+                                            length($val) ne 4)) {
+                                               ERROR("NON_OCTAL_PERMISSIONS",
+                                                     "Use 4 digit octal (0777) not decimal permissions\n" . $herecurr);
+                                       }
                                }
                        }
                }