mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-20 18:09:27 +02:00
* 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:
parent
a73d5b6da7
commit
0b7b6361fe
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user