Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-pascal / 2010-05

FPC bug or brain bug ?

11 messages · 5 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Yann Bat

Hi,

I don't understand why compilation of the program below failed in fpc and objfpc mode. In tp and delphi mode it works as expected but in fpc and objfpc mode the compiler complains :

  blob.pas(17,3) Error: Constants of objects containing a VMT aren't allowed
  blob.pas(17,3) Fatal: Syntax error, ";" expected but "(" found

Since my object has no virtual methods why a VMT ?

Thanks.

{$mode fpc}
program Blob;
type
  TBlob = object
    private
      fId : LongInt;
    public
      constructor Init;
      function Id: LongInt;
  end;
  PBlob=^TBlob;
const
  NullBlob : TBlob = (fId: 0);
{=== TBlob ===}
constructor TBlob.Init;
begin
  fId:=Random(1024) + 1;
end;
function TBlob.Id;
begin
  Id:=fId;
end;
var
  B : TBlob;
begin
  B:=NullBlob;
  WriteLn('B : ', B.Id);
  B.Init;
  WriteLn('B : ', B.Id);
end.

Reply by email

Flávio Etrusco
to Yann Bat

All TObject descendants have a VMT. The destructor is virtual, BTW.

-Flávio

Yann Bat wrote 56 lines
Hi, I don't understand why compilation of the program below failed in fpc and objfpc mode. In tp and delphi mode it works as expected but in fpc and objfpc mode the compiler complains :  blob.pas(17,3) Error: Constants of objects containing a VMT aren't allowed  blob.pas(17,3) Fatal: Syntax error, ";" expected but "(" found Since my object has no virtual methods why a VMT ? Thanks. {$mode fpc} program Blob; type  TBlob = object    private      fId : LongInt;    public      constructor Init;      function Id: LongInt;  end;  PBlob=^TBlob; const  NullBlob : TBlob = (fId: 0); {=== TBlob ===} constructor TBlob.Init; begin  fId:=Random(1024) + 1; end; function TBlob.Id; begin  Id:=fId; end; var  B : TBlob; begin  B:=NullBlob;  WriteLn('B : ', B.Id);  B.Init;  WriteLn('B : ', B.Id); end. _______________________________________________ fpc-pascal maillist  -   http://lists.freepascal.org/mailman/listinfo/fpc-pascal

Reply by email

Jonas Maebe
to Yann Bat: I don't understand why compilation of the program below failed in fpc and objfpc mode. In…
Yann Bat wrote 8 lines
I don't understand why compilation of the program below failed in fpc and objfpc mode. In tp and delphi mode it works as expected but in fpc and objfpc mode the compiler complains : blob.pas(17,3) Error: Constants of objects containing a VMT aren't allowed blob.pas(17,3) Fatal: Syntax error, ";" expected but "(" found Since my object has no virtual methods why a VMT ?

The compiler always adds a VMT if an object has a constructor or destructor. The reason is that the VMT also contains the instance size, which is used by the constructor helper to allocate the required amount of memory.

Jonas

Reply by email

Jonas Maebe
to Flávio Etrusco: All TObject descendants have a VMT. The destructor is virtual, BTW. -Flávio
Flávio Etrusco wrote 24 lines
On Thu, May 27, 2010 at 11:01 AM, Yann Bat wrote: > type > TBlob = object > private > fId : LongInt; > > public > constructor Init; > function Id: LongInt; > end; > > PBlob=^TBlob; > > const > NullBlob : TBlob = (fId: 0); > > {=== TBlob ===} > constructor TBlob.Init; > begin > fId:=Random(1024) + 1; > end; > All TObject descendants have a VMT.

The above is not a TObject descendant. It's a TP-style object.

Jonas

Reply by email

Jonas Maebe
to Yann Bat
Yann Bat wrote
> The compiler always adds a VMT if an object has a constructor or destructor. The reason is that the VMT also contains the instance size, which is used by the constructor helper to allocate the required amount of memory. Ok but why a different behaviour between [fpc | objfpc] mode and [tp | delphi] mode ?

It is allowed in Delphi and TP because they allow declaring typed constants of objects. I don't remember why it was disabled in the FPC modes, but that happened a long time ago (before the move from cvs to svn). Maybe someone else does.

Jonas

Reply by email

Frank Peelo
to Jonas Maebe: It is allowed in Delphi and TP because they allow declaring typed constants of objects. I…
Jonas Maebe wrote 10 lines
On 27 May 2010, at 23:31, Yann Bat wrote: >> The compiler always adds a VMT if an object has a constructor or destructor. The reason is that the VMT also contains the instance size, which is used by the constructor helper to allocate the required amount of memory. >> > Ok but why a different behaviour between [fpc | objfpc] mode and [tp | > delphi] mode ? > It is allowed in Delphi and TP because they allow declaring typed constants of objects. I don't remember why it was disabled in the FPC modes, but that happened a long time ago (before the move from cvs to svn). Maybe someone else does.

