2 ** Splint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2002 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: splint@cs.virginia.edu
21 ** To report a bug: splint-bug@cs.virginia.edu
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;
47 stateClause_create (lltok tok, qual q, sRefSet s)
49 stateClause ret = (stateClause) dmalloc (sizeof (*ret));
51 if (lltok_getTok (tok) == QPRECLAUSE)
53 ret->state = TK_BEFORE;
55 else if (lltok_getTok (tok) == QPOSTCLAUSE)
57 ret->state = TK_AFTER;
64 ret->loc = fileloc_copy (lltok_getLoc (tok));
69 if (sRefSet_isDefined (s))
75 ret->kind = SP_GLOBAL;
81 bool stateClause_isBeforeOnly (stateClause cl)
83 return (cl->state == TK_BEFORE);
86 bool stateClause_isBefore (stateClause cl)
88 return (cl->state == TK_BEFORE || cl->state == TK_BOTH);
91 bool stateClause_isAfter (stateClause cl)
93 return (cl->state == TK_AFTER || cl->state == TK_BOTH);
96 bool stateClause_isEnsures (stateClause cl)
98 return (cl->state == TK_AFTER);
101 bool stateClause_isQual (stateClause cl)
103 return (cl->kind == SP_QUAL);
106 bool stateClause_isMemoryAllocation (stateClause cl)
120 return (qual_isMemoryAllocation (cl->squal)
121 || qual_isSharing (cl->squal));
128 ** An error is reported if the test is NOT true.
131 sRefTest stateClause_getPreTestFunction (stateClause cl)
136 return sRef_isStrictReadable;
138 return sRef_hasNoStorage;
140 return sRef_hasNoStorage;
142 return sRef_isNotUndefined;
144 return sRef_isNotUndefined;
149 if (qual_isOnly (cl->squal)) {
151 } else if (qual_isShared (cl->squal)) {
152 return sRef_isShared;
153 } else if (qual_isDependent (cl->squal)) {
154 return sRef_isDependent;
155 } else if (qual_isOwned (cl->squal)) {
157 } else if (qual_isObserver (cl->squal)) {
158 return sRef_isObserver;
159 } else if (qual_isExposed (cl->squal)) {
160 return sRef_isExposed;
161 } else if (qual_isNotNull (cl->squal)) {
162 return sRef_isNotNull;
163 } else if (qual_isIsNull (cl->squal)) {
164 return sRef_isDefinitelyNull;
174 sRefTest stateClause_getPostTestFunction (stateClause cl)
176 llassert (stateClause_isAfter (cl));
183 return sRef_isAllocated;
185 return sRef_isReallyDefined;
187 return sRef_isReallyDefined;
189 return sRef_isDeadStorage;
193 if (qual_isOnly (cl->squal)) {
195 } else if (qual_isShared (cl->squal)) {
196 return sRef_isShared;
197 } else if (qual_isDependent (cl->squal)) {
198 return sRef_isDependent;
199 } else if (qual_isOwned (cl->squal)) {
201 } else if (qual_isObserver (cl->squal)) {
202 return sRef_isObserver;
203 } else if (qual_isExposed (cl->squal)) {
204 return sRef_isExposed;
205 } else if (qual_isNotNull (cl->squal)) {
206 return sRef_isNotNull;
207 } else if (qual_isIsNull (cl->squal)) {
208 return sRef_isDefinitelyNull;
217 sRefShower stateClause_getPostTestShower (stateClause cl)
226 return sRef_showNotReallyDefined;
232 if (qual_isMemoryAllocation (cl->squal)) {
233 return sRef_showAliasInfo;
234 } else if (qual_isSharing (cl->squal)) {
235 return sRef_showExpInfo;
236 } else if (qual_isIsNull (cl->squal) || qual_isNotNull (cl->squal)) {
237 return sRef_showNullInfo;
246 sRefMod stateClause_getEntryFunction (stateClause cl)
248 if (cl->state == TK_BEFORE || cl->state == TK_BOTH)
253 return sRef_setDefinedComplete;
255 return sRef_setUndefined; /* evans 2002-01-01 */
257 return sRef_setUndefined; /* evans 2002-01-01 */
259 return sRef_setAllocatedComplete;
261 return sRef_setDefinedComplete;
265 if (qual_isOnly (cl->squal)) {
267 } else if (qual_isShared (cl->squal)) {
268 return sRef_setShared;
269 } else if (qual_isDependent (cl->squal)) {
270 return sRef_setDependent;
271 } else if (qual_isOwned (cl->squal)) {
272 return sRef_setOwned;
273 } else if (qual_isObserver (cl->squal)) {
274 return sRef_setObserver;
275 } else if (qual_isExposed (cl->squal)) {
276 return sRef_setExposed;
277 } else if (qual_isNotNull (cl->squal)) {
278 return sRef_setNotNull;
279 } else if (qual_isIsNull (cl->squal)) {
280 return sRef_setDefNull;
282 DPRINTF (("Here we are: %s",
283 qual_unparse (cl->squal)));
298 sRefMod stateClause_getEffectFunction (stateClause cl)
300 if (cl->state == TK_AFTER || cl->state == TK_BOTH)
307 return sRef_setAllocatedComplete;
309 return sRef_setDefinedNCComplete;
311 return sRef_setDefinedNCComplete;
313 return sRef_killComplete;
317 if (qual_isOnly (cl->squal)) {
319 } else if (qual_isShared (cl->squal)) {
320 return sRef_setShared;
321 } else if (qual_isDependent (cl->squal)) {
322 return sRef_setDependent;
323 } else if (qual_isOwned (cl->squal)) {
324 return sRef_setOwned;
325 } else if (qual_isObserver (cl->squal)) {
326 return sRef_setObserver;
327 } else if (qual_isExposed (cl->squal)) {
328 return sRef_setExposed;
329 } else if (qual_isNotNull (cl->squal)) {
330 return sRef_setNotNull;
331 } else if (qual_isIsNull (cl->squal)) {
332 return sRef_setDefNull;
348 sRefMod stateClause_getReturnEffectFunction (stateClause cl)
350 if (cl->state == TK_AFTER || cl->state == TK_BOTH)
363 if (qual_isOnly (cl->squal)) {
364 return sRef_killComplete;
380 static flagcode stateClause_qualErrorCode (stateClause cl)
382 if (qual_isOnly (cl->squal)) {
383 return FLG_ONLYTRANS;
384 } else if (qual_isShared (cl->squal)) {
385 return FLG_SHAREDTRANS;
386 } else if (qual_isDependent (cl->squal)) {
387 return FLG_DEPENDENTTRANS;
388 } else if (qual_isOwned (cl->squal)) {
389 return FLG_OWNEDTRANS;
390 } else if (qual_isObserver (cl->squal)) {
391 return FLG_OBSERVERTRANS;
392 } else if (qual_isExposed (cl->squal)) {
393 return FLG_EXPOSETRANS;
394 } else if (qual_isIsNull (cl->squal)
395 || qual_isNotNull (cl->squal)) {
396 return FLG_NULLSTATE;
401 BADBRANCHRET (INVALID_FLAG);
404 flagcode stateClause_preErrorCode (stateClause cl)
406 llassert (cl->state == TK_BOTH || cl->state == TK_BEFORE);
412 case SP_ALLOCATES: /*@fallthrough@*/
415 return FLG_MUSTFREEONLY;
420 return stateClause_qualErrorCode (cl);
423 BADBRANCHRET (INVALID_FLAG);
426 static /*@observer@*/ cstring stateClause_qualErrorString (stateClause cl, sRef sr)
428 if (qual_isMemoryAllocation (cl->squal)) {
429 return alkind_capName (sRef_getAliasKind (sr));
430 } else if (qual_isObserver (cl->squal)) {
431 return cstring_makeLiteralTemp ("Non-observer");
432 } else if (qual_isExposed (cl->squal)) {
433 if (sRef_isObserver (sr))
435 return cstring_makeLiteralTemp ("Observer");
439 return cstring_makeLiteralTemp ("Non-exposed");
441 } else if (qual_isNotNull (cl->squal)) {
442 if (sRef_isDefinitelyNull (sr))
444 return cstring_makeLiteralTemp ("Null");
448 return cstring_makeLiteralTemp ("Possibly null");
450 } else if (qual_isIsNull (cl->squal)) {
451 return cstring_makeLiteralTemp ("Non-null");
456 BADBRANCHRET (cstring_undefined);
459 cstring stateClause_preErrorString (stateClause cl, sRef sr)
461 llassert (cl->state == TK_BOTH || cl->state == TK_BEFORE);
466 if (sRef_isDead (sr))
467 return cstring_makeLiteralTemp ("Dead");
469 return cstring_makeLiteralTemp ("Undefined");
470 case SP_ALLOCATES: /*@fallthrough@*/
473 return cstring_makeLiteralTemp ("Allocated");
475 if (sRef_isDead (sr))
477 return cstring_makeLiteralTemp ("Dead");
479 else if (sRef_isDependent (sr)
480 || sRef_isShared (sr))
482 return alkind_unparse (sRef_getAliasKind (sr));
484 else if (sRef_isObserver (sr) || sRef_isExposed (sr))
486 return exkind_unparse (sRef_getExKind (sr));
490 return cstring_makeLiteralTemp ("Undefined");
495 return stateClause_qualErrorString (cl, sr);
501 flagcode stateClause_postErrorCode (stateClause cl)
503 llassert (cl->state == TK_BOTH || cl->state == TK_AFTER);
515 return FLG_MUSTFREEONLY;
519 return stateClause_qualErrorCode (cl);
522 BADBRANCHRET (INVALID_FLAG);
525 cstring stateClause_postErrorString (stateClause cl, sRef sr)
527 llassert (cl->state == TK_BOTH || cl->state == TK_AFTER);
533 return cstring_makeLiteralTemp ("<ERROR>");
535 return cstring_makeLiteralTemp ("Unallocated");
538 return cstring_makeLiteralTemp ("Undefined");
540 return cstring_makeLiteralTemp ("Unreleased");
544 return stateClause_qualErrorString (cl, sr);
550 cstring stateClause_dump (stateClause s)
552 return (message ("%d.%d.%q.%q",
555 qual_dump (s->squal),
556 sRefSet_dump (s->refs)));
559 stateClause stateClause_undump (char **s)
561 stateClause ret = (stateClause) dmalloc (sizeof (*ret));
563 ret->loc = fileloc_undefined;
564 ret->state = (stateConstraint) reader_getInt (s);
565 reader_checkChar (s, '.');
566 ret->kind = (stateClauseKind) reader_getInt (s);
567 reader_checkChar (s, '.');
568 ret->squal = qual_undump (s);
569 reader_checkChar (s, '.');
570 ret->refs = sRefSet_undump (s);
575 stateClause stateClause_copy (stateClause s)
577 stateClause ret = (stateClause) dmalloc (sizeof (*ret));
579 ret->state = s->state;
581 ret->squal = s->squal;
582 ret->refs = sRefSet_newCopy (s->refs);
583 ret->loc = fileloc_copy (s->loc);
588 bool stateClause_sameKind (stateClause s1, stateClause s2)
590 return (s1->state == s2->state
591 && s1->kind == s2->kind
592 && qual_match (s1->squal, s2->squal));
595 void stateClause_free (stateClause s)
597 sRefSet_free (s->refs);
598 fileloc_free (s->loc);
602 static /*@observer@*/ cstring
603 stateClauseKind_unparse (stateClause s)
608 return cstring_makeLiteralTemp ("uses");
610 return cstring_makeLiteralTemp ("defines");
612 return cstring_makeLiteralTemp ("allocates");
614 return cstring_makeLiteralTemp ("releases");
616 return cstring_makeLiteralTemp ("sets");
618 return qual_unparse (s->squal);
620 return qual_unparse (s->squal);
626 cstring stateClause_unparseKind (stateClause s)
630 cstring_makeLiteralTemp (s->state == TK_BEFORE
632 : (s->state == TK_AFTER
634 stateClauseKind_unparse (s)));
637 cstring stateClause_unparse (stateClause s)
639 return (message ("%q %q",
640 stateClause_unparseKind (s), sRefSet_unparsePlain (s->refs)));
643 stateClause stateClause_createDefines (sRefSet s)
645 return (stateClause_createRaw (TK_BOTH, SP_DEFINES, s));
648 stateClause stateClause_createUses (sRefSet s)
650 return (stateClause_createRaw (TK_BOTH, SP_USES, s));
653 stateClause stateClause_createSets (sRefSet s)
655 return (stateClause_createRaw (TK_BOTH, SP_SETS, s));
658 stateClause stateClause_createReleases (sRefSet s)
660 return (stateClause_createRaw (TK_BOTH, SP_RELEASES, s));
663 stateClause stateClause_createPlain (lltok tok, sRefSet s)
665 switch (lltok_getTok (tok))
668 return stateClause_createUses (s);
670 return stateClause_createDefines (s);
672 return stateClause_createAllocates (s);
674 return stateClause_createSets (s);
676 return stateClause_createReleases (s);
682 BADBRANCHRET (stateClause_createUses (sRefSet_undefined));
685 stateClause stateClause_createAllocates (sRefSet s)
687 return (stateClause_createRaw (TK_BOTH, SP_ALLOCATES, s));
690 bool stateClause_matchKind (stateClause s1, stateClause s2)
692 return (s1->state == s2->state && s1->kind == s2->kind
693 && qual_match (s1->squal, s2->squal));
696 bool stateClause_hasEnsures (stateClause cl)
698 return (cl->state == TK_AFTER && (cl->kind == SP_QUAL || cl->kind == SP_GLOBAL));
701 bool stateClause_hasRequires (stateClause cl)
703 return (cl->state == TK_BEFORE && (cl->kind == SP_QUAL || cl->kind == SP_GLOBAL));
706 bool stateClause_setsMetaState (stateClause cl)
708 return ((cl->kind == SP_QUAL || cl->kind == SP_GLOBAL)
709 && qual_isMetaState (cl->squal));
712 qual stateClause_getMetaQual (stateClause cl)
714 llassert (cl->kind == SP_QUAL || cl->kind == SP_GLOBAL);
718 static sRefModVal stateClause_getStateFunction (stateClause cl)
722 llassert (cl->kind == SP_QUAL || cl->kind == SP_GLOBAL);
728 if (qual_isNullStateQual (sq))
730 return (sRefModVal) sRef_setNullState;
732 else if (qual_isExQual (sq))
734 return (sRefModVal) sRef_setExKind;
736 else if (qual_isAliasQual (sq))
738 return (sRefModVal) sRef_setAliasKind; /*@i23 complete? @*/
742 DPRINTF (("Unhandled ensures qual: %s", qual_unparse (sq)));
749 int stateClause_getStateParameter (stateClause cl)
753 llassert (cl->kind == SP_QUAL || cl->kind == SP_GLOBAL);
757 /*@+relaxtypes@*/ /*@i523 this is wrong, remove the enumint@*/
760 if (qual_isNotNull (sq))
764 else if (qual_isIsNull (sq))
768 else if (qual_isNull (sq))
772 else if (qual_isRelNull (sq))
776 else if (qual_isExposed (sq))
780 else if (qual_isObserver (sq))
784 else if (qual_isAliasQual (sq))
786 if (qual_isOnly (sq)) return AK_ONLY;
787 if (qual_isImpOnly (sq)) return AK_IMPONLY;
788 if (qual_isTemp (sq)) return AK_TEMP;
789 if (qual_isOwned (sq)) return AK_OWNED;
790 if (qual_isShared (sq)) return AK_SHARED;
791 if (qual_isUnique (sq)) return AK_UNIQUE;
792 if (qual_isDependent (sq)) return AK_DEPENDENT;
793 if (qual_isKeep (sq)) return AK_KEEP;
794 if (qual_isKept (sq)) return AK_KEPT;
799 DPRINTF (("Unhandled ensures qual: %s", qual_unparse (sq)));
808 sRefModVal stateClause_getEnsuresFunction (stateClause cl)
810 llassertprint (cl->state == TK_AFTER, ("Not after: %s", stateClause_unparse (cl)));
811 llassert (cl->kind == SP_QUAL || cl->kind == SP_GLOBAL);
812 return stateClause_getStateFunction (cl);
815 sRefModVal stateClause_getRequiresBodyFunction (stateClause cl)
817 llassertprint (cl->state == TK_BEFORE, ("Not before: %s", stateClause_unparse (cl)));
818 llassert (cl->kind == SP_QUAL || cl->kind == SP_GLOBAL);
819 return stateClause_getStateFunction (cl);
822 /*@observer@*/ fileloc stateClause_loc (stateClause s)