Ver Fonte

* new node flag nf_modify to mark nodes being read and then written by one load node
* dfa takes care of nf_modify to create better life information
o resolves #11846 and #11849

git-svn-id: trunk@11615 -

florian há 17 anos atrás
pai
commit
369ed493f2

+ 3 - 0
.gitattributes

@@ -8105,6 +8105,7 @@ tests/webtbf/tw1157a.pp svneol=native#text/plain
 tests/webtbf/tw11619b.pp svneol=native#text/plain
 tests/webtbf/tw11632.pp svneol=native#text/plain
 tests/webtbf/tw11848a.pp svneol=native#text/plain
+tests/webtbf/tw11849a.pp svneol=native#text/plain
 tests/webtbf/tw11862a.pp svneol=native#text/plain
 tests/webtbf/tw1238.pp svneol=native#text/plain
 tests/webtbf/tw1251a.pp svneol=native#text/plain
@@ -8541,7 +8542,9 @@ tests/webtbs/tw1157.pp svneol=native#text/plain
 tests/webtbs/tw1157b.pp svneol=native#text/plain
 tests/webtbs/tw11619.pp svneol=native#text/plain
 tests/webtbs/tw1181.pp svneol=native#text/plain
+tests/webtbs/tw11846.pp svneol=native#text/plain
 tests/webtbs/tw11848.pp svneol=native#text/plain
+tests/webtbs/tw11849.pp svneol=native#text/plain
 tests/webtbs/tw11852.pp svneol=native#text/plain
 tests/webtbs/tw11861.pp svneol=native#text/plain
 tests/webtbs/tw11862.pp svneol=native#text/plain

+ 50 - 43
compiler/htypechk.pas

@@ -850,49 +850,56 @@ implementation
              loadn :
                begin
                  if (tloadnode(p).symtableentry.typ in [localvarsym,paravarsym,staticvarsym]) then
-                  begin
-                    hsym:=tabstractvarsym(tloadnode(p).symtableentry);
-                    if (vsf_must_be_valid in varstateflags) and
-                       (hsym.varstate in [vs_declared,vs_read_not_warned,vs_referred_not_inited]) then
-                      begin
-                        { Give warning/note for uninitialized locals }
-                        if assigned(hsym.owner) and
-                          not(cs_opt_nodedfa in current_settings.optimizerswitches) and
-                           not(vo_is_external in hsym.varoptions) and
-                           (hsym.owner.symtabletype in [parasymtable,localsymtable,staticsymtable]) and
-                           ((hsym.owner=current_procinfo.procdef.localst) or
-                            (hsym.owner=current_procinfo.procdef.parast)) then
-                          begin
-                            if (vo_is_funcret in hsym.varoptions) then
-                              begin
-                                if (vsf_use_hints in varstateflags) then
-                                  CGMessagePos(p.fileinfo,sym_h_function_result_uninitialized)
-                                else
-                                  CGMessagePos(p.fileinfo,sym_w_function_result_uninitialized)
-                              end
-                            else
-                              begin
-                                if tloadnode(p).symtable.symtabletype=localsymtable then
-                                  begin
-                                    if (vsf_use_hints in varstateflags) then
-                                      CGMessagePos1(p.fileinfo,sym_h_uninitialized_local_variable,hsym.realname)
-                                    else
-                                      CGMessagePos1(p.fileinfo,sym_w_uninitialized_local_variable,hsym.realname);
-                                  end
-                                else
-                                  begin
-                                    if (vsf_use_hints in varstateflags) then
-                                      CGMessagePos1(p.fileinfo,sym_h_uninitialized_variable,hsym.realname)
-                                    else
-                                      CGMessagePos1(p.fileinfo,sym_w_uninitialized_variable,hsym.realname);
-                                  end;
-                              end;
-                          end
-                        else if (newstate = vs_read) then
-                          newstate := vs_read_not_warned;
-                      end;
-                    hsym.varstate := vstrans[hsym.varstate,newstate];
-                  end;
+                   begin
+                     hsym:=tabstractvarsym(tloadnode(p).symtableentry);
+                     if (vsf_must_be_valid in varstateflags) and
+                        (hsym.varstate in [vs_declared,vs_read_not_warned,vs_referred_not_inited]) then
+                       begin
+                         { Give warning/note for uninitialized locals }
+                         if assigned(hsym.owner) and
+                           not(cs_opt_nodedfa in current_settings.optimizerswitches) and
+                            not(vo_is_external in hsym.varoptions) and
+                            (hsym.owner.symtabletype in [parasymtable,localsymtable,staticsymtable]) and
+                            ((hsym.owner=current_procinfo.procdef.localst) or
+                             (hsym.owner=current_procinfo.procdef.parast)) then
+                           begin
+                             if (vo_is_funcret in hsym.varoptions) then
+                               begin
+                                 if (vsf_use_hints in varstateflags) then
+                                   CGMessagePos(p.fileinfo,sym_h_function_result_uninitialized)
+                                 else
+                                   CGMessagePos(p.fileinfo,sym_w_function_result_uninitialized)
+                               end
+                             else
+                               begin
+                                 if tloadnode(p).symtable.symtabletype=localsymtable then
+                                   begin
+                                     if (vsf_use_hints in varstateflags) then
+                                       CGMessagePos1(p.fileinfo,sym_h_uninitialized_local_variable,hsym.realname)
+                                     else
+                                       CGMessagePos1(p.fileinfo,sym_w_uninitialized_local_variable,hsym.realname);
+                                   end
+                                 else
+                                   begin
+                                     if (vsf_use_hints in varstateflags) then
+                                       CGMessagePos1(p.fileinfo,sym_h_uninitialized_variable,hsym.realname)
+                                     else
+                                       CGMessagePos1(p.fileinfo,sym_w_uninitialized_variable,hsym.realname);
+                                   end;
+                               end;
+                           end
+                         else if (newstate = vs_read) then
+                           newstate := vs_read_not_warned;
+                       end;
+                     hsym.varstate := vstrans[hsym.varstate,newstate];
+                   end;
+                 case newstate of
+                   vs_written:
+                     include(tloadnode(p).flags,nf_write);
+                   vs_readwritten:
+                     if not(nf_write in tloadnode(p).flags) then
+                       include(tloadnode(p).flags,nf_modify);
+                 end;
                  break;
                end;
              callparan :

