|
@@ -781,6 +781,16 @@ implementation
|
|
|
if codegenerror then
|
|
|
exit;
|
|
|
|
|
|
+ { if right is a function call for which the address of the result }
|
|
|
+ { is allocated by the caller and passed to the function via an }
|
|
|
+ { invisible function result, try to pass the x in "x:=f(...)" as }
|
|
|
+ { that function result instead. Condition: x cannot be accessible }
|
|
|
+ { from within f. This is the case if x is a temp, or x is a local }
|
|
|
+ { variable or value parameter of the current block and its address }
|
|
|
+ { is not passed to f. One problem: what if someone takes the }
|
|
|
+ { address of x, puts it in a pointer variable/field and then }
|
|
|
+ { accesses it that way from within the function? This is solved }
|
|
|
+ { (in a conservative way) using the ti_addr_taken/addr_taken flags }
|
|
|
if (cs_opt_level1 in current_settings.optimizerswitches) and
|
|
|
(right.nodetype = calln) and
|
|
|
(right.resultdef=left.resultdef) and
|
|
@@ -790,7 +800,25 @@ implementation
|
|
|
{ function }
|
|
|
(
|
|
|
(
|
|
|
- (left.nodetype = temprefn) and
|
|
|
+ (((left.nodetype = temprefn) and
|
|
|
+ not(ti_addr_taken in ttemprefnode(left).tempinfo^.flags) and
|
|
|
+ not(ti_may_be_in_reg in ttemprefnode(left).tempinfo^.flags)) or
|
|
|
+ ((left.nodetype = loadn) and
|
|
|
+ { nested procedures may access the current procedure's locals }
|
|
|
+ (tcallnode(right).procdefinition.parast.symtablelevel=normal_function_level) and
|
|
|
+ { must be a local variable or a value para }
|
|
|
+ ((tloadnode(left).symtableentry.typ = localvarsym) or
|
|
|
+ ((tloadnode(left).symtableentry.typ = paravarsym) and
|
|
|
+ (tparavarsym(tloadnode(left).symtableentry).varspez = vs_value)
|
|
|
+ )
|
|
|
+ ) and
|
|
|
+ { the address may not have been taken of the variable/parameter, because }
|
|
|
+ { otherwise it's possible that the called function can access it via a }
|
|
|
+ { global variable or other stored state }
|
|
|
+ not(tabstractvarsym(tloadnode(left).symtableentry).addr_taken) and
|
|
|
+ (tabstractvarsym(tloadnode(left).symtableentry).varregable in [vr_none,vr_addr])
|
|
|
+ )
|
|
|
+ ) and
|
|
|
paramanager.ret_in_param(right.resultdef,tcallnode(right).procdefinition.proccalloption)
|
|
|
) or
|
|
|
{ there's special support for ansi/widestrings in the callnode }
|
|
@@ -798,7 +826,8 @@ implementation
|
|
|
is_widestring(right.resultdef)
|
|
|
) then
|
|
|
begin
|
|
|
- make_not_regable(left,vr_addr);
|
|
|
+ if assigned(tcallnode(right).funcretnode) then
|
|
|
+ internalerror(2007080201);
|
|
|
tcallnode(right).funcretnode := left;
|
|
|
result := right;
|
|
|
left := nil;
|