Bladeren bron

When searching for the generic def of nested types inside specializations we first need to check local declarations inside the method if we are in one. Only then we may search inside the type's declaration. Fixes #20836 .

git-svn-id: trunk@19777 -
svenbarth 13 jaren geleden
bovenliggende
commit
a1ef0add65
3 gewijzigde bestanden met toevoegingen van 56 en 2 verwijderingen
  1. 1 0
      .gitattributes
  2. 26 2
      compiler/pdecl.pas
  3. 29 0
      tests/webtbs/tw20836.pp

+ 1 - 0
.gitattributes

@@ -11942,6 +11942,7 @@ tests/webtbs/tw2069.pp svneol=native#text/plain
 tests/webtbs/tw20690.pp svneol=native#text/pascal
 tests/webtbs/tw20690.pp svneol=native#text/pascal
 tests/webtbs/tw2072.pp svneol=native#text/plain
 tests/webtbs/tw2072.pp svneol=native#text/plain
 tests/webtbs/tw20744.pp svneol=native#text/plain
 tests/webtbs/tw20744.pp svneol=native#text/plain
+tests/webtbs/tw20836.pp svneol=native#text/pascal
 tests/webtbs/tw2109.pp svneol=native#text/plain
 tests/webtbs/tw2109.pp svneol=native#text/plain
 tests/webtbs/tw2110.pp svneol=native#text/plain
 tests/webtbs/tw2110.pp svneol=native#text/plain
 tests/webtbs/tw2128.pp svneol=native#text/plain
 tests/webtbs/tw2128.pp svneol=native#text/plain

+ 26 - 2
compiler/pdecl.pas

@@ -363,6 +363,8 @@ implementation
          p:tnode;
          p:tnode;
          gendef : tstoreddef;
          gendef : tstoreddef;
          s : shortstring;
          s : shortstring;
+         pd: tprocdef;
+         hashedid : thashedidstring;
       begin
       begin
          old_block_type:=block_type;
          old_block_type:=block_type;
          { save unit container of forward declarations -
          { save unit container of forward declarations -
@@ -535,9 +537,31 @@ implementation
                       if not assigned(current_structdef.genericdef) or
                       if not assigned(current_structdef.genericdef) or
                           not (current_structdef.genericdef.typ in [recorddef,objectdef]) then
                           not (current_structdef.genericdef.typ in [recorddef,objectdef]) then
                         internalerror(2011052301);
                         internalerror(2011052301);
-                      sym:=tsym(tabstractrecorddef(current_structdef.genericdef).symtable.Find(gentypename));
+                      hashedid.id:=gentypename;
+                      { we could be inside a method of the specialization
+                        instead of its declaration, so check that first (as
+                        local nested types aren't allowed we don't need to
+                        walk the symtablestack to find the localsymtable) }
+                      if symtablestack.top.symtabletype=localsymtable then
+                        begin
+                          { we are in a method }
+                          if not assigned(symtablestack.top.defowner) or
+                              (symtablestack.top.defowner.typ<>procdef) then
+                            internalerror(2011120701);
+                          pd:=tprocdef(symtablestack.top.defowner);
+                          if not assigned(pd.genericdef) or (pd.genericdef.typ<>procdef) then
+                            internalerror(2011120702);
+                          sym:=tsym(tprocdef(pd.genericdef).localst.findwithhash(hashedid));
+                        end
+                      else
+                        sym:=nil;
                       if not assigned(sym) or not (sym.typ=typesym) then
                       if not assigned(sym) or not (sym.typ=typesym) then
-                        internalerror(2011052302);
+                        begin
+                          { now search in the declaration of the generic }
+                          sym:=tsym(tabstractrecorddef(current_structdef.genericdef).symtable.findwithhash(hashedid));
+                          if not assigned(sym) or not (sym.typ=typesym) then
+                            internalerror(2011052302);
+                        end;
                       { use the corresponding type in the generic's symtable as
                       { use the corresponding type in the generic's symtable as
                         genericdef for the specialized type }
                         genericdef for the specialized type }
                       gendef:=tstoreddef(ttypesym(sym).typedef);
                       gendef:=tstoreddef(ttypesym(sym).typedef);

+ 29 - 0
tests/webtbs/tw20836.pp

@@ -0,0 +1,29 @@
+program tw20836;
+
+{$mode objfpc}{$H+}
+
+uses
+  {$IFDEF UNIX}{$IFDEF UseCThreads}
+  cthreads,
+  {$ENDIF}{$ENDIF}
+  Classes
+  { you can add units after this };
+
+{.$R *.res}
+type
+  generic TGObjectChangeCommand<_T>=object
+                                        private
+                                        DoData,UnDoData:_T;
+                                        method:tmethod;
+                                        public
+                                        procedure UnDo;virtual;
+                                    end;
+  TCommand=specialize TGObjectChangeCommand<Integer>;
+procedure TGObjectChangeCommand.UnDo;
+type
+    TCangeMethod=procedure(const data:_T)of object;
+begin
+     TCangeMethod(method)(UnDoData);
+end;
+begin
+end.