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"
31 alkind
alkind_fromInt (int n
)
34 if (n
< AK_UNKNOWN
|| n
> AK_LOCAL
)
36 llbug (message ("Alias kind out of range: %d", n
));
43 nstate
nstate_fromInt (int n
)
46 llassertprint (n
>= NS_ERROR
&& n
<= NS_ABSNULL
,
47 ("Bad null state: %d", n
));
53 sstate
sstate_fromInt (int n
)
56 llassert (n
>= SS_UNKNOWN
&& n
< SS_LAST
);
62 exkind
exkind_fromInt (int n
)
65 llassert (n
>= XO_UNKNOWN
&& n
<= XO_OBSERVER
);
71 cstring
sstate_unparse (sstate s
)
75 case SS_UNKNOWN
: return cstring_makeLiteralTemp ("unknown");
76 case SS_UNUSEABLE
: return cstring_makeLiteralTemp ("unuseable");
77 case SS_UNDEFINED
: return cstring_makeLiteralTemp ("undefined");
78 case SS_MUNDEFINED
:return cstring_makeLiteralTemp ("possibly undefined");
79 case SS_ALLOCATED
: return cstring_makeLiteralTemp ("allocated");
80 case SS_PDEFINED
: return cstring_makeLiteralTemp ("partially defined");
81 case SS_DEFINED
: return cstring_makeLiteralTemp ("defined");
82 case SS_PARTIAL
: return cstring_makeLiteralTemp ("partial");
83 case SS_SPECIAL
: return cstring_makeLiteralTemp ("special");
84 case SS_DEAD
: return cstring_makeLiteralTemp ("dead");
85 case SS_HOFFA
: return cstring_makeLiteralTemp ("probably dead");
86 case SS_FIXED
: return cstring_makeLiteralTemp ("unmodifiable");
87 case SS_RELDEF
: return cstring_makeLiteralTemp ("reldef");
88 case SS_LAST
: llcontbuglit ("sstate_unparse: last");
89 return cstring_makeLiteralTemp ("<error>");
90 case SS_UNDEFGLOB
: return cstring_makeLiteralTemp ("undefglob");
91 case SS_KILLED
: return cstring_makeLiteralTemp ("killed");
93 return cstring_makeLiteralTemp ("undefkilled");
99 bool nstate_possiblyNull (nstate n
)
102 ** note: not NS_UNKNOWN or NS_ERROR
105 return ((n
>= NS_CONSTNULL
) && (n
<= NS_ABSNULL
));
108 bool nstate_perhapsNull (nstate n
)
111 ** note: not NS_UNKNOWN or NS_ERROR
114 return ((n
>= NS_RELNULL
) && (n
<= NS_ABSNULL
));
117 cstring
nstate_unparse (nstate n
)
121 case NS_ERROR
: return cstring_makeLiteralTemp ("<null error>");
122 case NS_UNKNOWN
: return cstring_makeLiteralTemp ("implicitly non-null");
123 case NS_POSNULL
: return cstring_makeLiteralTemp ("null");
124 case NS_DEFNULL
: return cstring_makeLiteralTemp ("null");
125 case NS_NOTNULL
: return cstring_makeLiteralTemp ("notnull");
126 case NS_MNOTNULL
: return cstring_makeLiteralTemp ("notnull");
127 case NS_ABSNULL
: return cstring_makeLiteralTemp ("null");
128 case NS_RELNULL
: return cstring_makeLiteralTemp ("relnull");
129 case NS_CONSTNULL
: return cstring_makeLiteralTemp ("null");
132 /*@notreached@*/ llcontbuglit ("bad null state!");
133 /*@notreached@*/ return cstring_makeLiteralTemp ("!!! bad null state !!!");
138 ** ??? (used to do something different for guarded)
141 int nstate_compare (nstate n1
, nstate n2
)
143 return (generic_compare (n1
, n2
));
147 ** This occurs when we select a field with alkind inner,
148 ** from a structure with alkind outer. It is probably
152 alkind
alkind_derive (alkind outer
, alkind inner
)
157 case AK_UNKNOWN
: return inner
;
163 case AK_IMPDEPENDENT
:
165 if (inner
== AK_SHARED
) return AK_SHARED
;
166 else if (outer
== AK_DEPENDENT
) return AK_IMPDEPENDENT
;
167 else if (outer
== AK_ONLY
) return AK_IMPONLY
;
169 /* not so sure about these? */
184 if (alkind_isKnown (inner
)) return inner
;
190 cstring
alkind_unparse (alkind a
)
194 case AK_ERROR
: return cstring_makeLiteralTemp ("<error>");
195 case AK_UNKNOWN
: return cstring_makeLiteralTemp ("unqualified");
196 case AK_ONLY
: return cstring_makeLiteralTemp ("only");
197 case AK_IMPONLY
: return cstring_makeLiteralTemp ("implicitly only");
198 case AK_OWNED
: return cstring_makeLiteralTemp ("owned");
199 case AK_IMPDEPENDENT
: return cstring_makeLiteralTemp ("implicitly dependent");
200 case AK_DEPENDENT
: return cstring_makeLiteralTemp ("dependent");
201 case AK_KEEP
: return cstring_makeLiteralTemp ("keep");
202 case AK_KEPT
: return cstring_makeLiteralTemp ("kept");
203 case AK_IMPTEMP
: return cstring_makeLiteralTemp ("implicitly temp");
204 case AK_TEMP
: return cstring_makeLiteralTemp ("temp");
205 case AK_SHARED
: return cstring_makeLiteralTemp ("shared");
206 case AK_UNIQUE
: return cstring_makeLiteralTemp ("unique");
207 case AK_RETURNED
: return cstring_makeLiteralTemp ("returned");
208 case AK_FRESH
: return cstring_makeLiteralTemp ("fresh");
209 case AK_STACK
: return cstring_makeLiteralTemp ("stack");
210 case AK_REFCOUNTED
: return cstring_makeLiteralTemp ("refcounted");
211 case AK_REFS
: return cstring_makeLiteralTemp ("refs");
212 case AK_KILLREF
: return cstring_makeLiteralTemp ("killref");
213 case AK_NEWREF
: return cstring_makeLiteralTemp ("newref");
214 case AK_LOCAL
: return cstring_makeLiteralTemp ("local");
215 case AK_STATIC
: return cstring_makeLiteralTemp ("unqualified static");
220 cstring
exkind_unparse (exkind a
)
224 case XO_UNKNOWN
: return cstring_makeLiteralTemp ("unknown");
225 case XO_NORMAL
: return cstring_makeLiteralTemp ("unexposed");
226 case XO_EXPOSED
: return cstring_makeLiteralTemp ("exposed");
227 case XO_OBSERVER
: return cstring_makeLiteralTemp ("observer");
232 cstring
exkind_capName (exkind a
)
236 case XO_UNKNOWN
: return cstring_makeLiteralTemp ("Unknown");
237 case XO_NORMAL
: return cstring_makeLiteralTemp ("Unexposed");
238 case XO_EXPOSED
: return cstring_makeLiteralTemp ("Exposed");
239 case XO_OBSERVER
: return cstring_makeLiteralTemp ("Observer");
244 cstring
exkind_unparseError (exkind a
)
248 case XO_UNKNOWN
: return cstring_makeLiteralTemp ("unqualified");
249 case XO_NORMAL
: return cstring_makeLiteralTemp ("unqualifier");
250 case XO_EXPOSED
: return cstring_makeLiteralTemp ("exposed");
251 case XO_OBSERVER
: return cstring_makeLiteralTemp ("observer");
256 cstring
alkind_capName (alkind a
)
261 return cstring_makeLiteralTemp ("<Error>");
263 return cstring_makeLiteralTemp ("Unqualified");
265 return cstring_makeLiteralTemp ("Only");
267 return cstring_makeLiteralTemp ("Implicitly only");
269 return cstring_makeLiteralTemp ("Owned");
270 case AK_IMPDEPENDENT
:
271 return cstring_makeLiteralTemp ("Implicitly dependent");
273 return cstring_makeLiteralTemp ("Dependent");
275 return cstring_makeLiteralTemp ("Keep");
277 return cstring_makeLiteralTemp ("Kept");
279 return cstring_makeLiteralTemp ("Implicitly temp");
281 return cstring_makeLiteralTemp ("Temp");
283 return cstring_makeLiteralTemp ("Shared");
285 return cstring_makeLiteralTemp ("Unique");
287 return cstring_makeLiteralTemp ("Returned");
289 return cstring_makeLiteralTemp ("Fresh");
291 return cstring_makeLiteralTemp ("Stack");
293 return cstring_makeLiteralTemp ("Refcounted");
295 return cstring_makeLiteralTemp ("Refs");
297 return cstring_makeLiteralTemp ("Killref");
299 return cstring_makeLiteralTemp ("Newref");
301 return cstring_makeLiteralTemp ("Local");
303 return cstring_makeLiteralTemp ("Unqualified static");
309 exkind_fromQual (qual q
)
311 if (qual_isExposed (q
)) {
313 } else if (qual_isObserver (q
)) {
317 llcontbug (message ("exkind_fromQual: not exp qualifier: %s" ,
324 sstate_fromQual (qual q
)
326 if (qual_isOut (q
)) return SS_ALLOCATED
;
327 if (qual_isIn (q
)) return SS_DEFINED
;
328 else if (qual_isPartial (q
)) return SS_PARTIAL
;
329 else if (qual_isRelDef (q
)) return SS_RELDEF
;
330 else if (qual_isUndef (q
)) return SS_UNDEFGLOB
;
331 else if (qual_isKilled (q
)) return SS_KILLED
;
332 else if (qual_isSpecial (q
)) return SS_SPECIAL
;
335 llcontbug (message ("sstate_fromQual: not alias qualifier: %s",
342 exitkind_fromQual (qual q
)
344 if (qual_isExits (q
)) return XK_MUSTEXIT
;
345 if (qual_isMayExit (q
)) return XK_MAYEXIT
;
346 if (qual_isTrueExit (q
)) return XK_TRUEEXIT
;
347 if (qual_isFalseExit (q
)) return XK_FALSEEXIT
;
348 if (qual_isNeverExit (q
)) return XK_NEVERESCAPE
;
351 llcontbug (message ("exitkind_fromQual: not exit qualifier: %s",
358 alkind_fromQual (qual q
)
360 if (qual_isOnly (q
)) return AK_ONLY
;
361 if (qual_isImpOnly (q
)) return AK_IMPONLY
;
362 if (qual_isKeep (q
)) return AK_KEEP
;
363 if (qual_isKept (q
)) return AK_KEPT
;
364 if (qual_isTemp (q
)) return AK_TEMP
;
365 if (qual_isShared (q
)) return AK_SHARED
;
366 if (qual_isUnique (q
)) return AK_UNIQUE
;
367 if (qual_isRefCounted (q
)) return AK_REFCOUNTED
;
368 if (qual_isRefs (q
)) return AK_REFS
;
369 if (qual_isNewRef (q
)) return AK_NEWREF
;
370 if (qual_isKillRef (q
)) return AK_KILLREF
;
371 if (qual_isTempRef (q
)) return AK_KILLREF
; /* kludge? use kill ref for this */
372 if (qual_isOwned (q
)) return AK_OWNED
;
373 if (qual_isDependent (q
)) return AK_DEPENDENT
;
375 llcontbug (message ("alkind_fromQual: not alias qualifier: %s", qual_unparse (q
)));
379 static bool alkind_isMeaningless (alkind a1
)
381 return (a1
== AK_ERROR
|| a1
== AK_UNKNOWN
|| a1
== AK_RETURNED
382 || a1
== AK_STACK
|| a1
== AK_REFCOUNTED
383 || a1
== AK_REFS
|| a1
== AK_KILLREF
|| a1
== AK_NEWREF
387 bool alkind_compatible (alkind a1
, alkind a2
)
389 if (a1
== a2
) return TRUE
;
390 if (a2
== AK_ERROR
) return TRUE
;
391 if (a2
== AK_UNKNOWN
)
393 return (alkind_isMeaningless (a1
) || (a1
== AK_IMPTEMP
));
398 case AK_ERROR
: return TRUE
;
399 case AK_UNKNOWN
: return (alkind_isMeaningless (a2
)
400 || (a2
== AK_IMPTEMP
));
401 case AK_IMPONLY
: return (a2
== AK_KEEP
|| a2
== AK_FRESH
403 case AK_ONLY
: return (a2
== AK_KEEP
|| a2
== AK_FRESH
404 || a2
== AK_IMPONLY
);
405 case AK_OWNED
: return FALSE
;
406 case AK_IMPDEPENDENT
: return (a2
== AK_DEPENDENT
);
407 case AK_DEPENDENT
: return (a2
== AK_IMPDEPENDENT
);
408 case AK_KEEP
: return (a2
== AK_ONLY
|| a2
== AK_FRESH
409 || a2
== AK_IMPONLY
);
410 case AK_KEPT
: return FALSE
;
411 case AK_IMPTEMP
: return (a2
== AK_TEMP
);
412 case AK_TEMP
: return (a2
== AK_IMPTEMP
);
413 case AK_SHARED
: return FALSE
;
414 case AK_UNIQUE
: return (a2
== AK_TEMP
);
415 case AK_RETURNED
: return (alkind_isMeaningless (a2
));
416 case AK_FRESH
: return (alkind_isOnly (a2
));
417 case AK_STACK
: return (alkind_isMeaningless (a2
));
418 case AK_REFCOUNTED
: return (alkind_isMeaningless (a2
));
419 case AK_REFS
: return (alkind_isMeaningless (a2
));
420 case AK_KILLREF
: return (alkind_isMeaningless (a2
));
421 case AK_NEWREF
: return (alkind_isMeaningless (a2
));
422 case AK_LOCAL
: return (alkind_isMeaningless (a2
));
423 case AK_STATIC
: return (alkind_isMeaningless (a2
));
428 bool alkind_equal (alkind a1
, alkind a2
)
430 if (a1
== a2
) return TRUE
;
431 if (a2
== AK_ERROR
) return TRUE
;
435 case AK_ERROR
: return TRUE
;
436 case AK_IMPONLY
: return (a2
== AK_ONLY
);
437 case AK_ONLY
: return (a2
== AK_IMPONLY
);
438 case AK_IMPDEPENDENT
: return (a2
== AK_DEPENDENT
);
439 case AK_DEPENDENT
: return (a2
== AK_IMPDEPENDENT
);
440 case AK_IMPTEMP
: return (a2
== AK_TEMP
);
441 case AK_TEMP
: return (a2
== AK_IMPTEMP
);
442 default: return FALSE
;
449 alkind_fixImplicit (alkind a
)
451 if (a
== AK_IMPTEMP
) return AK_TEMP
;
452 if (a
== AK_IMPONLY
) return AK_IMPONLY
;
453 if (a
== AK_IMPDEPENDENT
) return AK_DEPENDENT
;
458 cstring
exitkind_unparse (exitkind k
)
462 case XK_ERROR
: return (cstring_makeLiteralTemp ("<error>"));
463 case XK_UNKNOWN
: return (cstring_makeLiteralTemp ("?"));
464 case XK_NEVERESCAPE
: return (cstring_makeLiteralTemp ("never escape"));
465 case XK_MAYEXIT
: return (cstring_makeLiteralTemp ("mayexit"));
466 case XK_MUSTEXIT
: return (cstring_makeLiteralTemp ("exits"));
467 case XK_TRUEEXIT
: return (cstring_makeLiteralTemp ("trueexit"));
468 case XK_FALSEEXIT
: return (cstring_makeLiteralTemp ("falseexit"));
469 case XK_MUSTRETURN
: return (cstring_makeLiteralTemp ("mustreturn"));
470 case XK_MAYRETURN
: return (cstring_makeLiteralTemp ("mayreturn"));
471 case XK_MUSTRETURNEXIT
: return (cstring_makeLiteralTemp ("mustreturnexit"));
472 case XK_MAYRETURNEXIT
: return (cstring_makeLiteralTemp ("mayreturnexit"));
473 case XK_GOTO
: return (cstring_makeLiteralTemp ("goto"));
474 case XK_MAYGOTO
: return (cstring_makeLiteralTemp ("maygoto"));
480 exitkind
exitkind_makeConditional (exitkind k
)
486 case XK_MUSTEXIT
: return XK_MAYEXIT
;
487 case XK_MUSTRETURN
: return XK_MAYRETURN
;
488 case XK_MUSTRETURNEXIT
: return XK_MAYRETURNEXIT
;
489 case XK_GOTO
: return XK_MAYGOTO
;
494 exitkind
exitkind_combine (exitkind k1
, exitkind k2
)
508 case XK_ERROR
: return XK_ERROR
;
510 case XK_NEVERESCAPE
: return (exitkind_makeConditional (k2
));
514 case XK_MUSTRETURNEXIT
:
515 case XK_MUSTRETURN
: return XK_MUSTRETURNEXIT
;
516 case XK_MAYRETURNEXIT
:
517 case XK_MAYRETURN
: return XK_MAYRETURNEXIT
;
518 default: return XK_MAYEXIT
;
527 case XK_MUSTRETURNEXIT
:
528 case XK_MAYRETURNEXIT
:
530 case XK_MUSTRETURN
: return XK_MAYRETURNEXIT
;
531 default: return XK_MAYEXIT
;
538 case XK_MUSTRETURNEXIT
:
539 case XK_MUSTEXIT
: return XK_MUSTRETURNEXIT
;
540 case XK_MAYRETURNEXIT
:
543 case XK_MAYEXIT
: return XK_MAYRETURNEXIT
;
544 default: return XK_MAYRETURN
;
549 if (exitkind_couldExit (k2
))
551 return XK_MAYRETURNEXIT
;
558 case XK_MUSTRETURNEXIT
:
562 case XK_MUSTEXIT
: return XK_MUSTRETURNEXIT
;
563 default: return XK_MAYRETURNEXIT
;
567 case XK_MAYRETURNEXIT
: return XK_MAYRETURNEXIT
;
570 if (exitkind_couldExit (k2
))
572 return XK_MAYRETURNEXIT
;
580 bool exitkind_couldExit (exitkind e
)
588 case XK_MAYRETURNEXIT
:
589 case XK_MUSTRETURNEXIT
:
591 case XK_MAYGOTO
: return TRUE
;
592 default: return FALSE
;
596 static bool exitkind_couldReturn (exitkind e
) /*@*/
602 case XK_MAYRETURNEXIT
:
603 case XK_MUSTRETURNEXIT
: return TRUE
;
604 default: return FALSE
;
608 static bool exitkind_couldGoto (exitkind e
) /*@*/
610 return (e
== XK_GOTO
|| e
== XK_MAYGOTO
);
613 bool exitkind_couldEscape (exitkind e
)
615 return exitkind_couldReturn (e
) || exitkind_couldExit (e
)
616 || exitkind_couldGoto (e
);
619 exitkind
exitkind_fromInt (int x
)
622 llassert (x
>= XK_ERROR
&& x
<= XK_LAST
);