pgenutil.pas, generate_specialization:

- Remove unneeded check for "parse_generic" (it's already checked in the outer if-clause).
+ Check whether we are trying to specialize one of the surrounding type declarations of a
  nested type (as long as nested generics are forbidden this is always the outermost generic
  or specialization). This check can not rely on the symbol, because while parsing the
  generic or the specialization the symbol's def is still an errordef. This fixes 
  Mantis #19498 .

+ Added test from bug report.

git-svn-id: trunk@20247 -
This commit is contained in:
svenbarth 2012-02-04 14:20:26 +00:00
parent a7a0ba0cf4
commit 04683c5f13
3 changed files with 81 additions and 14 deletions

1
.gitattributes vendored
View File

@ -12106,6 +12106,7 @@ tests/webtbs/tw1936.pp svneol=native#text/plain
tests/webtbs/tw19368.pp svneol=native#text/pascal
tests/webtbs/tw1938.pp svneol=native#text/plain
tests/webtbs/tw1948.pp svneol=native#text/plain
tests/webtbs/tw19498.pp svneol=native#text/pascal
tests/webtbs/tw1950.pp svneol=native#text/plain
tests/webtbs/tw19500.pp svneol=native#text/pascal
tests/webtbs/tw19548.pp svneol=native#text/pascal

View File

@ -74,7 +74,7 @@ uses
err : boolean;
i,
gencount,crc : longint;
genericdef : tstoreddef;
genericdef,def : tstoreddef;
generictype : ttypesym;
genericdeflist : TFPObjectList;
generictypelist : TFPObjectList;
@ -118,7 +118,7 @@ uses
consume(_RSHARPBRACKET);
{ we need to return a def that can later pass some checks like
whether it's an interface or not }
if parse_generic and (not assigned(tt) or (tt.typ=undefineddef)) then
if not assigned(tt) or (tt.typ=undefineddef) then
begin
if (symname='') and (df_generic in genericdef.defoptions) then
{ this happens in non-Delphi modes }
@ -134,19 +134,39 @@ uses
genname:=symname;
genname:=genname+'$'+countstr;
ugenname:=upper(genname);
if not searchsym(ugenname,srsym,st) or
(srsym.typ<>typesym) then
{ first check whether the found name is the same as that of
the current def or one of its (generic) surrounding defs;
this is necessary as the symbol of the generic can not yet
be used for lookup as it still contains a reference to an
errordef) }
def:=current_genericdef;
repeat
if def.typ in [objectdef,recorddef] then
if tabstractrecorddef(def).objname^=ugenname then
begin
tt:=def;
break;
end;
def:=tstoreddef(def.owner.defowner);
until not assigned(def) or not (df_generic in def.defoptions);
{ it's not part of the current object hierarchy, so search
for the symbol }
if not assigned(tt) then
begin
identifier_not_found(genname);
exit;
end;
tt:=ttypesym(srsym).typedef;
{ this happens in non-Delphi modes if we encounter a
specialization of the generic class or record we're
currently parsing }
if (tt.typ=errordef) and assigned(current_structdef) and
(current_structdef.objname^=ugenname) then
tt:=current_structdef;
if not searchsym(ugenname,srsym,st) or
(srsym.typ<>typesym) then
begin
identifier_not_found(genname);
exit;
end;
tt:=ttypesym(srsym).typedef;
{ this happens in non-Delphi modes if we encounter a
specialization of the generic class or record we're
currently parsing }
if (tt.typ=errordef) and assigned(current_structdef) and
(current_structdef.objname^=ugenname) then
tt:=current_structdef;
end;
end;
end;
exit;
@ -312,6 +332,25 @@ uses
specializest:=current_module.localsymtable;
{ Can we reuse an already specialized type? }
{ for this first check whether we are currently specializing a nested
type of the current (main) specialization (this is necessary, because
during that time the symbol of the main specialization will still
contain a reference to an errordef) }
if not assigned(tt) and assigned(current_specializedef) then
begin
def:=current_specializedef;
repeat
if def.typ in [objectdef,recorddef] then
if tabstractrecorddef(def).objname^=ufinalspecializename then begin
tt:=def;
break;
end;
def:=tstoreddef(def.owner.defowner);
until not assigned(def) or not (df_specialization in def.defoptions);
end;
{ now check whether there is a specialization somewhere else }
if not assigned(tt) then
begin
hashedid.id:=ufinalspecializename;

27
tests/webtbs/tw19498.pp Normal file
View File

@ -0,0 +1,27 @@
{ %NORUN }
{$MODE OBJFPC} { -*- text -*- }
program tw19498;
type
generic TFoo1 <T> = class
type
TFoo2 = class
constructor Create(Owner: specialize TFoo1<T>);
end;
end;
constructor TFoo1.TFoo2.Create(Owner: specialize TFoo1<T>);
begin
end;
type
TIntegerFoo1 = specialize TFoo1<Integer>;
var
Foo1: TIntegerFoo1;
Foo2: TIntegerFoo1.TFoo2;
begin
end.