Recent

Author Topic: likely bug in FPC v3.2.2 handling of booleans  (Read 8352 times)

440bx

  • Hero Member
  • *****
  • Posts: 6063
Re: likely bug in FPC v3.2.2 handling of booleans
« Reply #45 on: January 29, 2025, 12:50:40 am »
And does not hold up for the boolean16 type.
I don't think I am getting what you mean.  Can you elaborate please ?  Thank you.
FPC v3.2.2 and Lazarus v4.0rc3 on Windows 7 SP1 64bit.

TRon

  • Hero Member
  • *****
  • Posts: 4377
Re: likely bug in FPC v3.2.2 handling of booleans
« Reply #46 on: January 29, 2025, 12:57:15 am »
I don't think I am getting what you mean.  Can you elaborate please ?  Thank you.
According to documentation:
Quote
In addition to the simple Boolean type, the additional Boolean16, Boolean32 and Boolean64 types exist. These are in fact integer types, which are assignment-compatible with the simple boolean type. As an integer, the values for True and False are 1 and 0. This can be used to interface with C code that defines a boolean of this size with values 0 and 1.
So, while the statement you made might be true for the boolean type (as details other than written are further undocumented) this allows for the interpretation that you can assign an integer value to a boolean16 or boolean32 type.

 If you look at the modified example from martin that I posted, that fails miserably for boolean (unable to compare the booleans against each other) but can perhaps be described as being undefined behaviour. Doing the same for boolean16 does work as intended and according to the bolded part also should (imho).

Nonetheless, 0 is zero and 1 is one *period*
« Last Edit: January 29, 2025, 01:00:15 am by TRon »
Today is tomorrow's yesterday.

440bx

  • Hero Member
  • *****
  • Posts: 6063
Re: likely bug in FPC v3.2.2 handling of booleans
« Reply #47 on: January 29, 2025, 01:11:07 am »
this allows for the interpretation that you can assign an integer value to a boolean16 or boolean32 type.
I see your point now, thank you for clarifying. 

However, the sentence that follows reinforces that even for those types, the values for TRUE and FALSE are 1 and 0 (respectively).  Therefore, IMO, they should still be treated as harboring a single bit thus unable to accommodate values greater than 1.
FPC v3.2.2 and Lazarus v4.0rc3 on Windows 7 SP1 64bit.

TRon

  • Hero Member
  • *****
  • Posts: 4377
Re: likely bug in FPC v3.2.2 handling of booleans
« Reply #48 on: January 29, 2025, 01:28:22 am »
I see your point now, thank you for clarifying. 
No problem. fwiw the fact that in your original example the code does the casts the other way around should imho not matter.

Quote
However, the sentence that follows reinforces that even for those types, the values for TRUE and FALSE are 1 and 0 (respectively).  Therefore, IMO, they should still be treated as harboring a single bit thus unable to accommodate values greater than 1.
Although in general I agree with that interpretation I am however a bit more hesitant because the following:
Quote
The only difference with the Boolean16/32/64 types
So while that reinforces that it is possible for bool16/32/64 to be assigned an integer the documentation cleverly leaves out the boolean type  :)

No matter what: ord(true) = 1 as per documentation and that clearly isn't the case (whatever booleanXX type) . That is why I ended my previous reply last sentence with period because something is off. Wouldn't surprise me if that would be caused by Delphi sickness  :D
Today is tomorrow's yesterday.

Fred vS

  • Hero Member
  • *****
  • Posts: 3773
    • StrumPract is the musicians best friend
Re: likely bug in FPC v3.2.2 handling of booleans
« Reply #49 on: January 29, 2025, 02:11:39 am »
Sorry to be a troublemaker but why use the problematic boolean?
It's easier to use byte and if result < 1 it's false and if result > 0 it's true.

Unless you accidentally use a signed expression. So use <>0.

Hum, the trick mentioned: It's easier to use byte

So using byte(-25) will give 231 as result who is, imho, > 0.
The same for every value, even > 256 or < 0, the value is always unsigned.

The same if you use a boolean:
Code: Pascal  [Select][+][-]
  1. var
  2. abool : boolean = false;
  3. ...
  4. writeln(byte(abool)); // will give 0 as result and 1 if abool is true.

