From 2ad3c6dd97d08494ba0406b59868a5fd1198cbb9 Mon Sep 17 00:00:00 2001 From: svenbarth <pascaldragon@googlemail.com> Date: Sun, 16 Feb 2020 09:53:37 +0000 Subject: [PATCH] * fix global generic functions with constraints in mode Delphi by handling implementations with defines outside of parse_generic_parameters + added tests git-svn-id: trunk@44189 - --- .gitattributes | 3 +++ compiler/pdecsub.pas | 7 ++++++- compiler/pparautl.pas | 15 +++++++++++---- tests/test/tgenfunc20.pp | 35 +++++++++++++++++++++++++++++++++++ tests/test/tgenfunc21.pp | 35 +++++++++++++++++++++++++++++++++++ tests/test/tgenfunc22.pp | 19 +++++++++++++++++++ 6 files changed, 109 insertions(+), 5 deletions(-) create mode 100644 tests/test/tgenfunc20.pp create mode 100644 tests/test/tgenfunc21.pp create mode 100644 tests/test/tgenfunc22.pp diff --git a/.gitattributes b/.gitattributes index 66deef6aa7..0f81e59b24 100644 --- a/.gitattributes +++ b/.gitattributes @@ -14768,6 +14768,9 @@ tests/test/tgenfunc17.pp svneol=native#text/pascal tests/test/tgenfunc18.pp svneol=native#text/pascal tests/test/tgenfunc19.pp svneol=native#text/pascal tests/test/tgenfunc2.pp svneol=native#text/pascal +tests/test/tgenfunc20.pp svneol=native#text/pascal +tests/test/tgenfunc21.pp svneol=native#text/pascal +tests/test/tgenfunc22.pp svneol=native#text/pascal tests/test/tgenfunc3.pp svneol=native#text/pascal tests/test/tgenfunc4.pp svneol=native#text/pascal tests/test/tgenfunc5.pp svneol=native#text/pascal diff --git a/compiler/pdecsub.pas b/compiler/pdecsub.pas index 011677fc8e..b3f6d4e5f7 100644 --- a/compiler/pdecsub.pas +++ b/compiler/pdecsub.pas @@ -664,7 +664,7 @@ implementation message(type_e_type_id_expected) else begin - genericparams:=parse_generic_parameters(not(m_delphi in current_settings.modeswitches) or parse_only); + genericparams:=parse_generic_parameters(true); if not assigned(genericparams) then internalerror(2015061201); if genericparams.count=0 then @@ -835,6 +835,11 @@ implementation messagepos1(decltype.fileinfo,sym_e_generic_type_param_decl,decltype.realname); result:=false; end; + if df_genconstraint in impltype.typedef.defoptions then + begin + messagepos(tstoreddef(impltype.typedef).genconstraintdata.fileinfo,parser_e_generic_constraints_not_allowed_here); + result:=false; + end; end; end; diff --git a/compiler/pparautl.pas b/compiler/pparautl.pas index f18ca3a515..73f4ef3e4b 100644 --- a/compiler/pparautl.pas +++ b/compiler/pparautl.pas @@ -644,6 +644,11 @@ implementation messagepos1(fwtype.fileinfo,sym_e_generic_type_param_decl,fwtype.realname); result:=false; end; + if (fwpd.interfacedef or assigned(fwpd.struct)) and (df_genconstraint in currtype.typedef.defoptions) then + begin + messagepos(tstoreddef(currtype.typedef).genconstraintdata.fileinfo,parser_e_generic_constraints_not_allowed_here); + result:=false; + end; end; end; @@ -664,15 +669,17 @@ implementation - proc declared in interface of unit (or in class/record/object) and defined in implementation; here the fwpd might contain constraints while currpd must only contain undefineddefs - - forward declaration in implementation } + - forward declaration in implementation: here constraints must be + repeated } foundretdef:=false; for i:=0 to fwpd.genericparas.count-1 do begin fwtype:=ttypesym(fwpd.genericparas[i]); currtype:=ttypesym(currpd.genericparas[i]); - { if the type in the currpd isn't a pure undefineddef, then we can - stop right there } - if (currtype.typedef.typ<>undefineddef) or (df_genconstraint in currtype.typedef.defoptions) then + { if the type in the currpd isn't a pure undefineddef (thus there + are constraints and the fwpd was declared in the interface, then + we can stop right there } + if fwpd.interfacedef and ((currtype.typedef.typ<>undefineddef) or (df_genconstraint in currtype.typedef.defoptions)) then exit; if not foundretdef then begin diff --git a/tests/test/tgenfunc20.pp b/tests/test/tgenfunc20.pp new file mode 100644 index 0000000000..834ad7c7a0 --- /dev/null +++ b/tests/test/tgenfunc20.pp @@ -0,0 +1,35 @@ +unit tgenfunc20; + +{$mode objfpc}{$H+} + +interface + +{generic procedure TestProc1<T: class>; + +type + TTest = class + generic procedure Test<T: class>; + end;} + +implementation + +generic procedure TestProc2<T: class>; forward; + +{generic procedure TestProc1<T>; +begin +end; + +generic procedure TestProc1<T: class>(aArg1: T); +begin +end;} + +generic procedure TestProc2<T: class>; +begin +end; + +{generic procedure TTest.Test<T>; +begin +end;} + +end. + diff --git a/tests/test/tgenfunc21.pp b/tests/test/tgenfunc21.pp new file mode 100644 index 0000000000..f6879823ed --- /dev/null +++ b/tests/test/tgenfunc21.pp @@ -0,0 +1,35 @@ +unit tgenfunc21; + +{$mode delphi} + +interface + +procedure TestProc1<T: class>; overload; + +type + TTest = class + procedure Test<T: class>; + end; + +implementation + +procedure TestProc2<T: class>; forward; + +procedure TestProc1<T>; +begin +end; + +procedure TestProc1<T: class>(aArg1: T); overload; +begin +end; + +procedure TestProc2<T: class>; +begin +end; + +procedure TTest.Test<T>; +begin +end; + +end. + diff --git a/tests/test/tgenfunc22.pp b/tests/test/tgenfunc22.pp new file mode 100644 index 0000000000..acb01c8c1e --- /dev/null +++ b/tests/test/tgenfunc22.pp @@ -0,0 +1,19 @@ +{ %FAIL } + +unit tgenfunc22; + +{$mode delphi} + +interface + +procedure Test<T: class>; + +implementation + +procedure Test<T: class>; +begin + +end; + +end. +