mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-09-06 12:31:23 +02:00
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:
parent
d55684937f
commit
6a83ebc4a5
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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,'');
|
||||
|
Loading…
Reference in New Issue
Block a user