7976 lines · 239.6 KB · Perl
RawDownload
			my $ctx = '';			my $has_flow_statement = 0;			my $has_arg_concat = 0;			($dstat, $dcond, $ln, $cnt, $off) =				ctx_statement_block($linenr, $realcnt, 0);			$ctx = $dstat;			#print "dstat<$dstat> dcond<$dcond> cnt<$cnt> off<$off>\n";			#print "LINE<$lines[$ln-1]> len<" . length($lines[$ln-1]) . "\n"; 			$has_flow_statement = 1 if ($ctx =~ /\b(goto|return)\b/);			$has_arg_concat = 1 if ($ctx =~ /\#\#/ && $ctx !~ /\#\#\s*(?:__VA_ARGS__|args)\b/); 			$dstat =~ s/^.\s*\#\s*define\s+$Ident(\([^\)]*\))?\s*//;			my $define_args = $1;			my $define_stmt = $dstat;			my @def_args = (); 			if (defined $define_args && $define_args ne "") {				$define_args = substr($define_args, 1, length($define_args) - 2);				$define_args =~ s/\s*//g;				$define_args =~ s/\\\+?//g;				@def_args = split(",", $define_args);			} 			$dstat =~ s/$;//g;			$dstat =~ s/\\\n.//g;			$dstat =~ s/^\s*//s;			$dstat =~ s/\s*$//s; 			# Flatten any parentheses and braces			while ($dstat =~ s/\([^\(\)]*\)/1u/ ||			       $dstat =~ s/\{[^\{\}]*\}/1u/ ||			       $dstat =~ s/.\[[^\[\]]*\]/1u/)			{			} 			# Flatten any obvious string concatenation.			while ($dstat =~ s/($String)\s*$Ident/$1/ ||			       $dstat =~ s/$Ident\s*($String)/$1/)			{			} 			# Make asm volatile uses seem like a generic function			$dstat =~ s/\b_*asm_*\s+_*volatile_*\b/asm_volatile/g; 			my $exceptions = qr{				$Declare|				# named exceptions				module_param_named|				MODULE_PARM_DESC|				DECLARE_PER_CPU|				DEFINE_PER_CPU|				static_assert|				# declaration primitives				__typeof__\(|				union|				struct|				\.$Ident\s*=\s*|				^\"|\"$|				^\[			}x;			#print "REST<$rest> dstat<$dstat> ctx<$ctx>\n"; 			$ctx =~ s/\n*$//;			my $stmt_cnt = statement_rawlines($ctx);			my $herectx = get_stat_here($linenr, $stmt_cnt, $here); 			if ($dstat ne '' &&			    $dstat !~ /^(?:$Ident|-?$Constant),$/ &&			# 10, // foo(),			    $dstat !~ /^(?:$Ident|-?$Constant);$/ &&			# foo();			    $dstat !~ /^[!~-]?(?:$Lval|$Constant)$/ &&		# 10 // foo() // !foo // ~foo // -foo // foo->bar // foo.bar->baz			    $dstat !~ /^'X'$/ && $dstat !~ /^'XX'$/ &&			# character constants			    $dstat !~ /$exceptions/ &&			    $dstat !~ /^\.$Ident\s*=/ &&				# .foo =			    $dstat !~ /^(?:\#\s*$Ident|\#\s*$Constant)\s*$/ &&		# stringification #foo			    $dstat !~ /^case\b/ &&					# case ...			    $dstat !~ /^do\s*$Constant\s*while\s*$Constant;?$/ &&	# do {...} while (...); // do {...} while (...)			    $dstat !~ /^while\s*$Constant\s*$Constant\s*$/ &&		# while (...) {...}			    $dstat !~ /^for\s*$Constant$/ &&				# for (...)			    $dstat !~ /^for\s*$Constant\s+(?:$Ident|-?$Constant)$/ &&	# for (...) bar()			    $dstat !~ /^do\s*{/ &&					# do {...			    $dstat !~ /^\(\{/ &&						# ({...			    $ctx !~ /^.\s*#\s*define\s+TRACE_(?:SYSTEM|INCLUDE_FILE|INCLUDE_PATH)\b/)			{				if ($dstat =~ /^\s*if\b/) {					ERROR("MULTISTATEMENT_MACRO_USE_DO_WHILE",					      "Macros starting with if should be enclosed by a do - while loop to avoid possible if/else logic defects\n" . "$herectx");				} elsif ($dstat =~ /;/) {					WARN("MULTISTATEMENT_MACRO_USE_DO_WHILE",					      "Non-declarative macros with multiple statements should be enclosed in a do - while loop\n" . "$herectx\nBUT SEE:\n$DO_WHILE_0_ADVICE");				} else {					ERROR("COMPLEX_MACRO",					      "Macros with complex values should be enclosed in parentheses\n" . "$herectx\nBUT SEE:\n$DO_WHILE_0_ADVICE");				} 			} 			# Make $define_stmt single line, comment-free, etc			my @stmt_array = split('\n', $define_stmt);			my $first = 1;			$define_stmt = "";			foreach my $l (@stmt_array) {				$l =~ s/\\$//;				if ($first) {					$define_stmt = $l;					$first = 0;				} elsif ($l =~ /^[\+ ]/) {					$define_stmt .= substr($l, 1);				}			}			$define_stmt =~ s/$;//g;			$define_stmt =~ s/\s+/ /g;			$define_stmt = trim($define_stmt); # check if any macro arguments are reused (ignore '...' and 'type')			foreach my $arg (@def_args) {			        next if ($arg =~ /\.\.\./);			        next if ($arg =~ /^type$/i);				my $tmp_stmt = $define_stmt;				$tmp_stmt =~ s/\b(__must_be_array|offsetof|sizeof|sizeof_field|__stringify|typeof|__typeof__|__builtin\w+|typecheck\s*\(\s*$Type\s*,|\#+)\s*\(*\s*$arg\s*\)*\b//g;				$tmp_stmt =~ s/\#+\s*$arg\b//g;				$tmp_stmt =~ s/\b$arg\s*\#\#//g;				my $use_cnt = () = $tmp_stmt =~ /\b$arg\b/g;				if ($use_cnt > 1) {					CHK("MACRO_ARG_REUSE",					    "Macro argument reuse '$arg' - possible side-effects?\n" . "$herectx");				    }# check if any macro arguments may have other precedence issues				if ($tmp_stmt =~ m/($Operators)?\s*\b$arg\b\s*($Operators)?/m &&				    ((defined($1) && $1 ne ',') ||				     (defined($2) && $2 ne ','))) {					CHK("MACRO_ARG_PRECEDENCE",					    "Macro argument '$arg' may be better as '($arg)' to avoid precedence issues\n" . "$herectx");				} # check if this is an unused argument				if ($define_stmt !~ /\b$arg\b/ && $define_stmt) {					WARN("MACRO_ARG_UNUSED",					     "Argument '$arg' is not used in function-like macro\n" . "$herectx");				}			} # check for macros with flow control, but without ## concatenation# ## concatenation is commonly a macro that defines a function so ignore those			if ($has_flow_statement && !$has_arg_concat) {				my $cnt = statement_rawlines($ctx);				my $herectx = get_stat_here($linenr, $cnt, $here); 				WARN("MACRO_WITH_FLOW_CONTROL",				     "Macros with flow control statements should be avoided\n" . "$herectx");			} # 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			    $line !~ /^\+.*\b(__asm__|asm)\b.*\\$/ &&	# asm			    $line =~ /^\+.*\\$/) {				WARN("LINE_CONTINUATIONS",				     "Avoid unnecessary line continuations\n" . $herecurr);			}		} # do {} while (0) macro tests:# single-statement macros do not need to be enclosed in do while (0) loop,# macro should not end with a semicolon		if ($perl_version_ok &&		    $realfile !~ m@/vmlinux.lds.h$@ &&		    $line =~ /^.\s*\#\s*define\s+$Ident(\()?/) {			my $ln = $linenr;			my $cnt = $realcnt;			my ($off, $dstat, $dcond, $rest);			my $ctx = '';			($dstat, $dcond, $ln, $cnt, $off) =				ctx_statement_block($linenr, $realcnt, 0);			$ctx = $dstat; 			$dstat =~ s/\\\n.//g;			$dstat =~ s/$;/ /g; 			if ($dstat =~ /^\+\s*#\s*define\s+$Ident\s*${balanced_parens}\s*do\s*{(.*)\s*}\s*while\s*\(\s*0\s*\)\s*([;\s]*)\s*$/) {				my $stmts = $2;				my $semis = $3; 				$ctx =~ s/\n*$//;				my $cnt = statement_rawlines($ctx);				my $herectx = get_stat_here($linenr, $cnt, $here); 				if (($stmts =~ tr/;/;/) == 1 &&				    $stmts !~ /^\s*(if|while|for|switch)\b/) {					WARN("SINGLE_STATEMENT_DO_WHILE_MACRO",					     "Single statement macros should not use a do {} while (0) loop\n" . "$herectx");				}				if (defined $semis && $semis ne "") {					WARN("DO_WHILE_MACRO_WITH_TRAILING_SEMICOLON",					     "do {} while (0) macros should not be semicolon terminated\n" . "$herectx");				}			} elsif ($dstat =~ /^\+\s*#\s*define\s+$Ident.*;\s*$/) {				$ctx =~ s/\n*$//;				my $cnt = statement_rawlines($ctx);				my $herectx = get_stat_here($linenr, $cnt, $here); 				WARN("TRAILING_SEMICOLON",				     "macros should not use a trailing semicolon\n" . "$herectx");			}		} # check for redundant bracing round if etc		if ($line =~ /(^.*)\bif\b/ && $1 !~ /else\s*$/) {			my ($level, $endln, @chunks) =				ctx_statement_full($linenr, $realcnt, 1);			#print "chunks<$#chunks> linenr<$linenr> endln<$endln> level<$level>\n";			#print "APW: <<$chunks[1][0]>><<$chunks[1][1]>>\n";			if ($#chunks > 0 && $level == 0) {				my @allowed = ();				my $allow = 0;				my $seen = 0;				my $herectx = $here . "\n";				my $ln = $linenr - 1;				for my $chunk (@chunks) {					my ($cond, $block) = @{$chunk}; 					# If the condition carries leading newlines, then count those as offsets.					my ($whitespace) = ($cond =~ /^((?:\s*\n[+-])*\s*)/s);					my $offset = statement_rawlines($whitespace) - 1; 					$allowed[$allow] = 0;					#print "COND<$cond> whitespace<$whitespace> offset<$offset>\n"; 					# We have looked at and allowed this specific line.					$suppress_ifbraces{$ln + $offset} = 1; 					$herectx .= "$rawlines[$ln + $offset]\n[...]\n";					$ln += statement_rawlines($block) - 1; 					substr($block, 0, length($cond), ''); 					$seen++ if ($block =~ /^\s*{/); 					#print "cond<$cond> block<$block> allowed<$allowed[$allow]>\n";					if (statement_lines($cond) > 1) {						#print "APW: ALLOWED: cond<$cond>\n";						$allowed[$allow] = 1;					}					if ($block =~/\b(?:if|for|while)\b/) {						#print "APW: ALLOWED: block<$block>\n";						$allowed[$allow] = 1;					}					if (statement_block_size($block) > 1) {						#print "APW: ALLOWED: lines block<$block>\n";						$allowed[$allow] = 1;					}					$allow++;				}				if ($seen) {					my $sum_allowed = 0;					foreach (@allowed) {						$sum_allowed += $_;					}					if ($sum_allowed == 0) {						WARN("BRACES",						     "braces {} are not necessary for any arm of this statement\n" . $herectx);					} elsif ($sum_allowed != $allow &&						 $seen != $allow) {						CHK("BRACES",						    "braces {} should be used on all arms of this statement\n" . $herectx);					}				}			}		}		if (!defined $suppress_ifbraces{$linenr - 1} &&					$line =~ /\b(if|while|for|else)\b/) {			my $allowed = 0; 			# Check the pre-context.			if (substr($line, 0, $-[0]) =~ /(\}\s*)$/) {				#print "APW: ALLOWED: pre<$1>\n";				$allowed = 1;			} 			my ($level, $endln, @chunks) =				ctx_statement_full($linenr, $realcnt, $-[0]); 			# Check the condition.			my ($cond, $block) = @{$chunks[0]};			#print "CHECKING<$linenr> cond<$cond> block<$block>\n";			if (defined $cond) {				substr($block, 0, length($cond), '');			}			if (statement_lines($cond) > 1) {				#print "APW: ALLOWED: cond<$cond>\n";				$allowed = 1;			}			if ($block =~/\b(?:if|for|while)\b/) {				#print "APW: ALLOWED: block<$block>\n";				$allowed = 1;			}			if (statement_block_size($block) > 1) {				#print "APW: ALLOWED: lines block<$block>\n";				$allowed = 1;			}			# Check the post-context.			if (defined $chunks[1]) {				my ($cond, $block) = @{$chunks[1]};				if (defined $cond) {					substr($block, 0, length($cond), '');				}				if ($block =~ /^\s*\{/) {					#print "APW: ALLOWED: chunk-1 block<$block>\n";					$allowed = 1;				}			}			if ($level == 0 && $block =~ /^\s*\{/ && !$allowed) {				my $cnt = statement_rawlines($block);				my $herectx = get_stat_here($linenr, $cnt, $here); 				WARN("BRACES",				     "braces {} are not necessary for single statement blocks\n" . $herectx);			}		} # check for single line unbalanced braces		if ($sline =~ /^.\s*\}\s*else\s*$/ ||		    $sline =~ /^.\s*else\s*\{\s*$/) {			CHK("BRACES", "Unbalanced braces around else statement\n" . $herecurr);		} # check for unnecessary blank lines around braces		if (($line =~ /^.\s*}\s*$/ && $prevrawline =~ /^.\s*$/)) {			if (CHK("BRACES",				"Blank lines aren't necessary before a close brace '}'\n" . $hereprev) &&			    $fix && $prevrawline =~ /^\+/) {				fix_delete_line($fixlinenr - 1, $prevrawline);			}		}		if (($rawline =~ /^.\s*$/ && $prevline =~ /^..*{\s*$/)) {			if (CHK("BRACES",				"Blank lines aren't necessary after an open brace '{'\n" . $hereprev) &&			    $fix) {				fix_delete_line($fixlinenr, $rawline);			}		} # no volatiles please		my $asm_volatile = qr{\b(__asm__|asm)\s+(__volatile__|volatile)\b};		if ($line =~ /\bvolatile\b/ && $line !~ /$asm_volatile/) {			WARN("VOLATILE",			     "Use of volatile is usually wrong: see Documentation/process/volatile-considered-harmful.rst\n" . $herecurr);		} # Check for user-visible strings broken across lines, which breaks the ability# to grep for the string.  Make exceptions when the previous string ends in a# newline (multiple lines in one string constant) or '\t', '\r', ';', or '{'# (common in inline assembly) or is a octal \123 or hexadecimal \xaf value		if ($line =~ /^\+\s*$String/ &&		    $prevline =~ /"\s*$/ &&		    $prevrawline !~ /(?:\\(?:[ntr]|[0-7]{1,3}|x[0-9a-fA-F]{1,2})|;\s*|\{\s*)"\s*$/) {			if (WARN("SPLIT_STRING",				 "quoted string split across lines\n" . $hereprev) &&				     $fix &&				     $prevrawline =~ /^\+.*"\s*$/ &&				     $last_coalesced_string_linenr != $linenr - 1) {				my $extracted_string = get_quoted_string($line, $rawline);				my $comma_close = "";				if ($rawline =~ /\Q$extracted_string\E(\s*\)\s*;\s*$|\s*,\s*)/) {					$comma_close = $1;				} 				fix_delete_line($fixlinenr - 1, $prevrawline);				fix_delete_line($fixlinenr, $rawline);				my $fixedline = $prevrawline;				$fixedline =~ s/"\s*$//;				$fixedline .= substr($extracted_string, 1) . trim($comma_close);				fix_insert_line($fixlinenr - 1, $fixedline);				$fixedline = $rawline;				$fixedline =~ s/\Q$extracted_string\E\Q$comma_close\E//;				if ($fixedline !~ /\+\s*$/) {					fix_insert_line($fixlinenr, $fixedline);				}				$last_coalesced_string_linenr = $linenr;			}		} # check for missing a space in a string concatenation		if ($prevrawline =~ /[^\\]\w"$/ && $rawline =~ /^\+[\t ]+"\w/) {			WARN('MISSING_SPACE',			     "break quoted strings at a space character\n" . $hereprev);		} # check for an embedded function name in a string when the function is known# This does not work very well for -f --file checking as it depends on patch# context providing the function name or a single line form for in-file# function declarations		if ($line =~ /^\+.*$String/ &&		    defined($context_function) &&		    get_quoted_string($line, $rawline) =~ /\b$context_function\b/ &&		    length(get_quoted_string($line, $rawline)) != (length($context_function) + 2)) {			WARN("EMBEDDED_FUNCTION_NAME",			     "Prefer using '\"%s...\", __func__' to using '$context_function', this function's name, in a string\n" . $herecurr);		} # check for unnecessary function tracing like uses# This does not use $logFunctions because there are many instances like# 'dprintk(FOO, "%s()\n", __func__);' which do not match $logFunctions		if ($rawline =~ /^\+.*\([^"]*"$tracing_logging_tags{0,3}%s(?:\s*\(\s*\)\s*)?$tracing_logging_tags{0,3}(?:\\n)?"\s*,\s*__func__\s*\)\s*;/) {			if (WARN("TRACING_LOGGING",				 "Unnecessary ftrace-like logging - prefer using ftrace\n" . $herecurr) &&			    $fix) {                                fix_delete_line($fixlinenr, $rawline);			}		} # check for spaces before a quoted newline		if ($rawline =~ /^.*\".*\s\\n/) {			if (WARN("QUOTED_WHITESPACE_BEFORE_NEWLINE",				 "unnecessary whitespace before a quoted newline\n" . $herecurr) &&			    $fix) {				$fixed[$fixlinenr] =~ s/^(\+.*\".*)\s+\\n/$1\\n/;			} 		} # concatenated string without spaces between elements		if ($line =~ /$String[A-Z_]/ ||		    ($line =~ /([A-Za-z0-9_]+)$String/ && $1 !~ /^[Lu]$/)) {			if (CHK("CONCATENATED_STRING",				"Concatenated strings should use spaces between elements\n" . $herecurr) &&			    $fix) {				while ($line =~ /($String)/g) {					my $extracted_string = substr($rawline, $-[0], $+[0] - $-[0]);					$fixed[$fixlinenr] =~ s/\Q$extracted_string\E([A-Za-z0-9_])/$extracted_string $1/;					$fixed[$fixlinenr] =~ s/([A-Za-z0-9_])\Q$extracted_string\E/$1 $extracted_string/;				}			}		} # uncoalesced string fragments		if ($line =~ /$String\s*[Lu]?"/) {			if (WARN("STRING_FRAGMENTS",				 "Consecutive strings are generally better as a single string\n" . $herecurr) &&			    $fix) {				while ($line =~ /($String)(?=\s*")/g) {					my $extracted_string = substr($rawline, $-[0], $+[0] - $-[0]);					$fixed[$fixlinenr] =~ s/\Q$extracted_string\E\s*"/substr($extracted_string, 0, -1)/e;				}			}		} # check for non-standard and hex prefixed decimal printf formats		my $show_L = 1;	#don't show the same defect twice		my $show_Z = 1;		while ($line =~ /(?:^|")([X\t]*)(?:"|$)/g) {			my $string = substr($rawline, $-[1], $+[1] - $-[1]);			$string =~ s/%%/__/g;			# check for %L			if ($show_L && $string =~ /%[\*\d\.\$]*L([diouxX])/) {				WARN("PRINTF_L",				     "\%L$1 is non-standard C, use %ll$1\n" . $herecurr);				$show_L = 0;			}			# check for %Z			if ($show_Z && $string =~ /%[\*\d\.\$]*Z([diouxX])/) {				WARN("PRINTF_Z",				     "%Z$1 is non-standard C, use %z$1\n" . $herecurr);				$show_Z = 0;			}			# check for 0x<decimal>			if ($string =~ /0x%[\*\d\.\$\Llzth]*[diou]/) {				ERROR("PRINTF_0XDECIMAL",				      "Prefixing 0x with decimal output is defective\n" . $herecurr);			}		} # check for line continuations in quoted strings with odd counts of "		if ($rawline =~ /\\$/ && $sline =~ tr/"/"/ % 2) {			WARN("LINE_CONTINUATIONS",			     "Avoid line continuations in quoted strings\n" . $herecurr);		} # warn about #if 0		if ($line =~ /^.\s*\#\s*if\s+0\b/) {			WARN("IF_0",			     "Consider removing the code enclosed by this #if 0 and its #endif\n" . $herecurr);		} # warn about #if 1		if ($line =~ /^.\s*\#\s*if\s+1\b/) {			WARN("IF_1",			     "Consider removing the #if 1 and its #endif\n" . $herecurr);		} # check for needless "if (<foo>) fn(<foo>)" uses		if ($prevline =~ /\bif\s*\(\s*($Lval)\s*\)/) {			my $tested = quotemeta($1);			my $expr = '\s*\(\s*' . $tested . '\s*\)\s*;';			if ($line =~ /\b(kfree|usb_free_urb|debugfs_remove(?:_recursive)?|(?:kmem_cache|mempool|dma_pool)_destroy)$expr/) {

Lines 6001–6500 of 7976. Previous lines