]> andersk Git - splint.git/blobdiff - src/transferChecks.c
Fixed problem with NULL being changed.
[splint.git] / src / transferChecks.c
index 9a6bcc1c3907d05e90681a0e8ecf5087b375cf1b..4fe2247ba761a3ec75c851f6ee8ec6dc1ed3103c 100644 (file)
@@ -1,6 +1,6 @@
 /*
-** LCLint - annotation-assisted static program checker
-** Copyright (C) 1994-2001 University of Virginia,
+** Splint - annotation-assisted static program checker
+** Copyright (C) 1994-2003 University of Virginia,
 **         Massachusetts Institute of Technology
 **
 ** This program is free software; you can redistribute it and/or modify it
 ** the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
 ** MA 02111-1307, USA.
 **
-** For information on lclint: lclint-request@cs.virginia.edu
-** To report a bug: lclint-bug@cs.virginia.edu
-** For more information: http://lclint.cs.virginia.edu
+** For information on splint: info@splint.org
+** To report a bug: splint-bug@splint.org
+** For more information: http://www.splint.org
 */
 /*
 ** transferChecks.c
 */
 
-# include "lclintMacros.nf"
+# include "splintMacros.nf"
 # include "basic.h"
 # include "transferChecks.h"
 
+/* transfer types: */
+typedef enum
+{
+  TT_FCNRETURN,
+  TT_DOASSIGN,
+  TT_FIELDASSIGN,
+  TT_FCNPASS,
+  TT_GLOBPASS,
+  TT_GLOBRETURN,
+  TT_PARAMRETURN,
+  TT_LEAVETRANS,
+  TT_GLOBINIT
+} transferKind;
+
 static void checkStructTransfer (exprNode p_lhs, sRef p_slhs, exprNode p_rhs, sRef p_srhs,
                                 fileloc p_loc, transferKind p_tt);
 static void checkMetaStateConsistent (/*@exposed@*/ sRef p_fref, sRef p_tref, 
@@ -37,6 +51,7 @@ static void checkMetaStateConsistent (/*@exposed@*/ sRef p_fref, sRef p_tref,
 static void checkLeaveTrans (uentry p_actual, transferKind p_transferType);
 static void checkTransfer (exprNode p_fexp, /*@dependent@*/ sRef p_fref,
                           exprNode p_texp, /*@dependent@*/ sRef p_tref, 
+                          exprNode p_fcn, /* for printing better error messages */
                           fileloc p_loc, transferKind p_transferType);
 static void checkGlobTrans (uentry p_glob, transferKind p_type);
 
@@ -94,7 +109,7 @@ transferErrorMessage (transferKind transferType, alkind tkind) /*@*/
 }
 
 static /*@only@*/ cstring
-transferErrorExcerpt (transferKind transferType, exprNode fexp, exprNode texp) /*@*/ 
+transferErrorExcerpt (transferKind transferType, exprNode fexp, exprNode texp, exprNode fcn) /*@*/ 
 {
   switch (transferType)
     {
@@ -105,8 +120,16 @@ transferErrorExcerpt (transferKind transferType, exprNode fexp, exprNode texp) /
     case TT_GLOBINIT:
       return (message ("%s = %s", exprNode_unparse (texp), exprNode_unparse (fexp)));
     case TT_FCNPASS:
-      /*@i32 make it so called fcn is known here! */
-      return cstring_copy (exprNode_unparse (fexp)); 
+      if (exprNode_isDefined (fcn))
+       {
+         return message ("%s(..., %s, ...)",
+                         exprNode_unparse (fcn),
+                         exprNode_unparse (fexp));
+       }
+      else
+       {
+         return cstring_copy (exprNode_unparse (fexp));  
+       }
     BADDEFAULT;
     }
   BADEXIT;
@@ -284,7 +307,7 @@ checkCompletelyDefined (exprNode fexp, /*@exposed@*/ sRef fref, sRef ofref,
   ctype ct;
   alkind fkind = sRef_getAliasKind (fref);
   alkind tkind = sRef_getAliasKind (tref);
-
+  
   DPRINTF (("Check completely defined: %s [%s] / %s [%s]",
            exprNode_unparse (fexp), sRef_unparseFull (fref),
            exprNode_unparse (texp), sRef_unparseFull (tref)));
@@ -296,7 +319,7 @@ checkCompletelyDefined (exprNode fexp, /*@exposed@*/ sRef fref, sRef ofref,
         ("Check definition limit exceeded, checking %q. "
          "This either means there is a variable with at least "
          "%d indirections apparent in the program text, or "
-         "there is a bug in LCLint.",
+         "there is a bug in Splint.",
          sRef_unparse (fref),
          MAXDEPTH));
 
@@ -482,7 +505,8 @@ checkCompletelyDefined (exprNode fexp, /*@exposed@*/ sRef fref, sRef ofref,
            {
              ; /* no error (will be a definition error) */
            }
-         else if (transferType == TT_DOASSIGN)
+         else if (transferType == TT_DOASSIGN
+                  || transferType == TT_FIELDASSIGN) /* evans 2002-02-05 - added TT_FIELDASSIGN */
            {
              ; /* no error */
            }
@@ -743,6 +767,8 @@ checkCompletelyDefined (exprNode fexp, /*@exposed@*/ sRef fref, sRef ofref,
                                      sRef_undefined, TT_FCNPASS)),
               loc))
            {
+             DPRINTF (("fref: %s", sRef_unparseFull (fref)));
+             DPRINTF (("tref: %s", sRef_unparseFull (tref)));
              sRef_showNullInfo (fref);
              sRef_setNullError (fref);
            }
@@ -750,6 +776,7 @@ checkCompletelyDefined (exprNode fexp, /*@exposed@*/ sRef fref, sRef ofref,
       else
        {
          llassert (transferType == TT_DOASSIGN
+                   || transferType == TT_FIELDASSIGN /* evans 2002-02-05: no warnings for local fields */
                    || transferType == TT_GLOBINIT
                    || transferType == TT_LEAVETRANS);
        }
@@ -766,6 +793,8 @@ checkCompletelyDefined (exprNode fexp, /*@exposed@*/ sRef fref, sRef ofref,
 
   ct = ctype_realType (sRef_getType (fref));
 
+  DPRINTF (("Here: %s", ctype_unparse (ct)));
+
   if (!(sRef_isAnyDefined (fref) 
        || sRef_isPdefined (fref)
        || sRef_isAllocated (fref)
@@ -867,7 +896,8 @@ checkCompletelyDefined (exprNode fexp, /*@exposed@*/ sRef fref, sRef ofref,
                        {
                          sRef rb = sRef_getRootBase (fref);
                          sRef_showStateInfo (fref);
-                         sRef_setDefinedComplete (rb, loc);
+                         
+                         sRef_setDefinedCompleteDirect (rb, loc);
                        }
                    }
                }
@@ -891,7 +921,7 @@ checkCompletelyDefined (exprNode fexp, /*@exposed@*/ sRef fref, sRef ofref,
     {
       return YES;
     }
-  else if (ctype_isPointer (ct))
+  else if (ctype_isPointer (ct) || ctype_isArray (ct)) /* evans 2001-07-12 added ctype_isArray */
     {
       ctype tct = ctype_realType (sRef_getType (tref));
 
@@ -901,11 +931,16 @@ checkCompletelyDefined (exprNode fexp, /*@exposed@*/ sRef fref, sRef ofref,
        }
       else
        {
+         DPRINTF (("Here fref: %s", sRef_unparseFull (fref)));
+         DPRINTF (("Here tref: %s", sRef_unparseFull (tref)));
+
          if (ctype_isAP (tct) || ctype_isUnknown (tct))
            {
              sRef fptr = sRef_constructDeref (fref);
              sRef tptr = sRef_constructDeref (tref);
 
+             DPRINTF (("Here tptr: %s", sRef_unparseFull (tptr)));
+
              return (checkCompletelyDefined (fexp, fptr, ofref,
                                              texp, tptr,
                                              FALSE, inUnion, FALSE, loc, 
@@ -917,10 +952,6 @@ checkCompletelyDefined (exprNode fexp, /*@exposed@*/ sRef fref, sRef ofref,
            }
        }
     }
-  else if (ctype_isArray (ct))
-    {
-      return YES;
-    }
   else if (ctype_isStruct (ct))
     {
       ctype tct = ctype_realType (sRef_getType (tref));
@@ -1188,6 +1219,17 @@ checkCompletelyDefined (exprNode fexp, /*@exposed@*/ sRef fref, sRef ofref,
                                      sRef_unparse (fref)),
                             loc);
                        }
+                     /* evans 2001-08-21: added this branch for global returns */
+                     else if (transferType == TT_GLOBRETURN)
+                       {
+                         voptgenerror 
+                           (FLG_UNIONDEF,
+                            message ("Union %q reachable from global %q has "
+                                     "no defined field",
+                                     sRef_unparse (fref),
+                                     sRef_unparse (sRef_getRootBase (fref))),
+                            loc);
+                       }
                      else if (transferType == TT_DOASSIGN
                               || transferType == TT_FIELDASSIGN
                               || transferType == TT_GLOBINIT)
@@ -1246,17 +1288,18 @@ static /*@observer@*/ cstring dscCode_unparse (dscCode desc) /*@*/
 }
 
 static bool 
-  checkCompletelyDestroyed (exprNode p_fexp, sRef p_fref, bool p_topLevel, 
-                           fileloc p_loc, int p_depth, dscCode p_desc,
-                           bool p_hideErrors);
+checkCompletelyDestroyed (exprNode p_fexp, sRef p_fref, bool p_topLevel, bool p_isField,
+                         fileloc p_loc, int p_depth, dscCode p_desc,
+                         bool p_hideErrors);
 
-bool checkGlobalDestroyed (sRef fref, fileloc loc)
+bool transferChecks_globalDestroyed (sRef fref, fileloc loc)
 {
-  return (checkCompletelyDestroyed (exprNode_undefined, fref, TRUE,
+  DPRINTF (("Global destroyed: %s", sRef_unparseFull (fref)));
+  return (checkCompletelyDestroyed (exprNode_undefined, fref, TRUE, FALSE,
                                    loc, 0, DSC_GLOB, FALSE));
 }
 
-void checkLocalDestroyed (sRef fref, fileloc loc)
+void transferChecks_localDestroyed (sRef fref, fileloc loc)
 {
   if (sRef_isObserver (fref) || sRef_isExposed (fref)
       || sRef_isPartial (fref))
@@ -1265,12 +1308,12 @@ void checkLocalDestroyed (sRef fref, fileloc loc)
     }
   else
     {
-      (void) checkCompletelyDestroyed (exprNode_undefined, fref, TRUE,
+      (void) checkCompletelyDestroyed (exprNode_undefined, fref, TRUE, FALSE,
                                       loc, 0, DSC_LOCAL, FALSE);
     }
 }
 
-void checkStructDestroyed (sRef fref, fileloc loc)
+void transferChecks_structDestroyed (sRef fref, fileloc loc)
 {
   DPRINTF (("Check struct destroyed: %s", sRef_unparse (fref)));
 
@@ -1281,19 +1324,21 @@ void checkStructDestroyed (sRef fref, fileloc loc)
     }
   else
     {
-      (void) checkCompletelyDestroyed (exprNode_undefined, fref, TRUE,
+      (void) checkCompletelyDestroyed (exprNode_undefined, fref, TRUE, FALSE,
                                       loc, 0, DSC_STRUCT, FALSE);
     }
 }
 
 static bool
-  checkCompletelyDestroyed (exprNode fexp, sRef fref, bool topLevel,
-                           fileloc loc, int depth,
-                           dscCode desc, bool hideErrors)
+checkCompletelyDestroyed (exprNode fexp, sRef fref, bool topLevel, bool isField,
+                         fileloc loc, int depth,
+                         dscCode desc, bool hideErrors)
 {
   ctype ct;
-
-  DPRINTF (("Check completely destroyed: %s", sRef_unparseFull (fref)));
+  
+  DPRINTF (("Check completely destroyed: %s / %s",
+           sRef_unparse (fref),
+           bool_unparse (hideErrors)));
 
   if (depth > MAXDEPTH)
     {
@@ -1349,23 +1394,40 @@ static bool
       }
   }
 
-  if (sRef_isPdefined (fref) && !context_getFlag (FLG_STRICTDESTROY))
+  ct = ctype_realType (sRef_getType (fref));
+
+  if (sRef_isPdefined (fref) 
+      && ctype_isAP (ct)
+      && !isField
+      && !context_getFlag (FLG_STRICTDESTROY))
     {
-      DPRINTF (("Partial: %s", sRef_unparseFull (fref)));
-      hideErrors = TRUE; /* Don't report any more errors, but still change ownership. */
-    }
+      /*
+      ** Don't report errors for array elements (unless strictdestroy)
+      ** when at least one appears to have been destroyed.
+      */
 
+      DPRINTF (("Partial: %s / hiding errors: %s", sRef_unparseFull (fref),
+               ctype_unparse (ct)));
+      hideErrors = TRUE;
+      /* Don't report any more errors, but still change ownership. */
+    }
+  
   if (usymtab_isDefinitelyNull (fref)) 
     {
       DPRINTF (("Probably null!"));
       return TRUE;
     }
 
-  if (!context_getFlag (FLG_COMPDESTROY)) return TRUE;
-  if (!context_getFlag (FLG_MUSTFREE)) return TRUE;
+  /*
+  ** evans 2002-01-02: removed this
+  ** if (!context_flagOn (FLG_COMPDESTROY, loc)) 
+  ** {
+  ** return TRUE;
+  ** }
+  ** 
+  ** if (!context_getFlag (FLG_MUSTFREEONLY)) return TRUE;
+  */
   
-  ct = ctype_realType (sRef_getType (fref));
-
   DPRINTF (("Here: %s", ctype_unparse (ct)));
 
   if (!topLevel)
@@ -1483,7 +1545,7 @@ static bool
          return FALSE;
        }
       
-      if (/*! evs-2001-03-24 sRef_isAnyDefined (fref) || */
+      if (/*! evs-2002-03-24 sRef_isAnyDefined (fref) || */
          sRef_isDead (fref)
          || (sRef_isPdefined (fref) 
              && sRefSet_isEmpty (sRef_derivedFields (fref)))) 
@@ -1503,8 +1565,8 @@ static bool
       sRef fptr = sRef_constructDeadDeref (fref);
       bool res;
 
-      res = checkCompletelyDestroyed (fexp, fptr, FALSE, loc,
-                                     depth + 1, desc, hideErrors);
+      res = checkCompletelyDestroyed (fexp, fptr, FALSE, FALSE,
+                                     loc, depth + 1, desc, hideErrors);
       
       return res;
     }
@@ -1523,8 +1585,8 @@ static bool
        {
          sRef farr = sRef_constructDeadDeref (fref);
          
-         return (checkCompletelyDestroyed (fexp, farr, FALSE, loc, 
-                                           depth + 1, desc, hideErrors));
+         return (checkCompletelyDestroyed (fexp, farr, FALSE, FALSE,
+                                           loc, depth + 1, desc, hideErrors));
        }
     }
   else if (ctype_isStruct (ct))
@@ -1558,12 +1620,12 @@ static bool
              
              DPRINTF (("Check field: %s", sRef_unparseFull (field)));
 
-             isOk = (checkCompletelyDestroyed (fexp, field, FALSE, loc,
-                                               depth + 1, desc, hideErrors)
+             isOk = (checkCompletelyDestroyed (fexp, field, FALSE, TRUE,
+                                               loc, depth + 1, desc, hideErrors)
                      && isOk);
            } end_uentryList_elements;
        }
-
+      
       return isOk;
     }
   else
@@ -1573,7 +1635,7 @@ static bool
 }
 
 void
-checkReturnTransfer (exprNode fexp, uentry rval)
+transferChecks_return (exprNode fexp, uentry rval)
 {
   sRef uref = uentry_getSref (rval);
   sRef rref = sRef_makeNew (sRef_getType (uref), uref, cstring_undefined);
@@ -1595,7 +1657,7 @@ checkReturnTransfer (exprNode fexp, uentry rval)
     {
       if (stateClause_isGlobal (cl))
        {
-         ; /*@i32@*/
+         ; 
        }
       else if (stateClause_setsMetaState (cl))
        {
@@ -1633,7 +1695,6 @@ checkReturnTransfer (exprNode fexp, uentry rval)
                           exprNode_loc (fexp)))
                        {
                          sRef_showAliasInfo (sr); 
-                         /*@i32@*/
                        }
                    }
                }
@@ -1662,7 +1723,8 @@ checkReturnTransfer (exprNode fexp, uentry rval)
              DPRINTF (("el: %s / %s", sRef_unparse (el),
                        sRef_unparse (base)));
              
-             if (sRef_isResult (base))
+             if (sRef_isResult (base) 
+                 && !sRef_isDefinitelyNull (fref)) /* evans 2002-07-22: don't report allocation errors for null results */
                {
                  sRef sr = sRef_fixBase (el, fref);
                  
@@ -1716,6 +1778,7 @@ checkReturnTransfer (exprNode fexp, uentry rval)
     {
       (void) checkTransfer (fexp, exprNode_getSref (fexp),
                            exprNode_undefined, rref, 
+                           exprNode_undefined,
                            exprNode_loc (fexp), TT_FCNRETURN);
     }
 }
@@ -1798,8 +1861,8 @@ static void
 */
 
 void
-checkPassTransfer (exprNode fexp, uentry arg, bool isSpec,
-                  /*@dependent@*/ exprNode fcn, int argno, int totargs)
+transferChecks_passParam (exprNode fexp, uentry arg, bool isSpec,
+                         /*@dependent@*/ exprNode fcn, int argno, int totargs)
 {
   sRef tref = uentry_getSref (arg);
   sRef fref = exprNode_getSref (fexp);
@@ -1887,8 +1950,8 @@ checkPassTransfer (exprNode fexp, uentry arg, bool isSpec,
            }
        }
       
-      (void) checkCompletelyDestroyed (fexp, fref, TRUE, exprNode_loc (fexp),
-                                      0, DSC_PARAM, FALSE);
+      (void) checkCompletelyDestroyed (fexp, fref, TRUE, FALSE,
+                                      exprNode_loc (fexp), 0, DSC_PARAM, FALSE);
 
       /* make it defined now, so checkTransfer is okay */
       sRef_setDefined (fref, exprNode_loc (fexp)); 
@@ -2105,13 +2168,14 @@ checkPassTransfer (exprNode fexp, uentry arg, bool isSpec,
        
        {
          voptgenerror 
-           (FLG_MUSTFREE,
+           (FLG_MUSTFREEFRESH,
             message ("New fresh storage %q(type %s) passed as %s (not released): %s",
                      sRef_unparseOpt (fref),
                      ctype_unparse (sRef_getType (fref)),
                      alkind_unparse (sRef_getAliasKind (tref)),
                      exprNode_unparse (fexp)),
             exprNode_loc (fexp));
+
          DPRINTF (("Fresh: %s", sRef_unparseFull (fref)));
        }
       else 
@@ -2123,7 +2187,7 @@ checkPassTransfer (exprNode fexp, uentry arg, bool isSpec,
              if (!alkind_isError (ak))
                {
                  voptgenerror 
-                   (FLG_MUSTFREE,
+                   (FLG_MUSTFREEFRESH,
                     message ("New reference %q(type %s) passed as %s (not released): %s",
                              sRef_unparseOpt (fref),
                              ctype_unparse (sRef_getType (fref)),
@@ -2137,6 +2201,7 @@ checkPassTransfer (exprNode fexp, uentry arg, bool isSpec,
   
   (void) checkTransfer (fexp, exprNode_getSref (fexp),
                        exprNode_undefined, tref,
+                       fcn,
                        exprNode_loc (fexp), TT_FCNPASS);
 
   setCodePoint ();
@@ -2171,7 +2236,10 @@ checkPassTransfer (exprNode fexp, uentry arg, bool isSpec,
          sRef_clearDerived (base);
          sRef_setDefined (base, exprNode_loc (fexp));
          usymtab_clearAlias (base);
-         sRef_setNullUnknown (base, exprNode_loc (fexp));
+         /* evans 2004-07-31: Don't change state of constants! */
+         if (!sRef_isConst (base)) {
+           sRef_setNullUnknown (base, exprNode_loc (fexp));
+         }
        }
     }
 
@@ -2199,19 +2267,19 @@ checkPassTransfer (exprNode fexp, uentry arg, bool isSpec,
 }
 
 void
-checkGlobReturn (uentry glob)
+transferChecks_globalReturn (uentry glob)
 {
   sRef_protectDerivs ();
   checkGlobTrans (glob, TT_GLOBRETURN);
   sRef_clearProtectDerivs ();
 }
 
-void checkParamReturn (uentry actual)
+void transferChecks_paramReturn (uentry actual)
 {
   checkLeaveTrans (actual, TT_PARAMRETURN);
 }
 
-void checkLoseRef (uentry actual)
+void transferChecks_loseReference (uentry actual)
 {
   checkLeaveTrans (actual, TT_LEAVETRANS);
 }
@@ -2251,8 +2319,11 @@ static void
 checkGlobTrans (uentry glob, transferKind type)
 {
   sRef eref = uentry_getOrigSref (glob);
-  
-  (void) checkCompletelyDefined (exprNode_undefined, uentry_getSref (glob), uentry_getSref (glob),
+  DPRINTF (("Completely defined: %s", uentry_unparseFull (glob)));
+
+  (void) checkCompletelyDefined (exprNode_undefined, uentry_getSref (glob), 
+                                uentry_getSref (glob),
                                 exprNode_undefined, eref, 
                                 TRUE, FALSE, FALSE,
                                 g_currentloc, type, 0, TRUE);
@@ -2278,7 +2349,7 @@ static void checkStructTransfer (exprNode lhs, sRef slhs, exprNode rhs, sRef srh
   if (ctype_isSU (st) && ctype_isRealSU (sRef_getType (slhs))
       && ctype_match (sRef_getType (slhs), st))
     {
-      if (tt == TT_DOASSIGN && sRef_isStateDefined (srhs))
+      if ((tt == TT_DOASSIGN || tt == TT_FIELDASSIGN) && sRef_isStateDefined (srhs))
        {
          sRef_setDefinedComplete (slhs, loc);
        }
@@ -2294,66 +2365,76 @@ static void checkStructTransfer (exprNode lhs, sRef slhs, exprNode rhs, sRef srh
          if (sRef_isLocalVar (slhs)
              && sRef_isFileOrGlobalScope (sRef_getRootBase (srhs)))
            {
+             DPRINTF (("Global scope!"));
              sRef_setDependent (slhs, exprNode_loc (lhs));
            }
-         else
-           {
-             if (ctype_isUnion (st))
-               {
-                 sRef_setDefState (slhs, sRef_getDefState (srhs), 
-                                   exprNode_loc (lhs));
+       }
 
-                 sRefSet_realElements (sRef_derivedFields (srhs), sr)
-                   {
-                     if (sRef_isField (sr))
-                       {
-                         cstring fieldname = sRef_getField (sr);
-                         sRef lfld = sRef_makeField (slhs, fieldname);
+      /*
+      ** evans 2003-07-10: should always copy the fields!
+      */
 
-                         (void) checkTransfer (rhs, sr, lhs, lfld, 
-                                               exprNode_loc (lhs), tt);
-                       }
-                   } end_sRefSet_realElements ;
-               }
-             else
+      if (ctype_isUnion (st))
+       {
+         sRef_setDefState (slhs, sRef_getDefState (srhs), 
+                           exprNode_loc (lhs));
+         
+         sRefSet_realElements (sRef_derivedFields (srhs), sr)
+           {
+             if (sRef_isField (sr))
                {
-                 uentryList fields = ctype_getFields (st);
+                 cstring fieldname = sRef_getField (sr);
+                 sRef lfld = sRef_makeField (slhs, fieldname);
                  
-                 uentryList_elements (fields, field)
-                   {
-                     sRef rfld = sRef_makeField (srhs, uentry_rawName (field));
-                     sRef lfld = sRef_makeField (slhs, uentry_rawName (field));
-                     (void) checkTransfer (rhs, rfld, lhs, lfld, exprNode_loc (lhs), tt);
-                   } end_uentryList_elements ;
-               }
-
-             if (sRef_isOnly (srhs))
-               {
-                 sRef_setKeptComplete (srhs, loc);
+                 (void) checkTransfer (rhs, sr, lhs, lfld, 
+                                       exprNode_undefined,
+                                       exprNode_loc (lhs), tt);
                }
-           }
+           } end_sRefSet_realElements ;
+       }
+      else
+       {
+         uentryList fields = ctype_getFields (st);
+         
+         uentryList_elements (fields, field)
+           {
+             sRef rfld = sRef_makeField (srhs, uentry_rawName (field));
+             sRef lfld = sRef_makeField (slhs, uentry_rawName (field));
+             DPRINTF (("Transfer field: %s := %s", 
+                       sRef_unparse (lfld), sRef_unparse (rfld)));
+             (void) checkTransfer (rhs, rfld, lhs, lfld, 
+                                   exprNode_undefined,
+                                   exprNode_loc (lhs), tt);
+           } end_uentryList_elements ;
+       }
+      
+      if (sRef_isOnly (srhs))
+       {
+         sRef_setKeptComplete (srhs, loc);
        }
     }
 }
 
 void
-checkInitTransfer (exprNode lhs, exprNode rhs)
+transferChecks_initialization (exprNode lhs, exprNode rhs)
 {
   sRef slhs = exprNode_getSref (lhs);
   
   if (sRef_isFileOrGlobalScope (slhs) || (!sRef_isCvar (slhs)))
     {
       (void) checkTransfer (rhs, exprNode_getSref (rhs), 
-                           lhs, slhs, exprNode_loc (rhs), TT_GLOBINIT);
+                           lhs, slhs, 
+                           exprNode_undefined,
+                           exprNode_loc (rhs), TT_GLOBINIT);
     }
   else
     {
-      checkAssignTransfer (lhs, rhs);
+      transferChecks_assign (lhs, rhs);
     }
 }
 
 void
-checkAssignTransfer (exprNode lhs, exprNode rhs)
+transferChecks_assign (exprNode lhs, exprNode rhs)
 {
   sRef slhs = exprNode_getSref (lhs);
   sRef srhs = exprNode_getSref (rhs);
@@ -2367,6 +2448,8 @@ checkAssignTransfer (exprNode lhs, exprNode rhs)
 
   if (ctype_isRealSU (sRef_getType (srhs)))
     {
+      DPRINTF (("Check struct transfer: %s := %s", exprNode_unparse (lhs),
+               exprNode_unparse (rhs)));
       checkStructTransfer (lhs, slhs, rhs, srhs, exprNode_loc (lhs), TT_FIELDASSIGN);
     }
   else
@@ -2374,6 +2457,7 @@ checkAssignTransfer (exprNode lhs, exprNode rhs)
       DPRINTF (("lhs: %s", sRef_unparseFull (slhs)));
       DPRINTF (("rhs: %s", sRef_unparseFull (srhs)));
       (void) checkTransfer (rhs, srhs, lhs, slhs, 
+                           exprNode_undefined,
                            exprNode_loc (lhs), TT_DOASSIGN);
       DPRINTF (("lhs: %s", sRef_unparseFull (slhs)));
       DPRINTF (("rhs: %s", sRef_unparseFull (srhs)));
@@ -2423,6 +2507,8 @@ checkTransferNullAux (sRef fref, exprNode fexp, /*@unused@*/ bool ffix,
   alkind tkind = sRef_getAliasKind (tref);
   ctype ttyp = ctype_realType (sRef_getType (tref));
 
+  DPRINTF (("Null transfer: %s => %s", sRef_unparseFull (fref), sRef_unparseFull (tref)));
+
   if (ctype_isUnknown (ttyp))
     {
       ttyp = exprNode_getType (texp);
@@ -2460,7 +2546,7 @@ checkTransferNullAux (sRef fref, exprNode fexp, /*@unused@*/ bool ffix,
              if (sRef_isNotNull (tref))
                {
                  if (optgenerror
-                     (FLG_SYNTAX, /*@i432 kuldge flag... */
+                     (FLG_NULLINIT, /* kuldge flag... */
                       message ("%s %q initialized to %s value: %q",
                                sRef_getScopeName (tref),
                                sRef_unparse (tref),
@@ -2542,83 +2628,82 @@ checkTransferAssignAux (sRef fref, exprNode fexp, /*@unused@*/ bool ffix,
       && !(sRef_same (fref, tref)) /* okay to assign to self (returned params) */
       && !(usymtab_isDefinitelyNull (tref))) 
     {
-      if (context_getFlag (FLG_MUSTFREE))
+      if (transferChecks_canLoseReference (tref, loc))
        {
-         if (canLoseReference (tref, loc))
+         ; /* no error */
+       }
+      else
+       {
+         flagcode flg = sRef_isFresh (tref) ? FLG_MUSTFREEFRESH : FLG_MUSTFREEONLY;
+
+         if (sRef_hasLastReference (tref))
            {
-             ; /* no error */
+             if (optgenerror 
+                 (flg,
+                  message ("Last reference %q to %s storage %q(type %s) not released "
+                           "before assignment: %q",
+                           sRef_unparse (tref),
+                           alkind_unparse (tkind),
+                           sRef_unparseOpt (sRef_getAliasInfoRef (tref)),
+                           ctype_unparse (sRef_getType (tref)),
+                           generateText (fexp, texp, tref, transferType)),
+                  loc))
+               {
+                 sRef_showRefLost (tref);
+               }
            }
          else
            {
-             if (sRef_hasLastReference (tref))
+             if (context_inGlobalScope ())
                {
-                 if (optgenerror 
-                     (FLG_MUSTFREE,
-                      message ("Last reference %q to %s storage %q(type %s) not released "
-                               "before assignment: %q",
-                               sRef_unparse (tref),
-                               alkind_unparse (tkind),
-                               sRef_unparseOpt (sRef_getAliasInfoRef (tref)),
-                               ctype_unparse (sRef_getType (tref)),
-                               generateText (fexp, texp, tref, transferType)),
-                      loc))
-                   {
-                     sRef_showRefLost (tref);
-                   }
+                 /* no errors for static initializations */
                }
-             else
+             else 
                {
-                 if (context_inGlobalScope ())
-                   {
-                     /* no errors for static initializations */
-                   }
-                 else 
+                 /*
+                 ** don't report this error for a[i], since it could
+                 ** be a new element.
+                 */
+                 
+                 if (alkind_isNewRef (tkind))
                    {
-                     /*
-                      ** don't report this error for a[i], since it could
-                      ** be a new element.
-                      */
-                     
-                     if (alkind_isNewRef (tkind))
-                       {
-                         if (optgenerror 
-                             (FLG_MUSTFREE,
-                              message 
-                              ("%q %q(type %s) not released before assignment: %q",
-                               cstring_makeLiteral
-                               (alkind_isKillRef (sRef_getOrigAliasKind (tref))
-                                ? "Kill reference parameter" : "New reference"),
-                               sRef_unparseOpt (tref),
-                               ctype_unparse (sRef_getType (tref)),
-                               generateText (fexp, texp, tref, transferType)),
-                              loc))
-                           {
-                             sRef_showAliasInfo (tref);
-                             sRef_setAliasKind (tref, AK_ERROR, loc);
-                           }
-                       }
-                     else if
-                       (!(sRef_isUnknownArrayFetch (tref)
-                          && !context_getFlag (FLG_STRICTDESTROY))
-                        && !sRef_isUnionField (tref)
-                        && !sRef_isRelDef (tref)
-                        && optgenerror 
-                        (FLG_MUSTFREE,
-                         message 
-                         ("%s storage %q(type %s) not released before assignment: %q",
-                          alkind_capName (tkind),
-                          sRef_unparseOpt (tref),
-                          ctype_unparse (sRef_getType (tref)),
-                          generateText (fexp, texp, tref, transferType)),
-                         loc))
-                         {
-                           sRef_showAliasInfo (tref);
-                         }
-                     else
+                     if (optgenerror 
+                         (flg,
+                          message 
+                          ("%q %q(type %s) not released before assignment: %q",
+                           cstring_makeLiteral
+                           (alkind_isKillRef (sRef_getOrigAliasKind (tref))
+                            ? "Kill reference parameter" : "New reference"),
+                           sRef_unparseOpt (tref),
+                           ctype_unparse (sRef_getType (tref)),
+                           generateText (fexp, texp, tref, transferType)),
+                          loc))
                        {
-                         ;
+                         sRef_showAliasInfo (tref);
+                         sRef_setAliasKind (tref, AK_ERROR, loc);
                        }
                    }
+                 else if
+                   (!(sRef_isUnknownArrayFetch (tref)
+                      && !context_getFlag (FLG_STRICTDESTROY))
+                    && !sRef_isUnionField (tref)
+                    && !sRef_isRelDef (tref)
+                    && optgenerror 
+                    (flg,
+                     message 
+                     ("%s storage %q(type %s) not released before assignment: %q",
+                      alkind_capName (tkind),
+                      sRef_unparseOpt (tref),
+                      ctype_unparse (sRef_getType (tref)),
+                      generateText (fexp, texp, tref, transferType)),
+                     loc))
+                   {
+                     sRef_showAliasInfo (tref);
+                   }
+                 else
+                   {
+                     ;
+                   }
                }
            }
        }
@@ -2677,6 +2762,8 @@ checkTransferAssignAux (sRef fref, exprNode fexp, /*@unused@*/ bool ffix,
            }
        }
     }
+
+  DPRINTF (("Transfer ==> %s", sRef_unparseFull (tref)));
 }
 
 /*
@@ -3276,7 +3363,9 @@ checkTransferExposure (sRef fref, exprNode fexp, /*@unused@*/ bool ffix,
              ;
            }
        }
-      else if (transferType == TT_DOASSIGN)
+      else if (transferType == TT_DOASSIGN
+              /* evans 2001-10-05: added TT_FIELDASSIGN: */
+              || transferType == TT_FIELDASSIGN)
        {
          if (!(sRef_isExposed (tref) 
                || !sRef_isCvar (tref)
@@ -3335,6 +3424,12 @@ checkTransferAux (exprNode fexp, /*@exposed@*/ sRef fref, bool ffix,
   bool isfcnpass = (transferType == TT_FCNPASS);
   bool isfcnreturn = (transferType == TT_FCNRETURN);
 
+  DPRINTF (("Check transfer: %s [%s] => %s [%s]",
+           exprNode_unparse (fexp),
+           sRef_unparseFull (fref),
+           exprNode_unparse (texp),
+           sRef_unparseFull (tref)));
+
   setCodePoint ();
 
   if (!ffix && !tfix)
@@ -3342,6 +3437,7 @@ checkTransferAux (exprNode fexp, /*@exposed@*/ sRef fref, bool ffix,
       setCodePoint ();
       checkTransferNullAux (fref, fexp, ffix, tref, texp, tfix, 
                            loc, transferType);
+      DPRINTF (("Transfer ==> %s", sRef_unparseFull (fref)));
     }
 
   if (isassign)
@@ -3349,6 +3445,7 @@ checkTransferAux (exprNode fexp, /*@exposed@*/ sRef fref, bool ffix,
       setCodePoint ();
       checkTransferAssignAux (fref, fexp, ffix, tref, texp, tfix,
                              loc, transferType);
+      DPRINTF (("Transfer ==> %s", sRef_unparseFull (fref)));
     }
 
   /*
@@ -3823,7 +3920,7 @@ checkTransferAux (exprNode fexp, /*@exposed@*/ sRef fref, bool ffix,
              && ctype_isMutable (exprNode_getType (fexp))
              && (!iseitherassign || sRef_isReference (tref)))
            {
-             if (canLoseReference (fref, loc))
+             if (transferChecks_canLoseReference (fref, loc))
                {
                  ;
                }
@@ -3900,6 +3997,8 @@ checkTransferAux (exprNode fexp, /*@exposed@*/ sRef fref, bool ffix,
       ;
     }
 
+  DPRINTF (("Transfer ==> %s", sRef_unparseFull (fref)));
+  DPRINTF (("Transfer ==> %s", sRef_unparseFull (tref)));
   setCodePoint ();
 }
 
@@ -3942,7 +4041,6 @@ checkMetaStateConsistent (/*@exposed@*/ sRef fref, sRef tref,
          }
        else
          {
-           /*@i#!@!!@*/
            DPRINTF (("Cannot find meta state for: %s / to: %s / %s", sRef_unparseFull (fref),
                      sRef_unparseFull (tref),
                      fkey));
@@ -3956,36 +4054,102 @@ checkMetaStateConsistent (/*@exposed@*/ sRef fref, sRef tref,
          {
            ;
          }
-       else if (!stateValue_sameValue (fval, tval))
+       else if (sRef_isDefinitelyNull (fref)
+                || usymtab_isDefinitelyNull (fref))
          {
-           DPRINTF (("Check: %s / %s / %s / %s", fkey,
-                     metaStateInfo_unparse (minfo),
-                     stateValue_unparse (fval),
-                     stateValue_unparse (tval)));
+           ; /* No errors for null values in state transfers. */
+         }
+       
+       else
+         {
+           stateCombinationTable sctable = metaStateInfo_getTransferTable (minfo);
+           cstring msg = cstring_undefined;
+           int nval = stateCombinationTable_lookup (sctable, 
+                                                    stateValue_getValue (fval), 
+                                                    stateValue_getValue (tval), 
+                                                    &msg);
            
-           if (sRef_isDefinitelyNull (fref)
-               || usymtab_isDefinitelyNull (fref))
+           if (nval == stateValue_error)
              {
-               ; /* No errors for null values in state transfers. */
-             }
-           else
-             {
-               if (optgenerror 
-                   (FLG_STATETRANSFER,
-                    message
-                    ("Invalid transfer from %q %x to %q",
-                     stateValue_unparseValue (fval, minfo),
-                     sRef_unparse (fref),
-                     stateValue_unparseValue (tval, minfo)),
-                    loc))
+               if (transferType == TT_LEAVETRANS)
+                 {
+                   BADBRANCH;
+                 }
+               else if (transferType == TT_GLOBRETURN)
+                 {
+                   if (optgenerror 
+                       (FLG_STATETRANSFER,
+                        message
+                        ("Function returns with global %q in inconsistent state (%q is %q, should be %q)%q",
+                         sRef_unparse (sRef_getRootBase (fref)),
+                         sRef_unparse (fref),
+                         stateValue_unparseValue (fval, minfo),
+                         stateValue_unparseValue (tval, minfo),
+                         cstring_isDefined (msg) 
+                         ? message (": %s", msg) : cstring_undefined),
+                        loc))
+                     {
+                       sRef_showMetaStateInfo (fref, fkey);
+                     }             
+                 }
+               else if (transferType == TT_GLOBPASS)
+                 {
+                   if (optgenerror 
+                       (FLG_STATETRANSFER,
+                        message
+                        ("Function called with global %q in inconsistent state (%q is %q, should be %q)%q",
+                         sRef_unparse (sRef_getRootBase (fref)),
+                         stateValue_unparseValue (fval, minfo),
+                         sRef_unparse (fref),
+                         stateValue_unparseValue (tval, minfo),
+                         cstring_isDefined (msg) 
+                         ? message (": %s", msg) : cstring_undefined),
+                        loc))
+                     {
+                       sRef_showMetaStateInfo (fref, fkey);
+                     }             
+                 }
+               else if (transferType == TT_PARAMRETURN)
                  {
-                   sRef_showMetaStateInfo (fref, fkey);
+                   if (optgenerror 
+                       (FLG_STATETRANSFER,
+                        message
+                        ("Function returns with parameter %q in inconsistent state (%q is %q, should be %q)%q",
+                         sRef_unparse (sRef_getRootBase (fref)),
+                         sRef_unparse (fref),                  
+                         stateValue_unparseValue (fval, minfo),
+                         stateValue_unparseValue (tval, minfo),
+                         cstring_isDefined (msg) 
+                         ? message (": %s", msg) : cstring_undefined),
+                        loc))
+                     {
+                       sRef_showMetaStateInfo (fref, fkey);
+                     }
                  }
+               else
+                 {
+                   if (optgenerror 
+                       (FLG_STATETRANSFER,
+                        message
+                        ("Invalid transfer from %q %x to %q (%q)%q",
+                         stateValue_unparseValue (fval, minfo),
+                         sRef_unparse (fref),
+                         stateValue_unparseValue (tval, minfo),
+                         sRef_unparse (tref),
+                         cstring_isDefined (msg) 
+                         ? message (": %s", msg) : cstring_undefined),
+                        loc))
+                     {
+                       sRef_showMetaStateInfo (fref, fkey);
+                     }
+                 }
+
+             }
+                   
+           if (stateValue_getValue (fval) != nval)
+             {
+               stateValue_updateValueLoc (fval, nval, loc);
              }
-         }
-       else
-         {
-           ; /* Match okay */
          }
       }
     
@@ -3996,13 +4160,14 @@ checkMetaStateConsistent (/*@exposed@*/ sRef fref, sRef tref,
 
 static void
 checkMetaStateTransfer (exprNode fexp, sRef fref, exprNode texp, sRef tref, 
-                       fileloc loc, transferKind /*@i32@*/ transferType)
+                       exprNode fcn,
+                       fileloc loc, transferKind transferType)
 {
   valueTable fvalues = sRef_getValueTable (fref);
   valueTable tvalues = sRef_getValueTable (tref);
 
   DPRINTF (("Metastate transfer: from %s", exprNode_unparse (fexp)));
-
+  
   DPRINTF (("Metastate transfer: %s => %s",
            sRef_unparseFull (fref),
            sRef_unparseFull (tref)));
@@ -4034,7 +4199,6 @@ checkMetaStateTransfer (exprNode fexp, sRef fref, exprNode texp, sRef tref,
          }
        else
          {
-           /*@i#!@!!@*/
            DPRINTF (("Metastate transfer: %s => %s",
                      exprNode_unparse (fexp), exprNode_unparse (texp)));
            DPRINTF (("Cannot find meta state for: %s / to: %s / %s", sRef_unparseFull (fref),
@@ -4046,10 +4210,28 @@ checkMetaStateTransfer (exprNode fexp, sRef fref, exprNode texp, sRef tref,
       {
        llassert (metaStateInfo_isDefined (minfo));
        
-       if (stateValue_isError (fval) || stateValue_isError (tval))
+       if (stateValue_isError (fval))
          {
            ;
          }
+       else if (stateValue_isError (tval))
+         {
+           if (sRef_isLocalVar (tref) && transferType == TT_DOASSIGN)
+             {
+               /* Local assignments just replace state. */
+               stateValue_updateValueLoc (tval, stateValue_getValue (fval), loc);
+               DPRINTF (("Update: %s", stateValue_unparse (tval)));
+             }
+           else if (transferType == TT_FCNRETURN)
+             {
+               ; /* Returning from an unannotated function */
+             }
+           else
+             {
+               DPRINTF (("Transfer to error: %s / %s", sRef_unparseFull (tref),
+                         transferType_unparse (transferType)));
+             }
+         }
        else 
          {
            DPRINTF (("Check: %s / %s / %s / %s", fkey,
@@ -4070,25 +4252,26 @@ checkMetaStateTransfer (exprNode fexp, sRef fref, exprNode texp, sRef tref,
                /* Local assignments just replace state. */
                DPRINTF (("No transfer error assigning to local: %s", msg));
                stateValue_updateValueLoc (tval, stateValue_getValue (fval), loc);
+               DPRINTF (("Update: %s", stateValue_unparse (tval)));
              }
            else
              {
-               if (cstring_isDefined (msg)) 
+               if (nval == stateValue_error)
                  {
-                   /*@i32 print extra info for assignments@*/
-                   
                    if (optgenerror 
                        (FLG_STATETRANSFER,
                         message
-                        ("Invalid transfer from %q %x to %q (%s): %q",
+                        ("Invalid transfer from %q %x to %q%q: %q",
                          stateValue_unparseValue (fval, minfo),
                          sRef_unparse (fref),
                          stateValue_unparseValue (tval, minfo),
-                         msg,
-                         transferErrorExcerpt (transferType, fexp, texp)),
+                         cstring_isDefined (msg) 
+                         ? message (" (%s)", msg) : cstring_undefined,
+                         transferErrorExcerpt (transferType, fexp, texp, fcn)),
                         loc))
                      {
                        sRef_showMetaStateInfo (fref, fkey);
+                       sRef_showMetaStateInfo (tref, fkey);
                      }
                    else
                      {
@@ -4133,6 +4316,7 @@ checkMetaStateTransfer (exprNode fexp, sRef fref, exprNode texp, sRef tref,
 static void
 checkTransfer (exprNode fexp, /*@dependent@*/ sRef fref, 
               exprNode texp, /*@dependent@*/ sRef tref, 
+              exprNode fcn,
               fileloc loc, transferKind transferType)
 {
   setCodePoint ();
@@ -4149,7 +4333,8 @@ checkTransfer (exprNode fexp, /*@dependent@*/ sRef fref,
            exprNode_unparse (fexp),
            exprNode_unparse (texp)));
 
-  checkMetaStateTransfer (fexp, fref, texp, tref, loc, transferType);
+  checkMetaStateTransfer (fexp, fref, texp, tref, fcn,
+                         loc, transferType);
 
   /*
   ** for local references, we need to check
@@ -4280,11 +4465,13 @@ static /*@exposed@*/ sRef
   return sRef_undefined;
 }
 
-bool canLoseReference (/*@dependent@*/ sRef sr, fileloc loc)
+bool transferChecks_canLoseReference (/*@dependent@*/ sRef sr, fileloc loc)
 {
   bool gotone = FALSE;
   sRefSet ab = usymtab_aliasedBy (sr); /* yes, really mean aliasedBy */
-    
+
+  DPRINTF (("Aliased by: %s", sRefSet_unparse (ab)));
+
   /*
   ** if there is a local variable that aliases sr, then there is no
   ** error.  Make the local an only.
This page took 0.089104 seconds and 4 git commands to generate.