From 17a276aabc1328f5374ef88dca6c4aa34d723aef Mon Sep 17 00:00:00 2001 From: svenbarth Date: Mon, 2 Jan 2012 16:02:51 +0000 Subject: [PATCH] * compiler\pdecl.pas: in "array_dec" and "procvar_dec" "parse_generic" needs to be true if the currently parsed declaration (array or procvar) is declared inside a generic, because only then specializations of other types (it does not matter whether they are inline or in a type section of the current generic) are parsed correctly (this fixes Mantis #20577 and Mantis #20955 ) + add tests for the mentioned bug reports (testing only the array case) (tests\webtbs) and tests for the procvar case (tests\test) git-svn-id: trunk@19953 - --- .gitattributes | 7 +++++++ compiler/ptype.pas | 20 ++++++++++++++++++-- tests/test/tgeneric69.pp | 23 +++++++++++++++++++++++ tests/test/tgeneric70.pp | 22 ++++++++++++++++++++++ tests/test/tgeneric71.pp | 23 +++++++++++++++++++++++ tests/webtbs/tw20577a.pp | 33 +++++++++++++++++++++++++++++++++ tests/webtbs/tw20577b.pp | 36 ++++++++++++++++++++++++++++++++++++ tests/webtbs/tw20995a.pp | 20 ++++++++++++++++++++ tests/webtbs/tw20995b.pp | 18 ++++++++++++++++++ 9 files changed, 200 insertions(+), 2 deletions(-) create mode 100644 tests/test/tgeneric69.pp create mode 100644 tests/test/tgeneric70.pp create mode 100644 tests/test/tgeneric71.pp create mode 100644 tests/webtbs/tw20577a.pp create mode 100644 tests/webtbs/tw20577b.pp create mode 100644 tests/webtbs/tw20995a.pp create mode 100644 tests/webtbs/tw20995b.pp diff --git a/.gitattributes b/.gitattributes index 2191dbb969..85a92d3105 100644 --- a/.gitattributes +++ b/.gitattributes @@ -10228,7 +10228,10 @@ tests/test/tgeneric65.pp svneol=native#text/pascal tests/test/tgeneric66.pp svneol=native#text/pascal tests/test/tgeneric67.pp svneol=native#text/pascal tests/test/tgeneric68.pp svneol=native#text/pascal +tests/test/tgeneric69.pp svneol=native#text/pascal tests/test/tgeneric7.pp svneol=native#text/plain +tests/test/tgeneric70.pp svneol=native#text/pascal +tests/test/tgeneric71.pp svneol=native#text/pascal tests/test/tgeneric8.pp svneol=native#text/plain tests/test/tgeneric9.pp svneol=native#text/plain tests/test/tgoto.pp svneol=native#text/plain @@ -12024,6 +12027,8 @@ tests/webtbs/tw2045.pp svneol=native#text/plain tests/webtbs/tw2046a.pp svneol=native#text/plain tests/webtbs/tw20527.pp svneol=native#text/plain tests/webtbs/tw20557.pp svneol=native#text/pascal +tests/webtbs/tw20577a.pp svneol=native#text/pascal +tests/webtbs/tw20577b.pp svneol=native#text/pascal tests/webtbs/tw2059.pp svneol=native#text/plain tests/webtbs/tw20594.pp svneol=native#text/pascal tests/webtbs/tw20627.pp svneol=native#text/pascal @@ -12046,6 +12051,8 @@ tests/webtbs/tw20872c.pp svneol=native#text/pascal tests/webtbs/tw20874a.pp svneol=native#text/pascal tests/webtbs/tw20874b.pp svneol=native#text/pascal tests/webtbs/tw20889.pp svneol=native#text/pascal +tests/webtbs/tw20995a.pp svneol=native#text/pascal +tests/webtbs/tw20995b.pp svneol=native#text/pascal tests/webtbs/tw2109.pp svneol=native#text/plain tests/webtbs/tw2110.pp svneol=native#text/plain tests/webtbs/tw2128.pp svneol=native#text/plain diff --git a/compiler/ptype.pas b/compiler/ptype.pas index 411ef868f6..ab5fc03d2e 100644 --- a/compiler/ptype.pas +++ b/compiler/ptype.pas @@ -1119,7 +1119,15 @@ implementation current_genericdef:=arrdef; symtablestack.push(arrdef.symtable); insert_generic_parameter_types(arrdef,genericdef,genericlist); - parse_generic:=(df_generic in arrdef.defoptions); + { there are two possibilties for the following to be true: + * the array declaration itself is generic + * the array is declared inside a generic + in both cases we need "parse_generic" and "current_genericdef" + so that e.g. specializations of another generic inside the + current generic can be used (either inline ones or "type" ones) } + parse_generic:=(df_generic in arrdef.defoptions) or old_parse_generic; + if parse_generic and not assigned(current_genericdef) then + current_genericdef:=old_current_genericdef; end; consume(_OF); read_anon_type(tt2,true); @@ -1166,7 +1174,15 @@ implementation current_genericdef:=pd; symtablestack.push(pd.parast); insert_generic_parameter_types(pd,genericdef,genericlist); - parse_generic:=(df_generic in pd.defoptions); + { there are two possibilties for the following to be true: + * the procvar declaration itself is generic + * the procvar is declared inside a generic + in both cases we need "parse_generic" and "current_genericdef" + so that e.g. specializations of another generic inside the + current generic can be used (either inline ones or "type" ones) } + parse_generic:=(df_generic in pd.defoptions) or old_parse_generic; + if parse_generic and not assigned(current_genericdef) then + current_genericdef:=old_current_genericdef; { don't allow to add defs to the symtable - use it for type param search only } tparasymtable(pd.parast).readonly:=true; diff --git a/tests/test/tgeneric69.pp b/tests/test/tgeneric69.pp new file mode 100644 index 0000000000..c2dbd20252 --- /dev/null +++ b/tests/test/tgeneric69.pp @@ -0,0 +1,23 @@ +{ %NORUN } + +{ This tests that one can use a specialization of another generic which was + introduced in the currently parsed generic can be used as a parameter type + in a procedure variable introduced in the current generic as well } +program tgeneric69; + +{$mode delphi} + +type + TSomeGeneric = class + + end; + + TSomeOtherGeneric = class + type + TSomeGenericT = TSomeGeneric; + TSomeProc = procedure(aParam: TSomeGenericT); + end; + +begin + +end. diff --git a/tests/test/tgeneric70.pp b/tests/test/tgeneric70.pp new file mode 100644 index 0000000000..684bd7bec2 --- /dev/null +++ b/tests/test/tgeneric70.pp @@ -0,0 +1,22 @@ +{ %NORUN } + +{ This tests that one can use a specialization of another generic which was + introduced in the currently parsed generic can be used as a parameter type + in a procedure variable introduced in the current generic as well } +program tgeneric70; + +{$mode delphi} + +type + TSomeGeneric = class + + end; + + TSomeOtherGeneric = class + type + TSomeProc = procedure(aParam: TSomeGeneric); + end; + +begin + +end. diff --git a/tests/test/tgeneric71.pp b/tests/test/tgeneric71.pp new file mode 100644 index 0000000000..06235c8143 --- /dev/null +++ b/tests/test/tgeneric71.pp @@ -0,0 +1,23 @@ +{ %NORUN } + +{ This tests that one can use a specialization of another generic which was + introduced in the currently parsed generic can be used as a parameter type + in a procedure variable introduced in the current generic as well } +program tgeneric71; + +{$mode objfpc} + +type + generic TSomeGeneric = class + + end; + + generic TSomeOtherGeneric = class + type + TSomeGenericT = specialize TSomeGeneric; + TSomeProc = procedure(aParam: TSomeGenericT); + end; + +begin + +end. diff --git a/tests/webtbs/tw20577a.pp b/tests/webtbs/tw20577a.pp new file mode 100644 index 0000000000..a6521d2ac4 --- /dev/null +++ b/tests/webtbs/tw20577a.pp @@ -0,0 +1,33 @@ +program tw20577a; + +{$mode delphi}{$H+} + +type + + TSimpleHashBucket = record + HashCode : Integer; + Value : T; + end; + + TSimpleHashBucketArray = array of TSimpleHashBucket; + + { TSimpleHash } + + TSimpleHash = class + private + FBuckets : TSimpleHashBucketArray; + procedure test; + end; + +{ TSimpleHash } + +procedure TSimpleHash.test; +var + oldBuckets : TSimpleHashBucketArray; +begin + oldBuckets := FBuckets; + +end; + +begin +end. diff --git a/tests/webtbs/tw20577b.pp b/tests/webtbs/tw20577b.pp new file mode 100644 index 0000000000..a2078fd7b4 --- /dev/null +++ b/tests/webtbs/tw20577b.pp @@ -0,0 +1,36 @@ +program tw20577b; + +{$mode delphi}{$H+} + +type + + TSimpleHashBucket = record + HashCode : Integer; + Value : T; + end; + + TSimpleHashBucketArray = array of TSimpleHashBucket; + + { TSimpleHash } + + TSimpleHash = class + private + type + THashBucket = TSimpleHashBucket; + var + FBuckets: array of THashBucket; + procedure test; + end; + +{ TSimpleHash } + +procedure TSimpleHash.test; +var + oldBuckets : TSimpleHashBucketArray; +begin + oldBuckets := FBuckets; + +end; + +begin +end. diff --git a/tests/webtbs/tw20995a.pp b/tests/webtbs/tw20995a.pp new file mode 100644 index 0000000000..1be690fc01 --- /dev/null +++ b/tests/webtbs/tw20995a.pp @@ -0,0 +1,20 @@ +program tw20995a; + +{$mode delphi}{$H+} + +type + ITest = interface + end; + + TTest = class + type + IGenTest = ITest; + private + FData: array of IGenTest; + end; + + TObjTest = TTest; + +begin +end. + diff --git a/tests/webtbs/tw20995b.pp b/tests/webtbs/tw20995b.pp new file mode 100644 index 0000000000..101b9cf6ee --- /dev/null +++ b/tests/webtbs/tw20995b.pp @@ -0,0 +1,18 @@ +program tw20995b; + +{$mode delphi}{$H+} + +type + ITest = interface + end; + + TTest = class + private + FData: array of ITest; + end; + + TObjTest = TTest; + +begin +end. +