Commit a1d94aa5 authored by Randy Dunlap's avatar Randy Dunlap Committed by Sam Ravnborg

kernel-doc: check for extra kernel-doc notations

Add functionality to check for function parameters or structure (or
union/typedef/enum) field members that are described in kernel-doc but
are not part of the expected (declared) parameters or structure.
These generate warnings that are called "Excess" descriptions.
Signed-off-by: default avatarRandy Dunlap <randy.dunlap@oracle.com>
Signed-off-by: default avatarSam Ravnborg <sam@ravnborg.org>
parent 179efcb4
...@@ -289,6 +289,8 @@ my %parameterdescs; ...@@ -289,6 +289,8 @@ my %parameterdescs;
my @parameterlist; my @parameterlist;
my %sections; my %sections;
my @sectionlist; my @sectionlist;
my $sectcheck;
my $struct_actual;
my $contents = ""; my $contents = "";
my $section_default = "Description"; # default section my $section_default = "Description"; # default section
...@@ -378,10 +380,12 @@ sub dump_section { ...@@ -378,10 +380,12 @@ sub dump_section {
# print STDERR "parameter def '$1' = '$contents'\n"; # print STDERR "parameter def '$1' = '$contents'\n";
$name = $1; $name = $1;
$parameterdescs{$name} = $contents; $parameterdescs{$name} = $contents;
$sectcheck = $sectcheck . $name . " ";
} elsif ($name eq "@\.\.\.") { } elsif ($name eq "@\.\.\.") {
# print STDERR "parameter def '...' = '$contents'\n"; # print STDERR "parameter def '...' = '$contents'\n";
$name = "..."; $name = "...";
$parameterdescs{$name} = $contents; $parameterdescs{$name} = $contents;
$sectcheck = $sectcheck . $name . " ";
} else { } else {
# print STDERR "other section '$name' = '$contents'\n"; # print STDERR "other section '$name' = '$contents'\n";
if (defined($sections{$name}) && ($sections{$name} ne "")) { if (defined($sections{$name}) && ($sections{$name} ne "")) {
...@@ -1405,21 +1409,25 @@ sub dump_union($$) { ...@@ -1405,21 +1409,25 @@ sub dump_union($$) {
sub dump_struct($$) { sub dump_struct($$) {
my $x = shift; my $x = shift;
my $file = shift; my $file = shift;
my $nested;
if ($x =~/(struct|union)\s+(\w+)\s*{(.*)}/) { if ($x =~/(struct|union)\s+(\w+)\s*{(.*)}/) {
$declaration_name = $2; $declaration_name = $2;
my $members = $3; my $members = $3;
# ignore embedded structs or unions # ignore embedded structs or unions
$members =~ s/{.*}//g; $members =~ s/({.*})//g;
$nested = $1;
# ignore members marked private: # ignore members marked private:
$members =~ s/\/\*.*?private:.*?public:.*?\*\///gos; $members =~ s/\/\*.*?private:.*?public:.*?\*\///gos;
$members =~ s/\/\*.*?private:.*//gos; $members =~ s/\/\*.*?private:.*//gos;
# strip comments: # strip comments:
$members =~ s/\/\*.*?\*\///gos; $members =~ s/\/\*.*?\*\///gos;
$nested =~ s/\/\*.*?\*\///gos;
create_parameterlist($members, ';', $file); create_parameterlist($members, ';', $file);
check_sections($file, $declaration_name, "struct", $sectcheck, $struct_actual, $nested);
output_declaration($declaration_name, output_declaration($declaration_name,
'struct', 'struct',
...@@ -1505,6 +1513,14 @@ sub dump_typedef($$) { ...@@ -1505,6 +1513,14 @@ sub dump_typedef($$) {
} }
} }
sub save_struct_actual($) {
my $actual = shift;
# strip all spaces from the actual param so that it looks like one string item
$actual =~ s/\s*//g;
$struct_actual = $struct_actual . $actual . " ";
}
sub create_parameterlist($$$) { sub create_parameterlist($$$) {
my $args = shift; my $args = shift;
my $splitter = shift; my $splitter = shift;
...@@ -1537,6 +1553,7 @@ sub create_parameterlist($$$) { ...@@ -1537,6 +1553,7 @@ sub create_parameterlist($$$) {
$param = $1; $param = $1;
$type = $arg; $type = $arg;
$type =~ s/([^\(]+\(\*?)\s*$param/$1/; $type =~ s/([^\(]+\(\*?)\s*$param/$1/;
save_struct_actual($param);
push_parameter($param, $type, $file); push_parameter($param, $type, $file);
} elsif ($arg) { } elsif ($arg) {
$arg =~ s/\s*:\s*/:/g; $arg =~ s/\s*:\s*/:/g;
...@@ -1561,14 +1578,17 @@ sub create_parameterlist($$$) { ...@@ -1561,14 +1578,17 @@ sub create_parameterlist($$$) {
foreach $param (@args) { foreach $param (@args) {
if ($param =~ m/^(\*+)\s*(.*)/) { if ($param =~ m/^(\*+)\s*(.*)/) {
save_struct_actual($2);
push_parameter($2, "$type $1", $file); push_parameter($2, "$type $1", $file);
} }
elsif ($param =~ m/(.*?):(\d+)/) { elsif ($param =~ m/(.*?):(\d+)/) {
if ($type ne "") { # skip unnamed bit-fields if ($type ne "") { # skip unnamed bit-fields
save_struct_actual($1);
push_parameter($1, "$type:$2", $file) push_parameter($1, "$type:$2", $file)
} }
} }
else { else {
save_struct_actual($param);
push_parameter($param, $type, $file); push_parameter($param, $type, $file);
} }
} }
...@@ -1634,6 +1654,46 @@ sub push_parameter($$$) { ...@@ -1634,6 +1654,46 @@ sub push_parameter($$$) {
$parametertypes{$param} = $type; $parametertypes{$param} = $type;
} }
sub check_sections($$$$$$) {
my ($file, $decl_name, $decl_type, $sectcheck, $prmscheck, $nested) = @_;
my @sects = split ' ', $sectcheck;
my @prms = split ' ', $prmscheck;
my $err;
my ($px, $sx);
my $prm_clean; # strip trailing "[array size]" and/or beginning "*"
foreach $sx (0 .. $#sects) {
$err = 1;
foreach $px (0 .. $#prms) {
$prm_clean = $prms[$px];
$prm_clean =~ s/\[.*\]//;
$prm_clean =~ s/__attribute__\s*\(\([a-z,_\*\s\(\)]*\)\)//;
##$prm_clean =~ s/^\**//;
if ($prm_clean eq $sects[$sx]) {
$err = 0;
last;
}
}
if ($err) {
if ($decl_type eq "function") {
print STDERR "Warning(${file}:$.): " .
"Excess function parameter " .
"'$sects[$sx]' " .
"description in '$decl_name'\n";
++$warnings;
} else {
if ($nested !~ m/\Q$sects[$sx]\E/) {
print STDERR "Warning(${file}:$.): " .
"Excess struct/union/enum/typedef member " .
"'$sects[$sx]' " .
"description in '$decl_name'\n";
++$warnings;
}
}
}
}
}
## ##
# takes a function prototype and the name of the current file being # takes a function prototype and the name of the current file being
# processed and spits out all the details stored in the global # processed and spits out all the details stored in the global
...@@ -1699,6 +1759,9 @@ sub dump_function($$) { ...@@ -1699,6 +1759,9 @@ sub dump_function($$) {
return; return;
} }
my $prms = join " ", @parameterlist;
check_sections($file, $declaration_name, "function", $sectcheck, $prms, "");
output_declaration($declaration_name, output_declaration($declaration_name,
'function', 'function',
{'function' => $declaration_name, {'function' => $declaration_name,
...@@ -1757,6 +1820,8 @@ sub reset_state { ...@@ -1757,6 +1820,8 @@ sub reset_state {
@parameterlist = (); @parameterlist = ();
%sections = (); %sections = ();
@sectionlist = (); @sectionlist = ();
$sectcheck = "";
$struct_actual = "";
$prototype = ""; $prototype = "";
$state = 0; $state = 0;
......
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