Home > OS >  Delphi compiler bug? using "object", but with "record" it compiles
Delphi compiler bug? using "object", but with "record" it compiles

Time:11-17

This code doesn't compile (on Delphi 7 and Delphi XE2), and gives error message "E2036 Variable required". But if I change "object" to "record" then it compiles fine on Delphi XE2, since it has advanced records. I wanted to write portable code between Delphi versions, and use "object" on D7 and "record" on XE2 with IFDEFs, but it looks like impossibile in this case. Am I wrong, or this is a real compiler bug?

type

  TD = String;

  TC = object
  public
    V: String;
    function D: TD;
  end;

  TB = object
  public
    V: String;
    function C: TC;
  end;

  TA = object
  public
    V: String;
    function B: TB;
  end;

function TC.D: TD; begin end;
function TB.C: TC; begin end;
function TA.B: TB; begin end;

procedure Test;
var
  A: TA;
  s: string;
begin
  s := A.V; // Ok
  s := A.B.V; // Ok
  s := A.B.C.V; // "E2036 Variable required", the cursor is between "C" and "."
end;

Thanks to everyone for the fast response. Surprisingly I found a workaround some minutes later. The "object" must have at leas one virtual method (and it's size must not be zero, so it must have a data field, but it don't have to be a managed type as "V: string" is). This ugly code compiles on Delphi 7 and also on Delphi XE2 if HAS_ADVANCEDRECORD is defined.

{.$define HAS_ADVANCEDRECORD}

type

  TE = String;

  TD = {$ifdef HAS_ADVANCEDRECORD}record{$else}object{$endif}
  public
    V: String;
    function E: TE; {$ifndef HAS_ADVANCEDRECORD}virtual;{$endif}
  end;

  TC = {$ifdef HAS_ADVANCEDRECORD}record{$else}object{$endif}
  public
    V: String;
    function D: TD; {$ifndef HAS_ADVANCEDRECORD}virtual;{$endif}
  end;

  TB = {$ifdef HAS_ADVANCEDRECORD}record{$else}object{$endif}
  public
    V: String;
    function C: TC; {$ifndef HAS_ADVANCEDRECORD}virtual;{$endif}
  end;

  TA = {$ifdef HAS_ADVANCEDRECORD}record{$else}object{$endif}
  public
    V: String;
    function B: TB; {$ifndef HAS_ADVANCEDRECORD}virtual;{$endif}
  end;

function TD.E: TE; begin end;
function TC.D: TD; begin end;
function TB.C: TC; begin end;
function TA.B: TB; begin end;

procedure Test;
var
  A: TA;
  s: string;
begin
  s := A.V; //* Ok
  s := A.B.V; //* Ok
  s := A.B.C.D.E; //* Solved: "E2036 Variable required"
end;

Actually I wanted to play with a fluent syntax sql query builder, and advanced records have an advantage over TObject. That is, they don't require lifetime management. A natural solution is using interfaces here, but I always got trouble with them.

I guess, it better worth to improve my knowledge on interfaces...

CodePudding user response:

This is a bug. You could submit a bug report, which would at least document it. However, I seriously doubt that Embarcadero will ever devote more resources to fixing it, and in any case that wouldn't help you with your older versions of Delphi.

  • Related