Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Compiler bug when using generics and forward declaration in Delphi XE2

I started project on Delphi 2010, then migrated to XE and now I try to migrate to XE2. After compiling in XE2 (Update 4 Hotfix 1), unit tests began fail with AV. After some debugging, it became clear that the following code is not correctly compiled:

program ForwardDeclaration;

{$APPTYPE CONSOLE}

uses
    System.SysUtils;

type
    TEntityBase = class(TObject)
    protected
        FModel: Integer;
    public
        constructor Create(const AModel: Integer);
    end;

    TEntity<TKey> = class(TEntityBase)
    end;

    TMyEntity2 = class;

    TMyEntity1 = class(TEntity<Integer>)
        FData: Integer;
    end;

    TMyEntity2 = class(TMyEntity1)
    end;

constructor TEntityBase.Create(const AModel: Integer);
begin
    inherited Create;
    FModel := AModel;
end;

var
    MyEntity: TMyEntity1;
begin
    try
        Writeln(TEntityBase.ClassName, ': ', TEntityBase.InstanceSize, ' bytes');
        Writeln(TMyEntity1.ClassName, ': ', TMyEntity1.InstanceSize, ' bytes');
        MyEntity := TMyEntity1.Create(100);
        Assert(MyEntity.FData = 0);
    except
        on E: Exception do Writeln(E.ClassName, ': ', E.Message);
    end;
end.

Program outputs:

TEntityBase: 12 bytes
TMyEntity1: 12 bytes <-- Must be 16 bytes!
EAssertionFailed: Assertion failure (ForwardDeclaration.dpr, line 41)

Is it possible to resolve the problem by tuning compiler options?

Whether this problem repeats at someone else?

P.S. QC107110

like image 935
Chaa Avatar asked Jul 13 '12 03:07

Chaa


1 Answers

Is it possible to resolve the problem by tuning compiler options?

No, you cannot fix the error by tuning, it's a (very specific) bug in the compiler.

[Can someone tell me] Whether this problem repeats at someone else?

I can reproduce the code, but only in XE2 update 4.

I was not able to check it in XE3 (don't have that version). It is fixed in XE4 (as per the comments).

So the only way to have the code to work is to:

a. remove the unneeded forward declaration.
b. use a different version of Delphi.

like image 123
Johan Avatar answered Sep 19 '22 22:09

Johan