2 ** Splint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2000 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 lclint: lclint-request@cs.virginia.edu
21 ** To report a bug: lclint-bug@cs.virginia.edu
22 ** For more information: http://www.splint.org
28 # include "lclintMacros.nf"
31 static bool specialClause_isMemoryAllocation (specialClause p_cl) /*@*/ ;
32 static void specialClause_free (/*@only@*/ specialClause p_s) ;
33 static cstring specialClause_dump (specialClause p_s) /*@*/ ;
34 static specialClause specialClause_undump (char **p_s) /*@modifies *p_s@*/ ;
35 static specialClause specialClause_copy (specialClause p_s) /*@*/ ;
36 static bool specialClause_sameKind (specialClause p_s1, specialClause p_s2) /*@*/ ;
39 specialClause_create (stateConstraint st, specialClauseKind k, sRefSet s)
41 specialClause ret = (specialClause) dmalloc (sizeof (*ret));
50 bool specialClause_isBefore (specialClause cl)
52 return (cl->state == TK_BEFORE || cl->state == TK_BOTH);
55 bool specialClause_isAfter (specialClause cl)
57 return (cl->state == TK_AFTER || cl->state == TK_BOTH);
60 bool specialClause_isMemoryAllocation (specialClause cl)
85 ** An error is reported if the test is NOT true.
88 sRefTest specialClause_getPreTestFunction (specialClause cl)
93 return sRef_isStrictReadable;
95 return sRef_hasNoStorage;
97 return sRef_hasNoStorage;
99 return sRef_isNotUndefined;
101 return sRef_isNotUndefined;
105 return sRef_isShared;
107 return sRef_isDependent;
111 return sRef_isObserver;
113 return sRef_isExposed;
115 return sRef_isNotNull;
117 return sRef_isDefinitelyNull;
123 sRefTest specialClause_getPostTestFunction (specialClause cl)
125 llassert (specialClause_isAfter (cl));
132 return sRef_isAllocated;
134 return sRef_isReallyDefined;
136 return sRef_isReallyDefined;
138 return sRef_isDeadStorage;
142 return sRef_isShared;
144 return sRef_isDependent;
148 return sRef_isObserver;
150 return sRef_isExposed;
152 return sRef_isNotNull;
154 return sRef_isDefinitelyNull;
160 sRefShower specialClause_getPostTestShower (specialClause cl)
169 return sRef_showNotReallyDefined;
176 return sRef_showAliasInfo;
179 return sRef_showExpInfo;
182 return sRef_showNullInfo;
188 sRefMod specialClause_getEntryFunction (specialClause cl)
190 if (cl->state == TK_BEFORE || cl->state == TK_BOTH)
195 return sRef_setDefinedComplete;
201 return sRef_setAllocatedComplete;
203 return sRef_setDefinedComplete;
207 return sRef_setShared;
209 return sRef_setDependent;
211 return sRef_setOwned;
213 return sRef_setObserver;
215 return sRef_setExposed;
217 return sRef_setNotNull;
219 return sRef_setDefNull;
230 sRefMod specialClause_getEffectFunction (specialClause cl)
232 if (cl->state == TK_AFTER || cl->state == TK_BOTH)
239 return sRef_setAllocatedComplete;
241 return sRef_setDefinedNCComplete;
243 return sRef_setDefinedNCComplete;
245 return sRef_killComplete;
249 return sRef_setShared;
251 return sRef_setDependent;
253 return sRef_setOwned;
255 return sRef_setObserver;
257 return sRef_setExposed;
259 return sRef_setNotNull;
261 return sRef_setDefNull;
272 sRefMod specialClause_getReturnEffectFunction (specialClause cl)
274 if (cl->state == TK_AFTER || cl->state == TK_BOTH)
285 return sRef_killComplete;
304 flagcode specialClause_preErrorCode (specialClause cl)
306 llassert (cl->state == TK_BOTH || cl->state == TK_BEFORE);
312 case SP_ALLOCATES: /*@fallthrough@*/
319 return FLG_ONLYTRANS;
321 return FLG_SHAREDTRANS;
323 return FLG_DEPENDENTTRANS;
325 return FLG_OWNEDTRANS;
327 return FLG_OBSERVERTRANS;
329 return FLG_EXPOSETRANS;
332 return FLG_NULLSTATE;
338 cstring specialClause_preErrorString (specialClause cl, sRef sr)
340 llassert (cl->state == TK_BOTH || cl->state == TK_BEFORE);
345 if (sRef_isDead (sr))
346 return cstring_makeLiteralTemp ("Dead");
348 return cstring_makeLiteralTemp ("Undefined");
349 case SP_ALLOCATES: /*@fallthrough@*/
352 return cstring_makeLiteralTemp ("Allocated");
354 if (sRef_isDead (sr))
356 return cstring_makeLiteralTemp ("Dead");
358 else if (sRef_isDependent (sr)
359 || sRef_isShared (sr))
361 return alkind_unparse (sRef_getAliasKind (sr));
363 else if (sRef_isObserver (sr) || sRef_isExposed (sr))
365 return exkind_unparse (sRef_getExKind (sr));
369 return cstring_makeLiteralTemp ("Undefined");
375 return alkind_capName (sRef_getAliasKind (sr));
377 return cstring_makeLiteralTemp ("Non-observer");
379 if (sRef_isObserver (sr))
381 return cstring_makeLiteralTemp ("Observer");
385 return cstring_makeLiteralTemp ("Non-exposed");
388 if (sRef_isDefinitelyNull (sr))
390 return cstring_makeLiteralTemp ("Null");
394 return cstring_makeLiteralTemp ("Possibly null");
397 return cstring_makeLiteralTemp ("Non-null");
403 flagcode specialClause_postErrorCode (specialClause cl)
405 llassert (cl->state == TK_BOTH || cl->state == TK_AFTER);
419 return FLG_ONLYTRANS;
421 return FLG_SHAREDTRANS;
423 return FLG_DEPENDENTTRANS;
425 return FLG_OWNEDTRANS;
427 return FLG_OBSERVERTRANS;
429 return FLG_EXPOSETRANS;
432 return FLG_NULLSTATE;
438 cstring specialClause_postErrorString (specialClause cl, sRef sr)
440 llassert (cl->state == TK_BOTH || cl->state == TK_AFTER);
446 return cstring_makeLiteralTemp ("<ERROR>");
448 return cstring_makeLiteralTemp ("Unallocated");
451 return cstring_makeLiteralTemp ("Undefined");
453 return cstring_makeLiteralTemp ("Unreleased");
458 return alkind_capName (sRef_getAliasKind (sr));
460 return cstring_makeLiteralTemp ("Non-observer");
462 if (sRef_isObserver (sr))
464 return cstring_makeLiteralTemp ("Observer");
468 return cstring_makeLiteralTemp ("Non-exposed");
471 return cstring_makeLiteralTemp ("Non-null");
473 if (sRef_isDefinitelyNull (sr))
475 return cstring_makeLiteralTemp ("Null");
479 return cstring_makeLiteralTemp ("Possibly null");
486 cstring specialClause_dump (specialClause s)
488 return (message ("%d.%d.%q",
491 sRefSet_dump (s->refs)));
494 specialClause specialClause_undump (char **s)
496 specialClause ret = (specialClause) dmalloc (sizeof (*ret));
498 ret->state = (stateConstraint) reader_getInt (s);
499 reader_checkChar (s, '.');
500 ret->kind = (specialClauseKind) reader_getInt (s);
501 reader_checkChar (s, '.');
502 ret->refs = sRefSet_undump (s);
507 specialClause specialClause_copy (specialClause s)
509 specialClause ret = (specialClause) dmalloc (sizeof (*ret));
511 ret->state = s->state;
513 ret->refs = sRefSet_newCopy (s->refs);
518 bool specialClause_sameKind (specialClause s1, specialClause s2)
520 return (s1->state == s2->state && s1->kind == s2->kind);
523 void specialClause_free (specialClause s)
525 sRefSet_free (s->refs);
529 static /*@observer@*/ cstring
530 specialClauseKind_unparse (specialClauseKind k)
535 return cstring_makeLiteralTemp ("uses");
537 return cstring_makeLiteralTemp ("defines");
539 return cstring_makeLiteralTemp ("allocates");
541 return cstring_makeLiteralTemp ("releases");
543 return cstring_makeLiteralTemp ("sets");
545 return cstring_makeLiteralTemp ("isnull");
547 return cstring_makeLiteralTemp ("notnull");
549 return cstring_makeLiteralTemp ("only");
551 return cstring_makeLiteralTemp ("shared");
553 return cstring_makeLiteralTemp ("dependent");
555 return cstring_makeLiteralTemp ("owned");
557 return cstring_makeLiteralTemp ("observer");
559 return cstring_makeLiteralTemp ("exposed");
565 cstring specialClause_unparseKind (specialClause s)
567 return (message ("%s%s",
568 cstring_makeLiteralTemp (s->state == TK_BEFORE
570 : (s->state == TK_AFTER
572 specialClauseKind_unparse (s->kind)));
575 cstring specialClause_unparse (specialClause s)
577 return (message ("%q %q",
578 specialClause_unparseKind (s), sRefSet_unparse (s->refs)));
581 specialClause specialClause_createDefines (sRefSet s)
583 return (specialClause_create (TK_BOTH, SP_DEFINES, s));
586 specialClause specialClause_createUses (sRefSet s)
588 return (specialClause_create (TK_BOTH, SP_USES, s));
591 specialClause specialClause_createSets (sRefSet s)
593 return (specialClause_create (TK_BOTH, SP_SETS, s));
596 specialClause specialClause_createReleases (sRefSet s)
598 return (specialClause_create (TK_BOTH, SP_RELEASES, s));
601 specialClause specialClause_createAllocates (sRefSet s)
603 return (specialClause_create (TK_BOTH, SP_ALLOCATES, s));
606 static /*@notnull@*/ specialClauses specialClauses_new (void)
608 specialClauses s = (specialClauses) dmalloc (sizeof (*s));
611 s->nspace = specialClausesBASESIZE;
612 s->elements = (specialClause *)
613 dmalloc (sizeof (*s->elements) * specialClausesBASESIZE);
619 specialClauses_grow (specialClauses s)
622 specialClause *newelements;
624 llassert (specialClauses_isDefined (s));
626 s->nspace += specialClausesBASESIZE;
628 newelements = (specialClause *)
629 dmalloc (sizeof (*newelements) * (s->nelements + s->nspace));
631 for (i = 0; i < s->nelements; i++)
633 newelements[i] = s->elements[i];
637 s->elements = newelements;
640 specialClauses specialClauses_add (specialClauses s, specialClause el)
642 if (specialClauses_isUndefined (s))
644 s = specialClauses_new ();
648 specialClauses_elements (s, cl)
650 if (specialClause_sameKind (cl, el))
654 message ("Multiple %q clauses for one function (using union)",
655 specialClause_unparseKind (cl)),
658 cl->refs = sRefSet_union (cl->refs, el->refs);
659 specialClause_free (el);
662 } end_specialClauses_elements ;
667 specialClauses_grow (s);
671 s->elements[s->nelements] = el;
677 cstring specialClauses_unparse (specialClauses s)
679 cstring st = cstring_undefined;
682 if (specialClauses_isDefined (s))
684 for (i = 0; i < specialClauses_size (s); i++)
688 st = message ("%q;", specialClause_unparse (s->elements[i]));
691 st = message ("%q %q;", st, specialClause_unparse (s->elements[i]));
698 specialClauses specialClauses_copy (specialClauses s)
700 if (specialClauses_isDefined (s))
702 specialClauses t = (specialClauses) dmalloc (sizeof (*t));
705 t->nelements = s->nelements;
708 if (s->nelements > 0)
710 t->elements = (specialClause *) dmalloc (sizeof (*t->elements) * t->nelements);
711 for (i = 0; i < s->nelements; i++)
713 t->elements[i] = specialClause_copy (s->elements[i]);
725 return specialClauses_undefined;
730 specialClauses_free (specialClauses s)
732 if (!specialClauses_isUndefined (s))
736 for (i = 0; i < s->nelements; i++)
738 specialClause_free (s->elements[i]);
746 cstring specialClauses_dump (specialClauses s)
748 cstring st = cstring_undefined;
750 if (specialClauses_isUndefined (s)) return st;
752 specialClauses_elements (s, current)
754 st = message ("%q%q$", st, specialClause_dump (current));
755 } end_specialClauses_elements;
760 specialClauses specialClauses_undump (char **s)
763 specialClauses pn = specialClauses_new ();
768 while (c != '#' && c != '@')
770 specialClause sc = specialClause_undump (s);
772 pn = specialClauses_add (pn, sc);
773 reader_checkChar (s, '$');
781 static /*@exposed@*/ sRefSet
782 specialClauses_getClause (specialClauses s, stateConstraint st,
785 specialClauses_elements (s, el)
787 if (el->state == st && el->kind == k)
791 } end_specialClauses_elements ;
793 return sRefSet_undefined;
796 void specialClauses_checkAll (uentry ue)
798 specialClauses clauses = uentry_getSpecialClauses (ue);
799 sRef res = uentry_getSref (ue);
800 bool specialResult = FALSE;
802 specialClauses_elements (clauses, cl)
804 bool isPre = (cl->state == TK_BEFORE);
805 sRefSet refs = cl->refs;
807 sRefSet_allElements (refs, el)
809 sRef rb = sRef_getRootBase (el);
811 if (sRef_isResult (rb))
817 message ("Function result is used in %q clause of %q "
818 "(%q applies to the state before function is "
819 "called, so should not use result): %q",
820 specialClause_unparseKind (cl),
822 specialClause_unparseKind (cl),
824 uentry_whereLast (ue));
828 if (!sRef_isStateSpecial (res))
834 message ("Function result is used in %q clause of %q "
835 "but not annotated with special: %q",
836 specialClause_unparseKind (cl),
839 uentry_whereLast (ue));
841 specialResult = TRUE;
845 (void) sRef_fixResultType (el, sRef_getType (res), ue);
848 else if (sRef_isParam (rb))
850 if (!sRef_isStateSpecial (rb))
854 message ("Reference %q used in %q clause of %q, "
855 "but not annotated with special: %q",
857 specialClause_unparseKind (cl),
860 uentry_whereLast (ue));
863 else if (sRef_isInvalid (rb))
865 /*@innercontinue@*/ continue;
870 /*@innercontinue@*/ continue;
873 if (specialClause_isMemoryAllocation (cl))
875 if (!ctype_isVisiblySharable (sRef_getType (el)))
879 message ("Special clause %q includes %q of "
880 "non-dynamically allocatated type %s",
881 specialClause_unparseKind (cl),
883 ctype_unparse (sRef_getType (el))));
887 } end_sRefSet_allElements ;
888 } end_specialClauses_elements ;
891 void specialClauses_checkEqual (uentry old, uentry unew)
893 specialClauses oldClauses = uentry_getSpecialClauses (old);
894 specialClauses newClauses = uentry_getSpecialClauses (unew);
896 if (specialClauses_isDefined (newClauses))
898 specialClauses_elements (newClauses, cl)
900 sRefSet sc = specialClauses_getClause (oldClauses, cl->state, cl->kind);
902 if (!sRefSet_equal (sc, cl->refs))
906 message ("Function %q %rdeclared with inconsistent %q clause: %q",
907 uentry_getName (old),
908 uentry_isDeclared (old),
909 specialClause_unparseKind (cl),
910 sRefSet_unparsePlain (cl->refs)),
913 uentry_showWhereLastExtra (old, sRefSet_unparsePlain (sc));
916 } end_specialClauses_elements ;
918 specialClauses_elements (oldClauses, cl)
920 sRefSet sc = specialClauses_getClause (newClauses, cl->state, cl->kind);
922 if (sRefSet_isUndefined (sc) && !sRefSet_isEmpty (cl->refs))
926 message ("Function %q %rdeclared without %q clause (either "
927 "use no special clauses in redeclaration, or "
928 "they must match exactly: %q",
929 uentry_getName (old),
930 uentry_isDeclared (old),
931 specialClause_unparseKind (cl),
932 sRefSet_unparsePlain (cl->refs)),
935 uentry_showWhereLastExtra (old, sRefSet_unparsePlain (sc));
938 } end_specialClauses_elements ;