Browse Source

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

svenbarth 5 years ago
parent
commit
b62045809d
7 changed files with 187 additions and 26 deletions
  1. 5 0
      .gitattributes
  2. 61 26
      compiler/pparautl.pas
  3. 22 0
      tests/test/tover5.pp
  4. 25 0
      tests/test/tover6.pp
  5. 17 0
      tests/test/tover7.pp
  6. 17 0
      tests/test/tover8.pp
  7. 40 0
      tests/test/tover9.pp

+ 5 - 0
.gitattributes

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

+ 61 - 26
compiler/pparautl.pas

@@ -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 - 0
tests/test/tover5.pp

@@ -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 - 0
tests/test/tover6.pp

@@ -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 - 0
tests/test/tover7.pp

@@ -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 - 0
tests/test/tover8.pp

@@ -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 - 0
tests/test/tover9.pp

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