1 /*
2 ** Splint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2003 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 splint: info@splint.org
21 ** To report a bug: splint-bug@splint.org
22 ** For more information: http://www.splint.org
23 */
24 /*
25 ** storeRef.c
26 **
27 ** Memory management:
28 ** storeRef's are kept in allRefs for each function scope, and all are
29 ** free'd at the end of the function. This relies on the constraint that
30 ** no storeRef created while checking a function is used outside that
31 ** function.
32 **
33 ** storeRefs in the file and global scopes are free'd by the uentry.
34 **
35 */
36
37 # include "splintMacros.nf"
38 # include "basic.h"
39 # include "exprChecks.h"
40 # include "transferChecks.h"
41 # include "sRefTable.h"
42 # include "structNames.h"
43
44 /*
45 ** Predicate functions that evaluate both arguments in order.
46 */
47
48 /*@notfunction@*/
49 # define OR(a,b) (a ? (b, TRUE) : b)
50
51 /*@notfunction@*/
52 # define AND(a,b) (a ? b : (b, FALSE))
53
54 static void sRef_checkValidAux (sRef p_s, sRefSet p_checkedsofar) /*@modifies p_checkedsofar@*/ ;
55
56 static bool sRef_isDerived (sRef p_s) /*@*/ ;
57
58 static /*@exposed@*/ sRef sRef_fixDirectBase (sRef p_s, sRef p_base)
59 /*@modifies p_base@*/ ;
60
61 static void sRef_updateNullState (sRef p_res, sRef p_other) /*@modifies p_res@*/ ;
62
63 static bool sRef_isAllocatedStorage (sRef p_s) /*@*/ ;
64 static void sRef_setNullErrorLoc (sRef p_s, fileloc) /*@*/ ;
65 static void sRef_setNullStateN (sRef p_s, nstate p_n) /*@modifies p_s@*/ ;
66
67 static int sRef_depth (sRef p_s) /*@*/ ;
68
69 static void
70 sRef_innerAliasSetComplete (void (p_predf) (sRef, fileloc), sRef p_s,
71 fileloc p_loc)
72 /*@modifies p_s@*/ ;
73
74 static void
75 sRef_innerAliasSetCompleteParam (void (p_predf) (sRef, sRef), sRef p_s, sRef p_t)
76 /*@modifies p_s@*/ ;
77
78 static speckind speckind_fromInt (int p_i);
79 static bool sRef_equivalent (sRef p_s1, sRef p_s2);
80 static bool sRef_isDeepUnionField (sRef p_s);
81 static void sRef_addDeriv (/*@notnull@*/ sRef p_s, /*@notnull@*/ /*@exposed@*/ sRef p_t);
82 static bool sRef_checkModify (sRef p_s, sRefSet p_sl) /*@*/ ;
83
84 /*
85 ** If s is definitely null, it has no memory state.
86 */
87
sRef_resetAliasKind(sRef s)88 static void sRef_resetAliasKind (/*@notnull@*/ sRef s) /*@modifies s->aliaskind@*/
89 {
90 if (s->nullstate == NS_DEFNULL)
91 {
92 /* s->aliaskind = AK_ERROR; */
93 }
94 }
95
96 # ifdef DEBUGSPLINT
sRef_checkCompletelyReasonable(sRef s)97 extern void sRef_checkCompletelyReasonable (sRef s) /*@*/
98 {
99 DPRINTF (("Check sRef: [%p] %s / %s", s, sRef_unparse (s),
100 sRefSet_unparse (sRef_derivedFields (s))));
101
102 if (sRef_isReasonable (s))
103 {
104 sRefSet_elements (s->deriv, el)
105 {
106 llassert (el != s);
107 sRef_checkCompletelyReasonable (el);
108 } end_sRefSet_elements ;
109 }
110 }
111 # endif
112
sRef_isReasonable(sRef s)113 /*@falsewhennull@*/ bool sRef_isReasonable (sRef s) /*@*/
114 {
115 if (sRef_isValid (s))
116 {
117 # ifdef DEBUGSPLINT
118 if (!bool_isReasonable (s->safe)
119 || !bool_isReasonable (s->modified)
120 || !bool_isReasonable (s->immut))
121 {
122 llcontbug (message ("Unreasonable sRef [%p]", s));
123 return FALSE;
124 }
125
126 if (!sstate_isValid (s->defstate))
127 {
128 llcontbug (message ("Unreasonable sRef [%p]", s));
129 return FALSE;
130 }
131
132 if (!nstate_isValid (s->nullstate))
133 {
134 llcontbug (message ("Unreasonable sRef [%p]", s));
135 return FALSE;
136 }
137
138 if (!alkind_isValid (s->aliaskind)
139 || !alkind_isValid (s->oaliaskind))
140 {
141 llcontbug (message ("Unreasonable sRef [%p]", s));
142 return FALSE;
143 }
144
145 if (!exkind_isValid (s->expkind)
146 || !exkind_isValid (s->oexpkind))
147 {
148 llcontbug (message ("Unreasonable sRef [%p]", s));
149 return FALSE;
150 }
151 # endif
152
153 return TRUE;
154 }
155
156 return FALSE;
157 }
158
sRef_isUnreasonable(sRef s)159 static /*@nullwhentrue@*/ bool sRef_isUnreasonable (sRef s) /*@*/
160 {
161 return (!sRef_isReasonable (s));
162 }
163
sRef_checkMutable(sRef s)164 static void sRef_checkMutable (/*@unused@*/ sRef s)
165 {
166 if (sRef_isReasonable (s) && s->immut)
167 {
168 llcontbug (message ("Modification to sRef marked immutable: %q",
169 sRef_unparseFull (s)));
170 }
171 }
172
skind_isSimple(skind sk)173 static bool skind_isSimple (skind sk)
174 {
175 switch (sk)
176 {
177 case SK_PARAM: case SK_CVAR: case SK_CONST:
178 case SK_OBJECT: case SK_UNKNOWN: case SK_NEW:
179 return TRUE;
180 default:
181 return FALSE;
182 }
183 }
184
185 static void sinfo_free (/*@special@*/ /*@temp@*/ /*@notnull@*/ sRef p_s)
186 /*@uses p_s->kind, p_s->info@*/
187 /*@releases p_s->info@*/ ;
188
189 static /*@null@*/ sinfo sinfo_copy (/*@notnull@*/ sRef p_s) /*@*/ ;
190 static void sRef_setPartsFromUentry (sRef p_s, uentry p_ue)
191 /*@modifies p_s@*/ ;
192 static bool checkDeadState (/*@notnull@*/ sRef p_el, /*@null@*/ sRef p_e2,
193 bool p_tbranch, fileloc p_loc);
194 static /*@dependent@*/ sRef sRef_constructPointerAux (/*@notnull@*/ /*@exposed@*/ sRef p_t) /*@*/ ;
195
196 static void
197 sRef_combineExKinds (/*@notnull@*/ sRef p_res, /*@notnull@*/ sRef p_other)
198 /*@modifies p_res@*/ ;
199
200 static void
201 sRef_combineAliasKinds (/*@notnull@*/ sRef p_res, /*@notnull@*/ sRef p_other,
202 clause p_cl, fileloc p_loc)
203 /*@modifies p_res@*/ ;
204
205 static void
206 sRef_combineNullState (/*@notnull@*/ sRef p_res, /*@notnull@*/ sRef p_other)
207 /*@modifies p_res@*/ ;
208
209 static void
210 sRef_combineDefState (/*@notnull@*/ sRef p_res, /*@notnull@*/ sRef p_other)
211 /*@modifies p_res@*/ ;
212
213 static void sRef_setStateFromAbstractUentry (sRef p_s, uentry p_ue)
214 /*@modifies p_s@*/ ;
215
216 static void
217 sinfo_update (/*@notnull@*/ /*@exposed@*/ sRef p_res,
218 /*@notnull@*/ /*@exposed@*/ sRef p_other);
219 static void sRef_setDefinedAux (sRef p_s, fileloc p_loc, bool p_clear)
220 /*@modifies p_s@*/ ;
221 static void sRef_setDefinedNoClear (sRef p_s, fileloc p_loc)
222 /*@modifies p_s@*/ ;
223 static void sRef_setStateAux (sRef p_s, sstate p_ss, fileloc p_loc)
224 /*@modifies p_s@*/;
225
226 static /*@exposed@*/ sRef
227 sRef_buildNCField (/*@exposed@*/ sRef p_rec, /*@exposed@*/ cstring p_f);
228
229 static void
230 sRef_mergeStateAux (/*@notnull@*/ sRef p_res, /*@notnull@*/ sRef p_other,
231 clause p_cl, bool p_opt, fileloc p_loc,
232 bool p_doDerivs)
233 /*@modifies p_res, p_other@*/ ;
234
235 static /*@null@*/ sinfo sinfo_fullCopy (/*@notnull@*/ sRef p_s);
236 static bool sRef_doModify (sRef p_s, sRefSet p_sl) /*@modifies p_s@*/ ;
237 static bool sRef_doModifyVal (sRef p_s, sRefSet p_sl) /*@modifies p_s@*/;
238 static bool sRef_checkModifyVal (sRef p_s, sRefSet p_sl) /*@*/ ;
239
240 static /*@only@*/ sRefSet
241 sRef_mergeDerivs (/*@only@*/ sRefSet p_res, sRefSet p_other,
242 bool p_opt, clause p_cl, fileloc p_loc);
243
244 static /*@only@*/ sRefSet
245 sRef_mergeUnionDerivs (/*@only@*/ sRefSet p_res,
246 /*@exposed@*/ sRefSet p_other,
247 bool p_opt, clause p_cl, fileloc p_loc);
248
249 static /*@only@*/ sRefSet
250 sRef_mergePdefinedDerivs (/*@only@*/ sRefSet p_res, sRefSet p_other, bool p_opt,
251 clause p_cl, fileloc p_loc);
252
253 static /*@only@*/ cstring sRef_unparseWithArgs (sRef p_s, uentryList p_args);
254 static /*@only@*/ cstring sRef_unparseNoArgs (sRef p_s);
255
256 static /*@exposed@*/ sRef sRef_findDerivedPointer (sRef p_s);
257 static /*@exposed@*/ sRef sRef_findDerivedArrayFetch (/*@notnull@*/ sRef, bool, int, bool) ;
258 static /*@exposed@*/ sRef sRef_findDerivedField (/*@notnull@*/ sRef p_rec, cstring p_f);
259 static /*@exposed@*/ sRef
260 sRef_getDeriv (/*@notnull@*/ /*@returned@*/ sRef p_set, sRef p_guide);
261
262 static bool inFunction = FALSE;
263 static /*@only@*/ sRefTable allRefs;
264
265 /* # define DEBUGREFS */
266
267 # ifdef DEBUGREFS
268 static nsrefs = 0;
269 static totnsrefs = 0;
270 static maxnsrefs = 0;
271 static ntotrefers = 0;
272 static nrefers = 0;
273 # endif
274
275 static /*@checked@*/ bool protectDerivs = FALSE;
276
277 /*
278 ** Result of sRef_alloc is dependent since allRefs may
279 ** reference it. It is only if !inFunction.
280 */
281
282 static /*@dependent@*/ /*@out@*/ /*@notnull@*/ sRef
sRef_alloc(void)283 sRef_alloc (void)
284 {
285 sRef s = (sRef) dmalloc (sizeof (*s));
286
287 s->immut = FALSE;
288
289 DPRINTF (("Alloc sref: [%p]", s));
290
291 if (inFunction)
292 {
293 allRefs = sRefTable_add (allRefs, s);
294 /*@-branchstate@*/
295 }
296 else
297 {
298 DPRINTF (("Not in function!"));
299 }
300
301 /*@=branchstate@*/
302
303 # ifdef DEBUGREFS
304 if (nsrefs >= maxnsrefs)
305 {
306 maxnsrefs = nsrefs;
307 }
308
309 totnsrefs++;
310 nsrefs++;
311 # endif
312
313 /*@-mustfree@*/ /*@-freshtrans@*/
314 return s;
315 /*@=mustfree@*/ /*@=freshtrans@*/
316 }
317
sRef_checkValidAux(sRef s,sRefSet checkedsofar)318 static void sRef_checkValidAux (sRef s, sRefSet checkedsofar)
319 {
320 llassert (FALSE);
321
322 if (!sRef_isReasonable (s)) return;
323
324 if (sRefSet_containsSameObject (checkedsofar, s))
325 {
326 return;
327 }
328
329 /*@-temptrans@*/
330 checkedsofar = sRefSet_insert (checkedsofar, s);
331 /*@=temptrans@*/ /* checksofar will be destroyed before checkValid returns */
332
333 switch (s->kind)
334 {
335 case SK_UNCONSTRAINED:
336 llassert (cstring_length (s->info->fname) < 100);
337 break;
338
339 case SK_CVAR:
340 llassert (s->info->cvar->lexlevel >= 0);
341 /* llassert (s->info->cvar->lexlevel <= usymtab_getCurrentDepth ()); */
342 break;
343
344 case SK_PARAM:
345 llassert (s->info->paramno >= -1);
346 llassert (s->info->paramno <= 999); /* sanity check */
347 break;
348
349 case SK_ARRAYFETCH:
350 sRef_checkValidAux (s->info->arrayfetch->arr, checkedsofar);
351 break;
352
353 case SK_FIELD:
354 sRef_checkValidAux (s->info->field->rec, checkedsofar);
355 llassert (cstring_length (s->info->field->field) < 100);
356 break;
357
358 case SK_PTR:
359 sRef_checkValidAux (s->info->ref, checkedsofar);
360 break;
361
362 case SK_ADR:
363 sRef_checkValidAux (s->info->ref, checkedsofar);
364 break;
365
366 case SK_OBJECT:
367 /* check ctype s->info->object */
368 break;
369
370 case SK_CONJ:
371 sRef_checkValidAux (s->info->conj->a, checkedsofar);
372 sRef_checkValidAux (s->info->conj->b, checkedsofar);
373 break;
374
375 case SK_NEW:
376 llassert (cstring_length (s->info->fname) < 100);
377 break;
378
379 case SK_DERIVED:
380 sRef_checkValidAux (s->info->ref, checkedsofar);
381 break;
382
383 case SK_EXTERNAL:
384 sRef_checkValidAux (s->info->ref, checkedsofar);
385 break;
386
387 case SK_TYPE:
388 case SK_CONST:
389 case SK_RESULT:
390 /* check ctyp s->type */
391 break;
392
393 case SK_SPECIAL:
394 llassert (s->info->spec == SR_NOTHING
395 || s->info->spec == SR_INTERNAL
396 || s->info->spec == SR_SPECSTATE
397 || s->info->spec == SR_SYSTEM);
398 break;
399
400 case SK_UNKNOWN:
401 break;
402
403 BADDEFAULT;
404 }
405
406
407 sRefSet_elements (s->deriv, el)
408 {
409 sRef_checkValidAux (el, checkedsofar);
410 } end_sRefSet_elements ;
411 }
412
sRef_checkValid(sRef s)413 void sRef_checkValid (/*@unused@*/ sRef s)
414 {
415 return;
416 /*
417 sRefSet checkedsofar = sRefSet_new ();
418 sRef_checkValidAux (s, checkedsofar);
419 */
420 }
421
422 static /*@dependent@*/ /*@notnull@*/ /*@special@*/ sRef
sRef_new(void)423 sRef_new (void)
424 /*@defines result@*/
425 /*@ensures isnull result->aliasinfo, result->definfo,
426 result->expinfo, result->info, result->deriv, result->state@*/
427 {
428 sRef s = sRef_alloc ();
429
430 s->kind = SK_UNKNOWN;
431 s->safe = TRUE;
432 s->modified = FALSE;
433 s->immut = FALSE;
434 s->val = multiVal_undefined;
435
436 s->type = ctype_unknown;
437 s->defstate = SS_UNKNOWN;
438
439 /* start modifications */
440 s->bufinfo.bufstate = BB_NOTNULLTERMINATED;
441 s->bufinfo.size = -1;
442 s->bufinfo.len = -1;
443 /* end modifications */
444
445 s->aliaskind = AK_UNKNOWN;
446 s->oaliaskind = AK_UNKNOWN;
447
448 s->nullstate = NS_UNKNOWN;
449
450 s->expkind = XO_UNKNOWN;
451 s->oexpkind = XO_UNKNOWN;
452
453 s->aliasinfo = stateInfo_undefined;
454 s->definfo = stateInfo_undefined;
455 s->nullinfo = stateInfo_undefined;
456 s->expinfo = stateInfo_undefined;
457
458 s->info = NULL;
459 s->deriv = sRefSet_undefined;
460
461 s->state = valueTable_undefined;
462
463 return s;
464 }
465
466 static /*@dependent@*/ /*@notnull@*/ /*@special@*/ sRef
sRef_newRef(void)467 sRef_newRef (void)
468 /*@defines result@*/
469 /*@ensures isnull result->aliasinfo, result->definfo,
470 result->expinfo, result->info, result->deriv@*/
471 {
472 sRef res = sRef_new ();
473 res->immut = FALSE;
474 res->state = valueTable_undefined;
475 return res;
476 }
477
478
sRef_protectDerivs(void)479 void sRef_protectDerivs (void) /*@modifies protectDerivs@*/
480 {
481 llassert (!protectDerivs);
482 protectDerivs = TRUE;
483 }
484
sRef_clearProtectDerivs(void)485 void sRef_clearProtectDerivs (void) /*@modifies protectDerivs@*/
486 {
487 llassert (protectDerivs);
488 protectDerivs = FALSE;
489 }
490
491 /*
492 ** hmmm...here be kind of a hack. This function mysteriously appeared
493 ** in my code, but I'm sure I didn't write it.
494 */
495
496 bool
sRef_isRecursiveField(sRef s)497 sRef_isRecursiveField (sRef s)
498 {
499 if (sRef_isField (s))
500 {
501 if (sRef_depth (s) > 13)
502 {
503 sRef base;
504 cstring fieldname;
505
506 fieldname = sRef_getField (s);
507 base = sRef_getBase (s);
508
509 while (sRef_isReasonable (base))
510 {
511 if (sRef_isField (base))
512 {
513 if (cstring_equal (fieldname, sRef_getField (base)))
514 {
515 return TRUE;
516 }
517 }
518
519 base = sRef_getBaseSafe (base);
520 }
521 }
522 }
523
524 return FALSE;
525 }
526
527 static void
sRef_addDeriv(sRef s,sRef t)528 sRef_addDeriv (/*@notnull@*/ sRef s, /*@notnull@*/ /*@exposed@*/ sRef t)
529 {
530 if (!context_inProtectVars ()
531 && !protectDerivs
532 && sRef_isReasonable (s)
533 && sRef_isReasonable (t)
534 && !sRef_isConst (s))
535 {
536 int sd = sRef_depth (s);
537 int td = sRef_depth (t);
538
539 if (sd >= td)
540 {
541 return;
542 }
543
544 /* This sometimes fails: (evans 2001-07-12)
545 if (sRef_isArrayFetch (t))
546 {
547 DPRINTF (("Derived fetch: %s / %s / %s",
548 sRef_unparseFull (s), sRef_unparseFull (t),
549 sRef_unparseFull (t->info->arrayfetch->arr)));
550 llassert (t->info->arrayfetch->arr == s);
551 }
552 */
553
554 if (sRef_isFileOrGlobalScope (s))
555 {
556 if (context_inFunctionLike ()
557 && ctype_isKnown (sRef_getType (s))
558 && !ctype_isFunction (sRef_getType (s)))
559 {
560 globSet g = context_getUsedGlobs ();
561
562 if (!globSet_member (g, s))
563 {
564 /*
565 ** don't report as a bug
566 **
567
568 llcontbug
569 (message ("sRef_addDeriv: global variable not in used "
570 "globs: %q / %s / %q",
571 sRef_unparse (s),
572 ctype_unparse (sRef_getType (s)),
573 sRefSet_unparse (s->deriv)));
574 */
575 }
576 else
577 {
578 DPRINTF (("Add deriv: [%p] %s / [%p] %s",
579 s, sRef_unparse (s),
580 t, sRef_unparse (t)));
581
582 s->deriv = sRefSet_insert (s->deriv, t);
583 }
584 }
585 }
586 else
587 {
588 DPRINTF (("Add deriv: [%p] %s / [%p] %s",
589 s, sRef_unparse (s),
590 t, sRef_unparse (t)));
591
592 s->deriv = sRefSet_insert (s->deriv, t);
593 }
594 }
595 }
596
597 bool
sRef_deepPred(bool (predf)(sRef),sRef s)598 sRef_deepPred (bool (predf) (sRef), sRef s)
599 {
600 if (sRef_isReasonable (s))
601 {
602 if ((*predf)(s)) return TRUE;
603
604 switch (s->kind)
605 {
606 case SK_PTR:
607 return (sRef_deepPred (predf, s->info->ref));
608 case SK_ARRAYFETCH:
609 return (sRef_deepPred (predf, s->info->arrayfetch->arr));
610 case SK_FIELD:
611 return (sRef_deepPred (predf, s->info->field->rec));
612 case SK_CONJ:
613 return (sRef_deepPred (predf, s->info->conj->a)
614 || sRef_deepPred (predf, s->info->conj->b));
615 default:
616 return FALSE;
617 }
618 }
619
620 return FALSE;
621 }
622
sRef_modInFunction(void)623 bool sRef_modInFunction (void)
624 {
625 return inFunction;
626 }
627
sRef_setStateFromType(sRef s,ctype ct)628 void sRef_setStateFromType (sRef s, ctype ct)
629 {
630 if (sRef_isReasonable (s))
631 {
632 if (ctype_isUser (ct))
633 {
634 DPRINTF (("Here we are: %s", sRef_unparseFull (s)));
635 sRef_setStateFromUentry
636 (s, usymtab_getTypeEntry (ctype_typeId (ct)));
637 }
638 else if (ctype_isAbstract (ct))
639 {
640 DPRINTF (("Here we are: %s", sRef_unparseFull (s)));
641 sRef_setStateFromAbstractUentry
642 (s, usymtab_getTypeEntry (ctype_typeId (ct)));
643 }
644 else
645 {
646 ; /* not a user type */
647 }
648 }
649 }
650
sRef_setTypeState(sRef s)651 static void sRef_setTypeState (sRef s)
652 {
653 if (sRef_isReasonable (s))
654 {
655 sRef_setStateFromType (s, s->type);
656 }
657 }
658
sRef_hasAliasInfoLoc(sRef s)659 bool sRef_hasAliasInfoLoc (sRef s)
660 {
661 return (sRef_isReasonable (s) && (s->aliasinfo != NULL)
662 && (fileloc_isDefined (s->aliasinfo->loc)));
663 }
664
sRef_hasStateInfoLoc(sRef s)665 /*@falsewhennull@*/ bool sRef_hasStateInfoLoc (sRef s)
666 {
667 return (sRef_isReasonable (s) && (s->definfo != NULL)
668 && (fileloc_isDefined (s->definfo->loc)));
669 }
670
sRef_hasExpInfoLoc(sRef s)671 /*@falsewhennull@*/ bool sRef_hasExpInfoLoc (sRef s)
672 {
673 return (sRef_isReasonable (s)
674 && (s->expinfo != NULL) && (fileloc_isDefined (s->expinfo->loc)));
675 }
676
677 # if 0
678 static /*@observer@*/ /*@unused@*/ stateInfo sRef_getInfo (sRef s, cstring key)
679 {
680 stateValue sv;
681
682 if (!sRef_isReasonable (s)) {
683 return stateInfo_undefined;
684 }
685
686 sv = valueTable_lookup (s->state, key);
687
688 if (stateValue_isDefined (sv))
689 {
690 return stateValue_getInfo (sv);
691 }
692
693 return stateInfo_undefined;
694 }
695 # endif
696
697 static bool
sRef_hasNullInfoLoc(sRef s)698 sRef_hasNullInfoLoc (sRef s)
699 {
700 return (sRef_isReasonable (s) && s->nullinfo != NULL
701 && (fileloc_isDefined (s->nullinfo->loc)));
702 }
703
704 bool
sRef_hasAliasInfoRef(sRef s)705 sRef_hasAliasInfoRef (sRef s)
706 {
707 return (sRef_isReasonable (s) && (s->aliasinfo != NULL)
708 && (sRef_isReasonable (s->aliasinfo->ref)));
709 }
710
711 static /*@observer@*/ fileloc
sRef_getAliasInfoLoc(sRef s)712 sRef_getAliasInfoLoc (/*@exposed@*/ sRef s)
713 {
714 llassert (sRef_isReasonable (s) && s->aliasinfo != NULL
715 && (fileloc_isDefined (s->aliasinfo->loc)));
716 return (s->aliasinfo->loc);
717 }
718
719 static /*@observer@*/ fileloc
sRef_getStateInfoLoc(sRef s)720 sRef_getStateInfoLoc (/*@exposed@*/ sRef s)
721 {
722 llassert (sRef_isReasonable (s) && s->definfo != NULL
723 && (fileloc_isDefined (s->definfo->loc)));
724 return (s->definfo->loc);
725 }
726
727 static /*@observer@*/ fileloc
sRef_getExpInfoLoc(sRef s)728 sRef_getExpInfoLoc (/*@exposed@*/ sRef s)
729 {
730 llassert (sRef_isReasonable (s) && s->expinfo != NULL
731 && (fileloc_isDefined (s->expinfo->loc)));
732 return (s->expinfo->loc);
733 }
734
735 static /*@observer@*/ fileloc
sRef_getNullInfoLoc(sRef s)736 sRef_getNullInfoLoc (/*@exposed@*/ sRef s)
737 {
738 llassert (sRef_isReasonable (s) && s->nullinfo != NULL
739 && (fileloc_isDefined (s->nullinfo->loc)));
740 return (s->nullinfo->loc);
741 }
742
743 /*@observer@*/ sRef
sRef_getAliasInfoRef(sRef s)744 sRef_getAliasInfoRef (/*@temp@*/ sRef s)
745 {
746 llassert (sRef_isReasonable (s) && s->aliasinfo != NULL);
747 return (s->aliasinfo->ref);
748 }
749
sRef_inGlobalScope()750 bool sRef_inGlobalScope ()
751 {
752 return !inFunction;
753 }
754
755 /*
756 ** This function should be called before new sRefs are created
757 ** somewhere where they will have a lifetime greater than the
758 ** current function scope.
759 */
760
sRef_setGlobalScope()761 void sRef_setGlobalScope ()
762 {
763 llassert (inFunction);
764 DPRINTF (("leave function"));
765 inFunction = FALSE;
766 }
767
sRef_clearGlobalScope()768 void sRef_clearGlobalScope ()
769 {
770 llassert (!inFunction);
771 DPRINTF (("enter function"));
772 inFunction = TRUE;
773 }
774
775 static bool oldInFunction = FALSE;
776 static int nestedScope = 0;
777
sRef_setGlobalScopeSafe()778 void sRef_setGlobalScopeSafe ()
779 {
780 if (nestedScope == 0)
781 {
782 oldInFunction = inFunction;
783 }
784
785 nestedScope++;
786 DPRINTF (("leave function safe"));
787 inFunction = FALSE;
788 }
789
sRef_clearGlobalScopeSafe()790 void sRef_clearGlobalScopeSafe ()
791 {
792 nestedScope--;
793 llassert (nestedScope >= 0);
794
795 if (nestedScope == 0)
796 {
797 inFunction = oldInFunction;
798 }
799
800 DPRINTF (("clear function: %s", bool_unparse (inFunction)));
801 }
802
sRef_enterFunctionScope()803 void sRef_enterFunctionScope ()
804 {
805 /* evans 2001-09-09 - cleanup if we are in a macro! */
806 if (context_inMacro ())
807 {
808 if (inFunction) {
809 sRef_exitFunctionScope ();
810 }
811 }
812
813 llassert (!inFunction);
814 llassert (sRefTable_isEmpty (allRefs));
815 inFunction = TRUE;
816 DPRINTF (("enter function"));
817 }
818
sRef_exitFunctionScope()819 void sRef_exitFunctionScope ()
820 {
821 if (inFunction)
822 {
823 DPRINTF (("Exit function scope."));
824 sRefTable_clear (allRefs);
825 DPRINTF (("Exit function scope done."));
826 inFunction = FALSE;
827 }
828 else
829 {
830 llbuglit ("sRef_exitFunctionScope: not in function");
831 }
832 }
833
sRef_destroyMod()834 void sRef_destroyMod () /*@globals killed allRefs;@*/
835 {
836 # ifdef DEBUGREFS
837 llmsg (message ("Live: %d / %d ", nsrefs, totnsrefs));
838 # endif
839
840 sRefTable_free (allRefs);
841 }
842
843
844 static /*@notnull@*/ /*@exposed@*/ sRef
sRef_fixConj(sRef s)845 sRef_fixConj (/*@notnull@*/ sRef s)
846 {
847 if (sRef_isConj (s))
848 {
849 do {
850 s = sRef_getConjA (s);
851 } while (sRef_isConj (s));
852
853 llassert (sRef_isReasonable (s));
854 return s; /* don't need to ref */
855 }
856 else
857 {
858 return s;
859 }
860 }
861
862 static bool
sRef_isExternallyVisibleAux(sRef s)863 sRef_isExternallyVisibleAux (sRef s)
864 {
865 bool res = FALSE;
866 sRef base = sRef_getRootBase (s);
867
868 if (sRef_isReasonable (base))
869 {
870 res = sRef_isParam (base) || sRef_isFileOrGlobalScope (base) || sRef_isExternal (base);
871 }
872
873 return res;
874 }
875
876 bool
sRef_isExternallyVisible(sRef s)877 sRef_isExternallyVisible (sRef s)
878 {
879 return (sRef_aliasCheckSimplePred (sRef_isExternallyVisibleAux, s));
880 }
881
882 /*@exposed@*/ uentry
sRef_getBaseUentry(sRef s)883 sRef_getBaseUentry (sRef s)
884 {
885 sRef base = sRef_getRootBase (s);
886 uentry res = uentry_undefined;
887
888 if (sRef_isReasonable (base))
889 {
890 switch (base->kind)
891 {
892 case SK_PARAM:
893 res = usymtab_getRefQuiet (paramsScope, usymId_fromInt (base->info->paramno));
894 break;
895
896 case SK_CVAR:
897 res = usymtab_getRefQuiet (base->info->cvar->lexlevel,
898 base->info->cvar->index);
899 break;
900
901 default:
902 break;
903 }
904 }
905
906 return res;
907 }
908
909 /*
910 ** lookup the current uentry corresponding to s, and return the corresponding sRef.
911 ** yuk yuk yuk yuk yuk yuk yuk yuk
912 */
913
914 /*@exposed@*/ sRef
sRef_updateSref(sRef s)915 sRef_updateSref (sRef s)
916 {
917 sRef inner;
918 sRef ret;
919 sRef res;
920
921 if (!sRef_isReasonable (s)) return sRef_undefined;
922
923 switch (s->kind)
924 {
925 case SK_UNKNOWN:
926 case SK_OBJECT:
927 case SK_NEW:
928 case SK_TYPE:
929 case SK_DERIVED:
930 case SK_UNCONSTRAINED:
931 case SK_CONST:
932 case SK_SPECIAL:
933 case SK_RESULT:
934 return s;
935 case SK_EXTERNAL:
936 {
937 sRef r = sRef_updateSref (s->info->ref);
938
939 if (r != s->info->ref)
940 {
941 return sRef_makeExternal (r);
942 }
943 else
944 {
945 return s;
946 }
947 }
948 case SK_PARAM:
949 case SK_CVAR:
950 {
951 uentry ue = sRef_getUentry (s);
952
953 /* must be raw name! (need the marker) */
954 /* Must be in the correct scope! */
955
956 ue = usymtab_lookupSafeScope (uentry_rawName (ue), sRef_lexLevel (s));
957
958 if (uentry_isUndefined (ue))
959 {
960 return s;
961 }
962 else
963 {
964 DPRINTF (("Update sref: %s", uentry_unparseFull (ue)));
965 return (uentry_getSref (ue));
966 }
967 }
968 case SK_ARRAYFETCH:
969 /* special case if ind known */
970 inner = s->info->arrayfetch->arr;
971 ret = sRef_updateSref (inner);
972
973 if (ret == inner)
974 {
975 res = s;
976 }
977 else
978 {
979 res = sRef_makeArrayFetch (ret);
980 }
981
982 return res;
983
984 case SK_FIELD:
985 inner = s->info->field->rec;
986 ret = sRef_updateSref (inner);
987
988 if (ret == inner)
989 {
990 res = s;
991 }
992 else
993 {
994 res = (sRef_makeField (ret, s->info->field->field));
995 }
996
997 return (res);
998 case SK_PTR:
999 inner = s->info->ref;
1000 ret = sRef_updateSref (inner);
1001 if (ret == inner)
1002 {
1003 res = s;
1004 }
1005 else
1006 {
1007 res = sRef_makePointer (ret);
1008 }
1009
1010 return (res);
1011
1012 case SK_ADR:
1013 inner = s->info->ref;
1014 ret = sRef_updateSref (inner);
1015
1016 if (ret == inner)
1017 {
1018 res = s;
1019 }
1020 else
1021 {
1022 res = sRef_makeAddress (ret);
1023 }
1024
1025 return (res);
1026
1027 case SK_CONJ:
1028 {
1029 sRef innera = s->info->conj->a;
1030 sRef innerb = s->info->conj->b;
1031 sRef reta = sRef_updateSref (innera);
1032 sRef retb = sRef_updateSref (innerb);
1033
1034 if (innera == reta && innerb == retb)
1035 {
1036 res = s;
1037 }
1038 else
1039 {
1040 res = sRef_makeConj (reta, retb);
1041 }
1042
1043 return (res);
1044 }
1045 }
1046
1047 BADEXIT;
1048 }
1049
1050 uentry
sRef_getUentry(sRef s)1051 sRef_getUentry (sRef s)
1052 {
1053 llassert (sRef_isReasonable (s));
1054
1055 switch (s->kind)
1056 {
1057 case SK_PARAM:
1058 return (usymtab_getRefQuiet (paramsScope, usymId_fromInt (s->info->paramno)));
1059 case SK_CVAR:
1060 return (usymtab_getRefQuiet (s->info->cvar->lexlevel, s->info->cvar->index));
1061 case SK_CONJ:
1062 {
1063 if (sRef_isCvar (s->info->conj->a) || sRef_isParam (s->info->conj->a)
1064 || sRef_isConj (s->info->conj->a))
1065 {
1066 return sRef_getUentry (s->info->conj->a);
1067 }
1068 else
1069 {
1070 return sRef_getUentry (s->info->conj->b);
1071 }
1072 }
1073 case SK_FIELD: /* evans 2002-07-17: added case for SK_FIELD */
1074 case SK_UNKNOWN:
1075 case SK_SPECIAL:
1076 return uentry_undefined;
1077 BADDEFAULT;
1078 }
1079 }
1080
1081 int
sRef_getParam(sRef s)1082 sRef_getParam (sRef s)
1083 {
1084 llassert (sRef_isReasonable (s));
1085 llassert (s->kind == SK_PARAM);
1086
1087 return s->info->paramno;
1088 }
1089
1090 bool
sRef_isModified(sRef s)1091 sRef_isModified (sRef s)
1092 {
1093 return (!sRef_isReasonable (s) || s->modified);
1094 }
1095
sRef_setModified(sRef s)1096 void sRef_setModified (sRef s)
1097 {
1098 if (sRef_isReasonable (s))
1099 {
1100 s->modified = TRUE;
1101
1102
1103 if (sRef_isRefsField (s))
1104 {
1105 sRef base = sRef_getBase (s);
1106
1107 llassert (s->kind == SK_FIELD);
1108
1109 if (sRef_isPointer (base))
1110 {
1111 base = sRef_getBase (base);
1112 }
1113
1114 if (sRef_isRefCounted (base))
1115 {
1116 base->aliaskind = AK_NEWREF;
1117 }
1118 }
1119 }
1120 }
1121
1122 /*
1123 ** note: this side-effects sRefSet to set modified to TRUE
1124 ** for any sRef similar to s.
1125 */
1126
1127 bool
sRef_canModifyVal(sRef s,sRefSet sl)1128 sRef_canModifyVal (sRef s, sRefSet sl)
1129 {
1130 if (context_getFlag (FLG_MUSTMOD))
1131 {
1132 return (sRef_doModifyVal (s, sl));
1133 }
1134 else
1135 {
1136 return (sRef_checkModifyVal (s, sl));
1137 }
1138 }
1139
1140 bool
sRef_canModify(sRef s,sRefSet sl)1141 sRef_canModify (sRef s, sRefSet sl)
1142 {
1143 if (context_getFlag (FLG_MUSTMOD))
1144 {
1145 return (sRef_doModify (s, sl));
1146 }
1147 else
1148 {
1149 return (sRef_checkModify (s, sl));
1150 }
1151 }
1152
1153 /*
1154 ** No side-effects
1155 */
1156
1157 static
sRef_checkModifyVal(sRef s,sRefSet sl)1158 bool sRef_checkModifyVal (sRef s, sRefSet sl)
1159 {
1160 DPRINTF (("Check modify val: %s", sRef_unparse (s)));
1161
1162 if (sRef_isInvalid (s))
1163 {
1164 return TRUE;
1165 }
1166
1167 switch (s->kind)
1168 {
1169 case SK_UNCONSTRAINED:
1170 case SK_CONST:
1171 return TRUE;
1172 case SK_CVAR:
1173 DPRINTF (("Modify var: %s", sRef_unparse (s)));
1174
1175 if (sRef_isFileOrGlobalScope (s))
1176 {
1177 if (context_checkGlobMod (s))
1178 {
1179 return (sRefSet_member (sl, s));
1180 }
1181
1182 return TRUE;
1183 }
1184 else
1185 {
1186 return TRUE;
1187 }
1188 case SK_PARAM:
1189 return (sRefSet_member (sl, s)
1190 || alkind_isOnly (sRef_getOrigAliasKind (s)));
1191 case SK_ARRAYFETCH:
1192 /* special case if ind known */
1193 return (sRefSet_member (sl, s) ||
1194 sRef_checkModifyVal (s->info->arrayfetch->arr, sl));
1195 case SK_FIELD:
1196 return (sRefSet_member (sl, s) || sRef_checkModifyVal (s->info->field->rec, sl));
1197 case SK_PTR:
1198 return (sRefSet_member (sl, s) || sRef_checkModifyVal (s->info->ref, sl));
1199 case SK_ADR:
1200 return (sRefSet_member (sl, s) || sRef_checkModifyVal (s->info->ref, sl));
1201 case SK_CONJ:
1202 return ((sRef_checkModifyVal (s->info->conj->a, sl)) &&
1203 (sRef_checkModifyVal (s->info->conj->b, sl)));
1204 case SK_UNKNOWN:
1205 case SK_OBJECT:
1206 case SK_NEW:
1207 case SK_TYPE:
1208 case SK_DERIVED:
1209 return TRUE;
1210 case SK_EXTERNAL:
1211 return TRUE;
1212 case SK_SPECIAL:
1213 {
1214 switch (s->info->spec)
1215 {
1216 case SR_NOTHING: return TRUE;
1217 case SR_INTERNAL:
1218 if (context_getFlag (FLG_INTERNALGLOBS))
1219 {
1220 return (sRefSet_member (sl, s));
1221 }
1222 else
1223 {
1224 return TRUE;
1225 }
1226 case SR_SPECSTATE: return TRUE;
1227 case SR_SYSTEM: return (sRefSet_member (sl, s));
1228 case SR_GLOBALMARKER: BADBRANCH;
1229 }
1230 }
1231 case SK_RESULT: BADBRANCH;
1232 }
1233 BADEXIT;
1234 }
1235
1236 /*
1237 ** this should probably be elsewhere...
1238 **
1239 ** returns TRUE iff sl indicates that s can be modified
1240 */
1241
sRef_checkModify(sRef s,sRefSet sl)1242 static bool sRef_checkModify (sRef s, sRefSet sl)
1243 {
1244 llassert (sRef_isReasonable (s));
1245
1246 switch (s->kind)
1247 {
1248 case SK_UNCONSTRAINED:
1249 case SK_CONST:
1250 return TRUE;
1251 case SK_CVAR:
1252 if (sRef_isFileOrGlobalScope (s))
1253 {
1254 if (context_checkGlobMod (s))
1255 {
1256 return (sRefSet_member (sl, s));
1257 }
1258
1259 return TRUE;
1260 }
1261 else
1262 {
1263 return TRUE;
1264 }
1265 case SK_PARAM:
1266 return TRUE;
1267 case SK_ARRAYFETCH:
1268 return (sRefSet_member (sl, s) ||
1269 sRef_checkModifyVal (s->info->arrayfetch->arr, sl));
1270 case SK_FIELD:
1271 {
1272 sRef sr = s->info->field->rec;
1273
1274 if (sr->kind == SK_PARAM)
1275 return TRUE; /* structs are copied on call */
1276
1277 return (sRefSet_member (sl, s) || sRef_checkModifyVal (s->info->field->rec, sl));
1278 }
1279 case SK_PTR:
1280 {
1281 bool sm;
1282
1283 sm = sRefSet_member (sl, s);
1284
1285 if (sm)
1286 return TRUE;
1287 else
1288 return (sRef_checkModifyVal (s->info->ref, sl));
1289 }
1290 case SK_ADR:
1291 return (sRefSet_member (sl, s) || sRef_checkModifyVal (s->info->ref, sl));
1292 case SK_CONJ:
1293 return ((sRef_checkModify (s->info->conj->a, sl)) &&
1294 (sRef_checkModify (s->info->conj->b, sl)));
1295 case SK_NEW:
1296 case SK_OBJECT:
1297 case SK_UNKNOWN:
1298 case SK_TYPE:
1299 case SK_DERIVED:
1300 case SK_EXTERNAL:
1301 return TRUE;
1302 case SK_SPECIAL:
1303 {
1304 switch (s->info->spec)
1305 {
1306 case SR_NOTHING: return TRUE;
1307 case SR_INTERNAL:
1308 if (context_getFlag (FLG_INTERNALGLOBS))
1309 {
1310 return (sRefSet_member (sl, s));
1311 }
1312 else
1313 {
1314 return TRUE;
1315 }
1316 case SR_SPECSTATE: return TRUE;
1317 case SR_SYSTEM: return (sRefSet_member (sl, s));
1318 case SR_GLOBALMARKER: BADBRANCH;
1319 }
1320 }
1321 case SK_RESULT: BADBRANCH;
1322 }
1323 BADEXIT;
1324 }
1325
sRef_stateVerb(sRef s)1326 cstring sRef_stateVerb (sRef s)
1327 {
1328 if (sRef_isDead (s))
1329 {
1330 return cstring_makeLiteralTemp ("released");
1331 }
1332 else if (sRef_isKept (s))
1333 {
1334 return cstring_makeLiteralTemp ("kept");
1335 }
1336 else if (sRef_isDependent (s))
1337 {
1338 return cstring_makeLiteralTemp ("dependent");
1339 }
1340 else
1341 {
1342 BADEXIT;
1343 }
1344 }
1345
sRef_stateAltVerb(sRef s)1346 cstring sRef_stateAltVerb (sRef s)
1347 {
1348 if (sRef_isDead (s))
1349 {
1350 return cstring_makeLiteralTemp ("live");
1351 }
1352 else if (sRef_isKept (s))
1353 {
1354 return cstring_makeLiteralTemp ("not kept");
1355 }
1356 else if (sRef_isDependent (s))
1357 {
1358 return cstring_makeLiteralTemp ("independent");
1359 }
1360 else
1361 {
1362 BADEXIT;
1363 }
1364 }
1365
1366 static
sRef_doModifyVal(sRef s,sRefSet sl)1367 bool sRef_doModifyVal (sRef s, sRefSet sl)
1368 {
1369 llassert (sRef_isReasonable (s));
1370
1371
1372 switch (s->kind)
1373 {
1374 case SK_UNCONSTRAINED:
1375 case SK_CONST:
1376 return TRUE;
1377 case SK_CVAR:
1378 if (sRef_isFileOrGlobalScope (s))
1379 {
1380
1381 if (context_checkGlobMod (s))
1382 {
1383 return (sRefSet_modifyMember (sl, s));
1384 }
1385 else
1386 {
1387 (void) sRefSet_modifyMember (sl, s);
1388 }
1389
1390 return TRUE;
1391 }
1392 else
1393 {
1394 return TRUE;
1395 }
1396 case SK_PARAM:
1397 return (sRefSet_modifyMember (sl, s)
1398 || alkind_isOnly (sRef_getOrigAliasKind (s)));
1399 case SK_ARRAYFETCH:
1400 /* special case if ind known */
1401 /* unconditional OR, need side effect */
1402 return (OR (sRefSet_modifyMember (sl, s),
1403 sRef_doModifyVal (s->info->arrayfetch->arr, sl)));
1404 case SK_FIELD:
1405 return (OR (sRefSet_modifyMember (sl, s),
1406 sRef_doModifyVal (s->info->field->rec, sl)));
1407 case SK_PTR:
1408 return (OR (sRefSet_modifyMember (sl, s),
1409 sRef_doModifyVal (s->info->ref, sl)));
1410 case SK_ADR:
1411 return (OR (sRefSet_modifyMember (sl, s),
1412 sRef_doModifyVal (s->info->ref, sl)));
1413 case SK_CONJ:
1414 return (AND (sRef_doModifyVal (s->info->conj->a, sl) ,
1415 sRef_doModifyVal (s->info->conj->b, sl)));
1416 case SK_OBJECT:
1417 case SK_DERIVED:
1418 case SK_EXTERNAL:
1419 case SK_UNKNOWN:
1420 case SK_NEW:
1421 case SK_TYPE:
1422 return TRUE;
1423 case SK_SPECIAL:
1424 {
1425 switch (s->info->spec)
1426 {
1427 case SR_NOTHING: return TRUE;
1428 case SR_INTERNAL:
1429 if (context_getFlag (FLG_INTERNALGLOBS))
1430 {
1431 return (sRefSet_modifyMember (sl, s));
1432 }
1433 else
1434 {
1435 (void) sRefSet_modifyMember (sl, s);
1436 return TRUE;
1437 }
1438 case SR_SPECSTATE: return TRUE;
1439 case SR_SYSTEM: return (sRefSet_modifyMember (sl, s));
1440 case SR_GLOBALMARKER: BADBRANCH;
1441
1442 }
1443 }
1444 case SK_RESULT: BADBRANCH;
1445 }
1446 BADEXIT;
1447 }
1448
1449 /*
1450 ** this should probably be elsewhere...
1451 **
1452 ** returns TRUE iff sl indicates that s can be modified
1453 */
1454
1455 static
sRef_doModify(sRef s,sRefSet sl)1456 bool sRef_doModify (sRef s, sRefSet sl)
1457 {
1458 llassert (sRef_isReasonable (s));
1459
1460 switch (s->kind)
1461 {
1462 case SK_UNCONSTRAINED:
1463 case SK_CONST:
1464 return TRUE;
1465 case SK_CVAR:
1466 if (sRef_isFileOrGlobalScope (s))
1467 {
1468 if (context_checkGlobMod (s))
1469 {
1470 return (sRefSet_modifyMember (sl, s));
1471 }
1472 else
1473 {
1474 (void) sRefSet_modifyMember (sl, s);
1475 }
1476
1477 return TRUE;
1478 }
1479 else
1480 {
1481 return TRUE;
1482 }
1483 case SK_PARAM:
1484 return TRUE;
1485 case SK_ARRAYFETCH:
1486 return (OR (sRefSet_modifyMember (sl, s),
1487 sRef_doModifyVal (s->info->arrayfetch->arr, sl)));
1488 case SK_FIELD:
1489 {
1490 sRef sr = s->info->field->rec;
1491
1492 if (sr->kind == SK_PARAM)
1493 {
1494 return TRUE; /* structs are shallow-copied on call */
1495 }
1496
1497 return (OR (sRefSet_modifyMember (sl, s),
1498 sRef_doModifyVal (s->info->field->rec, sl)));
1499 }
1500 case SK_PTR:
1501 {
1502 return (OR (sRefSet_modifyMember (sl, s),
1503 sRef_doModifyVal (s->info->ref, sl)));
1504 }
1505 case SK_ADR:
1506 return (OR (sRefSet_modifyMember (sl, s),
1507 sRef_doModifyVal (s->info->ref, sl)));
1508 case SK_CONJ:
1509 return (AND (sRef_doModify (s->info->conj->a, sl),
1510 (sRef_doModify (s->info->conj->b, sl))));
1511 case SK_UNKNOWN:
1512 case SK_NEW:
1513 case SK_TYPE:
1514 return TRUE;
1515 case SK_OBJECT:
1516 case SK_DERIVED:
1517 case SK_EXTERNAL:
1518 return TRUE;
1519 case SK_SPECIAL:
1520 {
1521 switch (s->info->spec)
1522 {
1523 case SR_NOTHING: return TRUE;
1524 case SR_INTERNAL: return TRUE;
1525 case SR_SPECSTATE: return TRUE;
1526 case SR_SYSTEM: return (sRefSet_modifyMember (sl, s));
1527 case SR_GLOBALMARKER: BADBRANCH;
1528 }
1529 }
1530 case SK_RESULT: BADBRANCH;
1531 }
1532 BADEXIT;
1533 }
1534
1535 static /*@exposed@*/ sRef
sRef_leastCommon(sRef s1,sRef s2)1536 sRef_leastCommon (/*@exposed@*/ sRef s1, sRef s2)
1537 {
1538 llassert (sRef_similar (s1, s2));
1539
1540 if (!sRef_isReasonable (s1)) return s1;
1541 if (!sRef_isReasonable (s2)) return s1;
1542
1543 sRef_combineDefState (s1, s2);
1544 sRef_combineNullState (s1, s2);
1545 sRef_combineExKinds (s1, s2);
1546
1547 if (s1->aliaskind != s2->aliaskind)
1548 {
1549 if (s1->aliaskind == AK_UNKNOWN)
1550 {
1551 s1->aliaskind = s2->aliaskind;
1552 }
1553 else if (s2->aliaskind == AK_UNKNOWN)
1554 {
1555 ;
1556 }
1557 else
1558 {
1559 s1->aliaskind = AK_ERROR;
1560 }
1561 }
1562
1563 return s1;
1564 }
1565
sRef_compare(sRef s1,sRef s2)1566 int sRef_compare (sRef s1, sRef s2)
1567 {
1568 if (s1 == s2) return 0;
1569
1570 if (sRef_isInvalid (s1)) return -1;
1571 if (sRef_isInvalid (s2)) return 1;
1572
1573 INTCOMPARERETURN (s1->kind, s2->kind);
1574 INTCOMPARERETURN (s1->defstate, s2->defstate);
1575 INTCOMPARERETURN (s1->aliaskind, s2->aliaskind);
1576
1577 DPRINTF (("Compare null state: %s / %s",
1578 sRef_unparseFull (s1),
1579 sRef_unparseFull (s2)));
1580
1581 COMPARERETURN (nstate_compare (sRef_getNullState (s1),
1582 sRef_getNullState (s2)));
1583
1584 switch (s1->kind)
1585 {
1586 case SK_PARAM:
1587 return (int_compare (s1->info->paramno, s2->info->paramno));
1588 case SK_ARRAYFETCH:
1589 {
1590 COMPARERETURN (sRef_compare (s1->info->arrayfetch->arr,
1591 s2->info->arrayfetch->arr));
1592
1593 if (s1->info->arrayfetch->indknown && s2->info->arrayfetch->indknown)
1594 {
1595 return (int_compare (s1->info->arrayfetch->ind,
1596 s2->info->arrayfetch->ind));
1597 }
1598 if (!s1->info->arrayfetch->indknown && !s2->info->arrayfetch->indknown)
1599 return 0;
1600
1601 return 1;
1602 }
1603 case SK_FIELD:
1604 {
1605 COMPARERETURN (sRef_compare (s1->info->field->rec, s2->info->field->rec));
1606
1607 if (cstring_equal (s1->info->field->field, s2->info->field->field))
1608 return 0;
1609
1610 return 1;
1611 }
1612 case SK_PTR:
1613 case SK_ADR:
1614 return (sRef_compare (s1->info->ref, s2->info->ref));
1615 case SK_CONJ:
1616 COMPARERETURN (sRef_compare (s1->info->conj->a, s2->info->conj->a));
1617 return (sRef_compare (s1->info->conj->b, s2->info->conj->b));
1618 case SK_UNCONSTRAINED:
1619 return (cstring_compare (s1->info->fname, s2->info->fname));
1620 case SK_NEW:
1621 case SK_CVAR:
1622 case SK_UNKNOWN:
1623 case SK_OBJECT:
1624 case SK_TYPE:
1625 case SK_DERIVED:
1626 case SK_EXTERNAL:
1627 case SK_CONST:
1628 case SK_RESULT:
1629 return 0;
1630 case SK_SPECIAL:
1631 return (generic_compare (s1->info->spec, s2->info->spec));
1632 }
1633 BADEXIT;
1634 }
1635
cref_equal(cref c1,cref c2)1636 static bool cref_equal (cref c1, cref c2)
1637 {
1638 return ((c1->lexlevel == c2->lexlevel) &&
1639 (usymId_equal (c1->index, c2->index)));
1640 }
1641
1642 /*
1643 ** returns true if s1 could be the same storage as s2.
1644 ** i.e., a[?] ~ a[3]. Note its not symmetric ... s1
1645 ** should be more specific.
1646 */
1647
1648 /*
1649 ** like similar, but matches objects <-> non-objects
1650 */
1651
1652 static bool
sRef_uniqueReference(sRef s)1653 sRef_uniqueReference (sRef s)
1654 {
1655 return (sRef_isFresh (s) || sRef_isUnique (s)
1656 || sRef_isOnly (s) || sRef_isStack (s)
1657 || sRef_isAddress (s));
1658 }
1659
1660 static bool
sRef_similarRelaxedAux(sRef s1,sRef s2)1661 sRef_similarRelaxedAux (sRef s1, sRef s2)
1662 {
1663 if (s1 == s2)
1664 {
1665 if (sRef_isUnknownArrayFetch (s1))
1666 {
1667 return FALSE;
1668 }
1669 else
1670 {
1671 return TRUE;
1672 }
1673 }
1674
1675 if (sRef_isInvalid (s1) || sRef_isInvalid (s2)) return FALSE;
1676
1677 if (sRef_isConj (s2))
1678 return (sRef_similarRelaxedAux (s1, sRef_getConjA (s2)) ||
1679 sRef_similarRelaxedAux (s1, sRef_getConjB (s2)));
1680
1681 switch (s1->kind)
1682 {
1683 case SK_CVAR:
1684 return ((s2->kind == SK_CVAR)
1685 && (cref_equal (s1->info->cvar, s2->info->cvar)));
1686 case SK_PARAM:
1687 return ((s2->kind == SK_PARAM)
1688 && (s1->info->paramno == s2->info->paramno));
1689 case SK_ARRAYFETCH:
1690 if (s2->kind == SK_ARRAYFETCH)
1691 {
1692 if (sRef_similarRelaxedAux (s1->info->arrayfetch->arr,
1693 s2->info->arrayfetch->arr))
1694 {
1695 if (s1->info->arrayfetch->indknown)
1696 {
1697 if (s2->info->arrayfetch->indknown)
1698 {
1699 return (s1->info->arrayfetch->ind == s2->info->arrayfetch->ind);
1700 }
1701 else
1702 {
1703 return FALSE;
1704 }
1705 }
1706 else
1707 {
1708 return FALSE;
1709 }
1710 }
1711 }
1712 return FALSE;
1713 case SK_FIELD:
1714 return ((s2->kind == SK_FIELD
1715 && (sRef_similarRelaxedAux (s1->info->field->rec,
1716 s2->info->field->rec)
1717 && cstring_equal (s1->info->field->field,
1718 s2->info->field->field))));
1719 case SK_PTR:
1720 return ((s2->kind == SK_PTR)
1721 && sRef_similarRelaxedAux (s1->info->ref, s2->info->ref));
1722 case SK_ADR:
1723 return ((s2->kind == SK_ADR)
1724 && sRef_similarRelaxedAux (s1->info->ref, s2->info->ref));
1725 case SK_CONJ:
1726 return ((sRef_similarRelaxedAux (s1->info->conj->a, s2) ||
1727 (sRef_similarRelaxedAux (s1->info->conj->b, s2))));
1728 case SK_SPECIAL:
1729 return (s1->info->spec == s2->info->spec);
1730 case SK_UNCONSTRAINED:
1731 return (cstring_equal (s1->info->fname, s2->info->fname));
1732 case SK_DERIVED:
1733 case SK_CONST:
1734 case SK_TYPE:
1735 case SK_NEW:
1736 case SK_UNKNOWN:
1737 case SK_OBJECT:
1738 case SK_EXTERNAL:
1739 case SK_RESULT:
1740 return FALSE;
1741 }
1742 BADEXIT;
1743 }
1744
1745 bool
sRef_similarRelaxed(sRef s1,sRef s2)1746 sRef_similarRelaxed (sRef s1, sRef s2)
1747 {
1748 bool us1, us2;
1749
1750 if (s1 == s2)
1751 {
1752 if (sRef_isThroughArrayFetch (s1))
1753 {
1754 return FALSE;
1755 }
1756 else
1757 {
1758 return TRUE;
1759 }
1760 }
1761
1762 if (sRef_isInvalid (s1) || sRef_isInvalid (s2)) return FALSE;
1763
1764 us1 = sRef_uniqueReference (s1);
1765 us2 = sRef_uniqueReference (s2);
1766
1767 if ((s1->kind == SK_EXTERNAL && (s2->kind != SK_EXTERNAL && !us2))
1768 || (s2->kind == SK_EXTERNAL && (s1->kind != SK_EXTERNAL && !us1)))
1769 {
1770 /*
1771 ** Previously, also:
1772 ** || (sRef_isExposed (s1) && !us2) || (sRef_isExposed (s2) && !us1)) ????
1773 **
1774 ** No clue why this was there?!
1775 */
1776
1777
1778 if (sRef_isExposed (s1) && sRef_isCvar (s1))
1779 {
1780 uentry ue1 = sRef_getUentry (s1);
1781
1782 if (uentry_isRefParam (ue1))
1783 {
1784 return sRef_similarRelaxedAux (s1, s2);
1785 }
1786 }
1787
1788 if (sRef_isExposed (s2) && sRef_isCvar (s2))
1789 {
1790 uentry ue2 = sRef_getUentry (s2);
1791
1792 if (uentry_isRefParam (ue2))
1793 {
1794 return sRef_similarRelaxedAux (s1, s2);
1795 }
1796 }
1797
1798 return (ctype_match (s1->type, s2->type));
1799 }
1800 else
1801 {
1802 return sRef_similarRelaxedAux (s1, s2);
1803 }
1804 }
1805
1806 bool
sRef_similar(sRef s1,sRef s2)1807 sRef_similar (sRef s1, sRef s2)
1808 {
1809 if (s1 == s2) return TRUE;
1810 if (sRef_isInvalid (s1) || sRef_isInvalid (s2)) return FALSE;
1811
1812 if (sRef_isConj (s2))
1813 {
1814 return (sRef_similar (s1, sRef_getConjA (s2)) ||
1815 sRef_similar (s1, sRef_getConjB (s2)));
1816 }
1817
1818 if (sRef_isDerived (s2))
1819 {
1820 return (sRef_includedBy (s1, s2->info->ref));
1821 }
1822
1823 switch (s1->kind)
1824 {
1825 case SK_CVAR:
1826 return ((s2->kind == SK_CVAR)
1827 && (cref_equal (s1->info->cvar, s2->info->cvar)));
1828 case SK_PARAM:
1829 return ((s2->kind == SK_PARAM)
1830 && (s1->info->paramno == s2->info->paramno));
1831 case SK_ARRAYFETCH:
1832 if (s2->kind == SK_ARRAYFETCH)
1833 {
1834 if (sRef_similar (s1->info->arrayfetch->arr,
1835 s2->info->arrayfetch->arr))
1836 {
1837 if (s1->info->arrayfetch->indknown)
1838 {
1839 if (s2->info->arrayfetch->indknown)
1840 {
1841 return (s1->info->arrayfetch->ind == s2->info->arrayfetch->ind);
1842 }
1843 else
1844 {
1845 return TRUE;
1846 }
1847 }
1848 else
1849 {
1850 return TRUE;
1851 }
1852 }
1853 }
1854 else
1855 {
1856 if (s2->kind == SK_PTR)
1857 {
1858 if (sRef_similar (s1->info->arrayfetch->arr,
1859 s2->info->ref))
1860 {
1861 return TRUE;
1862 }
1863 }
1864 }
1865
1866 return FALSE;
1867 case SK_FIELD:
1868 return ((s2->kind == SK_FIELD
1869 && (sRef_similar (s1->info->field->rec,
1870 s2->info->field->rec)
1871 && cstring_equal (s1->info->field->field,
1872 s2->info->field->field))));
1873 case SK_PTR:
1874 if (s2->kind == SK_PTR)
1875 {
1876 return sRef_similar (s1->info->ref, s2->info->ref);
1877 }
1878 else
1879 {
1880 if (s2->kind == SK_ARRAYFETCH)
1881 {
1882 if (sRef_similar (s2->info->arrayfetch->arr,
1883 s1->info->ref))
1884 {
1885 return TRUE;
1886 }
1887 }
1888 }
1889
1890 return FALSE;
1891 case SK_ADR:
1892 return ((s2->kind == SK_ADR)
1893 && sRef_similar (s1->info->ref, s2->info->ref));
1894 case SK_CONJ:
1895 return ((sRef_similar (s1->info->conj->a, s2) ||
1896 (sRef_similar (s1->info->conj->b, s2))));
1897 case SK_DERIVED:
1898 return (sRef_includedBy (s2, s1->info->ref));
1899 case SK_UNCONSTRAINED:
1900 return (s2->kind == SK_UNCONSTRAINED
1901 && cstring_equal (s1->info->fname, s2->info->fname));
1902 case SK_CONST:
1903 case SK_TYPE:
1904 case SK_NEW:
1905 case SK_UNKNOWN:
1906 case SK_OBJECT:
1907 case SK_EXTERNAL:
1908 case SK_RESULT:
1909 return FALSE;
1910 case SK_SPECIAL:
1911 return (s2->kind == SK_SPECIAL
1912 && (s1->info->spec == s2->info->spec));
1913 }
1914
1915 /*@notreached@*/ DPRINTF (("Fell through for: %s / %s", sRef_unparse (s1), sRef_unparse (s2)));
1916 BADEXIT;
1917 }
1918
1919 /*
1920 ** return TRUE iff small can be derived from big.
1921 **
1922 ** (e.g. x, x.a is includedBy x;
1923 ** x.a is included By x.a;
1924 */
1925
1926 bool
sRef_includedBy(sRef small,sRef big)1927 sRef_includedBy (sRef small, sRef big)
1928 {
1929 if (small == big) return TRUE;
1930 if (sRef_isInvalid (small) || sRef_isInvalid (big)) return FALSE;
1931
1932 if (sRef_isConj (big))
1933 return (sRef_similar (small, sRef_getConjA (big)) ||
1934 sRef_similar (small, sRef_getConjB (big)));
1935
1936 switch (small->kind)
1937 {
1938 case SK_CVAR:
1939 case SK_PARAM:
1940 return (sRef_same (small, big));
1941 case SK_ARRAYFETCH:
1942 if (big->kind == SK_ARRAYFETCH)
1943 {
1944 if (sRef_same (small->info->arrayfetch->arr, big->info->arrayfetch->arr))
1945 {
1946 if (small->info->arrayfetch->indknown)
1947 {
1948 if (big->info->arrayfetch->indknown)
1949 {
1950 return (small->info->arrayfetch->ind == big->info->arrayfetch->ind);
1951 }
1952 else
1953 {
1954 return TRUE;
1955 }
1956 }
1957 else
1958 {
1959 return TRUE;
1960 }
1961 }
1962 }
1963 return (sRef_includedBy (small->info->arrayfetch->arr, big));
1964 case SK_FIELD:
1965 if (big->kind == SK_FIELD)
1966 {
1967 return
1968 (sRef_same (small->info->field->rec, big->info->field->rec) &&
1969 cstring_equal (small->info->field->field, big->info->field->field));
1970 }
1971 else
1972 {
1973 return (sRef_includedBy (small->info->field->rec, big));
1974 }
1975
1976 case SK_PTR:
1977 if (big->kind == SK_PTR)
1978 {
1979 return sRef_same (small->info->ref, big->info->ref);
1980 }
1981 else
1982 {
1983 return (sRef_includedBy (small->info->ref, big));
1984 }
1985
1986 case SK_ADR:
1987 return ((big->kind == SK_ADR) && sRef_similar (small->info->ref, big->info->ref));
1988 case SK_CONJ:
1989 return ((sRef_includedBy (small->info->conj->a, big) ||
1990 (sRef_includedBy (small->info->conj->b, big))));
1991 case SK_DERIVED:
1992 return (sRef_includedBy (small->info->ref, big));
1993 case SK_UNCONSTRAINED:
1994 case SK_CONST:
1995 case SK_TYPE:
1996 case SK_NEW:
1997 case SK_UNKNOWN:
1998 case SK_OBJECT:
1999 case SK_EXTERNAL:
2000 case SK_RESULT:
2001 return FALSE;
2002 case SK_SPECIAL:
2003 switch (small->info->spec)
2004 {
2005 case SR_NOTHING: return TRUE;
2006 case SR_SPECSTATE:
2007 case SR_INTERNAL: return (sRef_isSpecInternalState (big) ||
2008 sRef_isFileStatic (big));
2009 case SR_SYSTEM: return (sRef_isSystemState (big));
2010 case SR_GLOBALMARKER: BADBRANCH;
2011 }
2012 }
2013 BADEXIT;
2014 }
2015
2016 /*
2017 ** Same is similar to similar, but not quite the same.
2018 ** same and realSame aren't the same, but they are really similar.
2019 ** similarly, same is the same as same. but realSame is
2020 ** not really the same as same, or similar to similar.
2021 **
2022 ** Similarly to similar, same checks if two sRefs are the same.
2023 ** The similarities end, however, when same compares arrays
2024 ** with unknown indexes. Similar returns false; same returns true.
2025 **
2026 ** Similarly to similar and same, realSame is the same as same,
2027 ** except they do not behave the same when face with unknown
2028 ** sRefs. Same thinks they are not the same, but realSame thinks
2029 ** the are.
2030 **
2031 */
2032
2033 bool
sRef_realSame(sRef s1,sRef s2)2034 sRef_realSame (sRef s1, sRef s2)
2035 {
2036 if (s1 == s2) return TRUE;
2037
2038 if (sRef_isUnreasonable (s1)
2039 || sRef_isUnreasonable (s2))
2040 {
2041 return FALSE;
2042 }
2043
2044 switch (s1->kind)
2045 {
2046 case SK_CVAR:
2047 return ((s2->kind == SK_CVAR) && (cref_equal (s1->info->cvar, s2->info->cvar)));
2048 case SK_PARAM:
2049 return ((s2->kind == SK_PARAM) && (s1->info->paramno == s2->info->paramno));
2050 case SK_ARRAYFETCH:
2051 if (s2->kind == SK_ARRAYFETCH)
2052 {
2053 if (sRef_realSame (s1->info->arrayfetch->arr, s2->info->arrayfetch->arr))
2054 {
2055 if (s1->info->arrayfetch->indknown && s2->info->arrayfetch->indknown)
2056 {
2057 return (s1->info->arrayfetch->ind == s2->info->arrayfetch->ind);
2058 }
2059 if (!s1->info->arrayfetch->indknown && !s2->info->arrayfetch->indknown)
2060 {
2061 return TRUE;
2062 }
2063 return FALSE;
2064 }
2065 }
2066 return FALSE;
2067 case SK_FIELD:
2068 return ((s2->kind == SK_FIELD &&
2069 (sRef_realSame (s1->info->field->rec, s2->info->field->rec) &&
2070 cstring_equal (s1->info->field->field, s2->info->field->field))));
2071 case SK_PTR:
2072 return ((s2->kind == SK_PTR) && sRef_realSame (s1->info->ref, s2->info->ref));
2073 case SK_ADR:
2074 return ((s2->kind == SK_ADR) && sRef_realSame (s1->info->ref, s2->info->ref));
2075 case SK_CONJ:
2076 return ((sRef_realSame (s1->info->conj->a, s2) ||
2077 (sRef_realSame (s1->info->conj->b, s2))));
2078 case SK_OBJECT:
2079 return ((s2->kind == SK_OBJECT)
2080 && ctype_match (s1->info->object, s2->info->object));
2081 case SK_EXTERNAL:
2082 return ((s2->kind == SK_EXTERNAL)
2083 && sRef_realSame (s1->info->ref, s2->info->ref));
2084 case SK_SPECIAL:
2085 return ((s2->kind == SK_SPECIAL) && s1->info->spec == s2->info->spec);
2086 case SK_DERIVED:
2087 return ((s2->kind == SK_DERIVED) && sRef_realSame (s1->info->ref, s2->info->ref));
2088 case SK_UNCONSTRAINED:
2089 return ((s2->kind == SK_UNCONSTRAINED)
2090 && (cstring_equal (s1->info->fname, s2->info->fname)));
2091 case SK_TYPE:
2092 case SK_CONST:
2093 case SK_NEW:
2094 case SK_UNKNOWN:
2095 case SK_RESULT:
2096 return TRUE; /* changed this! was false */
2097 }
2098 BADEXIT;
2099 }
2100
2101 bool
sRef_sameObject(sRef s1,sRef s2)2102 sRef_sameObject (sRef s1, sRef s2)
2103 {
2104 return (s1 == s2);
2105 }
2106
2107 /*
2108 ** same is similar to similar, but not quite the same.
2109 **
2110 ** Similarly to similar, same checks is two sRefs are the same.
2111 ** The similarities end, however, when same compares arrays
2112 ** with unknown indexes. Similar returns false; same returns true.
2113 */
2114
2115 bool
sRef_same(sRef s1,sRef s2)2116 sRef_same (sRef s1, sRef s2)
2117 {
2118 if (s1 == s2) return TRUE;
2119 if (sRef_isInvalid (s1) || sRef_isInvalid (s2)) return FALSE;
2120
2121 switch (s1->kind)
2122 {
2123 case SK_CVAR:
2124 return ((s2->kind == SK_CVAR) && (cref_equal (s1->info->cvar, s2->info->cvar)));
2125 case SK_PARAM:
2126 return ((s2->kind == SK_PARAM) && (s1->info->paramno == s2->info->paramno));
2127 case SK_ARRAYFETCH:
2128 if (s2->kind == SK_ARRAYFETCH)
2129 {
2130 llassert (s1->info->field->rec != s1);
2131 if (sRef_same (s1->info->arrayfetch->arr, s2->info->arrayfetch->arr))
2132 {
2133 if (s1->info->arrayfetch->indknown && s2->info->arrayfetch->indknown)
2134 {
2135 return (s1->info->arrayfetch->ind == s2->info->arrayfetch->ind);
2136 }
2137 return TRUE;
2138 }
2139 }
2140 return FALSE;
2141 case SK_FIELD:
2142 {
2143 llassert (s1->info->field->rec != s1);
2144 return ((s2->kind == SK_FIELD &&
2145 (sRef_same (s1->info->field->rec, s2->info->field->rec) &&
2146 cstring_equal (s1->info->field->field, s2->info->field->field))));
2147 }
2148 case SK_PTR:
2149 {
2150 llassert (s1->info->ref != s1);
2151 return ((s2->kind == SK_PTR) && sRef_same (s1->info->ref, s2->info->ref));
2152 }
2153 case SK_ADR:
2154 {
2155 llassert (s1->info->ref != s1);
2156 return ((s2->kind == SK_ADR) && sRef_same (s1->info->ref, s2->info->ref));
2157 }
2158 case SK_CONJ:
2159 llassert (s1->info->conj->a != s1);
2160 llassert (s1->info->conj->b != s1);
2161 return ((sRef_same (s1->info->conj->a, s2)) && /* or or and? */
2162 (sRef_same (s1->info->conj->b, s2)));
2163 case SK_SPECIAL:
2164 return ((s2->kind == SK_SPECIAL) && s1->info->spec == s2->info->spec);
2165 case SK_DERIVED:
2166 llassert (s1->info->ref != s1);
2167 return ((s2->kind == SK_DERIVED) && sRef_same (s1->info->ref, s2->info->ref));
2168 case SK_CONST:
2169 case SK_UNCONSTRAINED:
2170 case SK_TYPE:
2171 case SK_UNKNOWN:
2172 case SK_NEW:
2173 case SK_OBJECT:
2174 case SK_EXTERNAL:
2175 case SK_RESULT:
2176 return FALSE;
2177 }
2178 BADEXIT;
2179 }
2180
2181 /*
2182 ** sort of similar, for use in def/use
2183 */
2184
2185 static bool
sRef_closeEnough(sRef s1,sRef s2)2186 sRef_closeEnough (sRef s1, sRef s2)
2187 {
2188 if (s1 == s2) return TRUE;
2189 if (sRef_isInvalid (s1) || sRef_isInvalid (s2)) return FALSE;
2190
2191 switch (s1->kind)
2192 {
2193 case SK_CVAR:
2194 return (((s2->kind == SK_CVAR) &&
2195 (cref_equal (s1->info->cvar, s2->info->cvar))) ||
2196 (s2->kind == SK_UNCONSTRAINED && s1->info->cvar->lexlevel == 0));
2197 case SK_UNCONSTRAINED:
2198 return (s2->kind == SK_UNCONSTRAINED
2199 || ((s2->kind == SK_CVAR) && (s2->info->cvar->lexlevel == 0)));
2200 case SK_PARAM:
2201 return ((s2->kind == SK_PARAM)
2202 && (s1->info->paramno == s2->info->paramno));
2203 case SK_ARRAYFETCH:
2204 if (s2->kind == SK_ARRAYFETCH)
2205 {
2206 if (sRef_closeEnough (s1->info->arrayfetch->arr, s2->info->arrayfetch->arr))
2207 {
2208 if (s1->info->arrayfetch->indknown && s2->info->arrayfetch->indknown)
2209 {
2210 return (s1->info->arrayfetch->ind == s2->info->arrayfetch->ind);
2211 }
2212 return TRUE;
2213 }
2214 }
2215 return FALSE;
2216 case SK_FIELD:
2217 return ((s2->kind == SK_FIELD &&
2218 (sRef_closeEnough (s1->info->field->rec, s2->info->field->rec) &&
2219 cstring_equal (s1->info->field->field, s2->info->field->field))));
2220 case SK_PTR:
2221 return ((s2->kind == SK_PTR) && sRef_closeEnough (s1->info->ref, s2->info->ref));
2222 case SK_ADR:
2223 return ((s2->kind == SK_ADR) && sRef_closeEnough (s1->info->ref, s2->info->ref));
2224 case SK_DERIVED:
2225 return ((s2->kind == SK_DERIVED) && sRef_closeEnough (s1->info->ref, s2->info->ref));
2226 case SK_CONJ:
2227 return ((sRef_closeEnough (s1->info->conj->a, s2)) ||
2228 (sRef_closeEnough (s1->info->conj->b, s2)));
2229 case SK_SPECIAL:
2230 return ((s2->kind == SK_SPECIAL) && s1->info->spec == s2->info->spec);
2231 case SK_TYPE:
2232 case SK_CONST:
2233 case SK_UNKNOWN:
2234 case SK_NEW:
2235 case SK_OBJECT:
2236 case SK_EXTERNAL:
2237 case SK_RESULT:
2238
2239 return FALSE;
2240 }
2241 BADEXIT;
2242 }
2243
2244 /*
2245 drl add 12/24/2000
2246 s is an sRef of a formal paramenter in a function call constraint
2247 we trys to return a constraint expression derived from the actual parementer of a function call.
2248 */
2249
sRef_fixConstraintParam(sRef s,exprNodeList args)2250 /*@only@*/ constraintExpr sRef_fixConstraintParam (/*@observer@*/ sRef s, /*@observer@*/ /*@temp@*/ exprNodeList args)
2251 {
2252 constraintExpr ce;
2253
2254 if (sRef_isInvalid (s))
2255 llfatalbug((message("Invalid sRef")));
2256
2257 switch (s->kind)
2258 {
2259 case SK_RESULT:
2260 {
2261 ce = constraintExpr_makeTermsRef (s);
2262 return ce;
2263 }
2264 case SK_FIELD:
2265 {
2266 sRef temp;
2267
2268 temp = (sRef_makeField (sRef_fixBaseParam (s->info->field->rec, args),
2269 s->info->field->field));
2270 ce = constraintExpr_makeTermsRef (temp);
2271 return ce;
2272 }
2273 case SK_PTR:
2274 {
2275 sRef temp;
2276 temp = (sRef_makePointer (sRef_fixBaseParam (s->info->ref, args)));
2277 ce = constraintExpr_makeTermsRef (temp);
2278 return ce;
2279 }
2280
2281 case SK_ARRAYFETCH:
2282 {
2283 sRef temp;
2284 temp = sRef_saveCopy(s);
2285 temp = sRef_fixBaseParam (temp, args);
2286 ce = constraintExpr_makeTermsRef (temp);
2287
2288 sRef_free(temp);
2289 return ce;
2290 }
2291 case SK_CVAR:
2292 {
2293 sRef temp;
2294 temp = sRef_saveCopy(s);
2295 ce = constraintExpr_makeTermsRef (temp);
2296 sRef_free(temp);
2297 return ce;
2298 }
2299 case SK_PARAM:
2300 {
2301 exprNode e;
2302 llassert (exprNodeList_size (args) > s->info->paramno);
2303 e = exprNodeList_nth (args, s->info->paramno);
2304
2305 llassert (!(exprNode_isError (e)));
2306 ce = constraintExpr_makeExprNode (e);
2307 return ce;
2308 }
2309
2310 default:
2311 {
2312 sRef temp;
2313 llcontbug (message ("Trying to do fixConstraintParam on nonparam, nonglobal: %q for function with arguments %q",
2314 sRef_unparse (s), exprNodeList_unparse(args)));
2315 temp = sRef_saveCopy(s);
2316 ce = constraintExpr_makeTermsRef (temp);
2317
2318 sRef_free(temp);
2319 return ce;
2320 }
2321 }
2322 }
2323
2324 /*@exposed@*/ sRef
sRef_fixBaseParam(sRef s,exprNodeList args)2325 sRef_fixBaseParam (/*@returned@*/ sRef s, exprNodeList args)
2326 {
2327 if (sRef_isInvalid (s)) return (sRef_undefined);
2328
2329 switch (s->kind)
2330 {
2331 case SK_UNCONSTRAINED:
2332 case SK_CVAR:
2333 return s;
2334 case SK_PARAM:
2335 {
2336 if (exprNodeList_size (args) > s->info->paramno)
2337 {
2338 exprNode e = exprNodeList_nth (args, s->info->paramno);
2339
2340 if (exprNode_isError (e))
2341 {
2342 return sRef_makeUnknown ();
2343 }
2344
2345 return (exprNode_getSref (e));
2346 }
2347 else
2348 {
2349 return sRef_makeUnknown ();
2350 }
2351 }
2352 case SK_ARRAYFETCH:
2353
2354 if (s->info->arrayfetch->indknown)
2355 {
2356 return (sRef_makeArrayFetchKnown
2357 (sRef_fixBaseParam (s->info->arrayfetch->arr, args),
2358 s->info->arrayfetch->ind));
2359 }
2360 else
2361 {
2362 return (sRef_makeArrayFetch
2363 (sRef_fixBaseParam (s->info->arrayfetch->arr, args)));
2364 }
2365 case SK_FIELD:
2366 {
2367 sRef res;
2368 DPRINTF (("Fix field: %s", sRef_unparseFull (s)));
2369 res = sRef_makeField (sRef_fixBaseParam (s->info->field->rec, args),
2370 s->info->field->field);
2371 DPRINTF (("Returns: %s", sRef_unparseFull (res)));
2372 return res;
2373 }
2374 case SK_PTR:
2375 return (sRef_makePointer (sRef_fixBaseParam (s->info->ref, args)));
2376
2377 case SK_ADR:
2378 return (sRef_makeAddress (sRef_fixBaseParam (s->info->ref, args)));
2379
2380 case SK_CONJ:
2381 return (sRef_makeConj (sRef_fixBaseParam (s->info->conj->a, args),
2382 sRef_fixBaseParam (s->info->conj->b, args)));
2383 case SK_DERIVED:
2384 case SK_SPECIAL:
2385 case SK_TYPE:
2386 case SK_CONST:
2387 case SK_NEW:
2388 case SK_UNKNOWN:
2389 case SK_OBJECT:
2390 case SK_EXTERNAL:
2391 case SK_RESULT:
2392 return s;
2393 }
2394 BADEXIT;
2395 }
2396
2397 /*@exposed@*/ sRef
sRef_undumpGlobal(char ** c)2398 sRef_undumpGlobal (char **c)
2399 {
2400 char p = **c;
2401
2402 (*c)++;
2403
2404 switch (p)
2405 {
2406 case 'g':
2407 {
2408 usymId uid = usymId_fromInt (reader_getInt (c));
2409 sstate defstate;
2410 nstate nullstate;
2411 sRef ret;
2412
2413 reader_checkChar (c, '@');
2414 defstate = sstate_fromInt (reader_getInt (c));
2415
2416 reader_checkChar (c, '@');
2417 nullstate = nstate_fromInt (reader_getInt (c));
2418
2419 ret = sRef_makeGlobal (uid, ctype_unknown, stateInfo_currentLoc ());
2420 sRef_setNullStateN (ret, nullstate);
2421 ret->defstate = defstate;
2422 return ret;
2423 }
2424 case 's':
2425 {
2426 int i = reader_getInt (c);
2427 speckind sk = speckind_fromInt (i);
2428
2429 switch (sk)
2430 {
2431 case SR_NOTHING: return (sRef_makeNothing ());
2432 case SR_INTERNAL: return (sRef_makeInternalState ());
2433 case SR_SPECSTATE: return (sRef_makeSpecState ());
2434 case SR_SYSTEM: return (sRef_makeSystemState ());
2435 case SR_GLOBALMARKER: BADBRANCH;
2436 }
2437 BADEXIT;
2438 }
2439 case '-':
2440 return sRef_undefined;
2441 case 'u':
2442 return sRef_makeUnknown ();
2443 case 'x':
2444 return sRef_makeUnknown ();
2445 default:
2446 llfatalerror (message ("sRef_undumpGlobal: bad line: %s",
2447 cstring_fromChars (*c)));
2448 }
2449 BADEXIT;
2450 }
2451
sRef_undumpBody(char ** c)2452 static /*@exposed@*/ sRef sRef_undumpBody (char **c)
2453 {
2454 char p = **c;
2455
2456 (*c)++;
2457
2458 switch (p)
2459 {
2460 case 'g':
2461 return (sRef_makeGlobal (usymId_fromInt (reader_getInt (c)),
2462 ctype_unknown, stateInfo_currentLoc ()));
2463 case 'p':
2464 return (sRef_makeParam (reader_getInt (c), ctype_unknown,
2465 stateInfo_makeLoc (g_currentloc, SA_DECLARED)));
2466 case 'r':
2467 return (sRef_makeResult (ctype_undump (c)));
2468 case 'a':
2469 {
2470 if ((**c >= '0' && **c <= '9') || **c == '-')
2471 {
2472 int i = reader_getInt (c);
2473 sRef arr = sRef_undump (c);
2474 sRef ret = sRef_buildArrayFetchKnown (arr, i);
2475
2476 return ret;
2477 }
2478 else
2479 {
2480 sRef arr = sRef_undump (c);
2481 sRef ret = sRef_buildArrayFetch (arr);
2482
2483 return ret;
2484 }
2485 }
2486 case 'f':
2487 {
2488 cstring fname = cstring_undefined;
2489 sRef ret;
2490
2491 while (**c != '.')
2492 {
2493 fname = cstring_appendChar (fname, **c);
2494 (*c)++;
2495 }
2496 (*c)++;
2497
2498 ret = sRef_buildField (sRef_undump (c), fname);
2499 cstring_markOwned (fname);
2500 return (ret);
2501 }
2502 case 's':
2503 {
2504 int i = reader_getInt (c);
2505 speckind sk = speckind_fromInt (i);
2506
2507 switch (sk)
2508 {
2509 case SR_NOTHING: return (sRef_makeNothing ());
2510 case SR_INTERNAL: return (sRef_makeInternalState ());
2511 case SR_SPECSTATE: return (sRef_makeSpecState ());
2512 case SR_SYSTEM: return (sRef_makeSystemState ());
2513 case SR_GLOBALMARKER: BADBRANCH;
2514 }
2515 BADEXIT;
2516 }
2517 case 't':
2518 {
2519 sRef ptr = sRef_undump (c);
2520 sRef ret = sRef_makePointer (ptr);
2521
2522 return (ret);
2523 }
2524 case 'd':
2525 {
2526 sRef adr = sRef_undump (c);
2527 sRef ret = sRef_makeAddress (adr);
2528
2529 return (ret);
2530 }
2531 case 'o':
2532 {
2533 return (sRef_makeObject (ctype_undump (c)));
2534 }
2535 case 'c':
2536 {
2537 sRef s1 = sRef_undump (c);
2538 sRef s2 = ((*c)++, sRef_undump (c));
2539 sRef ret = sRef_makeConj (s1, s2);
2540
2541 return (ret);
2542 }
2543 case '-':
2544 return sRef_undefined;
2545 case 'u':
2546 return sRef_makeUnknown ();
2547 case 'x':
2548 return sRef_makeUnknown ();
2549 default:
2550 llfatalerror (message ("sRef_undump: bad line: %s", cstring_fromChars (*c)));
2551 }
2552 BADEXIT;
2553 }
2554
sRef_undump(char ** c)2555 /*@exposed@*/ sRef sRef_undump (char **c)
2556 {
2557 sRef res = sRef_undumpBody (c);
2558
2559 if (reader_optCheckChar (c, '='))
2560 {
2561 multiVal mv = multiVal_undump (c);
2562 sRef_setValue (res, mv);
2563 reader_checkChar (c, '=');
2564 }
2565
2566 return res;
2567 }
2568
sRef_dumpBody(sRef s)2569 static /*@only@*/ cstring sRef_dumpBody (sRef s)
2570 {
2571 if (sRef_isInvalid (s))
2572 {
2573 return (cstring_makeLiteral ("-"));
2574 }
2575 else
2576 {
2577 switch (s->kind)
2578 {
2579 case SK_PARAM:
2580 return (message ("p%d", s->info->paramno));
2581 case SK_ARRAYFETCH:
2582 if (s->info->arrayfetch->indknown)
2583 {
2584 return (message ("a%d%q", s->info->arrayfetch->ind,
2585 sRef_dump (s->info->arrayfetch->arr)));
2586 }
2587 else
2588 {
2589 return (message ("a%q", sRef_dump (s->info->arrayfetch->arr)));
2590 }
2591 case SK_FIELD:
2592 return (message ("f%s.%q", s->info->field->field,
2593 sRef_dump (s->info->field->rec)));
2594 case SK_PTR:
2595 return (message ("t%q", sRef_dump (s->info->ref)));
2596 case SK_ADR:
2597 return (message ("d%q", sRef_dump (s->info->ref)));
2598 case SK_OBJECT:
2599 return (message ("o%q", ctype_dump (s->info->object)));
2600 case SK_SPECIAL:
2601 return (message ("s%d", (int) s->info->spec));
2602 case SK_CONJ:
2603 return (message ("c%q.%q",
2604 sRef_dump (s->info->conj->a),
2605 sRef_dump (s->info->conj->b)));
2606 case SK_CVAR:
2607 if (sRef_isFileOrGlobalScope (s))
2608 {
2609 return (message ("g%d",
2610 usymtab_convertId (s->info->cvar->index)));
2611 }
2612 else
2613 {
2614 llcontbug (message ("Dumping local variable: %q",
2615 sRef_unparseDebug (s)));
2616 return (cstring_makeLiteral ("u"));
2617 }
2618 case SK_UNKNOWN:
2619 return (cstring_makeLiteral ("u"));
2620 case SK_RESULT:
2621 return (message ("r%q", ctype_dump (s->type)));
2622 case SK_TYPE:
2623 case SK_CONST:
2624 case SK_EXTERNAL:
2625 case SK_DERIVED:
2626 case SK_NEW:
2627 case SK_UNCONSTRAINED:
2628 llcontbug (message ("sRef_dump: bad kind: %q",
2629 sRef_unparseFull (s)));
2630 return (cstring_makeLiteral ("x"));
2631 }
2632 }
2633
2634 BADEXIT;
2635 }
2636
sRef_dump(sRef s)2637 /*@only@*/ cstring sRef_dump (sRef s)
2638 {
2639 cstring res = sRef_dumpBody (s);
2640
2641 if (sRef_hasValue (s))
2642 {
2643 res = message ("%q=%q=", res, multiVal_dump (sRef_getValue (s)));
2644 }
2645
2646 return res;
2647 }
2648
sRef_dumpGlobal(sRef s)2649 cstring sRef_dumpGlobal (sRef s)
2650 {
2651 llassert (!sRef_hasValue (s));
2652
2653 if (sRef_isInvalid (s))
2654 {
2655 return (cstring_makeLiteral ("-"));
2656 }
2657 else
2658 {
2659 switch (s->kind)
2660 {
2661 case SK_CVAR:
2662 if (sRef_isFileOrGlobalScope (s))
2663 {
2664 return (message ("g%d@%d@%d",
2665 usymtab_convertId (s->info->cvar->index),
2666 (int) s->defstate,
2667 (int) sRef_getNullState (s)));
2668 }
2669 else
2670 {
2671 llcontbug (message ("Dumping local variable: %q",
2672 sRef_unparseDebug (s)));
2673 return (cstring_makeLiteral ("u"));
2674 }
2675 case SK_UNKNOWN:
2676 return (cstring_makeLiteral ("u"));
2677 case SK_SPECIAL:
2678 return (message ("s%d", (int) s->info->spec));
2679 default:
2680 llcontbug (message ("sRef_dumpGlobal: bad kind: %q",
2681 sRef_unparseFull (s)));
2682 return (cstring_makeLiteral ("x"));
2683 }
2684 }
2685
2686 BADEXIT;
2687 }
2688
2689 ctype
sRef_deriveType(sRef s,uentryList cl)2690 sRef_deriveType (sRef s, uentryList cl)
2691 {
2692 if (sRef_isInvalid (s)) return ctype_unknown;
2693
2694 switch (s->kind)
2695 {
2696 case SK_CVAR:
2697 return (uentry_getType (usymtab_getRefQuiet (s->info->cvar->lexlevel,
2698 s->info->cvar->index)));
2699 case SK_UNCONSTRAINED:
2700 return (ctype_unknown);
2701 case SK_PARAM:
2702 if (s->info->paramno >= 0)
2703 {
2704 return uentry_getType (uentryList_getN (cl, s->info->paramno));
2705 }
2706 else
2707 {
2708 return ctype_unknown;
2709 }
2710 case SK_ARRAYFETCH:
2711 {
2712 ctype ca = sRef_deriveType (s->info->arrayfetch->arr, cl);
2713
2714 if (ctype_isArray (ca))
2715 {
2716 return (ctype_baseArrayPtr (ca));
2717 }
2718 else if (ctype_isUnknown (ca))
2719 {
2720 return (ca);
2721 }
2722 else
2723 {
2724 llcontbuglit ("sRef_deriveType: inconsistent array type");
2725 return ca;
2726 }
2727 }
2728 case SK_FIELD:
2729 {
2730 ctype ct = sRef_deriveType (s->info->field->rec, cl);
2731
2732 if (ctype_isStructorUnion (ct))
2733 {
2734 uentry ue = uentryList_lookupField (ctype_getFields (ct),
2735 s->info->field->field);
2736
2737 if (uentry_isValid (ue))
2738 {
2739 return (uentry_getType (ue));
2740 }
2741 else
2742 {
2743 llcontbuglit ("sRef_deriveType: bad field");
2744 return ctype_unknown;
2745 }
2746 }
2747 else if (ctype_isUnknown (ct))
2748 {
2749 return (ct);
2750 }
2751 else
2752 {
2753 llcontbuglit ("sRef_deriveType: inconsistent field type");
2754 return (ct);
2755 }
2756 }
2757 case SK_PTR:
2758 {
2759 ctype ct = sRef_deriveType (s->info->ref, cl);
2760
2761 if (ctype_isUnknown (ct)) return ct;
2762 if (ctype_isPointer (ct)) return (ctype_baseArrayPtr (ct));
2763 else
2764 {
2765 llcontbuglit ("sRef_deriveType: inconsistent pointer type");
2766 return (ct);
2767 }
2768 }
2769 case SK_ADR:
2770 {
2771 ctype ct = sRef_deriveType (s->info->ref, cl);
2772
2773 if (ctype_isUnknown (ct)) return ct;
2774 return ctype_makePointer (ct);
2775 }
2776 case SK_DERIVED:
2777 {
2778 return sRef_deriveType (s->info->ref, cl);
2779 }
2780 case SK_OBJECT:
2781 {
2782 return (s->info->object);
2783 }
2784 case SK_CONJ:
2785 {
2786 return (ctype_makeConj (sRef_deriveType (s->info->conj->a, cl),
2787 sRef_deriveType (s->info->conj->b, cl)));
2788 }
2789 case SK_RESULT:
2790 case SK_CONST:
2791 case SK_TYPE:
2792 {
2793 return (s->type);
2794 }
2795 case SK_SPECIAL:
2796 case SK_UNKNOWN:
2797 case SK_EXTERNAL:
2798 case SK_NEW:
2799 return ctype_unknown;
2800 }
2801 BADEXIT;
2802 }
2803
2804 ctype
sRef_getType(sRef s)2805 sRef_getType (sRef s)
2806 {
2807 if (sRef_isInvalid (s)) return ctype_unknown;
2808 return s->type;
2809 }
2810
2811
2812 /*@only@*/ cstring
sRef_unparseOpt(sRef s)2813 sRef_unparseOpt (sRef s)
2814 {
2815 sRef rb = sRef_getRootBase (s);
2816
2817 if (sRef_isMeaningful (rb) && !sRef_isConst (rb))
2818 {
2819 cstring ret = sRef_unparse (s);
2820
2821 llassertprint (!cstring_equalLit (ret, "?"), ("print: %s", sRef_unparseDebug (s)));
2822
2823 if (!cstring_isEmpty (ret))
2824 {
2825 return (cstring_appendChar (ret, ' '));
2826 }
2827 else
2828 {
2829 return ret;
2830 }
2831 }
2832
2833 return cstring_undefined;
2834 }
2835
2836 cstring
sRef_unparsePreOpt(sRef s)2837 sRef_unparsePreOpt (sRef s)
2838 {
2839 sRef rb = sRef_getRootBase (s);
2840
2841 if (sRef_isMeaningful (rb) && !sRef_isConst (rb))
2842 {
2843 cstring ret = sRef_unparse (s);
2844
2845 llassertprint (!cstring_equalLit (ret, "?"), ("print: %s", sRef_unparseDebug (s)));
2846 return (cstring_prependCharO (' ', ret));
2847 }
2848
2849 return cstring_undefined;
2850 }
2851
2852 /*@only@*/ cstring
sRef_unparse(sRef s)2853 sRef_unparse (sRef s)
2854 {
2855 if (sRef_isInvalid (s)) return (cstring_makeLiteral ("?"));
2856
2857 if (context_inFunctionLike ())
2858 {
2859 return (sRef_unparseWithArgs (s, context_getParams ()));
2860 }
2861 else
2862 {
2863 DPRINTF (("Not in function like: %s", context_unparse ()));
2864 return (sRef_unparseNoArgs (s));
2865 }
2866 }
2867
2868 static /*@only@*/ cstring
sRef_unparseWithArgs(sRef s,uentryList args)2869 sRef_unparseWithArgs (sRef s, uentryList args)
2870 {
2871 if (sRef_isInvalid (s))
2872 {
2873 return (cstring_makeLiteral ("?"));
2874 }
2875
2876 switch (s->kind)
2877 {
2878 case SK_CVAR:
2879 return (uentry_getName (usymtab_getRefQuiet (s->info->cvar->lexlevel,
2880 s->info->cvar->index)));
2881 case SK_UNCONSTRAINED:
2882 return (cstring_copy (s->info->fname));
2883 case SK_PARAM:
2884 {
2885 if (s->info->paramno < uentryList_size (args)
2886 && s->info->paramno >= 0)
2887 {
2888 uentry ue = uentryList_getN (args, s->info->paramno);
2889
2890 if (uentry_isValid (ue))
2891 return uentry_getName (ue);
2892 }
2893
2894 return (message ("parameter %d", s->info->paramno + 1));
2895 }
2896 case SK_ARRAYFETCH:
2897 if (s->info->arrayfetch->indknown)
2898 {
2899 return (message ("%q[%d]", sRef_unparseWithArgs (s->info->arrayfetch->arr, args),
2900 s->info->arrayfetch->ind));
2901 }
2902 else
2903 {
2904 return (message ("%q[]", sRef_unparseWithArgs (s->info->arrayfetch->arr, args)));
2905 }
2906 case SK_FIELD:
2907 if (s->info->field->rec->kind == SK_PTR)
2908 {
2909 sRef ptr = s->info->field->rec;
2910
2911 return (message ("%q->%s", sRef_unparseWithArgs (ptr->info->ref, args),
2912 s->info->field->field));
2913 }
2914 return (message ("%q.%s", sRef_unparseWithArgs (s->info->field->rec, args),
2915 s->info->field->field));
2916
2917 case SK_PTR:
2918 {
2919 sRef ref = sRef_fixConj (s->info->ref);
2920 skind sk = ref->kind;
2921 cstring ret;
2922
2923 if (sk == SK_NEW)
2924 {
2925 ret = message ("storage pointed to by %q",
2926 sRef_unparseWithArgs (ref, args));
2927 }
2928 else if (skind_isSimple (sk) || sk == SK_PTR)
2929 {
2930 ret = message ("*%q", sRef_unparseWithArgs (ref, args));
2931 }
2932 else
2933 {
2934 ret = message ("*(%q)", sRef_unparseWithArgs (ref, args));
2935 }
2936
2937 return ret;
2938 }
2939 case SK_ADR:
2940 return (message ("&%q", sRef_unparseWithArgs (s->info->ref, args)));
2941 case SK_OBJECT:
2942 return (cstring_copy (ctype_unparse (s->info->object)));
2943 case SK_CONJ:
2944 return (sRef_unparseWithArgs (sRef_getConjA (s), args));
2945 case SK_NEW:
2946 if (cstring_isDefined (s->info->fname))
2947 {
2948 return (message ("[result of %s]", s->info->fname));
2949 }
2950 else
2951 {
2952 return (cstring_makeLiteral ("<new>"));
2953 }
2954 case SK_UNKNOWN:
2955 return (cstring_makeLiteral ("?"));
2956 case SK_DERIVED:
2957 return (message ("<derived %q>", sRef_unparse (s->info->ref)));
2958 case SK_EXTERNAL:
2959 return (message ("<external %q>", sRef_unparse (s->info->ref)));
2960 case SK_TYPE:
2961 return (message ("<type %s>", ctype_unparse (s->type)));
2962 case SK_CONST:
2963 return (message ("<const %s>", ctype_unparse (s->type)));
2964 case SK_SPECIAL:
2965 switch (s->info->spec)
2966 {
2967 case SR_NOTHING: return cstring_makeLiteral ("nothing");
2968 case SR_INTERNAL: return cstring_makeLiteral ("internal state");
2969 case SR_SPECSTATE: return cstring_makeLiteral ("spec state");
2970 case SR_SYSTEM: return cstring_makeLiteral ("file system state");
2971 case SR_GLOBALMARKER: return cstring_makeLiteral ("<global marker>");
2972 }
2973 BADBRANCH;
2974 case SK_RESULT:
2975 return cstring_makeLiteral ("result");
2976 default:
2977 {
2978 llbug (message ("Bad sref, kind = %d", (int) s->kind));
2979 }
2980 }
2981
2982 BADEXIT;
2983 }
2984
2985 /*@only@*/ cstring
sRef_unparseDebug(sRef s)2986 sRef_unparseDebug (sRef s)
2987 {
2988 if (sRef_isInvalid (s))
2989 {
2990 return (cstring_makeLiteral ("<undef>"));
2991 }
2992
2993
2994 switch (s->kind)
2995 {
2996 case SK_UNCONSTRAINED:
2997 return (message ("<unconstrained %s>", s->info->fname));
2998 case SK_CVAR:
2999 {
3000 uentry ce;
3001
3002 ce = usymtab_getRefQuiet (s->info->cvar->lexlevel, s->info->cvar->index);
3003
3004 if (uentry_isInvalid (ce))
3005 {
3006 return (message ("<scope: %d.%d *invalid*>",
3007 s->info->cvar->lexlevel,
3008 s->info->cvar->index));
3009 }
3010 else
3011 {
3012 return (message ("<scope: %d.%d *%q*>",
3013 s->info->cvar->lexlevel,
3014 s->info->cvar->index,
3015 uentry_getName (ce)));
3016 }
3017
3018 }
3019 case SK_PARAM:
3020 {
3021 return (message ("<parameter %d>", s->info->paramno + 1));
3022 }
3023 case SK_ARRAYFETCH:
3024 if (s->info->arrayfetch->indknown)
3025 {
3026 return (message ("%q[%d]", sRef_unparseDebug (s->info->arrayfetch->arr),
3027 s->info->arrayfetch->ind));
3028 }
3029 else
3030 {
3031 return (message ("%q[]", sRef_unparseDebug (s->info->arrayfetch->arr)));
3032 }
3033 case SK_FIELD:
3034 return (message ("%q.%s", sRef_unparseDebug (s->info->field->rec),
3035 s->info->field->field));
3036 case SK_PTR:
3037 if (sRef_isField (s->info->ref))
3038 {
3039 sRef fld = s->info->ref;
3040
3041 return (message ("%q->%s", sRef_unparseDebug (fld->info->field->rec),
3042 fld->info->field->field));
3043 }
3044 else
3045 {
3046 return (message ("*(%q)", sRef_unparseDebug (s->info->ref)));
3047 }
3048 case SK_ADR:
3049 return (message ("&%q", sRef_unparseDebug (s->info->ref)));
3050 case SK_OBJECT:
3051 return (message ("<object type %s>", ctype_unparse (s->info->object)));
3052 case SK_CONJ:
3053 return (message ("%q | %q", sRef_unparseDebug (s->info->conj->a),
3054 sRef_unparseDebug (s->info->conj->b)));
3055 case SK_NEW:
3056 return message ("<new: %s>", s->info->fname);
3057 case SK_DERIVED:
3058 return (message ("<derived %q>", sRef_unparseDebug (s->info->ref)));
3059 case SK_EXTERNAL:
3060 return (message ("<external %q>", sRef_unparseDebug (s->info->ref)));
3061 case SK_TYPE:
3062 return (message ("<type %s>", ctype_unparse (s->type)));
3063 case SK_CONST:
3064 if (sRef_hasValue (s))
3065 {
3066 return (message ("<const %s=%q>", ctype_unparse (s->type), multiVal_unparse (sRef_getValue (s))));
3067 }
3068 else
3069 {
3070 return (message ("<const %s>", ctype_unparse (s->type)));
3071 }
3072 case SK_RESULT:
3073 return (message ("<result %s>", ctype_unparse (s->type)));
3074 case SK_SPECIAL:
3075 return (message ("<spec %s>",
3076 cstring_makeLiteralTemp
3077 (s->info->spec == SR_NOTHING ? "nothing"
3078 : s->info->spec == SR_INTERNAL ? "internalState"
3079 : s->info->spec == SR_SPECSTATE ? "spec state"
3080 : s->info->spec == SR_SYSTEM ? "fileSystem"
3081 : "error")));
3082 case SK_UNKNOWN:
3083 return cstring_makeLiteral ("<unknown>");
3084 }
3085
3086 BADEXIT;
3087 }
3088
3089 static /*@only@*/ cstring
sRef_unparseNoArgs(sRef s)3090 sRef_unparseNoArgs (sRef s)
3091 {
3092 if (sRef_isInvalid (s)) return (cstring_makeLiteral ("?"));
3093
3094 switch (s->kind)
3095 {
3096 case SK_UNCONSTRAINED:
3097 return (cstring_copy (s->info->fname));
3098 case SK_CVAR:
3099 {
3100 uentry ce = usymtab_getRefQuiet (s->info->cvar->lexlevel,
3101 s->info->cvar->index);
3102
3103 if (uentry_isInvalid (ce))
3104 {
3105 llcontbug (message ("sRef_unparseNoArgs: bad cvar: %q",
3106 sRef_unparseDebug (s)));
3107 return (sRef_unparseDebug (s));
3108 }
3109 else
3110 {
3111 return (uentry_getName (ce));
3112 }
3113 }
3114 case SK_ARRAYFETCH:
3115 if (s->info->arrayfetch->indknown)
3116 {
3117 return (message ("%q[%d]", sRef_unparseNoArgs (s->info->arrayfetch->arr),
3118 s->info->arrayfetch->ind));
3119 }
3120 else
3121 {
3122 return (message ("%q[]", sRef_unparseNoArgs (s->info->arrayfetch->arr)));
3123 }
3124 case SK_FIELD:
3125 return (message ("%q.%s", sRef_unparseNoArgs (s->info->field->rec),
3126 s->info->field->field));
3127 case SK_PTR:
3128 {
3129 sRef ref = sRef_fixConj (s->info->ref);
3130 skind sk = ref->kind;
3131 cstring ret;
3132
3133 if (skind_isSimple (sk) || sk == SK_PTR)
3134 {
3135 ret = message ("*%q", sRef_unparseNoArgs (ref));
3136 }
3137 else
3138 {
3139 ret = message ("*(%q)", sRef_unparseNoArgs (ref));
3140 }
3141
3142 return (ret);
3143 }
3144 case SK_ADR:
3145 return (message ("&%q", sRef_unparseNoArgs (s->info->ref)));
3146 case SK_OBJECT:
3147 return (cstring_copy (ctype_unparse (s->info->object)));
3148 case SK_CONJ:
3149 return (sRef_unparseNoArgs (s->info->conj->a));
3150 case SK_NEW:
3151 return (message ("result of %s", s->info->fname));
3152 case SK_DERIVED:
3153 return (message ("<der %q>", sRef_unparseNoArgs (s->info->ref)));
3154 case SK_EXTERNAL:
3155 return message ("<ext %q>", sRef_unparseNoArgs (s->info->ref));
3156 case SK_SPECIAL:
3157 return (cstring_makeLiteral
3158 (s->info->spec == SR_NOTHING ? "nothing"
3159 : s->info->spec == SR_INTERNAL ? "internal state"
3160 : s->info->spec == SR_SPECSTATE ? "spec state"
3161 : s->info->spec == SR_SYSTEM ? "file system state"
3162 : "<spec error>"));
3163 case SK_RESULT:
3164 return cstring_makeLiteral ("result");
3165 case SK_CONST:
3166 case SK_TYPE:
3167 case SK_UNKNOWN:
3168 return cstring_makeLiteral ("?");
3169 case SK_PARAM:
3170 /* llcontbug (message ("sRef_unparseNoArgs: bad case: %q", sRef_unparseDebug (s))); */
3171 return (sRef_unparseDebug (s));
3172 }
3173 BADEXIT;
3174 }
3175
sRef_makeUnconstrained(cstring fname)3176 /*@dependent@*/ sRef sRef_makeUnconstrained (cstring fname)
3177 {
3178 sRef s = sRef_new ();
3179
3180 s->kind = SK_UNCONSTRAINED;
3181 s->info = (sinfo) dmalloc (sizeof (*s->info));
3182 s->info->fname = cstring_copy (fname); /* evans 2002-07-12: this was exposed, causing memory errors */
3183
3184 return (s);
3185 }
3186
sRef_unconstrainedName(sRef s)3187 cstring sRef_unconstrainedName (sRef s)
3188 {
3189 llassert (sRef_isUnconstrained (s));
3190
3191 return s->info->fname;
3192 }
3193
sRef_isUnconstrained(sRef s)3194 bool sRef_isUnconstrained (sRef s)
3195 {
3196 return (sRef_isReasonable(s) && s->kind == SK_UNCONSTRAINED);
3197 }
3198
3199 static /*@dependent@*/ /*@notnull@*/ sRef
sRef_makeCvarAux(int level,usymId index,ctype ct,stateInfo stinfo)3200 sRef_makeCvarAux (int level, usymId index, ctype ct, /*@only@*/ stateInfo stinfo)
3201 {
3202 sRef s = sRef_newRef ();
3203
3204 s->kind = SK_CVAR;
3205 s->info = (sinfo) dmalloc (sizeof (*s->info));
3206
3207 s->info->cvar = (cref) dmalloc (sizeof (*s->info->cvar));
3208 s->info->cvar->lexlevel = level;
3209 s->info->cvar->index = index;
3210
3211 /* for now, all globals are defined; all locals, aren't */
3212
3213 if (level <= fileScope)
3214 {
3215 s->defstate = SS_UNKNOWN;
3216 }
3217 else
3218 {
3219 ctype rct = ctype_realType (ct);
3220
3221 if (level != paramsScope
3222 && (ctype_isStructorUnion (rct) || ctype_isRealArray (rct)))
3223 {
3224 s->defstate = SS_ALLOCATED;
3225 s->oaliaskind = s->aliaskind = AK_STACK;
3226 }
3227 else
3228 {
3229 s->defstate = SS_UNDEFINED;
3230 s->oaliaskind = s->aliaskind = AK_LOCAL;
3231 }
3232 }
3233
3234 s->type = ct;
3235
3236 llassert (level >= globScope);
3237 llassert (usymId_isValid (index));
3238
3239 DPRINTF (("Made cvar: [%p] %s", s, sRef_unparseDebug (s)));
3240 llassert (valueTable_isUndefined (s->state));
3241 s->state = context_createValueTable (s, stinfo);
3242 return s;
3243 }
3244
sRef_makeCvar(int level,usymId index,ctype ct,stateInfo stinfo)3245 /*@dependent@*/ sRef sRef_makeCvar (int level, usymId index, ctype ct, /*@only@*/ stateInfo stinfo)
3246 {
3247 return (sRef_makeCvarAux (level, index, ct, stinfo));
3248 }
3249
sRef_lexLevel(sRef s)3250 int sRef_lexLevel (sRef s)
3251 {
3252 if (sRef_isReasonable (s))
3253 {
3254 sRef conj;
3255
3256 conj = sRef_fixConj (s);
3257 s = sRef_getRootBase (conj);
3258
3259 if (sRef_isReasonable (s) && s->kind == SK_CVAR)
3260 {
3261 return (s->info->cvar->lexlevel);
3262 }
3263 }
3264
3265 return globScope;
3266 }
3267
3268 sRef
sRef_makeGlobal(usymId l,ctype ct,stateInfo stinfo)3269 sRef_makeGlobal (usymId l, ctype ct, /*@only@*/ stateInfo stinfo)
3270 {
3271 return (sRef_makeCvar (globScope, l, ct, stinfo));
3272 }
3273
3274 void
sRef_setParamNo(sRef s,int l)3275 sRef_setParamNo (sRef s, int l)
3276 {
3277 llassert (sRef_isReasonable (s) && s->kind == SK_PARAM);
3278 s->info->paramno = l;
3279 llassert (l >= -1);
3280 }
3281
3282 /*@dependent@*/ sRef
sRef_makeParam(int l,ctype ct,stateInfo stinfo)3283 sRef_makeParam (int l, ctype ct, stateInfo stinfo)
3284 {
3285 sRef s = sRef_new ();
3286
3287 s->kind = SK_PARAM;
3288 s->type = ct;
3289
3290 s->info = (sinfo) dmalloc (sizeof (*s->info));
3291 s->info->paramno = l;
3292 llassert (l >= -1);
3293 s->defstate = SS_UNKNOWN;
3294 /* (probably defined, unless its an out parameter) */
3295
3296 llassert (valueTable_isUndefined (s->state));
3297 s->state = context_createValueTable (s, stinfo);
3298 return s;
3299 }
3300
3301 bool
sRef_isIndexKnown(sRef arr)3302 sRef_isIndexKnown (sRef arr)
3303 {
3304 bool res;
3305
3306 llassert (sRef_isReasonable (arr));
3307 arr = sRef_fixConj (arr);
3308
3309 llassert (arr->kind == SK_ARRAYFETCH);
3310 res = arr->info->arrayfetch->indknown;
3311 return (res);
3312 }
3313
3314 int
sRef_getIndex(sRef arr)3315 sRef_getIndex (sRef arr)
3316 {
3317 int result;
3318
3319 llassert (sRef_isReasonable (arr));
3320 arr = sRef_fixConj (arr);
3321
3322 llassert (arr->kind == SK_ARRAYFETCH);
3323
3324 if (!arr->info->arrayfetch->indknown)
3325 {
3326 llcontbug (message ("sRef_getIndex: unknown: %q", sRef_unparse (arr)));
3327 result = 0;
3328 }
3329 else
3330 {
3331 result = arr->info->arrayfetch->ind;
3332 }
3333
3334 return result;
3335 }
3336
sRef_isZerothArrayFetch(sRef s)3337 static bool sRef_isZerothArrayFetch (/*@notnull@*/ sRef s)
3338 {
3339 return (s->kind == SK_ARRAYFETCH
3340 && s->info->arrayfetch->indknown
3341 && (s->info->arrayfetch->ind == 0));
3342 }
3343
sRef_makeAddress(sRef t)3344 /*@exposed@*/ sRef sRef_makeAddress (/*@exposed@*/ sRef t)
3345 {
3346
3347 if (sRef_isInvalid (t)) return sRef_undefined;
3348
3349 if (sRef_isPointer (t))
3350 {
3351 return (t->info->ref);
3352 }
3353 else if (sRef_isZerothArrayFetch (t))
3354 {
3355 return (t->info->arrayfetch->arr);
3356 }
3357 else
3358 {
3359 sRef s = sRef_newRef ();
3360
3361 s->kind = SK_ADR;
3362 s->type = ctype_makePointer (t->type);
3363 s->info = (sinfo) dmalloc (sizeof (*s->info));
3364 s->info->ref = t;
3365
3366 if (t->defstate == SS_UNDEFINED)
3367 /* no! it is allocated even still: && !ctype_isPointer (t->type)) */
3368 {
3369 s->defstate = SS_ALLOCATED;
3370 }
3371 else
3372 {
3373 s->defstate = t->defstate;
3374 }
3375
3376 if (t->aliaskind == AK_LOCAL)
3377 {
3378 if (sRef_isLocalVar (t))
3379 {
3380 s->aliaskind = AK_STACK;
3381 }
3382 }
3383
3384 llassert (valueTable_isUndefined (s->state));
3385 s->state = context_createValueTable (s,
3386 stateInfo_makeLoc (g_currentloc, SA_CREATED));
3387 return s;
3388 }
3389 }
3390
sRef_getField(sRef s)3391 cstring sRef_getField (sRef s)
3392 {
3393 cstring res;
3394
3395 llassert (sRef_isReasonable (s));
3396 s = sRef_fixConj (s);
3397
3398 llassertprint (sRef_isReasonable (s) && (s->kind == SK_FIELD),
3399 ("s = %s", sRef_unparseDebug (s)));
3400
3401 res = s->info->field->field;
3402 return (res);
3403 }
3404
sRef_getBase(sRef s)3405 sRef sRef_getBase (sRef s)
3406 {
3407 sRef res;
3408
3409 if (sRef_isInvalid (s)) return (sRef_undefined);
3410
3411 s = sRef_fixConj (s);
3412
3413 switch (s->kind)
3414 {
3415 case SK_ADR:
3416 case SK_PTR:
3417 case SK_DERIVED:
3418 case SK_EXTERNAL:
3419 res = s->info->ref;
3420 break;
3421 case SK_FIELD:
3422 res = s->info->field->rec;
3423 break;
3424
3425 case SK_ARRAYFETCH:
3426 res = s->info->arrayfetch->arr;
3427 break;
3428
3429 default:
3430 res = sRef_undefined; /* shouldn't need it */
3431 }
3432
3433 return (res);
3434 }
3435
3436 /*
3437 ** same as getBase, except returns invalid
3438 ** (and doesn't use adr's)
3439 */
3440
3441 sRef
sRef_getBaseSafe(sRef s)3442 sRef_getBaseSafe (sRef s)
3443 {
3444 sRef res;
3445
3446 if (sRef_isInvalid (s)) { return sRef_undefined; }
3447
3448 s = sRef_fixConj (s);
3449
3450 switch (s->kind)
3451 {
3452 case SK_PTR:
3453 res = s->info->ref;
3454 break;
3455 case SK_FIELD:
3456 res = s->info->field->rec; break;
3457 case SK_ARRAYFETCH:
3458 res = s->info->arrayfetch->arr;
3459 break;
3460 default:
3461 res = sRef_undefined; break;
3462 }
3463
3464 return res;
3465 }
3466
3467 /*@constant int MAXBASEDEPTH;@*/
3468 # define MAXBASEDEPTH 25
3469
3470 static /*@exposed@*/ sRef
sRef_getRootBaseAux(sRef s,int depth)3471 sRef_getRootBaseAux (sRef s, int depth)
3472 {
3473 if (sRef_isInvalid (s)) return sRef_undefined;
3474
3475 if (depth > MAXBASEDEPTH)
3476 {
3477 llgenmsg (message
3478 ("Warning: reference base limit exceeded for %q. "
3479 "This either means there is a variable with at least "
3480 "%d indirections from this reference, or "
3481 "there is a bug in Splint.",
3482 sRef_unparse (s),
3483 MAXBASEDEPTH),
3484 g_currentloc);
3485
3486 return sRef_undefined;
3487 }
3488
3489 switch (s->kind)
3490 {
3491 case SK_ADR:
3492 case SK_PTR:
3493 return (sRef_getRootBaseAux (s->info->ref, depth + 1));
3494 case SK_FIELD:
3495 return (sRef_getRootBaseAux (s->info->field->rec, depth + 1));
3496 case SK_ARRAYFETCH:
3497 return (sRef_getRootBaseAux (s->info->arrayfetch->arr, depth + 1));
3498 case SK_CONJ:
3499 return (sRef_getRootBaseAux (sRef_fixConj (s), depth + 1));
3500 default:
3501 return s;
3502 }
3503 }
3504
sRef_getRootBase(sRef s)3505 sRef sRef_getRootBase (sRef s)
3506 {
3507 return (sRef_getRootBaseAux (s, 0));
3508 }
3509
sRef_isDeep(sRef s)3510 static bool sRef_isDeep (sRef s)
3511 {
3512 if (sRef_isInvalid (s)) return FALSE;
3513
3514 switch (s->kind)
3515 {
3516 case SK_ADR:
3517 case SK_PTR:
3518 case SK_FIELD:
3519 case SK_ARRAYFETCH:
3520 return TRUE;
3521 case SK_CONJ:
3522 return (sRef_isDeep (sRef_fixConj (s)));
3523 default:
3524 return FALSE;
3525 }
3526 }
3527
sRef_depth(sRef s)3528 static int sRef_depth (sRef s)
3529 {
3530 if (sRef_isInvalid (s)) return 0;
3531
3532 switch (s->kind)
3533 {
3534 case SK_ADR:
3535 case SK_PTR:
3536 case SK_DERIVED:
3537 case SK_EXTERNAL:
3538 return 1 + sRef_depth (s->info->ref);
3539 case SK_FIELD:
3540 return 1 + sRef_depth (s->info->field->rec);
3541 case SK_ARRAYFETCH:
3542 return 1 + sRef_depth (s->info->arrayfetch->arr);
3543 case SK_CONJ:
3544 return (sRef_depth (sRef_fixConj (s)));
3545 default:
3546 return 1;
3547 }
3548 }
3549
3550 sRef
sRef_makeObject(ctype o)3551 sRef_makeObject (ctype o)
3552 {
3553 sRef s = sRef_newRef ();
3554
3555 s->kind = SK_OBJECT;
3556 s->info = (sinfo) dmalloc (sizeof (*s->info));
3557 s->info->object = o;
3558 llassert (valueTable_isUndefined (s->state));
3559 s->state = context_createValueTable (s, stateInfo_makeLoc (g_currentloc, SA_CREATED));
3560 return s;
3561 }
3562
3563 /*
3564 ** This is used to represent storage referenced by a parameter.
3565 */
3566
sRef_makeExternal(sRef t)3567 sRef sRef_makeExternal (sRef t)
3568 {
3569 sRef s = sRef_newRef ();
3570
3571 llassert (sRef_isReasonable (t));
3572
3573 s->kind = SK_EXTERNAL;
3574 s->info = (sinfo) dmalloc (sizeof (*s->info));
3575 s->type = t->type;
3576 s->info->ref = t;
3577 llassert (valueTable_isUndefined (s->state));
3578 s->state = context_createValueTable (s, stateInfo_makeLoc (g_currentloc, SA_DECLARED));
3579 return s;
3580 }
3581
sRef_makeDerived(sRef t)3582 /*@dependent@*/ sRef sRef_makeDerived (/*@exposed@*/ sRef t)
3583 {
3584 if (sRef_isReasonable (t))
3585 {
3586 sRef s = sRef_newRef ();
3587
3588 s->kind = SK_DERIVED;
3589 s->info = (sinfo) dmalloc (sizeof (*s->info));
3590 s->info->ref = t;
3591
3592 s->type = t->type;
3593 llassert (valueTable_isUndefined (s->state));
3594 s->state = context_createValueTable (s, stateInfo_makeLoc (g_currentloc, SA_CREATED));
3595 return s;
3596 }
3597 else
3598 {
3599 return sRef_undefined;
3600 }
3601 }
3602
3603 /*
3604 ** definitely NOT symmetric:
3605 **
3606 ** res fills in unknown state information from other
3607 */
3608
3609 void
sRef_mergeStateQuiet(sRef res,sRef other)3610 sRef_mergeStateQuiet (sRef res, sRef other)
3611 {
3612 llassert (sRef_isReasonable (res));
3613 llassert (sRef_isReasonable (other));
3614
3615 res->modified = res->modified || other->modified;
3616 res->safe = res->safe && other->safe;
3617
3618 if (res->defstate == SS_UNKNOWN)
3619 {
3620 res->defstate = other->defstate;
3621 res->definfo = stateInfo_update (res->definfo, other->definfo);
3622 }
3623
3624 if (res->aliaskind == AK_UNKNOWN ||
3625 (res->aliaskind == AK_LOCAL && alkind_isKnown (other->aliaskind)))
3626 {
3627 res->aliaskind = other->aliaskind;
3628 res->oaliaskind = other->oaliaskind;
3629 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
3630 }
3631
3632 if (res->expkind == XO_UNKNOWN)
3633 {
3634 res->expkind = other->expkind;
3635 res->oexpkind = other->oexpkind;
3636 res->expinfo = stateInfo_update (res->expinfo, other->expinfo);
3637 }
3638
3639 /* out takes precedence over implicitly defined */
3640 if (res->defstate == SS_DEFINED && other->defstate != SS_UNKNOWN)
3641 {
3642 res->defstate = other->defstate;
3643 res->definfo = stateInfo_update (res->definfo, other->definfo);
3644 }
3645
3646 if (sRef_getNullState (other) == NS_ERROR || sRef_getNullState (res) == NS_ERROR)
3647 {
3648 sRef_setNullState (res, NS_ERROR, fileloc_undefined);
3649 }
3650 else
3651 {
3652 if (sRef_getNullState (other) != NS_UNKNOWN
3653 && (sRef_getNullState (res) == NS_UNKNOWN || sRef_getNullState (res) == NS_NOTNULL
3654 || sRef_getNullState (res) == NS_MNOTNULL))
3655 {
3656 sRef_updateNullState (res, other);
3657 }
3658 }
3659 }
3660
3661 /*
3662 ** definitely NOT symmetric:
3663 **
3664 ** res fills in known state information from other
3665 */
3666
3667 void
sRef_mergeStateQuietReverse(sRef res,sRef other)3668 sRef_mergeStateQuietReverse (/*@dependent@*/ sRef res, /*@dependent@*/ sRef other)
3669 {
3670 bool changed = FALSE;
3671
3672 llassert (sRef_isReasonable (res));
3673 llassert (sRef_isReasonable (other));
3674 sRef_checkMutable (res);
3675
3676 if (res->kind != other->kind)
3677 {
3678 changed = TRUE;
3679
3680 sinfo_free (res);
3681
3682 res->kind = other->kind;
3683 res->type = other->type;
3684 res->info = sinfo_fullCopy (other);
3685 }
3686 else
3687 {
3688 if (!ctype_equal (res->type, other->type))
3689 {
3690 changed = TRUE;
3691 res->type = other->type;
3692 }
3693
3694 sinfo_update (res, other);
3695 }
3696
3697 res->modified = res->modified || other->modified;
3698 res->safe = res->safe && other->safe;
3699
3700 if (res->aliaskind != other->aliaskind
3701 && (res->aliaskind == AK_UNKNOWN
3702 || ((res->aliaskind == AK_LOCAL
3703 || (res->aliaskind == AK_REFCOUNTED
3704 && other->aliaskind != AK_LOCAL))
3705 && other->aliaskind != AK_UNKNOWN)))
3706 {
3707 changed = TRUE;
3708 res->aliaskind = other->aliaskind;
3709 res->oaliaskind = other->oaliaskind;
3710 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
3711 }
3712
3713 if (other->expkind != XO_UNKNOWN && other->expkind != res->expkind)
3714 {
3715 changed = TRUE;
3716 res->expkind = other->expkind;
3717 res->expinfo = stateInfo_update (res->expinfo, other->expinfo);
3718 }
3719
3720 if (other->oexpkind != XO_UNKNOWN)
3721 {
3722 res->oexpkind = other->oexpkind;
3723 }
3724
3725 /* out takes precedence over implicitly defined */
3726
3727 if (res->defstate != other->defstate)
3728 {
3729 if (other->defstate != SS_UNKNOWN)
3730 {
3731 res->defstate = other->defstate;
3732 res->definfo = stateInfo_update (res->definfo, other->definfo);
3733 }
3734 }
3735
3736 if (sRef_getNullState (other) == NS_ERROR || sRef_getNullState (res) == NS_ERROR)
3737 {
3738 if (sRef_getNullState (res) != NS_ERROR)
3739 {
3740 sRef_setNullStateN (res, NS_ERROR);
3741 changed = TRUE;
3742 }
3743 }
3744 else
3745 {
3746 if (sRef_getNullState (other) != NS_UNKNOWN
3747 && sRef_getNullState (other) != sRef_getNullState (res))
3748 {
3749 changed = TRUE;
3750 sRef_updateNullState (res, other);
3751 }
3752 }
3753
3754 if (changed)
3755 {
3756 sRef_clearDerived (res);
3757 }
3758 }
3759
3760 void
sRef_mergeState(sRef res,sRef other,clause cl,fileloc loc)3761 sRef_mergeState (sRef res, sRef other, clause cl, fileloc loc)
3762 {
3763 if (sRef_isReasonable (res) && sRef_isReasonable (other))
3764 {
3765 sRef_mergeStateAux (res, other, cl, FALSE, loc, TRUE);
3766 }
3767 else
3768 {
3769 if (sRef_isInvalid (res))
3770 {
3771 llbug (message ("sRef_mergeState: invalid res sRef: %q",
3772 sRef_unparseDebug (other)));
3773 }
3774 else
3775 {
3776 llbug (message ("sRef_mergeState: invalid other sRef: %q",
3777 sRef_unparseDebug (res)));
3778 }
3779 }
3780 }
3781
3782 void
sRef_mergeOptState(sRef res,sRef other,clause cl,fileloc loc)3783 sRef_mergeOptState (sRef res, sRef other, clause cl, fileloc loc)
3784 {
3785 if (sRef_isReasonable (res) && sRef_isReasonable (other))
3786 {
3787 sRef_mergeStateAux (res, other, cl, TRUE, loc, TRUE);
3788 }
3789 else
3790 {
3791 if (sRef_isInvalid (res))
3792 {
3793 llbug (message ("sRef_mergeOptState: invalid res sRef: %q",
3794 sRef_unparseDebug (other)));
3795 }
3796 else
3797 {
3798 llbug (message ("sRef_mergeOptState: invalid other sRef: %q",
3799 sRef_unparseDebug (res)));
3800 }
3801 }
3802 }
3803
3804 static void
sRef_mergeStateAux(sRef res,sRef other,clause cl,bool opt,fileloc loc,bool doDerivs)3805 sRef_mergeStateAux (/*@notnull@*/ sRef res, /*@notnull@*/ sRef other,
3806 clause cl, bool opt, fileloc loc,
3807 bool doDerivs)
3808 /*@modifies res@*/
3809 {
3810 llassertfatal (sRef_isReasonable (res));
3811 llassertfatal (sRef_isReasonable (other));
3812
3813 DPRINTF (("Merge aux: %s / %s",
3814 sRef_unparseFull (res),
3815 sRef_unparseFull (other)));
3816
3817 sRef_checkMutable (res);
3818 sRef_checkMutable (other);
3819
3820 res->modified = res->modified || other->modified;
3821
3822 if (res->kind == other->kind
3823 || (other->kind == SK_UNKNOWN || res->kind == SK_UNKNOWN))
3824 {
3825 sstate odef = other->defstate;
3826 sstate rdef = res->defstate;
3827 nstate onull = sRef_getNullState (other);
3828
3829 /*
3830 ** yucky stuff to handle
3831 **
3832 ** if (s) free (s);
3833 */
3834
3835 if (other->defstate == SS_DEAD
3836 && ((sRef_isOnly (res) && sRef_definitelyNull (res))
3837 || (res->defstate == SS_UNDEFINED
3838 || res->defstate == SS_UNUSEABLE)))
3839 {
3840 if (res->defstate == SS_UNDEFINED
3841 || res->defstate == SS_UNUSEABLE)
3842 {
3843 res->defstate = SS_UNUSEABLE;
3844 }
3845 else
3846 {
3847 res->defstate = SS_DEAD;
3848 }
3849
3850 res->definfo = stateInfo_update (res->definfo, other->definfo);
3851 sRef_clearDerived (other);
3852 sRef_clearDerived (res);
3853 }
3854 else if (res->defstate == SS_DEAD
3855 && ((sRef_isOnly (other) && sRef_definitelyNull (other))
3856 || (other->defstate == SS_UNDEFINED
3857 || other->defstate == SS_UNUSEABLE)))
3858 {
3859 if (other->defstate == SS_UNDEFINED
3860 || other->defstate == SS_UNUSEABLE)
3861 {
3862 res->defstate = SS_UNUSEABLE;
3863 }
3864 else
3865 {
3866 res->defstate = SS_DEAD;
3867 }
3868
3869 res->definfo = stateInfo_update (res->definfo, other->definfo);
3870 sRef_clearDerived (other);
3871 sRef_clearDerived (res);
3872 }
3873 else if (res->defstate == SS_DEFINED
3874 && (other->defstate == SS_ALLOCATED
3875 && sRef_definitelyNull (other)))
3876 {
3877 other->defstate = SS_DEFINED; /* definitely null! */
3878 }
3879 else if (other->defstate == SS_DEFINED
3880 && (res->defstate == SS_ALLOCATED && sRef_definitelyNull (res)))
3881 {
3882 res->defstate = SS_DEFINED;
3883 res->definfo = stateInfo_update (res->definfo, other->definfo);
3884 }
3885 else
3886 {
3887 ; /* okay */
3888 }
3889
3890 if (res->defstate == SS_DEAD && other->defstate == SS_DEAD)
3891 {
3892 sRef_clearDerived (other);
3893 sRef_clearDerived (res);
3894 }
3895
3896 /*
3897 ** only & dead isn't really an only!
3898 */
3899
3900 if (alkind_isOnly (other->aliaskind) && other->defstate == SS_DEAD)
3901 {
3902 other->aliaskind = AK_UNKNOWN;
3903 }
3904
3905 if (alkind_isOnly (res->aliaskind) && res->defstate == SS_DEAD)
3906 {
3907 res->aliaskind = AK_UNKNOWN;
3908 }
3909
3910 /*
3911 ** Dead and dependent -> dead
3912 */
3913
3914 if (alkind_isDependent (other->aliaskind) && res->defstate == SS_DEAD)
3915 {
3916 other->aliaskind = AK_UNKNOWN;
3917 other->defstate = SS_DEAD;
3918 sRef_clearDerived (res);
3919 sRef_clearDerived (other);
3920 }
3921
3922 if (alkind_isDependent (res->aliaskind) && other->defstate == SS_DEAD)
3923 {
3924 res->aliaskind = AK_UNKNOWN;
3925 res->defstate = SS_DEAD;
3926 sRef_clearDerived (res);
3927 sRef_clearDerived (other);
3928 }
3929
3930 /*
3931 ** must do alias combine first, since it depends on
3932 ** original values of state and null.
3933 */
3934
3935 sRef_combineAliasKinds (res, other, cl, loc);
3936 sRef_combineDefState (res, other);
3937 sRef_combineNullState (res, other);
3938
3939 if (rdef == SS_ALLOCATED || rdef == SS_SPECIAL)
3940 {
3941 if (odef == SS_DEFINED)
3942 {
3943 if (onull == NS_DEFNULL || onull == NS_CONSTNULL)
3944 {
3945 res->deriv = sRefSet_copyInto (res->deriv, other->deriv);
3946 DPRINTF (("Copy derivs: %s", sRef_unparseFull (res)));
3947 }
3948 }
3949 else if (odef == SS_ALLOCATED || odef == SS_SPECIAL)
3950 {
3951
3952 if (doDerivs)
3953 {
3954 if (ctype_isUnion (ctype_realType (sRef_getType (res))))
3955 {
3956 res->deriv = sRef_mergeUnionDerivs (res->deriv,
3957 other->deriv,
3958 opt, cl, loc);
3959 DPRINTF (("Copy derivs: %s", sRef_unparseFull (res)));
3960 }
3961 else
3962 {
3963 res->deriv = sRef_mergeDerivs (res->deriv, other->deriv,
3964 opt, cl, loc);
3965 DPRINTF (("Copy derivs: %s", sRef_unparseFull (res)));
3966 }
3967 }
3968 }
3969 else
3970 {
3971 if (doDerivs)
3972 {
3973 res->deriv = sRef_mergeDerivs (res->deriv, other->deriv,
3974 opt, cl, loc);
3975 DPRINTF (("Copy derivs: %s", sRef_unparseFull (res)));
3976 }
3977 else
3978 {
3979 ;
3980 }
3981 }
3982 }
3983 else
3984 {
3985 if (rdef == SS_PDEFINED
3986 || (rdef == SS_DEFINED && odef == SS_PDEFINED))
3987 {
3988 if (doDerivs)
3989 {
3990 res->deriv = sRef_mergePdefinedDerivs (res->deriv, other->deriv,
3991 opt, cl, loc);
3992 DPRINTF (("Copy derivs: %s", sRef_unparseFull (res)));
3993 }
3994 }
3995 else
3996 {
3997 if ((rdef == SS_DEFINED || rdef == SS_UNKNOWN)
3998 && res->defstate == SS_ALLOCATED)
3999 {
4000 res->deriv = sRefSet_copyInto (res->deriv, other->deriv);
4001 }
4002 else
4003 {
4004 if (doDerivs)
4005 {
4006 res->deriv = sRef_mergeDerivs (res->deriv, other->deriv,
4007 opt, cl, loc);
4008 DPRINTF (("Copy derivs: %s", sRef_unparseFull (res)));
4009 }
4010 }
4011 }
4012 }
4013
4014
4015 sRef_combineExKinds (res, other);
4016 }
4017 else
4018 {
4019 if (res->kind == SK_ARRAYFETCH && other->kind == SK_PTR)
4020 {
4021 sRef nother = sRef_buildArrayFetchKnown (sRef_getBase (other), 0);
4022
4023 sRef_copyState (nother, other);
4024 sRef_mergeStateAux (res, nother, cl, opt, loc, doDerivs);
4025 }
4026 else if (res->kind == SK_PTR && other->kind == SK_ARRAYFETCH)
4027 {
4028 sRef nother = sRef_buildPointer (sRef_getBase (other));
4029
4030 if (sRef_isReasonable (nother))
4031 {
4032 sRef_copyState (nother, other);
4033 sRef_mergeStateAux (res, nother, cl, opt, loc, doDerivs);
4034 }
4035 }
4036 else
4037 {
4038 llcontbug (message ("merge conj: %q / %q", sRef_unparseFull (res),
4039 sRef_unparseFull (other)));
4040
4041 }
4042 }
4043
4044 /*
4045 ** Merge value table states
4046 */
4047
4048 # if 0
4049 /*
4050 ** This doesn't do anything. And its broken too...
4051 */
4052
4053 valueTable_elements (res->state, key, sv)
4054 {
4055 stateValue os = valueTable_lookup (other->state, key);
4056 /*@unused@*/ int val;
4057 /*@unused@*/ char *msg;
4058
4059 llassert (stateValue_isDefined (os));
4060
4061 DPRINTF (("Merge state: %s / %s",
4062 cstring_toCharsSafe (stateValue_unparse (sv)),
4063 cstring_toCharsSafe (stateValue_unparse (os))));
4064 /*
4065 val = valueMatix_lookup (key,
4066 stateValue_getValue (os),
4067 stateValue_getValue (sv),
4068 &msg);
4069 DPRINTF (("Val: %d / %s", val, msg));
4070 */
4071 } end_valueTable_elements ;
4072 # endif
4073
4074 DPRINTF (("Merge aux: %s / %s",
4075 sRef_unparseFull (res),
4076 sRef_unparseFull (other)));
4077 }
4078
4079 static sRefSet
sRef_mergeUnionDerivs(sRefSet res,sRefSet other,bool opt,clause cl,fileloc loc)4080 sRef_mergeUnionDerivs (/*@only@*/ sRefSet res,
4081 /*@exposed@*/ sRefSet other, bool opt,
4082 clause cl, fileloc loc)
4083 {
4084 if (sRefSet_isEmpty (res))
4085 {
4086 return sRefSet_copyInto (res, other);
4087 }
4088 else
4089 {
4090 sRefSet_allElements (other, el)
4091 {
4092 if (sRef_isReasonable (el))
4093 {
4094 sRef e2 = sRefSet_lookupMember (other, el);
4095
4096 if (sRef_isReasonable (e2))
4097 {
4098 sRef_mergeStateAux (el, e2, cl, opt, loc, FALSE);
4099 }
4100 else
4101 {
4102 res = sRefSet_insert (res, el);
4103 }
4104 }
4105 } end_sRefSet_allElements ;
4106
4107 return res;
4108 }
4109 }
4110
4111 static /*@only@*/ sRefSet
sRef_mergeDerivs(sRefSet res,sRefSet other,bool opt,clause cl,fileloc loc)4112 sRef_mergeDerivs (/*@only@*/ sRefSet res, sRefSet other,
4113 bool opt, clause cl, fileloc loc)
4114 {
4115 sRefSet ret = sRefSet_new ();
4116
4117 sRefSet_allElements (res, el)
4118 {
4119 if (sRef_isReasonable (el))
4120 {
4121 sRef e2 = sRefSet_lookupMember (other, el);
4122
4123 if (sRef_isReasonable (e2))
4124 {
4125 if (el->defstate == SS_ALLOCATED &&
4126 e2->defstate == SS_PDEFINED)
4127 {
4128 e2->defstate = SS_ALLOCATED;
4129 }
4130 else if (e2->defstate == SS_ALLOCATED &&
4131 el->defstate == SS_PDEFINED)
4132 {
4133 el->defstate = SS_ALLOCATED;
4134 el->definfo = stateInfo_update (el->definfo, e2->definfo);
4135 sRef_clearDerived (el);
4136 }
4137 else if ((el->defstate == SS_DEAD || sRef_isKept (el)) &&
4138 (e2->defstate == SS_DEFINED && !sRef_isKept (e2)))
4139 {
4140 DPRINTF (("Checking dead: %s / %s", sRef_unparseFull (el),
4141 sRef_unparseFull (e2)));
4142
4143 if (checkDeadState (el, e2, TRUE, loc))
4144 {
4145 if (sRef_isThroughArrayFetch (el))
4146 {
4147 sRef_maybeKill (el, loc);
4148 sRef_maybeKill (e2, loc);
4149 }
4150 }
4151 }
4152 else if ((e2->defstate == SS_DEAD || sRef_isKept (e2)) &&
4153 (el->defstate == SS_DEFINED && !sRef_isKept (el)))
4154 {
4155 DPRINTF (("Checking dead: %s / %s", sRef_unparseFull (el),
4156 sRef_unparseFull (e2)));
4157
4158 if (checkDeadState (e2, el, FALSE, loc))
4159 {
4160 if (sRef_isThroughArrayFetch (el))
4161 {
4162 sRef_maybeKill (el, loc);
4163 sRef_maybeKill (e2, loc);
4164 }
4165 }
4166 }
4167 else if (el->defstate == SS_DEFINED &&
4168 e2->defstate == SS_PDEFINED)
4169 {
4170 DPRINTF (("set pdefined: %s", sRef_unparseFull (el)));
4171 el->defstate = SS_PDEFINED;
4172 el->definfo = stateInfo_update (el->definfo, e2->definfo);
4173 }
4174 else if (e2->defstate == SS_DEFINED &&
4175 el->defstate == SS_PDEFINED)
4176 {
4177 DPRINTF (("set pdefined: %s", sRef_unparseFull (e2)));
4178 e2->defstate = SS_PDEFINED;
4179 e2->definfo = stateInfo_update (e2->definfo, el->definfo);
4180 }
4181 else
4182 {
4183 ; /* okay */
4184 }
4185
4186 if (ctype_isUnion (ctype_realType (sRef_getType (el))))
4187 {
4188 el->deriv = sRef_mergeUnionDerivs (el->deriv, e2->deriv,
4189 opt, cl, loc);
4190 }
4191 else
4192 {
4193 el->deriv = sRef_mergeDerivs (el->deriv, e2->deriv, opt, cl, loc);
4194 }
4195
4196 if (sRef_equivalent (el, e2))
4197 {
4198 ret = sRefSet_insert (ret, el);
4199 }
4200 else
4201 {
4202 sRef sr = sRef_leastCommon (el, e2);
4203
4204 if (sRef_isReasonable (sr))
4205 {
4206 ret = sRefSet_insert (ret, sr);
4207 }
4208 else
4209 {
4210 ;
4211 }
4212 }
4213
4214 (void) sRefSet_delete (other, e2);
4215 }
4216 else /* not defined */
4217 {
4218 DPRINTF (("Checking dead: %s", sRef_unparseFull (el)));
4219 (void) checkDeadState (el, e2, TRUE, loc);
4220 }
4221 }
4222 } end_sRefSet_allElements;
4223
4224 sRefSet_allElements (other, el)
4225 {
4226 if (sRef_isReasonable (el))
4227 {
4228 DPRINTF (("Checking dead: %s", sRef_unparseFull (el)));
4229 (void) checkDeadState (el, sRef_undefined, FALSE, loc);
4230 }
4231 } end_sRefSet_allElements;
4232
4233 sRefSet_free (res);
4234 return (ret);
4235 }
4236
4237 /*
4238 ** Returns TRUE is there is an error.
4239 */
4240
checkDeadState(sRef el,sRef e2,bool tbranch,fileloc loc)4241 static bool checkDeadState (/*@notnull@*/ sRef el, sRef e2, bool tbranch, fileloc loc)
4242 {
4243 /*
4244 ** usymtab_isGuarded --- the utab should still be in the
4245 ** state of the alternate branch.
4246 **
4247 ** tbranch TRUE means el is released in the last branch, e.g.
4248 ** if (x != NULL) { ; } else { sfree (x); }
4249 ** so, if x is null in the other branch no error is reported.
4250 **
4251 ** tbranch FALSE means this is the other branch:
4252 ** if (x != NULL) { sfree (x); } else { ; }
4253 ** so, if x is null in this branch there is no error.
4254 */
4255
4256
4257 if ((sRef_isDead (el) || sRef_isKept (el))
4258 && !sRef_isDeepUnionField (el)
4259 && !sRef_isThroughArrayFetch (el))
4260 {
4261
4262 if (!tbranch)
4263 {
4264 if (usymtab_isDefinitelyNullDeep (el))
4265 {
4266 return TRUE;
4267 }
4268 }
4269 else
4270 {
4271 if (usymtab_isAltDefinitelyNullDeep (el))
4272 {
4273 return TRUE;
4274 }
4275 }
4276
4277 if (optgenerror
4278 (FLG_BRANCHSTATE,
4279 message ("Storage %q is %q in one path, but live in another.",
4280 sRef_unparse (el),
4281 cstring_makeLiteral (sRef_isKept (el)
4282 ? "kept" : "released")),
4283 loc))
4284 {
4285 if (sRef_isKept (el))
4286 {
4287 sRef_showAliasInfo (el);
4288 }
4289 else
4290 {
4291 sRef_showStateInfo (el);
4292 }
4293
4294 if (sRef_isValid (e2))
4295 {
4296 if (sRef_isKept (e2))
4297 {
4298 sRef_showAliasInfo (e2);
4299 }
4300 else
4301 {
4302 sRef_showStateInfo (e2);
4303 }
4304 }
4305
4306 /* prevent further errors */
4307 el->defstate = SS_UNKNOWN;
4308 sRef_setAliasKind (el, AK_ERROR, fileloc_undefined);
4309 return FALSE;
4310 }
4311 }
4312
4313 return TRUE;
4314 }
4315
4316 static void
checkDerivDeadState(sRef el,bool tbranch,fileloc loc)4317 checkDerivDeadState (/*@notnull@*/ sRef el, bool tbranch, fileloc loc)
4318 {
4319 if (checkDeadState (el, sRef_undefined, tbranch, loc))
4320 {
4321 sRefSet_allElements (el->deriv, t)
4322 {
4323 if (sRef_isReasonable (t))
4324 {
4325 checkDerivDeadState (t, tbranch, loc);
4326 }
4327 } end_sRefSet_allElements;
4328 }
4329 }
4330
4331 static sRefSet
sRef_mergePdefinedDerivs(sRefSet res,sRefSet other,bool opt,clause cl,fileloc loc)4332 sRef_mergePdefinedDerivs (sRefSet res, sRefSet other, bool opt,
4333 clause cl, fileloc loc)
4334 {
4335 sRefSet ret = sRefSet_new ();
4336
4337 sRefSet_allElements (res, el)
4338 {
4339 if (sRef_isReasonable (el))
4340 {
4341 sRef e2 = sRefSet_lookupMember (other, el);
4342
4343 if (sRef_isReasonable (e2))
4344 {
4345 if (sRef_isAllocated (el) && !sRef_isAllocated (e2))
4346 {
4347 ;
4348 }
4349 else if (sRef_isAllocated (e2) && !sRef_isAllocated (el))
4350 {
4351 el->deriv = sRefSet_copyInto (el->deriv, e2->deriv);
4352 }
4353 else
4354 {
4355 el->deriv = sRef_mergePdefinedDerivs (el->deriv, e2->deriv,
4356 opt, cl, loc);
4357 }
4358
4359 sRef_mergeStateAux (el, e2, cl, opt, loc, FALSE);
4360
4361 ret = sRefSet_insert (ret, el);
4362 (void) sRefSet_delete (other, e2);
4363 }
4364 else
4365 {
4366 if (!opt)
4367 {
4368 checkDerivDeadState (el, (cl == FALSECLAUSE), loc);
4369 }
4370
4371 ret = sRefSet_insert (ret, el);
4372 }
4373 }
4374 } end_sRefSet_allElements;
4375
4376 sRefSet_allElements (other, el)
4377 {
4378 if (sRef_isReasonable (el))
4379 {
4380 if (!sRefSet_member (ret, el))
4381 {
4382 /* was cl == FALSECLAUSE */
4383 checkDerivDeadState (el, FALSE, loc);
4384 ret = sRefSet_insert (ret, el);
4385 }
4386 else
4387 {
4388 /*
4389 ** it's okay --- member is a different equality test
4390 */
4391 }
4392 }
4393 } end_sRefSet_allElements;
4394
4395 sRefSet_free (res);
4396 return (ret);
4397 }
4398
sRef_makeConj(sRef a,sRef b)4399 sRef sRef_makeConj (/*@exposed@*/ /*@returned@*/ sRef a, /*@exposed@*/ sRef b)
4400 {
4401 llassert (sRef_isReasonable (a));
4402 llassert (sRef_isReasonable (b));
4403
4404 if (!sRef_equivalent (a, b))
4405 {
4406 sRef s = sRef_newRef ();
4407
4408 s->kind = SK_CONJ;
4409 s->info = (sinfo) dmalloc (sizeof (*s->info));
4410 s->info->conj = (cjinfo) dmalloc (sizeof (*s->info->conj));
4411 s->info->conj->a = a;
4412 s->info->conj->b = b;
4413
4414 if (ctype_equal (a->type, b->type)) s->type = a->type;
4415 else s->type = ctype_makeConj (a->type, b->type);
4416
4417 if (a->defstate == b->defstate)
4418 {
4419 s->defstate = a->defstate;
4420 s->definfo = stateInfo_update (s->definfo, a->definfo);
4421 s->definfo = stateInfo_update (s->definfo, b->definfo);
4422 }
4423 else
4424 {
4425 s->defstate = SS_UNKNOWN;
4426 }
4427
4428 sRef_setNullStateN (s, NS_UNKNOWN);
4429
4430 s->safe = a->safe && b->safe;
4431 s->aliaskind = alkind_resolve (a->aliaskind, b->aliaskind);
4432
4433 llassert (valueTable_isUndefined (s->state));
4434 s->state = context_createValueTable (s, stateInfo_makeLoc (g_currentloc, SA_MERGED));
4435 return s;
4436 }
4437 else
4438 {
4439 /*@-exposetrans@*/ return a; /*@=exposetrans@*/
4440 }
4441 }
4442
4443 /*@dependent@*/ sRef
sRef_makeUnknown()4444 sRef_makeUnknown ()
4445 {
4446 sRef s = sRef_new ();
4447
4448 s->kind = SK_UNKNOWN;
4449 return s;
4450 }
4451
4452 static /*@owned@*/ /*@notnull@*/ sRef
sRef_makeSpecial(speckind sk)4453 sRef_makeSpecial (speckind sk) /*@*/
4454 {
4455 sRef s = sRef_new ();
4456
4457 s->kind = SK_SPECIAL;
4458 s->info = (sinfo) dmalloc (sizeof (*s->info));
4459 s->info->spec = sk;
4460 /*@-dependenttrans@*/
4461 return s;
4462 /*@=dependenttrans@*/
4463 }
4464
4465 static /*@owned@*/ sRef srnothing = sRef_undefined;
4466 static /*@owned@*/ sRef srinternal = sRef_undefined;
4467 static /*@owned@*/ sRef srsystem = sRef_undefined;
4468 static /*@owned@*/ sRef srspec = sRef_undefined;
4469
4470 /*@dependent@*/ sRef
sRef_makeNothing(void)4471 sRef_makeNothing (void)
4472 {
4473 if (sRef_isInvalid (srnothing))
4474 {
4475 srnothing = sRef_makeSpecial (SR_NOTHING);
4476 }
4477
4478 return srnothing;
4479 }
4480
4481 sRef
sRef_makeInternalState(void)4482 sRef_makeInternalState (void)
4483 {
4484 if (sRef_isInvalid (srinternal))
4485 {
4486 srinternal = sRef_makeSpecial (SR_INTERNAL);
4487 }
4488
4489 return srinternal;
4490 }
4491
4492 sRef
sRef_makeSpecState(void)4493 sRef_makeSpecState (void)
4494 {
4495 if (sRef_isInvalid (srspec))
4496 {
4497 srspec = sRef_makeSpecial (SR_SPECSTATE);
4498 }
4499
4500 return srspec;
4501 }
4502
4503 sRef
sRef_makeSystemState(void)4504 sRef_makeSystemState (void)
4505 {
4506 if (sRef_isInvalid (srsystem))
4507 {
4508 srsystem = sRef_makeSpecial (SR_SYSTEM);
4509 }
4510
4511 return srsystem;
4512 }
4513
4514 sRef
sRef_makeGlobalMarker(void)4515 sRef_makeGlobalMarker (void)
4516 {
4517 sRef s = sRef_makeSpecial (SR_GLOBALMARKER);
4518 llassert (valueTable_isUndefined (s->state));
4519 s->state = context_createGlobalMarkerValueTable (stateInfo_undefined);
4520 return s;
4521 }
4522
4523 sRef
sRef_makeResult(ctype c)4524 sRef_makeResult (ctype c)
4525 {
4526 sRef s = sRef_newRef ();
4527
4528 s->kind = SK_RESULT;
4529 s->type = c;
4530 s->defstate = SS_UNKNOWN;
4531 s->aliaskind = AK_UNKNOWN;
4532 sRef_setNullStateN (s, NS_UNKNOWN);
4533 llassert (valueTable_isUndefined (s->state));
4534 s->state = context_createValueTable (s, stateInfo_makeLoc (g_currentloc, SA_DECLARED));
4535
4536 DPRINTF (("Result: [%p] %s", s, sRef_unparseFull (s)));
4537 return s;
4538 }
4539
4540
4541 bool
sRef_isNothing(sRef s)4542 sRef_isNothing (sRef s)
4543 {
4544 return (sRef_isKindSpecial (s) && s->info->spec == SR_NOTHING);
4545 }
4546
4547 bool
sRef_isInternalState(sRef s)4548 sRef_isInternalState (sRef s)
4549 {
4550 return (sRef_isKindSpecial (s) && s->info->spec == SR_INTERNAL);
4551 }
4552
4553 bool
sRef_isSpecInternalState(sRef s)4554 sRef_isSpecInternalState (sRef s)
4555 {
4556 return (sRef_isKindSpecial (s)
4557 && (s->info->spec == SR_INTERNAL || s->info->spec == SR_SPECSTATE));
4558 }
4559
4560 bool
sRef_isSpecState(sRef s)4561 sRef_isSpecState (sRef s)
4562 {
4563 return (sRef_isKindSpecial (s) && s->info->spec == SR_SPECSTATE);
4564 }
4565
4566 bool
sRef_isResult(sRef s)4567 sRef_isResult (sRef s)
4568 {
4569 return (sRef_isReasonable (s) && s->kind == SK_RESULT);
4570 }
4571
4572 bool
sRef_isSystemState(sRef s)4573 sRef_isSystemState (sRef s)
4574 {
4575 return (sRef_isKindSpecial (s) && s->info->spec == SR_SYSTEM);
4576 }
4577
4578 bool
sRef_isGlobalMarker(sRef s)4579 sRef_isGlobalMarker (sRef s)
4580 {
4581 return (sRef_isKindSpecial (s) && s->info->spec == SR_GLOBALMARKER);
4582 }
4583
4584 usymId
sRef_getScopeIndex(sRef s)4585 sRef_getScopeIndex (sRef s)
4586 {
4587 llassert (sRef_isReasonable (s));
4588 llassert (sRef_isCvar (s));
4589
4590 return (s->info->cvar->index);
4591 }
4592
4593 void
sRef_makeSafe(sRef s)4594 sRef_makeSafe (sRef s)
4595 {
4596 if (sRef_isReasonable (s))
4597 {
4598 s->safe = TRUE;
4599 }
4600 }
4601
4602 void
sRef_makeUnsafe(sRef s)4603 sRef_makeUnsafe (sRef s)
4604 {
4605 if (sRef_isReasonable (s))
4606 {
4607 s->safe = FALSE;
4608 }
4609 }
4610
4611 /*
4612 ** memory state operations
4613 */
4614
sRef_unparseFull(sRef s)4615 /*@only@*/ cstring sRef_unparseFull (sRef s)
4616 {
4617 if (sRef_isInvalid (s)) return (cstring_undefined);
4618
4619 return (message ("[%p] %q - %q { %q } [%s] { %q } < %q >",
4620 s,
4621 sRef_unparseDebug (s),
4622 sRef_unparseState (s),
4623 stateInfo_unparse (s->definfo),
4624 exkind_unparse (s->oexpkind),
4625 sRefSet_unparseDebug (s->deriv),
4626 valueTable_unparse (s->state)));
4627 }
4628
sRef_unparseDeep(sRef s)4629 /*@unused@*/ cstring sRef_unparseDeep (sRef s)
4630 {
4631 cstring st = cstring_undefined;
4632
4633 st = message ("%q:", sRef_unparseFull (s));
4634
4635 if (sRef_isReasonable (s))
4636 {
4637 sRefSet_allElements (s->deriv, el)
4638 {
4639 st = message("%q\n%q", st, sRef_unparseDeep (el));
4640 } end_sRefSet_allElements ;
4641 }
4642
4643 return st;
4644 }
4645
sRef_unparseState(sRef s)4646 /*@only@*/ cstring sRef_unparseState (sRef s)
4647 {
4648 if (sRef_isConj (s))
4649 {
4650 return (message ("%q | %q",
4651 sRef_unparseState (s->info->conj->a),
4652 sRef_unparseState (s->info->conj->b)));
4653 }
4654
4655 if (sRef_isInvalid (s))
4656 {
4657 return (cstring_makeLiteral ("<invalid>"));
4658 }
4659
4660 return (message ("%s.%s.%s.%s",
4661 alkind_unparse (s->aliaskind),
4662 nstate_unparse (sRef_getNullState (s)),
4663 exkind_unparse (s->expkind),
4664 sstate_unparse (s->defstate)));
4665 }
4666
sRef_isNotUndefined(sRef s)4667 bool sRef_isNotUndefined (sRef s)
4668 {
4669 return (sRef_isInvalid (s)
4670 || (s->defstate != SS_UNDEFINED
4671 && s->defstate != SS_UNUSEABLE
4672 && s->defstate != SS_DEAD));
4673 }
4674
sRef_isWriteable(sRef s)4675 ynm sRef_isWriteable (sRef s)
4676 {
4677 if (sRef_isInvalid (s)) return MAYBE;
4678
4679 if (sRef_isConj (s) && s->defstate == SS_UNKNOWN)
4680 {
4681 if (ynm_toBoolStrict (sRef_isWriteable (sRef_getConjA (s))))
4682 {
4683 if (ynm_toBoolStrict (sRef_isWriteable (sRef_getConjB (s))))
4684 {
4685 return YES;
4686 }
4687 return MAYBE;
4688 }
4689 else
4690 {
4691 if (ynm_toBoolStrict (sRef_isWriteable (sRef_getConjB (s))))
4692 {
4693 return MAYBE;
4694 }
4695 return NO;
4696 }
4697 }
4698
4699 return (ynm_fromBool (s->defstate != SS_UNUSEABLE));
4700 }
4701
sRef_hasNoStorage(sRef s)4702 bool sRef_hasNoStorage (sRef s)
4703 {
4704 return (!sRef_isAllocatedStorage (s) || sRef_isDefinitelyNull (s));
4705 }
4706
sRef_isStrictReadable(sRef s)4707 bool sRef_isStrictReadable (sRef s)
4708 {
4709 return (ynm_toBoolStrict (sRef_isValidLvalue (s)));
4710 }
4711
4712 /*
4713 ** Is this what is does?
4714 ** Returns YES if s can be used as an rvalue,
4715 ** MAYBE if its not clear
4716 ** NO if s cannot be safely used as an rvalue.
4717 */
4718
sRef_isValidLvalue(sRef s)4719 ynm sRef_isValidLvalue (sRef s)
4720 {
4721 sstate ss;
4722
4723 if (sRef_isInvalid (s)) return YES;
4724
4725 ss = s->defstate;
4726
4727 if (sRef_isConj (s) && s->defstate == SS_UNKNOWN)
4728 {
4729 if (ynm_toBoolStrict (sRef_isValidLvalue (sRef_getConjA (s))))
4730 {
4731 if (ynm_toBoolStrict (sRef_isValidLvalue (sRef_getConjB (s))))
4732 {
4733 return YES;
4734 }
4735 return MAYBE;
4736 }
4737 else
4738 {
4739 if (ynm_toBoolStrict (sRef_isValidLvalue (sRef_getConjB (s))))
4740 {
4741 return MAYBE;
4742 }
4743 return NO;
4744 }
4745 }
4746 else if (ss == SS_HOFFA)
4747 {
4748 if (context_getFlag (FLG_STRICTUSERELEASED))
4749 {
4750 return MAYBE;
4751 }
4752 else
4753 {
4754 return YES;
4755 }
4756 }
4757 else
4758 {
4759 return (ynm_fromBool (ss == SS_DEFINED
4760 || ss == SS_FIXED
4761 || ss == SS_RELDEF
4762 || ss == SS_PDEFINED
4763 || ss == SS_PARTIAL
4764 || ss == SS_SPECIAL
4765 || ss == SS_ALLOCATED
4766 || ss == SS_KILLED /* evans 2001-05-26: added this for killed globals */
4767 || ss == SS_UNKNOWN));
4768 }
4769 }
4770
whatUndefined(sRef fref,int depth)4771 static /*@exposed@*/ sRef whatUndefined (/*@exposed@*/ sRef fref, int depth)
4772 {
4773 ctype ct;
4774
4775
4776 if (depth > MAXDEPTH)
4777 {
4778 llgenmsg (message
4779 ("Warning: check definition limit exceeded, checking %q. "
4780 "This either means there is a variable with at least "
4781 "%d indirections apparent in the program text, or "
4782 "there is a bug in Splint.",
4783 sRef_unparse (fref),
4784 MAXDEPTH),
4785 g_currentloc);
4786
4787 return sRef_undefined;
4788 }
4789
4790 if (!sRef_isKnown (fref) || sRef_isAnyDefined (fref))
4791 {
4792 return sRef_undefined;
4793 }
4794
4795 if (sRef_isUnuseable (fref) || sRef_isStateUndefined (fref))
4796 {
4797 return fref;
4798 }
4799
4800 ct = ctype_realType (sRef_getType (fref));
4801
4802 if (ctype_isUnknown (ct))
4803 {
4804 return sRef_undefined;
4805 }
4806 else if (ctype_isPointer (ct) || ctype_isArray (ct))
4807 {
4808 if (sRef_isStateUnknown (fref))
4809 {
4810 return sRef_undefined;
4811 }
4812 else
4813 {
4814 sRef fptr = sRef_constructDeref (fref);
4815
4816 return (whatUndefined (fptr, depth + 1));
4817 }
4818 }
4819 else if (ctype_isStruct (ct))
4820 {
4821 bool hasOneDefined = FALSE;
4822
4823 if (sRef_isStateUnknown (fref))
4824 {
4825 return fref;
4826 }
4827
4828 if (sRef_isPdefined (fref) || sRef_isAnyDefined (fref))
4829 {
4830 sRefSet_realElements (sRef_derivedFields (fref), sr)
4831 {
4832 hasOneDefined = TRUE;
4833
4834 if (sRef_isField (sr))
4835 {
4836 cstring fieldname = sRef_getField (sr);
4837 sRef fldref = sRef_makeField (fref, fieldname);
4838 bool shouldCheck = !sRef_isRecursiveField (fldref);
4839
4840 if (shouldCheck)
4841 {
4842 sRef wdef = whatUndefined (fldref, depth + 1);
4843
4844 if (sRef_isReasonable (wdef))
4845 {
4846 return wdef;
4847 }
4848 }
4849 }
4850 } end_sRefSet_realElements;
4851 }
4852 else if (sRef_isAllocated (fref))
4853 {
4854 /*
4855 ** for structures, each field must be completely defined
4856 */
4857
4858 uentryList fields = ctype_getFields (ct);
4859
4860 uentryList_elements (fields, ue)
4861 {
4862 cstring name = uentry_getRealName (ue);
4863 sRef ffield = sRef_makeField (fref, name);
4864 bool shouldCheck = !sRef_isRecursiveField (ffield);
4865
4866 if (sRef_isRelDef (uentry_getSref (ue)))
4867 {
4868 ; /* no error */
4869 }
4870 else
4871 {
4872 if (shouldCheck)
4873 {
4874 sRef wdef = whatUndefined (ffield, depth + 1);
4875
4876 if (sRef_isInvalid (wdef))
4877 {
4878 return wdef;
4879 }
4880 }
4881 }
4882 } end_uentryList_elements;
4883 }
4884 else
4885 {
4886 ;
4887 }
4888 }
4889 else if (ctype_isUnion (ct))
4890 {
4891 ;
4892 }
4893 else
4894 {
4895 ;
4896 }
4897
4898 return sRef_undefined;
4899 }
4900
checkDefined(sRef sr)4901 static bool checkDefined (/*@temp@*/ sRef sr)
4902 {
4903 /*@-temptrans@*/ /* the result from whatUndefined is lost */
4904 return (sRef_isInvalid (whatUndefined (sr, 0)));
4905 /*@=temptrans@*/
4906 }
4907
sRef_isReallyDefined(sRef s)4908 bool sRef_isReallyDefined (sRef s)
4909 {
4910 if (sRef_isReasonable (s))
4911 {
4912 if (sRef_isAnyDefined (s))
4913 {
4914 return TRUE;
4915 }
4916 else
4917 {
4918 if (sRef_isAllocated (s) || sRef_isPdefined (s))
4919 {
4920 return checkDefined (s);
4921 }
4922 else
4923 {
4924 return FALSE;
4925 }
4926 }
4927 }
4928 else
4929 {
4930 return TRUE;
4931 }
4932 }
4933
sRef_showNotReallyDefined(sRef s)4934 void sRef_showNotReallyDefined (sRef s)
4935 {
4936 if (sRef_isReasonable (s))
4937 {
4938 if (sRef_isAnyDefined (s))
4939 {
4940 BADBRANCH;
4941 }
4942 else
4943 {
4944 if (sRef_isAllocated (s) || sRef_isPdefined (s))
4945 {
4946 /*@-temptrans@*/ /* the result of whatUndefined is lost */
4947 sRef ref = whatUndefined (s, 0);
4948
4949 llassert (sRef_isReasonable (ref));
4950
4951 if (ref != s)
4952 {
4953 llgenindentmsgnoloc
4954 (message ("This sub-reference is %s: %q",
4955 sstate_unparse (sRef_getDefState (ref)),
4956 sRef_unparse (ref)));
4957 }
4958 }
4959 else
4960 {
4961 ;
4962 }
4963 }
4964 }
4965 else
4966 {
4967 BADBRANCH;
4968 }
4969 }
4970
sRef_getDefState(sRef s)4971 sstate sRef_getDefState (sRef s)
4972 {
4973 if (sRef_isInvalid (s)) return (SS_UNKNOWN);
4974 return (s->defstate);
4975 }
4976
sRef_setDefState(sRef s,sstate defstate,fileloc loc)4977 void sRef_setDefState (sRef s, sstate defstate, fileloc loc)
4978 {
4979 sRef_checkMutable (s);
4980 sRef_setStateAux (s, defstate, loc);
4981 }
4982
sRef_clearAliasStateAux(sRef s,fileloc loc)4983 static void sRef_clearAliasStateAux (sRef s, fileloc loc)
4984 {
4985 sRef_checkMutable (s);
4986 sRef_setAliasKind (s, AK_ERROR, loc);
4987 }
4988
sRef_clearAliasState(sRef s,fileloc loc)4989 void sRef_clearAliasState (sRef s, fileloc loc)
4990 {
4991 sRef_checkMutable (s);
4992 sRef_aliasSetComplete (sRef_clearAliasStateAux, s, loc);
4993 }
4994
sRef_setAliasKindComplete(sRef s,alkind kind,fileloc loc)4995 void sRef_setAliasKindComplete (sRef s, alkind kind, fileloc loc)
4996 {
4997 sRef_checkMutable (s);
4998 sRef_aliasSetCompleteAlkParam (sRef_setAliasKind, s, kind, loc);
4999 }
5000
sRef_setAliasKind(sRef s,alkind kind,fileloc loc)5001 void sRef_setAliasKind (sRef s, alkind kind, fileloc loc)
5002 {
5003 sRef_checkMutable (s);
5004
5005 if (sRef_isReasonable (s))
5006 {
5007 sRef_clearDerived (s);
5008
5009 if ((kind != s->aliaskind && kind != s->oaliaskind)
5010 && fileloc_isDefined (loc))
5011 {
5012 s->aliasinfo = stateInfo_updateLoc (s->aliasinfo, stateAction_fromAlkind (kind), loc);
5013 }
5014
5015 s->aliaskind = kind;
5016 }
5017 }
5018
sRef_setOrigAliasKind(sRef s,alkind kind)5019 void sRef_setOrigAliasKind (sRef s, alkind kind)
5020 {
5021 sRef_checkMutable (s);
5022
5023 if (sRef_isReasonable (s))
5024 {
5025 s->oaliaskind = kind;
5026 }
5027 }
5028
sRef_getExKind(sRef s)5029 exkind sRef_getExKind (sRef s)
5030 {
5031 if (sRef_isReasonable (s))
5032 {
5033 return (s->expkind);
5034 }
5035 else
5036 {
5037 return XO_UNKNOWN;
5038 }
5039 }
5040
sRef_getOrigExKind(sRef s)5041 exkind sRef_getOrigExKind (sRef s)
5042 {
5043 if (sRef_isReasonable (s))
5044 {
5045 return (s->oexpkind);
5046 }
5047 else
5048 {
5049 return XO_UNKNOWN;
5050 }
5051 }
5052
sRef_clearExKindAux(sRef s,fileloc loc)5053 static void sRef_clearExKindAux (sRef s, fileloc loc)
5054 {
5055 sRef_checkMutable (s);
5056 sRef_setExKind (s, XO_UNKNOWN, loc);
5057 }
5058
sRef_setObserver(sRef s,fileloc loc)5059 void sRef_setObserver (sRef s, fileloc loc)
5060 {
5061 sRef_checkMutable (s);
5062 sRef_setExKind (s, XO_OBSERVER, loc);
5063 }
5064
sRef_setExposed(sRef s,fileloc loc)5065 void sRef_setExposed (sRef s, fileloc loc)
5066 {
5067 sRef_checkMutable (s);
5068 sRef_setExKind (s, XO_EXPOSED, loc);
5069 }
5070
sRef_clearExKindComplete(sRef s,fileloc loc)5071 void sRef_clearExKindComplete (sRef s, fileloc loc)
5072 {
5073 (void) sRef_aliasSetComplete (sRef_clearExKindAux, s, loc);
5074 }
5075
sRef_setExKind(sRef s,exkind exp,fileloc loc)5076 void sRef_setExKind (sRef s, exkind exp, fileloc loc)
5077 {
5078 sRef_checkMutable (s);
5079
5080 if (sRef_isReasonable (s))
5081 {
5082 if (s->expkind != exp)
5083 {
5084 s->expinfo = stateInfo_updateLoc (s->expinfo, stateAction_fromExkind (exp), loc);
5085 }
5086
5087 s->expkind = exp;
5088 }
5089 }
5090
5091 /*
5092 ** s1->derived = s2->derived
5093 */
5094
sRef_copyRealDerived(sRef s1,sRef s2)5095 static void sRef_copyRealDerived (sRef s1, sRef s2)
5096 {
5097 DPRINTF (("Copy real: %s / %s", sRef_unparse (s1), sRef_unparse (s2)));
5098 sRef_checkMutable (s1);
5099
5100 if (sRef_isReasonable (s1) && sRef_isReasonable (s2))
5101 {
5102 sRef sb = sRef_getRootBase (s1);
5103
5104 sRefSet_clear (s1->deriv);
5105
5106 sRefSet_allElements (s2->deriv, el)
5107 {
5108 if (sRef_isReasonable (el))
5109 {
5110 sRef rb = sRef_getRootBase (el);
5111
5112 if (!sRef_same (rb, sb))
5113 {
5114 sRef fb = sRef_fixDirectBase (el, s1);
5115
5116 if (sRef_isReasonable (fb))
5117 {
5118 sRef_copyRealDerived (fb, el);
5119 sRef_addDeriv (s1, fb);
5120 }
5121 }
5122 else
5123 {
5124 sRef_addDeriv (s1, el);
5125 }
5126 }
5127 } end_sRefSet_allElements ;
5128 }
5129
5130 }
5131
sRef_copyRealDerivedComplete(sRef s1,sRef s2)5132 void sRef_copyRealDerivedComplete (sRef s1, sRef s2)
5133 {
5134 sRef_innerAliasSetCompleteParam (sRef_copyRealDerived, s1, s2);
5135 }
5136
sRef_setUndefined(sRef s,fileloc loc)5137 void sRef_setUndefined (sRef s, fileloc loc)
5138 {
5139 sRef_checkMutable (s);
5140
5141 if (sRef_isReasonable (s))
5142 {
5143 s->defstate = SS_UNDEFINED;
5144 s->definfo = stateInfo_updateLoc (s->definfo, SA_UNDEFINED, loc);
5145
5146 sRef_clearDerived (s);
5147 }
5148 }
5149
sRef_setDefinedAux(sRef s,fileloc loc,bool clear)5150 static void sRef_setDefinedAux (sRef s, fileloc loc, bool clear)
5151 {
5152 sRef_checkMutable (s);
5153 if (sRef_isInvalid (s)) return;
5154
5155 DPRINTF (("Set defined: %s", sRef_unparseFull (s)));
5156
5157 s->definfo = stateInfo_updateLoc (s->definfo, SA_DEFINED, loc);
5158 s->defstate = SS_DEFINED;
5159
5160 DPRINTF (("Set defined: %s", sRef_unparseFull (s)));
5161
5162 /* e.g., if x is allocated, *x = 3 defines x */
5163
5164 if (s->kind == SK_PTR)
5165 {
5166 sRef p = s->info->ref;
5167 sRef arr;
5168
5169 if (p->defstate == SS_ALLOCATED
5170 || p->defstate == SS_SPECIAL) /* evans 2001-07-12: shouldn't need this */
5171 {
5172 sRef_setDefinedAux (p, loc, clear);
5173 }
5174
5175 /*
5176 ** Defines a[0] also:
5177 */
5178
5179 arr = sRef_findDerivedArrayFetch (p, FALSE, 0, FALSE);
5180
5181 if (sRef_isReasonable (arr))
5182 {
5183 sRef_setDefinedAux (arr, loc, clear);
5184 }
5185 }
5186 else if (s->kind == SK_ARRAYFETCH)
5187 {
5188 if (!s->info->arrayfetch->indknown
5189 || (s->info->arrayfetch->ind == 0))
5190 {
5191 sRef p = s->info->arrayfetch->arr;
5192 sRef ptr = sRef_constructPointer (p);
5193
5194 if (sRef_isReasonable (ptr))
5195 {
5196 if (ptr->defstate == SS_ALLOCATED
5197 || ptr->defstate == SS_UNDEFINED
5198 || ptr->defstate == SS_SPECIAL) /* evans 2001-07-12: shouldn't need this */
5199 {
5200 sRef_setDefinedAux (ptr, loc, clear);
5201 }
5202 }
5203
5204 if (p->defstate == SS_RELDEF)
5205 {
5206 ;
5207 }
5208 else if (p->defstate == SS_ALLOCATED || p->defstate == SS_PDEFINED
5209 || p->defstate == SS_SPECIAL) /* evans 2001-07-12: shouldn't need this */
5210 {
5211 p->defstate = SS_DEFINED;
5212 }
5213 else
5214 {
5215 }
5216 }
5217 }
5218 else if (s->kind == SK_FIELD)
5219 {
5220 sRef parent = s->info->field->rec;
5221
5222 if (sRef_isReasonable (parent))
5223 {
5224 if (ctype_isUnion (ctype_realType (parent->type)))
5225 {
5226 /*
5227 ** Should not clear derived from here.
5228 */
5229
5230 sRef_setDefinedNoClear (parent, loc);
5231 }
5232 else
5233 {
5234 ; /* Nothing to do for structures. */
5235 }
5236 }
5237
5238 }
5239 else
5240 {
5241 ;
5242 }
5243
5244 if (clear)
5245 {
5246 sRef_clearDerived (s);
5247 }
5248 else
5249 {
5250 /* evans 2001-07-12: need to define the derived references */
5251 sRefSet_elements (s->deriv, el)
5252 {
5253 llassert (sRef_isReasonable (el));
5254 el->defstate = SS_DEFINED;
5255 } end_sRefSet_elements ;
5256 }
5257
5258 DPRINTF (("Set defined: %s", sRef_unparseFull (s)));
5259 }
5260
sRef_setPartialDefined(sRef s,fileloc loc)5261 static void sRef_setPartialDefined (sRef s, fileloc loc)
5262 {
5263 sRef_checkMutable (s);
5264
5265 if (!sRef_isPartial (s))
5266 {
5267 sRef_setDefined (s, loc);
5268 }
5269 }
5270
sRef_setPartialDefinedComplete(sRef s,fileloc loc)5271 void sRef_setPartialDefinedComplete (sRef s, fileloc loc)
5272 {
5273 sRef_innerAliasSetComplete (sRef_setPartialDefined, s, loc);
5274 }
5275
sRef_setDefinedComplete(sRef s,fileloc loc)5276 void sRef_setDefinedComplete (sRef s, fileloc loc)
5277 {
5278 sRef_innerAliasSetComplete (sRef_setDefined, s, loc);
5279 }
5280
sRef_setDefinedCompleteDirect(sRef s,fileloc loc)5281 void sRef_setDefinedCompleteDirect (sRef s, fileloc loc)
5282 {
5283 sRefSet aliases;
5284
5285 aliases = usymtab_allAliases (s);
5286 DPRINTF (("Set defined complete: %s", sRef_unparseFull (s)));
5287 DPRINTF (("All aliases: %s", sRefSet_unparseFull (aliases)));
5288
5289 sRef_setDefined (s, loc);
5290
5291 sRefSet_realElements (aliases, current)
5292 {
5293 if (sRef_isReasonable (current))
5294 {
5295 current = sRef_updateSref (current);
5296 sRef_setDefined (current, loc);
5297 }
5298 } end_sRefSet_realElements;
5299
5300 sRefSet_free (aliases);
5301 sRef_innerAliasSetComplete (sRef_setDefined, s, loc);
5302 }
5303
sRef_setDefined(sRef s,fileloc loc)5304 void sRef_setDefined (sRef s, fileloc loc)
5305 {
5306 sRef_checkMutable (s);
5307 sRef_setDefinedAux (s, loc, TRUE);
5308 }
5309
sRef_setDefinedNoClear(sRef s,fileloc loc)5310 static void sRef_setDefinedNoClear (sRef s, fileloc loc)
5311 {
5312 sRef_checkMutable (s);
5313 DPRINTF (("Defining: %s", sRef_unparseFull (s)));
5314 sRef_setDefinedAux (s, loc, FALSE);
5315 DPRINTF (("==> %s", sRef_unparseFull (s)));
5316 }
5317
sRef_setDefinedNCComplete(sRef s,fileloc loc)5318 void sRef_setDefinedNCComplete (sRef s, fileloc loc)
5319 {
5320 sRef_checkMutable (s);
5321 DPRINTF (("Set Defined Complete: %s", sRef_unparseFull (s)));
5322 sRef_innerAliasSetComplete (sRef_setDefinedNoClear, s, loc);
5323 DPRINTF (("==> %s", sRef_unparseFull (s)));
5324 }
5325
sRef_isDeepUnionField(sRef s)5326 static bool sRef_isDeepUnionField (sRef s)
5327 {
5328 return (sRef_deepPred (sRef_isUnionField, s));
5329 }
5330
sRef_isUnionField(sRef s)5331 bool sRef_isUnionField (sRef s)
5332 {
5333 if (sRef_isReasonable (s) && s->kind == SK_FIELD)
5334 {
5335 /*
5336 ** defining one field of a union defines the union
5337 */
5338
5339 sRef base = s->info->field->rec;
5340
5341 if (sRef_isReasonable (base))
5342 {
5343 return (ctype_isUnion (ctype_realType (base->type)));
5344 }
5345 }
5346
5347 return FALSE;
5348 }
5349
sRef_setPdefined(sRef s,fileloc loc)5350 void sRef_setPdefined (sRef s, fileloc loc)
5351 {
5352 sRef_checkMutable (s);
5353 if (sRef_isReasonable (s) && !sRef_isPartial (s))
5354 {
5355 sRef base = sRef_getBaseSafe (s);
5356
5357 if (s->defstate == SS_ALLOCATED)
5358 {
5359 return;
5360 }
5361
5362 s->definfo = stateInfo_updateLoc (s->definfo, SA_PDEFINED, loc);
5363 s->defstate = SS_PDEFINED;
5364
5365 /* e.g., if x is allocated, *x = 3 defines x */
5366
5367 while (sRef_isReasonable (base) && sRef_isKnown (base))
5368 {
5369 if (base->defstate == SS_DEFINED)
5370 {
5371 sRef nb;
5372
5373 DPRINTF (("set pdefined: %s", sRef_unparseFull (base)));
5374 base->defstate = SS_PDEFINED;
5375 nb = sRef_getBaseSafe (base);
5376 base = nb;
5377 }
5378 else
5379 {
5380 break;
5381 }
5382 }
5383 }
5384 }
5385
sRef_setStateAux(sRef s,sstate ss,fileloc loc)5386 static void sRef_setStateAux (sRef s, sstate ss, fileloc loc)
5387 {
5388 sRef_checkMutable (s);
5389
5390 DPRINTF (("Set state: %s => %s", sRef_unparseFull (s), sstate_unparse (ss)));
5391
5392 if (sRef_isReasonable (s))
5393 {
5394 /* if (s->defstate == SS_RELDEF) return; */
5395
5396 if (s->defstate != ss && fileloc_isDefined (loc))
5397 {
5398 s->definfo = stateInfo_updateLoc (s->definfo,
5399 stateAction_fromSState (ss), loc);
5400 }
5401
5402 s->defstate = ss;
5403 sRef_clearDerived (s);
5404
5405 if (ss == SS_ALLOCATED)
5406 {
5407 sRef base = sRef_getBaseSafe (s);
5408
5409 while (sRef_isReasonable (base) && sRef_isKnown (base))
5410 {
5411 if (base->defstate == SS_DEFINED)
5412 {
5413 sRef nb;
5414
5415 DPRINTF (("set pdefined: %s", sRef_unparseFull (s)));
5416 base->defstate = SS_PDEFINED;
5417 nb = sRef_getBaseSafe (base);
5418 base = nb;
5419 }
5420 else
5421 {
5422 break;
5423 }
5424 }
5425 }
5426 }
5427 }
5428
sRef_setAllocatedComplete(sRef s,fileloc loc)5429 void sRef_setAllocatedComplete (sRef s, fileloc loc)
5430 {
5431 sRef_innerAliasSetComplete (sRef_setAllocated, s, loc);
5432 }
5433
sRef_setAllocatedShallow(sRef s,fileloc loc)5434 static void sRef_setAllocatedShallow (sRef s, fileloc loc)
5435 {
5436 sRef_checkMutable (s);
5437
5438 if (sRef_isReasonable (s))
5439 {
5440 if (s->defstate == SS_DEAD || s->defstate == SS_UNDEFINED)
5441 {
5442 s->defstate = SS_ALLOCATED;
5443 s->definfo = stateInfo_updateLoc (s->definfo, SA_ALLOCATED, loc);
5444 }
5445 }
5446 }
5447
sRef_setAllocatedShallowComplete(sRef s,fileloc loc)5448 void sRef_setAllocatedShallowComplete (sRef s, fileloc loc)
5449 {
5450 sRef_innerAliasSetComplete (sRef_setAllocatedShallow, s, loc);
5451 }
5452
sRef_setAllocated(sRef s,fileloc loc)5453 void sRef_setAllocated (sRef s, fileloc loc)
5454 {
5455 sRef_checkMutable (s);
5456 sRef_setStateAux (s, SS_ALLOCATED, loc);
5457 }
5458
sRef_setPartial(sRef s,fileloc loc)5459 void sRef_setPartial (sRef s, fileloc loc)
5460 {
5461 sRef_checkMutable (s);
5462 sRef_setStateAux (s, SS_PARTIAL, loc);
5463 }
5464
sRef_setShared(sRef s,fileloc loc)5465 void sRef_setShared (sRef s, fileloc loc)
5466 {
5467 sRef_checkMutable (s);
5468
5469 if (sRef_isReasonable (s))
5470 {
5471 if (s->aliaskind != AK_SHARED && fileloc_isDefined (loc))
5472 {
5473 s->aliasinfo = stateInfo_updateLoc (s->aliasinfo, SA_SHARED, loc);
5474 }
5475
5476 s->aliaskind = AK_SHARED;
5477 /* don't! sRef_clearDerived (s); */
5478 }
5479 }
5480
sRef_setLastReference(sRef s,sRef ref,fileloc loc)5481 void sRef_setLastReference (sRef s, /*@exposed@*/ sRef ref, fileloc loc)
5482 {
5483 sRef_checkMutable (s);
5484
5485 if (sRef_isReasonable (s))
5486 {
5487 s->aliaskind = sRef_getAliasKind (ref);
5488 s->aliasinfo = stateInfo_updateRefLoc (s->aliasinfo, ref, stateAction_fromAlkind (s->aliaskind), loc);
5489 }
5490 }
5491
5492 static
sRef_setNullStateAux(sRef s,nstate ns,fileloc loc)5493 void sRef_setNullStateAux (/*@notnull@*/ sRef s, nstate ns, fileloc loc)
5494 {
5495 sRef_checkMutable (s);
5496 s->nullstate = ns;
5497 sRef_resetAliasKind (s);
5498
5499 if (fileloc_isDefined (loc))
5500 {
5501 s->nullinfo = stateInfo_updateLoc (s->nullinfo, stateAction_fromNState (ns), loc);
5502 }
5503 }
5504
sRef_setNotNull(sRef s,fileloc loc)5505 void sRef_setNotNull (sRef s, fileloc loc)
5506 {
5507 if (sRef_isReasonable (s))
5508 {
5509 sRef_setNullStateAux (s, NS_NOTNULL, loc);
5510 }
5511 }
5512
sRef_setNullStateN(sRef s,nstate n)5513 void sRef_setNullStateN (sRef s, nstate n)
5514 {
5515 if (sRef_isReasonable (s))
5516 {
5517 sRef_checkMutable (s);
5518 s->nullstate = n;
5519 DPRINTF (("Set null state ==> %s", sRef_unparseFull (s)));
5520 sRef_resetAliasKind (s);
5521 }
5522 }
5523
sRef_setNullState(sRef s,nstate n,fileloc loc)5524 void sRef_setNullState (sRef s, nstate n, fileloc loc)
5525 {
5526 if (sRef_isReasonable (s))
5527 {
5528 sRef_setNullStateAux (s, n, loc);
5529 }
5530 }
5531
sRef_setNullTerminatedStateInnerComplete(sRef s,struct s_bbufinfo b,fileloc loc)5532 void sRef_setNullTerminatedStateInnerComplete (sRef s, struct s_bbufinfo b, /*@unused@*/ fileloc loc)
5533 {
5534 switch (b.bufstate) {
5535 case BB_NULLTERMINATED:
5536 sRef_setNullTerminatedState (s);
5537 sRef_setLen (s, b.len);
5538 break;
5539 case BB_POSSIBLYNULLTERMINATED:
5540 sRef_setPossiblyNullTerminatedState(s);
5541 break;
5542 case BB_NOTNULLTERMINATED:
5543 sRef_setNotNullTerminatedState (s);
5544 break;
5545 }
5546
5547 sRef_setSize (s, b.size);
5548
5549 /* PL: TO BE DONE : Aliases are not modified right now, have to be similar to
5550 * setNullStateInnerComplete.
5551 */
5552 }
5553
sRef_setNullStateInnerComplete(sRef s,nstate n,fileloc loc)5554 void sRef_setNullStateInnerComplete (sRef s, nstate n, fileloc loc)
5555 {
5556 DPRINTF (("Set null state: %s", nstate_unparse (n)));
5557
5558 sRef_setNullState (s, n, loc);
5559
5560 switch (n)
5561 {
5562 case NS_POSNULL:
5563 sRef_innerAliasSetComplete (sRef_setPosNull, s, loc);
5564 break;
5565 case NS_DEFNULL:
5566 sRef_innerAliasSetComplete (sRef_setDefNull, s, loc);
5567 break;
5568 case NS_UNKNOWN:
5569 sRef_innerAliasSetComplete (sRef_setNullUnknown, s, loc);
5570 break;
5571 case NS_NOTNULL:
5572 sRef_innerAliasSetComplete (sRef_setNotNull, s, loc);
5573 break;
5574 case NS_MNOTNULL:
5575 sRef_innerAliasSetComplete (sRef_setNotNull, s, loc);
5576 break;
5577 case NS_RELNULL:
5578 sRef_innerAliasSetComplete (sRef_setNullUnknown, s, loc);
5579 break;
5580 case NS_CONSTNULL:
5581 sRef_innerAliasSetComplete (sRef_setDefNull, s, loc);
5582 break;
5583 case NS_ABSNULL:
5584 sRef_innerAliasSetComplete (sRef_setNullUnknown, s, loc);
5585 break;
5586 case NS_ERROR:
5587 sRef_innerAliasSetComplete (sRef_setNullErrorLoc, s, loc);
5588 break;
5589 }
5590 }
5591
sRef_setPosNull(sRef s,fileloc loc)5592 void sRef_setPosNull (sRef s, fileloc loc)
5593 {
5594 if (sRef_isReasonable (s))
5595 {
5596 sRef_setNullStateAux (s, NS_POSNULL, loc);
5597 }
5598 }
5599
sRef_setDefNull(sRef s,fileloc loc)5600 void sRef_setDefNull (sRef s, fileloc loc)
5601 {
5602 if (sRef_isReasonable (s))
5603 {
5604 sRef_setNullStateAux (s, NS_DEFNULL, loc);
5605 }
5606 }
5607
sRef_setNullUnknown(sRef s,fileloc loc)5608 void sRef_setNullUnknown (sRef s, fileloc loc)
5609 {
5610 if (sRef_isReasonable (s))
5611 {
5612 sRef_setNullStateAux (s, NS_UNKNOWN, loc);
5613 }
5614 }
5615
sRef_setNullError(sRef s)5616 void sRef_setNullError (sRef s)
5617 {
5618 if (sRef_isReasonable (s) && !sRef_isConst (s))
5619 {
5620 sRef_setNullStateAux (s, NS_UNKNOWN, fileloc_undefined);
5621 }
5622 }
5623
sRef_setNullErrorLoc(sRef s,fileloc loc)5624 void sRef_setNullErrorLoc (sRef s, fileloc loc)
5625 {
5626 if (sRef_isReasonable (s) && !sRef_isConst (s))
5627 {
5628 sRef_setNullStateAux (s, NS_UNKNOWN, loc);
5629 }
5630 }
5631
sRef_setOnly(sRef s,fileloc loc)5632 void sRef_setOnly (sRef s, fileloc loc)
5633 {
5634 if (sRef_isReasonable (s) && s->aliaskind != AK_ONLY)
5635 {
5636 sRef_checkMutable (s);
5637 s->aliaskind = AK_ONLY;
5638 s->aliasinfo = stateInfo_updateLoc (s->aliasinfo, SA_ONLY, loc);
5639 }
5640 }
5641
sRef_setDependent(sRef s,fileloc loc)5642 void sRef_setDependent (sRef s, fileloc loc)
5643 {
5644 if (sRef_isReasonable (s) && !sRef_isConst (s) && (s->aliaskind != AK_DEPENDENT))
5645 {
5646 sRef_checkMutable (s);
5647 DPRINTF (("Setting dependent: %s", sRef_unparseFull (s)));
5648 s->aliaskind = AK_DEPENDENT;
5649 s->aliasinfo = stateInfo_updateLoc (s->aliasinfo, SA_DEPENDENT, loc);
5650 }
5651 }
5652
sRef_setOwned(sRef s,fileloc loc)5653 void sRef_setOwned (sRef s, fileloc loc)
5654 {
5655 if (sRef_isReasonable (s) && !sRef_isConst (s) && (s->aliaskind != AK_OWNED))
5656 {
5657 sRef_checkMutable (s);
5658 s->aliaskind = AK_OWNED;
5659 s->aliasinfo = stateInfo_updateLoc (s->aliasinfo, SA_OWNED, loc);
5660 }
5661 }
5662
sRef_setKept(sRef s,fileloc loc)5663 void sRef_setKept (sRef s, fileloc loc)
5664 {
5665 if (sRef_isReasonable (s) && !sRef_isConst (s) && (s->aliaskind != AK_KEPT))
5666 {
5667 sRef base = sRef_getBaseSafe (s);
5668
5669 while (sRef_isReasonable (base) && sRef_isKnown (base))
5670 {
5671 if (base->defstate == SS_DEFINED)
5672 {
5673 sRef_checkMutable (base);
5674 base->defstate = SS_PDEFINED;
5675 base = sRef_getBaseSafe (base);
5676 }
5677 else
5678 {
5679 break;
5680 }
5681 }
5682
5683 sRef_checkMutable (s);
5684 s->aliaskind = AK_KEPT;
5685 s->aliasinfo = stateInfo_updateLoc (s->aliasinfo, SA_KEPT, loc);
5686 }
5687 }
5688
sRef_setKeptAux(sRef s,fileloc loc)5689 static void sRef_setKeptAux (sRef s, fileloc loc)
5690 {
5691 if (!sRef_isShared (s))
5692 {
5693 sRef_setKept (s, loc);
5694 }
5695 }
5696
sRef_setDependentAux(sRef s,fileloc loc)5697 static void sRef_setDependentAux (sRef s, fileloc loc)
5698 {
5699 if (!sRef_isShared (s))
5700 {
5701 sRef_setDependent (s, loc);
5702 }
5703 }
5704
sRef_setKeptComplete(sRef s,fileloc loc)5705 void sRef_setKeptComplete (sRef s, fileloc loc)
5706 {
5707 sRef_aliasSetComplete (sRef_setKeptAux, s, loc);
5708 }
5709
sRef_setDependentComplete(sRef s,fileloc loc)5710 void sRef_setDependentComplete (sRef s, fileloc loc)
5711 {
5712 sRef_aliasSetComplete (sRef_setDependentAux, s, loc);
5713 }
5714
sRef_setFresh(sRef s,fileloc loc)5715 void sRef_setFresh (sRef s, fileloc loc)
5716 {
5717 if (sRef_isReasonable (s) && !sRef_isConst (s))
5718 {
5719 sRef_checkMutable (s);
5720 s->aliaskind = AK_FRESH;
5721 s->aliasinfo = stateInfo_updateLoc (s->aliasinfo, SA_CREATED, loc);
5722 DPRINTF (("SetFresh: %s", sRef_unparseFull (s)));
5723 }
5724 }
5725
sRef_kill(sRef s,fileloc loc)5726 void sRef_kill (sRef s, fileloc loc)
5727 {
5728 DPRINTF (("Kill: %s", sRef_unparseFull (s)));
5729
5730 if (sRef_isReasonable (s) && !sRef_isShared (s) && !sRef_isConst (s))
5731 {
5732 sRef base = sRef_getBaseSafe (s);
5733 sRef_checkMutable (s);
5734
5735 while (sRef_isReasonable (base) && sRef_isKnown (base))
5736 {
5737 if (base->defstate == SS_DEFINED)
5738 {
5739 sRef_checkMutable (base);
5740 base->defstate = SS_PDEFINED;
5741 base = sRef_getBaseSafe (base);
5742 }
5743 else
5744 {
5745 break;
5746 }
5747 }
5748
5749 s->aliaskind = s->oaliaskind;
5750 s->defstate = SS_DEAD;
5751 s->definfo = stateInfo_updateLoc (s->definfo, SA_KILLED, loc);
5752 DPRINTF (("State info: %s", stateInfo_unparse (s->definfo)));
5753 sRef_clearDerived (s);
5754 }
5755 }
5756
sRef_maybeKill(sRef s,fileloc loc)5757 void sRef_maybeKill (sRef s, fileloc loc)
5758 {
5759 if (sRef_isReasonable (s))
5760 {
5761 sRef base = sRef_getBaseSafe (s);
5762 sRef_checkMutable (s);
5763
5764 while (sRef_isReasonable (base) && sRef_isKnown (base))
5765 {
5766 if (base->defstate == SS_DEFINED || base->defstate == SS_RELDEF)
5767 {
5768 sRef_checkMutable (base);
5769 base->defstate = SS_PDEFINED;
5770 base = sRef_getBaseSafe (base);
5771 }
5772 else
5773 {
5774 break;
5775 }
5776
5777 }
5778
5779 s->aliaskind = s->oaliaskind;
5780 s->defstate = SS_HOFFA;
5781 s->definfo = stateInfo_updateLoc (s->definfo, SA_PKILLED, loc);
5782 DPRINTF (("State info: %s / %s", sRef_unparse (s),
5783 stateInfo_unparse (s->definfo)));
5784 sRef_clearDerived (s);
5785 }
5786
5787 }
5788
5789 /*
5790 ** just for type checking...
5791 */
5792
sRef_killAux(sRef s,fileloc loc)5793 static void sRef_killAux (sRef s, fileloc loc)
5794 {
5795 if (sRef_isReasonable (s) && !sRef_isShared (s))
5796 {
5797 if (sRef_isUnknownArrayFetch (s))
5798 {
5799 sRef_maybeKill (s, loc);
5800 }
5801 else
5802 {
5803 sRef_kill (s, loc);
5804 }
5805 }
5806 }
5807
5808 /*
5809 ** kills s and all aliases to s
5810 */
5811
sRef_killComplete(sRef s,fileloc loc)5812 void sRef_killComplete (sRef s, fileloc loc)
5813 {
5814 DPRINTF (("Kill complete: %s", sRef_unparseFull (s)));
5815 sRef_aliasSetComplete (sRef_killAux, s, loc);
5816 }
5817
sRef_equivalent(sRef s1,sRef s2)5818 static bool sRef_equivalent (sRef s1, sRef s2)
5819 {
5820 return (sRef_compare (s1, s2) == 0);
5821 }
5822
5823 /*
5824 ** returns an sRef that will not be free'd on function exit.
5825 */
5826
sRef_saveCopy(sRef s)5827 /*@only@*/ sRef sRef_saveCopy (sRef s)
5828 {
5829 sRef ret;
5830
5831 if (sRef_isReasonable (s))
5832 {
5833 bool old = inFunction;
5834
5835 /*
5836 ** Exit the function scope, so this sRef is not
5837 ** stored in the deallocation table.
5838 */
5839
5840 inFunction = FALSE;
5841 DPRINTF (("Copying sref: %s", sRef_unparseFull(s)));
5842 ret = sRef_copy (s);
5843 DPRINTF (("Copying ===>: %s", sRef_unparseFull(ret)));
5844 inFunction = old;
5845 }
5846 else
5847 {
5848 ret = sRef_undefined;
5849 }
5850
5851 /*@-dependenttrans@*/
5852 return ret;
5853 /*@=dependenttrans@*/
5854 }
5855
sRef_copy(sRef s)5856 sRef sRef_copy (sRef s)
5857 {
5858 if (sRef_isKindSpecial (s) && !sRef_isGlobalMarker (s))
5859 {
5860 /*@-retalias@*/
5861 return s; /* don't copy specials (except for global markers) */
5862 /*@=retalias@*/
5863 }
5864
5865 if (sRef_isReasonable (s))
5866 {
5867 sRef t = sRef_alloc ();
5868
5869 DPRINTF (("Copying: [%p] %s", s, sRef_unparse (s)));
5870 DPRINTF (("Full: %s", sRef_unparseFull (s)));
5871
5872 t->kind = s->kind;
5873 t->safe = s->safe;
5874 t->modified = s->modified;
5875 t->immut = FALSE; /* Note mutability is not copied. */
5876 t->type = s->type;
5877 t->val = multiVal_copy (s->val);
5878
5879 t->info = sinfo_copy (s);
5880 t->defstate = s->defstate;
5881 t->nullstate = s->nullstate;
5882 DPRINTF (("Set null state==> %s", sRef_unparseFull (t)));
5883
5884
5885 /* start modifications */
5886 t->bufinfo.bufstate = s->bufinfo.bufstate;
5887 t->bufinfo.len = s->bufinfo.len;
5888 t->bufinfo.size = s->bufinfo.size;
5889 /* end modifications */
5890
5891 t->aliaskind = s->aliaskind;
5892 t->oaliaskind = s->oaliaskind;
5893
5894 t->expkind = s->expkind;
5895 t->oexpkind = s->oexpkind;
5896
5897 t->nullinfo = stateInfo_copy (s->nullinfo);
5898 t->aliasinfo = stateInfo_copy (s->aliasinfo);
5899 t->definfo = stateInfo_copy (s->definfo);
5900 t->expinfo = stateInfo_copy (s->expinfo);
5901
5902 t->deriv = sRefSet_newDeepCopy (s->deriv);
5903 t->state = valueTable_copy (s->state);
5904
5905 DPRINTF (("Made copy: %s => %s", sRef_unparseFull (s), sRef_unparseFull (t)));
5906 return t;
5907 }
5908 else
5909 {
5910 return sRef_undefined;
5911 }
5912 }
5913
5914 /*@notfunction@*/
5915 # define PREDTEST(func,s) \
5916 do { if (sRef_isInvalid (s)) { return FALSE; } \
5917 else { if (sRef_isConj (s)) \
5918 { return (func (sRef_getConjA (s)) \
5919 || func (sRef_getConjB (s))); }}} while (FALSE);
5920
sRef_isAddress(sRef s)5921 bool sRef_isAddress (sRef s)
5922 {
5923 PREDTEST (sRef_isAddress, s);
5924 return (s->kind == SK_ADR);
5925 }
5926
5927 /*
5928 ** pretty weak... maybe a flag should control this.
5929 */
5930
sRef_isThroughArrayFetch(sRef s)5931 bool sRef_isThroughArrayFetch (sRef s)
5932 {
5933 if (sRef_isReasonable (s))
5934 {
5935 sRef tref = s;
5936
5937 do
5938 {
5939 sRef lt;
5940
5941 if (sRef_isArrayFetch (tref))
5942 {
5943 return TRUE;
5944 }
5945
5946 lt = sRef_getBase (tref);
5947 tref = lt;
5948 } while (sRef_isReasonable (tref));
5949 }
5950
5951 return FALSE;
5952 }
5953
sRef_isArrayFetch(sRef s)5954 bool sRef_isArrayFetch (sRef s)
5955 {
5956 PREDTEST (sRef_isArrayFetch, s);
5957 return (s->kind == SK_ARRAYFETCH);
5958 }
5959
sRef_isMacroParamRef(sRef s)5960 bool sRef_isMacroParamRef (sRef s)
5961 {
5962 if (context_inMacro () && sRef_isCvar (s))
5963 {
5964 uentry ue = sRef_getUentry (s);
5965 cstring pname = makeParam (uentry_rawName (ue));
5966 uentry mac = usymtab_lookupSafe (pname);
5967
5968 cstring_free (pname);
5969 return (uentry_isValid (mac));
5970 }
5971
5972 return FALSE;
5973 }
5974
sRef_isCvar(sRef s)5975 bool sRef_isCvar (sRef s)
5976 {
5977 PREDTEST (sRef_isCvar, s);
5978 return (s->kind == SK_CVAR);
5979 }
5980
sRef_isConst(sRef s)5981 bool sRef_isConst (sRef s)
5982 {
5983 PREDTEST (sRef_isConst, s);
5984 return (s->kind == SK_CONST);
5985 }
5986
sRef_isObject(sRef s)5987 bool sRef_isObject (sRef s)
5988 {
5989 PREDTEST (sRef_isObject, s);
5990 return (s->kind == SK_OBJECT);
5991 }
5992
sRef_isExternal(sRef s)5993 bool sRef_isExternal (sRef s)
5994 {
5995 PREDTEST (sRef_isExternal, s);
5996 return (s->kind == SK_EXTERNAL);
5997 }
5998
sRef_isDerived(sRef s)5999 static bool sRef_isDerived (sRef s)
6000 {
6001 PREDTEST (sRef_isDerived, s);
6002 return (s->kind == SK_DERIVED);
6003 }
6004
sRef_isField(sRef s)6005 bool sRef_isField (sRef s)
6006 {
6007 PREDTEST (sRef_isField, s);
6008 return (s->kind == SK_FIELD);
6009 }
6010
sRef_isIndex(sRef s)6011 static bool sRef_isIndex (sRef s)
6012 {
6013 PREDTEST (sRef_isIndex, s);
6014 return (s->kind == SK_ARRAYFETCH);
6015 }
6016
sRef_isAnyParam(sRef s)6017 bool sRef_isAnyParam (sRef s)
6018 {
6019 PREDTEST (sRef_isAnyParam, s);
6020 return (s->kind == SK_PARAM);
6021 }
6022
sRef_isParam(sRef s)6023 bool sRef_isParam (sRef s)
6024 {
6025 PREDTEST (sRef_isParam, s);
6026 return (s->kind == SK_PARAM);
6027 }
6028
sRef_isDirectParam(sRef s)6029 bool sRef_isDirectParam (sRef s)
6030 {
6031 PREDTEST (sRef_isDirectParam, s);
6032
6033 return ((s->kind == SK_CVAR) &&
6034 (s->info->cvar->lexlevel == functionScope) &&
6035 (context_inFunction () &&
6036 (s->info->cvar->index <= usymId_fromInt (uentryList_size (context_getParams ())))));
6037 }
6038
sRef_isPointer(sRef s)6039 bool sRef_isPointer (sRef s)
6040 {
6041 PREDTEST (sRef_isPointer, s);
6042 return (s->kind == SK_PTR);
6043 }
6044
6045 /*
6046 ** returns true if storage referenced by s is visible
6047 */
6048
sRef_isReference(sRef s)6049 bool sRef_isReference (sRef s)
6050 {
6051 PREDTEST (sRef_isReference, s);
6052
6053 return (sRef_isPointer (s) || sRef_isIndex (s) || sRef_isFileOrGlobalScope (s)
6054 || (sRef_isField (s) && (sRef_isReference (s->info->field->rec))));
6055 }
6056
sRef_isIReference(sRef s)6057 bool sRef_isIReference (sRef s)
6058 {
6059 return (sRef_isPointer (s) || sRef_isAddress (s) || sRef_isIndex (s)
6060 || sRef_isField (s) || sRef_isArrayFetch (s));
6061 }
6062
sRef_isFileOrGlobalScope(sRef s)6063 bool sRef_isFileOrGlobalScope (sRef s)
6064 {
6065 return (sRef_isCvar (s) && (s->info->cvar->lexlevel <= fileScope));
6066 }
6067
sRef_isRealGlobal(sRef s)6068 bool sRef_isRealGlobal (sRef s)
6069 {
6070 return (sRef_isCvar (s) && (s->info->cvar->lexlevel == globScope));
6071 }
6072
sRef_isFileStatic(sRef s)6073 bool sRef_isFileStatic (sRef s)
6074 {
6075 return (sRef_isCvar (s) && (s->info->cvar->lexlevel == fileScope));
6076 }
6077
sRef_isAliasCheckedGlobal(sRef s)6078 bool sRef_isAliasCheckedGlobal (sRef s)
6079 {
6080 if (sRef_isFileOrGlobalScope (s))
6081 {
6082 uentry ue = sRef_getUentry (s);
6083
6084 return context_checkAliasGlob (ue);
6085 }
6086 else
6087 {
6088 return FALSE;
6089 }
6090 }
6091
sRef_free(sRef s)6092 void sRef_free (/*@only@*/ sRef s)
6093 {
6094 if (s != sRef_undefined && s->kind != SK_SPECIAL)
6095 {
6096 DPRINTF (("Free sref: [%p]", s));
6097
6098 sRef_checkValid (s);
6099
6100 multiVal_free (s->val); /* evans 2002-07-12 */
6101
6102 stateInfo_free (s->expinfo);
6103 stateInfo_free (s->aliasinfo);
6104 stateInfo_free (s->definfo);
6105 stateInfo_free (s->nullinfo);
6106
6107 sRefSet_free (s->deriv);
6108 s->deriv = sRefSet_undefined;
6109
6110 valueTable_free (s->state);
6111 sinfo_free (s);
6112
6113
6114 /* drl added to help locate use after release*/
6115 s->expinfo = stateInfo_undefined;
6116 s->aliasinfo = stateInfo_undefined;
6117 s->definfo = stateInfo_undefined;
6118 s->nullinfo = stateInfo_undefined;
6119
6120 sfree (s);
6121 }
6122 }
6123
sRef_setType(sRef s,ctype t)6124 void sRef_setType (sRef s, ctype t)
6125 {
6126 if (sRef_isReasonable (s))
6127 {
6128 sRef_checkMutable (s);
6129 s->type = t;
6130 }
6131 }
6132
sRef_setTypeFull(sRef s,ctype t)6133 void sRef_setTypeFull (sRef s, ctype t)
6134 {
6135 if (sRef_isReasonable (s))
6136 {
6137 sRef_checkMutable (s);
6138 s->type = t;
6139
6140 sRefSet_allElements (s->deriv, current)
6141 {
6142 sRef_setTypeFull (current, ctype_unknown);
6143 } end_sRefSet_allElements ;
6144 }
6145 }
6146
6147 /*@exposed@*/ sRef
sRef_buildField(sRef rec,cstring f)6148 sRef_buildField (/*@exposed@*/ sRef rec, /*@dependent@*/ cstring f)
6149 {
6150 return (sRef_buildNCField (rec, f));
6151 }
6152
6153 static /*@exposed@*/ sRef
sRef_findDerivedField(sRef rec,cstring f)6154 sRef_findDerivedField (/*@notnull@*/ sRef rec, cstring f)
6155 {
6156 sRefSet_allElements (sRef_derivedFields (rec), sr)
6157 {
6158 if (sRef_isReasonable (sr))
6159 {
6160 if (sRef_isReasonable (sr))
6161 {
6162 if (sr->info != NULL)
6163 {
6164 if (sr->kind == SK_FIELD && cstring_equal (sr->info->field->field, f))
6165 {
6166 return sr;
6167 }
6168 }
6169 }
6170 else
6171 {
6172 llcontbug (message ("Invalid sRef as derived field of %s", sRef_unparse (rec)));
6173 }
6174 }
6175 } end_sRefSet_allElements;
6176
6177 return sRef_undefined;
6178 }
6179
sRef_derivedFields(sRef rec)6180 /*@dependent@*/ /*@observer@*/ sRefSet sRef_derivedFields (/*@temp@*/ sRef rec)
6181 {
6182 if (sRef_isReasonable (rec))
6183 {
6184 sRefSet ret;
6185 ret = rec->deriv;
6186 return (ret);
6187 }
6188 else
6189 {
6190 return (sRefSet_undefined);
6191 }
6192 }
6193
6194 static /*@exposed@*/ sRef
sRef_findDerivedPointer(sRef s)6195 sRef_findDerivedPointer (sRef s)
6196 {
6197 if (sRef_isReasonable (s))
6198 {
6199 sRefSet_realElements (s->deriv, sr)
6200 {
6201 if (sRef_isReasonable (sr) && sr->kind == SK_PTR)
6202 {
6203 return sr;
6204 }
6205 } end_sRefSet_realElements;
6206 }
6207
6208 return sRef_undefined;
6209 }
6210
6211 bool
sRef_isUnknownArrayFetch(sRef s)6212 sRef_isUnknownArrayFetch (sRef s)
6213 {
6214 return (sRef_isReasonable (s)
6215 && s->kind == SK_ARRAYFETCH
6216 && !s->info->arrayfetch->indknown);
6217 }
6218
6219 static /*@exposed@*/ sRef
sRef_findDerivedArrayFetch(sRef s,bool isknown,int idx,bool dead)6220 sRef_findDerivedArrayFetch (/*@notnull@*/ sRef s, bool isknown, int idx, bool dead)
6221 {
6222
6223 if (isknown)
6224 {
6225 sRefSet_realElements (s->deriv, sr)
6226 {
6227 if (sRef_isReasonable (sr)
6228 && sr->kind == SK_ARRAYFETCH
6229 && sr->info->arrayfetch->indknown
6230 && (sr->info->arrayfetch->ind == idx))
6231 {
6232 return sr;
6233 }
6234 } end_sRefSet_realElements;
6235 }
6236 else
6237 {
6238 sRefSet_realElements (s->deriv, sr)
6239 {
6240 if (sRef_isReasonable (sr)
6241 && sr->kind == SK_ARRAYFETCH
6242 && (!sr->info->arrayfetch->indknown
6243 || (sr->info->arrayfetch->indknown &&
6244 sr->info->arrayfetch->ind == 0)))
6245 {
6246 if (sRef_isDead (sr) || sRef_isKept (sr))
6247 {
6248 if (dead || context_getFlag (FLG_STRICTUSERELEASED))
6249 {
6250 return sr;
6251 }
6252 }
6253 else
6254 {
6255 return sr;
6256 }
6257 }
6258 } end_sRefSet_realElements;
6259 }
6260
6261 return sRef_undefined;
6262 }
6263
6264 static /*@exposed@*/ sRef
sRef_buildNCField(sRef rec,cstring f)6265 sRef_buildNCField (/*@exposed@*/ sRef rec, /*@exposed@*/ cstring f)
6266 {
6267 sRef s;
6268
6269 DPRINTF (("Build nc field: %s / %s",
6270 sRef_unparseFull (rec), f));
6271
6272 if (sRef_isInvalid (rec))
6273 {
6274 return sRef_undefined;
6275 }
6276
6277 /*
6278 ** check if the field already has been referenced
6279 */
6280
6281 s = sRef_findDerivedField (rec, f);
6282
6283 if (sRef_isReasonable (s))
6284 {
6285 return s;
6286 }
6287 else
6288 {
6289 ctype ct = ctype_realType (rec->type);
6290
6291 DPRINTF (("Field of: %s", sRef_unparse (rec)));
6292
6293 s = sRef_newRef ();
6294 s->kind = SK_FIELD;
6295 s->info = (sinfo) dmalloc (sizeof (*s->info));
6296 s->info->field = (fldinfo) dmalloc (sizeof (*s->info->field));
6297 s->info->field->rec = rec;
6298 s->info->field->field = f; /* doesn't copy f */
6299
6300 if (ctype_isKnown (ct) && ctype_isSU (ct))
6301 {
6302 uentry ue = uentryList_lookupField (ctype_getFields (ct), f);
6303
6304 if (!uentry_isUndefined (ue))
6305 {
6306 DPRINTF (("lookup: %s for %s", uentry_unparseFull (ue),
6307 ctype_unparse (ct)));
6308
6309 s->type = uentry_getType (ue);
6310
6311 if (ctype_isMutable (s->type)
6312 && rec->aliaskind != AK_STACK
6313 && !alkind_isStatic (rec->aliaskind))
6314 {
6315 s->aliaskind = rec->aliaskind;
6316 }
6317 else
6318 {
6319 s->aliaskind = AK_UNKNOWN;
6320 }
6321
6322 if (sRef_isStateDefined (rec) || sRef_isStateUnknown (rec)
6323 || sRef_isPdefined (rec))
6324 {
6325 sRef_setStateFromUentry (s, ue);
6326 }
6327 else
6328 {
6329 sRef_setPartsFromUentry (s, ue);
6330 }
6331
6332 s->oaliaskind = s->aliaskind;
6333 s->oexpkind = s->expkind;
6334
6335 DPRINTF (("sref: %s", sRef_unparseFull (s)));
6336 }
6337 else
6338 {
6339 /*
6340 Never report this as an error. It can happen whenever there
6341 is casting involved.
6342
6343 if (report)
6344 {
6345 llcontbug (message ("buildNCField --- no field %s: %q / %s",
6346 f, sRef_unparse (s), ctype_unparse (ct)));
6347 }
6348 */
6349
6350 return sRef_undefined;
6351 }
6352 }
6353
6354 if (rec->defstate == SS_DEFINED
6355 && (s->defstate == SS_UNDEFINED || s->defstate == SS_UNKNOWN))
6356 {
6357 s->defstate = SS_DEFINED;
6358 }
6359 else if (rec->defstate == SS_PARTIAL)
6360 {
6361 s->defstate = SS_PARTIAL;
6362 }
6363 else if (rec->defstate == SS_ALLOCATED)
6364 {
6365 if (ctype_isStackAllocated (ct) && ctype_isStackAllocated (s->type))
6366 {
6367 s->defstate = SS_ALLOCATED;
6368 }
6369 else
6370 {
6371 s->defstate = SS_UNDEFINED;
6372 }
6373 }
6374 else if (s->defstate == SS_UNKNOWN)
6375 {
6376 s->defstate = rec->defstate;
6377 }
6378 else
6379 {
6380 ; /* no change */
6381 }
6382
6383 if (s->defstate == SS_UNDEFINED)
6384 {
6385 ctype rt = ctype_realType (s->type);
6386
6387 if (ctype_isArray (rt) || ctype_isSU (rt))
6388 {
6389 s->defstate = SS_ALLOCATED;
6390 }
6391 }
6392
6393 sRef_addDeriv (rec, s);
6394 DPRINTF (("Add deriv: %s", sRef_unparseFull (rec)));
6395
6396 if (ctype_isInt (s->type) && cstring_equal (f, REFSNAME))
6397 {
6398 s->aliaskind = AK_REFS;
6399 s->oaliaskind = AK_REFS;
6400 }
6401
6402 DPRINTF (("Build field ==> %s", sRef_unparseFull (s)));
6403 return s;
6404 }
6405 }
6406
6407 bool
sRef_isStackAllocated(sRef s)6408 sRef_isStackAllocated (sRef s)
6409 {
6410 return (sRef_isReasonable(s)
6411 && s->defstate == SS_ALLOCATED && ctype_isStackAllocated (s->type));
6412 }
6413
6414 static
sRef_setArrayFetchState(sRef s,sRef arr)6415 void sRef_setArrayFetchState (/*@notnull@*/ /*@exposed@*/ sRef s,
6416 /*@notnull@*/ /*@exposed@*/ sRef arr)
6417 {
6418 sRef_checkMutable (s);
6419
6420 if (ctype_isRealAP (arr->type))
6421 {
6422 s->type = ctype_baseArrayPtr (arr->type);
6423 }
6424
6425 /* a hack, methinks... makeArrayFetch (&a[0]) ==> a[] */
6426 /* evans - 2001-08-27: not sure where this was necessary - it
6427 ** causes an assertion in in aliasCheckPred to fail.
6428 */
6429
6430 if (sRef_isAddress (arr))
6431 {
6432 sRef t = arr->info->ref;
6433
6434 if (sRef_isArrayFetch (t))
6435 {
6436 s->info->arrayfetch->arr = t->info->arrayfetch->arr;
6437 }
6438 }
6439 else if (ctype_isRealPointer (arr->type))
6440 {
6441 sRef sp = sRef_findDerivedPointer (arr);
6442
6443 if (sRef_isReasonable (sp))
6444 {
6445
6446 if (ctype_isMutable (s->type))
6447 {
6448 s->expkind = sRef_getExKind (sp);
6449 s->expinfo = stateInfo_copy (sp->expinfo);
6450
6451 s->aliaskind = sp->aliaskind;
6452 s->aliasinfo = stateInfo_copy (sp->aliasinfo);
6453 }
6454
6455 s->defstate = sp->defstate;
6456
6457 if (s->defstate == SS_DEFINED)
6458 {
6459 if (!context_getFlag (FLG_STRICTDESTROY))
6460 {
6461 s->defstate = SS_PARTIAL;
6462 }
6463 }
6464
6465 DPRINTF (("Set null state: %s / %s", sRef_unparseFull (s), sRef_unparseFull (sp)));
6466 sRef_setNullStateN (s, sRef_getNullState (sp));
6467 }
6468 else
6469 {
6470 if (arr->defstate == SS_UNDEFINED)
6471 {
6472 s->defstate = SS_UNUSEABLE;
6473 }
6474 else if ((arr->defstate == SS_ALLOCATED) && !ctype_isSU (s->type))
6475 {
6476 s->defstate = SS_UNDEFINED;
6477 }
6478 else
6479 {
6480 if (!context_getFlag (FLG_STRICTDESTROY))
6481 {
6482 s->defstate = SS_PARTIAL;
6483 }
6484 else
6485 {
6486 s->defstate = SS_DEFINED;
6487 }
6488
6489 /*
6490 ** Very weak checking for array elements.
6491 ** Was:
6492 ** s->defstate = arr->defstate;
6493 */
6494 }
6495
6496 s->expkind = sRef_getExKind (arr);
6497 s->expinfo = stateInfo_copy (arr->expinfo);
6498
6499 if (arr->aliaskind == AK_LOCAL || arr->aliaskind == AK_FRESH)
6500 {
6501 s->aliaskind = AK_LOCAL;
6502 }
6503 else
6504 {
6505 s->aliaskind = AK_UNKNOWN;
6506 }
6507
6508 sRef_setTypeState (s);
6509 }
6510 }
6511 else
6512 {
6513 if (arr->defstate == SS_DEFINED)
6514 {
6515 /*
6516 ** Very weak checking for array elements.
6517 ** Was:
6518 ** s->defstate = arr->defstate;
6519 */
6520
6521 if (context_getFlag (FLG_STRICTDESTROY))
6522 {
6523 s->defstate = SS_DEFINED;
6524 }
6525 else
6526 {
6527 s->defstate = SS_PARTIAL;
6528 }
6529 }
6530 else if (arr->defstate == SS_ALLOCATED)
6531 {
6532 if (ctype_isRealArray (s->type))
6533 {
6534 s->defstate = SS_ALLOCATED;
6535 }
6536 else
6537 {
6538 if (!s->info->arrayfetch->indknown)
6539 {
6540 /*
6541 ** is index is unknown, elements is defined or
6542 ** allocated is any element is!
6543 */
6544
6545 s->defstate = SS_UNDEFINED;
6546
6547 sRefSet_allElements (arr->deriv, sr)
6548 {
6549 if (sRef_isReasonable (sr))
6550 {
6551 if (sRef_isReasonable (sr))
6552 {
6553 if (sr->defstate == SS_ALLOCATED)
6554 {
6555 s->defstate = SS_ALLOCATED;
6556 }
6557 else
6558 {
6559 if (sr->defstate == SS_DEFINED)
6560 {
6561 if (context_getFlag (FLG_STRICTDESTROY))
6562 {
6563 s->defstate = SS_DEFINED;
6564 }
6565 else
6566 {
6567 s->defstate = SS_PARTIAL;
6568 }
6569
6570 break;
6571 }
6572 }
6573 }
6574 else
6575 {
6576 llcontbug (message ("Invalid sRef as derived element of %s", sRef_unparse (arr)));
6577 }
6578 }
6579 } end_sRefSet_allElements;
6580 }
6581 else
6582 {
6583 s->defstate = SS_UNDEFINED;
6584 }
6585 }
6586 }
6587 else
6588 {
6589 s->defstate = arr->defstate;
6590 }
6591
6592
6593 /*
6594 ** kludgey way to guess where aliaskind applies
6595 */
6596
6597 if (ctype_isMutable (s->type)
6598 && !ctype_isPointer (arr->type)
6599 && !alkind_isStatic (arr->aliaskind)
6600 && !alkind_isStack (arr->aliaskind)) /* evs - 2000-06-20: don't pass stack allocation to members */
6601 {
6602 s->aliaskind = arr->aliaskind;
6603 }
6604 else
6605 {
6606 s->aliaskind = AK_UNKNOWN;
6607 }
6608
6609 sRef_setTypeState (s);
6610 }
6611
6612 if (sRef_isObserver (arr))
6613 {
6614 s->expkind = XO_OBSERVER;
6615 s->expinfo = stateInfo_copy (arr->expinfo);
6616 }
6617 }
6618
sRef_buildArrayFetch(sRef arr)6619 /*@exposed@*/ sRef sRef_buildArrayFetch (/*@exposed@*/ sRef arr)
6620 {
6621 sRef s;
6622
6623 if (!sRef_isReasonable (arr)) {
6624 /*@-nullret@*/ return arr /*@=nullret@*/;
6625 }
6626
6627 if (ctype_isRealPointer (arr->type))
6628 {
6629 (void) sRef_buildPointer (arr); /* do this to define arr! */
6630 }
6631
6632 s = sRef_findDerivedArrayFetch (arr, FALSE, 0, FALSE);
6633
6634 if (sRef_isReasonable (s))
6635 {
6636 /* evans 2001-07-12: this is bogus, clean-up hack */
6637 if (s->info->arrayfetch->arr != arr)
6638 {
6639 sRef res;
6640 check (sRefSet_delete (arr->deriv, s));
6641 res = sRef_buildArrayFetch (arr);
6642 sRef_copyState (res, s);
6643 llassert (res->info->arrayfetch->arr == arr);
6644 return res;
6645 }
6646
6647 s->expkind = sRef_getExKind (arr);
6648 s->expinfo = stateInfo_copy (arr->expinfo);
6649
6650 return s;
6651 }
6652 else
6653 {
6654 s = sRef_newRef ();
6655
6656 s->kind = SK_ARRAYFETCH;
6657 s->info = (sinfo) dmalloc (sizeof (*s->info));
6658 s->info->arrayfetch = (ainfo) dmalloc (sizeof (*s->info->arrayfetch));
6659 s->info->arrayfetch->indknown = FALSE;
6660 s->info->arrayfetch->ind = 0;
6661 s->info->arrayfetch->arr = arr;
6662
6663 sRef_setArrayFetchState (s, arr);
6664
6665 s->oaliaskind = s->aliaskind;
6666 s->oexpkind = s->expkind;
6667
6668 if (!context_inProtectVars ())
6669 {
6670 sRef_addDeriv (arr, s);
6671 }
6672
6673 if (valueTable_isUndefined (s->state))
6674 {
6675 s->state = context_createValueTable
6676 (s, stateInfo_makeLoc (g_currentloc, SA_CREATED));
6677 }
6678
6679 return (s);
6680 }
6681 }
6682
6683 /*@exposed@*/ sRef
sRef_buildArrayFetchKnown(sRef arr,int i)6684 sRef_buildArrayFetchKnown (/*@exposed@*/ sRef arr, int i)
6685 {
6686 sRef s;
6687
6688 if (!sRef_isReasonable (arr)) {
6689 /*@-nullret@*/ return arr /*@=nullret@*/;
6690 }
6691
6692 if (ctype_isRealPointer (arr->type))
6693 {
6694 (void) sRef_buildPointer (arr); /* do this to define arr! */
6695 }
6696
6697 s = sRef_findDerivedArrayFetch (arr, TRUE, i, FALSE);
6698
6699 if (sRef_isReasonable (s))
6700 {
6701 /* evans 2001-07-12: this is bogus, clean-up hack */
6702 if (s->info->arrayfetch->arr != arr)
6703 {
6704 sRef res;
6705
6706 check (sRefSet_delete (arr->deriv, s));
6707 res = sRef_buildArrayFetchKnown (arr, i);
6708
6709 llassert (res->info->arrayfetch->arr == arr);
6710 sRef_copyState (res, s);
6711 llassert (res->info->arrayfetch->arr == arr);
6712 return res;
6713 }
6714
6715 s->expkind = sRef_getExKind (arr);
6716 s->expinfo = stateInfo_copy (arr->expinfo);
6717
6718 llassert (s->info->arrayfetch->arr == arr);
6719 return s;
6720 }
6721 else
6722 {
6723 s = sRef_newRef ();
6724
6725 s->kind = SK_ARRAYFETCH;
6726 s->info = (sinfo) dmalloc (sizeof (*s->info));
6727 s->info->arrayfetch = (ainfo) dmalloc (sizeof (*s->info->arrayfetch));
6728 s->info->arrayfetch->arr = arr;
6729 s->info->arrayfetch->indknown = TRUE;
6730 s->info->arrayfetch->ind = i;
6731
6732 sRef_setArrayFetchState (s, arr);
6733 /* evans 2001-08-27 no: can change this - llassert (s->info->arrayfetch->arr == arr); */
6734
6735 s->oaliaskind = s->aliaskind;
6736 s->oexpkind = s->expkind;
6737 sRef_addDeriv (arr, s);
6738
6739 llassert (valueTable_isUndefined (s->state));
6740 s->state = context_createValueTable (s, stateInfo_makeLoc (g_currentloc, SA_CREATED));
6741 return (s);
6742 }
6743 }
6744
6745 /*
6746 ** sets everything except for defstate
6747 */
6748
6749 static void
sRef_setPartsFromUentry(sRef s,uentry ue)6750 sRef_setPartsFromUentry (sRef s, uentry ue)
6751 {
6752 sRef uref = uentry_getSref (ue);
6753
6754 llassert (sRef_isReasonable (s));
6755
6756 s->aliaskind = alkind_derive (s->aliaskind, uentry_getAliasKind (ue));
6757 s->oaliaskind = s->aliaskind;
6758
6759 if (s->expkind == XO_UNKNOWN)
6760 {
6761 s->expkind = uentry_getExpKind (ue);
6762 }
6763
6764 s->oexpkind = s->expkind;
6765
6766 if (sRef_getNullState (s) == NS_UNKNOWN)
6767 {
6768 DPRINTF (("Set null state: %s / %s", sRef_unparseFull (s), uentry_unparseFull (ue)));
6769 sRef_setNullStateN (s, sRef_getNullState (uentry_getSref (ue)));
6770 }
6771 else
6772 {
6773 DPRINTF (("Skipping null null state!"));
6774 }
6775
6776 if (s->aliaskind == AK_IMPONLY && (sRef_isExposed (s) || sRef_isObserver (s)))
6777 {
6778 s->oaliaskind = s->aliaskind = AK_IMPDEPENDENT;
6779 }
6780
6781 if (sRef_isReasonable (uref))
6782 {
6783 valueTable utable = uref->state;
6784 valueTable_free (s->state);
6785 s->state = valueTable_copy (utable);
6786 }
6787 }
6788
6789 static void
sRef_setStateFromAbstractUentry(sRef s,uentry ue)6790 sRef_setStateFromAbstractUentry (sRef s, uentry ue)
6791 {
6792 llassert (sRef_isReasonable (s));
6793 sRef_checkMutable (s);
6794
6795 sRef_setPartsFromUentry (s, ue);
6796
6797 s->aliaskind = alkind_derive (s->aliaskind, uentry_getAliasKind (ue));
6798 s->oaliaskind = s->aliaskind;
6799
6800 if (s->expkind == XO_UNKNOWN)
6801 {
6802 s->expkind = uentry_getExpKind (ue);
6803 }
6804
6805 s->oexpkind = s->expkind;
6806 }
6807
6808 void
sRef_setStateFromUentry(sRef s,uentry ue)6809 sRef_setStateFromUentry (sRef s, uentry ue)
6810 {
6811 sstate defstate;
6812
6813 sRef_checkMutable (s);
6814 llassert (sRef_isReasonable (s));
6815
6816 sRef_setPartsFromUentry (s, ue);
6817
6818 defstate = uentry_getDefState (ue);
6819
6820 if (sstate_isKnown (defstate))
6821 {
6822 s->defstate = defstate;
6823 }
6824 else
6825 {
6826 ;
6827 }
6828 }
6829
6830 /*@exposed@*/ sRef
sRef_buildPointer(sRef t)6831 sRef_buildPointer (/*@exposed@*/ sRef t)
6832 {
6833 DPRINTF (("build pointer: %s", sRef_unparse (t)));
6834
6835 if (sRef_isInvalid (t)) return sRef_undefined;
6836
6837 if (sRef_isAddress (t))
6838 {
6839 DPRINTF (("Return ref: %s", sRef_unparse (t->info->ref)));
6840 return (t->info->ref);
6841 }
6842 else
6843 {
6844 sRef s = sRef_findDerivedPointer (t);
6845
6846 DPRINTF (("find derived: %s", sRef_unparse (s)));
6847
6848 if (sRef_isReasonable (s))
6849 {
6850 s->expkind = sRef_getExKind (t);
6851 s->expinfo = stateInfo_copy (t->expinfo);
6852
6853 s->oaliaskind = s->aliaskind;
6854 s->oexpkind = s->expkind;
6855
6856 return s;
6857 }
6858 else
6859 {
6860 s = sRef_constructPointerAux (t);
6861
6862 DPRINTF (("construct: %s", sRef_unparse (s)));
6863
6864 if (sRef_isReasonable (s))
6865 {
6866 sRef_addDeriv (t, s);
6867
6868 s->oaliaskind = s->aliaskind;
6869 s->oexpkind = s->expkind;
6870 }
6871
6872 return s;
6873 }
6874 }
6875 }
6876
6877 /*@exposed@*/ sRef
sRef_constructPointer(sRef t)6878 sRef_constructPointer (/*@exposed@*/ sRef t)
6879 /*@modifies t@*/
6880 {
6881 return sRef_buildPointer (t);
6882 }
6883
sRef_constructDerefAux(sRef t,bool isdead)6884 static /*@exposed@*/ sRef sRef_constructDerefAux (sRef t, bool isdead)
6885 {
6886 if (sRef_isReasonable (t))
6887 {
6888 sRef s;
6889
6890 /*
6891 ** if there is a derived t[?], return that. Otherwise, *t.
6892 */
6893
6894 s = sRef_findDerivedArrayFetch (t, FALSE, 0, isdead);
6895
6896 if (sRef_isReasonable (s))
6897 {
6898 DPRINTF (("Found array fetch: %s", sRef_unparseFull (s)));
6899 return s;
6900 }
6901 else
6902 {
6903 sRef ret = sRef_constructPointer (t);
6904
6905 DPRINTF (("Constructed pointer: %s", sRef_unparseFull (ret)));
6906
6907 return ret;
6908 }
6909 }
6910 else
6911 {
6912 return sRef_undefined;
6913 }
6914 }
6915
sRef_constructDeref(sRef t)6916 sRef sRef_constructDeref (sRef t)
6917 {
6918 return sRef_constructDerefAux (t, FALSE);
6919 }
6920
sRef_constructDeadDeref(sRef t)6921 sRef sRef_constructDeadDeref (sRef t)
6922 {
6923 return sRef_constructDerefAux (t, TRUE);
6924 }
6925
6926 static sRef
sRef_constructPointerAux(sRef t)6927 sRef_constructPointerAux (/*@notnull@*/ /*@exposed@*/ sRef t)
6928 {
6929 sRef s = sRef_newRef ();
6930 ctype rt = t->type;
6931 ctype st;
6932
6933 llassert (valueTable_isUndefined (s->state));
6934
6935 s->kind = SK_PTR;
6936 s->info = (sinfo) dmalloc (sizeof (*s->info));
6937 s->info->ref = t;
6938
6939 if (ctype_isRealAP (rt))
6940 {
6941 s->type = ctype_baseArrayPtr (rt);
6942 }
6943
6944 st = ctype_realType (s->type);
6945
6946 if (t->defstate == SS_UNDEFINED)
6947 {
6948 s->defstate = SS_UNUSEABLE;
6949 s->definfo = stateInfo_copy (t->definfo);
6950 }
6951 else if ((t->defstate == SS_ALLOCATED) && !ctype_isSU (st))
6952 {
6953 s->defstate = SS_UNDEFINED;
6954 s->definfo = stateInfo_copy (t->definfo);
6955 }
6956 else
6957 {
6958 s->defstate = t->defstate;
6959 s->definfo = stateInfo_copy (t->definfo);
6960 }
6961
6962 if (t->aliaskind == AK_LOCAL || t->aliaskind == AK_FRESH)
6963 {
6964 s->aliaskind = AK_LOCAL;
6965 }
6966 else
6967 {
6968 s->aliaskind = AK_UNKNOWN;
6969 }
6970
6971 s->expkind = sRef_getExKind (t);
6972 s->expinfo = stateInfo_copy (t->expinfo);
6973
6974 sRef_setTypeState (s);
6975
6976 s->oaliaskind = s->aliaskind;
6977 s->oexpkind = s->expkind;
6978
6979 if (valueTable_isUndefined (s->state))
6980 {
6981 s->state = context_createValueTable (s, stateInfo_makeLoc (g_currentloc, SA_CREATED));
6982 }
6983
6984 DPRINTF (("pointer: %s", sRef_unparseFull (s)));
6985 return s;
6986 }
6987
sRef_hasDerived(sRef s)6988 bool sRef_hasDerived (sRef s)
6989 {
6990 return (sRef_isReasonable (s) && !sRefSet_isEmpty (s->deriv));
6991 }
6992
6993 void
sRef_clearDerived(sRef s)6994 sRef_clearDerived (sRef s)
6995 {
6996 if (sRef_isReasonable (s))
6997 {
6998 DPRINTF (("Clear derived: [%p] %s", s, sRef_unparseDebug (s)));
6999 sRefSet_clear (s->deriv);
7000 }
7001 }
7002
7003 void
sRef_clearDerivedComplete(sRef s)7004 sRef_clearDerivedComplete (sRef s)
7005 {
7006 if (sRef_isReasonable (s))
7007 {
7008 sRef base = sRef_getBaseSafe (s);
7009
7010 while (sRef_isReasonable (base))
7011 {
7012 DPRINTF (("Clear derived: [%p] %s", base, sRef_unparse (base)));
7013 sRefSet_clear (base->deriv);
7014 base = sRef_getBaseSafe (base);
7015 }
7016
7017 DPRINTF (("Clear derived: [%p] %s", s, sRef_unparse (s)));
7018 sRefSet_clear (s->deriv);
7019 }
7020 }
7021
sRef_makePointer(sRef s)7022 /*@exposed@*/ sRef sRef_makePointer (/*@exposed@*/ sRef s)
7023 /*@modifies s@*/
7024 {
7025 sRef res = sRef_buildPointer (s);
7026
7027 DPRINTF (("Res: %s", sRef_unparseFull (res)));
7028 return res;
7029 }
7030
7031 /*
7032 ** &a[] => a (this is for out params)
7033 */
7034
7035 /*@exposed@*/ sRef
sRef_makeAnyArrayFetch(sRef arr)7036 sRef_makeAnyArrayFetch (/*@exposed@*/ sRef arr)
7037 {
7038 if (sRef_isAddress (arr))
7039 {
7040 return (arr->info->ref);
7041 }
7042 else
7043 {
7044 return (sRef_buildArrayFetch (arr));
7045 }
7046 }
7047
7048 /*@exposed@*/ sRef
sRef_makeArrayFetch(sRef arr)7049 sRef_makeArrayFetch (/*@exposed@*/ sRef arr)
7050 {
7051 return (sRef_buildArrayFetch (arr));
7052 }
7053
7054 /*@exposed@*/ sRef
sRef_makeArrayFetchKnown(sRef arr,int i)7055 sRef_makeArrayFetchKnown (/*@exposed@*/ sRef arr, int i)
7056 {
7057 return (sRef_buildArrayFetchKnown (arr, i));
7058 }
7059
7060 /*@exposed@*/ sRef
sRef_makeField(sRef rec,cstring f)7061 sRef_makeField (sRef rec, /*@dependent@*/ cstring f)
7062 {
7063 sRef ret;
7064 ret = sRef_buildField (rec, f);
7065 return ret;
7066 }
7067
7068 /*@exposed@*/ sRef
sRef_makeNCField(sRef rec,cstring f)7069 sRef_makeNCField (/*@exposed@*/ sRef rec, /*@dependent@*/ cstring f)
7070 {
7071 return (sRef_buildNCField (rec, f));
7072 }
7073
7074 /*@only@*/ cstring
sRef_unparseKindName(sRef s)7075 sRef_unparseKindName (sRef s)
7076 {
7077 cstring result;
7078
7079 if (s == sRef_undefined) return cstring_makeLiteral ("<invalid>");
7080
7081 s = sRef_fixConj (s);
7082
7083 switch (s->kind)
7084 {
7085 case SK_CVAR:
7086 if (sRef_isLocalVar (s))
7087 {
7088 result = cstring_makeLiteral ("Variable");
7089 }
7090 else
7091 {
7092 result = cstring_makeLiteral ("Undef global");
7093 }
7094 break;
7095 case SK_PARAM:
7096 result = cstring_makeLiteral ("Out parameter");
7097 break;
7098 case SK_ARRAYFETCH:
7099 if (sRef_isAnyParam (s->info->arrayfetch->arr))
7100 {
7101 result = cstring_makeLiteral ("Out parameter");
7102 }
7103 else if (sRef_isIndexKnown (s))
7104 {
7105 result = cstring_makeLiteral ("Array element");
7106 }
7107 else
7108 {
7109 result = cstring_makeLiteral ("Value");
7110 }
7111 break;
7112 case SK_PTR:
7113 if (sRef_isAnyParam (s->info->ref))
7114 {
7115 result = cstring_makeLiteral ("Out parameter");
7116 }
7117 else
7118 {
7119 result = cstring_makeLiteral ("Value");
7120 }
7121 break;
7122 case SK_ADR:
7123 result = cstring_makeLiteral ("Value");
7124 break;
7125 case SK_FIELD:
7126 result = cstring_makeLiteral ("Field");
7127 break;
7128 case SK_OBJECT:
7129 result = cstring_makeLiteral ("Object");
7130 break;
7131 case SK_UNCONSTRAINED:
7132 result = cstring_makeLiteral ("<anything>");
7133 break;
7134 case SK_RESULT:
7135 case SK_SPECIAL:
7136 case SK_UNKNOWN:
7137 case SK_EXTERNAL:
7138 case SK_DERIVED:
7139 case SK_CONST:
7140 case SK_TYPE:
7141 result = cstring_makeLiteral ("<unknown>");
7142 break;
7143 case SK_CONJ:
7144 result = cstring_makeLiteral ("<conj>");
7145 break;
7146 case SK_NEW:
7147 result = cstring_makeLiteral ("Storage");
7148 break;
7149 }
7150
7151 return result;
7152 }
7153
7154 /*@only@*/ cstring
sRef_unparseKindNamePlain(sRef s)7155 sRef_unparseKindNamePlain (sRef s)
7156 {
7157 cstring result;
7158
7159 if (s == sRef_undefined) return cstring_makeLiteral ("<invalid>");
7160
7161 s = sRef_fixConj (s);
7162
7163 switch (s->kind)
7164 {
7165 case SK_CVAR:
7166 if (sRef_isLocalVar (s))
7167 {
7168 result = cstring_makeLiteral ("Variable");
7169 }
7170 else
7171 {
7172 result = cstring_makeLiteral ("Global");
7173 }
7174 break;
7175 case SK_PARAM:
7176 result = cstring_makeLiteral ("Parameter");
7177 break;
7178 case SK_ARRAYFETCH:
7179 if (sRef_isAnyParam (s->info->arrayfetch->arr))
7180 {
7181 result = cstring_makeLiteral ("Parameter");
7182 }
7183 else if (sRef_isIndexKnown (s))
7184 {
7185 result = cstring_makeLiteral ("Array element");
7186 }
7187 else
7188 {
7189 result = cstring_makeLiteral ("Value");
7190 }
7191 break;
7192 case SK_PTR:
7193 if (sRef_isAnyParam (s->info->ref))
7194 {
7195 result = cstring_makeLiteral ("Parameter");
7196 }
7197 else
7198 {
7199 result = cstring_makeLiteral ("Value");
7200 }
7201 break;
7202 case SK_ADR:
7203 result = cstring_makeLiteral ("Value");
7204 break;
7205 case SK_FIELD:
7206 result = cstring_makeLiteral ("Field");
7207 break;
7208 case SK_OBJECT:
7209 result = cstring_makeLiteral ("Object");
7210 break;
7211 case SK_NEW:
7212 result = cstring_makeLiteral ("Storage");
7213 break;
7214 case SK_UNCONSTRAINED:
7215 result = cstring_makeLiteral ("<anything>");
7216 break;
7217 case SK_RESULT:
7218 case SK_TYPE:
7219 case SK_CONST:
7220 case SK_EXTERNAL:
7221 case SK_DERIVED:
7222 case SK_UNKNOWN:
7223 case SK_SPECIAL:
7224 result = cstring_makeLiteral ("<unknown>");
7225 break;
7226 case SK_CONJ:
7227 result = cstring_makeLiteral ("<conj>");
7228 break;
7229 }
7230
7231 return result;
7232 }
7233
7234 /*
7235 ** s1 <- s2
7236 */
7237
7238 void
sRef_copyState(sRef s1,sRef s2)7239 sRef_copyState (sRef s1, sRef s2)
7240 {
7241 if (sRef_isReasonable (s1) && sRef_isReasonable (s2))
7242 {
7243 s1->defstate = s2->defstate;
7244
7245 /* start modifications */
7246 s1->bufinfo.bufstate = s2->bufinfo.bufstate;
7247 s1->bufinfo.len = s2->bufinfo.len;
7248 s1->bufinfo.size = s2->bufinfo.size;
7249 /* end modifications */
7250
7251 s1->aliaskind = s2->aliaskind;
7252 s1->aliasinfo = stateInfo_update (s1->aliasinfo, s2->aliasinfo);
7253
7254 s1->expkind = s2->expkind;
7255 s1->expinfo = stateInfo_update (s1->expinfo, s2->expinfo);
7256
7257 s1->nullstate = s2->nullstate;
7258 DPRINTF (("Set null state==> %s", sRef_unparseFull (s1)));
7259 s1->nullinfo = stateInfo_update (s1->nullinfo, s2->nullinfo);
7260
7261 valueTable_free (s1->state);
7262 s1->state = valueTable_copy (s2->state);
7263 s1->safe = s2->safe;
7264 }
7265 }
7266
7267 sRef
sRef_makeNew(ctype ct,sRef t,cstring name)7268 sRef_makeNew (ctype ct, sRef t, cstring name)
7269 {
7270 sRef s = sRef_newRef ();
7271
7272 s->kind = SK_NEW;
7273 s->type = ct;
7274
7275 llassert (sRef_isReasonable (t));
7276 s->defstate = t->defstate;
7277
7278 s->aliaskind = t->aliaskind;
7279 s->oaliaskind = s->aliaskind;
7280 s->nullstate = t->nullstate;
7281
7282 s->expkind = t->expkind;
7283 s->oexpkind = s->expkind;
7284
7285 s->info = (sinfo) dmalloc (sizeof (*s->info));
7286 s->info->fname = name;
7287
7288 /* start modifications */
7289 s->bufinfo.bufstate = t->bufinfo.bufstate;
7290 /* end modifications */
7291
7292 llassert (valueTable_isUndefined (s->state));
7293 s->state = valueTable_copy (t->state);
7294
7295 DPRINTF (("==> Copying state: %s", valueTable_unparse (s->state)));
7296 DPRINTF (("==> new: %s", sRef_unparseFull (s)));
7297 return s;
7298 }
7299
7300 sRef
sRef_makeType(ctype ct)7301 sRef_makeType (ctype ct)
7302 {
7303 sRef s = sRef_newRef ();
7304
7305 sRef_checkMutable (s);
7306
7307 s->kind = SK_TYPE;
7308 s->type = ct;
7309
7310 s->defstate = SS_UNKNOWN;
7311 s->aliaskind = AK_UNKNOWN;
7312 sRef_setNullStateN (s, NS_UNKNOWN);
7313
7314 /* start modification */
7315 s->bufinfo.bufstate = BB_NOTNULLTERMINATED;
7316 /* end modification */
7317
7318
7319 if (ctype_isUA (ct))
7320 {
7321 typeId uid = ctype_typeId (ct);
7322 uentry ue = usymtab_getTypeEntrySafe (uid);
7323
7324 if (uentry_isValid (ue))
7325 {
7326 sRef_mergeStateQuiet (s, uentry_getSref (ue));
7327 }
7328 }
7329
7330 s->oaliaskind = s->aliaskind;
7331 s->oexpkind = s->expkind;
7332 llassert (valueTable_isUndefined (s->state));
7333 s->state = context_createValueTable (s, stateInfo_makeLoc (g_currentloc, SA_CREATED));
7334
7335 DPRINTF (("Create: %s", sRef_unparseFull (s)));
7336 return s;
7337 }
7338
7339 sRef
sRef_makeConst(ctype ct)7340 sRef_makeConst (ctype ct)
7341 {
7342 sRef s = sRef_newRef ();
7343
7344 s->kind = SK_CONST;
7345 s->type = ct;
7346
7347 s->defstate = SS_UNKNOWN;
7348 s->aliaskind = AK_UNKNOWN;
7349 sRef_setNullStateN (s, NS_UNKNOWN);
7350
7351 /* start modification */
7352 s->bufinfo.bufstate = BB_NULLTERMINATED;
7353 /* end modification */
7354
7355 /* evans 2002-04-22: added isManifestBool to avoid errors for -boolfalse initializations */
7356 if (!ctype_isManifestBool (ct) && ctype_isUA (ct))
7357 {
7358 typeId uid = ctype_typeId (ct);
7359 uentry te = usymtab_getTypeEntrySafe (uid);
7360
7361 if (uentry_isValid (te))
7362 {
7363 sRef_mergeStateQuiet (s, uentry_getSref (te));
7364 }
7365 }
7366
7367 s->oaliaskind = s->aliaskind;
7368 s->oexpkind = s->expkind;
7369
7370 llassert (valueTable_isUndefined (s->state));
7371 s->state = context_createValueTable (s, stateInfo_makeLoc (g_currentloc, SA_CREATED));
7372
7373 return s;
7374 }
7375
sRef_hasName(sRef s)7376 bool sRef_hasName (sRef s)
7377 {
7378 if (sRef_isInvalid (s))
7379 {
7380 return (FALSE);
7381 }
7382
7383 switch (s->kind)
7384 {
7385 case SK_CVAR:
7386 {
7387 uentry u = usymtab_getRefQuiet (s->info->cvar->lexlevel,
7388 s->info->cvar->index);
7389 return (uentry_hasName (u));
7390 }
7391 case SK_PARAM:
7392 {
7393 if (s->info->paramno >= 0)
7394 {
7395 uentry u = uentryList_getN (context_getParams (),
7396 s->info->paramno);
7397
7398 return (uentry_hasName (u));
7399 }
7400 else
7401 {
7402 llassert (s->info->paramno == PARAMUNKNOWN);
7403 return FALSE;
7404 }
7405 }
7406 default:
7407 return TRUE;
7408 }
7409 }
7410
7411 bool
sRef_sameName(sRef s1,sRef s2)7412 sRef_sameName (sRef s1, sRef s2)
7413 {
7414 if (sRef_isInvalid (s1))
7415 {
7416 return sRef_isInvalid (s2);
7417 }
7418
7419 if (sRef_isInvalid (s2))
7420 {
7421 return (FALSE);
7422 }
7423
7424 switch (s1->kind)
7425 {
7426 case SK_CVAR:
7427 if (s2->kind == SK_CVAR)
7428 {
7429 return (s1->info->cvar->lexlevel == s2->info->cvar->lexlevel
7430 && s1->info->cvar->index == s2->info->cvar->index);
7431 }
7432 else if (s2->kind == SK_PARAM)
7433 {
7434 if (context_inFunctionLike ())
7435 {
7436 if (s2->info->paramno != PARAMUNKNOWN)
7437 {
7438 uentry u1 = usymtab_getRefQuiet (s1->info->cvar->lexlevel,
7439 s1->info->cvar->index);
7440 uentry u2 = uentryList_getN (context_getParams (),
7441 s2->info->paramno);
7442
7443 return (cstring_equalFree (uentry_getName (u1),
7444 uentry_getName (u2)));
7445 }
7446 else
7447 {
7448 return s1->info->paramno == PARAMUNKNOWN;
7449 }
7450 }
7451 else
7452 {
7453 return FALSE;
7454 }
7455 }
7456 else
7457 {
7458 return FALSE;
7459 }
7460 case SK_PARAM:
7461 {
7462 if (s2->kind == SK_PARAM)
7463 {
7464 return (s1->info->paramno == s2->info->paramno);
7465 }
7466 else if (s2->kind == SK_CVAR)
7467 {
7468 if (context_inFunctionLike ())
7469 {
7470 if (s1->info->paramno == PARAMUNKNOWN)
7471 {
7472 return FALSE;
7473 }
7474 else
7475 {
7476 uentry u1 = uentryList_getN (context_getParams (),
7477 s1->info->paramno);
7478 uentry u2 = usymtab_getRefQuiet (s2->info->cvar->lexlevel,
7479 s2->info->cvar->index);
7480
7481
7482 return (cstring_equalFree (uentry_getName (u1),
7483 uentry_getName (u2)));
7484 }
7485 }
7486 else
7487 {
7488 return FALSE;
7489 }
7490 }
7491 else
7492 {
7493 return FALSE;
7494 }
7495 }
7496
7497 case SK_UNCONSTRAINED:
7498 return FALSE;
7499
7500 case SK_ARRAYFETCH:
7501 if (s2->kind == SK_ARRAYFETCH)
7502 {
7503 if (bool_equal (s1->info->arrayfetch->indknown,
7504 s2->info->arrayfetch->indknown))
7505 {
7506 if (!s1->info->arrayfetch->indknown
7507 || (s1->info->arrayfetch->ind == s2->info->arrayfetch->ind))
7508 {
7509 return sRef_sameName (s1->info->arrayfetch->arr,
7510 s2->info->arrayfetch->arr);
7511 }
7512 }
7513 }
7514
7515 return FALSE;
7516 case SK_FIELD:
7517 if (s2->kind == SK_FIELD)
7518 {
7519 if (cstring_equal (s1->info->field->field,
7520 s2->info->field->field))
7521 {
7522 return sRef_sameName (s1->info->field->rec,
7523 s2->info->field->rec);
7524 }
7525
7526 }
7527 return FALSE;
7528 case SK_PTR:
7529 case SK_ADR:
7530 case SK_DERIVED:
7531 case SK_EXTERNAL:
7532 if (s2->kind == s1->kind)
7533 {
7534 return sRef_sameName (s1->info->ref,
7535 s2->info->ref);
7536 }
7537
7538 return FALSE;
7539 case SK_OBJECT:
7540 return FALSE;
7541 case SK_CONJ:
7542 return sRef_sameName (sRef_getConjA (s1), s2);
7543 case SK_NEW:
7544 return FALSE;
7545 case SK_UNKNOWN:
7546 return (s2->kind == SK_UNKNOWN);
7547 case SK_TYPE:
7548 case SK_CONST:
7549 if (s2->kind == s1->kind)
7550 {
7551 return (ctype_equal (s1->type, s2->type));
7552 }
7553
7554 return FALSE;
7555 case SK_SPECIAL:
7556 if (s2->kind == SK_SPECIAL)
7557 {
7558 return (s1->info->spec == s2->info->spec);
7559 }
7560 return FALSE;
7561 case SK_RESULT:
7562 return (s2->kind == SK_RESULT);
7563 default:
7564 return FALSE;
7565 }
7566 BADEXIT;
7567 }
7568
7569 sRef
sRef_fixOuterRef(sRef s)7570 sRef_fixOuterRef (/*@returned@*/ sRef s)
7571 {
7572 sRef root = sRef_getRootBase (s);
7573
7574 if (sRef_isCvar (root))
7575 {
7576 uentry ue = usymtab_getRefQuiet (root->info->cvar->lexlevel,
7577 root->info->cvar->index);
7578
7579 if (uentry_isValid (ue))
7580 {
7581 sRef uref = uentry_getSref (ue);
7582 sRef sr = sRef_fixBase (s, uref);
7583
7584 return (sr);
7585 }
7586 else
7587 {
7588 llcontbug (message ("sRef_fixOuterRef: undefined: %q", sRef_unparseDebug (s)));
7589 return (s);
7590 }
7591 }
7592
7593 return (s);
7594 }
7595
7596 void
sRef_storeState(sRef s)7597 sRef_storeState (sRef s)
7598 {
7599 if (sRef_isInvalid (s)) return;
7600
7601 sRef_checkMutable (s);
7602 s->oaliaskind = s->aliaskind;
7603 s->oexpkind = s->expkind;
7604 }
7605
sRef_resetStateAux(sRef s,fileloc loc)7606 static void sRef_resetStateAux (sRef s, /*@unused@*/ fileloc loc)
7607 {
7608 sRef_resetState (s);
7609 }
7610
7611 void
sRef_resetState(sRef s)7612 sRef_resetState (sRef s)
7613 {
7614 bool changed = FALSE;
7615 if (sRef_isInvalid (s)) return;
7616
7617
7618 if (s->oaliaskind == AK_KILLREF && !sRef_isParam (s))
7619 {
7620 /*
7621 ** killref is used in a kludgey way, to save having to add
7622 ** another alias kind (see usymtab_handleParams)
7623 */
7624
7625 if (s->expkind != s->oexpkind)
7626 {
7627 changed = TRUE;
7628 s->expkind = s->oexpkind;
7629 }
7630 }
7631 else
7632 {
7633 if (s->expkind != s->oexpkind)
7634 {
7635 changed = TRUE;
7636 s->expkind = s->oexpkind;
7637 }
7638
7639 if (s->aliaskind != s->oaliaskind
7640 && s->aliaskind != AK_REFCOUNTED
7641 && s->aliaskind != AK_REFS)
7642 {
7643 changed = TRUE;
7644 s->aliaskind = s->oaliaskind;
7645 }
7646 }
7647
7648 if (changed)
7649 {
7650 sRef_clearDerived (s);
7651 }
7652
7653 }
7654
7655 void
sRef_resetStateComplete(sRef s)7656 sRef_resetStateComplete (sRef s)
7657 {
7658 sRef_innerAliasSetComplete (sRef_resetStateAux, s, fileloc_undefined);
7659 }
7660
7661 /*@exposed@*/ sRef
sRef_fixBase(sRef s,sRef base)7662 sRef_fixBase (/*@returned@*/ sRef s, /*@returned@*/ sRef base)
7663 {
7664 sRef tmp = sRef_undefined;
7665 sRef ret;
7666
7667 if (sRef_isInvalid (s)) return s;
7668 if (sRef_isInvalid (base)) return base;
7669
7670 switch (s->kind)
7671 {
7672 case SK_RESULT:
7673 case SK_PARAM:
7674 case SK_CVAR:
7675 ret = base;
7676 break;
7677 case SK_ARRAYFETCH:
7678 tmp = sRef_fixBase (s->info->arrayfetch->arr, base);
7679
7680 if (s->info->arrayfetch->indknown)
7681 {
7682 ret = sRef_makeArrayFetchKnown (tmp, s->info->arrayfetch->ind);
7683 }
7684 else
7685 {
7686 ret = sRef_makeArrayFetch (tmp);
7687 }
7688 break;
7689 case SK_FIELD:
7690 tmp = sRef_fixBase (s->info->field->rec, base);
7691 ret = sRef_buildNCField (tmp, s->info->field->field);
7692 break;
7693 case SK_PTR:
7694 tmp = sRef_fixBase (s->info->ref, base);
7695 ret = sRef_makePointer (tmp);
7696 break;
7697 case SK_ADR:
7698 tmp = sRef_fixBase (s->info->ref, base);
7699 ret = sRef_makeAddress (tmp);
7700 break;
7701 case SK_CONJ:
7702 {
7703 sRef tmpb;
7704
7705 tmp = sRef_fixBase (s->info->conj->a, base);
7706 tmpb = sRef_fixBase (s->info->conj->b, base);
7707
7708 ret = sRef_makeConj (tmp, tmpb);
7709 break;
7710 }
7711 BADDEFAULT;
7712 }
7713
7714 return ret;
7715 }
7716
7717 static /*@exposed@*/ sRef
sRef_fixDirectBase(sRef s,sRef base)7718 sRef_fixDirectBase (sRef s, sRef base)
7719 {
7720 sRef ret;
7721
7722
7723 if (sRef_isInvalid (s))
7724 {
7725 return sRef_undefined;
7726 }
7727
7728 switch (s->kind)
7729 {
7730 case SK_ARRAYFETCH:
7731 if (s->info->arrayfetch->indknown)
7732 {
7733 ret = sRef_makeArrayFetchKnown (base, s->info->arrayfetch->ind);
7734 }
7735 else
7736 {
7737 ret = sRef_makeArrayFetch (base);
7738 }
7739 break;
7740 case SK_FIELD:
7741 ret = sRef_buildNCField (base, s->info->field->field);
7742 break;
7743 case SK_PTR:
7744 ret = sRef_makePointer (base);
7745 break;
7746 case SK_ADR:
7747 ret = sRef_makeAddress (base);
7748 break;
7749 case SK_CONJ:
7750 {
7751 sRef tmpa, tmpb;
7752
7753 tmpa = sRef_fixDirectBase (s->info->conj->a, base);
7754 tmpb = sRef_fixDirectBase (s->info->conj->b, base);
7755
7756 ret = sRef_makeConj (tmpa, tmpb);
7757 break;
7758 }
7759 BADDEFAULT;
7760 }
7761
7762 sRef_copyState (ret, s);
7763 return ret;
7764 }
7765
7766 bool
sRef_isAllocIndexRef(sRef s)7767 sRef_isAllocIndexRef (sRef s)
7768 {
7769 return (sRef_isArrayFetch (s) && !(s->info->arrayfetch->indknown)
7770 && sRef_isAllocated (s->info->arrayfetch->arr));
7771 }
7772
7773 void
sRef_showRefLost(sRef s)7774 sRef_showRefLost (sRef s)
7775 {
7776 if (sRef_hasAliasInfoLoc (s))
7777 {
7778 llgenindentmsg (cstring_makeLiteral ("Original reference lost"),
7779 sRef_getAliasInfoLoc (s));
7780 }
7781 }
7782
7783 void
sRef_showRefKilled(sRef s)7784 sRef_showRefKilled (sRef s)
7785 {
7786 if (sRef_isValid (s))
7787 {
7788 DPRINTF (("Killed: %s", sRef_unparseFull (s)));
7789 if (context_getLocIndentSpaces () == 0) {
7790 stateInfo_display (s->definfo, message (" Storage %q", sRef_unparseOpt (s)));
7791 } else {
7792 stateInfo_display (s->definfo, message ("Storage %q", sRef_unparseOpt (s)));
7793 }
7794 }
7795 }
7796
7797 void
sRef_showStateInconsistent(sRef s)7798 sRef_showStateInconsistent (sRef s)
7799 {
7800 if (sRef_hasStateInfoLoc (s))
7801 {
7802 llgenindentmsg
7803 (message ("Storage %qbecomes inconsistent (released on one branch)",
7804 sRef_unparseOpt (s)),
7805 sRef_getStateInfoLoc (s));
7806 }
7807 }
7808
7809 void
sRef_showStateInfo(sRef s)7810 sRef_showStateInfo (sRef s)
7811 {
7812 if (sRef_isValid (s)) {
7813 if (context_getLocIndentSpaces () == 0) {
7814 stateInfo_display (s->definfo, message (" Storage %q", sRef_unparseOpt (s)));
7815 } else {
7816 stateInfo_display (s->definfo, message ("Storage %q", sRef_unparseOpt (s)));
7817 }
7818 }
7819 }
7820
7821 void
sRef_showExpInfo(sRef s)7822 sRef_showExpInfo (sRef s)
7823 {
7824 if (sRef_isValid (s)) {
7825 if (context_getLocIndentSpaces () == 0) {
7826 stateInfo_display (s->expinfo, message (" Storage %q", sRef_unparseOpt (s)));
7827 } else {
7828 stateInfo_display (s->expinfo, message ("Storage %q", sRef_unparseOpt (s)));
7829 }
7830 }
7831 }
7832
7833 void
sRef_showMetaStateInfo(sRef s,cstring key)7834 sRef_showMetaStateInfo (sRef s, cstring key)
7835 {
7836 stateValue val;
7837 metaStateInfo minfo = context_lookupMetaStateInfo (key);
7838
7839 llassert (sRef_isReasonable (s));
7840 llassert (valueTable_isDefined (s->state));
7841 llassert (metaStateInfo_isDefined (minfo));
7842
7843 val = valueTable_lookup (s->state, key);
7844
7845 if (stateValue_hasLoc (val))
7846 {
7847 llgenindentmsg
7848 (message ("%qbecomes %q", sRef_unparseOpt (s),
7849 stateValue_unparseValue (val, minfo)),
7850 stateValue_getLoc (val));
7851 }
7852 }
7853
7854 void
sRef_showNullInfo(sRef s)7855 sRef_showNullInfo (sRef s)
7856 {
7857 DPRINTF (("Show null info: %s", sRef_unparseFull (s)));
7858
7859 if (sRef_hasNullInfoLoc (s) && sRef_isKnown (s))
7860 {
7861 DPRINTF (("has null info: %s",
7862 fileloc_unparse (sRef_getNullInfoLoc (s))));
7863
7864 switch (sRef_getNullState (s))
7865 {
7866 case NS_CONSTNULL:
7867 {
7868 fileloc loc = sRef_getNullInfoLoc (s);
7869
7870 if (fileloc_isDefined (loc) && !fileloc_isLib (loc))
7871 {
7872 llgenindentmsg
7873 (message ("Storage %qbecomes null", sRef_unparseOpt (s)),
7874 loc);
7875 }
7876 break;
7877 }
7878 case NS_DEFNULL:
7879 {
7880 fileloc loc = sRef_getNullInfoLoc (s);
7881
7882 if (fileloc_isDefined (loc) && !fileloc_isLib (loc))
7883 {
7884 llgenindentmsg (message ("Storage %qbecomes null", sRef_unparseOpt (s)),
7885 loc);
7886 }
7887 break;
7888 }
7889 case NS_ABSNULL:
7890 case NS_POSNULL:
7891 llgenindentmsg
7892 (message ("Storage %qmay become null", sRef_unparseOpt (s)),
7893 sRef_getNullInfoLoc (s));
7894 break;
7895 case NS_NOTNULL:
7896 case NS_MNOTNULL:
7897 llgenindentmsg
7898 (message ("Storage %qbecomes not null", sRef_unparseOpt (s)),
7899 sRef_getNullInfoLoc (s));
7900 break;
7901 case NS_UNKNOWN:
7902 llgenindentmsg
7903 (message ("Storage %qnull state becomes unknown",
7904 sRef_unparseOpt (s)),
7905 sRef_getNullInfoLoc (s));
7906 break;
7907
7908 case NS_ERROR:
7909 BADBRANCHCONT;
7910 break;
7911
7912 default:
7913 llgenindentmsg
7914 (message ("<error case> Storage %q becomes %s",
7915 sRef_unparse (s),
7916 nstate_unparse (sRef_getNullState (s))),
7917 sRef_getNullInfoLoc (s));
7918
7919 break;
7920 }
7921 }
7922 }
7923
7924 void
sRef_showAliasInfo(sRef s)7925 sRef_showAliasInfo (sRef s)
7926 {
7927 if (sRef_isValid (s))
7928 {
7929 if (sRef_isFresh (s))
7930 {
7931 if (context_getLocIndentSpaces () == 0) {
7932 stateInfo_display (s->aliasinfo, message (" Fresh storage %q", sRef_unparseOpt (s)));
7933 } else {
7934 stateInfo_display (s->aliasinfo, message ("Fresh storage %q", sRef_unparseOpt (s)));
7935 }
7936 }
7937 else
7938 {
7939 if (context_getLocIndentSpaces () == 0) {
7940 stateInfo_display (s->aliasinfo, message (" Storage %q", sRef_unparseOpt (s)));
7941 } else {
7942 stateInfo_display (s->aliasinfo, message ("Storage %q", sRef_unparseOpt (s)));
7943 }
7944 }
7945 }
7946 }
7947
7948 void
sRef_mergeNullState(sRef s,nstate n)7949 sRef_mergeNullState (sRef s, nstate n)
7950 {
7951 if (sRef_isReasonable (s))
7952 {
7953 nstate old;
7954
7955 old = sRef_getNullState (s);
7956
7957 if (n != old && n != NS_UNKNOWN)
7958 {
7959 sRef_setNullState (s, n, g_currentloc);
7960 }
7961 }
7962 else
7963 {
7964 llbuglit ("sRef_mergeNullState: invalid");
7965 }
7966 }
7967
7968 bool
sRef_possiblyNull(sRef s)7969 sRef_possiblyNull (sRef s)
7970 {
7971 if (sRef_isReasonable (s))
7972 {
7973 if (sRef_getNullState (s) == NS_ABSNULL)
7974 {
7975 ctype rct = ctype_realType (s->type);
7976
7977 if (ctype_isAbstract (rct))
7978 {
7979 return FALSE;
7980 }
7981 else
7982 {
7983 if (ctype_isUser (rct))
7984 {
7985 uentry ue = usymtab_getTypeEntry (ctype_typeId (rct));
7986
7987 return (nstate_possiblyNull
7988 (sRef_getNullState (uentry_getSref (ue))));
7989 }
7990 else
7991 {
7992 return FALSE;
7993 }
7994 }
7995 }
7996 else
7997 {
7998 return nstate_possiblyNull (sRef_getNullState (s));
7999 }
8000 }
8001
8002 return FALSE;
8003 }
8004
8005 cstring
sRef_getScopeName(sRef s)8006 sRef_getScopeName (sRef s)
8007 {
8008 sRef base = sRef_getRootBase (s);
8009
8010 if (sRef_isRealGlobal (base))
8011 {
8012 return (cstring_makeLiteralTemp ("Global"));
8013 }
8014 else if (sRef_isFileStatic (base))
8015 {
8016 return (cstring_makeLiteralTemp ("Static"));
8017 }
8018 else
8019 {
8020 return (cstring_makeLiteralTemp ("Local"));
8021 }
8022 }
8023
8024 cstring
sRef_unparseScope(sRef s)8025 sRef_unparseScope (sRef s)
8026 {
8027 sRef base = sRef_getRootBase (s);
8028
8029 if (sRef_isRealGlobal (base))
8030 {
8031 return (cstring_makeLiteralTemp ("global"));
8032 }
8033 else if (sRef_isFileStatic (base))
8034 {
8035 return (cstring_makeLiteralTemp ("file static"));
8036 }
8037 else
8038 {
8039 BADEXIT;
8040 }
8041 }
8042
8043 int
sRef_getScope(sRef s)8044 sRef_getScope (sRef s)
8045 {
8046 llassert (sRef_isReasonable (s));
8047
8048 if (sRef_isCvar (s))
8049 {
8050 return s->info->cvar->lexlevel;
8051 }
8052 else if (sRef_isParam (s))
8053 {
8054 return paramsScope;
8055 }
8056 else
8057 {
8058 return fileScope;
8059 }
8060 }
8061
8062 bool
sRef_isDead(sRef s)8063 sRef_isDead (sRef s)
8064 {
8065 return (sRef_isReasonable (s) && (s)->defstate == SS_DEAD);
8066 }
8067
8068 bool
sRef_isDeadStorage(sRef s)8069 sRef_isDeadStorage (sRef s)
8070 {
8071 if (sRef_isReasonable (s))
8072 {
8073 if (s->defstate == SS_DEAD
8074 || s->defstate == SS_UNUSEABLE
8075 || s->defstate == SS_UNDEFINED
8076 || s->defstate == SS_UNKNOWN)
8077 {
8078 return TRUE;
8079 }
8080 else
8081 {
8082 return (sRef_isDefinitelyNull (s));
8083 }
8084 }
8085 else
8086 {
8087 return FALSE;
8088 }
8089 }
8090
8091 bool
sRef_isPossiblyDead(sRef s)8092 sRef_isPossiblyDead (sRef s)
8093 {
8094 return (sRef_isReasonable (s) && s->defstate == SS_HOFFA);
8095 }
8096
sRef_isStateLive(sRef s)8097 bool sRef_isStateLive (sRef s)
8098 {
8099 if (sRef_isReasonable (s))
8100 {
8101 sstate ds = s->defstate;
8102
8103 return (!(ds == SS_UNDEFINED
8104 || ds == SS_DEAD
8105 || ds == SS_UNUSEABLE
8106 || ds == SS_HOFFA));
8107 }
8108 else
8109 {
8110 return FALSE;
8111 }
8112 }
8113
8114
sRef_isStateUndefined(sRef s)8115 bool sRef_isStateUndefined (sRef s)
8116 {
8117 return ((sRef_isReasonable(s)) && ((s)->defstate == SS_UNDEFINED));
8118 }
8119
sRef_isJustAllocated(sRef s)8120 bool sRef_isJustAllocated (sRef s)
8121 {
8122 if (sRef_isAllocated (s))
8123 {
8124 sRefSet_allElements (s->deriv, el)
8125 {
8126 if (!(sRef_isStateUndefined (el) || sRef_isUnuseable (el)))
8127 {
8128 return FALSE;
8129 }
8130 } end_sRefSet_allElements ;
8131
8132 return TRUE;
8133 }
8134
8135 return FALSE;
8136 }
8137
8138 static bool
sRef_isAllocatedStorage(sRef s)8139 sRef_isAllocatedStorage (sRef s)
8140 {
8141 if (sRef_isReasonable (s) && ynm_toBoolStrict (sRef_isValidLvalue (s)))
8142 {
8143 return (ctype_isVisiblySharable (sRef_getType (s)));
8144 }
8145 else
8146 {
8147 return FALSE;
8148 }
8149 }
8150
8151 bool
sRef_isUnuseable(sRef s)8152 sRef_isUnuseable (sRef s)
8153 {
8154 return ((sRef_isValid(s)) && ((s)->defstate == SS_UNUSEABLE));
8155 }
8156
8157 bool
sRef_perhapsNull(sRef s)8158 sRef_perhapsNull (sRef s)
8159 {
8160 if (sRef_isReasonable (s))
8161 {
8162 if (sRef_getNullState (s) == NS_ABSNULL)
8163 {
8164 ctype rct = ctype_realType (s->type);
8165
8166 if (ctype_isAbstract (rct))
8167 {
8168 return FALSE;
8169 }
8170 else
8171 {
8172 if (ctype_isUser (rct))
8173 {
8174 uentry ue = usymtab_getTypeEntry (ctype_typeId (rct));
8175
8176 return (nstate_perhapsNull
8177 (sRef_getNullState (uentry_getSref (ue))));
8178 }
8179 else
8180 {
8181 return FALSE;
8182 }
8183 }
8184 }
8185 else
8186 {
8187 return nstate_perhapsNull (sRef_getNullState (s));
8188 }
8189 }
8190
8191 return FALSE;
8192 }
8193
8194 /*
8195 ** definitelyNull --- called when TRUE is good
8196 */
8197
8198 bool
sRef_definitelyNull(sRef s)8199 sRef_definitelyNull (sRef s)
8200 {
8201 return (sRef_isReasonable (s)
8202 && (sRef_getNullState (s) == NS_DEFNULL || sRef_getNullState (s) == NS_CONSTNULL));
8203 }
8204
8205 /*
8206 ** based on sRef_similar
8207 */
8208
8209 void
sRef_setDerivNullState(sRef set,sRef guide,nstate ns)8210 sRef_setDerivNullState (sRef set, sRef guide, nstate ns)
8211 {
8212 if (sRef_isReasonable (set))
8213 {
8214 sRef deriv = sRef_getDeriv (set, guide);
8215
8216 if (sRef_isReasonable (deriv))
8217 {
8218 sRef_setNullStateN (deriv, ns);
8219 }
8220 }
8221 }
8222
8223 static /*@exposed@*/ sRef
sRef_getDeriv(sRef set,sRef guide)8224 sRef_getDeriv (/*@returned@*/ /*@notnull@*/ sRef set, sRef guide)
8225 {
8226 llassert (sRef_isReasonable (set));
8227 llassert (sRef_isReasonable (guide));
8228
8229 switch (guide->kind)
8230 {
8231 case SK_CVAR:
8232 llassert (set->kind == SK_CVAR);
8233 return set;
8234
8235 case SK_PARAM:
8236 llassert (set->kind == guide->kind);
8237 llassert (set->info->paramno == guide->info->paramno);
8238 return set;
8239
8240 case SK_ARRAYFETCH:
8241
8242 if (set->kind == SK_ARRAYFETCH
8243 && (sRef_similar (set->info->arrayfetch->arr,
8244 guide->info->arrayfetch->arr)))
8245 {
8246 return set;
8247 }
8248 else
8249 {
8250 return (sRef_makeAnyArrayFetch
8251 (sRef_getDeriv (set, guide->info->arrayfetch->arr)));
8252 }
8253
8254 case SK_PTR:
8255
8256 if (set->kind == SK_PTR && sRef_similar (set->info->ref, guide->info->ref))
8257 {
8258 return set;
8259 }
8260 else
8261 {
8262 return (sRef_makePointer (sRef_getDeriv (set, guide->info->ref)));
8263 }
8264
8265 case SK_FIELD:
8266
8267 if ((set->kind == SK_FIELD &&
8268 (sRef_similar (set->info->field->rec, guide->info->field->rec) &&
8269 cstring_equal (set->info->field->field, guide->info->field->field))))
8270 {
8271 return set;
8272 }
8273 else
8274 {
8275 return (sRef_makeField (sRef_getDeriv (set, guide->info->field->rec),
8276 guide->info->field->field));
8277 }
8278 case SK_ADR:
8279
8280 if ((set->kind == SK_ADR) && sRef_similar (set->info->ref, guide->info->ref))
8281 {
8282 return set;
8283 }
8284 else
8285 {
8286 return (sRef_makeAddress (sRef_getDeriv (set, guide->info->ref)));
8287 }
8288
8289 case SK_CONJ:
8290
8291 return sRef_undefined;
8292
8293 case SK_RESULT:
8294 case SK_SPECIAL:
8295 case SK_UNCONSTRAINED:
8296 case SK_TYPE:
8297 case SK_CONST:
8298 case SK_NEW:
8299 case SK_UNKNOWN:
8300 case SK_OBJECT:
8301 case SK_DERIVED:
8302 case SK_EXTERNAL:
8303 return sRef_undefined;
8304 }
8305
8306 BADEXIT;
8307 }
8308
8309 /*
8310 ** sRef_aliasCheckPred
8311 **
8312 ** A confusing but spiffy function:
8313 **
8314 ** Calls predf (s, e, text, <alias>) on s and all of s's aliases
8315 ** (unless checkAliases (s) is FALSE).
8316 **
8317 ** For alias calls, calls as
8318 ** predf (alias, e, text, s)
8319 */
8320
8321 void
sRef_aliasCheckPred(bool (predf)(sRef,exprNode,sRef,exprNode),bool (checkAliases)(sRef),sRef s,exprNode e,exprNode err)8322 sRef_aliasCheckPred (bool (predf) (sRef, exprNode, sRef, exprNode),
8323 /*@null@*/ bool (checkAliases) (sRef),
8324 sRef s, exprNode e, exprNode err)
8325 {
8326 bool error = (*predf)(s, e, sRef_undefined, err);
8327
8328
8329 if (checkAliases != NULL && !(checkAliases (s)))
8330 {
8331 /* don't check aliases */
8332 }
8333 else
8334 {
8335 sRefSet aliases = usymtab_allAliases (s);
8336
8337 sRefSet_realElements (aliases, current)
8338 {
8339 if (sRef_isReasonable (current))
8340 {
8341 if (sRef_isReasonable (current))
8342 {
8343 if (!sRef_similar (current, s)
8344 || (error && sRef_sameName (current, s)))
8345 {
8346 (void) (*predf)(current, e, s, err);
8347 }
8348 }
8349 else
8350 {
8351 llcontbug (message ("Invalid sRef as alias field of %s", sRef_unparse (s)));
8352 }
8353 }
8354 } end_sRefSet_realElements;
8355
8356 sRefSet_free (aliases);
8357 }
8358 }
8359
8360 /*
8361 ** return TRUE iff predf (s) is true for s or any alias of s
8362 */
8363
8364 bool
sRef_aliasCheckSimplePred(sRefTest predf,sRef s)8365 sRef_aliasCheckSimplePred (sRefTest predf, sRef s)
8366 {
8367
8368 if ((*predf)(s))
8369 {
8370 return TRUE;
8371 }
8372 else
8373 {
8374 sRefSet aliases;
8375
8376 aliases = usymtab_allAliases (s);
8377
8378 sRefSet_realElements (aliases, current)
8379 {
8380 if (sRef_isReasonable (current))
8381 {
8382 sRef cref = sRef_updateSref (current);
8383
8384 /* Whoa! a very kludgey way to make sure the right sref is used
8385 ** where there is a conditional symbol table. I am beginning
8386 ** to think that having a conditional symbol table wasn't such
8387 ** a great idea. ;(
8388 */
8389
8390 if ((*predf)(cref))
8391 {
8392 DPRINTF (("Checking alias: %s", sRef_unparseFull (cref)));
8393 sRefSet_free (aliases);
8394 return TRUE;
8395 }
8396 }
8397 } end_sRefSet_realElements;
8398
8399 sRefSet_free (aliases);
8400 }
8401 return FALSE;
8402 }
8403
8404 bool
sRef_aliasCompleteSimplePred(bool (predf)(sRef),sRef s)8405 sRef_aliasCompleteSimplePred (bool (predf) (sRef), sRef s)
8406 {
8407 sRefSet aliases;
8408 bool result = FALSE;
8409
8410
8411 aliases = usymtab_allAliases (s);
8412
8413 if ((*predf)(s)) result = TRUE;
8414
8415
8416 sRefSet_realElements (aliases, current)
8417 {
8418 if (sRef_isReasonable (current))
8419 {
8420 current = sRef_updateSref (current);
8421 if ((*predf)(current)) result = TRUE;
8422 }
8423 } end_sRefSet_realElements;
8424
8425 sRefSet_free (aliases);
8426 return result;
8427 }
8428
8429 void
sRef_aliasSetComplete(void (predf)(sRef,fileloc),sRef s,fileloc loc)8430 sRef_aliasSetComplete (void (predf) (sRef, fileloc), sRef s, fileloc loc)
8431 {
8432 sRefSet aliases;
8433
8434 aliases = usymtab_allAliases (s);
8435
8436 DPRINTF (("All aliases: %s --> %s", sRef_unparseFull (s), sRefSet_unparseFull (aliases)));
8437
8438 (*predf)(s, loc);
8439
8440 sRefSet_realElements (aliases, current)
8441 {
8442 if (sRef_isReasonable (current))
8443 {
8444 DPRINTF (("Update: %s", sRef_unparseFull (current)));
8445 current = sRef_updateSref (current);
8446 DPRINTF (("Updated ==> %s", sRef_unparseFull (current)));
8447 ((*predf)(current, loc));
8448 DPRINTF (("Killed: %s", sRef_unparseFull (current)));
8449 }
8450 } end_sRefSet_realElements;
8451
8452 sRefSet_free (aliases);
8453 }
8454
8455 void
sRef_aliasSetCompleteParam(void (predf)(sRef,int,fileloc),sRef s,int kind,fileloc loc)8456 sRef_aliasSetCompleteParam (void (predf) (sRef, int, fileloc), sRef s,
8457 int kind, fileloc loc)
8458 {
8459 sRefSet aliases;
8460
8461 if (sRef_isDeep (s))
8462 {
8463 aliases = usymtab_allAliases (s);
8464 }
8465 else
8466 {
8467 aliases = usymtab_aliasedBy (s);
8468 }
8469
8470 (*predf)(s, kind, loc);
8471
8472 sRefSet_realElements (aliases, current)
8473 {
8474 if (sRef_isReasonable (current))
8475 {
8476 current = sRef_updateSref (current);
8477 ((*predf)(current, kind, loc));
8478 }
8479 } end_sRefSet_realElements;
8480
8481 sRefSet_free (aliases);
8482 }
8483
8484 /*
8485 ** Version of aliasSetCompleteParam for alkind parameters
8486 */
8487
8488 void
sRef_aliasSetCompleteAlkParam(void (predf)(sRef,alkind,fileloc),sRef s,alkind kind,fileloc loc)8489 sRef_aliasSetCompleteAlkParam (void (predf) (sRef, alkind, fileloc), sRef s,
8490 alkind kind, fileloc loc)
8491 {
8492 sRefSet aliases;
8493
8494 if (sRef_isDeep (s))
8495 {
8496 aliases = usymtab_allAliases (s);
8497 }
8498 else
8499 {
8500 aliases = usymtab_aliasedBy (s);
8501 }
8502
8503 (*predf)(s, kind, loc);
8504
8505 sRefSet_realElements (aliases, current)
8506 {
8507 if (sRef_isReasonable (current))
8508 {
8509 current = sRef_updateSref (current);
8510 ((*predf)(current, kind, loc));
8511 }
8512 } end_sRefSet_realElements;
8513
8514 sRefSet_free (aliases);
8515 }
8516
8517 static void
sRef_innerAliasSetComplete(void (predf)(sRef,fileloc),sRef s,fileloc loc)8518 sRef_innerAliasSetComplete (void (predf) (sRef, fileloc), sRef s, fileloc loc)
8519 {
8520 sRef inner;
8521 sRefSet aliases;
8522 ctype ct;
8523
8524 if (!sRef_isReasonable (s)) return;
8525
8526 /*
8527 ** Type equivalence checking is necessary --- there might be casting.
8528 */
8529
8530 (*predf)(s, loc);
8531
8532 switch (s->kind)
8533 {
8534 case SK_UNCONSTRAINED:
8535 case SK_CVAR:
8536 case SK_PARAM:
8537 break;
8538 case SK_PTR:
8539 inner = s->info->ref;
8540 aliases = usymtab_allAliases (inner);
8541 ct = sRef_getType (inner);
8542
8543 sRefSet_realElements (aliases, current)
8544 {
8545 if (sRef_isReasonable (current))
8546 {
8547 current = sRef_updateSref (current);
8548
8549 if (ctype_equal (ct, sRef_getType (current)))
8550 {
8551 sRef ptr = sRef_makePointer (current);
8552 ((*predf)(ptr, loc));
8553 }
8554 }
8555 } end_sRefSet_realElements;
8556
8557 sRefSet_free (aliases);
8558 break;
8559 case SK_ARRAYFETCH:
8560 inner = s->info->arrayfetch->arr;
8561 aliases = usymtab_allAliases (inner);
8562 ct = sRef_getType (inner);
8563
8564 DPRINTF (("Array fetch: %s", sRefSet_unparse (aliases)));
8565
8566 sRefSet_realElements (aliases, current)
8567 {
8568 if (sRef_isReasonable (current))
8569 {
8570 current = sRef_updateSref (current);
8571 DPRINTF (("Current: %s", sRef_unparseFull (current)));
8572
8573 if (ctype_equal (ct, sRef_getType (current)))
8574 {
8575 if (s->info->arrayfetch->indknown)
8576 {
8577 sRef af = sRef_makeArrayFetchKnown (current, s->info->arrayfetch->ind);
8578 DPRINTF (("Defining: %s", sRef_unparseFull (af)));
8579 /* evans 2001-08-27 This isn't true:
8580 llassert (af->info->arrayfetch->arr == current);
8581 see comments in buildArrayFetchKnown
8582 */
8583 ((*predf)(af, loc));
8584 }
8585 else
8586 {
8587 sRef af = sRef_makeArrayFetch (current);
8588 /* evans 2001-08-27 This isn't true:
8589 llassert (af->info->arrayfetch->arr == current);
8590 see comments in buildArrayFetch
8591 */
8592 DPRINTF (("Defining: %s", sRef_unparseFull (af)));
8593 ((*predf)(af, loc));
8594 }
8595 }
8596 else
8597 {
8598 DPRINTF (("Type mismatch: %s / %s",
8599 ctype_unparse (ct),
8600 ctype_unparse (sRef_getType (current))));
8601 }
8602 }
8603 } end_sRefSet_realElements;
8604
8605 sRefSet_free (aliases);
8606 break;
8607 case SK_FIELD:
8608 inner = s->info->field->rec;
8609 aliases = usymtab_allAliases (inner);
8610 ct = sRef_getType (inner);
8611
8612 sRefSet_realElements (aliases, current)
8613 {
8614 if (sRef_isReasonable (current))
8615 {
8616 current = sRef_updateSref (current);
8617
8618 if (ctype_equal (ct, sRef_getType (current)))
8619 {
8620 sRef f = sRef_makeField (current, s->info->field->field);
8621
8622 ((*predf)(f, loc));
8623 }
8624 }
8625 } end_sRefSet_realElements;
8626
8627 sRefSet_free (aliases);
8628 break;
8629 case SK_CONJ:
8630 sRef_innerAliasSetComplete (predf, s->info->conj->a, loc);
8631 sRef_innerAliasSetComplete (predf, s->info->conj->b, loc);
8632 break;
8633 case SK_SPECIAL:
8634 case SK_ADR:
8635 case SK_TYPE:
8636 case SK_CONST:
8637 case SK_NEW:
8638 case SK_UNKNOWN:
8639 case SK_OBJECT:
8640 case SK_DERIVED:
8641 case SK_EXTERNAL:
8642 case SK_RESULT:
8643 break;
8644 }
8645 }
8646
8647 static void
sRef_innerAliasSetCompleteParam(void (predf)(sRef,sRef),sRef s,sRef t)8648 sRef_innerAliasSetCompleteParam (void (predf) (sRef, sRef), sRef s, sRef t)
8649 {
8650 sRef inner;
8651 sRefSet aliases;
8652 ctype ct;
8653
8654 if (!sRef_isReasonable (s)) return;
8655
8656 /*
8657 ** Type equivalence checking is necessary --- there might be casting.
8658 */
8659
8660 (*predf)(s, t);
8661
8662 switch (s->kind)
8663 {
8664 case SK_UNCONSTRAINED:
8665 case SK_CVAR:
8666 case SK_PARAM:
8667 break;
8668 case SK_PTR:
8669 inner = s->info->ref;
8670 aliases = usymtab_allAliases (inner);
8671 ct = sRef_getType (inner);
8672
8673 sRefSet_realElements (aliases, current)
8674 {
8675 if (sRef_isReasonable (current))
8676 {
8677 current = sRef_updateSref (current);
8678
8679 if (ctype_equal (ct, sRef_getType (current)))
8680 {
8681 sRef ptr = sRef_makePointer (current);
8682
8683 ((*predf)(ptr, t));
8684 }
8685 }
8686 } end_sRefSet_realElements;
8687
8688 sRefSet_free (aliases);
8689 break;
8690 case SK_ARRAYFETCH:
8691 inner = s->info->arrayfetch->arr;
8692 aliases = usymtab_allAliases (inner);
8693 ct = sRef_getType (inner);
8694
8695 sRefSet_realElements (aliases, current)
8696 {
8697 if (sRef_isReasonable (current))
8698 {
8699 current = sRef_updateSref (current);
8700
8701 if (ctype_equal (ct, sRef_getType (current)))
8702 {
8703
8704 if (s->info->arrayfetch->indknown)
8705 {
8706 sRef af = sRef_makeArrayFetchKnown (current, s->info->arrayfetch->ind);
8707
8708 ((*predf)(af, t));
8709 }
8710 else
8711 {
8712 sRef af = sRef_makeArrayFetch (current);
8713
8714 ((*predf)(af, t));
8715 }
8716 }
8717 }
8718 } end_sRefSet_realElements;
8719
8720 sRefSet_free (aliases);
8721 break;
8722 case SK_FIELD:
8723 inner = s->info->field->rec;
8724 aliases = usymtab_allAliases (inner);
8725 ct = sRef_getType (inner);
8726
8727
8728 sRefSet_realElements (aliases, current)
8729 {
8730 if (sRef_isReasonable (current))
8731 {
8732 current = sRef_updateSref (current);
8733
8734 if (ctype_equal (ct, sRef_getType (current)))
8735 {
8736 sRef f = sRef_makeField (current, s->info->field->field);
8737
8738 ((*predf)(f, t));
8739 }
8740 }
8741 } end_sRefSet_realElements;
8742
8743 sRefSet_free (aliases);
8744 break;
8745 case SK_CONJ:
8746 sRef_innerAliasSetCompleteParam (predf, s->info->conj->a, t);
8747 sRef_innerAliasSetCompleteParam (predf, s->info->conj->b, t);
8748 break;
8749 case SK_SPECIAL:
8750 case SK_ADR:
8751 case SK_TYPE:
8752 case SK_CONST:
8753 case SK_NEW:
8754 case SK_UNKNOWN:
8755 case SK_OBJECT:
8756 case SK_DERIVED:
8757 case SK_EXTERNAL:
8758 case SK_RESULT:
8759 break;
8760 }
8761 }
8762
sRef_combineExKinds(sRef res,sRef other)8763 static void sRef_combineExKinds (/*@notnull@*/ sRef res, /*@notnull@*/ sRef other)
8764 {
8765 exkind a1 = sRef_getExKind (res);
8766 exkind a2 = sRef_getExKind (other);
8767
8768 if (a1 == a2 || a2 == XO_UNKNOWN)
8769 {
8770 ;
8771 }
8772 else if (a1 == XO_UNKNOWN)
8773 {
8774 res->expinfo = stateInfo_update (res->expinfo, other->expinfo);
8775 res->expkind = a2;
8776 }
8777 else
8778 {
8779 res->expkind = XO_OBSERVER;
8780 }
8781 }
8782
8783 /*
8784 ** Currently, this is a very ad hoc implementation, with lots of fixes to
8785 ** make real code work okay. I need to come up with some more general
8786 ** rules or principles here.
8787 */
8788
8789 static void
sRef_combineAliasKindsError(sRef res,sRef other,clause cl,fileloc loc)8790 sRef_combineAliasKindsError (/*@notnull@*/ sRef res,
8791 /*@notnull@*/ sRef other,
8792 clause cl, fileloc loc)
8793 {
8794 bool hasError = FALSE;
8795 alkind ares = sRef_getAliasKind (res);
8796 alkind aother = sRef_getAliasKind (other);
8797
8798 sRef_checkMutable (res);
8799
8800 if (alkind_isDependent (ares))
8801 {
8802 if (aother == AK_KEPT)
8803 {
8804 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8805 res->aliaskind = AK_KEPT;
8806 }
8807 else
8808 {
8809 if (aother == AK_LOCAL || aother == AK_STATIC
8810 || alkind_isTemp (aother))
8811 {
8812 DPRINTF (("Setting dependent: %s", sRef_unparseFull (res)));
8813 res->aliaskind = AK_DEPENDENT;
8814 }
8815 }
8816 }
8817 else if (alkind_isDependent (aother))
8818 {
8819 if (ares == AK_KEPT)
8820 {
8821 res->aliaskind = AK_KEPT;
8822 }
8823 else
8824 {
8825 if (ares == AK_LOCAL || ares == AK_STATIC || alkind_isTemp (ares))
8826 {
8827 DPRINTF (("Setting dependent: %s", sRef_unparseFull (res)));
8828 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8829 res->aliaskind = AK_DEPENDENT;
8830 }
8831 }
8832 }
8833 else if ((ares == AK_LOCAL || ares == AK_UNIQUE
8834 || ares == AK_STATIC || alkind_isTemp (ares))
8835 && sRef_isFresh (other))
8836 {
8837 /*
8838 ** cases like: if (s == NULL) s = malloc...;
8839 ** don't generate errors
8840 */
8841
8842 if (usymtab_isAltDefinitelyNullDeep (res))
8843 {
8844 res->aliaskind = ares;
8845 }
8846 else
8847 {
8848 hasError = TRUE;
8849 }
8850 }
8851 else if ((aother == AK_LOCAL || aother == AK_UNIQUE
8852 || aother == AK_STATIC || alkind_isTemp (aother))
8853 && sRef_isFresh (res))
8854 {
8855 /*
8856 ** cases like: if (s == NULL) s = malloc...;
8857 ** don't generate errors
8858 */
8859
8860 if (usymtab_isDefinitelyNullDeep (other))
8861 {
8862 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8863 res->aliaskind = aother;
8864 }
8865 else
8866 {
8867 hasError = TRUE;
8868 }
8869 }
8870 else if (ares == AK_NEWREF && aother == AK_REFCOUNTED
8871 && sRef_isConst (other))
8872 {
8873 res->aliaskind = AK_NEWREF;
8874 }
8875 else if (aother == AK_NEWREF && ares == AK_REFCOUNTED
8876 && sRef_isConst (res))
8877 {
8878 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8879 res->aliaskind = AK_NEWREF;
8880 }
8881 else if (sRef_isLocalVar (res)
8882 && ((ares == AK_KEPT && aother == AK_LOCAL)
8883 || (aother == AK_KEPT && ares == AK_LOCAL)))
8884 {
8885 res->aliaskind = AK_KEPT;
8886 }
8887 else if ((ares == AK_OWNED && aother == AK_ONLY)
8888 || (aother == AK_OWNED && ares == AK_ONLY))
8889 {
8890 res->aliaskind = AK_OWNED;
8891
8892 if (aother == AK_OWNED)
8893 {
8894 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8895 }
8896 }
8897 else
8898 {
8899 hasError = TRUE;
8900 }
8901
8902 if (hasError)
8903 {
8904 if (sRef_isThroughArrayFetch (res))
8905 {
8906 if (optgenerror2
8907 (FLG_BRANCHSTATE, FLG_STRICTBRANCHSTATE,
8908 message
8909 ("Clauses exit with %q possibly referencing %s storage %s, "
8910 "%s storage %s",
8911 sRef_unparse (res),
8912 alkind_unparse (aother),
8913 clause_nameTaken (cl),
8914 alkind_unparse (ares),
8915 clause_nameAlternate (cl)),
8916 loc))
8917 {
8918 sRef_showAliasInfo (res);
8919 sRef_showAliasInfo (other);
8920 res->aliaskind = AK_ERROR;
8921 }
8922 else
8923 {
8924 if (ares == AK_KEPT || aother == AK_KEPT)
8925 {
8926 sRef_maybeKill (res, loc);
8927 }
8928 }
8929 }
8930 else
8931 {
8932 if (optgenerror
8933 (FLG_BRANCHSTATE,
8934 message ("Clauses exit with %q referencing %s storage %s, "
8935 "%s storage %s",
8936 sRef_unparse (res),
8937 alkind_unparse (aother),
8938 clause_nameTaken (cl),
8939 alkind_unparse (ares),
8940 clause_nameAlternate (cl)),
8941 loc))
8942 {
8943 sRef_showAliasInfo (res);
8944 sRef_showAliasInfo (other);
8945
8946 res->aliaskind = AK_ERROR;
8947 }
8948 }
8949
8950 res->aliaskind = (sRef_isLocalVar (res) ? AK_LOCAL : AK_UNKNOWN);
8951 }
8952 }
8953
8954 static void
sRef_combineAliasKinds(sRef res,sRef other,clause cl,fileloc loc)8955 sRef_combineAliasKinds (/*@notnull@*/ sRef res, /*@notnull@*/ sRef other,
8956 clause cl, fileloc loc)
8957 {
8958 alkind ares = sRef_getAliasKind (res);
8959 alkind aother = sRef_getAliasKind (other);
8960
8961 sRef_checkMutable (res);
8962
8963 DPRINTF (("Combine alias kinds: \n\t%s / \n\t%s",
8964 sRef_unparseFull (res), sRef_unparseFull (other)));
8965 if (alkind_equal (ares, aother)
8966 || aother == AK_UNKNOWN
8967 || aother == AK_ERROR)
8968 {
8969 ; /* keep current state */
8970 }
8971 else if (sRef_isDead (res) || sRef_isDead (other))
8972 {
8973 /* dead error reported (or storage is dead) */
8974 res ->aliaskind = AK_ERROR;
8975 }
8976 else if (ares == AK_UNKNOWN || ares == AK_ERROR
8977 || sRef_isStateUndefined (res)
8978 || sRef_isDefinitelyNull (res))
8979 {
8980 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8981 res->aliaskind = aother;
8982 }
8983 else if (sRef_isStateUndefined (other)
8984 || sRef_isDefinitelyNull (other))
8985 {
8986 ;
8987 }
8988 else if (((ares == AK_UNIQUE || alkind_isTemp (ares))
8989 && aother == AK_LOCAL)
8990 || ((aother == AK_UNIQUE || alkind_isTemp (aother))
8991 && ares == AK_LOCAL))
8992 {
8993 if (ares != AK_LOCAL)
8994 {
8995 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8996 }
8997
8998 res->aliaskind = AK_LOCAL;
8999 }
9000 else if ((ares == AK_OWNED && aother == AK_FRESH)
9001 || (aother == AK_OWNED && ares == AK_FRESH))
9002 {
9003 if (ares != AK_FRESH)
9004 {
9005 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
9006 }
9007
9008 res->aliaskind = AK_FRESH;
9009 }
9010 else if ((ares == AK_KEEP && aother == AK_FRESH) ||
9011 (aother == AK_KEEP && ares == AK_FRESH))
9012 {
9013 if (ares != AK_KEEP)
9014 {
9015 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
9016 }
9017
9018 res->aliaskind = AK_KEEP;
9019 }
9020 else if ((ares == AK_LOCAL && aother == AK_STACK) ||
9021 (aother == AK_LOCAL && ares == AK_STACK))
9022 {
9023 if (ares != AK_STACK)
9024 {
9025 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
9026 }
9027
9028 res->aliaskind = AK_STACK;
9029 }
9030 else if ((ares == AK_LOCAL
9031 && (aother == AK_OWNED && sRef_isLocalVar (other)))
9032 || (aother == AK_LOCAL
9033 && (ares == AK_OWNED && sRef_isLocalVar (res))))
9034 {
9035 if (ares != AK_LOCAL)
9036 {
9037 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
9038 }
9039
9040 res->aliaskind = AK_LOCAL;
9041 }
9042 else if ((ares == AK_FRESH && alkind_isOnly (aother))
9043 || (aother == AK_FRESH && alkind_isOnly (ares)))
9044 {
9045 res->aliaskind = AK_FRESH;
9046 }
9047 else if ((aother == AK_FRESH && sRef_definitelyNull (res))
9048 || (ares == AK_FRESH && sRef_definitelyNull (other)))
9049 {
9050 if (ares != AK_FRESH)
9051 {
9052 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
9053 res->aliaskind = AK_FRESH;
9054 }
9055 }
9056 else if ((sRef_isFresh (res) && sRef_isConst (other))
9057 || (sRef_isFresh (other) && sRef_isConst (res)))
9058 {
9059 /*
9060 ** for NULL constantants
9061 ** this is bogus!
9062 */
9063
9064 if (!sRef_isFresh (res))
9065 {
9066 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
9067 }
9068
9069 res->aliaskind = AK_FRESH;
9070 }
9071 else if ((alkind_isStatic (aother) && sRef_isConst (res))
9072 || (alkind_isStatic (ares) && sRef_isConst (other)))
9073 {
9074 if (!alkind_isStatic (ares))
9075 {
9076 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
9077 res->aliaskind = AK_STATIC;
9078 }
9079 }
9080 else
9081 {
9082 sRef_combineAliasKindsError (res, other, cl, loc);
9083 }
9084 }
9085
sRef_combineDefState(sRef res,sRef other)9086 static void sRef_combineDefState (/*@notnull@*/ sRef res,
9087 /*@notnull@*/ sRef other)
9088 {
9089 sstate s1 = res->defstate;
9090 sstate s2 = other->defstate;
9091 bool flip = FALSE;
9092
9093 sRef_checkMutable (res);
9094
9095 if (s1 == s2 || s2 == SS_UNKNOWN)
9096 {
9097 ;
9098 }
9099 else if (s1 == SS_UNKNOWN)
9100 {
9101 flip = TRUE;
9102 }
9103 else
9104 {
9105 switch (s1)
9106 {
9107 case SS_FIXED:
9108 if (s2 == SS_DEFINED)
9109 {
9110 break;
9111 }
9112 else
9113 {
9114 llcontbuglit ("ssfixed: not implemented");
9115 flip = TRUE;
9116 }
9117 break;
9118 case SS_DEFINED:
9119 flip = TRUE;
9120 break;
9121 case SS_PDEFINED:
9122 case SS_ALLOCATED:
9123 flip = (s2 != SS_DEFINED);
9124 break;
9125 case SS_HOFFA:
9126 case SS_RELDEF:
9127 case SS_UNUSEABLE:
9128 case SS_UNDEFINED:
9129 case SS_PARTIAL:
9130 case SS_UNDEFGLOB:
9131 case SS_KILLED:
9132 case SS_DEAD:
9133 case SS_SPECIAL:
9134 break;
9135 BADDEFAULT;
9136 }
9137 }
9138
9139 if (flip)
9140 {
9141 res->definfo = stateInfo_update (res->definfo, other->definfo);
9142 res->defstate = s2;
9143 }
9144 }
9145
sRef_getConjA(sRef s)9146 extern /*@notnull@*/ sRef sRef_getConjA (sRef s)
9147 {
9148 sRef ret;
9149 llassert (sRef_isConj (s));
9150
9151 ret = s->info->conj->a;
9152 llassert (ret != NULL);
9153 return ret;
9154 }
9155
sRef_getConjB(sRef s)9156 extern /*@notnull@*/ sRef sRef_getConjB (sRef s)
9157 {
9158 sRef ret;
9159 llassert (sRef_isConj (s));
9160
9161 ret = s->info->conj->b;
9162 llassert (ret != NULL);
9163 return ret;
9164 }
9165
sRef_makeArrow(sRef s,cstring f)9166 extern /*@exposed@*/ sRef sRef_makeArrow (sRef s, /*@dependent@*/ cstring f)
9167 {
9168 sRef p;
9169 sRef ret;
9170
9171 p = sRef_makePointer (s);
9172 ret = sRef_makeField (p, f);
9173 DPRINTF (("Arrow: %s => %s",
9174 sRef_unparseFull (s), sRef_unparseFull (ret)));
9175 return ret;
9176 }
9177
sRef_buildArrow(sRef s,cstring f)9178 extern /*@exposed@*/ sRef sRef_buildArrow (sRef s, cstring f)
9179 {
9180 sRef p;
9181 sRef ret;
9182
9183 p = sRef_buildPointer (s);
9184 ret = sRef_buildField (p, f);
9185
9186 return ret;
9187 }
9188
sinfo_copy(sRef s)9189 static /*@null@*/ sinfo sinfo_copy (/*@notnull@*/ sRef s)
9190 {
9191 sinfo ret;
9192
9193 switch (s->kind)
9194 {
9195 case SK_CVAR:
9196 ret = (sinfo) dmalloc (sizeof (*ret));
9197 ret->cvar = (cref) dmalloc (sizeof (*ret->cvar));
9198 ret->cvar->lexlevel = s->info->cvar->lexlevel;
9199 ret->cvar->index = s->info->cvar->index;
9200 break;
9201
9202 case SK_PARAM:
9203 ret = (sinfo) dmalloc (sizeof (*ret));
9204 ret->paramno = s->info->paramno;
9205 llassert (ret->paramno >= -1);
9206 break;
9207
9208 case SK_ARRAYFETCH:
9209 ret = (sinfo) dmalloc (sizeof (*ret));
9210 ret->arrayfetch = (ainfo) dmalloc (sizeof (*ret->arrayfetch));
9211 ret->arrayfetch->indknown = s->info->arrayfetch->indknown;
9212 ret->arrayfetch->ind = s->info->arrayfetch->ind;
9213 ret->arrayfetch->arr = s->info->arrayfetch->arr;
9214 break;
9215
9216 case SK_FIELD:
9217 ret = (sinfo) dmalloc (sizeof (*ret));
9218 ret->field = (fldinfo) dmalloc (sizeof (*ret->field));
9219 ret->field->rec = s->info->field->rec;
9220 ret->field->field = s->info->field->field;
9221 break;
9222
9223 case SK_OBJECT:
9224 ret = (sinfo) dmalloc (sizeof (*ret));
9225 ret->object = s->info->object;
9226 break;
9227
9228 case SK_PTR:
9229 case SK_ADR:
9230 case SK_DERIVED:
9231 case SK_EXTERNAL:
9232 ret = (sinfo) dmalloc (sizeof (*ret));
9233 ret->ref = s->info->ref; /* Ref_copy (s->info->ref); */
9234 break;
9235
9236 case SK_CONJ:
9237 ret = (sinfo) dmalloc (sizeof (*ret));
9238 ret->conj = (cjinfo) dmalloc (sizeof (*ret->conj));
9239 ret->conj->a = s->info->conj->a; /* sRef_copy (s->info->conj->a); */
9240 ret->conj->b = s->info->conj->b; /* sRef_copy (s->info->conj->b);*/
9241 break;
9242 case SK_SPECIAL:
9243 ret = (sinfo) dmalloc (sizeof (*ret));
9244 ret->spec = s->info->spec;
9245 break;
9246
9247 case SK_UNCONSTRAINED:
9248 case SK_NEW:
9249 ret = (sinfo) dmalloc (sizeof (*ret));
9250 ret->fname = s->info->fname;
9251 break;
9252
9253 case SK_RESULT:
9254 case SK_CONST:
9255 case SK_TYPE:
9256 case SK_UNKNOWN:
9257 llassertprint (s->info == NULL, ("s = %s", sRef_unparse (s)));
9258 ret = NULL;
9259 break;
9260 }
9261
9262 return ret;
9263 }
9264
sinfo_fullCopy(sRef s)9265 static /*@null@*/ sinfo sinfo_fullCopy (/*@notnull@*/ sRef s)
9266 {
9267 sinfo ret;
9268
9269 /*
9270 ** Since its a full copy, only storage is assigned
9271 ** to dependent fields.
9272 */
9273 /*@-onlytrans@*/
9274
9275 switch (s->kind)
9276 {
9277 case SK_CVAR:
9278 ret = (sinfo) dmalloc (sizeof (*ret));
9279 ret->cvar = (cref) dmalloc (sizeof (*ret->cvar));
9280 ret->cvar->lexlevel = s->info->cvar->lexlevel;
9281 ret->cvar->index = s->info->cvar->index;
9282 break;
9283
9284 case SK_PARAM:
9285 ret = (sinfo) dmalloc (sizeof (*ret));
9286 ret->paramno = s->info->paramno;
9287 llassert (ret->paramno >= -1);
9288 break;
9289
9290 case SK_ARRAYFETCH:
9291 ret = (sinfo) dmalloc (sizeof (*ret));
9292 ret->arrayfetch = (ainfo) dmalloc (sizeof (*ret->arrayfetch));
9293 ret->arrayfetch->indknown = s->info->arrayfetch->indknown;
9294 ret->arrayfetch->ind = s->info->arrayfetch->ind;
9295 ret->arrayfetch->arr = sRef_saveCopy (s->info->arrayfetch->arr);
9296 break;
9297
9298 case SK_FIELD:
9299 ret = (sinfo) dmalloc (sizeof (*ret));
9300 ret->field = (fldinfo) dmalloc (sizeof (*ret->field));
9301 ret->field->rec = sRef_saveCopy (s->info->field->rec);
9302 ret->field->field = s->info->field->field;
9303 break;
9304
9305 case SK_OBJECT:
9306 ret = (sinfo) dmalloc (sizeof (*ret));
9307 ret->object = s->info->object;
9308 break;
9309
9310 case SK_PTR:
9311 case SK_ADR:
9312 case SK_DERIVED:
9313 case SK_EXTERNAL:
9314 ret = (sinfo) dmalloc (sizeof (*ret));
9315 ret->ref = sRef_saveCopy (s->info->ref);
9316 break;
9317
9318 case SK_CONJ:
9319 ret = (sinfo) dmalloc (sizeof (*ret));
9320 ret->conj = (cjinfo) dmalloc (sizeof (*ret->conj));
9321 ret->conj->a = sRef_saveCopy (s->info->conj->a);
9322 ret->conj->b = sRef_saveCopy (s->info->conj->b);
9323 break;
9324 case SK_SPECIAL:
9325 ret = (sinfo) dmalloc (sizeof (*ret));
9326 ret->spec = s->info->spec;
9327 break;
9328 case SK_NEW:
9329 case SK_UNCONSTRAINED:
9330 ret = (sinfo) dmalloc (sizeof (*ret));
9331 ret->fname = s->info->fname;
9332 break;
9333 case SK_CONST:
9334 case SK_TYPE:
9335 case SK_RESULT:
9336 case SK_UNKNOWN:
9337 llassert (s->info == NULL);
9338 ret = NULL;
9339 break;
9340 }
9341 /*@=onlytrans@*/
9342 return ret;
9343 }
9344
9345
9346 static void
sinfo_update(sRef res,sRef other)9347 sinfo_update (/*@notnull@*/ /*@exposed@*/ sRef res,
9348 /*@notnull@*/ /*@exposed@*/ sRef other)
9349 {
9350 llassert (res->kind == other->kind);
9351
9352 switch (res->kind)
9353 {
9354 case SK_CVAR:
9355 res->info->cvar->lexlevel = other->info->cvar->lexlevel;
9356 res->info->cvar->index = other->info->cvar->index;
9357 break;
9358
9359 case SK_PARAM:
9360 res->info->paramno = other->info->paramno;
9361 llassert (res->info->paramno >= -1);
9362 break;
9363
9364 case SK_ARRAYFETCH:
9365 res->info->arrayfetch->indknown = other->info->arrayfetch->indknown;
9366 res->info->arrayfetch->ind = other->info->arrayfetch->ind;
9367 res->info->arrayfetch->arr = other->info->arrayfetch->arr;
9368 break;
9369
9370 case SK_FIELD:
9371 res->info->field->rec = other->info->field->rec;
9372 res->info->field->field = other->info->field->field;
9373 break;
9374
9375 case SK_OBJECT:
9376 res->info->object = other->info->object;
9377 break;
9378
9379 case SK_PTR:
9380 case SK_ADR:
9381 case SK_DERIVED:
9382 case SK_EXTERNAL:
9383 res->info->ref = other->info->ref;
9384 break;
9385
9386 case SK_CONJ:
9387 res->info->conj->a = other->info->conj->a;
9388 res->info->conj->b = other->info->conj->b;
9389 break;
9390
9391 case SK_SPECIAL:
9392 res->info->spec = other->info->spec;
9393 break;
9394
9395 case SK_NEW:
9396 case SK_UNCONSTRAINED:
9397 res->info->fname = other->info->fname;
9398 break;
9399
9400 case SK_CONST:
9401 case SK_TYPE:
9402 case SK_UNKNOWN:
9403 case SK_RESULT:
9404 llassert (res->info == NULL);
9405 break;
9406 }
9407 }
9408
sinfo_free(sRef s)9409 static void sinfo_free (/*@special@*/ /*@temp@*/ /*@notnull@*/ sRef s)
9410 /*@uses s->kind, s->info@*/
9411 /*@releases s->info@*/
9412 {
9413 switch (s->kind)
9414 {
9415 case SK_CVAR:
9416 DPRINTF (("Free sinfo: [%p]", s->info->cvar));
9417 sfree (s->info->cvar);
9418 break;
9419
9420 case SK_PARAM:
9421 break;
9422
9423 case SK_ARRAYFETCH:
9424 DPRINTF (("Free sinfo: [%p]", s->info->arrayfetch));
9425 sfree (s->info->arrayfetch);
9426 break;
9427
9428 case SK_FIELD:
9429 DPRINTF (("Free sinfo: [%p]", s->info->field));
9430 sfree (s->info->field);
9431 break;
9432
9433 case SK_OBJECT:
9434 break;
9435
9436 case SK_PTR:
9437 case SK_ADR:
9438 case SK_DERIVED:
9439 case SK_EXTERNAL: /* is copy now! */
9440 break;
9441
9442 case SK_CONJ:
9443 DPRINTF (("Free sinfo: [%p]", s->info->conj));
9444 sfree (s->info->conj);
9445 break;
9446
9447 case SK_UNCONSTRAINED:
9448 case SK_SPECIAL:
9449 case SK_CONST:
9450 case SK_NEW:
9451 case SK_TYPE:
9452 case SK_UNKNOWN:
9453 case SK_RESULT:
9454 break;
9455 }
9456
9457 if (s->info != NULL) {
9458 DPRINTF (("Free sinfo: [%p]", s->info));
9459 }
9460
9461 sfree (s->info);
9462 }
9463
sRef_isNSLocalVar(sRef s)9464 bool sRef_isNSLocalVar (sRef s)
9465 {
9466 if (sRef_isLocalVar (s))
9467 {
9468 uentry ue = sRef_getUentry (s);
9469
9470 return (!uentry_isStatic (ue));
9471 }
9472 else
9473 {
9474 return FALSE;
9475 }
9476 }
9477
sRef_isLocalVar(sRef s)9478 bool sRef_isLocalVar (sRef s)
9479 {
9480 if (sRef_isValid(s))
9481 {
9482 return (s->kind == SK_CVAR
9483 && (s->info->cvar->lexlevel > fileScope));
9484 }
9485
9486 return FALSE;
9487 }
9488
sRef_isRealLocalVar(sRef s)9489 bool sRef_isRealLocalVar (sRef s)
9490 {
9491 if (sRef_isValid(s))
9492 {
9493 if (s->kind == SK_CVAR)
9494 {
9495 if (s->info->cvar->lexlevel == functionScope)
9496 {
9497 uentry ue = sRef_getUentry (s);
9498
9499 if (uentry_isAnyParam (ue)
9500 || uentry_isRefParam (ue))
9501 {
9502 return FALSE;
9503 }
9504 else
9505 {
9506 return TRUE;
9507 }
9508 }
9509 else
9510 {
9511 return (s->info->cvar->lexlevel > functionScope);
9512 }
9513 }
9514 }
9515
9516 return FALSE;
9517 }
9518
sRef_isLocalParamVar(sRef s)9519 bool sRef_isLocalParamVar (sRef s)
9520 {
9521 if (sRef_isValid(s))
9522 {
9523 return (s->kind == SK_PARAM
9524 || (s->kind == SK_CVAR
9525 && (s->info->cvar->lexlevel > fileScope)));
9526 }
9527
9528 return FALSE;
9529 }
9530
speckind_fromInt(int i)9531 static speckind speckind_fromInt (int i)
9532 {
9533 /*@+enumint@*/
9534 llassert (i >= SR_NOTHING && i <= SR_SYSTEM);
9535 /*@=enumint@*/
9536
9537 return ((speckind) i);
9538 }
9539
9540
sRef_updateNullState(sRef res,sRef other)9541 static void sRef_updateNullState (/*@notnull@*/ sRef res, /*@notnull@*/ sRef other)
9542 /*@modifies res@*/
9543 {
9544 res->nullstate = other->nullstate;
9545 DPRINTF (("update null state==> %s", sRef_unparseFull (res)));
9546 res->nullinfo = stateInfo_update (res->nullinfo, other->nullinfo);
9547 sRef_resetAliasKind (res);
9548 }
9549
sRef_combineNullState(sRef res,sRef other)9550 void sRef_combineNullState (/*@notnull@*/ sRef res, /*@notnull@*/ sRef other)
9551 {
9552 nstate n1 = sRef_getNullState (res);
9553 nstate n2 = sRef_getNullState (other);
9554 bool flip = FALSE;
9555 nstate nn = n1;
9556
9557 if (n1 == n2 || n2 == NS_UNKNOWN)
9558 {
9559 ;
9560 }
9561 else
9562 {
9563 /* note: n2 is not unknown or defnull */
9564
9565 switch (n1)
9566 {
9567 case NS_ERROR: nn = NS_ERROR; break;
9568 case NS_UNKNOWN: flip = TRUE; nn = n2; break;
9569 case NS_POSNULL: break;
9570 case NS_DEFNULL: nn = NS_POSNULL; break;
9571 case NS_RELNULL: break;
9572 case NS_NOTNULL:
9573 if (n2 == NS_MNOTNULL)
9574 {
9575 ;
9576 }
9577 else
9578 {
9579 flip = TRUE;
9580 nn = NS_POSNULL;
9581 }
9582 break;
9583 case NS_MNOTNULL:
9584 if (n2 == NS_NOTNULL)
9585 {
9586 nn = NS_NOTNULL;
9587 }
9588 else
9589 {
9590 flip = TRUE;
9591 nn = NS_POSNULL;
9592 }
9593 break;
9594 case NS_CONSTNULL:
9595 case NS_ABSNULL:
9596 flip = TRUE;
9597 nn = n2;
9598 }
9599 }
9600
9601 if (flip)
9602 {
9603 res->nullinfo = stateInfo_update (res->nullinfo, other->nullinfo);
9604 }
9605
9606 res->nullstate = nn;
9607 DPRINTF (("update null state==> %s", sRef_unparseFull (res)));
9608 sRef_resetAliasKind (res);
9609 }
9610
sRef_nullMessage(sRef s)9611 cstring sRef_nullMessage (sRef s)
9612 {
9613 llassert (sRef_isReasonable (s));
9614
9615 switch (sRef_getNullState (s))
9616 {
9617 case NS_DEFNULL:
9618 case NS_CONSTNULL:
9619 return (cstring_makeLiteralTemp ("null"));
9620 default:
9621 return (cstring_makeLiteralTemp ("possibly null"));
9622 }
9623 BADEXIT;
9624 }
9625
sRef_ntMessage(sRef s)9626 /*@observer@*/ cstring sRef_ntMessage (sRef s)
9627 {
9628 llassert (sRef_isReasonable (s));
9629
9630 switch (s->nullstate)
9631 {
9632 case NS_DEFNULL:
9633 case NS_CONSTNULL:
9634 return (cstring_makeLiteralTemp ("not nullterminated"));
9635 default:
9636 return (cstring_makeLiteralTemp ("possibly non-nullterminated"));
9637 }
9638 BADEXIT;
9639 }
9640
9641
9642
sRef_fixResultType(sRef s,ctype typ,uentry ue)9643 sRef sRef_fixResultType (/*@returned@*/ sRef s, ctype typ, uentry ue)
9644 {
9645 sRef tmp = sRef_undefined;
9646 sRef ret;
9647
9648 llassert (sRef_isReasonable (s));
9649
9650 switch (s->kind)
9651 {
9652 case SK_RESULT:
9653 s->type = typ;
9654 ret = s;
9655 break;
9656 case SK_ARRAYFETCH:
9657 {
9658 ctype ct;
9659 tmp = sRef_fixResultType (s->info->arrayfetch->arr, typ, ue);
9660
9661 ct = ctype_realType (sRef_getType (tmp));
9662
9663
9664 if (ctype_isKnown (ct))
9665 {
9666 if (ctype_isAP (ct))
9667 {
9668 ;
9669 }
9670 else
9671 {
9672 voptgenerror
9673 (FLG_TYPE,
9674 message
9675 ("Special clause indexes non-array (%t): *%q",
9676 ct, sRef_unparse (s->info->arrayfetch->arr)),
9677 uentry_whereLast (ue));
9678 }
9679 }
9680
9681 tmp = sRef_fixResultType (s->info->arrayfetch->arr, typ, ue);
9682
9683 if (s->info->arrayfetch->indknown)
9684 {
9685 ret = sRef_makeArrayFetchKnown (tmp, s->info->arrayfetch->ind);
9686 }
9687 else
9688 {
9689 ret = sRef_makeArrayFetch (tmp);
9690 }
9691 }
9692 break;
9693 case SK_FIELD:
9694 {
9695 sRef rec = sRef_fixResultType (s->info->field->rec, typ, ue);
9696 ctype ct = ctype_realType (sRef_getType (rec));
9697
9698 if (ctype_isKnown (ct))
9699 {
9700 if (ctype_isSU (ct))
9701 {
9702 if (uentry_isValid (uentryList_lookupField (ctype_getFields (ct),
9703 s->info->field->field)))
9704 {
9705 ;
9706 }
9707 else
9708 {
9709 voptgenerror
9710 (FLG_TYPE,
9711 message
9712 ("Special clause accesses non-existent field of result: %q.%s",
9713 sRef_unparse (rec), s->info->field->field),
9714 uentry_whereLast (ue));
9715 }
9716 }
9717 else
9718 {
9719 voptgenerror
9720 (FLG_TYPE,
9721 message
9722 ("Special clause accesses field of non-struct or union result (%t): %q.%s",
9723 ct, sRef_unparse (rec), s->info->field->field),
9724 uentry_whereLast (ue));
9725 }
9726 }
9727
9728 ret = sRef_makeField (tmp, s->info->field->field);
9729 break;
9730 }
9731 case SK_PTR:
9732 {
9733 ctype ct;
9734 tmp = sRef_fixResultType (s->info->ref, typ, ue);
9735
9736 ct = ctype_realType (sRef_getType (tmp));
9737
9738 if (ctype_isKnown (ct))
9739 {
9740 if (ctype_isAP (ct))
9741 {
9742 ;
9743 }
9744 else
9745 {
9746 voptgenerror
9747 (FLG_TYPE,
9748 message
9749 ("Special clause dereferences non-pointer (%t): *%q",
9750 ct, sRef_unparse (s->info->ref)),
9751 uentry_whereLast (ue));
9752 }
9753 }
9754
9755 ret = sRef_makePointer (tmp);
9756 break;
9757 }
9758 case SK_ADR:
9759 voptgenerror
9760 (FLG_TYPE,
9761 message
9762 ("Special clause uses & operator (not allowed): &%q", sRef_unparse (s->info->ref)),
9763 uentry_whereLast (ue));
9764 ret = s;
9765 break;
9766 BADDEFAULT;
9767 }
9768
9769 return ret;
9770 }
9771
sRef_isOnly(sRef s)9772 bool sRef_isOnly (sRef s)
9773 {
9774 return (sRef_isValid(s) && alkind_isOnly (s->aliaskind));
9775 }
9776
sRef_isDependent(sRef s)9777 bool sRef_isDependent (sRef s)
9778 {
9779 return (sRef_isValid(s) && alkind_isDependent (s->aliaskind));
9780 }
9781
sRef_isOwned(sRef s)9782 bool sRef_isOwned (sRef s)
9783 {
9784 return (sRef_isReasonable (s) && (s->aliaskind == AK_OWNED));
9785 }
9786
sRef_isKeep(sRef s)9787 bool sRef_isKeep (sRef s)
9788 {
9789 return (sRef_isReasonable (s) && (s->aliaskind == AK_KEEP));
9790 }
9791
sRef_isTemp(sRef s)9792 bool sRef_isTemp (sRef s)
9793 {
9794 return (sRef_isReasonable (s) && alkind_isTemp (s->aliaskind));
9795 }
9796
sRef_isLocalState(sRef s)9797 bool sRef_isLocalState (sRef s)
9798 {
9799 return (sRef_isReasonable (s) && (s->aliaskind == AK_LOCAL));
9800 }
9801
sRef_isUnique(sRef s)9802 bool sRef_isUnique (sRef s)
9803 {
9804 return (sRef_isReasonable (s) && (s->aliaskind == AK_UNIQUE));
9805 }
9806
sRef_isShared(sRef s)9807 bool sRef_isShared (sRef s)
9808 {
9809 return (sRef_isReasonable (s) && (s->aliaskind == AK_SHARED));
9810 }
9811
sRef_isExposed(sRef s)9812 bool sRef_isExposed (sRef s)
9813 {
9814 return (sRef_isReasonable (s) && (s->expkind == XO_EXPOSED));
9815 }
9816
sRef_isObserver(sRef s)9817 bool sRef_isObserver (sRef s)
9818 {
9819 return (sRef_isReasonable (s) && (s->expkind == XO_OBSERVER));
9820 }
9821
sRef_isFresh(sRef s)9822 bool sRef_isFresh (sRef s)
9823 {
9824 return (sRef_isReasonable (s) && (s->aliaskind == AK_FRESH));
9825 }
9826
sRef_isDefinitelyNull(sRef s)9827 bool sRef_isDefinitelyNull (sRef s)
9828 {
9829 return (sRef_isReasonable (s) && (sRef_getNullState (s) == NS_DEFNULL
9830 || sRef_getNullState (s) == NS_CONSTNULL));
9831 }
9832
sRef_isAllocated(sRef s)9833 bool sRef_isAllocated (sRef s)
9834 {
9835 return (sRef_isReasonable (s) && (s->defstate == SS_ALLOCATED));
9836 }
9837
sRef_isStack(sRef s)9838 bool sRef_isStack (sRef s)
9839 {
9840 return (sRef_isReasonable (s) && (s->aliaskind == AK_STACK));
9841 }
9842
sRef_isNotNull(sRef s)9843 bool sRef_isNotNull (sRef s)
9844 {
9845 return (sRef_isValid(s) && (sRef_getNullState (s) == NS_MNOTNULL
9846 || sRef_getNullState (s) == NS_NOTNULL));
9847 }
9848
sRef_getAliasKind(sRef s)9849 alkind sRef_getAliasKind (sRef s)
9850 {
9851 if (sRef_isValid(s)) {
9852 llassert (alkind_isValid (s->aliaskind));
9853 return s->aliaskind;
9854 }
9855
9856 return AK_ERROR;
9857 }
9858
sRef_getNullState(sRef s)9859 nstate sRef_getNullState (sRef s)
9860 {
9861 if (sRef_isReasonable (s)) {
9862 llassert (nstate_isValid (s->nullstate));
9863 return s->nullstate;
9864 }
9865
9866 return NS_UNKNOWN;
9867 }
9868
sRef_reflectAnnotation(sRef s,annotationInfo a,fileloc loc)9869 void sRef_reflectAnnotation (sRef s, annotationInfo a, fileloc loc)
9870 {
9871 if (sRef_isReasonable (s))
9872 {
9873 if (!valueTable_isDefined (s->state))
9874 {
9875 s->state = valueTable_create (1);
9876 valueTable_insert
9877 (s->state,
9878 cstring_copy (metaStateInfo_getName (annotationInfo_getState (a))),
9879 stateValue_create (annotationInfo_getValue (a),
9880 stateInfo_makeLoc (loc, SA_DECLARED)));
9881 }
9882 else
9883 {
9884 DPRINTF (("reflect loc: %s", fileloc_unparse (loc)));
9885 valueTable_update
9886 (s->state,
9887 metaStateInfo_getName (annotationInfo_getState (a)),
9888 stateValue_create (annotationInfo_getValue (a),
9889 stateInfo_makeLoc (loc, SA_DECLARED)));
9890
9891 DPRINTF (("sref: %s", sRef_unparse (s)));
9892 DPRINTF (("sref: %s", sRef_unparseFull (s)));
9893 }
9894 }
9895 }
9896
sRef_setMetaStateValueComplete(sRef s,cstring key,int value,fileloc loc)9897 void sRef_setMetaStateValueComplete (sRef s, cstring key, int value, fileloc loc)
9898 {
9899 sRefSet aliases = usymtab_allAliases (s);
9900
9901 sRef_setMetaStateValue (s, key, value, loc);
9902
9903 sRefSet_realElements (aliases, current)
9904 {
9905 if (sRef_isReasonable (current))
9906 {
9907 current = sRef_updateSref (current);
9908 sRef_setMetaStateValue (current, key, value, loc);
9909 }
9910 } end_sRefSet_realElements ;
9911
9912 sRefSet_free (aliases);
9913 }
9914
sRef_setMetaStateValue(sRef s,cstring key,int value,fileloc loc)9915 void sRef_setMetaStateValue (sRef s, cstring key, int value, fileloc loc)
9916 {
9917 sRef_checkMutable (s);
9918
9919 if (sRef_isReasonable (s))
9920 {
9921 if (!valueTable_isDefined (s->state))
9922 {
9923 DPRINTF (("inserting state: %s: %s %d", sRef_unparse (s), key, value));
9924 s->state = valueTable_create (1);
9925 valueTable_insert (s->state, cstring_copy (key),
9926 stateValue_create (value,
9927 stateInfo_makeLoc (loc, SA_CHANGED)));
9928 }
9929 else
9930 {
9931 DPRINTF (("Updating state: %s: %s %d / %s", sRef_unparse (s), key, value,
9932 fileloc_unparse (loc)));
9933 if (valueTable_contains (s->state, key))
9934 {
9935 valueTable_update
9936 (s->state, key, stateValue_create (value,
9937 stateInfo_makeLoc (loc, SA_CHANGED)));
9938 }
9939 else
9940 {
9941 valueTable_insert
9942 (s->state, cstring_copy (key),
9943 stateValue_create (value, stateInfo_makeLoc (loc, SA_CHANGED)));
9944 }
9945
9946 DPRINTF (("After: %s", sRef_unparseFull (s)));
9947 }
9948 }
9949 }
9950
sRef_checkMetaStateValue(sRef s,cstring key,int value)9951 bool sRef_checkMetaStateValue (sRef s, cstring key, int value)
9952 {
9953 if (sRef_isReasonable (s))
9954 {
9955 if (valueTable_isDefined (s->state))
9956 {
9957 stateValue val;
9958
9959 DPRINTF (("check state: %s: %s %d", sRef_unparse (s), key, value));
9960
9961 val = valueTable_lookup (s->state, key);
9962 llassert (stateValue_isDefined (val));
9963 return (stateValue_isError (val)
9964 || stateValue_getValue (val) == value);
9965 }
9966 else
9967 {
9968 return TRUE;
9969 }
9970 }
9971 else
9972 {
9973 return TRUE;
9974 }
9975 }
9976
sRef_getMetaStateValue(sRef s,cstring key)9977 /*@observer@*/ stateValue sRef_getMetaStateValue (sRef s, cstring key)
9978 {
9979 if (sRef_isReasonable (s))
9980 {
9981 if (valueTable_isDefined (s->state))
9982 {
9983 stateValue val;
9984
9985 val = valueTable_lookup (s->state, key);
9986 /* Okay if its not defined, just returns stateValue_undefined */
9987 return val;
9988 }
9989 else
9990 {
9991 return stateValue_undefined;
9992 }
9993 }
9994 else
9995 {
9996 return stateValue_undefined;
9997 }
9998 }
9999
sRef_getValueTable(sRef s)10000 /*@observer@*/ valueTable sRef_getValueTable (sRef s)
10001 {
10002 DPRINTF (("Get value table: %s", sRef_unparse (s)));
10003
10004 if (sRef_isReasonable (s))
10005 {
10006 llassert (sRef_isReasonable (s));
10007 DPRINTF (("Value table: %s", valueTable_unparse (s->state)));
10008 return s->state;
10009 }
10010 else
10011 {
10012 DPRINTF (("No value table!"));
10013 return valueTable_undefined;
10014 }
10015 }
10016
sRef_makeStateSpecial(sRef s)10017 bool sRef_makeStateSpecial (sRef s)
10018 {
10019 /*
10020 ** Default defined state can be made special.
10021 */
10022
10023 llassert (sRef_isReasonable (s));
10024
10025 if (s->defstate == SS_UNKNOWN || s->defstate == SS_DEFINED || s->defstate == SS_SPECIAL)
10026 {
10027 /* s->aliaskind = AK_IMPTEMP; */ /* evans 2001-07-23 shouldn't effect alias state */
10028 s->defstate = SS_SPECIAL;
10029 DPRINTF (("Made special: %s", sRef_unparseFull (s)));
10030 return TRUE;
10031 }
10032 else
10033 {
10034 /* s->aliaskind = AK_IMPTEMP; */
10035 s->defstate = SS_SPECIAL;
10036 return FALSE;
10037 }
10038 }
10039
sRef_markImmutable(sRef s)10040 void sRef_markImmutable (sRef s)
10041 {
10042 if (sRef_isReasonable (s))
10043 {
10044 DPRINTF (("Mark immutable: %s", sRef_unparseFull (s)));
10045 s->immut = TRUE;
10046 }
10047 }
10048
sRef_definitelyNullContext(sRef s)10049 bool sRef_definitelyNullContext (sRef s)
10050 {
10051 return (sRef_definitelyNull (s)
10052 || usymtab_isDefinitelyNullDeep (s));
10053 }
10054
sRef_definitelyNullAltContext(sRef s)10055 bool sRef_definitelyNullAltContext (sRef s)
10056 {
10057 return (sRef_definitelyNull (s)
10058 || usymtab_isAltDefinitelyNullDeep (s));
10059 }
10060
10061
10062 /* start modifications */
sRef_getNullTerminatedState(sRef p_s)10063 struct s_bbufinfo sRef_getNullTerminatedState (sRef p_s) {
10064 struct s_bbufinfo BUFSTATE_UNKNOWN;
10065 BUFSTATE_UNKNOWN.bufstate = BB_NOTNULLTERMINATED;
10066 BUFSTATE_UNKNOWN.size = 0;
10067 BUFSTATE_UNKNOWN.len = 0;
10068
10069 if (sRef_isValid(p_s))
10070 return p_s->bufinfo;
10071 return BUFSTATE_UNKNOWN;
10072 }
10073
sRef_setNullTerminatedState(sRef p_s)10074 void sRef_setNullTerminatedState(sRef p_s) {
10075 if(sRef_isReasonable (p_s)) {
10076 p_s->bufinfo.bufstate = BB_NULLTERMINATED;
10077 } else {
10078 llfatalbug( message("sRef_setNT passed a invalid sRef\n"));
10079 }
10080 }
10081
10082
sRef_setPossiblyNullTerminatedState(sRef p_s)10083 void sRef_setPossiblyNullTerminatedState(sRef p_s) {
10084 if( sRef_isReasonable (p_s)) {
10085 p_s->bufinfo.bufstate = BB_POSSIBLYNULLTERMINATED;
10086 } else {
10087 llfatalbug( message("sRef_setPossNT passed a invalid sRef\n"));
10088 }
10089 }
10090
sRef_setNotNullTerminatedState(sRef p_s)10091 void sRef_setNotNullTerminatedState(sRef p_s) {
10092 if( sRef_isReasonable (p_s)) {
10093 p_s->bufinfo.bufstate = BB_NOTNULLTERMINATED;
10094 } else {
10095 llfatalbug( message("sRef_unsetNT passed a invalid sRef\n"));
10096 }
10097 }
10098
sRef_setLen(sRef p_s,int len)10099 void sRef_setLen(sRef p_s, int len) {
10100 if (sRef_isReasonable (p_s) && sRef_isNullTerminated(p_s))
10101 {
10102 p_s->bufinfo.len = len;
10103 }
10104 else
10105 {
10106 llfatalbug( message("sRef_setLen passed an invalid sRef\n"));
10107 }
10108 }
10109
10110
sRef_setSize(sRef p_s,int size)10111 void sRef_setSize(sRef p_s, int size) {
10112 if( sRef_isValid(p_s))
10113 {
10114 p_s->bufinfo.size = size;
10115 }
10116 else
10117 {
10118 llfatalbug( message("sRef_setSize passed a invalid sRef\n"));
10119 }
10120 }
10121
sRef_resetLen(sRef p_s)10122 void sRef_resetLen(sRef p_s) {
10123 if (sRef_isReasonable (p_s))
10124 {
10125 p_s->bufinfo.len = 0;
10126 }
10127 else
10128 {
10129 llfatalbug (message ("sRef_setLen passed an invalid sRef\n"));
10130 }
10131 }
10132
10133 /*drl7x 11/28/2000 */
10134
sRef_isFixedArray(sRef p_s)10135 bool sRef_isFixedArray (sRef p_s) /*@*/ {
10136 ctype c;
10137 c = sRef_getType (p_s);
10138 return ( ctype_isFixedArray (c) );
10139 }
10140
sRef_getArraySize(sRef p_s)10141 size_t sRef_getArraySize (sRef p_s) /*@*/
10142 {
10143 ctype c;
10144 llassert (sRef_isFixedArray(p_s) );
10145 DPRINTF (( message ("sRef_getArraySize getting array size for %s", sRef_unparse(p_s) ) ));
10146
10147 c = sRef_getType (p_s);
10148 return (ctype_getArraySize (c));
10149 }
10150
sRef_setValue(sRef s,multiVal val)10151 void sRef_setValue (sRef s, multiVal val)
10152 {
10153 if (!sRef_isReasonable (s))
10154 {
10155 llcontbuglit ("Unreasonable sRef");
10156 llcontbug (message ("sRef: %s", sRef_unparse (s)));
10157 return;
10158 }
10159
10160 multiVal_free (s->val);
10161 s->val = val;
10162 }
10163
sRef_hasValue(sRef s)10164 bool sRef_hasValue (sRef s)
10165 {
10166 return (sRef_isReasonable (s)
10167 && multiVal_isDefined (s->val));
10168 }
10169
sRef_getValue(sRef s)10170 multiVal sRef_getValue (sRef s)
10171 {
10172 if (sRef_isReasonable (s))
10173 {
10174 return s->val;
10175 }
10176
10177 return multiVal_undefined;
10178 }
10179