+ 3 - 5
compiler/nmem.pas

@@ -561,10 +561,8 @@ implementation
 
 
     function tsubscriptnode.dogetcopy : tnode;
-
       var
          p : tsubscriptnode;
-
       begin
          p:=tsubscriptnode(inherited dogetcopy);
          p.vs:=vs;
@@ -587,10 +585,10 @@ implementation
       end;
 
     procedure Tsubscriptnode.mark_write;
+      begin
+        include(flags,nf_write);
+      end;
 
-    begin
-      include(flags,nf_write);
-    end;
 
     function tsubscriptnode.pass_1 : tnode;
       begin

+ 2 - 1
compiler/node.pas

@@ -201,7 +201,8 @@ interface
 
          { general }
          nf_pass1_done,
-         nf_write,       { Node is written to            }
+         nf_write,       { Node is written to    }
+         nf_modify,      { Node is modified      }
          nf_is_funcret,
          nf_isproperty,
          nf_processing,

+ 34 - 2
compiler/optdfa.pas

@@ -116,7 +116,12 @@ unit optdfa;
           loadn:
             begin
               pdfainfo(arg)^.map.Add(n);
-              if nf_write in n.flags then
+              if nf_modify in n.flags then
+                begin
+                  DFASetInclude(pdfainfo(arg)^.use^,n.optinfo^.index);
+                  DFASetInclude(pdfainfo(arg)^.def^,n.optinfo^.index)
+                end
+              else if nf_write in n.flags then
                 DFASetInclude(pdfainfo(arg)^.def^,n.optinfo^.index)
               else
                 DFASetInclude(pdfainfo(arg)^.use^,n.optinfo^.index);
@@ -424,6 +429,7 @@ unit optdfa;
                             { get info from faked resultnode }
                             node.optinfo^.use:=resultnode.optinfo^.use;
                             node.optinfo^.life:=node.optinfo^.use;
+                            changed:=true;
                           end;
                       end;
                   end;
@@ -524,14 +530,40 @@ unit optdfa;
 
 
     procedure TDFABuilder.createdfainfo(node : tnode);
+    {
+      var
+        lastnode : tnode;
+        fakeexitnode : texitnode;
+    }
       begin
         if not(assigned(nodemap)) then
           nodemap:=TIndexedNodeSet.Create;
         { add controll flow information }
         SetNodeSucessors(node);
-
+     {
+        { create an exit node for functions to get
+          the function result at the end handled properly }
+        if not(is_void(current_procinfo.procdef.returndef)) and
+          not(current_procinfo.procdef.proctypeoption=potype_constructor) then
+          begin
+            lastnode:=node;
+            while assigned(lastnode.successor) do
+              lastnode:=lastnode.successor;
+            fakeexitnode:=cexitnode.create(nil);
+            lastnode.successor:=fakeexitnode;
+          end
+        else
+           fakeexitnode:=nil;
+     }
         { now, collect life information }
         CreateLifeInfo(node,nodemap);
+     {
+        if assigned(fakeexitnode) then
+          begin
+            lastnode.successor.free;
+            lastnode.successor:=nil;
+          end;
+     }
       end;
 
 

+ 19 - 0
tests/webtbf/tw11849a.pp

@@ -0,0 +1,19 @@
+{ %OPT=-Sew -Oodfa }
+{ %fail }
+{$mode objfpc}
+procedure GiveMe(var i: integer);
+begin
+  i:=0;
+end;
+
+function Test(a: integer): integer;
+var
+  i: integer;
+begin
+  GiveMe(i);
+  Result:=i;
+end;
+
+
+begin
+end.

+ 13 - 0
tests/webtbs/tw11846.pp

@@ -0,0 +1,13 @@
+{ %OPT=-Sew -Oodfa }
+{ %NORUN }
+{$mode objfpc}
+function Test(a: integer): boolean;
+var
+  i: Integer;
+begin
+  for i:=1 to 2 do
+    Result:=true;
+end;
+
+begin
+end.

+ 19 - 0
tests/webtbs/tw11849.pp

@@ -0,0 +1,19 @@
+{ %OPT=-Sew -Oodfa }
+{ %norun }
+{$mode objfpc}
+procedure GiveMe(out i: integer);
+begin
+  i:=0;
+end;
+
+function Test(a: integer): integer;
+var
+  i: integer;
+begin
+  GiveMe(i);
+  Result:=i;
+end;
+
+
+begin
+end.