瀏覽代碼

* fix #39858: correctly keep track of symbols that need to be captured into the capturer
+ added test

Sven/Sarah Barth 3 年之前
父節點
當前提交
5e7330448d
共有 2 個文件被更改,包括 55 次插入4 次删除
  1. 11 4
      compiler/procdefutil.pas
  2. 44 0
      tests/webtbs/tw39858.pp

+ 11 - 4
compiler/procdefutil.pas

@@ -1463,6 +1463,7 @@ implementation
     var
       i,j : longint;
       capturer : tobjectdef;
+      tocapture,
       capturedsyms : tfplist;
       convertarg : tconvert_arg;
       mapping : pconvert_mapping;
@@ -1550,6 +1551,10 @@ implementation
 
           selfsym:=get_capturer(pd);
 
+          { only capture those symbols that weren't capture already by one of
+            the above if-clauses and thus are now listed in capturedsyms }
+          tocapture:=tfplist.create;
+
           for i:=0 to pd.localst.symlist.count-1 do
             begin
               sym:=tsym(pd.localst.symlist[i]);
@@ -1557,7 +1562,7 @@ implementation
                 continue;
               if assigned(tabstractnormalvarsym(sym).capture_sym) then
                 if capturedsyms.indexof(sym)<0 then
-                  capturedsyms.add(sym);
+                  tocapture.add(sym);
             end;
 
           for i:=0 to pd.parast.symlist.count-1 do
@@ -1570,13 +1575,13 @@ implementation
                     outermost method }
                   not (vo_is_self in tabstractvarsym(sym).varoptions) then
                 if capturedsyms.indexof(sym)<0 then
-                  capturedsyms.add(sym);
+                  tocapture.add(sym);
             end;
 
-          for i:=0 to capturedsyms.count-1 do
+          for i:=0 to tocapture.count-1 do
             begin
               new(mapping);
-              mapping^.oldsym:=tsym(capturedsyms[i]);
+              mapping^.oldsym:=tsym(tocapture[i]);
               {$ifdef DEBUG_CAPTURER}writeln('Replacing symbol ',mapping^.oldsym.Name);{$endif}
               mapping^.newsym:=tabstractnormalvarsym(mapping^.oldsym).capture_sym;
               if not assigned(mapping^.newsym) then
@@ -1584,6 +1589,8 @@ implementation
               mapping^.selfnode:=self_tree_for_sym(selfsym,mapping^.newsym);
               convertarg.mappings.add(mapping);
             end;
+
+          tocapture.free;
         end;
 
       { not required anymore }

+ 44 - 0
tests/webtbs/tw39858.pp

@@ -0,0 +1,44 @@
+program tw39858;
+
+{$mode objfpc}{$H+}
+{$ModeSwitch anonymousfunctions}
+{$ModeSwitch functionreferences}
+
+type
+  TProc = reference to procedure;
+
+procedure Meth1(proc: TProc);
+begin
+  Writeln('Enter Meth1');
+  proc();
+  Writeln('Exit Meth1');
+end;
+
+procedure Meth2(proc: TProc);
+begin
+  Writeln('Enter Meth2');
+  proc();
+  Writeln('Exit Meth2');
+end;
+
+procedure Test;
+var
+  z: integer;
+begin
+  z := 0;
+  Meth1(procedure begin
+    Writeln('Enter Anon1');
+    z:= 42;                               // this captured assigment causes the problem
+    Meth2(procedure begin
+      Writeln('Anon2');
+    end);
+    Writeln('Exit Anon1');
+  end);
+  if z <> 42 then
+    Halt(1);
+end;
+
+begin
+  Test;
+end.
+