From c96641f901daa34aab14f6ccf88e860039dbbaa7 Mon Sep 17 00:00:00 2001 From: Jonas Maebe Date: Thu, 14 Sep 2023 15:02:11 +0200 Subject: [PATCH] LLVM: fix double init/fini of local managed variables accessed from nested functions resolves #40392 --- compiler/ngenutil.pas | 4 +-- tests/webtbs/tw40392.pp | 64 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+), 2 deletions(-) create mode 100644 tests/webtbs/tw40392.pp diff --git a/compiler/ngenutil.pas b/compiler/ngenutil.pas index 2e5be5858e..7b574b94ba 100644 --- a/compiler/ngenutil.pas +++ b/compiler/ngenutil.pas @@ -239,7 +239,7 @@ implementation if (target_info.system in systems_fpnestedstruct) and (p.nodetype=loadn) and (tloadnode(p).symtableentry.typ=localvarsym) and - (tloadnode(p).symtableentry.visibility=vis_hidden) then + tlocalvarsym(tloadnode(p).symtableentry).inparentfpstruct then begin p.free; result:=cnothingnode.create; @@ -288,7 +288,7 @@ implementation if (target_info.system in systems_fpnestedstruct) and (p.nodetype=loadn) and (tloadnode(p).symtableentry.typ=localvarsym) and - (tloadnode(p).symtableentry.visibility=vis_hidden) then + tlocalvarsym(tloadnode(p).symtableentry).inparentfpstruct then begin p.free; result:=cnothingnode.create; diff --git a/tests/webtbs/tw40392.pp b/tests/webtbs/tw40392.pp new file mode 100644 index 0000000000..70b7e050f5 --- /dev/null +++ b/tests/webtbs/tw40392.pp @@ -0,0 +1,64 @@ +{$mode objfpc} {$modeswitch advancedrecords} + +{ define doublefree} +var + InitCount: int32 = 0; + +type + ManRec = record + x: int32; + class operator Initialize(var self: ManRec); + class operator Finalize(var self: ManRec); + class operator Copy(constref b: ManRec; var self: ManRec); + class operator AddRef(var self: ManRec); + end; + + class operator ManRec.Initialize(var self: ManRec); + begin + inc(InitCount); + end; + + class operator ManRec.Finalize(var self: ManRec); + begin + dec(InitCount); + end; + + class operator ManRec.Copy(constref b: ManRec; var self: ManRec); + begin + writeln('shouldn''t happen'); + halt(1); + end; + + class operator ManRec.AddRef(var self: ManRec); + begin + writeln('shouldn''t happen'); + halt(2); + end; + + function GetManRec: ManRec; + begin + result.x := 1; + end; + + procedure Use(const mr: ManRec); + begin + end; + + procedure Main; + var + mr: ManRec; + begin + {$ifdef doublefree} + GetManRec; // imperfect, double Finalize() + {$else} + mr := GetManRec; // ok + Use(GetManRec); // ok as well + {$endif} + end; + +begin + Main; + writeln('InitCount = ', InitCount, ' (should ideally be 0).'); + if InitCount <> 0 then + halt(1); +end.