Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-devel / 2021-06

Unexpected range check error (64-bit only)

8 messages · 2 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Bart

Hi,

Something like this:

Int64 := Byte + Byte + (Signed integer type (8,16 or 32 bit) with value < 0) will always give a range check error on X86_64 platform (if range checking is enabled).

From a mathematical POV, this can never give a range error, max value

would be 2147484157 (255 +255 High(int32)), min value would be -2147483649 (0-High(Int32)).

At some point the negative integer is extended to a 64-bit value and then tested to be <= High(Int64).
This of course will always fail, since the high bit will be set for the negative integer (and comparion is unsigned).

Is this a consequnece of how fpc treats integer arithmetics (and thus to be expected) or is this a bug.
If it is as designed, then why does the same not happen for Int64 := Byte + (Signed integer type (8,16 or 32 bit) with value < 0) nor for the 32-bit platform.

(Tested on Windows and Linux only with fpc 3.2.2 and fpc trunk)

Bart

Reply by email

Bart
to Bart
PM Bart wrote
Int64 := Byte + Byte + (Signed integer type (8,16 or 32 bit) with value < 0) will always give a range check error on X86_64 platform (if range checking is enabled).

Bump...

Bart

Reply by email

Jonas Maebe
to Bart
Bart wrote 5 lines
On Tue, Dec 28, 2021 at 9:38 PM Jonas Maebe via fpc-devel wrote: > https://gitlab.com/freepascal.org/fpc/source/-/issues/37875 OK, but from reading that it is still unclear to me wether this is a bug or not.

It's something that is annoying, but impossible to fix in all cases without adding support for 128 bit (or at least 65 bit) arithmetic. It's what you get in exchange for support for unsigned arithmetic at the highest available bit width. It could be considered a bug if the behaviour is different from Delphi, but then we need the rules to follow/implement.

Nor why it only triggers with Byte + Byte + Unsigned, and not with

In you original mail, you said it triggered for Byte + Byte + Signed.

Byte + Unsigned.

It doesn't trigger for Byte + *Signed* because that expression gets evaluated as a signed expression. It would trigger an overflow for Byte
+ Int64 where the Int64 contains high(int64) and the byte a non-zero value though (because it will overflow int64 in that case).

Jonas

Reply by email

Bart
to Jonas Maebe
PM Jonas Maebe wrote
> Nor why it only triggers with Byte + Byte + Unsigned, and not with In you original mail, you said it triggered for Byte + Byte + Signed.

Yes, of course, the original mail is correct.

It doesn't trigger for Byte + *Signed* because that expression gets evaluated as a signed expression

OK, let me see if I understand it correctly now:

1. (Signed) Int64 := unsigned(32-16-8bit) + unsigned(32-16-8-bit) + signed(32-16-8-bit)
gets evaluated with unsigned 64-bit arithmetic and then the test for <high(signed 64-bit) fails.

2. (Signed) Int64 := unsigned(32-16-8-bit) + signed(32-16-8-bit)
gets eval with signed arithmetic.

How to workaround (1) then, other then turning range checking off? (Since I hardly ever trust myself, almost all of my applications ahve range checking on even in release mode.)

And the consequence is that even if we eventually have native 128-bit integer support, the problem will persist but now for Int128?

Annoying it is.

Bart

Reply by email

Jonas Maebe
to Bart
Bart wrote 9 lines
OK, let me see if I understand it correctly now: 1. (Signed) Int64 := unsigned(32-16-8bit) + unsigned(32-16-8-bit) + signed(32-16-8-bit) gets evaluated with unsigned 64-bit arithmetic and then the test for <high(signed 64-bit) fails. 2. (Signed) Int64 := unsigned(32-16-8-bit) + signed(32-16-8-bit) gets eval with signed arithmetic.

Correct.

How to workaround (1) then, other then turning range checking off? (Since I hardly ever trust myself, almost all of my applications ahve range checking on even in release mode.)

Add an explicit typecast to longint or int64 for the first term.

Pascal evaluates expressions independent of how the result is used. Even if it did take the final use into account, we'd end up with tons of peculiar cases related to overloads and intrinsics like writeln.

And the consequence is that even if we eventually have native 128-bit integer support, the problem will persist but now for Int128?

Yes, unless we would only support/use it for intermediate results.

Jonas

Reply by email

Bart
to Jonas Maebe
PM Jonas Maebe wrote
> And the consequence is that even if we eventually have native 128-bit > integer support, the problem will persist but now for Int128? Yes, unless we would only support/use it for intermediate results.

Thanks for explaining.

Bart

Reply by email