Re: [PATCH] kconfig: nconf: stop endless search-up loops
From: Mihai Moldovan
Date: Sun Mar 28 2021 - 06:04:49 EST
* On 3/27/21 11:26 PM, Randy Dunlap wrote:
> There is a test for it in checkpatch.pl but I also used checkpatch.pl
> without it complaining, so I don't know what it takes to make the script
> complain.
>
> if ($lead !~ /(?:$Operators|\.)\s*$/ &&
> $to !~ /^(?:Constant|[A-Z_][A-Z0-9_]*)$/ &&
> WARN("CONSTANT_COMPARISON",
> "Comparisons should place the constant on the right side of the test\n" . $herecurr) &&
There are multiple issues, err, "challenges" there:
- literal "Constant" instead of "$Constant"
- the left part is misinterpreted as an operation due to the minus sign
(arithmetic operator)
- $Constant is defined as "qr{$Float|$Binary|$Octal|$Hex|$Int}" (which is
okay), but all these types do not include their negative range.
As far as I can tell, the latter is intentional. Making these types compatible
with negative values causes a lot of other places to break, so I'm not keen on
changing this.
The minus sign being misinterpreted as an operator is highly difficult to fix
in a sane manner. The original intention was to avoid misinterpreting
expressions like (var - CONSTANT real_op ...) as a constant-on-left expression
(and, more importantly, to not misfix it when --fix is given).
The general idea is sane and we probably shouldn't change that, but it would
be good to handle negative values as well.
At first, I was thinking of overriding this detection by checking if the
leading part matches "(-\s*$", which should only be true for negative values,
assuming that there is always an opening parenthesis as part of a conditional
statement/loop (if, while). After playing around with this and composing this
message for a few hours, it dawned on me that there can easily be free-
standing forms (for instance as part of for loops or assignment lines), so
that wouldn't cut it.
It really goes downhill from here.
I assume that false negatives are nuisances due to stylistic errors in the
code, but false positives actually harmful since a lot of them make code
review by maintainers very tedious.
So far, minus signs were always part of the leading capture group. I'd
actually like to have them in the constant capture group instead:
- $line =~ /^\+(.*)\b($Constant|[A-Z_][A-Z0-9_]*)\s*($Compare)\s*($LvalOrFunc)/) {
+ $line =~ /^\+(.*)(-?\s*$Constant|[A-Z_][A-Z0-9_]*)\s*($Compare)\s*($LvalOrFunc)/) {
With that sorted, the next best thing I could come up with to weed out
preceding variables was this (which shouldn't influence non-negative
constants):
- if ($lead !~ /(?:$Operators|\.)\s*$/ &&
+ if ($lead !~ /(?:$Operators|\.|[a-z])\s*$/ &&
There still are a lot of expressions that won't match this, like
"-1 + 0 == var" (i.e., "CONSTANT <arith_op> CONSTANT <op> ...") or
constellations like a simple "(CONSTANT) <op> ..." (e.g.,
"(1) == var").
This is all fuzzy and getting this right would involve moving away from
trying to make sense of C code with regular expressions in Perl, but actually
parsing it to extract the semantics. Not exactly something I'd like to do...
Thoughts on my workaround for this issue? Did I miss anything crucial or
introduce a new bug inadvertently?