浏览代码

* 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 年之前
父节点
当前提交
0b7b6361fe
共有 5 个文件被更改,包括 60 次插入9 次删除
  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;
         FProcsymtable : tsymtable;
         FOperator    : ttoken;
         FOperator    : ttoken;
         FCandidateProcs    : pcandidate;
         FCandidateProcs    : pcandidate;
+        FIgnoredCandidateProcs: tfpobjectlist;
         FProcCnt    : integer;
         FProcCnt    : integer;
         FParaNode   : tnode;
         FParaNode   : tnode;
         FParaLength : smallint;
         FParaLength : smallint;
@@ -1862,6 +1863,7 @@ implementation
         FProcsym:=sym;
         FProcsym:=sym;
         FProcsymtable:=st;
         FProcsymtable:=st;
         FParanode:=ppn;
         FParanode:=ppn;
+        FIgnoredCandidateProcs:=tfpobjectlist.create(false);
         create_candidate_list(ignorevisibility,allowdefaultparas,objcidcall,explicitunit,searchhelpers,anoninherited);
         create_candidate_list(ignorevisibility,allowdefaultparas,objcidcall,explicitunit,searchhelpers,anoninherited);
       end;
       end;
 
 
@@ -1872,6 +1874,7 @@ implementation
         FProcsym:=nil;
         FProcsym:=nil;
         FProcsymtable:=nil;
         FProcsymtable:=nil;
         FParanode:=ppn;
         FParanode:=ppn;
+        FIgnoredCandidateProcs:=tfpobjectlist.create(false);
         create_candidate_list(false,false,false,false,false,false);
         create_candidate_list(false,false,false,false,false,false);
       end;
       end;
 
 
@@ -1881,6 +1884,7 @@ implementation
         hpnext,
         hpnext,
         hp : pcandidate;
         hp : pcandidate;
       begin
       begin
+        FIgnoredCandidateProcs.free;
         hp:=FCandidateProcs;
         hp:=FCandidateProcs;
         while assigned(hp) do
         while assigned(hp) do
          begin
          begin
@@ -1904,6 +1908,11 @@ implementation
           for j:=0 to srsym.ProcdefList.Count-1 do
           for j:=0 to srsym.ProcdefList.Count-1 do
             begin
             begin
               pd:=tprocdef(srsym.ProcdefList[j]);
               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
               { in case of anonymous inherited, only match procdefs identical
                 to the current one (apart from hidden parameters), rather than
                 to the current one (apart from hidden parameters), rather than
                 anything compatible to the parameters -- except in case of
                 anything compatible to the parameters -- except in case of
@@ -2059,14 +2068,19 @@ implementation
                 if assigned(srsym) and
                 if assigned(srsym) and
                    (srsym.typ=procsym) then
                    (srsym.typ=procsym) then
                   begin
                   begin
-                    { Store first procsym found }
-                    if not assigned(FProcsym) then
-                      FProcsym:=tprocsym(srsym);
                     { add all definitions }
                     { add all definitions }
                     hasoverload:=false;
                     hasoverload:=false;
                     for j:=0 to tprocsym(srsym).ProcdefList.Count-1 do
                     for j:=0 to tprocsym(srsym).ProcdefList.Count-1 do
                       begin
                       begin
                         pd:=tprocdef(tprocsym(srsym).ProcdefList[j]);
                         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
                         if po_overload in pd.procoptions then
                           hasoverload:=true;
                           hasoverload:=true;
                         ProcdefOverloadList.Add(tprocsym(srsym).ProcdefList[j]);
                         ProcdefOverloadList.Add(tprocsym(srsym).ProcdefList[j]);
@@ -2896,6 +2910,7 @@ implementation
 
 
     function tcallcandidates.choose_best(var bestpd:tabstractprocdef; singlevariant: boolean):integer;
     function tcallcandidates.choose_best(var bestpd:tabstractprocdef; singlevariant: boolean):integer;
       var
       var
+        pd: tprocdef;
         besthpstart,
         besthpstart,
         hp            : pcandidate;
         hp            : pcandidate;
         cntpd,
         cntpd,
@@ -2950,6 +2965,32 @@ implementation
             end;
             end;
          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;
         result:=cntpd;
       end;
       end;
 
 

+ 4 - 2
compiler/pjvm.pas

@@ -144,8 +144,8 @@ implementation
             pd.proctypeoption:=potype_constructor;
             pd.proctypeoption:=potype_constructor;
             { needs to be exported }
             { needs to be exported }
             include(pd.procoptions,po_global);
             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 }
             { generate anonymous inherited call in the implementation }
             pd.synthetickind:=tsk_anon_inherited;
             pd.synthetickind:=tsk_anon_inherited;
             { public }
             { public }
@@ -551,6 +551,8 @@ implementation
           in that case) }
           in that case) }
         if po_overridingmethod in pd.procoptions then
         if po_overridingmethod in pd.procoptions then
           begin
           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;
             wrapperpd.synthetickind:=tsk_anon_inherited;
             symtablestack.pop(pd.owner);
             symtablestack.pop(pd.owner);
             exit;
             exit;

+ 7 - 1
compiler/symconst.pas

@@ -318,7 +318,13 @@ type
     po_delphi_nested_cc,
     po_delphi_nested_cc,
     { Non-virtual method of a Java class that has been transformed into a
     { Non-virtual method of a Java class that has been transformed into a
       "virtual; final;" method for JVM-implementation reasons }
       "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;
   tprocoptions=set of tprocoption;
 
 

+ 2 - 1
compiler/symcreat.pas

@@ -306,9 +306,10 @@ implementation
             childpd.visibility:=forcevis;
             childpd.visibility:=forcevis;
           if po_virtualmethod in childpd.procoptions then
           if po_virtualmethod in childpd.procoptions then
             include(childpd.procoptions,po_overridingmethod);
             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);
           finish_copied_procdef(childpd,parentpd.procsym.realname,obj.symtable,obj);
           exclude(childpd.procoptions,po_external);
           exclude(childpd.procoptions,po_external);
-          include(childpd.procoptions,po_overload);
           childpd.synthetickind:=tsk_anon_inherited;
           childpd.synthetickind:=tsk_anon_inherited;
           include(obj.objectoptions,oo_has_constructor);
           include(obj.objectoptions,oo_has_constructor);
         end;
         end;

+ 3 - 2
compiler/utils/ppudump.pp

@@ -1085,7 +1085,7 @@ type
   end;
   end;
   tprocopt=record
   tprocopt=record
     mask : tprocoption;
     mask : tprocoption;
-    str  : string[30];
+    str  : string[31];
   end;
   end;
 const
 const
   {proccalloptionStr  is also in globtype unit }
   {proccalloptionStr  is also in globtype unit }
@@ -1149,7 +1149,8 @@ const
      (mask:po_enumerator_movenext; str:'EnumeratorMoveNext'),
      (mask:po_enumerator_movenext; str:'EnumeratorMoveNext'),
      (mask:po_optional;        str: 'Optional'),
      (mask:po_optional;        str: 'Optional'),
      (mask:po_delphi_nested_cc;str: 'Delphi-style nested frameptr'),
      (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
 var
   proctypeoption  : tproctypeoption;
   proctypeoption  : tproctypeoption;