| From: Jim Cromie <jim.cromie@gmail.com> |
| Subject: checkpatch: special case extern struct in .c |
| Date: Mon, 7 Aug 2023 21:30:18 -0600 |
| |
| "externs should be avoided in .c files" needs an exception for linker |
| symbols, like those that mark the start, stop of many kernel sections. |
| |
| Since checkpatch already checks REALNAME to avoid looking at fragments |
| changing vmlinux.lds.h, add a new else-if block to look at them |
| instead. As a simple heuristic, treat all words (in the patch-line) |
| as possible symbols, to screen later warnings. |
| |
| For my test case, the possible-symbols included BOUNDED_BY (a macro), |
| which is extra, but not troublesome - these are just to screen |
| WARNINGS that might be issued on later fragments (changing .c files) |
| |
| Where the WARN is issued, precede it with an else-if block to catch |
| one common extern-in-c use case: "extern struct foo bar[]". Here we |
| can at least issue a softer warning, after checking for a match with a |
| maybe-linker-symbol parsed earlier from the patch. |
| |
| Though heuristic, it worked for my test-case, allowing both start__, |
| stop__ $symbol's (wo the prefixes specifically named). I've coded it |
| narrowly, it can be expanded later to cover any other expressions. |
| |
| It does require that the externs in .c's have the additions to |
| vmlinux.lds.h in the same patch. And requires vmlinux.lds.h before .c |
| fragments. |
| |
| Link: https://lkml.kernel.org/r/20230808033019.21911-2-jim.cromie@gmail.com |
| Signed-off-by: Jim Cromie <jim.cromie@gmail.com> |
| Cc: Joe Perches <joe@perches.com> |
| Signed-off-by: Andrew Morton <akpm@linux-foundation.org> |
| --- |
| |
| scripts/checkpatch.pl | 20 ++++++++++++++++++++ |
| 1 file changed, 20 insertions(+) |
| |
| --- a/scripts/checkpatch.pl~checkpatch-special-case-extern-struct-in-c |
| +++ a/scripts/checkpatch.pl |
| @@ -74,6 +74,8 @@ my $git_command ='export LANGUAGE=en_US. |
| my $tabsize = 8; |
| my ${CONFIG_} = "CONFIG_"; |
| |
| +my %maybe_linker_symbol; # for externs in c exceptions, when seen in *vmlinux.lds.h |
| + |
| sub help { |
| my ($exitcode) = @_; |
| |
| @@ -6051,6 +6053,9 @@ sub process { |
| |
| # check for line continuations outside of #defines, preprocessor #, and asm |
| |
| + } elsif ($realfile =~ m@/vmlinux.lds.h$@) { |
| + $line =~ s/(\w+)/$maybe_linker_symbol{$1}++/ge; |
| + #print "REAL: $realfile\nln: $line\nkeys:", sort keys %maybe_linker_symbol; |
| } else { |
| if ($prevline !~ /^..*\\$/ && |
| $line !~ /^\+\s*\#.*\\$/ && # preprocessor |
| @@ -7120,6 +7125,21 @@ sub process { |
| } |
| |
| } elsif ($realfile =~ /\.c$/ && defined $stat && |
| + $stat =~ /^\+extern struct\s+(\w+)\s+(\w+)\[\];/) |
| + { |
| + my ($st_type, $st_name) = ($1, $2); |
| + |
| + for my $s (keys %maybe_linker_symbol) { |
| + #print "Linker symbol? $st_name : $s\n"; |
| + goto LIKELY_LINKER_SYMBOL |
| + if $st_name =~ /$s/; |
| + } |
| + WARN("AVOID_EXTERNS", |
| + "found a file-scoped extern type:$st_type name:$st_name in .c file\n" |
| + . "is this a linker symbol ?\n" . $herecurr); |
| + LIKELY_LINKER_SYMBOL: |
| + |
| + } elsif ($realfile =~ /\.c$/ && defined $stat && |
| $stat =~ /^.\s*extern\s+/) |
| { |
| WARN("AVOID_EXTERNS", |
| _ |