X-Git-Url: http://andersk.mit.edu/gitweb/splint.git/blobdiff_plain/cd7d9b17c558f5857f07f55865d5378fd1ad7c41..508533c52d02429894d89b95224577d8e3cf3c48:/src/transferChecks.c diff --git a/src/transferChecks.c b/src/transferChecks.c index bac3b5f..4efa027 100644 --- a/src/transferChecks.c +++ b/src/transferChecks.c @@ -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-2002 University of Virginia, ** Massachusetts Institute of Technology ** ** This program is free software; you can redistribute it and/or modify it @@ -17,18 +17,32 @@ ** 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; @@ -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 */ } @@ -752,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); } @@ -871,10 +896,8 @@ checkCompletelyDefined (exprNode fexp, /*@exposed@*/ sRef fref, sRef ofref, { sRef rb = sRef_getRootBase (fref); sRef_showStateInfo (fref); - - DPRINTF (("fref: %s", sRef_unparseFull (fref))); - DPRINTF (("rb: %s", sRef_unparseFull (rb))); - sRef_setDefinedComplete (rb, loc); + + sRef_setDefinedCompleteDirect (rb, loc); } } } @@ -1196,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) @@ -1254,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)) @@ -1273,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))); @@ -1289,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) { @@ -1357,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) @@ -1491,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)))) @@ -1511,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; } @@ -1531,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)) @@ -1566,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 @@ -1581,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); @@ -1670,7 +1724,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); @@ -1724,6 +1779,7 @@ checkReturnTransfer (exprNode fexp, uentry rval) { (void) checkTransfer (fexp, exprNode_getSref (fexp), exprNode_undefined, rref, + exprNode_undefined, exprNode_loc (fexp), TT_FCNRETURN); } } @@ -1806,8 +1862,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); @@ -1895,8 +1951,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)); @@ -2113,13 +2169,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 @@ -2131,7 +2188,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)), @@ -2145,6 +2202,7 @@ checkPassTransfer (exprNode fexp, uentry arg, bool isSpec, (void) checkTransfer (fexp, exprNode_getSref (fexp), exprNode_undefined, tref, + fcn, exprNode_loc (fexp), TT_FCNPASS); setCodePoint (); @@ -2207,19 +2265,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); } @@ -2259,8 +2317,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); @@ -2319,6 +2380,7 @@ static void checkStructTransfer (exprNode lhs, sRef slhs, exprNode rhs, sRef srh sRef lfld = sRef_makeField (slhs, fieldname); (void) checkTransfer (rhs, sr, lhs, lfld, + exprNode_undefined, exprNode_loc (lhs), tt); } } end_sRefSet_realElements ; @@ -2331,7 +2393,9 @@ static void checkStructTransfer (exprNode lhs, sRef slhs, exprNode rhs, sRef srh { 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); + (void) checkTransfer (rhs, rfld, lhs, lfld, + exprNode_undefined, + exprNode_loc (lhs), tt); } end_uentryList_elements ; } @@ -2345,23 +2409,25 @@ static void checkStructTransfer (exprNode lhs, sRef slhs, exprNode rhs, sRef srh } 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); @@ -2382,6 +2448,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))); @@ -2550,83 +2617,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 + { + ; + } } } } @@ -3284,7 +3350,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) @@ -3831,7 +3899,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)) { ; } @@ -3964,36 +4032,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)) - { - ; /* No errors for null values in state transfers. */ - } - else + if (nval == stateValue_error) { - 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) { - sRef_showMetaStateInfo (fref, fkey); + 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) + { + 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 */ } } @@ -4004,6 +4138,7 @@ checkMetaStateConsistent (/*@exposed@*/ sRef fref, sRef tref, static void checkMetaStateTransfer (exprNode fexp, sRef fref, exprNode texp, sRef tref, + exprNode fcn, fileloc loc, transferKind /*@i32@*/ transferType) { valueTable fvalues = sRef_getValueTable (fref); @@ -4100,22 +4235,24 @@ checkMetaStateTransfer (exprNode fexp, sRef fref, exprNode texp, sRef tref, } 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 { @@ -4160,6 +4297,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 (); @@ -4176,7 +4314,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 @@ -4307,7 +4446,7 @@ 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 */