Browse Source

* ensure that if we create a temp for the funcretnode in a call node,
the funcretnode field keeps a reference to this temp even after we
assign it to the call-by-reference return parameter if it is deleted
by changing it into a normal temp (after which it will be freed when
the result of the call node is used), because in that case getcopy
for the callnode must copy this reference after copying the
tempdeletenode in order to reset tempinfo^.hookoncopy (mantis #29891)

git-svn-id: trunk@33569 -

Jonas Maebe 9 years ago
parent
commit
44682f9f4d
3 changed files with 45 additions and 2 deletions
  1. 1 0
      .gitattributes
  2. 18 2
      compiler/ncal.pas
  3. 26 0
      tests/webtbs/tw29891.pp

+ 1 - 0
.gitattributes

@@ -15015,6 +15015,7 @@ tests/webtbs/tw2976.pp svneol=native#text/plain
 tests/webtbs/tw29792.pp svneol=native#text/pascal
 tests/webtbs/tw2983.pp svneol=native#text/plain
 tests/webtbs/tw2984.pp svneol=native#text/plain
+tests/webtbs/tw29891.pp svneol=native#text/plain
 tests/webtbs/tw29893.pp svneol=native#text/pascal
 tests/webtbs/tw29912.pp svneol=native#text/plain
 tests/webtbs/tw29923.pp svneol=native#text/plain

+ 18 - 2
compiler/ncal.pas

@@ -3027,8 +3027,24 @@ implementation
                  begin
                    if not assigned(funcretnode) then
                      internalerror(200709083);
-                   para.left:=funcretnode;
-                   funcretnode:=nil;
+                   { if funcretnode is a temprefnode, we have to keep it intact
+                     if it may have been created in maybe_create_funcret_node(),
+                     because then it will also be destroyed by a
+                     ctempdeletenode.create_normal_temp() in the cleanup code
+                     for this call code. In that case we have to copy this
+                     ttemprefnode after the tempdeletenode to reset its
+                     tempinfo^.hookoncopy. This is done by copying funcretnode
+                     in tcallnode.getcopy(), but for that to work we can't reset
+                     funcretnode to nil here. }
+                   if (funcretnode.nodetype<>temprefn) or
+                      (not(cnf_return_value_used in callnodeflags) and
+                       (cnf_do_inline in callnodeflags)) then
+                     begin
+                       para.left:=funcretnode;
+                       funcretnode:=nil;
+                     end
+                   else
+                     para.left:=funcretnode.getcopy;
                  end
                 else
                  if vo_is_self in para.parasym.varoptions then

+ 26 - 0
tests/webtbs/tw29891.pp

@@ -0,0 +1,26 @@
+{ %NORUN }
+
+program tinterr;
+
+{$mode objfpc}{$H+}
+
+type
+  TALVector3f = array[0..2] of Single;
+
+function alGetSource3f: TALVector3f;
+begin
+
+end;
+
+function VectorToNiceStr(const v: array of Single): string;
+begin
+
+end;
+
+  function SampleSourceState:string;
+  begin
+   result := 'POSITION : '+ VectorToNiceStr(alGetSource3f) + LineEnding;
+  end;
+
+begin
+end.