]> andersk Git - splint.git/blame_incremental - src/sRef.c
Fixed problem with shadow parameters.
[splint.git] / src / sRef.c
... / ...
CommitLineData
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
54static void sRef_checkValidAux (sRef p_s, sRefSet p_checkedsofar) /*@modifies p_checkedsofar@*/ ;
55
56static bool sRef_isDerived (sRef p_s) /*@*/ ;
57
58static /*@exposed@*/ sRef sRef_fixDirectBase (sRef p_s, sRef p_base)
59 /*@modifies p_base@*/ ;
60
61static void sRef_updateNullState (sRef p_res, sRef p_other) /*@modifies p_res@*/ ;
62
63static bool sRef_isAllocatedStorage (sRef p_s) /*@*/ ;
64static void sRef_setNullErrorLoc (sRef p_s, fileloc) /*@*/ ;
65static void sRef_setNullStateN (sRef p_s, nstate p_n) /*@modifies p_s@*/ ;
66
67static int sRef_depth (sRef p_s) /*@*/ ;
68
69static void
70 sRef_innerAliasSetComplete (void (p_predf) (sRef, fileloc), sRef p_s,
71 fileloc p_loc)
72 /*@modifies p_s@*/ ;
73
74static void
75sRef_innerAliasSetCompleteParam (void (p_predf) (sRef, sRef), sRef p_s, sRef p_t)
76 /*@modifies p_s@*/ ;
77
78static speckind speckind_fromInt (int p_i);
79static bool sRef_equivalent (sRef p_s1, sRef p_s2);
80static bool sRef_isDeepUnionField (sRef p_s);
81static void sRef_addDeriv (/*@notnull@*/ sRef p_s, /*@notnull@*/ /*@exposed@*/ sRef p_t);
82static bool sRef_checkModify (sRef p_s, sRefSet p_sl) /*@*/ ;
83
84/*
85** If s is definitely null, it has no memory state.
86*/
87
88static 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
97extern 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
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
159static /*@nullwhentrue@*/ bool sRef_isUnreasonable (sRef s) /*@*/
160{
161 return (!sRef_isReasonable (s));
162}
163
164static 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
173static 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
185static void sinfo_free (/*@special@*/ /*@temp@*/ /*@notnull@*/ sRef p_s)
186 /*@uses p_s->kind, p_s->info@*/
187 /*@releases p_s->info@*/ ;
188
189static /*@null@*/ sinfo sinfo_copy (/*@notnull@*/ sRef p_s) /*@*/ ;
190static void sRef_setPartsFromUentry (sRef p_s, uentry p_ue)
191 /*@modifies p_s@*/ ;
192static bool checkDeadState (/*@notnull@*/ sRef p_el, /*@null@*/ sRef p_e2,
193 bool p_tbranch, fileloc p_loc);
194static /*@dependent@*/ sRef sRef_constructPointerAux (/*@notnull@*/ /*@exposed@*/ sRef p_t) /*@*/ ;
195
196static void
197 sRef_combineExKinds (/*@notnull@*/ sRef p_res, /*@notnull@*/ sRef p_other)
198 /*@modifies p_res@*/ ;
199
200static void
201 sRef_combineAliasKinds (/*@notnull@*/ sRef p_res, /*@notnull@*/ sRef p_other,
202 clause p_cl, fileloc p_loc)
203 /*@modifies p_res@*/ ;
204
205static void
206 sRef_combineNullState (/*@notnull@*/ sRef p_res, /*@notnull@*/ sRef p_other)
207 /*@modifies p_res@*/ ;
208
209static void
210 sRef_combineDefState (/*@notnull@*/ sRef p_res, /*@notnull@*/ sRef p_other)
211 /*@modifies p_res@*/ ;
212
213static void sRef_setStateFromAbstractUentry (sRef p_s, uentry p_ue)
214 /*@modifies p_s@*/ ;
215
216static void
217 sinfo_update (/*@notnull@*/ /*@exposed@*/ sRef p_res,
218 /*@notnull@*/ /*@exposed@*/ sRef p_other);
219static void sRef_setDefinedAux (sRef p_s, fileloc p_loc, bool p_clear)
220 /*@modifies p_s@*/ ;
221static void sRef_setDefinedNoClear (sRef p_s, fileloc p_loc)
222 /*@modifies p_s@*/ ;
223static void sRef_setStateAux (sRef p_s, sstate p_ss, fileloc p_loc)
224 /*@modifies p_s@*/;
225
226static /*@exposed@*/ sRef
227 sRef_buildNCField (/*@exposed@*/ sRef p_rec, /*@exposed@*/ cstring p_f);
228
229static 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
235static /*@null@*/ sinfo sinfo_fullCopy (/*@notnull@*/ sRef p_s);
236static bool sRef_doModify (sRef p_s, sRefSet p_sl) /*@modifies p_s@*/ ;
237static bool sRef_doModifyVal (sRef p_s, sRefSet p_sl) /*@modifies p_s@*/;
238static bool sRef_checkModifyVal (sRef p_s, sRefSet p_sl) /*@*/ ;
239
240static /*@only@*/ sRefSet
241 sRef_mergeDerivs (/*@only@*/ sRefSet p_res, sRefSet p_other,
242 bool p_opt, clause p_cl, fileloc p_loc);
243
244static /*@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
249static /*@only@*/ sRefSet
250 sRef_mergePdefinedDerivs (/*@only@*/ sRefSet p_res, sRefSet p_other, bool p_opt,
251 clause p_cl, fileloc p_loc);
252
253static /*@only@*/ cstring sRef_unparseWithArgs (sRef p_s, uentryList p_args);
254static /*@only@*/ cstring sRef_unparseNoArgs (sRef p_s);
255
256static /*@exposed@*/ sRef sRef_findDerivedPointer (sRef p_s);
257static /*@exposed@*/ sRef sRef_findDerivedArrayFetch (/*@notnull@*/ sRef, bool, int, bool) ;
258static /*@exposed@*/ sRef sRef_findDerivedField (/*@notnull@*/ sRef p_rec, cstring p_f);
259static /*@exposed@*/ sRef
260 sRef_getDeriv (/*@notnull@*/ /*@returned@*/ sRef p_set, sRef p_guide);
261
262static bool inFunction = FALSE;
263static /*@only@*/ sRefTable allRefs;
264
265/* # define DEBUGREFS */
266
267# ifdef DEBUGREFS
268static nsrefs = 0;
269static totnsrefs = 0;
270static maxnsrefs = 0;
271static ntotrefers = 0;
272static nrefers = 0;
273# endif
274
275static /*@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
282static /*@dependent@*/ /*@out@*/ /*@notnull@*/ sRef
283sRef_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
318static 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
413void sRef_checkValid (/*@unused@*/ sRef s)
414{
415 return;
416 /*
417 sRefSet checkedsofar = sRefSet_new ();
418 sRef_checkValidAux (s, checkedsofar);
419 */
420}
421
422static /*@dependent@*/ /*@notnull@*/ /*@special@*/ sRef
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
466static /*@dependent@*/ /*@notnull@*/ /*@special@*/ sRef
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
479void sRef_protectDerivs (void) /*@modifies protectDerivs@*/
480{
481 llassert (!protectDerivs);
482 protectDerivs = TRUE;
483}
484
485void 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
496bool
497sRef_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
527static void
528sRef_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
597bool
598sRef_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
623bool sRef_modInFunction (void)
624{
625 return inFunction;
626}
627
628void 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
651static void sRef_setTypeState (sRef s)
652{
653 if (sRef_isReasonable (s))
654 {
655 sRef_setStateFromType (s, s->type);
656 }
657}
658
659bool sRef_hasAliasInfoLoc (sRef s)
660{
661 return (sRef_isReasonable (s) && (s->aliasinfo != NULL)
662 && (fileloc_isDefined (s->aliasinfo->loc)));
663}
664
665/*@falsewhennull@*/ bool sRef_hasStateInfoLoc (sRef s)
666{
667 return (sRef_isReasonable (s) && (s->definfo != NULL)
668 && (fileloc_isDefined (s->definfo->loc)));
669}
670
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
678static /*@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
697static bool
698sRef_hasNullInfoLoc (sRef s)
699{
700 return (sRef_isReasonable (s) && s->nullinfo != NULL
701 && (fileloc_isDefined (s->nullinfo->loc)));
702}
703
704bool
705sRef_hasAliasInfoRef (sRef s)
706{
707 return (sRef_isReasonable (s) && (s->aliasinfo != NULL)
708 && (sRef_isReasonable (s->aliasinfo->ref)));
709}
710
711static /*@observer@*/ fileloc
712sRef_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
719static /*@observer@*/ fileloc
720sRef_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
727static /*@observer@*/ fileloc
728sRef_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
735static /*@observer@*/ fileloc
736sRef_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
744 sRef_getAliasInfoRef (/*@temp@*/ sRef s)
745{
746 llassert (sRef_isReasonable (s) && s->aliasinfo != NULL);
747 return (s->aliasinfo->ref);
748}
749
750bool 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
761void sRef_setGlobalScope ()
762{
763 llassert (inFunction);
764 DPRINTF (("leave function"));
765 inFunction = FALSE;
766}
767
768void sRef_clearGlobalScope ()
769{
770 llassert (!inFunction);
771 DPRINTF (("enter function"));
772 inFunction = TRUE;
773}
774
775static bool oldInFunction = FALSE;
776static int nestedScope = 0;
777
778void 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
790void 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
803void 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
819void 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
834void 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
844static /*@notnull@*/ /*@exposed@*/ sRef
845sRef_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
862static bool
863sRef_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
876bool
877 sRef_isExternallyVisible (sRef s)
878{
879 return (sRef_aliasCheckSimplePred (sRef_isExternallyVisibleAux, s));
880}
881
882/*@exposed@*/ uentry
883sRef_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
915sRef_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
1050uentry
1051sRef_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
1081int
1082sRef_getParam (sRef s)
1083{
1084 llassert (sRef_isReasonable (s));
1085 llassert (s->kind == SK_PARAM);
1086
1087 return s->info->paramno;
1088}
1089
1090bool
1091sRef_isModified (sRef s)
1092{
1093 return (!sRef_isReasonable (s) || s->modified);
1094}
1095
1096void 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
1127bool
1128sRef_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
1140bool
1141sRef_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
1157static
1158bool 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
1242static 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
1326cstring 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
1346cstring 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
1366static
1367bool 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
1455static
1456bool 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
1535static /*@exposed@*/ sRef
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
1566int 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
1636static 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
1652static bool
1653sRef_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
1660static bool
1661sRef_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
1745bool
1746sRef_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
1806bool
1807sRef_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
1926bool
1927sRef_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
2033bool
2034sRef_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
2101bool
2102sRef_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
2115bool
2116sRef_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
2185static bool
2186sRef_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
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
2325sRef_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
2398sRef_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
2452static /*@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
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
2569static /*@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
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
2649cstring 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
2689ctype
2690sRef_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
2804ctype
2805sRef_getType (sRef s)
2806{
2807 if (sRef_isInvalid (s)) return ctype_unknown;
2808 return s->type;
2809}
2810
2811
2812/*@only@*/ cstring
2813sRef_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
2836cstring
2837sRef_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
2853sRef_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
2868static /*@only@*/ cstring
2869sRef_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
2986sRef_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
3089static /*@only@*/ cstring
3090sRef_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
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
3187cstring sRef_unconstrainedName (sRef s)
3188{
3189 llassert (sRef_isUnconstrained (s));
3190
3191 return s->info->fname;
3192}
3193
3194bool sRef_isUnconstrained (sRef s)
3195{
3196 return (sRef_isReasonable(s) && s->kind == SK_UNCONSTRAINED);
3197}
3198
3199static /*@dependent@*/ /*@notnull@*/ sRef
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
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
3250int 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
3268sRef
3269sRef_makeGlobal (usymId l, ctype ct, /*@only@*/ stateInfo stinfo)
3270{
3271 return (sRef_makeCvar (globScope, l, ct, stinfo));
3272}
3273
3274void
3275sRef_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
3283sRef_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
3301bool
3302sRef_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
3314int
3315sRef_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
3337static 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
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
3391cstring 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
3405sRef 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
3441sRef
3442sRef_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
3470static /*@exposed@*/ sRef
3471sRef_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
3505sRef sRef_getRootBase (sRef s)
3506{
3507 return (sRef_getRootBaseAux (s, 0));
3508}
3509
3510static 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
3528static 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
3550sRef
3551sRef_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
3567sRef 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
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
3609void
3610sRef_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
3667void
3668sRef_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
3760void
3761sRef_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
3782void
3783sRef_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
3804static void
3805sRef_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
4079static sRefSet
4080sRef_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
4111static /*@only@*/ sRefSet
4112sRef_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
4241static 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
4316static void
4317checkDerivDeadState (/*@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
4331static sRefSet
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
4399sRef 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
4444sRef_makeUnknown ()
4445{
4446 sRef s = sRef_new ();
4447
4448 s->kind = SK_UNKNOWN;
4449 return s;
4450}
4451
4452static /*@owned@*/ /*@notnull@*/ sRef
4453sRef_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
4465static /*@owned@*/ sRef srnothing = sRef_undefined;
4466static /*@owned@*/ sRef srinternal = sRef_undefined;
4467static /*@owned@*/ sRef srsystem = sRef_undefined;
4468static /*@owned@*/ sRef srspec = sRef_undefined;
4469
4470/*@dependent@*/ sRef
4471sRef_makeNothing (void)
4472{
4473 if (sRef_isInvalid (srnothing))
4474 {
4475 srnothing = sRef_makeSpecial (SR_NOTHING);
4476 }
4477
4478 return srnothing;
4479}
4480
4481sRef
4482sRef_makeInternalState (void)
4483{
4484 if (sRef_isInvalid (srinternal))
4485 {
4486 srinternal = sRef_makeSpecial (SR_INTERNAL);
4487 }
4488
4489 return srinternal;
4490}
4491
4492sRef
4493sRef_makeSpecState (void)
4494{
4495 if (sRef_isInvalid (srspec))
4496 {
4497 srspec = sRef_makeSpecial (SR_SPECSTATE);
4498 }
4499
4500 return srspec;
4501}
4502
4503sRef
4504sRef_makeSystemState (void)
4505{
4506 if (sRef_isInvalid (srsystem))
4507 {
4508 srsystem = sRef_makeSpecial (SR_SYSTEM);
4509 }
4510
4511 return srsystem;
4512}
4513
4514sRef
4515sRef_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
4523sRef
4524sRef_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
4541bool
4542sRef_isNothing (sRef s)
4543{
4544 return (sRef_isKindSpecial (s) && s->info->spec == SR_NOTHING);
4545}
4546
4547bool
4548sRef_isInternalState (sRef s)
4549{
4550 return (sRef_isKindSpecial (s) && s->info->spec == SR_INTERNAL);
4551}
4552
4553bool
4554sRef_isSpecInternalState (sRef s)
4555{
4556 return (sRef_isKindSpecial (s)
4557 && (s->info->spec == SR_INTERNAL || s->info->spec == SR_SPECSTATE));
4558}
4559
4560bool
4561sRef_isSpecState (sRef s)
4562{
4563 return (sRef_isKindSpecial (s) && s->info->spec == SR_SPECSTATE);
4564}
4565
4566bool
4567sRef_isResult (sRef s)
4568{
4569 return (sRef_isReasonable (s) && s->kind == SK_RESULT);
4570}
4571
4572bool
4573sRef_isSystemState (sRef s)
4574{
4575 return (sRef_isKindSpecial (s) && s->info->spec == SR_SYSTEM);
4576}
4577
4578bool
4579sRef_isGlobalMarker (sRef s)
4580{
4581 return (sRef_isKindSpecial (s) && s->info->spec == SR_GLOBALMARKER);
4582}
4583
4584usymId
4585sRef_getScopeIndex (sRef s)
4586{
4587 llassert (sRef_isReasonable (s));
4588 llassert (sRef_isCvar (s));
4589
4590 return (s->info->cvar->index);
4591}
4592
4593void
4594sRef_makeSafe (sRef s)
4595{
4596 if (sRef_isReasonable (s))
4597 {
4598 s->safe = TRUE;
4599 }
4600}
4601
4602void
4603sRef_makeUnsafe (sRef s)
4604{
4605 if (sRef_isReasonable (s))
4606 {
4607 s->safe = FALSE;
4608 }
4609}
4610
4611/*
4612** memory state operations
4613*/
4614
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
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
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
4667bool 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
4675ynm 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
4702bool sRef_hasNoStorage (sRef s)
4703{
4704 return (!sRef_isAllocatedStorage (s) || sRef_isDefinitelyNull (s));
4705}
4706
4707bool 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
4719ynm 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
4771static /*@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
4901static 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
4908bool 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
4934void 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
4971sstate sRef_getDefState (sRef s)
4972{
4973 if (sRef_isInvalid (s)) return (SS_UNKNOWN);
4974 return (s->defstate);
4975}
4976
4977void sRef_setDefState (sRef s, sstate defstate, fileloc loc)
4978{
4979 sRef_checkMutable (s);
4980 sRef_setStateAux (s, defstate, loc);
4981}
4982
4983static void sRef_clearAliasStateAux (sRef s, fileloc loc)
4984{
4985 sRef_checkMutable (s);
4986 sRef_setAliasKind (s, AK_ERROR, loc);
4987}
4988
4989void sRef_clearAliasState (sRef s, fileloc loc)
4990{
4991 sRef_checkMutable (s);
4992 sRef_aliasSetComplete (sRef_clearAliasStateAux, s, loc);
4993}
4994
4995void sRef_setAliasKindComplete (sRef s, alkind kind, fileloc loc)
4996{
4997 sRef_checkMutable (s);
4998 sRef_aliasSetCompleteAlkParam (sRef_setAliasKind, s, kind, loc);
4999}
5000
5001void 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
5019void 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
5029exkind 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
5041exkind 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
5053static void sRef_clearExKindAux (sRef s, fileloc loc)
5054{
5055 sRef_checkMutable (s);
5056 sRef_setExKind (s, XO_UNKNOWN, loc);
5057}
5058
5059void sRef_setObserver (sRef s, fileloc loc)
5060{
5061 sRef_checkMutable (s);
5062 sRef_setExKind (s, XO_OBSERVER, loc);
5063}
5064
5065void sRef_setExposed (sRef s, fileloc loc)
5066{
5067 sRef_checkMutable (s);
5068 sRef_setExKind (s, XO_EXPOSED, loc);
5069}
5070
5071void sRef_clearExKindComplete (sRef s, fileloc loc)
5072{
5073 (void) sRef_aliasSetComplete (sRef_clearExKindAux, s, loc);
5074}
5075
5076void 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
5095static 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
5132void sRef_copyRealDerivedComplete (sRef s1, sRef s2)
5133{
5134 sRef_innerAliasSetCompleteParam (sRef_copyRealDerived, s1, s2);
5135}
5136
5137void 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
5150static 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
5261static 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
5271void sRef_setPartialDefinedComplete (sRef s, fileloc loc)
5272{
5273 sRef_innerAliasSetComplete (sRef_setPartialDefined, s, loc);
5274}
5275
5276void sRef_setDefinedComplete (sRef s, fileloc loc)
5277{
5278 sRef_innerAliasSetComplete (sRef_setDefined, s, loc);
5279}
5280
5281void 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
5304void sRef_setDefined (sRef s, fileloc loc)
5305{
5306 sRef_checkMutable (s);
5307 sRef_setDefinedAux (s, loc, TRUE);
5308}
5309
5310static 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
5318void 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
5326static bool sRef_isDeepUnionField (sRef s)
5327{
5328 return (sRef_deepPred (sRef_isUnionField, s));
5329}
5330
5331bool 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
5350void 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
5386static 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
5429void sRef_setAllocatedComplete (sRef s, fileloc loc)
5430{
5431 sRef_innerAliasSetComplete (sRef_setAllocated, s, loc);
5432}
5433
5434static 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
5448void sRef_setAllocatedShallowComplete (sRef s, fileloc loc)
5449{
5450 sRef_innerAliasSetComplete (sRef_setAllocatedShallow, s, loc);
5451}
5452
5453void sRef_setAllocated (sRef s, fileloc loc)
5454{
5455 sRef_checkMutable (s);
5456 sRef_setStateAux (s, SS_ALLOCATED, loc);
5457}
5458
5459void sRef_setPartial (sRef s, fileloc loc)
5460{
5461 sRef_checkMutable (s);
5462 sRef_setStateAux (s, SS_PARTIAL, loc);
5463}
5464
5465void 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
5481void 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
5492static
5493void 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
5505void sRef_setNotNull (sRef s, fileloc loc)
5506{
5507 if (sRef_isReasonable (s))
5508 {
5509 sRef_setNullStateAux (s, NS_NOTNULL, loc);
5510 }
5511}
5512
5513void sRef_setNullStateN (sRef s, nstate n)
5514{
5515 if (sRef_isReasonable (s))
5516 {
5517 sRef_checkMutable (s);
5518 s->nullstate = n;
5519 sRef_resetAliasKind (s);
5520 }
5521}
5522
5523void sRef_setNullState (sRef s, nstate n, fileloc loc)
5524{
5525 if (sRef_isReasonable (s))
5526 {
5527 sRef_setNullStateAux (s, n, loc);
5528 }
5529}
5530
5531void sRef_setNullTerminatedStateInnerComplete (sRef s, struct s_bbufinfo b, /*@unused@*/ fileloc loc)
5532{
5533 switch (b.bufstate) {
5534 case BB_NULLTERMINATED:
5535 sRef_setNullTerminatedState (s);
5536 sRef_setLen (s, b.len);
5537 break;
5538 case BB_POSSIBLYNULLTERMINATED:
5539 sRef_setPossiblyNullTerminatedState(s);
5540 break;
5541 case BB_NOTNULLTERMINATED:
5542 sRef_setNotNullTerminatedState (s);
5543 break;
5544 }
5545
5546 sRef_setSize (s, b.size);
5547
5548 /* PL: TO BE DONE : Aliases are not modified right now, have to be similar to
5549 * setNullStateInnerComplete.
5550 */
5551}
5552
5553void sRef_setNullStateInnerComplete (sRef s, nstate n, fileloc loc)
5554{
5555 DPRINTF (("Set null state: %s", nstate_unparse (n)));
5556
5557 sRef_setNullState (s, n, loc);
5558
5559 switch (n)
5560 {
5561 case NS_POSNULL:
5562 sRef_innerAliasSetComplete (sRef_setPosNull, s, loc);
5563 break;
5564 case NS_DEFNULL:
5565 sRef_innerAliasSetComplete (sRef_setDefNull, s, loc);
5566 break;
5567 case NS_UNKNOWN:
5568 sRef_innerAliasSetComplete (sRef_setNullUnknown, s, loc);
5569 break;
5570 case NS_NOTNULL:
5571 sRef_innerAliasSetComplete (sRef_setNotNull, s, loc);
5572 break;
5573 case NS_MNOTNULL:
5574 sRef_innerAliasSetComplete (sRef_setNotNull, s, loc);
5575 break;
5576 case NS_RELNULL:
5577 sRef_innerAliasSetComplete (sRef_setNullUnknown, s, loc);
5578 break;
5579 case NS_CONSTNULL:
5580 sRef_innerAliasSetComplete (sRef_setDefNull, s, loc);
5581 break;
5582 case NS_ABSNULL:
5583 sRef_innerAliasSetComplete (sRef_setNullUnknown, s, loc);
5584 break;
5585 case NS_ERROR:
5586 sRef_innerAliasSetComplete (sRef_setNullErrorLoc, s, loc);
5587 break;
5588 }
5589}
5590
5591void sRef_setPosNull (sRef s, fileloc loc)
5592{
5593 if (sRef_isReasonable (s))
5594 {
5595 sRef_setNullStateAux (s, NS_POSNULL, loc);
5596 }
5597}
5598
5599void sRef_setDefNull (sRef s, fileloc loc)
5600{
5601 if (sRef_isReasonable (s))
5602 {
5603 sRef_setNullStateAux (s, NS_DEFNULL, loc);
5604 }
5605}
5606
5607void sRef_setNullUnknown (sRef s, fileloc loc)
5608{
5609 if (sRef_isReasonable (s))
5610 {
5611 sRef_setNullStateAux (s, NS_UNKNOWN, loc);
5612 }
5613}
5614
5615void sRef_setNullError (sRef s)
5616{
5617 if (sRef_isReasonable (s) && !sRef_isConst (s))
5618 {
5619 sRef_setNullStateAux (s, NS_UNKNOWN, fileloc_undefined);
5620 }
5621}
5622
5623void sRef_setNullErrorLoc (sRef s, fileloc loc)
5624{
5625 if (sRef_isReasonable (s) && !sRef_isConst (s))
5626 {
5627 sRef_setNullStateAux (s, NS_UNKNOWN, loc);
5628 }
5629}
5630
5631void sRef_setOnly (sRef s, fileloc loc)
5632{
5633 if (sRef_isReasonable (s) && s->aliaskind != AK_ONLY)
5634 {
5635 sRef_checkMutable (s);
5636 s->aliaskind = AK_ONLY;
5637 s->aliasinfo = stateInfo_updateLoc (s->aliasinfo, SA_ONLY, loc);
5638 }
5639}
5640
5641void sRef_setDependent (sRef s, fileloc loc)
5642{
5643 if (sRef_isReasonable (s) && !sRef_isConst (s) && (s->aliaskind != AK_DEPENDENT))
5644 {
5645 sRef_checkMutable (s);
5646 DPRINTF (("Setting dependent: %s", sRef_unparseFull (s)));
5647 s->aliaskind = AK_DEPENDENT;
5648 s->aliasinfo = stateInfo_updateLoc (s->aliasinfo, SA_DEPENDENT, loc);
5649 }
5650}
5651
5652void sRef_setOwned (sRef s, fileloc loc)
5653{
5654 if (sRef_isReasonable (s) && !sRef_isConst (s) && (s->aliaskind != AK_OWNED))
5655 {
5656 sRef_checkMutable (s);
5657 s->aliaskind = AK_OWNED;
5658 s->aliasinfo = stateInfo_updateLoc (s->aliasinfo, SA_OWNED, loc);
5659 }
5660}
5661
5662void sRef_setKept (sRef s, fileloc loc)
5663{
5664 if (sRef_isReasonable (s) && !sRef_isConst (s) && (s->aliaskind != AK_KEPT))
5665 {
5666 sRef base = sRef_getBaseSafe (s);
5667
5668 while (sRef_isReasonable (base) && sRef_isKnown (base))
5669 {
5670 if (base->defstate == SS_DEFINED)
5671 {
5672 sRef_checkMutable (base);
5673 base->defstate = SS_PDEFINED;
5674 base = sRef_getBaseSafe (base);
5675 }
5676 else
5677 {
5678 break;
5679 }
5680 }
5681
5682 sRef_checkMutable (s);
5683 s->aliaskind = AK_KEPT;
5684 s->aliasinfo = stateInfo_updateLoc (s->aliasinfo, SA_KEPT, loc);
5685 }
5686}
5687
5688static void sRef_setKeptAux (sRef s, fileloc loc)
5689{
5690 if (!sRef_isShared (s))
5691 {
5692 sRef_setKept (s, loc);
5693 }
5694}
5695
5696static void sRef_setDependentAux (sRef s, fileloc loc)
5697{
5698 if (!sRef_isShared (s))
5699 {
5700 sRef_setDependent (s, loc);
5701 }
5702}
5703
5704void sRef_setKeptComplete (sRef s, fileloc loc)
5705{
5706 sRef_aliasSetComplete (sRef_setKeptAux, s, loc);
5707}
5708
5709void sRef_setDependentComplete (sRef s, fileloc loc)
5710{
5711 sRef_aliasSetComplete (sRef_setDependentAux, s, loc);
5712}
5713
5714void sRef_setFresh (sRef s, fileloc loc)
5715{
5716 if (sRef_isReasonable (s) && !sRef_isConst (s))
5717 {
5718 sRef_checkMutable (s);
5719 s->aliaskind = AK_FRESH;
5720 s->aliasinfo = stateInfo_updateLoc (s->aliasinfo, SA_CREATED, loc);
5721 DPRINTF (("SetFresh: %s", sRef_unparseFull (s)));
5722 }
5723}
5724
5725void sRef_kill (sRef s, fileloc loc)
5726{
5727 DPRINTF (("Kill: %s", sRef_unparseFull (s)));
5728
5729 if (sRef_isReasonable (s) && !sRef_isShared (s) && !sRef_isConst (s))
5730 {
5731 sRef base = sRef_getBaseSafe (s);
5732 sRef_checkMutable (s);
5733
5734 while (sRef_isReasonable (base) && sRef_isKnown (base))
5735 {
5736 if (base->defstate == SS_DEFINED)
5737 {
5738 sRef_checkMutable (base);
5739 base->defstate = SS_PDEFINED;
5740 base = sRef_getBaseSafe (base);
5741 }
5742 else
5743 {
5744 break;
5745 }
5746 }
5747
5748 s->aliaskind = s->oaliaskind;
5749 s->defstate = SS_DEAD;
5750 s->definfo = stateInfo_updateLoc (s->definfo, SA_KILLED, loc);
5751 DPRINTF (("State info: %s", stateInfo_unparse (s->definfo)));
5752 sRef_clearDerived (s);
5753 }
5754}
5755
5756void sRef_maybeKill (sRef s, fileloc loc)
5757{
5758 if (sRef_isReasonable (s))
5759 {
5760 sRef base = sRef_getBaseSafe (s);
5761 sRef_checkMutable (s);
5762
5763 while (sRef_isReasonable (base) && sRef_isKnown (base))
5764 {
5765 if (base->defstate == SS_DEFINED || base->defstate == SS_RELDEF)
5766 {
5767 sRef_checkMutable (base);
5768 base->defstate = SS_PDEFINED;
5769 base = sRef_getBaseSafe (base);
5770 }
5771 else
5772 {
5773 break;
5774 }
5775
5776 }
5777
5778 s->aliaskind = s->oaliaskind;
5779 s->defstate = SS_HOFFA;
5780 s->definfo = stateInfo_updateLoc (s->definfo, SA_PKILLED, loc);
5781 DPRINTF (("State info: %s / %s", sRef_unparse (s),
5782 stateInfo_unparse (s->definfo)));
5783 sRef_clearDerived (s);
5784 }
5785
5786 }
5787
5788/*
5789** just for type checking...
5790*/
5791
5792static void sRef_killAux (sRef s, fileloc loc)
5793{
5794 if (sRef_isReasonable (s) && !sRef_isShared (s))
5795 {
5796 if (sRef_isUnknownArrayFetch (s))
5797 {
5798 sRef_maybeKill (s, loc);
5799 }
5800 else
5801 {
5802 sRef_kill (s, loc);
5803 }
5804 }
5805}
5806
5807/*
5808** kills s and all aliases to s
5809*/
5810
5811void sRef_killComplete (sRef s, fileloc loc)
5812{
5813 DPRINTF (("Kill complete: %s", sRef_unparseFull (s)));
5814 sRef_aliasSetComplete (sRef_killAux, s, loc);
5815}
5816
5817static bool sRef_equivalent (sRef s1, sRef s2)
5818{
5819 return (sRef_compare (s1, s2) == 0);
5820}
5821
5822/*
5823** returns an sRef that will not be free'd on function exit.
5824*/
5825
5826/*@only@*/ sRef sRef_saveCopy (sRef s)
5827{
5828 sRef ret;
5829
5830 if (sRef_isReasonable (s))
5831 {
5832 bool old = inFunction;
5833
5834 /*
5835 ** Exit the function scope, so this sRef is not
5836 ** stored in the deallocation table.
5837 */
5838
5839 inFunction = FALSE;
5840 DPRINTF (("Copying sref: %s", sRef_unparseFull(s)));
5841 ret = sRef_copy (s);
5842 DPRINTF (("Copying ===>: %s", sRef_unparseFull(ret)));
5843 inFunction = old;
5844 }
5845 else
5846 {
5847 ret = sRef_undefined;
5848 }
5849
5850 /*@-dependenttrans@*/
5851 return ret;
5852 /*@=dependenttrans@*/
5853}
5854
5855sRef sRef_copy (sRef s)
5856{
5857 if (sRef_isKindSpecial (s) && !sRef_isGlobalMarker (s))
5858 {
5859 /*@-retalias@*/
5860 return s; /* don't copy specials (except for global markers) */
5861 /*@=retalias@*/
5862 }
5863
5864 if (sRef_isReasonable (s))
5865 {
5866 sRef t = sRef_alloc ();
5867
5868 DPRINTF (("Copying: [%p] %s", s, sRef_unparse (s)));
5869 DPRINTF (("Full: %s", sRef_unparseFull (s)));
5870
5871 t->kind = s->kind;
5872 t->safe = s->safe;
5873 t->modified = s->modified;
5874 t->immut = FALSE; /* Note mutability is not copied. */
5875 t->type = s->type;
5876 t->val = multiVal_copy (s->val);
5877
5878 t->info = sinfo_copy (s);
5879 t->defstate = s->defstate;
5880 t->nullstate = s->nullstate;
5881
5882 /* start modifications */
5883 t->bufinfo.bufstate = s->bufinfo.bufstate;
5884 t->bufinfo.len = s->bufinfo.len;
5885 t->bufinfo.size = s->bufinfo.size;
5886 /* end modifications */
5887
5888 t->aliaskind = s->aliaskind;
5889 t->oaliaskind = s->oaliaskind;
5890
5891 t->expkind = s->expkind;
5892 t->oexpkind = s->oexpkind;
5893
5894 t->nullinfo = stateInfo_copy (s->nullinfo);
5895 t->aliasinfo = stateInfo_copy (s->aliasinfo);
5896 t->definfo = stateInfo_copy (s->definfo);
5897 t->expinfo = stateInfo_copy (s->expinfo);
5898
5899 t->deriv = sRefSet_newDeepCopy (s->deriv);
5900 t->state = valueTable_copy (s->state);
5901
5902 DPRINTF (("Made copy: %s => %s", sRef_unparseFull (s), sRef_unparseFull (t)));
5903 return t;
5904 }
5905 else
5906 {
5907 return sRef_undefined;
5908 }
5909}
5910
5911/*@notfunction@*/
5912# define PREDTEST(func,s) \
5913 do { if (sRef_isInvalid (s)) { return FALSE; } \
5914 else { if (sRef_isConj (s)) \
5915 { return (func (sRef_getConjA (s)) \
5916 || func (sRef_getConjB (s))); }}} while (FALSE);
5917
5918bool sRef_isAddress (sRef s)
5919{
5920 PREDTEST (sRef_isAddress, s);
5921 return (s->kind == SK_ADR);
5922}
5923
5924/*
5925** pretty weak... maybe a flag should control this.
5926*/
5927
5928bool sRef_isThroughArrayFetch (sRef s)
5929{
5930 if (sRef_isReasonable (s))
5931 {
5932 sRef tref = s;
5933
5934 do
5935 {
5936 sRef lt;
5937
5938 if (sRef_isArrayFetch (tref))
5939 {
5940 return TRUE;
5941 }
5942
5943 lt = sRef_getBase (tref);
5944 tref = lt;
5945 } while (sRef_isReasonable (tref));
5946 }
5947
5948 return FALSE;
5949}
5950
5951bool sRef_isArrayFetch (sRef s)
5952{
5953 PREDTEST (sRef_isArrayFetch, s);
5954 return (s->kind == SK_ARRAYFETCH);
5955}
5956
5957bool sRef_isMacroParamRef (sRef s)
5958{
5959 if (context_inMacro () && sRef_isCvar (s))
5960 {
5961 uentry ue = sRef_getUentry (s);
5962 cstring pname = makeParam (uentry_rawName (ue));
5963 uentry mac = usymtab_lookupSafe (pname);
5964
5965 cstring_free (pname);
5966 return (uentry_isValid (mac));
5967 }
5968
5969 return FALSE;
5970}
5971
5972bool sRef_isCvar (sRef s)
5973{
5974 PREDTEST (sRef_isCvar, s);
5975 return (s->kind == SK_CVAR);
5976}
5977
5978bool sRef_isConst (sRef s)
5979{
5980 PREDTEST (sRef_isConst, s);
5981 return (s->kind == SK_CONST);
5982}
5983
5984bool sRef_isObject (sRef s)
5985{
5986 PREDTEST (sRef_isObject, s);
5987 return (s->kind == SK_OBJECT);
5988}
5989
5990bool sRef_isExternal (sRef s)
5991{
5992 PREDTEST (sRef_isExternal, s);
5993 return (s->kind == SK_EXTERNAL);
5994}
5995
5996static bool sRef_isDerived (sRef s)
5997{
5998 PREDTEST (sRef_isDerived, s);
5999 return (s->kind == SK_DERIVED);
6000}
6001
6002bool sRef_isField (sRef s)
6003{
6004 PREDTEST (sRef_isField, s);
6005 return (s->kind == SK_FIELD);
6006}
6007
6008static bool sRef_isIndex (sRef s)
6009{
6010 PREDTEST (sRef_isIndex, s);
6011 return (s->kind == SK_ARRAYFETCH);
6012}
6013
6014bool sRef_isAnyParam (sRef s)
6015{
6016 PREDTEST (sRef_isAnyParam, s);
6017 return (s->kind == SK_PARAM);
6018}
6019
6020bool sRef_isParam (sRef s)
6021{
6022 PREDTEST (sRef_isParam, s);
6023 return (s->kind == SK_PARAM);
6024}
6025
6026bool sRef_isDirectParam (sRef s)
6027{
6028 PREDTEST (sRef_isDirectParam, s);
6029
6030 return ((s->kind == SK_CVAR) &&
6031 (s->info->cvar->lexlevel == functionScope) &&
6032 (context_inFunction () &&
6033 (s->info->cvar->index <= usymId_fromInt (uentryList_size (context_getParams ())))));
6034}
6035
6036bool sRef_isPointer (sRef s)
6037{
6038 PREDTEST (sRef_isPointer, s);
6039 return (s->kind == SK_PTR);
6040}
6041
6042/*
6043** returns true if storage referenced by s is visible
6044*/
6045
6046bool sRef_isReference (sRef s)
6047{
6048 PREDTEST (sRef_isReference, s);
6049
6050 return (sRef_isPointer (s) || sRef_isIndex (s) || sRef_isFileOrGlobalScope (s)
6051 || (sRef_isField (s) && (sRef_isReference (s->info->field->rec))));
6052}
6053
6054bool sRef_isIReference (sRef s)
6055{
6056 return (sRef_isPointer (s) || sRef_isAddress (s) || sRef_isIndex (s)
6057 || sRef_isField (s) || sRef_isArrayFetch (s));
6058}
6059
6060bool sRef_isFileOrGlobalScope (sRef s)
6061{
6062 return (sRef_isCvar (s) && (s->info->cvar->lexlevel <= fileScope));
6063}
6064
6065bool sRef_isRealGlobal (sRef s)
6066{
6067 return (sRef_isCvar (s) && (s->info->cvar->lexlevel == globScope));
6068}
6069
6070bool sRef_isFileStatic (sRef s)
6071{
6072 return (sRef_isCvar (s) && (s->info->cvar->lexlevel == fileScope));
6073}
6074
6075bool sRef_isAliasCheckedGlobal (sRef s)
6076{
6077 if (sRef_isFileOrGlobalScope (s))
6078 {
6079 uentry ue = sRef_getUentry (s);
6080
6081 return context_checkAliasGlob (ue);
6082 }
6083 else
6084 {
6085 return FALSE;
6086 }
6087}
6088
6089void sRef_free (/*@only@*/ sRef s)
6090{
6091 if (s != sRef_undefined && s->kind != SK_SPECIAL)
6092 {
6093 DPRINTF (("Free sref: [%p]", s));
6094
6095 sRef_checkValid (s);
6096
6097 multiVal_free (s->val); /* evans 2002-07-12 */
6098
6099 stateInfo_free (s->expinfo);
6100 stateInfo_free (s->aliasinfo);
6101 stateInfo_free (s->definfo);
6102 stateInfo_free (s->nullinfo);
6103
6104 sRefSet_free (s->deriv);
6105 s->deriv = sRefSet_undefined;
6106
6107 valueTable_free (s->state);
6108 sinfo_free (s);
6109
6110
6111 /* drl added to help locate use after release*/
6112 s->expinfo = stateInfo_undefined;
6113 s->aliasinfo = stateInfo_undefined;
6114 s->definfo = stateInfo_undefined;
6115 s->nullinfo = stateInfo_undefined;
6116
6117 sfree (s);
6118 }
6119}
6120
6121void sRef_setType (sRef s, ctype t)
6122{
6123 if (sRef_isReasonable (s))
6124 {
6125 sRef_checkMutable (s);
6126 s->type = t;
6127 }
6128}
6129
6130void sRef_setTypeFull (sRef s, ctype t)
6131{
6132 if (sRef_isReasonable (s))
6133 {
6134 sRef_checkMutable (s);
6135 s->type = t;
6136
6137 sRefSet_allElements (s->deriv, current)
6138 {
6139 sRef_setTypeFull (current, ctype_unknown);
6140 } end_sRefSet_allElements ;
6141 }
6142}
6143
6144/*@exposed@*/ sRef
6145 sRef_buildField (/*@exposed@*/ sRef rec, /*@dependent@*/ cstring f)
6146{
6147 return (sRef_buildNCField (rec, f));
6148}
6149
6150static /*@exposed@*/ sRef
6151sRef_findDerivedField (/*@notnull@*/ sRef rec, cstring f)
6152{
6153 sRefSet_allElements (sRef_derivedFields (rec), sr)
6154 {
6155 if (sRef_isReasonable (sr))
6156 {
6157 if (sRef_isReasonable (sr))
6158 {
6159 if (sr->info != NULL)
6160 {
6161 if (sr->kind == SK_FIELD && cstring_equal (sr->info->field->field, f))
6162 {
6163 return sr;
6164 }
6165 }
6166 }
6167 else
6168 {
6169 llcontbug (message ("Invalid sRef as derived field of %s", sRef_unparse (rec)));
6170 }
6171 }
6172 } end_sRefSet_allElements;
6173
6174 return sRef_undefined;
6175}
6176
6177/*@dependent@*/ /*@observer@*/ sRefSet sRef_derivedFields (/*@temp@*/ sRef rec)
6178{
6179 if (sRef_isReasonable (rec))
6180 {
6181 sRefSet ret;
6182 ret = rec->deriv;
6183 return (ret);
6184 }
6185 else
6186 {
6187 return (sRefSet_undefined);
6188 }
6189}
6190
6191static /*@exposed@*/ sRef
6192 sRef_findDerivedPointer (sRef s)
6193{
6194 if (sRef_isReasonable (s))
6195 {
6196 sRefSet_realElements (s->deriv, sr)
6197 {
6198 if (sRef_isReasonable (sr) && sr->kind == SK_PTR)
6199 {
6200 return sr;
6201 }
6202 } end_sRefSet_realElements;
6203 }
6204
6205 return sRef_undefined;
6206}
6207
6208bool
6209sRef_isUnknownArrayFetch (sRef s)
6210{
6211 return (sRef_isReasonable (s)
6212 && s->kind == SK_ARRAYFETCH
6213 && !s->info->arrayfetch->indknown);
6214}
6215
6216static /*@exposed@*/ sRef
6217sRef_findDerivedArrayFetch (/*@notnull@*/ sRef s, bool isknown, int idx, bool dead)
6218{
6219
6220 if (isknown)
6221 {
6222 sRefSet_realElements (s->deriv, sr)
6223 {
6224 if (sRef_isReasonable (sr)
6225 && sr->kind == SK_ARRAYFETCH
6226 && sr->info->arrayfetch->indknown
6227 && (sr->info->arrayfetch->ind == idx))
6228 {
6229 return sr;
6230 }
6231 } end_sRefSet_realElements;
6232 }
6233 else
6234 {
6235 sRefSet_realElements (s->deriv, sr)
6236 {
6237 if (sRef_isReasonable (sr)
6238 && sr->kind == SK_ARRAYFETCH
6239 && (!sr->info->arrayfetch->indknown
6240 || (sr->info->arrayfetch->indknown &&
6241 sr->info->arrayfetch->ind == 0)))
6242 {
6243 if (sRef_isDead (sr) || sRef_isKept (sr))
6244 {
6245 if (dead || context_getFlag (FLG_STRICTUSERELEASED))
6246 {
6247 return sr;
6248 }
6249 }
6250 else
6251 {
6252 return sr;
6253 }
6254 }
6255 } end_sRefSet_realElements;
6256 }
6257
6258 return sRef_undefined;
6259}
6260
6261static /*@exposed@*/ sRef
6262sRef_buildNCField (/*@exposed@*/ sRef rec, /*@exposed@*/ cstring f)
6263{
6264 sRef s;
6265
6266 DPRINTF (("Build nc field: %s / %s",
6267 sRef_unparseFull (rec), f));
6268
6269 if (sRef_isInvalid (rec))
6270 {
6271 return sRef_undefined;
6272 }
6273
6274 /*
6275 ** check if the field already has been referenced
6276 */
6277
6278 s = sRef_findDerivedField (rec, f);
6279
6280 if (sRef_isReasonable (s))
6281 {
6282 return s;
6283 }
6284 else
6285 {
6286 ctype ct = ctype_realType (rec->type);
6287
6288 DPRINTF (("Field of: %s", sRef_unparse (rec)));
6289
6290 s = sRef_newRef ();
6291 s->kind = SK_FIELD;
6292 s->info = (sinfo) dmalloc (sizeof (*s->info));
6293 s->info->field = (fldinfo) dmalloc (sizeof (*s->info->field));
6294 s->info->field->rec = rec;
6295 s->info->field->field = f; /* doesn't copy f */
6296
6297 if (ctype_isKnown (ct) && ctype_isSU (ct))
6298 {
6299 uentry ue = uentryList_lookupField (ctype_getFields (ct), f);
6300
6301 if (!uentry_isUndefined (ue))
6302 {
6303 DPRINTF (("lookup: %s for %s", uentry_unparseFull (ue),
6304 ctype_unparse (ct)));
6305
6306 s->type = uentry_getType (ue);
6307
6308 if (ctype_isMutable (s->type)
6309 && rec->aliaskind != AK_STACK
6310 && !alkind_isStatic (rec->aliaskind))
6311 {
6312 s->aliaskind = rec->aliaskind;
6313 }
6314 else
6315 {
6316 s->aliaskind = AK_UNKNOWN;
6317 }
6318
6319 if (sRef_isStateDefined (rec) || sRef_isStateUnknown (rec)
6320 || sRef_isPdefined (rec))
6321 {
6322 sRef_setStateFromUentry (s, ue);
6323 }
6324 else
6325 {
6326 sRef_setPartsFromUentry (s, ue);
6327 }
6328
6329 s->oaliaskind = s->aliaskind;
6330 s->oexpkind = s->expkind;
6331
6332 DPRINTF (("sref: %s", sRef_unparseFull (s)));
6333 }
6334 else
6335 {
6336 /*
6337 Never report this as an error. It can happen whenever there
6338 is casting involved.
6339
6340 if (report)
6341 {
6342 llcontbug (message ("buildNCField --- no field %s: %q / %s",
6343 f, sRef_unparse (s), ctype_unparse (ct)));
6344 }
6345 */
6346
6347 return sRef_undefined;
6348 }
6349 }
6350
6351 if (rec->defstate == SS_DEFINED
6352 && (s->defstate == SS_UNDEFINED || s->defstate == SS_UNKNOWN))
6353 {
6354 s->defstate = SS_DEFINED;
6355 }
6356 else if (rec->defstate == SS_PARTIAL)
6357 {
6358 s->defstate = SS_PARTIAL;
6359 }
6360 else if (rec->defstate == SS_ALLOCATED)
6361 {
6362 if (ctype_isStackAllocated (ct) && ctype_isStackAllocated (s->type))
6363 {
6364 s->defstate = SS_ALLOCATED;
6365 }
6366 else
6367 {
6368 s->defstate = SS_UNDEFINED;
6369 }
6370 }
6371 else if (s->defstate == SS_UNKNOWN)
6372 {
6373 s->defstate = rec->defstate;
6374 }
6375 else
6376 {
6377 ; /* no change */
6378 }
6379
6380 if (s->defstate == SS_UNDEFINED)
6381 {
6382 ctype rt = ctype_realType (s->type);
6383
6384 if (ctype_isArray (rt) || ctype_isSU (rt))
6385 {
6386 s->defstate = SS_ALLOCATED;
6387 }
6388 }
6389
6390 sRef_addDeriv (rec, s);
6391 DPRINTF (("Add deriv: %s", sRef_unparseFull (rec)));
6392
6393 if (ctype_isInt (s->type) && cstring_equal (f, REFSNAME))
6394 {
6395 s->aliaskind = AK_REFS;
6396 s->oaliaskind = AK_REFS;
6397 }
6398
6399 DPRINTF (("Build field ==> %s", sRef_unparseFull (s)));
6400 return s;
6401 }
6402}
6403
6404bool
6405sRef_isStackAllocated (sRef s)
6406{
6407 return (sRef_isReasonable(s)
6408 && s->defstate == SS_ALLOCATED && ctype_isStackAllocated (s->type));
6409}
6410
6411static
6412void sRef_setArrayFetchState (/*@notnull@*/ /*@exposed@*/ sRef s,
6413 /*@notnull@*/ /*@exposed@*/ sRef arr)
6414{
6415 sRef_checkMutable (s);
6416
6417 if (ctype_isRealAP (arr->type))
6418 {
6419 s->type = ctype_baseArrayPtr (arr->type);
6420 }
6421
6422 /* a hack, methinks... makeArrayFetch (&a[0]) ==> a[] */
6423 /* evans - 2001-08-27: not sure where this was necessary - it
6424 ** causes an assertion in in aliasCheckPred to fail.
6425 */
6426
6427 if (sRef_isAddress (arr))
6428 {
6429 sRef t = arr->info->ref;
6430
6431 if (sRef_isArrayFetch (t))
6432 {
6433 s->info->arrayfetch->arr = t->info->arrayfetch->arr;
6434 }
6435 }
6436 else if (ctype_isRealPointer (arr->type))
6437 {
6438 sRef sp = sRef_findDerivedPointer (arr);
6439
6440 if (sRef_isReasonable (sp))
6441 {
6442
6443 if (ctype_isMutable (s->type))
6444 {
6445 s->expkind = sRef_getExKind (sp);
6446 s->expinfo = stateInfo_copy (sp->expinfo);
6447
6448 s->aliaskind = sp->aliaskind;
6449 s->aliasinfo = stateInfo_copy (sp->aliasinfo);
6450 }
6451
6452 s->defstate = sp->defstate;
6453
6454 if (s->defstate == SS_DEFINED)
6455 {
6456 if (!context_getFlag (FLG_STRICTDESTROY))
6457 {
6458 s->defstate = SS_PARTIAL;
6459 }
6460 }
6461
6462 DPRINTF (("Set null state: %s / %s", sRef_unparseFull (s), sRef_unparseFull (sp)));
6463 sRef_setNullStateN (s, sRef_getNullState (sp));
6464 }
6465 else
6466 {
6467 if (arr->defstate == SS_UNDEFINED)
6468 {
6469 s->defstate = SS_UNUSEABLE;
6470 }
6471 else if ((arr->defstate == SS_ALLOCATED) && !ctype_isSU (s->type))
6472 {
6473 s->defstate = SS_UNDEFINED;
6474 }
6475 else
6476 {
6477 if (!context_getFlag (FLG_STRICTDESTROY))
6478 {
6479 s->defstate = SS_PARTIAL;
6480 }
6481 else
6482 {
6483 s->defstate = SS_DEFINED;
6484 }
6485
6486 /*
6487 ** Very weak checking for array elements.
6488 ** Was:
6489 ** s->defstate = arr->defstate;
6490 */
6491 }
6492
6493 s->expkind = sRef_getExKind (arr);
6494 s->expinfo = stateInfo_copy (arr->expinfo);
6495
6496 if (arr->aliaskind == AK_LOCAL || arr->aliaskind == AK_FRESH)
6497 {
6498 s->aliaskind = AK_LOCAL;
6499 }
6500 else
6501 {
6502 s->aliaskind = AK_UNKNOWN;
6503 }
6504
6505 sRef_setTypeState (s);
6506 }
6507 }
6508 else
6509 {
6510 if (arr->defstate == SS_DEFINED)
6511 {
6512 /*
6513 ** Very weak checking for array elements.
6514 ** Was:
6515 ** s->defstate = arr->defstate;
6516 */
6517
6518 if (context_getFlag (FLG_STRICTDESTROY))
6519 {
6520 s->defstate = SS_DEFINED;
6521 }
6522 else
6523 {
6524 s->defstate = SS_PARTIAL;
6525 }
6526 }
6527 else if (arr->defstate == SS_ALLOCATED)
6528 {
6529 if (ctype_isRealArray (s->type))
6530 {
6531 s->defstate = SS_ALLOCATED;
6532 }
6533 else
6534 {
6535 if (!s->info->arrayfetch->indknown)
6536 {
6537 /*
6538 ** is index is unknown, elements is defined or
6539 ** allocated is any element is!
6540 */
6541
6542 s->defstate = SS_UNDEFINED;
6543
6544 sRefSet_allElements (arr->deriv, sr)
6545 {
6546 if (sRef_isReasonable (sr))
6547 {
6548 if (sRef_isReasonable (sr))
6549 {
6550 if (sr->defstate == SS_ALLOCATED)
6551 {
6552 s->defstate = SS_ALLOCATED;
6553 }
6554 else
6555 {
6556 if (sr->defstate == SS_DEFINED)
6557 {
6558 if (context_getFlag (FLG_STRICTDESTROY))
6559 {
6560 s->defstate = SS_DEFINED;
6561 }
6562 else
6563 {
6564 s->defstate = SS_PARTIAL;
6565 }
6566
6567 break;
6568 }
6569 }
6570 }
6571 else
6572 {
6573 llcontbug (message ("Invalid sRef as derived element of %s", sRef_unparse (arr)));
6574 }
6575 }
6576 } end_sRefSet_allElements;
6577 }
6578 else
6579 {
6580 s->defstate = SS_UNDEFINED;
6581 }
6582 }
6583 }
6584 else
6585 {
6586 s->defstate = arr->defstate;
6587 }
6588
6589
6590 /*
6591 ** kludgey way to guess where aliaskind applies
6592 */
6593
6594 if (ctype_isMutable (s->type)
6595 && !ctype_isPointer (arr->type)
6596 && !alkind_isStatic (arr->aliaskind)
6597 && !alkind_isStack (arr->aliaskind)) /* evs - 2000-06-20: don't pass stack allocation to members */
6598 {
6599 s->aliaskind = arr->aliaskind;
6600 }
6601 else
6602 {
6603 s->aliaskind = AK_UNKNOWN;
6604 }
6605
6606 sRef_setTypeState (s);
6607 }
6608
6609 if (sRef_isObserver (arr))
6610 {
6611 s->expkind = XO_OBSERVER;
6612 s->expinfo = stateInfo_copy (arr->expinfo);
6613 }
6614}
6615
6616/*@exposed@*/ sRef sRef_buildArrayFetch (/*@exposed@*/ sRef arr)
6617{
6618 sRef s;
6619
6620 if (!sRef_isReasonable (arr)) {
6621 /*@-nullret@*/ return arr /*@=nullret@*/;
6622 }
6623
6624 if (ctype_isRealPointer (arr->type))
6625 {
6626 (void) sRef_buildPointer (arr); /* do this to define arr! */
6627 }
6628
6629 s = sRef_findDerivedArrayFetch (arr, FALSE, 0, FALSE);
6630
6631 if (sRef_isReasonable (s))
6632 {
6633 /* evans 2001-07-12: this is bogus, clean-up hack */
6634 if (s->info->arrayfetch->arr != arr)
6635 {
6636 sRef res;
6637 check (sRefSet_delete (arr->deriv, s));
6638 res = sRef_buildArrayFetch (arr);
6639 sRef_copyState (res, s);
6640 llassert (res->info->arrayfetch->arr == arr);
6641 return res;
6642 }
6643
6644 s->expkind = sRef_getExKind (arr);
6645 s->expinfo = stateInfo_copy (arr->expinfo);
6646
6647 return s;
6648 }
6649 else
6650 {
6651 s = sRef_newRef ();
6652
6653 s->kind = SK_ARRAYFETCH;
6654 s->info = (sinfo) dmalloc (sizeof (*s->info));
6655 s->info->arrayfetch = (ainfo) dmalloc (sizeof (*s->info->arrayfetch));
6656 s->info->arrayfetch->indknown = FALSE;
6657 s->info->arrayfetch->ind = 0;
6658 s->info->arrayfetch->arr = arr;
6659
6660 sRef_setArrayFetchState (s, arr);
6661
6662 s->oaliaskind = s->aliaskind;
6663 s->oexpkind = s->expkind;
6664
6665 if (!context_inProtectVars ())
6666 {
6667 sRef_addDeriv (arr, s);
6668 }
6669
6670 if (valueTable_isUndefined (s->state))
6671 {
6672 s->state = context_createValueTable
6673 (s, stateInfo_makeLoc (g_currentloc, SA_CREATED));
6674 }
6675
6676 return (s);
6677 }
6678}
6679
6680/*@exposed@*/ sRef
6681 sRef_buildArrayFetchKnown (/*@exposed@*/ sRef arr, int i)
6682{
6683 sRef s;
6684
6685 if (!sRef_isReasonable (arr)) {
6686 /*@-nullret@*/ return arr /*@=nullret@*/;
6687 }
6688
6689 if (ctype_isRealPointer (arr->type))
6690 {
6691 (void) sRef_buildPointer (arr); /* do this to define arr! */
6692 }
6693
6694 s = sRef_findDerivedArrayFetch (arr, TRUE, i, FALSE);
6695
6696 if (sRef_isReasonable (s))
6697 {
6698 /* evans 2001-07-12: this is bogus, clean-up hack */
6699 if (s->info->arrayfetch->arr != arr)
6700 {
6701 sRef res;
6702
6703 check (sRefSet_delete (arr->deriv, s));
6704 res = sRef_buildArrayFetchKnown (arr, i);
6705
6706 llassert (res->info->arrayfetch->arr == arr);
6707 sRef_copyState (res, s);
6708 llassert (res->info->arrayfetch->arr == arr);
6709 return res;
6710 }
6711
6712 s->expkind = sRef_getExKind (arr);
6713 s->expinfo = stateInfo_copy (arr->expinfo);
6714
6715 llassert (s->info->arrayfetch->arr == arr);
6716 return s;
6717 }
6718 else
6719 {
6720 s = sRef_newRef ();
6721
6722 s->kind = SK_ARRAYFETCH;
6723 s->info = (sinfo) dmalloc (sizeof (*s->info));
6724 s->info->arrayfetch = (ainfo) dmalloc (sizeof (*s->info->arrayfetch));
6725 s->info->arrayfetch->arr = arr;
6726 s->info->arrayfetch->indknown = TRUE;
6727 s->info->arrayfetch->ind = i;
6728
6729 sRef_setArrayFetchState (s, arr);
6730 /* evans 2001-08-27 no: can change this - llassert (s->info->arrayfetch->arr == arr); */
6731
6732 s->oaliaskind = s->aliaskind;
6733 s->oexpkind = s->expkind;
6734 sRef_addDeriv (arr, s);
6735
6736 llassert (valueTable_isUndefined (s->state));
6737 s->state = context_createValueTable (s, stateInfo_makeLoc (g_currentloc, SA_CREATED));
6738 return (s);
6739 }
6740}
6741
6742/*
6743** sets everything except for defstate
6744*/
6745
6746static void
6747sRef_setPartsFromUentry (sRef s, uentry ue)
6748{
6749 sRef uref = uentry_getSref (ue);
6750
6751 llassert (sRef_isReasonable (s));
6752
6753 s->aliaskind = alkind_derive (s->aliaskind, uentry_getAliasKind (ue));
6754 s->oaliaskind = s->aliaskind;
6755
6756 if (s->expkind == XO_UNKNOWN)
6757 {
6758 s->expkind = uentry_getExpKind (ue);
6759 }
6760
6761 s->oexpkind = s->expkind;
6762
6763 if (sRef_getNullState (s) == NS_UNKNOWN)
6764 {
6765 DPRINTF (("Set null state: %s / %s", sRef_unparseFull (s), uentry_unparseFull (ue)));
6766 sRef_setNullStateN (s, sRef_getNullState (uentry_getSref (ue)));
6767 }
6768 else
6769 {
6770 DPRINTF (("Skipping null null state!"));
6771 }
6772
6773 if (s->aliaskind == AK_IMPONLY && (sRef_isExposed (s) || sRef_isObserver (s)))
6774 {
6775 s->oaliaskind = s->aliaskind = AK_IMPDEPENDENT;
6776 }
6777
6778 if (sRef_isReasonable (uref))
6779 {
6780 valueTable utable = uref->state;
6781 valueTable_free (s->state);
6782 s->state = valueTable_copy (utable);
6783 }
6784}
6785
6786static void
6787sRef_setStateFromAbstractUentry (sRef s, uentry ue)
6788{
6789 llassert (sRef_isReasonable (s));
6790 sRef_checkMutable (s);
6791
6792 sRef_setPartsFromUentry (s, ue);
6793
6794 s->aliaskind = alkind_derive (s->aliaskind, uentry_getAliasKind (ue));
6795 s->oaliaskind = s->aliaskind;
6796
6797 if (s->expkind == XO_UNKNOWN)
6798 {
6799 s->expkind = uentry_getExpKind (ue);
6800 }
6801
6802 s->oexpkind = s->expkind;
6803}
6804
6805void
6806sRef_setStateFromUentry (sRef s, uentry ue)
6807{
6808 sstate defstate;
6809
6810 sRef_checkMutable (s);
6811 llassert (sRef_isReasonable (s));
6812
6813 sRef_setPartsFromUentry (s, ue);
6814
6815 defstate = uentry_getDefState (ue);
6816
6817 if (sstate_isKnown (defstate))
6818 {
6819 s->defstate = defstate;
6820 }
6821 else
6822 {
6823 ;
6824 }
6825}
6826
6827/*@exposed@*/ sRef
6828 sRef_buildPointer (/*@exposed@*/ sRef t)
6829{
6830 DPRINTF (("build pointer: %s", sRef_unparse (t)));
6831
6832 if (sRef_isInvalid (t)) return sRef_undefined;
6833
6834 if (sRef_isAddress (t))
6835 {
6836 DPRINTF (("Return ref: %s", sRef_unparse (t->info->ref)));
6837 return (t->info->ref);
6838 }
6839 else
6840 {
6841 sRef s = sRef_findDerivedPointer (t);
6842
6843 DPRINTF (("find derived: %s", sRef_unparse (s)));
6844
6845 if (sRef_isReasonable (s))
6846 {
6847 s->expkind = sRef_getExKind (t);
6848 s->expinfo = stateInfo_copy (t->expinfo);
6849
6850 s->oaliaskind = s->aliaskind;
6851 s->oexpkind = s->expkind;
6852
6853 return s;
6854 }
6855 else
6856 {
6857 s = sRef_constructPointerAux (t);
6858
6859 DPRINTF (("construct: %s", sRef_unparse (s)));
6860
6861 if (sRef_isReasonable (s))
6862 {
6863 sRef_addDeriv (t, s);
6864
6865 s->oaliaskind = s->aliaskind;
6866 s->oexpkind = s->expkind;
6867 }
6868
6869 return s;
6870 }
6871 }
6872}
6873
6874/*@exposed@*/ sRef
6875sRef_constructPointer (/*@exposed@*/ sRef t)
6876 /*@modifies t@*/
6877{
6878 return sRef_buildPointer (t);
6879}
6880
6881static /*@exposed@*/ sRef sRef_constructDerefAux (sRef t, bool isdead)
6882{
6883 if (sRef_isReasonable (t))
6884 {
6885 sRef s;
6886
6887 /*
6888 ** if there is a derived t[?], return that. Otherwise, *t.
6889 */
6890
6891 s = sRef_findDerivedArrayFetch (t, FALSE, 0, isdead);
6892
6893 if (sRef_isReasonable (s))
6894 {
6895 DPRINTF (("Found array fetch: %s", sRef_unparseFull (s)));
6896 return s;
6897 }
6898 else
6899 {
6900 sRef ret = sRef_constructPointer (t);
6901
6902 DPRINTF (("Constructed pointer: %s", sRef_unparseFull (ret)));
6903
6904 return ret;
6905 }
6906 }
6907 else
6908 {
6909 return sRef_undefined;
6910 }
6911}
6912
6913sRef sRef_constructDeref (sRef t)
6914{
6915 return sRef_constructDerefAux (t, FALSE);
6916}
6917
6918sRef sRef_constructDeadDeref (sRef t)
6919{
6920 return sRef_constructDerefAux (t, TRUE);
6921}
6922
6923static sRef
6924sRef_constructPointerAux (/*@notnull@*/ /*@exposed@*/ sRef t)
6925{
6926 sRef s = sRef_newRef ();
6927 ctype rt = t->type;
6928 ctype st;
6929
6930 llassert (valueTable_isUndefined (s->state));
6931
6932 s->kind = SK_PTR;
6933 s->info = (sinfo) dmalloc (sizeof (*s->info));
6934 s->info->ref = t;
6935
6936 if (ctype_isRealAP (rt))
6937 {
6938 s->type = ctype_baseArrayPtr (rt);
6939 }
6940
6941 st = ctype_realType (s->type);
6942
6943 if (t->defstate == SS_UNDEFINED)
6944 {
6945 s->defstate = SS_UNUSEABLE;
6946 s->definfo = stateInfo_copy (t->definfo);
6947 }
6948 else if ((t->defstate == SS_ALLOCATED) && !ctype_isSU (st))
6949 {
6950 s->defstate = SS_UNDEFINED;
6951 s->definfo = stateInfo_copy (t->definfo);
6952 }
6953 else
6954 {
6955 s->defstate = t->defstate;
6956 s->definfo = stateInfo_copy (t->definfo);
6957 }
6958
6959 if (t->aliaskind == AK_LOCAL || t->aliaskind == AK_FRESH)
6960 {
6961 s->aliaskind = AK_LOCAL;
6962 }
6963 else
6964 {
6965 s->aliaskind = AK_UNKNOWN;
6966 }
6967
6968 s->expkind = sRef_getExKind (t);
6969 s->expinfo = stateInfo_copy (t->expinfo);
6970
6971 sRef_setTypeState (s);
6972
6973 s->oaliaskind = s->aliaskind;
6974 s->oexpkind = s->expkind;
6975
6976 if (valueTable_isUndefined (s->state))
6977 {
6978 s->state = context_createValueTable (s, stateInfo_makeLoc (g_currentloc, SA_CREATED));
6979 }
6980
6981 DPRINTF (("pointer: %s", sRef_unparseFull (s)));
6982 return s;
6983}
6984
6985bool sRef_hasDerived (sRef s)
6986{
6987 return (sRef_isReasonable (s) && !sRefSet_isEmpty (s->deriv));
6988}
6989
6990void
6991sRef_clearDerived (sRef s)
6992{
6993 if (sRef_isReasonable (s))
6994 {
6995 DPRINTF (("Clear derived: [%p] %s", s, sRef_unparseDebug (s)));
6996 sRefSet_clear (s->deriv);
6997 }
6998}
6999
7000void
7001sRef_clearDerivedComplete (sRef s)
7002{
7003 if (sRef_isReasonable (s))
7004 {
7005 sRef base = sRef_getBaseSafe (s);
7006
7007 while (sRef_isReasonable (base))
7008 {
7009 DPRINTF (("Clear derived: [%p] %s", base, sRef_unparse (base)));
7010 sRefSet_clear (base->deriv);
7011 base = sRef_getBaseSafe (base);
7012 }
7013
7014 DPRINTF (("Clear derived: [%p] %s", s, sRef_unparse (s)));
7015 sRefSet_clear (s->deriv);
7016 }
7017}
7018
7019/*@exposed@*/ sRef sRef_makePointer (/*@exposed@*/ sRef s)
7020 /*@modifies s@*/
7021{
7022 sRef res = sRef_buildPointer (s);
7023
7024 DPRINTF (("Res: %s", sRef_unparseFull (res)));
7025 return res;
7026}
7027
7028/*
7029** &a[] => a (this is for out params)
7030*/
7031
7032/*@exposed@*/ sRef
7033sRef_makeAnyArrayFetch (/*@exposed@*/ sRef arr)
7034{
7035 if (sRef_isAddress (arr))
7036 {
7037 return (arr->info->ref);
7038 }
7039 else
7040 {
7041 return (sRef_buildArrayFetch (arr));
7042 }
7043}
7044
7045/*@exposed@*/ sRef
7046sRef_makeArrayFetch (/*@exposed@*/ sRef arr)
7047{
7048 return (sRef_buildArrayFetch (arr));
7049}
7050
7051/*@exposed@*/ sRef
7052sRef_makeArrayFetchKnown (/*@exposed@*/ sRef arr, int i)
7053{
7054 return (sRef_buildArrayFetchKnown (arr, i));
7055}
7056
7057/*@exposed@*/ sRef
7058sRef_makeField (sRef rec, /*@dependent@*/ cstring f)
7059{
7060 sRef ret;
7061 ret = sRef_buildField (rec, f);
7062 return ret;
7063}
7064
7065/*@exposed@*/ sRef
7066sRef_makeNCField (/*@exposed@*/ sRef rec, /*@dependent@*/ cstring f)
7067{
7068 return (sRef_buildNCField (rec, f));
7069}
7070
7071/*@only@*/ cstring
7072sRef_unparseKindName (sRef s)
7073{
7074 cstring result;
7075
7076 if (s == sRef_undefined) return cstring_makeLiteral ("<invalid>");
7077
7078 s = sRef_fixConj (s);
7079
7080 switch (s->kind)
7081 {
7082 case SK_CVAR:
7083 if (sRef_isLocalVar (s))
7084 {
7085 result = cstring_makeLiteral ("Variable");
7086 }
7087 else
7088 {
7089 result = cstring_makeLiteral ("Undef global");
7090 }
7091 break;
7092 case SK_PARAM:
7093 result = cstring_makeLiteral ("Out parameter");
7094 break;
7095 case SK_ARRAYFETCH:
7096 if (sRef_isAnyParam (s->info->arrayfetch->arr))
7097 {
7098 result = cstring_makeLiteral ("Out parameter");
7099 }
7100 else if (sRef_isIndexKnown (s))
7101 {
7102 result = cstring_makeLiteral ("Array element");
7103 }
7104 else
7105 {
7106 result = cstring_makeLiteral ("Value");
7107 }
7108 break;
7109 case SK_PTR:
7110 if (sRef_isAnyParam (s->info->ref))
7111 {
7112 result = cstring_makeLiteral ("Out parameter");
7113 }
7114 else
7115 {
7116 result = cstring_makeLiteral ("Value");
7117 }
7118 break;
7119 case SK_ADR:
7120 result = cstring_makeLiteral ("Value");
7121 break;
7122 case SK_FIELD:
7123 result = cstring_makeLiteral ("Field");
7124 break;
7125 case SK_OBJECT:
7126 result = cstring_makeLiteral ("Object");
7127 break;
7128 case SK_UNCONSTRAINED:
7129 result = cstring_makeLiteral ("<anything>");
7130 break;
7131 case SK_RESULT:
7132 case SK_SPECIAL:
7133 case SK_UNKNOWN:
7134 case SK_EXTERNAL:
7135 case SK_DERIVED:
7136 case SK_CONST:
7137 case SK_TYPE:
7138 result = cstring_makeLiteral ("<unknown>");
7139 break;
7140 case SK_CONJ:
7141 result = cstring_makeLiteral ("<conj>");
7142 break;
7143 case SK_NEW:
7144 result = cstring_makeLiteral ("Storage");
7145 break;
7146 }
7147
7148 return result;
7149}
7150
7151/*@only@*/ cstring
7152sRef_unparseKindNamePlain (sRef s)
7153{
7154 cstring result;
7155
7156 if (s == sRef_undefined) return cstring_makeLiteral ("<invalid>");
7157
7158 s = sRef_fixConj (s);
7159
7160 switch (s->kind)
7161 {
7162 case SK_CVAR:
7163 if (sRef_isLocalVar (s))
7164 {
7165 result = cstring_makeLiteral ("Variable");
7166 }
7167 else
7168 {
7169 result = cstring_makeLiteral ("Global");
7170 }
7171 break;
7172 case SK_PARAM:
7173 result = cstring_makeLiteral ("Parameter");
7174 break;
7175 case SK_ARRAYFETCH:
7176 if (sRef_isAnyParam (s->info->arrayfetch->arr))
7177 {
7178 result = cstring_makeLiteral ("Parameter");
7179 }
7180 else if (sRef_isIndexKnown (s))
7181 {
7182 result = cstring_makeLiteral ("Array element");
7183 }
7184 else
7185 {
7186 result = cstring_makeLiteral ("Value");
7187 }
7188 break;
7189 case SK_PTR:
7190 if (sRef_isAnyParam (s->info->ref))
7191 {
7192 result = cstring_makeLiteral ("Parameter");
7193 }
7194 else
7195 {
7196 result = cstring_makeLiteral ("Value");
7197 }
7198 break;
7199 case SK_ADR:
7200 result = cstring_makeLiteral ("Value");
7201 break;
7202 case SK_FIELD:
7203 result = cstring_makeLiteral ("Field");
7204 break;
7205 case SK_OBJECT:
7206 result = cstring_makeLiteral ("Object");
7207 break;
7208 case SK_NEW:
7209 result = cstring_makeLiteral ("Storage");
7210 break;
7211 case SK_UNCONSTRAINED:
7212 result = cstring_makeLiteral ("<anything>");
7213 break;
7214 case SK_RESULT:
7215 case SK_TYPE:
7216 case SK_CONST:
7217 case SK_EXTERNAL:
7218 case SK_DERIVED:
7219 case SK_UNKNOWN:
7220 case SK_SPECIAL:
7221 result = cstring_makeLiteral ("<unknown>");
7222 break;
7223 case SK_CONJ:
7224 result = cstring_makeLiteral ("<conj>");
7225 break;
7226 }
7227
7228 return result;
7229}
7230
7231/*
7232** s1 <- s2
7233*/
7234
7235void
7236sRef_copyState (sRef s1, sRef s2)
7237{
7238 if (sRef_isReasonable (s1) && sRef_isReasonable (s2))
7239 {
7240 s1->defstate = s2->defstate;
7241
7242 /* start modifications */
7243 s1->bufinfo.bufstate = s2->bufinfo.bufstate;
7244 s1->bufinfo.len = s2->bufinfo.len;
7245 s1->bufinfo.size = s2->bufinfo.size;
7246 /* end modifications */
7247
7248 s1->aliaskind = s2->aliaskind;
7249 s1->aliasinfo = stateInfo_update (s1->aliasinfo, s2->aliasinfo);
7250
7251 s1->expkind = s2->expkind;
7252 s1->expinfo = stateInfo_update (s1->expinfo, s2->expinfo);
7253
7254 s1->nullstate = s2->nullstate;
7255 s1->nullinfo = stateInfo_update (s1->nullinfo, s2->nullinfo);
7256
7257 valueTable_free (s1->state);
7258 s1->state = valueTable_copy (s2->state);
7259 s1->safe = s2->safe;
7260 }
7261}
7262
7263sRef
7264sRef_makeNew (ctype ct, sRef t, cstring name)
7265{
7266 sRef s = sRef_newRef ();
7267
7268 s->kind = SK_NEW;
7269 s->type = ct;
7270
7271 llassert (sRef_isReasonable (t));
7272 s->defstate = t->defstate;
7273
7274 s->aliaskind = t->aliaskind;
7275 s->oaliaskind = s->aliaskind;
7276 s->nullstate = t->nullstate;
7277
7278 s->expkind = t->expkind;
7279 s->oexpkind = s->expkind;
7280
7281 s->info = (sinfo) dmalloc (sizeof (*s->info));
7282 s->info->fname = name;
7283
7284 /* start modifications */
7285 s->bufinfo.bufstate = t->bufinfo.bufstate;
7286 /* end modifications */
7287
7288 llassert (valueTable_isUndefined (s->state));
7289 s->state = valueTable_copy (t->state);
7290
7291 DPRINTF (("==> Copying state: %s", valueTable_unparse (s->state)));
7292 DPRINTF (("==> new: %s", sRef_unparseFull (s)));
7293 return s;
7294}
7295
7296sRef
7297sRef_makeType (ctype ct)
7298{
7299 sRef s = sRef_newRef ();
7300
7301 sRef_checkMutable (s);
7302
7303 s->kind = SK_TYPE;
7304 s->type = ct;
7305
7306 s->defstate = SS_UNKNOWN;
7307 s->aliaskind = AK_UNKNOWN;
7308 sRef_setNullStateN (s, NS_UNKNOWN);
7309
7310 /* start modification */
7311 s->bufinfo.bufstate = BB_NOTNULLTERMINATED;
7312 /* end modification */
7313
7314
7315 if (ctype_isUA (ct))
7316 {
7317 typeId uid = ctype_typeId (ct);
7318 uentry ue = usymtab_getTypeEntrySafe (uid);
7319
7320 if (uentry_isValid (ue))
7321 {
7322 sRef_mergeStateQuiet (s, uentry_getSref (ue));
7323 }
7324 }
7325
7326 s->oaliaskind = s->aliaskind;
7327 s->oexpkind = s->expkind;
7328 llassert (valueTable_isUndefined (s->state));
7329 s->state = context_createValueTable (s, stateInfo_makeLoc (g_currentloc, SA_CREATED));
7330
7331 DPRINTF (("Create: %s", sRef_unparseFull (s)));
7332 return s;
7333}
7334
7335sRef
7336sRef_makeConst (ctype ct)
7337{
7338 sRef s = sRef_newRef ();
7339
7340 s->kind = SK_CONST;
7341 s->type = ct;
7342
7343 s->defstate = SS_UNKNOWN;
7344 s->aliaskind = AK_UNKNOWN;
7345 sRef_setNullStateN (s, NS_UNKNOWN);
7346
7347 /* start modification */
7348 s->bufinfo.bufstate = BB_NULLTERMINATED;
7349 /* end modification */
7350
7351 /* evans 2002-04-22: added isManifestBool to avoid errors for -boolfalse initializations */
7352 if (!ctype_isManifestBool (ct) && ctype_isUA (ct))
7353 {
7354 typeId uid = ctype_typeId (ct);
7355 uentry te = usymtab_getTypeEntrySafe (uid);
7356
7357 if (uentry_isValid (te))
7358 {
7359 sRef_mergeStateQuiet (s, uentry_getSref (te));
7360 }
7361 }
7362
7363 s->oaliaskind = s->aliaskind;
7364 s->oexpkind = s->expkind;
7365
7366 llassert (valueTable_isUndefined (s->state));
7367 s->state = context_createValueTable (s, stateInfo_makeLoc (g_currentloc, SA_CREATED));
7368
7369 return s;
7370}
7371
7372bool sRef_hasName (sRef s)
7373{
7374 if (sRef_isInvalid (s))
7375 {
7376 return (FALSE);
7377 }
7378
7379 switch (s->kind)
7380 {
7381 case SK_CVAR:
7382 {
7383 uentry u = usymtab_getRefQuiet (s->info->cvar->lexlevel,
7384 s->info->cvar->index);
7385 return (uentry_hasName (u));
7386 }
7387 case SK_PARAM:
7388 {
7389 if (s->info->paramno >= 0)
7390 {
7391 uentry u = uentryList_getN (context_getParams (),
7392 s->info->paramno);
7393
7394 return (uentry_hasName (u));
7395 }
7396 else
7397 {
7398 llassert (s->info->paramno == PARAMUNKNOWN);
7399 return FALSE;
7400 }
7401 }
7402 default:
7403 return TRUE;
7404 }
7405}
7406
7407bool
7408sRef_sameName (sRef s1, sRef s2)
7409{
7410 if (sRef_isInvalid (s1))
7411 {
7412 return sRef_isInvalid (s2);
7413 }
7414
7415 if (sRef_isInvalid (s2))
7416 {
7417 return (FALSE);
7418 }
7419
7420 switch (s1->kind)
7421 {
7422 case SK_CVAR:
7423 if (s2->kind == SK_CVAR)
7424 {
7425 return (s1->info->cvar->lexlevel == s2->info->cvar->lexlevel
7426 && s1->info->cvar->index == s2->info->cvar->index);
7427 }
7428 else if (s2->kind == SK_PARAM)
7429 {
7430 if (context_inFunctionLike ())
7431 {
7432 if (s2->info->paramno != PARAMUNKNOWN)
7433 {
7434 uentry u1 = usymtab_getRefQuiet (s1->info->cvar->lexlevel,
7435 s1->info->cvar->index);
7436 uentry u2 = uentryList_getN (context_getParams (),
7437 s2->info->paramno);
7438
7439 return (cstring_equalFree (uentry_getName (u1),
7440 uentry_getName (u2)));
7441 }
7442 else
7443 {
7444 return s1->info->paramno == PARAMUNKNOWN;
7445 }
7446 }
7447 else
7448 {
7449 return FALSE;
7450 }
7451 }
7452 else
7453 {
7454 return FALSE;
7455 }
7456 case SK_PARAM:
7457 {
7458 if (s2->kind == SK_PARAM)
7459 {
7460 return (s1->info->paramno == s2->info->paramno);
7461 }
7462 else if (s2->kind == SK_CVAR)
7463 {
7464 if (context_inFunctionLike ())
7465 {
7466 if (s1->info->paramno == PARAMUNKNOWN)
7467 {
7468 return FALSE;
7469 }
7470 else
7471 {
7472 uentry u1 = uentryList_getN (context_getParams (),
7473 s1->info->paramno);
7474 uentry u2 = usymtab_getRefQuiet (s2->info->cvar->lexlevel,
7475 s2->info->cvar->index);
7476
7477
7478 return (cstring_equalFree (uentry_getName (u1),
7479 uentry_getName (u2)));
7480 }
7481 }
7482 else
7483 {
7484 return FALSE;
7485 }
7486 }
7487 else
7488 {
7489 return FALSE;
7490 }
7491 }
7492
7493 case SK_UNCONSTRAINED:
7494 return FALSE;
7495
7496 case SK_ARRAYFETCH:
7497 if (s2->kind == SK_ARRAYFETCH)
7498 {
7499 if (bool_equal (s1->info->arrayfetch->indknown,
7500 s2->info->arrayfetch->indknown))
7501 {
7502 if (!s1->info->arrayfetch->indknown
7503 || (s1->info->arrayfetch->ind == s2->info->arrayfetch->ind))
7504 {
7505 return sRef_sameName (s1->info->arrayfetch->arr,
7506 s2->info->arrayfetch->arr);
7507 }
7508 }
7509 }
7510
7511 return FALSE;
7512 case SK_FIELD:
7513 if (s2->kind == SK_FIELD)
7514 {
7515 if (cstring_equal (s1->info->field->field,
7516 s2->info->field->field))
7517 {
7518 return sRef_sameName (s1->info->field->rec,
7519 s2->info->field->rec);
7520 }
7521
7522 }
7523 return FALSE;
7524 case SK_PTR:
7525 case SK_ADR:
7526 case SK_DERIVED:
7527 case SK_EXTERNAL:
7528 if (s2->kind == s1->kind)
7529 {
7530 return sRef_sameName (s1->info->ref,
7531 s2->info->ref);
7532 }
7533
7534 return FALSE;
7535 case SK_OBJECT:
7536 return FALSE;
7537 case SK_CONJ:
7538 return sRef_sameName (sRef_getConjA (s1), s2);
7539 case SK_NEW:
7540 return FALSE;
7541 case SK_UNKNOWN:
7542 return (s2->kind == SK_UNKNOWN);
7543 case SK_TYPE:
7544 case SK_CONST:
7545 if (s2->kind == s1->kind)
7546 {
7547 return (ctype_equal (s1->type, s2->type));
7548 }
7549
7550 return FALSE;
7551 case SK_SPECIAL:
7552 if (s2->kind == SK_SPECIAL)
7553 {
7554 return (s1->info->spec == s2->info->spec);
7555 }
7556 return FALSE;
7557 case SK_RESULT:
7558 return (s2->kind == SK_RESULT);
7559 default:
7560 return FALSE;
7561 }
7562 BADEXIT;
7563}
7564
7565sRef
7566sRef_fixOuterRef (/*@returned@*/ sRef s)
7567{
7568 sRef root = sRef_getRootBase (s);
7569
7570 if (sRef_isCvar (root))
7571 {
7572 uentry ue = usymtab_getRefQuiet (root->info->cvar->lexlevel,
7573 root->info->cvar->index);
7574
7575 if (uentry_isValid (ue))
7576 {
7577 sRef uref = uentry_getSref (ue);
7578 sRef sr = sRef_fixBase (s, uref);
7579
7580 return (sr);
7581 }
7582 else
7583 {
7584 llcontbug (message ("sRef_fixOuterRef: undefined: %q", sRef_unparseDebug (s)));
7585 return (s);
7586 }
7587 }
7588
7589 return (s);
7590}
7591
7592void
7593sRef_storeState (sRef s)
7594{
7595 if (sRef_isInvalid (s)) return;
7596
7597 sRef_checkMutable (s);
7598 s->oaliaskind = s->aliaskind;
7599 s->oexpkind = s->expkind;
7600}
7601
7602static void sRef_resetStateAux (sRef s, /*@unused@*/ fileloc loc)
7603{
7604 sRef_resetState (s);
7605}
7606
7607void
7608sRef_resetState (sRef s)
7609{
7610 bool changed = FALSE;
7611 if (sRef_isInvalid (s)) return;
7612
7613
7614 if (s->oaliaskind == AK_KILLREF && !sRef_isParam (s))
7615 {
7616 /*
7617 ** killref is used in a kludgey way, to save having to add
7618 ** another alias kind (see usymtab_handleParams)
7619 */
7620
7621 if (s->expkind != s->oexpkind)
7622 {
7623 changed = TRUE;
7624 s->expkind = s->oexpkind;
7625 }
7626 }
7627 else
7628 {
7629 if (s->expkind != s->oexpkind)
7630 {
7631 changed = TRUE;
7632 s->expkind = s->oexpkind;
7633 }
7634
7635 if (s->aliaskind != s->oaliaskind
7636 && s->aliaskind != AK_REFCOUNTED
7637 && s->aliaskind != AK_REFS)
7638 {
7639 changed = TRUE;
7640 s->aliaskind = s->oaliaskind;
7641 }
7642 }
7643
7644 if (changed)
7645 {
7646 sRef_clearDerived (s);
7647 }
7648
7649 }
7650
7651void
7652sRef_resetStateComplete (sRef s)
7653{
7654 sRef_innerAliasSetComplete (sRef_resetStateAux, s, fileloc_undefined);
7655}
7656
7657/*@exposed@*/ sRef
7658sRef_fixBase (/*@returned@*/ sRef s, /*@returned@*/ sRef base)
7659{
7660 sRef tmp = sRef_undefined;
7661 sRef ret;
7662
7663 if (sRef_isInvalid (s)) return s;
7664 if (sRef_isInvalid (base)) return base;
7665
7666 switch (s->kind)
7667 {
7668 case SK_RESULT:
7669 case SK_PARAM:
7670 case SK_CVAR:
7671 ret = base;
7672 break;
7673 case SK_ARRAYFETCH:
7674 tmp = sRef_fixBase (s->info->arrayfetch->arr, base);
7675
7676 if (s->info->arrayfetch->indknown)
7677 {
7678 ret = sRef_makeArrayFetchKnown (tmp, s->info->arrayfetch->ind);
7679 }
7680 else
7681 {
7682 ret = sRef_makeArrayFetch (tmp);
7683 }
7684 break;
7685 case SK_FIELD:
7686 tmp = sRef_fixBase (s->info->field->rec, base);
7687 ret = sRef_buildNCField (tmp, s->info->field->field);
7688 break;
7689 case SK_PTR:
7690 tmp = sRef_fixBase (s->info->ref, base);
7691 ret = sRef_makePointer (tmp);
7692 break;
7693 case SK_ADR:
7694 tmp = sRef_fixBase (s->info->ref, base);
7695 ret = sRef_makeAddress (tmp);
7696 break;
7697 case SK_CONJ:
7698 {
7699 sRef tmpb;
7700
7701 tmp = sRef_fixBase (s->info->conj->a, base);
7702 tmpb = sRef_fixBase (s->info->conj->b, base);
7703
7704 ret = sRef_makeConj (tmp, tmpb);
7705 break;
7706 }
7707 BADDEFAULT;
7708 }
7709
7710 return ret;
7711}
7712
7713static /*@exposed@*/ sRef
7714sRef_fixDirectBase (sRef s, sRef base)
7715{
7716 sRef ret;
7717
7718
7719 if (sRef_isInvalid (s))
7720 {
7721 return sRef_undefined;
7722 }
7723
7724 switch (s->kind)
7725 {
7726 case SK_ARRAYFETCH:
7727 if (s->info->arrayfetch->indknown)
7728 {
7729 ret = sRef_makeArrayFetchKnown (base, s->info->arrayfetch->ind);
7730 }
7731 else
7732 {
7733 ret = sRef_makeArrayFetch (base);
7734 }
7735 break;
7736 case SK_FIELD:
7737 ret = sRef_buildNCField (base, s->info->field->field);
7738 break;
7739 case SK_PTR:
7740 ret = sRef_makePointer (base);
7741 break;
7742 case SK_ADR:
7743 ret = sRef_makeAddress (base);
7744 break;
7745 case SK_CONJ:
7746 {
7747 sRef tmpa, tmpb;
7748
7749 tmpa = sRef_fixDirectBase (s->info->conj->a, base);
7750 tmpb = sRef_fixDirectBase (s->info->conj->b, base);
7751
7752 ret = sRef_makeConj (tmpa, tmpb);
7753 break;
7754 }
7755 BADDEFAULT;
7756 }
7757
7758 sRef_copyState (ret, s);
7759 return ret;
7760}
7761
7762bool
7763sRef_isAllocIndexRef (sRef s)
7764{
7765 return (sRef_isArrayFetch (s) && !(s->info->arrayfetch->indknown)
7766 && sRef_isAllocated (s->info->arrayfetch->arr));
7767}
7768
7769void
7770sRef_showRefLost (sRef s)
7771{
7772 if (sRef_hasAliasInfoLoc (s))
7773 {
7774 llgenindentmsg (cstring_makeLiteral ("Original reference lost"),
7775 sRef_getAliasInfoLoc (s));
7776 }
7777}
7778
7779void
7780sRef_showRefKilled (sRef s)
7781{
7782 if (sRef_isValid (s))
7783 {
7784 DPRINTF (("Killed: %s", sRef_unparseFull (s)));
7785 if (context_getLocIndentSpaces () == 0) {
7786 stateInfo_display (s->definfo, message (" Storage %q", sRef_unparseOpt (s)));
7787 } else {
7788 stateInfo_display (s->definfo, message ("Storage %q", sRef_unparseOpt (s)));
7789 }
7790 }
7791}
7792
7793void
7794sRef_showStateInconsistent (sRef s)
7795{
7796 if (sRef_hasStateInfoLoc (s))
7797 {
7798 llgenindentmsg
7799 (message ("Storage %qbecomes inconsistent (released on one branch)",
7800 sRef_unparseOpt (s)),
7801 sRef_getStateInfoLoc (s));
7802 }
7803}
7804
7805void
7806sRef_showStateInfo (sRef s)
7807{
7808 if (sRef_isValid (s)) {
7809 if (context_getLocIndentSpaces () == 0) {
7810 stateInfo_display (s->definfo, message (" Storage %q", sRef_unparseOpt (s)));
7811 } else {
7812 stateInfo_display (s->definfo, message ("Storage %q", sRef_unparseOpt (s)));
7813 }
7814 }
7815}
7816
7817void
7818sRef_showExpInfo (sRef s)
7819{
7820 if (sRef_isValid (s)) {
7821 if (context_getLocIndentSpaces () == 0) {
7822 stateInfo_display (s->expinfo, message (" Storage %q", sRef_unparseOpt (s)));
7823 } else {
7824 stateInfo_display (s->expinfo, message ("Storage %q", sRef_unparseOpt (s)));
7825 }
7826 }
7827}
7828
7829void
7830sRef_showMetaStateInfo (sRef s, cstring key)
7831{
7832 stateValue val;
7833 metaStateInfo minfo = context_lookupMetaStateInfo (key);
7834
7835 llassert (sRef_isReasonable (s));
7836 llassert (valueTable_isDefined (s->state));
7837 llassert (metaStateInfo_isDefined (minfo));
7838
7839 val = valueTable_lookup (s->state, key);
7840
7841 if (stateValue_hasLoc (val))
7842 {
7843 llgenindentmsg
7844 (message ("%qbecomes %q", sRef_unparseOpt (s),
7845 stateValue_unparseValue (val, minfo)),
7846 stateValue_getLoc (val));
7847 }
7848}
7849
7850void
7851sRef_showNullInfo (sRef s)
7852{
7853 DPRINTF (("Show null info: %s", sRef_unparseFull (s)));
7854
7855 if (sRef_hasNullInfoLoc (s) && sRef_isKnown (s))
7856 {
7857 DPRINTF (("has null info: %s",
7858 fileloc_unparse (sRef_getNullInfoLoc (s))));
7859
7860 switch (sRef_getNullState (s))
7861 {
7862 case NS_CONSTNULL:
7863 {
7864 fileloc loc = sRef_getNullInfoLoc (s);
7865
7866 if (fileloc_isDefined (loc) && !fileloc_isLib (loc))
7867 {
7868 llgenindentmsg
7869 (message ("Storage %qbecomes null", sRef_unparseOpt (s)),
7870 loc);
7871 }
7872 break;
7873 }
7874 case NS_DEFNULL:
7875 {
7876 fileloc loc = sRef_getNullInfoLoc (s);
7877
7878 if (fileloc_isDefined (loc) && !fileloc_isLib (loc))
7879 {
7880 llgenindentmsg (message ("Storage %qbecomes null", sRef_unparseOpt (s)),
7881 loc);
7882 }
7883 break;
7884 }
7885 case NS_ABSNULL:
7886 case NS_POSNULL:
7887 llgenindentmsg
7888 (message ("Storage %qmay become null", sRef_unparseOpt (s)),
7889 sRef_getNullInfoLoc (s));
7890 break;
7891 case NS_NOTNULL:
7892 case NS_MNOTNULL:
7893 llgenindentmsg
7894 (message ("Storage %qbecomes not null", sRef_unparseOpt (s)),
7895 sRef_getNullInfoLoc (s));
7896 break;
7897 case NS_UNKNOWN:
7898 llgenindentmsg
7899 (message ("Storage %qnull state becomes unknown",
7900 sRef_unparseOpt (s)),
7901 sRef_getNullInfoLoc (s));
7902 break;
7903
7904 case NS_ERROR:
7905 BADBRANCHCONT;
7906 break;
7907
7908 default:
7909 llgenindentmsg
7910 (message ("<error case> Storage %q becomes %s",
7911 sRef_unparse (s),
7912 nstate_unparse (sRef_getNullState (s))),
7913 sRef_getNullInfoLoc (s));
7914
7915 break;
7916 }
7917 }
7918}
7919
7920void
7921sRef_showAliasInfo (sRef s)
7922{
7923 if (sRef_isValid (s))
7924 {
7925 if (sRef_isFresh (s))
7926 {
7927 if (context_getLocIndentSpaces () == 0) {
7928 stateInfo_display (s->aliasinfo, message (" Fresh storage %q", sRef_unparseOpt (s)));
7929 } else {
7930 stateInfo_display (s->aliasinfo, message ("Fresh storage %q", sRef_unparseOpt (s)));
7931 }
7932 }
7933 else
7934 {
7935 if (context_getLocIndentSpaces () == 0) {
7936 stateInfo_display (s->aliasinfo, message (" Storage %q", sRef_unparseOpt (s)));
7937 } else {
7938 stateInfo_display (s->aliasinfo, message ("Storage %q", sRef_unparseOpt (s)));
7939 }
7940 }
7941 }
7942}
7943
7944void
7945sRef_mergeNullState (sRef s, nstate n)
7946{
7947 if (sRef_isReasonable (s))
7948 {
7949 nstate old;
7950
7951 old = sRef_getNullState (s);
7952
7953 if (n != old && n != NS_UNKNOWN)
7954 {
7955 sRef_setNullState (s, n, g_currentloc);
7956 }
7957 }
7958 else
7959 {
7960 llbuglit ("sRef_mergeNullState: invalid");
7961 }
7962}
7963
7964bool
7965sRef_possiblyNull (sRef s)
7966{
7967 if (sRef_isReasonable (s))
7968 {
7969 if (sRef_getNullState (s) == NS_ABSNULL)
7970 {
7971 ctype rct = ctype_realType (s->type);
7972
7973 if (ctype_isAbstract (rct))
7974 {
7975 return FALSE;
7976 }
7977 else
7978 {
7979 if (ctype_isUser (rct))
7980 {
7981 uentry ue = usymtab_getTypeEntry (ctype_typeId (rct));
7982
7983 return (nstate_possiblyNull
7984 (sRef_getNullState (uentry_getSref (ue))));
7985 }
7986 else
7987 {
7988 return FALSE;
7989 }
7990 }
7991 }
7992 else
7993 {
7994 return nstate_possiblyNull (sRef_getNullState (s));
7995 }
7996 }
7997
7998 return FALSE;
7999}
8000
8001cstring
8002sRef_getScopeName (sRef s)
8003{
8004 sRef base = sRef_getRootBase (s);
8005
8006 if (sRef_isRealGlobal (base))
8007 {
8008 return (cstring_makeLiteralTemp ("Global"));
8009 }
8010 else if (sRef_isFileStatic (base))
8011 {
8012 return (cstring_makeLiteralTemp ("Static"));
8013 }
8014 else
8015 {
8016 return (cstring_makeLiteralTemp ("Local"));
8017 }
8018}
8019
8020cstring
8021sRef_unparseScope (sRef s)
8022{
8023 sRef base = sRef_getRootBase (s);
8024
8025 if (sRef_isRealGlobal (base))
8026 {
8027 return (cstring_makeLiteralTemp ("global"));
8028 }
8029 else if (sRef_isFileStatic (base))
8030 {
8031 return (cstring_makeLiteralTemp ("file static"));
8032 }
8033 else
8034 {
8035 BADEXIT;
8036 }
8037}
8038
8039int
8040sRef_getScope (sRef s)
8041{
8042 llassert (sRef_isReasonable (s));
8043
8044 if (sRef_isCvar (s))
8045 {
8046 return s->info->cvar->lexlevel;
8047 }
8048 else if (sRef_isParam (s))
8049 {
8050 return paramsScope;
8051 }
8052 else
8053 {
8054 return fileScope;
8055 }
8056}
8057
8058bool
8059sRef_isDead (sRef s)
8060{
8061 return (sRef_isReasonable (s) && (s)->defstate == SS_DEAD);
8062}
8063
8064bool
8065sRef_isDeadStorage (sRef s)
8066{
8067 if (sRef_isReasonable (s))
8068 {
8069 if (s->defstate == SS_DEAD
8070 || s->defstate == SS_UNUSEABLE
8071 || s->defstate == SS_UNDEFINED
8072 || s->defstate == SS_UNKNOWN)
8073 {
8074 return TRUE;
8075 }
8076 else
8077 {
8078 return (sRef_isDefinitelyNull (s));
8079 }
8080 }
8081 else
8082 {
8083 return FALSE;
8084 }
8085}
8086
8087bool
8088sRef_isPossiblyDead (sRef s)
8089{
8090 return (sRef_isReasonable (s) && s->defstate == SS_HOFFA);
8091}
8092
8093bool sRef_isStateLive (sRef s)
8094{
8095 if (sRef_isReasonable (s))
8096 {
8097 sstate ds = s->defstate;
8098
8099 return (!(ds == SS_UNDEFINED
8100 || ds == SS_DEAD
8101 || ds == SS_UNUSEABLE
8102 || ds == SS_HOFFA));
8103 }
8104 else
8105 {
8106 return FALSE;
8107 }
8108}
8109
8110
8111bool sRef_isStateUndefined (sRef s)
8112{
8113 return ((sRef_isReasonable(s)) && ((s)->defstate == SS_UNDEFINED));
8114}
8115
8116bool sRef_isJustAllocated (sRef s)
8117{
8118 if (sRef_isAllocated (s))
8119 {
8120 sRefSet_allElements (s->deriv, el)
8121 {
8122 if (!(sRef_isStateUndefined (el) || sRef_isUnuseable (el)))
8123 {
8124 return FALSE;
8125 }
8126 } end_sRefSet_allElements ;
8127
8128 return TRUE;
8129 }
8130
8131 return FALSE;
8132}
8133
8134static bool
8135sRef_isAllocatedStorage (sRef s)
8136{
8137 if (sRef_isReasonable (s) && ynm_toBoolStrict (sRef_isValidLvalue (s)))
8138 {
8139 return (ctype_isVisiblySharable (sRef_getType (s)));
8140 }
8141 else
8142 {
8143 return FALSE;
8144 }
8145}
8146
8147bool
8148sRef_isUnuseable (sRef s)
8149{
8150 return ((sRef_isValid(s)) && ((s)->defstate == SS_UNUSEABLE));
8151}
8152
8153bool
8154sRef_perhapsNull (sRef s)
8155{
8156 if (sRef_isReasonable (s))
8157 {
8158 if (sRef_getNullState (s) == NS_ABSNULL)
8159 {
8160 ctype rct = ctype_realType (s->type);
8161
8162 if (ctype_isAbstract (rct))
8163 {
8164 return FALSE;
8165 }
8166 else
8167 {
8168 if (ctype_isUser (rct))
8169 {
8170 uentry ue = usymtab_getTypeEntry (ctype_typeId (rct));
8171
8172 return (nstate_perhapsNull
8173 (sRef_getNullState (uentry_getSref (ue))));
8174 }
8175 else
8176 {
8177 return FALSE;
8178 }
8179 }
8180 }
8181 else
8182 {
8183 return nstate_perhapsNull (sRef_getNullState (s));
8184 }
8185 }
8186
8187 return FALSE;
8188}
8189
8190/*
8191** definitelyNull --- called when TRUE is good
8192*/
8193
8194bool
8195sRef_definitelyNull (sRef s)
8196{
8197 return (sRef_isReasonable (s)
8198 && (sRef_getNullState (s) == NS_DEFNULL || sRef_getNullState (s) == NS_CONSTNULL));
8199}
8200
8201/*
8202** based on sRef_similar
8203*/
8204
8205void
8206sRef_setDerivNullState (sRef set, sRef guide, nstate ns)
8207{
8208 if (sRef_isReasonable (set))
8209 {
8210 sRef deriv = sRef_getDeriv (set, guide);
8211
8212 if (sRef_isReasonable (deriv))
8213 {
8214 sRef_setNullStateN (deriv, ns);
8215 }
8216 }
8217}
8218
8219static /*@exposed@*/ sRef
8220sRef_getDeriv (/*@returned@*/ /*@notnull@*/ sRef set, sRef guide)
8221{
8222 llassert (sRef_isReasonable (set));
8223 llassert (sRef_isReasonable (guide));
8224
8225 switch (guide->kind)
8226 {
8227 case SK_CVAR:
8228 llassert (set->kind == SK_CVAR);
8229 return set;
8230
8231 case SK_PARAM:
8232 llassert (set->kind == guide->kind);
8233 llassert (set->info->paramno == guide->info->paramno);
8234 return set;
8235
8236 case SK_ARRAYFETCH:
8237
8238 if (set->kind == SK_ARRAYFETCH
8239 && (sRef_similar (set->info->arrayfetch->arr,
8240 guide->info->arrayfetch->arr)))
8241 {
8242 return set;
8243 }
8244 else
8245 {
8246 return (sRef_makeAnyArrayFetch
8247 (sRef_getDeriv (set, guide->info->arrayfetch->arr)));
8248 }
8249
8250 case SK_PTR:
8251
8252 if (set->kind == SK_PTR && sRef_similar (set->info->ref, guide->info->ref))
8253 {
8254 return set;
8255 }
8256 else
8257 {
8258 return (sRef_makePointer (sRef_getDeriv (set, guide->info->ref)));
8259 }
8260
8261 case SK_FIELD:
8262
8263 if ((set->kind == SK_FIELD &&
8264 (sRef_similar (set->info->field->rec, guide->info->field->rec) &&
8265 cstring_equal (set->info->field->field, guide->info->field->field))))
8266 {
8267 return set;
8268 }
8269 else
8270 {
8271 return (sRef_makeField (sRef_getDeriv (set, guide->info->field->rec),
8272 guide->info->field->field));
8273 }
8274 case SK_ADR:
8275
8276 if ((set->kind == SK_ADR) && sRef_similar (set->info->ref, guide->info->ref))
8277 {
8278 return set;
8279 }
8280 else
8281 {
8282 return (sRef_makeAddress (sRef_getDeriv (set, guide->info->ref)));
8283 }
8284
8285 case SK_CONJ:
8286
8287 return sRef_undefined;
8288
8289 case SK_RESULT:
8290 case SK_SPECIAL:
8291 case SK_UNCONSTRAINED:
8292 case SK_TYPE:
8293 case SK_CONST:
8294 case SK_NEW:
8295 case SK_UNKNOWN:
8296 case SK_OBJECT:
8297 case SK_DERIVED:
8298 case SK_EXTERNAL:
8299 return sRef_undefined;
8300 }
8301
8302 BADEXIT;
8303}
8304
8305/*
8306** sRef_aliasCheckPred
8307**
8308** A confusing but spiffy function:
8309**
8310** Calls predf (s, e, text, <alias>) on s and all of s's aliases
8311** (unless checkAliases (s) is FALSE).
8312**
8313** For alias calls, calls as
8314** predf (alias, e, text, s)
8315*/
8316
8317void
8318sRef_aliasCheckPred (bool (predf) (sRef, exprNode, sRef, exprNode),
8319 /*@null@*/ bool (checkAliases) (sRef),
8320 sRef s, exprNode e, exprNode err)
8321{
8322 bool error = (*predf)(s, e, sRef_undefined, err);
8323
8324
8325 if (checkAliases != NULL && !(checkAliases (s)))
8326 {
8327 /* don't check aliases */
8328 }
8329 else
8330 {
8331 sRefSet aliases = usymtab_allAliases (s);
8332
8333 sRefSet_realElements (aliases, current)
8334 {
8335 if (sRef_isReasonable (current))
8336 {
8337 if (sRef_isReasonable (current))
8338 {
8339 if (!sRef_similar (current, s)
8340 || (error && sRef_sameName (current, s)))
8341 {
8342 (void) (*predf)(current, e, s, err);
8343 }
8344 }
8345 else
8346 {
8347 llcontbug (message ("Invalid sRef as alias field of %s", sRef_unparse (s)));
8348 }
8349 }
8350 } end_sRefSet_realElements;
8351
8352 sRefSet_free (aliases);
8353 }
8354}
8355
8356/*
8357** return TRUE iff predf (s) is true for s or any alias of s
8358*/
8359
8360bool
8361sRef_aliasCheckSimplePred (sRefTest predf, sRef s)
8362{
8363
8364 if ((*predf)(s))
8365 {
8366 return TRUE;
8367 }
8368 else
8369 {
8370 sRefSet aliases;
8371
8372 aliases = usymtab_allAliases (s);
8373
8374 sRefSet_realElements (aliases, current)
8375 {
8376 if (sRef_isReasonable (current))
8377 {
8378 sRef cref = sRef_updateSref (current);
8379
8380 /* Whoa! a very kludgey way to make sure the right sref is used
8381 ** where there is a conditional symbol table. I am beginning
8382 ** to think that having a conditional symbol table wasn't such
8383 ** a great idea. ;(
8384 */
8385
8386 if ((*predf)(cref))
8387 {
8388 DPRINTF (("Checking alias: %s", sRef_unparseFull (cref)));
8389 sRefSet_free (aliases);
8390 return TRUE;
8391 }
8392 }
8393 } end_sRefSet_realElements;
8394
8395 sRefSet_free (aliases);
8396 }
8397 return FALSE;
8398}
8399
8400bool
8401sRef_aliasCompleteSimplePred (bool (predf) (sRef), sRef s)
8402{
8403 sRefSet aliases;
8404 bool result = FALSE;
8405
8406
8407 aliases = usymtab_allAliases (s);
8408
8409 if ((*predf)(s)) result = TRUE;
8410
8411
8412 sRefSet_realElements (aliases, current)
8413 {
8414 if (sRef_isReasonable (current))
8415 {
8416 current = sRef_updateSref (current);
8417 if ((*predf)(current)) result = TRUE;
8418 }
8419 } end_sRefSet_realElements;
8420
8421 sRefSet_free (aliases);
8422 return result;
8423}
8424
8425void
8426sRef_aliasSetComplete (void (predf) (sRef, fileloc), sRef s, fileloc loc)
8427{
8428 sRefSet aliases;
8429
8430 aliases = usymtab_allAliases (s);
8431
8432 DPRINTF (("All aliases: %s --> %s", sRef_unparseFull (s), sRefSet_unparseFull (aliases)));
8433
8434 (*predf)(s, loc);
8435
8436 sRefSet_realElements (aliases, current)
8437 {
8438 if (sRef_isReasonable (current))
8439 {
8440 DPRINTF (("Update: %s", sRef_unparseFull (current)));
8441 current = sRef_updateSref (current);
8442 DPRINTF (("Updated ==> %s", sRef_unparseFull (current)));
8443 ((*predf)(current, loc));
8444 DPRINTF (("Killed: %s", sRef_unparseFull (current)));
8445 }
8446 } end_sRefSet_realElements;
8447
8448 sRefSet_free (aliases);
8449}
8450
8451void
8452sRef_aliasSetCompleteParam (void (predf) (sRef, int, fileloc), sRef s,
8453 int kind, fileloc loc)
8454{
8455 sRefSet aliases;
8456
8457 if (sRef_isDeep (s))
8458 {
8459 aliases = usymtab_allAliases (s);
8460 }
8461 else
8462 {
8463 aliases = usymtab_aliasedBy (s);
8464 }
8465
8466 (*predf)(s, kind, loc);
8467
8468 sRefSet_realElements (aliases, current)
8469 {
8470 if (sRef_isReasonable (current))
8471 {
8472 current = sRef_updateSref (current);
8473 ((*predf)(current, kind, loc));
8474 }
8475 } end_sRefSet_realElements;
8476
8477 sRefSet_free (aliases);
8478}
8479
8480/*
8481** Version of aliasSetCompleteParam for alkind parameters
8482*/
8483
8484void
8485sRef_aliasSetCompleteAlkParam (void (predf) (sRef, alkind, fileloc), sRef s,
8486 alkind kind, fileloc loc)
8487{
8488 sRefSet aliases;
8489
8490 if (sRef_isDeep (s))
8491 {
8492 aliases = usymtab_allAliases (s);
8493 }
8494 else
8495 {
8496 aliases = usymtab_aliasedBy (s);
8497 }
8498
8499 (*predf)(s, kind, loc);
8500
8501 sRefSet_realElements (aliases, current)
8502 {
8503 if (sRef_isReasonable (current))
8504 {
8505 current = sRef_updateSref (current);
8506 ((*predf)(current, kind, loc));
8507 }
8508 } end_sRefSet_realElements;
8509
8510 sRefSet_free (aliases);
8511}
8512
8513static void
8514sRef_innerAliasSetComplete (void (predf) (sRef, fileloc), sRef s, fileloc loc)
8515{
8516 sRef inner;
8517 sRefSet aliases;
8518 ctype ct;
8519
8520 if (!sRef_isReasonable (s)) return;
8521
8522 /*
8523 ** Type equivalence checking is necessary --- there might be casting.
8524 */
8525
8526 (*predf)(s, loc);
8527
8528 switch (s->kind)
8529 {
8530 case SK_UNCONSTRAINED:
8531 case SK_CVAR:
8532 case SK_PARAM:
8533 break;
8534 case SK_PTR:
8535 inner = s->info->ref;
8536 aliases = usymtab_allAliases (inner);
8537 ct = sRef_getType (inner);
8538
8539 sRefSet_realElements (aliases, current)
8540 {
8541 if (sRef_isReasonable (current))
8542 {
8543 current = sRef_updateSref (current);
8544
8545 if (ctype_equal (ct, sRef_getType (current)))
8546 {
8547 sRef ptr = sRef_makePointer (current);
8548 ((*predf)(ptr, loc));
8549 }
8550 }
8551 } end_sRefSet_realElements;
8552
8553 sRefSet_free (aliases);
8554 break;
8555 case SK_ARRAYFETCH:
8556 inner = s->info->arrayfetch->arr;
8557 aliases = usymtab_allAliases (inner);
8558 ct = sRef_getType (inner);
8559
8560 DPRINTF (("Array fetch: %s", sRefSet_unparse (aliases)));
8561
8562 sRefSet_realElements (aliases, current)
8563 {
8564 if (sRef_isReasonable (current))
8565 {
8566 current = sRef_updateSref (current);
8567 DPRINTF (("Current: %s", sRef_unparseFull (current)));
8568
8569 if (ctype_equal (ct, sRef_getType (current)))
8570 {
8571 if (s->info->arrayfetch->indknown)
8572 {
8573 sRef af = sRef_makeArrayFetchKnown (current, s->info->arrayfetch->ind);
8574 DPRINTF (("Defining: %s", sRef_unparseFull (af)));
8575 /* evans 2001-08-27 This isn't true:
8576 llassert (af->info->arrayfetch->arr == current);
8577 see comments in buildArrayFetchKnown
8578 */
8579 ((*predf)(af, loc));
8580 }
8581 else
8582 {
8583 sRef af = sRef_makeArrayFetch (current);
8584 /* evans 2001-08-27 This isn't true:
8585 llassert (af->info->arrayfetch->arr == current);
8586 see comments in buildArrayFetch
8587 */
8588 DPRINTF (("Defining: %s", sRef_unparseFull (af)));
8589 ((*predf)(af, loc));
8590 }
8591 }
8592 else
8593 {
8594 DPRINTF (("Type mismatch: %s / %s",
8595 ctype_unparse (ct),
8596 ctype_unparse (sRef_getType (current))));
8597 }
8598 }
8599 } end_sRefSet_realElements;
8600
8601 sRefSet_free (aliases);
8602 break;
8603 case SK_FIELD:
8604 inner = s->info->field->rec;
8605 aliases = usymtab_allAliases (inner);
8606 ct = sRef_getType (inner);
8607
8608 sRefSet_realElements (aliases, current)
8609 {
8610 if (sRef_isReasonable (current))
8611 {
8612 current = sRef_updateSref (current);
8613
8614 if (ctype_equal (ct, sRef_getType (current)))
8615 {
8616 sRef f = sRef_makeField (current, s->info->field->field);
8617
8618 ((*predf)(f, loc));
8619 }
8620 }
8621 } end_sRefSet_realElements;
8622
8623 sRefSet_free (aliases);
8624 break;
8625 case SK_CONJ:
8626 sRef_innerAliasSetComplete (predf, s->info->conj->a, loc);
8627 sRef_innerAliasSetComplete (predf, s->info->conj->b, loc);
8628 break;
8629 case SK_SPECIAL:
8630 case SK_ADR:
8631 case SK_TYPE:
8632 case SK_CONST:
8633 case SK_NEW:
8634 case SK_UNKNOWN:
8635 case SK_OBJECT:
8636 case SK_DERIVED:
8637 case SK_EXTERNAL:
8638 case SK_RESULT:
8639 break;
8640 }
8641}
8642
8643static void
8644sRef_innerAliasSetCompleteParam (void (predf) (sRef, sRef), sRef s, sRef t)
8645{
8646 sRef inner;
8647 sRefSet aliases;
8648 ctype ct;
8649
8650 if (!sRef_isReasonable (s)) return;
8651
8652 /*
8653 ** Type equivalence checking is necessary --- there might be casting.
8654 */
8655
8656 (*predf)(s, t);
8657
8658 switch (s->kind)
8659 {
8660 case SK_UNCONSTRAINED:
8661 case SK_CVAR:
8662 case SK_PARAM:
8663 break;
8664 case SK_PTR:
8665 inner = s->info->ref;
8666 aliases = usymtab_allAliases (inner);
8667 ct = sRef_getType (inner);
8668
8669 sRefSet_realElements (aliases, current)
8670 {
8671 if (sRef_isReasonable (current))
8672 {
8673 current = sRef_updateSref (current);
8674
8675 if (ctype_equal (ct, sRef_getType (current)))
8676 {
8677 sRef ptr = sRef_makePointer (current);
8678
8679 ((*predf)(ptr, t));
8680 }
8681 }
8682 } end_sRefSet_realElements;
8683
8684 sRefSet_free (aliases);
8685 break;
8686 case SK_ARRAYFETCH:
8687 inner = s->info->arrayfetch->arr;
8688 aliases = usymtab_allAliases (inner);
8689 ct = sRef_getType (inner);
8690
8691 sRefSet_realElements (aliases, current)
8692 {
8693 if (sRef_isReasonable (current))
8694 {
8695 current = sRef_updateSref (current);
8696
8697 if (ctype_equal (ct, sRef_getType (current)))
8698 {
8699
8700 if (s->info->arrayfetch->indknown)
8701 {
8702 sRef af = sRef_makeArrayFetchKnown (current, s->info->arrayfetch->ind);
8703
8704 ((*predf)(af, t));
8705 }
8706 else
8707 {
8708 sRef af = sRef_makeArrayFetch (current);
8709
8710 ((*predf)(af, t));
8711 }
8712 }
8713 }
8714 } end_sRefSet_realElements;
8715
8716 sRefSet_free (aliases);
8717 break;
8718 case SK_FIELD:
8719 inner = s->info->field->rec;
8720 aliases = usymtab_allAliases (inner);
8721 ct = sRef_getType (inner);
8722
8723
8724 sRefSet_realElements (aliases, current)
8725 {
8726 if (sRef_isReasonable (current))
8727 {
8728 current = sRef_updateSref (current);
8729
8730 if (ctype_equal (ct, sRef_getType (current)))
8731 {
8732 sRef f = sRef_makeField (current, s->info->field->field);
8733
8734 ((*predf)(f, t));
8735 }
8736 }
8737 } end_sRefSet_realElements;
8738
8739 sRefSet_free (aliases);
8740 break;
8741 case SK_CONJ:
8742 sRef_innerAliasSetCompleteParam (predf, s->info->conj->a, t);
8743 sRef_innerAliasSetCompleteParam (predf, s->info->conj->b, t);
8744 break;
8745 case SK_SPECIAL:
8746 case SK_ADR:
8747 case SK_TYPE:
8748 case SK_CONST:
8749 case SK_NEW:
8750 case SK_UNKNOWN:
8751 case SK_OBJECT:
8752 case SK_DERIVED:
8753 case SK_EXTERNAL:
8754 case SK_RESULT:
8755 break;
8756 }
8757}
8758
8759static void sRef_combineExKinds (/*@notnull@*/ sRef res, /*@notnull@*/ sRef other)
8760{
8761 exkind a1 = sRef_getExKind (res);
8762 exkind a2 = sRef_getExKind (other);
8763
8764 if (a1 == a2 || a2 == XO_UNKNOWN)
8765 {
8766 ;
8767 }
8768 else if (a1 == XO_UNKNOWN)
8769 {
8770 res->expinfo = stateInfo_update (res->expinfo, other->expinfo);
8771 res->expkind = a2;
8772 }
8773 else
8774 {
8775 res->expkind = XO_OBSERVER;
8776 }
8777}
8778
8779/*
8780** Currently, this is a very ad hoc implementation, with lots of fixes to
8781** make real code work okay. I need to come up with some more general
8782** rules or principles here.
8783*/
8784
8785static void
8786 sRef_combineAliasKindsError (/*@notnull@*/ sRef res,
8787 /*@notnull@*/ sRef other,
8788 clause cl, fileloc loc)
8789{
8790 bool hasError = FALSE;
8791 alkind ares = sRef_getAliasKind (res);
8792 alkind aother = sRef_getAliasKind (other);
8793
8794 sRef_checkMutable (res);
8795
8796 if (alkind_isDependent (ares))
8797 {
8798 if (aother == AK_KEPT)
8799 {
8800 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8801 res->aliaskind = AK_KEPT;
8802 }
8803 else
8804 {
8805 if (aother == AK_LOCAL || aother == AK_STATIC
8806 || alkind_isTemp (aother))
8807 {
8808 DPRINTF (("Setting dependent: %s", sRef_unparseFull (res)));
8809 res->aliaskind = AK_DEPENDENT;
8810 }
8811 }
8812 }
8813 else if (alkind_isDependent (aother))
8814 {
8815 if (ares == AK_KEPT)
8816 {
8817 res->aliaskind = AK_KEPT;
8818 }
8819 else
8820 {
8821 if (ares == AK_LOCAL || ares == AK_STATIC || alkind_isTemp (ares))
8822 {
8823 DPRINTF (("Setting dependent: %s", sRef_unparseFull (res)));
8824 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8825 res->aliaskind = AK_DEPENDENT;
8826 }
8827 }
8828 }
8829 else if ((ares == AK_LOCAL || ares == AK_UNIQUE
8830 || ares == AK_STATIC || alkind_isTemp (ares))
8831 && sRef_isFresh (other))
8832 {
8833 /*
8834 ** cases like: if (s == NULL) s = malloc...;
8835 ** don't generate errors
8836 */
8837
8838 if (usymtab_isAltDefinitelyNullDeep (res))
8839 {
8840 res->aliaskind = ares;
8841 }
8842 else
8843 {
8844 hasError = TRUE;
8845 }
8846 }
8847 else if ((aother == AK_LOCAL || aother == AK_UNIQUE
8848 || aother == AK_STATIC || alkind_isTemp (aother))
8849 && sRef_isFresh (res))
8850 {
8851 /*
8852 ** cases like: if (s == NULL) s = malloc...;
8853 ** don't generate errors
8854 */
8855
8856 if (usymtab_isDefinitelyNullDeep (other))
8857 {
8858 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8859 res->aliaskind = aother;
8860 }
8861 else
8862 {
8863 hasError = TRUE;
8864 }
8865 }
8866 else if (ares == AK_NEWREF && aother == AK_REFCOUNTED
8867 && sRef_isConst (other))
8868 {
8869 res->aliaskind = AK_NEWREF;
8870 }
8871 else if (aother == AK_NEWREF && ares == AK_REFCOUNTED
8872 && sRef_isConst (res))
8873 {
8874 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8875 res->aliaskind = AK_NEWREF;
8876 }
8877 else if (sRef_isLocalVar (res)
8878 && ((ares == AK_KEPT && aother == AK_LOCAL)
8879 || (aother == AK_KEPT && ares == AK_LOCAL)))
8880 {
8881 res->aliaskind = AK_KEPT;
8882 }
8883 else if ((ares == AK_OWNED && aother == AK_ONLY)
8884 || (aother == AK_OWNED && ares == AK_ONLY))
8885 {
8886 res->aliaskind = AK_OWNED;
8887
8888 if (aother == AK_OWNED)
8889 {
8890 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8891 }
8892 }
8893 else
8894 {
8895 hasError = TRUE;
8896 }
8897
8898 if (hasError)
8899 {
8900 if (sRef_isThroughArrayFetch (res))
8901 {
8902 if (optgenerror2
8903 (FLG_BRANCHSTATE, FLG_STRICTBRANCHSTATE,
8904 message
8905 ("Clauses exit with %q possibly referencing %s storage %s, "
8906 "%s storage %s",
8907 sRef_unparse (res),
8908 alkind_unparse (aother),
8909 clause_nameTaken (cl),
8910 alkind_unparse (ares),
8911 clause_nameAlternate (cl)),
8912 loc))
8913 {
8914 sRef_showAliasInfo (res);
8915 sRef_showAliasInfo (other);
8916 res->aliaskind = AK_ERROR;
8917 }
8918 else
8919 {
8920 if (ares == AK_KEPT || aother == AK_KEPT)
8921 {
8922 sRef_maybeKill (res, loc);
8923 }
8924 }
8925 }
8926 else
8927 {
8928 if (optgenerror
8929 (FLG_BRANCHSTATE,
8930 message ("Clauses exit with %q referencing %s storage %s, "
8931 "%s storage %s",
8932 sRef_unparse (res),
8933 alkind_unparse (aother),
8934 clause_nameTaken (cl),
8935 alkind_unparse (ares),
8936 clause_nameAlternate (cl)),
8937 loc))
8938 {
8939 sRef_showAliasInfo (res);
8940 sRef_showAliasInfo (other);
8941
8942 res->aliaskind = AK_ERROR;
8943 }
8944 }
8945
8946 res->aliaskind = (sRef_isLocalVar (res) ? AK_LOCAL : AK_UNKNOWN);
8947 }
8948}
8949
8950static void
8951 sRef_combineAliasKinds (/*@notnull@*/ sRef res, /*@notnull@*/ sRef other,
8952 clause cl, fileloc loc)
8953{
8954 alkind ares = sRef_getAliasKind (res);
8955 alkind aother = sRef_getAliasKind (other);
8956
8957 sRef_checkMutable (res);
8958
8959 DPRINTF (("Combine alias kinds: \n\t%s / \n\t%s",
8960 sRef_unparseFull (res), sRef_unparseFull (other)));
8961 if (alkind_equal (ares, aother)
8962 || aother == AK_UNKNOWN
8963 || aother == AK_ERROR)
8964 {
8965 ; /* keep current state */
8966 }
8967 else if (sRef_isDead (res) || sRef_isDead (other))
8968 {
8969 /* dead error reported (or storage is dead) */
8970 res ->aliaskind = AK_ERROR;
8971 }
8972 else if (ares == AK_UNKNOWN || ares == AK_ERROR
8973 || sRef_isStateUndefined (res)
8974 || sRef_isDefinitelyNull (res))
8975 {
8976 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8977 res->aliaskind = aother;
8978 }
8979 else if (sRef_isStateUndefined (other)
8980 || sRef_isDefinitelyNull (other))
8981 {
8982 ;
8983 }
8984 else if (((ares == AK_UNIQUE || alkind_isTemp (ares))
8985 && aother == AK_LOCAL)
8986 || ((aother == AK_UNIQUE || alkind_isTemp (aother))
8987 && ares == AK_LOCAL))
8988 {
8989 if (ares != AK_LOCAL)
8990 {
8991 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8992 }
8993
8994 res->aliaskind = AK_LOCAL;
8995 }
8996 else if ((ares == AK_OWNED && aother == AK_FRESH)
8997 || (aother == AK_OWNED && ares == AK_FRESH))
8998 {
8999 if (ares != AK_FRESH)
9000 {
9001 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
9002 }
9003
9004 res->aliaskind = AK_FRESH;
9005 }
9006 else if ((ares == AK_KEEP && aother == AK_FRESH) ||
9007 (aother == AK_KEEP && ares == AK_FRESH))
9008 {
9009 if (ares != AK_KEEP)
9010 {
9011 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
9012 }
9013
9014 res->aliaskind = AK_KEEP;
9015 }
9016 else if ((ares == AK_LOCAL && aother == AK_STACK) ||
9017 (aother == AK_LOCAL && ares == AK_STACK))
9018 {
9019 if (ares != AK_STACK)
9020 {
9021 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
9022 }
9023
9024 res->aliaskind = AK_STACK;
9025 }
9026 else if ((ares == AK_LOCAL
9027 && (aother == AK_OWNED && sRef_isLocalVar (other)))
9028 || (aother == AK_LOCAL
9029 && (ares == AK_OWNED && sRef_isLocalVar (res))))
9030 {
9031 if (ares != AK_LOCAL)
9032 {
9033 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
9034 }
9035
9036 res->aliaskind = AK_LOCAL;
9037 }
9038 else if ((ares == AK_FRESH && alkind_isOnly (aother))
9039 || (aother == AK_FRESH && alkind_isOnly (ares)))
9040 {
9041 res->aliaskind = AK_FRESH;
9042 }
9043 else if ((aother == AK_FRESH && sRef_definitelyNull (res))
9044 || (ares == AK_FRESH && sRef_definitelyNull (other)))
9045 {
9046 if (ares != AK_FRESH)
9047 {
9048 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
9049 res->aliaskind = AK_FRESH;
9050 }
9051 }
9052 else if ((sRef_isFresh (res) && sRef_isConst (other))
9053 || (sRef_isFresh (other) && sRef_isConst (res)))
9054 {
9055 /*
9056 ** for NULL constantants
9057 ** this is bogus!
9058 */
9059
9060 if (!sRef_isFresh (res))
9061 {
9062 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
9063 }
9064
9065 res->aliaskind = AK_FRESH;
9066 }
9067 else if ((alkind_isStatic (aother) && sRef_isConst (res))
9068 || (alkind_isStatic (ares) && sRef_isConst (other)))
9069 {
9070 if (!alkind_isStatic (ares))
9071 {
9072 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
9073 res->aliaskind = AK_STATIC;
9074 }
9075 }
9076 else
9077 {
9078 sRef_combineAliasKindsError (res, other, cl, loc);
9079 }
9080}
9081
9082static void sRef_combineDefState (/*@notnull@*/ sRef res,
9083 /*@notnull@*/ sRef other)
9084{
9085 sstate s1 = res->defstate;
9086 sstate s2 = other->defstate;
9087 bool flip = FALSE;
9088
9089 sRef_checkMutable (res);
9090
9091 if (s1 == s2 || s2 == SS_UNKNOWN)
9092 {
9093 ;
9094 }
9095 else if (s1 == SS_UNKNOWN)
9096 {
9097 flip = TRUE;
9098 }
9099 else
9100 {
9101 switch (s1)
9102 {
9103 case SS_FIXED:
9104 if (s2 == SS_DEFINED)
9105 {
9106 break;
9107 }
9108 else
9109 {
9110 llcontbuglit ("ssfixed: not implemented");
9111 flip = TRUE;
9112 }
9113 break;
9114 case SS_DEFINED:
9115 flip = TRUE;
9116 break;
9117 case SS_PDEFINED:
9118 case SS_ALLOCATED:
9119 flip = (s2 != SS_DEFINED);
9120 break;
9121 case SS_HOFFA:
9122 case SS_RELDEF:
9123 case SS_UNUSEABLE:
9124 case SS_UNDEFINED:
9125 case SS_PARTIAL:
9126 case SS_UNDEFGLOB:
9127 case SS_KILLED:
9128 case SS_DEAD:
9129 case SS_SPECIAL:
9130 break;
9131 BADDEFAULT;
9132 }
9133 }
9134
9135 if (flip)
9136 {
9137 res->definfo = stateInfo_update (res->definfo, other->definfo);
9138 res->defstate = s2;
9139 }
9140}
9141
9142extern /*@notnull@*/ sRef sRef_getConjA (sRef s)
9143{
9144 sRef ret;
9145 llassert (sRef_isConj (s));
9146
9147 ret = s->info->conj->a;
9148 llassert (ret != NULL);
9149 return ret;
9150}
9151
9152extern /*@notnull@*/ sRef sRef_getConjB (sRef s)
9153{
9154 sRef ret;
9155 llassert (sRef_isConj (s));
9156
9157 ret = s->info->conj->b;
9158 llassert (ret != NULL);
9159 return ret;
9160}
9161
9162extern /*@exposed@*/ sRef sRef_makeArrow (sRef s, /*@dependent@*/ cstring f)
9163{
9164 sRef p;
9165 sRef ret;
9166
9167 p = sRef_makePointer (s);
9168 ret = sRef_makeField (p, f);
9169 DPRINTF (("Arrow: %s => %s",
9170 sRef_unparseFull (s), sRef_unparseFull (ret)));
9171 return ret;
9172}
9173
9174extern /*@exposed@*/ sRef sRef_buildArrow (sRef s, cstring f)
9175{
9176 sRef p;
9177 sRef ret;
9178
9179 p = sRef_buildPointer (s);
9180 ret = sRef_buildField (p, f);
9181
9182 return ret;
9183}
9184
9185static /*@null@*/ sinfo sinfo_copy (/*@notnull@*/ sRef s)
9186{
9187 sinfo ret;
9188
9189 switch (s->kind)
9190 {
9191 case SK_CVAR:
9192 ret = (sinfo) dmalloc (sizeof (*ret));
9193 ret->cvar = (cref) dmalloc (sizeof (*ret->cvar));
9194 ret->cvar->lexlevel = s->info->cvar->lexlevel;
9195 ret->cvar->index = s->info->cvar->index;
9196 break;
9197
9198 case SK_PARAM:
9199 ret = (sinfo) dmalloc (sizeof (*ret));
9200 ret->paramno = s->info->paramno;
9201 llassert (ret->paramno >= -1);
9202 break;
9203
9204 case SK_ARRAYFETCH:
9205 ret = (sinfo) dmalloc (sizeof (*ret));
9206 ret->arrayfetch = (ainfo) dmalloc (sizeof (*ret->arrayfetch));
9207 ret->arrayfetch->indknown = s->info->arrayfetch->indknown;
9208 ret->arrayfetch->ind = s->info->arrayfetch->ind;
9209 ret->arrayfetch->arr = s->info->arrayfetch->arr;
9210 break;
9211
9212 case SK_FIELD:
9213 ret = (sinfo) dmalloc (sizeof (*ret));
9214 ret->field = (fldinfo) dmalloc (sizeof (*ret->field));
9215 ret->field->rec = s->info->field->rec;
9216 ret->field->field = s->info->field->field;
9217 break;
9218
9219 case SK_OBJECT:
9220 ret = (sinfo) dmalloc (sizeof (*ret));
9221 ret->object = s->info->object;
9222 break;
9223
9224 case SK_PTR:
9225 case SK_ADR:
9226 case SK_DERIVED:
9227 case SK_EXTERNAL:
9228 ret = (sinfo) dmalloc (sizeof (*ret));
9229 ret->ref = s->info->ref; /* Ref_copy (s->info->ref); */
9230 break;
9231
9232 case SK_CONJ:
9233 ret = (sinfo) dmalloc (sizeof (*ret));
9234 ret->conj = (cjinfo) dmalloc (sizeof (*ret->conj));
9235 ret->conj->a = s->info->conj->a; /* sRef_copy (s->info->conj->a); */
9236 ret->conj->b = s->info->conj->b; /* sRef_copy (s->info->conj->b);*/
9237 break;
9238 case SK_SPECIAL:
9239 ret = (sinfo) dmalloc (sizeof (*ret));
9240 ret->spec = s->info->spec;
9241 break;
9242
9243 case SK_UNCONSTRAINED:
9244 case SK_NEW:
9245 ret = (sinfo) dmalloc (sizeof (*ret));
9246 ret->fname = s->info->fname;
9247 break;
9248
9249 case SK_RESULT:
9250 case SK_CONST:
9251 case SK_TYPE:
9252 case SK_UNKNOWN:
9253 llassertprint (s->info == NULL, ("s = %s", sRef_unparse (s)));
9254 ret = NULL;
9255 break;
9256 }
9257
9258 return ret;
9259}
9260
9261static /*@null@*/ sinfo sinfo_fullCopy (/*@notnull@*/ sRef s)
9262{
9263 sinfo ret;
9264
9265 /*
9266 ** Since its a full copy, only storage is assigned
9267 ** to dependent fields.
9268 */
9269 /*@-onlytrans@*/
9270
9271 switch (s->kind)
9272 {
9273 case SK_CVAR:
9274 ret = (sinfo) dmalloc (sizeof (*ret));
9275 ret->cvar = (cref) dmalloc (sizeof (*ret->cvar));
9276 ret->cvar->lexlevel = s->info->cvar->lexlevel;
9277 ret->cvar->index = s->info->cvar->index;
9278 break;
9279
9280 case SK_PARAM:
9281 ret = (sinfo) dmalloc (sizeof (*ret));
9282 ret->paramno = s->info->paramno;
9283 llassert (ret->paramno >= -1);
9284 break;
9285
9286 case SK_ARRAYFETCH:
9287 ret = (sinfo) dmalloc (sizeof (*ret));
9288 ret->arrayfetch = (ainfo) dmalloc (sizeof (*ret->arrayfetch));
9289 ret->arrayfetch->indknown = s->info->arrayfetch->indknown;
9290 ret->arrayfetch->ind = s->info->arrayfetch->ind;
9291 ret->arrayfetch->arr = sRef_saveCopy (s->info->arrayfetch->arr);
9292 break;
9293
9294 case SK_FIELD:
9295 ret = (sinfo) dmalloc (sizeof (*ret));
9296 ret->field = (fldinfo) dmalloc (sizeof (*ret->field));
9297 ret->field->rec = sRef_saveCopy (s->info->field->rec);
9298 ret->field->field = s->info->field->field;
9299 break;
9300
9301 case SK_OBJECT:
9302 ret = (sinfo) dmalloc (sizeof (*ret));
9303 ret->object = s->info->object;
9304 break;
9305
9306 case SK_PTR:
9307 case SK_ADR:
9308 case SK_DERIVED:
9309 case SK_EXTERNAL:
9310 ret = (sinfo) dmalloc (sizeof (*ret));
9311 ret->ref = sRef_saveCopy (s->info->ref);
9312 break;
9313
9314 case SK_CONJ:
9315 ret = (sinfo) dmalloc (sizeof (*ret));
9316 ret->conj = (cjinfo) dmalloc (sizeof (*ret->conj));
9317 ret->conj->a = sRef_saveCopy (s->info->conj->a);
9318 ret->conj->b = sRef_saveCopy (s->info->conj->b);
9319 break;
9320 case SK_SPECIAL:
9321 ret = (sinfo) dmalloc (sizeof (*ret));
9322 ret->spec = s->info->spec;
9323 break;
9324 case SK_NEW:
9325 case SK_UNCONSTRAINED:
9326 ret = (sinfo) dmalloc (sizeof (*ret));
9327 ret->fname = s->info->fname;
9328 break;
9329 case SK_CONST:
9330 case SK_TYPE:
9331 case SK_RESULT:
9332 case SK_UNKNOWN:
9333 llassert (s->info == NULL);
9334 ret = NULL;
9335 break;
9336 }
9337 /*@=onlytrans@*/
9338 return ret;
9339}
9340
9341
9342static void
9343 sinfo_update (/*@notnull@*/ /*@exposed@*/ sRef res,
9344 /*@notnull@*/ /*@exposed@*/ sRef other)
9345{
9346 llassert (res->kind == other->kind);
9347
9348 switch (res->kind)
9349 {
9350 case SK_CVAR:
9351 res->info->cvar->lexlevel = other->info->cvar->lexlevel;
9352 res->info->cvar->index = other->info->cvar->index;
9353 break;
9354
9355 case SK_PARAM:
9356 res->info->paramno = other->info->paramno;
9357 llassert (res->info->paramno >= -1);
9358 break;
9359
9360 case SK_ARRAYFETCH:
9361 res->info->arrayfetch->indknown = other->info->arrayfetch->indknown;
9362 res->info->arrayfetch->ind = other->info->arrayfetch->ind;
9363 res->info->arrayfetch->arr = other->info->arrayfetch->arr;
9364 break;
9365
9366 case SK_FIELD:
9367 res->info->field->rec = other->info->field->rec;
9368 res->info->field->field = other->info->field->field;
9369 break;
9370
9371 case SK_OBJECT:
9372 res->info->object = other->info->object;
9373 break;
9374
9375 case SK_PTR:
9376 case SK_ADR:
9377 case SK_DERIVED:
9378 case SK_EXTERNAL:
9379 res->info->ref = other->info->ref;
9380 break;
9381
9382 case SK_CONJ:
9383 res->info->conj->a = other->info->conj->a;
9384 res->info->conj->b = other->info->conj->b;
9385 break;
9386
9387 case SK_SPECIAL:
9388 res->info->spec = other->info->spec;
9389 break;
9390
9391 case SK_NEW:
9392 case SK_UNCONSTRAINED:
9393 res->info->fname = other->info->fname;
9394 break;
9395
9396 case SK_CONST:
9397 case SK_TYPE:
9398 case SK_UNKNOWN:
9399 case SK_RESULT:
9400 llassert (res->info == NULL);
9401 break;
9402 }
9403}
9404
9405static void sinfo_free (/*@special@*/ /*@temp@*/ /*@notnull@*/ sRef s)
9406 /*@uses s->kind, s->info@*/
9407 /*@releases s->info@*/
9408{
9409 switch (s->kind)
9410 {
9411 case SK_CVAR:
9412 DPRINTF (("Free sinfo: [%p]", s->info->cvar));
9413 sfree (s->info->cvar);
9414 break;
9415
9416 case SK_PARAM:
9417 break;
9418
9419 case SK_ARRAYFETCH:
9420 DPRINTF (("Free sinfo: [%p]", s->info->arrayfetch));
9421 sfree (s->info->arrayfetch);
9422 break;
9423
9424 case SK_FIELD:
9425 DPRINTF (("Free sinfo: [%p]", s->info->field));
9426 sfree (s->info->field);
9427 break;
9428
9429 case SK_OBJECT:
9430 break;
9431
9432 case SK_PTR:
9433 case SK_ADR:
9434 case SK_DERIVED:
9435 case SK_EXTERNAL: /* is copy now! */
9436 break;
9437
9438 case SK_CONJ:
9439 DPRINTF (("Free sinfo: [%p]", s->info->conj));
9440 sfree (s->info->conj);
9441 break;
9442
9443 case SK_UNCONSTRAINED:
9444 case SK_SPECIAL:
9445 case SK_CONST:
9446 case SK_NEW:
9447 case SK_TYPE:
9448 case SK_UNKNOWN:
9449 case SK_RESULT:
9450 break;
9451 }
9452
9453 if (s->info != NULL) {
9454 DPRINTF (("Free sinfo: [%p]", s->info));
9455 }
9456
9457 sfree (s->info);
9458}
9459
9460bool sRef_isNSLocalVar (sRef s)
9461{
9462 if (sRef_isLocalVar (s))
9463 {
9464 uentry ue = sRef_getUentry (s);
9465
9466 return (!uentry_isStatic (ue));
9467 }
9468 else
9469 {
9470 return FALSE;
9471 }
9472}
9473
9474bool sRef_isLocalVar (sRef s)
9475{
9476 if (sRef_isValid(s))
9477 {
9478 return (s->kind == SK_CVAR
9479 && (s->info->cvar->lexlevel > fileScope));
9480 }
9481
9482 return FALSE;
9483}
9484
9485bool sRef_isRealLocalVar (sRef s)
9486{
9487 if (sRef_isValid(s))
9488 {
9489 if (s->kind == SK_CVAR)
9490 {
9491 if (s->info->cvar->lexlevel == functionScope)
9492 {
9493 uentry ue = sRef_getUentry (s);
9494
9495 if (uentry_isAnyParam (ue)
9496 || uentry_isRefParam (ue))
9497 {
9498 return FALSE;
9499 }
9500 else
9501 {
9502 return TRUE;
9503 }
9504 }
9505 else
9506 {
9507 return (s->info->cvar->lexlevel > functionScope);
9508 }
9509 }
9510 }
9511
9512 return FALSE;
9513}
9514
9515bool sRef_isLocalParamVar (sRef s)
9516{
9517 if (sRef_isValid(s))
9518 {
9519 return (s->kind == SK_PARAM
9520 || (s->kind == SK_CVAR
9521 && (s->info->cvar->lexlevel > fileScope)));
9522 }
9523
9524 return FALSE;
9525}
9526
9527static speckind speckind_fromInt (int i)
9528{
9529 /*@+enumint@*/
9530 llassert (i >= SR_NOTHING && i <= SR_SYSTEM);
9531 /*@=enumint@*/
9532
9533 return ((speckind) i);
9534}
9535
9536
9537static void sRef_updateNullState (/*@notnull@*/ sRef res, /*@notnull@*/ sRef other)
9538 /*@modifies res@*/
9539{
9540 res->nullstate = other->nullstate;
9541 res->nullinfo = stateInfo_update (res->nullinfo, other->nullinfo);
9542 sRef_resetAliasKind (res);
9543}
9544
9545void sRef_combineNullState (/*@notnull@*/ sRef res, /*@notnull@*/ sRef other)
9546{
9547 nstate n1 = sRef_getNullState (res);
9548 nstate n2 = sRef_getNullState (other);
9549 bool flip = FALSE;
9550 nstate nn = n1;
9551
9552 if (n1 == n2 || n2 == NS_UNKNOWN)
9553 {
9554 ;
9555 }
9556 else
9557 {
9558 /* note: n2 is not unknown or defnull */
9559
9560 switch (n1)
9561 {
9562 case NS_ERROR: nn = NS_ERROR; break;
9563 case NS_UNKNOWN: flip = TRUE; nn = n2; break;
9564 case NS_POSNULL: break;
9565 case NS_DEFNULL: nn = NS_POSNULL; break;
9566 case NS_RELNULL: break;
9567 case NS_NOTNULL:
9568 if (n2 == NS_MNOTNULL)
9569 {
9570 ;
9571 }
9572 else
9573 {
9574 flip = TRUE;
9575 nn = NS_POSNULL;
9576 }
9577 break;
9578 case NS_MNOTNULL:
9579 if (n2 == NS_NOTNULL)
9580 {
9581 nn = NS_NOTNULL;
9582 }
9583 else
9584 {
9585 flip = TRUE;
9586 nn = NS_POSNULL;
9587 }
9588 break;
9589 case NS_CONSTNULL:
9590 case NS_ABSNULL:
9591 flip = TRUE;
9592 nn = n2;
9593 }
9594 }
9595
9596 if (flip)
9597 {
9598 res->nullinfo = stateInfo_update (res->nullinfo, other->nullinfo);
9599 }
9600
9601 res->nullstate = nn;
9602 sRef_resetAliasKind (res);
9603}
9604
9605cstring sRef_nullMessage (sRef s)
9606{
9607 llassert (sRef_isReasonable (s));
9608
9609 switch (sRef_getNullState (s))
9610 {
9611 case NS_DEFNULL:
9612 case NS_CONSTNULL:
9613 return (cstring_makeLiteralTemp ("null"));
9614 default:
9615 return (cstring_makeLiteralTemp ("possibly null"));
9616 }
9617 BADEXIT;
9618}
9619
9620/*@observer@*/ cstring sRef_ntMessage (sRef s)
9621{
9622 llassert (sRef_isReasonable (s));
9623
9624 switch (s->nullstate)
9625 {
9626 case NS_DEFNULL:
9627 case NS_CONSTNULL:
9628 return (cstring_makeLiteralTemp ("not nullterminated"));
9629 default:
9630 return (cstring_makeLiteralTemp ("possibly non-nullterminated"));
9631 }
9632 BADEXIT;
9633}
9634
9635
9636
9637sRef sRef_fixResultType (/*@returned@*/ sRef s, ctype typ, uentry ue)
9638{
9639 sRef tmp = sRef_undefined;
9640 sRef ret;
9641
9642 llassert (sRef_isReasonable (s));
9643
9644 switch (s->kind)
9645 {
9646 case SK_RESULT:
9647 s->type = typ;
9648 ret = s;
9649 break;
9650 case SK_ARRAYFETCH:
9651 {
9652 ctype ct;
9653 tmp = sRef_fixResultType (s->info->arrayfetch->arr, typ, ue);
9654
9655 ct = ctype_realType (sRef_getType (tmp));
9656
9657
9658 if (ctype_isKnown (ct))
9659 {
9660 if (ctype_isAP (ct))
9661 {
9662 ;
9663 }
9664 else
9665 {
9666 voptgenerror
9667 (FLG_TYPE,
9668 message
9669 ("Special clause indexes non-array (%t): *%q",
9670 ct, sRef_unparse (s->info->arrayfetch->arr)),
9671 uentry_whereLast (ue));
9672 }
9673 }
9674
9675 tmp = sRef_fixResultType (s->info->arrayfetch->arr, typ, ue);
9676
9677 if (s->info->arrayfetch->indknown)
9678 {
9679 ret = sRef_makeArrayFetchKnown (tmp, s->info->arrayfetch->ind);
9680 }
9681 else
9682 {
9683 ret = sRef_makeArrayFetch (tmp);
9684 }
9685 }
9686 break;
9687 case SK_FIELD:
9688 {
9689 sRef rec = sRef_fixResultType (s->info->field->rec, typ, ue);
9690 ctype ct = ctype_realType (sRef_getType (rec));
9691
9692 if (ctype_isKnown (ct))
9693 {
9694 if (ctype_isSU (ct))
9695 {
9696 if (uentry_isValid (uentryList_lookupField (ctype_getFields (ct),
9697 s->info->field->field)))
9698 {
9699 ;
9700 }
9701 else
9702 {
9703 voptgenerror
9704 (FLG_TYPE,
9705 message
9706 ("Special clause accesses non-existent field of result: %q.%s",
9707 sRef_unparse (rec), s->info->field->field),
9708 uentry_whereLast (ue));
9709 }
9710 }
9711 else
9712 {
9713 voptgenerror
9714 (FLG_TYPE,
9715 message
9716 ("Special clause accesses field of non-struct or union result (%t): %q.%s",
9717 ct, sRef_unparse (rec), s->info->field->field),
9718 uentry_whereLast (ue));
9719 }
9720 }
9721
9722 ret = sRef_makeField (tmp, s->info->field->field);
9723 break;
9724 }
9725 case SK_PTR:
9726 {
9727 ctype ct;
9728 tmp = sRef_fixResultType (s->info->ref, typ, ue);
9729
9730 ct = ctype_realType (sRef_getType (tmp));
9731
9732 if (ctype_isKnown (ct))
9733 {
9734 if (ctype_isAP (ct))
9735 {
9736 ;
9737 }
9738 else
9739 {
9740 voptgenerror
9741 (FLG_TYPE,
9742 message
9743 ("Special clause dereferences non-pointer (%t): *%q",
9744 ct, sRef_unparse (s->info->ref)),
9745 uentry_whereLast (ue));
9746 }
9747 }
9748
9749 ret = sRef_makePointer (tmp);
9750 break;
9751 }
9752 case SK_ADR:
9753 voptgenerror
9754 (FLG_TYPE,
9755 message
9756 ("Special clause uses & operator (not allowed): &%q", sRef_unparse (s->info->ref)),
9757 uentry_whereLast (ue));
9758 ret = s;
9759 break;
9760 BADDEFAULT;
9761 }
9762
9763 return ret;
9764}
9765
9766bool sRef_isOnly (sRef s)
9767{
9768 return (sRef_isValid(s) && alkind_isOnly (s->aliaskind));
9769}
9770
9771bool sRef_isDependent (sRef s)
9772{
9773 return (sRef_isValid(s) && alkind_isDependent (s->aliaskind));
9774}
9775
9776bool sRef_isOwned (sRef s)
9777{
9778 return (sRef_isReasonable (s) && (s->aliaskind == AK_OWNED));
9779}
9780
9781bool sRef_isKeep (sRef s)
9782{
9783 return (sRef_isReasonable (s) && (s->aliaskind == AK_KEEP));
9784}
9785
9786bool sRef_isTemp (sRef s)
9787{
9788 return (sRef_isReasonable (s) && alkind_isTemp (s->aliaskind));
9789}
9790
9791bool sRef_isLocalState (sRef s)
9792{
9793 return (sRef_isReasonable (s) && (s->aliaskind == AK_LOCAL));
9794}
9795
9796bool sRef_isUnique (sRef s)
9797{
9798 return (sRef_isReasonable (s) && (s->aliaskind == AK_UNIQUE));
9799}
9800
9801bool sRef_isShared (sRef s)
9802{
9803 return (sRef_isReasonable (s) && (s->aliaskind == AK_SHARED));
9804}
9805
9806bool sRef_isExposed (sRef s)
9807{
9808 return (sRef_isReasonable (s) && (s->expkind == XO_EXPOSED));
9809}
9810
9811bool sRef_isObserver (sRef s)
9812{
9813 return (sRef_isReasonable (s) && (s->expkind == XO_OBSERVER));
9814}
9815
9816bool sRef_isFresh (sRef s)
9817{
9818 return (sRef_isReasonable (s) && (s->aliaskind == AK_FRESH));
9819}
9820
9821bool sRef_isDefinitelyNull (sRef s)
9822{
9823 return (sRef_isReasonable (s) && (sRef_getNullState (s) == NS_DEFNULL
9824 || sRef_getNullState (s) == NS_CONSTNULL));
9825}
9826
9827bool sRef_isAllocated (sRef s)
9828{
9829 return (sRef_isReasonable (s) && (s->defstate == SS_ALLOCATED));
9830}
9831
9832bool sRef_isStack (sRef s)
9833{
9834 return (sRef_isReasonable (s) && (s->aliaskind == AK_STACK));
9835}
9836
9837bool sRef_isNotNull (sRef s)
9838{
9839 return (sRef_isValid(s) && (sRef_getNullState (s) == NS_MNOTNULL
9840 || sRef_getNullState (s) == NS_NOTNULL));
9841}
9842
9843alkind sRef_getAliasKind (sRef s)
9844{
9845 if (sRef_isValid(s)) {
9846 llassert (alkind_isValid (s->aliaskind));
9847 return s->aliaskind;
9848 }
9849
9850 return AK_ERROR;
9851}
9852
9853nstate sRef_getNullState (sRef s)
9854{
9855 if (sRef_isReasonable (s)) {
9856 llassert (nstate_isValid (s->nullstate));
9857 return s->nullstate;
9858 }
9859
9860 return NS_UNKNOWN;
9861}
9862
9863void sRef_reflectAnnotation (sRef s, annotationInfo a, fileloc loc)
9864{
9865 if (sRef_isReasonable (s))
9866 {
9867 if (!valueTable_isDefined (s->state))
9868 {
9869 s->state = valueTable_create (1);
9870 valueTable_insert
9871 (s->state,
9872 cstring_copy (metaStateInfo_getName (annotationInfo_getState (a))),
9873 stateValue_create (annotationInfo_getValue (a),
9874 stateInfo_makeLoc (loc, SA_DECLARED)));
9875 }
9876 else
9877 {
9878 DPRINTF (("reflect loc: %s", fileloc_unparse (loc)));
9879 valueTable_update
9880 (s->state,
9881 metaStateInfo_getName (annotationInfo_getState (a)),
9882 stateValue_create (annotationInfo_getValue (a),
9883 stateInfo_makeLoc (loc, SA_DECLARED)));
9884
9885 DPRINTF (("sref: %s", sRef_unparse (s)));
9886 DPRINTF (("sref: %s", sRef_unparseFull (s)));
9887 }
9888 }
9889}
9890
9891void sRef_setMetaStateValueComplete (sRef s, cstring key, int value, fileloc loc)
9892{
9893 sRefSet aliases = usymtab_allAliases (s);
9894
9895 sRef_setMetaStateValue (s, key, value, loc);
9896
9897 sRefSet_realElements (aliases, current)
9898 {
9899 if (sRef_isReasonable (current))
9900 {
9901 current = sRef_updateSref (current);
9902 sRef_setMetaStateValue (current, key, value, loc);
9903 }
9904 } end_sRefSet_realElements ;
9905
9906 sRefSet_free (aliases);
9907}
9908
9909void sRef_setMetaStateValue (sRef s, cstring key, int value, fileloc loc)
9910{
9911 sRef_checkMutable (s);
9912
9913 if (sRef_isReasonable (s))
9914 {
9915 if (!valueTable_isDefined (s->state))
9916 {
9917 DPRINTF (("inserting state: %s: %s %d", sRef_unparse (s), key, value));
9918 s->state = valueTable_create (1);
9919 valueTable_insert (s->state, cstring_copy (key),
9920 stateValue_create (value,
9921 stateInfo_makeLoc (loc, SA_CHANGED)));
9922 }
9923 else
9924 {
9925 DPRINTF (("Updating state: %s: %s %d / %s", sRef_unparse (s), key, value,
9926 fileloc_unparse (loc)));
9927 if (valueTable_contains (s->state, key))
9928 {
9929 valueTable_update
9930 (s->state, key, stateValue_create (value,
9931 stateInfo_makeLoc (loc, SA_CHANGED)));
9932 }
9933 else
9934 {
9935 valueTable_insert
9936 (s->state, cstring_copy (key),
9937 stateValue_create (value, stateInfo_makeLoc (loc, SA_CHANGED)));
9938 }
9939
9940 DPRINTF (("After: %s", sRef_unparseFull (s)));
9941 }
9942 }
9943}
9944
9945bool sRef_checkMetaStateValue (sRef s, cstring key, int value)
9946{
9947 if (sRef_isReasonable (s))
9948 {
9949 if (valueTable_isDefined (s->state))
9950 {
9951 stateValue val;
9952
9953 DPRINTF (("check state: %s: %s %d", sRef_unparse (s), key, value));
9954
9955 val = valueTable_lookup (s->state, key);
9956 llassert (stateValue_isDefined (val));
9957 return (stateValue_isError (val)
9958 || stateValue_getValue (val) == value);
9959 }
9960 else
9961 {
9962 return TRUE;
9963 }
9964 }
9965 else
9966 {
9967 return TRUE;
9968 }
9969}
9970
9971/*@observer@*/ stateValue sRef_getMetaStateValue (sRef s, cstring key)
9972{
9973 if (sRef_isReasonable (s))
9974 {
9975 if (valueTable_isDefined (s->state))
9976 {
9977 stateValue val;
9978
9979 val = valueTable_lookup (s->state, key);
9980 /* Okay if its not defined, just returns stateValue_undefined */
9981 return val;
9982 }
9983 else
9984 {
9985 return stateValue_undefined;
9986 }
9987 }
9988 else
9989 {
9990 return stateValue_undefined;
9991 }
9992}
9993
9994/*@observer@*/ valueTable sRef_getValueTable (sRef s)
9995{
9996 DPRINTF (("Get value table: %s", sRef_unparse (s)));
9997
9998 if (sRef_isReasonable (s))
9999 {
10000 llassert (sRef_isReasonable (s));
10001 DPRINTF (("Value table: %s", valueTable_unparse (s->state)));
10002 return s->state;
10003 }
10004 else
10005 {
10006 DPRINTF (("No value table!"));
10007 return valueTable_undefined;
10008 }
10009}
10010
10011bool sRef_makeStateSpecial (sRef s)
10012{
10013 /*
10014 ** Default defined state can be made special.
10015 */
10016
10017 llassert (sRef_isReasonable (s));
10018
10019 if (s->defstate == SS_UNKNOWN || s->defstate == SS_DEFINED || s->defstate == SS_SPECIAL)
10020 {
10021 /* s->aliaskind = AK_IMPTEMP; */ /* evans 2001-07-23 shouldn't effect alias state */
10022 s->defstate = SS_SPECIAL;
10023 DPRINTF (("Made special: %s", sRef_unparseFull (s)));
10024 return TRUE;
10025 }
10026 else
10027 {
10028 /* s->aliaskind = AK_IMPTEMP; */
10029 s->defstate = SS_SPECIAL;
10030 return FALSE;
10031 }
10032}
10033
10034void sRef_markImmutable (sRef s)
10035{
10036 if (sRef_isReasonable (s))
10037 {
10038 DPRINTF (("Mark immutable: %s", sRef_unparseFull (s)));
10039 s->immut = TRUE;
10040 }
10041}
10042
10043bool sRef_definitelyNullContext (sRef s)
10044{
10045 return (sRef_definitelyNull (s)
10046 || usymtab_isDefinitelyNullDeep (s));
10047}
10048
10049bool sRef_definitelyNullAltContext (sRef s)
10050{
10051 return (sRef_definitelyNull (s)
10052 || usymtab_isAltDefinitelyNullDeep (s));
10053}
10054
10055
10056/* start modifications */
10057struct s_bbufinfo sRef_getNullTerminatedState (sRef p_s) {
10058 struct s_bbufinfo BUFSTATE_UNKNOWN;
10059 BUFSTATE_UNKNOWN.bufstate = BB_NOTNULLTERMINATED;
10060 BUFSTATE_UNKNOWN.size = 0;
10061 BUFSTATE_UNKNOWN.len = 0;
10062
10063 if (sRef_isValid(p_s))
10064 return p_s->bufinfo;
10065 return BUFSTATE_UNKNOWN;
10066}
10067
10068void sRef_setNullTerminatedState(sRef p_s) {
10069 if(sRef_isReasonable (p_s)) {
10070 p_s->bufinfo.bufstate = BB_NULLTERMINATED;
10071 } else {
10072 llfatalbug( message("sRef_setNT passed a invalid sRef\n"));
10073 }
10074}
10075
10076
10077void sRef_setPossiblyNullTerminatedState(sRef p_s) {
10078 if( sRef_isReasonable (p_s)) {
10079 p_s->bufinfo.bufstate = BB_POSSIBLYNULLTERMINATED;
10080 } else {
10081 llfatalbug( message("sRef_setPossNT passed a invalid sRef\n"));
10082 }
10083}
10084
10085void sRef_setNotNullTerminatedState(sRef p_s) {
10086 if( sRef_isReasonable (p_s)) {
10087 p_s->bufinfo.bufstate = BB_NOTNULLTERMINATED;
10088 } else {
10089 llfatalbug( message("sRef_unsetNT passed a invalid sRef\n"));
10090 }
10091}
10092
10093void sRef_setLen(sRef p_s, int len) {
10094 if (sRef_isReasonable (p_s) && sRef_isNullTerminated(p_s))
10095 {
10096 p_s->bufinfo.len = len;
10097 }
10098 else
10099 {
10100 llfatalbug( message("sRef_setLen passed an invalid sRef\n"));
10101 }
10102}
10103
10104
10105void sRef_setSize(sRef p_s, int size) {
10106 if( sRef_isValid(p_s))
10107 {
10108 p_s->bufinfo.size = size;
10109 }
10110 else
10111 {
10112 llfatalbug( message("sRef_setSize passed a invalid sRef\n"));
10113 }
10114}
10115
10116void sRef_resetLen(sRef p_s) {
10117 if (sRef_isReasonable (p_s))
10118 {
10119 p_s->bufinfo.len = 0;
10120 }
10121 else
10122 {
10123 llfatalbug (message ("sRef_setLen passed an invalid sRef\n"));
10124 }
10125}
10126
10127/*drl7x 11/28/2000 */
10128
10129bool sRef_isFixedArray (sRef p_s) /*@*/ {
10130 ctype c;
10131 c = sRef_getType (p_s);
10132 return ( ctype_isFixedArray (c) );
10133}
10134
10135size_t sRef_getArraySize (sRef p_s) /*@*/
10136{
10137 ctype c;
10138 llassert (sRef_isFixedArray(p_s) );
10139 DPRINTF (( message ("sRef_getArraySize getting array size for %s", sRef_unparse(p_s) ) ));
10140
10141 c = sRef_getType (p_s);
10142 return (ctype_getArraySize (c));
10143}
10144
10145void sRef_setValue (sRef s, multiVal val)
10146{
10147 if (!sRef_isReasonable (s))
10148 {
10149 llcontbuglit ("Unreasonable sRef");
10150 llcontbug (message ("sRef: %s", sRef_unparse (s)));
10151 return;
10152 }
10153
10154 multiVal_free (s->val);
10155 s->val = val;
10156}
10157
10158bool sRef_hasValue (sRef s)
10159{
10160 return (sRef_isReasonable (s)
10161 && multiVal_isDefined (s->val));
10162}
10163
10164multiVal sRef_getValue (sRef s)
10165{
10166 if (sRef_isReasonable (s))
10167 {
10168 return s->val;
10169 }
10170
10171 return multiVal_undefined;
10172}
This page took 0.178691 seconds and 5 git commands to generate.