Corrected the handling of hint directives.

pgenutils.pas/generate_specialization:
- parse hint directives of the generic if they are recorded
- output hint messages of the generic after the ">" is successfully parsed

pexpr.pas:
- factor: don't display hints of a potential generic type if the next token is a "<"
- sub_expr:
 * added two inline methods which
    a) checks whether a node is a typenode or a loadvmtaddrnode with a typenode
    b) returns the typedef of such a node
 * check hint directives for the first parsed type argument of a specialization
 * in the case of parsing a non-generic type the hints of the left and right node of the resulting "<" node need to be checked (the right ones only if another "<" is following)

git-svn-id: branches/svenbarth/generics@17539 -
This commit is contained in:
svenbarth 2011-05-23 19:16:39 +00:00
parent c17a8d36ae
commit 6c96270eb6
2 changed files with 77 additions and 38 deletions

View File

@ -1913,14 +1913,12 @@ implementation
exit;
end;
{ check hints if it is the final symbol that is used (e.g. in
case of generics only the dummy symbol or the non-generic one
is found here }
{ TODO : correct this check }
{ check hints, but only if it isn't a potential generic symbol;
that is checked in sub_expr if it isn't a generic }
if assigned(srsym) and
not (
typeonly and (srsym.typ=typesym) and
(ttypesym(srsym).typedef.typ=undefineddef) and
(srsym.typ=typesym) and
(ttypesym(srsym).typedef.typ in [recorddef,objectdef,arraydef,procvardef,undefineddef]) and
not (sp_generic_para in srsym.symoptions) and
(token in [_LT, _LSHARPBRACKET])
) then
@ -2838,6 +2836,32 @@ implementation
{Reads a subexpression while the operators are of the current precedence
level, or any higher level. Replaces the old term, simpl_expr and
simpl2_expr.}
function istypenode(n:tnode):boolean;inline;
{ Checks whether the given node is a type node or a VMT node containing a
typenode. This is used in the code for inline specializations in the
_LT branch below }
begin
result:=assigned(n) and
(
(n.nodetype=typen) or
(
(n.nodetype=loadvmtaddrn) and
(tloadvmtaddrnode(n).left.nodetype=typen)
)
);
end;
function gettypedef(n:tnode):tdef;inline;
{ This returns the typedef that belongs to the given typenode or
loadvmtaddrnode. n must not be Nil! }
begin
if n.nodetype=typen then
result:=ttypenode(n).typedef
else
result:=ttypenode(tloadvmtaddrnode(n).left).typedef;
end;
var
p1,p2 : tnode;
oldt : Ttoken;
@ -2878,57 +2902,57 @@ implementation
_LT :
begin
isgeneric:=false;
if (
{ the left node needs to be a type node }
(p1.nodetype=typen) or
(
(p1.nodetype=loadvmtaddrn) and
(tloadvmtaddrnode(p1).left.nodetype=typen)
)
) and
(
{ the right node needs to be a type node }
(p2.nodetype=typen) or
(
(p2.nodetype=loadvmtaddrn) and
(tloadvmtaddrnode(p2).left.nodetype=typen)
)
) and
if istypenode(p1) and istypenode(p2) and
(m_delphi in current_settings.modeswitches) and
(token in [_GT,_RSHARPBRACKET,_COMMA]) then
begin
{ this is an inline specialization }
{ retrive the def of the left node }
if p1.nodetype=typen then
gendef:=ttypenode(p1).typedef
else
gendef:=ttypenode(tloadvmtaddrnode(p1).left).typedef;
{ retrieve the right node }
if p2.nodetype=typen then
parseddef:=ttypenode(p2).typedef
else
parseddef:=ttypenode(tloadvmtaddrnode(p2).left).typedef;
{ retrieve the defs of two nodes }
gendef:=gettypedef(p1);
parseddef:=gettypedef(p2);
if gendef.typesym.typ<>typesym then
Internalerror(2011050301);
if parseddef.typesym.typ<>typesym then
Internalerror(2011051001);
{ check the hints for parseddef }
check_hints(parseddef.typesym,parseddef.typesym.symoptions,parseddef.typesym.deprecatedmsg);
{ generate the specialization }
generate_specialization(gendef,false,parseddef);
isgeneric:=gendef<>generrordef;
isgeneric:=true;
end;
if not isgeneric then
p1:=caddnode.create(ltn,p1,p2)
begin
{ for potential generic types that are followed by a "<"
the hints are not checked }
if istypenode(p1) then
begin
gendef:=gettypedef(p1);
if gendef.typ in [objectdef,recorddef,arraydef,procvardef] then
check_hints(gendef.typesym,gendef.typesym.symoptions,gendef.typesym.deprecatedmsg);
end;
if istypenode(p2) and
(token in [_LT, _LSHARPBRACKET]) then
begin
gendef:=gettypedef(p2);
if gendef.typ in [objectdef,recorddef,arraydef,procvardef] then
check_hints(gendef.typesym,gendef.typesym.symoptions,gendef.typesym.deprecatedmsg);
end;
{ create the comparison node for "<" }
p1:=caddnode.create(ltn,p1,p2)
end
else
begin
{ we don't need the old left and right nodes anymore }
p1.Free;
p2.Free;
{ in case of a class this is always a classrefdef }
{ in case of a class or a record the specialized generic
is always a classrefdef }
if is_class_or_interface_or_object(gendef) or
is_record(gendef) then
gendef:=tclassrefdef.create(gendef);

View File

@ -48,6 +48,7 @@ uses
{ modules }
fmodule,
{ pass 1 }
htypechk,
node,nobj,
{ parser }
scanner,
@ -332,9 +333,12 @@ uses
tt.typesym:=srsym;
case tt.typ of
{ Build VMT indexes for classes }
{ Build VMT indexes for classes and read hint directives }
objectdef:
begin
try_consume_hintdirective(srsym.symoptions,srsym.deprecatedmsg);
consume(_SEMICOLON);
vmtbuilder:=TVMTBuilder.Create(tobjectdef(tt));
vmtbuilder.generate_vmt;
vmtbuilder.free;
@ -352,6 +356,12 @@ uses
if try_consume_hintdirective(ttypesym(srsym).symoptions,ttypesym(srsym).deprecatedmsg) then
consume(_SEMICOLON);
end;
else
{ parse hint directives for records and arrays }
begin
try_consume_hintdirective(srsym.symoptions,srsym.deprecatedmsg);
consume(_SEMICOLON);
end;
end;
{ Consume the semicolon if it is also recorded }
try_to_consume(_SEMICOLON);
@ -384,7 +394,12 @@ uses
genericdeflist.free;
generictypelist.free;
if not try_to_consume(_GT) then
consume(_RSHARPBRACKET);
consume(_RSHARPBRACKET)
else
if assigned(srsym) then
{ check the hints of the found generic symbol (this way we are
behind the closing ">") }
check_hints(srsym,srsym.symoptions,srsym.deprecatedmsg);
end;