* 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:
Jonas Maebe 2012-03-23 11:26:30 +00:00
parent 94bffa65e9
commit 94b058fe19
4 changed files with 17 additions and 16 deletions

View File

@ -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

View File

@ -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);

View File

@ -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);

View File

@ -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