From ad871b6acd88e8fdce28d230669020c4417d73e8 Mon Sep 17 00:00:00 2001 From: Jonas Maebe Date: Sat, 20 Aug 2011 08:27:07 +0000 Subject: [PATCH] * 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 - --- compiler/pdecobj.pas | 2 +- compiler/pjvm.pas | 4 ++-- compiler/symcreat.pas | 24 +++++++++++++++++------- 3 files changed, 20 insertions(+), 10 deletions(-) diff --git a/compiler/pdecobj.pas b/compiler/pdecobj.pas index ab17348481..07484b22c2 100644 --- a/compiler/pdecobj.pas +++ b/compiler/pdecobj.pas @@ -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)); diff --git a/compiler/pjvm.pas b/compiler/pjvm.pas index 2df846b0db..e63f2e45bc 100644 --- a/compiler/pjvm.pas +++ b/compiler/pjvm.pas @@ -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 } diff --git a/compiler/symcreat.pas b/compiler/symcreat.pas index f40852d3c5..60efb3cfc3 100644 --- a/compiler/symcreat.pas +++ b/compiler/symcreat.pas @@ -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