Browse Source

* fixed version of r20547: can't check the number of abstract methods of a
class before its VMT has been built, because that's the process that looks
for inherited abstract methods that are overridden -> instead use a new
synthetic method kind (tsk_callthrough_nonabstract) that will call
through to another method (in this case a constructor) if the owning
class does not contain any abstract methods, and generates an
empty routine otherwise

git-svn-id: branches/jvmbackend@20589 -

Jonas Maebe 13 years ago
parent
commit
94b058fe19
4 changed files with 17 additions and 16 deletions
  1. 1 1
      compiler/jvm/njvmcal.pas
  2. 7 15
      compiler/jvm/pjvm.pas
  3. 8 0
      compiler/symcreat.pas
  4. 1 0
      compiler/symdef.pas

+ 1 - 1
compiler/jvm/njvmcal.pas

@@ -571,7 +571,7 @@ implementation
             be indirect; make sure we don't replace the callthrough to the
             original constructor with another call to the wrapper }
           if (procdefinition.typ=procdef) and
-             (current_procinfo.procdef.synthetickind<>tsk_callthrough) and
+             not(current_procinfo.procdef.synthetickind in [tsk_callthrough,tsk_callthrough_nonabstract]) and
              not(cnf_inherited in callnodeflags) and
              ((procdefinition.proctypeoption=potype_constructor) or
               (po_classmethod in procdefinition.procoptions)) and

+ 7 - 15
compiler/jvm/pjvm.pas

@@ -677,21 +677,13 @@ implementation
           copy the vmt parameter from the constructor, that's different) }
         insert_self_and_vmt_para(wrapperpd);
         wrapperpd.calcparas;
-        { implementation: call through to the constructor, except in case of
-          an abstract class: then do nothing, because constructing an abstract
-          class is not possible; we still need the method definition because
-          it's used elsewhere by the compiler (it can be "overridden" by
-          child classes) }
-        if (pd.struct.typ=objectdef) and
-           (tobjectdef(pd.struct).abstractcnt=0) then
-          begin
-            wrapperpd.synthetickind:=tsk_callthrough;
-            wrapperpd.skpara:=pd;
-          end
-        else
-          begin
-            wrapperpd.synthetickind:=tsk_empty;
-          end;
+        { implementation: call through to the constructor
+          Exception: if the current class is abstract, do not call the
+            constructor, since abstract class cannot be constructed (and the
+            Android verifier does not accept such code, even if it is
+            unreachable) }
+        wrapperpd.synthetickind:=tsk_callthrough_nonabstract;
+        wrapperpd.skpara:=pd;
         symtablestack.pop(pd.owner);
         { and now wrap this generated virtual static method itself as well }
         jvm_wrap_virtual_class_method(wrapperpd);

+ 8 - 0
compiler/symcreat.pas

@@ -878,6 +878,14 @@ implementation
               implement_empty(pd);
             tsk_callthrough:
               implement_callthrough(pd);
+            tsk_callthrough_nonabstract:
+              begin
+                if (pd.owner.defowner.typ<>objectdef) or
+                   (tobjectdef(pd.owner.defowner).abstractcnt=0) then
+                  implement_callthrough(pd)
+                else
+                  implement_empty(pd);
+              end;
 {$ifdef jvm}
             tsk_jvm_enum_values:
               implement_jvm_enum_values(pd);

+ 1 - 0
compiler/symdef.pas

@@ -519,6 +519,7 @@ interface
          tsk_empty,                 // an empty routine
          tsk_tcinit,                // initialisation of typed constants
          tsk_callthrough,           // call through to another routine with the same parameters/return type (its def is stored in the skpara field)
+         tsk_callthrough_nonabstract,// call through to another routine if the current class not abstract (otherwise do the same as tsk_empty)
          tsk_jvm_enum_values,       // Java "values" class method of JLEnum descendants
          tsk_jvm_enum_valueof,      // Java "valueOf" class method of JLEnum descendants
          tsk_jvm_enum_classconstr,  // Java class constructor for JLEnum descendants