Let's look at the code again (added a few lines to output truth values of the variables):
{$MODE OBJFPC }
program BooleanBug;
function TestBoolean() : boolean;
var
b8 : Boolean = FALSE;
b16 : Boolean16 = FALSE;
BooleanArray : bitpacked array[0..1] of boolean = (FALSE, FALSE);
begin
ord(b8) := 4; // true
ord(b16) := 8; // true
writeln('ord(b8) = ', ord(b8));
writeln('ord(b16) = ', ord(b16));
writeln;
{ ------------------------------------------------------------------------- }
{ have the compiler output how it sees the values of b8 and b16 }
{ in both cases it compares the value against 0 to determine if the value }
{ is TRUE or FALSE. This means that, the compiler is NOT considering 1 as }
{ the value TRUE but, any non-zero value which is NOT what the documentation}
{ says the compiler does with Boolean, Boolean16, Boolean32 and Boolean64 }
if b8 then writeln('b8 is TRUE') else writeln('b8 is FALSE');
if b16 then writeln('b16 is TRUE') else writeln('b16 is FALSE');
writeln;
{ ------------------------------------------------------------------------- }
// assign the variables to the bitpacked elements
// both, b8 and b16 are supposedly true but, when assigned to a bitpacked
// boolean, one of them is no longer true.
BooleanArray[0] := b8;
writeln('b8 = ', b8, ' ord(b8) = ', ord(b8), ' BooleanArray[0] = ', BooleanArray[0]);
BooleanArray[1] := b16;
writeln('b16 = ', b16, ' ord(b16) = ', ord(b16), ' BooleanArray[1] = ', BooleanArray[1]);
writeln;
result := true;
end;
begin
TestBoolean();
end.
The writeln statements in line 28 and 29 establish that the compiler chooses to interpret the values of b8 and b16 as TRUE. This is a choice made by the compiler. This choice can be clearly seen in the assembly code where the compiler tests both values against zero (0) to determine whether their value is TRUE or FALSE. Refer to the attachment.
Therefore, there can be no doubt that, as far as the compiler is concerned, b8 and b16 are both TRUE. Fact established by comparing against zero (0) which means that, contrary to the documentation, it is NOT the value 1 that represents TRUE but any non-zero value.
The bug is simple, what the compiler considers a TRUE value is being assigned to BooleanArray[0] and to BooleanArray[1], therefore they should both be TRUE but, they are not both TRUE, one is and the other one isn't. Refer to the output part of the attachment.
Based on the documentation, b8 and b16 should both be FALSE since their least significant bit is not set and the value 1 is supposedly the only value that yields TRUE. See "Table 3.4 Boolean types" (which by the way is missing the Boolean8 type.)
Essentially, the compiler is _sometimes_ treating b8 and b16 as if they were ByteBool and WordBool respectively and sometimes not. This can be observed in the assembly code where the value b8 is compared against the value 1 to determine its truth value while the value of b16 is determined by whether or not b16 is non-zero.
The inconsistent treatment which is exposed when assigning the values to a bitpacked array is the bug.