Recent

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

440bx

  • Hero Member
  • *****
  • Posts: 6063
Re: likely bug in FPC v3.2.2 handling of booleans
« Reply #30 on: January 28, 2025, 09:46:23 pm »
"One is the only one that yields true" is a half truth.
Table 3.4 Boolean types clearly indicates that the value 1 is the only value considered TRUE for Boolean, Boolean16, Boolean32 and Boolean64.    When other values are considered TRUE, the table indicates "any nonzero value" and that is not what it states for those types. 

IOW, according to the documentation, if ord(boolean_var) <> 1 then boolean_var is supposedly FALSE.  Supposedly, that's the difference between the BooleanXX and the xxxBool type family.

OTH, the compiler doesn't see it that way depending on how the variable is being used. 




On a different note, the statement "ord(b8) := 4" can be subsituted by "b8 := boolean(4)" and there is no change whatsoever in the results and code generated.  IOW, the statements are functionally and semantically equivalent.   The same applies to b16.
« Last Edit: January 28, 2025, 09:48:01 pm by 440bx »
FPC v3.2.2 and Lazarus v4.0rc3 on Windows 7 SP1 64bit.

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 12073
  • Debugger - SynEdit - and more
    • wiki
Re: likely bug in FPC v3.2.2 handling of booleans
« Reply #31 on: January 28, 2025, 10:08:00 pm »
Table 3.4 Boolean types clearly indicates that the value 1 is the only value considered TRUE for Boolean, Boolean16, Boolean32 and Boolean64.    When other values are considered TRUE, the table indicates "any nonzero value" and that is not what it states for those types. 

IOW, according to the documentation, if ord(boolean_var) <> 1 then boolean_var is supposedly FALSE.  Supposedly, that's the difference between the BooleanXX and the xxxBool type family.

Then at best it is an issue with the documentation.
- Which does not contain explicitly the statement, that the only allowed ordinal values are 0 and 1.
- Or in other words that "0 is the only value that yields false"
- Mind that also nowhere in that documentation it says that "every value <> 1 yields false".
- And it certainly does not state that every ordinal (or every ordinal fitting into a given size) is a valid input.

It does say
Quote
with its two predefined possible values
and
Quote
As an integer, the values for True and False are 1 and 0.
(if a boolean value is interpreted as an integer then....)

The only ordinal value that the documentation actually states to be false is 0.

All other value are not specified in the documentation (for Boolean / they are for ByteBool).
And that makes sense. As far as the documentation should be concerned, they do not exist. They are not defined.

