* 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:
Jonas Maebe 2010-09-12 16:03:00 +00:00
parent df295ca8d6
commit c43fda1fe1
7 changed files with 107 additions and 4 deletions

2
.gitattributes vendored
View File

@ -10649,6 +10649,8 @@ tests/webtbs/tw17337.pp svneol=native#text/plain
tests/webtbs/tw17342.pp svneol=native#text/plain tests/webtbs/tw17342.pp svneol=native#text/plain
tests/webtbs/tw1735.pp svneol=native#text/plain tests/webtbs/tw1735.pp svneol=native#text/plain
tests/webtbs/tw1737.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/tw1744.pp svneol=native#text/plain
tests/webtbs/tw1754c.pp svneol=native#text/plain tests/webtbs/tw1754c.pp svneol=native#text/plain
tests/webtbs/tw1755.pp svneol=native#text/plain tests/webtbs/tw1755.pp svneol=native#text/plain

View File

@ -139,6 +139,11 @@ interface
{ procvar handling } { procvar handling }
function is_proc2procvar_load(p:tnode;out realprocdef:tprocdef):boolean; 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); procedure test_local_to_procvar(from_def:tprocvardef;to_def:tdef);
{ sets varsym varstate field correctly } { sets varsym varstate field correctly }
@ -797,6 +802,25 @@ implementation
end; 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 } { local routines can't be assigned to procvars }
procedure test_local_to_procvar(from_def:tprocvardef;to_def:tdef); procedure test_local_to_procvar(from_def:tprocvardef;to_def:tdef);
begin begin
@ -1607,6 +1631,10 @@ implementation
(m_nested_procvars in current_settings.modeswitches) and (m_nested_procvars in current_settings.modeswitches) and
is_proc2procvar_load(p.left,realprocdef) then is_proc2procvar_load(p.left,realprocdef) then
tmpeq:=proc_to_procvar_equal(realprocdef,tprocvardef(def_to),false); 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 if tmpeq<>te_incompatible then
eq:=tmpeq; eq:=tmpeq;
end; end;

View File

@ -650,6 +650,7 @@ implementation
block : tblocknode; block : tblocknode;
statements : tstatementnode; statements : tstatementnode;
temp : ttempcreatenode; temp : ttempcreatenode;
owningprocdef: tprocdef;
begin begin
{ Be sure to have the resultdef } { Be sure to have the resultdef }
if not assigned(left.resultdef) then if not assigned(left.resultdef) then
@ -657,6 +658,22 @@ implementation
if (left.nodetype<>nothingn) then if (left.nodetype<>nothingn) then
begin 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 { Convert tp procvars, this is needs to be done
here to make the change permanent. in the overload here to make the change permanent. in the overload
choosing the changes are only made temporarily } choosing the changes are only made temporarily }
@ -664,7 +681,7 @@ implementation
not(parasym.vardef.typ in [procvardef,formaldef]) then not(parasym.vardef.typ in [procvardef,formaldef]) then
begin begin
if maybe_call_procvar(left,true) then if maybe_call_procvar(left,true) then
resultdef:=left.resultdef; resultdef:=left.resultdef
end; end;
{ Remove implicitly inserted typecast to pointer for { Remove implicitly inserted typecast to pointer for

View File

@ -357,7 +357,7 @@ implementation
result:=false; result:=false;
if (p1.resultdef.typ<>procvardef) or if (p1.resultdef.typ<>procvardef) or
(tponly and (tponly and
not(m_tp_procvar in current_settings.modeswitches)) then ([m_tp_procvar,m_mac_procvar] * current_settings.modeswitches = [])) then
exit; exit;
{ ignore vecn,subscriptn } { ignore vecn,subscriptn }
hp:=p1; hp:=p1;
@ -517,7 +517,6 @@ implementation
end; end;
function call_fail_node:tnode; function call_fail_node:tnode;
var var
para : tcallparanode; para : tcallparanode;

View File

@ -48,7 +48,7 @@ begin
B(@A); B(@A);
n := nil; n := nil;
n := A; n := A;
if nil <> n then if assigned(n) then
C(n); C(n);
C(A); C(A);
C(@A); C(@A);

22
tests/webtbs/tw17379.pp Normal file
View 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
View 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.