Commit df4bf98e authored by Niklas Söderlund's avatar Niklas Söderlund Committed by Jonathan Corbet

scripts: kernel-doc: Always increment warnings counter

Some warnings do not increment the warnings counter making the behavior
of running kernel-doc with -Werror unlogical as some warnings will be
generated but not treated as errors.

Fix this by creating a helper function that always incrementing the
warnings counter every time a warning is emitted. There is one location
in get_sphinx_version() where a warning is not touched as it concerns
the execution environment of the kernel-doc and not the documentation
being processed.

Incrementing the counter only have effect when running kernel-doc in
either verbose mode (-v or environment variable KBUILD_VERBOSE) or when
treating warnings as errors (-Werror or environment variable
KDOC_WERROR). In both cases the number of warnings printed is printed to
stderr and for the later the exit code of kernel-doc is non-zero if
warnings where encountered.

Simple test case to demo one of the warnings,

    $ cat test.c
    /**
     * foo() - Description
     */
    int bar();

    # Without this change
    $ ./scripts/kernel-doc -Werror -none test.c
    test.c:4: warning: expecting prototype for foo(). Prototype was for
    bar() instead

    # With this change
    $ ./scripts/kernel-doc -Werror -none test.c
    test.c:4: warning: expecting prototype for foo(). Prototype was for
    bar() instead
    1 warnings as Errors
