* 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 -
This commit is contained in:
Jonas Maebe 2011-08-20 08:32:47 +00:00
parent a73d5b6da7
commit 0b7b6361fe
5 changed files with 60 additions and 9 deletions

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;