]> andersk Git - splint.git/blame - src/varKinds.c
commitng to fix cvs archive. Code works with gcc272 but not 295. Currently passed...
[splint.git] / src / varKinds.c
CommitLineData
885824d3 1/*
2** LCLint - annotation-assisted static program checker
3** Copyright (C) 1994-2000 University of Virginia,
4** Massachusetts Institute of Technology
5**
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.
10**
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.
15**
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.
19**
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
23*/
24/*
25** varKinds.c
26*/
27
28# include "lclintMacros.nf"
29# include "basic.h"
30
31alkind alkind_fromInt (int n)
32{
33 /*@+enumint@*/
34 llassert (n >= AK_UNKNOWN && n <= AK_LOCAL);
35 /*@=enumint@*/
36
37 return ((alkind)n);
38}
39
40nstate nstate_fromInt (int n)
41{
42 /*@+enumint@*/
43 llassert (n >= NS_ERROR && n <= NS_ABSNULL);
44 /*@=enumint@*/
45
46 return ((nstate)n);
47}
48
49sstate sstate_fromInt (int n)
50{
51 /*@+enumint@*/
52 llassert (n >= SS_UNKNOWN && n < SS_LAST);
53 /*@=enumint@*/
54
55 return ((sstate)n);
56}
57
58exkind exkind_fromInt (int n)
59{
60 /*@+enumint@*/
61 llassert (n >= XO_UNKNOWN && n <= XO_OBSERVER);
62 /*@=enumint@*/
63
64 return ((exkind) n);
65}
66
67cstring sstate_unparse (sstate s)
68{
69 switch (s)
70 {
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");
88 case SS_UNDEFKILLED:
89 return cstring_makeLiteralTemp ("undefkilled");
90 }
91
92 BADEXIT;
93}
94
95bool nstate_possiblyNull (nstate n)
96{
97 /*
98 ** note: not NS_UNKNOWN or NS_ERROR
99 */
100
101 return ((n >= NS_CONSTNULL) && (n <= NS_ABSNULL));
102}
103
104bool nstate_perhapsNull (nstate n)
105{
106 /*
107 ** note: not NS_UNKNOWN or NS_ERROR
108 */
109
110 return ((n >= NS_RELNULL) && (n <= NS_ABSNULL));
111}
112
113cstring nstate_unparse (nstate n)
114{
115 switch (n)
116 {
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");
126 }
127
128 BADEXIT;
129}
130
131/*
132** ??? (used to do something different for guarded)
133*/
134
135int nstate_compare (nstate n1, nstate n2)
136{
137 return (generic_compare (n1, n2));
138}
139
140/*
141** This occurs when we select a field with alkind inner,
142** from a structure with alkind outer. It is probably
143** unnecessary.
144*/
145
146alkind alkind_derive (alkind outer, alkind inner)
147{
148 switch (outer)
149 {
150 case AK_ERROR:
151 case AK_UNKNOWN: return inner;
152 case AK_KEPT:
153 case AK_KEEP:
154 case AK_ONLY:
155 case AK_IMPONLY:
156 case AK_OWNED:
157 case AK_IMPDEPENDENT:
158 case AK_DEPENDENT:
159 if (inner == AK_SHARED) return AK_SHARED;
160 else return outer;
161 /* not so sure about these? */
162 case AK_REFCOUNTED:
163 case AK_NEWREF:
164 case AK_KILLREF:
165 case AK_REFS:
166 case AK_STACK:
167 case AK_STATIC:
168 return outer;
169 case AK_TEMP:
170 case AK_IMPTEMP:
171 case AK_SHARED:
172 case AK_UNIQUE:
173 case AK_LOCAL:
174 case AK_FRESH:
175 case AK_RETURNED:
176 if (alkind_isKnown (inner)) return inner;
177 else return outer;
178 }
179 BADEXIT;
180}
181
182cstring alkind_unparse (alkind a)
183{
184 switch (a)
185 {
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");
208 }
209 BADEXIT;
210}
211
212cstring exkind_unparse (exkind a)
213{
214 switch (a)
215 {
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");
220 }
221 BADEXIT;
222}
223
224cstring exkind_capName (exkind a)
225{
226 switch (a)
227 {
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");
232 }
233 BADEXIT;
234}
235
236cstring exkind_unparseError (exkind a)
237{
238 switch (a)
239 {
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");
244 }
245 BADEXIT;
246}
247
248cstring alkind_capName (alkind a)
249{
250 switch (a)
251 {
252 case AK_ERROR:
253 return cstring_makeLiteralTemp ("<Error>");
254 case AK_UNKNOWN:
255 return cstring_makeLiteralTemp ("Unqualified");
256 case AK_ONLY:
257 return cstring_makeLiteralTemp ("Only");
258 case AK_IMPONLY:
259 return cstring_makeLiteralTemp ("Implicitly only");
260 case AK_OWNED:
261 return cstring_makeLiteralTemp ("Owned");
262 case AK_IMPDEPENDENT:
263 return cstring_makeLiteralTemp ("Implicitly dependent");
264 case AK_DEPENDENT:
265 return cstring_makeLiteralTemp ("Dependent");
266 case AK_KEEP:
267 return cstring_makeLiteralTemp ("Keep");
268 case AK_KEPT:
269 return cstring_makeLiteralTemp ("Kept");
270 case AK_IMPTEMP:
271 return cstring_makeLiteralTemp ("Implicitly temp");
272 case AK_TEMP:
273 return cstring_makeLiteralTemp ("Temp");
274 case AK_SHARED:
275 return cstring_makeLiteralTemp ("Shared");
276 case AK_UNIQUE:
277 return cstring_makeLiteralTemp ("Unique");
278 case AK_RETURNED:
279 return cstring_makeLiteralTemp ("Returned");
280 case AK_FRESH:
281 return cstring_makeLiteralTemp ("Fresh");
282 case AK_STACK:
283 return cstring_makeLiteralTemp ("Stack");
284 case AK_REFCOUNTED:
285 return cstring_makeLiteralTemp ("Refcounted");
286 case AK_REFS:
287 return cstring_makeLiteralTemp ("Refs");
288 case AK_KILLREF:
289 return cstring_makeLiteralTemp ("Killref");
290 case AK_NEWREF:
291 return cstring_makeLiteralTemp ("Newref");
292 case AK_LOCAL:
293 return cstring_makeLiteralTemp ("Local");
294 case AK_STATIC:
295 return cstring_makeLiteralTemp ("Unqualified static");
296 }
297 BADEXIT;
298}
299
300exkind
301exkind_fromQual (qual q)
302{
303 if (qual_isExposed (q)) return XO_EXPOSED;
304 if (qual_isObserver (q)) return XO_OBSERVER;
305 else
306 {
307 llcontbug (message ("exkind_fromQual: not exp qualifier: %d" , (int)q));
308 return XO_UNKNOWN;
309 }
310}
311
312sstate
313sstate_fromQual (qual q)
314{
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;
322 else
323 {
324 llcontbug (message ("sstate_fromQual: not alias qualifier: %s (%d)" ,
325 qual_unparse (q),
326 (int)q));
327 return SS_UNKNOWN;
328 }
329}
330
331exitkind
332exitkind_fromQual (qual q)
333{
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;
339 else
340 {
341 llcontbug (message ("exitkind_fromQual: not exit qualifier: %s",
342 qual_unparse (q)));
343 return XK_UNKNOWN;
344 }
345}
346
347alkind
348alkind_fromQual (qual q)
349{
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;
364
365 llcontbug (message ("alkind_fromQual: not alias qualifier: %d" , (int)q));
366 return AK_ERROR;
367}
368
369static bool alkind_isMeaningless (alkind a1)
370{
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
374 || a1 == AK_LOCAL);
375}
376
377bool alkind_compatible (alkind a1, alkind a2)
378{
379 if (a1 == a2) return TRUE;
380 if (a2 == AK_ERROR) return TRUE;
381 if (a2 == AK_UNKNOWN)
382 {
383 return (alkind_isMeaningless (a1) || (a1 == AK_IMPTEMP));
384 }
385
386 switch (a1)
387 {
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
392 || a2 == AK_ONLY);
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));
414 }
415 BADEXIT;
416}
417
418bool alkind_equal (alkind a1, alkind a2)
419{
420 if (a1 == a2) return TRUE;
421 if (a2 == AK_ERROR) return TRUE;
422
423 switch (a1)
424 {
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;
433 }
434
435 BADEXIT;
436}
437
438alkind
439alkind_fixImplicit (alkind a)
440{
441 if (a == AK_IMPTEMP) return AK_TEMP;
442 if (a == AK_IMPONLY) return AK_IMPONLY;
443 if (a == AK_IMPDEPENDENT) return AK_DEPENDENT;
444
445 return a;
446}
447
448cstring exitkind_unparse (exitkind k)
449{
450 switch (k)
451 {
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"));
465 }
466
467 BADEXIT;
468}
469
470exitkind exitkind_makeConditional (exitkind k)
471{
472 switch (k)
473 {
474 case XK_TRUEEXIT:
475 case XK_FALSEEXIT:
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;
480 default: return k;
481 }
482}
483
484exitkind exitkind_combine (exitkind k1, exitkind k2)
485{
486 if (k1 == k2)
487 {
488 return k1;
489 }
490
491 if (k2 == XK_ERROR)
492 {
493 return XK_ERROR;
494 }
495
496 switch (k1)
497 {
498 case XK_ERROR: return XK_ERROR;
499 case XK_UNKNOWN:
500 case XK_NEVERESCAPE: return (exitkind_makeConditional (k2));
501 case XK_MUSTEXIT:
502 switch (k2)
503 {
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;
509 }
510 BADEXIT;
511
512 case XK_MAYEXIT:
513 case XK_TRUEEXIT:
514 case XK_FALSEEXIT:
515 switch (k2)
516 {
517 case XK_MUSTRETURNEXIT:
518 case XK_MAYRETURNEXIT:
519 case XK_MAYRETURN:
520 case XK_MUSTRETURN: return XK_MAYRETURNEXIT;
521 default: return XK_MAYEXIT;
522 }
523 BADEXIT;
524
525 case XK_MUSTRETURN:
526 switch (k2)
527 {
528 case XK_MUSTRETURNEXIT:
529 case XK_MUSTEXIT: return XK_MUSTRETURNEXIT;
530 case XK_MAYRETURNEXIT:
531 case XK_TRUEEXIT:
532 case XK_FALSEEXIT:
533 case XK_MAYEXIT: return XK_MAYRETURNEXIT;
534 default: return XK_MAYRETURN;
535 }
536 BADEXIT;
537
538 case XK_MAYRETURN:
539 if (exitkind_couldExit (k2))
540 {
541 return XK_MAYRETURNEXIT;
542 }
543 else
544 {
545 return XK_MAYRETURN;
546 }
547
548 case XK_MUSTRETURNEXIT:
549 switch (k2)
550 {
551 case XK_MUSTRETURN:
552 case XK_MUSTEXIT: return XK_MUSTRETURNEXIT;
553 default: return XK_MAYRETURNEXIT;
554 }
555 BADEXIT;
556
557 case XK_MAYRETURNEXIT: return XK_MAYRETURNEXIT;
558 case XK_GOTO:
559 case XK_MAYGOTO:
560 if (exitkind_couldExit (k2))
561 {
562 return XK_MAYRETURNEXIT;
563 }
564 return XK_MAYGOTO;
565 }
566
567 BADEXIT;
568}
569
570bool exitkind_couldExit (exitkind e)
571{
572 switch (e)
573 {
574 case XK_MAYEXIT:
575 case XK_MUSTEXIT:
576 case XK_TRUEEXIT:
577 case XK_FALSEEXIT:
578 case XK_MAYRETURNEXIT:
579 case XK_MUSTRETURNEXIT:
580 case XK_GOTO:
581 case XK_MAYGOTO: return TRUE;
582 default: return FALSE;
583 }
584}
585
586static bool exitkind_couldReturn (exitkind e) /*@*/
587{
588 switch (e)
589 {
590 case XK_MUSTRETURN:
591 case XK_MAYRETURN:
592 case XK_MAYRETURNEXIT:
593 case XK_MUSTRETURNEXIT: return TRUE;
594 default: return FALSE;
595 }
596}
597
598static bool exitkind_couldGoto (exitkind e) /*@*/
599{
600 return (e == XK_GOTO || e == XK_MAYGOTO);
601}
602
603bool exitkind_couldEscape (exitkind e)
604{
605 return exitkind_couldReturn (e) || exitkind_couldExit (e)
606 || exitkind_couldGoto (e);
607}
608
609exitkind exitkind_fromInt (int x)
610{
611 /*@+enumint@*/
612 llassert (x >= XK_ERROR && x <= XK_LAST);
613 /*@=enumint@*/
614
615 return (exitkind) x;
616}
617
618
619
620
621
622
623
This page took 0.125916 seconds and 5 git commands to generate.