Skip to content

Commit f74bd19

Browse files
Andy Whitcrofttorvalds
authored andcommitted
checkpatch: correctly track the end of preprocessor commands in context
When looking for a statement we currently run on through preprocessor commands. This means that a header file with just definitions is parsed over and over again combining all of the lines from the current line to the end of file leading to severe performance issues. Fix up context accumulation to track preprocessor commands and stop when reaching the end of them. At the same time vastly simplify the #define handling. Signed-off-by: Andy Whitcroft <apw@canonical.com> Cc: Joe Perches <joe@perches.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
1 parent 5f14d3b commit f74bd19

File tree

1 file changed

+39
-51
lines changed

1 file changed

+39
-51
lines changed

scripts/checkpatch.pl

Lines changed: 39 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -676,6 +676,10 @@ sub ctx_statement_block {
676676
if ($off >= $len) {
677677
last;
678678
}
679+
if ($level == 0 && substr($blk, $off) =~ /^.\s*#\s*define/) {
680+
$level++;
681+
$type = '#';
682+
}
679683
}
680684
$p = $c;
681685
$c = substr($blk, $off, 1);
@@ -738,6 +742,13 @@ sub ctx_statement_block {
738742
last;
739743
}
740744
}
745+
# Preprocessor commands end at the newline unless escaped.
746+
if ($type eq '#' && $c eq "\n" && $p ne "\\") {
747+
$level--;
748+
$type = '';
749+
$off++;
750+
last;
751+
}
741752
$off++;
742753
}
743754
# We are truly at the end, so shuffle to the next line.
@@ -1801,6 +1812,8 @@ sub process {
18011812
$stat =~ s/\n./\n /g;
18021813
$cond =~ s/\n./\n /g;
18031814

1815+
#print "stat<$stat>\n";
1816+
18041817
# Find the real next line.
18051818
$realline_next = $line_nr_next;
18061819
if (defined $realline_next &&
@@ -2781,47 +2794,13 @@ sub process {
27812794
my $cnt = $realcnt;
27822795
my ($off, $dstat, $dcond, $rest);
27832796
my $ctx = '';
2784-
2785-
my $args = defined($1);
2786-
2787-
# Find the end of the macro and limit our statement
2788-
# search to that.
2789-
while ($cnt > 0 && defined $lines[$ln - 1] &&
2790-
$lines[$ln - 1] =~ /^(?:-|..*\\$)/)
2791-
{
2792-
$ctx .= $rawlines[$ln - 1] . "\n";
2793-
$cnt-- if ($lines[$ln - 1] !~ /^-/);
2794-
$ln++;
2795-
}
2796-
$ctx .= $rawlines[$ln - 1];
2797-
27982797
($dstat, $dcond, $ln, $cnt, $off) =
2799-
ctx_statement_block($linenr, $ln - $linenr + 1, 0);
2798+
ctx_statement_block($linenr, $realcnt, 0);
2799+
$ctx = $dstat;
28002800
#print "dstat<$dstat> dcond<$dcond> cnt<$cnt> off<$off>\n";
28012801
#print "LINE<$lines[$ln-1]> len<" . length($lines[$ln-1]) . "\n";
28022802

2803-
# Extract the remainder of the define (if any) and
2804-
# rip off surrounding spaces, and trailing \'s.
2805-
$rest = '';
2806-
while ($off != 0 || ($cnt > 0 && $rest =~ /\\\s*$/)) {
2807-
#print "ADDING cnt<$cnt> $off <" . substr($lines[$ln - 1], $off) . "> rest<$rest>\n";
2808-
if ($off != 0 || $lines[$ln - 1] !~ /^-/) {
2809-
$rest .= substr($lines[$ln - 1], $off) . "\n";
2810-
$cnt--;
2811-
}
2812-
$ln++;
2813-
$off = 0;
2814-
}
2815-
$rest =~ s/\\\n.//g;
2816-
$rest =~ s/^\s*//s;
2817-
$rest =~ s/\s*$//s;
2818-
2819-
# Clean up the original statement.
2820-
if ($args) {
2821-
substr($dstat, 0, length($dcond), '');
2822-
} else {
2823-
$dstat =~ s/^.\s*\#\s*define\s+$Ident\s*//;
2824-
}
2803+
$dstat =~ s/^.\s*\#\s*define\s+$Ident(?:\([^\)]*\))?\s*//;
28252804
$dstat =~ s/$;//g;
28262805
$dstat =~ s/\\\n.//g;
28272806
$dstat =~ s/^\s*//s;
@@ -2847,23 +2826,32 @@ sub process {
28472826
^\"|\"$
28482827
}x;
28492828
#print "REST<$rest> dstat<$dstat> ctx<$ctx>\n";
2850-
if ($rest ne '' && $rest ne ',') {
2851-
if ($rest !~ /while\s*\(/ &&
2852-
$dstat !~ /$exceptions/)
2853-
{
2854-
ERROR("MULTISTATEMENT_MACRO_USE_DO_WHILE",
2855-
"Macros with multiple statements should be enclosed in a do - while loop\n" . "$here\n$ctx\n");
2829+
if ($dstat ne '' &&
2830+
$dstat !~ /^(?:$Ident|-?$Constant),$/ && # 10, // foo(),
2831+
$dstat !~ /^(?:$Ident|-?$Constant);$/ && # foo();
2832+
$dstat !~ /^(?:$Ident|-?$Constant)$/ && # 10 // foo()
2833+
$dstat !~ /$exceptions/ &&
2834+
$dstat !~ /^\.$Ident\s*=/ && # .foo =
2835+
$dstat !~ /^do\s*$Constant\s*while\s*$Constant;$/ && # do {...} while (...);
2836+
$dstat !~ /^for\s*$Constant$/ && # for (...)
2837+
$dstat !~ /^for\s*$Constant\s+(?:$Ident|-?$Constant)$/ && # for (...) bar()
2838+
$dstat !~ /^do\s*{/ && # do {...
2839+
$dstat !~ /^\({/) # ({...
2840+
{
2841+
$ctx =~ s/\n*$//;
2842+
my $herectx = $here . "\n";
2843+
my $cnt = statement_rawlines($ctx);
2844+
2845+
for (my $n = 0; $n < $cnt; $n++) {
2846+
$herectx .= raw_line($linenr, $n) . "\n";
28562847
}
28572848

2858-
} elsif ($ctx !~ /;/) {
2859-
if ($dstat ne '' &&
2860-
$dstat !~ /^(?:$Ident|-?$Constant)$/ &&
2861-
$dstat !~ /$exceptions/ &&
2862-
$dstat !~ /^\.$Ident\s*=/ &&
2863-
$dstat =~ /$Operators/)
2864-
{
2849+
if ($dstat =~ /;/) {
2850+
ERROR("MULTISTATEMENT_MACRO_USE_DO_WHILE",
2851+
"Macros with multiple statements should be enclosed in a do - while loop\n" . "$herectx");
2852+
} else {
28652853
ERROR("COMPLEX_MACRO",
2866-
"Macros with complex values should be enclosed in parenthesis\n" . "$here\n$ctx\n");
2854+
"Macros with complex values should be enclosed in parenthesis\n" . "$herectx");
28672855
}
28682856
}
28692857
}

0 commit comments

Comments
 (0)