mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-10-17 23:11:47 +02:00
* fixed version of r20547: can't check the number of abstract methods of a
class before its VMT has been built, because that's the process that looks for inherited abstract methods that are overridden -> instead use a new synthetic method kind (tsk_callthrough_nonabstract) that will call through to another method (in this case a constructor) if the owning class does not contain any abstract methods, and generates an empty routine otherwise git-svn-id: branches/jvmbackend@20589 -
This commit is contained in:
parent
94bffa65e9
commit
94b058fe19
@ -571,7 +571,7 @@ implementation
|
||||
be indirect; make sure we don't replace the callthrough to the
|
||||
original constructor with another call to the wrapper }
|
||||
if (procdefinition.typ=procdef) and
|
||||
(current_procinfo.procdef.synthetickind<>tsk_callthrough) and
|
||||
not(current_procinfo.procdef.synthetickind in [tsk_callthrough,tsk_callthrough_nonabstract]) and
|
||||
not(cnf_inherited in callnodeflags) and
|
||||
((procdefinition.proctypeoption=potype_constructor) or
|
||||
(po_classmethod in procdefinition.procoptions)) and
|
||||
|
@ -677,21 +677,13 @@ implementation
|
||||
copy the vmt parameter from the constructor, that's different) }
|
||||
insert_self_and_vmt_para(wrapperpd);
|
||||
wrapperpd.calcparas;
|
||||
{ implementation: call through to the constructor, except in case of
|
||||
an abstract class: then do nothing, because constructing an abstract
|
||||
class is not possible; we still need the method definition because
|
||||
it's used elsewhere by the compiler (it can be "overridden" by
|
||||
child classes) }
|
||||
if (pd.struct.typ=objectdef) and
|
||||
(tobjectdef(pd.struct).abstractcnt=0) then
|
||||
begin
|
||||
wrapperpd.synthetickind:=tsk_callthrough;
|
||||
wrapperpd.skpara:=pd;
|
||||
end
|
||||
else
|
||||
begin
|
||||
wrapperpd.synthetickind:=tsk_empty;
|
||||
end;
|
||||
{ implementation: call through to the constructor
|
||||
Exception: if the current class is abstract, do not call the
|
||||
constructor, since abstract class cannot be constructed (and the
|
||||
Android verifier does not accept such code, even if it is
|
||||
unreachable) }
|
||||
wrapperpd.synthetickind:=tsk_callthrough_nonabstract;
|
||||
wrapperpd.skpara:=pd;
|
||||
symtablestack.pop(pd.owner);
|
||||
{ and now wrap this generated virtual static method itself as well }
|
||||
jvm_wrap_virtual_class_method(wrapperpd);
|
||||
|
@ -878,6 +878,14 @@ implementation
|
||||
implement_empty(pd);
|
||||
tsk_callthrough:
|
||||
implement_callthrough(pd);
|
||||
tsk_callthrough_nonabstract:
|
||||
begin
|
||||
if (pd.owner.defowner.typ<>objectdef) or
|
||||
(tobjectdef(pd.owner.defowner).abstractcnt=0) then
|
||||
implement_callthrough(pd)
|
||||
else
|
||||
implement_empty(pd);
|
||||
end;
|
||||
{$ifdef jvm}
|
||||
tsk_jvm_enum_values:
|
||||
implement_jvm_enum_values(pd);
|
||||
|
@ -519,6 +519,7 @@ interface
|
||||
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)
|
||||
tsk_callthrough_nonabstract,// call through to another routine if the current class not abstract (otherwise do the same as tsk_empty)
|
||||
tsk_jvm_enum_values, // Java "values" class method of JLEnum descendants
|
||||
tsk_jvm_enum_valueof, // Java "valueOf" class method of JLEnum descendants
|
||||
tsk_jvm_enum_classconstr, // Java class constructor for JLEnum descendants
|
||||
|
Loading…
Reference in New Issue
Block a user