View Issue Details

IDProjectCategoryView StatusLast Update
0036738FPCCompilerpublic2020-03-04 14:29
ReporteravkAssigned ToSven Barth 
PrioritynormalSeverityminorReproducibilityalways
Status closedResolutionfixed 
PlatformanyOSanyOS Versionany
Product Version3.3.1Product Build44245 
Target VersionFixed in Version3.3.1 
Summary0036738: record management operators
DescriptionThere seem to be some problems with record management operators(specifically with the Copy operator?).
A simple example showing the problem is attached.
TagsNo tags attached.
Fixed in Revision44257
FPCOldBugId
FPCTarget-
Attached Files
  • test.pas (2,266 bytes)
    program test;
    
    {$mode objfpc}
    {$modeswitch advancedrecords}
    
    uses
      SysUtils;
    
    type
    
      TMyManagedRec = record
        Field1: Integer;
        Field2: Int64;
        class operator Initialize(var r: TMyManagedRec);
        class operator Copy(constref aSrc: TMyManagedRec; var aDst: TMyManagedRec);
      end;
    
      generic TGenericRec<T> = record
        SomeField: Integer;
        GenField: T;
      end;
    
      TSimpleRec = record
        SomeField: Integer;
        MngField: TMyManagedRec;
      end;
    
      TMyRecSpec = specialize TGenericRec<TMyManagedRec>;
    
    class operator TMyManagedRec.Initialize(var r: TMyManagedRec);
    begin
      r.Field1 := 101;
      r.Field2 := 1001;
    end;
    
    class operator TMyManagedRec.Copy(constref aSrc: TMyManagedRec; var aDst: TMyManagedRec);
    begin
      if @aSrc <> @aDst then
        begin
          aDst.Field1 := aSrc.Field1 + 100;
          aDst.Field2 := aSrc.Field2 + 1000;
        end;
    end;
    
    var
      MyGenRec, MyGenRec2: TMyRecSpec;
      MyRec, MyRec2: TSimpleRec;
    
    begin
      if IsManagedType(TMyRecSpec) then
        begin
          WriteLn('Yes, TMyRecSpec is a managed type');
          WriteLn('MyGenRec.GenField.Field1 = ', MyGenRec.GenField.Field1);
          WriteLn('MyGenRec.GenField.Field2 = ', MyGenRec.GenField.Field2);
          WriteLn('MyGenRec2.GenField.Field1 = ', MyGenRec2.GenField.Field1);
          WriteLn('MyGenRec2.GenField.Field2 = ', MyGenRec2.GenField.Field2);
          MyGenRec2 := MyGenRec;
          WriteLn('MyGenRec2.GenField.Field1 = ', MyGenRec2.GenField.Field1);
          WriteLn('MyGenRec2.GenField.Field2 = ', MyGenRec2.GenField.Field2);
        end
      else
        WriteLn('No, TMyRecSpec is not a managed type');
    
      WriteLn;
    
      if IsManagedType(TSimpleRec) then
        begin
          WriteLn('Yes, TSimpleRec is a managed type');
          WriteLn('MyRec.MngField.Field1 = ', MyRec.MngField.Field1);
          WriteLn('MyRec.MngField.Field2 = ', MyRec.MngField.Field2);
          WriteLn('MyRec2.MngField.Field1 = ', MyRec2.MngField.Field1);
          WriteLn('MyRec2.MngField.Field2 = ', MyRec2.MngField.Field2);
          MyRec2 := MyRec;
          WriteLn('MyRec2.MngField.Field1 = ', MyRec2.MngField.Field1);
          WriteLn('MyRec2.MngField.Field2 = ', MyRec2.MngField.Field2);
        end
      else
        WriteLn('No, TSimpleRec is not a managed type');
      ReadLn;
    end.
    
    
    test.pas (2,266 bytes)

Activities

avk

2020-02-27 12:14

reporter  

test.pas (2,266 bytes)
program test;

{$mode objfpc}
{$modeswitch advancedrecords}

uses
  SysUtils;

