Jelajahi Sumber

* create a new vmt entry also if return type differs
* search all parent classes for matching interface implementations

git-svn-id: trunk@8138 -

peter 18 tahun lalu
induk
melakukan
5e36a73b80
5 mengubah file dengan 159 tambahan dan 62 penghapusan
  1. 2 1
      .gitattributes
  2. 31 47
      compiler/nobj.pas
  3. 0 14
      tests/webtbf/tw3183b.pp
  4. 63 0
      tests/webtbs/tw9306a.pp
  5. 63 0
      tests/webtbs/tw9306b.pp

+ 2 - 1
.gitattributes

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

+ 31 - 47
compiler/nobj.pas

@@ -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 }
-                    else if (compare_paras(procdefcoll^.data.paras,pd.paras,cp_all,[])>=te_equal) then
+                    { same parameter and return types (parameter specifiers will be checked below) }
+                    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 }
-                        { only if both are virtual !!  }
-                        if (procdefcoll^.data.proccalloption<>pd.proccalloption) or
+                        { All parameter specifiers and some procedure the flags have to match
+                          except abstract and override }
+                        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;
-
-        sym:=tsym(search_class_member(_class,name));
-        if assigned(sym) and
-           (sym.typ=procsym) then
+        hashedid.id:=name;
+        hclass:=_class;
+        while assigned(hclass) do
           begin
           begin
-            { when the definition has overload directive set, we search for
-              overloaded definitions in the class, this only needs to be done once
-              for class entries as the tree keeps always the same }
-            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
+            srsym:=tsym(hclass.symtable.FindWithHash(hashedid));
+            if assigned(srsym) and
+               (srsym.typ=procsym) then
               begin
               begin
-                implprocdef:=tprocdef(Tprocsym(sym).ProcdefList[i]);
-                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
+                for i:=0 to Tprocsym(srsym).ProcdefList.Count-1 do
                   begin
                   begin
-                    result:=implprocdef;
-                    exit;
+                    implprocdef:=tprocdef(tprocsym(srsym).ProcdefList[i]);
+                    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
-                    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
+                  ImplIntf.AddImplProc(implprocdef)
                 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));

+ 0 - 14
tests/webtbf/tw3183b.pp

@@ -1,14 +0,0 @@
-{ %fail }
-{$mode objfpc}
-
-type
-  ta = interface
-    function a: longint;
-  end;
-
-  tb = interface(ta)
-    function a: ansistring;
-  end;
-
-begin
-end.

+ 63 - 0
tests/webtbs/tw9306a.pp

@@ -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 - 0
tests/webtbs/tw9306b.pp

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