Merge tag 'spi-v3.17-rc3-2' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi
[pandora-kernel.git] / scripts / checkpatch.pl
index 182be0f..b385bcb 100755 (executable)
@@ -309,9 +309,12 @@ our $Operators     = qr{
 our $c90_Keywords = qr{do|for|while|if|else|return|goto|continue|switch|default|case|break}x;
 
 our $NonptrType;
+our $NonptrTypeMisordered;
 our $NonptrTypeWithAttr;
 our $Type;
+our $TypeMisordered;
 our $Declare;
+our $DeclareMisordered;
 
 our $NON_ASCII_UTF8    = qr{
        [\xC2-\xDF][\x80-\xBF]               # non-overlong 2-byte
@@ -353,16 +356,36 @@ our $signature_tags = qr{(?xi:
        Cc:
 )};
 
+our @typeListMisordered = (
+       qr{char\s+(?:un)?signed},
+       qr{int\s+(?:(?:un)?signed\s+)?short\s},
+       qr{int\s+short(?:\s+(?:un)?signed)},
+       qr{short\s+int(?:\s+(?:un)?signed)},
+       qr{(?:un)?signed\s+int\s+short},
+       qr{short\s+(?:un)?signed},
+       qr{long\s+int\s+(?:un)?signed},
+       qr{int\s+long\s+(?:un)?signed},
+       qr{long\s+(?:un)?signed\s+int},
+       qr{int\s+(?:un)?signed\s+long},
+       qr{int\s+(?:un)?signed},
+       qr{int\s+long\s+long\s+(?:un)?signed},
+       qr{long\s+long\s+int\s+(?:un)?signed},
+       qr{long\s+long\s+(?:un)?signed\s+int},
+       qr{long\s+long\s+(?:un)?signed},
+       qr{long\s+(?:un)?signed},
+);
+
 our @typeList = (
        qr{void},
-       qr{(?:unsigned\s+)?char},
-       qr{(?:unsigned\s+)?short},
-       qr{(?:unsigned\s+)?int},
-       qr{(?:unsigned\s+)?long},
-       qr{(?:unsigned\s+)?long\s+int},
-       qr{(?:unsigned\s+)?long\s+long},
-       qr{(?:unsigned\s+)?long\s+long\s+int},
-       qr{unsigned},
+       qr{(?:(?:un)?signed\s+)?char},
+       qr{(?:(?:un)?signed\s+)?short\s+int},
+       qr{(?:(?:un)?signed\s+)?short},
+       qr{(?:(?:un)?signed\s+)?int},
+       qr{(?:(?:un)?signed\s+)?long\s+int},
+       qr{(?:(?:un)?signed\s+)?long\s+long\s+int},
+       qr{(?:(?:un)?signed\s+)?long\s+long},
+       qr{(?:(?:un)?signed\s+)?long},
+       qr{(?:un)?signed},
        qr{float},
        qr{double},
        qr{bool},
@@ -372,6 +395,7 @@ our @typeList = (
        qr{${Ident}_t},
        qr{${Ident}_handler},
        qr{${Ident}_handler_fn},
+       @typeListMisordered,
 );
 our @typeListWithAttr = (
        @typeList,
@@ -399,11 +423,6 @@ foreach my $entry (@mode_permission_funcs) {
        $mode_perms_search .= $entry->[0];
 }
 
-our $declaration_macros = qr{(?x:
-       (?:$Storage\s+)?(?:DECLARE|DEFINE)_[A-Z]+\s*\(|
-       (?:$Storage\s+)?LIST_HEAD\s*\(
-)};
-
 our $allowed_asm_includes = qr{(?x:
        irq|
        memory
@@ -413,6 +432,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 $Misordered = "(?x:  \n" . join("|\n  ", @typeListMisordered) . "\n)";
        my $allWithAttr = "(?x:  \n" . join("|\n  ", @typeListWithAttr) . "\n)";
        $Modifier       = qr{(?:$Attribute|$Sparse|$mods)};
        $NonptrType     = qr{
@@ -424,6 +444,13 @@ sub build_types {
                        )
                        (?:\s+$Modifier|\s+const)*
                  }x;
+       $NonptrTypeMisordered   = qr{
+                       (?:$Modifier\s+|const\s+)*
+                       (?:
+                               (?:${Misordered}\b)
+                       )
+                       (?:\s+$Modifier|\s+const)*
+                 }x;
        $NonptrTypeWithAttr     = qr{
                        (?:$Modifier\s+|const\s+)*
                        (?:
@@ -435,10 +462,16 @@ sub build_types {
                  }x;
        $Type   = qr{
                        $NonptrType
-                       (?:(?:\s|\*|\[\])+\s*const|(?:\s|\*|\[\])+|(?:\s*\[\s*\])+)?
+                       (?:(?:\s|\*|\[\])+\s*const|(?:\s|\*\s*(?:const\s*)?|\[\])+|(?:\s*\[\s*\])+)?
+                       (?:\s+$Inline|\s+$Modifier)*
+                 }x;
+       $TypeMisordered = qr{
+                       $NonptrTypeMisordered
+                       (?:(?:\s|\*|\[\])+\s*const|(?:\s|\*\s*(?:const\s*)?|\[\])+|(?:\s*\[\s*\])+)?
                        (?:\s+$Inline|\s+$Modifier)*
                  }x;
        $Declare        = qr{(?:$Storage\s+(?:$Inline\s+)?)?$Type};
+       $DeclareMisordered      = qr{(?:$Storage\s+(?:$Inline\s+)?)?$TypeMisordered};
 }
 build_types();
 
@@ -452,6 +485,12 @@ our $balanced_parens = qr/(\((?:[^\(\)]++|(?-1))*\))/;
 our $LvalOrFunc        = qr{((?:[\&\*]\s*)?$Lval)\s*($balanced_parens{0,1})\s*};
 our $FuncArg = qr{$Typecast{0,1}($LvalOrFunc|$Constant)};
 
+our $declaration_macros = qr{(?x:
+       (?:$Storage\s+)?(?:[A-Z_][A-Z0-9]*_){0,2}(?:DEFINE|DECLARE)(?:_[A-Z0-9]+){1,2}\s*\(|
+       (?:$Storage\s+)?LIST_HEAD\s*\(|
+       (?:$Storage\s+)?${Type}\s+uninitialized_var\s*\(
+)};
+
 sub deparenthesize {
        my ($string) = @_;
        return "" if (!defined($string));
@@ -550,11 +589,43 @@ sub seed_camelcase_includes {
        }
 }
 
+sub git_commit_info {
+       my ($commit, $id, $desc) = @_;
+
+       return ($id, $desc) if ((which("git") eq "") || !(-e ".git"));
+
+       my $output = `git log --no-color --format='%H %s' -1 $commit 2>&1`;
+       $output =~ s/^\s*//gm;
+       my @lines = split("\n", $output);
+
+       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...
+#
+#              echo "checking commits $1..."
+#              git rev-list --remotes | grep -i "^$1" |
+#              while read line ; do
+#                  git log --format='%H %s' -1 $line |
+#                  echo "commit $(cut -c 1-12,41-)"
+#              done
+       } elsif ($lines[0] =~ /^fatal: ambiguous argument '$commit': unknown revision or path not in the working tree\./) {
+       } else {
+               $id = substr($lines[0], 0, 12);
+               $desc = substr($lines[0], 41);
+       }
+
+       return ($id, $desc);
+}
+
 $chk_signoff = 0 if ($file);
 
 my @rawlines = ();
 my @lines = ();
 my @fixed = ();
+my @fixed_inserted = ();
+my @fixed_deleted = ();
+my $fixlinenr = -1;
+
 my $vname;
 for my $filename (@ARGV) {
        my $FILE;
@@ -583,6 +654,9 @@ for my $filename (@ARGV) {
        @rawlines = ();
        @lines = ();
        @fixed = ();
+       @fixed_inserted = ();
+       @fixed_deleted = ();
+       $fixlinenr = -1;
 }
 
 exit($exit);
@@ -674,6 +748,18 @@ sub format_email {
        return $formatted_email;
 }
 
+sub which {
+       my ($bin) = @_;
+
+       foreach my $path (split(/:/, $ENV{PATH})) {
+               if (-e "$path/$bin") {
+                       return "$path/$bin";
+               }
+       }
+
+       return "";
+}
+
 sub which_conf {
        my ($conf) = @_;
 
@@ -1483,6 +1569,90 @@ sub report_dump {
        our @report;
 }
 
+sub fixup_current_range {
+       my ($lineRef, $offset, $length) = @_;
+
+       if ($$lineRef =~ /^\@\@ -\d+,\d+ \+(\d+),(\d+) \@\@/) {
+               my $o = $1;
+               my $l = $2;
+               my $no = $o + $offset;
+               my $nl = $l + $length;
+               $$lineRef =~ s/\+$o,$l \@\@/\+$no,$nl \@\@/;
+       }
+}
+
+sub fix_inserted_deleted_lines {
+       my ($linesRef, $insertedRef, $deletedRef) = @_;
+
+       my $range_last_linenr = 0;
+       my $delta_offset = 0;
+
+       my $old_linenr = 0;
+       my $new_linenr = 0;
+
+       my $next_insert = 0;
+       my $next_delete = 0;
+
+       my @lines = ();
+
+       my $inserted = @{$insertedRef}[$next_insert++];
+       my $deleted = @{$deletedRef}[$next_delete++];
+
+       foreach my $old_line (@{$linesRef}) {
+               my $save_line = 1;
+               my $line = $old_line;   #don't modify the array
+               if ($line =~ /^(?:\+\+\+\|\-\-\-)\s+\S+/) {     #new filename
+                       $delta_offset = 0;
+               } elsif ($line =~ /^\@\@ -\d+,\d+ \+\d+,\d+ \@\@/) {    #new hunk
+                       $range_last_linenr = $new_linenr;
+                       fixup_current_range(\$line, $delta_offset, 0);
+               }
+
+               while (defined($deleted) && ${$deleted}{'LINENR'} == $old_linenr) {
+                       $deleted = @{$deletedRef}[$next_delete++];
+                       $save_line = 0;
+                       fixup_current_range(\$lines[$range_last_linenr], $delta_offset--, -1);
+               }
+
+               while (defined($inserted) && ${$inserted}{'LINENR'} == $old_linenr) {
+                       push(@lines, ${$inserted}{'LINE'});
+                       $inserted = @{$insertedRef}[$next_insert++];
+                       $new_linenr++;
+                       fixup_current_range(\$lines[$range_last_linenr], $delta_offset++, 1);
+               }
+
+               if ($save_line) {
+                       push(@lines, $line);
+                       $new_linenr++;
+               }
+
+               $old_linenr++;
+       }
+
+       return @lines;
+}
+
+sub fix_insert_line {
+       my ($linenr, $line) = @_;
+
+       my $inserted = {
+               LINENR => $linenr,
+               LINE => $line,
+       };
+       push(@fixed_inserted, $inserted);
+}
+
+sub fix_delete_line {
+       my ($linenr, $line) = @_;
+
+       my $deleted = {
+               LINENR => $linenr,
+               LINE => $line,
+       };
+
+       push(@fixed_deleted, $deleted);
+}
+
 sub ERROR {
        my ($type, $msg) = @_;
 
@@ -1637,11 +1807,13 @@ sub process {
        my $signoff = 0;
        my $is_patch = 0;
 
-       my $in_header_lines = 1;
+       my $in_header_lines = $file ? 0 : 1;
        my $in_commit_log = 0;          #Scanning lines before patch
-
+       my $reported_maintainer_file = 0;
        my $non_utf8_charset = 0;
 
+       my $last_blank_line = 0;
+
        our @report = ();
        our $cnt_lines = 0;
        our $cnt_error = 0;
@@ -1759,8 +1931,10 @@ sub process {
 
        $realcnt = 0;
        $linenr = 0;
+       $fixlinenr = -1;
        foreach my $line (@lines) {
                $linenr++;
+               $fixlinenr++;
                my $sline = $line;      #copy of $line
                $sline =~ s/$;/ /g;     #with comments as spaces
 
@@ -1891,7 +2065,7 @@ sub process {
                                if (WARN("BAD_SIGN_OFF",
                                         "Do not use whitespace before $ucfirst_sign_off\n" . $herecurr) &&
                                    $fix) {
-                                       $fixed[$linenr - 1] =
+                                       $fixed[$fixlinenr] =
                                            "$ucfirst_sign_off $email";
                                }
                        }
@@ -1899,7 +2073,7 @@ sub process {
                                if (WARN("BAD_SIGN_OFF",
                                         "'$ucfirst_sign_off' is the preferred signature form\n" . $herecurr) &&
                                    $fix) {
-                                       $fixed[$linenr - 1] =
+                                       $fixed[$fixlinenr] =
                                            "$ucfirst_sign_off $email";
                                }
 
@@ -1908,7 +2082,7 @@ sub process {
                                if (WARN("BAD_SIGN_OFF",
                                         "Use a single space after $ucfirst_sign_off\n" . $herecurr) &&
                                    $fix) {
-                                       $fixed[$linenr - 1] =
+                                       $fixed[$fixlinenr] =
                                            "$ucfirst_sign_off $email";
                                }
                        }
@@ -1956,6 +2130,31 @@ sub process {
                              "Remove Gerrit Change-Id's before submitting upstream.\n" . $herecurr);
                }
 
+# Check for improperly formed commit descriptions
+               if ($in_commit_log &&
+                   $line =~ /\bcommit\s+[0-9a-f]{5,}/i &&
+                   $line !~ /\b[Cc]ommit [0-9a-f]{12,40} \("/) {
+                       $line =~ /\b(c)ommit\s+([0-9a-f]{5,})/i;
+                       my $init_char = $1;
+                       my $orig_commit = lc($2);
+                       my $id = '01234567890ab';
+                       my $desc = 'commit description';
+                       ($id, $desc) = git_commit_info($orig_commit, $id, $desc);
+                       ERROR("GIT_COMMIT_ID",
+                             "Please use 12 or more chars for the git commit ID like: '${init_char}ommit $id (\"$desc\")'\n" . $herecurr);
+               }
+
+# Check for added, moved or deleted files
+               if (!$reported_maintainer_file && !$in_commit_log &&
+                   ($line =~ /^(?:new|deleted) file mode\s*\d+\s*$/ ||
+                    $line =~ /^rename (?:from|to) [\w\/\.\-]+\s*$/ ||
+                    ($line =~ /\{\s*([\w\/\.\-]*)\s*\=\>\s*([\w\/\.\-]*)\s*\}/ &&
+                     (defined($1) || defined($2))))) {
+                       $reported_maintainer_file = 1;
+                       WARN("FILE_PATH_CHANGES",
+                            "added, moved or deleted file(s), does MAINTAINERS need updating?\n" . $herecurr);
+               }
+
 # Check for wrappage within a valid hunk of the file
                if ($realcnt != 0 && $line !~ m{^(?:\+|-| |\\ No newline|$)}) {
                        ERROR("CORRUPTED_PATCH",
@@ -1993,7 +2192,8 @@ sub process {
 # Check if it's the start of a commit log
 # (not a header line and we haven't seen the patch filename)
                if ($in_header_lines && $realfile =~ /^$/ &&
-                   $rawline !~ /^(commit\b|from\b|[\w-]+:).+$/i) {
+                   !($rawline =~ /^\s+\S/ ||
+                     $rawline =~ /^(commit\b|from\b|[\w-]+:).*$/i)) {
                        $in_header_lines = 0;
                        $in_commit_log = 1;
                }
@@ -2021,14 +2221,14 @@ sub process {
                        if (ERROR("DOS_LINE_ENDINGS",
                                  "DOS line endings\n" . $herevet) &&
                            $fix) {
-                               $fixed[$linenr - 1] =~ s/[\s\015]+$//;
+                               $fixed[$fixlinenr] =~ s/[\s\015]+$//;
                        }
                } elsif ($rawline =~ /^\+.*\S\s+$/ || $rawline =~ /^\+\s+$/) {
                        my $herevet = "$here\n" . cat_vet($rawline) . "\n";
                        if (ERROR("TRAILING_WHITESPACE",
                                  "trailing whitespace\n" . $herevet) &&
                            $fix) {
-                               $fixed[$linenr - 1] =~ s/\s+$//;
+                               $fixed[$fixlinenr] =~ s/\s+$//;
                        }
 
                        $rpt_cleaners = 1;
@@ -2049,7 +2249,7 @@ sub process {
 # Only applies when adding the entry originally, after that we do not have
 # sufficient context to determine whether it is indeed long enough.
                if ($realfile =~ /Kconfig/ &&
-                   $line =~ /.\s*config\s+/) {
+                   $line =~ /^\+\s*config\s+/) {
                        my $length = 0;
                        my $cnt = $realcnt;
                        my $ln = $linenr + 1;
@@ -2062,10 +2262,11 @@ sub process {
                                $is_end = $lines[$ln - 1] =~ /^\+/;
 
                                next if ($f =~ /^-/);
+                               last if (!$file && $f =~ /^\@\@/);
 
-                               if ($lines[$ln - 1] =~ /.\s*(?:bool|tristate)\s*\"/) {
+                               if ($lines[$ln - 1] =~ /^\+\s*(?:bool|tristate)\s*\"/) {
                                        $is_start = 1;
-                               } elsif ($lines[$ln - 1] =~ /.\s*(?:---)?help(?:---)?$/) {
+                               } elsif ($lines[$ln - 1] =~ /^\+\s*(?:---)?help(?:---)?$/) {
                                        $length = -1;
                                }
 
@@ -2161,12 +2362,18 @@ sub process {
                             "quoted string split across lines\n" . $hereprev);
                }
 
+# check for missing a space in a string concatination
+               if ($prevrawline =~ /[^\\]\w"$/ && $rawline =~ /^\+[\t ]+"\w/) {
+                       WARN('MISSING_SPACE',
+                            "break quoted strings at a space character\n" . $hereprev);
+               }
+
 # check for spaces before a quoted newline
                if ($rawline =~ /^.*\".*\s\\n/) {
                        if (WARN("QUOTED_WHITESPACE_BEFORE_NEWLINE",
                                 "unnecessary whitespace before a quoted newline\n" . $herecurr) &&
                            $fix) {
-                               $fixed[$linenr - 1] =~ s/^(\+.*\".*)\s+\\n/$1\\n/;
+                               $fixed[$fixlinenr] =~ s/^(\+.*\".*)\s+\\n/$1\\n/;
                        }
 
                }
@@ -2203,7 +2410,7 @@ sub process {
                        if (ERROR("CODE_INDENT",
                                  "code indent should use tabs where possible\n" . $herevet) &&
                            $fix) {
-                               $fixed[$linenr - 1] =~ s/^\+([ \t]+)/"\+" . tabify($1)/e;
+                               $fixed[$fixlinenr] =~ s/^\+([ \t]+)/"\+" . tabify($1)/e;
                        }
                }
 
@@ -2213,9 +2420,9 @@ sub process {
                        if (WARN("SPACE_BEFORE_TAB",
                                "please, no space before tabs\n" . $herevet) &&
                            $fix) {
-                               while ($fixed[$linenr - 1] =~
+                               while ($fixed[$fixlinenr] =~
                                           s/(^\+.*) {8,8}+\t/$1\t\t/) {}
-                               while ($fixed[$linenr - 1] =~
+                               while ($fixed[$fixlinenr] =~
                                           s/(^\+.*) +\t/$1\t/) {}
                        }
                }
@@ -2249,19 +2456,19 @@ sub process {
                                        if (CHK("PARENTHESIS_ALIGNMENT",
                                                "Alignment should match open parenthesis\n" . $hereprev) &&
                                            $fix && $line =~ /^\+/) {
-                                               $fixed[$linenr - 1] =~
+                                               $fixed[$fixlinenr] =~
                                                    s/^\+[ \t]*/\+$goodtabindent/;
                                        }
                                }
                        }
                }
 
-               if ($line =~ /^\+.*\*[ \t]*\)[ \t]+(?!$Assignment|$Arithmetic)/) {
+               if ($line =~ /^\+.*\(\s*$Type\s*\)[ \t]+(?!$Assignment|$Arithmetic|{)/) {
                        if (CHK("SPACING",
-                               "No space is necessary after a cast\n" . $hereprev) &&
+                               "No space is necessary after a cast\n" . $herecurr) &&
                            $fix) {
-                               $fixed[$linenr - 1] =~
-                                   s/^(\+.*\*[ \t]*\))[ \t]+/$1/;
+                               $fixed[$fixlinenr] =~
+                                   s/(\(\s*$Type\s*\))[ \t]+/$1/;
                        }
                }
 
@@ -2291,10 +2498,44 @@ sub process {
                             "networking block comments put the trailing */ on a separate line\n" . $herecurr);
                }
 
+# check for missing blank lines after struct/union declarations
+# with exceptions for various attributes and macros
+               if ($prevline =~ /^[\+ ]};?\s*$/ &&
+                   $line =~ /^\+/ &&
+                   !($line =~ /^\+\s*$/ ||
+                     $line =~ /^\+\s*EXPORT_SYMBOL/ ||
+                     $line =~ /^\+\s*MODULE_/i ||
+                     $line =~ /^\+\s*\#\s*(?:end|elif|else)/ ||
+                     $line =~ /^\+[a-z_]*init/ ||
+                     $line =~ /^\+\s*(?:static\s+)?[A-Z_]*ATTR/ ||
+                     $line =~ /^\+\s*DECLARE/ ||
+                     $line =~ /^\+\s*__setup/)) {
+                       if (CHK("LINE_SPACING",
+                               "Please use a blank line after function/struct/union/enum declarations\n" . $hereprev) &&
+                           $fix) {
+                               fix_insert_line($fixlinenr, "\+");
+                       }
+               }
+
+# check for multiple consecutive blank lines
+               if ($prevline =~ /^[\+ ]\s*$/ &&
+                   $line =~ /^\+\s*$/ &&
+                   $last_blank_line != ($linenr - 1)) {
+                       if (CHK("LINE_SPACING",
+                               "Please don't use multiple blank lines\n" . $hereprev) &&
+                           $fix) {
+                               fix_delete_line($fixlinenr, $rawline);
+                       }
+
+                       $last_blank_line = $linenr;
+               }
+
 # check for missing blank lines after declarations
                if ($sline =~ /^\+\s+\S/ &&                     #Not at char 1
                        # actual declarations
                    ($prevline =~ /^\+\s+$Declare\s*$Ident\s*[=,;:\[]/ ||
+                       # function pointer declarations
+                    $prevline =~ /^\+\s+$Declare\s*\(\s*\*\s*$Ident\s*\)\s*[=,;:\[\(]/ ||
                        # foo bar; where foo is some local typedef or #define
                     $prevline =~ /^\+\s+$Ident(?:\s+|\s*\*\s*)$Ident\s*[=,;\[]/ ||
                        # known declaration macros
@@ -2307,6 +2548,8 @@ sub process {
                      $prevline =~ /(?:\{\s*|\\)$/) &&
                        # looks like a declaration
                    !($sline =~ /^\+\s+$Declare\s*$Ident\s*[=,;:\[]/ ||
+                       # function pointer declarations
+                     $sline =~ /^\+\s+$Declare\s*\(\s*\*\s*$Ident\s*\)\s*[=,;:\[\(]/ ||
                        # foo bar; where foo is some local typedef or #define
                      $sline =~ /^\+\s+$Ident(?:\s+|\s*\*\s*)$Ident\s*[=,;\[]/ ||
                        # known declaration macros
@@ -2321,8 +2564,11 @@ sub process {
                      $sline =~ /^\+\s+\(?\s*(?:$Compare|$Assignment|$Operators)/) &&
                        # indentation of previous and current line are the same
                    (($prevline =~ /\+(\s+)\S/) && $sline =~ /^\+$1\S/)) {
-                       WARN("SPACING",
-                            "Missing a blank line after declarations\n" . $hereprev);
+                       if (WARN("LINE_SPACING",
+                                "Missing a blank line after declarations\n" . $hereprev) &&
+                           $fix) {
+                               fix_insert_line($fixlinenr, "\+");
+                       }
                }
 
 # check for spaces at the beginning of a line.
@@ -2335,13 +2581,33 @@ sub process {
                        if (WARN("LEADING_SPACE",
                                 "please, no spaces at the start of a line\n" . $herevet) &&
                            $fix) {
-                               $fixed[$linenr - 1] =~ s/^\+([ \t]+)/"\+" . tabify($1)/e;
+                               $fixed[$fixlinenr] =~ s/^\+([ \t]+)/"\+" . tabify($1)/e;
                        }
                }
 
 # check we are in a valid C source file if not then ignore this hunk
                next if ($realfile !~ /\.(h|c)$/);
 
+# check indentation of any line with a bare else
+# if the previous line is a break or return and is indented 1 tab more...
+               if ($sline =~ /^\+([\t]+)(?:}[ \t]*)?else(?:[ \t]*{)?\s*$/) {
+                       my $tabs = length($1) + 1;
+                       if ($prevline =~ /^\+\t{$tabs,$tabs}(?:break|return)\b/) {
+                               WARN("UNNECESSARY_ELSE",
+                                    "else is not generally useful after a break or return\n" . $hereprev);
+                       }
+               }
+
+# check indentation of a line with a break;
+# if the previous line is a goto or return and is indented the same # of tabs
+               if ($sline =~ /^\+([\t]+)break\s*;\s*$/) {
+                       my $tabs = $1;
+                       if ($prevline =~ /^\+$tabs(?:goto|return)\b/) {
+                               WARN("UNNECESSARY_BREAK",
+                                    "break is not useful after a goto or return\n" . $hereprev);
+                       }
+               }
+
 # discourage the addition of CONFIG_EXPERIMENTAL in #if(def).
                if ($line =~ /^\+\s*\#\s*if.*\bCONFIG_EXPERIMENTAL\b/) {
                        WARN("CONFIG_EXPERIMENTAL",
@@ -2477,7 +2743,7 @@ sub process {
 
 # if/while/etc brace do not go on next line, unless defining a do while loop,
 # or if that brace on the next line is for something else
-               if ($line =~ /(.*)\b((?:if|while|for|switch)\s*\(|do\b|else\b)/ && $line !~ /^.\s*\#/) {
+               if ($line =~ /(.*)\b((?:if|while|for|switch|(?:[a-z_]+|)for_each[a-z_]+)\s*\(|do\b|else\b)/ && $line !~ /^.\s*\#/) {
                        my $pre_ctx = "$1$2";
 
                        my ($level, @ctx) = ctx_statement_level($linenr, $realcnt, 0);
@@ -2504,7 +2770,7 @@ sub process {
                        #print "realcnt<$realcnt> ctx_cnt<$ctx_cnt>\n";
                        #print "pre<$pre_ctx>\nline<$line>\nctx<$ctx>\nnext<$lines[$ctx_ln - 1]>\n";
 
-                       if ($ctx !~ /{\s*/ && defined($lines[$ctx_ln -1]) && $lines[$ctx_ln - 1] =~ /^\+\s*{/) {
+                       if ($ctx !~ /{\s*/ && defined($lines[$ctx_ln - 1]) && $lines[$ctx_ln - 1] =~ /^\+\s*{/) {
                                ERROR("OPEN_BRACE",
                                      "that open brace { should be on the previous line\n" .
                                        "$here\n$ctx\n$rawlines[$ctx_ln - 1]\n");
@@ -2523,7 +2789,7 @@ sub process {
                }
 
 # Check relative indent for conditionals and blocks.
-               if ($line =~ /\b(?:(?:if|while|for)\s*\(|do\b)/ && $line !~ /^.\s*#/ && $line !~ /\}\s*while\s*/) {
+               if ($line =~ /\b(?:(?:if|while|for|(?:[a-z_]+|)for_each[a-z_]+)\s*\(|do\b)/ && $line !~ /^.\s*#/ && $line !~ /\}\s*while\s*/) {
                        ($stat, $cond, $line_nr_next, $remain_next, $off_next) =
                                ctx_statement_block($linenr, $realcnt, 0)
                                        if (!defined $stat);
@@ -2654,8 +2920,18 @@ sub process {
 # check for initialisation to aggregates open brace on the next line
                if ($line =~ /^.\s*{/ &&
                    $prevline =~ /(?:^|[^=])=\s*$/) {
-                       ERROR("OPEN_BRACE",
-                             "that open brace { should be on the previous line\n" . $hereprev);
+                       if (ERROR("OPEN_BRACE",
+                                 "that open brace { should be on the previous line\n" . $hereprev) &&
+                           $fix && $prevline =~ /^\+/ && $line =~ /^\+/) {
+                               fix_delete_line($fixlinenr - 1, $prevrawline);
+                               fix_delete_line($fixlinenr, $rawline);
+                               my $fixedline = $prevrawline;
+                               $fixedline =~ s/\s*=\s*$/ = {/;
+                               fix_insert_line($fixlinenr, $fixedline);
+                               $fixedline = $line;
+                               $fixedline =~ s/^(.\s*){\s*/$1/;
+                               fix_insert_line($fixlinenr, $fixedline);
+                       }
                }
 
 #
@@ -2680,10 +2956,10 @@ sub process {
                        if (ERROR("C99_COMMENTS",
                                  "do not use C99 // comments\n" . $herecurr) &&
                            $fix) {
-                               my $line = $fixed[$linenr - 1];
+                               my $line = $fixed[$fixlinenr];
                                if ($line =~ /\/\/(.*)$/) {
                                        my $comment = trim($1);
-                                       $fixed[$linenr - 1] =~ s@\/\/(.*)$@/\* $comment \*/@;
+                                       $fixed[$fixlinenr] =~ s@\/\/(.*)$@/\* $comment \*/@;
                                }
                        }
                }
@@ -2742,7 +3018,7 @@ sub process {
                                  "do not initialise globals to 0 or NULL\n" .
                                      $herecurr) &&
                            $fix) {
-                               $fixed[$linenr - 1] =~ s/($Type\s*$Ident\s*(?:\s+$Modifier))*\s*=\s*(0|NULL|false)\s*;/$1;/;
+                               $fixed[$fixlinenr] =~ s/($Type\s*$Ident\s*(?:\s+$Modifier))*\s*=\s*(0|NULL|false)\s*;/$1;/;
                        }
                }
 # check for static initialisers.
@@ -2751,10 +3027,17 @@ sub process {
                                  "do not initialise statics to 0 or NULL\n" .
                                      $herecurr) &&
                            $fix) {
-                               $fixed[$linenr - 1] =~ s/(\bstatic\s.*?)\s*=\s*(0|NULL|false)\s*;/$1;/;
+                               $fixed[$fixlinenr] =~ s/(\bstatic\s.*?)\s*=\s*(0|NULL|false)\s*;/$1;/;
                        }
                }
 
+# check for misordered declarations of char/short/int/long with signed/unsigned
+               while ($sline =~ m{(\b$TypeMisordered\b)}g) {
+                       my $tmp = trim($1);
+                       WARN("MISORDERED_TYPE",
+                            "type '$tmp' should be specified in [[un]signed] [short|int|long|long long] order\n" . $herecurr);
+               }
+
 # 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",
@@ -2781,7 +3064,7 @@ sub process {
                        if (ERROR("FUNCTION_WITHOUT_ARGS",
                                  "Bad function definition - $1() should probably be $1(void)\n" . $herecurr) &&
                            $fix) {
-                               $fixed[$linenr - 1] =~ s/(\b($Type)\s+($Ident))\s*\(\s*\)/$2 $3(void)/;
+                               $fixed[$fixlinenr] =~ s/(\b($Type)\s+($Ident))\s*\(\s*\)/$2 $3(void)/;
                        }
                }
 
@@ -2790,7 +3073,7 @@ sub process {
                        if (WARN("DEFINE_PCI_DEVICE_TABLE",
                                 "Prefer struct pci_device_id over deprecated DEFINE_PCI_DEVICE_TABLE\n" . $herecurr) &&
                            $fix) {
-                               $fixed[$linenr - 1] =~ s/\b(?:static\s+|)DEFINE_PCI_DEVICE_TABLE\s*\(\s*(\w+)\s*\)\s*=\s*/static const struct pci_device_id $1\[\] = /;
+                               $fixed[$fixlinenr] =~ s/\b(?:static\s+|)DEFINE_PCI_DEVICE_TABLE\s*\(\s*(\w+)\s*\)\s*=\s*/static const struct pci_device_id $1\[\] = /;
                        }
                }
 
@@ -2827,7 +3110,7 @@ sub process {
                                        my $sub_from = $ident;
                                        my $sub_to = $ident;
                                        $sub_to =~ s/\Q$from\E/$to/;
-                                       $fixed[$linenr - 1] =~
+                                       $fixed[$fixlinenr] =~
                                            s@\Q$sub_from\E@$sub_to@;
                                }
                        }
@@ -2855,7 +3138,7 @@ sub process {
                                        my $sub_from = $match;
                                        my $sub_to = $match;
                                        $sub_to =~ s/\Q$from\E/$to/;
-                                       $fixed[$linenr - 1] =~
+                                       $fixed[$fixlinenr] =~
                                            s@\Q$sub_from\E@$sub_to@;
                                }
                        }
@@ -2917,7 +3200,7 @@ sub process {
                        if (WARN("PREFER_PR_LEVEL",
                                 "Prefer pr_warn(... to pr_warning(...\n" . $herecurr) &&
                            $fix) {
-                               $fixed[$linenr - 1] =~
+                               $fixed[$fixlinenr] =~
                                    s/\bpr_warning\b/pr_warn/;
                        }
                }
@@ -2933,17 +3216,40 @@ sub process {
 
 # function brace can't be on same line, except for #defines of do while,
 # or if closed on same line
-               if (($line=~/$Type\s*$Ident\(.*\).*\s{/) and
+               if (($line=~/$Type\s*$Ident\(.*\).*\s*{/) and
                    !($line=~/\#\s*define.*do\s{/) and !($line=~/}/)) {
-                       ERROR("OPEN_BRACE",
-                             "open brace '{' following function declarations go on the next line\n" . $herecurr);
+                       if (ERROR("OPEN_BRACE",
+                                 "open brace '{' following function declarations go on the next line\n" . $herecurr) &&
+                           $fix) {
+                               fix_delete_line($fixlinenr, $rawline);
+                               my $fixed_line = $rawline;
+                               $fixed_line =~ /(^..*$Type\s*$Ident\(.*\)\s*){(.*)$/;
+                               my $line1 = $1;
+                               my $line2 = $2;
+                               fix_insert_line($fixlinenr, ltrim($line1));
+                               fix_insert_line($fixlinenr, "\+{");
+                               if ($line2 !~ /^\s*$/) {
+                                       fix_insert_line($fixlinenr, "\+\t" . trim($line2));
+                               }
+                       }
                }
 
 # open braces for enum, union and struct go on the same line.
                if ($line =~ /^.\s*{/ &&
                    $prevline =~ /^.\s*(?:typedef\s+)?(enum|union|struct)(?:\s+$Ident)?\s*$/) {
-                       ERROR("OPEN_BRACE",
-                             "open brace '{' following $1 go on the same line\n" . $hereprev);
+                       if (ERROR("OPEN_BRACE",
+                                 "open brace '{' following $1 go on the same line\n" . $hereprev) &&
+                           $fix && $prevline =~ /^\+/ && $line =~ /^\+/) {
+                               fix_delete_line($fixlinenr - 1, $prevrawline);
+                               fix_delete_line($fixlinenr, $rawline);
+                               my $fixedline = rtrim($prevrawline) . " {";
+                               fix_insert_line($fixlinenr, $fixedline);
+                               $fixedline = $rawline;
+                               $fixedline =~ s/^(.\s*){\s*/$1\t/;
+                               if ($fixedline !~ /^\+\s*$/) {
+                                       fix_insert_line($fixlinenr, $fixedline);
+                               }
+                       }
                }
 
 # missing space after union, struct or enum definition
@@ -2951,7 +3257,7 @@ sub process {
                        if (WARN("SPACING",
                                 "missing space after $1 definition\n" . $herecurr) &&
                            $fix) {
-                               $fixed[$linenr - 1] =~
+                               $fixed[$fixlinenr] =~
                                    s/^(.\s*(?:typedef\s+)?(?:enum|union|struct)(?:\s+$Ident){1,2})([=\{])/$1 $2/;
                        }
                }
@@ -3021,7 +3327,7 @@ sub process {
                        }
 
                        if (show_type("SPACING") && $fix) {
-                               $fixed[$linenr - 1] =~
+                               $fixed[$fixlinenr] =~
                                    s/^(.\s*)$Declare\s*\(\s*\*\s*$Ident\s*\)\s*\(/$1 . $declare . $post_declare_space . '(*' . $funcname . ')('/ex;
                        }
                }
@@ -3038,7 +3344,7 @@ sub process {
                                if (ERROR("BRACKET_SPACE",
                                          "space prohibited before open square bracket '['\n" . $herecurr) &&
                                    $fix) {
-                                   $fixed[$linenr - 1] =~
+                                   $fixed[$fixlinenr] =~
                                        s/^(\+.*?)\s+\[/$1\[/;
                                }
                        }
@@ -3073,7 +3379,7 @@ sub process {
                                if (WARN("SPACING",
                                         "space prohibited between function name and open parenthesis '('\n" . $herecurr) &&
                                             $fix) {
-                                       $fixed[$linenr - 1] =~
+                                       $fixed[$fixlinenr] =~
                                            s/\b$name\s+\(/$name\(/;
                                }
                        }
@@ -3341,8 +3647,8 @@ sub process {
                                $fixed_line = $fixed_line . $fix_elements[$#elements];
                        }
 
-                       if ($fix && $line_fixed && $fixed_line ne $fixed[$linenr - 1]) {
-                               $fixed[$linenr - 1] = $fixed_line;
+                       if ($fix && $line_fixed && $fixed_line ne $fixed[$fixlinenr]) {
+                               $fixed[$fixlinenr] = $fixed_line;
                        }
 
 
@@ -3353,7 +3659,7 @@ sub process {
                        if (WARN("SPACING",
                                 "space prohibited before semicolon\n" . $herecurr) &&
                            $fix) {
-                               1 while $fixed[$linenr - 1] =~
+                               1 while $fixed[$fixlinenr] =~
                                    s/^(\+.*\S)\s+;/$1;/;
                        }
                }
@@ -3386,7 +3692,7 @@ sub process {
                        if (ERROR("SPACING",
                                  "space required before the open brace '{'\n" . $herecurr) &&
                            $fix) {
-                               $fixed[$linenr - 1] =~ s/^(\+.*(?:do|\))){/$1 {/;
+                               $fixed[$fixlinenr] =~ s/^(\+.*(?:do|\))){/$1 {/;
                        }
                }
 
@@ -3404,7 +3710,7 @@ sub process {
                        if (ERROR("SPACING",
                                  "space required after that close brace '}'\n" . $herecurr) &&
                            $fix) {
-                               $fixed[$linenr - 1] =~
+                               $fixed[$fixlinenr] =~
                                    s/}((?!(?:,|;|\)))\S)/} $1/;
                        }
                }
@@ -3414,7 +3720,7 @@ sub process {
                        if (ERROR("SPACING",
                                  "space prohibited after that open square bracket '['\n" . $herecurr) &&
                            $fix) {
-                               $fixed[$linenr - 1] =~
+                               $fixed[$fixlinenr] =~
                                    s/\[\s+/\[/;
                        }
                }
@@ -3422,7 +3728,7 @@ sub process {
                        if (ERROR("SPACING",
                                  "space prohibited before that close square bracket ']'\n" . $herecurr) &&
                            $fix) {
-                               $fixed[$linenr - 1] =~
+                               $fixed[$fixlinenr] =~
                                    s/\s+\]/\]/;
                        }
                }
@@ -3433,7 +3739,7 @@ sub process {
                        if (ERROR("SPACING",
                                  "space prohibited after that open parenthesis '('\n" . $herecurr) &&
                            $fix) {
-                               $fixed[$linenr - 1] =~
+                               $fixed[$fixlinenr] =~
                                    s/\(\s+/\(/;
                        }
                }
@@ -3443,18 +3749,27 @@ sub process {
                        if (ERROR("SPACING",
                                  "space prohibited before that close parenthesis ')'\n" . $herecurr) &&
                            $fix) {
-                               $fixed[$linenr - 1] =~
+                               print("fixlinenr: <$fixlinenr> fixed[fixlinenr]: <$fixed[$fixlinenr]>\n");
+                               $fixed[$fixlinenr] =~
                                    s/\s+\)/\)/;
                        }
                }
 
+# check unnecessary parentheses around addressof/dereference single $Lvals
+# ie: &(foo->bar) should be &foo->bar and *(foo->bar) should be *foo->bar
+
+               while ($line =~ /(?:[^&]&\s*|\*)\(\s*($Ident\s*(?:$Member\s*)+)\s*\)/g) {
+                       CHK("UNNECESSARY_PARENTHESES",
+                           "Unnecessary parentheses around $1\n" . $herecurr);
+                   }
+
 #goto labels aren't indented, allow a single space however
                if ($line=~/^.\s+[A-Za-z\d_]+:(?![0-9]+)/ and
                   !($line=~/^. [A-Za-z\d_]+:/) and !($line=~/^.\s+default:/)) {
                        if (WARN("INDENTED_LABEL",
                                 "labels should not be indented\n" . $herecurr) &&
                            $fix) {
-                               $fixed[$linenr - 1] =~
+                               $fixed[$fixlinenr] =~
                                    s/^(.)\s+/$1/;
                        }
                }
@@ -3516,7 +3831,7 @@ sub process {
                        if (ERROR("SPACING",
                                  "space required before the open parenthesis '('\n" . $herecurr) &&
                            $fix) {
-                               $fixed[$linenr - 1] =~
+                               $fixed[$fixlinenr] =~
                                    s/\b(if|while|for|switch)\(/$1 \(/;
                        }
                }
@@ -3606,7 +3921,7 @@ sub process {
 # if should not continue a brace
                if ($line =~ /}\s*if\b/) {
                        ERROR("TRAILING_STATEMENTS",
-                             "trailing statements should be on next line\n" .
+                             "trailing statements should be on next line (or did you mean 'else if'?)\n" .
                                $herecurr);
                }
 # case and default should not have general statements after them
@@ -3622,14 +3937,26 @@ sub process {
 
                # Check for }<nl>else {, these must be at the same
                # indent level to be relevant to each other.
-               if ($prevline=~/}\s*$/ and $line=~/^.\s*else\s*/ and
-                                               $previndent == $indent) {
-                       ERROR("ELSE_AFTER_BRACE",
-                             "else should follow close brace '}'\n" . $hereprev);
+               if ($prevline=~/}\s*$/ and $line=~/^.\s*else\s*/ &&
+                   $previndent == $indent) {
+                       if (ERROR("ELSE_AFTER_BRACE",
+                                 "else should follow close brace '}'\n" . $hereprev) &&
+                           $fix && $prevline =~ /^\+/ && $line =~ /^\+/) {
+                               fix_delete_line($fixlinenr - 1, $prevrawline);
+                               fix_delete_line($fixlinenr, $rawline);
+                               my $fixedline = $prevrawline;
+                               $fixedline =~ s/}\s*$//;
+                               if ($fixedline !~ /^\+\s*$/) {
+                                       fix_insert_line($fixlinenr, $fixedline);
+                               }
+                               $fixedline = $rawline;
+                               $fixedline =~ s/^(.\s*)else/$1} else/;
+                               fix_insert_line($fixlinenr, $fixedline);
+                       }
                }
 
-               if ($prevline=~/}\s*$/ and $line=~/^.\s*while\s*/ and
-                                               $previndent == $indent) {
+               if ($prevline=~/}\s*$/ and $line=~/^.\s*while\s*/ &&
+                   $previndent == $indent) {
                        my ($s, $c) = ctx_statement_block($linenr, $realcnt, 0);
 
                        # Find out what is on the end of the line after the
@@ -3638,8 +3965,18 @@ sub process {
                        $s =~ s/\n.*//g;
 
                        if ($s =~ /^\s*;/) {
-                               ERROR("WHILE_AFTER_BRACE",
-                                     "while should follow close brace '}'\n" . $hereprev);
+                               if (ERROR("WHILE_AFTER_BRACE",
+                                         "while should follow close brace '}'\n" . $hereprev) &&
+                                   $fix && $prevline =~ /^\+/ && $line =~ /^\+/) {
+                                       fix_delete_line($fixlinenr - 1, $prevrawline);
+                                       fix_delete_line($fixlinenr, $rawline);
+                                       my $fixedline = $prevrawline;
+                                       my $trailing = $rawline;
+                                       $trailing =~ s/^\+//;
+                                       $trailing = trim($trailing);
+                                       $fixedline =~ s/}\s*$/} $trailing/;
+                                       fix_insert_line($fixlinenr, $fixedline);
+                               }
                        }
                }
 
@@ -3653,7 +3990,7 @@ sub process {
                                         "Avoid gcc v4.3+ binary constant extension: <$var>\n" . $herecurr) &&
                                    $fix) {
                                        my $hexval = sprintf("0x%x", oct($var));
-                                       $fixed[$linenr - 1] =~
+                                       $fixed[$fixlinenr] =~
                                            s/\b$var\b/$hexval/;
                                }
                        }
@@ -3689,7 +4026,7 @@ sub process {
                        if (WARN("WHITESPACE_AFTER_LINE_CONTINUATION",
                                 "Whitespace after \\ makes next lines useless\n" . $herecurr) &&
                            $fix) {
-                               $fixed[$linenr - 1] =~ s/\s+$//;
+                               $fixed[$fixlinenr] =~ s/\s+$//;
                        }
                }
 
@@ -3762,7 +4099,7 @@ sub process {
                            $dstat !~ /^(?:$Ident|-?$Constant),$/ &&                    # 10, // foo(),
                            $dstat !~ /^(?:$Ident|-?$Constant);$/ &&                    # foo();
                            $dstat !~ /^[!~-]?(?:$Lval|$Constant)$/ &&          # 10 // foo() // !foo // ~foo // -foo // foo->bar // foo.bar->baz
-                           $dstat !~ /^'X'$/ &&                                        # character constants
+                           $dstat !~ /^'X'$/ && $dstat !~ /^'XX'$/ &&                  # character constants
                            $dstat !~ /$exceptions/ &&
                            $dstat !~ /^\.$Ident\s*=/ &&                                # .foo =
                            $dstat !~ /^(?:\#\s*$Ident|\#\s*$Constant)\s*$/ &&          # stringification #foo
@@ -4014,6 +4351,23 @@ sub process {
                        }
                }
 
+# check for unnecessary "Out of Memory" messages
+               if ($line =~ /^\+.*\b$logFunctions\s*\(/ &&
+                   $prevline =~ /^[ \+]\s*if\s*\(\s*(\!\s*|NULL\s*==\s*)?($Lval)(\s*==\s*NULL\s*)?\s*\)/ &&
+                   (defined $1 || defined $3) &&
+                   $linenr > 3) {
+                       my $testval = $2;
+                       my $testline = $lines[$linenr - 3];
+
+                       my ($s, $c) = ctx_statement_block($linenr - 3, $realcnt, 0);
+#                      print("line: <$line>\nprevline: <$prevline>\ns: <$s>\nc: <$c>\n\n\n");
+
+                       if ($c =~ /(?:^|\n)[ \+]\s*(?:$Type\s*)?\Q$testval\E\s*=\s*(?:\([^\)]*\)\s*)?\s*(?:devm_)?(?:[kv][czm]alloc(?:_node|_array)?\b|kstrdup|(?:dev_)?alloc_skb)/) {
+                               WARN("OOM_MESSAGE",
+                                    "Possible unnecessary 'out of memory' message\n" . $hereprev);
+                       }
+               }
+
 # check for bad placement of section $InitAttribute (e.g.: __initdata)
                if ($line =~ /(\b$InitAttribute\b)/) {
                        my $attr = $1;
@@ -4027,7 +4381,7 @@ sub process {
                                      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;
+                                       $fixed[$fixlinenr] =~ 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;
                                }
                        }
                }
@@ -4041,7 +4395,7 @@ sub process {
                        if (ERROR("INIT_ATTRIBUTE",
                                  "Use of const init definition must use ${attr_prefix}initconst\n" . $herecurr) &&
                            $fix) {
-                               $fixed[$linenr - 1] =~
+                               $fixed[$fixlinenr] =~
                                    s/$InitAttributeData/${attr_prefix}initconst/;
                        }
                }
@@ -4052,12 +4406,12 @@ sub process {
                        if (ERROR("INIT_ATTRIBUTE",
                                  "Use of $attr requires a separate use of const\n" . $herecurr) &&
                            $fix) {
-                               my $lead = $fixed[$linenr - 1] =~
+                               my $lead = $fixed[$fixlinenr] =~
                                    /(^\+\s*(?:static\s+))/;
                                $lead = rtrim($1);
                                $lead = "$lead " if ($lead !~ /^\+$/);
                                $lead = "${lead}const ";
-                               $fixed[$linenr - 1] =~ s/(^\+\s*(?:static\s+))/$lead/;
+                               $fixed[$fixlinenr] =~ s/(^\+\s*(?:static\s+))/$lead/;
                        }
                }
 
@@ -4070,7 +4424,7 @@ sub process {
                        if (WARN("CONSTANT_CONVERSION",
                                 "$constant_func should be $func\n" . $herecurr) &&
                            $fix) {
-                               $fixed[$linenr - 1] =~ s/\b$constant_func\b/$func/g;
+                               $fixed[$fixlinenr] =~ s/\b$constant_func\b/$func/g;
                        }
                }
 
@@ -4120,7 +4474,7 @@ sub process {
                        if (ERROR("SPACING",
                                  "exactly one space required after that #$1\n" . $herecurr) &&
                            $fix) {
-                               $fixed[$linenr - 1] =~
+                               $fixed[$fixlinenr] =~
                                    s/^(.\s*\#\s*(ifdef|ifndef|elif))\s{2,}/$1 /;
                        }
 
@@ -4168,7 +4522,7 @@ sub process {
                        if (WARN("INLINE",
                                 "plain inline is preferred over $1\n" . $herecurr) &&
                            $fix) {
-                               $fixed[$linenr - 1] =~ s/\b(__inline__|__inline)\b/inline/;
+                               $fixed[$fixlinenr] =~ s/\b(__inline__|__inline)\b/inline/;
 
                        }
                }
@@ -4193,7 +4547,7 @@ sub process {
                        if (WARN("PREFER_PRINTF",
                                 "__printf(string-index, first-to-check) is preferred over __attribute__((format(printf, string-index, first-to-check)))\n" . $herecurr) &&
                            $fix) {
-                               $fixed[$linenr - 1] =~ s/\b__attribute__\s*\(\s*\(\s*format\s*\(\s*printf\s*,\s*(.*)\)\s*\)\s*\)/"__printf(" . trim($1) . ")"/ex;
+                               $fixed[$fixlinenr] =~ s/\b__attribute__\s*\(\s*\(\s*format\s*\(\s*printf\s*,\s*(.*)\)\s*\)\s*\)/"__printf(" . trim($1) . ")"/ex;
 
                        }
                }
@@ -4204,7 +4558,7 @@ sub process {
                        if (WARN("PREFER_SCANF",
                                 "__scanf(string-index, first-to-check) is preferred over __attribute__((format(scanf, string-index, first-to-check)))\n" . $herecurr) &&
                            $fix) {
-                               $fixed[$linenr - 1] =~ s/\b__attribute__\s*\(\s*\(\s*format\s*\(\s*scanf\s*,\s*(.*)\)\s*\)\s*\)/"__scanf(" . trim($1) . ")"/ex;
+                               $fixed[$fixlinenr] =~ s/\b__attribute__\s*\(\s*\(\s*format\s*\(\s*scanf\s*,\s*(.*)\)\s*\)\s*\)/"__scanf(" . trim($1) . ")"/ex;
                        }
                }
 
@@ -4219,7 +4573,7 @@ sub process {
                        if (WARN("SIZEOF_PARENTHESIS",
                                 "sizeof $1 should be sizeof($1)\n" . $herecurr) &&
                            $fix) {
-                               $fixed[$linenr - 1] =~ s/\bsizeof\s+((?:\*\s*|)$Lval|$Type(?:\s+$Lval|))/"sizeof(" . trim($1) . ")"/ex;
+                               $fixed[$fixlinenr] =~ s/\bsizeof\s+((?:\*\s*|)$Lval|$Type(?:\s+$Lval|))/"sizeof(" . trim($1) . ")"/ex;
                        }
                }
 
@@ -4242,7 +4596,7 @@ sub process {
                                if (WARN("PREFER_SEQ_PUTS",
                                         "Prefer seq_puts to seq_printf\n" . $herecurr) &&
                                    $fix) {
-                                       $fixed[$linenr - 1] =~ s/\bseq_printf\b/seq_puts/;
+                                       $fixed[$fixlinenr] =~ s/\bseq_printf\b/seq_puts/;
                                }
                        }
                }
@@ -4271,7 +4625,7 @@ sub process {
                        if (WARN("PREFER_ETHER_ADDR_COPY",
                                 "Prefer ether_addr_copy() over memcpy() if the Ethernet addresses are __aligned(2)\n" . $herecurr) &&
                            $fix) {
-                               $fixed[$linenr - 1] =~ s/\bmemcpy\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\,\s*ETH_ALEN\s*\)/ether_addr_copy($2, $7)/;
+                               $fixed[$fixlinenr] =~ s/\bmemcpy\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\,\s*ETH_ALEN\s*\)/ether_addr_copy($2, $7)/;
                        }
                }
 
@@ -4359,7 +4713,7 @@ sub process {
                        if (CHK("AVOID_EXTERNS",
                                "extern prototypes should be avoided in .h files\n" . $herecurr) &&
                            $fix) {
-                               $fixed[$linenr - 1] =~ s/(.*)\bextern\b\s*(.*)/$1$2/;
+                               $fixed[$fixlinenr] =~ s/(.*)\bextern\b\s*(.*)/$1$2/;
                        }
                }
 
@@ -4419,23 +4773,24 @@ sub process {
 
 # check for k[mz]alloc with multiplies that could be kmalloc_array/kcalloc
                if ($^V && $^V ge 5.10.0 &&
-                   $line =~ /\b($Lval)\s*\=\s*(?:$balanced_parens)?\s*(k[mz]alloc)\s*\(\s*($FuncArg)\s*\*\s*($FuncArg)/) {
+                   $line =~ /\b($Lval)\s*\=\s*(?:$balanced_parens)?\s*(k[mz]alloc)\s*\(\s*($FuncArg)\s*\*\s*($FuncArg)\s*,/) {
                        my $oldfunc = $3;
                        my $a1 = $4;
                        my $a2 = $10;
                        my $newfunc = "kmalloc_array";
                        $newfunc = "kcalloc" if ($oldfunc eq "kzalloc");
-                       if ($a1 =~ /^sizeof\s*\S/ || $a2 =~ /^sizeof\s*\S/) {
+                       my $r1 = $a1;
+                       my $r2 = $a2;
+                       if ($a1 =~ /^sizeof\s*\S/) {
+                               $r1 = $a2;
+                               $r2 = $a1;
+                       }
+                       if ($r1 !~ /^sizeof\b/ && $r2 =~ /^sizeof\s*\S/ &&
+                           !($r1 =~ /^$Constant$/ || $r1 =~ /^[A-Z_][A-Z0-9_]*$/)) {
                                if (WARN("ALLOC_WITH_MULTIPLY",
                                         "Prefer $newfunc over $oldfunc with multiply\n" . $herecurr) &&
                                    $fix) {
-                                       my $r1 = $a1;
-                                       my $r2 = $a2;
-                                       if ($a1 =~ /^sizeof\s*\S/) {
-                                               $r1 = $a2;
-                                               $r2 = $a1;
-                                       }
-                                       $fixed[$linenr - 1] =~ s/\b($Lval)\s*\=\s*(?:$balanced_parens)?\s*(k[mz]alloc)\s*\(\s*($FuncArg)\s*\*\s*($FuncArg)/$1 . ' = ' . "$newfunc(" . trim($r1) . ', ' . trim($r2)/e;
+                                       $fixed[$fixlinenr] =~ s/\b($Lval)\s*\=\s*(?:$balanced_parens)?\s*(k[mz]alloc)\s*\(\s*($FuncArg)\s*\*\s*($FuncArg)/$1 . ' = ' . "$newfunc(" . trim($r1) . ', ' . trim($r2)/e;
 
                                }
                        }
@@ -4459,17 +4814,17 @@ sub process {
                        if (WARN("ONE_SEMICOLON",
                                 "Statements terminations use 1 semicolon\n" . $herecurr) &&
                            $fix) {
-                               $fixed[$linenr - 1] =~ s/(\s*;\s*){2,}$/;/g;
+                               $fixed[$fixlinenr] =~ s/(\s*;\s*){2,}$/;/g;
                        }
                }
 
-# check for case / default statements not preceeded by break/fallthrough/switch
+# check for case / default statements not preceded by break/fallthrough/switch
                if ($line =~ /^.\s*(?:case\s+(?:$Ident|$Constant)\s*|default):/) {
                        my $has_break = 0;
                        my $has_statement = 0;
                        my $count = 0;
                        my $prevline = $linenr;
-                       while ($prevline > 1 && $count < 3 && !$has_break) {
+                       while ($prevline > 1 && ($file || $count < 3) && !$has_break) {
                                $prevline--;
                                my $rline = $rawlines[$prevline - 1];
                                my $fline = $lines[$prevline - 1];
@@ -4507,7 +4862,7 @@ sub process {
                        if (WARN("USE_FUNC",
                                 "__func__ should be used instead of gcc specific __FUNCTION__\n"  . $herecurr) &&
                            $fix) {
-                               $fixed[$linenr - 1] =~ s/\b__FUNCTION__\b/__func__/g;
+                               $fixed[$fixlinenr] =~ s/\b__FUNCTION__\b/__func__/g;
                        }
                }
 
@@ -4750,12 +5105,16 @@ sub process {
        hash_show_words(\%use_type, "Used");
        hash_show_words(\%ignore_type, "Ignored");
 
-       if ($clean == 0 && $fix && "@rawlines" ne "@fixed") {
+       if ($clean == 0 && $fix &&
+           ("@rawlines" ne "@fixed" ||
+            $#fixed_inserted >= 0 || $#fixed_deleted >= 0)) {
                my $newfile = $filename;
                $newfile .= ".EXPERIMENTAL-checkpatch-fixes" if (!$fix_inplace);
                my $linecount = 0;
                my $f;
 
+               @fixed = fix_inserted_deleted_lines(\@fixed, \@fixed_inserted, \@fixed_deleted);
+
                open($f, '>', $newfile)
                    or die "$P: Can't open $newfile for write\n";
                foreach my $fixed_line (@fixed) {
@@ -4763,7 +5122,7 @@ sub process {
                        if ($file) {
                                if ($linecount > 3) {
                                        $fixed_line =~ s/^\+//;
-                                       print $f $fixed_line. "\n";
+                                       print $f $fixed_line . "\n";
                                }
                        } else {
                                print $f $fixed_line . "\n";