type

  TMyManagedRec = record
    Field1: Integer;
    Field2: Int64;
    class operator Initialize(var r: TMyManagedRec);
    class operator Copy(constref aSrc: TMyManagedRec; var aDst: TMyManagedRec);
  end;

  generic TGenericRec<T> = record
    SomeField: Integer;
    GenField: T;
  end;

  TSimpleRec = record
    SomeField: Integer;
    MngField: TMyManagedRec;
  end;

  TMyRecSpec = specialize TGenericRec<TMyManagedRec>;

class operator TMyManagedRec.Initialize(var r: TMyManagedRec);
begin
  r.Field1 := 101;
  r.Field2 := 1001;
end;

class operator TMyManagedRec.Copy(constref aSrc: TMyManagedRec; var aDst: TMyManagedRec);
begin
  if @aSrc <> @aDst then
    begin
      aDst.Field1 := aSrc.Field1 + 100;
      aDst.Field2 := aSrc.Field2 + 1000;
    end;
end;

var
  MyGenRec, MyGenRec2: TMyRecSpec;
  MyRec, MyRec2: TSimpleRec;

begin
  if IsManagedType(TMyRecSpec) then
    begin
      WriteLn('Yes, TMyRecSpec is a managed type');
      WriteLn('MyGenRec.GenField.Field1 = ', MyGenRec.GenField.Field1);
      WriteLn('MyGenRec.GenField.Field2 = ', MyGenRec.GenField.Field2);
      WriteLn('MyGenRec2.GenField.Field1 = ', MyGenRec2.GenField.Field1);
      WriteLn('MyGenRec2.GenField.Field2 = ', MyGenRec2.GenField.Field2);
      MyGenRec2 := MyGenRec;
      WriteLn('MyGenRec2.GenField.Field1 = ', MyGenRec2.GenField.Field1);
      WriteLn('MyGenRec2.GenField.Field2 = ', MyGenRec2.GenField.Field2);
    end
  else
    WriteLn('No, TMyRecSpec is not a managed type');

  WriteLn;

  if IsManagedType(TSimpleRec) then
    begin
      WriteLn('Yes, TSimpleRec is a managed type');
      WriteLn('MyRec.MngField.Field1 = ', MyRec.MngField.Field1);
      WriteLn('MyRec.MngField.Field2 = ', MyRec.MngField.Field2);
      WriteLn('MyRec2.MngField.Field1 = ', MyRec2.MngField.Field1);
      WriteLn('MyRec2.MngField.Field2 = ', MyRec2.MngField.Field2);
      MyRec2 := MyRec;
      WriteLn('MyRec2.MngField.Field1 = ', MyRec2.MngField.Field1);
      WriteLn('MyRec2.MngField.Field2 = ', MyRec2.MngField.Field2);
    end
  else
    WriteLn('No, TSimpleRec is not a managed type');
  ReadLn;
end.

test.pas (2,266 bytes)

avk

2020-02-27 16:43

reporter   ~0121245

This issue was discussed in this forum thread https://forum.lazarus.freepascal.org/index.php/topic,48685.0.html
And I believe this problem is not "minor".

Serge Anvarov

2020-02-27 17:46

reporter   ~0121246

It looks like the problem is in the system copy procedure. If you add a packed to a record in the example, everything starts working. That is, empty spaces are not correctly accounted for in the copy procedure when aligning.

Sven Barth

2020-03-02 23:07

manager   ~0121327

Please test and close if okay.

avk

2020-03-04 14:29

reporter   ~0121359

It seems to be solved, thank you very much.

Issue History

Date Modified Username Field Change
2020-02-27 12:14 avk New Issue
2020-02-27 12:14 avk File Added: test.pas
2020-02-27 16:43 avk Note Added: 0121245
2020-02-27 17:46 Serge Anvarov Note Added: 0121246
2020-03-02 22:33 Sven Barth Assigned To => Sven Barth
2020-03-02 22:33 Sven Barth Status new => assigned
2020-03-02 23:07 Sven Barth Status assigned => resolved
2020-03-02 23:07 Sven Barth Resolution open => fixed
2020-03-02 23:07 Sven Barth Fixed in Version => 3.3.1
2020-03-02 23:07 Sven Barth Fixed in Revision => 44257
2020-03-02 23:07 Sven Barth FPCTarget => -
2020-03-02 23:07 Sven Barth Note Added: 0121327
2020-03-04 14:29 avk Status resolved => closed
2020-03-04 14:29 avk Note Added: 0121359