X-Git-Url: http://andersk.mit.edu/gitweb/splint.git/blobdiff_plain/990ec8680b4718e26f8774a8f2ccff44fb97b3c5..419f7a7a4b388dfc03c75bebaffcf97116ea0410:/src/exprNode.c diff --git a/src/exprNode.c b/src/exprNode.c index 0970500..9ddccbe 100644 --- a/src/exprNode.c +++ b/src/exprNode.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,28 +17,31 @@ ** 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 */ /* ** exprNode.c */ # include /* for isdigit */ -# include "lclintMacros.nf" +# include "splintMacros.nf" # include "basic.h" # include "cgrammar.h" +# include "cscanner.h" +# include "cscannerHelp.h" # include "cgrammar_tokens.h" # include "exprChecks.h" # include "transferChecks.h" # include "exprNodeSList.h" +static bool exprNode_sameStorage (exprNode p_e1, exprNode p_e2) /*@*/ ; static bool exprNode_isEmptyStatement (exprNode p_e); static /*@exposed@*/ exprNode exprNode_firstStatement (/*@returned@*/ exprNode p_e); static bool exprNode_isFalseConstant (exprNode p_e) /*@*/ ; -static bool exprNode_isBlock (exprNode p_e); +static bool exprNode_isStatement (exprNode p_e); static void checkGlobUse (uentry p_glob, bool p_isCall, /*@notnull@*/ exprNode p_e); static void exprNode_addUse (exprNode p_e, /*@exposed@*/ sRef p_s); static bool exprNode_matchArgType (ctype p_ct, exprNode p_e); @@ -49,9 +52,10 @@ static void checkUniqueParams (exprNode p_fcn, /*@notnull@*/ exprNode p_current, exprNodeList p_args, int p_paramno, uentry p_ucurrent); static void updateAliases (/*@notnull@*/ exprNode p_e1, /*@notnull@*/ exprNode p_e2); -static void abstractOpError (ctype p_tr1, ctype p_tr2, lltok p_op, +static bool abstractOpError (ctype p_tr1, ctype p_tr2, lltok p_op, /*@notnull@*/ exprNode p_e1, /*@notnull@*/ exprNode p_e2, - fileloc p_loc1, fileloc p_loc2); + fileloc p_loc1, fileloc p_loc2) + /*@modifies g_warningstream@*/ ; static ctype checkNumerics (ctype p_tr1, ctype p_tr2, ctype p_te1, ctype p_te2, /*@notnull@*/ exprNode p_e1, /*@notnull@*/ exprNode p_e2, lltok p_op); static void doAssign (/*@notnull@*/ exprNode p_e1, /*@notnull@*/ exprNode p_e2, bool p_isInit); @@ -81,8 +85,7 @@ static /*@observer@*/ cstring exprNode_rootVarName (exprNode p_e); static /*@exposed@*/ exprNode exprNode_lastStatement (/*@returned@*/ exprNode p_e); -static /*@null@*/ sRef defref = sRef_undefined; -static /*@only@*/ exprNode mustExitNode = exprNode_undefined; +static /*@only@*/ exprNode s_mustExitNode = exprNode_undefined; static int checkArgsReal (uentry p_fcn, /*@dependent@*/ exprNode p_f, uentryList p_cl, @@ -105,16 +108,20 @@ static ctype ctypeType; static ctype filelocType; static bool initMod = FALSE; -static void exprNode_defineConstraints(/*@sef@*/ /*@special@*/ /*@notnull@*/ exprNode p_e) - /*@defines p_e->requiresConstraints, p_e->ensuresConstraints, p_e->trueEnsuresConstraints, p_e->falseEnsuresConstraints @*/ - ; - -# define exprNode_defineConstraints(e) \ -do{ (e)->requiresConstraints = constraintList_makeNew(); \ - (e)->ensuresConstraints = constraintList_makeNew(); \ - (e)->trueEnsuresConstraints = constraintList_makeNew(); \ - (e)->falseEnsuresConstraints = constraintList_makeNew(); } while(FALSE) +/*@function void exprNode_swap (sef exprNode, sef exprNode)@*/ +/*@-macroassign@*/ +# define exprNode_swap(e1,e2) do { exprNode m_tmp = (e1); (e1) = (e2); (e2) = m_tmp; } while (FALSE) +/*@=macroassign@*/ +static void exprNode_defineConstraints(/*@sef@*/ /*@special@*/ /*@notnull@*/ exprNode e) + /*@defines e->requiresConstraints, e->ensuresConstraints, + e->trueEnsuresConstraints, e->falseEnsuresConstraints @*/ +{ + e->requiresConstraints = constraintList_makeNew (); + e->ensuresConstraints = constraintList_makeNew (); + e->trueEnsuresConstraints = constraintList_makeNew (); + e->falseEnsuresConstraints = constraintList_makeNew (); +} /* ** must occur after library has been read @@ -133,8 +140,6 @@ void exprNode_initMod (void) ctypeType = ctype_unknown; filelocType = ctype_unknown; - defref = sRef_undefined; - if (usymtab_existsType (cstring_makeLiteralTemp ("cstring"))) { cstringType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("cstring")); @@ -212,24 +217,25 @@ void exprNode_initMod (void) void exprNode_destroyMod (void) /*@globals killed regArg, killed outArg, killed outStringArg, - killed mustExitNode, initMod @*/ + killed s_mustExitNode, initMod @*/ { if (initMod) { - uentry_free (regArg); - uentry_free (outArg); - uentry_free (outStringArg); + /* evans 2002-07-12: changed uentry_free to uentry_freeComplete */ + uentry_freeComplete (regArg); + uentry_freeComplete (outArg); + uentry_freeComplete (outStringArg); - exprNode_free (mustExitNode); + exprNode_free (s_mustExitNode); initMod = FALSE; - /*@-branchstate@*/ + /*@-branchstate@*/ } /*@=branchstate@*/ } static void exprNode_resetSref (/*@notnull@*/ exprNode e) { - e->sref = defref; + e->sref = sRef_undefined; } exprNode exprNode_fakeCopy (exprNode e) @@ -434,7 +440,7 @@ static /*@notnull@*/ /*@special@*/ exprNode e->typ = c; e->kind = XPR_EMPTY; e->val = multiVal_undefined; - e->sref = defref; + e->sref = sRef_undefined; e->etext = cstring_undefined; e->loc = fileloc_undefined; e->guards = guardSet_undefined; @@ -454,13 +460,13 @@ static /*@notnull@*/ /*@special@*/ exprNode /*@observer@*/ exprNode exprNode_makeMustExit (void) { - if (exprNode_isUndefined (mustExitNode)) + if (exprNode_isUndefined (s_mustExitNode)) { - mustExitNode = exprNode_createPlain (ctype_unknown); - mustExitNode->exitCode = XK_MUSTEXIT; + s_mustExitNode = exprNode_createPlain (ctype_unknown); + s_mustExitNode->exitCode = XK_MUSTEXIT; } - return mustExitNode; + return s_mustExitNode; } @@ -546,7 +552,7 @@ static /*@notnull@*/ /*@special@*/ exprNode } ret->kind = XPR_EMPTY; - ret->sref = defref; + ret->sref = sRef_undefined; ret->etext = cstring_undefined; ret->exitCode = XK_NEVERESCAPE; ret->canBreak = FALSE; @@ -598,7 +604,7 @@ static /*@notnull@*/ /*@special@*/ exprNode ret->val = multiVal_undefined; ret->kind = XPR_EMPTY; - ret->sref = defref; + ret->sref = sRef_undefined; ret->etext = cstring_undefined; ret->exitCode = XK_NEVERESCAPE; ret->canBreak = FALSE; @@ -635,7 +641,7 @@ static /*@notnull@*/ /*@special@*/ exprNode ret->msets = sRefSet_undefined; ret->kind = XPR_EMPTY; - ret->sref = defref; + ret->sref = sRef_undefined; ret->etext = cstring_undefined; ret->exitCode = XK_NEVERESCAPE; ret->canBreak = FALSE; @@ -671,7 +677,13 @@ exprNode_isUnknownConstant (/*@notnull@*/ exprNode e) while (e->kind == XPR_PARENS) { e = exprData_getUopNode (e->edata); - llassert (exprNode_isDefined (e)); + + if (!exprNode_isDefined (e)) + { + return FALSE; + } + + /* evans 2002-02-05: was llassert (exprNode_isDefined (e)); but this can fail */ } if (e->kind == XPR_CONST) @@ -804,17 +816,17 @@ exprNode_combineLiterals (exprNode e, exprNode rest) exprNode_rawStringLiteral (/*@only@*/ cstring t, /*@only@*/ fileloc loc) { exprNode e = exprNode_createLoc (ctype_string, loc); - int len = cstring_length (t); + size_t len = cstring_length (t); if (context_getFlag (FLG_STRINGLITERALLEN)) { - if (len > context_getValue (FLG_STRINGLITERALLEN)) + if (len > size_fromInt (context_getValue (FLG_STRINGLITERALLEN))) { voptgenerror (FLG_STRINGLITERALLEN, message ("String literal length (%d) exceeds maximum " "length (%d): \"%s\"", - len, + size_toInt (len), context_getValue (FLG_STRINGLITERALLEN), t), e->loc); @@ -824,7 +836,7 @@ exprNode_rawStringLiteral (/*@only@*/ cstring t, /*@only@*/ fileloc loc) e->kind = XPR_STRINGLITERAL; e->val = multiVal_makeString (cstring_copy (t)); e->edata = exprData_makeLiteral (t); - e->sref = sRef_makeType (ctype_string); + e->sref = sRef_makeConst (ctype_string); if (context_getFlag (FLG_READONLYSTRINGS)) { @@ -839,15 +851,23 @@ exprNode_rawStringLiteral (/*@only@*/ cstring t, /*@only@*/ fileloc loc) return (e); /* s released */ } +/*@only@*/ exprNode +exprNode_wideStringLiteral (/*@only@*/ cstring t, /*@only@*/ fileloc loc) +{ + exprNode res = exprNode_stringLiteral (t, loc); + res->typ = ctype_makeWideString (); + return res; +} + /*@only@*/ exprNode exprNode_stringLiteral (/*@only@*/ cstring t, /*@only@*/ fileloc loc) { - int len = cstring_length (t) - 2; + size_t len = size_fromInt (size_toInt (cstring_length (t)) - 2); char *ts = cstring_toCharsSafe (t); char *s = cstring_toCharsSafe (cstring_create (len + 1)); llassert (*ts == '\"' && *(ts + len + 1) == '\"'); - strncpy (s, ts+1, size_fromInt (len)); + strncpy (s, ts+1, len); *(s + len) = '\0'; cstring_free (t); return exprNode_rawStringLiteral (cstring_fromCharsO (s), loc); @@ -866,7 +886,7 @@ exprNode exprNode_fromUIO (cstring c) } e->loc = loc; /* save loc was mangled */ - e->sref = defref; + e->sref = sRef_undefined; if (usymtab_exists (c)) { @@ -922,12 +942,30 @@ exprNode exprNode_fromUIO (cstring c) return (e); } +exprNode exprNode_makeConstantString (cstring c, /*@only@*/ fileloc loc) +{ + exprNode e = exprNode_createPlain (ctype_unknown); + e->kind = XPR_VAR; + e->loc = loc; + e->sref = sRef_makeConst (ctype_string); + e->edata = exprData_makeId (uentry_makeUnrecognized (c, fileloc_copy (loc))); + e->typ = ctype_string; + + /* No alias errors for unrecognized identifiers */ + sRef_setAliasKind (e->sref, AK_STATIC, loc); + sRef_setExKind (e->sref, XO_OBSERVER, loc); + + return (e); +} + exprNode exprNode_createId (/*@observer@*/ uentry c) { if (uentry_isValid (c)) { exprNode e = exprNode_new (); - + + DPRINTF (("create id: %s", uentry_unparse (c))); + e->typ = uentry_getType (c); if (uentry_isFunction (c) @@ -947,7 +985,7 @@ exprNode exprNode_createId (/*@observer@*/ uentry c) /* ** yoikes! leaving this out was a heinous bug...that would have been - ** caught if i had lclint working first. gag! + ** caught if i had splint working first. gag! */ e->etext = cstring_undefined; @@ -973,18 +1011,18 @@ exprNode exprNode_createId (/*@observer@*/ uentry c) } e->guards = guardSet_new (); + e->sets = sRefSet_new (); e->msets = sRefSet_new (); e->uses = sRefSet_new (); - /*> missing fields, detected by lclint <*/ + /*> missing fields, detected by splint <*/ e->exitCode = XK_NEVERESCAPE; e->isJumpPoint = FALSE; e->canBreak = FALSE; e->mustBreak = FALSE; - exprNode_defineConstraints(e); - + exprNode_defineConstraints (e); return e; } else @@ -1000,7 +1038,7 @@ exprNode_fromIdentifier (/*@observer@*/ uentry c) if (context_justPopped ()) /* watch out! c could be dead */ { - uentry ce = usymtab_lookupSafe (LastIdentifier ()); + uentry ce = usymtab_lookupSafe (cscannerHelp_observeLastIdentifier ()); if (uentry_isValid (ce)) { @@ -1013,10 +1051,82 @@ exprNode_fromIdentifier (/*@observer@*/ uentry c) } ret = exprNode_fromIdentifierAux (c); - return ret; } +static void exprNode_checkStringLiteralLength (ctype t1, exprNode e2) +{ + multiVal mval = exprNode_getValue (e2); + cstring slit; + size_t len; + + if (ctype_isFixedArray (t1)) + { + size_t nelements = ctype_getArraySize (t1); + + llassert (multiVal_isString (mval)); + slit = multiVal_forceString (mval); + + len = cstring_lengthExpandEscapes (slit); + + llassert (exprNode_isDefined (e2)); + + if (len == nelements) + { + mstring temp; + + temp = cstring_expandEscapes (slit); + + if (temp[len-1] == '\0') + { + voptgenerror + (FLG_STRINGLITNOROOMFINALNULL, + message ("String literal with %d character%& " + "is assigned to %s (no room for final null terminator): %s", + size_toInt (len + 1), + ctype_unparse (t1), + exprNode_unparse (e2)), + e2->loc); + } + else + { + voptgenerror + (FLG_STRINGLITNOROOM, + message ("String literal with %d character%& " + "is assigned to %s (no room for null terminator): %s", + size_toInt (len + 1), + ctype_unparse (t1), + exprNode_unparse (e2)), + e2->loc); + } + } + else if (len > nelements) + { + voptgenerror + (FLG_STRINGLITTOOLONG, + message ("String literal with %d character%& (counting null terminator) " + "is assigned to %s (insufficient storage available): %s", + size_toInt (len + 1), + ctype_unparse (t1), + exprNode_unparse (e2)), + e2->loc); + } + else if (len < nelements - 1) + { + voptgenerror + (FLG_STRINGLITSMALLER, + message ("String literal with %d character%& is assigned to %s (possible waste of storage): %s", + size_toInt (len + 1), + ctype_unparse (t1), + exprNode_unparse (e2)), + e2->loc); + } + else + { + ; /* okay */ + } + } +} static /*@only@*/ /*@notnull@*/ exprNode exprNode_fromIdentifierAux (/*@observer@*/ uentry c) @@ -1061,6 +1171,16 @@ exprNode_isNonNegative (exprNode e) { return (multiVal_forceInt (m) >= 0); } + + /* + ** This is not always true if programmer defines enum + ** values, but then the constant should be known. + */ + + if (ctype_isEnum (ctype_realType (e->typ))) + { + return TRUE; + } } return FALSE; @@ -1083,6 +1203,9 @@ exprNode_arrayFetch (/*@only@*/ exprNode e1, /*@only@*/ exprNode e2) ** error in ind, assume valid and continue */ + DPRINTF (("Array fetch: %s / %s", + exprNode_unparse (e1), exprNode_unparse (e2))); + if (exprNode_isError (e1)) { exprNode_free (e2); @@ -1097,10 +1220,12 @@ exprNode_arrayFetch (/*@only@*/ exprNode e1, /*@only@*/ exprNode e2) /* ** this sets up funny aliasing, that leads to spurious - ** lclint errors. Hence, the i2 comments. + ** splint errors. Hence, the i2 comments. */ - if (!ctype_isRealArray (crarr) + /* evans 2001-09-09 added ctype_isKnown so there is no swap when e1 type is unknown */ + if (ctype_isKnown (crarr) + && !ctype_isRealArray (crarr) && ctype_isRealNumeric (crarr) && !exprNode_isError (e2) && ctype_isRealAP (exprNode_getType (e2))) /* fetch like 3[a] */ @@ -1117,21 +1242,27 @@ exprNode_arrayFetch (/*@only@*/ exprNode e1, /*@only@*/ exprNode e2) ind = e2; } + DPRINTF (("arr: %s", exprNode_unparse (arr))); + if (sRef_possiblyNull (arr->sref)) { if (!usymtab_isGuarded (arr->sref)) { - if (optgenerror (FLG_NULLDEREF, - message ("Index of %s pointer %q: %s", - sRef_nullMessage (arr->sref), - sRef_unparse (arr->sref), - exprNode_unparse (arr)), - arr->loc)) - { - sRef_showNullInfo (arr->sref); - - /* suppress future messages */ - sRef_setNullError (arr->sref); + if (!context_inSizeof() ) + { + if (optgenerror (FLG_NULLDEREF, + message ("Index of %s pointer %q: %s", + sRef_nullMessage (arr->sref), + sRef_unparse (arr->sref), + exprNode_unparse (arr)), + arr->loc)) + { + DPRINTF (("ref: %s", sRef_unparseFull (arr->sref))); + sRef_showNullInfo (arr->sref); + + /* suppress future messages */ + sRef_setNullError (arr->sref); + } } } } @@ -1200,6 +1331,15 @@ exprNode_arrayFetch (/*@only@*/ exprNode e1, /*@only@*/ exprNode e2) exprNode_unparse (e1), exprNode_unparse (e2)), arr->loc); } + else if (ctype_isNumAbstract (rt)) + { + vnoptgenerror + (FLG_NUMABSTRACTINDEX, + message ("Array fetch using numabstract type, %t: %s[%s]", + ind->typ, + exprNode_unparse (e1), exprNode_unparse (e2)), + arr->loc); + } else { voptgenerror @@ -1490,7 +1630,12 @@ checkPrintfArgs (/*@notnull@*/ /*@dependent@*/ exprNode f, uentry fcn, /*@switchbreak@*/ break; case 'c': /* int converted to char (check its a char?) */ - expecttype = ctype_makeConj (ctype_char, ctype_uchar); + expecttype = ctype_makeConj (ctype_int, + ctype_makeConj (ctype_char, + ctype_uchar)); + /* evans 2001-10-05 - changed to reflect correct ISO spec: + int converted to char */ + /*@switchbreak@*/ break; case 's': /* string */ @@ -1517,7 +1662,11 @@ checkPrintfArgs (/*@notnull@*/ /*@dependent@*/ exprNode f, uentry fcn, case 'p': /* pointer */ expecttype = ctype_makePointer (ctype_void); - /* really! */ + /* need not be defined */ + uentry_setDefState (regArg, SS_RELDEF); + sRef_setPosNull (uentry_getSref (regArg), + fileloc_undefined); + /* could be null */ /*@switchbreak@*/ break; case 'n': /* pointer to int, modified by call! */ @@ -1589,7 +1738,7 @@ checkPrintfArgs (/*@notnull@*/ /*@dependent@*/ exprNode f, uentry fcn, uentry_setType (regArg, ctype_unknown); uentry_fixupSref (regArg); - + if (modified) { exprNode_checkCallModifyVal (a->sref, args, f, ret); @@ -1782,9 +1931,12 @@ checkScanfArgs (/*@notnull@*/ /*@dependent@*/ exprNode f, uentry fcn, case 'i': case 'd': + expecttype = ctype_makePointer (ctype_combine (ctype_int, modtype)); + /*@switchbreak@*/ break; + case 'x': case 'X': /* unsigned int */ - expecttype = ctype_makePointer (ctype_combine (ctype_int, modtype)); + expecttype = ctype_makePointer (ctype_combine (ctype_uint, modtype)); /*@switchbreak@*/ break; case 'e': @@ -1835,10 +1987,17 @@ checkScanfArgs (/*@notnull@*/ /*@dependent@*/ exprNode f, uentry fcn, expecttype = ctype_string; /*@switchbreak@*/ break; + case 'p': /* pointer */ + voptgenerror + (FLG_FORMATCODE, + message ("Format code should not be used in scanf: %s", + cstring_fromChars (origcode)), + fileloc_isDefined (formatloc) + ? formatloc : g_currentloc); + expecttype = ctype_unknown; - /* really! */ /*@switchbreak@*/ break; case 'n': /* pointer to int, modified by call! */ @@ -1903,7 +2062,7 @@ checkScanfArgs (/*@notnull@*/ /*@dependent@*/ exprNode f, uentry fcn, } else { - /* a->sref = defref; */ + /* a->sref = sRef_undefined; */ } } } @@ -2043,6 +2202,14 @@ checkMessageArgs (/*@notnull@*/ /*@dependent@*/ exprNode f, case 'f': expecttype = ctype_float; break; case 'b': expecttype = ctype_bool; break; case 't': expecttype = ctypeType; break; + case 'p': + expecttype = ctype_makePointer (ctype_void); + /* need not be defined */ + uentry_setDefState (regArg, SS_RELDEF); + sRef_setPosNull (uentry_getSref (regArg), + fileloc_undefined); + /* could be null */ + /*@switchbreak@*/ break; case 'l': expecttype = filelocType; break; case '&': /* a wee bit of a hack methinks */ expecttype = ctype_int; @@ -2080,7 +2247,7 @@ checkMessageArgs (/*@notnull@*/ /*@dependent@*/ exprNode f, codetext, expecttype, a->typ, exprNode_unparse (a)), a->loc)) - { + { if (fileloc_isDefined (formatloc) && context_getFlag (FLG_SHOWCOL)) { @@ -2276,8 +2443,10 @@ static void checkExpressionDefined (exprNode e1, exprNode e2, lltok op) hasError = optgenerror (FLG_EVALORDER, message ("Expression has undefined behavior " - "(value of left operand is modified " - "by right operand): %s %s %s", + "(value of left operand %s is modified " + "by right operand %s): %s %s %s", + exprNode_unparse (e1), + exprNode_unparse (e2), exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)), e2->loc); @@ -2426,7 +2595,7 @@ static int f->guards = guardSet_union (f->guards, a->guards); DPRINTF (("match arg: %s / %s", ctype_unparse (ct), ctype_unparse (a->typ))); - + if (!(exprNode_matchArgType (ct, a))) { DPRINTF (("Args mismatch!")); @@ -2760,7 +2929,7 @@ checkGlobMods (/*@notnull@*/ /*@dependent@*/ exprNode f, uentry_unparse (le))); params = ctype_argsFunction (ct); - return; /*@32 ! remove this? */ + return; /* No checking for non-function */ } /* @@ -3023,7 +3192,7 @@ checkGlobMods (/*@notnull@*/ /*@dependent@*/ exprNode f, if (freshMods) { /* - ** Spurious errors reported, because lclint can't tell + ** Spurious errors reported, because splint can't tell ** mods must be fresh if freshMods is true. */ @@ -3077,7 +3246,7 @@ void checkGlobUse (uentry glob, bool isCall, /*@notnull@*/ exprNode e) } static void -reflectEnsuresClause (uentry le, exprNode f, exprNodeList args) +reflectEnsuresClause (exprNode ret, uentry le, exprNode f, exprNodeList args) { DPRINTF (("Reflect ensures clause: %s(%s) / %s / %s", exprNode_unparse (f), exprNodeList_unparse (args), @@ -3131,16 +3300,17 @@ reflectEnsuresClause (uentry le, exprNode f, exprNodeList args) if (sRef_isResult (sRef_getRootBase (sel))) { - ; /*@i423 what do we do about results */ + s = exprNode_getSref (ret); } else { s = sRef_fixBaseParam (sel, args); - DPRINTF (("Reflecting state clause on: %s / %s", - sRef_unparse (sel), sRef_unparse (s))); - - sRef_setMetaStateValueComplete (s, key, mvalue, exprNode_loc (f)); } + + DPRINTF (("Reflecting state clause on: %s / %s", + sRef_unparse (sel), sRef_unparse (s))); + + sRef_setMetaStateValueComplete (s, key, mvalue, exprNode_loc (f)); } end_sRefSet_elements; sRefSet_free (osrs); @@ -3150,7 +3320,9 @@ reflectEnsuresClause (uentry le, exprNode f, exprNodeList args) sRefSet srs = stateClause_getRefs (cl); sRefModVal modf = stateClause_getEnsuresFunction (cl); int eparam = stateClause_getStateParameter (cl); - + + llassert (modf != NULL); + DPRINTF (("Reflect after clause: %s / %s", stateClause_unparse (cl), sRefSet_unparse (srs))); @@ -3164,25 +3336,259 @@ reflectEnsuresClause (uentry le, exprNode f, exprNodeList args) if (sRef_isResult (sRef_getRootBase (sel))) { - ; /*@i423 what do we do about results */ + DPRINTF (("Fix base: %s / %s", + sRef_unparse (sel), sRef_unparse (exprNode_getSref (ret)))); + s = sRef_fixBase (sel, exprNode_getSref (ret)); + DPRINTF (("==> %s", sRef_unparseFull (s))); } else { s = sRef_fixBaseParam (sel, args); + } + + DPRINTF (("elements: %s", sRef_unparse (s))); + DPRINTF (("elements: %s", sRef_unparseFull (s))); + + DPRINTF (("Reflecting state clause on: %s / %s", + sRef_unparseFull (sel), sRef_unparseFull (s))); + + /* evans 2001-08-24 - added aliasSetCompleteParam */ + sRef_aliasSetCompleteParam (modf, s, eparam, exprNode_loc (f)); + + DPRINTF (("After reflecting state clause on: %s / %s", + sRef_unparseFull (sel), sRef_unparseFull (s))); + } end_sRefSet_elements; + } + } + } end_stateClauseList_elements ; + } + + DPRINTF (("Here: %s / %s", + uentry_unparseFull (le), + bool_unparse (uentry_hasMetaStateEnsures (le)))); + + if (uentry_hasMetaStateEnsures (le)) + { + fileloc loc = exprNode_loc (f); + + metaStateConstraintList mscl = uentry_getMetaStateEnsures (le); + + metaStateConstraintList_elements (mscl, msc) + { + metaStateSpecifier msspec = metaStateConstraint_getSpecifier (msc); + metaStateInfo msinfo = metaStateSpecifier_getMetaStateInfo (msspec); + metaStateExpression msexpr = metaStateConstraint_getExpression (msc); + cstring key = metaStateInfo_getName (msinfo); + sRef mlsr = metaStateSpecifier_getSref (msspec); + sRef s; + sRef lastref = sRef_undefined; + stateValue sval = stateValue_undefined; + + DPRINTF (("Meta state constraint for %s: %s", uentry_unparse (le), + metaStateConstraint_unparse (msc))); + DPRINTF (("Matches left: %s", sRef_unparseDebug (mlsr))); + + if (sRef_isResult (sRef_getRootBase (mlsr))) + { + s = exprNode_getSref (ret); + } + else + { + s = sRef_fixBaseParam (mlsr, args); + } + + DPRINTF (("Setting state: %s", sRef_unparseFull (s))); + + while (metaStateExpression_isDefined (msexpr)) + { + metaStateSpecifier ms = metaStateExpression_getSpecifier (msexpr); + metaStateInfo msi = metaStateSpecifier_getMetaStateInfo (ms); + sRef msr, fs; + + DPRINTF (("Check expression: %s", metaStateExpression_unparse (msexpr))); + + if (metaStateExpression_isMerge (msexpr)) + { + msexpr = metaStateExpression_getRest (msexpr); + } + else + { + msexpr = metaStateExpression_undefined; + } + + if (metaStateInfo_isDefined (msi)) + { + /* Must match lhs state */ + llassert (metaStateInfo_equal (msinfo, msi)); + } + + if (metaStateSpecifier_isElipsis (ms)) + { + /* + ** For elipsis, we need to merge all the relevant elipsis parameters + ** + */ + + uentryList params = uentry_getParams (le); + int paramno = uentryList_size (params) - 1; + + if (!uentry_isElipsisMarker (uentryList_getN (params, paramno))) + { + voptgenerror + (FLG_TYPE, + message ("Ensures clauses uses ... for function without ... in parameter list: %q", + uentry_getName (le)), + uentry_whereLast (le)); + /*@innerbreak@*/ break; + } + + while (paramno < exprNodeList_size (args)) + { + exprNode arg = exprNodeList_getN (args, paramno); + fs = exprNode_getSref (arg); + DPRINTF (("Merge arg: %s", exprNode_unparse (arg))); + + /* cut and pasted... gack*/ + if (stateValue_isDefined (sval)) + { + /* Use combination table to merge old state value with new one: */ + stateValue tval = sRef_getMetaStateValue (fs, key); - DPRINTF (("elements: %s", sRef_unparse (s))); - DPRINTF (("elements: %s", sRef_unparseFull (s))); + if (stateValue_isDefined (tval)) + { + stateCombinationTable sctable = metaStateInfo_getMergeTable (msinfo); + cstring msg = cstring_undefined; + int nval = stateCombinationTable_lookup (sctable, + stateValue_getValue (sval), + stateValue_getValue (tval), + &msg); + DPRINTF (("Combining: %s + %s -> %d", + stateValue_unparseValue (sval, msinfo), + stateValue_unparseValue (tval, msinfo), + nval)); + + if (nval == stateValue_error) + { + if (optgenerror + (FLG_STATEMERGE, + message + ("Attributes merged in ensures clause in states that " + "cannot be combined (%q is %q, %q is %q)%q", + sRef_unparse (lastref), + stateValue_unparseValue (sval, msinfo), + sRef_unparse (fs), + stateValue_unparseValue (tval, msinfo), + cstring_isDefined (msg) ? + message (": %s", msg) : cstring_undefined), + exprNode_loc (f))) + { + sRef_showMetaStateInfo (fs, key); + } + } + + stateValue_updateValueLoc (sval, nval, fileloc_undefined); + loc = exprNode_loc (arg); + } + else + { + DPRINTF (("No value for: %s:%s", sRef_unparse (fs), key)); + } + } + else + { + sval = sRef_getMetaStateValue (fs, key); + } + + lastref = fs; + + if (stateValue_isError (sval)) + { + /*@innerbreak@*/ break; /* Don't merge any more values if here was an error */ + } + + + paramno++; + } + } + else + { + msr = metaStateSpecifier_getSref (ms); + + + llassert (sRef_isParam (sRef_getRootBase (msr))); + fs = sRef_fixBaseParam (msr, args); + + if (stateValue_isDefined (sval)) + { + /* Use combination table to merge old state value with new one: */ + stateValue tval = sRef_getMetaStateValue (fs, key); + + if (stateValue_isDefined (tval)) + { + stateCombinationTable sctable = metaStateInfo_getMergeTable (msinfo); + cstring msg = cstring_undefined; + int nval = stateCombinationTable_lookup (sctable, + stateValue_getValue (sval), + stateValue_getValue (tval), + &msg); + DPRINTF (("Combining: %s + %s -> %d", + stateValue_unparseValue (sval, msinfo), + stateValue_unparseValue (tval, msinfo), + nval)); - DPRINTF (("Reflecting state clause on: %s / %s", - sRef_unparse (sel), sRef_unparse (s))); + if (nval == stateValue_error) + { + if (optgenerror + (FLG_STATEMERGE, + message + ("Attributes merged in ensures clause in states that " + "cannot be combined (%q is %q, %q is %q)%q", + sRef_unparse (lastref), + stateValue_unparseValue (sval, msinfo), + sRef_unparse (fs), + stateValue_unparseValue (tval, msinfo), + cstring_isDefined (msg) + ? message (": %s", msg) : cstring_undefined), + exprNode_loc (f))) + { + sRef_showMetaStateInfo (fs, key); + } + } - modf (s, eparam, exprNode_loc (f)); + stateValue_updateValueLoc (sval, nval, fileloc_undefined); } - } end_sRefSet_elements; + else + { + DPRINTF (("No value for: %s:%s", sRef_unparse (fs), key)); + } + } + else + { + sval = sRef_getMetaStateValue (fs, key); + } + + lastref = fs; + + if (stateValue_isError (sval)) + { + /*@innerbreak@*/ break; /* Don't merge any more values if here was an error */ + } } } - } end_stateClauseList_elements ; - + + DPRINTF (("Setting: %s:%s <- %s", sRef_unparse (s), key, stateValue_unparse (sval))); + + if (stateValue_isDefined (sval)) + { + sRef_setMetaStateValueComplete (s, key, stateValue_getValue (sval), loc); + } + else + { + DPRINTF (("Undefined state: %s", cstring_toCharsSafe (sRef_unparse (s)))); + } + } end_metaStateConstraintList_elements ; + + metaStateConstraintList_free (mscl); } } } @@ -3244,7 +3650,7 @@ checkRequiresClause (uentry le, exprNode f, exprNodeList args) if (sRef_isResult (sRef_getRootBase (sel))) { - ; /*@i423 what do we do about results */ + BADBRANCH; } else { @@ -3290,6 +3696,8 @@ checkRequiresClause (uentry le, exprNode f, exprNodeList args) stateClause_unparse (cl), sRefSet_unparse (srs))); + llassert (modf != NULL); + sRefSet_elements (srs, sel) { sRef s; @@ -3304,7 +3712,7 @@ checkRequiresClause (uentry le, exprNode f, exprNodeList args) if (sRef_isResult (sRef_getRootBase (sel))) { - ; /*@i423 what do we do about results */ + ; /* what do we do about results? */ } else { @@ -3377,10 +3785,6 @@ functionCallSafe (/*@only@*/ /*@notnull@*/ exprNode f, checkRequiresClause (le, f, args); setCodePoint (); - DPRINTF (("Reflect: %s", uentry_unparseFull (le))); - reflectEnsuresClause (le, f, args); - setCodePoint (); - if (uentry_isValid (le) && (uentry_isFunction (le) || (uentry_isVariable (le) @@ -3390,11 +3794,12 @@ functionCallSafe (/*@only@*/ /*@notnull@*/ exprNode f, /* f->typ is already set to the return type */ - ret->sref = uentry_returnedRef (le, args); + DPRINTF (("Function: %s", uentry_unparseFull (le))); + ret->sref = uentry_returnedRef (le, args, exprNode_loc (f)); DPRINTF (("Returned: %s / %s", uentry_unparseFull (le), sRef_unparseFull (ret->sref))); - + if (uentry_isFunction (le) && exprNodeList_size (args) >= 1) { qual nullPred = uentry_nullPred (le); @@ -3499,10 +3904,16 @@ functionCallSafe (/*@only@*/ /*@notnull@*/ exprNode f, } else { - ret->sref = defref; + ret->sref = sRef_undefined; exprNode_checkSetAny (ret, uentry_rawName (le)); } + DPRINTF (("Before reflect: %s", sRef_unparseFull (ret->sref))); + DPRINTF (("Reflect: %s", uentry_unparseFull (le))); + reflectEnsuresClause (ret, le, f, args); + setCodePoint (); + + DPRINTF (("Here: %s", sRef_unparseFull (ret->sref))); return (ret); } @@ -3510,8 +3921,7 @@ functionCallSafe (/*@only@*/ /*@notnull@*/ exprNode f, ** this is yucky! should keep the uentry as part of exprNode! */ -/*@observer@*/ uentry -exprNode_getUentry (exprNode e) +uentry exprNode_getUentry (exprNode e) { if (exprNode_isError (e)) { @@ -3526,6 +3936,19 @@ exprNode_getUentry (exprNode e) } } +/* +** Returns true iff e1 and e2 are both exactly the same storage +** (conservative). +*/ + +static bool exprNode_sameStorage (exprNode e1, exprNode e2) +{ + sRef s1 = exprNode_getSref (e1); + sRef s2 = exprNode_getSref (e2); + + return (sRef_realSame (s1, s2)); +} + exprNode exprNode_makeInitBlock (lltok brace, /*@only@*/ exprNodeList inits) { @@ -3543,7 +3966,9 @@ exprNode_functionCall (/*@only@*/ exprNode f, /*@only@*/ exprNodeList args) { ctype t; - setCodePoint (); +# ifdef DEBUGSPLINT + usymtab_checkAllValid (); +# endif if (exprNode_isUndefined (f)) { @@ -3722,7 +4147,7 @@ exprNode_fieldAccess (/*@only@*/ exprNode s, /*@only@*/ lltok dot, /*@only@*/ cstring f) { exprNode res = exprNode_fieldAccessAux (s, lltok_getLoc (dot), f); - lltok_release (dot); + lltok_free (dot); return res; } @@ -3926,7 +4351,7 @@ exprNode_arrowAccess (/*@only@*/ exprNode s, /*@only@*/ cstring f) { exprNode res = exprNode_arrowAccessAux (s, lltok_getLoc (arrow), f); - lltok_release (arrow); + lltok_free (arrow); return res; } @@ -3976,11 +4401,15 @@ exprNode_postOp (/*@only@*/ exprNode e, /*@only@*/ lltok op) { if (ctype_isRealAbstract (t)) { - voptgenerror - (FLG_ABSTRACT, - message ("Operand of %s is abstract type (%t): %s", - lltok_unparse (op), t, exprNode_unparse (e)), - e->loc); + if (ctype_isRealNumAbstract (t)) { + ; /* Allow operations on numabstract types */ + } else { + voptgenerror + (FLG_ABSTRACT, + message ("Operand of %s is abstract type (%t): %s", + lltok_unparse (op), t, exprNode_unparse (e)), + e->loc); + } } else { @@ -3998,57 +4427,53 @@ exprNode_postOp (/*@only@*/ exprNode e, /*@only@*/ lltok op) exprNode_checkModify (e, ret); /* added 7/11/2000 D.L */ - /*@i223*/ - /*DRL 6/8/01 I decided to disable all LCLint Warning here since the code - probably needs a rewrite any way */ - - /*@ignore@*/ - - // updateEnvironmentForPostOp (e); - - /* start modifications */ - /* added by Seejo on 4/16/2000 */ - - /* Arithmetic operations on pointers wil modify the size/len/null terminated - status */ - if ((sRef_isPossiblyNullTerminated (e->sref)) || (sRef_isNullTerminated(e->sref))) { - ret->sref = sRef_copy (e->sref); - - /* Operator : ++ */ - if (lltok_getTok (op) == INC_OP) { - if (sRef_getSize(e->sref) > 0) { - - sRef_setSize (ret->sref, sRef_getSize(e->sref) - 1); - - if (sRef_getLen(e->sref) == 1) { /* i.e. the first character is \0 */ - /* Assumption: there is only 1 \0 in the buffer */ - /* This will not be correct if there are 2 \0's in the buffer */ - sRef_setNotNullTerminatedState(ret->sref); - sRef_resetLen(ret->sref); - } else { - sRef_setNullTerminatedState(ret->sref); - sRef_setLen (ret->sref, sRef_getLen(e->sref) - 1); - } - if (sRef_isNullTerminated (ret->sref)) - printf ("ret->sref is Null Terminated\n"); - else if (sRef_isPossiblyNullTerminated (ret->sref)) - printf ("ret->sref is Possibly Null Terminated\n"); - else if (sRef_isNotNullTerminated (ret->sref)) - printf ("ret->sref is Not Null Terminated\n"); - } - } - - /* Operator : -- */ - if (lltok_getTok (op) == DEC_OP) { - if (sRef_getSize(e->sref) >= 0) { - sRef_setSize (ret->sref, sRef_getSize(e->sref) + 1); - sRef_setLen (ret->sref, sRef_getLen(e->sref) + 1); - } - } - } - /*@end@*/ - /* end modifications */ + /* updateEnvironmentForPostOp (e); */ + + /* start modifications */ + /* added by Seejo on 4/16/2000 */ + + /* Arithmetic operations on pointers wil modify the size/len/null terminated + status */ + if ((sRef_isPossiblyNullTerminated (e->sref)) || (sRef_isNullTerminated(e->sref))) { + + ret->sref = sRef_copy (e->sref); + + /* Operator : ++ */ + if (lltok_getTok (op) == INC_OP) { + if (sRef_getSize(e->sref) > 0) { + + sRef_setSize (ret->sref, sRef_getSize(e->sref) - 1); + + if (sRef_getLen(e->sref) == 1) { /* i.e. the first character is \0 */ + /* Assumption: there is only 1 \0 in the buffer */ + /* This will not be correct if there are 2 \0's in the buffer */ + sRef_setNotNullTerminatedState(ret->sref); + sRef_resetLen(ret->sref); + } else { + sRef_setNullTerminatedState(ret->sref); + sRef_setLen (ret->sref, sRef_getLen(e->sref) - 1); + } + if (sRef_isNullTerminated (ret->sref)) + printf ("ret->sref is Null Terminated\n"); + else if (sRef_isPossiblyNullTerminated (ret->sref)) + printf ("ret->sref is Possibly Null Terminated\n"); + else if (sRef_isNotNullTerminated (ret->sref)) + printf ("ret->sref is Not Null Terminated\n"); + else + {} + } + } + + /* Operator : -- */ + if (lltok_getTok (op) == DEC_OP) { + if (sRef_getSize(e->sref) >= 0) { + sRef_setSize (ret->sref, sRef_getSize(e->sref) + 1); + sRef_setLen (ret->sref, sRef_getLen(e->sref) + 1); + } + } + } + /* end modifications */ return ret; } @@ -4086,15 +4511,22 @@ exprNode_preOp (/*@only@*/ exprNode e, /*@only@*/ lltok op) if (ctype_isRealAbstract (tr) && (!(ctype_isRealBool (te) && (opid == TEXCL)))) { - if (optgenerror (FLG_ABSTRACT, - message ("Operand of %s is abstract type (%t): %s", - lltok_unparse (op), tr, - exprNode_unparse (ret)), - e->loc)) + if (ctype_isRealNumAbstract (tr)) { - tr = te = ctype_unknown; - ret->typ = ctype_unknown; - sRef_setNullError (e->sref); + ; /* no warning for numabstract types */ + } + else + { + if (optgenerror (FLG_ABSTRACT, + message ("Operand of %s is abstract type (%t): %s", + lltok_unparse (op), tr, + exprNode_unparse (ret)), + e->loc)) + { + tr = te = ctype_unknown; + ret->typ = ctype_unknown; + sRef_setNullError (e->sref); + } } } } @@ -4137,8 +4569,8 @@ exprNode_preOp (/*@only@*/ exprNode e, /*@only@*/ lltok op) /* Arithmetic operations on pointers wil modify the size/len/null terminated status */ - if ((sRef_isPossiblyNullTerminated (e->sref)) || (sRef_isNullTerminated(e->sref))) { - + if ((sRef_isPossiblyNullTerminated (e->sref)) + || (sRef_isNullTerminated(e->sref))) { ret->sref = sRef_copy (e->sref); /* Operator : ++ */ @@ -4310,8 +4742,11 @@ exprNode_preOp (/*@only@*/ exprNode e, /*@only@*/ lltok op) if (sRef_isKnown (e->sref)) { + DPRINTF (("Checking possibly null: %s", sRef_unparseFull (e->sref))); + if (sRef_possiblyNull (e->sref)) { + DPRINTF (("Checking possibly null: %s", sRef_unparse (e->sref))); if (!usymtab_isGuarded (e->sref) && !context_inProtectVars ()) { if (optgenerror @@ -4365,7 +4800,7 @@ ctype sizeof_resultType (void) } else { - sizet = ctype_ulint; + sizet = ctype_ulint; } } return sizet; @@ -4561,7 +4996,7 @@ exprNode_cast (/*@only@*/ lltok tok, /*@only@*/ exprNode e, /*@only@*/ qtype q) if (exprNode_isError (e)) { qtype_free (q); - lltok_release (tok); + lltok_free (tok); return exprNode_undefined; } @@ -4577,28 +5012,18 @@ exprNode_cast (/*@only@*/ lltok tok, /*@only@*/ exprNode e, /*@only@*/ qtype q) ret->kind = XPR_CAST; ret->edata = exprData_makeCast (tok, e, q); - if (ctype_isRealSU (ctype_getBaseType (sRef_getType (e->sref)))) - { - /* - ** This is a bit of a hack to avoid a problem - ** when the code does, - ** (some other struct) x - ** ... - ** x->field - */ + ret->sref = sRef_copy (e->sref); - ret->sref = sRef_copy (e->sref); - usymtab_addForceMustAlias (ret->sref, e->sref); - sRef_setTypeFull (ret->sref, c); - DPRINTF (("Cast: %s -> %s", sRef_unparseFull (e->sref), - sRef_unparseFull (ret->sref))); - } - else + DPRINTF (("Cast: -> %s", sRef_unparseFull (ret->sref))); + + if (!sRef_isConst (e->sref)) { - ret->sref = e->sref; - sRef_setTypeFull (ret->sref, c); - DPRINTF (("Cast 2: -> %s", sRef_unparseFull (ret->sref))); + usymtab_addForceMustAlias (ret->sref, e->sref); } + + DPRINTF (("Cast 2: -> %s", sRef_unparseFull (ret->sref))); + sRef_setTypeFull (ret->sref, c); + DPRINTF (("Cast 2: -> %s", sRef_unparseFull (ret->sref))); /* ** we allow @@ -4610,7 +5035,18 @@ exprNode_cast (/*@only@*/ lltok tok, /*@only@*/ exprNode e, /*@only@*/ qtype q) if (ctype_isVoid (c)) /* cast to void is always okay --- discard value */ { - ; + /* evans 2002-07-19: added this warning */ + DPRINTF (("Checking: %s / %s", exprNode_unparse (ret), sRef_unparseFull (ret->sref))); + if (sRef_isFresh (ret->sref)) + { + voptgenerror + (FLG_MUSTFREEFRESH, + message ("New fresh storage %q(type %s) cast to void (not released): %s", + sRef_unparseOpt (ret->sref), + ctype_unparse (exprNode_getType (ret)), + exprNode_unparse (ret)), + exprNode_loc (ret)); + } } else if (ctype_isRealAP (c)) /* casting to array or pointer */ { @@ -4730,16 +5166,38 @@ exprNode_cast (/*@only@*/ lltok tok, /*@only@*/ exprNode e, /*@only@*/ qtype q) } else { - DPRINTF (("No access to: %s / %d", - ctype_unparse (bc), ctype_typeId (bc))); - DPRINTF (("Context %s %s", - bool_unparse (context_inFunctionLike ()), - context_unparse ())); - voptgenerror - (FLG_ABSTRACT, - message ("Cast to abstract type %t: %s", bc, - exprNode_unparse (ret)), - e->loc); + if (ctype_isNumAbstract (bc)) + { + if (exprNode_isNumLiteral (e)) + { + voptgenerror + (FLG_NUMABSTRACTCAST, + message ("Cast from literal to numabstract type %t: %s", bc, + exprNode_unparse (ret)), + e->loc); + } + else + { + voptgenerror + (FLG_NUMABSTRACT, + message ("Cast to numabstract type %t: %s", bc, + exprNode_unparse (ret)), + e->loc); + } + } + else + { + DPRINTF (("No access to: %s / %d", + ctype_unparse (bc), ctype_typeId (bc))); + DPRINTF (("Context %s %s", + bool_unparse (context_inFunctionLike ()), + context_unparse ())); + voptgenerror + (FLG_ABSTRACT, + message ("Cast to abstract type %t: %s", bc, + exprNode_unparse (ret)), + e->loc); + } } } } @@ -4873,6 +5331,7 @@ exprNode_makeOp (/*@keep@*/ exprNode e1, /*@keep@*/ exprNode e2, } ret->val = multiVal_undefined; + ret->kind = XPR_OP; ret->edata = exprData_makeOp (e1, e2, op); @@ -4901,6 +5360,7 @@ exprNode_makeOp (/*@keep@*/ exprNode e1, /*@keep@*/ exprNode e2, tret = ctype_unknown; te1 = exprNode_getType (e1); + DPRINTF (("te1 = %s / %s", exprNode_unparse (e1), ctype_unparse (te1))); te2 = exprNode_getType (e2); @@ -4910,10 +5370,14 @@ exprNode_makeOp (/*@keep@*/ exprNode e1, /*@keep@*/ exprNode e2, if (opid == OR_OP) { + exprNode_produceGuards (e2); ret->guards = guardSet_or (ret->guards, e2->guards); } else if (opid == AND_OP) { + exprNode_produceGuards (e2); /* evans 2003-08-13: need to produce guards for expression */ + /* Shouldn't this have already happened? */ + DPRINTF (("Anding guards: %s / %s", guardSet_unparse (ret->guards), guardSet_unparse (e2->guards))); ret->guards = guardSet_and (ret->guards, e2->guards); } else @@ -4951,243 +5415,310 @@ exprNode_makeOp (/*@keep@*/ exprNode e1, /*@keep@*/ exprNode e2, (opid == AND_OP || opid == OR_OP || opid == EQ_OP || opid == NE_OP)))) { - abstractOpError (tr1, tr2, op, e1, e2, e1->loc, e2->loc); + if (abstractOpError (tr1, tr2, op, e1, e2, e1->loc, e2->loc)) + { + tret = ctype_unknown; + goto skiprest; + } } - else if (ctype_isUnknown (te1) || ctype_isUnknown (te2)) + + if (ctype_isUnknown (te1) || ctype_isUnknown (te2)) { /* unknown types, no comparisons possible */ + goto skiprest; } - else + + switch (opid) { - switch (opid) + case TMULT: /* multiplication and division: */ + case TDIV: /* */ + case MUL_ASSIGN: /* numeric, numeric -> numeric */ + case DIV_ASSIGN: /* */ + if (opid == TMULT || opid == MUL_ASSIGN) + { + ret->val = multiVal_multiply (exprNode_getValue (e1), + exprNode_getValue (e2)); + } + else { - case TMULT: /* multiplication and division: */ - case TDIV: /* */ - case MUL_ASSIGN: /* numeric, numeric -> numeric */ - case DIV_ASSIGN: /* */ + ret->val = multiVal_divide (exprNode_getValue (e1), + exprNode_getValue (e2)); + } + + tret = checkNumerics (tr1, tr2, te1, te2, e1, e2, op); + break; + + case TPLUS: /* addition and subtraction: */ + case TMINUS: /* pointer, int -> pointer */ + case SUB_ASSIGN: /* int, pointer -> pointer */ + case ADD_ASSIGN: /* numeric, numeric -> numeric */ + if (opid == TPLUS || opid == ADD_ASSIGN) + { + ret->val = multiVal_add (exprNode_getValue (e1), + exprNode_getValue (e2)); + } + else + { + ret->val = multiVal_subtract (exprNode_getValue (e1), + exprNode_getValue (e2)); + } + + tr1 = ctype_fixArrayPtr (tr1); + + if ((ctype_isRealPointer (tr1) && !exprNode_isNullValue (e1)) + && (!ctype_isRealPointer (tr2) && ctype_isRealInt (tr2))) + { + /* pointer + int */ - tret = checkNumerics (tr1, tr2, te1, te2, e1, e2, op); - break; + if (context_msgPointerArith ()) + { + voptgenerror + (FLG_POINTERARITH, + message ("Pointer arithmetic (%t, %t): %s", + te1, te2, exprNode_unparse (ret)), + e1->loc); + } - case TPLUS: /* addition and subtraction: */ - case TMINUS: /* pointer, int -> pointer */ - case SUB_ASSIGN: /* int, pointer -> pointer */ - case ADD_ASSIGN: /* numeric, numeric -> numeric */ + /* + ** Swap terms so e1 is always the pointer + */ - tr1 = ctype_fixArrayPtr (tr1); - - if ((ctype_isRealPointer (tr1) && !exprNode_isNullValue (e1)) - && (!ctype_isRealPointer (tr2) && ctype_isRealInt (tr2))) + if (ctype_isRealPointer (tr1)) { - /* pointer + int */ - - if (context_msgPointerArith ()) - { - voptgenerror - (FLG_POINTERARITH, - message ("Pointer arithmetic (%t, %t): %s", - te1, te2, exprNode_unparse (ret)), - e1->loc); - } - - if (sRef_possiblyNull (e1->sref) - && !usymtab_isGuarded (e1->sref)) - { - voptgenerror - (FLG_NULLPOINTERARITH, - message ("Pointer arithmetic involving possibly " - "null pointer %s: %s", - exprNode_unparse (e1), - exprNode_unparse (ret)), - e1->loc); - } - - ret->sref = sRef_copy (e1->sref); - - /* start modifications */ - /* added by Seejo on 4/16/2000 */ - - /* Arithmetic operations on pointers wil modify the size/len/null terminated - status */ - if ((sRef_isPossiblyNullTerminated (e1->sref)) || (sRef_isNullTerminated(e1->sref))) { - //if (sRef_isKnown (e->sref)) { - //ret->sref = sRef_makeAddress (e->sref); - //} - - int val; - /*drl 1-4-2001 - added ugly fixed to stop - program from crashing on point + int +int - one day I'll fix this or ask Seejo wtf the codes supposed to do. */ - - if (!multiVal_isInt (e2->val) ) - break; - /*end drl*/ - - val = (int) multiVal_forceInt (e2->val); - - /* Operator : + or += */ - if ((lltok_getTok (op) == TPLUS) || (lltok_getTok(op) == ADD_ASSIGN)) { - if (sRef_getSize(e1->sref) >= val) {/* Incrementing the pointer by - val should not result in a - size < 0 (size = 0 is ok !) */ - - sRef_setSize (ret->sref, sRef_getSize(e1->sref) - val); - - if (sRef_getLen(e1->sref) == val) { /* i.e. the character at posn val is \0 */ - sRef_setNotNullTerminatedState(ret->sref); - sRef_resetLen (ret->sref); - } else { - sRef_setNullTerminatedState(ret->sref); - sRef_setLen (ret->sref, sRef_getLen(e1->sref) - val); - } - } - } - - /* Operator : - or -= */ - if ((lltok_getTok (op) == TMINUS) || (lltok_getTok (op) == SUB_ASSIGN)) { - if (sRef_getSize(e1->sref) >= 0) { - sRef_setSize (ret->sref, sRef_getSize(e1->sref) + val); - sRef_setLen (ret->sref, sRef_getLen(e1->sref) + val); - } - } + ; } - - /* end modifications */ - - sRef_setNullError (ret->sref); - - /* - ** Fixed for 2.2c: the alias state of ptr + int is dependent, - ** since is points to storage that should not be deallocated - ** through this pointer. - */ - - if (sRef_isOnly (ret->sref) - || sRef_isFresh (ret->sref)) - { - sRef_setAliasKind (ret->sref, AK_DEPENDENT, exprNode_loc (ret)); - } - - tret = e1->typ; + else + { + exprNode_swap (e1, e2); } - else if ((!ctype_isRealPointer(tr1) && ctype_isRealInt (tr1)) - && (ctype_isRealPointer (tr2) && !exprNode_isNullValue (e2))) + + if (sRef_possiblyNull (e1->sref) + && !usymtab_isGuarded (e1->sref)) { - if (context_msgPointerArith ()) - { - voptgenerror - (FLG_POINTERARITH, - message ("Pointer arithmetic (%t, %t): %s", - te1, te2, exprNode_unparse (ret)), - e1->loc); - } - - if (sRef_possiblyNull (e1->sref) - && !usymtab_isGuarded (e1->sref)) - { - voptgenerror - (FLG_NULLPOINTERARITH, - message ("Pointer arithmetic involving possibly " - "null pointer %s: %s", - exprNode_unparse (e2), - exprNode_unparse (ret)), - e2->loc); + voptgenerror + (FLG_NULLPOINTERARITH, + message ("Pointer arithmetic involving possibly " + "null pointer %s: %s", + exprNode_unparse (e1), + exprNode_unparse (ret)), + e1->loc); + } + + ret->sref = sRef_copy (e1->sref); + + /* start modifications */ + /* added by Seejo on 4/16/2000 */ + + /* Arithmetic operations on pointers wil modify the size/len/null terminated + status */ + if ((sRef_isPossiblyNullTerminated (e1->sref)) || (sRef_isNullTerminated(e1->sref))) { + int val; + /*drl 1-4-2002 + added ugly fixed to stop + program from crashing on point + int +int + one day I'll fix this or ask Seejo wtf the codes supposed to do. */ + + if (!multiVal_isInt (e2->val) ) + break; + /*end drl*/ + + val = (int) multiVal_forceInt (e2->val); + + /* Operator : + or += */ + if ((lltok_getTok (op) == TPLUS) || (lltok_getTok(op) == ADD_ASSIGN)) { + if (sRef_getSize(e1->sref) >= val) {/* Incrementing the pointer by + val should not result in a + size < 0 (size = 0 is ok !) */ + + sRef_setSize (ret->sref, sRef_getSize(e1->sref) - val); + + if (sRef_getLen(e1->sref) == val) { /* i.e. the character at posn val is \0 */ + sRef_setNotNullTerminatedState(ret->sref); + sRef_resetLen (ret->sref); + } else { + sRef_setNullTerminatedState(ret->sref); + sRef_setLen (ret->sref, sRef_getLen(e1->sref) - val); } - - ret->sref = sRef_copy (e2->sref); - - /* start modifications */ - /* added by Seejo on 4/16/2000 */ - - /* Arithmetic operations on pointers wil modify the size/len/null terminated - status */ - - if ((sRef_isPossiblyNullTerminated (e2->sref)) || (sRef_isNullTerminated(e2->sref))) { - //if (sRef_isKnown (e->sref)) { - //ret->sref = sRef_makeAddress (e->sref); - //} - - int val = (int) multiVal_forceInt (e1->val); - - /* Operator : + or += */ - if ((lltok_getTok (op) == TPLUS) || (lltok_getTok(op) == ADD_ASSIGN)) { - if (sRef_getSize(e2->sref) >= val) {/* Incrementing the pointer by - val should not result in a - size < 0 (size = 0 is ok !) */ - - sRef_setSize (ret->sref, sRef_getSize(e2->sref) - val); - - if (sRef_getLen(e2->sref) == val) { /* i.e. the character at posn val is \0 */ - sRef_setNotNullTerminatedState(ret->sref); - sRef_resetLen (ret->sref); - } else { - sRef_setNullTerminatedState(ret->sref); - sRef_setLen (ret->sref, sRef_getLen(e2->sref) - val); - } - } - } - - /* Operator : - or -= */ - if ((lltok_getTok (op) == TMINUS) || (lltok_getTok (op) == SUB_ASSIGN)) { - if (sRef_getSize(e2->sref) >= 0) { - sRef_setSize (ret->sref, sRef_getSize(e2->sref) + val); - sRef_setLen (ret->sref, sRef_getLen(e2->sref) + val); - } - } - } - - /* end modifications */ - - sRef_setNullError (ret->sref); - - /* - ** Fixed for 2.2c: the alias state of ptr + int is dependent, - ** since is points to storage that should not be deallocated - ** through this pointer. - */ - - if (sRef_isOnly (ret->sref) - || sRef_isFresh (ret->sref)) { - sRef_setAliasKind (ret->sref, AK_DEPENDENT, exprNode_loc (ret)); } - - tret = e2->typ; - ret->sref = e2->sref; } - else + + /* Operator : - or -= */ + if ((lltok_getTok (op) == TMINUS) || (lltok_getTok (op) == SUB_ASSIGN)) { + if (sRef_getSize(e1->sref) >= 0) { + sRef_setSize (ret->sref, sRef_getSize(e1->sref) + val); + sRef_setLen (ret->sref, sRef_getLen(e1->sref) + val); + } + } + } + + /* end modifications */ + + sRef_setNullError (ret->sref); + + /* + ** Fixed for 2.2c: the alias state of ptr + int is dependent, + ** since is points to storage that should not be deallocated + ** through this pointer. + */ + + if (sRef_isOnly (ret->sref) + || sRef_isFresh (ret->sref)) { - tret = checkNumerics (tr1, tr2, te1, te2, e1, e2, op); + sRef_setAliasKind (ret->sref, AK_DEPENDENT, exprNode_loc (ret)); } - break; + tret = e1->typ; + } + else if ((!ctype_isRealPointer(tr1) && ctype_isRealInt (tr1)) + && (ctype_isRealPointer (tr2) && !exprNode_isNullValue (e2))) + { + if (context_msgPointerArith ()) + { + voptgenerror + (FLG_POINTERARITH, + message ("Pointer arithmetic (%t, %t): %s", + te1, te2, exprNode_unparse (ret)), + e1->loc); + } + + if (sRef_possiblyNull (e1->sref) + && !usymtab_isGuarded (e1->sref)) + { + voptgenerror + (FLG_NULLPOINTERARITH, + message ("Pointer arithmetic involving possibly " + "null pointer %s: %s", + exprNode_unparse (e2), + exprNode_unparse (ret)), + e2->loc); + } + + ret->sref = sRef_copy (e2->sref); + + /* start modifications */ + /* added by Seejo on 4/16/2000 */ + + /* Arithmetic operations on pointers wil modify the size/len/null terminated + status */ + + if ((sRef_isPossiblyNullTerminated (e2->sref)) || (sRef_isNullTerminated(e2->sref))) { + if (multiVal_isDefined (e1->val)) + { + int val = (int) multiVal_forceInt (e1->val); + + /* Operator : + or += */ + if ((lltok_getTok (op) == TPLUS) || (lltok_getTok(op) == ADD_ASSIGN)) { + if (sRef_getSize(e2->sref) >= val) {/* Incrementing the pointer by + val should not result in a + size < 0 (size = 0 is ok !) */ + + sRef_setSize (ret->sref, sRef_getSize(e2->sref) - val); + + if (sRef_getLen(e2->sref) == val) { /* i.e. the character at posn val is \0 */ + sRef_setNotNullTerminatedState(ret->sref); + sRef_resetLen (ret->sref); + } else { + sRef_setNullTerminatedState(ret->sref); + sRef_setLen (ret->sref, sRef_getLen(e2->sref) - val); + } + } + } + + /* Operator : - or -= */ + if ((lltok_getTok (op) == TMINUS) || (lltok_getTok (op) == SUB_ASSIGN)) { + if (sRef_getSize(e2->sref) >= 0) { + sRef_setSize (ret->sref, sRef_getSize(e2->sref) + val); + sRef_setLen (ret->sref, sRef_getLen(e2->sref) + val); + } + } + } + } - case LEFT_ASSIGN: /* Shifts: should be unsigned values */ - case RIGHT_ASSIGN: - case LEFT_OP: - case RIGHT_OP: - case TAMPERSAND: /* bitwise & */ - case AND_ASSIGN: - case TCIRC: /* ^ (XOR) */ - case TBAR: - case XOR_ASSIGN: - case OR_ASSIGN: + /* end modifications */ + + sRef_setNullError (ret->sref); + + /* + ** Fixed for 2.2c: the alias state of ptr + int is dependent, + ** since is points to storage that should not be deallocated + ** through this pointer. + */ + + if (sRef_isOnly (ret->sref) + || sRef_isFresh (ret->sref)) { + sRef_setAliasKind (ret->sref, AK_DEPENDENT, exprNode_loc (ret)); + } + + tret = e2->typ; + ret->sref = e2->sref; + } + else + { + tret = checkNumerics (tr1, tr2, te1, te2, e1, e2, op); + } + + break; + + case LEFT_ASSIGN: + case RIGHT_ASSIGN: + case LEFT_OP: + case RIGHT_OP: + case TAMPERSAND: /* bitwise & */ + case AND_ASSIGN: + case TCIRC: /* ^ (XOR) */ + case TBAR: + case XOR_ASSIGN: + case OR_ASSIGN: + { + bool reported = FALSE; + + /* + ** Shift Operator + */ + + if (opid == LEFT_OP || opid == LEFT_ASSIGN + || opid == RIGHT_OP || opid == RIGHT_ASSIGN) { - bool reported = FALSE; - flagcode code = FLG_BITWISEOPS; + /* + ** evans 2002-01-01: fixed this to follow ISO 6.5.7. + */ - if (opid == LEFT_OP || opid == LEFT_ASSIGN - || opid == RIGHT_OP || opid == RIGHT_ASSIGN) { - code = FLG_SHIFTSIGNED; - } - + if (!ctype_isUnsigned (tr2) + && !exprNode_isNonNegative (e2)) + { + reported = optgenerror + (FLG_SHIFTNEGATIVE, + message ("Right operand of %s may be negative (%t): %s", + lltok_unparse (op), te2, + exprNode_unparse (ret)), + e2->loc); + } + + if (!ctype_isUnsigned (tr1) + && !exprNode_isNonNegative (e1)) + { + reported = optgenerror + (FLG_SHIFTIMPLEMENTATION, + message ("Left operand of %s may be negative (%t): %s", + lltok_unparse (op), te1, + exprNode_unparse (ret)), + e1->loc); + } + + /* + ** Should check size of right operand also... + */ + + } + else + { if (!ctype_isUnsigned (tr1)) { if (exprNode_isNonNegative (e1)) { ; } else { reported = optgenerror - (code, + (FLG_BITWISEOPS, message ("Left operand of %s is not unsigned value (%t): %s", lltok_unparse (op), te1, exprNode_unparse (ret)), @@ -5200,13 +5731,11 @@ exprNode_makeOp (/*@keep@*/ exprNode e1, /*@keep@*/ exprNode e2, } else { - /* right need not be signed for shifts */ - if (code != FLG_SHIFTSIGNED - && !ctype_isUnsigned (tr2)) + if (!ctype_isUnsigned (tr2)) { if (!exprNode_isNonNegative (e2)) { reported = optgenerror - (code, + (FLG_BITWISEOPS, message ("Right operand of %s is not unsigned value (%t): %s", lltok_unparse (op), te2, exprNode_unparse (ret)), @@ -5214,243 +5743,276 @@ exprNode_makeOp (/*@keep@*/ exprNode e1, /*@keep@*/ exprNode e2, } } } - - if (!reported) - { - if (!checkIntegral (e1, e2, ret, op)) { - te1 = ctype_unknown; - } - } - - DPRINTF (("Set: %s", ctype_unparse (te1))); - - /* - ** tret is the widest type of te1 and te2 - */ - - tret = ctype_widest (te1, te2); - break; } - case MOD_ASSIGN: - case TPERCENT: - if (checkIntegral (e1, e2, ret, op)) { - tret = te1; - } else { - tret = ctype_unknown; + + if (!reported) + { + if (!checkIntegral (e1, e2, ret, op)) { + te1 = ctype_unknown; + } } - break; - case EQ_OP: - case NE_OP: - case TLT: /* comparisons */ - case TGT: /* numeric, numeric -> bool */ - if ((ctype_isReal (tr1) && !ctype_isInt (tr1)) - || (ctype_isReal (tr2) && !ctype_isInt (tr2))) + + DPRINTF (("Set: %s", ctype_unparse (te1))); + + /* + ** tret is the widest type of te1 and te2 + */ + + tret = ctype_widest (te1, te2); + break; + } + case MOD_ASSIGN: + case TPERCENT: + if (checkIntegral (e1, e2, ret, op)) { + tret = te1; + } else { + tret = ctype_unknown; + } + break; + case EQ_OP: + case NE_OP: + case TLT: /* comparisons */ + case TGT: /* numeric, numeric -> bool */ + + DPRINTF (("Here we go: %s / %s", + ctype_unparse (tr1), ctype_unparse (tr2))); + + if ((ctype_isReal (tr1) && !ctype_isInt (tr1)) + || (ctype_isReal (tr2) && !ctype_isInt (tr2))) + { + ctype rtype = tr1; + bool fepsilon = FALSE; + + if (!ctype_isReal (rtype) || ctype_isInt (rtype)) { - ctype rtype = tr1; - bool fepsilon = FALSE; - - if (!ctype_isReal (rtype) || ctype_isInt (rtype)) - { - rtype = tr2; - } + rtype = tr2; + } + + if (opid == TLT || opid == TGT) + { + uentry ue1 = exprNode_getUentry (e1); + uentry ue2 = exprNode_getUentry (e2); + + /* + ** FLT_EPSILON, etc. really is a variable, not + ** a constant. + */ - if (opid == TLT || opid == TGT) + if (uentry_isVariable (ue1)) { - uentry ue1 = exprNode_getUentry (e1); - uentry ue2 = exprNode_getUentry (e2); - - /* - ** FLT_EPSILON, etc. really is a variable, not - ** a constant. - */ - - if (uentry_isVariable (ue1)) + cstring uname = uentry_rawName (ue1); + + if (cstring_equalLit (uname, "FLT_EPSILON") + || cstring_equalLit (uname, "DBL_EPSILON") + || cstring_equalLit (uname, "LDBL_EPSILON")) { - cstring uname = uentry_rawName (ue1); - - if (cstring_equalLit (uname, "FLT_EPSILON") - || cstring_equalLit (uname, "DBL_EPSILON") - || cstring_equalLit (uname, "LDBL_EPSILON")) - { - fepsilon = TRUE; - } + fepsilon = TRUE; } - - if (uentry_isVariable (ue2)) + } + + if (uentry_isVariable (ue2)) + { + cstring uname = uentry_rawName (ue2); + + if (cstring_equalLit (uname, "FLT_EPSILON") + || cstring_equalLit (uname, "DBL_EPSILON") + || cstring_equalLit (uname, "LDBL_EPSILON")) { - cstring uname = uentry_rawName (ue2); - - if (cstring_equalLit (uname, "FLT_EPSILON") - || cstring_equalLit (uname, "DBL_EPSILON") - || cstring_equalLit (uname, "LDBL_EPSILON")) - { - fepsilon = TRUE; - } + fepsilon = TRUE; } } - - if (fepsilon) + } + + if (fepsilon) + { + ; /* Don't complain. */ + } + else + { + if (opid == EQ_OP || opid == NE_OP) { - ; /* Don't complain. */ + voptgenerror + (FLG_REALCOMPARE, + message ("Dangerous equality comparison involving %s types: %s", + ctype_unparse (rtype), + exprNode_unparse (ret)), + ret->loc); } else { voptgenerror - (FLG_REALCOMPARE, - message ("Dangerous comparison involving %s types: %s", + (FLG_REALRELATECOMPARE, + message ("Possibly dangerous relational comparison involving %s types: %s", ctype_unparse (rtype), exprNode_unparse (ret)), ret->loc); } } - /*@fallthrough@*/ - case LE_OP: - case GE_OP: - - /* - ** Types should match. - */ - - if (!exprNode_matchTypes (e1, e2)) + } + /*@fallthrough@*/ + case LE_OP: + case GE_OP: + + /* + ** Types should match. + */ + + DPRINTF (("Match types: %s / %s", exprNode_unparse (e1), + exprNode_unparse (e2))); + + if (!exprNode_matchTypes (e1, e2)) + { + hasError = gentypeerror + (te1, e1, te2, e2, + message ("Operands of %s have incompatible types (%t, %t): %s", + lltok_unparse (op), te1, te2, exprNode_unparse (ret)), + e1->loc); + + } + + if (hasError + || (ctype_isForceRealNumeric (&tr1) + && ctype_isForceRealNumeric (&tr2)) || + (ctype_isRealPointer (tr1) && ctype_isRealPointer (tr2))) + { + ; /* okay */ + } + else + { + if ((ctype_isRealNumeric (tr1) && ctype_isRealPointer (tr2)) || + (ctype_isRealPointer (tr1) && ctype_isRealNumeric (tr2))) { - hasError = gentypeerror - (te1, e1, te2, e2, - message ("Operands of %s have incompatible types (%t, %t): %s", - lltok_unparse (op), te1, te2, exprNode_unparse (ret)), + voptgenerror + (FLG_PTRNUMCOMPARE, + message ("Comparison of pointer and numeric (%t, %t): %s", + te1, te2, exprNode_unparse (ret)), e1->loc); - } - - if (hasError - || (ctype_isForceRealNumeric (&tr1) - && ctype_isForceRealNumeric (&tr2)) || - (ctype_isRealPointer (tr1) && ctype_isRealPointer (tr2))) + else { - ; /* okay */ + (void) checkNumerics (tr1, tr2, te1, te2, e1, e2, op); } - else + tret = ctype_bool; + } + + /* certain comparisons on unsigned's and zero look suspicious */ + + if (opid == TLT || opid == LE_OP || opid == GE_OP) + { + if ((ctype_isUnsigned (tr1) && exprNode_isZero (e2)) + || (ctype_isUnsigned (tr2) && exprNode_isZero (e1))) { - if ((ctype_isRealNumeric (tr1) && ctype_isRealPointer (tr2)) || - (ctype_isRealPointer (tr1) && ctype_isRealNumeric (tr2))) - { - voptgenerror - (FLG_PTRNUMCOMPARE, - message ("Comparison of pointer and numeric (%t, %t): %s", - te1, te2, exprNode_unparse (ret)), - e1->loc); - } - else - { - (void) checkNumerics (tr1, tr2, te1, te2, e1, e2, op); - } - tret = ctype_bool; + voptgenerror + (FLG_UNSIGNEDCOMPARE, + message ("Comparison of unsigned value involving zero: %s", + exprNode_unparse (ret)), + e1->loc); } - - /* EQ_OP should NOT be used with booleans (unless one is FALSE) */ + } + + /* EQ_OP should NOT be used with booleans (unless one is FALSE) */ + + if ((opid == EQ_OP || opid == NE_OP) && + ctype_isDirectBool (tr1) && ctype_isDirectBool (tr2)) + { + /* + ** is one a variable? + */ - if ((opid == EQ_OP || opid == NE_OP) && - ctype_isDirectBool (tr1) && ctype_isDirectBool (tr2)) + if (uentry_isVariable (exprNode_getUentry (e1)) + || uentry_isVariable (exprNode_getUentry (e2))) { /* - ** is one a variable? + ** comparisons with FALSE are okay */ - - if (uentry_isVariable (exprNode_getUentry (e1)) - || uentry_isVariable (exprNode_getUentry (e2))) + + if (exprNode_isFalseConstant (e1) + || exprNode_isFalseConstant (e2)) { - /* - ** comparisons with FALSE are okay - */ - - if (exprNode_isFalseConstant (e1) - || exprNode_isFalseConstant (e2)) - { - ; - } - else - { - voptgenerror - (FLG_BOOLCOMPARE, - message - ("Use of %q with %s variables (risks inconsistency because " - "of multiple true values): %s", - cstring_makeLiteral ((opid == EQ_OP) ? "==" : "!="), - context_printBoolName (), exprNode_unparse (ret)), - e1->loc); - } + ; + } + else + { + voptgenerror + (FLG_BOOLCOMPARE, + message + ("Use of %q with %s variables (risks inconsistency because " + "of multiple true values): %s", + cstring_makeLiteral ((opid == EQ_OP) ? "==" : "!="), + context_printBoolName (), exprNode_unparse (ret)), + e1->loc); } } - break; - - case AND_OP: /* bool, bool -> bool */ - case OR_OP: - - if (ctype_isForceRealBool (&tr1) && ctype_isForceRealBool (&tr2)) - { - ; - } - else + } + break; + + case AND_OP: /* bool, bool -> bool */ + case OR_OP: + if (ctype_isForceRealBool (&tr1) && ctype_isForceRealBool (&tr2)) + { + ; + } + else + { + if (context_maybeSet (FLG_BOOLOPS)) { - if (context_maybeSet (FLG_BOOLOPS)) + if (!ctype_isRealBool (te1) && !ctype_isRealBool (te2)) { - if (!ctype_isRealBool (te1) && !ctype_isRealBool (te2)) - { - if (ctype_sameName (te1, te2)) - { - voptgenerror - (FLG_BOOLOPS, - message ("Operands of %s are non-boolean (%t): %s", - lltok_unparse (op), te1, - exprNode_unparse (ret)), - e1->loc); - } - else - { - voptgenerror - (FLG_BOOLOPS, - message - ("Operands of %s are non-booleans (%t, %t): %s", - lltok_unparse (op), te1, te2, exprNode_unparse (ret)), - e1->loc); - } - } - else if (!ctype_isRealBool (te1)) + if (ctype_sameName (te1, te2)) { voptgenerror (FLG_BOOLOPS, - message ("Left operand of %s is non-boolean (%t): %s", - lltok_unparse (op), te1, exprNode_unparse (ret)), + message ("Operands of %s are non-boolean (%t): %s", + lltok_unparse (op), te1, + exprNode_unparse (ret)), e1->loc); } - else if (!ctype_isRealBool (te2)) - { - voptgenerror - (FLG_BOOLOPS, - message ("Right operand of %s is non-boolean (%t): %s", - lltok_unparse (op), te2, exprNode_unparse (ret)), - e2->loc); - } else { - ; + voptgenerror + (FLG_BOOLOPS, + message + ("Operands of %s are non-booleans (%t, %t): %s", + lltok_unparse (op), te1, te2, exprNode_unparse (ret)), + e1->loc); } } - tret = ctype_bool; + else if (!ctype_isRealBool (te1)) + { + voptgenerror + (FLG_BOOLOPS, + message ("Left operand of %s is non-boolean (%t): %s", + lltok_unparse (op), te1, exprNode_unparse (ret)), + e1->loc); + } + else if (!ctype_isRealBool (te2)) + { + voptgenerror + (FLG_BOOLOPS, + message ("Right operand of %s is non-boolean (%t): %s", + lltok_unparse (op), te2, exprNode_unparse (ret)), + e2->loc); + } + else + { + ; + } } - break; - default: { - llfatalbug - (cstring_makeLiteral - ("There has been a problem in the parser. This is believed to result " - "from a problem with bison v. 1.25. Please try rebuidling LCLint " - "using the pre-compiled grammar files by commenting out the " - "BISON= line in the top-level Makefile.")); - } + tret = ctype_bool; } + break; + default: + llfatalbug + (cstring_makeLiteral + ("There has been a problem in the parser. This is believed to result " + "from a problem with bison v. 1.25. Please try rebuidling Splint " + "using the pre-compiled grammar files by commenting out the " + "BISON= line in the top-level Makefile.")); } - DPRINTF (("Return type: %s", ctype_unparse (tret))); +skiprest: ret->typ = tret; + DPRINTF (("Return type %s: %s", exprNode_unparse (ret), ctype_unparse (tret))); exprNode_checkUse (ret, e1->sref, e1->loc); exprNode_mergeUSs (ret, e2); @@ -5514,11 +6076,11 @@ void exprNode_checkAssignMod (exprNode e1, exprNode ret) } exprNode -exprNode_assign (/*@only@*/ exprNode e1, - /*@only@*/ exprNode e2, /*@only@*/ lltok op) +exprNode_assign (/*@only@*/ exprNode e1, /*@only@*/ exprNode e2, /*@only@*/ lltok op) { bool isalloc = FALSE; bool isjustalloc = FALSE; + bool noalias = FALSE; exprNode ret; DPRINTF (("%s [%s] <- %s [%s]", @@ -5530,7 +6092,22 @@ exprNode_assign (/*@only@*/ exprNode e1, if (lltok_getTok (op) != TASSIGN) { ret = exprNode_makeOp (e1, e2, op); - } + + DPRINTF (("Here goes: %s %s", + ctype_unparse (e1->typ), + ctype_unparse (e2->typ))); + + if (exprNode_isDefined (e1) + && exprNode_isDefined (e2)) + { + if (ctype_isNumeric (e2->typ) + || ctype_isNumeric (e1->typ)) + { + /* Its a pointer arithmetic expression like ptr += i */ + noalias = TRUE; + } + } + } else { ret = exprNode_createPartialCopy (e1); @@ -5614,6 +6191,8 @@ exprNode_assign (/*@only@*/ exprNode e1, sRef_unparse (e1->sref)), g_currentloc); } + + exprNode_checkAssignMod (e1, ret); /* evans 2001-07-22 */ } } else @@ -5628,11 +6207,37 @@ exprNode_assign (/*@only@*/ exprNode e1, ctype te1 = exprNode_getType (e1); ctype te2 = exprNode_getType (e2); - if (!ctype_forceMatch (te1, te2)) + if (ctype_isVoid (te2)) + { + (void) gentypeerror + (te2, e2, te1, e1, + message ("Assignment of void value to %t: %s %s %s", + te1, exprNode_unparse (e1), + lltok_unparse (op), + exprNode_unparse (e2)), + e1->loc); + } + else if (!ctype_forceMatch (te1, te2)) { if (exprNode_matchLiteral (te1, e2)) { - ; + DPRINTF (("Literals match: %s / %s", + ctype_unparse (te1), exprNode_unparse (e2))); + if (ctype_isNumAbstract (te1)) { + if (!context_flagOn (FLG_NUMABSTRACTLIT, e1->loc)) { + (void) llgenhinterror + (FLG_NUMABSTRACT, + message + ("Assignment of %t literal to numabstract type %t: %s %s %s", + te2, te1, + exprNode_unparse (e1), + lltok_unparse (op), + exprNode_unparse (e2)), + cstring_makeLiteral + ("Use +numabstractlit to allow numeric literals to be used as numabstract values"), + e1->loc); + } + } } else { @@ -5645,12 +6250,25 @@ exprNode_assign (/*@only@*/ exprNode e1, e1->loc); } } + else + { + /* Type checks okay */ + } } exprNode_mergeUSs (ret, e2); exprNode_checkUse (ret, e2->sref, e2->loc); - doAssign (e1, e2, FALSE); + DPRINTF (("Do assign! %s %s", exprNode_unparse (e1), exprNode_unparse (e2))); + if (noalias) + { + ; + } + else + { + doAssign (e1, e2, FALSE); + } + ret->sref = e1->sref; } else @@ -5658,7 +6276,7 @@ exprNode_assign (/*@only@*/ exprNode e1, if (exprNode_isDefined (e2)) { exprNode_mergeUSs (ret, e2); - exprNode_checkUse (ret, e2->sref, e2->loc); + exprNode_checkUse (ret, e2->sref, e2->loc); } } @@ -5684,11 +6302,11 @@ exprNode_assign (/*@only@*/ exprNode e1, /* ** be careful! this defines e1->sref. */ - - if (!sRef_isMacroParamRef (e1->sref)) - { - exprNode_checkSet (ret, e1->sref); - } + + /* evans 2001-07-22: removed if (!sRef_isMacroParamRef (e1->sref)) */ + + DPRINTF (("Setting: %s -> %s", exprNode_unparse (ret), sRef_unparse (e1->sref))); + exprNode_checkSet (ret, e1->sref); if (isjustalloc) { @@ -5839,7 +6457,7 @@ exprNode_cond (/*@keep@*/ exprNode pred, /*@keep@*/ exprNode ifclause, } else /* all errors! */ { - ret = exprNode_createLoc (ctype_unknown, g_currentloc); + ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc)); } } @@ -5878,8 +6496,8 @@ exprNode_vaArg (/*@only@*/ lltok tok, /*@only@*/ exprNode arg, /*@only@*/ qtype */ if (!ctype_isUA (targ) || - (!usymId_equal (ctype_typeId (targ), - usymtab_getTypeId (cstring_makeLiteralTemp ("va_list"))))) + (!typeId_equal (ctype_typeId (targ), + usymtab_getTypeId (cstring_makeLiteralTemp ("va_list"))))) { voptgenerror (FLG_TYPE, @@ -6045,6 +6663,7 @@ exprNode_mustBreak (exprNode e) { return e->mustBreak; } + return FALSE; } @@ -6167,7 +6786,7 @@ exprNode exprNode_concat (/*@only@*/ exprNode e1, /*@only@*/ exprNode e2) { voptgenerror (FLG_CASEBREAK, cstring_makeLiteral - ("Fall through case (no preceeding break)"), + ("Fall through case (no preceding break)"), e2->loc); } } @@ -6183,13 +6802,13 @@ exprNode exprNode_concat (/*@only@*/ exprNode e1, /*@only@*/ exprNode e2) usymtab_setMustBreak (); } + DPRINTF (("==> %s", exprNode_unparse (ret))); return ret; } exprNode exprNode_createTok (/*@only@*/ lltok t) { - exprNode ret; /*@i23 if on same line, bad things happen...!@*/ - ret = exprNode_create (ctype_unknown); + exprNode ret = exprNode_create (ctype_unknown); ret->kind = XPR_TOK; ret->edata = exprData_makeTok (t); return ret; @@ -6199,7 +6818,7 @@ exprNode exprNode_statement (/*@only@*/ exprNode e, /*@only@*/ lltok t) { if (!exprNode_isError (e)) { - exprNode_checkStatement(e); + exprChecks_checkStatementEffect(e); } return (exprNode_statementError (e, t)); @@ -6254,6 +6873,36 @@ void exprNode_produceGuards (exprNode pred) } } +exprNode exprNode_compoundStatementExpression (/*@only@*/ lltok tlparen, /*@only@*/ exprNode e) +{ + exprNode laststmt; + + DPRINTF (("Compound: %s", exprNode_unparse (e))); + + if (!context_flagOn (FLG_GNUEXTENSIONS, exprNode_loc (e))) + { + (void) llgenhinterror + (FLG_SYNTAX, + message ("Compound statement expressions is not supported by ISO C99"), + message ("Use +gnuextensions to allow compound statement expressions (and other GNU language extensions) " + "without this warning"), + exprNode_loc (e)); + } + + /* + ** The type of a compoundStatementExpression is the type of the last statement + */ + + llassert (exprNode_isBlock (e)); + laststmt = exprNode_lastStatement (e); + + DPRINTF (("Last statement: %s / %s", exprNode_unparse (laststmt), ctype_unparse (exprNode_getType (laststmt)))); + DPRINTF (("e: %s", exprNode_unparse (e))); + e->typ = exprNode_getType (laststmt); + return exprNode_addParens (tlparen, e); +} + + exprNode exprNode_makeBlock (/*@only@*/ exprNode e) { exprNode ret = exprNode_createPartialCopy (e); @@ -6265,8 +6914,10 @@ exprNode exprNode_makeBlock (/*@only@*/ exprNode e) ret->mustBreak = e->mustBreak; } + DPRINTF (("Block e: %s", exprNode_unparse (e))); ret->edata = exprData_makeSingle (e); ret->kind = XPR_BLOCK; + DPRINTF (("Block: %s", exprNode_unparse (ret))); return ret; } @@ -6275,6 +6926,12 @@ bool exprNode_isBlock (exprNode e) return (exprNode_isDefined (e) && ((e)->kind == XPR_BLOCK)); } + +bool exprNode_isStatement (exprNode e) +{ + return (exprNode_isDefined (e) + && ((e)->kind == XPR_STMT)); +} bool exprNode_isAssign (exprNode e) { @@ -6293,6 +6950,27 @@ bool exprNode_isEmptyStatement (exprNode e) && (lltok_isSemi (exprData_getTok (e->edata)))); } +bool exprNode_isMultiStatement (exprNode e) +{ + return (exprNode_isDefined (e) + && ((e->kind == XPR_FOR) + || (e->kind == XPR_FORPRED) + || (e->kind == XPR_IF) + || (e->kind == XPR_IFELSE) + || (e->kind == XPR_WHILE) + || (e->kind == XPR_WHILEPRED) + || (e->kind == XPR_DOWHILE) + || (e->kind == XPR_BLOCK) + || (e->kind == XPR_STMT) + || (e->kind == XPR_STMTLIST) + || (e->kind == XPR_SWITCH))); +} + +void exprNode_checkIfPred (exprNode pred) +{ + exprNode_checkPred (cstring_makeLiteralTemp ("if"), pred); +} + exprNode exprNode_if (/*@only@*/ exprNode pred, /*@only@*/ exprNode tclause) { exprNode ret; @@ -6326,7 +7004,7 @@ exprNode exprNode_if (/*@only@*/ exprNode pred, /*@only@*/ exprNode tclause) { if (exprNode_isError (tclause)) { - ret = exprNode_createLoc (ctype_unknown, g_currentloc); + ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc)); } else { @@ -6342,8 +7020,7 @@ exprNode exprNode_if (/*@only@*/ exprNode pred, /*@only@*/ exprNode tclause) message ("Predicate always exits: %s", exprNode_unparse (pred)), exprNode_loc (pred)); } - - exprNode_checkPred (cstring_makeLiteralTemp ("if"), pred); + exprNode_checkUse (pred, pred->sref, pred->loc); if (!exprNode_isError (tclause)) @@ -6448,7 +7125,7 @@ exprNode exprNode_ifelse (/*@only@*/ exprNode pred, { if (exprNode_isError (eclause)) { - ret = exprNode_createLoc (ctype_unknown, g_currentloc); + ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc)); } else { @@ -6472,9 +7149,7 @@ exprNode exprNode_ifelse (/*@only@*/ exprNode pred, exprNode_loc (pred)); } - exprNode_checkPred (cstring_makeLiteralTemp ("if"), pred); exprNode_checkUse (ret, pred->sref, pred->loc); - exprNode_mergeCondUSs (ret, tclause, eclause); } @@ -6527,6 +7202,9 @@ checkSwitchExpr (exprNode test, /*@dependent@*/ exprNode e, /*@out@*/ bool *allp exprNodeSList_elements (el, current) { + + DPRINTF ((message("checkSwitchExpr current = %s ", exprNode_unparse(current) ) )); + if (exprNode_isDefined (current)) { switch (current->kind) @@ -6536,7 +7214,7 @@ checkSwitchExpr (exprNode test, /*@dependent@*/ exprNode e, /*@out@*/ bool *allp if (hasDefault) { voptgenerror - (FLG_CONTROL, + (FLG_DUPLICATECASES, message ("Duplicate default cases in switch"), exprNode_loc (current)); } @@ -6564,7 +7242,7 @@ checkSwitchExpr (exprNode test, /*@dependent@*/ exprNode e, /*@out@*/ bool *allp (/*@-usedef@*/usedEnums/*@=usedef@*/, cname)) { voptgenerror - (FLG_CONTROL, + (FLG_DUPLICATECASES, message ("Duplicate case in switch: %s", cname), current->loc); @@ -6631,6 +7309,7 @@ checkSwitchExpr (exprNode test, /*@dependent@*/ exprNode e, /*@out@*/ bool *allp g_currentloc); enumNameSList_free (unused); + *allpaths = FALSE; /* evans 2002-01-01 */ } else { @@ -6852,7 +7531,7 @@ exprNode exprNode_while (/*@keep@*/ exprNode t, /*@keep@*/ exprNode b) { if (exprNode_isError (b)) { - ret = exprNode_createLoc (ctype_unknown, g_currentloc); + ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc)); } else { @@ -6897,7 +7576,7 @@ exprNode exprNode_while (/*@keep@*/ exprNode t, /*@keep@*/ exprNode b) if (exprNode_isDefined (t) && exprNode_mustEscape (t)) { voptgenerror - (FLG_CONTROL, + (FLG_ALWAYSEXITS, message ("Predicate always exits: %s", exprNode_unparse (t)), exprNode_loc (t)); } @@ -6943,12 +7622,15 @@ exprNode exprNode_while (/*@keep@*/ exprNode t, /*@keep@*/ exprNode b) exprNode exprNode_doWhile (/*@only@*/ exprNode b, /*@only@*/ exprNode t) { exprNode ret; - + + DPRINTF (("Do while: %s / %s", + exprNode_unparse (b), exprNode_unparse (t))); + if (exprNode_isError (t)) { if (exprNode_isError (b)) { - ret = exprNode_createLoc (ctype_unknown, g_currentloc); + ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc)); } else { @@ -6958,11 +7640,15 @@ exprNode exprNode_doWhile (/*@only@*/ exprNode b, /*@only@*/ exprNode t) exprNode_checkUse (ret, b->sref, b->loc); ret->exitCode = b->exitCode; ret->canBreak = b->canBreak; - ret->mustBreak = b->mustBreak; + ret->mustBreak = FALSE; } } else { + DPRINTF (("Do while: %s / %s", + exitkind_unparse (t->exitCode), + exitkind_unparse (b->exitCode))); + ret = exprNode_createPartialCopy (t); exprNode_checkPred (cstring_makeLiteralTemp ("while"), t); @@ -6976,24 +7662,102 @@ exprNode exprNode_doWhile (/*@only@*/ exprNode b, /*@only@*/ exprNode t) ret->msets = sRefSet_copyInto (ret->msets, b->msets); ret->uses = sRefSet_copyInto (ret->uses, b->uses); - /* left this out --- causes and aliasing bug (infinite loop) - should be detected?? */ + /* left this out --- causes and aliasing bug (infinite loop) + should be detected?? */ + + exprNode_checkUse (ret, b->sref, b->loc); + exprNode_mergeUSs (ret, t); + exprNode_checkUse (ret, t->sref, t->loc); + + /* evans 2001-10-05: while loop can break */ + ret->exitCode = exitkind_makeConditional (b->exitCode); + + DPRINTF (("Do while: %s", + exitkind_unparse (ret->exitCode))); + + ret->canBreak = b->canBreak; + + /* Always FALSE for doWhile loops - break's when test is false */ + ret->mustBreak = FALSE; /* b->mustBreak; */ + } + } + + context_exitDoWhileClause (t); + + ret->kind = XPR_DOWHILE; + ret->edata = exprData_makePair (t, b); + return ret; +} + +bool exprNode_loopMustExec (exprNode forPred) +{ + /* + ** Returns true if it is obvious that the loop always executes at least once + ** + ** For now, we only identify the most obvious cases. Should be true anytime + ** we can prove init => !test. + */ + + if (exprNode_isDefined (forPred)) + { + exprNode init, test, inc; + exprData edata; + + llassert (forPred->kind == XPR_FORPRED); + + edata = forPred->edata; + init = exprData_getTripleInit (edata); + test = exprData_getTripleTest (edata); + inc = exprData_getTripleInc (edata); + + if (exprNode_isAssign (init)) + { + exprNode loopVar = exprData_getOpA (init->edata); + exprNode loopInit = exprData_getOpB (init->edata); + + if (exprNode_isDefined (test) && test->kind == XPR_OP) + { + exprNode testVar = exprData_getOpA (test->edata); + exprNode testVal = exprData_getOpB (test->edata); + lltok comp = exprData_getOpTok (test->edata); + int opid = lltok_getTok (comp); + + DPRINTF (("Same storage: %s / %s", exprNode_unparse (loopVar), + exprNode_unparse (testVar))); + + if (exprNode_sameStorage (loopVar, testVar)) + { + multiVal valinit = exprNode_getValue (loopInit); + multiVal valtest = exprNode_getValue (testVal); + + DPRINTF (("Values: %s / %s", multiVal_unparse (valinit), + multiVal_unparse (valtest))); - exprNode_checkUse (ret, b->sref, b->loc); - exprNode_mergeUSs (ret, t); - exprNode_checkUse (ret, t->sref, t->loc); + if (multiVal_isInt (valinit) && multiVal_isInt (valtest)) + { + long v1 = multiVal_forceInt (valinit); + long v2 = multiVal_forceInt (valtest); - ret->exitCode = b->exitCode; - ret->canBreak = b->canBreak; - ret->mustBreak = b->mustBreak; + DPRINTF (("Here: %ld %ld", v1, v2)); + + if ((opid == EQ_OP && v1 < v2) + || (opid == NE_OP && v1 != v2) + || (opid == TLT && v1 <= v2) + || (opid == TGT && v1 >= v2) + || (opid == LE_OP && v1 < v2) + || (opid == GE_OP && v1 > v2)) + { + DPRINTF (("mustexec if inc")); + return TRUE; + } + } + } + } } } - - context_exitDoWhileClause (t); - ret->kind = XPR_DOWHILE; - ret->edata = exprData_makePair (t, b); - return ret; + DPRINTF (("loop must exec: FALSE")); + return FALSE; } exprNode exprNode_for (/*@keep@*/ exprNode inc, /*@keep@*/ exprNode body) @@ -7049,14 +7813,13 @@ exprNode exprNode_for (/*@keep@*/ exprNode inc, /*@keep@*/ exprNode body) ret->exitCode = exitkind_makeConditional (body->exitCode); - exprNode_mergeUSs (inc, body); + exprNode_mergeUSs (inc, body); if (exprNode_isDefined (inc)) { exprNode tmp; context_setMessageAnnote (cstring_makeLiteral ("in post loop increment")); - tmp = exprNode_effect (exprData_getTripleInc (inc->edata)); exprNode_freeShallow (tmp); @@ -7428,7 +8191,7 @@ exprNode exprNode_comma (/*@only@*/ exprNode e1, /*@only@*/ exprNode e2) { if (exprNode_isError (e2)) { - ret = exprNode_createLoc (ctype_unknown, g_currentloc); + ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc)); } else { @@ -7507,6 +8270,10 @@ static bool exprNode_checkOneInit (/*@notnull@*/ exprNode el, exprNode val) ctype t2 = exprNode_getType (val); bool hasError = FALSE; + DPRINTF (("Check one init: %s / %s", + exprNode_unparse (el), + exprNode_unparse (val))); + if (ctype_isUnknown (t1)) { voptgenerror (FLG_IMPTYPE, @@ -7521,12 +8288,44 @@ static bool exprNode_checkOneInit (/*@notnull@*/ exprNode el, exprNode val) if (exprNode_isDefined (val) && val->kind == XPR_INITBLOCK) { exprNodeList vals = exprData_getArgs (val->edata); + + DPRINTF (("Check one init: %s", exprNodeList_unparse (vals))); + DPRINTF (("Type: %s", ctype_unparse (t1))); if (ctype_isRealAP (t1)) { int i = 0; int nerrors = 0; + if (ctype_isFixedArray (t1)) + { + size_t nelements = ctype_getArraySize (t1); + + DPRINTF (("Checked array: %s / %d", + ctype_unparse (t1), nelements)); + + if (exprNode_isStringLiteral (val)) + { + exprNode_checkStringLiteralLength (t1, val); + } + else + { + if (exprNodeList_size (vals) != size_toInt (nelements)) + { + hasError = optgenerror + (exprNodeList_size (vals) > size_toInt (nelements) + ? FLG_INITSIZE : FLG_INITALLELEMENTS, + message ("Initializer block for " + "%s has %d element%&, but declared as %s: %q", + exprNode_unparse (el), + exprNodeList_size (vals), + ctype_unparse (t1), + exprNodeList_unparse (vals)), + val->loc); + } + } + } + exprNodeList_elements (vals, oneval) { cstring istring = message ("%d", i); @@ -7637,6 +8436,50 @@ static bool exprNode_checkOneInit (/*@notnull@*/ exprNode el, exprNode val) } end_exprNodeList_elements; } } + /* evans 2001-12-30: added to fix bug reported by Jim Zelenka */ + else if (ctype_isUnion (ctype_realType (t1))) + { + uentryList fields = ctype_getFields (t1); + int i = 0; + + /* + ** Union initializers set the first member always. + */ + + DPRINTF (("Union initializer: %s / %s", + exprNode_unparse (el), ctype_unparse (ctype_realType (t1)))); + + if (exprNodeList_size (vals) != 1) + { + hasError = optgenerror + (FLG_TYPE, + message ("Initializer block for union " + "%s has %d elements, union initializers should have one element: %q", + exprNode_unparse (el), + exprNodeList_size (vals), + exprNodeList_unparse (vals)), + val->loc); + } + else + { + exprNode oneval = exprNodeList_head (vals); + uentry thisfield = uentryList_getN (fields, i); + exprNode newel = + exprNode_fieldAccessAux (exprNode_fakeCopy (el), + exprNode_loc (el), + uentry_getName (thisfield)); + + if (exprNode_isDefined (newel)) + { + if (exprNode_checkOneInit (newel, oneval)) + { + hasError = TRUE; + } + + exprNode_freeIniter (newel); + } + } + } else { hasError = optgenerror @@ -7669,51 +8512,25 @@ static bool exprNode_checkOneInit (/*@notnull@*/ exprNode el, exprNode val) return hasError; } -static exprNode +static /*@notnull@*/ exprNode exprNode_makeInitializationAux (/*@temp@*/ idDecl t) { exprNode ret; + DPRINTF (("Initialization: %s", idDecl_unparse (t))); + if (usymtab_exists (idDecl_observeId (t))) { uentry ue = usymtab_lookup (idDecl_observeId (t)); ret = exprNode_createId (ue); - - /*@i723 don't do this...but why? */ -# if 0 - ct = ctype_realishType (ret->typ); - - DPRINTF (("Type: %s", ctype_unparse (ret->typ))); - - if (ctype_isUnknown (ct)) - { - if (uentry_isAnyTag (ue)) - { - voptgenerror - (FLG_IMPTYPE, - message ("%s used but not previously declared: %s", - uentry_ekindName (ue), - idDecl_getName (t)), - g_currentloc); - - } - else - { - voptgenerror - (FLG_IMPTYPE, - message ("Variable has unknown (implicitly int) type: %s", - idDecl_getName (t)), - g_currentloc); - } - - ct = ctype_int; - } -# endif } else { - uentry ue = uentry_makeUnrecognized (idDecl_observeId (t), - g_currentloc); + uentry ue; + + DPRINTF (("Unrecognized: %s", idDecl_unparse (t))); + + ue = uentry_makeUnrecognized (idDecl_observeId (t), fileloc_copy (g_currentloc)); ret = exprNode_fromIdentifierAux (ue); /* @@ -7751,13 +8568,14 @@ exprNode exprNode_makeInitialization (/*@only@*/ idDecl t, exprNode ret = exprNode_makeInitializationAux (t); fileloc loc = exprNode_loc (e); + DPRINTF (("initialization: %s = %s", idDecl_unparse (t), exprNode_unparse (e))); + if (exprNode_isError (e)) { e = exprNode_createUnknown (); - idDecl_free (t); - /* error: assume initializer is defined */ sRef_setDefined (ret->sref, g_currentloc); + ret->edata = exprData_makeInit (t, e); } else { @@ -7773,6 +8591,7 @@ exprNode exprNode_makeInitialization (/*@only@*/ idDecl t, exprData_free (ret->edata, ret->kind); ret->edata = exprData_makeInit (t, e); + DPRINTF (("ret: %s", exprNode_unparse (ret))); exprNode_checkUse (ret, e->sref, e->loc); @@ -7788,7 +8607,7 @@ exprNode exprNode_makeInitialization (/*@only@*/ idDecl t, { sRef_setDefState (lhs->sref, SS_PARTIAL, fileloc_undefined); } - + (void) exprNode_checkOneInit (lhs, e); if (uentry_isStatic (ue)) @@ -7825,14 +8644,42 @@ exprNode exprNode_makeInitialization (/*@only@*/ idDecl t, sRef_setDefState (ret->sref, SS_PARTIAL, fileloc_undefined); } - doAssign (ret, e, TRUE); + if (exprNode_isStringLiteral (e) + && (ctype_isArray (ct)) + && (ctype_isChar (ctype_realType (ctype_baseArrayPtr (ct))))) + { + /* + ** If t is a char [], the literal is copied. + */ + + exprNode_checkStringLiteralLength (ct, e); + sRef_setDefState (ret->sref, SS_DEFINED, e->loc); + ret->val = multiVal_copy (e->val); + + sRef_setNullTerminatedState (ret->sref); + + if (multiVal_isDefined (e->val)) + { + cstring slit = multiVal_forceString (e->val); + sRef_setLen (ret->sref, size_toInt (cstring_length (slit) + 1)); + } + + if (ctype_isFixedArray (ct)) + { + sRef_setSize (ret->sref, size_toInt (ctype_getArraySize (ct))); + } + } + else + { + doAssign (ret, e, TRUE); + } if (uentry_isStatic (ue)) { sRef_setDefState (ret->sref, SS_DEFINED, fileloc_undefined); } } - + if (context_inIterDef ()) { /* should check if it is yield */ @@ -7844,6 +8691,15 @@ exprNode exprNode_makeInitialization (/*@only@*/ idDecl t, } exprNode_mergeUSs (ret, e); + DPRINTF (("Ret: %s %p %p", + exprNode_unparse (ret), + ret->requiresConstraints, + ret->ensuresConstraints)); + + DPRINTF (("Ret: %s %s %s", + exprNode_unparse (ret), + constraintList_unparse (ret->requiresConstraints), + constraintList_unparse (ret->ensuresConstraints))); return ret; } @@ -7864,23 +8720,23 @@ exprNode exprNode_iter (/*@observer@*/ uentry name, if (uentry_isInvalid (end)) { - llerror (FLG_ITER, + llerror (FLG_ITERBALANCE, message ("Iter %s not balanced with end_%s", iname, iname)); } else { cstring ename = uentry_getName (end); - if (!cstring_equalPrefix (ename, "end_")) + if (!cstring_equalPrefixLit (ename, "end_")) { - llerror (FLG_ITER, message ("Iter %s not balanced with end_%s: %s", + llerror (FLG_ITERBALANCE, message ("Iter %s not balanced with end_%s: %s", iname, iname, ename)); } else { if (!cstring_equal (iname, cstring_suffix (ename, 4))) { - llerror (FLG_ITER, + llerror (FLG_ITERBALANCE, message ("Iter %s not balanced with end_%s: %s", iname, iname, ename)); } @@ -7927,11 +8783,11 @@ exprNode_iterNewId (/*@only@*/ cstring s) e->kind = XPR_VAR; e->val = multiVal_unknown (); e->guards = guardSet_new (); - e->sref = defref; + e->sref = sRef_undefined; e->isJumpPoint = FALSE; e->exitCode = XK_NEVERESCAPE; - /*> missing fields, detected by lclint <*/ + /*> missing fields, detected by splint <*/ e->canBreak = FALSE; e->mustBreak = FALSE; e->etext = cstring_undefined; @@ -8007,7 +8863,7 @@ exprNode_iterExpr (/*@returned@*/ exprNode e) if (fileloc_isDefined (e->loc)) { voptgenerror - (FLG_ITER, + (FLG_ITERYIELD, message ("Yield parameter is not simple identifier: %s", exprNode_unparse (e)), e->loc); @@ -8015,7 +8871,7 @@ exprNode_iterExpr (/*@returned@*/ exprNode e) else { voptgenerror - (FLG_ITER, + (FLG_ITERYIELD, message ("Yield parameter is not simple identifier: %s", exprNode_unparse (e)), g_currentloc); @@ -8058,7 +8914,7 @@ exprNode_iterId (/*@observer@*/ uentry c) if (!context_inHeader ()) { if (optgenerror - (FLG_ITER, + (FLG_ITERYIELD, message ("Yield parameter shadows local declaration: %q", uentry_getName (c)), fileloc_isDefined (e->loc) ? e->loc : g_currentloc)) @@ -8118,8 +8974,7 @@ exprNode exprNode_iterStart (/*@observer@*/ uentry name, /*@only@*/ exprNodeList { if (exprNode_isDefined (e)) { - /*@access sRef@*/ - if (e->sref == defref) /*@noaccess sRef@*/ + if (sRef_isInvalid (e->sref)) { /*@-mods@*/ e->sref = sRef_makeUnknown (); @@ -8300,9 +9155,47 @@ static /*@only@*/ exprNode exprNode_effect (exprNode e) exprNode_effect (exprData_getPairB (data))); break; case XPR_OP: - ret = exprNode_op (exprNode_effect (exprData_getOpA (data)), - exprNode_effect (exprData_getOpB (data)), - exprData_getOpTok (data)); + /* + ** evans 2002-03-15: for && and ||, need to do the guards also + ** this is what cgrammar.y does - should be + ** able to avoid duplication, but need to + ** time with grammar productions. + */ + + DPRINTF (("Effect: %s", exprNode_unparse (e))); + + if (lltok_getTok (exprData_getOpTok (data)) == AND_OP) + { + exprNode e1 = exprNode_effect (exprData_getOpA (data)); + exprNode e2; + exprNode_produceGuards (e1); + context_enterAndClause (e1); + e2 = exprNode_effect (exprData_getOpB (data)); + + ret = exprNode_op (e1, e2, + exprData_getOpTok (data)); + + context_exitAndClause (ret, e2); + } + else if (lltok_getTok (exprData_getOpTok (data)) == OR_OP) + { + exprNode e1 = exprNode_effect (exprData_getOpA (data)); + exprNode e2; + exprNode_produceGuards (e1); + context_enterOrClause (e1); + e2 = exprNode_effect (exprData_getOpB (data)); + + ret = exprNode_op (e1, e2, + exprData_getOpTok (data)); + + context_exitOrClause (ret, e2); + } + else + { + ret = exprNode_op (exprNode_effect (exprData_getOpA (data)), + exprNode_effect (exprData_getOpB (data)), + exprData_getOpTok (data)); + } break; case XPR_POSTOP: @@ -8518,6 +9411,9 @@ static /*@observer@*/ cstring exprNode_rootVarName (exprNode e) case XPR_VAR: ret = exprData_getId (data); break; + case XPR_INIT: + ret = idDecl_getName (exprData_getInitId (data)); + break; case XPR_LABEL: case XPR_TOK: case XPR_ITERCALL: @@ -8559,7 +9455,6 @@ static /*@observer@*/ cstring exprNode_rootVarName (exprNode e) case XPR_BLOCK: case XPR_STMT: case XPR_STMTLIST: - case XPR_INIT: case XPR_FACCESS: case XPR_ARROW: case XPR_NODE: @@ -8770,17 +9665,31 @@ static /*@only@*/ cstring exprNode_doUnparse (exprNode e) break; case XPR_BLOCK: - ret = message ("{ %s }", exprNode_unparseFirst (exprData_getSingle (data))); + ret = message ("{ %s }", exprNode_unparse (exprData_getSingle (data))); + /* evans 2002-02-20 was unparseFirst! */ break; case XPR_STMT: - ret = cstring_copy (exprNode_unparse (exprData_getUopNode (data))); + ret = message ("%s;", exprNode_unparse (exprData_getUopNode (data))); break; case XPR_STMTLIST: - ret = message ("%s; %s", - exprNode_unparse (exprData_getPairA (data)), - exprNode_unparse (exprData_getPairB (data))); + if (exprNode_isStatement (exprData_getPairA (data))) + { + /* + ** statement expressions already print the ; + */ + + ret = message ("%s %s", + exprNode_unparse (exprData_getPairA (data)), + exprNode_unparse (exprData_getPairB (data))); + } + else + { + ret = message ("%s; %s", + exprNode_unparse (exprData_getPairA (data)), + exprNode_unparse (exprData_getPairB (data))); + } break; case XPR_FTDEFAULT: @@ -8826,7 +9735,14 @@ static /*@only@*/ cstring exprNode_doUnparse (exprNode e) break; case XPR_STRINGLITERAL: - ret = message ("\"%s\"", exprData_getLiteral (data)); + if (ctype_isWideString (e->typ)) + { + ret = message ("L\"%s\"", exprData_getLiteral (data)); + } + else + { + ret = message ("\"%s\"", exprData_getLiteral (data)); + } break; case XPR_NUMLIT: @@ -8849,7 +9765,7 @@ exprNode_isInitializer (exprNode e) } bool -exprNode_isCharLit (exprNode e) +exprNode_isCharLiteral (exprNode e) { if (exprNode_isDefined (e)) { @@ -8862,7 +9778,7 @@ exprNode_isCharLit (exprNode e) } bool -exprNode_isNumLit (exprNode e) +exprNode_isNumLiteral (exprNode e) { if (exprNode_isDefined (e)) { @@ -8903,6 +9819,12 @@ exprNode_matchLiteral (ctype expected, exprNode e) { long int val = multiVal_forceInt (m); + if (ctype_isNumAbstract (expected) + && context_flagOn (FLG_NUMABSTRACTLIT, exprNode_loc (e))) + { + return TRUE; + } + if (ctype_isDirectBool (ctype_realishType (expected))) { if (val == 0) @@ -8955,7 +9877,22 @@ exprNode_matchLiteral (ctype expected, exprNode e) } else if (ctype_isArrayPtr (expected)) { - return (val == 0); + /* + ** evans 2001-10-14: We allow 0 to match any pointer, but only if the type matches or is void *. + */ + + if (val == 0) + { + if (ctype_match (exprNode_getType (e), expected) + || ctype_isVoidPointer (exprNode_getType (e))) + { + return TRUE; + } + } + else + { + return FALSE; + } } else if (ctype_isAnyFloat (expected)) { @@ -8975,11 +9912,11 @@ exprNode_matchLiteral (ctype expected, exprNode e) } else if (multiVal_isChar (m)) { - char val = multiVal_forceChar (m); + /*signed? */ char val = multiVal_forceChar (m); if (ctype_isChar (expected)) { - if (ctype_isUnsigned (expected) && ((int)val) < 0) + if (ctype_isUnsigned (expected) && ((int) val) < 0) { return FALSE; } @@ -9038,6 +9975,10 @@ exprNode_matchTypes (exprNode e1, exprNode e2) return TRUE; } + DPRINTF (("Matching literal! %s %s %s %s", + ctype_unparse (t1), exprNode_unparse (e2), + ctype_unparse (t2), exprNode_unparse (e1))); + return (exprNode_matchLiteral (t1, e2) || exprNode_matchLiteral (t2, e1)); } @@ -9223,7 +10164,7 @@ exprNode_checkUse (exprNode e, /*@exposed@*/ sRef s, fileloc loc) while (sRef_isValid (s) && sRef_isKnown (s)) { - ynm readable = sRef_isReadable (s); + ynm readable = sRef_isValidLvalue (s); DPRINTF (("Readable: %s / %s", sRef_unparseFull (s), ynm_unparse (readable))); @@ -9234,6 +10175,7 @@ exprNode_checkUse (exprNode e, /*@exposed@*/ sRef s, fileloc loc) { lastRef = errorRef; errorRef = s; + DPRINTF (("Setting ERROR: %s", sRef_unparseFull (s))); deadRef = sRef_isPossiblyDead (errorRef); unuseable = sRef_isUnuseable (errorRef); errorMaybe = TRUE; @@ -9242,15 +10184,20 @@ exprNode_checkUse (exprNode e, /*@exposed@*/ sRef s, fileloc loc) { lastRef = errorRef; errorRef = s; + DPRINTF (("Setting ERROR: %s", sRef_unparseFull (s))); deadRef = sRef_isDead (errorRef); unuseable = sRef_isUnuseable (errorRef); errorMaybe = FALSE; } + /* if (!sRef_isPartial (s)) { - sRef_setDefined (s, fileloc_undefined); + DPRINTF (("Defining! %s", sRef_unparseFull (s))); + sRef_setDefined (s, loc); + DPRINTF (("Defining! %s", sRef_unparseFull (s))); } + */ } s = sRef_getBaseSafe (s); @@ -9262,6 +10209,7 @@ exprNode_checkUse (exprNode e, /*@exposed@*/ sRef s, fileloc loc) && sRef_isPointer (errorRef)) { errorRef = lastRef; + DPRINTF (("errorRef: %s", sRef_unparseFull (errorRef))); } if (deadRef) @@ -9285,7 +10233,7 @@ exprNode_checkUse (exprNode e, /*@exposed@*/ sRef s, fileloc loc) } else { - DPRINTF (("HERE: %s", sRef_unparse (errorRef))); + DPRINTF (("HERE: %s", sRef_unparseFull (errorRef))); if (optgenerror (FLG_USERELEASED, @@ -9322,13 +10270,18 @@ exprNode_checkUse (exprNode e, /*@exposed@*/ sRef s, fileloc loc) { DPRINTF (("HERE: %s", sRef_unparseFull (errorRef))); - voptgenerror - (FLG_USEDEF, - message ("%q %q%qused before definition", - sRef_unparseKindName (errorRef), - sRef_unparseOpt (errorRef), - cstring_makeLiteral (errorMaybe ? "may be " : "")), - loc); + if (optgenerror + (FLG_USEDEF, + message ("%q %q%qused before definition", + sRef_unparseKindName (errorRef), + sRef_unparseOpt (errorRef), + cstring_makeLiteral (errorMaybe ? "may be " : "")), + loc)) + { + ; + } + + DPRINTF (("Error: %s", sRef_unparseFull (errorRef))); } sRef_setDefined (errorRef, loc); @@ -9385,8 +10338,7 @@ exprNode_checkSet (exprNode e, /*@exposed@*/ sRef s) } if (sRef_isMeaningful (s)) - { - + { if (sRef_isDead (s)) { sRef base = sRef_getBaseSafe (s); @@ -9581,7 +10533,7 @@ checkOneArg (uentry ucurrent, /*@notnull@*/ exprNode current, } } - checkPassTransfer (current, ucurrent, isSpec, fcn, argno, totargs); + transferChecks_passParam (current, ucurrent, isSpec, fcn, argno, totargs); exprNode_mergeUSs (fcn, current); } } @@ -9748,31 +10700,73 @@ static ctype if ((ctype_isRealInt (tr1) || ctype_isReal (tr1)) && (ctype_isRealInt (tr2) || ctype_isReal (tr2))) { - ; + DPRINTF (("No error: [%s] %s / [%s] %s", + exprNode_unparse (e1), ctype_unparse (tr1), + exprNode_unparse (e2), ctype_unparse (tr2))); + + /* + ** evans 2003-06-15: changed this so if either type is a literal, + ** the other type is used. + ** (Need to look at the ISO C99 rules on this...) + */ + + if (exprNode_isNumLiteral (e1)) { + ret = tr2; + } else if (exprNode_isNumLiteral (e2)) { + ret = tr1; + } else { + ret = ctype_biggerType (tr1, tr2); + } } else { - (void) gentypeerror - (tr1, e1, tr2, e2, - message ("Incompatible types for %s (%s, %s): %s %s %s", - lltok_unparse (op), - ctype_unparse (te1), - ctype_unparse (te2), - exprNode_unparse (e1), lltok_unparse (op), - exprNode_unparse (e2)), - e1->loc); + if (ctype_isNumAbstract (tr1) + && exprNode_isNumLiteral (e2) + && context_flagOn (FLG_NUMABSTRACTLIT, e1->loc)) + { + ret = tr1; /* No error */ + } + else if (ctype_isNumAbstract (tr2) + && exprNode_isNumLiteral (e1) + && context_flagOn (FLG_NUMABSTRACTLIT, e1->loc)) + { + ret = tr2; + } + else + { + if (gentypeerror + (tr1, e1, tr2, e2, + message ("Incompatible types for %s (%s, %s): %s %s %s", + lltok_unparse (op), + ctype_unparse (te1), + ctype_unparse (te2), + exprNode_unparse (e1), lltok_unparse (op), + exprNode_unparse (e2)), + e1->loc)) + { + ret = ctype_unknown; + } + else + { + ret = ctype_biggerType (tr1, tr2); + } + } } - ret = ctype_unknown; } else { - if (ctype_isForceRealNumeric (&tr1) && ctype_isForceRealNumeric (&tr2)) + if (ctype_isNumAbstract (tr1)) + { + ret = tr1; + } + else if (ctype_isForceRealNumeric (&tr1) + && ctype_isForceRealNumeric (&tr2)) { ret = ctype_resolveNumerics (tr1, tr2); } else if (!context_msgStrictOps ()) { - if (ctype_isPointer (tr1)) + if (ctype_isPointer (tr1)) { if (ctype_isPointer (tr2) && !exprNode_isNullValue (e2)) { @@ -9878,7 +10872,7 @@ static ctype return ret; } -static void +static bool abstractOpError (ctype tr1, ctype tr2, lltok op, /*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2, fileloc loc1, fileloc loc2) @@ -9887,26 +10881,60 @@ abstractOpError (ctype tr1, ctype tr2, lltok op, { if (ctype_match (tr1, tr2)) { - voptgenerror - (FLG_ABSTRACT, - message ("Operands of %s are abstract type (%t): %s %s %s", - lltok_unparse (op), tr1, - exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)), - loc1); + if (ctype_isRealNumAbstract (tr1)) + { + ; /* No warning for numabstract types */ + } + else + { + if (lltok_isEqOp (op) || lltok_isNotEqOp (op)) + { + return optgenerror + (FLG_ABSTRACTCOMPARE, + message ("Object equality comparison (%s) on objects of abstract type (%t): %s %s %s", + lltok_unparse (op), tr1, + exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)), + loc1); + } + else + { + return optgenerror + (FLG_ABSTRACT, + message ("Operands of %s are abstract type (%t): %s %s %s", + lltok_unparse (op), tr1, + exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)), + loc1); + } + } } else { - voptgenerror - (FLG_ABSTRACT, - message ("Operands of %s are abstract types (%t, %t): %s %s %s", - lltok_unparse (op), tr1, tr2, - exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)), - loc1); + if (ctype_isRealNumAbstract (tr1) && ctype_isRealNumAbstract (tr2)) + { + return optgenerror + (FLG_NUMABSTRACT, + message + ("Operands of %s are different numabstract types (%t, %t): %s %s %s", + lltok_unparse (op), tr1, tr2, + exprNode_unparse (e1), + lltok_unparse (op), exprNode_unparse (e2)), + loc1); + } + else + { + return optgenerror + (FLG_ABSTRACT, + message ("Operands of %s are abstract types (%t, %t): %s %s %s", + lltok_unparse (op), tr1, tr2, + exprNode_unparse (e1), lltok_unparse (op), + exprNode_unparse (e2)), + loc1); + } } } - else if (ctype_isRealAbstract (tr1)) + else if (ctype_isRealAbstract (tr1) && !ctype_isRealNumAbstract (tr1)) { - voptgenerror + return optgenerror (FLG_ABSTRACT, message ("Left operand of %s is abstract type (%t): %s %s %s", lltok_unparse (op), tr1, @@ -9915,9 +10943,9 @@ abstractOpError (ctype tr1, ctype tr2, lltok op, } else { - if (ctype_isRealAbstract (tr2)) + if (ctype_isRealAbstract (tr2) && !ctype_isRealNumAbstract (tr2)) { - voptgenerror + return optgenerror (FLG_ABSTRACT, message ("Right operand of %s is abstract type (%t): %s %s %s", lltok_unparse (op), tr2, @@ -9925,6 +10953,8 @@ abstractOpError (ctype tr1, ctype tr2, lltok op, loc2); } } + + return FALSE; } /* @@ -9956,9 +10986,12 @@ checkOneRepExpose (sRef ysr, sRef base, sRef s2b) { if (!(sRef_isOnly (ysr) || sRef_isKeep (ysr) - || sRef_isOwned (ysr) || sRef_isExposed (ysr))) + || sRef_isOwned (ysr) + || sRef_isExposed (ysr))) { - if (sRef_isAnyParam (base) && !sRef_isExposed (base)) + if (sRef_isAnyParam (base) && !sRef_isExposed (base) + && !sRef_isObserver (base)) /* evans 2001-07-11: added isObserver */ + { if (sRef_isIReference (ysr)) { @@ -10057,6 +11090,10 @@ checkOneRepExpose (sRef ysr, sRef base, static void doAssign (/*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2, bool isInit) { + DPRINTF (("Do assign: %s <- %s", + exprNode_unparse (e1), exprNode_unparse (e2))); + DPRINTF (("Ctype: %s", ctype_unparse (exprNode_getType (e1)))); + if (ctype_isRealFunction (exprNode_getType (e1)) && !ctype_isRealPointer (exprNode_getType (e1))) { @@ -10075,6 +11112,7 @@ doAssign (/*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2, bool isInit) ctype ct = sRef_getType (sr); if (ctype_isAbstract (t2) + && !ctype_isNumAbstract (t2) && !(uentry_isMutableDatatype (usymtab_getTypeEntry (ctype_typeId (t2))))) { /* it is immutable, okay to reference */ @@ -10166,11 +11204,11 @@ doAssign (/*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2, bool isInit) { DPRINTF (("Check init: %s / %s", exprNode_unparse (e1), exprNode_unparse (e2))); - checkInitTransfer (e1, e2); + transferChecks_initialization (e1, e2); } else { - checkAssignTransfer (e1, e2); + transferChecks_assign (e1, e2); } } else @@ -10204,6 +11242,11 @@ doAssign (/*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2, bool isInit) } } + if (exprNode_isStringLiteral (e2)) + { + exprNode_checkStringLiteralLength (exprNode_getType (e1), e2); + } + if (isInit && sRef_isFileOrGlobalScope (e1->sref)) { ; @@ -10431,30 +11474,22 @@ static void checkUniqueParams (exprNode fcn, } end_exprNodeList_elements; } -long exprNode_getLongValue (exprNode e) { +long exprNode_getLongValue (exprNode e) +{ long value; - - if (exprNode_hasValue (e) - && multiVal_isInt (exprNode_getValue (e))) + + if (exprNode_hasValue (e) && multiVal_isInt (exprNode_getValue (e))) { value = multiVal_forceInt (exprNode_getValue (e)); } else { - value = 0; + value = 0; /* Unknown value */ } return value; } -/*@observer@*/ fileloc exprNode_getfileloc (exprNode p_e) -{ - if (exprNode_isDefined (p_e) ) - return ( p_e->loc ); - else - return fileloc_undefined; -} - /*@only@*/ fileloc exprNode_getNextSequencePoint (exprNode e) { /* @@ -10467,8 +11502,9 @@ long exprNode_getLongValue (exprNode e) { lltok t = exprData_getUopTok (e->edata); return fileloc_copy(lltok_getLoc (t)); } else { - //drl possible problem : warning fix - // llcontbug (message ("Cannot get next sequence point: %s", exprNode_unparse (e))); + /* drl possible problem : warning fix + llcontbug (message ("Cannot get next sequence point: %s", exprNode_unparse (e))); + */ return fileloc_undefined; } } @@ -10481,3 +11517,37 @@ exprNode exprNode_createNew(ctype c) return ret; } + +bool exprNode_isInitBlock (exprNode e) +{ + return (exprNode_isDefined(e) && e->kind == XPR_INITBLOCK); +} + +/*drl 3/2/2003 moved this function out of constraint.c */ +exprNode exprNode_copyConstraints (/*@returned@*/ exprNode dst, exprNode src) +{ + + llassert (exprNode_isDefined (dst) ); + llassert (exprNode_isDefined (src) ); + + constraintList_free (dst->ensuresConstraints); + constraintList_free (dst->requiresConstraints); + constraintList_free (dst->trueEnsuresConstraints); + constraintList_free (dst->falseEnsuresConstraints); + + dst->ensuresConstraints = constraintList_copy (src->ensuresConstraints); + dst->requiresConstraints = constraintList_copy (src->requiresConstraints); + dst->trueEnsuresConstraints = constraintList_copy (src->trueEnsuresConstraints); + dst->falseEnsuresConstraints = constraintList_copy (src->falseEnsuresConstraints); + return dst; +} + +void exprNode_revealState (exprNode e) +{ + if (exprNode_isDefined (e)) { + llmsg (message ("%s: State of %s: %s", fileloc_unparse (exprNode_loc (e)), + exprNode_unparse (e), sRef_unparseFull (e->sref))); + } else { + llmsg (message ("%s: Reveal state undefined", fileloc_unparse (g_currentloc))); + } +}