2
0
Эх сурвалжийг харах

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

Jonas Maebe 14 жил өмнө
parent
commit
ad871b6acd

+ 1 - 1
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));

+ 2 - 2
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 }

+ 17 - 7
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