Definitely TP-style objects did not have a VMT unless you declared a virtual method, in TP. And a destructor was only virtual if it was declared virtual. Hence typed constant objects could be possible. Presumably FPC decided compatibility with this feature was not desirable?

FP

Reply by email

Tomas Hajny
to Frank Peelo
Frank Peelo wrote 22 lines
On 27/05/10 23:13, Jonas Maebe wrote: > On 27 May 2010, at 23:31, Yann Bat wrote: > > >>> The compiler always adds a VMT if an object has a constructor or >>> destructor. The reason is that the VMT also contains the instance >>> size, which is used by the constructor helper to allocate the required >>> amount of memory. >>> >> Ok but why a different behaviour between [fpc | objfpc] mode and [tp | >> delphi] mode ? >> > It is allowed in Delphi and TP because they allow declaring typed > constants of objects. I don't remember why it was disabled in the FPC > modes, but that happened a long time ago (before the move from cvs to > svn). Maybe someone else does. > Definitely TP-style objects did not have a VMT unless you declared a virtual method, in TP. And a destructor was only virtual if it was declared virtual. Hence typed constant objects could be possible. Presumably FPC decided compatibility with this feature was not desirable?

I believe the same is the case with FPC and _objects_ (not classes) and FPC is thus compatible here. The text above (mentioning constructors allocating the memory) probably refers to classes. In case of objects, constructor does not need to allocate memory because the object is either declared statically, or it's declared dynamically, but the allocation happens before the constructor is invoked.

Tomas

Reply by email

Jonas Maebe
to Tomas Hajny
Tomas Hajny wrote 6 lines
I believe the same is the case with FPC and _objects_ (not classes) and FPC is thus compatible here. The text above (mentioning constructors allocating the memory) probably refers to classes. In case of objects, constructor does not need to allocate memory because the object is either declared statically, or it's declared dynamically, but the allocation happens before the constructor is invoked.

Semantically, yes. Implementation-wise, no:

# [13] new(o,init);
movl _U_P$PROGRAM_O,%ebx
movl L_VMT_P$PROGRAM_TOBJ$non_lazy_ptr,%edx
movl $0,%eax
call L_P$PROGRAM_TOBJ_$__INIT$$LONGBOOL$stub
movl %eax,_U_P$PROGRAM_O

The first $0 parameter (in %eax) indicates that memory still has to be reserved. P$PROGRAM_TOBJ_$__INIT$$LONGBOOL (= tobj.init) calls fpc_help_constructor, which allocates the memory if necessary (based on the size in the VMT, and the VMT is loaded in %edx in the code above).

Jonas

Reply by email

Jonas Maebe
to Frank Peelo: Definitely TP-style objects did not have a VMT unless you declared a virtual method, in…
Frank Peelo wrote 11 lines
On 27/05/10 23:13, Jonas Maebe wrote: > On 27 May 2010, at 23:31, Yann Bat wrote: > >>> The compiler always adds a VMT if an object has a constructor or destructor. The reason is that the VMT also contains the instance size, which is used by the constructor helper to allocate the required amount of memory. >>> >> Ok but why a different behaviour between [fpc | objfpc] mode and [tp | >> delphi] mode ? >> > It is allowed in Delphi and TP because they allow declaring typed constants of objects. I don't remember why it was disabled in the FPC modes, but that happened a long time ago (before the move from cvs to svn). Maybe someone else does. Definitely TP-style objects did not have a VMT unless you declared a virtual method, in TP. And a destructor was only virtual if it was declared virtual. Hence typed constant objects could be possible.

I made a typo in the comment above (my first quoted statement at the top of the mail is still correct though), it should have read "It is allowed in Delphi and TP because they allow declaring typed constants of objects *that contain a VMT*". As I explained, FPC adds a VMT for any object type that contains a constructor or destructor. This by itself may be another incompatibility with TP/Delphi.

Presumably FPC decided compatibility with this feature was not desirable?

The reason for adding the VMT as soon as there is a constructor or destructor may be for implementation reasons, although it's strange that this is TP-incompatible since this was probably implemented by Pierre or Carl-Eric, and they generally paid a lot of attention to being binary compatible to TP as much as possible.

As mentioned before, I don't know the reason for not allowing typed constants of TP-style objects that have a VMT.

Reply by email