2 ** Splint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2003 University of Virginia,
4 ** Massachusetts Institute of Technology
6 ** This program is free software; you can redistribute it and/or modify it
7 ** under the terms of the GNU General Public License as published by the
8 ** Free Software Foundation; either version 2 of the License, or (at your
9 ** option) any later version.
11 ** This program is distributed in the hope that it will be useful, but
12 ** WITHOUT ANY WARRANTY; without even the implied warranty of
13 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 ** General Public License for more details.
16 ** The GNU General Public License is available from http://www.gnu.org/ or
17 ** the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
18 ** MA 02111-1307, USA.
20 ** For information on splint: info@splint.org
21 ** To report a bug: splint-bug@splint.org
22 ** For more information: http://www.splint.org
28 # include "splintMacros.nf"
30 # include "cgrammar.h"
31 # include "cgrammar_tokens.h"
34 stateClause_createRaw (stateConstraint st, stateClauseKind sk, /*@only@*/ sRefSet s)
36 stateClause ret = (stateClause) dmalloc (sizeof (*ret));
40 ret->squal = qual_createUnknown ();
42 ret->loc = fileloc_undefined;
46 /*drl added 3/7/2003*/
47 bool stateClause_hasEmptyReferences (stateClause s)
49 if (sRefSet_isUndefined(s->refs) )
55 bool stateClause_isMetaState (stateClause s)
58 if (qual_isMetaState (s->squal) )
65 stateClause_create (lltok tok, qual q, sRefSet s)
67 stateClause ret = (stateClause) dmalloc (sizeof (*ret));
69 if (lltok_getTok (tok) == QPRECLAUSE)
71 ret->state = TK_BEFORE;
73 else if (lltok_getTok (tok) == QPOSTCLAUSE)
75 ret->state = TK_AFTER;
82 ret->loc = fileloc_copy (lltok_getLoc (tok));
87 if (sRefSet_isDefined (s))
93 ret->kind = SP_GLOBAL;
99 bool stateClause_isBeforeOnly (stateClause cl)
101 return (cl->state == TK_BEFORE);
104 bool stateClause_isBefore (stateClause cl)
106 return (cl->state == TK_BEFORE || cl->state == TK_BOTH);
109 bool stateClause_isAfter (stateClause cl)
111 return (cl->state == TK_AFTER || cl->state == TK_BOTH);
114 bool stateClause_isEnsures (stateClause cl)
116 return (cl->state == TK_AFTER);
119 bool stateClause_isQual (stateClause cl)
121 return (cl->kind == SP_QUAL);
124 bool stateClause_isMemoryAllocation (stateClause cl)
138 return (qual_isMemoryAllocation (cl->squal)
139 || qual_isSharing (cl->squal));
146 ** An error is reported if the test is NOT true.
150 /* Microsoft doesn't believe in higher order functions... */
\r
151 # pragma warning( disable : 4550 )
\r
154 sRefTest stateClause_getPreTestFunction (stateClause cl)
159 return sRef_isStrictReadable;
161 return sRef_hasNoStorage;
163 return sRef_hasNoStorage;
165 return sRef_isNotUndefined;
167 return sRef_isNotUndefined;
172 if (qual_isOnly (cl->squal)) {
174 } else if (qual_isShared (cl->squal)) {
175 return sRef_isShared;
176 } else if (qual_isDependent (cl->squal)) {
177 return sRef_isDependent;
178 } else if (qual_isOwned (cl->squal)) {
180 } else if (qual_isObserver (cl->squal)) {
181 return sRef_isObserver;
182 } else if (qual_isExposed (cl->squal)) {
183 return sRef_isExposed;
184 } else if (qual_isNotNull (cl->squal)) {
185 return sRef_isNotNull;
186 } else if (qual_isIsNull (cl->squal)) {
187 return sRef_isDefinitelyNull;
197 sRefTest stateClause_getPostTestFunction (stateClause cl)
199 llassert (stateClause_isAfter (cl));
206 return sRef_isAllocated;
208 return sRef_isReallyDefined;
210 return sRef_isReallyDefined;
212 return sRef_isDeadStorage;
216 if (qual_isOnly (cl->squal)) {
218 } else if (qual_isShared (cl->squal)) {
219 return sRef_isShared;
220 } else if (qual_isDependent (cl->squal)) {
221 return sRef_isDependent;
222 } else if (qual_isOwned (cl->squal)) {
224 } else if (qual_isObserver (cl->squal)) {
225 return sRef_isObserver;
226 } else if (qual_isExposed (cl->squal)) {
227 return sRef_isExposed;
228 } else if (qual_isNotNull (cl->squal)) {
229 return sRef_isNotNull;
230 } else if (qual_isIsNull (cl->squal)) {
231 return sRef_isDefinitelyNull;
240 sRefShower stateClause_getPostTestShower (stateClause cl)
249 return sRef_showNotReallyDefined;
255 if (qual_isMemoryAllocation (cl->squal)) {
256 return sRef_showAliasInfo;
257 } else if (qual_isSharing (cl->squal)) {
258 return sRef_showExpInfo;
259 } else if (qual_isIsNull (cl->squal) || qual_isNotNull (cl->squal)) {
260 return sRef_showNullInfo;
269 sRefMod stateClause_getEntryFunction (stateClause cl)
271 if (cl->state == TK_BEFORE || cl->state == TK_BOTH)
276 return sRef_setDefinedComplete;
278 return sRef_setUndefined; /* evans 2002-01-01 */
280 return sRef_setUndefined; /* evans 2002-01-01 */
282 return sRef_setAllocatedComplete;
284 return sRef_setDefinedComplete;
288 if (qual_isOnly (cl->squal)) {
290 } else if (qual_isShared (cl->squal)) {
291 return sRef_setShared;
292 } else if (qual_isDependent (cl->squal)) {
293 return sRef_setDependent;
294 } else if (qual_isOwned (cl->squal)) {
295 return sRef_setOwned;
296 } else if (qual_isObserver (cl->squal)) {
297 return sRef_setObserver;
298 } else if (qual_isExposed (cl->squal)) {
299 return sRef_setExposed;
300 } else if (qual_isNotNull (cl->squal)) {
301 return sRef_setNotNull;
302 } else if (qual_isIsNull (cl->squal)) {
303 return sRef_setDefNull;
305 DPRINTF (("Here we are: %s",
306 qual_unparse (cl->squal)));
321 sRefMod stateClause_getEffectFunction (stateClause cl)
323 if (cl->state == TK_AFTER || cl->state == TK_BOTH)
330 return sRef_setAllocatedComplete;
332 return sRef_setDefinedNCComplete;
334 return sRef_setDefinedNCComplete;
336 return sRef_killComplete;
340 if (qual_isOnly (cl->squal)) {
342 } else if (qual_isShared (cl->squal)) {
343 return sRef_setShared;
344 } else if (qual_isDependent (cl->squal)) {
345 return sRef_setDependent;
346 } else if (qual_isOwned (cl->squal)) {
347 return sRef_setOwned;
348 } else if (qual_isObserver (cl->squal)) {
349 return sRef_setObserver;
350 } else if (qual_isExposed (cl->squal)) {
351 return sRef_setExposed;
352 } else if (qual_isNotNull (cl->squal)) {
353 return sRef_setNotNull;
354 } else if (qual_isIsNull (cl->squal)) {
355 return sRef_setDefNull;
371 sRefMod stateClause_getReturnEffectFunction (stateClause cl)
373 if (cl->state == TK_AFTER || cl->state == TK_BOTH)
386 if (qual_isOnly (cl->squal)) {
387 return sRef_killComplete;
403 static flagcode stateClause_qualErrorCode (stateClause cl)
405 if (qual_isOnly (cl->squal)) {
406 return FLG_ONLYTRANS;
407 } else if (qual_isShared (cl->squal)) {
408 return FLG_SHAREDTRANS;
409 } else if (qual_isDependent (cl->squal)) {
410 return FLG_DEPENDENTTRANS;
411 } else if (qual_isOwned (cl->squal)) {
412 return FLG_OWNEDTRANS;
413 } else if (qual_isObserver (cl->squal)) {
414 return FLG_OBSERVERTRANS;
415 } else if (qual_isExposed (cl->squal)) {
416 return FLG_EXPOSETRANS;
417 } else if (qual_isIsNull (cl->squal)
418 || qual_isNotNull (cl->squal)) {
419 return FLG_NULLSTATE;
424 BADBRANCHRET (INVALID_FLAG);
427 flagcode stateClause_preErrorCode (stateClause cl)
429 llassert (cl->state == TK_BOTH || cl->state == TK_BEFORE);
435 case SP_ALLOCATES: /*@fallthrough@*/
438 return FLG_MUSTFREEONLY;
443 return stateClause_qualErrorCode (cl);
446 BADBRANCHRET (INVALID_FLAG);
449 static /*@observer@*/ cstring stateClause_qualErrorString (stateClause cl, sRef sr)
451 if (qual_isMemoryAllocation (cl->squal)) {
452 return alkind_capName (sRef_getAliasKind (sr));
453 } else if (qual_isObserver (cl->squal)) {
454 return cstring_makeLiteralTemp ("Non-observer");
455 } else if (qual_isExposed (cl->squal)) {
456 if (sRef_isObserver (sr))
458 return cstring_makeLiteralTemp ("Observer");
462 return cstring_makeLiteralTemp ("Non-exposed");
464 } else if (qual_isNotNull (cl->squal)) {
465 if (sRef_isDefinitelyNull (sr))
467 return cstring_makeLiteralTemp ("Null");
471 return cstring_makeLiteralTemp ("Possibly null");
473 } else if (qual_isIsNull (cl->squal)) {
474 return cstring_makeLiteralTemp ("Non-null");
479 BADBRANCHRET (cstring_undefined);
482 cstring stateClause_preErrorString (stateClause cl, sRef sr)
484 llassert (cl->state == TK_BOTH || cl->state == TK_BEFORE);
489 if (sRef_isDead (sr))
490 return cstring_makeLiteralTemp ("Dead");
492 return cstring_makeLiteralTemp ("Undefined");
493 case SP_ALLOCATES: /*@fallthrough@*/
496 return cstring_makeLiteralTemp ("Allocated");
498 if (sRef_isDead (sr))
500 return cstring_makeLiteralTemp ("Dead");
502 else if (sRef_isDependent (sr)
503 || sRef_isShared (sr))
505 return alkind_unparse (sRef_getAliasKind (sr));
507 else if (sRef_isObserver (sr) || sRef_isExposed (sr))
509 return exkind_unparse (sRef_getExKind (sr));
513 return cstring_makeLiteralTemp ("Undefined");
518 return stateClause_qualErrorString (cl, sr);
524 flagcode stateClause_postErrorCode (stateClause cl)
526 llassert (cl->state == TK_BOTH || cl->state == TK_AFTER);
538 return FLG_MUSTFREEONLY;
542 return stateClause_qualErrorCode (cl);
545 BADBRANCHRET (INVALID_FLAG);
548 cstring stateClause_postErrorString (stateClause cl, sRef sr)
550 llassert (cl->state == TK_BOTH || cl->state == TK_AFTER);
556 return cstring_makeLiteralTemp ("<ERROR>");
558 return cstring_makeLiteralTemp ("Unallocated");
561 return cstring_makeLiteralTemp ("Undefined");
563 return cstring_makeLiteralTemp ("Unreleased");
567 return stateClause_qualErrorString (cl, sr);
573 cstring stateClause_dump (stateClause s)
575 return (message ("%d.%d.%q.%q",
578 qual_dump (s->squal),
579 sRefSet_dump (s->refs)));
582 stateClause stateClause_undump (char **s)
584 stateClause ret = (stateClause) dmalloc (sizeof (*ret));
586 ret->loc = fileloc_undefined;
587 ret->state = (stateConstraint) reader_getInt (s);
588 reader_checkChar (s, '.');
589 ret->kind = (stateClauseKind) reader_getInt (s);
590 reader_checkChar (s, '.');
591 ret->squal = qual_undump (s);
592 reader_checkChar (s, '.');
593 ret->refs = sRefSet_undump (s);
598 stateClause stateClause_copy (stateClause s)
600 stateClause ret = (stateClause) dmalloc (sizeof (*ret));
602 ret->state = s->state;
604 ret->squal = s->squal;
605 ret->refs = sRefSet_newCopy (s->refs);
606 ret->loc = fileloc_copy (s->loc);
611 bool stateClause_sameKind (stateClause s1, stateClause s2)
613 return (s1->state == s2->state
614 && s1->kind == s2->kind
615 && qual_match (s1->squal, s2->squal));
618 void stateClause_free (stateClause s)
620 sRefSet_free (s->refs);
621 fileloc_free (s->loc);
625 static /*@observer@*/ cstring
626 stateClauseKind_unparse (stateClause s)
631 return cstring_makeLiteralTemp ("uses");
633 return cstring_makeLiteralTemp ("defines");
635 return cstring_makeLiteralTemp ("allocates");
637 return cstring_makeLiteralTemp ("releases");
639 return cstring_makeLiteralTemp ("sets");
641 return qual_unparse (s->squal);
643 return qual_unparse (s->squal);
649 cstring stateClause_unparseKind (stateClause s)
653 cstring_makeLiteralTemp (s->state == TK_BEFORE
655 : (s->state == TK_AFTER
657 stateClauseKind_unparse (s)));
660 cstring stateClause_unparse (stateClause s)
662 return (message ("%q %q",
663 stateClause_unparseKind (s), sRefSet_unparsePlain (s->refs)));
666 stateClause stateClause_createDefines (sRefSet s)
668 return (stateClause_createRaw (TK_BOTH, SP_DEFINES, s));
671 stateClause stateClause_createUses (sRefSet s)
673 return (stateClause_createRaw (TK_BOTH, SP_USES, s));
676 stateClause stateClause_createSets (sRefSet s)
678 return (stateClause_createRaw (TK_BOTH, SP_SETS, s));
681 stateClause stateClause_createReleases (sRefSet s)
683 return (stateClause_createRaw (TK_BOTH, SP_RELEASES, s));
686 stateClause stateClause_createPlain (lltok tok, sRefSet s)
688 switch (lltok_getTok (tok))
691 return stateClause_createUses (s);
693 return stateClause_createDefines (s);
695 return stateClause_createAllocates (s);
697 return stateClause_createSets (s);
699 return stateClause_createReleases (s);
705 BADBRANCHRET (stateClause_createUses (sRefSet_undefined));
708 stateClause stateClause_createAllocates (sRefSet s)
710 return (stateClause_createRaw (TK_BOTH, SP_ALLOCATES, s));
713 bool stateClause_matchKind (stateClause s1, stateClause s2)
715 return (s1->state == s2->state && s1->kind == s2->kind
716 && qual_match (s1->squal, s2->squal));
719 bool stateClause_hasEnsures (stateClause cl)
721 return (cl->state == TK_AFTER && (cl->kind == SP_QUAL || cl->kind == SP_GLOBAL));
724 bool stateClause_hasRequires (stateClause cl)
726 return (cl->state == TK_BEFORE && (cl->kind == SP_QUAL || cl->kind == SP_GLOBAL));
729 bool stateClause_setsMetaState (stateClause cl)
731 return ((cl->kind == SP_QUAL || cl->kind == SP_GLOBAL)
732 && qual_isMetaState (cl->squal));
735 qual stateClause_getMetaQual (stateClause cl)
737 llassert (cl->kind == SP_QUAL || cl->kind == SP_GLOBAL);
741 static sRefModVal stateClause_getStateFunction (stateClause cl)
745 llassert (cl->kind == SP_QUAL || cl->kind == SP_GLOBAL);
751 if (qual_isNullStateQual (sq))
753 return (sRefModVal) sRef_setNullState;
755 else if (qual_isExQual (sq))
757 return (sRefModVal) sRef_setExKind;
759 else if (qual_isAliasQual (sq))
761 return (sRefModVal) sRef_setAliasKind; /*@i23 complete? @*/
765 DPRINTF (("Unhandled ensures qual: %s", qual_unparse (sq)));
772 int stateClause_getStateParameter (stateClause cl)
776 llassert (cl->kind == SP_QUAL || cl->kind == SP_GLOBAL);
780 /*@+relaxtypes@*/ /*@i523 this is wrong, remove the enumint@*/
783 if (qual_isNotNull (sq))
787 else if (qual_isIsNull (sq))
791 else if (qual_isNull (sq))
795 else if (qual_isRelNull (sq))
799 else if (qual_isExposed (sq))
803 else if (qual_isObserver (sq))
807 else if (qual_isAliasQual (sq))
809 if (qual_isOnly (sq)) return AK_ONLY;
810 if (qual_isImpOnly (sq)) return AK_IMPONLY;
811 if (qual_isTemp (sq)) return AK_TEMP;
812 if (qual_isOwned (sq)) return AK_OWNED;
813 if (qual_isShared (sq)) return AK_SHARED;
814 if (qual_isUnique (sq)) return AK_UNIQUE;
815 if (qual_isDependent (sq)) return AK_DEPENDENT;
816 if (qual_isKeep (sq)) return AK_KEEP;
817 if (qual_isKept (sq)) return AK_KEPT;
822 DPRINTF (("Unhandled ensures qual: %s", qual_unparse (sq)));
831 sRefModVal stateClause_getEnsuresFunction (stateClause cl)
833 llassertprint (cl->state == TK_AFTER, ("Not after: %s", stateClause_unparse (cl)));
834 llassert (cl->kind == SP_QUAL || cl->kind == SP_GLOBAL);
835 return stateClause_getStateFunction (cl);
838 sRefModVal stateClause_getRequiresBodyFunction (stateClause cl)
840 llassertprint (cl->state == TK_BEFORE, ("Not before: %s", stateClause_unparse (cl)));
841 llassert (cl->kind == SP_QUAL || cl->kind == SP_GLOBAL);
842 return stateClause_getStateFunction (cl);
845 /*@observer@*/ fileloc stateClause_loc (stateClause s)