Free Pascal => Windows => Topic started by: nanobit on December 17, 2018, 12:01:22 pm
Title: longint range-check wrongly prevents compile
Post by: nanobit 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)
Title: Re: longint range-check wrongly prevents compile
Post by: Thaddy 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....
Title: Re: longint range-check wrongly prevents compile
Post by: nanobit 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.
Title: Re: longint range-check wrongly prevents compile
Post by: Thaddy 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.
Title: Re: longint range-check wrongly prevents compile
Post by: nanobit 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)
Title: Re: longint range-check wrongly prevents compile
Post by: Bart on December 17, 2018, 01:26:05 pm
Show us the complete code (a minimal test case) please, not just snippets.
Bart
Title: Re: longint range-check wrongly prevents compile
Post by: nanobit on December 17, 2018, 02:25:42 pm
"test.lpr(11,1) Error: range check error while evaluating constants (3422560256 must be between -2147483648 and 2147483647)"
}
end.
Title: Re: longint range-check wrongly prevents compile
Post by: Josh 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?
Title: Re: longint range-check wrongly prevents compile
Post by: nanobit on December 17, 2018, 03:43:21 pm
Only typeless constants don't work. Typed (longword, longint, dword) work.
Title: Re: longint range-check wrongly prevents compile
Post by: Thaddy 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.
Title: Re: longint range-check wrongly prevents compile
Post by: ASerge on December 17, 2018, 05:30:27 pm
I think there is an error in the function implementation (bug). This original implementation:
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.
Title: Re: longint range-check wrongly prevents compile
Post by: Thaddy 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.
function MAKEROP4(fore,back : longword): longword;inline;
begin
result:= back shl8and$FF000000or fore;
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
Title: Re: longint range-check wrongly prevents compile
Post by: nanobit 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 );
Title: Re: longint range-check wrongly prevents compile
Post by: Thaddy 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.