mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-09-12 09:29:07 +02:00
* create a new vmt entry also if return type differs
* search all parent classes for matching interface implementations git-svn-id: trunk@8138 -
This commit is contained in:
parent
98cc116dd2
commit
5e36a73b80
3
.gitattributes
vendored
3
.gitattributes
vendored
@ -7285,7 +7285,6 @@ tests/webtbf/tw3116.pp svneol=native#text/plain
|
|||||||
tests/webtbf/tw3126.pp svneol=native#text/plain
|
tests/webtbf/tw3126.pp svneol=native#text/plain
|
||||||
tests/webtbf/tw3145.pp svneol=native#text/plain
|
tests/webtbf/tw3145.pp svneol=native#text/plain
|
||||||
tests/webtbf/tw3183.pp svneol=native#text/plain
|
tests/webtbf/tw3183.pp svneol=native#text/plain
|
||||||
tests/webtbf/tw3183b.pp svneol=native#text/plain
|
|
||||||
tests/webtbf/tw3186.pp svneol=native#text/plain
|
tests/webtbf/tw3186.pp svneol=native#text/plain
|
||||||
tests/webtbf/tw3218.pp svneol=native#text/plain
|
tests/webtbf/tw3218.pp svneol=native#text/plain
|
||||||
tests/webtbf/tw3241.pp svneol=native#text/plain
|
tests/webtbf/tw3241.pp svneol=native#text/plain
|
||||||
@ -8353,6 +8352,8 @@ tests/webtbs/tw9209.pp svneol=native#text/plain
|
|||||||
tests/webtbs/tw9221.pp svneol=native#text/plain
|
tests/webtbs/tw9221.pp svneol=native#text/plain
|
||||||
tests/webtbs/tw9261.pp svneol=native#text/x-pascal
|
tests/webtbs/tw9261.pp svneol=native#text/x-pascal
|
||||||
tests/webtbs/tw9278.pp svneol=native#text/plain
|
tests/webtbs/tw9278.pp svneol=native#text/plain
|
||||||
|
tests/webtbs/tw9306a.pp -text
|
||||||
|
tests/webtbs/tw9306b.pp -text
|
||||||
tests/webtbs/tw9309.pp -text
|
tests/webtbs/tw9309.pp -text
|
||||||
tests/webtbs/ub1873.pp svneol=native#text/plain
|
tests/webtbs/ub1873.pp svneol=native#text/plain
|
||||||
tests/webtbs/ub1883.pp svneol=native#text/plain
|
tests/webtbs/ub1883.pp svneol=native#text/plain
|
||||||
|
@ -128,7 +128,7 @@ implementation
|
|||||||
uses
|
uses
|
||||||
SysUtils,
|
SysUtils,
|
||||||
globals,verbose,systems,
|
globals,verbose,systems,
|
||||||
symtable,symconst,symtype,defcmp,
|
symbase,symtable,symconst,symtype,defcmp,
|
||||||
dbgbase,
|
dbgbase,
|
||||||
ncgrtti
|
ncgrtti
|
||||||
;
|
;
|
||||||
@ -308,8 +308,9 @@ implementation
|
|||||||
MessagePos1(pd.fileinfo,parser_w_should_use_override,pd.fullprocname(false));
|
MessagePos1(pd.fileinfo,parser_w_should_use_override,pd.fullprocname(false));
|
||||||
end;
|
end;
|
||||||
end
|
end
|
||||||
{ same parameters }
|
{ same parameter and return types (parameter specifiers will be checked below) }
|
||||||
else if (compare_paras(procdefcoll^.data.paras,pd.paras,cp_all,[])>=te_equal) then
|
else if (compare_paras(procdefcoll^.data.paras,pd.paras,cp_none,[])>=te_equal) and
|
||||||
|
compatible_childmethod_resultdef(procdefcoll^.data.returndef,pd.returndef) then
|
||||||
begin
|
begin
|
||||||
{ overload is inherited }
|
{ overload is inherited }
|
||||||
if (po_overload in procdefcoll^.data.procoptions) then
|
if (po_overload in procdefcoll^.data.procoptions) then
|
||||||
@ -324,9 +325,10 @@ implementation
|
|||||||
include(pd.procoptions,po_hascallingconvention);
|
include(pd.procoptions,po_hascallingconvention);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ the flags have to match except abstract and override }
|
{ All parameter specifiers and some procedure the flags have to match
|
||||||
{ only if both are virtual !! }
|
except abstract and override }
|
||||||
if (procdefcoll^.data.proccalloption<>pd.proccalloption) or
|
if (compare_paras(procdefcoll^.data.paras,pd.paras,cp_all,[])<te_equal) or
|
||||||
|
(procdefcoll^.data.proccalloption<>pd.proccalloption) or
|
||||||
(procdefcoll^.data.proctypeoption<>pd.proctypeoption) or
|
(procdefcoll^.data.proctypeoption<>pd.proctypeoption) or
|
||||||
((procdefcoll^.data.procoptions*po_comp)<>(pd.procoptions*po_comp)) then
|
((procdefcoll^.data.procoptions*po_comp)<>(pd.procoptions*po_comp)) then
|
||||||
begin
|
begin
|
||||||
@ -334,19 +336,6 @@ implementation
|
|||||||
tprocsym(procdefcoll^.data.procsym).write_parameter_lists(pd);
|
tprocsym(procdefcoll^.data.procsym).write_parameter_lists(pd);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ error, if the return types aren't equal }
|
|
||||||
if not compatible_childmethod_resultdef(procdefcoll^.data.returndef,pd.returndef) then
|
|
||||||
begin
|
|
||||||
if not((m_delphi in current_settings.modeswitches) and
|
|
||||||
is_interface(_class)) then
|
|
||||||
Message2(parser_e_overridden_methods_not_same_ret,pd.fullprocname(false),
|
|
||||||
procdefcoll^.data.fullprocname(false))
|
|
||||||
else
|
|
||||||
{ Delphi allows changing the result type of interface methods from anything to
|
|
||||||
anything (JM) }
|
|
||||||
Message2(parser_w_overridden_methods_not_same_ret,pd.fullprocname(false),
|
|
||||||
procdefcoll^.data.fullprocname(false));
|
|
||||||
end;
|
|
||||||
{ check if the method to override is visible, check is only needed
|
{ check if the method to override is visible, check is only needed
|
||||||
for the current parsed class. Parent classes are already validated and
|
for the current parsed class. Parent classes are already validated and
|
||||||
need to include all virtual methods including the ones not visible in the
|
need to include all virtual methods including the ones not visible in the
|
||||||
@ -451,36 +440,37 @@ implementation
|
|||||||
po_comp = [po_classmethod,po_staticmethod,po_interrupt,po_iocheck,po_msgstr,po_msgint,
|
po_comp = [po_classmethod,po_staticmethod,po_interrupt,po_iocheck,po_msgstr,po_msgint,
|
||||||
po_exports,po_varargs,po_explicitparaloc,po_nostackframe];
|
po_exports,po_varargs,po_explicitparaloc,po_nostackframe];
|
||||||
var
|
var
|
||||||
sym: tsym;
|
|
||||||
implprocdef : Tprocdef;
|
implprocdef : Tprocdef;
|
||||||
i: cardinal;
|
i: cardinal;
|
||||||
|
hclass : tobjectdef;
|
||||||
|
hashedid : THashedIDString;
|
||||||
|
srsym : tsym;
|
||||||
begin
|
begin
|
||||||
result:=nil;
|
result:=nil;
|
||||||
|
hashedid.id:=name;
|
||||||
sym:=tsym(search_class_member(_class,name));
|
hclass:=_class;
|
||||||
if assigned(sym) and
|
while assigned(hclass) do
|
||||||
(sym.typ=procsym) then
|
|
||||||
begin
|
begin
|
||||||
{ when the definition has overload directive set, we search for
|
srsym:=tsym(hclass.symtable.FindWithHash(hashedid));
|
||||||
overloaded definitions in the class, this only needs to be done once
|
if assigned(srsym) and
|
||||||
for class entries as the tree keeps always the same }
|
(srsym.typ=procsym) then
|
||||||
if (not tprocsym(sym).overloadchecked) and
|
|
||||||
(po_overload in tprocdef(tprocsym(sym).ProcdefList[0]).procoptions) and
|
|
||||||
(tprocsym(sym).owner.symtabletype=ObjectSymtable) then
|
|
||||||
search_class_overloads(tprocsym(sym));
|
|
||||||
|
|
||||||
for i:=0 to Tprocsym(sym).ProcdefList.Count-1 do
|
|
||||||
begin
|
begin
|
||||||
implprocdef:=tprocdef(Tprocsym(sym).ProcdefList[i]);
|
for i:=0 to Tprocsym(srsym).ProcdefList.Count-1 do
|
||||||
if (compare_paras(proc.paras,implprocdef.paras,cp_none,[])>=te_equal) and
|
|
||||||
(proc.proccalloption=implprocdef.proccalloption) and
|
|
||||||
(proc.proctypeoption=implprocdef.proctypeoption) and
|
|
||||||
((proc.procoptions*po_comp)=((implprocdef.procoptions+[po_virtualmethod])*po_comp)) then
|
|
||||||
begin
|
begin
|
||||||
result:=implprocdef;
|
implprocdef:=tprocdef(tprocsym(srsym).ProcdefList[i]);
|
||||||
exit;
|
if (implprocdef.procsym=tprocsym(srsym)) and
|
||||||
|
(compare_paras(proc.paras,implprocdef.paras,cp_all,[cpo_ignorehidden,cpo_comparedefaultvalue])>=te_equal) and
|
||||||
|
compatible_childmethod_resultdef(proc.returndef,implprocdef.returndef) and
|
||||||
|
(proc.proccalloption=implprocdef.proccalloption) and
|
||||||
|
(proc.proctypeoption=implprocdef.proctypeoption) and
|
||||||
|
((proc.procoptions*po_comp)=((implprocdef.procoptions+[po_virtualmethod])*po_comp)) then
|
||||||
|
begin
|
||||||
|
result:=implprocdef;
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
hclass:=hclass.childof;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -513,13 +503,7 @@ implementation
|
|||||||
implprocdef:=intf_search_procdef_by_name(tprocdef(def),tprocdef(def).procsym.name);
|
implprocdef:=intf_search_procdef_by_name(tprocdef(def),tprocdef(def).procsym.name);
|
||||||
{ Add procdef to the implemented interface }
|
{ Add procdef to the implemented interface }
|
||||||
if assigned(implprocdef) then
|
if assigned(implprocdef) then
|
||||||
begin
|
ImplIntf.AddImplProc(implprocdef)
|
||||||
if (compare_paras(tprocdef(def).paras,implprocdef.paras,cp_all,[cpo_ignorehidden,cpo_comparedefaultvalue])<te_equal) or
|
|
||||||
not compatible_childmethod_resultdef(tprocdef(def).returndef,implprocdef.returndef) then
|
|
||||||
MessagePos1(tprocdef(implprocdef).fileinfo,parser_e_header_dont_match_forward,
|
|
||||||
tprocdef(def).fullprocname(false));
|
|
||||||
ImplIntf.AddImplProc(implprocdef)
|
|
||||||
end
|
|
||||||
else
|
else
|
||||||
if ImplIntf.IType = etStandard then
|
if ImplIntf.IType = etStandard then
|
||||||
Message1(sym_e_no_matching_implementation_found,tprocdef(def).fullprocname(false));
|
Message1(sym_e_no_matching_implementation_found,tprocdef(def).fullprocname(false));
|
||||||
|
@ -1,14 +0,0 @@
|
|||||||
{ %fail }
|
|
||||||
{$mode objfpc}
|
|
||||||
|
|
||||||
type
|
|
||||||
ta = interface
|
|
||||||
function a: longint;
|
|
||||||
end;
|
|
||||||
|
|
||||||
tb = interface(ta)
|
|
||||||
function a: ansistring;
|
|
||||||
end;
|
|
||||||
|
|
||||||
begin
|
|
||||||
end.
|
|
63
tests/webtbs/tw9306a.pp
Normal file
63
tests/webtbs/tw9306a.pp
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
{$mode objfpc}
|
||||||
|
|
||||||
|
type
|
||||||
|
IIntf = interface
|
||||||
|
function Foo(const S: string): string;
|
||||||
|
end;
|
||||||
|
|
||||||
|
IIntf2 = interface(IIntf)
|
||||||
|
function Foo(const S: string): Integer;
|
||||||
|
end;
|
||||||
|
|
||||||
|
TIntf = class(TInterfacedObject, IIntf)
|
||||||
|
protected
|
||||||
|
{ IIntf }
|
||||||
|
function Foo(const S: string): string;
|
||||||
|
end;
|
||||||
|
|
||||||
|
TIntf2 = class(TIntf, IIntf2)
|
||||||
|
public
|
||||||
|
{ IIntf2 }
|
||||||
|
function Foo(const S: string): Integer; overload;
|
||||||
|
end;
|
||||||
|
|
||||||
|
var
|
||||||
|
erridx : longint;
|
||||||
|
|
||||||
|
{ TIntf }
|
||||||
|
|
||||||
|
function TIntf.Foo(const S: string): string;
|
||||||
|
begin
|
||||||
|
writeln('TIntf.Foo: ',S);
|
||||||
|
if erridx=0 then
|
||||||
|
erridx:=1;
|
||||||
|
result:=S;
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ TIntf2 }
|
||||||
|
|
||||||
|
function TIntf2.Foo(const S: string): Integer;
|
||||||
|
begin
|
||||||
|
writeln('TIntf2.Foo: ',S);
|
||||||
|
if erridx=1 then
|
||||||
|
erridx:=2;
|
||||||
|
result:=0;
|
||||||
|
end;
|
||||||
|
|
||||||
|
var
|
||||||
|
i1 : IIntf;
|
||||||
|
i2 : IIntf2;
|
||||||
|
begin
|
||||||
|
erridx:=0;
|
||||||
|
|
||||||
|
i1:=TIntf2.Create;
|
||||||
|
i1.Foo('1234');
|
||||||
|
|
||||||
|
i2:=TIntf2.Create;
|
||||||
|
i2.Foo('1234');
|
||||||
|
if erridx<>2 then
|
||||||
|
begin
|
||||||
|
writeln('Error');
|
||||||
|
halt(1);
|
||||||
|
end;
|
||||||
|
end.
|
63
tests/webtbs/tw9306b.pp
Normal file
63
tests/webtbs/tw9306b.pp
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
{$mode delphi}
|
||||||
|
|
||||||
|
type
|
||||||
|
IIntf = interface
|
||||||
|
function Foo(const S: string): string;
|
||||||
|
end;
|
||||||
|
|
||||||
|
IIntf2 = interface(IIntf)
|
||||||
|
function Foo(const S: string): Integer;
|
||||||
|
end;
|
||||||
|
|
||||||
|
TIntf = class(TInterfacedObject, IIntf)
|
||||||
|
protected
|
||||||
|
{ IIntf }
|
||||||
|
function Foo(const S: string): string;
|
||||||
|
end;
|
||||||
|
|
||||||
|
TIntf2 = class(TIntf, IIntf2)
|
||||||
|
public
|
||||||
|
{ IIntf2 }
|
||||||
|
function Foo(const S: string): Integer; overload;
|
||||||
|
end;
|
||||||
|
|
||||||
|
var
|
||||||
|
erridx : longint;
|
||||||
|
|
||||||
|
{ TIntf }
|
||||||
|
|
||||||
|
function TIntf.Foo(const S: string): string;
|
||||||
|
begin
|
||||||
|
writeln('TIntf.Foo: ',S);
|
||||||
|
if erridx=0 then
|
||||||
|
erridx:=1;
|
||||||
|
result:=S;
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ TIntf2 }
|
||||||
|
|
||||||
|
function TIntf2.Foo(const S: string): Integer;
|
||||||
|
begin
|
||||||
|
writeln('TIntf2.Foo: ',S);
|
||||||
|
if erridx=1 then
|
||||||
|
erridx:=2;
|
||||||
|
result:=0;
|
||||||
|
end;
|
||||||
|
|
||||||
|
var
|
||||||
|
i1 : IIntf;
|
||||||
|
i2 : IIntf2;
|
||||||
|
begin
|
||||||
|
erridx:=0;
|
||||||
|
|
||||||
|
i1:=TIntf2.Create;
|
||||||
|
i1.Foo('1234');
|
||||||
|
|
||||||
|
i2:=TIntf2.Create;
|
||||||
|
i2.Foo('1234');
|
||||||
|
if erridx<>2 then
|
||||||
|
begin
|
||||||
|
writeln('Error');
|
||||||
|
halt(1);
|
||||||
|
end;
|
||||||
|
end.
|
Loading…
Reference in New Issue
Block a user