Or, of course, once again, I miss something.  :-[
« Last Edit: January 29, 2025, 02:26:04 am by Fred vS »
I use Lazarus 2.2.0 32/64 and FPC 3.2.2 32/64 on Debian 11 64 bit, Windows 10, Windows 7 32/64, Windows XP 32,  FreeBSD 64.
Widgetset: fpGUI, MSEgui, Win32, GTK2, Qt.

https://github.com/fredvs
https://gitlab.com/fredvs
https://codeberg.org/fredvs

ASerge

  • Hero Member
  • *****
  • Posts: 2475
Re: likely bug in FPC v3.2.2 handling of booleans
« Reply #50 on: January 29, 2025, 02:42:09 am »
..., the compiler "tolerates" assignments like that because underlying the boolean type is an integer type
But this is explicit typecast, so programmer take responsibility for what follows. In this case, the used the wrong type, so he ran into a problem.

440bx

  • Hero Member
  • *****
  • Posts: 6063
Re: likely bug in FPC v3.2.2 handling of booleans
« Reply #51 on: January 29, 2025, 03:52:56 am »
..., the compiler "tolerates" assignments like that because underlying the boolean type is an integer type
But this is explicit typecast, so programmer take responsibility for what follows. In this case, the used the wrong type, so he ran into a problem.
That is a reasonable argument but... the compiler isn't allowed to do things wrong because the programmer did it wrong.  IOW, no matter what the programmer does, the compiler is still expected to do what is correct.

The compiler's acceptance of invalid typecasts doesn't absolve it from producing code that enforces the specs that define a boolean, which is, 0 = false and 1 = true. 

Additionally, the compiler should reject that cast because it is invalid.  The compiler should treat a true/genuine boolean type as being a single bit type and neither 4 nor 8 fit in a single bit, therefore those casts are invalid and the compiler should reject them the same way it rejects a cast such as "integer(b8) := 4;"

I think there is a good argument to be made that accepting those casts is itself a bug (but, I know the developers wouldn't go for it because it would be too inconvenient.)
FPC v3.2.2 and Lazarus v4.0rc3 on Windows 7 SP1 64bit.

TRon

  • Hero Member
  • *****
  • Posts: 4377
Re: likely bug in FPC v3.2.2 handling of booleans
« Reply #52 on: January 29, 2025, 04:41:25 am »
Code: Pascal  [Select][+][-]
  1. var
  2.   a : boolean = false;
  3.   i : integer;
  4. begin
  5.   for i := 1 to 10 do
  6.   begin
  7.     writeln('a(',i,') ord(a) = ', ord(a), ' a = ', a);
  8.     inc(a);
  9.   end;
  10. end.
  11.  

Programmer's mistake #42  :-X
Today is tomorrow's yesterday.

440bx

  • Hero Member
  • *****
  • Posts: 6063
Re: likely bug in FPC v3.2.2 handling of booleans
« Reply #53 on: January 29, 2025, 09:39:06 am »
I thought it would be appropriate to mention that the statement:

Code: Pascal  [Select][+][-]
  1. ord(b8) := 4;
Is not acceptable to Delphi.  Delphi does consider "ord" to be a function and as such cannot be assigned a value.

FPC "sees" it a different way (likely as just a cast)
FPC v3.2.2 and Lazarus v4.0rc3 on Windows 7 SP1 64bit.

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 12630
  • FPC developer.
Re: likely bug in FPC v3.2.2 handling of booleans
« Reply #54 on: January 29, 2025, 10:04:19 am »
Bugs that make a case about giving undefined values of booleans meaning have been closed with "won't fix" for decades, and IMHO rightfully so because it inhibits optimisations.

I don't think that this way of reasoning will amount to much.

440bx

  • Hero Member
  • *****
  • Posts: 6063
Re: likely bug in FPC v3.2.2 handling of booleans
« Reply #55 on: January 29, 2025, 11:20:14 am »
Bugs that make a case about giving undefined values of booleans meaning have been closed with "won't fix" for decades, and IMHO rightfully so because it inhibits optimisations.

I don't think that this way of reasoning will amount to much.
The compiler should not accept those values, it knows they are invalid.  If, for whatever reason, the compiler allows them then it is its responsibility to ensure they do not get in the way of ensuring logical correctness.  Given that Pascal is supposed to be a strongly typed language those definitions should be unacceptable, just as "integer(b8) := 4;" is unacceptable.

A boolean is a single bit.  The only reason it is represented with a byte, word, dword or qword is to allow addressability since no CPU (at least that I know of) allows addressing single bits.  Addressability does not change the fact that the storage size of a boolean is 1 bit.

Lastly, the compiler's first and foremost responsibility is to produce correct code. speed, optimizations or any other concerns are secondary to that one.  IOW, optimizations and speed concerns do not justify producing incorrect code.
FPC v3.2.2 and Lazarus v4.0rc3 on Windows 7 SP1 64bit.

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 12630
  • FPC developer.
Re: likely bug in FPC v3.2.2 handling of booleans
« Reply #56 on: January 29, 2025, 11:33:40 am »
Lastly, the compiler's first and foremost responsibility is to produce correct code. speed, optimizations or any other concerns are secondary to that one.  IOW, optimizations and speed concerns do not justify producing incorrect code.

Non 0/1 values are considered undefined, and any operation on such variable gives an undefined result.

The reason to leave it that way is optimisation.   Trying to close those gaps to assign values to booleans only complicates the RTL and people writing streaming code for booleans, for at best hypothetical gains.

440bx

  • Hero Member
  • *****
  • Posts: 6063
Re: likely bug in FPC v3.2.2 handling of booleans
« Reply #57 on: January 29, 2025, 11:58:44 am »
Lastly, the compiler's first and foremost responsibility is to produce correct code. speed, optimizations or any other concerns are secondary to that one.  IOW, optimizations and speed concerns do not justify producing incorrect code.

Non 0/1 values are considered undefined, and any operation on such variable gives an undefined result.
And how do you justify the compiler accepting "ord(b8) := 4;" while rejecting "integer(b8) := 4;", it is rather easy to reject the first one too.  Why should the compiler allow "undefined" values ?  How can that be justified ?  (code wise it's rather simple to disallow those undefined boolean values. However, that is not sufficient, the code the compiler generates needs to be changed because it is incorrect even when the compiler prevents undefined values.)

The reason to leave it that way is optimisation.   Trying to close those gaps to assign values to booleans only complicates the RTL and people writing streaming code for booleans, for at best hypothetical gains.
Did optimization (or speed) become more important than correctness ?   if correctness still rules the day then a change in FPC is necessary.  Bugs are inconvenient and fixing them is usually inconvenient too but, that isn't normally a reason given to leave them uncorrected.

Also,

The documentation states:
Quote
Free Pascal supports the Boolean type, with its two predefined possible values True and False.
These are the only two values that can be assigned to a Boolean type.
...
In addition to the simple Boolean type, the additional Boolean16, Boolean32 and Boolean64
types exist. These are in fact integer types, which are assignment-compatible with the simple boolean
type. As an integer, the values for True and False are 1 and 0.
Emphasis mine.  The typecasts show that TRUE and FALSE are most definitely NOT the only two values that can be assigned to a Boolean type.

Now the problem is, the documentation is correct but the compiler is not operating as the spec/documentation requires.

Possible fixes:

a. "amend" the documentation to state the compiler allows values other than TRUE and FALSE for a boolean.
or
b. correct the compiler so it treats booleans correctly.

if (a) then it would be nice to include a warning in the documentation that unpredictable results should be expected in that case.  It would also be nice if the compiler emitted a warning stating as much too.

if (b) then the compiler would operate as documented which is a nice plus (correctness: 1, optimizations: do it right first, then do it faster while keeping it right)
FPC v3.2.2 and Lazarus v4.0rc3 on Windows 7 SP1 64bit.

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 12630
  • FPC developer.
Re: likely bug in FPC v3.2.2 handling of booleans
« Reply #58 on: January 29, 2025, 12:09:55 pm »
And how do you justify the compiler accepting "ord(b8) := 4;" while rejecting "integer(b8) := 4;", it is rather easy to reject the first one too. 

That is because the lvalue size doesn't match for a typecast, and you can't assign to a conversion.

Code: Pascal  [Select][+][-]
  1. var b : boolean;
  2.  
  3. begin
  4.   b:=boolean(20);
  5.   byte(b):=4;  // match size
  6.   writeln(ord(b));
  7. end.
  8.  

Anyway I don't, I reacted to the outcome further along, the evaluation of a b16 with <>0 rather than =1. The ord() thing has nothing to do with optimization.

Quote
Why should the compiler allow "undefined" values ? 

Because if they were defined, additional code of would have to be generated to address scenarios of low real value. And I already hinted on why access to those bits is allowed with typecasts, for variant and streaming code.

440bx

  • Hero Member
  • *****
  • Posts: 6063
Re: likely bug in FPC v3.2.2 handling of booleans
« Reply #59 on: January 29, 2025, 12:18:04 pm »
Because if they were defined, additional code of would have to be generated to address scenarios of low real value. And I already hinted on why access to those bits is allowed with typecasts, for variant and streaming code.
No.  The changes in the code would not have a significant impact on performance.  It may not even have any at all.

For instance, instead of having "cmp [rbp - 08], 0" it would have "and [rbp - 08], 1" to determine the truth value.  The performance difference is negligible and, that would be the case in other instances as well where the compiler (incorrectly) generates "or ax, ax" to determine if ax is nonzero instead of using an instruction to determine the value of the LSB.

The difference in the generated code is minimal and, disallowing invalid values is code wise trivial.

FPC v3.2.2 and Lazarus v4.0rc3 on Windows 7 SP1 64bit.

 

TinyPortal © 2005-2018