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
Unified · Split
| @@ -427,6 +427,13 @@ sub print_lineno { · 426 unmodified lines | |||
| 427 | print ".. LINENO " . $lineno . "\n"; | 427 | print ".. LINENO " . $lineno . "\n"; |
| 428 | } | 428 | } |
| 429 | } | 429 | } |
| 430 | |||
| 431 | sub emit_warning { | ||
| 432 | my $location = shift; | ||
| 433 | my $msg = shift; | ||
| 434 | print STDERR "$location: warning: $msg"; | ||
| 435 | ++$warnings; | ||
| 436 | } | ||
| 430 | ## | 437 | ## |
| 431 | # dumps section contents to arrays/hashes intended for that purpose. | 438 | # dumps section contents to arrays/hashes intended for that purpose. |
| 432 | # | 439 | # |
| @@ -451,8 +458,7 @@ sub dump_section { · 18 unmodified lines | |||
| 451 | if (defined($sections{$name}) && ($sections{$name} ne "")) { | 458 | if (defined($sections{$name}) && ($sections{$name} ne "")) { |
| 452 | # Only warn on user specified duplicate section names. | 459 | # Only warn on user specified duplicate section names. |
| 453 | if ($name ne $section_default) { | 460 | if ($name ne $section_default) { |
| 454 | print STDERR "${file}:$.: warning: duplicate section name '$name'\n"; | 461 | emit_warning("${file}:$.", "duplicate section name '$name'\n"); |
| 455 | ++$warnings; | ||
| 456 | } | 462 | } |
| 457 | $sections{$name} .= $contents; | 463 | $sections{$name} .= $contents; |
| 458 | } else { | 464 | } else { |
| @@ -1094,7 +1100,7 @@ sub dump_struct($$) { · 635 unmodified lines | |||
| 1094 | 1100 | ||
| 1095 | if ($members) { | 1101 | if ($members) { |
| 1096 | if ($identifier ne $declaration_name) { | 1102 | if ($identifier ne $declaration_name) { |
| 1097 | print STDERR "${file}:$.: warning: expecting prototype for $decl_type $identifier. Prototype was for $decl_type $declaration_name instead\n"; | 1103 | emit_warning("${file}:$.", "expecting prototype for $decl_type $identifier. Prototype was for $decl_type $declaration_name instead\n"); |
| 1098 | return; | 1104 | return; |
| 1099 | } | 1105 | } |
| 1100 | 1106 | ||
| @@ -1298,9 +1304,9 @@ sub dump_enum($$) { · 197 unmodified lines | |||
| 1298 | if ($members) { | 1304 | if ($members) { |
| 1299 | if ($identifier ne $declaration_name) { | 1305 | if ($identifier ne $declaration_name) { |
| 1300 | if ($identifier eq "") { | 1306 | if ($identifier eq "") { |
| 1301 | print STDERR "${file}:$.: warning: wrong kernel-doc identifier on line:\n"; | 1307 | emit_warning("${file}:$.", "wrong kernel-doc identifier on line:\n"); |
| 1302 | } else { | 1308 | } else { |
| 1303 | print STDERR "${file}:$.: warning: expecting prototype for enum $identifier. Prototype was for enum $declaration_name instead\n"; | 1309 | emit_warning("${file}:$.", "expecting prototype for enum $identifier. Prototype was for enum $declaration_name instead\n"); |
| 1304 | } | 1310 | } |
| 1305 | return; | 1311 | return; |
| 1306 | } | 1312 | } |
| @@ -1316,7 +1322,7 @@ sub dump_enum($$) { · 9 unmodified lines | |||
| 1316 | if (!$parameterdescs{$arg}) { | 1322 | if (!$parameterdescs{$arg}) { |
| 1317 | $parameterdescs{$arg} = $undescribed; | 1323 | $parameterdescs{$arg} = $undescribed; |
| 1318 | if (show_warnings("enum", $declaration_name)) { | 1324 | if (show_warnings("enum", $declaration_name)) { |
| 1319 | print STDERR "${file}:$.: warning: Enum value '$arg' not described in enum '$declaration_name'\n"; | 1325 | emit_warning("${file}:$.", "Enum value '$arg' not described in enum '$declaration_name'\n"); |
| 1320 | } | 1326 | } |
| 1321 | } | 1327 | } |
| 1322 | $_members{$arg} = 1; | 1328 | $_members{$arg} = 1; |
| @@ -1325,7 +1331,7 @@ sub dump_enum($$) { · 2 unmodified lines | |||
| 1325 | while (my ($k, $v) = each %parameterdescs) { | 1331 | while (my ($k, $v) = each %parameterdescs) { |
| 1326 | if (!exists($_members{$k})) { | 1332 | if (!exists($_members{$k})) { |
| 1327 | if (show_warnings("enum", $declaration_name)) { | 1333 | if (show_warnings("enum", $declaration_name)) { |
| 1328 | print STDERR "${file}:$.: warning: Excess enum value '$k' description in '$declaration_name'\n"; | 1334 | emit_warning("${file}:$.", "Excess enum value '$k' description in '$declaration_name'\n"); |
| 1329 | } | 1335 | } |
| 1330 | } | 1336 | } |
| 1331 | } | 1337 | } |
| @@ -1367,7 +1373,7 @@ sub dump_typedef($$) { · 35 unmodified lines | |||
| 1367 | $return_type =~ s/^\s+//; | 1373 | $return_type =~ s/^\s+//; |
| 1368 | 1374 | ||
| 1369 | if ($identifier ne $declaration_name) { | 1375 | if ($identifier ne $declaration_name) { |
| 1370 | print STDERR "${file}:$.: warning: expecting prototype for typedef $identifier. Prototype was for typedef $declaration_name instead\n"; | 1376 | emit_warning("${file}:$.", "expecting prototype for typedef $identifier. Prototype was for typedef $declaration_name instead\n"); |
| 1371 | return; | 1377 | return; |
| 1372 | } | 1378 | } |
| 1373 | 1379 | ||
| @@ -1398,7 +1404,7 @@ sub dump_typedef($$) { · 24 unmodified lines | |||
| 1398 | $declaration_name = $1; | 1404 | $declaration_name = $1; |
| 1399 | 1405 | ||
| 1400 | if ($identifier ne $declaration_name) { | 1406 | if ($identifier ne $declaration_name) { |
| 1401 | print STDERR "${file}:$.: warning: expecting prototype for typedef $identifier. Prototype was for typedef $declaration_name instead\n"; | 1407 | emit_warning("${file}:$.", "expecting prototype for typedef $identifier. Prototype was for typedef $declaration_name instead\n"); |
| 1402 | return; | 1408 | return; |
| 1403 | } | 1409 | } |
| 1404 | 1410 | ||
| @@ -1554,9 +1560,7 @@ sub push_parameter($$$$$) { · 149 unmodified lines | |||
| 1554 | $parameterdescs{$param} = $undescribed; | 1560 | $parameterdescs{$param} = $undescribed; |
| 1555 | 1561 | ||
| 1556 | if (show_warnings($type, $declaration_name) && $param !~ /\./) { | 1562 | if (show_warnings($type, $declaration_name) && $param !~ /\./) { |
| 1557 | print STDERR | 1563 | emit_warning("${file}:$.", "Function parameter or member '$param' not described in '$declaration_name'\n"); |
| 1558 | "${file}:$.: warning: Function parameter or member '$param' not described in '$declaration_name'\n"; | ||
| 1559 | ++$warnings; | ||
| 1560 | } | 1564 | } |
| 1561 | } | 1565 | } |
| 1562 | 1566 | ||
| @@ -1604,11 +1608,10 @@ sub check_sections($$$$$) { · 41 unmodified lines | |||
| 1604 | } | 1608 | } |
| 1605 | if ($err) { | 1609 | if ($err) { |
| 1606 | if ($decl_type eq "function") { | 1610 | if ($decl_type eq "function") { |
| 1607 | print STDERR "${file}:$.: warning: " . | 1611 | emit_warning("${file}:$.", |
| 1608 | "Excess function parameter " . | 1612 | "Excess function parameter " . |
| 1609 | "'$sects[$sx]' " . | 1613 | "'$sects[$sx]' " . |
| 1610 | "description in '$decl_name'\n"; | 1614 | "description in '$decl_name'\n"); |
| 1611 | ++$warnings; | ||
| 1612 | } | 1615 | } |
| 1613 | } | 1616 | } |
| 1614 | } | 1617 | } |
| @@ -1629,10 +1632,9 @@ sub check_return_section { · 14 unmodified lines | |||
| 1629 | 1632 | ||
| 1630 | if (!defined($sections{$section_return}) || | 1633 | if (!defined($sections{$section_return}) || |
| 1631 | $sections{$section_return} eq "") { | 1634 | $sections{$section_return} eq "") { |
| 1632 | print STDERR "${file}:$.: warning: " . | 1635 | emit_warning("${file}:$.", |
| 1633 | "No description found for return value of " . | 1636 | "No description found for return value of " . |
| 1634 | "'$declaration_name'\n"; | 1637 | "'$declaration_name'\n"); |
| 1635 | ++$warnings; | ||
| 1636 | } | 1638 | } |
| 1637 | } | 1639 | } |
| 1638 | 1640 | ||
| @@ -1714,12 +1716,12 @@ sub dump_function($$) { · 75 unmodified lines | |||
| 1714 | 1716 | ||
| 1715 | create_parameterlist($args, ',', $file, $declaration_name); | 1717 | create_parameterlist($args, ',', $file, $declaration_name); |
| 1716 | } else { | 1718 | } else { |
| 1717 | print STDERR "${file}:$.: warning: cannot understand function prototype: '$prototype'\n"; | 1719 | emit_warning("${file}:$.", "cannot understand function prototype: '$prototype'\n"); |
| 1718 | return; | 1720 | return; |
| 1719 | } | 1721 | } |
| 1720 | 1722 | ||
| 1721 | if ($identifier ne $declaration_name) { | 1723 | if ($identifier ne $declaration_name) { |
| 1722 | print STDERR "${file}:$.: warning: expecting prototype for $identifier(). Prototype was for $declaration_name() instead\n"; | 1724 | emit_warning("${file}:$.", "expecting prototype for $identifier(). Prototype was for $declaration_name() instead\n"); |
| 1723 | return; | 1725 | return; |
| 1724 | } | 1726 | } |
| 1725 | 1727 | ||
| @@ -1801,8 +1803,8 @@ sub tracepoint_munge($) { · 75 unmodified lines | |||
| 1801 | $tracepointargs = $1; | 1803 | $tracepointargs = $1; |
| 1802 | } | 1804 | } |
| 1803 | if (($tracepointname eq 0) || ($tracepointargs eq 0)) { | 1805 | if (($tracepointname eq 0) || ($tracepointargs eq 0)) { |
| 1804 | print STDERR "${file}:$.: warning: Unrecognized tracepoint format: \n". | 1806 | emit_warning("${file}:$.", "Unrecognized tracepoint format: \n". |
| 1805 | "$prototype\n"; | 1807 | "$prototype\n"); |
| 1806 | } else { | 1808 | } else { |
| 1807 | $prototype = "static inline void trace_$tracepointname($tracepointargs)"; | 1809 | $prototype = "static inline void trace_$tracepointname($tracepointargs)"; |
| 1808 | $identifier = "trace_$identifier"; | 1810 | $identifier = "trace_$identifier"; |
| @@ -2027,22 +2029,16 @@ sub process_name($$) { · 218 unmodified lines | |||
| 2027 | } | 2029 | } |
| 2028 | 2030 | ||
| 2029 | if (!$is_kernel_comment) { | 2031 | if (!$is_kernel_comment) { |
| 2030 | print STDERR "${file}:$.: warning: This comment starts with '/**', but isn't a kernel-doc comment. Refer Documentation/doc-guide/kernel-doc.rst\n"; | 2032 | emit_warning("${file}:$.", "This comment starts with '/**', but isn't a kernel-doc comment. Refer Documentation/doc-guide/kernel-doc.rst\n$_"); |
| 2031 | print STDERR $_; | ||
| 2032 | ++$warnings; | ||
| 2033 | $state = STATE_NORMAL; | 2033 | $state = STATE_NORMAL; |
| 2034 | } | 2034 | } |
| 2035 | 2035 | ||
| 2036 | if (($declaration_purpose eq "") && $verbose) { | 2036 | if (($declaration_purpose eq "") && $verbose) { |
| 2037 | print STDERR "${file}:$.: warning: missing initial short description on line:\n"; | 2037 | emit_warning("${file}:$.", "missing initial short description on line:\n$_"); |
| 2038 | print STDERR $_; | ||
| 2039 | ++$warnings; | ||
| 2040 | } | 2038 | } |
| 2041 | 2039 | ||
| 2042 | if ($identifier eq "" && $decl_type ne "enum") { | 2040 | if ($identifier eq "" && $decl_type ne "enum") { |
| 2043 | print STDERR "${file}:$.: warning: wrong kernel-doc identifier on line:\n"; | 2041 | emit_warning("${file}:$.", "wrong kernel-doc identifier on line:\n$_"); |
| 2044 | print STDERR $_; | ||
| 2045 | ++$warnings; | ||
| 2046 | $state = STATE_NORMAL; | 2042 | $state = STATE_NORMAL; |
| 2047 | } | 2043 | } |
| 2048 | 2044 | ||
| @@ -2050,9 +2046,7 @@ sub process_name($$) { · 1 unmodified line | |||
| 2050 | print STDERR "${file}:$.: info: Scanning doc for $decl_type $identifier\n"; | 2046 | print STDERR "${file}:$.: info: Scanning doc for $decl_type $identifier\n"; |
| 2051 | } | 2047 | } |
| 2052 | } else { | 2048 | } else { |
| 2053 | print STDERR "${file}:$.: warning: Cannot understand $_ on line $.", | 2049 | emit_warning("${file}:$.", "Cannot understand $_ on line $. - I thought it was a doc line\n"); |
| 2054 | " - I thought it was a doc line\n"; | ||
| 2055 | ++$warnings; | ||
| 2056 | $state = STATE_NORMAL; | 2050 | $state = STATE_NORMAL; |
| 2057 | } | 2051 | } |
| 2058 | } | 2052 | } |
| @@ -2071,8 +2065,7 @@ sub process_body($$) { · 12 unmodified lines | |||
| 2071 | $section =~ s/\.\.\.$//; | 2065 | $section =~ s/\.\.\.$//; |
| 2072 | 2066 | ||
| 2073 | if ($verbose) { | 2067 | if ($verbose) { |
| 2074 | print STDERR "${file}:$.: warning: Variable macro arguments should be documented without dots\n"; | 2068 | emit_warning("${file}:$.", "Variable macro arguments should be documented without dots\n"); |
| 2075 | ++$warnings; | ||
| 2076 | } | 2069 | } |
| 2077 | } | 2070 | } |
| 2078 | 2071 | ||
| @@ -2101,8 +2094,7 @@ sub process_body($$) { · 22 unmodified lines | |||
| 2101 | 2094 | ||
| 2102 | if (($contents ne "") && ($contents ne "\n")) { | 2095 | if (($contents ne "") && ($contents ne "\n")) { |
| 2103 | if (!$in_doc_sect && $verbose) { | 2096 | if (!$in_doc_sect && $verbose) { |
| 2104 | print STDERR "${file}:$.: warning: contents before sections\n"; | 2097 | emit_warning("${file}:$.", "contents before sections\n"); |
| 2105 | ++$warnings; | ||
| 2106 | } | 2098 | } |
| 2107 | dump_section($file, $section, $contents); | 2099 | dump_section($file, $section, $contents); |
| 2108 | $section = $section_default; | 2100 | $section = $section_default; |
| @@ -2128,8 +2120,7 @@ sub process_body($$) { · 19 unmodified lines | |||
| 2128 | } | 2120 | } |
| 2129 | # look for doc_com + <text> + doc_end: | 2121 | # look for doc_com + <text> + doc_end: |
| 2130 | if ($_ =~ m'\s*\*\s*[a-zA-Z_0-9:\.]+\*/') { | 2122 | if ($_ =~ m'\s*\*\s*[a-zA-Z_0-9:\.]+\*/') { |
| 2131 | print STDERR "${file}:$.: warning: suspicious ending line: $_"; | 2123 | emit_warning("${file}:$.", "suspicious ending line: $_"); |
| 2132 | ++$warnings; | ||
| 2133 | } | 2124 | } |
| 2134 | 2125 | ||
| 2135 | $prototype = ""; | 2126 | $prototype = ""; |
| @@ -2173,8 +2164,7 @@ sub process_body($$) { · 37 unmodified lines | |||
| 2173 | } | 2164 | } |
| 2174 | } else { | 2165 | } else { |
| 2175 | # i dont know - bad line? ignore. | 2166 | # i dont know - bad line? ignore. |
| 2176 | print STDERR "${file}:$.: warning: bad line: $_"; | 2167 | emit_warning("${file}:$.", "bad line: $_"); |
| 2177 | ++$warnings; | ||
| 2178 | } | 2168 | } |
| 2179 | } | 2169 | } |
| 2180 | 2170 | ||
| @@ -2268,9 +2258,7 @@ sub process_inline($$) { · 87 unmodified lines | |||
| 2268 | } | 2258 | } |
| 2269 | } elsif ($inline_doc_state == STATE_INLINE_NAME) { | 2259 | } elsif ($inline_doc_state == STATE_INLINE_NAME) { |
| 2270 | $inline_doc_state = STATE_INLINE_ERROR; | 2260 | $inline_doc_state = STATE_INLINE_ERROR; |
| 2271 | print STDERR "${file}:$.: warning: "; | 2261 | emit_warning("${file}:$.", "Incorrect use of kernel-doc format: $_"); |
| 2272 | print STDERR "Incorrect use of kernel-doc format: $_"; | ||
| 2273 | ++$warnings; | ||
| 2274 | } | 2262 | } |
| 2275 | } | 2263 | } |
| 2276 | } | 2264 | } |
| @@ -2319,11 +2307,11 @@ sub process_file($) { · 42 unmodified lines | |||
| 2319 | if ($initial_section_counter == $section_counter && $ | 2307 | if ($initial_section_counter == $section_counter && $ |
| 2320 | output_mode ne "none") { | 2308 | output_mode ne "none") { |
| 2321 | if ($output_selection == OUTPUT_INCLUDE) { | 2309 | if ($output_selection == OUTPUT_INCLUDE) { |
| 2322 | print STDERR "${file}:1: warning: '$_' not found\n" | 2310 | emit_warning("${file}:1", "'$_' not found\n") |
| 2323 | for keys %function_table; | 2311 | for keys %function_table; |
| 2324 | } | 2312 | } |
| 2325 | else { | 2313 | else { |
| 2326 | print STDERR "${file}:1: warning: no structured comments found\n"; | 2314 | emit_warning("${file}:1", "no structured comments found\n"); |
| 2327 | } | 2315 | } |
| 2328 | } | 2316 | } |
| 2329 | close IN_FILE; | 2317 | close IN_FILE; |