it also does not state what happens for
MyByteBool = 256 
MyByteBool = 257
Those are range check errors, but if not caught, they may yield one of the 2 boolean values.
Especially, if unlucky, and by random chance the 256 (even it is not zero) may yield False in a ByteBool. Yet it may not in all cases.... (don't know)


But feel free to ask for the documentation to be more explicit.


440bx

  • Hero Member
  • *****
  • Posts: 6063
Re: likely bug in FPC v3.2.2 handling of booleans
« Reply #32 on: January 28, 2025, 10:22:42 pm »
but the issue is simply that he seems to think Ord() is a cast, whereas it is of course a function.
Then why
Code: Pascal  [Select][+][-]
  1. ord(b8)  := 4;
is compiled at all?

You cannot do that with a function:
Code: Pascal  [Select][+][-]
  1. function BoolToInt(b: boolean): longint;
  2. begin
  3.     Result := ord(b);
  4. end;
  5. . . .
  6.  
  7. BoolToInt(b8) := 4;
  8.  
is not compiled with "Error: Argument cannot be assigned to".

@Zoran, the reason for the error is because a function's result cannot be set outside the function which is what "BoolToInt(b8) := 4;" tries to do.

That shows that the compiler doesn't see "ord" as a function but as a cast, otherwise "ord(b8) := 4;" would not be acceptable.  The advantage of using "ord" as a cast is that "ord" adapts to the size of its argument whereas a specific type does not.  IOW, trying "integer(b8) := 4;" fails because b8 is too small to be cast to integer. For a cast to work it would need to be cast to "Shortint" or "Byte".  Ord spares the programmer from having to take argument size into consideration.  That's another reason why "ord" shouldn't be considered a function, a function's result, unlike ord, _cannot_vary in size.

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

440bx

  • Hero Member
  • *****
  • Posts: 6063
Re: likely bug in FPC v3.2.2 handling of booleans
« Reply #33 on: January 28, 2025, 10:50:57 pm »
@Martin,

The _strict_, _mathematical_ and _correct_ definition of a boolean is an object (not in the sense of OOP) that can only have two (2) values: 0 and 1.  Nothing else is allowed.  By convention, 1 is usually considered to be TRUE and 0 usually considered FALSE.

Problems sometimes arise because of the fact that booleans are usually represented with 8, 16, 32 or 64 bits which is a lot more than the 1 bit required for 0 and 1.

Strictly speaking in the byte, word, dword and qword used to represent a boolean, only 1 bit is significant, the rest of the bits are uninvited guests the compiler has no business accounting for under _any_ circumstances and the code it generates _must_ account for that.    Code that in any way allows those extra bits to alter the truth value is simply incorrect.

The documentation is correct, for those types, only the value 1 is TRUE and, the documentation implies by its stating "with its two predefined values True and False" that, only the value 0 is FALSE. 

In some situations, the code generated by the compiler, FPC in this case, fails to enforce that condition.  That is a bug and it is made evident when the inconsistent treatment yields different truth values assigned to _bits_ when going from a larger types to a single bit type.

Lastly, it is important to note that ByteBool, WordBool, LongBool and QWordBool are _not_ booleans, they are a C-ism where 0 is FALSE and any other value is TRUE.  That is NOT what a boolean is, consequently the rules that apply to them are different.
« Last Edit: January 28, 2025, 10:55:18 pm by 440bx »
FPC v3.2.2 and Lazarus v4.0rc3 on Windows 7 SP1 64bit.

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 12073
  • Debugger - SynEdit - and more
    • wiki
Re: likely bug in FPC v3.2.2 handling of booleans
« Reply #34 on: January 28, 2025, 11:00:04 pm »
Well, we are talking about Pascal, not about Maths.

But, yes, the 1 or 0 rule remains (for the non "ByteBool").

And yes, the other bits are an error (in the sense of "not allowed"). And I have been saying that. If they are set, then the behaviour is undefined => as behaviour for "not allowed" values is throughout fpc generated code. Code simply does not check for that, it simply makes assumptions, and that is fine as valid code would never break them.

And, yeah different topic, don't make assumptions....


TRon

  • Hero Member
  • *****
  • Posts: 4377
Re: likely bug in FPC v3.2.2 handling of booleans
« Reply #35 on: January 28, 2025, 11:02:41 pm »
But, yes, the 1 or 0 rule remains (for the non "ByteBool").
Are you sure about that ?

Code: Pascal  [Select][+][-]
  1.   writeln('boolean(0) = ', boolean(0));
  2.   writeln('boolean(1) = ', boolean(1));
  3.   writeln('boolean(2) = ', boolean(2));
  4.   writeln('boolean(3) = ', boolean(3));
  5.   writeln('boolean(128) = ', boolean(128));
  6.  
Today is tomorrow's yesterday.

440bx

  • Hero Member
  • *****
  • Posts: 6063
Re: likely bug in FPC v3.2.2 handling of booleans
« Reply #36 on: January 28, 2025, 11:10:52 pm »
Well, we are talking about Pascal, not about Maths.
Pascal is implementing a Mathematical concept, therefore it has to be true to the mathematical definition.   IOW, Pascal cannot give itself the luxury of redefining mathematical concepts.

And yes, the other bits are an error (in the sense of "not allowed"). And I have been saying that. If they are set, then the behaviour is undefined => as behaviour for "not allowed" values is throughout fpc generated code. Code simply does not check for that, it simply makes assumptions, and that is fine as valid code would never break them.
No.  The behavior is not undefined.  It is _defined_ that only 1 bit is significant and that is from the definition of boolean (only 2 values, 0 and 1).  Therefore, whenever FPC is allowing other bits that are neither here nor there to alter the meaning of the 1 bit that matters, that's a well defined bug.
FPC v3.2.2 and Lazarus v4.0rc3 on Windows 7 SP1 64bit.

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 12073
  • Debugger - SynEdit - and more
    • wiki
Re: likely bug in FPC v3.2.2 handling of booleans
« Reply #37 on: January 28, 2025, 11:16:42 pm »
But, yes, the 1 or 0 rule remains (for the non "ByteBool").
Are you sure about that ?

Code: Pascal  [Select][+][-]
  1.   writeln('boolean(0) = ', boolean(0));
  2.   writeln('boolean(1) = ', boolean(1));
  3.   writeln('boolean(2) = ', boolean(2));
  4.   writeln('boolean(3) = ', boolean(3));
  5.   writeln('boolean(128) = ', boolean(128));
  6.  

Yes, (but ask someone from the fpc team, if you don't believe me => they defined the rules what the compiler should see in the language).


Mind that "only 1 or 2" means the rest has no defined behaviour. => It may still give the "expected" (as expected by you) result by chance.
But then you update the compiler, change a setting, change seemingly unrelated code, and it may not give the "expected" result.

Code: Pascal  [Select][+][-]
  1. program Project1;
  2. var a,b: boolean;
  3. begin
  4.   a := Boolean(2);
  5.   b := Boolean(3);
  6.   if a=b then writeln('!');
  7.   readln;
  8. end.
  9.  

For me prints nothing. But its not defined.
Using ByteBool, it will print.


TRon

  • Hero Member
  • *****
  • Posts: 4377
Re: likely bug in FPC v3.2.2 handling of booleans
« Reply #38 on: January 28, 2025, 11:25:37 pm »
Yes, (but ask someone from the fpc team, if you don't believe me => they defined the rules what the compiler should see in the language).


Mind that "only 1 or 2" means the rest has no defined behaviour. => It may still give the "expected" (as expected by you) result by chance.
But then you update the compiler, change a setting, change seemingly unrelated code, and it may not give the "expected" result.
That might very well be the case but the documentation is clear. 0 or 1, nothing else.

The example-code I used definitely does not adhere to the documentation. Even stronger the results from that code seem to suggest 0 (and only 0) is false and every bool not zero is treated as true (size of the boolean does not matter btw).

Even if the compiler does something different to it as an expression rather than f.e. assigning it to an actual boolean typed variable then there certainly is something off there.

Perhaps someone of the FPC team (w/c)ould indeed comment on that.
Today is tomorrow's yesterday.

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 12073
  • Debugger - SynEdit - and more
    • wiki
Re: likely bug in FPC v3.2.2 handling of booleans
« Reply #39 on: January 28, 2025, 11:26:39 pm »
Well, we are talking about Pascal, not about Maths.
Pascal is implementing a Mathematical concept, therefore it has to be true to the mathematical definition.   IOW, Pascal cannot give itself the luxury of redefining mathematical concepts.

And yes, the other bits are an error (in the sense of "not allowed"). And I have been saying that. If they are set, then the behaviour is undefined => as behaviour for "not allowed" values is throughout fpc generated code. Code simply does not check for that, it simply makes assumptions, and that is fine as valid code would never break them.
No.  The behavior is not undefined.  It is _defined_ that only 1 bit is significant and that is from the definition of boolean (only 2 values, 0 and 1).  Therefore, whenever FPC is allowing other bits that are neither here nor there to alter the meaning of the 1 bit that matters, that's a well defined bug.

Feel free to take that up with the FPC team.

If they document it, to explicitly state something different from what I said, then please let me know, so I can update my knowledge.

For all else, and until then, since my statements are based on what I have learned about Pascal from the FPC team (by various direct and indirect means). It has worked well till here. I will continue to base my work on that knowledge, because at this time I believe I have better chances at success by following the FPC team on this particular topic, than following your definitions. Especially when they match exactly what the compiler does. (As confirmation of the info gained from trusted sources / not otherwise relevant)




TRon

  • Hero Member
  • *****
  • Posts: 4377
Re: likely bug in FPC v3.2.2 handling of booleans
« Reply #40 on: January 28, 2025, 11:44:40 pm »
@Martin_fr
btw and fwiw in your example (thank you for that because it is a perfect illustration for the confusion in case there is any) the reason that those two booleans are not the same is because their ordinal value differ, and not their boolean value. So it seems that the compiler compares them (internally) as being integers.

I consider that unexpected (and afaik undocumented)

edit: /me hides into black hole

Code: Pascal  [Select][+][-]
  1. procedure HowToCompareTheTruth;
  2. var
  3.   a,b: boolean;
  4. begin
  5.   a := Boolean(2);
  6.   b := Boolean(3);
  7.  
  8.   if a=b then writeln('!');
  9.  
  10.   writeln('a = ', a);
  11.   writeln('b = ', b);
  12.  
  13.   writeln('ord(a) = ', ord(a));
  14.   writeln('ord(b) = ', ord(b));
  15.  
  16.   if (Boolean(a) = Boolean(b)) then writeln('*');
  17.  
  18.   writeln('boolean(a) = ', boolean(a));
  19.   writeln('boolean(b) = ', boolean(b));
  20.  
  21.   writeln('ord(boolean(a)) = ', ord(boolean(a)));
  22.   writeln('ord(boolean(b)) = ', ord(boolean(b)));
  23. end;
  24.  

Above which btw does work as expected for boolean16.
« Last Edit: January 29, 2025, 12:29:30 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 #41 on: January 29, 2025, 12:06:34 am »
Well, we are talking about Pascal, not about Maths.
...
If they document it, to explicitly state something different from what I said, then please let me know, so I can update my knowledge.
You, yourself said that for the BooleanXX types there are only two values allowed, 0 and 1 and, you pointed out that fact by quoting the "with its two predefined values... etc".

I believe we both agree that a true boolean (not the C bool stuff) can only have values 0 and 1.

FPC is not adhering to the spec which is: boolean values are either 0 or 1.  It is failing to adhere to that when it generates an "or al, al" or "or ax, ax" to determine the truth value of a boolean.  Such tests can only be used for types that are true for any nonzero value, not for a real boolean.

The same thing when it compares against 0 to determine truth value.  When a boolean is represented by more than 1 bit then not zero is NOT equal to TRUE because it confers meaning to bits that, by definition, do not have any.

The one thing that I am in full agreement with you is that one of the FPC developers should shed some light on the issue.


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

ASerge

  • Hero Member
  • *****
  • Posts: 2475
Re: likely bug in FPC v3.2.2 handling of booleans
« Reply #42 on: January 29, 2025, 12:32:43 am »
Comments welcome.
Assignment
Code: Pascal  [Select][+][-]
  1.     Ord(b8) := 4; // true
  2.     Ord(b16) := 8;  // true
not correct for Boolean type.
Change variable type as
Code: Pascal  [Select][+][-]
  1.     b8: ByteBool = False;
  2.     b16: WordBool = False;
to make the result correct.

440bx

  • Hero Member
  • *****
  • Posts: 6063
Re: likely bug in FPC v3.2.2 handling of booleans
« Reply #43 on: January 29, 2025, 12:39:39 am »
Comments welcome.
Assignment
Code: Pascal  [Select][+][-]
  1.     Ord(b8) := 4; // true
  2.     Ord(b16) := 8;  // true
not correct for Boolean type.
That's true, a boolean should not accommodate a value greater than 1 but... because booleans are usually implemented using types larger than 1 bit, the compiler "tolerates" assignments like that because underlying the boolean type is an integer type (see the FPC documentation.)  However, when the boolean variable is tested for its truth value, the compiler MUST test a single bit regardless of the size of the underlying integer type.  Doing otherwise yields incorrect results.

The compiler could choose to disallow casts such as "ord(b8) := 4;" but, that is not sufficient to ensure the proper treatment of boolean types.

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 #44 on: January 29, 2025, 12:47:21 am »
The compiler could choose to disallow casts such as "ord(b8) := 4;" but, that is not sufficient to ensure the proper treatment of boolean types.
And does not hold up for the boolean16 type.
Today is tomorrow's yesterday.

 

TinyPortal © 2005-2018