diff --git a/compiler/ngenutil.pas b/compiler/ngenutil.pas index b7464e09f50..f84d4252a15 100644 --- a/compiler/ngenutil.pas +++ b/compiler/ngenutil.pas @@ -350,7 +350,9 @@ implementation ((tsym(p).typ = staticvarsym) and ( is_record(tabstractvarsym(p).vardef) or - is_object(tabstractvarsym(p).vardef) + is_object(tabstractvarsym(p).vardef) or + (is_normal_array(tabstractvarsym(p).vardef) and + has_non_trivial_value_init(tabstractvarsym(p).vardef)) ) ) ) and @@ -363,8 +365,7 @@ implementation 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) + has_non_trivial_value_init(tabstractvarsym(p).vardef) ) ) and not(vo_is_typed_const in tabstractvarsym(p).varoptions) and diff --git a/compiler/symdef.pas b/compiler/symdef.pas index 2127d7fbaa3..2b1841f7c2e 100644 --- a/compiler/symdef.pas +++ b/compiler/symdef.pas @@ -1429,6 +1429,7 @@ tdefawaresymtablestack = class(TSymtablestack) function is_implicit_array_pointer(def: tdef): boolean; function is_class_or_object(def: tdef): boolean; function is_record(def: tdef): boolean; + function has_non_trivial_value_init(def: tdef): boolean; function is_javaclass(def: tdef): boolean; function is_javaclassref(def: tdef): boolean; @@ -9987,6 +9988,27 @@ (def.typ=recorddef))); (def.typ=recorddef); end; + function has_non_trivial_value_init(def: tdef): boolean; + begin + result:=false; + if not assigned(def) then + exit; + case def.typ of + recorddef: + result:= + (mop_initialize in trecordsymtable(trecorddef(def).symtable).managementoperators) or + def.has_non_trivial_init_child(true); + arraydef: + result:=is_normal_array(def) and + has_non_trivial_value_init(tarraydef(def).elementdef); + objectdef: + result:=(tobjectdef(def).objecttype=odt_object) and + def.has_non_trivial_init_child(true); + else + ; + end; + end; + function is_javaclass(def: tdef): boolean; begin result:= diff --git a/compiler/symtable.pas b/compiler/symtable.pas index 2faef4a312b..8b3238e1b6a 100644 --- a/compiler/symtable.pas +++ b/compiler/symtable.pas @@ -1172,12 +1172,13 @@ implementation localvarsym, paravarsym : begin - if assigned(tabstractvarsym(sym).vardef) and - is_managed_type(tabstractvarsym(sym).vardef) then - include(tableoptions,sto_needs_init_final); - if is_record((tabstractvarsym(sym).vardef)) and - (mop_initialize in trecordsymtable(trecorddef(tabstractvarsym(sym).vardef).symtable).managementoperators) then - include(tableoptions,sto_has_non_trivial_init); + if assigned(tabstractvarsym(sym).vardef) then + begin + if is_managed_type(tabstractvarsym(sym).vardef) then + include(tableoptions,sto_needs_init_final); + if has_non_trivial_value_init(tabstractvarsym(sym).vardef) then + include(tableoptions,sto_has_non_trivial_init); + end; end; else ; diff --git a/tests/webtbs/tw41451.pp b/tests/webtbs/tw41451.pp new file mode 100644 index 00000000000..f5ce80ca77e --- /dev/null +++ b/tests/webtbs/tw41451.pp @@ -0,0 +1,37 @@ +program tw41451; + +{$mode delphi} + +var + InitializeCount: Integer; + +type + TManaged = record + State: Word; + class operator Initialize(var Value: TManaged); + class operator Finalize(var Value: TManaged); + end; + +class operator TManaged.Initialize(var Value: TManaged); +begin + Inc(InitializeCount); + Value.State := $4145; +end; + +class operator TManaged.Finalize(var Value: TManaged); +begin +end; + +var + One: TManaged; + Many: array[1..6] of TManaged; + I: Integer; +begin + if InitializeCount <> 7 then + Halt(1); + if One.State <> $4145 then + Halt(2); + for I := Low(Many) to High(Many) do + if Many[I].State <> $4145 then + Halt(3); +end.