[fpc-pascal] Range checks
C Western
l at c-m-w.me.uk
Sat Jan 27 18:30:02 CET 2018
On 27/01/18 16:28, Jonas Maebe wrote:
>
> Jonas Maebe wrote:
>> C Western wrote:
>>> The following innocuous looking code generates a range check error:
>>>
>>> {$R+}
>>> function Count: qword;
>>> begin
>>> Result := 0;
>>> end;
>>> var
>>> i: Integer;
>>> begin
>>> for i := 0 to Count-1 do
>>> WriteLn(i);
>>> end.
>>>
>>> I can (more or less) see why
>> I changed the type used to evaluate for-loop bounds in ISO Pascal mode
>> because of https://bugs.freepascal.org/view.php?id=24318 . Maybe the
>> same should be done for other non-TP/Delphi modes too.
>
> Actually, it won't help because "qword - 1" will still be evaluated as
> qword. The issue is that there is no safe way to evaluate this with
> range checking that is correct in all cases without a 128 bit integer type:
> 1) if you evaluate it as qword, you get a range error if count is 0 (as
> above)
> 2) if you evaluate it as int64, then if count is high(int64)+1 you will
> get a range error even though the result could be represented in int64
>
> In this particular case, because the counter is 32 bit (which seems
> quite unsafe for use with a container whose "count" property is 64 bit),
> using int64 would be "correct", but it's not a systemic solution (as
> shown above) and hence not something to implement in the language.
>
The actual code that triggered my interest was:
procedure LCLViewExtension.lclSetEnabled(AEnabled: Boolean);
var
ns : NSArray;
i : integer;
obj : NSObject;
begin
ns := subviews;
for i := 0 to ns.count - 1 do
begin
obj := NSObject(ns.objectAtIndex( i ));
... process obj ...
end;
end;
I suppose i should be declared as the same type as ns.count which is
NSUInteger = qword, but this will still trigger the error. You can avoid
the problem by coding the loop as:
for i := 1 to ns.count do
begin
obj := NSObject(ns.objectAtIndex( i-1 ));
so I suppose the real flaw is that the first item is at index 0, rather
than 1, but I don't think that is a battle I am going to win.
Given how common the above bit of code is likely to be, I can't see any
way of fixing this without some work in the compiler.
Colin
More information about the fpc-pascal
mailing list