mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-10-23 18:35:47 +02:00
* enabled maybe_call_procvar() also for macpas mode (calls procvars that
don't have any parameters in most expressions, rather than using them as the procvar itself) -> replaced procvar<>nil with assigned(procvar) in test/tmacprocvar.pp to keep it compiling (otherwise it now called the procvar); necessary in combination with the next fix to compile webtbs/tw17379a.pp * automatically disambiguate the use of the function name when used as a parameter in macpas mode (if the formal parameter type is a procvar type then interpret it as the current function definition, otherwise as the current function result) (mantis #17379) git-svn-id: trunk@15971 -
This commit is contained in:
parent
df295ca8d6
commit
c43fda1fe1
2
.gitattributes
vendored
2
.gitattributes
vendored
@ -10649,6 +10649,8 @@ tests/webtbs/tw17337.pp svneol=native#text/plain
|
||||
tests/webtbs/tw17342.pp svneol=native#text/plain
|
||||
tests/webtbs/tw1735.pp svneol=native#text/plain
|
||||
tests/webtbs/tw1737.pp svneol=native#text/plain
|
||||
tests/webtbs/tw17379.pp svneol=native#text/plain
|
||||
tests/webtbs/tw17379a.pp svneol=native#text/plain
|
||||
tests/webtbs/tw1744.pp svneol=native#text/plain
|
||||
tests/webtbs/tw1754c.pp svneol=native#text/plain
|
||||
tests/webtbs/tw1755.pp svneol=native#text/plain
|
||||
|
@ -139,6 +139,11 @@ interface
|
||||
|
||||
{ procvar handling }
|
||||
function is_proc2procvar_load(p:tnode;out realprocdef:tprocdef):boolean;
|
||||
{ returns whether a node represents a load of the function result node via
|
||||
the function name (so it could also be a recursive call to the function
|
||||
in case there or no parameters, or the function could be passed as
|
||||
procvar }
|
||||
function is_ambiguous_funcret_load(p: tnode; out owningprocdef: tprocdef): boolean;
|
||||
procedure test_local_to_procvar(from_def:tprocvardef;to_def:tdef);
|
||||
|
||||
{ sets varsym varstate field correctly }
|
||||
@ -797,6 +802,25 @@ implementation
|
||||
end;
|
||||
|
||||
|
||||
function is_ambiguous_funcret_load(p: tnode; out owningprocdef: tprocdef): boolean;
|
||||
begin
|
||||
result:=false;
|
||||
{ the funcret is an absolutevarsym, which gets converted into a type
|
||||
conversion node of the loadnode of the actual function result. Its
|
||||
resulttype is obviously the same as that of the real function result }
|
||||
if (p.nodetype=typeconvn) and
|
||||
(p.resultdef=ttypeconvnode(p).left.resultdef) then
|
||||
p:=ttypeconvnode(p).left;
|
||||
if (p.nodetype=loadn) and
|
||||
(tloadnode(p).symtableentry.typ in [absolutevarsym,localvarsym,paravarsym]) and
|
||||
([vo_is_funcret,vo_is_result] * tabstractvarsym(tloadnode(p).symtableentry).varoptions = [vo_is_funcret]) then
|
||||
begin
|
||||
owningprocdef:=tprocdef(tloadnode(p).symtableentry.owner.defowner);
|
||||
result:=true;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
{ local routines can't be assigned to procvars }
|
||||
procedure test_local_to_procvar(from_def:tprocvardef;to_def:tdef);
|
||||
begin
|
||||
@ -1607,6 +1631,10 @@ implementation
|
||||
(m_nested_procvars in current_settings.modeswitches) and
|
||||
is_proc2procvar_load(p.left,realprocdef) then
|
||||
tmpeq:=proc_to_procvar_equal(realprocdef,tprocvardef(def_to),false);
|
||||
if (tmpeq=te_incompatible) and
|
||||
(m_mac in current_settings.modeswitches) and
|
||||
is_ambiguous_funcret_load(p.left,realprocdef) then
|
||||
tmpeq:=proc_to_procvar_equal(realprocdef,tprocvardef(def_to),false);
|
||||
if tmpeq<>te_incompatible then
|
||||
eq:=tmpeq;
|
||||
end;
|
||||
|
@ -650,6 +650,7 @@ implementation
|
||||
block : tblocknode;
|
||||
statements : tstatementnode;
|
||||
temp : ttempcreatenode;
|
||||
owningprocdef: tprocdef;
|
||||
begin
|
||||
{ Be sure to have the resultdef }
|
||||
if not assigned(left.resultdef) then
|
||||
@ -657,6 +658,22 @@ implementation
|
||||
|
||||
if (left.nodetype<>nothingn) then
|
||||
begin
|
||||
{ convert loads of the function result variable into procvars
|
||||
representing the current function in case the formal parameter is
|
||||
a procvar (CodeWarrior Pascal contains the same kind of
|
||||
automatic disambiguation; you can use the function name in both
|
||||
meanings, so we cannot statically pick either the function result
|
||||
or the function definition in pexpr) }
|
||||
if (m_mac in current_settings.modeswitches) and
|
||||
(parasym.vardef.typ=procvardef) and
|
||||
is_ambiguous_funcret_load(left,owningprocdef) then
|
||||
begin
|
||||
hp:=cloadnode.create_procvar(owningprocdef.procsym,owningprocdef,owningprocdef.procsym.owner);
|
||||
typecheckpass(hp);
|
||||
left.free;
|
||||
left:=hp;
|
||||
end;
|
||||
|
||||
{ Convert tp procvars, this is needs to be done
|
||||
here to make the change permanent. in the overload
|
||||
choosing the changes are only made temporarily }
|
||||
@ -664,7 +681,7 @@ implementation
|
||||
not(parasym.vardef.typ in [procvardef,formaldef]) then
|
||||
begin
|
||||
if maybe_call_procvar(left,true) then
|
||||
resultdef:=left.resultdef;
|
||||
resultdef:=left.resultdef
|
||||
end;
|
||||
|
||||
{ Remove implicitly inserted typecast to pointer for
|
||||
|
@ -357,7 +357,7 @@ implementation
|
||||
result:=false;
|
||||
if (p1.resultdef.typ<>procvardef) or
|
||||
(tponly and
|
||||
not(m_tp_procvar in current_settings.modeswitches)) then
|
||||
([m_tp_procvar,m_mac_procvar] * current_settings.modeswitches = [])) then
|
||||
exit;
|
||||
{ ignore vecn,subscriptn }
|
||||
hp:=p1;
|
||||
@ -517,7 +517,6 @@ implementation
|
||||
end;
|
||||
|
||||
|
||||
|
||||
function call_fail_node:tnode;
|
||||
var
|
||||
para : tcallparanode;
|
||||
|
@ -48,7 +48,7 @@ begin
|
||||
B(@A);
|
||||
n := nil;
|
||||
n := A;
|
||||
if nil <> n then
|
||||
if assigned(n) then
|
||||
C(n);
|
||||
C(A);
|
||||
C(@A);
|
||||
|
22
tests/webtbs/tw17379.pp
Normal file
22
tests/webtbs/tw17379.pp
Normal file
@ -0,0 +1,22 @@
|
||||
{ %norun }
|
||||
|
||||
{$mode macpas}
|
||||
{$warnings off}
|
||||
program recursivefunctionparam;
|
||||
|
||||
function first( function test( theint: integer): boolean): integer;
|
||||
begin {not implemented} end;
|
||||
|
||||
function find: integer;
|
||||
|
||||
function test( theint: integer): boolean;
|
||||
begin
|
||||
first( test)
|
||||
end;
|
||||
|
||||
begin
|
||||
{not implemented}
|
||||
end;
|
||||
|
||||
begin
|
||||
end.
|
35
tests/webtbs/tw17379a.pp
Normal file
35
tests/webtbs/tw17379a.pp
Normal file
@ -0,0 +1,35 @@
|
||||
{$mode macpas}
|
||||
|
||||
program tmacfunret;
|
||||
|
||||
var
|
||||
called:boolean;
|
||||
|
||||
function B(function x: integer): integer;
|
||||
|
||||
begin
|
||||
b:=x;
|
||||
end;
|
||||
|
||||
function A: Integer;
|
||||
|
||||
begin
|
||||
if not called then
|
||||
begin
|
||||
called:=true;
|
||||
A:=B(A);
|
||||
end
|
||||
else
|
||||
A:=42;
|
||||
end;
|
||||
|
||||
var
|
||||
i: Integer;
|
||||
|
||||
begin
|
||||
called:=false;
|
||||
i:= A;
|
||||
Writeln(i);
|
||||
if i <> 42 then
|
||||
halt(1);
|
||||
end.
|
Loading…
Reference in New Issue
Block a user