From 9fcff238f11a55187ccdce5772f53c7cdc4a614f Mon Sep 17 00:00:00 2001
From: florian <florian@freepascal.org>
Date: Fri, 6 Apr 2012 20:35:18 +0000
Subject: [PATCH] * create and push array def before the array range is parsed,
 this allows generic parameters to be used in the range definition, resolves
 #21592

git-svn-id: trunk@20725 -
---
 .gitattributes          |  1 +
 compiler/ptype.pas      | 62 ++++++++++++++++++++++++-----------------
 tests/webtbs/tw21592.pp | 14 ++++++++++
 3 files changed, 51 insertions(+), 26 deletions(-)
 create mode 100644 tests/webtbs/tw21592.pp

diff --git a/.gitattributes b/.gitattributes
index d4b020fcf8..307e70d59a 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -12310,6 +12310,7 @@ tests/webtbs/tw21472.pp svneol=native#text/pascal
 tests/webtbs/tw21551.pp svneol=native#text/plain
 tests/webtbs/tw2158.pp svneol=native#text/plain
 tests/webtbs/tw2159.pp svneol=native#text/plain
+tests/webtbs/tw21592.pp svneol=native#text/pascal
 tests/webtbs/tw21593.pp svneol=native#text/pascal
 tests/webtbs/tw2163.pp svneol=native#text/plain
 tests/webtbs/tw2176.pp svneol=native#text/plain
diff --git a/compiler/ptype.pas b/compiler/ptype.pas
index eb662085f4..6222a11168 100644
--- a/compiler/ptype.pas
+++ b/compiler/ptype.pas
@@ -1059,6 +1059,7 @@ implementation
         var
           old_current_genericdef,
           old_current_specializedef: tstoreddef;
+          first,
           old_parse_generic: boolean;
         begin
            old_current_genericdef:=current_genericdef;
@@ -1067,8 +1068,28 @@ implementation
 
            current_genericdef:=nil;
            current_specializedef:=nil;
-           arrdef:=nil;
+           first:=true;
+           arrdef:=tarraydef.create(0,0,s32inttype);
            consume(_ARRAY);
+
+           { usage of specialized type inside its generic template }
+           if assigned(genericdef) then
+             current_specializedef:=arrdef
+           { reject declaration of generic class inside generic class }
+           else if assigned(genericlist) then
+             current_genericdef:=arrdef;
+           symtablestack.push(arrdef.symtable);
+           insert_generic_parameter_types(arrdef,genericdef,genericlist);
+           { 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;
+
            { open array? }
            if try_to_consume(_LECKKLAMMER) then
              begin
@@ -1136,17 +1157,23 @@ implementation
                      pt.free;
                    end;
 
-                  { if the array is already created add the new arrray
-                    as element of the existing array, otherwise create a new array }
-                  if assigned(arrdef) then
+                  { if we are not at the first dimension, add the new arrray
+                    as element of the existing array, otherwise modify the existing array }
+                  if not(first) then
                     begin
                       arrdef.elementdef:=tarraydef.create(lowval.svalue,highval.svalue,indexdef);
+                      { push new symtable }
+                      symtablestack.pop(arrdef.symtable);
                       arrdef:=tarraydef(arrdef.elementdef);
+                      symtablestack.push(arrdef.symtable);
                     end
                   else
                     begin
-                      arrdef:=tarraydef.create(lowval.svalue,highval.svalue,indexdef);
+                      arrdef.lowrange:=lowval.svalue;
+                      arrdef.highrange:=highval.svalue;
+                      arrdef.rangedef:=indexdef;
                       def:=arrdef;
+                      first:=false;
                     end;
                   if is_packed then
                     include(arrdef.arrayoptions,ado_IsBitPacked);
@@ -1162,30 +1189,12 @@ implementation
              begin
                 if is_packed then
                   Message(parser_e_packed_dynamic_open_array);
-                arrdef:=tarraydef.create(0,-1,s32inttype);
+                arrdef.lowrange:=0;
+                arrdef.highrange:=-1;
+                arrdef.rangedef:=s32inttype;
                 include(arrdef.arrayoptions,ado_IsDynamicArray);
                 def:=arrdef;
              end;
-           if assigned(arrdef) then
-             begin
-               { usage of specialized type inside its generic template }
-               if assigned(genericdef) then
-                 current_specializedef:=arrdef
-               { reject declaration of generic class inside generic class }
-               else if assigned(genericlist) then
-                 current_genericdef:=arrdef;
-               symtablestack.push(arrdef.symtable);
-               insert_generic_parameter_types(arrdef,genericdef,genericlist);
-               { 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);
            { set element type of the last array definition }
@@ -1203,6 +1212,7 @@ implementation
            current_specializedef:=old_current_specializedef;
         end;
 
+
         function procvar_dec(genericdef:tstoreddef;genericlist:TFPObjectList):tdef;
           var
             is_func:boolean;
diff --git a/tests/webtbs/tw21592.pp b/tests/webtbs/tw21592.pp
new file mode 100644
index 0000000000..538e9d7ae4
--- /dev/null
+++ b/tests/webtbs/tw21592.pp
@@ -0,0 +1,14 @@
+{$MODE DELPHI}
+
+type
+  TBytesOverlay<T> = array [0..SizeOf(T) - 1] of Byte;
+    { Error: Identifier not found "T" }
+
+var
+  a : TBytesOverlay<Byte>;
+
+begin
+  if sizeof(a)<>1 then
+    halt(1);
+  writeln('ok');
+end.