Compile “length(string/array) = 0” as “pointer(string/array) = nil”.
This resolves #39549. Disclaimer: I don’t understand what’s going on and just tried randomly.
COM-based widestring
must be the only counterexample so far, and it was already special-cased in TransformLengthZero
because of the different length format.
Code irresponsible to the point of maliciousness that, say, manually writes 0 to the header is broken even without this MR: for example, reference_counted_string = ''
is compiled simply as pointer(reference_counted_string) = nil
, which would wrongly return false
with such an injected Len = 0
, and shows that the assumption that pointer(s) = nil
iff length(s) = 0
has been with us all along.
Additionally, this handles:
-
Length <> 0
asnot (Length = 0)
, -
Length > 0
asLength <> 0
, -
Length <= 0
asLength = 0
, -
Length >= 0
astrue
, -
Length < 0
asfalse
. (These two could warn.)
By my rough estimate with length\s*\(.*\)\s*(=|<>|>|<|>=|<=)\s*0
accounting for its tons of false positives, there are around 100–150 occurences in RTL and 300–500 in packages, and many of them are Length > 0
.