45
votes

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

1
Submit this to QualityCentral. Also, where do forward declarations come into it. The only such declaration is not used.David Heffernan
Code is most simplified, so that the compiler error was reproduced. In a real project forward declarations is used. If this problems not only at me, then I write to QC.Chaa
OK. When you submit the bug you should strip it down even further. Looks like forward declaration not relevant. Simply a codegen problem with InstanceSize. If you have support contract you could open a support issue although even doing that doesn't necessarily mean you'll get a response.David Heffernan
Without forward declaration code works well, and TMyEntity1.InstanceSize is 16 bytes. Without generics code works well. The problem consists in the forward declaration and generics.Chaa
That's interesting. The presence of an unused forward declaration changes the behaviour. Weird! FWIW, your code runs as expected, TMyEntity1.InstanceSize=16 on XE2 Update 3.David Heffernan

1 Answers

4
votes

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.