View Issue Details

IDProjectCategoryView StatusLast Update
0031117FPCDocumentationpublic2017-01-27 22:28
ReportercreaothceannAssigned ToMichael Van Canneyt 
PrioritynormalSeverityminorReproducibilityalways
Status resolvedResolutionfixed 
Platformx86 x64OSWindowsOS Version10
Product Version3.0.0Product Build53354 (Lazarus) 
Target Version3.2.0Fixed in Version3.1.1 
Summary0031117: no class variables in variant part of a record
DescriptionA record with a variant part that is specified as "class var" contains variables that are not class variables, but normal instance variables. The "class var" part seems to get ignored.
Steps To Reproduce- create console program
- add {$MODESWITCH AdvancedRecords}
- create type t with a variant part containing variable v
- add "class var" before the "case"
- declare two variables a, b of type t
- change a.v to any non-zero value, then display b.v

Result: b.v is still unmodified, meaning that the variables in the variant part are not 'class' variables.
Additional InformationA record with class variables (in mode AdvancedRecords) shares all these variables with all instances. A record can also have a variant part:

type t : record
case int of
0: (x : word);
1: (y : byte);
end;

In this case, y occupies the same location as the first byte of x.
TagsNo tags attached.
Fixed in Revision1383
FPCOldBugId
FPCTarget
Attached Files
  • ClassVarRecordTest.pas (234 bytes)
    program ClassVarRecordTest;  {$MODESWITCH AdvancedRecords}
    
    
    type t = record
            class var case integer of
                    0:  (v : integer);
            end;
    
    
    var a, b : T;
    
    
    begin
    a.v := 1234;
    WriteLn(a.v, ' ', b.v);
    ReadLn;
    end.
    
    

Activities

creaothceann

2016-12-14 22:27

reporter  

ClassVarRecordTest.pas (234 bytes)
program ClassVarRecordTest;  {$MODESWITCH AdvancedRecords}


type t = record
        class var case integer of
                0:  (v : integer);
        end;


var a, b : T;


begin
a.v := 1234;
WriteLn(a.v, ' ', b.v);
ReadLn;
end.

Thaddy de Koning

2016-12-15 12:53

reporter   ~0096807

Last edited: 2016-12-15 12:53

View 2 revisions

I am not quite sure the example should compile, but it does compile!
So either way there is a bug here.

I recommended reporter to write the bug report so throw/blame the stick on me if it is something else we overlooked.

Sven Barth

2016-12-17 20:56

manager   ~0096858

Class variables make no sense in a variant part. Delphi behaves the same by the way.

@Michael: would you please document for records that a "case" in a record implicitely starts a "var" section (thus ending an eventual "class var" section).

E.g. this

=== code begin ===

type
  TTest = record
  class var
    case int of
      0: (x : word);
      1: (y : byte);
  end;

=== code end ===

is the same as

=== code begin ===

type
  TTest = record
  class var
  var
    case int of
      0: (x : word);
      1: (y : byte);
  end;

=== code end ===

(and empty sections are allowed after all)

creaothceann

2016-12-17 21:58

reporter   ~0096861

Last edited: 2016-12-17 22:00

View 2 revisions

@Sven Barth:
>Class variables make no sense in a variant part.

I don't see how they wouldn't make sense? Having the variables in a variant part only means that some of them are allocated at the same memory addresses, while having them as "class" variables only means that all instances of the entire type share the same location in memory.

Sven Barth

2016-12-17 22:31

manager   ~0096864

Two class variables that belong to the same structured type (class or record) are independant of each other, they are essentially simply namespaced global variables. Allowing class variables in the variant part would introduce a dependency between them as they'd need to share their memory. Aside from Delphi compatibility and can't support this notion especially due to the minimal gain we'd get compared to the massive changes that would be needed in the compiler for that.

TL;DR: There won't be class variables in the variant part of a record.

creaothceann

2016-12-17 23:06

reporter   ~0096868

Last edited: 2016-12-17 23:08

View 3 revisions

>Two class variables that belong to the same structured type (class or record) are independent of each other, they are essentially simply namespaced global variables.

Ah, so that's why class variables don't contribute to the value reported when I apply SizeOf({record type})...

class variables in classes are not independent of each other though.


>Allowing class variables in the variant part would introduce a dependency between them as they'd need to share their memory.

Yeah, that memory sharing is intended.


>Aside from Delphi compatibility and

And what? Besides, this could be a FP-only feature.

Thaddy de Koning

2016-12-18 08:39

reporter   ~0096873

Last edited: 2016-12-18 10:25

View 4 revisions

