Recent

Author Topic: Range check error while evaluating constants  (Read 1372 times)

LemonParty

  • Hero Member
  • *****
  • Posts: 529
Range check error while evaluating constants
« on: September 14, 2025, 12:14:26 am »
Hello.

Can't compile code below:
Code: Pascal  [Select][+][-]
  1. {$mode objfpc}
  2. {$modeswitch advancedrecords}
  3.  
  4. type
  5.   Int24 = packed record
  6.     W: Word;
  7.     B: Byte;
  8.     class operator :=(aA: LongInt): Int24;inline;
  9.   end;
  10.  
  11.   class operator Int24.:=(aA: LongInt): Int24;
  12.   begin
  13.     Result.W:= Lo(aA);
  14.     Result.B:= Hi(aA);
  15.   end;
  16.  
  17. var
  18.   i24: Int24;
  19. begin
  20.   i24:= -5;
  21. end.
  22.  
Error
Quote
Range check error while evaluating constants (281474976710655 must be between 0 and 65535)
What I missing?
Lazarus v. 4.99. FPC v. 3.3.1. Windows 11

ASerge

  • Hero Member
  • *****
  • Posts: 2496
Re: Range check error while evaluating constants
« Reply #1 on: September 14, 2025, 01:09:17 am »
A workaround:
Code: Pascal  [Select][+][-]
  1.   class operator Int24. := (aA: LongInt): Int24;
  2.   var
  3.     bB: LongWord absolute aA;
  4.   begin
  5.     Result.W:= Lo(bB);
  6.     Result.B:= Hi(Hi(bB));
  7.   end;

Nitorami

  • Hero Member
  • *****
  • Posts: 605
Re: Range check error while evaluating constants
« Reply #2 on: September 14, 2025, 01:45:57 am »
What I don't understand here is how the compiler gets to 281474976710655 = $FFFF FFFF FFFF ?

jamie

  • Hero Member
  • *****
  • Posts: 7763
Re: Range check error while evaluating constants
« Reply #3 on: September 14, 2025, 02:29:06 am »
I thinking this is what he needs to do with the original code.

Code: Pascal  [Select][+][-]
  1. program Project1;
  2.  
  3. {$mode objfpc}{$H+}
  4. {$modeswitch advancedrecords}
  5.  
  6. type
  7.   Int24 = packed record
  8.     W: Word;
  9.     B: Byte;
  10.     class operator :=(aA: LongInt): Int24;inline;
  11.   end;
  12.  
  13.   class operator Int24.:=(aA: LongInt): Int24;
  14.   begin
  15.     Result.W:= Lo(aA);
  16.     Result.B:= Lo(Word(aA shr 16)); // fixed here.
  17.   end;
  18.  
  19. var
  20.   i24: Int24;
  21. begin
  22.   i24:= -5;
  23. end.                        
  24.  
  25.  

@Serge:
  neat trick, never thought of using double HI.

Jamie
« Last Edit: September 14, 2025, 02:31:14 am by jamie »
The only true wisdom is knowing you know nothing

jamie

  • Hero Member
  • *****
  • Posts: 7763
Re: Range check error while evaluating constants
« Reply #4 on: September 14, 2025, 02:37:31 am »
@Aserge
shouldn't it be like this?

Code: Pascal  [Select][+][-]
  1.   class operator Int24.:=(aA: LongInt): Int24;
  2.   begin
  3.     Result.W:= Lo(aA);
  4.     Result.B:= Lo(Hi(LongWord(aA)));
  5.   end;
  6.                                                
  7.  

I would think the upper byte would be at the lower end unless we are doing Big Endian?

Jamie
The only true wisdom is knowing you know nothing

jamie

  • Hero Member
  • *****
  • Posts: 7763
Re: Range check error while evaluating constants
« Reply #5 on: September 14, 2025, 03:03:08 am »
I see the issue now.

You need to set the upper bit of the Byte to what is was originally so the (-) flag will carry over.

so like this..

