Browse Source

* setup a proper symtable stack before parsing the generic declaration itself, resolves #9419

git-svn-id: trunk@8820 -
florian 18 years ago
parent
commit
7229dcfdcb
6 changed files with 76 additions and 26 deletions
  1. 1 0
      .gitattributes
  2. 19 0
      compiler/fmodule.pas
  3. 0 7
      compiler/pbase.pas
  4. 0 19
      compiler/psub.pas
  5. 36 0
      compiler/ptype.pas
  6. 20 0
      tests/webtbs/tw9419.pp

+ 1 - 0
.gitattributes

@@ -8478,6 +8478,7 @@ tests/webtbs/tw9347a.pp svneol=native#text/plain
 tests/webtbs/tw9347b.pp svneol=native#text/plain
 tests/webtbs/tw9384.pp svneol=native#text/plain
 tests/webtbs/tw9385.pp svneol=native#text/plain
+tests/webtbs/tw9419.pp svneol=native#text/plain
 tests/webtbs/tw9461.pp svneol=native#text/plain
 tests/webtbs/tw9667.pp svneol=native#text/plain
 tests/webtbs/tw9672.pp svneol=native#text/plain

+ 19 - 0
compiler/fmodule.pas

@@ -202,6 +202,7 @@ interface
     function get_module(moduleindex : longint) : tmodule;
     function get_source_file(moduleindex,fileindex : longint) : tinputfile;
     procedure addloadedunit(hp:tmodule);
+    function find_module_from_symtable(st:tsymtable):tmodule;
 
 
 implementation
@@ -221,6 +222,24 @@ implementation
                              Global Functions
 *****************************************************************************}
 
+    function find_module_from_symtable(st:tsymtable):tmodule;
+      var
+        hp : tmodule;
+      begin
+        result:=nil;
+        hp:=tmodule(loaded_units.first);
+        while assigned(hp) do
+          begin
+            if (hp.globalsymtable=st) or
+               (hp.localsymtable=st) then
+              begin
+                result:=hp;
+                exit;
+              end;
+            hp:=tmodule(hp.next);
+         end;
+      end;
+
     procedure set_current_module(p:tmodule);
       begin
         { save the state of the scanner }

+ 0 - 7
compiler/pbase.pas

@@ -116,13 +116,6 @@ implementation
        end;
 
 
-{ Unused:
-    function tokenstring(i : ttoken):string;
-      begin
-        tokenstring:=tokeninfo^[i].str;
-      end;
-}
-
     { consumes token i, write error if token is different }
     procedure consume(i : ttoken);
       begin

+ 0 - 19
compiler/psub.pas

@@ -1779,25 +1779,6 @@ implementation
 
 
     procedure specialize_objectdefs(p:TObject;arg:pointer);
-
-        function find_module_from_symtable(st:tsymtable):tmodule;
-        var
-          hp : tmodule;
-        begin
-          result:=nil;
-          hp:=tmodule(loaded_units.first);
-          while assigned(hp) do
-            begin
-              if (hp.globalsymtable=st) or
-                 (hp.localsymtable=st) then
-                begin
-                  result:=hp;
-                  exit;
-                end;
-              hp:=tmodule(hp.next);
-           end;
-        end;
-
       var
         i  : longint;
         hp : tdef;

+ 36 - 0
compiler/ptype.pas

@@ -67,6 +67,8 @@ implementation
        { symtable }
        symconst,symsym,symtable,
        defutil,defcmp,
+       { modules }
+       fmodule,
        { pass 1 }
        node,ncgrtti,nobj,
        nmat,nadd,ncal,nset,ncnv,ninl,ncon,nld,nflw,
@@ -86,6 +88,9 @@ implementation
         genericdef : tstoreddef;
         generictype : ttypesym;
         generictypelist : TFPObjectList;
+        oldsymtablestack   : tsymtablestack;
+        hmodule : tmodule;
+        pu : tused_unit;
       begin
         { retrieve generic def that we are going to replace }
         genericdef:=tstoreddef(pt1.resultdef);
@@ -148,6 +153,32 @@ implementation
         { force correct error location if too much type parameters are passed }
         if token<>_RSHARPBRACKET then
           consume(_RSHARPBRACKET);
+
+        { Setup symtablestack a definition time
+          to get types right, however this is not perfect, we should probably record
+          the resolved symbols }
+        oldsymtablestack:=symtablestack;
+        symtablestack:=tsymtablestack.create;
+        if not assigned(genericdef) then
+          internalerror(200705151);
+        hmodule:=find_module_from_symtable(genericdef.owner);
+        if hmodule=nil then
+          internalerror(200705152);
+        pu:=tused_unit(hmodule.used_units.first);
+        while assigned(pu) do
+          begin
+            if not assigned(pu.u.globalsymtable) then
+              internalerror(200705153);
+            symtablestack.push(pu.u.globalsymtable);
+            pu:=tused_unit(pu.next);
+          end;
+
+        if assigned(hmodule.globalsymtable) then
+          symtablestack.push(hmodule.globalsymtable);
+
+        { hacky, but necessary to insert the newly generated class properly }
+        symtablestack.push(oldsymtablestack.top);
+
         { Reparse the original type definition }
         if not err then
           begin
@@ -158,6 +189,11 @@ implementation
             { Consume the semicolon if it is also recorded }
             try_to_consume(_SEMICOLON);
           end;
+
+        { Restore symtablestack }
+        symtablestack.free;
+        symtablestack:=oldsymtablestack;
+
         generictypelist.free;
         consume(_RSHARPBRACKET);
       end;

+ 20 - 0
tests/webtbs/tw9419.pp

@@ -0,0 +1,20 @@
+uses
+  fgl;
+
+type
+  TEnum = (ta, tb, tc);
+
+  TMyMap = specialize TFPGMap<string, TEnum>;
+
+var
+  map : TMyMap;
+  c : TEnum;
+  i : Longint;
+
+begin
+  map := TMymap.Create();
+
+  map.Add('Hello', ta);
+
+  map.Find('Hello', i);
+end.