mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-10 11:32:46 +02:00
* changed initialization of records from constructing a new instance and
copying that over the old one into calling a dedicated fpcInitializeRec() method that initializes the required fields. The reason is that this initialization is performed for out-parameters, and the fpcDeepCopy() method (used to copy one instance over another) has an out-parameter -> infinite loop git-svn-id: branches/jvmbackend@18674 -
This commit is contained in:
parent
b52dcd4a56
commit
5bf16214cd
@ -1449,7 +1449,8 @@ implementation
|
||||
procedure thlcgjvm.g_initialize(list: TAsmList; t: tdef; const ref: treference);
|
||||
var
|
||||
dummyloc: tlocation;
|
||||
recref: treference;
|
||||
sym: tsym;
|
||||
pd: tprocdef;
|
||||
begin
|
||||
if (t.typ=arraydef) and
|
||||
not is_dynamic_array(t) then
|
||||
@ -1459,12 +1460,19 @@ implementation
|
||||
end
|
||||
else if is_record(t) then
|
||||
begin
|
||||
{ create a new, empty record and replace the contents of the old one
|
||||
with those of the new one (in the future we can generate a dedicate
|
||||
initialization helper) }
|
||||
tg.gethltemp(list,t,t.size,tt_persistent,recref);
|
||||
g_concatcopy(list,t,recref,ref);
|
||||
tg.ungettemp(list,recref);
|
||||
{ call the fpcInitializeRec method }
|
||||
sym:=tsym(trecorddef(t).symtable.find('FPCINITIALIZEREC'));
|
||||
if assigned(sym) and
|
||||
(sym.typ=procsym) then
|
||||
begin
|
||||
if tprocsym(sym).procdeflist.Count<>1 then
|
||||
internalerror(2011071713);
|
||||
pd:=tprocdef(tprocsym(sym).procdeflist[0]);
|
||||
end;
|
||||
a_load_ref_stack(list,java_jlobject,ref,prepare_stack_for_ref(list,ref,false));
|
||||
a_call_name(list,pd,pd.mangledname,false);
|
||||
{ parameter removed, no result }
|
||||
decstack(list,1);
|
||||
end
|
||||
else
|
||||
a_load_const_ref(list,t,0,ref);
|
||||
|
@ -195,6 +195,15 @@ implementation
|
||||
pd.synthetickind:=tsk_record_deepcopy
|
||||
else
|
||||
internalerror(2011032807);
|
||||
if def.needs_inittable then
|
||||
begin
|
||||
{ 'var' instead of 'out' parameter, because 'out' would trigger
|
||||
calling the initialize method recursively }
|
||||
if str_parse_method_dec('procedure fpcInitializeRec;',potype_procedure,false,def,pd) then
|
||||
pd.synthetickind:=tsk_record_initialize
|
||||
else
|
||||
internalerror(2011071711);
|
||||
end;
|
||||
restore_scanner(sstate);
|
||||
end;
|
||||
|
||||
|
@ -375,6 +375,38 @@ implementation
|
||||
end;
|
||||
|
||||
|
||||
procedure implement_record_initialize(pd: tprocdef);
|
||||
var
|
||||
struct: tabstractrecorddef;
|
||||
str: ansistring;
|
||||
i: longint;
|
||||
sym: tsym;
|
||||
fsym: tfieldvarsym;
|
||||
begin
|
||||
if not(pd.struct.typ in [recorddef,objectdef]) then
|
||||
internalerror(2011071710);
|
||||
struct:=pd.struct;
|
||||
{ anonymous record types must get an artificial name, so we can generate
|
||||
a typecast at the scanner level }
|
||||
if (struct.typ=recorddef) and
|
||||
not assigned(struct.typesym) then
|
||||
internalerror(2011032811);
|
||||
{ walk over all fields that need initialization }
|
||||
str:='begin ';
|
||||
for i:=0 to struct.symtable.symlist.count-1 do
|
||||
begin
|
||||
sym:=tsym(struct.symtable.symlist[i]);
|
||||
if (sym.typ=fieldvarsym) then
|
||||
begin
|
||||
fsym:=tfieldvarsym(sym);
|
||||
if fsym.vardef.needs_inittable then
|
||||
str:=str+'system.initialize(&'+fsym.realname+');';
|
||||
end;
|
||||
end;
|
||||
str:=str+'end;';
|
||||
str_parse_method_impl(str,pd,false);
|
||||
end;
|
||||
|
||||
procedure implement_empty(pd: tprocdef);
|
||||
var
|
||||
str: ansistring;
|
||||
@ -618,6 +650,8 @@ implementation
|
||||
implement_jvm_clone(pd);
|
||||
tsk_record_deepcopy:
|
||||
implement_record_deepcopy(pd);
|
||||
tsk_record_initialize:
|
||||
implement_record_initialize(pd);
|
||||
tsk_empty,
|
||||
{ special handling for this one is done in tnodeutils.wrap_proc_body }
|
||||
tsk_tcinit:
|
||||
|
@ -499,6 +499,7 @@ interface
|
||||
tsk_anon_inherited, // anonymous inherited call
|
||||
tsk_jvm_clone, // Java-style clone method
|
||||
tsk_record_deepcopy, // deepcopy for records field by field
|
||||
tsk_record_initialize, // initialize for records field by field (explicit rather than via rtti)
|
||||
tsk_empty, // an empty routine
|
||||
tsk_tcinit, // initialisation of typed constants
|
||||
tsk_callthrough, // call through to another routine with the same parameters/return type (its def is stored in the skpara field)
|
||||
|
Loading…
Reference in New Issue
Block a user