/* ;-*-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-2003 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
abst_typedef /*@null@*/ struct s_ctbase *ctbase;
-/*@private@*/ typedef struct {
+/*@function static bool ctuid_isAnyUserType (sef ctuid p_cid) @*/
+
+/*@-macrofcndecl@*/ /*@-macroparams@*/
+# define ctuid_isAnyUserType(cid) \
+ ((cid) == CT_ABST || (cid) == CT_USER || (cid) == CT_NUMABST)
+/*@=macrofcndecl@*/ /*@=macroparams@*/
+
+/*:private:*/ typedef struct {
ctkind kind;
ctbase ctbase;
ctype base; /* type I point to (or element of array) */
static cttable cttab = { 0, 0, NULL };
static /*@notnull@*/ /*@only@*/ ctbase ctbase_createAbstract (typeId p_u);
+static /*@notnull@*/ /*@only@*/ ctbase ctbase_createNumAbstract (typeId p_u);
static /*@observer@*/ cstring ctentry_doUnparse (ctentry p_c) /*@modifies p_c@*/;
static /*@only@*/ ctentry
ctentry_make (ctkind p_ctk, /*@keep@*/ ctbase p_c, ctype p_base,
static ctype cttable_addDerived (ctkind p_ctk, /*@keep@*/ ctbase p_cnew, ctype p_base);
static ctype cttable_addFull (/*@keep@*/ ctentry p_cnew);
static bool ctentry_isInteresting (ctentry p_c) /*@*/;
-static /*@notnull@*/ /*@only@*/ ctbase ctbase_makeFixedArray (ctype p_b, long p_size) /*@*/ ;
+static /*@notnull@*/ /*@only@*/ ctbase ctbase_makeFixedArray (ctype p_b, size_t p_size) /*@*/ ;
+static bool ctbase_isAnytype (/*@notnull@*/ ctbase p_b) /*@*/ ;
/*
** These are file-static macros (used in ctype.c). No way to
typedef struct
{
ctype base;
- long size;
+ size_t size;
} *tfixed;
typedef union
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
{
return ctbase_typeBaseUid (ctype_getCtbase (c->contents.base));
}
- else if (ct == CT_USER || ct == CT_ABST)
+ else if (ct == CT_USER || ct == CT_ABST || ct == CT_NUMABST)
{
return c->contents.tid;
}
return ctbase_isBaseUA (ctype_getCtbase (c->contents.farray->base));
}
else
- return (ct == CT_USER || ct == CT_ABST);
+ return (ct == CT_USER || ct == CT_ABST || ct == CT_NUMABST);
}
return FALSE;
}
{
if (ctbase_isConj (c))
{
- return ctbase_typeId (ctype_getCtbase (ctbase_getConjA (c)));
+ if (ctype_isUA (ctbase_getConjA (c))) {
+ return ctbase_typeId (ctype_getCtbase (ctbase_getConjA (c)));
+ } else if (ctype_isUA (ctbase_getConjB (c))) {
+ return ctbase_typeId (ctype_getCtbase (ctbase_getConjB (c)));
+ } else {
+ llcontbug (message ("ctbase_typeId: bad call: %q", ctbase_unparse (c)));
+ return typeId_invalid;
+ }
}
else
{
case CT_PRIM:
return (cprim_unparse (c->contents.prim));
case CT_USER:
- return (usymtab_getTypeEntryName (c->contents.tid));
case CT_ABST:
+ case CT_NUMABST:
return (usymtab_getTypeEntryName (c->contents.tid));
case CT_EXPFCN:
return (message ("<expf: %t>", c->contents.base));
return (message ("%t *", c->contents.base));
}
case CT_FIXEDARRAY:
- return (message ("%t [%d]", c->contents.farray->base,
- (int) c->contents.farray->size));
+ /*
+ ** C prints out array declarations backwards, if
+ ** base is an array need to print out in reverse order.
+ */
+
+ if (ctype_isArray (c->contents.farray->base))
+ {
+ ctype base = c->contents.farray->base;
+ cstring res = message ("[%d]", (int) c->contents.farray->size);
+
+ while (ctype_isArray (base))
+ {
+ if (ctype_isFixedArray (base))
+ {
+ res = message ("%q[%d]",
+ res, (int) ctype_getArraySize (base));
+ }
+ else
+ {
+ res = message ("%q[]", res);
+ }
+
+ base = ctype_baseArrayPtr (base);
+ }
+
+ return (message ("%t %q", base, res));
+ }
+ else
+ {
+ return (message ("%t [%d]",
+ c->contents.farray->base,
+ (int) c->contents.farray->size));
+ }
case CT_ARRAY:
- return (message ("%t []", c->contents.base));
+ if (ctype_isArray (c->contents.base))
+ {
+ ctype base = c->contents.base;
+ cstring res = cstring_makeLiteral ("[]");
+
+ while (ctype_isArray (base))
+ {
+ if (ctype_isFixedArray (base))
+ {
+ res = message ("%q[%d]",
+ res, (int) ctype_getArraySize (base));
+ }
+ else
+ {
+ res = message ("%q[]", res);
+ }
+
+ base = ctype_baseArrayPtr (base);
+ }
+
+ return (message ("%t %q", base, res));
+
+ }
+ else
+ {
+ return (message ("%t []", c->contents.base));
+ }
case CT_FCN:
return (message ("[function (%q) returns %t]",
uentryList_unparseParams (c->contents.fcn->params),
enumNameList_unparseBrief (c->contents.cenum->members)));
}
case CT_CONJ:
- if (c->contents.conj->isExplicit || context_getFlag (FLG_SHOWALLCONJS))
+ if (ctbase_isAnytype (c))
+ {
+ return (cstring_makeLiteral ("<any>"));
+ }
+ else if (c->contents.conj->isExplicit || context_getFlag (FLG_SHOWALLCONJS))
{
if (!ctype_isSimple (c->contents.conj->a) ||
!ctype_isSimple (c->contents.conj->b))
enumNameList_unparse (c->contents.cenum->members)));
}
case CT_USER:
- return (usymtab_getTypeEntryName (c->contents.tid));
case CT_ABST:
+ case CT_NUMABST:
return (usymtab_getTypeEntryName (c->contents.tid));
case CT_EXPFCN:
return (message ("<expf: %t>", c->contents.base));
case CT_UNION:
return (message ("union %s { ... }", c->contents.su->name));
case CT_CONJ:
- return (message ("%t", c->contents.conj->a));
+ if (ctbase_isAnytype (c))
+ {
+ return (cstring_makeLiteral ("<any>"));
+ }
+ else
+ {
+ return (message ("%t", c->contents.conj->a));
+ }
BADDEFAULT;
}
BADEXIT;
return (message ("uT#%d", c->contents.tid));
case CT_ABST:
return (message ("aT#%d", c->contents.tid));
+ case CT_NUMABST:
+ return (message ("nT#%d", c->contents.tid));
case CT_EXPFCN:
return (message ("<expf: %q >", ctbase_unparseNotypes (ctype_getCtbase (c->contents.base))));
case CT_PTR:
case CT_ENUMLIST:
return (message ("[enumlist]"));
case CT_CONJ:
- return (message ("%q/%q",
- ctbase_unparseNotypes (ctype_getCtbase (c->contents.conj->a)),
- ctbase_unparseNotypes (ctype_getCtbase (c->contents.conj->b))));
+ if (ctbase_isAnytype (c))
+ {
+ return (cstring_makeLiteral ("<any>"));
+ }
+ else
+ {
+ return (message ("%q/%q",
+ ctbase_unparseNotypes (ctype_getCtbase (c->contents.conj->a)),
+ ctbase_unparseNotypes (ctype_getCtbase (c->contents.conj->b))));
+ }
BADDEFAULT;
}
BADEXIT;
return (message ("%q %q", cprim_unparse (c->contents.prim), name));
case CT_USER:
case CT_ABST:
+ case CT_NUMABST:
return (message ("%q %q", usymtab_getTypeEntryName (c->contents.tid), name));
case CT_EXPFCN:
llcontbuglit ("ctbase_unparseDeclaration: expfcn");
enumNameList_unparseBrief (c->contents.cenum->members),
name));
}
- case CT_CONJ:
- if (c->contents.conj->isExplicit || context_getFlag (FLG_SHOWALLCONJS))
+ case CT_CONJ:
+ if (ctbase_isAnytype (c))
+ {
+ return (message ("<any> %q", name));
+ }
+ else if (c->contents.conj->isExplicit || context_getFlag (FLG_SHOWALLCONJS))
{
if (!ctype_isSimple (c->contents.conj->a) ||
!ctype_isSimple (c->contents.conj->b))
BADEXIT;
}
-static ctbase ctbase_undump (d_char *c)
+static ctbase ctbase_undump (d_char *c) /*@requires maxRead(*c) >= 2 @*/
{
ctbase res;
char p = **c;
res = ctbase_createAbstract (typeId_fromInt (reader_getInt (c)));
reader_checkChar (c, '|');
return res;
+ case 'n':
+ res = ctbase_createNumAbstract (typeId_fromInt (reader_getInt (c)));
+ reader_checkChar (c, '|');
+ return res;
case 't':
res = ctbase_makePointer (ctype_undump (c));
reader_checkChar (c, '|');
case 'F':
{
ctype ct = ctype_undump (c);
- int size;
+ size_t size;
reader_checkChar (c, '/');
- size = reader_getInt (c);
+ size = size_fromInt (reader_getInt (c));
reader_checkChar (c, '|');
return (ctbase_makeFixedArray (ct, size));
}
llerror (FLG_SYNTAX,
message ("Bad Library line (type): %s", cstring_fromChars (*c)));
- while (**c != '\0')
+ /*drl bee: pbr*/ while (**c != '\0')
{
(*c)++;
}
case CT_PRIM:
return (message ("p%d|", c->contents.prim));
case CT_USER:
- return (message ("s%d|",
- usymtab_convertId (c->contents.tid)));
+ return (message ("s%d|", usymtab_convertTypeId (c->contents.tid)));
case CT_ABST:
- return (message ("a%d|", usymtab_convertId (c->contents.tid)));
+ return (message ("a%d|", usymtab_convertTypeId (c->contents.tid)));
+ case CT_NUMABST:
+ return (message ("n%d|", usymtab_convertTypeId (c->contents.tid)));
case CT_PTR:
return (message ("t%q|", ctype_dump (c->contents.base)));
case CT_ARRAY:
return (ctbase_createUser (c->contents.tid));
case CT_ABST:
return (ctbase_createAbstract (c->contents.tid));
+ case CT_NUMABST:
+ return (ctbase_createNumAbstract (c->contents.tid));
case CT_EXPFCN:
return (ctbase_expectFunction (c->contents.base));
case CT_PTR:
sfree (c);
break;
case CT_USER:
- sfree (c);
- break;
case CT_ABST:
+ case CT_NUMABST:
sfree (c);
break;
case CT_PTR:
sfree (c);
break;
case CT_FCN:
- /*@i32@*/ /* uentryList_free (c->contents.fcn->params); */
+ /* Cannot free params: uentryList_free (c->contents.fcn->params); */
+ uentryList_freeShallow (c->contents.fcn->params);
sfree (c);
break;
case CT_STRUCT:
return (f);
}
+static bool
+ctbase_isExpectFunction (/*@notnull@*/ ctbase ct) /*@*/
+{
+ return (ct->type == CT_EXPFCN);
+}
+
+static ctype
+ctbase_getExpectFunction (/*@notnull@*/ ctbase ct)
+{
+ llassert (ctbase_isExpectFunction (ct));
+ return ct->contents.base;
+}
+
static bool
ctbase_genMatch (ctbase c1, ctbase c2, bool force, bool arg, bool def, bool deep)
{
return (context_msgBoolInt ());
}
- if ((c1tid == CT_BOOL && (c2tid == CT_ABST || c2tid == CT_USER))) {
+ if ((c1tid == CT_BOOL && (ctuid_isAnyUserType (c2tid)))) {
ctype t2c = c2->contents.base;
-
return (ctype_isBool (t2c));
}
- if ((c2tid == CT_BOOL && (c1tid == CT_ABST || c1tid == CT_USER))) {
+ if ((c2tid == CT_BOOL && (ctuid_isAnyUserType (c1tid)))) {
ctype t1c = c1->contents.base;
return (ctype_isBool (t1c));
if (context_getFlag (FLG_FORWARDDECL))
{
- if (c1tid == CT_ABST || c1tid == CT_USER)
+ if (ctuid_isAnyUserType (c1tid))
{
if (ctuid_isAP (c2tid))
{
}
}
- if (c2tid == CT_ABST || c2tid == CT_USER)
+ if (ctuid_isAnyUserType (c2tid))
{
if (ctuid_isAP (c1tid))
{
case CT_BOOL:
return (TRUE);
case CT_ABST:
- return (typeId_equal (c1->contents.tid, c2->contents.tid));
+ case CT_NUMABST:
case CT_USER:
return (typeId_equal (c1->contents.tid, c2->contents.tid));
case CT_ENUM:
return (c);
}
+static /*@only@*/ ctbase
+ctbase_createNumAbstract (typeId u)
+{
+ ctbase c = ctbase_new ();
+
+ c->type = CT_NUMABST;
+ c->contents.tid = u;
+
+ /* also check its abstract? */
+
+ llassert (typeId_isValid (c->contents.tid));
+ return (c);
+}
+
static /*@only@*/ ctbase
ctbase_createUnknown (void)
{
}
static /*@notnull@*/ /*@only@*/ ctbase
-ctbase_makeFixedArray (ctype b, long size)
+ctbase_makeFixedArray (ctype b, size_t size)
{
ctbase c = ctbase_new ();
return (c);
}
+static bool ctbase_isAnytype (/*@notnull@*/ ctbase b)
+{
+ /*
+ ** A unknown|dne conj is a special representation for an anytype.
+ */
+
+ if (b->type == CT_CONJ)
+ {
+ /*@access ctype@*/
+ return (b->contents.conj->a == ctype_unknown
+ && b->contents.conj->b == ctype_dne);
+ /*@noaccess ctype@*/
+ }
+
+ return FALSE;
+}
+
static ctype
ctbase_getConjA (/*@notnull@*/ ctbase c)
{
case CT_USER:
case CT_ENUM:
case CT_ABST:
+ case CT_NUMABST:
case CT_STRUCT:
case CT_UNION:
case CT_EXPFCN:
case CT_ENUMLIST:
case CT_BOOL:
case CT_ABST:
+ case CT_NUMABST:
case CT_FCN:
case CT_STRUCT:
case CT_UNION:
case CT_BOOL:
return 0;
case CT_USER:
- return (int_compare (c1->contents.tid, c2->contents.tid));
+ return (typeId_compare (c1->contents.tid, c2->contents.tid));
case CT_ENUMLIST:
return 1;
case CT_ENUM: /* for now, keep like abstract */
case CT_ABST:
- return (int_compare (c1->contents.tid, c2->contents.tid));
+ case CT_NUMABST:
+ return (typeId_compare (c1->contents.tid, c2->contents.tid));
case CT_PTR:
return (ctype_compare (c1->contents.base, c2->contents.base));
case CT_FIXEDARRAY:
static bool
ctbase_isAbstract (/*@notnull@*/ ctbase c)
{
- return (c->type == CT_ABST);
+ return (c->type == CT_ABST || c->type == CT_NUMABST);
+}
+
+static bool
+ctbase_isNumAbstract (/*@notnull@*/ ctbase c)
+{
+ return (c->type == CT_NUMABST);
}
static bool ctbase_isUA (ctbase c)
{
- return (ctbase_isDefined (c) && ((c)->type == CT_USER || (c)->type == CT_ABST));
+ return (ctbase_isDefined (c) && (ctuid_isAnyUserType (c->type)));
}
static bool
case CT_BOOL:
return TRUE;
case CT_ABST:
- return (typeId_equal (c1->contents.tid, c2->contents.tid));
+ case CT_NUMABST:
case CT_USER:
return (typeId_equal (c1->contents.tid, c2->contents.tid));
case CT_ENUM:
called by ctype_getArraySize
*/
-long int ctbase_getArraySize (ctbase ctb)
+size_t ctbase_getArraySize (ctbase ctb)
{
- llassert (ctbase_isDefined (ctb) );
+ /*drl 1/25/2002 fixed discovered by Jim Francis */
+ ctbase r;
- llassert (ctbase_isFixedArray(ctb) );
+ llassert (ctbase_isDefined (ctb) );
+ r = ctbase_realType (ctb);
+ llassert (ctbase_isFixedArray(r) );
+
+ return (r->contents.farray->size);
+}
+
+bool ctbase_isBigger (ctbase ct1, ctbase ct2)
+{
+ if (ct1 != NULL && ct2 != NULL
+ && (ct1->type == CT_PRIM && ct2->type == CT_PRIM))
+ {
+ /* Only compare sizes for primitives */
+ cprim cp1 = ct1->contents.prim;
+ cprim cp2 = ct2->contents.prim;
+ int nbits1 = cprim_getExpectedBits (cp1);
+ int nbits2 = cprim_getExpectedBits (cp2);
+
+ if (nbits1 > nbits2) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+ }
+ else
+ {
+ return FALSE;
+ }
+}
+
+int ctbase_getSize (ctbase ct)
+{
+ if (ct == NULL)
+ {
+ return 0;
+ }
- return (ctb->contents.farray->size);
+ switch (ct->type)
+ {
+ case CT_UNKNOWN:
+ case CT_BOOL:
+ case CT_PRIM:
+ {
+ cprim cp = ct->contents.prim;
+ int nbits = cprim_getExpectedBits (cp);
+ return nbits;
+ }
+ case CT_USER:
+ case CT_ABST:
+ case CT_NUMABST:
+ case CT_EXPFCN:
+ {
+ return 0;
+ }
+ case CT_PTR:
+ {
+ /* Malloc returns void *, but they are bytes. Normal void * is pointer size. */
+ if (ctype_isVoid (ct->contents.base))
+ {
+ return 8;
+ }
+ else
+ {
+ return ctype_getSize (ct->contents.base);
+ }
+ }
+ case CT_FIXEDARRAY:
+ case CT_ARRAY:
+ case CT_FCN:
+ case CT_STRUCT:
+ case CT_UNION:
+ case CT_ENUM:
+ case CT_CONJ:
+ break;
+ BADDEFAULT;
+ }
+ return 0;
+
}