* 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) }
if is_javaclass(current_structdef) then
begin
add_missing_parent_constructors_intf(tobjectdef(current_structdef),vis_none);
add_missing_parent_constructors_intf(tobjectdef(current_structdef),true,vis_none);
{$ifdef jvm}
maybe_add_public_default_java_constructor(tobjectdef(current_structdef));
jvm_wrap_virtual_class_methods(tobjectdef(current_structdef));

View File

@ -357,7 +357,7 @@ implementation
begin
{ insert "private constructor(string,int,int)" that calls inherited and
initialises the FPC value field }
add_missing_parent_constructors_intf(enumclass,vis_strictprivate);
add_missing_parent_constructors_intf(enumclass,false,vis_strictprivate);
end;
{ 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
@ -463,7 +463,7 @@ implementation
symtablestack.push(pvclass.symtable);
{ 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
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
them). To emulate the Pascal behaviour, we have to automatically add
all parent constructors to the current class as well.}
procedure add_missing_parent_constructors_intf(obj: tobjectdef; forcevis: tvisibility);
all parent constructors to the current class as well. We also have to do
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
added earlier }
@ -245,7 +246,7 @@ implementation
end;
procedure add_missing_parent_constructors_intf(obj: tobjectdef; forcevis: tvisibility);
procedure add_missing_parent_constructors_intf(obj: tobjectdef; addvirtclassmeth: boolean; forcevis: tvisibility);
var
parent: tobjectdef;
def: tdef;
@ -264,7 +265,9 @@ implementation
begin
def:=tdef(tobjectsymtable(parent.symtable).deflist[i]);
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
continue;
parentpd:=tprocdef(def);
@ -273,12 +276,12 @@ implementation
search parents too) }
if searchsym_in_record(obj,parentpd.procsym.name,srsym,srsymtable) then
begin
{ there's a symbol with the same name, is it a constructor
with the same parameters? }
{ there's a symbol with the same name, is it a routine of the
same type with the same parameters? }
if srsym.typ=procsym then
begin
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]);
if assigned(childpd) then
continue;
@ -287,6 +290,13 @@ implementation
{ if we get here, we did not find it in the current objectdef ->
add }
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
childpd.visibility:=forcevis;
if po_virtualmethod in childpd.procoptions then