mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	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: Randy Dunlap <randy.dunlap@oracle.com> Signed-off-by: Sam Ravnborg <sam@ravnborg.org>
This commit is contained in:
		
							parent
							
								
									179efcb47d
								
							
						
					
					
						commit
						a1d94aa556
					
				
					 1 changed files with 66 additions and 1 deletions
				
			
		| 
						 | 
					@ -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 {
 | 
				
			||||||
#	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($$) {
 | 
				
			||||||
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($$) {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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($$$) {
 | 
				
			||||||
	    $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($$$) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	    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($$$) {
 | 
				
			||||||
	$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($$) {
 | 
				
			||||||
	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 {
 | 
				
			||||||
    @parameterlist = ();
 | 
					    @parameterlist = ();
 | 
				
			||||||
    %sections = ();
 | 
					    %sections = ();
 | 
				
			||||||
    @sectionlist = ();
 | 
					    @sectionlist = ();
 | 
				
			||||||
 | 
					    $sectcheck = "";
 | 
				
			||||||
 | 
					    $struct_actual = "";
 | 
				
			||||||
    $prototype = "";
 | 
					    $prototype = "";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    $state = 0;
 | 
					    $state = 0;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue