2 ** LCLint - 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://lclint.cs.virginia.edu
28 # include "lclintMacros.nf"
31 alkind alkind_fromInt (int n)
34 llassert (n >= AK_UNKNOWN && n <= AK_LOCAL);
40 nstate nstate_fromInt (int n)
43 llassert (n >= NS_ERROR && n <= NS_ABSNULL);
49 sstate sstate_fromInt (int n)
52 llassert (n >= SS_UNKNOWN && n < SS_LAST);
58 exkind exkind_fromInt (int n)
61 llassert (n >= XO_UNKNOWN && n <= XO_OBSERVER);
67 cstring sstate_unparse (sstate s)
71 case SS_UNKNOWN: return cstring_makeLiteralTemp ("unknown");
72 case SS_UNUSEABLE: return cstring_makeLiteralTemp ("unuseable");
73 case SS_UNDEFINED: return cstring_makeLiteralTemp ("undefined");
74 case SS_MUNDEFINED:return cstring_makeLiteralTemp ("possibly undefined");
75 case SS_ALLOCATED: return cstring_makeLiteralTemp ("allocated");
76 case SS_PDEFINED: return cstring_makeLiteralTemp ("partially defined");
77 case SS_DEFINED: return cstring_makeLiteralTemp ("defined");
78 case SS_PARTIAL: return cstring_makeLiteralTemp ("partial");
79 case SS_SPECIAL: return cstring_makeLiteralTemp ("special");
80 case SS_DEAD: return cstring_makeLiteralTemp ("dead");
81 case SS_HOFFA: return cstring_makeLiteralTemp ("probably dead");
82 case SS_FIXED: return cstring_makeLiteralTemp ("unmodifiable");
83 case SS_RELDEF: return cstring_makeLiteralTemp ("reldef");
84 case SS_LAST: llcontbuglit ("sstate_unparse: last");
85 return cstring_makeLiteralTemp ("<error>");
86 case SS_UNDEFGLOB: return cstring_makeLiteralTemp ("undefglob");
87 case SS_KILLED: return cstring_makeLiteralTemp ("killed");
89 return cstring_makeLiteralTemp ("undefkilled");
95 bool nstate_possiblyNull (nstate n)
98 ** note: not NS_UNKNOWN or NS_ERROR
101 return ((n >= NS_CONSTNULL) && (n <= NS_ABSNULL));
104 bool nstate_perhapsNull (nstate n)
107 ** note: not NS_UNKNOWN or NS_ERROR
110 return ((n >= NS_RELNULL) && (n <= NS_ABSNULL));
113 cstring nstate_unparse (nstate n)
117 case NS_ERROR: return cstring_makeLiteralTemp ("<null error>");
118 case NS_UNKNOWN: return cstring_makeLiteralTemp ("implicitly non-null");
119 case NS_POSNULL: return cstring_makeLiteralTemp ("null");
120 case NS_DEFNULL: return cstring_makeLiteralTemp ("null");
121 case NS_NOTNULL: return cstring_makeLiteralTemp ("notnull");
122 case NS_MNOTNULL: return cstring_makeLiteralTemp ("notnull");
123 case NS_ABSNULL: return cstring_makeLiteralTemp ("null");
124 case NS_RELNULL: return cstring_makeLiteralTemp ("relnull");
125 case NS_CONSTNULL: return cstring_makeLiteralTemp ("null");
132 ** ??? (used to do something different for guarded)
135 int nstate_compare (nstate n1, nstate n2)
137 return (generic_compare (n1, n2));
141 ** This occurs when we select a field with alkind inner,
142 ** from a structure with alkind outer. It is probably
146 alkind alkind_derive (alkind outer, alkind inner)
151 case AK_UNKNOWN: return inner;
157 case AK_IMPDEPENDENT:
159 if (inner == AK_SHARED) return AK_SHARED;
161 /* not so sure about these? */
176 if (alkind_isKnown (inner)) return inner;
182 cstring alkind_unparse (alkind a)
186 case AK_ERROR: return cstring_makeLiteralTemp ("<error>");
187 case AK_UNKNOWN: return cstring_makeLiteralTemp ("unqualified");
188 case AK_ONLY: return cstring_makeLiteralTemp ("only");
189 case AK_IMPONLY: return cstring_makeLiteralTemp ("implicitly only");
190 case AK_OWNED: return cstring_makeLiteralTemp ("owned");
191 case AK_IMPDEPENDENT: return cstring_makeLiteralTemp ("implicitly dependent");
192 case AK_DEPENDENT: return cstring_makeLiteralTemp ("dependent");
193 case AK_KEEP: return cstring_makeLiteralTemp ("keep");
194 case AK_KEPT: return cstring_makeLiteralTemp ("kept");
195 case AK_IMPTEMP: return cstring_makeLiteralTemp ("implicitly temp");
196 case AK_TEMP: return cstring_makeLiteralTemp ("temp");
197 case AK_SHARED: return cstring_makeLiteralTemp ("shared");
198 case AK_UNIQUE: return cstring_makeLiteralTemp ("unique");
199 case AK_RETURNED: return cstring_makeLiteralTemp ("returned");
200 case AK_FRESH: return cstring_makeLiteralTemp ("fresh");
201 case AK_STACK: return cstring_makeLiteralTemp ("stack");
202 case AK_REFCOUNTED: return cstring_makeLiteralTemp ("refcounted");
203 case AK_REFS: return cstring_makeLiteralTemp ("refs");
204 case AK_KILLREF: return cstring_makeLiteralTemp ("killref");
205 case AK_NEWREF: return cstring_makeLiteralTemp ("newref");
206 case AK_LOCAL: return cstring_makeLiteralTemp ("local");
207 case AK_STATIC: return cstring_makeLiteralTemp ("unqualified static");
212 cstring exkind_unparse (exkind a)
216 case XO_UNKNOWN: return cstring_makeLiteralTemp ("unknown");
217 case XO_NORMAL: return cstring_makeLiteralTemp ("unexposed");
218 case XO_EXPOSED: return cstring_makeLiteralTemp ("exposed");
219 case XO_OBSERVER: return cstring_makeLiteralTemp ("observer");
224 cstring exkind_capName (exkind a)
228 case XO_UNKNOWN: return cstring_makeLiteralTemp ("Unknown");
229 case XO_NORMAL: return cstring_makeLiteralTemp ("Unexposed");
230 case XO_EXPOSED: return cstring_makeLiteralTemp ("Exposed");
231 case XO_OBSERVER: return cstring_makeLiteralTemp ("Observer");
236 cstring exkind_unparseError (exkind a)
240 case XO_UNKNOWN: return cstring_makeLiteralTemp ("unqualified");
241 case XO_NORMAL: return cstring_makeLiteralTemp ("unqualifier");
242 case XO_EXPOSED: return cstring_makeLiteralTemp ("exposed");
243 case XO_OBSERVER: return cstring_makeLiteralTemp ("observer");
248 cstring alkind_capName (alkind a)
253 return cstring_makeLiteralTemp ("<Error>");
255 return cstring_makeLiteralTemp ("Unqualified");
257 return cstring_makeLiteralTemp ("Only");
259 return cstring_makeLiteralTemp ("Implicitly only");
261 return cstring_makeLiteralTemp ("Owned");
262 case AK_IMPDEPENDENT:
263 return cstring_makeLiteralTemp ("Implicitly dependent");
265 return cstring_makeLiteralTemp ("Dependent");
267 return cstring_makeLiteralTemp ("Keep");
269 return cstring_makeLiteralTemp ("Kept");
271 return cstring_makeLiteralTemp ("Implicitly temp");
273 return cstring_makeLiteralTemp ("Temp");
275 return cstring_makeLiteralTemp ("Shared");
277 return cstring_makeLiteralTemp ("Unique");
279 return cstring_makeLiteralTemp ("Returned");
281 return cstring_makeLiteralTemp ("Fresh");
283 return cstring_makeLiteralTemp ("Stack");
285 return cstring_makeLiteralTemp ("Refcounted");
287 return cstring_makeLiteralTemp ("Refs");
289 return cstring_makeLiteralTemp ("Killref");
291 return cstring_makeLiteralTemp ("Newref");
293 return cstring_makeLiteralTemp ("Local");
295 return cstring_makeLiteralTemp ("Unqualified static");
301 exkind_fromQual (qual q)
303 if (qual_isExposed (q)) return XO_EXPOSED;
304 if (qual_isObserver (q)) return XO_OBSERVER;
307 llcontbug (message ("exkind_fromQual: not exp qualifier: %d" , (int)q));
313 sstate_fromQual (qual q)
315 if (qual_isOut (q)) return SS_ALLOCATED;
316 if (qual_isIn (q)) return SS_DEFINED;
317 else if (qual_isPartial (q)) return SS_PARTIAL;
318 else if (qual_isRelDef (q)) return SS_RELDEF;
319 else if (qual_isUndef (q)) return SS_UNDEFGLOB;
320 else if (qual_isKilled (q)) return SS_KILLED;
321 else if (qual_isSpecial (q)) return SS_SPECIAL;
324 llcontbug (message ("sstate_fromQual: not alias qualifier: %s (%d)" ,
332 exitkind_fromQual (qual q)
334 if (qual_isExits (q)) return XK_MUSTEXIT;
335 if (qual_isMayExit (q)) return XK_MAYEXIT;
336 if (qual_isTrueExit (q)) return XK_TRUEEXIT;
337 if (qual_isFalseExit (q)) return XK_FALSEEXIT;
338 if (qual_isNeverExit (q)) return XK_NEVERESCAPE;
341 llcontbug (message ("exitkind_fromQual: not exit qualifier: %s",
348 alkind_fromQual (qual q)
350 if (qual_isOnly (q)) return AK_ONLY;
351 if (qual_isImpOnly (q)) return AK_IMPONLY;
352 if (qual_isKeep (q)) return AK_KEEP;
353 if (qual_isKept (q)) return AK_KEPT;
354 if (qual_isTemp (q)) return AK_TEMP;
355 if (qual_isShared (q)) return AK_SHARED;
356 if (qual_isUnique (q)) return AK_UNIQUE;
357 if (qual_isRefCounted (q)) return AK_REFCOUNTED;
358 if (qual_isRefs (q)) return AK_REFS;
359 if (qual_isNewRef (q)) return AK_NEWREF;
360 if (qual_isKillRef (q)) return AK_KILLREF;
361 if (qual_isTempRef (q)) return AK_KILLREF; /* kludge? use kill ref for this */
362 if (qual_isOwned (q)) return AK_OWNED;
363 if (qual_isDependent (q)) return AK_DEPENDENT;
365 llcontbug (message ("alkind_fromQual: not alias qualifier: %d" , (int)q));
369 static bool alkind_isMeaningless (alkind a1)
371 return (a1 == AK_ERROR || a1 == AK_UNKNOWN || a1 == AK_RETURNED
372 || a1 == AK_STACK || a1 == AK_REFCOUNTED
373 || a1 == AK_REFS || a1 == AK_KILLREF || a1 == AK_NEWREF
377 bool alkind_compatible (alkind a1, alkind a2)
379 if (a1 == a2) return TRUE;
380 if (a2 == AK_ERROR) return TRUE;
381 if (a2 == AK_UNKNOWN)
383 return (alkind_isMeaningless (a1) || (a1 == AK_IMPTEMP));
388 case AK_ERROR: return TRUE;
389 case AK_UNKNOWN: return (alkind_isMeaningless (a2)
390 || (a2 == AK_IMPTEMP));
391 case AK_IMPONLY: return (a2 == AK_KEEP || a2 == AK_FRESH
393 case AK_ONLY: return (a2 == AK_KEEP || a2 == AK_FRESH
394 || a2 == AK_IMPONLY);
395 case AK_OWNED: return FALSE;
396 case AK_IMPDEPENDENT: return (a2 == AK_DEPENDENT);
397 case AK_DEPENDENT: return (a2 == AK_IMPDEPENDENT);
398 case AK_KEEP: return (a2 == AK_ONLY || a2 == AK_FRESH
399 || a2 == AK_IMPONLY);
400 case AK_KEPT: return FALSE;
401 case AK_IMPTEMP: return (a2 == AK_TEMP);
402 case AK_TEMP: return (a2 == AK_IMPTEMP);
403 case AK_SHARED: return FALSE;
404 case AK_UNIQUE: return (a2 == AK_TEMP);
405 case AK_RETURNED: return (alkind_isMeaningless (a2));
406 case AK_FRESH: return (alkind_isOnly (a2));
407 case AK_STACK: return (alkind_isMeaningless (a2));
408 case AK_REFCOUNTED: return (alkind_isMeaningless (a2));
409 case AK_REFS: return (alkind_isMeaningless (a2));
410 case AK_KILLREF: return (alkind_isMeaningless (a2));
411 case AK_NEWREF: return (alkind_isMeaningless (a2));
412 case AK_LOCAL: return (alkind_isMeaningless (a2));
413 case AK_STATIC: return (alkind_isMeaningless (a2));
418 bool alkind_equal (alkind a1, alkind a2)
420 if (a1 == a2) return TRUE;
421 if (a2 == AK_ERROR) return TRUE;
425 case AK_ERROR: return TRUE;
426 case AK_IMPONLY: return (a2 == AK_ONLY);
427 case AK_ONLY: return (a2 == AK_IMPONLY);
428 case AK_IMPDEPENDENT: return (a2 == AK_DEPENDENT);
429 case AK_DEPENDENT: return (a2 == AK_IMPDEPENDENT);
430 case AK_IMPTEMP: return (a2 == AK_TEMP);
431 case AK_TEMP: return (a2 == AK_IMPTEMP);
432 default: return FALSE;
439 alkind_fixImplicit (alkind a)
441 if (a == AK_IMPTEMP) return AK_TEMP;
442 if (a == AK_IMPONLY) return AK_IMPONLY;
443 if (a == AK_IMPDEPENDENT) return AK_DEPENDENT;
448 cstring exitkind_unparse (exitkind k)
452 case XK_ERROR: return (cstring_makeLiteralTemp ("<error>"));
453 case XK_UNKNOWN: return (cstring_makeLiteralTemp ("?"));
454 case XK_NEVERESCAPE: return (cstring_makeLiteralTemp ("never escape"));
455 case XK_MAYEXIT: return (cstring_makeLiteralTemp ("mayexit"));
456 case XK_MUSTEXIT: return (cstring_makeLiteralTemp ("exits"));
457 case XK_TRUEEXIT: return (cstring_makeLiteralTemp ("trueexit"));
458 case XK_FALSEEXIT: return (cstring_makeLiteralTemp ("falseexit"));
459 case XK_MUSTRETURN: return (cstring_makeLiteralTemp ("mustreturn"));
460 case XK_MAYRETURN: return (cstring_makeLiteralTemp ("mayreturn"));
461 case XK_MUSTRETURNEXIT: return (cstring_makeLiteralTemp ("mustreturnexit"));
462 case XK_MAYRETURNEXIT: return (cstring_makeLiteralTemp ("mayreturnexit"));
463 case XK_GOTO: return (cstring_makeLiteralTemp ("goto"));
464 case XK_MAYGOTO: return (cstring_makeLiteralTemp ("maygoto"));
470 exitkind exitkind_makeConditional (exitkind k)
476 case XK_MUSTEXIT: return XK_MAYEXIT;
477 case XK_MUSTRETURN: return XK_MAYRETURN;
478 case XK_MUSTRETURNEXIT: return XK_MAYRETURNEXIT;
479 case XK_GOTO: return XK_MAYGOTO;
484 exitkind exitkind_combine (exitkind k1, exitkind k2)
498 case XK_ERROR: return XK_ERROR;
500 case XK_NEVERESCAPE: return (exitkind_makeConditional (k2));
504 case XK_MUSTRETURNEXIT:
505 case XK_MUSTRETURN: return XK_MUSTRETURNEXIT;
506 case XK_MAYRETURNEXIT:
507 case XK_MAYRETURN: return XK_MAYRETURNEXIT;
508 default: return XK_MAYEXIT;
517 case XK_MUSTRETURNEXIT:
518 case XK_MAYRETURNEXIT:
520 case XK_MUSTRETURN: return XK_MAYRETURNEXIT;
521 default: return XK_MAYEXIT;
528 case XK_MUSTRETURNEXIT:
529 case XK_MUSTEXIT: return XK_MUSTRETURNEXIT;
530 case XK_MAYRETURNEXIT:
533 case XK_MAYEXIT: return XK_MAYRETURNEXIT;
534 default: return XK_MAYRETURN;
539 if (exitkind_couldExit (k2))
541 return XK_MAYRETURNEXIT;
548 case XK_MUSTRETURNEXIT:
552 case XK_MUSTEXIT: return XK_MUSTRETURNEXIT;
553 default: return XK_MAYRETURNEXIT;
557 case XK_MAYRETURNEXIT: return XK_MAYRETURNEXIT;
560 if (exitkind_couldExit (k2))
562 return XK_MAYRETURNEXIT;
570 bool exitkind_couldExit (exitkind e)
578 case XK_MAYRETURNEXIT:
579 case XK_MUSTRETURNEXIT:
581 case XK_MAYGOTO: return TRUE;
582 default: return FALSE;
586 static bool exitkind_couldReturn (exitkind e) /*@*/
592 case XK_MAYRETURNEXIT:
593 case XK_MUSTRETURNEXIT: return TRUE;
594 default: return FALSE;
598 static bool exitkind_couldGoto (exitkind e) /*@*/
600 return (e == XK_GOTO || e == XK_MAYGOTO);
603 bool exitkind_couldEscape (exitkind e)
605 return exitkind_couldReturn (e) || exitkind_couldExit (e)
606 || exitkind_couldGoto (e);
609 exitkind exitkind_fromInt (int x)
612 llassert (x >= XK_ERROR && x <= XK_LAST);