Преглед изворни кода

compiler: fix for-in loop with object enumerator (not a class instance) + test

git-svn-id: branches/paul/features@13946 -
paul пре 16 година
родитељ
комит
20ca62223e
3 измењених фајлова са 74 додато и 7 уклоњено
  1. 1 0
      .gitattributes
  2. 18 7
      compiler/pstatmnt.pas
  3. 55 0
      tests/test/tforin6.pp

+ 1 - 0
.gitattributes

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

+ 18 - 7
compiler/pstatmnt.pas

@@ -769,16 +769,27 @@ implementation
                 ccallnode.create(nil,tprocsym(enumerator_destructor.procsym), // finally node
                   enumerator_destructor.procsym.owner,ctemprefnode.create(enumvar),[]));
             end;
-          end;
-
-          { if getenumerator <> nil then do the loop }
-          addstatement(loopstatement,
-            cifnode.create(
+            { if getenumerator <> nil then do the loop }
+            whileloopnode:=cifnode.create(
               caddnode.create(unequaln, ctemprefnode.create(enumvar), cnilnode.create),
               whileloopnode,
               nil
-              )
-            );
+              );
+          end;
+
+          addstatement(loopstatement, whileloopnode);
+
+          if is_object(enumerator_get.returndef) then
+          begin
+            // call the object destructor too
+            enumerator_destructor:=tobjectdef(enumerator_get.returndef).Finddestructor;
+            if assigned(enumerator_destructor) then
+            begin
+              addstatement(loopstatement,
+                ccallnode.create(nil,tprocsym(enumerator_destructor.procsym),
+                    enumerator_destructor.procsym.owner,ctemprefnode.create(enumvar),[]));
+            end;
+          end;
 
           { free the temp variable for enumerator }
           addstatement(loopstatement,ctempdeletenode.create(enumvar));

+ 55 - 0
tests/test/tforin6.pp

@@ -0,0 +1,55 @@
+program Project18;
+
+{$APPTYPE CONSOLE}
+
+type
+  { TMyListEnumerator }
+
+  TMyListEnumerator = object
+  private
+    FCurrent: Integer;
+  public
+    constructor Create;
+    destructor Destroy;
+    function MoveNext: Boolean;
+    property Current: Integer read FCurrent;
+  end;
+
+  TMyList = class
+  end;
+
+{ TMyListEnumerator }
+
+constructor TMyListEnumerator.Create;
+begin
+  WriteLn('create');
+  FCurrent := 0;
+end;
+
+destructor TMyListEnumerator.Destroy;
+begin
+  WriteLn('destroy');
+  inherited;
+end;
+
+function TMyListEnumerator.MoveNext: Boolean;
+begin
+  inc(FCurrent);
+  Result := FCurrent <= 3;
+end;
+
+operator enumerator (AList: TMyList): TMyListEnumerator;
+begin
+  Result.Create;
+end;
+
+var
+  List: TMyList;
+  i: integer;
+begin
+  List := TMyList.Create;
+  for i in List do
+    WriteLn(i);
+  List.Free;
+end.
+