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

* fixed webtbf/tw3631
* properly set vs_read/written status for tp-style objects
without vmt of which a method is called

git-svn-id: trunk@6005 -

Jonas Maebe 18 жил өмнө
parent
commit
9ad579855e

+ 15 - 8
compiler/htypechk.pas

@@ -765,22 +765,29 @@ implementation
       const
         vstrans: array[tvarstate,tvarstate] of tvarstate = (
           { vs_none -> ... }
-          (vs_none,vs_declared,vs_initialised,vs_read,vs_read_not_warned,vs_written,vs_readwritten),
+          (vs_none,vs_declared,vs_initialised,vs_read,vs_read_not_warned,vs_referred_not_inited,vs_written,vs_readwritten),
           { vs_declared -> ... }
-          (vs_none,vs_declared,vs_initialised,vs_read,vs_read_not_warned,vs_written,vs_readwritten),
+          (vs_none,vs_declared,vs_initialised,vs_read,vs_read_not_warned,vs_referred_not_inited,vs_written,vs_readwritten),
           { vs_initialised -> ... }
-          (vs_none,vs_initialised,vs_initialised,vs_read,vs_read,vs_written,vs_readwritten),
+          (vs_none,vs_initialised,vs_initialised,vs_read,vs_read,vs_read,vs_written,vs_readwritten),
           { vs_read -> ... }
-          (vs_none,vs_read,vs_read,vs_read,vs_read_not_warned,vs_readwritten,vs_readwritten),
+          (vs_none,vs_read,vs_read,vs_read,vs_read,vs_read,vs_readwritten,vs_readwritten),
           { vs_read_not_warned -> ... }
-          (vs_none,vs_read_not_warned,vs_read,vs_read,vs_read_not_warned,vs_readwritten,vs_readwritten),
+          (vs_none,vs_read_not_warned,vs_read,vs_read,vs_read_not_warned,vs_read_not_warned,vs_readwritten,vs_readwritten),
+          { vs_referred_not_inited }
+          (vs_none,vs_referred_not_inited,vs_read,vs_read,vs_read,vs_referred_not_inited,vs_readwritten,vs_readwritten),
           { vs_written -> ... }
-          (vs_none,vs_written,vs_written,vs_readwritten,vs_readwritten,vs_written,vs_readwritten),
+          (vs_none,vs_written,vs_written,vs_readwritten,vs_readwritten,vs_written,vs_written,vs_readwritten),
           { vs_readwritten -> ... }
-          (vs_none,vs_readwritten,vs_readwritten,vs_readwritten,vs_readwritten,vs_readwritten,vs_readwritten));
+          (vs_none,vs_readwritten,vs_readwritten,vs_readwritten,vs_readwritten,vs_readwritten,vs_readwritten,vs_readwritten));
       var
         hsym : tabstractvarsym;
       begin
+        { make sure we can still warn about uninitialised use after high(v), @v etc }
+        if (newstate = vs_read) and
+           not(vsf_must_be_valid in varstateflags) then
+          newstate := vs_referred_not_inited;
+
         while assigned(p) do
          begin
            case p.nodetype of
@@ -822,7 +829,7 @@ implementation
                   begin
                     hsym:=tabstractvarsym(tloadnode(p).symtableentry);
                     if (vsf_must_be_valid in varstateflags) and
-                       (hsym.varstate in [vs_declared,vs_read_not_warned]) then
+                       (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

+ 8 - 8
compiler/ncal.pas

@@ -2144,15 +2144,15 @@ implementation
                  Also allow it for simple loads }
                if (procdefinition.proctypeoption=potype_constructor) or
                   ((hpt.nodetype=loadn) and
-                   (
-                    (methodpointer.resultdef.typ=classrefdef) or
-                    (
-                     (methodpointer.resultdef.typ=objectdef) and
-                     not(oo_has_virtual in tobjectdef(methodpointer.resultdef).objectoptions)
-                    )
-                   )
+                   (methodpointer.resultdef.typ=objectdef) and
+                   not(oo_has_virtual in tobjectdef(methodpointer.resultdef).objectoptions)
                   ) then
-                 set_varstate(methodpointer,vs_read,[])
+                 { a constructor will and a method may write something to }
+                 { the fields                                             }
+                 set_varstate(methodpointer,vs_written,[])
+               else if ((hpt.nodetype=loadn) and
+                     (methodpointer.resultdef.typ=classrefdef)) then
+                   set_varstate(methodpointer,vs_read,[])
                else
                  set_varstate(methodpointer,vs_read,[vsf_must_be_valid]);
 

+ 3 - 1
compiler/nmem.pas

@@ -452,7 +452,9 @@ implementation
          { To avoid false positives regarding "uninitialised"          }
          { warnings when using arrays, perform it in two steps         }
          set_varstate(left,vs_written,[]);
-         set_varstate(left,vs_read,[]);
+         { vsf_must_be_valid so it doesn't get changed into }
+         { vsf_referred_not_inited                          }
+         set_varstate(left,vs_read,[vsf_must_be_valid]);
          dec(parsing_para_level);
       end;
 

+ 20 - 2
compiler/symconst.pas

@@ -393,9 +393,27 @@ type
     macrosym
   );
 
-  { State of the variable, if it's declared, assigned or used }
+  { State of the variable:
+     vs_declared: variable has been declared, not initialised
+       (e.g. normal variable, out parameter)
+     vs_initialised: variable has been declared and is valid
+       (e.g. typed constant, var/const parameter)
+     vs_read: variable has been read and the read was checked for validity
+       (so a warning has been given if necessary)
+     vs_read_not_warned: variable has been read, but we didn't warn about
+       whether or not the variable was valid
+       (e.g. read of global variable -> warn at end of compilation unit if
+        the state is vs_read_not_warned, since that means it's only read and
+        never written)
+     vs_referred_not_inited: variable has been used in length/low/high/@/...
+        expression, was not yet initialised and needn't be at that time
+        (e.g. length() of a statically allocated array, or sizeof(variable))
+     vs_written: variable has been assigned/written to, but not yet read
+        (e.g. assigning something to a variable/parameter)
+     vs_readwritten: variable has been written to and read from }
   tvarstate=(vs_none,
-    vs_declared,vs_initialised,vs_read,vs_read_not_warned,vs_written,vs_readwritten
+    vs_declared,vs_initialised,vs_read,vs_read_not_warned,
+    vs_referred_not_inited,vs_written,vs_readwritten
   );
 
   tvarspez = (vs_value,vs_const,vs_var,vs_out);