* 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:
peter 2007-07-22 19:47:55 +00:00
parent 98cc116dd2
commit 5e36a73b80
5 changed files with 159 additions and 62 deletions

3
.gitattributes vendored
View File

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

View File

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

View File

@ -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
View 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
View 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.