* reject overloads if they only differ in the result types (as long as they aren't operator overloads)

+ added tests

git-svn-id: trunk@45973 -
This commit is contained in:
svenbarth 2020-07-31 15:55:34 +00:00
parent fa0c9adbf4
commit b62045809d
7 changed files with 187 additions and 26 deletions

5
.gitattributes vendored
View File

@ -15462,6 +15462,11 @@ tests/test/tover2.pp svneol=native#text/plain
tests/test/tover3.pp svneol=native#text/plain
tests/test/tover4.pas svneol=native#text/plain
tests/test/tover4.pp svneol=native#text/plain
tests/test/tover5.pp svneol=native#text/pascal
tests/test/tover6.pp svneol=native#text/pascal
tests/test/tover7.pp svneol=native#text/pascal
tests/test/tover8.pp svneol=native#text/pascal
tests/test/tover9.pp svneol=native#text/pascal
tests/test/tpackrec.pp svneol=native#text/plain
tests/test/tparray1.pp svneol=native#text/plain
tests/test/tparray10.pp svneol=native#text/plain

View File

@ -676,16 +676,18 @@ implementation
end;
function equal_generic_procdefs(fwpd,currpd:tprocdef):boolean;
function equal_generic_procdefs(fwpd,currpd:tprocdef;out sameparas,sameret:boolean):boolean;
var
i : longint;
fwsym,
currsym : tsym;
fwtype : ttypesym absolute fwsym;
currtype : ttypesym absolute currsym;
foundretdef : boolean;
convdummy: tconverttype;
pddummy: tprocdef;
begin
result:=false;
sameparas:=false;
sameret:=false;
if fwpd.genericparas.count<>currpd.genericparas.count then
exit;
{ comparing generic declarations is a bit more cumbersome as the
@ -696,7 +698,6 @@ implementation
constraints while currpd must only contain undefineddefs
- forward declaration in implementation: here constraints must be
repeated }
foundretdef:=false;
for i:=0 to fwpd.genericparas.count-1 do
begin
fwsym:=tsym(fwpd.genericparas[i]);
@ -728,28 +729,32 @@ implementation
as well }
exit;
end;
if not foundretdef and (fwsym.typ=typesym) then
begin
{ if the returndef is the same as this parameter's def then this
needs to be the case for both procdefs }
foundretdef:=fwpd.returndef=fwtype.typedef;
if foundretdef xor (currpd.returndef=currtype.typedef) then
exit;
end;
end;
if compare_paras(fwpd.paras,currpd.paras,cp_none,[cpo_ignorehidden,cpo_openequalisexact,cpo_ignoreuniv,cpo_generic])<>te_exact then
exit;
if not foundretdef then
begin
if (df_specialization in tstoreddef(fwpd.returndef).defoptions) and (df_specialization in tstoreddef(currpd.returndef).defoptions) then
{ for specializations we're happy with equal defs instead of exactly the same defs }
result:=equal_defs(fwpd.returndef,currpd.returndef)
else
{ the returndef isn't a type parameter, so compare as usual }
result:=compare_defs(fwpd.returndef,currpd.returndef,nothingn)=te_exact;
end
sameparas:=true;
if (df_specialization in tstoreddef(fwpd.returndef).defoptions) and (df_specialization in tstoreddef(currpd.returndef).defoptions) then
{ for specializations we're happy with equal defs instead of exactly the same defs }
result:=equal_defs(fwpd.returndef,currpd.returndef)
else
result:=true;
begin
{ strictly compare defs using compare_defs_ext, but allow
non exactly equal undefineddefs }
convdummy:=tc_none;
pddummy:=nil;
result:=(compare_defs_ext(fwpd.returndef,currpd.returndef,nothingn,convdummy,pddummy,[cdo_allow_variant,cdo_strict_undefined_check])=te_exact) or
equal_genfunc_paradefs(fwpd.returndef,currpd.returndef,fwpd.parast,currpd.parast);
end;
{ the result variable is only set depending on the return type, so we
can simply use "result" }
sameret:=result;
end;
function equal_signature(fwpd,currpd:tprocdef;out sameparas,sameret:boolean):boolean;
begin
sameparas:=compare_paras(fwpd.paras,currpd.paras,cp_none,[cpo_ignorehidden,cpo_openequalisexact,cpo_ignoreuniv])=te_exact;
sameret:=compare_defs(fwpd.returndef,currpd.returndef,nothingn)=te_exact;
result:=sameparas and sameret;
end;
{
@ -767,6 +772,11 @@ implementation
i : longint;
po_comp : tprocoptions;
paracompopt: tcompare_paras_options;
sameparasfound,
gensameparas,
gensameret,
sameparas,
sameret,
forwardfound : boolean;
symentry: TSymEntry;
item : tlinkedlistitem;
@ -781,6 +791,9 @@ implementation
exit;
end;
sameparasfound:=false;
fwpd:=nil;
{ check overloaded functions if the same function already exists }
for i:=0 to tprocsym(currpd.procsym).ProcdefList.Count-1 do
begin
@ -797,6 +810,11 @@ implementation
if fwpd.procsym<>currpd.procsym then
continue;
gensameparas:=false;
gensameret:=false;
sameparas:=false;
sameret:=false;
{ check the parameters, for delphi/tp it is possible to
leave the parameters away in the implementation (forwarddef=false).
But for an overload declared function this is not allowed }
@ -810,7 +828,7 @@ implementation
(
fwpd.is_generic and
currpd.is_generic and
equal_generic_procdefs(fwpd,currpd)
equal_generic_procdefs(fwpd,currpd,gensameparas,gensameret)
) or
{ check arguments, we need to check only the user visible parameters. The hidden parameters
can be in a different location because of the calling convention, eg. L-R vs. R-L order (PFV)
@ -819,8 +837,9 @@ implementation
values should be reported as mismatches (since you can't overload based on different default
parameter values) }
(
(compare_paras(fwpd.paras,currpd.paras,cp_none,[cpo_ignorehidden,cpo_openequalisexact,cpo_ignoreuniv])=te_exact) and
(compare_defs(fwpd.returndef,currpd.returndef,nothingn)=te_exact)
not fwpd.is_generic and
not currpd.is_generic and
equal_signature(fwpd,currpd,sameparas,sameret)
) then
begin
{ Check if we've found the forwarddef, if found then
@ -897,7 +916,7 @@ implementation
(
fwpd.is_generic and
currpd.is_generic and
not equal_generic_procdefs(fwpd,currpd)
not equal_generic_procdefs(fwpd,currpd,sameparas,sameret)
) or
(
(
@ -1124,8 +1143,24 @@ implementation
end;
end;
end; { equal arguments }
{ we found a match with the same parameter signature, but mismatching
return types; complain about that, but only once we've checked for
a forward to improve error recovery }
if (sameparas and not sameret and
{ ensure that specifiers are the same as well }
(compare_paras(fwpd.paras,currpd.paras,cp_all,[cpo_ignorehidden,cpo_openequalisexact,cpo_ignoreuniv])=te_exact)
) or (gensameparas and not gensameret) then
sameparasfound:=true;
end;
if sameparasfound and
not (currpd.proctypeoption=potype_operator) then
begin
MessagePos(currpd.fileinfo,parser_e_overloaded_have_same_parameters);
tprocsym(currpd.procsym).write_parameter_lists(currpd);
end;
{ if we didn't reuse a forwarddef then we add the procdef to the overloaded
list }
if not forwardfound then

22
tests/test/tover5.pp Normal file
View File

@ -0,0 +1,22 @@
{ %FAIL }
program tover5;
{$mode objfpc}
type
TTestClass = class
procedure Test(aArg1: LongInt);
function Test(aArg1: LongInt): LongInt;
end;
procedure TTestClass.Test(aArg1: LongInt);
begin
end;
function TTestClass.Test(aArg1: Longint): LongInt;
begin
end;
begin
end.

25
tests/test/tover6.pp Normal file
View File

@ -0,0 +1,25 @@
{ %FAIL }
unit tover6;
{$mode objfpc}{$H+}
interface
procedure Test(aArg: LongInt);
function Test(aArg: LongInt): LongInt;
implementation
procedure Test(aArg: LongInt);
begin
end;
function Test(aArg: LongInt): LongInt;
begin
end;
end.

17
tests/test/tover7.pp Normal file
View File

@ -0,0 +1,17 @@
{ %FAIL }
program tover7;
{$mode objfpc}
procedure Test(aArg: LongInt);
begin
end;
function Test(aArg: LongInt): LongInt;
begin
end;
begin
end.

17
tests/test/tover8.pp Normal file
View File

@ -0,0 +1,17 @@
{ %FAIL }
program tover8;
{$mode objfpc}
generic procedure Test<T>(aArg: T);
begin
end;
generic function Test<T>(aArg: T): T;
begin
end;
begin
end.

40
tests/test/tover9.pp Normal file
View File

@ -0,0 +1,40 @@
unit tover9;
{$mode objfpc}
interface
{ this is the for xmlSchemaSetParserErrors in the xmlschemas.inc of the libxml
package }
procedure Test(aArg: PLongInt);
function Test(var aArg: LongInt): LongInt;
{ also check generic routines just to be sure }
generic procedure Test2<T>(aArg: PLongInt);
generic function Test2<T>(var aArg: LongInt): LongInt;
implementation
procedure Test(aArg: PLongInt);
begin
end;
function Test(var aArg: LongInt): LongInt;
begin
end;
generic procedure Test2<T>(aArg: PLongInt);
begin
end;
generic function Test2<T>(var aArg: LongInt): LongInt;
begin
end;
end.