From e048266473f06c7e74ffa726e126a1cb3e11612f Mon Sep 17 00:00:00 2001 From: Sven/Sarah Barth Date: Fri, 18 Oct 2024 15:22:14 +0200 Subject: [PATCH] * 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 --- compiler/ngenutil.pas | 9 ++++++- tests/webtbs/tw40259.pp | 10 ++++++++ tests/webtbs/uw40259.pp | 55 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 73 insertions(+), 1 deletion(-) create mode 100644 tests/webtbs/tw40259.pp create mode 100644 tests/webtbs/uw40259.pp diff --git a/compiler/ngenutil.pas b/compiler/ngenutil.pas index bd916179b3..eb65ce5949 100644 --- a/compiler/ngenutil.pas +++ b/compiler/ngenutil.pas @@ -355,7 +355,14 @@ implementation they are used } ((tabstractvarsym(p).refs>0) or { 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 not(vo_is_typed_const in tabstractvarsym(p).varoptions) and not(vo_is_external in tabstractvarsym(p).varoptions) and diff --git a/tests/webtbs/tw40259.pp b/tests/webtbs/tw40259.pp new file mode 100644 index 0000000000..6b54a8ac88 --- /dev/null +++ b/tests/webtbs/tw40259.pp @@ -0,0 +1,10 @@ +program tw40259; + +{$mode objfpc} {$longstrings on} +uses + uw40259; + +begin + Con.Dump('Main'); +end. + diff --git a/tests/webtbs/uw40259.pp b/tests/webtbs/uw40259.pp new file mode 100644 index 0000000000..84de218f64 --- /dev/null +++ b/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.