I showed you already that the functionality you want can be obtained by making the whole record that has variant parts a class var.
type
  TMyClass = class
  type
    TLocal = record
    case i:integer of
    0:(a:integer);
    1:(b:double);
    end;
   private
     class var R:TLocal;
   end;
[edit]
or:
type
  TMyClass = class
  type
    TLocal = record
    case i:integer of
    0:(a:integer);
    1:(b:double);
    end;
   private
     class var R:TLocal;
   public
     class property a:integer read R.a write R.a;
     class property b:double read R.b write R.b;
   end;

@Sven: more worrying is that the example code compiles. Any way to add a warning in such cases? Empty sections should be detectable.

Thaddy de Koning

2016-12-18 11:24

reporter   ~0096886

Hm. that editted code only compiles without use. Should work though.

Sven Barth

2016-12-18 11:56

manager   ~0096890

@creaothceann:
Class variables in classes are also independant of each other. A class variable "Field1" and a class variable "Field2" that both belong to the same class "TTest" don't have any dealings with each other except they reside in the same class.

Also that memory sharing you'd intend to have would - as I mentioned - lead to heavy changes in the compiler for little to no gain. So definitely not something I'm inclined to implement nor maintain.

@Thaddy: empty sections exist since the beginning of Delphi's TObject model. Just look at what a new TForm descendant looks like that's created by Lazarus or Delphi.

Thaddy de Koning

2016-12-18 12:38

reporter   ~0096892

@Sven

Yes, but this is valid code and doesn't work?
type
  TMyClass = class
  type
    TLocal = record
    case i:integer of
    0:(a:integer);
    1:(b:double);
    end;
   private
     class var R:TLocal;
   public
     class property a:integer read R.a write R.a;
     class property b:double read R.b write R.b;
   end;

If you correct me? isn't that different bug report?

Sven Barth

2017-01-07 15:26

manager   ~0097351

@Thaddy: you should know by now that "doesn't work" isn't really a helpful description of a problem...
Anyway, Delphi doesn't allow to use a subfield in a class property at all and in FPC I'd say right now that it's a bug (at least if you get the same error message as I do, namely that when assigning e.g. to TMyClass.b it expects a TLocal instead of a Double).

creaothceann

2017-01-27 22:18

reporter   ~0097754

Just for the record, I've now restructured my program so that it no longer uses class variables/methods/properties.

Michael Van Canneyt

2017-01-27 22:28

administrator   ~0097755

Documented as Sven suggested.

Issue History

Date Modified Username Field Change
2016-12-14 22:27 creaothceann New Issue
2016-12-14 22:27 creaothceann File Added: ClassVarRecordTest.pas
2016-12-15 12:53 Thaddy de Koning Note Added: 0096807
2016-12-15 12:53 Thaddy de Koning Note Edited: 0096807 View Revisions
2016-12-17 20:56 Sven Barth Note Added: 0096858
2016-12-17 20:56 Sven Barth Assigned To => Michael Van Canneyt
2016-12-17 20:56 Sven Barth Status new => assigned
2016-12-17 20:56 Sven Barth Category Compiler => Documentation
2016-12-17 21:58 creaothceann Note Added: 0096861
2016-12-17 22:00 creaothceann Note Edited: 0096861 View Revisions
2016-12-17 22:31 Sven Barth Note Added: 0096864
2016-12-17 23:06 creaothceann Note Added: 0096868
2016-12-17 23:06 creaothceann Note Edited: 0096868 View Revisions
2016-12-17 23:08 creaothceann Note Edited: 0096868 View Revisions
2016-12-18 08:39 Thaddy de Koning Note Added: 0096873
2016-12-18 10:19 Thaddy de Koning Note Edited: 0096873 View Revisions
2016-12-18 10:25 Thaddy de Koning Note Edited: 0096873 View Revisions
2016-12-18 10:25 Thaddy de Koning Note Edited: 0096873 View Revisions
2016-12-18 11:24 Thaddy de Koning Note Added: 0096886
2016-12-18 11:56 Sven Barth Note Added: 0096890
2016-12-18 12:38 Thaddy de Koning Note Added: 0096892
2017-01-07 15:26 Sven Barth Note Added: 0097351
2017-01-27 22:18 creaothceann Note Added: 0097754
2017-01-27 22:28 Michael Van Canneyt Fixed in Revision => 1383
2017-01-27 22:28 Michael Van Canneyt Note Added: 0097755
2017-01-27 22:28 Michael Van Canneyt Status assigned => resolved
2017-01-27 22:28 Michael Van Canneyt Fixed in Version => 3.1.1
2017-01-27 22:28 Michael Van Canneyt Resolution open => fixed
2017-01-27 22:28 Michael Van Canneyt Target Version => 3.2.0