Internal error 200203273 when assigning to boolean member of record contained within const "array of " parameter
Summary
Given a function that takes a const
-qualified array of <record>
where <record>
contains a Boolean
field, the compiler crashes with internal error 200203273 whenever encountering an assignment that satisfies the following conditions:
- The left-hand side refers to the aforementioned
Boolean
field of any item of the array parameter, e.g.Hyperlinks[0].Visited
) - The right-hand side is an ephemeral (rvalue?) boolean expression that cannot be evaluated at compile-time (e.g.
PInteger(Nil)^ > 0
orLength(Hyperlinks) > 0
)
The internal error is not raised if any of the following conditions is met:
- The field type differs from
Boolean
; e.g. neitherInteger
norByteBool
trigger it - The right-hand side expression is a compile-time constant or refers to a memory location whose address is known at compile-time, e.g.
GlobalBoolVar
orPBoolean(Nil)^
- The dynamic array parameter is not declared
const
- The record type is changed to a class type
System Information
Confirmed on i386-win32
(3.2.2
), x86_64-win64
(3.2.2
) and x86_64-linux
(trunk
).
Steps to reproduce
Compile the following code (with or without any special command-line options):
Example Project
unit reproduce_200203273;
{$mode objfpc}
interface
type
TItem = record
Flag: Boolean;
end;
TItemArray = array of TItem;
procedure Foo(const Items: TItemArray);
implementation
procedure Foo(const Items: TItemArray);
begin
Items[0].Flag := (@Items <> Nil);
end;
end.
What is the current bug behavior?
The compiler aborts after raising an internal error.
What is the expected (correct) behavior?
The code should compile normally (without raising an internal error).
Relevant logs and/or screenshots
N/A
Possible fixes
I'm not very familiar with the compiler's internals, so unfortunately the best I can do is make an educated guess:
Judging from the source of the error in a non-exhaustive case statement operating on the left-hand side's location in tcgassignmentnode.pass_generate_code
, to me it seems that the combination of a const
base address + an array displacement + a record field offset and usage of the somewhat special Boolean
type doesn't mix well with complicated right-hand side expressions. However, I can't see why removing const
would fix the issue...