Skip to content

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 or Length(Hyperlinks) > 0)

The internal error is not raised if any of the following conditions is met:

  • The field type differs from Boolean; e.g. neither Integer nor ByteBool 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 or PBoolean(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...

To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information