If aA < 0 Then B := B or $80 else B:=B and $7F;

that should be done after the mov.

Code: Pascal  [Select][+][-]
  1.  class operator Int24.:=(aA: LongInt): Int24;
  2.   begin
  3.      Result.W:= Lo(aA);
  4.      Result.B:= Lo(Hi(LongWord(aA)));
  5.      If aA <0 Then result.B := Result.B or $80 else
  6.         Result.B := Result.B and $7F;
  7.   end;                          
  8.  
  9.  

Something like that.

« Last Edit: September 14, 2025, 03:12:43 am by jamie »
The only true wisdom is knowing you know nothing

Thaddy

  • Hero Member
  • *****
  • Posts: 19262
  • Glad to be alive.
Re: Range check error while evaluating constants
« Reply #6 on: September 14, 2025, 10:04:53 am »
You can also just declare the byte as shortint (-128..127) because that is what you mean with a signed type.
I think :
Code: Pascal  [Select][+][-]
  1. {$mode objfpc}{$modeswitch advancedrecords}
  2. type
  3.   Int24 = packed record
  4.     B: shortint;// msb+sign
  5.     W: Word;    // lsw
  6.     class operator :=(const aA: LongInt): Int24;inline;
  7.     class operator :=(const aA: Int24): longint;inline;
  8.  end;
  9.  
  10.   class operator Int24.:=(const aA: LongInt): Int24;
  11.   begin
  12.     Result.W:= Lo(aA);
  13.     Result.B:= shortint(aA shr 24);//preserves sign
  14.   end;
  15.  
  16.   class operator Int24.:=(const aA: Int24): longint;inline;
  17.   begin
  18.     Result:=aA.b shl 16 + aA.w;
  19.   end;
  20.  
  21. var
  22.   i24: Int24;
  23.   i:integer;
  24. begin
  25.   i24:= -5;
  26.   i := i24;
  27.   writeln(i);
  28. end.
« Last Edit: September 14, 2025, 01:58:37 pm by Thaddy »
objects are fine constructs. You can even initialize them with constructors.

LemonParty

  • Hero Member
  • *****
  • Posts: 529
Re: Range check error while evaluating constants
« Reply #7 on: September 14, 2025, 02:00:20 pm »
Thank you for answers.
I discovered that this solution is also working:
Code: Pascal  [Select][+][-]
  1.   class operator Int24.:=(aA: LongInt): Int24;
  2.   begin
  3.     Result.W:= Lo(DWord(aA));
  4.     Result.B:= Hi(DWord(aA));
  5.   end;
  6.  
Lazarus v. 4.99. FPC v. 3.3.1. Windows 11

Thaddy

  • Hero Member
  • *****
  • Posts: 19262
  • Glad to be alive.
Re: Range check error while evaluating constants
« Reply #8 on: September 14, 2025, 02:10:52 pm »
And where's the sign? Doesn't work here without warnings.
objects are fine constructs. You can even initialize them with constructors.

LemonParty

  • Hero Member
  • *****
  • Posts: 529
Re: Range check error while evaluating constants
« Reply #9 on: September 14, 2025, 05:04:32 pm »
No warning in this case:
Code: Pascal  [Select][+][-]
  1.   class operator Int24.:=(constref aA: LongInt): Int24;
  2.   begin
  3.     Result.W:= Lo(DWord(aA));
  4.     Result.B:= Byte(Hi(DWord(aA)));
  5.   end;
  6.  
Sign is saved.
Lazarus v. 4.99. FPC v. 3.3.1. Windows 11

jamie

  • Hero Member
  • *****
  • Posts: 7763
Re: Range check error while evaluating constants
« Reply #10 on: September 14, 2025, 06:07:56 pm »
I doubt the sign bit is saved.

Look at my last post.

You at least need to put a range check on the incoming integer;
Jamie
« Last Edit: September 14, 2025, 06:16:31 pm by jamie »
The only true wisdom is knowing you know nothing

LemonParty

  • Hero Member
  • *****
  • Posts: 529
