Browse Source

* ignore methods that are added for the purpose of the JVM (inherited
constructors, inherited virtual class methods) when deciding which
overloaded version of a routine to call. Otherwise they can change
which variant is called compared to code on platforms where such
implicit methods are not added

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

Jonas Maebe 14 years ago
parent
commit
0b7b6361fe
5 changed files with 60 additions and 9 deletions
  1. 44 3
      compiler/htypechk.pas
  2. 4 2
      compiler/pjvm.pas
  3. 7 1
      compiler/symconst.pas
  4. 2 1
      compiler/symcreat.pas
  5. 3 2
      compiler/utils/ppudump.pp

+ 44 - 3
compiler/htypechk.pas

@@ -63,6 +63,7 @@ interface
         FProcsymtable : tsymtable;
         FOperator    : ttoken;
         FCandidateProcs    : pcandidate;
+        FIgnoredCandidateProcs: tfpobjectlist;
         FProcCnt    : integer;
         FParaNode   : tnode;
         FParaLength : smallint;
@@ -1862,6 +1863,7 @@ implementation
         FProcsym:=sym;
         FProcsymtable:=st;
         FParanode:=ppn;
+        FIgnoredCandidateProcs:=tfpobjectlist.create(false);
         create_candidate_list(ignorevisibility,allowdefaultparas,objcidcall,explicitunit,searchhelpers,anoninherited);
       end;
 
@@ -1872,6 +1874,7 @@ implementation
         FProcsym:=nil;
         FProcsymtable:=nil;
         FParanode:=ppn;
+        FIgnoredCandidateProcs:=tfpobjectlist.create(false);
         create_candidate_list(false,false,false,false,false,false);
       end;
 
@@ -1881,6 +1884,7 @@ implementation
         hpnext,
         hp : pcandidate;
       begin
+        FIgnoredCandidateProcs.free;
         hp:=FCandidateProcs;
         while assigned(hp) do
          begin
@@ -1904,6 +1908,11 @@ implementation
           for j:=0 to srsym.ProcdefList.Count-1 do
             begin
               pd:=tprocdef(srsym.ProcdefList[j]);
+              if (po_ignore_for_overload_resolution in pd.procoptions) then
+                begin
+                  FIgnoredCandidateProcs.add(pd);
+                  continue;
+                end;
               { in case of anonymous inherited, only match procdefs identical
                 to the current one (apart from hidden parameters), rather than
                 anything compatible to the parameters -- except in case of
@@ -2059,14 +2068,19 @@ implementation
                 if assigned(srsym) and
                    (srsym.typ=procsym) then
                   begin
-                    { Store first procsym found }
-                    if not assigned(FProcsym) then
-                      FProcsym:=tprocsym(srsym);
                     { add all definitions }
                     hasoverload:=false;
                     for j:=0 to tprocsym(srsym).ProcdefList.Count-1 do
                       begin
                         pd:=tprocdef(tprocsym(srsym).ProcdefList[j]);
+                        if (po_ignore_for_overload_resolution in pd.procoptions) then
+                          begin
+                            FIgnoredCandidateProcs.add(pd);
+                            continue;
+                          end;
+                        { Store first procsym found }
+                        if not assigned(FProcsym) then
+                          FProcsym:=tprocsym(srsym);
                         if po_overload in pd.procoptions then
                           hasoverload:=true;
                         ProcdefOverloadList.Add(tprocsym(srsym).ProcdefList[j]);
@@ -2896,6 +2910,7 @@ implementation
 
     function tcallcandidates.choose_best(var bestpd:tabstractprocdef; singlevariant: boolean):integer;
       var
+        pd: tprocdef;
         besthpstart,
         hp            : pcandidate;
         cntpd,
@@ -2950,6 +2965,32 @@ implementation
             end;
          end;
 
+        { if we've found one, check the procdefs ignored for overload choosing
+          to see whether they contain one from a child class with the same
+          parameters (so the overload choosing was not influenced by their
+          presence, but now that we've decided which overloaded version to call,
+          make sure we call the version closest in terms of visibility }
+        if cntpd=1 then
+          begin
+            for res:=0 to FIgnoredCandidateProcs.count-1 do
+              begin
+                pd:=tprocdef(FIgnoredCandidateProcs[res]);
+                { stop searching when we start comparing methods of parent of
+                  the struct in which the current best method was found }
+                if assigned(pd.struct) and
+                   (pd.struct<>tprocdef(bestpd).struct) and
+                   tprocdef(bestpd).struct.is_related(pd.struct) then
+                  break;
+                if (pd.proctypeoption=bestpd.proctypeoption) and
+                   ((pd.procoptions*[po_classmethod,po_methodpointer])=(bestpd.procoptions*[po_classmethod,po_methodpointer])) and
+                   (compare_paras(pd.paras,bestpd.paras,cp_all,[cpo_ignorehidden,cpo_ignoreuniv,cpo_openequalisexact])=te_exact) then
+                  begin
+                    { first one encountered is closest in terms of visibility }
+                    bestpd:=pd;
+                    break;
+                  end;
+              end;
+          end;
         result:=cntpd;
       end;
 

+ 4 - 2
compiler/pjvm.pas

@@ -144,8 +144,8 @@ implementation
             pd.proctypeoption:=potype_constructor;
             { needs to be exported }
             include(pd.procoptions,po_global);
-            { for Delphi mode }
-            include(pd.procoptions,po_overload);
+            { by default do not include this routine when looking for overloads }
+            include(pd.procoptions,po_ignore_for_overload_resolution);
             { generate anonymous inherited call in the implementation }
             pd.synthetickind:=tsk_anon_inherited;
             { public }
@@ -551,6 +551,8 @@ implementation
           in that case) }
         if po_overridingmethod in pd.procoptions then
           begin
