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 -
This commit is contained in:
svenbarth 2011-12-08 08:59:33 +00:00
parent 5824a0272b
commit a1ef0add65
3 changed files with 56 additions and 2 deletions

1
.gitattributes vendored
View File

@ -11942,6 +11942,7 @@ tests/webtbs/tw2069.pp svneol=native#text/plain
tests/webtbs/tw20690.pp svneol=native#text/pascal
tests/webtbs/tw2072.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/tw2110.pp svneol=native#text/plain
tests/webtbs/tw2128.pp svneol=native#text/plain

View File

@ -363,6 +363,8 @@ implementation
p:tnode;
gendef : tstoreddef;
s : shortstring;
pd: tprocdef;
hashedid : thashedidstring;
begin
old_block_type:=block_type;
{ save unit container of forward declarations -
@ -535,9 +537,31 @@ implementation
if not assigned(current_structdef.genericdef) or
not (current_structdef.genericdef.typ in [recorddef,objectdef]) then
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
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
genericdef for the specialized type }
gendef:=tstoreddef(ttypesym(sym).typedef);

29
tests/webtbs/tw20836.pp Normal file
View File

@ -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.