Browse Source

* Delphi does not allow a generic method to be overloaded by a non generic type of the same name (unlike for generic types and non generic routines); this is probably done to simplify the implementation of implicit specializations of generic methods so we do this as well. For this we change the dummy symbol for generic routines from a typesym to a procsym
+ added tests

Note: what Delphi /does/ allow however is to overload a generic routine with a generic type... go figure. :/ We currently don't allow that

git-svn-id: trunk@48002 -

svenbarth 4 years ago
parent
commit
c96029ebd5
6 changed files with 114 additions and 3 deletions
  1. 4 0
      .gitattributes
  2. 13 3
      compiler/pdecsub.pas
  3. 25 0
      tests/test/tgenfunc24.pp
  4. 24 0
      tests/test/tgenfunc25.pp
  5. 24 0
      tests/test/tgenfunc26.pp
  6. 24 0
      tests/test/tgenfunc27.pp

+ 4 - 0
.gitattributes

@@ -15181,6 +15181,10 @@ tests/test/tgenfunc20.pp svneol=native#text/pascal
 tests/test/tgenfunc21.pp svneol=native#text/pascal
 tests/test/tgenfunc21.pp svneol=native#text/pascal
 tests/test/tgenfunc22.pp svneol=native#text/pascal
 tests/test/tgenfunc22.pp svneol=native#text/pascal
 tests/test/tgenfunc23.pp svneol=native#text/pascal
 tests/test/tgenfunc23.pp svneol=native#text/pascal
+tests/test/tgenfunc24.pp svneol=native#text/pascal
+tests/test/tgenfunc25.pp svneol=native#text/pascal
+tests/test/tgenfunc26.pp svneol=native#text/pascal
+tests/test/tgenfunc27.pp svneol=native#text/pascal
 tests/test/tgenfunc3.pp svneol=native#text/pascal
 tests/test/tgenfunc3.pp svneol=native#text/pascal
 tests/test/tgenfunc4.pp svneol=native#text/pascal
 tests/test/tgenfunc4.pp svneol=native#text/pascal
 tests/test/tgenfunc5.pp svneol=native#text/pascal
 tests/test/tgenfunc5.pp svneol=native#text/pascal

+ 13 - 3
compiler/pdecsub.pas

@@ -1066,7 +1066,8 @@ implementation
                            end
                            end
                          else if (srsym.typ=typesym) and
                          else if (srsym.typ=typesym) and
                              (sp_generic_dummy in srsym.symoptions) and
                              (sp_generic_dummy in srsym.symoptions) and
-                             (ttypesym(srsym).typedef.typ=undefineddef) then
+                             (ttypesym(srsym).typedef.typ=undefineddef) and
+                             not assigned(genericparams) then
                            begin
                            begin
                              { this is a generic dummy symbol that has not yet
                              { this is a generic dummy symbol that has not yet
                                been used; so we rename the dummy symbol and continue
                                been used; so we rename the dummy symbol and continue
@@ -1162,12 +1163,21 @@ implementation
               end;
               end;
             if not assigned(dummysym) then
             if not assigned(dummysym) then
               begin
               begin
-                dummysym:=ctypesym.create(orgspnongen,cundefineddef.create(true));
+                { overloading generic routines with non-generic types is not
+                  allowed, so we create a procsym as dummy }
+                dummysym:=cprocsym.create(orgspnongen);
                 if assigned(astruct) then
                 if assigned(astruct) then
                   astruct.symtable.insert(dummysym)
                   astruct.symtable.insert(dummysym)
                 else
                 else
                   symtablestack.top.insert(dummysym);
                   symtablestack.top.insert(dummysym);
-              end;
+              end
+            else if (dummysym.typ<>procsym) and
+                (
+                  { show error only for the declaration, not also the implementation }
+                  not assigned(astruct) or
+                  (symtablestack.top.symtablelevel<>main_program_level)
+                ) then
+              Message1(sym_e_duplicate_id,dummysym.realname);
             if not (sp_generic_dummy in dummysym.symoptions) then
             if not (sp_generic_dummy in dummysym.symoptions) then
               begin
               begin
                 include(dummysym.symoptions,sp_generic_dummy);
                 include(dummysym.symoptions,sp_generic_dummy);

+ 25 - 0
tests/test/tgenfunc24.pp

@@ -0,0 +1,25 @@
+{ %FAIL }
+
+program tgenfunc24;
+
+{$mode delphi}
+
+type
+  TTest = class
+  public type
+    Test = class
+    end;
+
+  public
+    procedure Test<T>;
+  end;
+
+procedure TTest.Test<T>;
+begin
+
+end;
+
+begin
+
+end.
+

+ 24 - 0
tests/test/tgenfunc25.pp

@@ -0,0 +1,24 @@
+{ %FAIL }
+
+program tgenfunc25;
+
+{$mode delphi}
+
+type
+  TTest = class
+  public
+    procedure Test<T>;
+  public type
+    Test = class
+    end;
+  end;
+
+procedure TTest.Test<T>;
+begin
+
+end;
+
+begin
+
+end.
+

+ 24 - 0
tests/test/tgenfunc26.pp

@@ -0,0 +1,24 @@
+{ %FAIL }
+
+unit tgenfunc26;
+
+{$mode objfpc}{$H+}
+
+interface
+
+generic procedure Test<T>;
+
+type
+  Test = record
+
+  end;
+
+implementation
+
+generic procedure Test<T>;
+begin
+
+end;
+
+end.
+

+ 24 - 0
tests/test/tgenfunc27.pp

@@ -0,0 +1,24 @@
+{ %FAIL }
+
+unit tgenfunc27;
+
+{$mode objfpc}{$H+}
+
+interface
+
+type
+  Test = record
+
+  end;
+
+generic procedure Test<T>;
+
+implementation
+
+generic procedure Test<T>;
+begin
+
+end;
+
+end.
+