2
0
Эх сурвалжийг харах

compiler: fix for-in loop for arrays. delphi does not copy arrays to a temp variable and it is possible to change array during loop. + test

git-svn-id: branches/paul/features@13943 -
paul 16 жил өмнө
parent
commit
88a9db5217

+ 1 - 0
.gitattributes

@@ -8212,6 +8212,7 @@ tests/test/tfinal2.pp svneol=native#text/pascal
 tests/test/tforin1.pp svneol=native#text/pascal
 tests/test/tforin1.pp svneol=native#text/pascal
 tests/test/tforin2.pp svneol=native#text/pascal
 tests/test/tforin2.pp svneol=native#text/pascal
 tests/test/tforin3.pp svneol=native#text/pascal
 tests/test/tforin3.pp svneol=native#text/pascal
+tests/test/tforin4.pp svneol=native#text/pascal
 tests/test/tfpu1.pp svneol=native#text/plain
 tests/test/tfpu1.pp svneol=native#text/plain
 tests/test/tfpu2.pp svneol=native#text/plain
 tests/test/tfpu2.pp svneol=native#text/plain
 tests/test/tfpu3.pp svneol=native#text/plain
 tests/test/tfpu3.pp svneol=native#text/plain

+ 7 - 4
compiler/pstatmnt.pas

@@ -569,7 +569,7 @@ implementation
           { result is a block of statements }
           { result is a block of statements }
           result:=internalstatements(loopstatement);
           result:=internalstatements(loopstatement);
 
 
-          if not is_open_array(expr.resultdef) then
+          if (node_complexity(expr) > 1) and not is_open_array(expr.resultdef) then
           begin
           begin
             { create a temp variable for expression }
             { create a temp variable for expression }
             arrayvar := ctempcreatenode.create(
             arrayvar := ctempcreatenode.create(
@@ -598,13 +598,16 @@ implementation
 
 
           addstatement(loopstatement,loopvar);
           addstatement(loopstatement,loopvar);
 
 
-
           arrayindex:=ctemprefnode.create(loopvar);
           arrayindex:=ctemprefnode.create(loopvar);
 
 
           loopbody:=internalstatements(loopbodystatement);
           loopbody:=internalstatements(loopbodystatement);
           // for-in loop variable := array_expression[index]
           // for-in loop variable := array_expression[index]
-          addstatement(loopbodystatement,
-              cassignmentnode.create(hloopvar,cvecnode.create(expr.getcopy,arrayindex)));
+          if assigned(arrayvar) then
+            addstatement(loopbodystatement,
+                cassignmentnode.create(hloopvar,cvecnode.create(ctemprefnode.create(arrayvar),arrayindex)))
+          else
+            addstatement(loopbodystatement,
+                cassignmentnode.create(hloopvar,cvecnode.create(expr.getcopy,arrayindex)));
 
 
           { add the actual statement to the loop }
           { add the actual statement to the loop }
           addstatement(loopbodystatement,hloopbody);
           addstatement(loopbodystatement,hloopbody);

+ 1 - 1
tests/test/tforin1.pp

@@ -1,4 +1,4 @@
-program project1;
+program tforin1;
 
 
 {$mode objfpc}{$H+}
 {$mode objfpc}{$H+}
 {$apptype console}
 {$apptype console}

+ 1 - 1
tests/test/tforin2.pp

@@ -1,4 +1,4 @@
-program project1;
+program tforin2;
 
 
 {$mode objfpc}{$H+}
 {$mode objfpc}{$H+}
 {$apptype console}
 {$apptype console}

+ 1 - 1
tests/test/tforin3.pp

@@ -1,4 +1,4 @@
-program Project18;
+program tforin3;
 
 
 {$APPTYPE CONSOLE}
 {$APPTYPE CONSOLE}
 
 

+ 56 - 0
tests/test/tforin4.pp

@@ -0,0 +1,56 @@
+program tforin4;
+
+{$APPTYPE CONSOLE}
+
+type
+  TMyArray = array of integer;
+
+function return_array: TMyArray;
+begin
+  SetLength(result, 3);
+  result[0] := 1;
+  result[1] := 2;
+  result[2] := 3;
+end;
+
+procedure TestArrayReturn;
+var
+  i: integer;
+begin
+  for i in return_array do
+    WriteLn(i);
+end;
+
+procedure TestDynamicArray;
+var
+  i: integer;
+  a: array of integer;
+begin
+  setlength(a, 3);
+  a[0]:=1;
+  a[1]:=2;
+  a[2]:=3;
+  for i in a do
+  begin
+    WriteLn(i);
+    a[2] := -1;
+  end;
+end;
+
+procedure TestOpenArray(a: array of integer);
+var
+  i: integer;
+begin
+  for i in a do
+  begin
+    WriteLn(i);
+    a[2] := -1;
+  end;
+end;
+
+begin
+  TestOpenArray([1,2,3]);
+  TestDynamicArray;
+  TestArrayReturn;
+end.
+