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
);
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... */
151 # pragma warning( disable : 4550 )
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
;
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
);
782 ** Since this can be many different types of state kinds, we need to allow all
783 ** enum's to be returned as int.
786 if (qual_isNotNull (sq
))
790 else if (qual_isIsNull (sq
))
794 else if (qual_isNull (sq
))
798 else if (qual_isRelNull (sq
))
802 else if (qual_isExposed (sq
))
806 else if (qual_isObserver (sq
))
810 else if (qual_isAliasQual (sq
))
812 if (qual_isOnly (sq
)) return AK_ONLY
;
813 if (qual_isImpOnly (sq
)) return AK_IMPONLY
;
814 if (qual_isTemp (sq
)) return AK_TEMP
;
815 if (qual_isOwned (sq
)) return AK_OWNED
;
816 if (qual_isShared (sq
)) return AK_SHARED
;
817 if (qual_isUnique (sq
)) return AK_UNIQUE
;
818 if (qual_isDependent (sq
)) return AK_DEPENDENT
;
819 if (qual_isKeep (sq
)) return AK_KEEP
;
820 if (qual_isKept (sq
)) return AK_KEPT
;
825 DPRINTF (("Unhandled ensures qual: %s", qual_unparse (sq
)));
834 sRefModVal
stateClause_getEnsuresFunction (stateClause cl
)
836 llassertprint (cl
->state
== TK_AFTER
, ("Not after: %s", stateClause_unparse (cl
)));
837 llassert (cl
->kind
== SP_QUAL
|| cl
->kind
== SP_GLOBAL
);
838 return stateClause_getStateFunction (cl
);
841 sRefModVal
stateClause_getRequiresBodyFunction (stateClause cl
)
843 llassertprint (cl
->state
== TK_BEFORE
, ("Not before: %s", stateClause_unparse (cl
)));
844 llassert (cl
->kind
== SP_QUAL
|| cl
->kind
== SP_GLOBAL
);
845 return stateClause_getStateFunction (cl
);
848 /*@observer@*/ fileloc
stateClause_loc (stateClause s
)