mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-11 23:06:07 +02:00
* 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:
parent
57c7e21d8f
commit
ad871b6acd
@ -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));
|
||||||
|
@ -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 }
|
||||||
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user