* automatically generate versions of inherited virtual class methods that

call through to the parent method in case they are not overridden in
    the child class, because otherwise the dynamic dispatch fails (looking
    up a class method only checks that particular class, since they are
    never virtual in Java and hence not inherited either)

git-svn-id: branches/jvmbackend@18715 -
This commit is contained in:
Jonas Maebe 2011-08-20 08:27:07 +00:00
parent 57c7e21d8f
commit ad871b6acd
3 changed files with 20 additions and 10 deletions

View File

@ -1429,7 +1429,7 @@ implementation
we obviously cannot add constructors to those) } we obviously cannot add constructors to those) }
if is_javaclass(current_structdef) then if is_javaclass(current_structdef) then
begin begin
add_missing_parent_constructors_intf(tobjectdef(current_structdef),vis_none); add_missing_parent_constructors_intf(tobjectdef(current_structdef),true,vis_none);
{$ifdef jvm} {$ifdef jvm}
maybe_add_public_default_java_constructor(tobjectdef(current_structdef)); maybe_add_public_default_java_constructor(tobjectdef(current_structdef));
jvm_wrap_virtual_class_methods(tobjectdef(current_structdef)); jvm_wrap_virtual_class_methods(tobjectdef(current_structdef));

View File

@ -357,7 +357,7 @@ implementation
begin begin
{ insert "private constructor(string,int,int)" that calls inherited and { insert "private constructor(string,int,int)" that calls inherited and
initialises the FPC value field } initialises the FPC value field }
add_missing_parent_constructors_intf(enumclass,vis_strictprivate); add_missing_parent_constructors_intf(enumclass,false,vis_strictprivate);
end; end;
{ add instance method to get the enum's value as declared in FPC } { add instance method to get the enum's value as declared in FPC }
if not str_parse_method_dec('function FPCOrdinal: longint;',potype_function,false,enumclass,pd) then if not str_parse_method_dec('function FPCOrdinal: longint;',potype_function,false,enumclass,pd) then
@ -463,7 +463,7 @@ implementation
symtablestack.push(pvclass.symtable); symtablestack.push(pvclass.symtable);
{ inherit constructor and keep public } { inherit constructor and keep public }
add_missing_parent_constructors_intf(pvclass,vis_public); add_missing_parent_constructors_intf(pvclass,true,vis_public);
{ add a method to call the procvar using unwrapped arguments, which { add a method to call the procvar using unwrapped arguments, which
then wraps them and calls through to JLRMethod.invoke } then wraps them and calls through to JLRMethod.invoke }

View File

@ -74,8 +74,9 @@ interface
{ in the JVM, constructors are not automatically inherited (so you can hide { in the JVM, constructors are not automatically inherited (so you can hide
them). To emulate the Pascal behaviour, we have to automatically add them). To emulate the Pascal behaviour, we have to automatically add
all parent constructors to the current class as well.} all parent constructors to the current class as well. We also have to do
procedure add_missing_parent_constructors_intf(obj: tobjectdef; forcevis: tvisibility); the same for the (emulated) virtual class methods }
procedure add_missing_parent_constructors_intf(obj: tobjectdef; addvirtclassmeth: boolean; forcevis: tvisibility);
{ goes through all defs in st to add implementations for synthetic methods { goes through all defs in st to add implementations for synthetic methods
added earlier } added earlier }
@ -245,7 +246,7 @@ implementation
end; end;
procedure add_missing_parent_constructors_intf(obj: tobjectdef; forcevis: tvisibility); procedure add_missing_parent_constructors_intf(obj: tobjectdef; addvirtclassmeth: boolean; forcevis: tvisibility);
var var
parent: tobjectdef; parent: tobjectdef;
def: tdef; def: tdef;
@ -264,7 +265,9 @@ implementation
begin begin
def:=tdef(tobjectsymtable(parent.symtable).deflist[i]); def:=tdef(tobjectsymtable(parent.symtable).deflist[i]);
if (def.typ<>procdef) or if (def.typ<>procdef) or
(tprocdef(def).proctypeoption<>potype_constructor) or ((tprocdef(def).proctypeoption<>potype_constructor) and
(not addvirtclassmeth or
not([po_classmethod,po_virtualmethod]<=tprocdef(def).procoptions))) or
not is_visible_for_object(tprocdef(def),obj) then not is_visible_for_object(tprocdef(def),obj) then
continue; continue;
parentpd:=tprocdef(def); parentpd:=tprocdef(def);
@ -273,12 +276,12 @@ implementation
search parents too) } search parents too) }
if searchsym_in_record(obj,parentpd.procsym.name,srsym,srsymtable) then if searchsym_in_record(obj,parentpd.procsym.name,srsym,srsymtable) then
begin begin
{ there's a symbol with the same name, is it a constructor { there's a symbol with the same name, is it a routine of the
with the same parameters? } same type with the same parameters? }
if srsym.typ=procsym then if srsym.typ=procsym then
begin begin
childpd:=tprocsym(srsym).find_procdef_bytype_and_para( childpd:=tprocsym(srsym).find_procdef_bytype_and_para(
potype_constructor,parentpd.paras,nil, tprocdef(def).proctypeoption,parentpd.paras,nil,
[cpo_ignorehidden,cpo_ignoreuniv,cpo_openequalisexact]); [cpo_ignorehidden,cpo_ignoreuniv,cpo_openequalisexact]);
if assigned(childpd) then if assigned(childpd) then
continue; continue;
@ -287,6 +290,13 @@ implementation
{ if we get here, we did not find it in the current objectdef -> { if we get here, we did not find it in the current objectdef ->
add } add }
childpd:=tprocdef(parentpd.getcopy); childpd:=tprocdef(parentpd.getcopy);
{ get rid of the import name for inherited virtual class methods,
it has to be regenerated rather than amended }
if [po_classmethod,po_virtualmethod]<=childpd.procoptions then
begin
stringdispose(childpd.import_name);
exclude(childpd.procoptions,po_has_importname);
end;
if forcevis<>vis_none then if forcevis<>vis_none then
childpd.visibility:=forcevis; childpd.visibility:=forcevis;
if po_virtualmethod in childpd.procoptions then if po_virtualmethod in childpd.procoptions then