Signed-off-by: default avatarNiklas Söderlund <niklas.soderlund@corigine.com>
Link: https://lore.kernel.org/r/20220613090510.3088294-1-niklas.soderlund@corigine.comSigned-off-by: default avatarJonathan Corbet <corbet@lwn.net>
parent b13baccc
...@@ -427,6 +427,13 @@ sub print_lineno { ...@@ -427,6 +427,13 @@ sub print_lineno {
print ".. LINENO " . $lineno . "\n"; print ".. LINENO " . $lineno . "\n";
} }
} }
sub emit_warning {
my $location = shift;
my $msg = shift;
print STDERR "$location: warning: $msg";
++$warnings;
}
## ##
# dumps section contents to arrays/hashes intended for that purpose. # dumps section contents to arrays/hashes intended for that purpose.
# #
...@@ -451,8 +458,7 @@ sub dump_section { ...@@ -451,8 +458,7 @@ sub dump_section {
if (defined($sections{$name}) && ($sections{$name} ne "")) { if (defined($sections{$name}) && ($sections{$name} ne "")) {
# Only warn on user specified duplicate section names. # Only warn on user specified duplicate section names.
if ($name ne $section_default) { if ($name ne $section_default) {
print STDERR "${file}:$.: warning: duplicate section name '$name'\n"; emit_warning("${file}:$.", "duplicate section name '$name'\n");
++$warnings;
} }
$sections{$name} .= $contents; $sections{$name} .= $contents;
} else { } else {
...@@ -1094,7 +1100,7 @@ sub dump_struct($$) { ...@@ -1094,7 +1100,7 @@ sub dump_struct($$) {
if ($members) { if ($members) {
if ($identifier ne $declaration_name) { if ($identifier ne $declaration_name) {
print STDERR "${file}:$.: warning: expecting prototype for $decl_type $identifier. Prototype was for $decl_type $declaration_name instead\n"; emit_warning("${file}:$.", "expecting prototype for $decl_type $identifier. Prototype was for $decl_type $declaration_name instead\n");
return; return;
} }
...@@ -1298,9 +1304,9 @@ sub dump_enum($$) { ...@@ -1298,9 +1304,9 @@ sub dump_enum($$) {
if ($members) { if ($members) {
if ($identifier ne $declaration_name) { if ($identifier ne $declaration_name) {
if ($identifier eq "") { if ($identifier eq "") {
print STDERR "${file}:$.: warning: wrong kernel-doc identifier on line:\n"; emit_warning("${file}:$.", "wrong kernel-doc identifier on line:\n");
} else { } else {
print STDERR "${file}:$.: warning: expecting prototype for enum $identifier. Prototype was for enum $declaration_name instead\n"; emit_warning("${file}:$.", "expecting prototype for enum $identifier. Prototype was for enum $declaration_name instead\n");
} }
return; return;
} }
...@@ -1316,7 +1322,7 @@ sub dump_enum($$) { ...@@ -1316,7 +1322,7 @@ sub dump_enum($$) {
if (!$parameterdescs{$arg}) { if (!$parameterdescs{$arg}) {
$parameterdescs{$arg} = $undescribed; $parameterdescs{$arg} = $undescribed;
if (show_warnings("enum", $declaration_name)) { if (show_warnings("enum", $declaration_name)) {
print STDERR "${file}:$.: warning: Enum value '$arg' not described in enum '$declaration_name'\n"; emit_warning("${file}:$.", "Enum value '$arg' not described in enum '$declaration_name'\n");
} }
} }
$_members{$arg} = 1; $_members{$arg} = 1;
...@@ -1325,7 +1331,7 @@ sub dump_enum($$) { ...@@ -1325,7 +1331,7 @@ sub dump_enum($$) {
while (my ($k, $v) = each %parameterdescs) { while (my ($k, $v) = each %parameterdescs) {
if (!exists($_members{$k})) { if (!exists($_members{$k})) {
if (show_warnings("enum", $declaration_name)) { if (show_warnings("enum", $declaration_name)) {
print STDERR "${file}:$.: warning: Excess enum value '$k' description in '$declaration_name'\n"; emit_warning("${file}:$.", "Excess enum value '$k' description in '$declaration_name'\n");
} }
} }
} }
...@@ -1367,7 +1373,7 @@ sub dump_typedef($$) { ...@@ -1367,7 +1373,7 @@ sub dump_typedef($$) {
$return_type =~ s/^\s+//; $return_type =~ s/^\s+//;
if ($identifier ne $declaration_name) { if ($identifier ne $declaration_name) {
print STDERR "${file}:$.: warning: expecting prototype for typedef $identifier. Prototype was for typedef $declaration_name instead\n"; emit_warning("${file}:$.", "expecting prototype for typedef $identifier. Prototype was for typedef $declaration_name instead\n");
return; return;
} }
...@@ -1398,7 +1404,7 @@ sub dump_typedef($$) { ...@@ -1398,7 +1404,7 @@ sub dump_typedef($$) {
$declaration_name = $1; $declaration_name = $1;
if ($identifier ne $declaration_name) { if ($identifier ne $declaration_name) {
print STDERR "${file}:$.: warning: expecting prototype for typedef $identifier. Prototype was for typedef $declaration_name instead\n"; emit_warning("${file}:$.", "expecting prototype for typedef $identifier. Prototype was for typedef $declaration_name instead\n");
return; return;
} }
...@@ -1554,9 +1560,7 @@ sub push_parameter($$$$$) { ...@@ -1554,9 +1560,7 @@ sub push_parameter($$$$$) {
$parameterdescs{$param} = $undescribed; $parameterdescs{$param} = $undescribed;
if (show_warnings($type, $declaration_name) && $param !~ /\./) { if (show_warnings($type, $declaration_name) && $param !~ /\./) {
print STDERR emit_warning("${file}:$.", "Function parameter or member '$param' not described in '$declaration_name'\n");
"${file}:$.: warning: Function parameter or member '$param' not described in '$declaration_name'\n";
++$warnings;
} }
} }
...@@ -1604,11 +1608,10 @@ sub check_sections($$$$$) { ...@@ -1604,11 +1608,10 @@ sub check_sections($$$$$) {
} }
if ($err) { if ($err) {
if ($decl_type eq "function") { if ($decl_type eq "function") {
print STDERR "${file}:$.: warning: " . emit_warning("${file}:$.",
"Excess function parameter " . "Excess function parameter " .
"'$sects[$sx]' " . "'$sects[$sx]' " .
"description in '$decl_name'\n"; "description in '$decl_name'\n");
++$warnings;
} }
} }
} }
...@@ -1629,10 +1632,9 @@ sub check_return_section { ...@@ -1629,10 +1632,9 @@ sub check_return_section {
if (!defined($sections{$section_return}) || if (!defined($sections{$section_return}) ||
$sections{$section_return} eq "") { $sections{$section_return} eq "") {
print STDERR "${file}:$.: warning: " . emit_warning("${file}:$.",
"No description found for return value of " . "No description found for return value of " .
"'$declaration_name'\n"; "'$declaration_name'\n");
++$warnings;
} }
} }
...@@ -1714,12 +1716,12 @@ sub dump_function($$) { ...@@ -1714,12 +1716,12 @@ sub dump_function($$) {
create_parameterlist($args, ',', $file, $declaration_name); create_parameterlist($args, ',', $file, $declaration_name);
} else { } else {
print STDERR "${file}:$.: warning: cannot understand function prototype: '$prototype'\n"; emit_warning("${file}:$.", "cannot understand function prototype: '$prototype'\n");
return; return;
} }
if ($identifier ne $declaration_name) { if ($identifier ne $declaration_name) {
print STDERR "${file}:$.: warning: expecting prototype for $identifier(). Prototype was for $declaration_name() instead\n"; emit_warning("${file}:$.", "expecting prototype for $identifier(). Prototype was for $declaration_name() instead\n");
return; return;
} }
...@@ -1801,8 +1803,8 @@ sub tracepoint_munge($) { ...@@ -1801,8 +1803,8 @@ sub tracepoint_munge($) {
$tracepointargs = $1; $tracepointargs = $1;
} }
if (($tracepointname eq 0) || ($tracepointargs eq 0)) { if (($tracepointname eq 0) || ($tracepointargs eq 0)) {
print STDERR "${file}:$.: warning: Unrecognized tracepoint format: \n". emit_warning("${file}:$.", "Unrecognized tracepoint format: \n".
"$prototype\n"; "$prototype\n");
} else { } else {
$prototype = "static inline void trace_$tracepointname($tracepointargs)"; $prototype = "static inline void trace_$tracepointname($tracepointargs)";
$identifier = "trace_$identifier"; $identifier = "trace_$identifier";
...@@ -2027,22 +2029,16 @@ sub process_name($$) { ...@@ -2027,22 +2029,16 @@ sub process_name($$) {
} }
if (!$is_kernel_comment) { if (!$is_kernel_comment) {
print STDERR "${file}:$.: warning: This comment starts with '/**', but isn't a kernel-doc comment. Refer Documentation/doc-guide/kernel-doc.rst\n"; emit_warning("${file}:$.", "This comment starts with '/**', but isn't a kernel-doc comment. Refer Documentation/doc-guide/kernel-doc.rst\n$_");
print STDERR $_;
++$warnings;
$state = STATE_NORMAL; $state = STATE_NORMAL;
} }
if (($declaration_purpose eq "") && $verbose) { if (($declaration_purpose eq "") && $verbose) {
print STDERR "${file}:$.: warning: missing initial short description on line:\n"; emit_warning("${file}:$.", "missing initial short description on line:\n$_");
print STDERR $_;
++$warnings;
} }
if ($identifier eq "" && $decl_type ne "enum") { if ($identifier eq "" && $decl_type ne "enum") {
print STDERR "${file}:$.: warning: wrong kernel-doc identifier on line:\n"; emit_warning("${file}:$.", "wrong kernel-doc identifier on line:\n$_");
print STDERR $_;
++$warnings;
$state = STATE_NORMAL; $state = STATE_NORMAL;
} }
...@@ -2050,9 +2046,7 @@ sub process_name($$) { ...@@ -2050,9 +2046,7 @@ sub process_name($$) {
print STDERR "${file}:$.: info: Scanning doc for $decl_type $identifier\n"; print STDERR "${file}:$.: info: Scanning doc for $decl_type $identifier\n";
} }
} else { } else {
print STDERR "${file}:$.: warning: Cannot understand $_ on line $.", emit_warning("${file}:$.", "Cannot understand $_ on line $. - I thought it was a doc line\n");
" - I thought it was a doc line\n";
++$warnings;
$state = STATE_NORMAL; $state = STATE_NORMAL;
} }
} }
...@@ -2071,8 +2065,7 @@ sub process_body($$) { ...@@ -2071,8 +2065,7 @@ sub process_body($$) {
$section =~ s/\.\.\.$//; $section =~ s/\.\.\.$//;
if ($verbose) { if ($verbose) {
print STDERR "${file}:$.: warning: Variable macro arguments should be documented without dots\n"; emit_warning("${file}:$.", "Variable macro arguments should be documented without dots\n");
++$warnings;
} }
} }
...@@ -2101,8 +2094,7 @@ sub process_body($$) { ...@@ -2101,8 +2094,7 @@ sub process_body($$) {
if (($contents ne "") && ($contents ne "\n")) { if (($contents ne "") && ($contents ne "\n")) {
if (!$in_doc_sect && $verbose) { if (!$in_doc_sect && $verbose) {
print STDERR "${file}:$.: warning: contents before sections\n"; emit_warning("${file}:$.", "contents before sections\n");
++$warnings;
} }
dump_section($file, $section, $contents); dump_section($file, $section, $contents);
$section = $section_default; $section = $section_default;
...@@ -2128,8 +2120,7 @@ sub process_body($$) { ...@@ -2128,8 +2120,7 @@ sub process_body($$) {
} }
# look for doc_com + <text> + doc_end: # look for doc_com + <text> + doc_end:
if ($_ =~ m'\s*\*\s*[a-zA-Z_0-9:\.]+\*/') { if ($_ =~ m'\s*\*\s*[a-zA-Z_0-9:\.]+\*/') {
print STDERR "${file}:$.: warning: suspicious ending line: $_"; emit_warning("${file}:$.", "suspicious ending line: $_");
++$warnings;
} }
$prototype = ""; $prototype = "";
...@@ -2173,8 +2164,7 @@ sub process_body($$) { ...@@ -2173,8 +2164,7 @@ sub process_body($$) {
} }
} else { } else {
# i dont know - bad line? ignore. # i dont know - bad line? ignore.
print STDERR "${file}:$.: warning: bad line: $_"; emit_warning("${file}:$.", "bad line: $_");
++$warnings;
} }
} }
...@@ -2268,9 +2258,7 @@ sub process_inline($$) { ...@@ -2268,9 +2258,7 @@ sub process_inline($$) {
} }
} elsif ($inline_doc_state == STATE_INLINE_NAME) { } elsif ($inline_doc_state == STATE_INLINE_NAME) {
$inline_doc_state = STATE_INLINE_ERROR; $inline_doc_state = STATE_INLINE_ERROR;
print STDERR "${file}:$.: warning: "; emit_warning("${file}:$.", "Incorrect use of kernel-doc format: $_");
print STDERR "Incorrect use of kernel-doc format: $_";
++$warnings;
} }
} }
} }
...@@ -2319,11 +2307,11 @@ sub process_file($) { ...@@ -2319,11 +2307,11 @@ sub process_file($) {
if ($initial_section_counter == $section_counter && $ if ($initial_section_counter == $section_counter && $
output_mode ne "none") { output_mode ne "none") {
if ($output_selection == OUTPUT_INCLUDE) { if ($output_selection == OUTPUT_INCLUDE) {
print STDERR "${file}:1: warning: '$_' not found\n" emit_warning("${file}:1", "'$_' not found\n")
for keys %function_table; for keys %function_table;
} }
else { else {
print STDERR "${file}:1: warning: no structured comments found\n"; emit_warning("${file}:1", "no structured comments found\n");
} }
} }
close IN_FILE; close IN_FILE;
......
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