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"
33 stateClause_createRaw (stateConstraint st
, stateClauseKind sk
, /*@only@*/ sRefSet s
)
35 stateClause ret
= (stateClause
) dmalloc (sizeof (*ret
));
39 ret
->squal
= qual_createUnknown ();
41 ret
->loc
= fileloc_undefined
;
45 /*drl added 3/7/2003*/
46 bool stateClause_hasEmptyReferences (stateClause s
)
48 if (sRefSet_isUndefined(s
->refs
) )
54 bool stateClause_isMetaState (stateClause s
)
57 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
);
115 bool stateClause_isEnsures (stateClause cl
)
117 return (cl
->state
== TK_AFTER
);
119 # endif /* DEADCODE */
121 bool stateClause_isQual (stateClause cl
)
123 return (cl
->kind
== SP_QUAL
);
126 bool stateClause_isMemoryAllocation (stateClause cl
)
140 return (qual_isMemoryAllocation (cl
->squal
)
141 || qual_isSharing (cl
->squal
));
148 ** An error is reported if the test is NOT true.
151 sRefTest
stateClause_getPreTestFunction (stateClause cl
)
156 return sRef_isStrictReadable
;
158 return sRef_hasNoStorage
;
160 return sRef_hasNoStorage
;
162 return sRef_isNotUndefined
;
164 return sRef_isNotUndefined
;
169 if (qual_isOnly (cl
->squal
)) {
171 } else if (qual_isShared (cl
->squal
)) {
172 return sRef_isShared
;
173 } else if (qual_isDependent (cl
->squal
)) {
174 return sRef_isDependent
;
175 } else if (qual_isOwned (cl
->squal
)) {
177 } else if (qual_isObserver (cl
->squal
)) {
178 return sRef_isObserver
;
179 } else if (qual_isExposed (cl
->squal
)) {
180 return sRef_isExposed
;
181 } else if (qual_isNotNull (cl
->squal
)) {
182 return sRef_isNotNull
;
183 } else if (qual_isIsNull (cl
->squal
)) {
184 return sRef_isDefinitelyNull
;
194 sRefTest
stateClause_getPostTestFunction (stateClause cl
)
196 llassert (stateClause_isAfter (cl
));
203 return sRef_isAllocated
;
205 return sRef_isReallyDefined
;
207 return sRef_isReallyDefined
;
209 return sRef_isDeadStorage
;
213 if (qual_isOnly (cl
->squal
)) {
215 } else if (qual_isShared (cl
->squal
)) {
216 return sRef_isShared
;
217 } else if (qual_isDependent (cl
->squal
)) {
218 return sRef_isDependent
;
219 } else if (qual_isOwned (cl
->squal
)) {
221 } else if (qual_isObserver (cl
->squal
)) {
222 return sRef_isObserver
;
223 } else if (qual_isExposed (cl
->squal
)) {
224 return sRef_isExposed
;
225 } else if (qual_isNotNull (cl
->squal
)) {
226 return sRef_isNotNull
;
227 } else if (qual_isIsNull (cl
->squal
)) {
228 return sRef_isDefinitelyNull
;
237 sRefShower
stateClause_getPostTestShower (stateClause cl
)
246 return sRef_showNotReallyDefined
;
252 if (qual_isMemoryAllocation (cl
->squal
)) {
253 return sRef_showAliasInfo
;
254 } else if (qual_isSharing (cl
->squal
)) {
255 return sRef_showExpInfo
;
256 } else if (qual_isIsNull (cl
->squal
) || qual_isNotNull (cl
->squal
)) {
257 return sRef_showNullInfo
;
266 sRefMod
stateClause_getEntryFunction (stateClause cl
)
268 if (cl
->state
== TK_BEFORE
|| cl
->state
== TK_BOTH
)
273 return sRef_setDefinedComplete
;
275 return sRef_setUndefined
; /* evans 2002-01-01 */
277 return sRef_setUndefined
; /* evans 2002-01-01 */
279 return sRef_setAllocatedComplete
;
281 return sRef_setDefinedComplete
;
285 if (qual_isOnly (cl
->squal
)) {
287 } else if (qual_isShared (cl
->squal
)) {
288 return sRef_setShared
;
289 } else if (qual_isDependent (cl
->squal
)) {
290 return sRef_setDependent
;
291 } else if (qual_isOwned (cl
->squal
)) {
292 return sRef_setOwned
;
293 } else if (qual_isObserver (cl
->squal
)) {
294 return sRef_setObserver
;
295 } else if (qual_isExposed (cl
->squal
)) {
296 return sRef_setExposed
;
297 } else if (qual_isNotNull (cl
->squal
)) {
298 return sRef_setNotNull
;
299 } else if (qual_isIsNull (cl
->squal
)) {
300 return sRef_setDefNull
;
302 DPRINTF (("Here we are: %s",
303 qual_unparse (cl
->squal
)));
318 sRefMod
stateClause_getEffectFunction (stateClause cl
)
320 if (cl
->state
== TK_AFTER
|| cl
->state
== TK_BOTH
)
327 return sRef_setAllocatedComplete
;
329 return sRef_setDefinedNCComplete
;
331 return sRef_setDefinedNCComplete
;
333 return sRef_killComplete
;
337 if (qual_isOnly (cl
->squal
)) {
339 } else if (qual_isShared (cl
->squal
)) {
340 return sRef_setShared
;
341 } else if (qual_isDependent (cl
->squal
)) {
342 return sRef_setDependent
;
343 } else if (qual_isOwned (cl
->squal
)) {
344 return sRef_setOwned
;
345 } else if (qual_isObserver (cl
->squal
)) {
346 return sRef_setObserver
;
347 } else if (qual_isExposed (cl
->squal
)) {
348 return sRef_setExposed
;
349 } else if (qual_isNotNull (cl
->squal
)) {
350 return sRef_setNotNull
;
351 } else if (qual_isIsNull (cl
->squal
)) {
352 return sRef_setDefNull
;
368 sRefMod
stateClause_getReturnEffectFunction (stateClause cl
)
370 if (cl
->state
== TK_AFTER
|| cl
->state
== TK_BOTH
)
383 if (qual_isOnly (cl
->squal
)) {
384 return sRef_killComplete
;
400 static flagcode
stateClause_qualErrorCode (stateClause cl
)
402 if (qual_isOnly (cl
->squal
)) {
403 return FLG_ONLYTRANS
;
404 } else if (qual_isShared (cl
->squal
)) {
405 return FLG_SHAREDTRANS
;
406 } else if (qual_isDependent (cl
->squal
)) {
407 return FLG_DEPENDENTTRANS
;
408 } else if (qual_isOwned (cl
->squal
)) {
409 return FLG_OWNEDTRANS
;
410 } else if (qual_isObserver (cl
->squal
)) {
411 return FLG_OBSERVERTRANS
;
412 } else if (qual_isExposed (cl
->squal
)) {
413 return FLG_EXPOSETRANS
;
414 } else if (qual_isIsNull (cl
->squal
)
415 || qual_isNotNull (cl
->squal
)) {
416 return FLG_NULLSTATE
;
421 BADBRANCHRET (INVALID_FLAG
);
424 flagcode
stateClause_preErrorCode (stateClause cl
)
426 llassert (cl
->state
== TK_BOTH
|| cl
->state
== TK_BEFORE
);
432 case SP_ALLOCATES
: /*@fallthrough@*/
435 return FLG_MUSTFREEONLY
;
440 return stateClause_qualErrorCode (cl
);
443 BADBRANCHRET (INVALID_FLAG
);
446 static /*@observer@*/ cstring
stateClause_qualErrorString (stateClause cl
, sRef sr
)
448 if (qual_isMemoryAllocation (cl
->squal
)) {
449 return alkind_capName (sRef_getAliasKind (sr
));
450 } else if (qual_isObserver (cl
->squal
)) {
451 return cstring_makeLiteralTemp ("Non-observer");
452 } else if (qual_isExposed (cl
->squal
)) {
453 if (sRef_isObserver (sr
))
455 return cstring_makeLiteralTemp ("Observer");
459 return cstring_makeLiteralTemp ("Non-exposed");
461 } else if (qual_isNotNull (cl
->squal
)) {
462 if (sRef_isDefinitelyNull (sr
))
464 return cstring_makeLiteralTemp ("Null");
468 return cstring_makeLiteralTemp ("Possibly null");
470 } else if (qual_isIsNull (cl
->squal
)) {
471 return cstring_makeLiteralTemp ("Non-null");
476 BADBRANCHRET (cstring_undefined
);
479 cstring
stateClause_preErrorString (stateClause cl
, sRef sr
)
481 llassert (cl
->state
== TK_BOTH
|| cl
->state
== TK_BEFORE
);
486 if (sRef_isDead (sr
))
487 return cstring_makeLiteralTemp ("Dead");
489 return cstring_makeLiteralTemp ("Undefined");
490 case SP_ALLOCATES
: /*@fallthrough@*/
493 return cstring_makeLiteralTemp ("Allocated");
495 if (sRef_isDead (sr
))
497 return cstring_makeLiteralTemp ("Dead");
499 else if (sRef_isDependent (sr
)
500 || sRef_isShared (sr
))
502 return alkind_unparse (sRef_getAliasKind (sr
));
504 else if (sRef_isObserver (sr
) || sRef_isExposed (sr
))
506 return exkind_unparse (sRef_getExKind (sr
));
510 return cstring_makeLiteralTemp ("Undefined");
515 return stateClause_qualErrorString (cl
, sr
);
521 flagcode
stateClause_postErrorCode (stateClause cl
)
523 llassert (cl
->state
== TK_BOTH
|| cl
->state
== TK_AFTER
);
535 return FLG_MUSTFREEONLY
;
539 return stateClause_qualErrorCode (cl
);
542 BADBRANCHRET (INVALID_FLAG
);
545 cstring
stateClause_postErrorString (stateClause cl
, sRef sr
)
547 llassert (cl
->state
== TK_BOTH
|| cl
->state
== TK_AFTER
);
553 return cstring_makeLiteralTemp ("<ERROR>");
555 return cstring_makeLiteralTemp ("Unallocated");
558 return cstring_makeLiteralTemp ("Undefined");
560 return cstring_makeLiteralTemp ("Unreleased");
564 return stateClause_qualErrorString (cl
, sr
);
570 cstring
stateClause_dump (stateClause s
)
572 return (message ("%d.%d.%q.%q",
575 qual_dump (s
->squal
),
576 sRefSet_dump (s
->refs
)));
579 stateClause
stateClause_undump (char **s
)
581 stateClause ret
= (stateClause
) dmalloc (sizeof (*ret
));
583 ret
->loc
= fileloc_undefined
;
584 ret
->state
= (stateConstraint
) reader_getInt (s
);
585 reader_checkChar (s
, '.');
586 ret
->kind
= (stateClauseKind
) reader_getInt (s
);
587 reader_checkChar (s
, '.');
588 ret
->squal
= qual_undump (s
);
589 reader_checkChar (s
, '.');
590 ret
->refs
= sRefSet_undump (s
);
595 stateClause
stateClause_copy (stateClause s
)
597 stateClause ret
= (stateClause
) dmalloc (sizeof (*ret
));
599 ret
->state
= s
->state
;
601 ret
->squal
= s
->squal
;
602 ret
->refs
= sRefSet_newCopy (s
->refs
);
603 ret
->loc
= fileloc_copy (s
->loc
);
608 bool stateClause_sameKind (stateClause s1
, stateClause s2
)
610 return (s1
->state
== s2
->state
611 && s1
->kind
== s2
->kind
612 && qual_match (s1
->squal
, s2
->squal
));
615 void stateClause_free (stateClause s
)
617 sRefSet_free (s
->refs
);
618 fileloc_free (s
->loc
);
622 static /*@observer@*/ cstring
623 stateClauseKind_unparse (stateClause s
)
628 return cstring_makeLiteralTemp ("uses");
630 return cstring_makeLiteralTemp ("defines");
632 return cstring_makeLiteralTemp ("allocates");
634 return cstring_makeLiteralTemp ("releases");
636 return cstring_makeLiteralTemp ("sets");
638 return qual_unparse (s
->squal
);
640 return qual_unparse (s
->squal
);
646 cstring
stateClause_unparseKind (stateClause s
)
650 cstring_makeLiteralTemp (s
->state
== TK_BEFORE
652 : (s
->state
== TK_AFTER
654 stateClauseKind_unparse (s
)));
657 cstring
stateClause_unparse (stateClause s
)
659 return (message ("%q %q",
660 stateClause_unparseKind (s
), sRefSet_unparsePlain (s
->refs
)));
663 static stateClause
stateClause_createDefines (/*@only@*/ sRefSet s
)
665 return (stateClause_createRaw (TK_BOTH
, SP_DEFINES
, s
));
668 static stateClause
stateClause_createUses (/*@only@*/ sRefSet s
)
670 return (stateClause_createRaw (TK_BOTH
, SP_USES
, s
));
673 static stateClause
stateClause_createSets (/*@only@*/ sRefSet s
)
675 return (stateClause_createRaw (TK_BOTH
, SP_SETS
, s
));
678 static stateClause
stateClause_createAllocates (/*@only@*/ sRefSet s
)
680 return (stateClause_createRaw (TK_BOTH
, SP_ALLOCATES
, s
));
683 static stateClause
stateClause_createReleases (/*@only@*/ sRefSet s
)
685 return (stateClause_createRaw (TK_BOTH
, SP_RELEASES
, s
));
688 stateClause
stateClause_createPlain (lltok tok
, sRefSet s
)
690 switch (lltok_getTok (tok
))
693 return stateClause_createUses (s
);
695 return stateClause_createDefines (s
);
697 return stateClause_createAllocates (s
);
699 return stateClause_createSets (s
);
701 return stateClause_createReleases (s
);
707 BADBRANCHRET (stateClause_createUses (sRefSet_undefined
));
710 bool stateClause_matchKind (stateClause s1
, stateClause s2
)
712 return (s1
->state
== s2
->state
&& s1
->kind
== s2
->kind
713 && qual_match (s1
->squal
, s2
->squal
));
716 bool stateClause_hasEnsures (stateClause cl
)
718 return (cl
->state
== TK_AFTER
&& (cl
->kind
== SP_QUAL
|| cl
->kind
== SP_GLOBAL
));
721 bool stateClause_hasRequires (stateClause cl
)
723 return (cl
->state
== TK_BEFORE
&& (cl
->kind
== SP_QUAL
|| cl
->kind
== SP_GLOBAL
));
726 bool stateClause_setsMetaState (stateClause cl
)
728 return ((cl
->kind
== SP_QUAL
|| cl
->kind
== SP_GLOBAL
)
729 && qual_isMetaState (cl
->squal
));
732 qual
stateClause_getMetaQual (stateClause cl
)
734 llassert (cl
->kind
== SP_QUAL
|| cl
->kind
== SP_GLOBAL
);
738 static sRefModVal
stateClause_getStateFunction (stateClause cl
)
742 llassert (cl
->kind
== SP_QUAL
|| cl
->kind
== SP_GLOBAL
);
748 if (qual_isNullStateQual (sq
))
750 return (sRefModVal
) sRef_setNullState
;
752 else if (qual_isExQual (sq
))
754 return (sRefModVal
) sRef_setExKind
;
756 else if (qual_isAliasQual (sq
))
758 return (sRefModVal
) sRef_setAliasKind
;
762 DPRINTF (("Unhandled ensures qual: %s", qual_unparse (sq
)));
769 int stateClause_getStateParameter (stateClause cl
)
773 llassert (cl
->kind
== SP_QUAL
|| cl
->kind
== SP_GLOBAL
);
779 ** Since this can be many different types of state kinds, we need to allow all
780 ** enum's to be returned as int.
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
)