/*
-** LCLint - annotation-assisted static program checker
-** Copyright (C) 1994-2001 University of Virginia,
+** Splint - annotation-assisted static program checker
+** Copyright (C) 1994-2003 University of Virginia,
** Massachusetts Institute of Technology
**
** This program is free software; you can redistribute it and/or modify it
** the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
** MA 02111-1307, USA.
**
-** For information on lclint: lclint-request@cs.virginia.edu
-** To report a bug: lclint-bug@cs.virginia.edu
-** For more information: http://lclint.cs.virginia.edu
+** For information on splint: info@splint.org
+** To report a bug: splint-bug@splint.org
+** For more information: http://www.splint.org
*/
/*
** exprNode.c
*/
# include <ctype.h> /* 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);
/*@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);
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,
ctypeType = ctype_unknown;
filelocType = ctype_unknown;
- defref = sRef_undefined;
-
if (usymtab_existsType (cstring_makeLiteralTemp ("cstring")))
{
cstringType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("cstring"));
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)
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;
/*@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;
}
}
ret->kind = XPR_EMPTY;
- ret->sref = defref;
+ ret->sref = sRef_undefined;
ret->etext = cstring_undefined;
ret->exitCode = XK_NEVERESCAPE;
ret->canBreak = FALSE;
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;
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;
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)
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);
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);
}
e->loc = loc; /* save loc was mangled */
- e->sref = defref;
+ e->sref = sRef_undefined;
if (usymtab_exists (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)
/*
** 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;
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
if (context_justPopped ()) /* watch out! c could be dead */
{
- uentry ce = usymtab_lookupSafe (LastIdentifier ());
+ uentry ce = usymtab_lookupSafe (cscannerHelp_observeLastIdentifier ());
if (uentry_isValid (ce))
{
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)
{
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;
/*
** this sets up funny aliasing, that leads to spurious
- ** lclint errors. Hence, the i2 comments.
+ ** splint errors. Hence, the i2 comments.
*/
/* evans 2001-09-09 added ctype_isKnown so there is no swap when e1 type is unknown */
{
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))
- {
- DPRINTF (("ref: %s", sRef_unparseFull (arr->sref)));
- 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);
+ }
}
}
}
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
expecttype = ctype_makeConj (ctype_int,
ctype_makeConj (ctype_char,
ctype_uchar));
- /*@i231@*/
/* evans 2001-10-05 - changed to reflect correct ISO spec:
int converted to char */
- /* expecttype = ctype_makeConj (ctype_char, ctype_uchar); */
/*@switchbreak@*/ break;
case 's': /* string */
case 'p': /* pointer */
expecttype = ctype_makePointer (ctype_void);
- uentry_setDefState (regArg, SS_RELDEF); /* need not be defined */
- sRef_setPosNull (uentry_getSref (regArg), fileloc_undefined); /* could be null */
+ /* 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! */
}
else
{
- /* a->sref = defref; */
+ /* a->sref = sRef_undefined; */
}
}
}
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;
codetext, expecttype,
a->typ, exprNode_unparse (a)),
a->loc))
- {
+ {
if (fileloc_isDefined (formatloc)
&& context_getFlag (FLG_SHOWCOL))
{
uentry_unparse (le)));
params = ctype_argsFunction (ct);
- return; /*@32 ! remove this? */
+ return; /* No checking for non-function */
}
/*
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.
*/
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)));
stateClause_unparse (cl),
sRefSet_unparse (srs)));
+ llassert (modf != NULL);
+
sRefSet_elements (srs, sel)
{
sRef s;
if (sRef_isResult (sRef_getRootBase (sel)))
{
- ; /*@i423 what do we do about results */
+ ; /* what do we do about results? */
}
else
{
/* f->typ is already set to the return type */
DPRINTF (("Function: %s", uentry_unparseFull (le)));
- ret->sref = uentry_returnedRef (le, args);
+ ret->sref = uentry_returnedRef (le, args, exprNode_loc (f));
DPRINTF (("Returned: %s / %s",
uentry_unparseFull (le),
sRef_unparseFull (ret->sref)));
}
else
{
- ret->sref = defref;
+ ret->sref = sRef_undefined;
exprNode_checkSetAny (ret, uentry_rawName (le));
}
reflectEnsuresClause (ret, le, f, args);
setCodePoint ();
+ DPRINTF (("Here: %s", sRef_unparseFull (ret->sref)));
return (ret);
}
}
}
+/*
+** 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)
{
{
ctype t;
- setCodePoint ();
+# ifdef DEBUGSPLINT
+ usymtab_checkAllValid ();
+# endif
if (exprNode_isUndefined (f))
{
/*@only@*/ cstring f)
{
exprNode res = exprNode_fieldAccessAux (s, lltok_getLoc (dot), f);
- lltok_release (dot);
+ lltok_free (dot);
return res;
}
/*@only@*/ cstring f)
{
exprNode res = exprNode_arrowAccessAux (s, lltok_getLoc (arrow), f);
- lltok_release (arrow);
+ lltok_free (arrow);
return res;
}
{
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
{
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 */
-
- /*@i65234@*/
- /*@ignore@*/
/* updateEnvironmentForPostOp (e); */
printf ("ret->sref is Possibly Null Terminated\n");
else if (sRef_isNotNullTerminated (ret->sref))
printf ("ret->sref is Not Null Terminated\n");
+ else
+ {}
}
}
}
}
}
- /*@end@*/
/* end modifications */
return ret;
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);
+ }
}
}
}
/* 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 : ++ */
}
else
{
- sizet = ctype_ulint;
+ sizet = ctype_ulint;
}
}
return sizet;
if (exprNode_isError (e))
{
qtype_free (q);
- lltok_release (tok);
+ lltok_free (tok);
return exprNode_undefined;
}
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
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 */
{
}
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);
+ }
}
}
}
}
ret->val = multiVal_undefined;
+
ret->kind = XPR_OP;
ret->edata = exprData_makeOp (e1, e2, op);
tret = ctype_unknown;
te1 = exprNode_getType (e1);
+
DPRINTF (("te1 = %s / %s", exprNode_unparse (e1), ctype_unparse (te1)));
te2 = exprNode_getType (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
+ {
+ 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)))
{
- case TMULT: /* multiplication and division: */
- case TDIV: /* */
- case MUL_ASSIGN: /* numeric, numeric -> numeric */
- case DIV_ASSIGN: /* */
+ /* 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);
- }
-
- /*
- ** Swap terms so e1 is always the pointer
- */
-
- if (ctype_isRealPointer (tr1))
- {
- ;
- }
- else
- {
- exprNode_swap (e1, e2);
- }
-
-
- 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))) {
- 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);
+ ;
+ }
+ else
+ {
+ exprNode_swap (e1, e2);
+ }
+
+ 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))) {
+ 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 !) */
- /* 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);
- }
- }
- }
+ sRef_setSize (ret->sref, sRef_getSize(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);
- }
+ 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);
}
}
-
- /* 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 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))) {
- int val = (int) multiVal_forceInt (e1->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 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))) {
+ 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 !) */
- /* 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);
- }
- }
- }
+ sRef_setSize (ret->sref, sRef_getSize(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);
- }
+ 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);
}
}
- /* 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);
+
+ /* 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 */
- break;
-
- 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:
+ 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)),
}
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)),
}
}
}
-
- 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"))
- {
- fepsilon = TRUE;
- }
- }
-
- if (uentry_isVariable (ue2))
+ 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 (ue2);
-
- if (cstring_equalLit (uname, "FLT_EPSILON")
- || cstring_equalLit (uname, "DBL_EPSILON")
- || cstring_equalLit (uname, "LDBL_EPSILON"))
- {
- fepsilon = TRUE;
- }
+ fepsilon = TRUE;
}
}
-
- if (fepsilon)
- {
- ; /* Don't complain. */
- }
- else
+
+ if (uentry_isVariable (ue2))
{
- voptgenerror
- (FLG_REALCOMPARE,
- message ("Dangerous comparison involving %s types: %s",
- ctype_unparse (rtype),
- exprNode_unparse (ret)),
- ret->loc);
+ cstring uname = uentry_rawName (ue2);
+
+ if (cstring_equalLit (uname, "FLT_EPSILON")
+ || cstring_equalLit (uname, "DBL_EPSILON")
+ || cstring_equalLit (uname, "LDBL_EPSILON"))
+ {
+ fepsilon = TRUE;
+ }
}
}
- /*@fallthrough@*/
- case LE_OP:
- case GE_OP:
-
- /*
- ** Types should match.
- */
-
- if (!exprNode_matchTypes (e1, e2))
+
+ if (fepsilon)
{
- 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);
-
+ ; /* Don't complain. */
}
-
- if (hasError
- || (ctype_isForceRealNumeric (&tr1)
- && ctype_isForceRealNumeric (&tr2)) ||
- (ctype_isRealPointer (tr1) && ctype_isRealPointer (tr2)))
+ else
+ {
+ voptgenerror
+ (FLG_REALCOMPARE,
+ message ("Dangerous comparison involving %s types: %s",
+ ctype_unparse (rtype),
+ exprNode_unparse (ret)),
+ ret->loc);
+ }
+ }
+ /*@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)))
{
- ; /* okay */
+ voptgenerror
+ (FLG_PTRNUMCOMPARE,
+ message ("Comparison of pointer and numeric (%t, %t): %s",
+ te1, te2, exprNode_unparse (ret)),
+ e1->loc);
}
else
{
- 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;
+ (void) checkNumerics (tr1, tr2, te1, te2, e1, e2, op);
}
-
- /* certain comparisons on unsigned's and zero look suspicious */
-
- if (opid == TLT || opid == LE_OP || opid == GE_OP)
+ 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_isUnsigned (tr1) && exprNode_isZero (e2))
- || (ctype_isUnsigned (tr2) && exprNode_isZero (e1)))
- {
- voptgenerror
- (FLG_UNSIGNEDCOMPARE,
- message ("Comparison of unsigned value involving zero: %s",
- exprNode_unparse (ret)),
- e1->loc);
- }
+ 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);
}
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;
ctype_unparse (e1->typ),
ctype_unparse (e2->typ)));
- if (ctype_isNumeric (e2->typ)
- || ctype_isNumeric (e1->typ))
+ if (exprNode_isDefined (e1)
+ && exprNode_isDefined (e2))
{
- /* Its a pointer arithmetic expression like ptr += i */
- noalias = TRUE;
- }
- }
+ if (ctype_isNumeric (e2->typ)
+ || ctype_isNumeric (e1->typ))
+ {
+ /* Its a pointer arithmetic expression like ptr += i */
+ noalias = TRUE;
+ }
+ }
+ }
else
{
ret = exprNode_createPartialCopy (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
{
e1->loc);
}
}
+ else
+ {
+ /* Type checks okay */
+ }
}
exprNode_mergeUSs (ret, e2);
*/
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,
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;
{
if (!exprNode_isError (e))
{
- exprNode_checkStatement(e);
+ exprChecks_checkStatementEffect(e);
}
return (exprNode_statementError (e, t));
}
}
+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);
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;
}
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)
{
return FALSE;
}
-bool exprNode_isEmptyStatement (exprNode e)
+bool exprNode_isEmptyStatement (exprNode e)
+{
+ return (exprNode_isDefined (e)
+ && (e->kind == XPR_TOK)
+ && (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)
{
- return (exprNode_isDefined (e)
- && (e->kind == XPR_TOK)
- && (lltok_isSemi (exprData_getTok (e->edata))));
+ exprNode_checkPred (cstring_makeLiteralTemp ("if"), pred);
}
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))
exprNode_loc (pred));
}
- exprNode_checkPred (cstring_makeLiteralTemp ("if"), pred);
exprNode_checkUse (ret, pred->sref, pred->loc);
-
exprNode_mergeCondUSs (ret, tclause, eclause);
}
exprNodeSList_elements (el, current)
{
+
+ DPRINTF ((message("checkSwitchExpr current = %s ", exprNode_unparse(current) ) ));
+
if (exprNode_isDefined (current))
{
switch (current->kind)
if (hasDefault)
{
voptgenerror
- (FLG_CONTROL,
+ (FLG_DUPLICATECASES,
message ("Duplicate default cases in switch"),
exprNode_loc (current));
}
(/*@-usedef@*/usedEnums/*@=usedef@*/, cname))
{
voptgenerror
- (FLG_CONTROL,
+ (FLG_DUPLICATECASES,
message ("Duplicate case in switch: %s",
cname),
current->loc);
g_currentloc);
enumNameSList_free (unused);
+ *allpaths = FALSE; /* evans 2002-01-01 */
}
else
{
if (exprNode_isDefined (t) && exprNode_mustEscape (t))
{
voptgenerror
- (FLG_CONTROL,
+ (FLG_ALWAYSEXITS,
message ("Predicate always exits: %s", exprNode_unparse (t)),
exprNode_loc (t));
}
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)));
+
+ if (multiVal_isInt (valinit) && multiVal_isInt (valtest))
+ {
+ long v1 = multiVal_forceInt (valinit);
+ long v2 = multiVal_forceInt (valtest);
+
+ 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;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ DPRINTF (("loop must exec: FALSE"));
+ return FALSE;
+}
+
exprNode exprNode_for (/*@keep@*/ exprNode inc, /*@keep@*/ exprNode body)
{
exprNode ret;
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);
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,
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;
- /*@i423 check number of entries int a[3] = { 1, 2, 3, 4 } ; */
+ 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);
} 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
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
{
DPRINTF (("Unrecognized: %s", idDecl_unparse (t)));
ue = uentry_makeUnrecognized (idDecl_observeId (t), fileloc_copy (g_currentloc));
- /*!! fileloc_copy (g_currentloc)); */
- /*@i32!!! should get error without this */
ret = exprNode_fromIdentifierAux (ue);
/*
exprData_free (ret->edata, ret->kind);
ret->edata = exprData_undefined;
-
ret->exitCode = XK_NEVERESCAPE;
ret->mustBreak = FALSE;
ret->kind = XPR_INIT;
uentry ue = usymtab_lookup (idDecl_observeId (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
{
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);
{
sRef_setDefState (lhs->sref, SS_PARTIAL, fileloc_undefined);
}
-
+
(void) exprNode_checkOneInit (lhs, e);
if (uentry_isStatic (ue))
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 */
}
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;
}
if (uentry_isInvalid (end))
{
- llerror (FLG_ITER,
+ llerror (FLG_ITERBALANCE,
message ("Iter %s not balanced with end_%s", iname, iname));
}
else
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));
}
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;
if (fileloc_isDefined (e->loc))
{
voptgenerror
- (FLG_ITER,
+ (FLG_ITERYIELD,
message ("Yield parameter is not simple identifier: %s",
exprNode_unparse (e)),
e->loc);
else
{
voptgenerror
- (FLG_ITER,
+ (FLG_ITERYIELD,
message ("Yield parameter is not simple identifier: %s",
exprNode_unparse (e)),
g_currentloc);
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))
{
if (exprNode_isDefined (e))
{
- /*@access sRef@*/
- if (e->sref == defref) /*@noaccess sRef@*/
+ if (sRef_isInvalid (e->sref))
{
/*@-mods@*/
e->sref = sRef_makeUnknown ();
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:
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:
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:
}
bool
-exprNode_isCharLit (exprNode e)
+exprNode_isCharLiteral (exprNode e)
{
if (exprNode_isDefined (e))
{
}
bool
-exprNode_isNumLit (exprNode e)
+exprNode_isNumLiteral (exprNode e)
{
if (exprNode_isDefined (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)
}
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))
{
}
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;
}
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));
}
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)));
{
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))
{
DPRINTF (("Defining! %s", sRef_unparseFull (s)));
- sRef_setDefined (s, fileloc_undefined);
+ sRef_setDefined (s, loc);
+ DPRINTF (("Defining! %s", sRef_unparseFull (s)));
}
+ */
}
s = sRef_getBaseSafe (s);
&& sRef_isPointer (errorRef))
{
errorRef = lastRef;
+ DPRINTF (("errorRef: %s", sRef_unparseFull (errorRef)));
}
if (deadRef)
}
else
{
- DPRINTF (("HERE: %s", sRef_unparse (errorRef)));
+ DPRINTF (("HERE: %s", sRef_unparseFull (errorRef)));
if (optgenerror
(FLG_USERELEASED,
{
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)));
}
}
}
- checkPassTransfer (current, ucurrent, isSpec, fcn, argno, totargs);
+ transferChecks_passParam (current, ucurrent, isSpec, fcn, argno, totargs);
exprNode_mergeUSs (fcn, current);
}
}
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)));
+
+ 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))
{
return ret;
}
-static void
+static bool
abstractOpError (ctype tr1, ctype tr2, lltok op,
/*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2,
fileloc loc1, fileloc loc2)
{
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,
}
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,
loc2);
}
}
+
+ return FALSE;
}
/*
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)))
{
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 */
{
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
}
}
+ if (exprNode_isStringLiteral (e2))
+ {
+ exprNode_checkStringLiteralLength (exprNode_getType (e1), e2);
+ }
+
if (isInit && sRef_isFileOrGlobalScope (e1->sref))
{
;
} 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)
{
/*
{
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;
+}