diff options
| author | Joe Perches <joe@perches.com> | 2013-09-11 17:24:05 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-09-11 18:58:49 -0400 |
| commit | 8716de383b82f16d920513138f1691e40ef5a9e3 (patch) | |
| tree | 2709bb597a4d722eb1777aea752aad62c843ba04 /scripts | |
| parent | 58cb3cf66cc6330910316abb1dc7a7aa78917a27 (diff) | |
checkpatch: add test for positional misuse of section specifiers like __initdata
As discussed recently on the arm [1] and lm-sensors [2] lists, it is
possible to use section markers on variables in a way which gcc doesn't
understand (or at least not the way the developer intended):
static struct __initdata samsung_pll_clock exynos4_plls[nr_plls] = {
does NOT put exynos4_plls in the .initdata section. The __initdata marker
can be virtually anywhere on the line, EXCEPT right after "struct". The
preferred location is before the "=" sign if there is one, or before the
trailing ";" otherwise.
[1] http://permalink.gmane.org/gmane.linux.ports.arm.kernel/258149
[2] http://lists.lm-sensors.org/pipermail/lm-sensors/2013-August/039836.html
So, update checkpatch to find these misuses and report an error when it's
immediately after struct or union, and a warning when it's otherwise not
immediately before the ; or =.
A similar patch was suggested by Andi Kleen
https://lkml.org/lkml/2013/8/5/648
Signed-off-by: Joe Perches <joe@perches.com>
Suggested-by: Jean Delvare <khali@linux-fr.org>
Tested-by: Guenter Roeck <linux@roeck-us.net>
Cc: Andi Kleen <andi@firstfloor.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'scripts')
| -rwxr-xr-x | scripts/checkpatch.pl | 47 |
1 files changed, 46 insertions, 1 deletions
diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index 9ba4fc44112a..47016c304c84 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl | |||
| @@ -242,6 +242,8 @@ our $Sparse = qr{ | |||
| 242 | __rcu | 242 | __rcu |
| 243 | }x; | 243 | }x; |
| 244 | 244 | ||
| 245 | our $InitAttribute = qr{__(?:mem|cpu|dev|net_|)(?:initdata|initconst|init\b)}; | ||
| 246 | |||
| 245 | # Notes to $Attribute: | 247 | # Notes to $Attribute: |
| 246 | # We need \b after 'init' otherwise 'initconst' will cause a false positive in a check | 248 | # We need \b after 'init' otherwise 'initconst' will cause a false positive in a check |
| 247 | our $Attribute = qr{ | 249 | our $Attribute = qr{ |
| @@ -262,7 +264,7 @@ our $Attribute = qr{ | |||
| 262 | __deprecated| | 264 | __deprecated| |
| 263 | __read_mostly| | 265 | __read_mostly| |
| 264 | __kprobes| | 266 | __kprobes| |
| 265 | __(?:mem|cpu|dev|)(?:initdata|initconst|init\b)| | 267 | $InitAttribute| |
| 266 | ____cacheline_aligned| | 268 | ____cacheline_aligned| |
| 267 | ____cacheline_aligned_in_smp| | 269 | ____cacheline_aligned_in_smp| |
| 268 | ____cacheline_internodealigned_in_smp| | 270 | ____cacheline_internodealigned_in_smp| |
| @@ -292,6 +294,7 @@ our $Operators = qr{ | |||
| 292 | }x; | 294 | }x; |
| 293 | 295 | ||
| 294 | our $NonptrType; | 296 | our $NonptrType; |
| 297 | our $NonptrTypeWithAttr; | ||
| 295 | our $Type; | 298 | our $Type; |
| 296 | our $Declare; | 299 | our $Declare; |
| 297 | 300 | ||
| @@ -354,6 +357,12 @@ our @typeList = ( | |||
| 354 | qr{${Ident}_handler}, | 357 | qr{${Ident}_handler}, |
| 355 | qr{${Ident}_handler_fn}, | 358 | qr{${Ident}_handler_fn}, |
| 356 | ); | 359 | ); |
| 360 | our @typeListWithAttr = ( | ||
| 361 | @typeList, | ||
| 362 | qr{struct\s+$InitAttribute\s+$Ident}, | ||
| 363 | qr{union\s+$InitAttribute\s+$Ident}, | ||
| 364 | ); | ||
| 365 | |||
| 357 | our @modifierList = ( | 366 | our @modifierList = ( |
| 358 | qr{fastcall}, | 367 | qr{fastcall}, |
| 359 | ); | 368 | ); |
| @@ -367,6 +376,7 @@ our $allowed_asm_includes = qr{(?x: | |||
| 367 | sub build_types { | 376 | sub build_types { |
| 368 | my $mods = "(?x: \n" . join("|\n ", @modifierList) . "\n)"; | 377 | my $mods = "(?x: \n" . join("|\n ", @modifierList) . "\n)"; |
| 369 | my $all = "(?x: \n" . join("|\n ", @typeList) . "\n)"; | 378 | my $all = "(?x: \n" . join("|\n ", @typeList) . "\n)"; |
| 379 | my $allWithAttr = "(?x: \n" . join("|\n ", @typeListWithAttr) . "\n)"; | ||
| 370 | $Modifier = qr{(?:$Attribute|$Sparse|$mods)}; | 380 | $Modifier = qr{(?:$Attribute|$Sparse|$mods)}; |
| 371 | $NonptrType = qr{ | 381 | $NonptrType = qr{ |
| 372 | (?:$Modifier\s+|const\s+)* | 382 | (?:$Modifier\s+|const\s+)* |
| @@ -377,6 +387,15 @@ sub build_types { | |||
| 377 | ) | 387 | ) |
| 378 | (?:\s+$Modifier|\s+const)* | 388 | (?:\s+$Modifier|\s+const)* |
| 379 | }x; | 389 | }x; |
| 390 | $NonptrTypeWithAttr = qr{ | ||
| 391 | (?:$Modifier\s+|const\s+)* | ||
| 392 | (?: | ||
| 393 | (?:typeof|__typeof__)\s*\([^\)]*\)| | ||
| 394 | (?:$typeTypedefs\b)| | ||
| 395 | (?:${allWithAttr}\b) | ||
| 396 | ) | ||
| 397 | (?:\s+$Modifier|\s+const)* | ||
| 398 | }x; | ||
| 380 | $Type = qr{ | 399 | $Type = qr{ |
| 381 | $NonptrType | 400 | $NonptrType |
| 382 | (?:(?:\s|\*|\[\])+\s*const|(?:\s|\*|\[\])+|(?:\s*\[\s*\])+)? | 401 | (?:(?:\s|\*|\[\])+\s*const|(?:\s|\*|\[\])+|(?:\s*\[\s*\])+)? |
| @@ -3706,6 +3725,32 @@ sub process { | |||
| 3706 | } | 3725 | } |
| 3707 | } | 3726 | } |
| 3708 | 3727 | ||
| 3728 | sub string_find_replace { | ||
| 3729 | my ($string, $find, $replace) = @_; | ||
| 3730 | |||
| 3731 | $string =~ s/$find/$replace/g; | ||
| 3732 | |||
| 3733 | return $string; | ||
| 3734 | } | ||
| 3735 | |||
| 3736 | # check for bad placement of section $InitAttribute (e.g.: __initdata) | ||
| 3737 | if ($line =~ /(\b$InitAttribute\b)/) { | ||
| 3738 | my $attr = $1; | ||
| 3739 | if ($line =~ /^\+\s*static\s+(?:const\s+)?(?:$attr\s+)?($NonptrTypeWithAttr)\s+(?:$attr\s+)?($Ident(?:\[[^]]*\])?)\s*[=;]/) { | ||
| 3740 | my $ptr = $1; | ||
| 3741 | my $var = $2; | ||
| 3742 | if ((($ptr =~ /\b(union|struct)\s+$attr\b/ && | ||
| 3743 | ERROR("MISPLACED_INIT", | ||
| 3744 | "$attr should be placed after $var\n" . $herecurr)) || | ||
| 3745 | ($ptr !~ /\b(union|struct)\s+$attr\b/ && | ||
| 3746 | WARN("MISPLACED_INIT", | ||
| 3747 | "$attr should be placed after $var\n" . $herecurr))) && | ||
| 3748 | $fix) { | ||
| 3749 | $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; | ||
| 3750 | } | ||
| 3751 | } | ||
| 3752 | } | ||
| 3753 | |||
| 3709 | # prefer usleep_range over udelay | 3754 | # prefer usleep_range over udelay |
| 3710 | if ($line =~ /\budelay\s*\(\s*(\d+)\s*\)/) { | 3755 | if ($line =~ /\budelay\s*\(\s*(\d+)\s*\)/) { |
| 3711 | # ignore udelay's < 10, however | 3756 | # ignore udelay's < 10, however |
