* don't insert anonymous functions into a withsymtable

+ added test
This commit is contained in:
Sven/Sarah Barth 2023-06-23 17:02:15 +02:00 committed by Pierre Muller
parent 2eac11a8ab
commit d40437901e
2 changed files with 52 additions and 12 deletions

View File

@ -545,6 +545,7 @@ implementation
found, found,
searchagain : boolean; searchagain : boolean;
st, st,
insertst,
genericst: TSymtable; genericst: TSymtable;
aprocsym : tprocsym; aprocsym : tprocsym;
popclass : integer; popclass : integer;
@ -854,19 +855,23 @@ implementation
hadspecialize:=false; hadspecialize:=false;
addgendummy:=false; addgendummy:=false;
{ ensure that we don't insert into a withsymtable (can happen with
anonymous functions) }
checkstack:=symtablestack.stack;
while checkstack^.symtable.symtabletype in [withsymtable] do
checkstack:=checkstack^.next;
insertst:=checkstack^.symtable;
if not assigned(genericdef) then if not assigned(genericdef) then
begin begin
if ppf_anonymous in flags then if ppf_anonymous in flags then
begin begin
checkstack:=symtablestack.stack; if not (insertst.symtabletype in [localsymtable,staticsymtable]) then
while checkstack^.symtable.symtabletype in [withsymtable] do
checkstack:=checkstack^.next;
if not (checkstack^.symtable.symtabletype in [localsymtable,staticsymtable]) then
internalerror(2021050101); internalerror(2021050101);
{ generate a unique name for the anonymous function; don't use { generate a unique name for the anonymous function; don't use
something like file position however as this might be inside something like file position however as this might be inside
an include file that's included multiple times } an include file that's included multiple times }
str(checkstack^.symtable.symlist.count,orgsp); str(insertst.symlist.count,orgsp);
orgsp:='__FPCINTERNAL__Anonymous_'+orgsp; orgsp:='__FPCINTERNAL__Anonymous_'+orgsp;
sp:=upper(orgsp); sp:=upper(orgsp);
spnongen:=sp; spnongen:=sp;
@ -1032,7 +1037,7 @@ implementation
if (potype=potype_operator)and(optoken=NOTOKEN) then if (potype=potype_operator)and(optoken=NOTOKEN) then
parse_operator_name; parse_operator_name;
srsym:=tsym(symtablestack.top.Find(sp)); srsym:=tsym(insertst.Find(sp));
{ Also look in the globalsymtable if we didn't found { Also look in the globalsymtable if we didn't found
the symbol in the localsymtable } the symbol in the localsymtable }
@ -1102,7 +1107,7 @@ implementation
operation } operation }
if (potype=potype_operator) then if (potype=potype_operator) then
begin begin
aprocsym:=Tprocsym(symtablestack.top.Find(sp)); aprocsym:=Tprocsym(insertst.Find(sp));
if aprocsym=nil then if aprocsym=nil then
aprocsym:=cprocsym.create('$'+sp); aprocsym:=cprocsym.create('$'+sp);
end end
@ -1115,7 +1120,7 @@ implementation
include(aprocsym.symoptions,sp_internal); include(aprocsym.symoptions,sp_internal);
if addgendummy then if addgendummy then
include(aprocsym.symoptions,sp_generic_dummy); include(aprocsym.symoptions,sp_generic_dummy);
symtablestack.top.insertsym(aprocsym); insertst.insertsym(aprocsym);
end; end;
end; end;
@ -1176,7 +1181,7 @@ implementation
dummysym:=tsym(astruct.symtable.find(spnongen)) dummysym:=tsym(astruct.symtable.find(spnongen))
else else
begin begin
dummysym:=tsym(symtablestack.top.find(spnongen)); dummysym:=tsym(insertst.find(spnongen));
if not assigned(dummysym) and if not assigned(dummysym) and
(symtablestack.top=current_module.localsymtable) and (symtablestack.top=current_module.localsymtable) and
assigned(current_module.globalsymtable) then assigned(current_module.globalsymtable) then
@ -1190,7 +1195,7 @@ implementation
if assigned(astruct) then if assigned(astruct) then
astruct.symtable.insertsym(dummysym) astruct.symtable.insertsym(dummysym)
else else
symtablestack.top.insertsym(dummysym); insertst.insertsym(dummysym);
end end
else if (dummysym.typ<>procsym) and else if (dummysym.typ<>procsym) and
( (
@ -1282,8 +1287,8 @@ implementation
{ symbol options that need to be kept per procdef } { symbol options that need to be kept per procdef }
pd.fileinfo:=procstartfilepos; pd.fileinfo:=procstartfilepos;
pd.visibility:=symtablestack.top.currentvisibility; pd.visibility:=insertst.currentvisibility;
if symtablestack.top.currentlyoptional then if insertst.currentlyoptional then
include(pd.procoptions,po_optional); include(pd.procoptions,po_optional);
{ parse parameters } { parse parameters }

35
tests/test/tanonfunc73.pp Normal file
View File

@ -0,0 +1,35 @@
{ %NORUN }
program tanonfunc73;
{$mode objfpc}
{$modeswitch anonymousfunctions}
{$modeswitch functionreferences}
type
TProc = reference to procedure;
procedure Test;
var
o: TObject;
p: TProc;
begin
with o do begin
p := procedure
begin
Writeln('Hello World');
end;
end;
end;
var
o: TObject;
p: TProc;
begin
with o do begin
p := procedure
begin
Writeln('Hello World');
end;
end;
end.