Browse Source

* fix #40259: global managed records with Initialize operator need to be initialized no matter if they are referenced in the current unit or not.
+ added test

Sven/Sarah Barth 9 months ago
parent
commit
e048266473
3 changed files with 73 additions and 1 deletions
  1. 8 1
      compiler/ngenutil.pas
  2. 10 0
      tests/webtbs/tw40259.pp
  3. 55 0
      tests/webtbs/uw40259.pp

+ 8 - 1
compiler/ngenutil.pas

@@ -355,7 +355,14 @@ implementation
            they are used }
            they are used }
          ((tabstractvarsym(p).refs>0) or
          ((tabstractvarsym(p).refs>0) or
           { managed return symbols must be inited }
           { managed return symbols must be inited }
-          ((tsym(p).typ=localvarsym) and (vo_is_funcret in tlocalvarsym(p).varoptions))
+          ((tsym(p).typ=localvarsym) and (vo_is_funcret in tlocalvarsym(p).varoptions)) or
+          { public managed records with Initialize operator need to be initialized
+            even if they aren't referenced in *this* unit }
+          (
+            (tsym(p).owner.symtabletype=globalsymtable) and
+            is_record(tabstractvarsym(p).vardef) and
+            (mop_initialize in trecordsymtable(trecorddef(tabstractvarsym(p).vardef).symtable).managementoperators)
+          )
          ) and
          ) and
          not(vo_is_typed_const in tabstractvarsym(p).varoptions) and
          not(vo_is_typed_const in tabstractvarsym(p).varoptions) and
          not(vo_is_external in tabstractvarsym(p).varoptions) and
          not(vo_is_external in tabstractvarsym(p).varoptions) and

+ 10 - 0
tests/webtbs/tw40259.pp

@@ -0,0 +1,10 @@
+program tw40259;
+
+{$mode objfpc} {$longstrings on}
+uses
+	uw40259;
+
+begin
+	Con.Dump('Main');
+end.
+

+ 55 - 0
tests/webtbs/uw40259.pp

@@ -0,0 +1,55 @@
+{$mode objfpc} {$longstrings on} {$modeswitch advancedrecords}
+{.$define enable_UseFromA}
+unit uw40259;
+
+interface
+
+type
+	Console = record
+		Initialized: boolean;
+		procedure Dump(const where: string);
+		class operator Initialize(var self: Console);
+		class operator Finalize(var self: Console);
+	end;
+
+{$ifdef enable_UseFromA}
+	procedure UseFromA;
+{$endif}
+
+var
+	Con: Console;
+
+implementation
+
+	procedure Console.Dump(const where: string);
+	begin
+		if not Initialized then begin
+                	write('/UNINITIALIZED/ ');
+                        Halt(1);
+                end;
+                writeln(where);
+	end;
+
+	class operator Console.Initialize(var self: Console);
+	begin
+		writeln('Console.Initialize');
+		self.Initialized := true;
+	end;
+
+	class operator Console.Finalize(var self: Console);
+	begin
+		self.Initialized := false;
+		writeln('Console.Finalize');
+	end;
+
+var
+        Con2: Console;
+
+{$ifdef enable_UseFromA}
+	procedure UseFromA;
+	begin
+		Con.Dump('UseFromA');
+	end;
+{$endif}
+
+end.