Re: Range check error while evaluating constants
« Reply #11 on: September 14, 2025, 07:44:20 pm »
I consider that incoming Longint is in range of 24-bit integer. In this case sign is OK. Extending integer is needed in opposite situation if we for example converting from Int16 to Int24.
Lazarus v. 4.99. FPC v. 3.3.1. Windows 11

jamie

  • Hero Member
  • *****
  • Posts: 7763
Re: Range check error while evaluating constants
« Reply #12 on: September 14, 2025, 07:53:20 pm »
Do as you please, but you won't be happen when your code starts entering integer values larger than 12 bit and you don't check for that.

The MSByte of the 32-bit incoming should be $FF or $00 for a valid 24bit value.

Have a good day and may your bugs be many! ;)

Jamie






The only true wisdom is knowing you know nothing

creaothceann

  • Sr. Member
  • ****
  • Posts: 375
Re: Range check error while evaluating constants
« Reply #13 on: September 17, 2025, 11:21:17 am »
Code: Pascal  [Select][+][-]
  1. {$mode ObjFPC}
  2. {$ModeSwitch AdvancedRecords}
  3.  
  4. {$ifdef ENDIAN_BIG}
  5.         {$fatal}
  6. {$endif}
  7.  
  8. interface
  9.  
  10. const Bit0  = 1 SHL  0;  Bits0  = Bit0  - 1;
  11. const Bit1  = 1 SHL  1;  Bits1  = Bit1  - 1;    type u1  = 0..Bits0;   i1  = -Bit0 ..Bits0;
  12. const Bit2  = 1 SHL  2;  Bits2  = Bit2  - 1;    type u2  = 0..Bits1;   i2  = -Bit1 ..Bits1;
  13. const Bit3  = 1 SHL  3;  Bits3  = Bit3  - 1;    type u3  = 0..Bits2;   i3  = -Bit2 ..Bits2;
  14. const Bit4  = 1 SHL  4;  Bits4  = Bit4  - 1;    type u4  = 0..Bits3;   i4  = -Bit3 ..Bits3;
  15. const Bit5  = 1 SHL  5;  Bits5  = Bit5  - 1;    type u5  = 0..Bits4;   i5  = -Bit4 ..Bits4;
  16. const Bit6  = 1 SHL  6;  Bits6  = Bit6  - 1;    type u6  = 0..Bits5;   i6  = -Bit5 ..Bits5;
  17. const Bit7  = 1 SHL  7;  Bits7  = Bit7  - 1;    type u7  = 0..Bits6;   i7  = -Bit6 ..Bits6;
  18. const Bit8  = 1 SHL  8;  Bits8  = Bit8  - 1;    type u8  = 0..Bits8;   i8  = -Bit7 ..Bits7;
  19. const Bit9  = 1 SHL  9;  Bits9  = Bit9  - 1;    type u9  = 0..Bits9;   i9  = -Bit8 ..Bits8;
  20. const Bit10 = 1 SHL 10;  Bits10 = Bit10 - 1;    type u10 = 0..Bits10;  i10 = -Bit9 ..Bits9;
  21. const Bit11 = 1 SHL 11;  Bits11 = Bit11 - 1;    type u11 = 0..Bits11;  i11 = -Bit10..Bits10;
  22. const Bit12 = 1 SHL 12;  Bits12 = Bit12 - 1;    type u12 = 0..Bits12;  i12 = -Bit11..Bits11;
  23. const Bit13 = 1 SHL 13;  Bits13 = Bit13 - 1;    type u13 = 0..Bits13;  i13 = -Bit12..Bits12;
  24. const Bit14 = 1 SHL 14;  Bits14 = Bit14 - 1;    type u14 = 0..Bits14;  i14 = -Bit13..Bits13;
  25. const Bit15 = 1 SHL 15;  Bits15 = Bit15 - 1;    type u15 = 0..Bits15;  i15 = -Bit14..Bits14;
  26. const Bit16 = 1 SHL 16;  Bits16 = Bit16 - 1;    type u16 = 0..Bits16;  i16 = -Bit15..Bits15;
  27. const Bit17 = 1 SHL 17;  Bits17 = Bit17 - 1;    type u17 = 0..Bits17;  i17 = -Bit16..Bits16;
  28. const Bit18 = 1 SHL 18;  Bits18 = Bit18 - 1;    type u18 = 0..Bits18;  i18 = -Bit17..Bits17;
  29. const Bit19 = 1 SHL 19;  Bits19 = Bit19 - 1;    type u19 = 0..Bits19;  i19 = -Bit18..Bits18;
  30. const Bit20 = 1 SHL 20;  Bits20 = Bit20 - 1;    type u20 = 0..Bits20;  i20 = -Bit19..Bits19;
  31. const Bit21 = 1 SHL 21;  Bits21 = Bit21 - 1;    type u21 = 0..Bits21;  i21 = -Bit20..Bits20;
  32. const Bit22 = 1 SHL 22;  Bits22 = Bit22 - 1;    type u22 = 0..Bits22;  i22 = -Bit21..Bits21;
  33. const Bit23 = 1 SHL 23;  Bits23 = Bit23 - 1;    type u23 = 0..Bits23;  i23 = -Bit22..Bits22;
  34. const Bit24 = 1 SHL 24;  Bits24 = Bit24 - 1;    type u24 = 0..Bits24;  i24 = -Bit23..Bits23;
  35. const Bit25 = 1 SHL 25;  Bits25 = Bit25 - 1;    type u25 = 0..Bits25;  i25 = -Bit24..Bits24;
  36. const Bit26 = 1 SHL 26;  Bits26 = Bit26 - 1;    type u26 = 0..Bits26;  i26 = -Bit25..Bits25;
  37. const Bit27 = 1 SHL 27;  Bits27 = Bit27 - 1;    type u27 = 0..Bits27;  i27 = -Bit26..Bits26;
  38. const Bit28 = 1 SHL 28;  Bits28 = Bit28 - 1;    type u28 = 0..Bits28;  i28 = -Bit27..Bits27;
  39. const Bit29 = 1 SHL 29;  Bits29 = Bit29 - 1;    type u29 = 0..Bits29;  i29 = -Bit28..Bits28;
  40. const Bit30 = 1 SHL 30;  Bits30 = Bit30 - 1;    type u30 = 0..Bits30;  i30 = -Bit29..Bits29;
  41. const Bit31 = 1 SHL 31;  Bits31 = Bit31 - 1;    type u31 = 0..Bits31;  i31 = -Bit30..Bits30;
  42. const Bit32 = 1 SHL 32;  Bits32 = Bit32 - 1;    type u32 = 0..Bits32;  i32 = -Bit31..Bits31;  uint = u32;  int = int32;
  43.  
  44.  
  45. type
  46.         Int24 = packed record
  47.                 L : u16;
  48.                 H : u8;
  49.  
  50.                 class operator :=(const Value : i32) : Int24;  inline;
  51.                 end;
  52.  
  53.  
  54. implementation
  55.  
  56.  
  57. type
  58.         u32_record = packed record
  59.                 case uint of
  60.                         0: (b0, b1, b2, b3 : u8 );
  61.                         1: (w0,     w1     : u16);
  62.                         2: (d0             : u32);
  63.                 end;
  64.  
  65.  
  66. class operator Int24.:=(const Value : i32) : Int24;  inline;
  67. var
  68.         v : u32_record absolute Value;
  69. begin
  70.         Assert(     v.b3 in [$00, $FF]);
  71.         Result.L := v.w0;
  72.         Result.H := v.b2;
  73. end;
  74.  
  75.  
  76. var
  77.         tmp_i24 : Int24;
  78.  
  79.  
  80. begin
  81.         tmp_i24 := -5;
  82. end.
  83.  
« Last Edit: September 17, 2025, 06:39:59 pm by creaothceann »

 

TinyPortal © 2005-2018