Fix for Mantis #24687.

pgenutil.pas:
  + add new function could_be_generic which checks whether a given symbol name could be a generic (which is determined using the genericdummysyms list for the current module)
pexpr.pas:
  * factor: only do a typecheck pass (postfixoperators does one as well) if the found node can not be a generic type
  * sub_expr: do a typecheck pass if it isn't a specialization

+ added test

git-svn-id: trunk@25579 -
This commit is contained in:
svenbarth 2013-09-26 10:21:11 +00:00
parent fb8b0e7a27
commit e8edbd29c0
4 changed files with 57 additions and 6 deletions

1
.gitattributes vendored
View File

@ -13585,6 +13585,7 @@ tests/webtbs/tw2483.pp svneol=native#text/plain
tests/webtbs/tw24848.pp svneol=native#text/pascal
tests/webtbs/tw24863.pp svneol=native#text/plain
tests/webtbs/tw24865.pp svneol=native#text/pascal
tests/webtbs/tw24867.pp svneol=native#text/pascal
tests/webtbs/tw24871.pp svneol=native#text/pascal
tests/webtbs/tw2492.pp svneol=native#text/plain
tests/webtbs/tw2494.pp svneol=native#text/plain

View File

@ -2825,12 +2825,15 @@ implementation
hdef : tdef;
filepos : tfileposinfo;
callflags : tcallnodeflags;
idstr : tidstring;
dopostfix,
again,
updatefpos,
nodechanged : boolean;
begin
{ can't keep a copy of p1 and compare pointers afterwards, because
p1 may be freed and reallocated in the same place! }
dopostfix:=true;
updatefpos:=false;
p1:=nil;
filepos:=current_tokenpos;
@ -2857,7 +2860,27 @@ implementation
filepos:=current_tokenpos;
end;
{ handle post fix operators }
updatefpos:=postfixoperators(p1,again,getaddr);
if (m_delphi in current_settings.modeswitches) and
(block_type=bt_body) and
(token in [_LT,_LSHARPBRACKET]) then
begin
if p1.nodetype=typen then
idstr:=ttypenode(p1).typesym.name
else
if (p1.nodetype=loadvmtaddrn) and
(tloadvmtaddrnode(p1).left.nodetype=typen) then
idstr:=ttypenode(tloadvmtaddrnode(p1).left).typesym.name
else
if (p1.nodetype=loadn) then
idstr:=tloadnode(p1).symtableentry.name
else
idstr:='';
{ if this is the case then the postfix handling is done in
sub_expr if necessary }
dopostfix:=not could_be_generic(idstr);
end;
if dopostfix then
updatefpos:=postfixoperators(p1,again,getaddr);
end
else
begin
@ -3327,8 +3350,8 @@ implementation
updatefpos:=true;
end;
{ get the resultdef for the node }
if (not assigned(p1.resultdef)) then
{ get the resultdef for the node if nothing stops us }
if (not assigned(p1.resultdef)) and dopostfix then
begin
do_typecheckpass_changed(p1,nodechanged);
updatefpos:=updatefpos or nodechanged;
@ -3516,9 +3539,13 @@ implementation
begin
{ this is a normal "<" comparison }
{ potential generic types that are followed by a "<" }
{ potential generic types that are followed by a "<": }
{ a) are not checked whether they are an undefined def,
{ a) might not have their resultdef set }
if not assigned(p1.resultdef) then
do_typecheckpass(p1);
{ b) are not checked whether they are an undefined def,
but not a generic parameter }
if (p1.nodetype=typen) and
(ttypenode(p1).typedef.typ=undefineddef) and
@ -3530,7 +3557,7 @@ implementation
p1:=cerrornode.create;
end;
{ b) don't have their hints checked }
{ c) don't have their hints checked }
if istypenode(p1) then
begin
gendef:=gettypedef(p1);

View File

@ -43,6 +43,7 @@ uses
function generate_generic_name(const name:tidstring;specializename:ansistring):tidstring;
procedure split_generic_name(const name:tidstring;out nongeneric:string;out count:longint);
function resolve_generic_dummysym(const name:tidstring):tsym;
function could_be_generic(const name:tidstring):boolean;inline;
type
tspecializationstate = record
@ -1137,6 +1138,12 @@ uses
end;
function could_be_generic(const name:tidstring):boolean;
begin
result:=(name<>'') and
(current_module.genericdummysyms.findindexof(name)>=0);
end;
procedure specialization_init(genericdef:tdef;var state: tspecializationstate);
var
pu : tused_unit;

16
tests/webtbs/tw24867.pp Normal file
View File

@ -0,0 +1,16 @@
{ %NORUN }
program tw24867;
{$MODE DELPHi}{$H+}
{$APPTYPE CONSOLE}
uses
fgl;
var
d: TFPGMap<string, string>; // ok
begin
d := TFPGMap<string, string>.Create; // Error: This type can't be a generic
end.