/* ;-*-C-*-;
-** Copyright (c) Massachusetts Institute of Technology 1994-1998.
-** All Rights Reserved.
-** Unpublished rights reserved under the copyright laws of
-** the United States.
+** Splint - annotation-assisted static program checker
+** Copyright (C) 1994-2002 University of Virginia,
+** Massachusetts Institute of Technology
**
-** THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
-** OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
+** This program is free software; you can redistribute it and/or modify it
+** under the terms of the GNU General Public License as published by the
+** Free Software Foundation; either version 2 of the License, or (at your
+** option) any later version.
+**
+** This program is distributed in the hope that it will be useful, but
+** WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+** General Public License for more details.
+**
+** The GNU General Public License is available from http://www.gnu.org/ or
+** the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+** MA 02111-1307, USA.
**
-** This code is distributed freely and may be used freely under the
-** following conditions:
-**
-** 1. This notice may not be removed or altered.
-**
-** 2. Works derived from this code are not distributed for
-** commercial gain without explicit permission from MIT
-** (for permission contact lclint-request@sds.lcs.mit.edu).
+** For information on splint: splint@cs.virginia.edu
+** To report a bug: splint-bug@cs.virginia.edu
+** For more information: http://www.splint.org
*/
/*
** ctbase.i
**
** NOTE: This is not a stand-alone source file, but is included in ctype.c.
-** (This is necessary becuase there is no other way in C to have a
+** (This is necessary because there is no other way in C to have a
** hidden scope, besides at the file level.)
*/
/*@access cprim*/
-typedef /*@null@*/ struct __ctbase *ctbase;
+abst_typedef /*@null@*/ struct s_ctbase *ctbase;
-typedef struct _ctentry {
+/*@private@*/ typedef struct {
ctkind kind;
- ctbase ctbase;
+ ctbase ctbase;
ctype base; /* type I point to (or element of array) */
ctype ptr; /* type of pointer to me */
ctype array; /* type of array of me */
typedef /*@only@*/ ctentry o_ctentry;
-typedef struct _cttable {
+typedef struct {
int size;
int nspace;
/*@relnull@*/ /*@only@*/ o_ctentry *entries;
static /*@notnull@*/ /*@only@*/ ctbase ctbase_createUnknown (void);
static bool ctbase_match (ctbase p_c1, ctbase p_c2) /*@modifies nothing@*/;
static bool ctbase_matchDef (ctbase p_c1, ctbase p_c2) /*@modifies nothing@*/;
-static bool ctbase_genMatch (ctbase p_c1, ctbase p_c2, bool p_force, bool p_arg, bool p_def);
+static bool ctbase_genMatch (ctbase p_c1, ctbase p_c2, bool p_force, bool p_arg, bool p_def, bool p_deep);
static bool ctbase_isAbstract (/*@notnull@*/ ctbase p_c) /*@*/ ;
static /*@notnull@*/ /*@only@*/ ctbase ctbase_makePointer (ctype p_b) /*@*/ ;
static /*@notnull@*/ /*@only@*/ ctbase ctbase_makeArray (ctype p_b) /*@*/ ;
static /*@notnull@*/ ctype
ctbase_makeFunction (ctype p_b, /*@only@*/ uentryList p_p) /*@*/ ;
-static /*@notnull@*/ /*@only@*/ ctbase
- ctbase_makeRealFunction (ctype p_b, /*@dependent@*/ uentryList p_p) /*@*/ ;
static /*@notnull@*/ /*@observer@*/ ctbase
ctbase_realFunction (/*@notnull@*/ /*@dependent@*/ ctbase p_c) /*@*/ ;
static ctype ctbase_baseArrayPtr (/*@notnull@*/ ctbase p_c) /*@*/ ;
# define cttable_lastIndex() (cttab.size - 1)
/*@=macroundef@*/
-typedef struct _cfcn
+typedef struct
{
ctype rval;
- /*@dependent@*/ uentryList params; /* params are owned if liveparams is TRUE */
- bool liveparams;
+ /*@only@*/ uentryList params;
} *cfcn;
-typedef struct _tsu
+typedef struct
{
cstring name;
uentryList fields;
} *tsu;
-typedef struct _tconj
+typedef struct
{
ctype a;
ctype b;
bool isExplicit;
} *tconj;
-typedef struct _tenum
+typedef struct
{
cstring tag;
enumNameList members;
} *tenum;
-typedef struct _tfixed
+typedef struct
{
ctype base;
long size;
} *tfixed;
-typedef union _uconts
+typedef union
{
cprim prim; /* primitive */
typeId tid; /* abstract, user */
tfixed farray; /* fixed array */
} uconts;
-struct __ctbase
+struct s_ctbase
{
ctuid type;
uconts contents;
static typeId ctbase_typeId (ctbase p_c);
static /*@only@*/ cstring ctbase_dump (ctbase p_c);
-static /*@only@*/ ctbase ctbase_undump (char **p_c);
+static /*@only@*/ ctbase ctbase_undump (char **p_c) /*@requires maxRead(*p_c) >= 2 @*/;
static int ctbase_compare (ctbase p_c1, ctbase p_c2, bool p_strict);
static bool ctbase_matchArg (ctbase p_c1, ctbase p_c2);
static /*@notnull@*/ /*@only@*/ ctbase
static ctype ctbase_getConjA (/*@notnull@*/ ctbase p_c) /*@*/ ;
static ctype ctbase_getConjB (/*@notnull@*/ ctbase p_c) /*@*/ ;
static bool ctbase_isExplicitConj (/*@notnull@*/ ctbase p_c) /*@*/ ;
-static bool ctbase_forceMatch (ctbase p_c1, ctbase p_c2);
+static bool ctbase_forceMatch (ctbase p_c1, ctbase p_c2) /*@modifies p_c1, p_c2@*/ ;
static /*@notnull@*/ /*@only@*/ ctbase ctbase_expectFunction (ctype p_c);
static bool ctbase_isVoidPointer(/*@notnull@*/ /*@dependent@*/ ctbase p_c) /*@*/ ;
-static bool ctbase_isUnion (/*@notnull@*/ /*@dependent@*/ ctbase p_c) /*@*/ ;
-static bool ctbase_isStruct (/*@notnull@*/ /*@dependent@*/ ctbase p_c) /*@*/ ;
+static bool ctbase_isUnion (/*@notnull@*/ /*@temp@*/ ctbase p_c) /*@*/ ;
+static bool ctbase_isStruct (/*@notnull@*/ /*@temp@*/ ctbase p_c) /*@*/ ;
static /*@observer@*/ cstring ctbase_enumTag (/*@notnull@*/ ctbase p_ct) /*@*/ ;
static /*@only@*/ cstring ctbase_unparseNotypes (ctbase p_c) /*@*/ ;
static int nctbases = 0;
static /*@notnull@*/ /*@only@*/
- ctbase ctbase_makeLiveFunction (ctype p_b, /*@owned@*/ uentryList p_p);
+ ctbase ctbase_makeLiveFunction (ctype p_b, /*@only@*/ uentryList p_p);
+
+static bool ctbase_isUnnamedSU (ctbase c)
+{
+ return (ctbase_isDefined (c)
+ && (ctbase_isStruct (c) || ctbase_isUnion (c))
+ && isFakeTag (c->contents.su->name));
+}
static /*@observer@*/ ctbase ctbase_realType (ctbase c)
{
}
static bool
-ctbase_isUnion (/*@notnull@*/ /*@dependent@*/ ctbase c)
+ctbase_isUnion (/*@notnull@*/ ctbase c)
{
ctbase r = ctbase_realType (c);
}
else
{
- llcontbug (message ("ctbase_typeId: bad call: %q", ctbase_unparse (c)));
- return typeId_invalid;
+ if (ctbase_isConj (c))
+ {
+ return ctbase_typeId (ctype_getCtbase (ctbase_getConjA (c)));
+ }
+ else
+ {
+ llcontbug (message ("ctbase_typeId: bad call: %q", ctbase_unparse (c)));
+ return typeId_invalid;
+ }
}
}
return (message ("%t *", c->contents.base));
}
case CT_FIXEDARRAY:
- return (message ("%t [%d]", c->contents.farray->base,
+ return (message ("%t [%d]",
+ c->contents.farray->base,
(int) c->contents.farray->size));
case CT_ARRAY:
return (message ("%t []", c->contents.base));
}
else
{
- return (message ("struct { %q }", uentryList_unparseAbbrev (c->contents.su->fields)));
+ return (message ("struct { %q }",
+ uentryList_unparseAbbrev (c->contents.su->fields)));
}
case CT_UNION:
if (cstring_isDefined (c->contents.su->name) &&
BADEXIT;
}
-static ctbase ctbase_undump (d_char *c)
+static ctbase ctbase_undump (d_char *c) /*@requires maxRead(*c) >= 2 @*/
{
ctbase res;
char p = **c;
case 'b':
return (ctbase_createBool ());
case 'p':
- res = ctbase_createPrim (cprim_fromInt (getInt (c)));
- checkChar (c, '|');
+ res = ctbase_createPrim (cprim_fromInt (reader_getInt (c)));
+ reader_checkChar (c, '|');
return res;
case 's':
- res = ctbase_createUser (typeId_fromInt (getInt (c)));
- checkChar (c, '|');
+ res = ctbase_createUser (typeId_fromInt (reader_getInt (c)));
+ reader_checkChar (c, '|');
return res;
case 'a':
- res = ctbase_createAbstract (typeId_fromInt (getInt (c)));
- checkChar (c, '|');
+ res = ctbase_createAbstract (typeId_fromInt (reader_getInt (c)));
+ reader_checkChar (c, '|');
return res;
case 't':
res = ctbase_makePointer (ctype_undump (c));
- checkChar (c, '|');
+ reader_checkChar (c, '|');
return res;
case 'y':
res = ctbase_makeArray (ctype_undump (c));
- checkChar (c, '|');
+ reader_checkChar (c, '|');
return res;
case 'F':
{
ctype ct = ctype_undump (c);
int size;
- checkChar (c, '/');
- size = getInt (c);
- checkChar (c, '|');
+ reader_checkChar (c, '/');
+ size = reader_getInt (c);
+ reader_checkChar (c, '|');
return (ctbase_makeFixedArray (ct, size));
}
case 'f':
bool isExplicit;
ctype c1, c2;
- isExplicit = bool_fromInt (getInt (c));
- checkChar (c, '.');
+ isExplicit = bool_fromInt (reader_getInt (c));
+ reader_checkChar (c, '.');
c1 = ctype_undump (c);
- checkChar (c, '/');
+ reader_checkChar (c, '/');
c2 = ctype_undump (c);
- checkChar (c, '|');
+ reader_checkChar (c, '|');
return (ctbase_makeConj (c1, c2, isExplicit));
}
llerror (FLG_SYNTAX,
message ("Bad Library line (type): %s", cstring_fromChars (*c)));
- while (**c != '\0')
+ /*drl bee: pbr*/ while (**c != '\0')
{
(*c)++;
}
ctype_dump (c->contents.farray->base),
(int) c->contents.farray->size));
case CT_FCN:
+ DPRINTF (("Dump function: %s", ctbase_unparse (c)));
return (message ("f%q (%q)", ctype_dump (c->contents.fcn->rval),
uentryList_dumpParams (c->contents.fcn->params)));
case CT_STRUCT:
sfree (c);
break;
case CT_FCN:
-
- if (c->contents.fcn->liveparams)
- {
- /* Because of liveparams, we know this can be released. */
-
- /*@-dependenttrans@*/ /*@-unqualifiedtrans@*/
- uentryList_free (c->contents.fcn->params);
- c->contents.fcn->params = NULL;
- /*@=dependenttrans@*/ /*@=unqualifiedtrans@*/
- }
-
+ /*@i32@*/ /* uentryList_free (c->contents.fcn->params); */
sfree (c);
break;
case CT_STRUCT:
}
static bool
-ctbase_genMatch (ctbase c1, ctbase c2, bool force, bool arg, bool def)
+ctbase_genMatch (ctbase c1, ctbase c2, bool force, bool arg, bool def, bool deep)
{
ctuid c1tid, c2tid;
c1 = ctbase_realType (c1);
c2 = ctbase_realType (c2);
+ DPRINTF (("Matching: %s / %s", ctbase_unparse (c1),
+ ctbase_unparse (c2)));
+
c1tid = c1->type;
c2tid = c2->type;
if (c1tid == CT_CONJ)
{
return (ctbase_genMatch (ctype_getCtbase (c1->contents.conj->a), c2,
- force, arg, def)
+ force, arg, def, deep)
|| ctbase_genMatch (ctype_getCtbase (c1->contents.conj->b), c2,
- force, arg, def));
+ force, arg, def, deep));
}
if (c2tid == CT_CONJ)
{
return (ctbase_genMatch (c1, ctype_getCtbase (c2->contents.conj->a),
- force, arg, def)
+ force, arg, def, deep)
|| ctbase_genMatch (c1, ctype_getCtbase (c2->contents.conj->b),
- force, arg, def));
+ force, arg, def, deep));
}
/*
return (ctbase_genMatch (ctype_getCtbase (c1->contents.farray->base),
ctype_getCtbase (c2->contents.base),
- force, arg, def));
+ force, arg, def, deep));
}
return (ctbase_genMatch (ctype_getCtbase (c1->contents.base),
ctype_getCtbase (c2->contents.farray->base),
- force, arg, def));
+ force, arg, def, deep));
}
- /* in most cases, bool and int are matched if FLG_BOOLINT */
-
+ /* evs 2000-07-25: Bool's may match user/abstract types */
+
if ((c1tid == CT_BOOL
&& (c2tid == CT_PRIM && cprim_isInt (c2->contents.prim))) ||
(c2tid == CT_BOOL
return (context_msgBoolInt ());
}
+ if ((c1tid == CT_BOOL && (c2tid == CT_ABST || c2tid == CT_USER))) {
+ ctype t2c = c2->contents.base;
+
+ return (ctype_isBool (t2c));
+ }
+
+ if ((c2tid == CT_BOOL && (c1tid == CT_ABST || c1tid == CT_USER))) {
+ ctype t1c = c1->contents.base;
+
+ return (ctype_isBool (t1c));
+ }
+
if ((c1tid == CT_ENUM
&& (c2tid == CT_PRIM && cprim_isInt (c2->contents.prim))) ||
(c2tid == CT_ENUM
case CT_UNKNOWN:
return (TRUE);
case CT_PRIM:
- return (cprim_closeEnough (c1->contents.prim, c2->contents.prim));
+ if (deep) {
+ return (cprim_closeEnoughDeep (c1->contents.prim, c2->contents.prim));
+ } else {
+ return (cprim_closeEnough (c1->contents.prim, c2->contents.prim));
+ }
case CT_BOOL:
return (TRUE);
case CT_ABST:
{
return FALSE;
}
-
+
return (ctype_genMatch (c1->contents.base,
- c2->contents.base, force, arg, def));
+ c2->contents.base, force, arg, def, TRUE));
}
case CT_FIXEDARRAY:
if (ctype_isVoid (c1->contents.farray->base)
return TRUE;
return (ctype_genMatch (c1->contents.farray->base,
c2->contents.farray->base,
- force, arg, def));
+ force, arg, def, deep));
case CT_ARRAY:
if (ctype_isVoid (c1->contents.base) || ctype_isVoid (c2->contents.base))
return TRUE;
- return (ctype_genMatch (c1->contents.base, c2->contents.base, force, arg, def));
+ return (ctype_genMatch (c1->contents.base, c2->contents.base, force, arg, def, TRUE));
case CT_FCN:
return (ctype_genMatch (c1->contents.fcn->rval,
c2->contents.fcn->rval,
- force, arg, def)
+ force, arg, def, TRUE)
&& uentryList_matchParams (c1->contents.fcn->params,
c2->contents.fcn->params,
force, TRUE));
case CT_STRUCT:
case CT_UNION:
- if (!cstring_isEmpty (c1->contents.su->name))
+ DPRINTF (("Struct: %s / %s",
+ c1->contents.su->name,
+ c2->contents.su->name));
+
+ if (isFakeTag (c1->contents.su->name)
+ && isFakeTag (c2->contents.su->name))
{
- return (cstring_equal (c1->contents.su->name, c2->contents.su->name));
+ /* Both fake tags, check structure */
+ if (cstring_equal (c1->contents.su->name, c2->contents.su->name))
+ {
+ return TRUE;
+ }
+ else
+ {
+ return uentryList_matchFields (c1->contents.su->fields,
+ c2->contents.su->fields);
+ }
}
else
{
- if (!cstring_isEmpty (c2->contents.su->name))
+ if (!cstring_isEmpty (c1->contents.su->name))
{
- return FALSE;
+ return (cstring_equal (c1->contents.su->name, c2->contents.su->name));
+ }
+ else
+ {
+ if (!cstring_isEmpty (c2->contents.su->name))
+ {
+ return FALSE;
+ }
+
+ llcontbuglit ("ctbase_genMatch: match fields");
+ return (FALSE);
}
-
- llcontbuglit ("ctbase_genMatch: match fields");
- return (FALSE);
}
default:
llcontbug (message ("ctbase_genMatch: unknown type: %d\n", (int)c1tid));
*/
static bool
-ctbase_forceMatch (ctbase c1, ctbase c2)
+ctbase_forceMatch (ctbase c1, ctbase c2) /*@modifies c1, c2@*/
{
- /*
- ** modifies c1, c2
- */
-
- return (ctbase_genMatch (c1, c2, TRUE, FALSE, FALSE));
+ return (ctbase_genMatch (c1, c2, TRUE, FALSE, FALSE, FALSE));
}
static bool
ctbase_match (ctbase c1, ctbase c2) /*@modifies nothing@*/
{
- return (ctbase_genMatch (c1, c2, FALSE, FALSE, FALSE));
+ return (ctbase_genMatch (c1, c2, FALSE, FALSE, FALSE, FALSE));
}
static bool
ctbase_matchDef (ctbase c1, ctbase c2) /*@modifies nothing@*/
{
- return (ctbase_genMatch (c1, c2, FALSE, FALSE, TRUE));
+ return (ctbase_genMatch (c1, c2, FALSE, FALSE, TRUE, FALSE));
}
static bool
ctbase_matchArg (ctbase c1, ctbase c2)
{
- return (ctbase_genMatch (c1, c2, FALSE, TRUE, FALSE));
+ return (ctbase_genMatch (c1, c2, FALSE, TRUE, FALSE, FALSE));
}
static /*@out@*/ /*@only@*/ /*@notnull@*/ ctbase
rval = ctype_makeFunction (ctb->contents.fcn->rval, p);
c->contents.fcn->rval = rval;
- c->contents.fcn->params = ctb->contents.fcn->params;
- c->contents.fcn->liveparams = FALSE;
+ c->contents.fcn->params = uentryList_copy (ctb->contents.fcn->params); /* no copy before */
}
else
{
c->contents.fcn->rval = b;
- /*@i@*/ c->contents.fcn->params = p;
- c->contents.fcn->liveparams = TRUE;
+ c->contents.fcn->params = uentryList_copy (p); /* no copy before */
/*@-branchstate@*/ /* p is really released on this branch */
}
/*@=branchstate@*/
rval = ctype_makeNFParamsFunction (ctb->contents.fcn->rval, p);
c->contents.fcn->rval = rval;
- c->contents.fcn->params = ctb->contents.fcn->params;
- c->contents.fcn->liveparams = FALSE;
+ c->contents.fcn->params = uentryList_copy (ctb->contents.fcn->params);
}
else
{
c->contents.fcn->rval = b;
- /*@i@*/ c->contents.fcn->params = p;
- c->contents.fcn->liveparams = TRUE;
-
+ c->contents.fcn->params = uentryList_copy (p);
/*@-branchstate@*/
}
/*@=branchstate@*/
}
static /*@only@*/ ctbase
- ctbase_makeLiveFunction (ctype b, /*@owned@*/ uentryList p)
+ ctbase_makeLiveFunction (ctype b, /*@only@*/ uentryList p)
{
ctbase c = ctbase_new ();
c->contents.fcn = (cfcn) dmalloc (sizeof (*c->contents.fcn));
c->contents.fcn->rval = b;
c->contents.fcn->params = p;
- c->contents.fcn->liveparams = TRUE;
/*@-mustfree@*/ return (c); /*@=mustfree@*/
}
-static /*@only@*/ ctbase
- ctbase_makeRealFunction (ctype b, /*@dependent@*/ uentryList p)
-{
- ctbase c = ctbase_new ();
-
- c->type = CT_FCN;
-
- c->contents.fcn = (cfcn) dmalloc (sizeof (*c->contents.fcn));
- c->contents.fcn->rval = b;
- c->contents.fcn->params = p;
- c->contents.fcn->liveparams = FALSE;
-
- return (c);
-}
-
static /*@observer@*/ /*@notnull@*/ ctbase
ctbase_realFunction (/*@dependent@*/ /*@notnull@*/ ctbase c)
{
if (cb->type == CT_FCN)
{
- c = ctype_removePointers (ctype_returnValue (c));
+ c = ctype_removePointers (ctype_getReturnType (c));
cb = ctype_getCtbase (c);
llassert (ctbase_isDefined (cb));
DPRINTF (("New base: %s / %s", ctype_unparse (c), ctype_unparse (p)));
- cb = ctype_getCtbase (c);
-
- if (ctype_isUndefined (c))
+ if (ctype_isUndefined (c) || ctype_isUnknown (c))
{
return p;
}
+ cb = ctype_getCtbase (c);
+
if (ctype_isConj (p))
{
ctbase pb = ctype_getCtbase (p);
case CT_ARRAY:
return (ctype_makeArray (ctbase_newBase (cb->contents.base, p)));
case CT_FCN:
- return (ctype_makeRealFunction (ctbase_newBase (cb->contents.fcn->rval, p),
+ return (ctype_makeRawFunction (ctbase_newBase (cb->contents.fcn->rval, p),
cb->contents.fcn->params));
case CT_CONJ:
return (ctype_makeConjAux (ctbase_newBase (cb->contents.conj->a, p),
if (!ctbase_isFunction (cb))
llbuglit ("ctbase_newBaseExpFcn: expFcn -> not a function");
- tmpct = ctype_getBaseType (ctype_returnValue (c));
+ tmpct = ctype_getBaseType (ctype_getReturnType (c));
/*
** pointers before expfcn -> p are pointers to function, not result
}
exitLoop:
- tmpct = ctype_returnValue (c);
+ tmpct = ctype_getReturnType (c);
/*
** pointers to expf are pointers to return value
** pointers to fp are pointers to function type
*/
- ret = ctype_makeRealFunction (p, ctargs);
+ ret = ctype_makeRawFunction (p, uentryList_copy (ctargs));
while (ctype_getCtKind (fp) > CTK_PLAIN)
{
return (ctype_compare (c1->contents.base, c2->contents.base));
case CT_STRUCT:
case CT_UNION:
+ /* evs 2000-07-28: this block was missing! */
+ if (strict) {
+ int ncmp = cstring_compare (c1->contents.su->name,
+ c2->contents.su->name);
+
+ if (ncmp != 0) {
+ if (isFakeTag (c1->contents.su->name)
+ && isFakeTag (c2->contents.su->name)) {
+ ; /* If they are both fake struct tags, don't require match. */
+ } else {
+ return ncmp;
+ }
+ }
+ }
+
+ DPRINTF (("Comparing fields: %s / %s",
+ ctbase_unparse (c1),
+ ctbase_unparse (c2)));
+
return (uentryList_compareFields (c1->contents.su->fields,
c2->contents.su->fields));
case CT_CONJ:
return (FALSE);
}
}
+
+/*drl added July 02, 001
+ called by ctype_getArraySize
+*/
+
+long int ctbase_getArraySize (ctbase ctb)
+{
+ /*drl 1/25/2002 fixed discover by Jim Francis */
+ ctbase r;
+
+
+ llassert (ctbase_isDefined (ctb) );
+ r = ctbase_realType (ctb);
+ llassert (ctbase_isFixedArray(r) );
+
+
+
+ return (r->contents.farray->size);
+
+}