浏览代码

* constref does not mean that a variable is written, resolves #41206

florian 3 月之前
父节点
当前提交
f672d4cccf
共有 2 个文件被更改,包括 30 次插入2 次删除
  1. 19 2
      compiler/ncal.pas
  2. 11 0
      tests/webtbs/tw41206.pp

+ 19 - 2
compiler/ncal.pas

@@ -1421,8 +1421,7 @@ implementation
                         else
                         else
                           make_not_regable(left,[ra_addr_regable,ra_addr_taken]);
                           make_not_regable(left,[ra_addr_regable,ra_addr_taken]);
                       end;
                       end;
-                    vs_var,
-                    vs_constref:
+                    vs_var:
                       begin
                       begin
                         set_varstate(left,vs_readwritten,[vsf_must_be_valid,vsf_use_hints]);
                         set_varstate(left,vs_readwritten,[vsf_must_be_valid,vsf_use_hints]);
                         { compilerprocs never capture the address of their
                         { compilerprocs never capture the address of their
@@ -1438,6 +1437,24 @@ implementation
                         else
                         else
                           make_not_regable(left,[ra_addr_regable,ra_addr_taken]);
                           make_not_regable(left,[ra_addr_regable,ra_addr_taken]);
                       end;
                       end;
+                    vs_constref:
+                      begin
+                        { constref does not mean that the variable is actually written, this might only
+                          happen if it's address is taken, this is handled below }
+                        set_varstate(left,vs_read,[vsf_must_be_valid,vsf_use_hints]);
+                        { compilerprocs never capture the address of their
+                          parameters }
+                        if (po_compilerproc in aktcallnode.procdefinition.procoptions) or
+                        { if we handled already the proc. body and it is not inlined,
+                          we can propagate the information if the address of a parameter is taken or not }
+                        ((aktcallnode.procdefinition.typ=procdef) and
+                         not(po_inline in tprocdef(aktcallnode.procdefinition).procoptions) and
+                         (tprocdef(aktcallnode.procdefinition).is_implemented) and
+                         not(parasym.addr_taken)) then
+                          make_not_regable(left,[ra_addr_regable])
+                        else
+                          make_not_regable(left,[ra_addr_regable,ra_addr_taken]);
+                      end;
                     else
                     else
                       set_varstate(left,vs_read,[vsf_must_be_valid]);
                       set_varstate(left,vs_read,[vsf_must_be_valid]);
                   end;
                   end;

+ 11 - 0
tests/webtbs/tw41206.pp

@@ -0,0 +1,11 @@
+{ %OPT=-O3 }
+procedure f(constref x: int32); noinline;
+begin
+end;
+
+var
+	i: int32;
+
+begin
+	for i := 0 to 9 do f(i);
+end.