Peter N Lewis wrote:
The next one is more challenging, since I don't see a good workaround.
s: String(255)
@s[1] range checks if Length(s) is 0.
While this might technically be correct (the subscript is out of bounds), the actual address is valid.
This is quite challenging to work around, since I'm often forced to deal with strings as a pointer to chars and a length, and this means that code to say draw a string like:
DrawString( @s[1], Length(s) );
now needs to special case for s = ''.
Yes, I've had such cases in my code a few times. I've added the check. Though a bit more to write, it might even be more efficient (providing that for an empty string, it's really a no-op). GPC optimizes the comparison `s = ''' to a simple integer comparison (Length = 0), in contrast to a dummy procedure call.
I would contend that in the case of @s[x], x should be checked against a range of 1..Length(x)+1 because it should be legal to point to the next free character.
Always depends on what you do with it. If you want to write there, you can usually increase the length before rather than afterwards (I've also had this a few times and basically only needed to exchange two statements). Reading from this location is usually undefined/invalid. The "length 0 / index 1" case is a bit special, it can become valid more easily, but also often avoided more easily, see above ...
Whether this is reasonably doable or not, I don't know.
Not really too easy. (It's a bit hard to tell the compiler that `s[Length (s) + 1]' is invalid, but becomes valid again in a certain context. Basically we'd have to either undo (always ugly) this range-checking, or postpone all range-checking to a later stage, i.e. almost add another pass to the compiler.)
If s were short strings, I could work around it with pointer arithmetic (@s+1), but given it is a Schema, I don't know how I would safely get the address of the first character of the string in the case where s might be empty.
Instead of such ugly tricks, you can always locally turn off range-checking if nothing else helps:
{$local R-} ... {$endlocal}
More precise control over range checking ,might be helpful, options to disable range checking for strings, or perhaps limit them to capacity range checking,
Well, that's what `--borland-pascal' does (for compatibility, obviously, types.c:2293), so it wouldn't be hard to make it a separate option (yeah -- it's about time for another one ... naming suggestions welcome ...). BTW, how does Mac Pascal behave?
Frank