Recent

Author Topic: longint range-check wrongly prevents compile  (Read 3178 times)

nanobit

  • New member
  • *
  • Posts: 20
longint range-check wrongly prevents compile
« on: December 17, 2018, 12:01:22 pm »
const Dst = $00AA0029;  SrcCopy = $00CC0020; // are longints
begin
  windows.makerop4( Dst, SrcCopy);  // this call expects longints
end;

On the call, SrcCopy produces this compile-error:
"range check error while evaluating constants (3422560256 must be between -2147483648 and 2147483647)"

I noticed the following:
This compile error does not occur if I use own functions instead of windows-function.
SrcCopy is $00CC0020 (unlike 3422560256 ($CC002000))
Typed "const SrcCopy: longint = $00CC0020;" (correctly) silents the compiler.

fpc3.0.4, win32 on Win10; and I cannot debug the RTL (would require different installation)

Thaddy

  • Hero Member
  • *****
  • Posts: 7610
Re: longint range-check wrongly prevents compile
« Reply #1 on: December 17, 2018, 12:08:21 pm »
No these are unsigned ints......Pointers are unsigned because you can not get below existing memory.... 8-) O:-) >:(
This is a legacy issue, but nowadays the hex notation assumes unsigned and is correct and not your code.
You need to cast a hexadecimal to a signed type depending on what is asked by some API.
Your code demonstrates this ( and is therefor wrong, because the initial declaration was wrong in the first place).

I can understand your frustration because many windows units in Pascal rely on signed types where they should have been unsigned.
This is rather common. You found a correct solution: assign to a longint if an API unit expects a longint. In this case it is an API bug....

« Last Edit: December 17, 2018, 12:29:31 pm by Thaddy »
Ad Brexinitum (can't help it)

nanobit

  • New member
  • *
  • Posts: 20
Re: longint range-check wrongly prevents compile
« Reply #2 on: December 17, 2018, 12:29:22 pm »
Thaddy, no casting in the call is working for me.
And SrcCopy is just copied declaration from
fpc\3.0.4\source\rtl\win\wininc\defines.inc

windows.makerop4( longint(Dst), longint(SrcCopy)); // gives the same error
I understand your explanation, but this is not the problem here.

Thaddy

  • Hero Member
  • *****
  • Posts: 7610
Re: longint range-check wrongly prevents compile
« Reply #3 on: December 17, 2018, 12:29:59 pm »
re-read my reply. I editted it
What I wrote is a fact. Casting the hex value to a longint or assigning to a longint is correct. See e.g. https://docs.microsoft.com/en-us/windows/desktop/api/wingdi/nf-wingdi-bitblt
And hex values are unsigned.
« Last Edit: December 17, 2018, 12:38:20 pm by Thaddy »
Ad Brexinitum (can't help it)

nanobit

  • New member
  • *
  • Posts: 20
Re: longint range-check wrongly prevents compile
« Reply #4 on: December 17, 2018, 12:57:28 pm »
Ok, we have a solution (longint-typed constant) to workaround this,
but the following appears still strange:
1) longint typecast placed in the call does not remove the error-message
2) in the error message, $00CC0020 is referred to as 3422560256 ($CC002000)

Bart

  • Hero Member
  • *****
  • Posts: 3360
    • Bart en Mariska's Webstek
Re: longint range-check wrongly prevents compile
« Reply #5 on: December 17, 2018, 01:26:05 pm »
Show us the complete code (a minimal test case) please, not just snippets.

Bart

nanobit

  • New member
  • *
  • Posts: 20
Re: longint range-check wrongly prevents compile
« Reply #6 on: December 17, 2018, 02:25:42 pm »
Code: Pascal  [Select]
  1. program test;
  2. {$R+}
  3.  
  4. uses
  5.   windows;
  6.  
  7. const
  8.   Dst = $00AA0029;
  9.   SrcCopy = $00CC0020;
  10. begin
  11. windows.makerop4( longint(Dst), longint(SrcCopy));
  12.  
  13. { halts with message:
  14. "test.lpr(11,1) Error: range check error while evaluating constants (3422560256 must be between -2147483648 and 2147483647)"
  15. }
  16. end.    
  17.  

josh

  • Hero Member
  • *****
  • Posts: 719
Re: longint range-check wrongly prevents compile
« Reply #7 on: December 17, 2018, 03:28:26 pm »
Hi

Not near a computer with Lazarus on at the moment.
When I have assigned const hex I explicity declare the type being used
ie
Const Dst:LongWord=$00AA0029;

Does this help?
Development Installation Lazarus 1.3, FPC 2.7.1,Windows 7/8 32/64, OSX, *nix

Test Environment Lazarus & FPC Trunk on Windows and OSX (Cocoa Mainly on OSX). Testing also Crosscompile windows to OSX.. 
Any posts made from 2015 will be based on Lazarus Trunk.

nanobit

  • New member
  • *
  • Posts: 20
Re: longint range-check wrongly prevents compile
« Reply #8 on: December 17, 2018, 03:43:21 pm »
Only typeless constants don't work.
Typed (longword, longint, dword) work.

Thaddy

  • Hero Member
  • *****
  • Posts: 7610
Re: longint range-check wrongly prevents compile
« Reply #9 on: December 17, 2018, 05:05:13 pm »
Only typeless constants don't work.
Typed (longword, longint, dword) work.
That is correct. (As I already pointed out). Hex literals may be even FPC version dependent. Currently hex literals are always UNsigned.
E.g:
$FF = 255 (a byte value) but shortint($FF) = -1
$FFFF = 65536 (a word value) but smallint($FFFF) = -1
etc..
If you mix integer values with hex literals that will give range errors.

The same goes for binary  - % -  literals and octal - & - literals, these are also always UNsigned. Decimal literals are  different depending on value.

An cast, or assignment to a var or typed const can change the literal to signed. As you observed. And is the only correct behavior.
« Last Edit: December 17, 2018, 05:21:13 pm by Thaddy »
Ad Brexinitum (can't help it)

ASerge

  • Hero Member
  • *****
  • Posts: 1122
Re: longint range-check wrongly prevents compile
« Reply #10 on: December 17, 2018, 05:30:27 pm »
I think there is an error in the function implementation (bug).
This original implementation:
Code: Pascal  [Select]
  1. function MAKEROP4(fore,back : longint) : DWORD; inline;
  2. begin
  3.   MAKEROP4:=DWORD((DWORD(back shl 8) and $FF000000) or DWORD(fore));
  4. end;
this corrected implementation:
Code: Pascal  [Select]
  1. function MAKEROP4(fore,back : longint) : DWORD; inline;
  2. begin
  3.   MAKEROP4:=DWORD(((DWORD(back) shl 8) and $FF000000) or DWORD(fore));
  4. end;
In the original, the expression "back shl 8" is evaluated at compile time (all constants, inline) and causes an error. If you make "DWORD(back) shl 8", no error occurs.

Thaddy

  • Hero Member
  • *****
  • Posts: 7610
Re: longint range-check wrongly prevents compile
« Reply #11 on: December 17, 2018, 05:40:29 pm »
@ASerge
You are right. (for the same theoretical reasons I explained).
That is a bug.

Here the hex literals are passed as longint parameters - so they are treated as valid longints -, but they need to be treated as unsigned internally to have valid results for the shift.
I forgot to look into the underlying code.
Code: Pascal  [Select]
  1. function MAKEROP4(fore,back : longword) : longword; inline;
  2. begin
  3.   result:= back shl 8 and $FF000000 or fore;
  4. end;
also makes more sense. All the brackets disappear, btw...

[edit]
Note the version from winunits-jedi is - almost - correct! (Why do some programmers have such trouble with operator precedence? , sigh)

I filed bug report 0034712 on Mantis
 
« Last Edit: December 17, 2018, 07:27:20 pm by Thaddy »
Ad Brexinitum (can't help it)

nanobit

  • New member
  • *
  • Posts: 20
Re: longint range-check wrongly prevents compile
« Reply #12 on: December 18, 2018, 08:39:20 am »
This explains the value (3422560256) in the error message:
The compile error in the project-unit refers to an operation inside the inline code.
Not to parameter (SrcCopy = $00CC0020), but to value $CC002000 ( = back shl 8 ).

The following gives the same compile-error:
const SrcCopy = $00CC0020; // error reported only if untyped
var back: longint; d: dword;
begin
back := SrcCopy;
d := dword( back shl 8 );

Thaddy

  • Hero Member
  • *****
  • Posts: 7610
Re: longint range-check wrongly prevents compile
« Reply #13 on: December 18, 2018, 08:44:26 am »
Correct observation: an untyped integer const is always a signed integer type. So assigning a hex value to it has the same issue as you observed before.
I am quite sure the bug will be fixed. You can also use my version of makerop4, which is correct and will not give range issues.

« Last Edit: December 18, 2018, 08:52:27 am by Thaddy »
Ad Brexinitum (can't help it)