+            { by default do not include this routine when looking for overloads }
+            include(wrapperpd.procoptions,po_ignore_for_overload_resolution);
             wrapperpd.synthetickind:=tsk_anon_inherited;
             symtablestack.pop(pd.owner);
             exit;

+ 7 - 1
compiler/symconst.pas

@@ -318,7 +318,13 @@ type
     po_delphi_nested_cc,
     { Non-virtual method of a Java class that has been transformed into a
       "virtual; final;" method for JVM-implementation reasons }
-    po_java_nonvirtual
+    po_java_nonvirtual,
+    { automatically inherited routine from parent class, ignore for resolving
+      overloads (on the JVM target, constructors are not automatically
+      inherited, so we explicitly have to add the constructors of the parent
+      class to the child class; this influences the overload resolution logic
+      though, so ignore them there) }
+    po_ignore_for_overload_resolution
   );
   tprocoptions=set of tprocoption;
 

+ 2 - 1
compiler/symcreat.pas

@@ -306,9 +306,10 @@ implementation
             childpd.visibility:=forcevis;
           if po_virtualmethod in childpd.procoptions then
             include(childpd.procoptions,po_overridingmethod);
+          { ignore this artificially added procdef when looking for overloads }
+          include(childpd.procoptions,po_ignore_for_overload_resolution);
           finish_copied_procdef(childpd,parentpd.procsym.realname,obj.symtable,obj);
           exclude(childpd.procoptions,po_external);
-          include(childpd.procoptions,po_overload);
           childpd.synthetickind:=tsk_anon_inherited;
           include(obj.objectoptions,oo_has_constructor);
         end;

+ 3 - 2
compiler/utils/ppudump.pp

@@ -1085,7 +1085,7 @@ type
   end;
   tprocopt=record
     mask : tprocoption;
-    str  : string[30];
+    str  : string[31];
   end;
 const
   {proccalloptionStr  is also in globtype unit }
@@ -1149,7 +1149,8 @@ const
      (mask:po_enumerator_movenext; str:'EnumeratorMoveNext'),
      (mask:po_optional;        str: 'Optional'),
      (mask:po_delphi_nested_cc;str: 'Delphi-style nested frameptr'),
-     (mask:po_java_nonvirtual; str: 'Java non-virtual method')
+     (mask:po_java_nonvirtual; str: 'Java non-virtual method'),
+     (mask:po_ignore_for_overload_resolution;str: 'Ignored for overload resolution')
   );
 var
   proctypeoption  : tproctypeoption;