Fix introduced regressions.

pgenutil.pas, generate_specialization:
* If we are parsing the result type of a function or operator that belongs to a generic (parse_generic is true) we need to accept also "_LT" and "_GT" as for this the "block_type" is NOT set to one of "bt_type", "bt_var_type", "bt_const_type" and only there "_LSHARPBRACKET" and "_RSHARPBRACKET" are returned by the scanner. This is part of the fix for webtbs\tw18567.pp.
* In non—Delphi modes if we encounter a specialization of the currently parsed class/record (using "specialization"!) the given "tt" will be an errordef (because the def of the generic's symbol was not yet set to "current_structdef"). To solve this we check in this case whether the calculated generic name is equal to that of the "current_structdef" and simply return that as specialized def. This fixes test\tgeneric11.pp.
* When searching for the generic symbol search if the generic belongs to a class or record then we need to search for it in the class or record. This fixes webtbs\tw16090.pp.

ptype.pas
* parse_nested_types: We now return the generic defs for specializations inside generics instead of an undefined def, so we must also parse nested type usages correctly, so that type checks don't fail (undefined defs circumvent them mostly). This fixes webtbs\tw10247.pp.
* single_type: We need to allow _LT as an indication for a Delphi specialization as return types are parsed with block_type not in "bt_type", "bt_var_type", "bt_const_type". This is also a fix a part of the fix for webtbs\tw18567.pp.
* read_named_type, expr_type:
Fixes for test\tgeneric17.pp and test\tgeneric22.pp:
(a) In non-Delphi modes we might encounter usages of the generic dummy symbol inside the generic class belonging to it. This is basically a specialization, but as the reference from the dummy symbol to the "current_structdef" is not yet established (this is done after "read_named_type" in "types_dec" returns) we need to use other ways to check for the valid use of the dummy symbol (basically we check whether the name of the dummy symbol and the name of the current_structdef without the type count match)
(b) For specializations we can check whether the genericdef of the currently parsed structdef (the specialization) is the same as the typedef of the encountered dummy symbol.

pexpr.pas, factor, factor_read_id:
Fixes for test\tgeneric17.pp and test\tgeneric22.pp:
To allow the mentioned fixes in ptype for the same tests to be usable at all we must not return an "identifier not found" error if we encounter such a valid use of a generic dummy symbol.

git-svn-id: branches/svenbarth/generics@19719 -
This commit is contained in:
svenbarth 2011-12-02 14:10:06 +00:00
parent d55684937f
commit 6a83ebc4a5
3 changed files with 62 additions and 13 deletions

View File

@ -2150,7 +2150,17 @@ implementation
assigned(ttypesym(srsym).typedef) and
(ttypesym(srsym).typedef.typ=undefineddef) and
not (sp_generic_para in srsym.symoptions) and
not (token in [_LT, _LSHARPBRACKET])) then
not (token in [_LT, _LSHARPBRACKET]) and
not (
{ in non-Delphi modes the generic class' name without a
"specialization" or "<T>" may be used to identify the
current class }
(sp_generic_dummy in srsym.symoptions) and
assigned(current_structdef) and
(df_generic in current_structdef.defoptions) and
not (m_delphi in current_settings.modeswitches) and
(upper(srsym.realname)=copy(current_structdef.objname^,1,pos('$',current_structdef.objname^)-1))
)) then
begin
identifier_not_found(orgstoredpattern);
srsym:=generrorsym;

View File

@ -60,6 +60,7 @@ uses
st : TSymtable;
srsym : tsym;
pt2 : tnode;
found,
first,
err : boolean;
i,
@ -98,14 +99,16 @@ uses
for recording in genericbuf }
if parse_generic then
begin
consume(_LSHARPBRACKET);
if not try_to_consume(_LT) then
consume(_LSHARPBRACKET);
gencount:=0;
repeat
pt2:=factor(false,true);
pt2.free;
inc(gencount);
until not try_to_consume(_COMMA);
consume(_RSHARPBRACKET);
if not try_to_consume(_GT) then
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
@ -131,6 +134,12 @@ uses
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;
exit;
@ -226,8 +235,17 @@ uses
genname:=genname+'$'+countstr;
ugenname:=upper(genname);
if not searchsym(ugenname,srsym,st)
or (srsym.typ<>typesym) then
if assigned(genericdef) and (genericdef.owner.symtabletype in [objectsymtable,recordsymtable]) then
begin
if genericdef.owner.symtabletype = objectsymtable then
found:=searchsym_in_class(tobjectdef(genericdef.owner.defowner),tobjectdef(genericdef.owner.defowner),ugenname,srsym,st,false)
else
found:=searchsym_in_record(tabstractrecorddef(genericdef.owner.defowner),ugenname,srsym,st);
end
else
found:=searchsym(ugenname,srsym,st);
if not found or (srsym.typ<>typesym) then
begin
identifier_not_found(genname);
genericdeflist.Free;

View File

@ -168,12 +168,7 @@ implementation
{ handle types inside classes, e.g. TNode.TLongint }
while (token=_POINT) do
begin
if parse_generic then
begin
consume(_POINT);
consume(_ID);
end
else if is_class_or_object(def) or is_record(def) then
if is_class_or_object(def) or is_record(def) then
begin
consume(_POINT);
if (structstackindex>=0) and
@ -373,7 +368,7 @@ implementation
until not again;
if ([stoAllowSpecialization,stoAllowTypeDef] * options <> []) and
(m_delphi in current_settings.modeswitches) then
dospecialize:=token=_LSHARPBRACKET;
dospecialize:=token in [_LSHARPBRACKET,_LT];
if dospecialize then
generate_specialization(def,stoParseClassParent in options,'',nil,'')
else
@ -848,7 +843,33 @@ implementation
def:=ttypenode(pt1).resultdef;
{ Delphi mode specialization? }
if (m_delphi in current_settings.modeswitches) then
dospecialize:=token=_LSHARPBRACKET;
dospecialize:=token=_LSHARPBRACKET
else
{ in non-Delphi modes we might get a inline specialization
without "specialize" or "<T>", so we need to handle that
special }
if not dospecialize and
assigned(ttypenode(pt1).typesym) and
(ttypenode(pt1).typesym.typ=typesym) and
(sp_generic_dummy in ttypenode(pt1).typesym.symoptions) and
assigned(current_structdef) and
(
(
not (m_delphi in current_settings.modeswitches) and
(ttypesym(ttypenode(pt1).typesym).typedef.typ=undefineddef) and
(df_generic in current_structdef.defoptions) and
(upper(ttypenode(pt1).typesym.realname)=copy(current_structdef.objname^,1,pos('$',current_structdef.objname^)-1))
) or (
(df_specialization in current_structdef.defoptions) and
(ttypesym(ttypenode(pt1).typesym).typedef=current_structdef.genericdef)
)
)
then
begin
def:=current_structdef;
{ handle nested types }
post_comp_expr_gendef(def);
end;
if dospecialize then
begin
generate_specialization(def,false,name,nil,'');