Commit 8716de38 authored by Joe Perches's avatar Joe Perches Committed by Linus Torvalds

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/648Signed-off-by: default avatarJoe Perches <joe@perches.com>
Suggested-by: default avatarJean Delvare <khali@linux-fr.org>
Tested-by: default avatarGuenter Roeck <linux@roeck-us.net>
Cc: Andi Kleen <andi@firstfloor.org>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 58cb3cf6
...@@ -242,6 +242,8 @@ our $Sparse = qr{ ...@@ -242,6 +242,8 @@ our $Sparse = qr{
__rcu __rcu
}x; }x;
our $InitAttribute = qr{__(?:mem|cpu|dev|net_|)(?:initdata|initconst|init\b)};
# Notes to $Attribute: # Notes to $Attribute:
# We need \b after 'init' otherwise 'initconst' will cause a false positive in a check # We need \b after 'init' otherwise 'initconst' will cause a false positive in a check
our $Attribute = qr{ our $Attribute = qr{
...@@ -262,7 +264,7 @@ our $Attribute = qr{ ...@@ -262,7 +264,7 @@ our $Attribute = qr{
__deprecated| __deprecated|
__read_mostly| __read_mostly|
__kprobes| __kprobes|
__(?:mem|cpu|dev|)(?:initdata|initconst|init\b)| $InitAttribute|
____cacheline_aligned| ____cacheline_aligned|
____cacheline_aligned_in_smp| ____cacheline_aligned_in_smp|
____cacheline_internodealigned_in_smp| ____cacheline_internodealigned_in_smp|
...@@ -292,6 +294,7 @@ our $Operators = qr{ ...@@ -292,6 +294,7 @@ our $Operators = qr{
}x; }x;
our $NonptrType; our $NonptrType;
our $NonptrTypeWithAttr;
our $Type; our $Type;
our $Declare; our $Declare;
...@@ -354,6 +357,12 @@ our @typeList = ( ...@@ -354,6 +357,12 @@ our @typeList = (
qr{${Ident}_handler}, qr{${Ident}_handler},
qr{${Ident}_handler_fn}, qr{${Ident}_handler_fn},
); );
our @typeListWithAttr = (
@typeList,
qr{struct\s+$InitAttribute\s+$Ident},
qr{union\s+$InitAttribute\s+$Ident},
);
our @modifierList = ( our @modifierList = (
qr{fastcall}, qr{fastcall},
); );
...@@ -367,6 +376,7 @@ our $allowed_asm_includes = qr{(?x: ...@@ -367,6 +376,7 @@ our $allowed_asm_includes = qr{(?x:
sub build_types { sub build_types {
my $mods = "(?x: \n" . join("|\n ", @modifierList) . "\n)"; my $mods = "(?x: \n" . join("|\n ", @modifierList) . "\n)";
my $all = "(?x: \n" . join("|\n ", @typeList) . "\n)"; my $all = "(?x: \n" . join("|\n ", @typeList) . "\n)";
my $allWithAttr = "(?x: \n" . join("|\n ", @typeListWithAttr) . "\n)";
$Modifier = qr{(?:$Attribute|$Sparse|$mods)}; $Modifier = qr{(?:$Attribute|$Sparse|$mods)};
$NonptrType = qr{ $NonptrType = qr{
(?:$Modifier\s+|const\s+)* (?:$Modifier\s+|const\s+)*
...@@ -377,6 +387,15 @@ sub build_types { ...@@ -377,6 +387,15 @@ sub build_types {
) )
(?:\s+$Modifier|\s+const)* (?:\s+$Modifier|\s+const)*
}x; }x;
$NonptrTypeWithAttr = qr{
(?:$Modifier\s+|const\s+)*
(?:
(?:typeof|__typeof__)\s*\([^\)]*\)|
(?:$typeTypedefs\b)|
(?:${allWithAttr}\b)
)
(?:\s+$Modifier|\s+const)*
}x;
$Type = qr{ $Type = qr{
$NonptrType $NonptrType
(?:(?:\s|\*|\[\])+\s*const|(?:\s|\*|\[\])+|(?:\s*\[\s*\])+)? (?:(?:\s|\*|\[\])+\s*const|(?:\s|\*|\[\])+|(?:\s*\[\s*\])+)?
...@@ -3706,6 +3725,32 @@ sub process { ...@@ -3706,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 # prefer usleep_range over udelay
if ($line =~ /\budelay\s*\(\s*(\d+)\s*\)/) { if ($line =~ /\budelay\s*\(\s*(\d+)\s*\)/) {
# ignore udelay's < 10, however # ignore udelay's < 10, however
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment