X-Git-Url: http://andersk.mit.edu/gitweb/splint.git/blobdiff_plain/da4500ed12e4d54281bf2ae98af0bf598b236657..5b99bfd6792ab9229bb5b1d9048833d21b22ecef:/src/transferChecks.c diff --git a/src/transferChecks.c b/src/transferChecks.c index 6aaad39..7a22b2a 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-2003 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; @@ -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 (); @@ -2199,19 +2264,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 +2316,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 +2346,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 +2362,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 +2445,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 +2454,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))); @@ -2460,7 +2541,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 +2623,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)) + { + ; /* no error */ + } + else { - if (canLoseReference (tref, loc)) + 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 + { + ; + } } } } @@ -3276,7 +3356,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 +3417,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) @@ -3823,7 +3911,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)) { ; } @@ -3942,7 +4030,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 +4043,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) { - sRef_showMetaStateInfo (fref, fkey); + 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) + { + 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 +4149,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 +4188,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), @@ -4055,7 +4208,6 @@ checkMetaStateTransfer (exprNode fexp, sRef fref, exprNode texp, sRef tref, if (sRef_isLocalVar (tref) && transferType == TT_DOASSIGN) { /* 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))); } @@ -4065,8 +4217,8 @@ checkMetaStateTransfer (exprNode fexp, sRef fref, exprNode texp, sRef tref, } else { - TPRINTF (("Transfer to error: %s", sRef_unparseFull (tref))); - BADBRANCH; + DPRINTF (("Transfer to error: %s / %s", sRef_unparseFull (tref), + transferType_unparse (transferType))); } } else @@ -4093,22 +4245,22 @@ 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 { @@ -4153,6 +4305,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 (); @@ -4169,7 +4322,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 @@ -4300,11 +4454,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.