mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-09-15 12:09:18 +02:00
* don't insert anonymous functions into a withsymtable
+ added test
This commit is contained in:
parent
2eac11a8ab
commit
d40437901e
@ -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
35
tests/test/tanonfunc73.pp
Normal 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.
|
Loading…
Reference in New Issue
Block a user