Various minor fixes for compiler/linter (other then splint itself) warnings.
[splint-patched.git] / src / sRef.c
blobc438e30fef9c3054880ae3339d3fbb5cdbb9568f
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.
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
25 ** storeRef.c
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.
33 ** storeRefs in the file and global scopes are free'd by the uentry.
37 # include "splintMacros.nf"
38 # include "basic.h"
39 # include "sRefTable.h"
40 # include "structNames.h"
43 ** Predicate functions that evaluate both arguments in order.
46 /*@notfunction@*/
47 # define OR(a,b) (a ? (b, TRUE) : b)
49 /*@notfunction@*/
50 # define AND(a,b) (a ? b : (b, FALSE))
52 static bool sRef_isDerived (sRef p_s) /*@*/ ;
54 static /*@exposed@*/ sRef sRef_fixDirectBase (sRef p_s, sRef p_base)
55 /*@modifies p_base@*/ ;
57 static void sRef_updateNullState (sRef p_res, sRef p_other) /*@modifies p_res@*/ ;
59 static bool sRef_isAllocatedStorage (sRef p_s) /*@*/ ;
60 static void sRef_setNullErrorLoc (sRef p_s, fileloc) /*@*/ ;
61 static void sRef_setNullStateN (sRef p_s, nstate p_n) /*@modifies p_s@*/ ;
63 static int sRef_depth (sRef p_s) /*@*/ ;
65 static void
66 sRef_innerAliasSetComplete (void (p_predf) (sRef, fileloc), sRef p_s,
67 fileloc p_loc)
68 /*@modifies p_s@*/ ;
70 static void
71 sRef_innerAliasSetCompleteParam (void (p_predf) (sRef, sRef), sRef p_s, sRef p_t)
72 /*@modifies p_s@*/ ;
74 static speckind speckind_fromInt (int p_i);
75 static bool sRef_equivalent (sRef p_s1, sRef p_s2);
76 static bool sRef_isDeepUnionField (sRef p_s);
77 static void sRef_addDeriv (/*@notnull@*/ sRef p_s, /*@notnull@*/ /*@exposed@*/ sRef p_t);
78 static bool sRef_checkModify (sRef p_s, sRefSet p_sl) /*@*/ ;
81 ** If s is definitely null, it has no memory state.
84 static void sRef_resetAliasKind (/*@notnull@*/ sRef s) /*@modifies s->aliaskind@*/
86 if (s->nullstate == NS_DEFNULL)
88 /* s->aliaskind = AK_ERROR; */
92 # ifdef DEBUGSPLINT
93 extern void sRef_checkCompletelyReasonable (sRef s) /*@*/
95 DPRINTF (("Check sRef: [%p] %s / %s", s, sRef_unparse (s),
96 sRefSet_unparse (sRef_derivedFields (s))));
98 if (sRef_isReasonable (s))
100 sRefSet_elements (s->deriv, el)
102 llassert (el != s);
103 sRef_checkCompletelyReasonable (el);
104 } end_sRefSet_elements ;
107 # endif
109 static /*@falsewhennull@*/ bool sRef_isReasonable (sRef s) /*@*/
111 if (sRef_isValid (s))
113 # ifdef DEBUGSPLINT
114 if (!bool_isReasonable (s->safe)
115 || !bool_isReasonable (s->modified)
116 || !bool_isReasonable (s->immut))
118 llcontbug (message ("Unreasonable sRef [%p]", s));
119 return FALSE;
122 if (!sstate_isValid (s->defstate))
124 llcontbug (message ("Unreasonable sRef [%p]", s));
125 return FALSE;
128 if (!nstate_isValid (s->nullstate))
130 llcontbug (message ("Unreasonable sRef [%p]", s));
131 return FALSE;
134 if (!alkind_isValid (s->aliaskind)
135 || !alkind_isValid (s->oaliaskind))
137 llcontbug (message ("Unreasonable sRef [%p]", s));
138 return FALSE;
141 if (!exkind_isValid (s->expkind)
142 || !exkind_isValid (s->oexpkind))
144 llcontbug (message ("Unreasonable sRef [%p]", s));
145 return FALSE;
147 # endif
149 return TRUE;
152 return FALSE;
155 static /*@nullwhentrue@*/ bool sRef_isUnreasonable (sRef s) /*@*/
157 return (!sRef_isReasonable (s));
160 static void sRef_checkMutable (/*@unused@*/ sRef s)
162 if (sRef_isReasonable (s) && s->immut)
164 llcontbug (message ("Modification to sRef marked immutable: %q",
165 sRef_unparseFull (s)));
169 static bool skind_isSimple (skind sk)
171 switch (sk)
173 case SK_PARAM: case SK_CVAR: case SK_CONST:
174 case SK_OBJECT: case SK_UNKNOWN: case SK_NEW:
175 return TRUE;
176 default:
177 return FALSE;
181 static void sinfo_free (/*@special@*/ /*@temp@*/ /*@notnull@*/ sRef p_s)
182 /*@uses p_s->kind, p_s->info@*/
183 /*@releases p_s->info@*/ ;
185 static /*@null@*/ sinfo sinfo_copy (/*@notnull@*/ sRef p_s) /*@*/ ;
186 static void sRef_setPartsFromUentry (sRef p_s, uentry p_ue)
187 /*@modifies p_s@*/ ;
188 static bool checkDeadState (/*@notnull@*/ sRef p_el, /*@null@*/ sRef p_e2,
189 bool p_tbranch, fileloc p_loc);
190 static /*@dependent@*/ sRef sRef_constructPointerAux (/*@notnull@*/ /*@exposed@*/ sRef p_t) /*@*/ ;
192 static void
193 sRef_combineExKinds (/*@notnull@*/ sRef p_res, /*@notnull@*/ sRef p_other)
194 /*@modifies p_res@*/ ;
196 static void
197 sRef_combineAliasKinds (/*@notnull@*/ sRef p_res, /*@notnull@*/ sRef p_other,
198 clause p_cl, fileloc p_loc)
199 /*@modifies p_res@*/ ;
201 static void
202 sRef_combineNullState (/*@notnull@*/ sRef p_res, /*@notnull@*/ sRef p_other)
203 /*@modifies p_res@*/ ;
205 static void
206 sRef_combineDefState (/*@notnull@*/ sRef p_res, /*@notnull@*/ sRef p_other)
207 /*@modifies p_res@*/ ;
209 static void sRef_setStateFromAbstractUentry (sRef p_s, uentry p_ue)
210 /*@modifies p_s@*/ ;
212 static void
213 sinfo_update (/*@notnull@*/ /*@exposed@*/ sRef p_res,
214 /*@notnull@*/ /*@exposed@*/ sRef p_other);
215 static void sRef_setDefinedAux (sRef p_s, fileloc p_loc, bool p_clear)
216 /*@modifies p_s@*/ ;
217 static void sRef_setDefinedNoClear (sRef p_s, fileloc p_loc)
218 /*@modifies p_s@*/ ;
219 static void sRef_setStateAux (sRef p_s, sstate p_ss, fileloc p_loc)
220 /*@modifies p_s@*/;
222 static /*@exposed@*/ sRef
223 sRef_buildNCField (/*@exposed@*/ sRef p_rec, /*@exposed@*/ cstring p_f);
225 static void
226 sRef_mergeStateAux (/*@notnull@*/ sRef p_res, /*@notnull@*/ sRef p_other,
227 clause p_cl, bool p_opt, fileloc p_loc,
228 bool p_doDerivs)
229 /*@modifies p_res, p_other@*/ ;
231 static /*@null@*/ sinfo sinfo_fullCopy (/*@notnull@*/ sRef p_s);
232 static bool sRef_doModify (sRef p_s, sRefSet p_sl) /*@modifies p_s@*/ ;
233 static bool sRef_doModifyVal (sRef p_s, sRefSet p_sl) /*@modifies p_s@*/;
234 static bool sRef_checkModifyVal (sRef p_s, sRefSet p_sl) /*@*/ ;
236 static /*@only@*/ sRefSet
237 sRef_mergeDerivs (/*@only@*/ sRefSet p_res, sRefSet p_other,
238 bool p_opt, clause p_cl, fileloc p_loc);
240 static /*@only@*/ sRefSet
241 sRef_mergeUnionDerivs (/*@only@*/ sRefSet p_res,
242 /*@exposed@*/ sRefSet p_other,
243 bool p_opt, clause p_cl, fileloc p_loc);
245 static /*@only@*/ sRefSet
246 sRef_mergePdefinedDerivs (/*@only@*/ sRefSet p_res, sRefSet p_other, bool p_opt,
247 clause p_cl, fileloc p_loc);
249 static /*@only@*/ cstring sRef_unparseWithArgs (sRef p_s, uentryList p_args);
250 static /*@only@*/ cstring sRef_unparseNoArgs (sRef p_s);
252 static /*@exposed@*/ sRef sRef_findDerivedPointer (sRef p_s);
253 static /*@exposed@*/ sRef sRef_findDerivedArrayFetch (/*@notnull@*/ sRef, bool, int, bool) ;
254 static /*@exposed@*/ sRef sRef_findDerivedField (/*@notnull@*/ sRef p_rec, cstring p_f);
255 static /*@exposed@*/ sRef
256 sRef_getDeriv (/*@notnull@*/ /*@returned@*/ sRef p_set, sRef p_guide);
258 static bool inFunction = FALSE;
259 static /*@only@*/ sRefTable allRefs;
261 /* # define DEBUGREFS */
263 # ifdef DEBUGREFS
264 static nsrefs = 0;
265 static totnsrefs = 0;
266 static maxnsrefs = 0;
267 static ntotrefers = 0;
268 static nrefers = 0;
269 # endif
271 static /*@checked@*/ bool protectDerivs = FALSE;
274 ** Result of sRef_alloc is dependent since allRefs may
275 ** reference it. It is only if !inFunction.
278 static /*@dependent@*/ /*@out@*/ /*@notnull@*/ sRef
279 sRef_alloc (void)
281 sRef s = (sRef) dmalloc (sizeof (*s));
283 s->immut = FALSE;
285 DPRINTF (("Alloc sref: [%p]", s));
287 if (inFunction)
289 allRefs = sRefTable_add (allRefs, s);
290 /*@-branchstate@*/
292 else
294 DPRINTF (("Not in function!"));
297 /*@=branchstate@*/
299 # ifdef DEBUGREFS
300 if (nsrefs >= maxnsrefs)
302 maxnsrefs = nsrefs;
305 totnsrefs++;
306 nsrefs++;
307 # endif
309 /*@-mustfree@*/ /*@-freshtrans@*/
310 return s;
311 /*@=mustfree@*/ /*@=freshtrans@*/
314 #ifdef DEADCODE
315 static void sRef_checkValidAux (sRef s, sRefSet checkedsofar)
317 llassert (FALSE);
319 if (!sRef_isReasonable (s)) return;
321 if (sRefSet_containsSameObject (checkedsofar, s))
323 return;
326 /*@-temptrans@*/
327 checkedsofar = sRefSet_insert (checkedsofar, s);
328 /*@=temptrans@*/ /* checksofar will be destroyed before checkValid returns */
330 switch (s->kind)
332 case SK_UNCONSTRAINED:
333 llassert (cstring_length (s->info->fname) < 100);
334 break;
336 case SK_CVAR:
337 llassert (s->info->cvar->lexlevel >= 0);
338 #if 0
339 llassert (s->info->cvar->lexlevel <= usymtab_getCurrentDepth ());
340 #endif
341 break;
343 case SK_PARAM:
344 llassert (s->info->paramno >= -1);
345 llassert (s->info->paramno <= 999); /* sanity check */
346 break;
348 case SK_ARRAYFETCH:
349 sRef_checkValidAux (s->info->arrayfetch->arr, checkedsofar);
350 break;
352 case SK_FIELD:
353 sRef_checkValidAux (s->info->field->rec, checkedsofar);
354 llassert (cstring_length (s->info->field->field) < 100);
355 break;
357 case SK_PTR:
358 sRef_checkValidAux (s->info->ref, checkedsofar);
359 break;
361 case SK_ADR:
362 sRef_checkValidAux (s->info->ref, checkedsofar);
363 break;
365 case SK_OBJECT:
366 /* check ctype s->info->object */
367 break;
369 case SK_CONJ:
370 sRef_checkValidAux (s->info->conj->a, checkedsofar);
371 sRef_checkValidAux (s->info->conj->b, checkedsofar);
372 break;
374 case SK_NEW:
375 llassert (cstring_length (s->info->fname) < 100);
376 break;
378 case SK_DERIVED:
379 sRef_checkValidAux (s->info->ref, checkedsofar);
380 break;
382 case SK_EXTERNAL:
383 sRef_checkValidAux (s->info->ref, checkedsofar);
384 break;
386 case SK_TYPE:
387 case SK_CONST:
388 case SK_RESULT:
389 /* check ctyp s->type */
390 break;
392 case SK_SPECIAL:
393 llassert (s->info->spec == SR_NOTHING
394 || s->info->spec == SR_INTERNAL
395 || s->info->spec == SR_SPECSTATE
396 || s->info->spec == SR_SYSTEM);
397 break;
399 case SK_UNKNOWN:
400 break;
402 BADDEFAULT;
406 sRefSet_elements (s->deriv, el)
408 sRef_checkValidAux (el, checkedsofar);
409 } end_sRefSet_elements ;
411 #endif
413 # if 0
414 static /*@maynotreturn@*/ void sRef_checkValid (/*@temp@*/ sRef s) /*@modifies stderr@*/
416 sRefSet checkedsofar = sRefSet_new ();
417 sRef_checkValidAux (s, checkedsofar);
419 # endif
421 static /*@dependent@*/ /*@notnull@*/ /*@special@*/ sRef
422 sRef_new (void)
423 /*@defines result@*/
424 /*@ensures isnull result->aliasinfo, result->definfo,
425 result->expinfo, result->info, result->deriv, result->state@*/
427 sRef s = sRef_alloc ();
429 s->kind = SK_UNKNOWN;
430 s->safe = TRUE;
431 s->modified = FALSE;
432 s->immut = FALSE;
433 s->val = multiVal_undefined;
435 s->type = ctype_unknown;
436 s->defstate = SS_UNKNOWN;
438 /* start modifications */
439 s->bufinfo.bufstate = BB_NOTNULLTERMINATED;
440 s->bufinfo.size = -1;
441 s->bufinfo.len = -1;
442 /* end modifications */
444 s->aliaskind = AK_UNKNOWN;
445 s->oaliaskind = AK_UNKNOWN;
447 s->nullstate = NS_UNKNOWN;
449 s->expkind = XO_UNKNOWN;
450 s->oexpkind = XO_UNKNOWN;
452 s->aliasinfo = stateInfo_undefined;
453 s->definfo = stateInfo_undefined;
454 s->nullinfo = stateInfo_undefined;
455 s->expinfo = stateInfo_undefined;
457 s->info = NULL;
458 s->deriv = sRefSet_undefined;
460 s->state = valueTable_undefined;
462 return s;
465 static /*@dependent@*/ /*@notnull@*/ /*@special@*/ sRef
466 sRef_newRef (void)
467 /*@defines result@*/
468 /*@ensures isnull result->aliasinfo, result->definfo,
469 result->expinfo, result->info, result->deriv@*/
471 sRef res = sRef_new ();
472 res->immut = FALSE;
473 res->state = valueTable_undefined;
474 return res;
478 void sRef_protectDerivs (void) /*@modifies protectDerivs@*/
480 llassert (!protectDerivs);
481 protectDerivs = TRUE;
484 void sRef_clearProtectDerivs (void) /*@modifies protectDerivs@*/
486 llassert (protectDerivs);
487 protectDerivs = FALSE;
491 ** hmmm...here be kind of a hack. This function mysteriously appeared
492 ** in my code, but I'm sure I didn't write it.
495 bool
496 sRef_isRecursiveField (sRef s)
498 if (sRef_isField (s))
500 if (sRef_depth (s) > 13)
502 sRef base;
503 cstring fieldname;
505 fieldname = sRef_getField (s);
506 base = sRef_getBase (s);
508 while (sRef_isReasonable (base))
510 if (sRef_isField (base))
512 if (cstring_equal (fieldname, sRef_getField (base)))
514 return TRUE;
518 base = sRef_getBaseSafe (base);
523 return FALSE;
526 static void
527 sRef_addDeriv (/*@notnull@*/ sRef s, /*@notnull@*/ /*@exposed@*/ sRef t)
529 if (!context_inProtectVars ()
530 && !protectDerivs
531 && sRef_isReasonable (s)
532 && sRef_isReasonable (t)
533 && !sRef_isConst (s))
535 int sd = sRef_depth (s);
536 int td = sRef_depth (t);
538 if (sd >= td)
540 return;
543 /* This sometimes fails: (evans 2001-07-12)
544 if (sRef_isArrayFetch (t))
546 DPRINTF (("Derived fetch: %s / %s / %s",
547 sRef_unparseFull (s), sRef_unparseFull (t),
548 sRef_unparseFull (t->info->arrayfetch->arr)));
549 llassert (t->info->arrayfetch->arr == s);
553 if (sRef_isFileOrGlobalScope (s))
555 if (context_inFunctionLike ()
556 && ctype_isKnown (sRef_getType (s))
557 && !ctype_isFunction (sRef_getType (s)))
559 globSet g = context_getUsedGlobs ();
561 if (!globSet_member (g, s))
564 ** don't report as a bug
567 llcontbug
568 (message ("sRef_addDeriv: global variable not in used "
569 "globs: %q / %s / %q",
570 sRef_unparse (s),
571 ctype_unparse (sRef_getType (s)),
572 sRefSet_unparse (s->deriv)));
575 else
577 DPRINTF (("Add deriv: [%p] %s / [%p] %s",
578 s, sRef_unparse (s),
579 t, sRef_unparse (t)));
581 s->deriv = sRefSet_insert (s->deriv, t);
585 else
587 DPRINTF (("Add deriv: [%p] %s / [%p] %s",
588 s, sRef_unparse (s),
589 t, sRef_unparse (t)));
591 s->deriv = sRefSet_insert (s->deriv, t);
596 bool
597 sRef_deepPred (bool (predf) (sRef), sRef s)
599 if (sRef_isReasonable (s))
601 if ((*predf)(s)) return TRUE;
603 switch (s->kind)
605 case SK_PTR:
606 return (sRef_deepPred (predf, s->info->ref));
607 case SK_ARRAYFETCH:
608 return (sRef_deepPred (predf, s->info->arrayfetch->arr));
609 case SK_FIELD:
610 return (sRef_deepPred (predf, s->info->field->rec));
611 case SK_CONJ:
612 return (sRef_deepPred (predf, s->info->conj->a)
613 || sRef_deepPred (predf, s->info->conj->b));
614 default:
615 return FALSE;
619 return FALSE;
622 bool sRef_modInFunction (void)
624 return inFunction;
627 void sRef_setStateFromType (sRef s, ctype ct)
629 if (sRef_isReasonable (s))
631 if (ctype_isUser (ct))
633 DPRINTF (("Here we are: %s", sRef_unparseFull (s)));
634 sRef_setStateFromUentry
635 (s, usymtab_getTypeEntry (ctype_typeId (ct)));
637 else if (ctype_isAbstract (ct))
639 DPRINTF (("Here we are: %s", sRef_unparseFull (s)));
640 sRef_setStateFromAbstractUentry
641 (s, usymtab_getTypeEntry (ctype_typeId (ct)));
643 else
645 ; /* not a user type */
650 static void sRef_setTypeState (sRef s)
652 if (sRef_isReasonable (s))
654 sRef_setStateFromType (s, s->type);
658 bool sRef_hasAliasInfoLoc (sRef s)
660 return (sRef_isReasonable (s) && (s->aliasinfo != NULL)
661 && (fileloc_isDefined (s->aliasinfo->loc)));
664 /*@falsewhennull@*/ bool sRef_hasStateInfoLoc (sRef s)
666 return (sRef_isReasonable (s) && (s->definfo != NULL)
667 && (fileloc_isDefined (s->definfo->loc)));
670 # ifdef DEADCODE
671 /*@falsewhennull@*/ bool sRef_hasExpInfoLoc (sRef s)
673 return (sRef_isReasonable (s)
674 && (s->expinfo != NULL) && (fileloc_isDefined (s->expinfo->loc)));
676 # endif /* DEADCODE */
678 # if 0
679 static /*@observer@*/ /*@unused@*/ stateInfo sRef_getInfo (sRef s, cstring key)
681 stateValue sv;
683 if (!sRef_isReasonable (s)) {
684 return stateInfo_undefined;
687 sv = valueTable_lookup (s->state, key);
689 if (stateValue_isDefined (sv))
691 return stateValue_getInfo (sv);
694 return stateInfo_undefined;
696 # endif
698 static bool
699 sRef_hasNullInfoLoc (sRef s)
701 return (sRef_isReasonable (s) && s->nullinfo != NULL
702 && (fileloc_isDefined (s->nullinfo->loc)));
705 bool
706 sRef_hasAliasInfoRef (sRef s)
708 return (sRef_isReasonable (s) && (s->aliasinfo != NULL)
709 && (sRef_isReasonable (s->aliasinfo->ref)));
712 static /*@observer@*/ fileloc
713 sRef_getAliasInfoLoc (/*@exposed@*/ sRef s)
715 llassert (sRef_isReasonable (s) && s->aliasinfo != NULL
716 && (fileloc_isDefined (s->aliasinfo->loc)));
717 return (s->aliasinfo->loc);
720 static /*@observer@*/ fileloc
721 sRef_getStateInfoLoc (/*@exposed@*/ sRef s)
723 llassert (sRef_isReasonable (s) && s->definfo != NULL
724 && (fileloc_isDefined (s->definfo->loc)));
725 return (s->definfo->loc);
728 #ifdef DEADCODE
729 static /*@observer@*/ fileloc
730 sRef_getExpInfoLoc (/*@exposed@*/ sRef s)
732 llassert (sRef_isReasonable (s) && s->expinfo != NULL
733 && (fileloc_isDefined (s->expinfo->loc)));
734 return (s->expinfo->loc);
736 #endif
738 static /*@observer@*/ fileloc
739 sRef_getNullInfoLoc (/*@exposed@*/ sRef s)
741 llassert (sRef_isReasonable (s) && s->nullinfo != NULL
742 && (fileloc_isDefined (s->nullinfo->loc)));
743 return (s->nullinfo->loc);
746 /*@observer@*/ sRef
747 sRef_getAliasInfoRef (/*@temp@*/ sRef s)
749 llassert (sRef_isReasonable (s) && s->aliasinfo != NULL);
750 return (s->aliasinfo->ref);
753 bool sRef_inGlobalScope (void)
755 return !inFunction;
759 ** This function should be called before new sRefs are created
760 ** somewhere where they will have a lifetime greater than the
761 ** current function scope.
764 void sRef_setGlobalScope (void)
766 llassert (inFunction);
767 DPRINTF (("leave function"));
768 inFunction = FALSE;
771 void sRef_clearGlobalScope (void)
773 llassert (!inFunction);
774 DPRINTF (("enter function"));
775 inFunction = TRUE;
778 static bool oldInFunction = FALSE;
779 static int nestedScope = 0;
781 void sRef_setGlobalScopeSafe (void)
783 if (nestedScope == 0)
785 oldInFunction = inFunction;
788 nestedScope++;
789 DPRINTF (("leave function safe"));
790 inFunction = FALSE;
793 void sRef_clearGlobalScopeSafe (void)
795 nestedScope--;
796 llassert (nestedScope >= 0);
798 if (nestedScope == 0)
800 inFunction = oldInFunction;
803 DPRINTF (("clear function: %s", bool_unparse (inFunction)));
806 void sRef_enterFunctionScope (void)
808 /* evans 2001-09-09 - cleanup if we are in a macro! */
809 if (context_inMacro ())
811 if (inFunction) {
812 sRef_exitFunctionScope ();
816 llassert (!inFunction);
817 llassert (sRefTable_isEmpty (allRefs));
818 inFunction = TRUE;
819 DPRINTF (("enter function"));
822 void sRef_exitFunctionScope (void)
824 if (inFunction)
826 DPRINTF (("Exit function scope."));
827 sRefTable_clear (allRefs);
828 DPRINTF (("Exit function scope done."));
829 inFunction = FALSE;
831 else
833 llbuglit ("sRef_exitFunctionScope: not in function");
837 void sRef_destroyMod (void) /*@globals killed allRefs;@*/
839 # ifdef DEBUGREFS
840 llmsg (message ("Live: %d / %d ", nsrefs, totnsrefs));
841 # endif
843 sRefTable_free (allRefs);
847 static /*@notnull@*/ /*@exposed@*/ sRef
848 sRef_fixConj (/*@notnull@*/ sRef s)
850 if (sRef_isConj (s))
852 do {
853 s = sRef_getConjA (s);
854 } while (sRef_isConj (s));
856 llassert (sRef_isReasonable (s));
857 return s; /* don't need to ref */
859 else
861 return s;
865 static bool
866 sRef_isExternallyVisibleAux (sRef s)
868 bool res = FALSE;
869 sRef base = sRef_getRootBase (s);
871 if (sRef_isReasonable (base))
873 res = sRef_isParam (base) || sRef_isFileOrGlobalScope (base) || sRef_isExternal (base);
876 return res;
879 bool
880 sRef_isExternallyVisible (sRef s)
882 return (sRef_aliasCheckSimplePred (sRef_isExternallyVisibleAux, s));
885 /*@exposed@*/ uentry
886 sRef_getBaseUentry (sRef s)
888 sRef base = sRef_getRootBase (s);
889 uentry res = uentry_undefined;
891 if (sRef_isReasonable (base))
893 switch (base->kind)
895 case SK_PARAM:
896 res = usymtab_getRefQuiet (paramsScope, usymId_fromInt (base->info->paramno));
897 break;
899 case SK_CVAR:
900 res = usymtab_getRefQuiet (base->info->cvar->lexlevel,
901 base->info->cvar->index);
902 break;
904 default:
905 break;
909 return res;
913 ** lookup the current uentry corresponding to s, and return the corresponding sRef.
914 ** yuk yuk yuk yuk yuk yuk yuk yuk
917 /*@exposed@*/ sRef
918 sRef_updateSref (sRef s)
920 sRef inner;
921 sRef ret;
922 sRef res;
924 if (!sRef_isReasonable (s)) return sRef_undefined;
926 switch (s->kind)
928 case SK_UNKNOWN:
929 case SK_OBJECT:
930 case SK_NEW:
931 case SK_TYPE:
932 case SK_DERIVED:
933 case SK_UNCONSTRAINED:
934 case SK_CONST:
935 case SK_SPECIAL:
936 case SK_RESULT:
937 return s;
938 case SK_EXTERNAL:
940 sRef r = sRef_updateSref (s->info->ref);
942 if (r != s->info->ref)
944 return sRef_makeExternal (r);
946 else
948 return s;
951 case SK_PARAM:
952 case SK_CVAR:
954 uentry ue = sRef_getUentry (s);
956 /* must be raw name! (need the marker) */
957 /* Must be in the correct scope! */
959 ue = usymtab_lookupSafeScope (uentry_rawName (ue), sRef_lexLevel (s));
961 if (uentry_isUndefined (ue))
963 return s;
965 else
967 DPRINTF (("Update sref: %s", uentry_unparseFull (ue)));
968 return (uentry_getSref (ue));
971 case SK_ARRAYFETCH:
972 /* special case if ind known */
973 inner = s->info->arrayfetch->arr;
974 ret = sRef_updateSref (inner);
976 if (ret == inner)
978 res = s;
980 else
982 res = sRef_makeArrayFetch (ret);
985 return res;
987 case SK_FIELD:
988 inner = s->info->field->rec;
989 ret = sRef_updateSref (inner);
991 if (ret == inner)
993 res = s;
995 else
997 res = (sRef_makeField (ret, s->info->field->field));
1000 return (res);
1001 case SK_PTR:
1002 inner = s->info->ref;
1003 ret = sRef_updateSref (inner);
1004 if (ret == inner)
1006 res = s;
1008 else
1010 res = sRef_makePointer (ret);
1013 return (res);
1015 case SK_ADR:
1016 inner = s->info->ref;
1017 ret = sRef_updateSref (inner);
1019 if (ret == inner)
1021 res = s;
1023 else
1025 res = sRef_makeAddress (ret);
1028 return (res);
1030 case SK_CONJ:
1032 sRef innera = s->info->conj->a;
1033 sRef innerb = s->info->conj->b;
1034 sRef reta = sRef_updateSref (innera);
1035 sRef retb = sRef_updateSref (innerb);
1037 if (innera == reta && innerb == retb)
1039 res = s;
1041 else
1043 res = sRef_makeConj (reta, retb);
1046 return (res);
1050 BADEXIT;
1053 uentry
1054 sRef_getUentry (sRef s)
1056 llassert (sRef_isReasonable (s));
1058 switch (s->kind)
1060 case SK_PARAM:
1061 return (usymtab_getRefQuiet (paramsScope, usymId_fromInt (s->info->paramno)));
1062 case SK_CVAR:
1063 return (usymtab_getRefQuiet (s->info->cvar->lexlevel, s->info->cvar->index));
1064 case SK_CONJ:
1066 if (sRef_isCvar (s->info->conj->a) || sRef_isParam (s->info->conj->a)
1067 || sRef_isConj (s->info->conj->a))
1069 return sRef_getUentry (s->info->conj->a);
1071 else
1073 return sRef_getUentry (s->info->conj->b);
1076 case SK_FIELD: /* evans 2002-07-17: added case for SK_FIELD */
1077 case SK_UNKNOWN:
1078 case SK_SPECIAL:
1079 return uentry_undefined;
1080 BADDEFAULT;
1085 sRef_getParam (sRef s)
1087 llassert (sRef_isReasonable (s));
1088 llassert (s->kind == SK_PARAM);
1090 return s->info->paramno;
1093 bool
1094 sRef_isModified (sRef s)
1096 return (!sRef_isReasonable (s) || s->modified);
1099 void sRef_setModified (sRef s)
1101 if (sRef_isReasonable (s))
1103 s->modified = TRUE;
1106 if (sRef_isRefsField (s))
1108 sRef base = sRef_getBase (s);
1110 llassert (s->kind == SK_FIELD);
1112 if (sRef_isPointer (base))
1114 base = sRef_getBase (base);
1117 if (sRef_isRefCounted (base))
1119 base->aliaskind = AK_NEWREF;
1126 ** note: this side-effects sRefSet to set modified to TRUE
1127 ** for any sRef similar to s.
1130 bool
1131 sRef_canModifyVal (sRef s, sRefSet sl)
1133 if (context_getFlag (FLG_MUSTMOD))
1135 return (sRef_doModifyVal (s, sl));
1137 else
1139 return (sRef_checkModifyVal (s, sl));
1143 bool
1144 sRef_canModify (sRef s, sRefSet sl)
1146 if (context_getFlag (FLG_MUSTMOD))
1148 return (sRef_doModify (s, sl));
1150 else
1152 return (sRef_checkModify (s, sl));
1157 ** No side-effects
1160 static
1161 bool sRef_checkModifyVal (sRef s, sRefSet sl)
1163 DPRINTF (("Check modify val: %s", sRef_unparse (s)));
1165 if (sRef_isInvalid (s))
1167 return TRUE;
1170 switch (s->kind)
1172 case SK_UNCONSTRAINED:
1173 case SK_CONST:
1174 return TRUE;
1175 case SK_CVAR:
1176 DPRINTF (("Modify var: %s", sRef_unparse (s)));
1178 if (sRef_isFileOrGlobalScope (s))
1180 if (context_checkGlobMod (s))
1182 return (sRefSet_member (sl, s));
1185 return TRUE;
1187 else
1189 return TRUE;
1191 case SK_PARAM:
1192 return (sRefSet_member (sl, s)
1193 || alkind_isOnly (sRef_getOrigAliasKind (s)));
1194 case SK_ARRAYFETCH:
1195 /* special case if ind known */
1196 return (sRefSet_member (sl, s) ||
1197 sRef_checkModifyVal (s->info->arrayfetch->arr, sl));
1198 case SK_FIELD:
1199 return (sRefSet_member (sl, s) || sRef_checkModifyVal (s->info->field->rec, sl));
1200 case SK_PTR:
1201 return (sRefSet_member (sl, s) || sRef_checkModifyVal (s->info->ref, sl));
1202 case SK_ADR:
1203 return (sRefSet_member (sl, s) || sRef_checkModifyVal (s->info->ref, sl));
1204 case SK_CONJ:
1205 return ((sRef_checkModifyVal (s->info->conj->a, sl)) &&
1206 (sRef_checkModifyVal (s->info->conj->b, sl)));
1207 case SK_UNKNOWN:
1208 case SK_OBJECT:
1209 case SK_NEW:
1210 case SK_TYPE:
1211 case SK_DERIVED:
1212 return TRUE;
1213 case SK_EXTERNAL:
1214 return TRUE;
1215 case SK_SPECIAL:
1217 switch (s->info->spec)
1219 case SR_NOTHING: return TRUE;
1220 case SR_INTERNAL:
1221 if (context_getFlag (FLG_INTERNALGLOBS))
1223 return (sRefSet_member (sl, s));
1225 else
1227 return TRUE;
1229 case SR_SPECSTATE: return TRUE;
1230 case SR_SYSTEM: return (sRefSet_member (sl, s));
1231 case SR_GLOBALMARKER: BADBRANCH;
1234 case SK_RESULT: BADBRANCH;
1236 BADEXIT;
1240 ** this should probably be elsewhere...
1242 ** returns TRUE iff sl indicates that s can be modified
1245 static bool sRef_checkModify (sRef s, sRefSet sl)
1247 llassert (sRef_isReasonable (s));
1249 switch (s->kind)
1251 case SK_UNCONSTRAINED:
1252 case SK_CONST:
1253 return TRUE;
1254 case SK_CVAR:
1255 if (sRef_isFileOrGlobalScope (s))
1257 if (context_checkGlobMod (s))
1259 return (sRefSet_member (sl, s));
1262 return TRUE;
1264 else
1266 return TRUE;
1268 case SK_PARAM:
1269 return TRUE;
1270 case SK_ARRAYFETCH:
1271 return (sRefSet_member (sl, s) ||
1272 sRef_checkModifyVal (s->info->arrayfetch->arr, sl));
1273 case SK_FIELD:
1275 sRef sr = s->info->field->rec;
1277 if (sr->kind == SK_PARAM)
1278 return TRUE; /* structs are copied on call */
1280 return (sRefSet_member (sl, s) || sRef_checkModifyVal (s->info->field->rec, sl));
1282 case SK_PTR:
1284 bool sm;
1286 sm = sRefSet_member (sl, s);
1288 if (sm)
1289 return TRUE;
1290 else
1291 return (sRef_checkModifyVal (s->info->ref, sl));
1293 case SK_ADR:
1294 return (sRefSet_member (sl, s) || sRef_checkModifyVal (s->info->ref, sl));
1295 case SK_CONJ:
1296 return ((sRef_checkModify (s->info->conj->a, sl)) &&
1297 (sRef_checkModify (s->info->conj->b, sl)));
1298 case SK_NEW:
1299 case SK_OBJECT:
1300 case SK_UNKNOWN:
1301 case SK_TYPE:
1302 case SK_DERIVED:
1303 case SK_EXTERNAL:
1304 return TRUE;
1305 case SK_SPECIAL:
1307 switch (s->info->spec)
1309 case SR_NOTHING: return TRUE;
1310 case SR_INTERNAL:
1311 if (context_getFlag (FLG_INTERNALGLOBS))
1313 return (sRefSet_member (sl, s));
1315 else
1317 return TRUE;
1319 case SR_SPECSTATE: return TRUE;
1320 case SR_SYSTEM: return (sRefSet_member (sl, s));
1321 case SR_GLOBALMARKER: BADBRANCH;
1324 case SK_RESULT: BADBRANCH;
1326 BADEXIT;
1329 cstring sRef_stateVerb (sRef s)
1331 if (sRef_isDead (s))
1333 return cstring_makeLiteralTemp ("released");
1335 else if (sRef_isKept (s))
1337 return cstring_makeLiteralTemp ("kept");
1339 else if (sRef_isDependent (s))
1341 return cstring_makeLiteralTemp ("dependent");
1343 else
1345 BADEXIT;
1349 cstring sRef_stateAltVerb (sRef s)
1351 if (sRef_isDead (s))
1353 return cstring_makeLiteralTemp ("live");
1355 else if (sRef_isKept (s))
1357 return cstring_makeLiteralTemp ("not kept");
1359 else if (sRef_isDependent (s))
1361 return cstring_makeLiteralTemp ("independent");
1363 else
1365 BADEXIT;
1369 static
1370 bool sRef_doModifyVal (sRef s, sRefSet sl)
1372 llassert (sRef_isReasonable (s));
1375 switch (s->kind)
1377 case SK_UNCONSTRAINED:
1378 case SK_CONST:
1379 return TRUE;
1380 case SK_CVAR:
1381 if (sRef_isFileOrGlobalScope (s))
1384 if (context_checkGlobMod (s))
1386 return (sRefSet_modifyMember (sl, s));
1388 else
1390 (void) sRefSet_modifyMember (sl, s);
1393 return TRUE;
1395 else
1397 return TRUE;
1399 case SK_PARAM:
1400 return (sRefSet_modifyMember (sl, s)
1401 || alkind_isOnly (sRef_getOrigAliasKind (s)));
1402 case SK_ARRAYFETCH:
1403 /* special case if ind known */
1404 /* unconditional OR, need side effect */
1405 return (OR (sRefSet_modifyMember (sl, s),
1406 sRef_doModifyVal (s->info->arrayfetch->arr, sl)));
1407 case SK_FIELD:
1408 return (OR (sRefSet_modifyMember (sl, s),
1409 sRef_doModifyVal (s->info->field->rec, sl)));
1410 case SK_PTR:
1411 return (OR (sRefSet_modifyMember (sl, s),
1412 sRef_doModifyVal (s->info->ref, sl)));
1413 case SK_ADR:
1414 return (OR (sRefSet_modifyMember (sl, s),
1415 sRef_doModifyVal (s->info->ref, sl)));
1416 case SK_CONJ:
1417 return (AND (sRef_doModifyVal (s->info->conj->a, sl) ,
1418 sRef_doModifyVal (s->info->conj->b, sl)));
1419 case SK_OBJECT:
1420 case SK_DERIVED:
1421 case SK_EXTERNAL:
1422 case SK_UNKNOWN:
1423 case SK_NEW:
1424 case SK_TYPE:
1425 return TRUE;
1426 case SK_SPECIAL:
1428 switch (s->info->spec)
1430 case SR_NOTHING: return TRUE;
1431 case SR_INTERNAL:
1432 if (context_getFlag (FLG_INTERNALGLOBS))
1434 return (sRefSet_modifyMember (sl, s));
1436 else
1438 (void) sRefSet_modifyMember (sl, s);
1439 return TRUE;
1441 case SR_SPECSTATE: return TRUE;
1442 case SR_SYSTEM: return (sRefSet_modifyMember (sl, s));
1443 case SR_GLOBALMARKER: BADBRANCH;
1447 case SK_RESULT: BADBRANCH;
1449 BADEXIT;
1453 ** this should probably be elsewhere...
1455 ** returns TRUE iff sl indicates that s can be modified
1458 static
1459 bool sRef_doModify (sRef s, sRefSet sl)
1461 llassert (sRef_isReasonable (s));
1463 switch (s->kind)
1465 case SK_UNCONSTRAINED:
1466 case SK_CONST:
1467 return TRUE;
1468 case SK_CVAR:
1469 if (sRef_isFileOrGlobalScope (s))
1471 if (context_checkGlobMod (s))
1473 return (sRefSet_modifyMember (sl, s));
1475 else
1477 (void) sRefSet_modifyMember (sl, s);
1480 return TRUE;
1482 else
1484 return TRUE;
1486 case SK_PARAM:
1487 return TRUE;
1488 case SK_ARRAYFETCH:
1489 return (OR (sRefSet_modifyMember (sl, s),
1490 sRef_doModifyVal (s->info->arrayfetch->arr, sl)));
1491 case SK_FIELD:
1493 sRef sr = s->info->field->rec;
1495 if (sr->kind == SK_PARAM)
1497 return TRUE; /* structs are shallow-copied on call */
1500 return (OR (sRefSet_modifyMember (sl, s),
1501 sRef_doModifyVal (s->info->field->rec, sl)));
1503 case SK_PTR:
1505 return (OR (sRefSet_modifyMember (sl, s),
1506 sRef_doModifyVal (s->info->ref, sl)));
1508 case SK_ADR:
1509 return (OR (sRefSet_modifyMember (sl, s),
1510 sRef_doModifyVal (s->info->ref, sl)));
1511 case SK_CONJ:
1512 return (AND (sRef_doModify (s->info->conj->a, sl),
1513 (sRef_doModify (s->info->conj->b, sl))));
1514 case SK_UNKNOWN:
1515 case SK_NEW:
1516 case SK_TYPE:
1517 return TRUE;
1518 case SK_OBJECT:
1519 case SK_DERIVED:
1520 case SK_EXTERNAL:
1521 return TRUE;
1522 case SK_SPECIAL:
1524 switch (s->info->spec)
1526 case SR_NOTHING: return TRUE;
1527 case SR_INTERNAL: return TRUE;
1528 case SR_SPECSTATE: return TRUE;
1529 case SR_SYSTEM: return (sRefSet_modifyMember (sl, s));
1530 case SR_GLOBALMARKER: BADBRANCH;
1533 case SK_RESULT: BADBRANCH;
1535 BADEXIT;
1538 static /*@exposed@*/ sRef
1539 sRef_leastCommon (/*@exposed@*/ sRef s1, sRef s2)
1541 llassert (sRef_similar (s1, s2));
1543 if (!sRef_isReasonable (s1)) return s1;
1544 if (!sRef_isReasonable (s2)) return s1;
1546 sRef_combineDefState (s1, s2);
1547 sRef_combineNullState (s1, s2);
1548 sRef_combineExKinds (s1, s2);
1550 if (s1->aliaskind != s2->aliaskind)
1552 if (s1->aliaskind == AK_UNKNOWN)
1554 s1->aliaskind = s2->aliaskind;
1556 else if (s2->aliaskind == AK_UNKNOWN)
1560 else
1562 s1->aliaskind = AK_ERROR;
1566 return s1;
1569 int sRef_compare (sRef s1, sRef s2)
1571 if (s1 == s2) return 0;
1573 if (sRef_isInvalid (s1)) return -1;
1574 if (sRef_isInvalid (s2)) return 1;
1576 INTCOMPARERETURN (s1->kind, s2->kind);
1577 INTCOMPARERETURN (s1->defstate, s2->defstate);
1578 INTCOMPARERETURN (s1->aliaskind, s2->aliaskind);
1580 DPRINTF (("Compare null state: %s / %s",
1581 sRef_unparseFull (s1),
1582 sRef_unparseFull (s2)));
1584 COMPARERETURN (nstate_compare (sRef_getNullState (s1),
1585 sRef_getNullState (s2)));
1587 switch (s1->kind)
1589 case SK_PARAM:
1590 return (int_compare (s1->info->paramno, s2->info->paramno));
1591 case SK_ARRAYFETCH:
1593 COMPARERETURN (sRef_compare (s1->info->arrayfetch->arr,
1594 s2->info->arrayfetch->arr));
1596 if (s1->info->arrayfetch->indknown && s2->info->arrayfetch->indknown)
1598 return (int_compare (s1->info->arrayfetch->ind,
1599 s2->info->arrayfetch->ind));
1601 if (!s1->info->arrayfetch->indknown && !s2->info->arrayfetch->indknown)
1602 return 0;
1604 return 1;
1606 case SK_FIELD:
1608 COMPARERETURN (sRef_compare (s1->info->field->rec, s2->info->field->rec));
1610 if (cstring_equal (s1->info->field->field, s2->info->field->field))
1611 return 0;
1613 return 1;
1615 case SK_PTR:
1616 case SK_ADR:
1617 return (sRef_compare (s1->info->ref, s2->info->ref));
1618 case SK_CONJ:
1619 COMPARERETURN (sRef_compare (s1->info->conj->a, s2->info->conj->a));
1620 return (sRef_compare (s1->info->conj->b, s2->info->conj->b));
1621 case SK_UNCONSTRAINED:
1622 return (cstring_compare (s1->info->fname, s2->info->fname));
1623 case SK_NEW:
1624 case SK_CVAR:
1625 case SK_UNKNOWN:
1626 case SK_OBJECT:
1627 case SK_TYPE:
1628 case SK_DERIVED:
1629 case SK_EXTERNAL:
1630 case SK_CONST:
1631 case SK_RESULT:
1632 return 0;
1633 case SK_SPECIAL:
1634 return (generic_compare (s1->info->spec, s2->info->spec));
1636 BADEXIT;
1639 static bool cref_equal (cref c1, cref c2)
1641 return ((c1->lexlevel == c2->lexlevel) &&
1642 (usymId_equal (c1->index, c2->index)));
1646 ** returns true if s1 could be the same storage as s2.
1647 ** i.e., a[?] ~ a[3]. Note its not symmetric ... s1
1648 ** should be more specific.
1652 ** like similar, but matches objects <-> non-objects
1655 static bool
1656 sRef_uniqueReference (sRef s)
1658 return (sRef_isFresh (s) || sRef_isUnique (s)
1659 || sRef_isOnly (s) || sRef_isStack (s)
1660 || sRef_isAddress (s));
1663 static bool
1664 sRef_similarRelaxedAux (sRef s1, sRef s2)
1666 if (s1 == s2)
1668 if (sRef_isUnknownArrayFetch (s1))
1670 return FALSE;
1672 else
1674 return TRUE;
1678 if (sRef_isInvalid (s1) || sRef_isInvalid (s2)) return FALSE;
1680 if (sRef_isConj (s2))
1681 return (sRef_similarRelaxedAux (s1, sRef_getConjA (s2)) ||
1682 sRef_similarRelaxedAux (s1, sRef_getConjB (s2)));
1684 switch (s1->kind)
1686 case SK_CVAR:
1687 return ((s2->kind == SK_CVAR)
1688 && (cref_equal (s1->info->cvar, s2->info->cvar)));
1689 case SK_PARAM:
1690 return ((s2->kind == SK_PARAM)
1691 && (s1->info->paramno == s2->info->paramno));
1692 case SK_ARRAYFETCH:
1693 if (s2->kind == SK_ARRAYFETCH)
1695 if (sRef_similarRelaxedAux (s1->info->arrayfetch->arr,
1696 s2->info->arrayfetch->arr))
1698 if (s1->info->arrayfetch->indknown)
1700 if (s2->info->arrayfetch->indknown)
1702 return (s1->info->arrayfetch->ind == s2->info->arrayfetch->ind);
1704 else
1706 return FALSE;
1709 else
1711 return FALSE;
1715 return FALSE;
1716 case SK_FIELD:
1717 return ((s2->kind == SK_FIELD
1718 && (sRef_similarRelaxedAux (s1->info->field->rec,
1719 s2->info->field->rec)
1720 && cstring_equal (s1->info->field->field,
1721 s2->info->field->field))));
1722 case SK_PTR:
1723 return ((s2->kind == SK_PTR)
1724 && sRef_similarRelaxedAux (s1->info->ref, s2->info->ref));
1725 case SK_ADR:
1726 return ((s2->kind == SK_ADR)
1727 && sRef_similarRelaxedAux (s1->info->ref, s2->info->ref));
1728 case SK_CONJ:
1729 return ((sRef_similarRelaxedAux (s1->info->conj->a, s2) ||
1730 (sRef_similarRelaxedAux (s1->info->conj->b, s2))));
1731 case SK_SPECIAL:
1732 return (s1->info->spec == s2->info->spec);
1733 case SK_UNCONSTRAINED:
1734 return (cstring_equal (s1->info->fname, s2->info->fname));
1735 case SK_DERIVED:
1736 case SK_CONST:
1737 case SK_TYPE:
1738 case SK_NEW:
1739 case SK_UNKNOWN:
1740 case SK_OBJECT:
1741 case SK_EXTERNAL:
1742 case SK_RESULT:
1743 return FALSE;
1745 BADEXIT;
1748 bool
1749 sRef_similarRelaxed (sRef s1, sRef s2)
1751 bool us1, us2;
1753 if (s1 == s2)
1755 if (sRef_isThroughArrayFetch (s1))
1757 return FALSE;
1759 else
1761 return TRUE;
1765 if (sRef_isInvalid (s1) || sRef_isInvalid (s2)) return FALSE;
1767 us1 = sRef_uniqueReference (s1);
1768 us2 = sRef_uniqueReference (s2);
1770 if ((s1->kind == SK_EXTERNAL && (s2->kind != SK_EXTERNAL && !us2))
1771 || (s2->kind == SK_EXTERNAL && (s1->kind != SK_EXTERNAL && !us1)))
1774 ** Previously, also:
1775 ** || (sRef_isExposed (s1) && !us2) || (sRef_isExposed (s2) && !us1)) ????
1777 ** No clue why this was there?!
1781 if (sRef_isExposed (s1) && sRef_isCvar (s1))
1783 uentry ue1 = sRef_getUentry (s1);
1785 if (uentry_isRefParam (ue1))
1787 return sRef_similarRelaxedAux (s1, s2);
1791 if (sRef_isExposed (s2) && sRef_isCvar (s2))
1793 uentry ue2 = sRef_getUentry (s2);
1795 if (uentry_isRefParam (ue2))
1797 return sRef_similarRelaxedAux (s1, s2);
1801 return (ctype_match (s1->type, s2->type));
1803 else
1805 return sRef_similarRelaxedAux (s1, s2);
1809 bool
1810 sRef_similar (sRef s1, sRef s2)
1812 if (s1 == s2) return TRUE;
1813 if (sRef_isInvalid (s1) || sRef_isInvalid (s2)) return FALSE;
1815 if (sRef_isConj (s2))
1817 return (sRef_similar (s1, sRef_getConjA (s2)) ||
1818 sRef_similar (s1, sRef_getConjB (s2)));
1821 if (sRef_isDerived (s2))
1823 return (sRef_includedBy (s1, s2->info->ref));
1826 switch (s1->kind)
1828 case SK_CVAR:
1829 return ((s2->kind == SK_CVAR)
1830 && (cref_equal (s1->info->cvar, s2->info->cvar)));
1831 case SK_PARAM:
1832 return ((s2->kind == SK_PARAM)
1833 && (s1->info->paramno == s2->info->paramno));
1834 case SK_ARRAYFETCH:
1835 if (s2->kind == SK_ARRAYFETCH)
1837 if (sRef_similar (s1->info->arrayfetch->arr,
1838 s2->info->arrayfetch->arr))
1840 if (s1->info->arrayfetch->indknown)
1842 if (s2->info->arrayfetch->indknown)
1844 return (s1->info->arrayfetch->ind == s2->info->arrayfetch->ind);
1846 else
1848 return TRUE;
1851 else
1853 return TRUE;
1857 else
1859 if (s2->kind == SK_PTR)
1861 if (sRef_similar (s1->info->arrayfetch->arr,
1862 s2->info->ref))
1864 return TRUE;
1869 return FALSE;
1870 case SK_FIELD:
1871 return ((s2->kind == SK_FIELD
1872 && (sRef_similar (s1->info->field->rec,
1873 s2->info->field->rec)
1874 && cstring_equal (s1->info->field->field,
1875 s2->info->field->field))));
1876 case SK_PTR:
1877 if (s2->kind == SK_PTR)
1879 return sRef_similar (s1->info->ref, s2->info->ref);
1881 else
1883 if (s2->kind == SK_ARRAYFETCH)
1885 if (sRef_similar (s2->info->arrayfetch->arr,
1886 s1->info->ref))
1888 return TRUE;
1893 return FALSE;
1894 case SK_ADR:
1895 return ((s2->kind == SK_ADR)
1896 && sRef_similar (s1->info->ref, s2->info->ref));
1897 case SK_CONJ:
1898 return ((sRef_similar (s1->info->conj->a, s2) ||
1899 (sRef_similar (s1->info->conj->b, s2))));
1900 case SK_DERIVED:
1901 return (sRef_includedBy (s2, s1->info->ref));
1902 case SK_UNCONSTRAINED:
1903 return (s2->kind == SK_UNCONSTRAINED
1904 && cstring_equal (s1->info->fname, s2->info->fname));
1905 case SK_CONST:
1906 case SK_TYPE:
1907 case SK_NEW:
1908 case SK_UNKNOWN:
1909 case SK_OBJECT:
1910 case SK_EXTERNAL:
1911 case SK_RESULT:
1912 return FALSE;
1913 case SK_SPECIAL:
1914 return (s2->kind == SK_SPECIAL
1915 && (s1->info->spec == s2->info->spec));
1918 /*@notreached@*/ DPRINTF (("Fell through for: %s / %s", sRef_unparse (s1), sRef_unparse (s2)));
1919 BADEXIT;
1923 ** return TRUE iff small can be derived from big.
1925 ** (e.g. x, x.a is includedBy x;
1926 ** x.a is included By x.a;
1929 bool
1930 sRef_includedBy (sRef small, sRef big)
1932 if (small == big) return TRUE;
1933 if (sRef_isInvalid (small) || sRef_isInvalid (big)) return FALSE;
1935 if (sRef_isConj (big))
1936 return (sRef_similar (small, sRef_getConjA (big)) ||
1937 sRef_similar (small, sRef_getConjB (big)));
1939 switch (small->kind)
1941 case SK_CVAR:
1942 case SK_PARAM:
1943 return (sRef_same (small, big));
1944 case SK_ARRAYFETCH:
1945 if (big->kind == SK_ARRAYFETCH)
1947 if (sRef_same (small->info->arrayfetch->arr, big->info->arrayfetch->arr))
1949 if (small->info->arrayfetch->indknown)
1951 if (big->info->arrayfetch->indknown)
1953 return (small->info->arrayfetch->ind == big->info->arrayfetch->ind);
1955 else
1957 return TRUE;
1960 else
1962 return TRUE;
1966 return (sRef_includedBy (small->info->arrayfetch->arr, big));
1967 case SK_FIELD:
1968 if (big->kind == SK_FIELD)
1970 return
1971 (sRef_same (small->info->field->rec, big->info->field->rec) &&
1972 cstring_equal (small->info->field->field, big->info->field->field));
1974 else
1976 return (sRef_includedBy (small->info->field->rec, big));
1979 case SK_PTR:
1980 if (big->kind == SK_PTR)
1982 return sRef_same (small->info->ref, big->info->ref);
1984 else
1986 return (sRef_includedBy (small->info->ref, big));
1989 case SK_ADR:
1990 return ((big->kind == SK_ADR) && sRef_similar (small->info->ref, big->info->ref));
1991 case SK_CONJ:
1992 return ((sRef_includedBy (small->info->conj->a, big) ||
1993 (sRef_includedBy (small->info->conj->b, big))));
1994 case SK_DERIVED:
1995 return (sRef_includedBy (small->info->ref, big));
1996 case SK_UNCONSTRAINED:
1997 case SK_CONST:
1998 case SK_TYPE:
1999 case SK_NEW:
2000 case SK_UNKNOWN:
2001 case SK_OBJECT:
2002 case SK_EXTERNAL:
2003 case SK_RESULT:
2004 return FALSE;
2005 case SK_SPECIAL:
2006 switch (small->info->spec)
2008 case SR_NOTHING: return TRUE;
2009 case SR_SPECSTATE:
2010 case SR_INTERNAL: return (sRef_isSpecInternalState (big) ||
2011 sRef_isFileStatic (big));
2012 case SR_SYSTEM: return (sRef_isSystemState (big));
2013 case SR_GLOBALMARKER: BADBRANCH;
2016 BADEXIT;
2020 ** Same is similar to similar, but not quite the same.
2021 ** same and realSame aren't the same, but they are really similar.
2022 ** similarly, same is the same as same. but realSame is
2023 ** not really the same as same, or similar to similar.
2025 ** Similarly to similar, same checks if two sRefs are the same.
2026 ** The similarities end, however, when same compares arrays
2027 ** with unknown indexes. Similar returns false; same returns true.
2029 ** Similarly to similar and same, realSame is the same as same,
2030 ** except they do not behave the same when face with unknown
2031 ** sRefs. Same thinks they are not the same, but realSame thinks
2032 ** the are.
2036 bool
2037 sRef_realSame (sRef s1, sRef s2)
2039 if (s1 == s2) return TRUE;
2041 if (sRef_isUnreasonable (s1)
2042 || sRef_isUnreasonable (s2))
2044 return FALSE;
2047 switch (s1->kind)
2049 case SK_CVAR:
2050 return ((s2->kind == SK_CVAR) && (cref_equal (s1->info->cvar, s2->info->cvar)));
2051 case SK_PARAM:
2052 return ((s2->kind == SK_PARAM) && (s1->info->paramno == s2->info->paramno));
2053 case SK_ARRAYFETCH:
2054 if (s2->kind == SK_ARRAYFETCH)
2056 if (sRef_realSame (s1->info->arrayfetch->arr, s2->info->arrayfetch->arr))
2058 if (s1->info->arrayfetch->indknown && s2->info->arrayfetch->indknown)
2060 return (s1->info->arrayfetch->ind == s2->info->arrayfetch->ind);
2062 if (!s1->info->arrayfetch->indknown && !s2->info->arrayfetch->indknown)
2064 return TRUE;
2066 return FALSE;
2069 return FALSE;
2070 case SK_FIELD:
2071 return ((s2->kind == SK_FIELD &&
2072 (sRef_realSame (s1->info->field->rec, s2->info->field->rec) &&
2073 cstring_equal (s1->info->field->field, s2->info->field->field))));
2074 case SK_PTR:
2075 return ((s2->kind == SK_PTR) && sRef_realSame (s1->info->ref, s2->info->ref));
2076 case SK_ADR:
2077 return ((s2->kind == SK_ADR) && sRef_realSame (s1->info->ref, s2->info->ref));
2078 case SK_CONJ:
2079 return ((sRef_realSame (s1->info->conj->a, s2) ||
2080 (sRef_realSame (s1->info->conj->b, s2))));
2081 case SK_OBJECT:
2082 return ((s2->kind == SK_OBJECT)
2083 && ctype_match (s1->info->object, s2->info->object));
2084 case SK_EXTERNAL:
2085 return ((s2->kind == SK_EXTERNAL)
2086 && sRef_realSame (s1->info->ref, s2->info->ref));
2087 case SK_SPECIAL:
2088 return ((s2->kind == SK_SPECIAL) && s1->info->spec == s2->info->spec);
2089 case SK_DERIVED:
2090 return ((s2->kind == SK_DERIVED) && sRef_realSame (s1->info->ref, s2->info->ref));
2091 case SK_UNCONSTRAINED:
2092 return ((s2->kind == SK_UNCONSTRAINED)
2093 && (cstring_equal (s1->info->fname, s2->info->fname)));
2094 case SK_TYPE:
2095 case SK_CONST:
2096 case SK_NEW:
2097 case SK_UNKNOWN:
2098 case SK_RESULT:
2099 return TRUE; /* changed this! was false */
2101 BADEXIT;
2104 #ifdef DEADCODE
2105 bool
2106 sRef_sameObject (sRef s1, sRef s2)
2108 return (s1 == s2);
2110 #endif
2113 ** same is similar to similar, but not quite the same.
2115 ** Similarly to similar, same checks is two sRefs are the same.
2116 ** The similarities end, however, when same compares arrays
2117 ** with unknown indexes. Similar returns false; same returns true.
2120 bool
2121 sRef_same (sRef s1, sRef s2)
2123 if (s1 == s2) return TRUE;
2124 if (sRef_isInvalid (s1) || sRef_isInvalid (s2)) return FALSE;
2126 switch (s1->kind)
2128 case SK_CVAR:
2129 return ((s2->kind == SK_CVAR) && (cref_equal (s1->info->cvar, s2->info->cvar)));
2130 case SK_PARAM:
2131 return ((s2->kind == SK_PARAM) && (s1->info->paramno == s2->info->paramno));
2132 case SK_ARRAYFETCH:
2133 if (s2->kind == SK_ARRAYFETCH)
2135 llassert (s1->info->field->rec != s1);
2136 if (sRef_same (s1->info->arrayfetch->arr, s2->info->arrayfetch->arr))
2138 if (s1->info->arrayfetch->indknown && s2->info->arrayfetch->indknown)
2140 return (s1->info->arrayfetch->ind == s2->info->arrayfetch->ind);
2142 return TRUE;
2145 return FALSE;
2146 case SK_FIELD:
2148 llassert (s1->info->field->rec != s1);
2149 return ((s2->kind == SK_FIELD &&
2150 (sRef_same (s1->info->field->rec, s2->info->field->rec) &&
2151 cstring_equal (s1->info->field->field, s2->info->field->field))));
2153 case SK_PTR:
2155 llassert (s1->info->ref != s1);
2156 return ((s2->kind == SK_PTR) && sRef_same (s1->info->ref, s2->info->ref));
2158 case SK_ADR:
2160 llassert (s1->info->ref != s1);
2161 return ((s2->kind == SK_ADR) && sRef_same (s1->info->ref, s2->info->ref));
2163 case SK_CONJ:
2164 llassert (s1->info->conj->a != s1);
2165 llassert (s1->info->conj->b != s1);
2166 return ((sRef_same (s1->info->conj->a, s2)) && /* or or and? */
2167 (sRef_same (s1->info->conj->b, s2)));
2168 case SK_SPECIAL:
2169 return ((s2->kind == SK_SPECIAL) && s1->info->spec == s2->info->spec);
2170 case SK_DERIVED:
2171 llassert (s1->info->ref != s1);
2172 return ((s2->kind == SK_DERIVED) && sRef_same (s1->info->ref, s2->info->ref));
2173 case SK_CONST:
2174 case SK_UNCONSTRAINED:
2175 case SK_TYPE:
2176 case SK_UNKNOWN:
2177 case SK_NEW:
2178 case SK_OBJECT:
2179 case SK_EXTERNAL:
2180 case SK_RESULT:
2181 return FALSE;
2183 BADEXIT;
2186 #ifdef DEADCODE
2188 ** sort of similar, for use in def/use
2191 static bool
2192 sRef_closeEnough (sRef s1, sRef s2)
2194 if (s1 == s2) return TRUE;
2195 if (sRef_isInvalid (s1) || sRef_isInvalid (s2)) return FALSE;
2197 switch (s1->kind)
2199 case SK_CVAR:
2200 return (((s2->kind == SK_CVAR) &&
2201 (cref_equal (s1->info->cvar, s2->info->cvar))) ||
2202 (s2->kind == SK_UNCONSTRAINED && s1->info->cvar->lexlevel == 0));
2203 case SK_UNCONSTRAINED:
2204 return (s2->kind == SK_UNCONSTRAINED
2205 || ((s2->kind == SK_CVAR) && (s2->info->cvar->lexlevel == 0)));
2206 case SK_PARAM:
2207 return ((s2->kind == SK_PARAM)
2208 && (s1->info->paramno == s2->info->paramno));
2209 case SK_ARRAYFETCH:
2210 if (s2->kind == SK_ARRAYFETCH)
2212 if (sRef_closeEnough (s1->info->arrayfetch->arr, s2->info->arrayfetch->arr))
2214 if (s1->info->arrayfetch->indknown && s2->info->arrayfetch->indknown)
2216 return (s1->info->arrayfetch->ind == s2->info->arrayfetch->ind);
2218 return TRUE;
2221 return FALSE;
2222 case SK_FIELD:
2223 return ((s2->kind == SK_FIELD &&
2224 (sRef_closeEnough (s1->info->field->rec, s2->info->field->rec) &&
2225 cstring_equal (s1->info->field->field, s2->info->field->field))));
2226 case SK_PTR:
2227 return ((s2->kind == SK_PTR) && sRef_closeEnough (s1->info->ref, s2->info->ref));
2228 case SK_ADR:
2229 return ((s2->kind == SK_ADR) && sRef_closeEnough (s1->info->ref, s2->info->ref));
2230 case SK_DERIVED:
2231 return ((s2->kind == SK_DERIVED) && sRef_closeEnough (s1->info->ref, s2->info->ref));
2232 case SK_CONJ:
2233 return ((sRef_closeEnough (s1->info->conj->a, s2)) ||
2234 (sRef_closeEnough (s1->info->conj->b, s2)));
2235 case SK_SPECIAL:
2236 return ((s2->kind == SK_SPECIAL) && s1->info->spec == s2->info->spec);
2237 case SK_TYPE:
2238 case SK_CONST:
2239 case SK_UNKNOWN:
2240 case SK_NEW:
2241 case SK_OBJECT:
2242 case SK_EXTERNAL:
2243 case SK_RESULT:
2245 return FALSE;
2247 BADEXIT;
2249 #endif
2252 drl add 12/24/2000
2253 s is an sRef of a formal paramenter in a function call constraint
2254 we trys to return a constraint expression derived from the actual parementer of a function call.
2257 /*@only@*/ constraintExpr sRef_fixConstraintParam (/*@observer@*/ sRef s, /*@observer@*/ /*@temp@*/ exprNodeList args)
2259 constraintExpr ce;
2261 if (sRef_isInvalid (s))
2262 llfatalbug((message("Invalid sRef")));
2264 switch (s->kind)
2266 case SK_RESULT:
2268 ce = constraintExpr_makeTermsRef (s);
2269 return ce;
2271 case SK_FIELD:
2273 sRef temp;
2275 temp = (sRef_makeField (sRef_fixBaseParam (s->info->field->rec, args),
2276 s->info->field->field));
2277 ce = constraintExpr_makeTermsRef (temp);
2278 return ce;
2280 case SK_PTR:
2282 sRef temp;
2283 temp = (sRef_makePointer (sRef_fixBaseParam (s->info->ref, args)));
2284 ce = constraintExpr_makeTermsRef (temp);
2285 return ce;
2288 case SK_ARRAYFETCH:
2290 sRef temp;
2291 temp = sRef_saveCopy(s);
2292 temp = sRef_fixBaseParam (temp, args);
2293 ce = constraintExpr_makeTermsRef (temp);
2295 sRef_free(temp);
2296 return ce;
2298 case SK_CVAR:
2300 sRef temp;
2301 temp = sRef_saveCopy(s);
2302 ce = constraintExpr_makeTermsRef (temp);
2303 sRef_free(temp);
2304 return ce;
2306 case SK_PARAM:
2308 exprNode e;
2309 llassert (exprNodeList_size (args) > s->info->paramno);
2310 e = exprNodeList_nth (args, s->info->paramno);
2312 llassert (!(exprNode_isError (e)));
2313 ce = constraintExpr_makeExprNode (e);
2314 return ce;
2317 default:
2319 sRef temp;
2320 llcontbug (message ("Trying to do fixConstraintParam on nonparam, nonglobal: %q for function with arguments %q",
2321 sRef_unparse (s), exprNodeList_unparse(args)));
2322 temp = sRef_saveCopy(s);
2323 ce = constraintExpr_makeTermsRef (temp);
2325 sRef_free(temp);
2326 return ce;
2331 /*@exposed@*/ sRef
2332 sRef_fixBaseParam (/*@returned@*/ sRef s, exprNodeList args)
2334 if (sRef_isInvalid (s)) return (sRef_undefined);
2336 switch (s->kind)
2338 case SK_UNCONSTRAINED:
2339 case SK_CVAR:
2340 return s;
2341 case SK_PARAM:
2343 if (exprNodeList_size (args) > s->info->paramno)
2345 exprNode e = exprNodeList_nth (args, s->info->paramno);
2347 if (exprNode_isError (e))
2349 return sRef_makeUnknown ();
2352 return (exprNode_getSref (e));
2354 else
2356 return sRef_makeUnknown ();
2359 case SK_ARRAYFETCH:
2361 if (s->info->arrayfetch->indknown)
2363 return (sRef_makeArrayFetchKnown
2364 (sRef_fixBaseParam (s->info->arrayfetch->arr, args),
2365 s->info->arrayfetch->ind));
2367 else
2369 return (sRef_makeArrayFetch
2370 (sRef_fixBaseParam (s->info->arrayfetch->arr, args)));
2372 case SK_FIELD:
2374 sRef res;
2375 DPRINTF (("Fix field: %s", sRef_unparseFull (s)));
2376 res = sRef_makeField (sRef_fixBaseParam (s->info->field->rec, args),
2377 s->info->field->field);
2378 DPRINTF (("Returns: %s", sRef_unparseFull (res)));
2379 return res;
2381 case SK_PTR:
2382 return (sRef_makePointer (sRef_fixBaseParam (s->info->ref, args)));
2384 case SK_ADR:
2385 return (sRef_makeAddress (sRef_fixBaseParam (s->info->ref, args)));
2387 case SK_CONJ:
2388 return (sRef_makeConj (sRef_fixBaseParam (s->info->conj->a, args),
2389 sRef_fixBaseParam (s->info->conj->b, args)));
2390 case SK_DERIVED:
2391 case SK_SPECIAL:
2392 case SK_TYPE:
2393 case SK_CONST:
2394 case SK_NEW:
2395 case SK_UNKNOWN:
2396 case SK_OBJECT:
2397 case SK_EXTERNAL:
2398 case SK_RESULT:
2399 return s;
2401 BADEXIT;
2404 /*@exposed@*/ sRef
2405 sRef_undumpGlobal (char **c)
2407 char p = **c;
2409 (*c)++;
2411 switch (p)
2413 case 'g':
2415 usymId uid = usymId_fromInt (reader_getInt (c));
2416 sstate defstate;
2417 nstate nullstate;
2418 sRef ret;
2420 reader_checkChar (c, '@');
2421 defstate = sstate_fromInt (reader_getInt (c));
2423 reader_checkChar (c, '@');
2424 nullstate = nstate_fromInt (reader_getInt (c));
2426 ret = sRef_makeGlobal (uid, ctype_unknown, stateInfo_currentLoc ());
2427 sRef_setNullStateN (ret, nullstate);
2428 ret->defstate = defstate;
2429 return ret;
2431 case 's':
2433 int i = reader_getInt (c);
2434 speckind sk = speckind_fromInt (i);
2436 switch (sk)
2438 case SR_NOTHING: return (sRef_makeNothing ());
2439 case SR_INTERNAL: return (sRef_makeInternalState ());
2440 case SR_SPECSTATE: return (sRef_makeSpecState ());
2441 case SR_SYSTEM: return (sRef_makeSystemState ());
2442 case SR_GLOBALMARKER: BADBRANCH;
2444 BADEXIT;
2446 case '-':
2447 return sRef_undefined;
2448 case 'u':
2449 return sRef_makeUnknown ();
2450 case 'x':
2451 return sRef_makeUnknown ();
2452 default:
2453 llfatalerror (message ("sRef_undumpGlobal: bad line: %s",
2454 cstring_fromChars (*c)));
2456 BADEXIT;
2459 static /*@exposed@*/ sRef sRef_undumpBody (char **c)
2461 char p = **c;
2463 (*c)++;
2465 switch (p)
2467 case 'g':
2468 return (sRef_makeGlobal (usymId_fromInt (reader_getInt (c)),
2469 ctype_unknown, stateInfo_currentLoc ()));
2470 case 'p':
2471 return (sRef_makeParam (reader_getInt (c), ctype_unknown,
2472 stateInfo_makeLoc (g_currentloc, SA_DECLARED)));
2473 case 'r':
2474 return (sRef_makeResult (ctype_undump (c)));
2475 case 'a':
2477 if ((**c >= '0' && **c <= '9') || **c == '-')
2479 int i = reader_getInt (c);
2480 sRef arr = sRef_undump (c);
2481 sRef ret = sRef_buildArrayFetchKnown (arr, i);
2483 return ret;
2485 else
2487 sRef arr = sRef_undump (c);
2488 sRef ret = sRef_buildArrayFetch (arr);
2490 return ret;
2493 case 'f':
2495 cstring fname = cstring_undefined;
2496 sRef ret;
2498 while (**c != '.')
2500 fname = cstring_appendChar (fname, **c);
2501 (*c)++;
2503 (*c)++;
2505 ret = sRef_buildField (sRef_undump (c), fname);
2506 cstring_markOwned (fname);
2507 return (ret);
2509 case 's':
2511 int i = reader_getInt (c);
2512 speckind sk = speckind_fromInt (i);
2514 switch (sk)
2516 case SR_NOTHING: return (sRef_makeNothing ());
2517 case SR_INTERNAL: return (sRef_makeInternalState ());
2518 case SR_SPECSTATE: return (sRef_makeSpecState ());
2519 case SR_SYSTEM: return (sRef_makeSystemState ());
2520 case SR_GLOBALMARKER: BADBRANCH;
2522 BADEXIT;
2524 case 't':
2526 sRef ptr = sRef_undump (c);
2527 sRef ret = sRef_makePointer (ptr);
2529 return (ret);
2531 case 'd':
2533 sRef adr = sRef_undump (c);
2534 sRef ret = sRef_makeAddress (adr);
2536 return (ret);
2538 case 'o':
2540 return (sRef_makeObject (ctype_undump (c)));
2542 case 'c':
2544 sRef s1 = sRef_undump (c);
2545 sRef s2 = ((*c)++, sRef_undump (c));
2546 sRef ret = sRef_makeConj (s1, s2);
2548 return (ret);
2550 case '-':
2551 return sRef_undefined;
2552 case 'u':
2553 return sRef_makeUnknown ();
2554 case 'x':
2555 return sRef_makeUnknown ();
2556 default:
2557 llfatalerror (message ("sRef_undump: bad line: %s", cstring_fromChars (*c)));
2559 BADEXIT;
2562 /*@exposed@*/ sRef sRef_undump (char **c)
2564 sRef res = sRef_undumpBody (c);
2566 if (reader_optCheckChar (c, '='))
2568 multiVal mv = multiVal_undump (c);
2569 sRef_setValue (res, mv);
2570 reader_checkChar (c, '=');
2573 return res;
2576 static /*@only@*/ cstring sRef_dumpBody (sRef s)
2578 if (sRef_isInvalid (s))
2580 return (cstring_makeLiteral ("-"));
2582 else
2584 switch (s->kind)
2586 case SK_PARAM:
2587 return (message ("p%d", s->info->paramno));
2588 case SK_ARRAYFETCH:
2589 if (s->info->arrayfetch->indknown)
2591 return (message ("a%d%q", s->info->arrayfetch->ind,
2592 sRef_dump (s->info->arrayfetch->arr)));
2594 else
2596 return (message ("a%q", sRef_dump (s->info->arrayfetch->arr)));
2598 case SK_FIELD:
2599 return (message ("f%s.%q", s->info->field->field,
2600 sRef_dump (s->info->field->rec)));
2601 case SK_PTR:
2602 return (message ("t%q", sRef_dump (s->info->ref)));
2603 case SK_ADR:
2604 return (message ("d%q", sRef_dump (s->info->ref)));
2605 case SK_OBJECT:
2606 return (message ("o%q", ctype_dump (s->info->object)));
2607 case SK_SPECIAL:
2608 return (message ("s%d", (int) s->info->spec));
2609 case SK_CONJ:
2610 return (message ("c%q.%q",
2611 sRef_dump (s->info->conj->a),
2612 sRef_dump (s->info->conj->b)));
2613 case SK_CVAR:
2614 if (sRef_isFileOrGlobalScope (s))
2616 return (message ("g%d",
2617 usymtab_convertId (s->info->cvar->index)));
2619 else
2621 llcontbug (message ("Dumping local variable: %q",
2622 sRef_unparseDebug (s)));
2623 return (cstring_makeLiteral ("u"));
2625 case SK_UNKNOWN:
2626 return (cstring_makeLiteral ("u"));
2627 case SK_RESULT:
2628 return (message ("r%q", ctype_dump (s->type)));
2629 case SK_TYPE:
2630 case SK_CONST:
2631 case SK_EXTERNAL:
2632 case SK_DERIVED:
2633 case SK_NEW:
2634 case SK_UNCONSTRAINED:
2635 llcontbug (message ("sRef_dump: bad kind: %q",
2636 sRef_unparseFull (s)));
2637 return (cstring_makeLiteral ("x"));
2641 BADEXIT;
2644 /*@only@*/ cstring sRef_dump (sRef s)
2646 cstring res = sRef_dumpBody (s);
2648 if (sRef_hasValue (s))
2650 res = message ("%q=%q=", res, multiVal_dump (sRef_getValue (s)));
2653 return res;
2656 cstring sRef_dumpGlobal (sRef s)
2658 llassert (!sRef_hasValue (s));
2660 if (sRef_isInvalid (s))
2662 return (cstring_makeLiteral ("-"));
2664 else
2666 switch (s->kind)
2668 case SK_CVAR:
2669 if (sRef_isFileOrGlobalScope (s))
2671 return (message ("g%d@%d@%d",
2672 usymtab_convertId (s->info->cvar->index),
2673 (int) s->defstate,
2674 (int) sRef_getNullState (s)));
2676 else
2678 llcontbug (message ("Dumping local variable: %q",
2679 sRef_unparseDebug (s)));
2680 return (cstring_makeLiteral ("u"));
2682 case SK_UNKNOWN:
2683 return (cstring_makeLiteral ("u"));
2684 case SK_SPECIAL:
2685 return (message ("s%d", (int) s->info->spec));
2686 default:
2687 llcontbug (message ("sRef_dumpGlobal: bad kind: %q",
2688 sRef_unparseFull (s)));
2689 return (cstring_makeLiteral ("x"));
2693 BADEXIT;
2696 ctype
2697 sRef_deriveType (sRef s, uentryList cl)
2699 if (sRef_isInvalid (s)) return ctype_unknown;
2701 switch (s->kind)
2703 case SK_CVAR:
2704 return (uentry_getType (usymtab_getRefQuiet (s->info->cvar->lexlevel,
2705 s->info->cvar->index)));
2706 case SK_UNCONSTRAINED:
2707 return (ctype_unknown);
2708 case SK_PARAM:
2709 if (s->info->paramno >= 0)
2711 return uentry_getType (uentryList_getN (cl, s->info->paramno));
2713 else
2715 return ctype_unknown;
2717 case SK_ARRAYFETCH:
2719 ctype ca = sRef_deriveType (s->info->arrayfetch->arr, cl);
2721 if (ctype_isArray (ca))
2723 return (ctype_baseArrayPtr (ca));
2725 else if (ctype_isUnknown (ca))
2727 return (ca);
2729 else
2731 llcontbuglit ("sRef_deriveType: inconsistent array type");
2732 return ca;
2735 case SK_FIELD:
2737 ctype ct = sRef_deriveType (s->info->field->rec, cl);
2739 if (ctype_isStructorUnion (ct))
2741 uentry ue = uentryList_lookupField (ctype_getFields (ct),
2742 s->info->field->field);
2744 if (uentry_isValid (ue))
2746 return (uentry_getType (ue));
2748 else
2750 llcontbuglit ("sRef_deriveType: bad field");
2751 return ctype_unknown;
2754 else if (ctype_isUnknown (ct))
2756 return (ct);
2758 else
2760 llcontbuglit ("sRef_deriveType: inconsistent field type");
2761 return (ct);
2764 case SK_PTR:
2766 ctype ct = sRef_deriveType (s->info->ref, cl);
2768 if (ctype_isUnknown (ct)) return ct;
2769 if (ctype_isPointer (ct)) return (ctype_baseArrayPtr (ct));
2770 else
2772 llcontbuglit ("sRef_deriveType: inconsistent pointer type");
2773 return (ct);
2776 case SK_ADR:
2778 ctype ct = sRef_deriveType (s->info->ref, cl);
2780 if (ctype_isUnknown (ct)) return ct;
2781 return ctype_makePointer (ct);
2783 case SK_DERIVED:
2785 return sRef_deriveType (s->info->ref, cl);
2787 case SK_OBJECT:
2789 return (s->info->object);
2791 case SK_CONJ:
2793 return (ctype_makeConj (sRef_deriveType (s->info->conj->a, cl),
2794 sRef_deriveType (s->info->conj->b, cl)));
2796 case SK_RESULT:
2797 case SK_CONST:
2798 case SK_TYPE:
2800 return (s->type);
2802 case SK_SPECIAL:
2803 case SK_UNKNOWN:
2804 case SK_EXTERNAL:
2805 case SK_NEW:
2806 return ctype_unknown;
2808 BADEXIT;
2811 ctype
2812 sRef_getType (sRef s)
2814 if (sRef_isInvalid (s)) return ctype_unknown;
2815 return s->type;
2819 /*@only@*/ cstring
2820 sRef_unparseOpt (sRef s)
2822 sRef rb = sRef_getRootBase (s);
2824 if (sRef_isMeaningful (rb) && !sRef_isConst (rb))
2826 cstring ret = sRef_unparse (s);
2828 llassertprint (!cstring_equalLit (ret, "?"), ("print: %s", sRef_unparseDebug (s)));
2830 if (!cstring_isEmpty (ret))
2832 return (cstring_appendChar (ret, ' '));
2834 else
2836 return ret;
2840 return cstring_undefined;
2843 cstring
2844 sRef_unparsePreOpt (sRef s)
2846 sRef rb = sRef_getRootBase (s);
2848 if (sRef_isMeaningful (rb) && !sRef_isConst (rb))
2850 cstring ret = sRef_unparse (s);
2852 llassertprint (!cstring_equalLit (ret, "?"), ("print: %s", sRef_unparseDebug (s)));
2853 return (cstring_prependCharO (' ', ret));
2856 return cstring_undefined;
2859 /*@only@*/ cstring
2860 sRef_unparse (sRef s)
2862 if (sRef_isInvalid (s)) return (cstring_makeLiteral ("?"));
2864 if (context_inFunctionLike ())
2866 return (sRef_unparseWithArgs (s, context_getParams ()));
2868 else
2870 DPRINTF (("Not in function like: %s", context_unparse ()));
2871 return (sRef_unparseNoArgs (s));
2875 static /*@only@*/ cstring
2876 sRef_unparseWithArgs (sRef s, uentryList args)
2878 if (sRef_isInvalid (s))
2880 return (cstring_makeLiteral ("?"));
2883 switch (s->kind)
2885 case SK_CVAR:
2886 return (uentry_getName (usymtab_getRefQuiet (s->info->cvar->lexlevel,
2887 s->info->cvar->index)));
2888 case SK_UNCONSTRAINED:
2889 return (cstring_copy (s->info->fname));
2890 case SK_PARAM:
2892 if (s->info->paramno < uentryList_size (args)
2893 && s->info->paramno >= 0)
2895 uentry ue = uentryList_getN (args, s->info->paramno);
2897 if (uentry_isValid (ue))
2898 return uentry_getName (ue);
2901 return (message ("parameter %d", s->info->paramno + 1));
2903 case SK_ARRAYFETCH:
2904 if (s->info->arrayfetch->indknown)
2906 return (message ("%q[%d]", sRef_unparseWithArgs (s->info->arrayfetch->arr, args),
2907 s->info->arrayfetch->ind));
2909 else
2911 return (message ("%q[]", sRef_unparseWithArgs (s->info->arrayfetch->arr, args)));
2913 case SK_FIELD:
2914 if (s->info->field->rec->kind == SK_PTR)
2916 sRef ptr = s->info->field->rec;
2918 return (message ("%q->%s", sRef_unparseWithArgs (ptr->info->ref, args),
2919 s->info->field->field));
2921 return (message ("%q.%s", sRef_unparseWithArgs (s->info->field->rec, args),
2922 s->info->field->field));
2924 case SK_PTR:
2926 sRef ref = sRef_fixConj (s->info->ref);
2927 skind sk = ref->kind;
2928 cstring ret;
2930 if (sk == SK_NEW)
2932 ret = message ("storage pointed to by %q",
2933 sRef_unparseWithArgs (ref, args));
2935 else if (skind_isSimple (sk) || sk == SK_PTR)
2937 ret = message ("*%q", sRef_unparseWithArgs (ref, args));
2939 else
2941 ret = message ("*(%q)", sRef_unparseWithArgs (ref, args));
2944 return ret;
2946 case SK_ADR:
2947 return (message ("&%q", sRef_unparseWithArgs (s->info->ref, args)));
2948 case SK_OBJECT:
2949 return (cstring_copy (ctype_unparse (s->info->object)));
2950 case SK_CONJ:
2951 return (sRef_unparseWithArgs (sRef_getConjA (s), args));
2952 case SK_NEW:
2953 if (cstring_isDefined (s->info->fname))
2955 return (message ("[result of %s]", s->info->fname));
2957 else
2959 return (cstring_makeLiteral ("<new>"));
2961 case SK_UNKNOWN:
2962 return (cstring_makeLiteral ("?"));
2963 case SK_DERIVED:
2964 return (message ("<derived %q>", sRef_unparse (s->info->ref)));
2965 case SK_EXTERNAL:
2966 return (message ("<external %q>", sRef_unparse (s->info->ref)));
2967 case SK_TYPE:
2968 return (message ("<type %s>", ctype_unparse (s->type)));
2969 case SK_CONST:
2970 return (message ("<const %s>", ctype_unparse (s->type)));
2971 case SK_SPECIAL:
2972 switch (s->info->spec)
2974 case SR_NOTHING: return cstring_makeLiteral ("nothing");
2975 case SR_INTERNAL: return cstring_makeLiteral ("internal state");
2976 case SR_SPECSTATE: return cstring_makeLiteral ("spec state");
2977 case SR_SYSTEM: return cstring_makeLiteral ("file system state");
2978 case SR_GLOBALMARKER: return cstring_makeLiteral ("<global marker>");
2980 BADBRANCH;
2981 case SK_RESULT:
2982 return cstring_makeLiteral ("result");
2983 default:
2985 llbug (message ("Bad sref, kind = %d", (int) s->kind));
2989 BADEXIT;
2992 /*@only@*/ cstring
2993 sRef_unparseDebug (sRef s)
2995 if (sRef_isInvalid (s))
2997 return (cstring_makeLiteral ("<undef>"));
3001 switch (s->kind)
3003 case SK_UNCONSTRAINED:
3004 return (message ("<unconstrained %s>", s->info->fname));
3005 case SK_CVAR:
3007 uentry ce;
3009 ce = usymtab_getRefQuiet (s->info->cvar->lexlevel, s->info->cvar->index);
3011 if (uentry_isInvalid (ce))
3013 return (message ("<scope: %d.%d *invalid*>",
3014 s->info->cvar->lexlevel,
3015 s->info->cvar->index));
3017 else
3019 return (message ("<scope: %d.%d *%q*>",
3020 s->info->cvar->lexlevel,
3021 s->info->cvar->index,
3022 uentry_getName (ce)));
3026 case SK_PARAM:
3028 return (message ("<parameter %d>", s->info->paramno + 1));
3030 case SK_ARRAYFETCH:
3031 if (s->info->arrayfetch->indknown)
3033 return (message ("%q[%d]", sRef_unparseDebug (s->info->arrayfetch->arr),
3034 s->info->arrayfetch->ind));
3036 else
3038 return (message ("%q[]", sRef_unparseDebug (s->info->arrayfetch->arr)));
3040 case SK_FIELD:
3041 return (message ("%q.%s", sRef_unparseDebug (s->info->field->rec),
3042 s->info->field->field));
3043 case SK_PTR:
3044 if (sRef_isField (s->info->ref))
3046 sRef fld = s->info->ref;
3048 return (message ("%q->%s", sRef_unparseDebug (fld->info->field->rec),
3049 fld->info->field->field));
3051 else
3053 return (message ("*(%q)", sRef_unparseDebug (s->info->ref)));
3055 case SK_ADR:
3056 return (message ("&%q", sRef_unparseDebug (s->info->ref)));
3057 case SK_OBJECT:
3058 return (message ("<object type %s>", ctype_unparse (s->info->object)));
3059 case SK_CONJ:
3060 return (message ("%q | %q", sRef_unparseDebug (s->info->conj->a),
3061 sRef_unparseDebug (s->info->conj->b)));
3062 case SK_NEW:
3063 return message ("<new: %s>", s->info->fname);
3064 case SK_DERIVED:
3065 return (message ("<derived %q>", sRef_unparseDebug (s->info->ref)));
3066 case SK_EXTERNAL:
3067 return (message ("<external %q>", sRef_unparseDebug (s->info->ref)));
3068 case SK_TYPE:
3069 return (message ("<type %s>", ctype_unparse (s->type)));
3070 case SK_CONST:
3071 if (sRef_hasValue (s))
3073 return (message ("<const %s=%q>", ctype_unparse (s->type), multiVal_unparse (sRef_getValue (s))));
3075 else
3077 return (message ("<const %s>", ctype_unparse (s->type)));
3079 case SK_RESULT:
3080 return (message ("<result %s>", ctype_unparse (s->type)));
3081 case SK_SPECIAL:
3082 return (message ("<spec %s>",
3083 cstring_makeLiteralTemp
3084 (s->info->spec == SR_NOTHING ? "nothing"
3085 : s->info->spec == SR_INTERNAL ? "internalState"
3086 : s->info->spec == SR_SPECSTATE ? "spec state"
3087 : s->info->spec == SR_SYSTEM ? "fileSystem"
3088 : "error")));
3089 case SK_UNKNOWN:
3090 return cstring_makeLiteral ("<unknown>");
3093 BADEXIT;
3096 static /*@only@*/ cstring
3097 sRef_unparseNoArgs (sRef s)
3099 if (sRef_isInvalid (s)) return (cstring_makeLiteral ("?"));
3101 switch (s->kind)
3103 case SK_UNCONSTRAINED:
3104 return (cstring_copy (s->info->fname));
3105 case SK_CVAR:
3107 uentry ce = usymtab_getRefQuiet (s->info->cvar->lexlevel,
3108 s->info->cvar->index);
3110 if (uentry_isInvalid (ce))
3112 llcontbug (message ("sRef_unparseNoArgs: bad cvar: %q",
3113 sRef_unparseDebug (s)));
3114 return (sRef_unparseDebug (s));
3116 else
3118 return (uentry_getName (ce));
3121 case SK_ARRAYFETCH:
3122 if (s->info->arrayfetch->indknown)
3124 return (message ("%q[%d]", sRef_unparseNoArgs (s->info->arrayfetch->arr),
3125 s->info->arrayfetch->ind));
3127 else
3129 return (message ("%q[]", sRef_unparseNoArgs (s->info->arrayfetch->arr)));
3131 case SK_FIELD:
3132 return (message ("%q.%s", sRef_unparseNoArgs (s->info->field->rec),
3133 s->info->field->field));
3134 case SK_PTR:
3136 sRef ref = sRef_fixConj (s->info->ref);
3137 skind sk = ref->kind;
3138 cstring ret;
3140 if (skind_isSimple (sk) || sk == SK_PTR)
3142 ret = message ("*%q", sRef_unparseNoArgs (ref));
3144 else
3146 ret = message ("*(%q)", sRef_unparseNoArgs (ref));
3149 return (ret);
3151 case SK_ADR:
3152 return (message ("&%q", sRef_unparseNoArgs (s->info->ref)));
3153 case SK_OBJECT:
3154 return (cstring_copy (ctype_unparse (s->info->object)));
3155 case SK_CONJ:
3156 return (sRef_unparseNoArgs (s->info->conj->a));
3157 case SK_NEW:
3158 return (message ("result of %s", s->info->fname));
3159 case SK_DERIVED:
3160 return (message ("<der %q>", sRef_unparseNoArgs (s->info->ref)));
3161 case SK_EXTERNAL:
3162 return message ("<ext %q>", sRef_unparseNoArgs (s->info->ref));
3163 case SK_SPECIAL:
3164 return (cstring_makeLiteral
3165 (s->info->spec == SR_NOTHING ? "nothing"
3166 : s->info->spec == SR_INTERNAL ? "internal state"
3167 : s->info->spec == SR_SPECSTATE ? "spec state"
3168 : s->info->spec == SR_SYSTEM ? "file system state"
3169 : "<spec error>"));
3170 case SK_RESULT:
3171 return cstring_makeLiteral ("result");
3172 case SK_CONST:
3173 case SK_TYPE:
3174 case SK_UNKNOWN:
3175 return cstring_makeLiteral ("?");
3176 case SK_PARAM:
3177 /* llcontbug (message ("sRef_unparseNoArgs: bad case: %q", sRef_unparseDebug (s))); */
3178 return (sRef_unparseDebug (s));
3180 BADEXIT;
3183 /*@dependent@*/ sRef sRef_makeUnconstrained (cstring fname)
3185 sRef s = sRef_new ();
3187 s->kind = SK_UNCONSTRAINED;
3188 s->info = (sinfo) dmalloc (sizeof (*s->info));
3189 s->info->fname = cstring_copy (fname); /* evans 2002-07-12: this was exposed, causing memory errors */
3191 return (s);
3194 cstring sRef_unconstrainedName (sRef s)
3196 llassert (sRef_isUnconstrained (s));
3198 return s->info->fname;
3201 bool sRef_isUnconstrained (sRef s)
3203 return (sRef_isReasonable(s) && s->kind == SK_UNCONSTRAINED);
3206 static /*@dependent@*/ /*@notnull@*/ sRef
3207 sRef_makeCvarAux (int level, usymId index, ctype ct, /*@only@*/ stateInfo stinfo)
3209 sRef s = sRef_newRef ();
3211 s->kind = SK_CVAR;
3212 s->info = (sinfo) dmalloc (sizeof (*s->info));
3214 s->info->cvar = (cref) dmalloc (sizeof (*s->info->cvar));
3215 s->info->cvar->lexlevel = level;
3216 s->info->cvar->index = index;
3218 /* for now, all globals are defined; all locals, aren't */
3220 if (level <= fileScope)
3222 s->defstate = SS_UNKNOWN;
3224 else
3226 ctype rct = ctype_realType (ct);
3228 if (level != paramsScope
3229 && (ctype_isStructorUnion (rct) || ctype_isRealArray (rct)))
3231 s->defstate = SS_ALLOCATED;
3232 s->oaliaskind = s->aliaskind = AK_STACK;
3234 else
3236 s->defstate = SS_UNDEFINED;
3237 s->oaliaskind = s->aliaskind = AK_LOCAL;
3241 s->type = ct;
3243 llassert (level >= globScope);
3244 llassert (usymId_isValid (index));
3246 DPRINTF (("Made cvar: [%p] %s", s, sRef_unparseDebug (s)));
3247 llassert (valueTable_isUndefined (s->state));
3248 s->state = context_createValueTable (s, stinfo);
3249 return s;
3252 /*@dependent@*/ sRef sRef_makeCvar (int level, usymId index, ctype ct, /*@only@*/ stateInfo stinfo)
3254 return (sRef_makeCvarAux (level, index, ct, stinfo));
3257 int sRef_lexLevel (sRef s)
3259 if (sRef_isReasonable (s))
3261 sRef conj;
3263 conj = sRef_fixConj (s);
3264 s = sRef_getRootBase (conj);
3266 if (sRef_isReasonable (s) && s->kind == SK_CVAR)
3268 return (s->info->cvar->lexlevel);
3272 return globScope;
3275 sRef
3276 sRef_makeGlobal (usymId l, ctype ct, /*@only@*/ stateInfo stinfo)
3278 return (sRef_makeCvar (globScope, l, ct, stinfo));
3281 void
3282 sRef_setParamNo (sRef s, int l)
3284 llassert (sRef_isReasonable (s) && s->kind == SK_PARAM);
3285 s->info->paramno = l;
3286 llassert (l >= -1);
3289 /*@dependent@*/ sRef
3290 sRef_makeParam (int l, ctype ct, stateInfo stinfo)
3292 sRef s = sRef_new ();
3294 s->kind = SK_PARAM;
3295 s->type = ct;
3297 s->info = (sinfo) dmalloc (sizeof (*s->info));
3298 s->info->paramno = l;
3299 llassert (l >= -1);
3300 s->defstate = SS_UNKNOWN;
3301 /* (probably defined, unless its an out parameter) */
3303 llassert (valueTable_isUndefined (s->state));
3304 s->state = context_createValueTable (s, stinfo);
3305 return s;
3308 bool
3309 sRef_isIndexKnown (sRef arr)
3311 bool res;
3313 llassert (sRef_isReasonable (arr));
3314 arr = sRef_fixConj (arr);
3316 llassert (arr->kind == SK_ARRAYFETCH);
3317 res = arr->info->arrayfetch->indknown;
3318 return (res);
3322 sRef_getIndex (sRef arr)
3324 int result;
3326 llassert (sRef_isReasonable (arr));
3327 arr = sRef_fixConj (arr);
3329 llassert (arr->kind == SK_ARRAYFETCH);
3331 if (!arr->info->arrayfetch->indknown)
3333 llcontbug (message ("sRef_getIndex: unknown: %q", sRef_unparse (arr)));
3334 result = 0;
3336 else
3338 result = arr->info->arrayfetch->ind;
3341 return result;
3344 static bool sRef_isZerothArrayFetch (/*@notnull@*/ sRef s)
3346 return (s->kind == SK_ARRAYFETCH
3347 && s->info->arrayfetch->indknown
3348 && (s->info->arrayfetch->ind == 0));
3351 /*@exposed@*/ sRef sRef_makeAddress (/*@exposed@*/ sRef t)
3354 if (sRef_isInvalid (t)) return sRef_undefined;
3356 if (sRef_isPointer (t))
3358 return (t->info->ref);
3360 else if (sRef_isZerothArrayFetch (t))
3362 return (t->info->arrayfetch->arr);
3364 else
3366 sRef s = sRef_newRef ();
3368 s->kind = SK_ADR;
3369 s->type = ctype_makePointer (t->type);
3370 s->info = (sinfo) dmalloc (sizeof (*s->info));
3371 s->info->ref = t;
3373 if (t->defstate == SS_UNDEFINED)
3374 /* no! it is allocated even still: && !ctype_isPointer (t->type)) */
3376 s->defstate = SS_ALLOCATED;
3378 else
3380 s->defstate = t->defstate;
3383 if (t->aliaskind == AK_LOCAL)
3385 if (sRef_isLocalVar (t))
3387 s->aliaskind = AK_STACK;
3391 llassert (valueTable_isUndefined (s->state));
3392 s->state = context_createValueTable (s,
3393 stateInfo_makeLoc (g_currentloc, SA_CREATED));
3394 return s;
3398 cstring sRef_getField (sRef s)
3400 cstring res;
3402 llassert (sRef_isReasonable (s));
3403 s = sRef_fixConj (s);
3405 llassertprint (sRef_isReasonable (s) && (s->kind == SK_FIELD),
3406 ("s = %s", sRef_unparseDebug (s)));
3408 res = s->info->field->field;
3409 return (res);
3412 sRef sRef_getBase (sRef s)
3414 sRef res;
3416 if (sRef_isInvalid (s)) return (sRef_undefined);
3418 s = sRef_fixConj (s);
3420 switch (s->kind)
3422 case SK_ADR:
3423 case SK_PTR:
3424 case SK_DERIVED:
3425 case SK_EXTERNAL:
3426 res = s->info->ref;
3427 break;
3428 case SK_FIELD:
3429 res = s->info->field->rec;
3430 break;
3432 case SK_ARRAYFETCH:
3433 res = s->info->arrayfetch->arr;
3434 break;
3436 default:
3437 res = sRef_undefined; /* shouldn't need it */
3440 return (res);
3444 ** same as getBase, except returns invalid
3445 ** (and doesn't use adr's)
3448 sRef
3449 sRef_getBaseSafe (sRef s)
3451 sRef res;
3453 if (sRef_isInvalid (s)) { return sRef_undefined; }
3455 s = sRef_fixConj (s);
3457 switch (s->kind)
3459 case SK_PTR:
3460 res = s->info->ref;
3461 break;
3462 case SK_FIELD:
3463 res = s->info->field->rec; break;
3464 case SK_ARRAYFETCH:
3465 res = s->info->arrayfetch->arr;
3466 break;
3467 default:
3468 res = sRef_undefined; break;
3471 return res;
3474 /*@constant int MAXBASEDEPTH;@*/
3475 # define MAXBASEDEPTH 25
3477 static /*@exposed@*/ sRef
3478 sRef_getRootBaseAux (sRef s, int depth)
3480 if (sRef_isInvalid (s)) return sRef_undefined;
3482 if (depth > MAXBASEDEPTH)
3484 llgenmsg (message
3485 ("Warning: reference base limit exceeded for %q. "
3486 "This either means there is a variable with at least "
3487 "%d indirections from this reference, or "
3488 "there is a bug in Splint.",
3489 sRef_unparse (s),
3490 MAXBASEDEPTH),
3491 g_currentloc);
3493 return sRef_undefined;
3496 switch (s->kind)
3498 case SK_ADR:
3499 case SK_PTR:
3500 return (sRef_getRootBaseAux (s->info->ref, depth + 1));
3501 case SK_FIELD:
3502 return (sRef_getRootBaseAux (s->info->field->rec, depth + 1));
3503 case SK_ARRAYFETCH:
3504 return (sRef_getRootBaseAux (s->info->arrayfetch->arr, depth + 1));
3505 case SK_CONJ:
3506 return (sRef_getRootBaseAux (sRef_fixConj (s), depth + 1));
3507 default:
3508 return s;
3512 sRef sRef_getRootBase (sRef s)
3514 return (sRef_getRootBaseAux (s, 0));
3517 static bool sRef_isDeep (sRef s)
3519 if (sRef_isInvalid (s)) return FALSE;
3521 switch (s->kind)
3523 case SK_ADR:
3524 case SK_PTR:
3525 case SK_FIELD:
3526 case SK_ARRAYFETCH:
3527 return TRUE;
3528 case SK_CONJ:
3529 return (sRef_isDeep (sRef_fixConj (s)));
3530 default:
3531 return FALSE;
3535 static int sRef_depth (sRef s)
3537 if (sRef_isInvalid (s)) return 0;
3539 switch (s->kind)
3541 case SK_ADR:
3542 case SK_PTR:
3543 case SK_DERIVED:
3544 case SK_EXTERNAL:
3545 return 1 + sRef_depth (s->info->ref);
3546 case SK_FIELD:
3547 return 1 + sRef_depth (s->info->field->rec);
3548 case SK_ARRAYFETCH:
3549 return 1 + sRef_depth (s->info->arrayfetch->arr);
3550 case SK_CONJ:
3551 return (sRef_depth (sRef_fixConj (s)));
3552 default:
3553 return 1;
3557 sRef
3558 sRef_makeObject (ctype o)
3560 sRef s = sRef_newRef ();
3562 s->kind = SK_OBJECT;
3563 s->info = (sinfo) dmalloc (sizeof (*s->info));
3564 s->info->object = o;
3565 llassert (valueTable_isUndefined (s->state));
3566 s->state = context_createValueTable (s, stateInfo_makeLoc (g_currentloc, SA_CREATED));
3567 return s;
3571 ** This is used to represent storage referenced by a parameter.
3574 sRef sRef_makeExternal (sRef t)
3576 sRef s = sRef_newRef ();
3578 llassert (sRef_isReasonable (t));
3580 s->kind = SK_EXTERNAL;
3581 s->info = (sinfo) dmalloc (sizeof (*s->info));
3582 s->type = t->type;
3583 s->info->ref = t;
3584 llassert (valueTable_isUndefined (s->state));
3585 s->state = context_createValueTable (s, stateInfo_makeLoc (g_currentloc, SA_DECLARED));
3586 return s;
3589 /*@dependent@*/ sRef sRef_makeDerived (/*@exposed@*/ sRef t)
3591 if (sRef_isReasonable (t))
3593 sRef s = sRef_newRef ();
3595 s->kind = SK_DERIVED;
3596 s->info = (sinfo) dmalloc (sizeof (*s->info));
3597 s->info->ref = t;
3599 s->type = t->type;
3600 llassert (valueTable_isUndefined (s->state));
3601 s->state = context_createValueTable (s, stateInfo_makeLoc (g_currentloc, SA_CREATED));
3602 return s;
3604 else
3606 return sRef_undefined;
3611 ** definitely NOT symmetric:
3613 ** res fills in unknown state information from other
3616 void
3617 sRef_mergeStateQuiet (sRef res, sRef other)
3619 llassert (sRef_isReasonable (res));
3620 llassert (sRef_isReasonable (other));
3622 res->modified = res->modified || other->modified;
3623 res->safe = res->safe && other->safe;
3625 if (res->defstate == SS_UNKNOWN)
3627 res->defstate = other->defstate;
3628 res->definfo = stateInfo_update (res->definfo, other->definfo);
3631 if (res->aliaskind == AK_UNKNOWN ||
3632 (res->aliaskind == AK_LOCAL && alkind_isKnown (other->aliaskind)))
3634 res->aliaskind = other->aliaskind;
3635 res->oaliaskind = other->oaliaskind;
3636 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
3639 if (res->expkind == XO_UNKNOWN)
3641 res->expkind = other->expkind;
3642 res->oexpkind = other->oexpkind;
3643 res->expinfo = stateInfo_update (res->expinfo, other->expinfo);
3646 /* out takes precedence over implicitly defined */
3647 if (res->defstate == SS_DEFINED && other->defstate != SS_UNKNOWN)
3649 res->defstate = other->defstate;
3650 res->definfo = stateInfo_update (res->definfo, other->definfo);
3653 if (sRef_getNullState (other) == NS_ERROR || sRef_getNullState (res) == NS_ERROR)
3655 sRef_setNullState (res, NS_ERROR, fileloc_undefined);
3657 else
3659 if (sRef_getNullState (other) != NS_UNKNOWN
3660 && (sRef_getNullState (res) == NS_UNKNOWN || sRef_getNullState (res) == NS_NOTNULL
3661 || sRef_getNullState (res) == NS_MNOTNULL))
3663 sRef_updateNullState (res, other);
3669 ** definitely NOT symmetric:
3671 ** res fills in known state information from other
3674 void
3675 sRef_mergeStateQuietReverse (/*@dependent@*/ sRef res, /*@dependent@*/ sRef other)
3677 bool changed = FALSE;
3679 llassert (sRef_isReasonable (res));
3680 llassert (sRef_isReasonable (other));
3681 sRef_checkMutable (res);
3683 if (res->kind != other->kind)
3685 changed = TRUE;
3687 sinfo_free (res);
3689 res->kind = other->kind;
3690 res->type = other->type;
3691 res->info = sinfo_fullCopy (other);
3693 else
3695 if (!ctype_equal (res->type, other->type))
3697 changed = TRUE;
3698 res->type = other->type;
3701 sinfo_update (res, other);
3704 res->modified = res->modified || other->modified;
3705 res->safe = res->safe && other->safe;
3707 if (res->aliaskind != other->aliaskind
3708 && (res->aliaskind == AK_UNKNOWN
3709 || ((res->aliaskind == AK_LOCAL
3710 || (res->aliaskind == AK_REFCOUNTED
3711 && other->aliaskind != AK_LOCAL))
3712 && other->aliaskind != AK_UNKNOWN)))
3714 changed = TRUE;
3715 res->aliaskind = other->aliaskind;
3716 res->oaliaskind = other->oaliaskind;
3717 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
3720 if (other->expkind != XO_UNKNOWN && other->expkind != res->expkind)
3722 changed = TRUE;
3723 res->expkind = other->expkind;
3724 res->expinfo = stateInfo_update (res->expinfo, other->expinfo);
3727 if (other->oexpkind != XO_UNKNOWN)
3729 res->oexpkind = other->oexpkind;
3732 /* out takes precedence over implicitly defined */
3734 if (res->defstate != other->defstate)
3736 if (other->defstate != SS_UNKNOWN)
3738 res->defstate = other->defstate;
3739 res->definfo = stateInfo_update (res->definfo, other->definfo);
3743 if (sRef_getNullState (other) == NS_ERROR || sRef_getNullState (res) == NS_ERROR)
3745 if (sRef_getNullState (res) != NS_ERROR)
3747 sRef_setNullStateN (res, NS_ERROR);
3748 changed = TRUE;
3751 else
3753 if (sRef_getNullState (other) != NS_UNKNOWN
3754 && sRef_getNullState (other) != sRef_getNullState (res))
3756 changed = TRUE;
3757 sRef_updateNullState (res, other);
3761 if (changed)
3763 sRef_clearDerived (res);
3767 void
3768 sRef_mergeState (sRef res, sRef other, clause cl, fileloc loc)
3770 if (sRef_isReasonable (res) && sRef_isReasonable (other))
3772 sRef_mergeStateAux (res, other, cl, FALSE, loc, TRUE);
3774 else
3776 if (sRef_isInvalid (res))
3778 llbug (message ("sRef_mergeState: invalid res sRef: %q",
3779 sRef_unparseDebug (other)));
3781 else
3783 llbug (message ("sRef_mergeState: invalid other sRef: %q",
3784 sRef_unparseDebug (res)));
3789 void
3790 sRef_mergeOptState (sRef res, sRef other, clause cl, fileloc loc)
3792 if (sRef_isReasonable (res) && sRef_isReasonable (other))
3794 sRef_mergeStateAux (res, other, cl, TRUE, loc, TRUE);
3796 else
3798 if (sRef_isInvalid (res))
3800 llbug (message ("sRef_mergeOptState: invalid res sRef: %q",
3801 sRef_unparseDebug (other)));
3803 else
3805 llbug (message ("sRef_mergeOptState: invalid other sRef: %q",
3806 sRef_unparseDebug (res)));
3811 static void
3812 sRef_mergeStateAux (/*@notnull@*/ sRef res, /*@notnull@*/ sRef other,
3813 clause cl, bool opt, fileloc loc,
3814 bool doDerivs)
3815 /*@modifies res@*/
3817 llassertfatal (sRef_isReasonable (res));
3818 llassertfatal (sRef_isReasonable (other));
3820 DPRINTF (("Merge aux: %s / %s",
3821 sRef_unparseFull (res),
3822 sRef_unparseFull (other)));
3824 sRef_checkMutable (res);
3825 sRef_checkMutable (other);
3827 res->modified = res->modified || other->modified;
3829 if (res->kind == other->kind
3830 || (other->kind == SK_UNKNOWN || res->kind == SK_UNKNOWN))
3832 sstate odef = other->defstate;
3833 sstate rdef = res->defstate;
3834 nstate onull = sRef_getNullState (other);
3837 ** yucky stuff to handle
3839 ** if (s) free (s);
3842 if (other->defstate == SS_DEAD
3843 && ((sRef_isOnly (res) && sRef_definitelyNull (res))
3844 || (res->defstate == SS_UNDEFINED
3845 || res->defstate == SS_UNUSEABLE)))
3847 if (res->defstate == SS_UNDEFINED
3848 || res->defstate == SS_UNUSEABLE)
3850 res->defstate = SS_UNUSEABLE;
3852 else
3854 res->defstate = SS_DEAD;
3857 res->definfo = stateInfo_update (res->definfo, other->definfo);
3858 sRef_clearDerived (other);
3859 sRef_clearDerived (res);
3861 else if (res->defstate == SS_DEAD
3862 && ((sRef_isOnly (other) && sRef_definitelyNull (other))
3863 || (other->defstate == SS_UNDEFINED
3864 || other->defstate == SS_UNUSEABLE)))
3866 if (other->defstate == SS_UNDEFINED
3867 || other->defstate == SS_UNUSEABLE)
3869 res->defstate = SS_UNUSEABLE;
3871 else
3873 res->defstate = SS_DEAD;
3876 res->definfo = stateInfo_update (res->definfo, other->definfo);
3877 sRef_clearDerived (other);
3878 sRef_clearDerived (res);
3880 else if (res->defstate == SS_DEFINED
3881 && (other->defstate == SS_ALLOCATED
3882 && sRef_definitelyNull (other)))
3884 other->defstate = SS_DEFINED; /* definitely null! */
3886 else if (other->defstate == SS_DEFINED
3887 && (res->defstate == SS_ALLOCATED && sRef_definitelyNull (res)))
3889 res->defstate = SS_DEFINED;
3890 res->definfo = stateInfo_update (res->definfo, other->definfo);
3892 else
3894 ; /* okay */
3897 if (res->defstate == SS_DEAD && other->defstate == SS_DEAD)
3899 sRef_clearDerived (other);
3900 sRef_clearDerived (res);
3904 ** only & dead isn't really an only!
3907 if (alkind_isOnly (other->aliaskind) && other->defstate == SS_DEAD)
3909 other->aliaskind = AK_UNKNOWN;
3912 if (alkind_isOnly (res->aliaskind) && res->defstate == SS_DEAD)
3914 res->aliaskind = AK_UNKNOWN;
3918 ** Dead and dependent -> dead
3921 if (alkind_isDependent (other->aliaskind) && res->defstate == SS_DEAD)
3923 other->aliaskind = AK_UNKNOWN;
3924 other->defstate = SS_DEAD;
3925 sRef_clearDerived (res);
3926 sRef_clearDerived (other);
3929 if (alkind_isDependent (res->aliaskind) && other->defstate == SS_DEAD)
3931 res->aliaskind = AK_UNKNOWN;
3932 res->defstate = SS_DEAD;
3933 sRef_clearDerived (res);
3934 sRef_clearDerived (other);
3938 ** must do alias combine first, since it depends on
3939 ** original values of state and null.
3942 sRef_combineAliasKinds (res, other, cl, loc);
3943 sRef_combineDefState (res, other);
3944 sRef_combineNullState (res, other);
3946 if (rdef == SS_ALLOCATED || rdef == SS_SPECIAL)
3948 if (odef == SS_DEFINED)
3950 if (onull == NS_DEFNULL || onull == NS_CONSTNULL)
3952 res->deriv = sRefSet_copyInto (res->deriv, other->deriv);
3953 DPRINTF (("Copy derivs: %s", sRef_unparseFull (res)));
3956 else if (odef == SS_ALLOCATED || odef == SS_SPECIAL)
3959 if (doDerivs)
3961 if (ctype_isUnion (ctype_realType (sRef_getType (res))))
3963 res->deriv = sRef_mergeUnionDerivs (res->deriv,
3964 other->deriv,
3965 opt, cl, loc);
3966 DPRINTF (("Copy derivs: %s", sRef_unparseFull (res)));
3968 else
3970 res->deriv = sRef_mergeDerivs (res->deriv, other->deriv,
3971 opt, cl, loc);
3972 DPRINTF (("Copy derivs: %s", sRef_unparseFull (res)));
3976 else
3978 if (doDerivs)
3980 res->deriv = sRef_mergeDerivs (res->deriv, other->deriv,
3981 opt, cl, loc);
3982 DPRINTF (("Copy derivs: %s", sRef_unparseFull (res)));
3984 else
3990 else
3992 if (rdef == SS_PDEFINED
3993 || (rdef == SS_DEFINED && odef == SS_PDEFINED))
3995 if (doDerivs)
3997 res->deriv = sRef_mergePdefinedDerivs (res->deriv, other->deriv,
3998 opt, cl, loc);
3999 DPRINTF (("Copy derivs: %s", sRef_unparseFull (res)));
4002 else
4004 if ((rdef == SS_DEFINED || rdef == SS_UNKNOWN)
4005 && res->defstate == SS_ALLOCATED)
4007 res->deriv = sRefSet_copyInto (res->deriv, other->deriv);
4009 else
4011 if (doDerivs)
4013 res->deriv = sRef_mergeDerivs (res->deriv, other->deriv,
4014 opt, cl, loc);
4015 DPRINTF (("Copy derivs: %s", sRef_unparseFull (res)));
4022 sRef_combineExKinds (res, other);
4024 else
4026 if (res->kind == SK_ARRAYFETCH && other->kind == SK_PTR)
4028 sRef nother = sRef_buildArrayFetchKnown (sRef_getBase (other), 0);
4030 sRef_copyState (nother, other);
4031 sRef_mergeStateAux (res, nother, cl, opt, loc, doDerivs);
4033 else if (res->kind == SK_PTR && other->kind == SK_ARRAYFETCH)
4035 sRef nother = sRef_buildPointer (sRef_getBase (other));
4037 if (sRef_isReasonable (nother))
4039 sRef_copyState (nother, other);
4040 sRef_mergeStateAux (res, nother, cl, opt, loc, doDerivs);
4043 else
4045 llcontbug (message ("merge conj: %q / %q", sRef_unparseFull (res),
4046 sRef_unparseFull (other)));
4052 ** Merge value table states
4055 # if 0
4057 ** This doesn't do anything. And its broken too...
4060 valueTable_elements (res->state, key, sv)
4062 stateValue os = valueTable_lookup (other->state, key);
4063 /*@unused@*/ int val;
4064 /*@unused@*/ char *msg;
4066 llassert (stateValue_isDefined (os));
4068 DPRINTF (("Merge state: %s / %s",
4069 cstring_toCharsSafe (stateValue_unparse (sv)),
4070 cstring_toCharsSafe (stateValue_unparse (os))));
4072 val = valueMatix_lookup (key,
4073 stateValue_getValue (os),
4074 stateValue_getValue (sv),
4075 &msg);
4076 DPRINTF (("Val: %d / %s", val, msg));
4078 } end_valueTable_elements ;
4079 # endif
4081 DPRINTF (("Merge aux: %s / %s",
4082 sRef_unparseFull (res),
4083 sRef_unparseFull (other)));
4086 static sRefSet
4087 sRef_mergeUnionDerivs (/*@only@*/ sRefSet res,
4088 /*@exposed@*/ sRefSet other, bool opt,
4089 clause cl, fileloc loc)
4091 if (sRefSet_isEmpty (res))
4093 return sRefSet_copyInto (res, other);
4095 else
4097 sRefSet_allElements (other, el)
4099 if (sRef_isReasonable (el))
4101 sRef e2 = sRefSet_lookupMember (other, el);
4103 if (sRef_isReasonable (e2))
4105 sRef_mergeStateAux (el, e2, cl, opt, loc, FALSE);
4107 else
4109 res = sRefSet_insert (res, el);
4112 } end_sRefSet_allElements ;
4114 return res;
4118 static /*@only@*/ sRefSet
4119 sRef_mergeDerivs (/*@only@*/ sRefSet res, sRefSet other,
4120 bool opt, clause cl, fileloc loc)
4122 sRefSet ret = sRefSet_new ();
4124 sRefSet_allElements (res, el)
4126 if (sRef_isReasonable (el))
4128 sRef e2 = sRefSet_lookupMember (other, el);
4130 if (sRef_isReasonable (e2))
4132 if (el->defstate == SS_ALLOCATED &&
4133 e2->defstate == SS_PDEFINED)
4135 e2->defstate = SS_ALLOCATED;
4137 else if (e2->defstate == SS_ALLOCATED &&
4138 el->defstate == SS_PDEFINED)
4140 el->defstate = SS_ALLOCATED;
4141 el->definfo = stateInfo_update (el->definfo, e2->definfo);
4142 sRef_clearDerived (el);
4144 else if ((el->defstate == SS_DEAD || sRef_isKept (el)) &&
4145 (e2->defstate == SS_DEFINED && !sRef_isKept (e2)))
4147 DPRINTF (("Checking dead: %s / %s", sRef_unparseFull (el),
4148 sRef_unparseFull (e2)));
4150 if (checkDeadState (el, e2, TRUE, loc))
4152 if (sRef_isThroughArrayFetch (el))
4154 sRef_maybeKill (el, loc);
4155 sRef_maybeKill (e2, loc);
4159 else if ((e2->defstate == SS_DEAD || sRef_isKept (e2)) &&
4160 (el->defstate == SS_DEFINED && !sRef_isKept (el)))
4162 DPRINTF (("Checking dead: %s / %s", sRef_unparseFull (el),
4163 sRef_unparseFull (e2)));
4165 if (checkDeadState (e2, el, FALSE, loc))
4167 if (sRef_isThroughArrayFetch (el))
4169 sRef_maybeKill (el, loc);
4170 sRef_maybeKill (e2, loc);
4174 else if (el->defstate == SS_DEFINED &&
4175 e2->defstate == SS_PDEFINED)
4177 DPRINTF (("set pdefined: %s", sRef_unparseFull (el)));
4178 el->defstate = SS_PDEFINED;
4179 el->definfo = stateInfo_update (el->definfo, e2->definfo);
4181 else if (e2->defstate == SS_DEFINED &&
4182 el->defstate == SS_PDEFINED)
4184 DPRINTF (("set pdefined: %s", sRef_unparseFull (e2)));
4185 e2->defstate = SS_PDEFINED;
4186 e2->definfo = stateInfo_update (e2->definfo, el->definfo);
4188 else
4190 ; /* okay */
4193 if (ctype_isUnion (ctype_realType (sRef_getType (el))))
4195 el->deriv = sRef_mergeUnionDerivs (el->deriv, e2->deriv,
4196 opt, cl, loc);
4198 else
4200 el->deriv = sRef_mergeDerivs (el->deriv, e2->deriv, opt, cl, loc);
4203 if (sRef_equivalent (el, e2))
4205 ret = sRefSet_insert (ret, el);
4207 else
4209 sRef sr = sRef_leastCommon (el, e2);
4211 if (sRef_isReasonable (sr))
4213 ret = sRefSet_insert (ret, sr);
4215 else
4221 (void) sRefSet_delete (other, e2);
4223 else /* not defined */
4225 DPRINTF (("Checking dead: %s", sRef_unparseFull (el)));
4226 (void) checkDeadState (el, e2, TRUE, loc);
4229 } end_sRefSet_allElements;
4231 sRefSet_allElements (other, el)
4233 if (sRef_isReasonable (el))
4235 DPRINTF (("Checking dead: %s", sRef_unparseFull (el)));
4236 (void) checkDeadState (el, sRef_undefined, FALSE, loc);
4238 } end_sRefSet_allElements;
4240 sRefSet_free (res);
4241 return (ret);
4245 ** Returns TRUE is there is an error.
4248 static bool checkDeadState (/*@notnull@*/ sRef el, sRef e2, bool tbranch, fileloc loc)
4251 ** usymtab_isGuarded --- the utab should still be in the
4252 ** state of the alternate branch.
4254 ** tbranch TRUE means el is released in the last branch, e.g.
4255 ** if (x != NULL) { ; } else { sfree (x); }
4256 ** so, if x is null in the other branch no error is reported.
4258 ** tbranch FALSE means this is the other branch:
4259 ** if (x != NULL) { sfree (x); } else { ; }
4260 ** so, if x is null in this branch there is no error.
4264 if ((sRef_isDead (el) || sRef_isKept (el))
4265 && !sRef_isDeepUnionField (el)
4266 && !sRef_isThroughArrayFetch (el))
4269 if (!tbranch)
4271 if (usymtab_isDefinitelyNullDeep (el))
4273 return TRUE;
4276 else
4278 if (usymtab_isAltDefinitelyNullDeep (el))
4280 return TRUE;
4284 if (optgenerror
4285 (FLG_BRANCHSTATE,
4286 message ("Storage %q is %q in one path, but live in another.",
4287 sRef_unparse (el),
4288 cstring_makeLiteral (sRef_isKept (el)
4289 ? "kept" : "released")),
4290 loc))
4292 if (sRef_isKept (el))
4294 sRef_showAliasInfo (el);
4296 else
4298 sRef_showStateInfo (el);
4301 if (sRef_isValid (e2))
4303 if (sRef_isKept (e2))
4305 sRef_showAliasInfo (e2);
4307 else
4309 sRef_showStateInfo (e2);
4313 /* prevent further errors */
4314 el->defstate = SS_UNKNOWN;
4315 sRef_setAliasKind (el, AK_ERROR, fileloc_undefined);
4316 return FALSE;
4320 return TRUE;
4323 static void
4324 checkDerivDeadState (/*@notnull@*/ sRef el, bool tbranch, fileloc loc)
4326 if (checkDeadState (el, sRef_undefined, tbranch, loc))
4328 sRefSet_allElements (el->deriv, t)
4330 if (sRef_isReasonable (t))
4332 checkDerivDeadState (t, tbranch, loc);
4334 } end_sRefSet_allElements;
4338 static sRefSet
4339 sRef_mergePdefinedDerivs (sRefSet res, sRefSet other, bool opt,
4340 clause cl, fileloc loc)
4342 sRefSet ret = sRefSet_new ();
4344 sRefSet_allElements (res, el)
4346 if (sRef_isReasonable (el))
4348 sRef e2 = sRefSet_lookupMember (other, el);
4350 if (sRef_isReasonable (e2))
4352 if (sRef_isAllocated (el) && !sRef_isAllocated (e2))
4356 else if (sRef_isAllocated (e2) && !sRef_isAllocated (el))
4358 el->deriv = sRefSet_copyInto (el->deriv, e2->deriv);
4360 else
4362 el->deriv = sRef_mergePdefinedDerivs (el->deriv, e2->deriv,
4363 opt, cl, loc);
4366 sRef_mergeStateAux (el, e2, cl, opt, loc, FALSE);
4368 ret = sRefSet_insert (ret, el);
4369 (void) sRefSet_delete (other, e2);
4371 else
4373 if (!opt)
4375 checkDerivDeadState (el, (cl == FALSECLAUSE), loc);
4378 ret = sRefSet_insert (ret, el);
4381 } end_sRefSet_allElements;
4383 sRefSet_allElements (other, el)
4385 if (sRef_isReasonable (el))
4387 if (!sRefSet_member (ret, el))
4389 /* was cl == FALSECLAUSE */
4390 checkDerivDeadState (el, FALSE, loc);
4391 ret = sRefSet_insert (ret, el);
4393 else
4396 ** it's okay --- member is a different equality test
4400 } end_sRefSet_allElements;
4402 sRefSet_free (res);
4403 return (ret);
4406 sRef sRef_makeConj (/*@exposed@*/ /*@returned@*/ sRef a, /*@exposed@*/ sRef b)
4408 llassert (sRef_isReasonable (a));
4409 llassert (sRef_isReasonable (b));
4411 if (!sRef_equivalent (a, b))
4413 sRef s = sRef_newRef ();
4415 s->kind = SK_CONJ;
4416 s->info = (sinfo) dmalloc (sizeof (*s->info));
4417 s->info->conj = (cjinfo) dmalloc (sizeof (*s->info->conj));
4418 s->info->conj->a = a;
4419 s->info->conj->b = b;
4421 if (ctype_equal (a->type, b->type)) s->type = a->type;
4422 else s->type = ctype_makeConj (a->type, b->type);
4424 if (a->defstate == b->defstate)
4426 s->defstate = a->defstate;
4427 s->definfo = stateInfo_update (s->definfo, a->definfo);
4428 s->definfo = stateInfo_update (s->definfo, b->definfo);
4430 else
4432 s->defstate = SS_UNKNOWN;
4435 sRef_setNullStateN (s, NS_UNKNOWN);
4437 s->safe = a->safe && b->safe;
4438 s->aliaskind = alkind_resolve (a->aliaskind, b->aliaskind);
4440 llassert (valueTable_isUndefined (s->state));
4441 s->state = context_createValueTable (s, stateInfo_makeLoc (g_currentloc, SA_MERGED));
4442 return s;
4444 else
4446 /*@-exposetrans@*/ return a; /*@=exposetrans@*/
4450 /*@dependent@*/ sRef
4451 sRef_makeUnknown (void)
4453 sRef s = sRef_new ();
4455 s->kind = SK_UNKNOWN;
4456 return s;
4459 static /*@owned@*/ /*@notnull@*/ sRef
4460 sRef_makeSpecial (speckind sk) /*@*/
4462 sRef s = sRef_new ();
4464 s->kind = SK_SPECIAL;
4465 s->info = (sinfo) dmalloc (sizeof (*s->info));
4466 s->info->spec = sk;
4467 /*@-dependenttrans@*/
4468 return s;
4469 /*@=dependenttrans@*/
4472 static /*@owned@*/ sRef srnothing = sRef_undefined;
4473 static /*@owned@*/ sRef srinternal = sRef_undefined;
4474 static /*@owned@*/ sRef srsystem = sRef_undefined;
4475 static /*@owned@*/ sRef srspec = sRef_undefined;
4477 /*@dependent@*/ sRef
4478 sRef_makeNothing (void)
4480 if (sRef_isInvalid (srnothing))
4482 srnothing = sRef_makeSpecial (SR_NOTHING);
4485 return srnothing;
4488 sRef
4489 sRef_makeInternalState (void)
4491 if (sRef_isInvalid (srinternal))
4493 srinternal = sRef_makeSpecial (SR_INTERNAL);
4496 return srinternal;
4499 sRef
4500 sRef_makeSpecState (void)
4502 if (sRef_isInvalid (srspec))
4504 srspec = sRef_makeSpecial (SR_SPECSTATE);
4507 return srspec;
4510 sRef
4511 sRef_makeSystemState (void)
4513 if (sRef_isInvalid (srsystem))
4515 srsystem = sRef_makeSpecial (SR_SYSTEM);
4518 return srsystem;
4521 sRef
4522 sRef_makeGlobalMarker (void)
4524 sRef s = sRef_makeSpecial (SR_GLOBALMARKER);
4525 llassert (valueTable_isUndefined (s->state));
4526 s->state = context_createGlobalMarkerValueTable (stateInfo_undefined);
4527 return s;
4530 sRef
4531 sRef_makeResult (ctype c)
4533 sRef s = sRef_newRef ();
4535 s->kind = SK_RESULT;
4536 s->type = c;
4537 s->defstate = SS_UNKNOWN;
4538 s->aliaskind = AK_UNKNOWN;
4539 sRef_setNullStateN (s, NS_UNKNOWN);
4540 llassert (valueTable_isUndefined (s->state));
4541 s->state = context_createValueTable (s, stateInfo_makeLoc (g_currentloc, SA_DECLARED));
4543 DPRINTF (("Result: [%p] %s", s, sRef_unparseFull (s)));
4544 return s;
4548 bool
4549 sRef_isNothing (sRef s)
4551 return (sRef_isKindSpecial (s) && s->info->spec == SR_NOTHING);
4554 bool
4555 sRef_isInternalState (sRef s)
4557 return (sRef_isKindSpecial (s) && s->info->spec == SR_INTERNAL);
4560 bool
4561 sRef_isSpecInternalState (sRef s)
4563 return (sRef_isKindSpecial (s)
4564 && (s->info->spec == SR_INTERNAL || s->info->spec == SR_SPECSTATE));
4567 bool
4568 sRef_isSpecState (sRef s)
4570 return (sRef_isKindSpecial (s) && s->info->spec == SR_SPECSTATE);
4573 bool
4574 sRef_isResult (sRef s)
4576 return (sRef_isReasonable (s) && s->kind == SK_RESULT);
4579 bool
4580 sRef_isSystemState (sRef s)
4582 return (sRef_isKindSpecial (s) && s->info->spec == SR_SYSTEM);
4585 bool
4586 sRef_isGlobalMarker (sRef s)
4588 return (sRef_isKindSpecial (s) && s->info->spec == SR_GLOBALMARKER);
4591 usymId
4592 sRef_getScopeIndex (sRef s)
4594 llassert (sRef_isReasonable (s));
4595 llassert (sRef_isCvar (s));
4597 return (s->info->cvar->index);
4600 void
4601 sRef_makeSafe (sRef s)
4603 if (sRef_isReasonable (s))
4605 s->safe = TRUE;
4609 void
4610 sRef_makeUnsafe (sRef s)
4612 if (sRef_isReasonable (s))
4614 s->safe = FALSE;
4619 ** memory state operations
4622 /*@only@*/ cstring sRef_unparseFull (sRef s)
4624 if (sRef_isInvalid (s)) return (cstring_undefined);
4626 return (message ("[%p] %q - %q { %q } [%s] { %q } < %q >",
4628 sRef_unparseDebug (s),
4629 sRef_unparseState (s),
4630 stateInfo_unparse (s->definfo),
4631 exkind_unparse (s->oexpkind),
4632 sRefSet_unparseDebug (s->deriv),
4633 valueTable_unparse (s->state)));
4636 #if 0
4637 cstring sRef_unparseDeep (sRef s)
4639 cstring st = cstring_undefined;
4641 st = message ("%q:", sRef_unparseFull (s));
4643 if (sRef_isReasonable (s))
4645 sRefSet_allElements (s->deriv, el)
4647 st = message("%q\n%q", st, sRef_unparseDeep (el));
4648 } end_sRefSet_allElements ;
4651 return st;
4653 #endif
4655 /*@only@*/ cstring sRef_unparseState (sRef s)
4657 if (sRef_isConj (s))
4659 return (message ("%q | %q",
4660 sRef_unparseState (s->info->conj->a),
4661 sRef_unparseState (s->info->conj->b)));
4664 if (sRef_isInvalid (s))
4666 return (cstring_makeLiteral ("<invalid>"));
4669 return (message ("%s.%s.%s.%s",
4670 alkind_unparse (s->aliaskind),
4671 nstate_unparse (sRef_getNullState (s)),
4672 exkind_unparse (s->expkind),
4673 sstate_unparse (s->defstate)));
4676 bool sRef_isNotUndefined (sRef s)
4678 return (sRef_isInvalid (s)
4679 || (s->defstate != SS_UNDEFINED
4680 && s->defstate != SS_UNUSEABLE
4681 && s->defstate != SS_DEAD));
4684 ynm sRef_isWriteable (sRef s)
4686 if (sRef_isInvalid (s)) return MAYBE;
4688 if (sRef_isConj (s) && s->defstate == SS_UNKNOWN)
4690 if (ynm_toBoolStrict (sRef_isWriteable (sRef_getConjA (s))))
4692 if (ynm_toBoolStrict (sRef_isWriteable (sRef_getConjB (s))))
4694 return YES;
4696 return MAYBE;
4698 else
4700 if (ynm_toBoolStrict (sRef_isWriteable (sRef_getConjB (s))))
4702 return MAYBE;
4704 return NO;
4708 return (ynm_fromBool (s->defstate != SS_UNUSEABLE));
4711 bool sRef_hasNoStorage (sRef s)
4713 return (!sRef_isAllocatedStorage (s) || sRef_isDefinitelyNull (s));
4716 bool sRef_isStrictReadable (sRef s)
4718 return (ynm_toBoolStrict (sRef_isValidLvalue (s)));
4722 ** Is this what is does?
4723 ** Returns YES if s can be used as an rvalue,
4724 ** MAYBE if its not clear
4725 ** NO if s cannot be safely used as an rvalue.
4728 ynm sRef_isValidLvalue (sRef s)
4730 sstate ss;
4732 if (sRef_isInvalid (s)) return YES;
4734 ss = s->defstate;
4736 if (sRef_isConj (s) && s->defstate == SS_UNKNOWN)
4738 if (ynm_toBoolStrict (sRef_isValidLvalue (sRef_getConjA (s))))
4740 if (ynm_toBoolStrict (sRef_isValidLvalue (sRef_getConjB (s))))
4742 return YES;
4744 return MAYBE;
4746 else
4748 if (ynm_toBoolStrict (sRef_isValidLvalue (sRef_getConjB (s))))
4750 return MAYBE;
4752 return NO;
4755 else if (ss == SS_HOFFA)
4757 if (context_getFlag (FLG_STRICTUSERELEASED))
4759 return MAYBE;
4761 else
4763 return YES;
4766 else
4768 return (ynm_fromBool (ss == SS_DEFINED
4769 || ss == SS_FIXED
4770 || ss == SS_RELDEF
4771 || ss == SS_PDEFINED
4772 || ss == SS_PARTIAL
4773 || ss == SS_SPECIAL
4774 || ss == SS_ALLOCATED
4775 || ss == SS_KILLED /* evans 2001-05-26: added this for killed globals */
4776 || ss == SS_UNKNOWN));
4780 static /*@exposed@*/ sRef whatUndefined (/*@exposed@*/ sRef fref, int depth)
4782 ctype ct;
4785 if (depth > MAXDEPTH)
4787 llgenmsg (message
4788 ("Warning: check definition limit exceeded, checking %q. "
4789 "This either means there is a variable with at least "
4790 "%d indirections apparent in the program text, or "
4791 "there is a bug in Splint.",
4792 sRef_unparse (fref),
4793 MAXDEPTH),
4794 g_currentloc);
4796 return sRef_undefined;
4799 if (!sRef_isKnown (fref) || sRef_isAnyDefined (fref))
4801 return sRef_undefined;
4804 if (sRef_isUnuseable (fref) || sRef_isStateUndefined (fref))
4806 return fref;
4809 ct = ctype_realType (sRef_getType (fref));
4811 if (ctype_isUnknown (ct))
4813 return sRef_undefined;
4815 else if (ctype_isPointer (ct) || ctype_isArray (ct))
4817 if (sRef_isStateUnknown (fref))
4819 return sRef_undefined;
4821 else
4823 sRef fptr = sRef_constructDeref (fref);
4825 return (whatUndefined (fptr, depth + 1));
4828 else if (ctype_isStruct (ct))
4830 if (sRef_isStateUnknown (fref))
4832 return fref;
4835 if (sRef_isPdefined (fref) || sRef_isAnyDefined (fref))
4837 sRefSet_realElements (sRef_derivedFields (fref), sr)
4839 if (sRef_isField (sr))
4841 cstring fieldname = sRef_getField (sr);
4842 sRef fldref = sRef_makeField (fref, fieldname);
4843 bool shouldCheck = !sRef_isRecursiveField (fldref);
4845 if (shouldCheck)
4847 sRef wdef = whatUndefined (fldref, depth + 1);
4849 if (sRef_isReasonable (wdef))
4851 return wdef;
4855 } end_sRefSet_realElements;
4857 else if (sRef_isAllocated (fref))
4860 ** for structures, each field must be completely defined
4863 uentryList fields = ctype_getFields (ct);
4865 uentryList_elements (fields, ue)
4867 cstring name = uentry_getRealName (ue);
4868 sRef ffield = sRef_makeField (fref, name);
4869 bool shouldCheck = !sRef_isRecursiveField (ffield);
4871 if (sRef_isRelDef (uentry_getSref (ue)))
4873 ; /* no error */
4875 else
4877 if (shouldCheck)
4879 sRef wdef = whatUndefined (ffield, depth + 1);
4881 if (sRef_isInvalid (wdef))
4883 return wdef;
4887 } end_uentryList_elements;
4889 else
4894 else if (ctype_isUnion (ct))
4898 else
4903 return sRef_undefined;
4906 static bool checkDefined (/*@temp@*/ sRef sr)
4908 /*@-temptrans@*/ /* the result from whatUndefined is lost */
4909 return (sRef_isInvalid (whatUndefined (sr, 0)));
4910 /*@=temptrans@*/
4913 bool sRef_isReallyDefined (sRef s)
4915 if (sRef_isReasonable (s))
4917 if (sRef_isAnyDefined (s))
4919 return TRUE;
4921 else
4923 if (sRef_isAllocated (s) || sRef_isPdefined (s))
4925 return checkDefined (s);
4927 else
4929 return FALSE;
4933 else
4935 return TRUE;
4939 void sRef_showNotReallyDefined (sRef s)
4941 if (sRef_isReasonable (s))
4943 if (sRef_isAnyDefined (s))
4945 BADBRANCH;
4947 else
4949 if (sRef_isAllocated (s) || sRef_isPdefined (s))
4951 /*@-temptrans@*/ /* the result of whatUndefined is lost */
4952 sRef ref = whatUndefined (s, 0);
4954 llassert (sRef_isReasonable (ref));
4956 if (ref != s)
4958 llgenindentmsgnoloc
4959 (message ("This sub-reference is %s: %q",
4960 sstate_unparse (sRef_getDefState (ref)),
4961 sRef_unparse (ref)));
4964 else
4970 else
4972 BADBRANCH;
4976 sstate sRef_getDefState (sRef s)
4978 if (sRef_isInvalid (s)) return (SS_UNKNOWN);
4979 return (s->defstate);
4982 void sRef_setDefState (sRef s, sstate defstate, fileloc loc)
4984 sRef_checkMutable (s);
4985 sRef_setStateAux (s, defstate, loc);
4988 static void sRef_clearAliasStateAux (sRef s, fileloc loc)
4990 sRef_checkMutable (s);
4991 sRef_setAliasKind (s, AK_ERROR, loc);
4994 void sRef_clearAliasState (sRef s, fileloc loc)
4996 sRef_checkMutable (s);
4997 sRef_aliasSetComplete (sRef_clearAliasStateAux, s, loc);
5000 void sRef_setAliasKindComplete (sRef s, alkind kind, fileloc loc)
5002 sRef_checkMutable (s);
5003 sRef_aliasSetCompleteAlkParam (sRef_setAliasKind, s, kind, loc);
5006 void sRef_setAliasKind (sRef s, alkind kind, fileloc loc)
5008 sRef_checkMutable (s);
5010 if (sRef_isReasonable (s))
5012 sRef_clearDerived (s);
5014 if ((kind != s->aliaskind && kind != s->oaliaskind)
5015 && fileloc_isDefined (loc))
5017 s->aliasinfo = stateInfo_updateLoc (s->aliasinfo, stateAction_fromAlkind (kind), loc);
5020 s->aliaskind = kind;
5024 void sRef_setOrigAliasKind (sRef s, alkind kind)
5026 sRef_checkMutable (s);
5028 if (sRef_isReasonable (s))
5030 s->oaliaskind = kind;
5034 exkind sRef_getExKind (sRef s)
5036 if (sRef_isReasonable (s))
5038 return (s->expkind);
5040 else
5042 return XO_UNKNOWN;
5046 exkind sRef_getOrigExKind (sRef s)
5048 if (sRef_isReasonable (s))
5050 return (s->oexpkind);
5052 else
5054 return XO_UNKNOWN;
5058 static void sRef_clearExKindAux (sRef s, fileloc loc)
5060 sRef_checkMutable (s);
5061 sRef_setExKind (s, XO_UNKNOWN, loc);
5064 void sRef_setObserver (sRef s, fileloc loc)
5066 sRef_checkMutable (s);
5067 sRef_setExKind (s, XO_OBSERVER, loc);
5070 void sRef_setExposed (sRef s, fileloc loc)
5072 sRef_checkMutable (s);
5073 sRef_setExKind (s, XO_EXPOSED, loc);
5076 void sRef_clearExKindComplete (sRef s, fileloc loc)
5078 (void) sRef_aliasSetComplete (sRef_clearExKindAux, s, loc);
5081 void sRef_setExKind (sRef s, exkind exp, fileloc loc)
5083 sRef_checkMutable (s);
5085 if (sRef_isReasonable (s))
5087 if (s->expkind != exp)
5089 s->expinfo = stateInfo_updateLoc (s->expinfo, stateAction_fromExkind (exp), loc);
5092 s->expkind = exp;
5097 ** s1->derived = s2->derived
5100 static void sRef_copyRealDerived (sRef s1, sRef s2)
5102 DPRINTF (("Copy real: %s / %s", sRef_unparse (s1), sRef_unparse (s2)));
5103 sRef_checkMutable (s1);
5105 if (sRef_isReasonable (s1) && sRef_isReasonable (s2))
5107 sRef sb = sRef_getRootBase (s1);
5109 sRefSet_clear (s1->deriv);
5111 sRefSet_allElements (s2->deriv, el)
5113 if (sRef_isReasonable (el))
5115 sRef rb = sRef_getRootBase (el);
5117 if (!sRef_same (rb, sb))
5119 sRef fb = sRef_fixDirectBase (el, s1);
5121 if (sRef_isReasonable (fb))
5123 sRef_copyRealDerived (fb, el);
5124 sRef_addDeriv (s1, fb);
5127 else
5129 sRef_addDeriv (s1, el);
5132 } end_sRefSet_allElements ;
5137 void sRef_copyRealDerivedComplete (sRef s1, sRef s2)
5139 sRef_innerAliasSetCompleteParam (sRef_copyRealDerived, s1, s2);
5142 void sRef_setUndefined (sRef s, fileloc loc)
5144 sRef_checkMutable (s);
5146 if (sRef_isReasonable (s))
5148 s->defstate = SS_UNDEFINED;
5149 s->definfo = stateInfo_updateLoc (s->definfo, SA_UNDEFINED, loc);
5151 sRef_clearDerived (s);
5155 static void sRef_setDefinedAux (sRef s, fileloc loc, bool clear)
5157 sRef_checkMutable (s);
5158 if (sRef_isInvalid (s)) return;
5160 DPRINTF (("Set defined: %s", sRef_unparseFull (s)));
5162 s->definfo = stateInfo_updateLoc (s->definfo, SA_DEFINED, loc);
5163 s->defstate = SS_DEFINED;
5165 DPRINTF (("Set defined: %s", sRef_unparseFull (s)));
5167 /* e.g., if x is allocated, *x = 3 defines x */
5169 if (s->kind == SK_PTR)
5171 sRef p = s->info->ref;
5172 sRef arr;
5174 if (p->defstate == SS_ALLOCATED
5175 || p->defstate == SS_SPECIAL) /* evans 2001-07-12: shouldn't need this */
5177 sRef_setDefinedAux (p, loc, clear);
5181 ** Defines a[0] also:
5184 arr = sRef_findDerivedArrayFetch (p, FALSE, 0, FALSE);
5186 if (sRef_isReasonable (arr))
5188 sRef_setDefinedAux (arr, loc, clear);
5191 else if (s->kind == SK_ARRAYFETCH)
5193 if (!s->info->arrayfetch->indknown
5194 || (s->info->arrayfetch->ind == 0))
5196 sRef p = s->info->arrayfetch->arr;
5197 sRef ptr = sRef_constructPointer (p);
5199 if (sRef_isReasonable (ptr))
5201 if (ptr->defstate == SS_ALLOCATED
5202 || ptr->defstate == SS_UNDEFINED
5203 || ptr->defstate == SS_SPECIAL) /* evans 2001-07-12: shouldn't need this */
5205 sRef_setDefinedAux (ptr, loc, clear);
5209 if (p->defstate == SS_RELDEF)
5213 else if (p->defstate == SS_ALLOCATED || p->defstate == SS_PDEFINED
5214 || p->defstate == SS_SPECIAL) /* evans 2001-07-12: shouldn't need this */
5216 p->defstate = SS_DEFINED;
5218 else
5223 else if (s->kind == SK_FIELD)
5225 sRef parent = s->info->field->rec;
5227 if (sRef_isReasonable (parent))
5229 if (ctype_isUnion (ctype_realType (parent->type)))
5232 ** Should not clear derived from here.
5235 sRef_setDefinedNoClear (parent, loc);
5237 else
5239 ; /* Nothing to do for structures. */
5244 else
5249 if (clear)
5251 sRef_clearDerived (s);
5253 else
5255 /* evans 2001-07-12: need to define the derived references */
5256 sRefSet_elements (s->deriv, el)
5258 llassert (sRef_isReasonable (el));
5259 el->defstate = SS_DEFINED;
5260 } end_sRefSet_elements ;
5263 DPRINTF (("Set defined: %s", sRef_unparseFull (s)));
5266 static void sRef_setPartialDefined (sRef s, fileloc loc)
5268 sRef_checkMutable (s);
5270 if (!sRef_isPartial (s))
5272 sRef_setDefined (s, loc);
5276 void sRef_setPartialDefinedComplete (sRef s, fileloc loc)
5278 sRef_innerAliasSetComplete (sRef_setPartialDefined, s, loc);
5281 void sRef_setDefinedComplete (sRef s, fileloc loc)
5283 sRef_innerAliasSetComplete (sRef_setDefined, s, loc);
5286 void sRef_setDefinedCompleteDirect (sRef s, fileloc loc)
5288 sRefSet aliases;
5290 aliases = usymtab_allAliases (s);
5291 DPRINTF (("Set defined complete: %s", sRef_unparseFull (s)));
5292 DPRINTF (("All aliases: %s", sRefSet_unparseFull (aliases)));
5294 sRef_setDefined (s, loc);
5296 sRefSet_realElements (aliases, current)
5298 if (sRef_isReasonable (current))
5300 current = sRef_updateSref (current);
5301 sRef_setDefined (current, loc);
5303 } end_sRefSet_realElements;
5305 sRefSet_free (aliases);
5306 sRef_innerAliasSetComplete (sRef_setDefined, s, loc);
5309 void sRef_setDefined (sRef s, fileloc loc)
5311 sRef_checkMutable (s);
5312 sRef_setDefinedAux (s, loc, TRUE);
5315 static void sRef_setDefinedNoClear (sRef s, fileloc loc)
5317 sRef_checkMutable (s);
5318 DPRINTF (("Defining: %s", sRef_unparseFull (s)));
5319 sRef_setDefinedAux (s, loc, FALSE);
5320 DPRINTF (("==> %s", sRef_unparseFull (s)));
5323 void sRef_setDefinedNCComplete (sRef s, fileloc loc)
5325 sRef_checkMutable (s);
5326 DPRINTF (("Set Defined Complete: %s", sRef_unparseFull (s)));
5327 sRef_innerAliasSetComplete (sRef_setDefinedNoClear, s, loc);
5328 DPRINTF (("==> %s", sRef_unparseFull (s)));
5331 static bool sRef_isDeepUnionField (sRef s)
5333 return (sRef_deepPred (sRef_isUnionField, s));
5336 bool sRef_isUnionField (sRef s)
5338 if (sRef_isReasonable (s) && s->kind == SK_FIELD)
5341 ** defining one field of a union defines the union
5344 sRef base = s->info->field->rec;
5346 if (sRef_isReasonable (base))
5348 return (ctype_isUnion (ctype_realType (base->type)));
5352 return FALSE;
5355 void sRef_setPdefined (sRef s, fileloc loc)
5357 sRef_checkMutable (s);
5358 if (sRef_isReasonable (s) && !sRef_isPartial (s))
5360 sRef base = sRef_getBaseSafe (s);
5362 if (s->defstate == SS_ALLOCATED)
5364 return;
5367 s->definfo = stateInfo_updateLoc (s->definfo, SA_PDEFINED, loc);
5368 s->defstate = SS_PDEFINED;
5370 /* e.g., if x is allocated, *x = 3 defines x */
5372 while (sRef_isReasonable (base) && sRef_isKnown (base))
5374 if (base->defstate == SS_DEFINED)
5376 sRef nb;
5378 DPRINTF (("set pdefined: %s", sRef_unparseFull (base)));
5379 base->defstate = SS_PDEFINED;
5380 nb = sRef_getBaseSafe (base);
5381 base = nb;
5383 else
5385 break;
5391 static void sRef_setStateAux (sRef s, sstate ss, fileloc loc)
5393 sRef_checkMutable (s);
5395 DPRINTF (("Set state: %s => %s", sRef_unparseFull (s), sstate_unparse (ss)));
5397 if (sRef_isReasonable (s))
5399 /* if (s->defstate == SS_RELDEF) return; */
5401 if (s->defstate != ss && fileloc_isDefined (loc))
5403 s->definfo = stateInfo_updateLoc (s->definfo,
5404 stateAction_fromSState (ss), loc);
5407 s->defstate = ss;
5408 sRef_clearDerived (s);
5410 if (ss == SS_ALLOCATED)
5412 sRef base = sRef_getBaseSafe (s);
5414 while (sRef_isReasonable (base) && sRef_isKnown (base))
5416 if (base->defstate == SS_DEFINED)
5418 sRef nb;
5420 DPRINTF (("set pdefined: %s", sRef_unparseFull (s)));
5421 base->defstate = SS_PDEFINED;
5422 nb = sRef_getBaseSafe (base);
5423 base = nb;
5425 else
5427 break;
5434 void sRef_setAllocatedComplete (sRef s, fileloc loc)
5436 sRef_innerAliasSetComplete (sRef_setAllocated, s, loc);
5439 static void sRef_setAllocatedShallow (sRef s, fileloc loc)
5441 sRef_checkMutable (s);
5443 if (sRef_isReasonable (s))
5445 if (s->defstate == SS_DEAD || s->defstate == SS_UNDEFINED)
5447 s->defstate = SS_ALLOCATED;
5448 s->definfo = stateInfo_updateLoc (s->definfo, SA_ALLOCATED, loc);
5453 void sRef_setAllocatedShallowComplete (sRef s, fileloc loc)
5455 sRef_innerAliasSetComplete (sRef_setAllocatedShallow, s, loc);
5458 void sRef_setAllocated (sRef s, fileloc loc)
5460 sRef_checkMutable (s);
5461 sRef_setStateAux (s, SS_ALLOCATED, loc);
5464 void sRef_setPartial (sRef s, fileloc loc)
5466 sRef_checkMutable (s);
5467 sRef_setStateAux (s, SS_PARTIAL, loc);
5470 void sRef_setShared (sRef s, fileloc loc)
5472 sRef_checkMutable (s);
5474 if (sRef_isReasonable (s))
5476 if (s->aliaskind != AK_SHARED && fileloc_isDefined (loc))
5478 s->aliasinfo = stateInfo_updateLoc (s->aliasinfo, SA_SHARED, loc);
5481 s->aliaskind = AK_SHARED;
5482 /* don't! sRef_clearDerived (s); */
5486 void sRef_setLastReference (sRef s, /*@exposed@*/ sRef ref, fileloc loc)
5488 sRef_checkMutable (s);
5490 if (sRef_isReasonable (s))
5492 s->aliaskind = sRef_getAliasKind (ref);
5493 s->aliasinfo = stateInfo_updateRefLoc (s->aliasinfo, ref, stateAction_fromAlkind (s->aliaskind), loc);
5497 static
5498 void sRef_setNullStateAux (/*@notnull@*/ sRef s, nstate ns, fileloc loc)
5500 sRef_checkMutable (s);
5501 s->nullstate = ns;
5502 sRef_resetAliasKind (s);
5504 if (fileloc_isDefined (loc))
5506 s->nullinfo = stateInfo_updateLoc (s->nullinfo, stateAction_fromNState (ns), loc);
5510 void sRef_setNotNull (sRef s, fileloc loc)
5512 if (sRef_isReasonable (s))
5514 sRef_setNullStateAux (s, NS_NOTNULL, loc);
5518 void sRef_setNullStateN (sRef s, nstate n)
5520 if (sRef_isReasonable (s))
5522 sRef_checkMutable (s);
5523 s->nullstate = n;
5524 DPRINTF (("Set null state ==> %s", sRef_unparseFull (s)));
5525 sRef_resetAliasKind (s);
5529 void sRef_setNullState (sRef s, nstate n, fileloc loc)
5531 if (sRef_isReasonable (s))
5533 sRef_setNullStateAux (s, n, loc);
5537 # ifdef DEADCODE
5538 void sRef_setNullTerminatedStateInnerComplete (sRef s, struct s_bbufinfo b, /*@unused@*/ fileloc loc)
5540 switch (b.bufstate) {
5541 case BB_NULLTERMINATED:
5542 sRef_setNullTerminatedState (s);
5543 sRef_setLen (s, b.len);
5544 break;
5545 case BB_POSSIBLYNULLTERMINATED:
5546 sRef_setPossiblyNullTerminatedState(s);
5547 break;
5548 case BB_NOTNULLTERMINATED:
5549 sRef_setNotNullTerminatedState (s);
5550 break;
5553 sRef_setSize (s, b.size);
5555 /* PL: TO BE DONE : Aliases are not modified right now, have to be similar to
5556 * setNullStateInnerComplete.
5559 # endif /* DEADCODE */
5561 void sRef_setNullStateInnerComplete (sRef s, nstate n, fileloc loc)
5563 DPRINTF (("Set null state: %s", nstate_unparse (n)));
5565 sRef_setNullState (s, n, loc);
5567 switch (n)
5569 case NS_POSNULL:
5570 sRef_innerAliasSetComplete (sRef_setPosNull, s, loc);
5571 break;
5572 case NS_DEFNULL:
5573 sRef_innerAliasSetComplete (sRef_setDefNull, s, loc);
5574 break;
5575 case NS_UNKNOWN:
5576 sRef_innerAliasSetComplete (sRef_setNullUnknown, s, loc);
5577 break;
5578 case NS_NOTNULL:
5579 sRef_innerAliasSetComplete (sRef_setNotNull, s, loc);
5580 break;
5581 case NS_MNOTNULL:
5582 sRef_innerAliasSetComplete (sRef_setNotNull, s, loc);
5583 break;
5584 case NS_RELNULL:
5585 sRef_innerAliasSetComplete (sRef_setNullUnknown, s, loc);
5586 break;
5587 case NS_CONSTNULL:
5588 sRef_innerAliasSetComplete (sRef_setDefNull, s, loc);
5589 break;
5590 case NS_ABSNULL:
5591 sRef_innerAliasSetComplete (sRef_setNullUnknown, s, loc);
5592 break;
5593 case NS_ERROR:
5594 sRef_innerAliasSetComplete (sRef_setNullErrorLoc, s, loc);
5595 break;
5599 void sRef_setPosNull (sRef s, fileloc loc)
5601 if (sRef_isReasonable (s))
5603 sRef_setNullStateAux (s, NS_POSNULL, loc);
5607 void sRef_setDefNull (sRef s, fileloc loc)
5609 if (sRef_isReasonable (s))
5611 sRef_setNullStateAux (s, NS_DEFNULL, loc);
5615 void sRef_setNullUnknown (sRef s, fileloc loc)
5617 if (sRef_isReasonable (s))
5619 sRef_setNullStateAux (s, NS_UNKNOWN, loc);
5623 void sRef_setNullError (sRef s)
5625 if (sRef_isReasonable (s) && !sRef_isConst (s))
5627 sRef_setNullStateAux (s, NS_UNKNOWN, fileloc_undefined);
5631 void sRef_setNullErrorLoc (sRef s, fileloc loc)
5633 if (sRef_isReasonable (s) && !sRef_isConst (s))
5635 sRef_setNullStateAux (s, NS_UNKNOWN, loc);
5639 void sRef_setOnly (sRef s, fileloc loc)
5641 if (sRef_isReasonable (s) && s->aliaskind != AK_ONLY)
5643 sRef_checkMutable (s);
5644 s->aliaskind = AK_ONLY;
5645 s->aliasinfo = stateInfo_updateLoc (s->aliasinfo, SA_ONLY, loc);
5649 void sRef_setDependent (sRef s, fileloc loc)
5651 if (sRef_isReasonable (s) && !sRef_isConst (s) && (s->aliaskind != AK_DEPENDENT))
5653 sRef_checkMutable (s);
5654 DPRINTF (("Setting dependent: %s", sRef_unparseFull (s)));
5655 s->aliaskind = AK_DEPENDENT;
5656 s->aliasinfo = stateInfo_updateLoc (s->aliasinfo, SA_DEPENDENT, loc);
5660 void sRef_setOwned (sRef s, fileloc loc)
5662 if (sRef_isReasonable (s) && !sRef_isConst (s) && (s->aliaskind != AK_OWNED))
5664 sRef_checkMutable (s);
5665 s->aliaskind = AK_OWNED;
5666 s->aliasinfo = stateInfo_updateLoc (s->aliasinfo, SA_OWNED, loc);
5670 void sRef_setKept (sRef s, fileloc loc)
5672 if (sRef_isReasonable (s) && !sRef_isConst (s) && (s->aliaskind != AK_KEPT))
5674 sRef base = sRef_getBaseSafe (s);
5676 while (sRef_isReasonable (base) && sRef_isKnown (base))
5678 if (base->defstate == SS_DEFINED)
5680 sRef_checkMutable (base);
5681 base->defstate = SS_PDEFINED;
5682 base = sRef_getBaseSafe (base);
5684 else
5686 break;
5690 sRef_checkMutable (s);
5691 s->aliaskind = AK_KEPT;
5692 s->aliasinfo = stateInfo_updateLoc (s->aliasinfo, SA_KEPT, loc);
5696 static void sRef_setKeptAux (sRef s, fileloc loc)
5698 if (!sRef_isShared (s))
5700 sRef_setKept (s, loc);
5704 static void sRef_setDependentAux (sRef s, fileloc loc)
5706 if (!sRef_isShared (s))
5708 sRef_setDependent (s, loc);
5712 void sRef_setKeptComplete (sRef s, fileloc loc)
5714 sRef_aliasSetComplete (sRef_setKeptAux, s, loc);
5717 void sRef_setDependentComplete (sRef s, fileloc loc)
5719 sRef_aliasSetComplete (sRef_setDependentAux, s, loc);
5722 void sRef_setFresh (sRef s, fileloc loc)
5724 if (sRef_isReasonable (s) && !sRef_isConst (s))
5726 sRef_checkMutable (s);
5727 s->aliaskind = AK_FRESH;
5728 s->aliasinfo = stateInfo_updateLoc (s->aliasinfo, SA_CREATED, loc);
5729 DPRINTF (("SetFresh: %s", sRef_unparseFull (s)));
5733 void sRef_kill (sRef s, fileloc loc)
5735 DPRINTF (("Kill: %s", sRef_unparseFull (s)));
5737 if (sRef_isReasonable (s) && !sRef_isShared (s) && !sRef_isConst (s))
5739 sRef base = sRef_getBaseSafe (s);
5740 sRef_checkMutable (s);
5742 while (sRef_isReasonable (base) && sRef_isKnown (base))
5744 if (base->defstate == SS_DEFINED)
5746 sRef_checkMutable (base);
5747 base->defstate = SS_PDEFINED;
5748 base = sRef_getBaseSafe (base);
5750 else
5752 break;
5756 s->aliaskind = s->oaliaskind;
5757 s->defstate = SS_DEAD;
5758 s->definfo = stateInfo_updateLoc (s->definfo, SA_KILLED, loc);
5759 DPRINTF (("State info: %s", stateInfo_unparse (s->definfo)));
5760 sRef_clearDerived (s);
5764 void sRef_maybeKill (sRef s, fileloc loc)
5766 if (sRef_isReasonable (s))
5768 sRef base = sRef_getBaseSafe (s);
5769 sRef_checkMutable (s);
5771 while (sRef_isReasonable (base) && sRef_isKnown (base))
5773 if (base->defstate == SS_DEFINED || base->defstate == SS_RELDEF)
5775 sRef_checkMutable (base);
5776 base->defstate = SS_PDEFINED;
5777 base = sRef_getBaseSafe (base);
5779 else
5781 break;
5786 s->aliaskind = s->oaliaskind;
5787 s->defstate = SS_HOFFA;
5788 s->definfo = stateInfo_updateLoc (s->definfo, SA_PKILLED, loc);
5789 DPRINTF (("State info: %s / %s", sRef_unparse (s),
5790 stateInfo_unparse (s->definfo)));
5791 sRef_clearDerived (s);
5797 ** just for type checking...
5800 static void sRef_killAux (sRef s, fileloc loc)
5802 if (sRef_isReasonable (s) && !sRef_isShared (s))
5804 if (sRef_isUnknownArrayFetch (s))
5806 sRef_maybeKill (s, loc);
5808 else
5810 sRef_kill (s, loc);
5816 ** kills s and all aliases to s
5819 void sRef_killComplete (sRef s, fileloc loc)
5821 DPRINTF (("Kill complete: %s", sRef_unparseFull (s)));
5822 sRef_aliasSetComplete (sRef_killAux, s, loc);
5825 static bool sRef_equivalent (sRef s1, sRef s2)
5827 return (sRef_compare (s1, s2) == 0);
5831 ** returns an sRef that will not be free'd on function exit.
5834 /*@only@*/ sRef sRef_saveCopy (sRef s)
5836 sRef ret;
5838 if (sRef_isReasonable (s))
5840 bool old = inFunction;
5843 ** Exit the function scope, so this sRef is not
5844 ** stored in the deallocation table.
5847 inFunction = FALSE;
5848 DPRINTF (("Copying sref: %s", sRef_unparseFull(s)));
5849 ret = sRef_copy (s);
5850 DPRINTF (("Copying ===>: %s", sRef_unparseFull(ret)));
5851 inFunction = old;
5853 else
5855 ret = sRef_undefined;
5858 /*@-dependenttrans@*/
5859 return ret;
5860 /*@=dependenttrans@*/
5863 sRef sRef_copy (sRef s)
5865 if (sRef_isKindSpecial (s) && !sRef_isGlobalMarker (s))
5867 /*@-retalias@*/
5868 return s; /* don't copy specials (except for global markers) */
5869 /*@=retalias@*/
5872 if (sRef_isReasonable (s))
5874 sRef t = sRef_alloc ();
5876 DPRINTF (("Copying: [%p] %s", s, sRef_unparse (s)));
5877 DPRINTF (("Full: %s", sRef_unparseFull (s)));
5879 t->kind = s->kind;
5880 t->safe = s->safe;
5881 t->modified = s->modified;
5882 t->immut = FALSE; /* Note mutability is not copied. */
5883 t->type = s->type;
5884 t->val = multiVal_copy (s->val);
5886 t->info = sinfo_copy (s);
5887 t->defstate = s->defstate;
5888 t->nullstate = s->nullstate;
5889 DPRINTF (("Set null state==> %s", sRef_unparseFull (t)));
5892 /* start modifications */
5893 t->bufinfo.bufstate = s->bufinfo.bufstate;
5894 t->bufinfo.len = s->bufinfo.len;
5895 t->bufinfo.size = s->bufinfo.size;
5896 /* end modifications */
5898 t->aliaskind = s->aliaskind;
5899 t->oaliaskind = s->oaliaskind;
5901 t->expkind = s->expkind;
5902 t->oexpkind = s->oexpkind;
5904 t->nullinfo = stateInfo_copy (s->nullinfo);
5905 t->aliasinfo = stateInfo_copy (s->aliasinfo);
5906 t->definfo = stateInfo_copy (s->definfo);
5907 t->expinfo = stateInfo_copy (s->expinfo);
5909 t->deriv = sRefSet_newDeepCopy (s->deriv);
5910 t->state = valueTable_copy (s->state);
5912 DPRINTF (("Made copy: %s => %s", sRef_unparseFull (s), sRef_unparseFull (t)));
5913 return t;
5915 else
5917 return sRef_undefined;
5921 /*@notfunction@*/
5922 # define PREDTEST(func,s) \
5923 do { if (sRef_isInvalid (s)) { return FALSE; } \
5924 else { if (sRef_isConj (s)) \
5925 { return (func (sRef_getConjA (s)) \
5926 || func (sRef_getConjB (s))); }}} while (FALSE);
5928 bool sRef_isAddress (sRef s)
5930 PREDTEST (sRef_isAddress, s);
5931 return (s->kind == SK_ADR);
5935 ** pretty weak... maybe a flag should control this.
5938 bool sRef_isThroughArrayFetch (sRef s)
5940 if (sRef_isReasonable (s))
5942 sRef tref = s;
5946 sRef lt;
5948 if (sRef_isArrayFetch (tref))
5950 return TRUE;
5953 lt = sRef_getBase (tref);
5954 tref = lt;
5955 } while (sRef_isReasonable (tref));
5958 return FALSE;
5961 bool sRef_isArrayFetch (sRef s)
5963 PREDTEST (sRef_isArrayFetch, s);
5964 return (s->kind == SK_ARRAYFETCH);
5967 bool sRef_isMacroParamRef (sRef s)
5969 if (context_inMacro () && sRef_isCvar (s))
5971 uentry ue = sRef_getUentry (s);
5972 cstring pname = makeParam (uentry_rawName (ue));
5973 uentry mac = usymtab_lookupSafe (pname);
5975 cstring_free (pname);
5976 return (uentry_isValid (mac));
5979 return FALSE;
5982 bool sRef_isCvar (sRef s)
5984 PREDTEST (sRef_isCvar, s);
5985 return (s->kind == SK_CVAR);
5988 bool sRef_isConst (sRef s)
5990 PREDTEST (sRef_isConst, s);
5991 return (s->kind == SK_CONST);
5994 # ifdef DEADCODE
5995 bool sRef_isObject (sRef s)
5997 PREDTEST (sRef_isObject, s);
5998 return (s->kind == SK_OBJECT);
6000 # endif /* DEADCODE */
6002 bool sRef_isExternal (sRef s)
6004 PREDTEST (sRef_isExternal, s);
6005 return (s->kind == SK_EXTERNAL);
6008 static bool sRef_isDerived (sRef s)
6010 PREDTEST (sRef_isDerived, s);
6011 return (s->kind == SK_DERIVED);
6014 bool sRef_isField (sRef s)
6016 PREDTEST (sRef_isField, s);
6017 return (s->kind == SK_FIELD);
6020 static bool sRef_isIndex (sRef s)
6022 PREDTEST (sRef_isIndex, s);
6023 return (s->kind == SK_ARRAYFETCH);
6026 bool sRef_isAnyParam (sRef s)
6028 PREDTEST (sRef_isAnyParam, s);
6029 return (s->kind == SK_PARAM);
6032 bool sRef_isParam (sRef s)
6034 PREDTEST (sRef_isParam, s);
6035 return (s->kind == SK_PARAM);
6038 bool sRef_isDirectParam (sRef s)
6040 PREDTEST (sRef_isDirectParam, s);
6042 return ((s->kind == SK_CVAR) &&
6043 (s->info->cvar->lexlevel == functionScope) &&
6044 (context_inFunction () &&
6045 (s->info->cvar->index <= usymId_fromInt (uentryList_size (context_getParams ())))));
6048 bool sRef_isPointer (sRef s)
6050 PREDTEST (sRef_isPointer, s);
6051 return (s->kind == SK_PTR);
6055 ** returns true if storage referenced by s is visible
6058 bool sRef_isReference (sRef s)
6060 PREDTEST (sRef_isReference, s);
6062 return (sRef_isPointer (s) || sRef_isIndex (s) || sRef_isFileOrGlobalScope (s)
6063 || (sRef_isField (s) && (sRef_isReference (s->info->field->rec))));
6066 bool sRef_isIReference (sRef s)
6068 return (sRef_isPointer (s) || sRef_isAddress (s) || sRef_isIndex (s)
6069 || sRef_isField (s) || sRef_isArrayFetch (s));
6072 bool sRef_isFileOrGlobalScope (sRef s)
6074 return (sRef_isCvar (s) && (s->info->cvar->lexlevel <= fileScope));
6077 bool sRef_isRealGlobal (sRef s)
6079 return (sRef_isCvar (s) && (s->info->cvar->lexlevel == globScope));
6082 bool sRef_isFileStatic (sRef s)
6084 return (sRef_isCvar (s) && (s->info->cvar->lexlevel == fileScope));
6087 bool sRef_isAliasCheckedGlobal (sRef s)
6089 if (sRef_isFileOrGlobalScope (s))
6091 uentry ue = sRef_getUentry (s);
6093 return context_checkAliasGlob (ue);
6095 else
6097 return FALSE;
6101 void sRef_free (/*@only@*/ sRef s)
6103 if (s != sRef_undefined && s->kind != SK_SPECIAL)
6105 DPRINTF (("Free sref: [%p]", s));
6107 # if 0
6108 sRef_checkValid (s);
6109 # endif
6111 multiVal_free (s->val); /* evans 2002-07-12 */
6113 stateInfo_free (s->expinfo);
6114 stateInfo_free (s->aliasinfo);
6115 stateInfo_free (s->definfo);
6116 stateInfo_free (s->nullinfo);
6118 sRefSet_free (s->deriv);
6119 s->deriv = sRefSet_undefined;
6121 valueTable_free (s->state);
6122 sinfo_free (s);
6125 /* drl added to help locate use after release*/
6126 s->expinfo = stateInfo_undefined;
6127 s->aliasinfo = stateInfo_undefined;
6128 s->definfo = stateInfo_undefined;
6129 s->nullinfo = stateInfo_undefined;
6131 sfree (s);
6135 void sRef_setType (sRef s, ctype t)
6137 if (sRef_isReasonable (s))
6139 sRef_checkMutable (s);
6140 s->type = t;
6144 void sRef_setTypeFull (sRef s, ctype t)
6146 if (sRef_isReasonable (s))
6148 sRef_checkMutable (s);
6149 s->type = t;
6151 sRefSet_allElements (s->deriv, current)
6153 sRef_setTypeFull (current, ctype_unknown);
6154 } end_sRefSet_allElements ;
6158 /*@exposed@*/ sRef
6159 sRef_buildField (/*@exposed@*/ sRef rec, /*@dependent@*/ cstring f)
6161 return (sRef_buildNCField (rec, f));
6164 static /*@exposed@*/ sRef
6165 sRef_findDerivedField (/*@notnull@*/ sRef rec, cstring f)
6167 sRefSet_allElements (sRef_derivedFields (rec), sr)
6169 if (sRef_isReasonable (sr))
6171 if (sRef_isReasonable (sr))
6173 if (sr->info != NULL)
6175 if (sr->kind == SK_FIELD && cstring_equal (sr->info->field->field, f))
6177 return sr;
6181 else
6183 llcontbug (message ("Invalid sRef as derived field of %s", sRef_unparse (rec)));
6186 } end_sRefSet_allElements;
6188 return sRef_undefined;
6191 /*@dependent@*/ /*@observer@*/ sRefSet sRef_derivedFields (/*@temp@*/ sRef rec)
6193 if (sRef_isReasonable (rec))
6195 sRefSet ret;
6196 ret = rec->deriv;
6197 return (ret);
6199 else
6201 return (sRefSet_undefined);
6205 static /*@exposed@*/ sRef
6206 sRef_findDerivedPointer (sRef s)
6208 if (sRef_isReasonable (s))
6210 sRefSet_realElements (s->deriv, sr)
6212 if (sRef_isReasonable (sr) && sr->kind == SK_PTR)
6214 return sr;
6216 } end_sRefSet_realElements;
6219 return sRef_undefined;
6222 bool
6223 sRef_isUnknownArrayFetch (sRef s)
6225 return (sRef_isReasonable (s)
6226 && s->kind == SK_ARRAYFETCH
6227 && !s->info->arrayfetch->indknown);
6230 static /*@exposed@*/ sRef
6231 sRef_findDerivedArrayFetch (/*@notnull@*/ sRef s, bool isknown, int idx, bool dead)
6234 if (isknown)
6236 sRefSet_realElements (s->deriv, sr)
6238 if (sRef_isReasonable (sr)
6239 && sr->kind == SK_ARRAYFETCH
6240 && sr->info->arrayfetch->indknown
6241 && (sr->info->arrayfetch->ind == idx))
6243 return sr;
6245 } end_sRefSet_realElements;
6247 else
6249 sRefSet_realElements (s->deriv, sr)
6251 if (sRef_isReasonable (sr)
6252 && sr->kind == SK_ARRAYFETCH
6253 && (!sr->info->arrayfetch->indknown
6254 || (sr->info->arrayfetch->indknown &&
6255 sr->info->arrayfetch->ind == 0)))
6257 if (sRef_isDead (sr) || sRef_isKept (sr))
6259 if (dead || context_getFlag (FLG_STRICTUSERELEASED))
6261 return sr;
6264 else
6266 return sr;
6269 } end_sRefSet_realElements;
6272 return sRef_undefined;
6275 static /*@exposed@*/ sRef
6276 sRef_buildNCField (/*@exposed@*/ sRef rec, /*@exposed@*/ cstring f)
6278 sRef s;
6280 DPRINTF (("Build nc field: %s / %s",
6281 sRef_unparseFull (rec), f));
6283 if (sRef_isInvalid (rec))
6285 return sRef_undefined;
6289 ** check if the field already has been referenced
6292 s = sRef_findDerivedField (rec, f);
6294 if (sRef_isReasonable (s))
6296 return s;
6298 else
6300 ctype ct = ctype_realType (rec->type);
6302 DPRINTF (("Field of: %s", sRef_unparse (rec)));
6304 s = sRef_newRef ();
6305 s->kind = SK_FIELD;
6306 s->info = (sinfo) dmalloc (sizeof (*s->info));
6307 s->info->field = (fldinfo) dmalloc (sizeof (*s->info->field));
6308 s->info->field->rec = rec;
6309 s->info->field->field = f; /* doesn't copy f */
6311 if (ctype_isKnown (ct) && ctype_isSU (ct))
6313 uentry ue = uentryList_lookupField (ctype_getFields (ct), f);
6315 if (!uentry_isUndefined (ue))
6317 DPRINTF (("lookup: %s for %s", uentry_unparseFull (ue),
6318 ctype_unparse (ct)));
6320 s->type = uentry_getType (ue);
6322 if (ctype_isMutable (s->type)
6323 && rec->aliaskind != AK_STACK
6324 && !alkind_isStatic (rec->aliaskind))
6326 s->aliaskind = rec->aliaskind;
6328 else
6330 s->aliaskind = AK_UNKNOWN;
6333 if (sRef_isStateDefined (rec) || sRef_isStateUnknown (rec)
6334 || sRef_isPdefined (rec))
6336 sRef_setStateFromUentry (s, ue);
6338 else
6340 sRef_setPartsFromUentry (s, ue);
6343 s->oaliaskind = s->aliaskind;
6344 s->oexpkind = s->expkind;
6346 DPRINTF (("sref: %s", sRef_unparseFull (s)));
6348 else
6351 Never report this as an error. It can happen whenever there
6352 is casting involved.
6354 if (report)
6356 llcontbug (message ("buildNCField --- no field %s: %q / %s",
6357 f, sRef_unparse (s), ctype_unparse (ct)));
6361 return sRef_undefined;
6365 if (rec->defstate == SS_DEFINED
6366 && (s->defstate == SS_UNDEFINED || s->defstate == SS_UNKNOWN))
6368 s->defstate = SS_DEFINED;
6370 else if (rec->defstate == SS_PARTIAL)
6372 s->defstate = SS_PARTIAL;
6374 else if (rec->defstate == SS_ALLOCATED)
6376 if (ctype_isStackAllocated (ct) && ctype_isStackAllocated (s->type))
6378 s->defstate = SS_ALLOCATED;
6380 else
6382 s->defstate = SS_UNDEFINED;
6385 else if (s->defstate == SS_UNKNOWN)
6387 s->defstate = rec->defstate;
6389 else
6391 ; /* no change */
6394 if (s->defstate == SS_UNDEFINED)
6396 ctype rt = ctype_realType (s->type);
6398 if (ctype_isArray (rt) || ctype_isSU (rt))
6400 s->defstate = SS_ALLOCATED;
6404 sRef_addDeriv (rec, s);
6405 DPRINTF (("Add deriv: %s", sRef_unparseFull (rec)));
6407 if (ctype_isInt (s->type) && cstring_equal (f, REFSNAME))
6409 s->aliaskind = AK_REFS;
6410 s->oaliaskind = AK_REFS;
6413 DPRINTF (("Build field ==> %s", sRef_unparseFull (s)));
6414 return s;
6418 bool
6419 sRef_isStackAllocated (sRef s)
6421 return (sRef_isReasonable(s)
6422 && s->defstate == SS_ALLOCATED && ctype_isStackAllocated (s->type));
6425 static
6426 void sRef_setArrayFetchState (/*@notnull@*/ /*@exposed@*/ sRef s,
6427 /*@notnull@*/ /*@exposed@*/ sRef arr)
6429 sRef_checkMutable (s);
6431 if (ctype_isRealAP (arr->type))
6433 s->type = ctype_baseArrayPtr (arr->type);
6436 /* a hack, methinks... makeArrayFetch (&a[0]) ==> a[] */
6437 /* evans - 2001-08-27: not sure where this was necessary - it
6438 ** causes an assertion in in aliasCheckPred to fail.
6441 if (sRef_isAddress (arr))
6443 sRef t = arr->info->ref;
6445 if (sRef_isArrayFetch (t))
6447 s->info->arrayfetch->arr = t->info->arrayfetch->arr;
6450 else if (ctype_isRealPointer (arr->type))
6452 sRef sp = sRef_findDerivedPointer (arr);
6454 if (sRef_isReasonable (sp))
6457 if (ctype_isMutable (s->type))
6459 s->expkind = sRef_getExKind (sp);
6460 s->expinfo = stateInfo_copy (sp->expinfo);
6462 s->aliaskind = sp->aliaskind;
6463 s->aliasinfo = stateInfo_copy (sp->aliasinfo);
6466 s->defstate = sp->defstate;
6468 if (s->defstate == SS_DEFINED)
6470 if (!context_getFlag (FLG_STRICTDESTROY))
6472 s->defstate = SS_PARTIAL;
6476 DPRINTF (("Set null state: %s / %s", sRef_unparseFull (s), sRef_unparseFull (sp)));
6477 sRef_setNullStateN (s, sRef_getNullState (sp));
6479 else
6481 if (arr->defstate == SS_UNDEFINED)
6483 s->defstate = SS_UNUSEABLE;
6485 else if ((arr->defstate == SS_ALLOCATED) && !ctype_isSU (s->type))
6487 s->defstate = SS_UNDEFINED;
6489 else
6491 if (!context_getFlag (FLG_STRICTDESTROY))
6493 s->defstate = SS_PARTIAL;
6495 else
6497 s->defstate = SS_DEFINED;
6501 ** Very weak checking for array elements.
6502 ** Was:
6503 ** s->defstate = arr->defstate;
6507 s->expkind = sRef_getExKind (arr);
6508 s->expinfo = stateInfo_copy (arr->expinfo);
6510 if (arr->aliaskind == AK_LOCAL || arr->aliaskind == AK_FRESH)
6512 s->aliaskind = AK_LOCAL;
6514 else
6516 s->aliaskind = AK_UNKNOWN;
6519 sRef_setTypeState (s);
6522 else
6524 if (arr->defstate == SS_DEFINED)
6527 ** Very weak checking for array elements.
6528 ** Was:
6529 ** s->defstate = arr->defstate;
6532 if (context_getFlag (FLG_STRICTDESTROY))
6534 s->defstate = SS_DEFINED;
6536 else
6538 s->defstate = SS_PARTIAL;
6541 else if (arr->defstate == SS_ALLOCATED)
6543 if (ctype_isRealArray (s->type))
6545 s->defstate = SS_ALLOCATED;
6547 else
6549 if (!s->info->arrayfetch->indknown)
6552 ** is index is unknown, elements is defined or
6553 ** allocated is any element is!
6556 s->defstate = SS_UNDEFINED;
6558 sRefSet_allElements (arr->deriv, sr)
6560 if (sRef_isReasonable (sr))
6562 if (sRef_isReasonable (sr))
6564 if (sr->defstate == SS_ALLOCATED)
6566 s->defstate = SS_ALLOCATED;
6568 else
6570 if (sr->defstate == SS_DEFINED)
6572 if (context_getFlag (FLG_STRICTDESTROY))
6574 s->defstate = SS_DEFINED;
6576 else
6578 s->defstate = SS_PARTIAL;
6581 break;
6585 else
6587 llcontbug (message ("Invalid sRef as derived element of %s", sRef_unparse (arr)));
6590 } end_sRefSet_allElements;
6592 else
6594 s->defstate = SS_UNDEFINED;
6598 else
6600 s->defstate = arr->defstate;
6605 ** kludgey way to guess where aliaskind applies
6608 if (ctype_isMutable (s->type)
6609 && !ctype_isPointer (arr->type)
6610 && !alkind_isStatic (arr->aliaskind)
6611 && !alkind_isStack (arr->aliaskind)) /* evs - 2000-06-20: don't pass stack allocation to members */
6613 s->aliaskind = arr->aliaskind;
6615 else
6617 s->aliaskind = AK_UNKNOWN;
6620 sRef_setTypeState (s);
6623 if (sRef_isObserver (arr))
6625 s->expkind = XO_OBSERVER;
6626 s->expinfo = stateInfo_copy (arr->expinfo);
6630 /*@exposed@*/ sRef sRef_buildArrayFetch (/*@exposed@*/ sRef arr)
6632 sRef s;
6634 if (!sRef_isReasonable (arr)) {
6635 /*@-nullret@*/ return arr /*@=nullret@*/;
6638 if (ctype_isRealPointer (arr->type))
6640 (void) sRef_buildPointer (arr); /* do this to define arr! */
6643 s = sRef_findDerivedArrayFetch (arr, FALSE, 0, FALSE);
6645 if (sRef_isReasonable (s))
6647 /* evans 2001-07-12: this is bogus, clean-up hack */
6648 if (s->info->arrayfetch->arr != arr)
6650 sRef res;
6651 check (sRefSet_delete (arr->deriv, s));
6652 res = sRef_buildArrayFetch (arr);
6653 sRef_copyState (res, s);
6654 llassert (res->info->arrayfetch->arr == arr);
6655 return res;
6658 s->expkind = sRef_getExKind (arr);
6659 s->expinfo = stateInfo_copy (arr->expinfo);
6661 return s;
6663 else
6665 s = sRef_newRef ();
6667 s->kind = SK_ARRAYFETCH;
6668 s->info = (sinfo) dmalloc (sizeof (*s->info));
6669 s->info->arrayfetch = (ainfo) dmalloc (sizeof (*s->info->arrayfetch));
6670 s->info->arrayfetch->indknown = FALSE;
6671 s->info->arrayfetch->ind = 0;
6672 s->info->arrayfetch->arr = arr;
6674 sRef_setArrayFetchState (s, arr);
6676 s->oaliaskind = s->aliaskind;
6677 s->oexpkind = s->expkind;
6679 if (!context_inProtectVars ())
6681 sRef_addDeriv (arr, s);
6684 if (valueTable_isUndefined (s->state))
6686 s->state = context_createValueTable
6687 (s, stateInfo_makeLoc (g_currentloc, SA_CREATED));
6690 return (s);
6694 /*@exposed@*/ sRef
6695 sRef_buildArrayFetchKnown (/*@exposed@*/ sRef arr, int i)
6697 sRef s;
6699 if (!sRef_isReasonable (arr)) {
6700 /*@-nullret@*/ return arr /*@=nullret@*/;
6703 if (ctype_isRealPointer (arr->type))
6705 (void) sRef_buildPointer (arr); /* do this to define arr! */
6708 s = sRef_findDerivedArrayFetch (arr, TRUE, i, FALSE);
6710 if (sRef_isReasonable (s))
6712 /* evans 2001-07-12: this is bogus, clean-up hack */
6713 if (s->info->arrayfetch->arr != arr)
6715 sRef res;
6717 check (sRefSet_delete (arr->deriv, s));
6718 res = sRef_buildArrayFetchKnown (arr, i);
6720 llassert (res->info->arrayfetch->arr == arr);
6721 sRef_copyState (res, s);
6722 llassert (res->info->arrayfetch->arr == arr);
6723 return res;
6726 s->expkind = sRef_getExKind (arr);
6727 s->expinfo = stateInfo_copy (arr->expinfo);
6729 llassert (s->info->arrayfetch->arr == arr);
6730 return s;
6732 else
6734 s = sRef_newRef ();
6736 s->kind = SK_ARRAYFETCH;
6737 s->info = (sinfo) dmalloc (sizeof (*s->info));
6738 s->info->arrayfetch = (ainfo) dmalloc (sizeof (*s->info->arrayfetch));
6739 s->info->arrayfetch->arr = arr;
6740 s->info->arrayfetch->indknown = TRUE;
6741 s->info->arrayfetch->ind = i;
6743 sRef_setArrayFetchState (s, arr);
6744 /* evans 2001-08-27 no: can change this - llassert (s->info->arrayfetch->arr == arr); */
6746 s->oaliaskind = s->aliaskind;
6747 s->oexpkind = s->expkind;
6748 sRef_addDeriv (arr, s);
6750 llassert (valueTable_isUndefined (s->state));
6751 s->state = context_createValueTable (s, stateInfo_makeLoc (g_currentloc, SA_CREATED));
6752 return (s);
6757 ** sets everything except for defstate
6760 static void
6761 sRef_setPartsFromUentry (sRef s, uentry ue)
6763 sRef uref = uentry_getSref (ue);
6765 llassert (sRef_isReasonable (s));
6767 s->aliaskind = alkind_derive (s->aliaskind, uentry_getAliasKind (ue));
6768 s->oaliaskind = s->aliaskind;
6770 if (s->expkind == XO_UNKNOWN)
6772 s->expkind = uentry_getExpKind (ue);
6775 s->oexpkind = s->expkind;
6777 if (sRef_getNullState (s) == NS_UNKNOWN)
6779 DPRINTF (("Set null state: %s / %s", sRef_unparseFull (s), uentry_unparseFull (ue)));
6780 sRef_setNullStateN (s, sRef_getNullState (uentry_getSref (ue)));
6782 else
6784 DPRINTF (("Skipping null null state!"));
6787 if (s->aliaskind == AK_IMPONLY && (sRef_isExposed (s) || sRef_isObserver (s)))
6789 s->oaliaskind = s->aliaskind = AK_IMPDEPENDENT;
6792 if (sRef_isReasonable (uref))
6794 valueTable utable = uref->state;
6795 valueTable_free (s->state);
6796 s->state = valueTable_copy (utable);
6800 static void
6801 sRef_setStateFromAbstractUentry (sRef s, uentry ue)
6803 llassert (sRef_isReasonable (s));
6804 sRef_checkMutable (s);
6806 sRef_setPartsFromUentry (s, ue);
6808 s->aliaskind = alkind_derive (s->aliaskind, uentry_getAliasKind (ue));
6809 s->oaliaskind = s->aliaskind;
6811 if (s->expkind == XO_UNKNOWN)
6813 s->expkind = uentry_getExpKind (ue);
6816 s->oexpkind = s->expkind;
6819 void
6820 sRef_setStateFromUentry (sRef s, uentry ue)
6822 sstate defstate;
6824 sRef_checkMutable (s);
6825 llassert (sRef_isReasonable (s));
6827 sRef_setPartsFromUentry (s, ue);
6829 defstate = uentry_getDefState (ue);
6831 if (sstate_isKnown (defstate))
6833 s->defstate = defstate;
6835 else
6841 /*@exposed@*/ sRef
6842 sRef_buildPointer (/*@exposed@*/ sRef t)
6844 DPRINTF (("build pointer: %s", sRef_unparse (t)));
6846 if (sRef_isInvalid (t)) return sRef_undefined;
6848 if (sRef_isAddress (t))
6850 DPRINTF (("Return ref: %s", sRef_unparse (t->info->ref)));
6851 return (t->info->ref);
6853 else
6855 sRef s = sRef_findDerivedPointer (t);
6857 DPRINTF (("find derived: %s", sRef_unparse (s)));
6859 if (sRef_isReasonable (s))
6861 s->expkind = sRef_getExKind (t);
6862 s->expinfo = stateInfo_copy (t->expinfo);
6864 s->oaliaskind = s->aliaskind;
6865 s->oexpkind = s->expkind;
6867 return s;
6869 else
6871 s = sRef_constructPointerAux (t);
6873 DPRINTF (("construct: %s", sRef_unparse (s)));
6875 if (sRef_isReasonable (s))
6877 sRef_addDeriv (t, s);
6879 s->oaliaskind = s->aliaskind;
6880 s->oexpkind = s->expkind;
6883 return s;
6888 /*@exposed@*/ sRef
6889 sRef_constructPointer (/*@exposed@*/ sRef t)
6890 /*@modifies t@*/
6892 return sRef_buildPointer (t);
6895 static /*@exposed@*/ sRef sRef_constructDerefAux (sRef t, bool isdead)
6897 if (sRef_isReasonable (t))
6899 sRef s;
6902 ** if there is a derived t[?], return that. Otherwise, *t.
6905 s = sRef_findDerivedArrayFetch (t, FALSE, 0, isdead);
6907 if (sRef_isReasonable (s))
6909 DPRINTF (("Found array fetch: %s", sRef_unparseFull (s)));
6910 return s;
6912 else
6914 sRef ret = sRef_constructPointer (t);
6916 DPRINTF (("Constructed pointer: %s", sRef_unparseFull (ret)));
6918 return ret;
6921 else
6923 return sRef_undefined;
6927 sRef sRef_constructDeref (sRef t)
6929 return sRef_constructDerefAux (t, FALSE);
6932 sRef sRef_constructDeadDeref (sRef t)
6934 return sRef_constructDerefAux (t, TRUE);
6937 static sRef
6938 sRef_constructPointerAux (/*@notnull@*/ /*@exposed@*/ sRef t)
6940 sRef s = sRef_newRef ();
6941 ctype rt = t->type;
6942 ctype st;
6944 llassert (valueTable_isUndefined (s->state));
6946 s->kind = SK_PTR;
6947 s->info = (sinfo) dmalloc (sizeof (*s->info));
6948 s->info->ref = t;
6950 if (ctype_isRealAP (rt))
6952 s->type = ctype_baseArrayPtr (rt);
6955 st = ctype_realType (s->type);
6957 if (t->defstate == SS_UNDEFINED)
6959 s->defstate = SS_UNUSEABLE;
6960 s->definfo = stateInfo_copy (t->definfo);
6962 else if ((t->defstate == SS_ALLOCATED) && !ctype_isSU (st))
6964 s->defstate = SS_UNDEFINED;
6965 s->definfo = stateInfo_copy (t->definfo);
6967 else
6969 s->defstate = t->defstate;
6970 s->definfo = stateInfo_copy (t->definfo);
6973 if (t->aliaskind == AK_LOCAL || t->aliaskind == AK_FRESH)
6975 s->aliaskind = AK_LOCAL;
6977 else
6979 s->aliaskind = AK_UNKNOWN;
6982 s->expkind = sRef_getExKind (t);
6983 s->expinfo = stateInfo_copy (t->expinfo);
6985 sRef_setTypeState (s);
6987 s->oaliaskind = s->aliaskind;
6988 s->oexpkind = s->expkind;
6990 if (valueTable_isUndefined (s->state))
6992 s->state = context_createValueTable (s, stateInfo_makeLoc (g_currentloc, SA_CREATED));
6995 DPRINTF (("pointer: %s", sRef_unparseFull (s)));
6996 return s;
6999 bool sRef_hasDerived (sRef s)
7001 return (sRef_isReasonable (s) && !sRefSet_isEmpty (s->deriv));
7004 void
7005 sRef_clearDerived (sRef s)
7007 if (sRef_isReasonable (s))
7009 DPRINTF (("Clear derived: [%p] %s", s, sRef_unparseDebug (s)));
7010 sRefSet_clear (s->deriv);
7014 void
7015 sRef_clearDerivedComplete (sRef s)
7017 if (sRef_isReasonable (s))
7019 sRef base = sRef_getBaseSafe (s);
7021 while (sRef_isReasonable (base))
7023 DPRINTF (("Clear derived: [%p] %s", base, sRef_unparse (base)));
7024 sRefSet_clear (base->deriv);
7025 base = sRef_getBaseSafe (base);
7028 DPRINTF (("Clear derived: [%p] %s", s, sRef_unparse (s)));
7029 sRefSet_clear (s->deriv);
7033 /*@exposed@*/ sRef sRef_makePointer (/*@exposed@*/ sRef s)
7034 /*@modifies s@*/
7036 sRef res = sRef_buildPointer (s);
7038 DPRINTF (("Res: %s", sRef_unparseFull (res)));
7039 return res;
7043 ** &a[] => a (this is for out params)
7046 /*@exposed@*/ sRef
7047 sRef_makeAnyArrayFetch (/*@exposed@*/ sRef arr)
7049 if (sRef_isAddress (arr))
7051 return (arr->info->ref);
7053 else
7055 return (sRef_buildArrayFetch (arr));
7059 /*@exposed@*/ sRef
7060 sRef_makeArrayFetch (/*@exposed@*/ sRef arr)
7062 return (sRef_buildArrayFetch (arr));
7065 /*@exposed@*/ sRef
7066 sRef_makeArrayFetchKnown (/*@exposed@*/ sRef arr, int i)
7068 return (sRef_buildArrayFetchKnown (arr, i));
7071 /*@exposed@*/ sRef
7072 sRef_makeField (sRef rec, /*@dependent@*/ cstring f)
7074 sRef ret;
7075 ret = sRef_buildField (rec, f);
7076 return ret;
7079 /*@exposed@*/ sRef
7080 sRef_makeNCField (/*@exposed@*/ sRef rec, /*@dependent@*/ cstring f)
7082 return (sRef_buildNCField (rec, f));
7085 /*@only@*/ cstring
7086 sRef_unparseKindName (sRef s)
7088 cstring result;
7090 if (s == sRef_undefined) return cstring_makeLiteral ("<invalid>");
7092 s = sRef_fixConj (s);
7094 switch (s->kind)
7096 case SK_CVAR:
7097 if (sRef_isLocalVar (s))
7099 result = cstring_makeLiteral ("Variable");
7101 else
7103 result = cstring_makeLiteral ("Undef global");
7105 break;
7106 case SK_PARAM:
7107 result = cstring_makeLiteral ("Out parameter");
7108 break;
7109 case SK_ARRAYFETCH:
7110 if (sRef_isAnyParam (s->info->arrayfetch->arr))
7112 result = cstring_makeLiteral ("Out parameter");
7114 else if (sRef_isIndexKnown (s))
7116 result = cstring_makeLiteral ("Array element");
7118 else
7120 result = cstring_makeLiteral ("Value");
7122 break;
7123 case SK_PTR:
7124 if (sRef_isAnyParam (s->info->ref))
7126 result = cstring_makeLiteral ("Out parameter");
7128 else
7130 result = cstring_makeLiteral ("Value");
7132 break;
7133 case SK_ADR:
7134 result = cstring_makeLiteral ("Value");
7135 break;
7136 case SK_FIELD:
7137 result = cstring_makeLiteral ("Field");
7138 break;
7139 case SK_OBJECT:
7140 result = cstring_makeLiteral ("Object");
7141 break;
7142 case SK_UNCONSTRAINED:
7143 result = cstring_makeLiteral ("<anything>");
7144 break;
7145 case SK_RESULT:
7146 case SK_SPECIAL:
7147 case SK_UNKNOWN:
7148 case SK_EXTERNAL:
7149 case SK_DERIVED:
7150 case SK_CONST:
7151 case SK_TYPE:
7152 result = cstring_makeLiteral ("<unknown>");
7153 break;
7154 case SK_CONJ:
7155 result = cstring_makeLiteral ("<conj>");
7156 break;
7157 case SK_NEW:
7158 result = cstring_makeLiteral ("Storage");
7159 break;
7162 return result;
7165 /*@only@*/ cstring
7166 sRef_unparseKindNamePlain (sRef s)
7168 cstring result;
7170 if (s == sRef_undefined) return cstring_makeLiteral ("<invalid>");
7172 s = sRef_fixConj (s);
7174 switch (s->kind)
7176 case SK_CVAR:
7177 if (sRef_isLocalVar (s))
7179 result = cstring_makeLiteral ("Variable");
7181 else
7183 result = cstring_makeLiteral ("Global");
7185 break;
7186 case SK_PARAM:
7187 result = cstring_makeLiteral ("Parameter");
7188 break;
7189 case SK_ARRAYFETCH:
7190 if (sRef_isAnyParam (s->info->arrayfetch->arr))
7192 result = cstring_makeLiteral ("Parameter");
7194 else if (sRef_isIndexKnown (s))
7196 result = cstring_makeLiteral ("Array element");
7198 else
7200 result = cstring_makeLiteral ("Value");
7202 break;
7203 case SK_PTR:
7204 if (sRef_isAnyParam (s->info->ref))
7206 result = cstring_makeLiteral ("Parameter");
7208 else
7210 result = cstring_makeLiteral ("Value");
7212 break;
7213 case SK_ADR:
7214 result = cstring_makeLiteral ("Value");
7215 break;
7216 case SK_FIELD:
7217 result = cstring_makeLiteral ("Field");
7218 break;
7219 case SK_OBJECT:
7220 result = cstring_makeLiteral ("Object");
7221 break;
7222 case SK_NEW:
7223 result = cstring_makeLiteral ("Storage");
7224 break;
7225 case SK_UNCONSTRAINED:
7226 result = cstring_makeLiteral ("<anything>");
7227 break;
7228 case SK_RESULT:
7229 case SK_TYPE:
7230 case SK_CONST:
7231 case SK_EXTERNAL:
7232 case SK_DERIVED:
7233 case SK_UNKNOWN:
7234 case SK_SPECIAL:
7235 result = cstring_makeLiteral ("<unknown>");
7236 break;
7237 case SK_CONJ:
7238 result = cstring_makeLiteral ("<conj>");
7239 break;
7242 return result;
7246 ** s1 <- s2
7249 void
7250 sRef_copyState (sRef s1, sRef s2)
7252 if (sRef_isReasonable (s1) && sRef_isReasonable (s2))
7254 s1->defstate = s2->defstate;
7256 /* start modifications */
7257 s1->bufinfo.bufstate = s2->bufinfo.bufstate;
7258 s1->bufinfo.len = s2->bufinfo.len;
7259 s1->bufinfo.size = s2->bufinfo.size;
7260 /* end modifications */
7262 s1->aliaskind = s2->aliaskind;
7263 s1->aliasinfo = stateInfo_update (s1->aliasinfo, s2->aliasinfo);
7265 s1->expkind = s2->expkind;
7266 s1->expinfo = stateInfo_update (s1->expinfo, s2->expinfo);
7268 s1->nullstate = s2->nullstate;
7269 DPRINTF (("Set null state==> %s", sRef_unparseFull (s1)));
7270 s1->nullinfo = stateInfo_update (s1->nullinfo, s2->nullinfo);
7272 valueTable_free (s1->state);
7273 s1->state = valueTable_copy (s2->state);
7274 s1->safe = s2->safe;
7278 sRef
7279 sRef_makeNew (ctype ct, sRef t, cstring name)
7281 sRef s = sRef_newRef ();
7283 s->kind = SK_NEW;
7284 s->type = ct;
7286 llassert (sRef_isReasonable (t));
7287 s->defstate = t->defstate;
7289 s->aliaskind = t->aliaskind;
7290 s->oaliaskind = s->aliaskind;
7291 s->nullstate = t->nullstate;
7293 s->expkind = t->expkind;
7294 s->oexpkind = s->expkind;
7296 s->info = (sinfo) dmalloc (sizeof (*s->info));
7297 s->info->fname = name;
7299 /* start modifications */
7300 s->bufinfo.bufstate = t->bufinfo.bufstate;
7301 /* end modifications */
7303 llassert (valueTable_isUndefined (s->state));
7304 s->state = valueTable_copy (t->state);
7306 DPRINTF (("==> Copying state: %s", valueTable_unparse (s->state)));
7307 DPRINTF (("==> new: %s", sRef_unparseFull (s)));
7308 return s;
7311 sRef
7312 sRef_makeType (ctype ct)
7314 sRef s = sRef_newRef ();
7316 sRef_checkMutable (s);
7318 s->kind = SK_TYPE;
7319 s->type = ct;
7321 s->defstate = SS_UNKNOWN;
7322 s->aliaskind = AK_UNKNOWN;
7323 sRef_setNullStateN (s, NS_UNKNOWN);
7325 /* start modification */
7326 s->bufinfo.bufstate = BB_NOTNULLTERMINATED;
7327 /* end modification */
7330 if (ctype_isUA (ct))
7332 typeId uid = ctype_typeId (ct);
7333 uentry ue = usymtab_getTypeEntrySafe (uid);
7335 if (uentry_isValid (ue))
7337 sRef_mergeStateQuiet (s, uentry_getSref (ue));
7341 s->oaliaskind = s->aliaskind;
7342 s->oexpkind = s->expkind;
7343 llassert (valueTable_isUndefined (s->state));
7344 s->state = context_createValueTable (s, stateInfo_makeLoc (g_currentloc, SA_CREATED));
7346 DPRINTF (("Create: %s", sRef_unparseFull (s)));
7347 return s;
7350 sRef
7351 sRef_makeConst (ctype ct)
7353 sRef s = sRef_newRef ();
7355 s->kind = SK_CONST;
7356 s->type = ct;
7358 s->defstate = SS_UNKNOWN;
7359 s->aliaskind = AK_UNKNOWN;
7360 sRef_setNullStateN (s, NS_UNKNOWN);
7362 /* start modification */
7363 s->bufinfo.bufstate = BB_NULLTERMINATED;
7364 /* end modification */
7366 /* evans 2002-04-22: added isManifestBool to avoid errors for -boolfalse initializations */
7367 if (!ctype_isManifestBool (ct) && ctype_isUA (ct))
7369 typeId uid = ctype_typeId (ct);
7370 uentry te = usymtab_getTypeEntrySafe (uid);
7372 if (uentry_isValid (te))
7374 sRef_mergeStateQuiet (s, uentry_getSref (te));
7378 s->oaliaskind = s->aliaskind;
7379 s->oexpkind = s->expkind;
7381 llassert (valueTable_isUndefined (s->state));
7382 s->state = context_createValueTable (s, stateInfo_makeLoc (g_currentloc, SA_CREATED));
7384 return s;
7387 bool sRef_hasName (sRef s)
7389 if (sRef_isInvalid (s))
7391 return (FALSE);
7394 switch (s->kind)
7396 case SK_CVAR:
7398 uentry u = usymtab_getRefQuiet (s->info->cvar->lexlevel,
7399 s->info->cvar->index);
7400 return (uentry_hasName (u));
7402 case SK_PARAM:
7404 if (s->info->paramno >= 0)
7406 uentry u = uentryList_getN (context_getParams (),
7407 s->info->paramno);
7409 return (uentry_hasName (u));
7411 else
7413 llassert (s->info->paramno == PARAMUNKNOWN);
7414 return FALSE;
7417 default:
7418 return TRUE;
7422 bool
7423 sRef_sameName (sRef s1, sRef s2)
7425 if (sRef_isInvalid (s1))
7427 return sRef_isInvalid (s2);
7430 if (sRef_isInvalid (s2))
7432 return (FALSE);
7435 switch (s1->kind)
7437 case SK_CVAR:
7438 if (s2->kind == SK_CVAR)
7440 return (s1->info->cvar->lexlevel == s2->info->cvar->lexlevel
7441 && s1->info->cvar->index == s2->info->cvar->index);
7443 else if (s2->kind == SK_PARAM)
7445 if (context_inFunctionLike ())
7447 if (s2->info->paramno != PARAMUNKNOWN)
7449 uentry u1 = usymtab_getRefQuiet (s1->info->cvar->lexlevel,
7450 s1->info->cvar->index);
7451 uentry u2 = uentryList_getN (context_getParams (),
7452 s2->info->paramno);
7454 return (cstring_equalFree (uentry_getName (u1),
7455 uentry_getName (u2)));
7457 else
7459 return s1->info->paramno == PARAMUNKNOWN;
7462 else
7464 return FALSE;
7467 else
7469 return FALSE;
7471 case SK_PARAM:
7473 if (s2->kind == SK_PARAM)
7475 return (s1->info->paramno == s2->info->paramno);
7477 else if (s2->kind == SK_CVAR)
7479 if (context_inFunctionLike ())
7481 if (s1->info->paramno == PARAMUNKNOWN)
7483 return FALSE;
7485 else
7487 uentry u1 = uentryList_getN (context_getParams (),
7488 s1->info->paramno);
7489 uentry u2 = usymtab_getRefQuiet (s2->info->cvar->lexlevel,
7490 s2->info->cvar->index);
7493 return (cstring_equalFree (uentry_getName (u1),
7494 uentry_getName (u2)));
7497 else
7499 return FALSE;
7502 else
7504 return FALSE;
7508 case SK_UNCONSTRAINED:
7509 return FALSE;
7511 case SK_ARRAYFETCH:
7512 if (s2->kind == SK_ARRAYFETCH)
7514 if (bool_equal (s1->info->arrayfetch->indknown,
7515 s2->info->arrayfetch->indknown))
7517 if (!s1->info->arrayfetch->indknown
7518 || (s1->info->arrayfetch->ind == s2->info->arrayfetch->ind))
7520 return sRef_sameName (s1->info->arrayfetch->arr,
7521 s2->info->arrayfetch->arr);
7526 return FALSE;
7527 case SK_FIELD:
7528 if (s2->kind == SK_FIELD)
7530 if (cstring_equal (s1->info->field->field,
7531 s2->info->field->field))
7533 return sRef_sameName (s1->info->field->rec,
7534 s2->info->field->rec);
7538 return FALSE;
7539 case SK_PTR:
7540 case SK_ADR:
7541 case SK_DERIVED:
7542 case SK_EXTERNAL:
7543 if (s2->kind == s1->kind)
7545 return sRef_sameName (s1->info->ref,
7546 s2->info->ref);
7549 return FALSE;
7550 case SK_OBJECT:
7551 return FALSE;
7552 case SK_CONJ:
7553 return sRef_sameName (sRef_getConjA (s1), s2);
7554 case SK_NEW:
7555 return FALSE;
7556 case SK_UNKNOWN:
7557 return (s2->kind == SK_UNKNOWN);
7558 case SK_TYPE:
7559 case SK_CONST:
7560 if (s2->kind == s1->kind)
7562 return (ctype_equal (s1->type, s2->type));
7565 return FALSE;
7566 case SK_SPECIAL:
7567 if (s2->kind == SK_SPECIAL)
7569 return (s1->info->spec == s2->info->spec);
7571 return FALSE;
7572 case SK_RESULT:
7573 return (s2->kind == SK_RESULT);
7574 default:
7575 return FALSE;
7577 BADEXIT;
7580 sRef
7581 sRef_fixOuterRef (/*@returned@*/ sRef s)
7583 sRef root = sRef_getRootBase (s);
7585 if (sRef_isCvar (root))
7587 uentry ue = usymtab_getRefQuiet (root->info->cvar->lexlevel,
7588 root->info->cvar->index);
7590 if (uentry_isValid (ue))
7592 sRef uref = uentry_getSref (ue);
7593 sRef sr = sRef_fixBase (s, uref);
7595 return (sr);
7597 else
7599 llcontbug (message ("sRef_fixOuterRef: undefined: %q", sRef_unparseDebug (s)));
7600 return (s);
7604 return (s);
7607 void
7608 sRef_storeState (sRef s)
7610 if (sRef_isInvalid (s)) return;
7612 sRef_checkMutable (s);
7613 s->oaliaskind = s->aliaskind;
7614 s->oexpkind = s->expkind;
7617 static void sRef_resetStateAux (sRef s, /*@unused@*/ fileloc loc)
7619 sRef_resetState (s);
7622 void
7623 sRef_resetState (sRef s)
7625 bool changed = FALSE;
7626 if (sRef_isInvalid (s)) return;
7629 if (s->oaliaskind == AK_KILLREF && !sRef_isParam (s))
7632 ** killref is used in a kludgey way, to save having to add
7633 ** another alias kind (see usymtab_handleParams)
7636 if (s->expkind != s->oexpkind)
7638 changed = TRUE;
7639 s->expkind = s->oexpkind;
7642 else
7644 if (s->expkind != s->oexpkind)
7646 changed = TRUE;
7647 s->expkind = s->oexpkind;
7650 if (s->aliaskind != s->oaliaskind
7651 && s->aliaskind != AK_REFCOUNTED
7652 && s->aliaskind != AK_REFS)
7654 changed = TRUE;
7655 s->aliaskind = s->oaliaskind;
7659 if (changed)
7661 sRef_clearDerived (s);
7666 void
7667 sRef_resetStateComplete (sRef s)
7669 sRef_innerAliasSetComplete (sRef_resetStateAux, s, fileloc_undefined);
7672 /*@exposed@*/ sRef
7673 sRef_fixBase (/*@returned@*/ sRef s, /*@returned@*/ sRef base)
7675 sRef tmp = sRef_undefined;
7676 sRef ret;
7678 if (sRef_isInvalid (s)) return s;
7679 if (sRef_isInvalid (base)) return base;
7681 switch (s->kind)
7683 case SK_RESULT:
7684 case SK_PARAM:
7685 case SK_CVAR:
7686 ret = base;
7687 break;
7688 case SK_ARRAYFETCH:
7689 tmp = sRef_fixBase (s->info->arrayfetch->arr, base);
7691 if (s->info->arrayfetch->indknown)
7693 ret = sRef_makeArrayFetchKnown (tmp, s->info->arrayfetch->ind);
7695 else
7697 ret = sRef_makeArrayFetch (tmp);
7699 break;
7700 case SK_FIELD:
7701 tmp = sRef_fixBase (s->info->field->rec, base);
7702 ret = sRef_buildNCField (tmp, s->info->field->field);
7703 break;
7704 case SK_PTR:
7705 tmp = sRef_fixBase (s->info->ref, base);
7706 ret = sRef_makePointer (tmp);
7707 break;
7708 case SK_ADR:
7709 tmp = sRef_fixBase (s->info->ref, base);
7710 ret = sRef_makeAddress (tmp);
7711 break;
7712 case SK_CONJ:
7714 sRef tmpb;
7716 tmp = sRef_fixBase (s->info->conj->a, base);
7717 tmpb = sRef_fixBase (s->info->conj->b, base);
7719 ret = sRef_makeConj (tmp, tmpb);
7720 break;
7722 BADDEFAULT;
7725 return ret;
7728 static /*@exposed@*/ sRef
7729 sRef_fixDirectBase (sRef s, sRef base)
7731 sRef ret;
7734 if (sRef_isInvalid (s))
7736 return sRef_undefined;
7739 switch (s->kind)
7741 case SK_ARRAYFETCH:
7742 if (s->info->arrayfetch->indknown)
7744 ret = sRef_makeArrayFetchKnown (base, s->info->arrayfetch->ind);
7746 else
7748 ret = sRef_makeArrayFetch (base);
7750 break;
7751 case SK_FIELD:
7752 ret = sRef_buildNCField (base, s->info->field->field);
7753 break;
7754 case SK_PTR:
7755 ret = sRef_makePointer (base);
7756 break;
7757 case SK_ADR:
7758 ret = sRef_makeAddress (base);
7759 break;
7760 case SK_CONJ:
7762 sRef tmpa, tmpb;
7764 tmpa = sRef_fixDirectBase (s->info->conj->a, base);
7765 tmpb = sRef_fixDirectBase (s->info->conj->b, base);
7767 ret = sRef_makeConj (tmpa, tmpb);
7768 break;
7770 BADDEFAULT;
7773 sRef_copyState (ret, s);
7774 return ret;
7777 bool
7778 sRef_isAllocIndexRef (sRef s)
7780 return (sRef_isArrayFetch (s) && !(s->info->arrayfetch->indknown)
7781 && sRef_isAllocated (s->info->arrayfetch->arr));
7784 void
7785 sRef_showRefLost (sRef s)
7787 if (sRef_hasAliasInfoLoc (s))
7789 llgenindentmsg (cstring_makeLiteral ("Original reference lost"),
7790 sRef_getAliasInfoLoc (s));
7794 void
7795 sRef_showRefKilled (sRef s)
7797 if (sRef_isValid (s))
7799 DPRINTF (("Killed: %s", sRef_unparseFull (s)));
7800 if (context_getLocIndentSpaces () == 0) {
7801 stateInfo_display (s->definfo, message (" Storage %q", sRef_unparseOpt (s)));
7802 } else {
7803 stateInfo_display (s->definfo, message ("Storage %q", sRef_unparseOpt (s)));
7808 void
7809 sRef_showStateInconsistent (sRef s)
7811 if (sRef_hasStateInfoLoc (s))
7813 llgenindentmsg
7814 (message ("Storage %qbecomes inconsistent (released on one branch)",
7815 sRef_unparseOpt (s)),
7816 sRef_getStateInfoLoc (s));
7820 void
7821 sRef_showStateInfo (sRef s)
7823 if (sRef_isValid (s)) {
7824 if (context_getLocIndentSpaces () == 0) {
7825 stateInfo_display (s->definfo, message (" Storage %q", sRef_unparseOpt (s)));
7826 } else {
7827 stateInfo_display (s->definfo, message ("Storage %q", sRef_unparseOpt (s)));
7832 void
7833 sRef_showExpInfo (sRef s)
7835 if (sRef_isValid (s)) {
7836 if (context_getLocIndentSpaces () == 0) {
7837 stateInfo_display (s->expinfo, message (" Storage %q", sRef_unparseOpt (s)));
7838 } else {
7839 stateInfo_display (s->expinfo, message ("Storage %q", sRef_unparseOpt (s)));
7844 void
7845 sRef_showMetaStateInfo (sRef s, cstring key)
7847 stateValue val;
7848 metaStateInfo minfo = context_lookupMetaStateInfo (key);
7850 llassert (sRef_isReasonable (s));
7851 llassert (valueTable_isDefined (s->state));
7852 llassert (metaStateInfo_isDefined (minfo));
7854 val = valueTable_lookup (s->state, key);
7856 if (stateValue_hasLoc (val))
7858 llgenindentmsg
7859 (message ("%qbecomes %q", sRef_unparseOpt (s),
7860 stateValue_unparseValue (val, minfo)),
7861 stateValue_getLoc (val));
7865 void
7866 sRef_showNullInfo (sRef s)
7868 DPRINTF (("Show null info: %s", sRef_unparseFull (s)));
7870 if (sRef_hasNullInfoLoc (s) && sRef_isKnown (s))
7872 DPRINTF (("has null info: %s",
7873 fileloc_unparse (sRef_getNullInfoLoc (s))));
7875 switch (sRef_getNullState (s))
7877 case NS_CONSTNULL:
7879 fileloc loc = sRef_getNullInfoLoc (s);
7881 if (fileloc_isDefined (loc) && !fileloc_isLib (loc))
7883 llgenindentmsg
7884 (message ("Storage %qbecomes null", sRef_unparseOpt (s)),
7885 loc);
7887 break;
7889 case NS_DEFNULL:
7891 fileloc loc = sRef_getNullInfoLoc (s);
7893 if (fileloc_isDefined (loc) && !fileloc_isLib (loc))
7895 llgenindentmsg (message ("Storage %qbecomes null", sRef_unparseOpt (s)),
7896 loc);
7898 break;
7900 case NS_ABSNULL:
7901 case NS_POSNULL:
7902 llgenindentmsg
7903 (message ("Storage %qmay become null", sRef_unparseOpt (s)),
7904 sRef_getNullInfoLoc (s));
7905 break;
7906 case NS_NOTNULL:
7907 case NS_MNOTNULL:
7908 llgenindentmsg
7909 (message ("Storage %qbecomes not null", sRef_unparseOpt (s)),
7910 sRef_getNullInfoLoc (s));
7911 break;
7912 case NS_UNKNOWN:
7913 llgenindentmsg
7914 (message ("Storage %qnull state becomes unknown",
7915 sRef_unparseOpt (s)),
7916 sRef_getNullInfoLoc (s));
7917 break;
7919 case NS_ERROR:
7920 BADBRANCHCONT;
7921 break;
7923 default:
7924 llgenindentmsg
7925 (message ("<error case> Storage %q becomes %s",
7926 sRef_unparse (s),
7927 nstate_unparse (sRef_getNullState (s))),
7928 sRef_getNullInfoLoc (s));
7930 break;
7935 void
7936 sRef_showAliasInfo (sRef s)
7938 if (sRef_isValid (s))
7940 if (sRef_isFresh (s))
7942 if (context_getLocIndentSpaces () == 0) {
7943 stateInfo_display (s->aliasinfo, message (" Fresh storage %q", sRef_unparseOpt (s)));
7944 } else {
7945 stateInfo_display (s->aliasinfo, message ("Fresh storage %q", sRef_unparseOpt (s)));
7948 else
7950 if (context_getLocIndentSpaces () == 0) {
7951 stateInfo_display (s->aliasinfo, message (" Storage %q", sRef_unparseOpt (s)));
7952 } else {
7953 stateInfo_display (s->aliasinfo, message ("Storage %q", sRef_unparseOpt (s)));
7959 void
7960 sRef_mergeNullState (sRef s, nstate n)
7962 if (sRef_isReasonable (s))
7964 nstate old;
7966 old = sRef_getNullState (s);
7968 if (n != old && n != NS_UNKNOWN)
7970 sRef_setNullState (s, n, g_currentloc);
7973 else
7975 llbuglit ("sRef_mergeNullState: invalid");
7979 bool
7980 sRef_possiblyNull (sRef s)
7982 if (sRef_isReasonable (s))
7984 if (sRef_getNullState (s) == NS_ABSNULL)
7986 ctype rct = ctype_realType (s->type);
7988 if (ctype_isAbstract (rct))
7990 return FALSE;
7992 else
7994 if (ctype_isUser (rct))
7996 uentry ue = usymtab_getTypeEntry (ctype_typeId (rct));
7998 return (nstate_possiblyNull
7999 (sRef_getNullState (uentry_getSref (ue))));
8001 else
8003 return FALSE;
8007 else
8009 return nstate_possiblyNull (sRef_getNullState (s));
8013 return FALSE;
8016 cstring
8017 sRef_getScopeName (sRef s)
8019 sRef base = sRef_getRootBase (s);
8021 if (sRef_isRealGlobal (base))
8023 return (cstring_makeLiteralTemp ("Global"));
8025 else if (sRef_isFileStatic (base))
8027 return (cstring_makeLiteralTemp ("Static"));
8029 else
8031 return (cstring_makeLiteralTemp ("Local"));
8035 cstring
8036 sRef_unparseScope (sRef s)
8038 sRef base = sRef_getRootBase (s);
8040 if (sRef_isRealGlobal (base))
8042 return (cstring_makeLiteralTemp ("global"));
8044 else if (sRef_isFileStatic (base))
8046 return (cstring_makeLiteralTemp ("file static"));
8048 else
8050 BADEXIT;
8055 sRef_getScope (sRef s)
8057 llassert (sRef_isReasonable (s));
8059 if (sRef_isCvar (s))
8061 return s->info->cvar->lexlevel;
8063 else if (sRef_isParam (s))
8065 return paramsScope;
8067 else
8069 return fileScope;
8073 bool
8074 sRef_isDead (sRef s)
8076 return (sRef_isReasonable (s) && (s)->defstate == SS_DEAD);
8079 bool
8080 sRef_isDeadStorage (sRef s)
8082 if (sRef_isReasonable (s))
8084 if (s->defstate == SS_DEAD
8085 || s->defstate == SS_UNUSEABLE
8086 || s->defstate == SS_UNDEFINED
8087 || s->defstate == SS_UNKNOWN)
8089 return TRUE;
8091 else
8093 return (sRef_isDefinitelyNull (s));
8096 else
8098 return FALSE;
8102 bool
8103 sRef_isPossiblyDead (sRef s)
8105 return (sRef_isReasonable (s) && s->defstate == SS_HOFFA);
8108 bool sRef_isStateLive (sRef s)
8110 if (sRef_isReasonable (s))
8112 sstate ds = s->defstate;
8114 return (!(ds == SS_UNDEFINED
8115 || ds == SS_DEAD
8116 || ds == SS_UNUSEABLE
8117 || ds == SS_HOFFA));
8119 else
8121 return FALSE;
8126 bool sRef_isStateUndefined (sRef s)
8128 return ((sRef_isReasonable(s)) && ((s)->defstate == SS_UNDEFINED));
8131 bool sRef_isJustAllocated (sRef s)
8133 if (sRef_isAllocated (s))
8135 sRefSet_allElements (s->deriv, el)
8137 if (!(sRef_isStateUndefined (el) || sRef_isUnuseable (el)))
8139 return FALSE;
8141 } end_sRefSet_allElements ;
8143 return TRUE;
8146 return FALSE;
8149 static bool
8150 sRef_isAllocatedStorage (sRef s)
8152 if (sRef_isReasonable (s) && ynm_toBoolStrict (sRef_isValidLvalue (s)))
8154 return (ctype_isVisiblySharable (sRef_getType (s)));
8156 else
8158 return FALSE;
8162 bool
8163 sRef_isUnuseable (sRef s)
8165 return ((sRef_isValid(s)) && ((s)->defstate == SS_UNUSEABLE));
8168 bool
8169 sRef_perhapsNull (sRef s)
8171 if (sRef_isReasonable (s))
8173 if (sRef_getNullState (s) == NS_ABSNULL)
8175 ctype rct = ctype_realType (s->type);
8177 if (ctype_isAbstract (rct))
8179 return FALSE;
8181 else
8183 if (ctype_isUser (rct))
8185 uentry ue = usymtab_getTypeEntry (ctype_typeId (rct));
8187 return (nstate_perhapsNull
8188 (sRef_getNullState (uentry_getSref (ue))));
8190 else
8192 return FALSE;
8196 else
8198 return nstate_perhapsNull (sRef_getNullState (s));
8202 return FALSE;
8206 ** definitelyNull --- called when TRUE is good
8209 bool
8210 sRef_definitelyNull (sRef s)
8212 return (sRef_isReasonable (s)
8213 && (sRef_getNullState (s) == NS_DEFNULL || sRef_getNullState (s) == NS_CONSTNULL));
8217 ** based on sRef_similar
8220 void
8221 sRef_setDerivNullState (sRef set, sRef guide, nstate ns)
8223 if (sRef_isReasonable (set))
8225 sRef deriv = sRef_getDeriv (set, guide);
8227 if (sRef_isReasonable (deriv))
8229 sRef_setNullStateN (deriv, ns);
8234 static /*@exposed@*/ sRef
8235 sRef_getDeriv (/*@returned@*/ /*@notnull@*/ sRef set, sRef guide)
8237 llassert (sRef_isReasonable (set));
8238 llassert (sRef_isReasonable (guide));
8240 switch (guide->kind)
8242 case SK_CVAR:
8243 llassert (set->kind == SK_CVAR);
8244 return set;
8246 case SK_PARAM:
8247 llassert (set->kind == guide->kind);
8248 llassert (set->info->paramno == guide->info->paramno);
8249 return set;
8251 case SK_ARRAYFETCH:
8253 if (set->kind == SK_ARRAYFETCH
8254 && (sRef_similar (set->info->arrayfetch->arr,
8255 guide->info->arrayfetch->arr)))
8257 return set;
8259 else
8261 return (sRef_makeAnyArrayFetch
8262 (sRef_getDeriv (set, guide->info->arrayfetch->arr)));
8265 case SK_PTR:
8267 if (set->kind == SK_PTR && sRef_similar (set->info->ref, guide->info->ref))
8269 return set;
8271 else
8273 return (sRef_makePointer (sRef_getDeriv (set, guide->info->ref)));
8276 case SK_FIELD:
8278 if ((set->kind == SK_FIELD &&
8279 (sRef_similar (set->info->field->rec, guide->info->field->rec) &&
8280 cstring_equal (set->info->field->field, guide->info->field->field))))
8282 return set;
8284 else
8286 return (sRef_makeField (sRef_getDeriv (set, guide->info->field->rec),
8287 guide->info->field->field));
8289 case SK_ADR:
8291 if ((set->kind == SK_ADR) && sRef_similar (set->info->ref, guide->info->ref))
8293 return set;
8295 else
8297 return (sRef_makeAddress (sRef_getDeriv (set, guide->info->ref)));
8300 case SK_CONJ:
8302 return sRef_undefined;
8304 case SK_RESULT:
8305 case SK_SPECIAL:
8306 case SK_UNCONSTRAINED:
8307 case SK_TYPE:
8308 case SK_CONST:
8309 case SK_NEW:
8310 case SK_UNKNOWN:
8311 case SK_OBJECT:
8312 case SK_DERIVED:
8313 case SK_EXTERNAL:
8314 return sRef_undefined;
8317 BADEXIT;
8321 ** sRef_aliasCheckPred
8323 ** A confusing but spiffy function:
8325 ** Calls predf (s, e, text, <alias>) on s and all of s's aliases
8326 ** (unless checkAliases (s) is FALSE).
8328 ** For alias calls, calls as
8329 ** predf (alias, e, text, s)
8332 void
8333 sRef_aliasCheckPred (bool (predf) (sRef, exprNode, sRef, exprNode),
8334 /*@null@*/ bool (checkAliases) (sRef),
8335 sRef s, exprNode e, exprNode err)
8337 bool error = (*predf)(s, e, sRef_undefined, err);
8340 if (checkAliases != NULL && !(checkAliases (s)))
8342 /* don't check aliases */
8344 else
8346 sRefSet aliases = usymtab_allAliases (s);
8348 sRefSet_realElements (aliases, current)
8350 if (sRef_isReasonable (current))
8352 if (sRef_isReasonable (current))
8354 if (!sRef_similar (current, s)
8355 || (error && sRef_sameName (current, s)))
8357 (void) (*predf)(current, e, s, err);
8360 else
8362 llcontbug (message ("Invalid sRef as alias field of %s", sRef_unparse (s)));
8365 } end_sRefSet_realElements;
8367 sRefSet_free (aliases);
8372 ** return TRUE iff predf (s) is true for s or any alias of s
8375 bool
8376 sRef_aliasCheckSimplePred (sRefTest predf, sRef s)
8379 if ((*predf)(s))
8381 return TRUE;
8383 else
8385 sRefSet aliases;
8387 aliases = usymtab_allAliases (s);
8389 sRefSet_realElements (aliases, current)
8391 if (sRef_isReasonable (current))
8393 sRef cref = sRef_updateSref (current);
8395 /* Whoa! a very kludgey way to make sure the right sref is used
8396 ** where there is a conditional symbol table. I am beginning
8397 ** to think that having a conditional symbol table wasn't such
8398 ** a great idea. ;(
8401 if ((*predf)(cref))
8403 DPRINTF (("Checking alias: %s", sRef_unparseFull (cref)));
8404 sRefSet_free (aliases);
8405 return TRUE;
8408 } end_sRefSet_realElements;
8410 sRefSet_free (aliases);
8412 return FALSE;
8415 bool
8416 sRef_aliasCompleteSimplePred (bool (predf) (sRef), sRef s)
8418 sRefSet aliases;
8419 bool result = FALSE;
8422 aliases = usymtab_allAliases (s);
8424 if ((*predf)(s)) result = TRUE;
8427 sRefSet_realElements (aliases, current)
8429 if (sRef_isReasonable (current))
8431 current = sRef_updateSref (current);
8432 if ((*predf)(current)) result = TRUE;
8434 } end_sRefSet_realElements;
8436 sRefSet_free (aliases);
8437 return result;
8440 void
8441 sRef_aliasSetComplete (void (predf) (sRef, fileloc), sRef s, fileloc loc)
8443 sRefSet aliases;
8445 aliases = usymtab_allAliases (s);
8447 DPRINTF (("All aliases: %s --> %s", sRef_unparseFull (s), sRefSet_unparseFull (aliases)));
8449 (*predf)(s, loc);
8451 sRefSet_realElements (aliases, current)
8453 if (sRef_isReasonable (current))
8455 DPRINTF (("Update: %s", sRef_unparseFull (current)));
8456 current = sRef_updateSref (current);
8457 DPRINTF (("Updated ==> %s", sRef_unparseFull (current)));
8458 ((*predf)(current, loc));
8459 DPRINTF (("Killed: %s", sRef_unparseFull (current)));
8461 } end_sRefSet_realElements;
8463 sRefSet_free (aliases);
8466 void
8467 sRef_aliasSetCompleteParam (void (predf) (sRef, int, fileloc), sRef s,
8468 int kind, fileloc loc)
8470 sRefSet aliases;
8472 if (sRef_isDeep (s))
8474 aliases = usymtab_allAliases (s);
8476 else
8478 aliases = usymtab_aliasedBy (s);
8481 (*predf)(s, kind, loc);
8483 sRefSet_realElements (aliases, current)
8485 if (sRef_isReasonable (current))
8487 current = sRef_updateSref (current);
8488 ((*predf)(current, kind, loc));
8490 } end_sRefSet_realElements;
8492 sRefSet_free (aliases);
8496 ** Version of aliasSetCompleteParam for alkind parameters
8499 void
8500 sRef_aliasSetCompleteAlkParam (void (predf) (sRef, alkind, fileloc), sRef s,
8501 alkind kind, fileloc loc)
8503 sRefSet aliases;
8505 if (sRef_isDeep (s))
8507 aliases = usymtab_allAliases (s);
8509 else
8511 aliases = usymtab_aliasedBy (s);
8514 (*predf)(s, kind, loc);
8516 sRefSet_realElements (aliases, current)
8518 if (sRef_isReasonable (current))
8520 current = sRef_updateSref (current);
8521 ((*predf)(current, kind, loc));
8523 } end_sRefSet_realElements;
8525 sRefSet_free (aliases);
8528 static void
8529 sRef_innerAliasSetComplete (void (predf) (sRef, fileloc), sRef s, fileloc loc)
8531 sRef inner;
8532 sRefSet aliases;
8533 ctype ct;
8535 if (!sRef_isReasonable (s)) return;
8538 ** Type equivalence checking is necessary --- there might be casting.
8541 (*predf)(s, loc);
8543 switch (s->kind)
8545 case SK_UNCONSTRAINED:
8546 case SK_CVAR:
8547 case SK_PARAM:
8548 break;
8549 case SK_PTR:
8550 inner = s->info->ref;
8551 aliases = usymtab_allAliases (inner);
8552 ct = sRef_getType (inner);
8554 sRefSet_realElements (aliases, current)
8556 if (sRef_isReasonable (current))
8558 current = sRef_updateSref (current);
8560 if (ctype_equal (ct, sRef_getType (current)))
8562 sRef ptr = sRef_makePointer (current);
8563 ((*predf)(ptr, loc));
8566 } end_sRefSet_realElements;
8568 sRefSet_free (aliases);
8569 break;
8570 case SK_ARRAYFETCH:
8571 inner = s->info->arrayfetch->arr;
8572 aliases = usymtab_allAliases (inner);
8573 ct = sRef_getType (inner);
8575 DPRINTF (("Array fetch: %s", sRefSet_unparse (aliases)));
8577 sRefSet_realElements (aliases, current)
8579 if (sRef_isReasonable (current))
8581 current = sRef_updateSref (current);
8582 DPRINTF (("Current: %s", sRef_unparseFull (current)));
8584 if (ctype_equal (ct, sRef_getType (current)))
8586 if (s->info->arrayfetch->indknown)
8588 sRef af = sRef_makeArrayFetchKnown (current, s->info->arrayfetch->ind);
8589 DPRINTF (("Defining: %s", sRef_unparseFull (af)));
8590 /* evans 2001-08-27 This isn't true:
8591 llassert (af->info->arrayfetch->arr == current);
8592 see comments in buildArrayFetchKnown
8594 ((*predf)(af, loc));
8596 else
8598 sRef af = sRef_makeArrayFetch (current);
8599 /* evans 2001-08-27 This isn't true:
8600 llassert (af->info->arrayfetch->arr == current);
8601 see comments in buildArrayFetch
8603 DPRINTF (("Defining: %s", sRef_unparseFull (af)));
8604 ((*predf)(af, loc));
8607 else
8609 DPRINTF (("Type mismatch: %s / %s",
8610 ctype_unparse (ct),
8611 ctype_unparse (sRef_getType (current))));
8614 } end_sRefSet_realElements;
8616 sRefSet_free (aliases);
8617 break;
8618 case SK_FIELD:
8619 inner = s->info->field->rec;
8620 aliases = usymtab_allAliases (inner);
8621 ct = sRef_getType (inner);
8623 sRefSet_realElements (aliases, current)
8625 if (sRef_isReasonable (current))
8627 current = sRef_updateSref (current);
8629 if (ctype_equal (ct, sRef_getType (current)))
8631 sRef f = sRef_makeField (current, s->info->field->field);
8633 ((*predf)(f, loc));
8636 } end_sRefSet_realElements;
8638 sRefSet_free (aliases);
8639 break;
8640 case SK_CONJ:
8641 sRef_innerAliasSetComplete (predf, s->info->conj->a, loc);
8642 sRef_innerAliasSetComplete (predf, s->info->conj->b, loc);
8643 break;
8644 case SK_SPECIAL:
8645 case SK_ADR:
8646 case SK_TYPE:
8647 case SK_CONST:
8648 case SK_NEW:
8649 case SK_UNKNOWN:
8650 case SK_OBJECT:
8651 case SK_DERIVED:
8652 case SK_EXTERNAL:
8653 case SK_RESULT:
8654 break;
8658 static void
8659 sRef_innerAliasSetCompleteParam (void (predf) (sRef, sRef), sRef s, sRef t)
8661 sRef inner;
8662 sRefSet aliases;
8663 ctype ct;
8665 if (!sRef_isReasonable (s)) return;
8668 ** Type equivalence checking is necessary --- there might be casting.
8671 (*predf)(s, t);
8673 switch (s->kind)
8675 case SK_UNCONSTRAINED:
8676 case SK_CVAR:
8677 case SK_PARAM:
8678 break;
8679 case SK_PTR:
8680 inner = s->info->ref;
8681 aliases = usymtab_allAliases (inner);
8682 ct = sRef_getType (inner);
8684 sRefSet_realElements (aliases, current)
8686 if (sRef_isReasonable (current))
8688 current = sRef_updateSref (current);
8690 if (ctype_equal (ct, sRef_getType (current)))
8692 sRef ptr = sRef_makePointer (current);
8694 ((*predf)(ptr, t));
8697 } end_sRefSet_realElements;
8699 sRefSet_free (aliases);
8700 break;
8701 case SK_ARRAYFETCH:
8702 inner = s->info->arrayfetch->arr;
8703 aliases = usymtab_allAliases (inner);
8704 ct = sRef_getType (inner);
8706 sRefSet_realElements (aliases, current)
8708 if (sRef_isReasonable (current))
8710 current = sRef_updateSref (current);
8712 if (ctype_equal (ct, sRef_getType (current)))
8715 if (s->info->arrayfetch->indknown)
8717 sRef af = sRef_makeArrayFetchKnown (current, s->info->arrayfetch->ind);
8719 ((*predf)(af, t));
8721 else
8723 sRef af = sRef_makeArrayFetch (current);
8725 ((*predf)(af, t));
8729 } end_sRefSet_realElements;
8731 sRefSet_free (aliases);
8732 break;
8733 case SK_FIELD:
8734 inner = s->info->field->rec;
8735 aliases = usymtab_allAliases (inner);
8736 ct = sRef_getType (inner);
8739 sRefSet_realElements (aliases, current)
8741 if (sRef_isReasonable (current))
8743 current = sRef_updateSref (current);
8745 if (ctype_equal (ct, sRef_getType (current)))
8747 sRef f = sRef_makeField (current, s->info->field->field);
8749 ((*predf)(f, t));
8752 } end_sRefSet_realElements;
8754 sRefSet_free (aliases);
8755 break;
8756 case SK_CONJ:
8757 sRef_innerAliasSetCompleteParam (predf, s->info->conj->a, t);
8758 sRef_innerAliasSetCompleteParam (predf, s->info->conj->b, t);
8759 break;
8760 case SK_SPECIAL:
8761 case SK_ADR:
8762 case SK_TYPE:
8763 case SK_CONST:
8764 case SK_NEW:
8765 case SK_UNKNOWN:
8766 case SK_OBJECT:
8767 case SK_DERIVED:
8768 case SK_EXTERNAL:
8769 case SK_RESULT:
8770 break;
8774 static void sRef_combineExKinds (/*@notnull@*/ sRef res, /*@notnull@*/ sRef other)
8776 exkind a1 = sRef_getExKind (res);
8777 exkind a2 = sRef_getExKind (other);
8779 if (a1 == a2 || a2 == XO_UNKNOWN)
8783 else if (a1 == XO_UNKNOWN)
8785 res->expinfo = stateInfo_update (res->expinfo, other->expinfo);
8786 res->expkind = a2;
8788 else
8790 res->expkind = XO_OBSERVER;
8795 ** Currently, this is a very ad hoc implementation, with lots of fixes to
8796 ** make real code work okay. I need to come up with some more general
8797 ** rules or principles here.
8800 static void
8801 sRef_combineAliasKindsError (/*@notnull@*/ sRef res,
8802 /*@notnull@*/ sRef other,
8803 clause cl, fileloc loc)
8805 bool hasError = FALSE;
8806 alkind ares = sRef_getAliasKind (res);
8807 alkind aother = sRef_getAliasKind (other);
8809 sRef_checkMutable (res);
8811 if (alkind_isDependent (ares))
8813 if (aother == AK_KEPT)
8815 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8816 res->aliaskind = AK_KEPT;
8818 else
8820 if (aother == AK_LOCAL || aother == AK_STATIC
8821 || alkind_isTemp (aother))
8823 DPRINTF (("Setting dependent: %s", sRef_unparseFull (res)));
8824 res->aliaskind = AK_DEPENDENT;
8828 else if (alkind_isDependent (aother))
8830 if (ares == AK_KEPT)
8832 res->aliaskind = AK_KEPT;
8834 else
8836 if (ares == AK_LOCAL || ares == AK_STATIC || alkind_isTemp (ares))
8838 DPRINTF (("Setting dependent: %s", sRef_unparseFull (res)));
8839 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8840 res->aliaskind = AK_DEPENDENT;
8844 else if ((ares == AK_LOCAL || ares == AK_UNIQUE
8845 || ares == AK_STATIC || alkind_isTemp (ares))
8846 && sRef_isFresh (other))
8849 ** cases like: if (s == NULL) s = malloc...;
8850 ** don't generate errors
8853 if (usymtab_isAltDefinitelyNullDeep (res))
8855 res->aliaskind = ares;
8857 else
8859 hasError = TRUE;
8862 else if ((aother == AK_LOCAL || aother == AK_UNIQUE
8863 || aother == AK_STATIC || alkind_isTemp (aother))
8864 && sRef_isFresh (res))
8867 ** cases like: if (s == NULL) s = malloc...;
8868 ** don't generate errors
8871 if (usymtab_isDefinitelyNullDeep (other))
8873 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8874 res->aliaskind = aother;
8876 else
8878 hasError = TRUE;
8881 else if (ares == AK_NEWREF && aother == AK_REFCOUNTED
8882 && sRef_isConst (other))
8884 res->aliaskind = AK_NEWREF;
8886 else if (aother == AK_NEWREF && ares == AK_REFCOUNTED
8887 && sRef_isConst (res))
8889 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8890 res->aliaskind = AK_NEWREF;
8892 else if (sRef_isLocalVar (res)
8893 && ((ares == AK_KEPT && aother == AK_LOCAL)
8894 || (aother == AK_KEPT && ares == AK_LOCAL)))
8896 res->aliaskind = AK_KEPT;
8898 else if ((ares == AK_OWNED && aother == AK_ONLY)
8899 || (aother == AK_OWNED && ares == AK_ONLY))
8901 res->aliaskind = AK_OWNED;
8903 if (aother == AK_OWNED)
8905 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8908 else
8910 hasError = TRUE;
8913 if (hasError)
8915 if (sRef_isThroughArrayFetch (res))
8917 if (optgenerror2
8918 (FLG_BRANCHSTATE, FLG_STRICTBRANCHSTATE,
8919 message
8920 ("Clauses exit with %q possibly referencing %s storage %s, "
8921 "%s storage %s",
8922 sRef_unparse (res),
8923 alkind_unparse (aother),
8924 clause_nameTaken (cl),
8925 alkind_unparse (ares),
8926 clause_nameAlternate (cl)),
8927 loc))
8929 sRef_showAliasInfo (res);
8930 sRef_showAliasInfo (other);
8931 res->aliaskind = AK_ERROR;
8933 else
8935 if (ares == AK_KEPT || aother == AK_KEPT)
8937 sRef_maybeKill (res, loc);
8941 else
8943 if (optgenerror
8944 (FLG_BRANCHSTATE,
8945 message ("Clauses exit with %q referencing %s storage %s, "
8946 "%s storage %s",
8947 sRef_unparse (res),
8948 alkind_unparse (aother),
8949 clause_nameTaken (cl),
8950 alkind_unparse (ares),
8951 clause_nameAlternate (cl)),
8952 loc))
8954 sRef_showAliasInfo (res);
8955 sRef_showAliasInfo (other);
8957 res->aliaskind = AK_ERROR;
8961 res->aliaskind = (sRef_isLocalVar (res) ? AK_LOCAL : AK_UNKNOWN);
8965 static void
8966 sRef_combineAliasKinds (/*@notnull@*/ sRef res, /*@notnull@*/ sRef other,
8967 clause cl, fileloc loc)
8969 alkind ares = sRef_getAliasKind (res);
8970 alkind aother = sRef_getAliasKind (other);
8972 sRef_checkMutable (res);
8974 DPRINTF (("Combine alias kinds: \n\t%s / \n\t%s",
8975 sRef_unparseFull (res), sRef_unparseFull (other)));
8976 if (alkind_equal (ares, aother)
8977 || aother == AK_UNKNOWN
8978 || aother == AK_ERROR)
8980 ; /* keep current state */
8982 else if (sRef_isDead (res) || sRef_isDead (other))
8984 /* dead error reported (or storage is dead) */
8985 res ->aliaskind = AK_ERROR;
8987 else if (ares == AK_UNKNOWN || ares == AK_ERROR
8988 || sRef_isStateUndefined (res)
8989 || sRef_isDefinitelyNull (res))
8991 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8992 res->aliaskind = aother;
8994 else if (sRef_isStateUndefined (other)
8995 || sRef_isDefinitelyNull (other))
8999 else if (((ares == AK_UNIQUE || alkind_isTemp (ares))
9000 && aother == AK_LOCAL)
9001 || ((aother == AK_UNIQUE || alkind_isTemp (aother))
9002 && ares == AK_LOCAL))
9004 if (ares != AK_LOCAL)
9006 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
9009 res->aliaskind = AK_LOCAL;
9011 else if ((ares == AK_OWNED && aother == AK_FRESH)
9012 || (aother == AK_OWNED && ares == AK_FRESH))
9014 if (ares != AK_FRESH)
9016 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
9019 res->aliaskind = AK_FRESH;
9021 else if ((ares == AK_KEEP && aother == AK_FRESH) ||
9022 (aother == AK_KEEP && ares == AK_FRESH))
9024 if (ares != AK_KEEP)
9026 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
9029 res->aliaskind = AK_KEEP;
9031 else if ((ares == AK_LOCAL && aother == AK_STACK) ||
9032 (aother == AK_LOCAL && ares == AK_STACK))
9034 if (ares != AK_STACK)
9036 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
9039 res->aliaskind = AK_STACK;
9041 else if ((ares == AK_LOCAL
9042 && (aother == AK_OWNED && sRef_isLocalVar (other)))
9043 || (aother == AK_LOCAL
9044 && (ares == AK_OWNED && sRef_isLocalVar (res))))
9046 if (ares != AK_LOCAL)
9048 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
9051 res->aliaskind = AK_LOCAL;
9053 else if ((ares == AK_FRESH && alkind_isOnly (aother))
9054 || (aother == AK_FRESH && alkind_isOnly (ares)))
9056 res->aliaskind = AK_FRESH;
9058 else if ((aother == AK_FRESH && sRef_definitelyNull (res))
9059 || (ares == AK_FRESH && sRef_definitelyNull (other)))
9061 if (ares != AK_FRESH)
9063 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
9064 res->aliaskind = AK_FRESH;
9067 else if ((sRef_isFresh (res) && sRef_isConst (other))
9068 || (sRef_isFresh (other) && sRef_isConst (res)))
9071 ** for NULL constantants
9072 ** this is bogus!
9075 if (!sRef_isFresh (res))
9077 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
9080 res->aliaskind = AK_FRESH;
9082 else if ((alkind_isStatic (aother) && sRef_isConst (res))
9083 || (alkind_isStatic (ares) && sRef_isConst (other)))
9085 if (!alkind_isStatic (ares))
9087 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
9088 res->aliaskind = AK_STATIC;
9091 else
9093 sRef_combineAliasKindsError (res, other, cl, loc);
9097 static void sRef_combineDefState (/*@notnull@*/ sRef res,
9098 /*@notnull@*/ sRef other)
9100 sstate s1 = res->defstate;
9101 sstate s2 = other->defstate;
9102 bool flip = FALSE;
9104 sRef_checkMutable (res);
9106 if (s1 == s2 || s2 == SS_UNKNOWN)
9110 else if (s1 == SS_UNKNOWN)
9112 flip = TRUE;
9114 else
9116 switch (s1)
9118 case SS_FIXED:
9119 if (s2 == SS_DEFINED)
9121 break;
9123 else
9125 llcontbuglit ("ssfixed: not implemented");
9126 flip = TRUE;
9128 break;
9129 case SS_DEFINED:
9130 flip = TRUE;
9131 break;
9132 case SS_PDEFINED:
9133 case SS_ALLOCATED:
9134 flip = (s2 != SS_DEFINED);
9135 break;
9136 case SS_HOFFA:
9137 case SS_RELDEF:
9138 case SS_UNUSEABLE:
9139 case SS_UNDEFINED:
9140 case SS_PARTIAL:
9141 case SS_UNDEFGLOB:
9142 case SS_KILLED:
9143 case SS_DEAD:
9144 case SS_SPECIAL:
9145 break;
9146 BADDEFAULT;
9150 if (flip)
9152 res->definfo = stateInfo_update (res->definfo, other->definfo);
9153 res->defstate = s2;
9157 extern /*@notnull@*/ sRef sRef_getConjA (sRef s)
9159 sRef ret;
9160 llassert (sRef_isConj (s));
9162 ret = s->info->conj->a;
9163 llassert (ret != NULL);
9164 return ret;
9167 extern /*@notnull@*/ sRef sRef_getConjB (sRef s)
9169 sRef ret;
9170 llassert (sRef_isConj (s));
9172 ret = s->info->conj->b;
9173 llassert (ret != NULL);
9174 return ret;
9177 extern /*@exposed@*/ sRef sRef_makeArrow (sRef s, /*@dependent@*/ cstring f)
9179 sRef p;
9180 sRef ret;
9182 p = sRef_makePointer (s);
9183 ret = sRef_makeField (p, f);
9184 DPRINTF (("Arrow: %s => %s",
9185 sRef_unparseFull (s), sRef_unparseFull (ret)));
9186 return ret;
9189 extern /*@exposed@*/ sRef sRef_buildArrow (sRef s, cstring f)
9191 sRef p;
9192 sRef ret;
9194 p = sRef_buildPointer (s);
9195 ret = sRef_buildField (p, f);
9197 return ret;
9200 static /*@null@*/ sinfo sinfo_copy (/*@notnull@*/ sRef s)
9202 sinfo ret;
9204 switch (s->kind)
9206 case SK_CVAR:
9207 ret = (sinfo) dmalloc (sizeof (*ret));
9208 ret->cvar = (cref) dmalloc (sizeof (*ret->cvar));
9209 ret->cvar->lexlevel = s->info->cvar->lexlevel;
9210 ret->cvar->index = s->info->cvar->index;
9211 break;
9213 case SK_PARAM:
9214 ret = (sinfo) dmalloc (sizeof (*ret));
9215 ret->paramno = s->info->paramno;
9216 llassert (ret->paramno >= -1);
9217 break;
9219 case SK_ARRAYFETCH:
9220 ret = (sinfo) dmalloc (sizeof (*ret));
9221 ret->arrayfetch = (ainfo) dmalloc (sizeof (*ret->arrayfetch));
9222 ret->arrayfetch->indknown = s->info->arrayfetch->indknown;
9223 ret->arrayfetch->ind = s->info->arrayfetch->ind;
9224 ret->arrayfetch->arr = s->info->arrayfetch->arr;
9225 break;
9227 case SK_FIELD:
9228 ret = (sinfo) dmalloc (sizeof (*ret));
9229 ret->field = (fldinfo) dmalloc (sizeof (*ret->field));
9230 ret->field->rec = s->info->field->rec;
9231 ret->field->field = s->info->field->field;
9232 break;
9234 case SK_OBJECT:
9235 ret = (sinfo) dmalloc (sizeof (*ret));
9236 ret->object = s->info->object;
9237 break;
9239 case SK_PTR:
9240 case SK_ADR:
9241 case SK_DERIVED:
9242 case SK_EXTERNAL:
9243 ret = (sinfo) dmalloc (sizeof (*ret));
9244 ret->ref = s->info->ref; /* Ref_copy (s->info->ref); */
9245 break;
9247 case SK_CONJ:
9248 ret = (sinfo) dmalloc (sizeof (*ret));
9249 ret->conj = (cjinfo) dmalloc (sizeof (*ret->conj));
9250 ret->conj->a = s->info->conj->a; /* sRef_copy (s->info->conj->a); */
9251 ret->conj->b = s->info->conj->b; /* sRef_copy (s->info->conj->b);*/
9252 break;
9253 case SK_SPECIAL:
9254 ret = (sinfo) dmalloc (sizeof (*ret));
9255 ret->spec = s->info->spec;
9256 break;
9258 case SK_UNCONSTRAINED:
9259 case SK_NEW:
9260 ret = (sinfo) dmalloc (sizeof (*ret));
9261 ret->fname = s->info->fname;
9262 break;
9264 default:
9265 llassertprint (s->info == NULL, ("s = %s", sRef_unparse (s)));
9266 ret = NULL;
9267 break;
9270 return ret;
9273 static /*@null@*/ sinfo sinfo_fullCopy (/*@notnull@*/ sRef s)
9275 sinfo ret;
9278 ** Since its a full copy, only storage is assigned
9279 ** to dependent fields.
9281 /*@-onlytrans@*/
9283 switch (s->kind)
9285 case SK_CVAR:
9286 ret = (sinfo) dmalloc (sizeof (*ret));
9287 ret->cvar = (cref) dmalloc (sizeof (*ret->cvar));
9288 ret->cvar->lexlevel = s->info->cvar->lexlevel;
9289 ret->cvar->index = s->info->cvar->index;
9290 break;
9292 case SK_PARAM:
9293 ret = (sinfo) dmalloc (sizeof (*ret));
9294 ret->paramno = s->info->paramno;
9295 llassert (ret->paramno >= -1);
9296 break;
9298 case SK_ARRAYFETCH:
9299 ret = (sinfo) dmalloc (sizeof (*ret));
9300 ret->arrayfetch = (ainfo) dmalloc (sizeof (*ret->arrayfetch));
9301 ret->arrayfetch->indknown = s->info->arrayfetch->indknown;
9302 ret->arrayfetch->ind = s->info->arrayfetch->ind;
9303 ret->arrayfetch->arr = sRef_saveCopy (s->info->arrayfetch->arr);
9304 break;
9306 case SK_FIELD:
9307 ret = (sinfo) dmalloc (sizeof (*ret));
9308 ret->field = (fldinfo) dmalloc (sizeof (*ret->field));
9309 ret->field->rec = sRef_saveCopy (s->info->field->rec);
9310 ret->field->field = s->info->field->field;
9311 break;
9313 case SK_OBJECT:
9314 ret = (sinfo) dmalloc (sizeof (*ret));
9315 ret->object = s->info->object;
9316 break;
9318 case SK_PTR:
9319 case SK_ADR:
9320 case SK_DERIVED:
9321 case SK_EXTERNAL:
9322 ret = (sinfo) dmalloc (sizeof (*ret));
9323 ret->ref = sRef_saveCopy (s->info->ref);
9324 break;
9326 case SK_CONJ:
9327 ret = (sinfo) dmalloc (sizeof (*ret));
9328 ret->conj = (cjinfo) dmalloc (sizeof (*ret->conj));
9329 ret->conj->a = sRef_saveCopy (s->info->conj->a);
9330 ret->conj->b = sRef_saveCopy (s->info->conj->b);
9331 break;
9332 case SK_SPECIAL:
9333 ret = (sinfo) dmalloc (sizeof (*ret));
9334 ret->spec = s->info->spec;
9335 break;
9336 case SK_NEW:
9337 case SK_UNCONSTRAINED:
9338 ret = (sinfo) dmalloc (sizeof (*ret));
9339 ret->fname = s->info->fname;
9340 break;
9341 case SK_CONST:
9342 case SK_TYPE:
9343 case SK_RESULT:
9344 case SK_UNKNOWN:
9345 llassert (s->info == NULL);
9346 ret = NULL;
9347 break;
9349 /*@=onlytrans@*/
9350 return ret;
9354 static void
9355 sinfo_update (/*@notnull@*/ /*@exposed@*/ sRef res,
9356 /*@notnull@*/ /*@exposed@*/ sRef other)
9358 llassert (res->kind == other->kind);
9360 switch (res->kind)
9362 case SK_CVAR:
9363 res->info->cvar->lexlevel = other->info->cvar->lexlevel;
9364 res->info->cvar->index = other->info->cvar->index;
9365 break;
9367 case SK_PARAM:
9368 res->info->paramno = other->info->paramno;
9369 llassert (res->info->paramno >= -1);
9370 break;
9372 case SK_ARRAYFETCH:
9373 res->info->arrayfetch->indknown = other->info->arrayfetch->indknown;
9374 res->info->arrayfetch->ind = other->info->arrayfetch->ind;
9375 res->info->arrayfetch->arr = other->info->arrayfetch->arr;
9376 break;
9378 case SK_FIELD:
9379 res->info->field->rec = other->info->field->rec;
9380 res->info->field->field = other->info->field->field;
9381 break;
9383 case SK_OBJECT:
9384 res->info->object = other->info->object;
9385 break;
9387 case SK_PTR:
9388 case SK_ADR:
9389 case SK_DERIVED:
9390 case SK_EXTERNAL:
9391 res->info->ref = other->info->ref;
9392 break;
9394 case SK_CONJ:
9395 res->info->conj->a = other->info->conj->a;
9396 res->info->conj->b = other->info->conj->b;
9397 break;
9399 case SK_SPECIAL:
9400 res->info->spec = other->info->spec;
9401 break;
9403 case SK_NEW:
9404 case SK_UNCONSTRAINED:
9405 res->info->fname = other->info->fname;
9406 break;
9408 default:
9409 llassert (res->info == NULL);
9410 break;
9414 static void sinfo_free (/*@special@*/ /*@temp@*/ /*@notnull@*/ sRef s)
9415 /*@uses s->kind, s->info@*/
9416 /*@releases s->info@*/
9418 switch (s->kind)
9420 case SK_CVAR:
9421 DPRINTF (("Free sinfo: [%p]", s->info->cvar));
9422 sfree (s->info->cvar);
9423 break;
9425 case SK_PARAM:
9426 break;
9428 case SK_ARRAYFETCH:
9429 DPRINTF (("Free sinfo: [%p]", s->info->arrayfetch));
9430 sfree (s->info->arrayfetch);
9431 break;
9433 case SK_FIELD:
9434 DPRINTF (("Free sinfo: [%p]", s->info->field));
9435 sfree (s->info->field);
9436 break;
9438 case SK_OBJECT:
9439 break;
9441 case SK_PTR:
9442 case SK_ADR:
9443 case SK_DERIVED:
9444 case SK_EXTERNAL: /* is copy now! */
9445 break;
9447 case SK_CONJ:
9448 DPRINTF (("Free sinfo: [%p]", s->info->conj));
9449 sfree (s->info->conj);
9450 break;
9452 default:
9453 break;
9456 if (s->info != NULL) {
9457 DPRINTF (("Free sinfo: [%p]", s->info));
9460 sfree (s->info);
9463 bool sRef_isNSLocalVar (sRef s)
9465 if (sRef_isLocalVar (s))
9467 uentry ue = sRef_getUentry (s);
9469 return (!uentry_isStatic (ue));
9471 else
9473 return FALSE;
9477 bool sRef_isLocalVar (sRef s)
9479 if (sRef_isValid(s))
9481 return (s->kind == SK_CVAR
9482 && (s->info->cvar->lexlevel > fileScope));
9485 return FALSE;
9488 bool sRef_isRealLocalVar (sRef s)
9490 if (sRef_isValid(s))
9492 if (s->kind == SK_CVAR)
9494 if (s->info->cvar->lexlevel == functionScope)
9496 uentry ue = sRef_getUentry (s);
9498 if (uentry_isAnyParam (ue)
9499 || uentry_isRefParam (ue))
9501 return FALSE;
9503 else
9505 return TRUE;
9508 else
9510 return (s->info->cvar->lexlevel > functionScope);
9515 return FALSE;
9518 bool sRef_isLocalParamVar (sRef s)
9520 if (sRef_isValid(s))
9522 return (s->kind == SK_PARAM
9523 || (s->kind == SK_CVAR
9524 && (s->info->cvar->lexlevel > fileScope)));
9527 return FALSE;
9530 static speckind speckind_fromInt (int i)
9532 /*@+enumint@*/
9533 llassert (i >= SR_NOTHING && i <= SR_SYSTEM);
9534 /*@=enumint@*/
9536 return ((speckind) i);
9540 static void sRef_updateNullState (/*@notnull@*/ sRef res, /*@notnull@*/ sRef other)
9541 /*@modifies res@*/
9543 res->nullstate = other->nullstate;
9544 DPRINTF (("update null state==> %s", sRef_unparseFull (res)));
9545 res->nullinfo = stateInfo_update (res->nullinfo, other->nullinfo);
9546 sRef_resetAliasKind (res);
9549 void sRef_combineNullState (/*@notnull@*/ sRef res, /*@notnull@*/ sRef other)
9551 nstate n1 = sRef_getNullState (res);
9552 nstate n2 = sRef_getNullState (other);
9553 bool flip = FALSE;
9554 nstate nn = n1;
9556 if (n1 == n2 || n2 == NS_UNKNOWN)
9560 else
9562 /* note: n2 is not unknown or defnull */
9564 switch (n1)
9566 case NS_ERROR: nn = NS_ERROR; break;
9567 case NS_UNKNOWN: flip = TRUE; nn = n2; break;
9568 case NS_POSNULL: break;
9569 case NS_DEFNULL: nn = NS_POSNULL; break;
9570 case NS_RELNULL: break;
9571 case NS_NOTNULL:
9572 if (n2 == NS_MNOTNULL)
9576 else
9578 flip = TRUE;
9579 nn = NS_POSNULL;
9581 break;
9582 case NS_MNOTNULL:
9583 if (n2 == NS_NOTNULL)
9585 nn = NS_NOTNULL;
9587 else
9589 flip = TRUE;
9590 nn = NS_POSNULL;
9592 break;
9593 case NS_CONSTNULL:
9594 case NS_ABSNULL:
9595 flip = TRUE;
9596 nn = n2;
9600 if (flip)
9602 res->nullinfo = stateInfo_update (res->nullinfo, other->nullinfo);
9605 res->nullstate = nn;
9606 DPRINTF (("update null state==> %s", sRef_unparseFull (res)));
9607 sRef_resetAliasKind (res);
9610 cstring sRef_nullMessage (sRef s)
9612 llassert (sRef_isReasonable (s));
9614 switch (sRef_getNullState (s))
9616 case NS_DEFNULL:
9617 case NS_CONSTNULL:
9618 return (cstring_makeLiteralTemp ("null"));
9619 default:
9620 return (cstring_makeLiteralTemp ("possibly null"));
9622 BADEXIT;
9625 # ifdef DEADCODE
9626 /*@observer@*/ cstring sRef_ntMessage (sRef s)
9628 llassert (sRef_isReasonable (s));
9630 switch (s->nullstate)
9632 case NS_DEFNULL:
9633 case NS_CONSTNULL:
9634 return (cstring_makeLiteralTemp ("not nullterminated"));
9635 default:
9636 return (cstring_makeLiteralTemp ("possibly non-nullterminated"));
9638 BADEXIT;
9640 # endif /* DEADCODE */
9643 sRef sRef_fixResultType (/*@returned@*/ sRef s, ctype typ, uentry ue)
9645 sRef tmp = sRef_undefined;
9646 sRef ret;
9648 llassert (sRef_isReasonable (s));
9650 switch (s->kind)
9652 case SK_RESULT:
9653 s->type = typ;
9654 ret = s;
9655 break;
9656 case SK_ARRAYFETCH:
9658 ctype ct;
9659 tmp = sRef_fixResultType (s->info->arrayfetch->arr, typ, ue);
9661 ct = ctype_realType (sRef_getType (tmp));
9664 if (ctype_isKnown (ct))
9666 if (ctype_isAP (ct))
9670 else
9672 voptgenerror
9673 (FLG_TYPE,
9674 message
9675 ("Special clause indexes non-array (%t): *%q",
9676 ct, sRef_unparse (s->info->arrayfetch->arr)),
9677 uentry_whereLast (ue));
9681 tmp = sRef_fixResultType (s->info->arrayfetch->arr, typ, ue);
9683 if (s->info->arrayfetch->indknown)
9685 ret = sRef_makeArrayFetchKnown (tmp, s->info->arrayfetch->ind);
9687 else
9689 ret = sRef_makeArrayFetch (tmp);
9692 break;
9693 case SK_FIELD:
9695 sRef rec = sRef_fixResultType (s->info->field->rec, typ, ue);
9696 ctype ct = ctype_realType (sRef_getType (rec));
9698 if (ctype_isKnown (ct))
9700 if (ctype_isSU (ct))
9702 if (uentry_isValid (uentryList_lookupField (ctype_getFields (ct),
9703 s->info->field->field)))
9707 else
9709 voptgenerror
9710 (FLG_TYPE,
9711 message
9712 ("Special clause accesses non-existent field of result: %q.%s",
9713 sRef_unparse (rec), s->info->field->field),
9714 uentry_whereLast (ue));
9717 else
9719 voptgenerror
9720 (FLG_TYPE,
9721 message
9722 ("Special clause accesses field of non-struct or union result (%t): %q.%s",
9723 ct, sRef_unparse (rec), s->info->field->field),
9724 uentry_whereLast (ue));
9728 ret = sRef_makeField (tmp, s->info->field->field);
9729 break;
9731 case SK_PTR:
9733 ctype ct;
9734 tmp = sRef_fixResultType (s->info->ref, typ, ue);
9736 ct = ctype_realType (sRef_getType (tmp));
9738 if (ctype_isKnown (ct))
9740 if (ctype_isAP (ct))
9744 else
9746 voptgenerror
9747 (FLG_TYPE,
9748 message
9749 ("Special clause dereferences non-pointer (%t): *%q",
9750 ct, sRef_unparse (s->info->ref)),
9751 uentry_whereLast (ue));
9755 ret = sRef_makePointer (tmp);
9756 break;
9758 case SK_ADR:
9759 voptgenerror
9760 (FLG_TYPE,
9761 message
9762 ("Special clause uses & operator (not allowed): &%q", sRef_unparse (s->info->ref)),
9763 uentry_whereLast (ue));
9764 ret = s;
9765 break;
9766 BADDEFAULT;
9769 return ret;
9772 bool sRef_isOnly (sRef s)
9774 return (sRef_isValid(s) && alkind_isOnly (s->aliaskind));
9777 bool sRef_isDependent (sRef s)
9779 return (sRef_isValid(s) && alkind_isDependent (s->aliaskind));
9782 bool sRef_isOwned (sRef s)
9784 return (sRef_isReasonable (s) && (s->aliaskind == AK_OWNED));
9787 bool sRef_isKeep (sRef s)
9789 return (sRef_isReasonable (s) && (s->aliaskind == AK_KEEP));
9792 # ifdef DEADCODE
9793 bool sRef_isTemp (sRef s)
9795 return (sRef_isReasonable (s) && alkind_isTemp (s->aliaskind));
9797 # endif /* DEADCODE */
9799 bool sRef_isLocalState (sRef s)
9801 return (sRef_isReasonable (s) && (s->aliaskind == AK_LOCAL));
9804 bool sRef_isUnique (sRef s)
9806 return (sRef_isReasonable (s) && (s->aliaskind == AK_UNIQUE));
9809 bool sRef_isShared (sRef s)
9811 return (sRef_isReasonable (s) && (s->aliaskind == AK_SHARED));
9814 bool sRef_isExposed (sRef s)
9816 return (sRef_isReasonable (s) && (s->expkind == XO_EXPOSED));
9819 bool sRef_isObserver (sRef s)
9821 return (sRef_isReasonable (s) && (s->expkind == XO_OBSERVER));
9824 bool sRef_isFresh (sRef s)
9826 return (sRef_isReasonable (s) && (s->aliaskind == AK_FRESH));
9829 bool sRef_isDefinitelyNull (sRef s)
9831 return (sRef_isReasonable (s) && (sRef_getNullState (s) == NS_DEFNULL
9832 || sRef_getNullState (s) == NS_CONSTNULL));
9835 bool sRef_isAllocated (sRef s)
9837 return (sRef_isReasonable (s) && (s->defstate == SS_ALLOCATED));
9840 bool sRef_isStack (sRef s)
9842 return (sRef_isReasonable (s) && (s->aliaskind == AK_STACK));
9845 bool sRef_isNotNull (sRef s)
9847 return (sRef_isValid(s) && (sRef_getNullState (s) == NS_MNOTNULL
9848 || sRef_getNullState (s) == NS_NOTNULL));
9851 alkind sRef_getAliasKind (sRef s)
9853 if (sRef_isValid(s)) {
9854 llassert (alkind_isValid (s->aliaskind));
9855 return s->aliaskind;
9858 return AK_ERROR;
9861 nstate sRef_getNullState (sRef s)
9863 if (sRef_isReasonable (s)) {
9864 llassert (nstate_isValid (s->nullstate));
9865 return s->nullstate;
9868 return NS_UNKNOWN;
9871 void sRef_reflectAnnotation (sRef s, annotationInfo a, fileloc loc)
9873 if (sRef_isReasonable (s))
9875 if (!valueTable_isDefined (s->state))
9877 s->state = valueTable_create (1);
9878 valueTable_insert
9879 (s->state,
9880 cstring_copy (metaStateInfo_getName (annotationInfo_getState (a))),
9881 stateValue_create (annotationInfo_getValue (a),
9882 stateInfo_makeLoc (loc, SA_DECLARED)));
9884 else
9886 DPRINTF (("reflect loc: %s", fileloc_unparse (loc)));
9887 valueTable_update
9888 (s->state,
9889 metaStateInfo_getName (annotationInfo_getState (a)),
9890 stateValue_create (annotationInfo_getValue (a),
9891 stateInfo_makeLoc (loc, SA_DECLARED)));
9893 DPRINTF (("sref: %s", sRef_unparse (s)));
9894 DPRINTF (("sref: %s", sRef_unparseFull (s)));
9899 void sRef_setMetaStateValueComplete (sRef s, cstring key, int value, fileloc loc)
9901 sRefSet aliases = usymtab_allAliases (s);
9903 sRef_setMetaStateValue (s, key, value, loc);
9905 sRefSet_realElements (aliases, current)
9907 if (sRef_isReasonable (current))
9909 current = sRef_updateSref (current);
9910 sRef_setMetaStateValue (current, key, value, loc);
9912 } end_sRefSet_realElements ;
9914 sRefSet_free (aliases);
9917 void sRef_setMetaStateValue (sRef s, cstring key, int value, fileloc loc)
9919 sRef_checkMutable (s);
9921 if (sRef_isReasonable (s))
9923 if (!valueTable_isDefined (s->state))
9925 DPRINTF (("inserting state: %s: %s %d", sRef_unparse (s), key, value));
9926 s->state = valueTable_create (1);
9927 valueTable_insert (s->state, cstring_copy (key),
9928 stateValue_create (value,
9929 stateInfo_makeLoc (loc, SA_CHANGED)));
9931 else
9933 DPRINTF (("Updating state: %s: %s %d / %s", sRef_unparse (s), key, value,
9934 fileloc_unparse (loc)));
9935 if (valueTable_contains (s->state, key))
9937 valueTable_update
9938 (s->state, key, stateValue_create (value,
9939 stateInfo_makeLoc (loc, SA_CHANGED)));
9941 else
9943 valueTable_insert
9944 (s->state, cstring_copy (key),
9945 stateValue_create (value, stateInfo_makeLoc (loc, SA_CHANGED)));
9948 DPRINTF (("After: %s", sRef_unparseFull (s)));
9953 bool sRef_checkMetaStateValue (sRef s, cstring key, int value)
9955 if (sRef_isReasonable (s))
9957 if (valueTable_isDefined (s->state))
9959 stateValue val;
9961 DPRINTF (("check state: %s: %s %d", sRef_unparse (s), key, value));
9963 val = valueTable_lookup (s->state, key);
9964 llassert (stateValue_isDefined (val));
9965 return (stateValue_isError (val)
9966 || stateValue_getValue (val) == value);
9968 else
9970 return TRUE;
9973 else
9975 return TRUE;
9979 /*@observer@*/ stateValue sRef_getMetaStateValue (sRef s, cstring key)
9981 if (sRef_isReasonable (s))
9983 if (valueTable_isDefined (s->state))
9985 stateValue val;
9987 val = valueTable_lookup (s->state, key);
9988 /* Okay if its not defined, just returns stateValue_undefined */
9989 return val;
9991 else
9993 return stateValue_undefined;
9996 else
9998 return stateValue_undefined;
10002 /*@observer@*/ valueTable sRef_getValueTable (sRef s)
10004 DPRINTF (("Get value table: %s", sRef_unparse (s)));
10006 if (sRef_isReasonable (s))
10008 llassert (sRef_isReasonable (s));
10009 DPRINTF (("Value table: %s", valueTable_unparse (s->state)));
10010 return s->state;
10012 else
10014 DPRINTF (("No value table!"));
10015 return valueTable_undefined;
10019 bool sRef_makeStateSpecial (sRef s)
10022 ** Default defined state can be made special.
10025 llassert (sRef_isReasonable (s));
10027 if (s->defstate == SS_UNKNOWN || s->defstate == SS_DEFINED || s->defstate == SS_SPECIAL)
10029 /* s->aliaskind = AK_IMPTEMP; */ /* evans 2001-07-23 shouldn't effect alias state */
10030 s->defstate = SS_SPECIAL;
10031 DPRINTF (("Made special: %s", sRef_unparseFull (s)));
10032 return TRUE;
10034 else
10036 /* s->aliaskind = AK_IMPTEMP; */
10037 s->defstate = SS_SPECIAL;
10038 return FALSE;
10042 void sRef_markImmutable (sRef s)
10044 if (sRef_isReasonable (s))
10046 DPRINTF (("Mark immutable: %s", sRef_unparseFull (s)));
10047 s->immut = TRUE;
10051 bool sRef_definitelyNullContext (sRef s)
10053 return (sRef_definitelyNull (s)
10054 || usymtab_isDefinitelyNullDeep (s));
10057 bool sRef_definitelyNullAltContext (sRef s)
10059 return (sRef_definitelyNull (s)
10060 || usymtab_isAltDefinitelyNullDeep (s));
10064 # ifdef DEADCODE
10065 /* start modifications */
10066 struct s_bbufinfo sRef_getNullTerminatedState (sRef p_s) {
10067 struct s_bbufinfo BUFSTATE_UNKNOWN;
10068 BUFSTATE_UNKNOWN.bufstate = BB_NOTNULLTERMINATED;
10069 BUFSTATE_UNKNOWN.size = 0;
10070 BUFSTATE_UNKNOWN.len = 0;
10072 if (sRef_isValid(p_s))
10073 return p_s->bufinfo;
10074 return BUFSTATE_UNKNOWN;
10076 # endif /* DEADCODE */
10078 void sRef_setNullTerminatedState(sRef p_s) {
10079 if(sRef_isReasonable (p_s)) {
10080 p_s->bufinfo.bufstate = BB_NULLTERMINATED;
10081 } else {
10082 llfatalbug( message("sRef_setNT passed a invalid sRef\n"));
10087 void sRef_setPossiblyNullTerminatedState(sRef p_s) {
10088 if( sRef_isReasonable (p_s)) {
10089 p_s->bufinfo.bufstate = BB_POSSIBLYNULLTERMINATED;
10090 } else {
10091 llfatalbug( message("sRef_setPossNT passed a invalid sRef\n"));
10095 void sRef_setNotNullTerminatedState(sRef p_s) {
10096 if( sRef_isReasonable (p_s)) {
10097 p_s->bufinfo.bufstate = BB_NOTNULLTERMINATED;
10098 } else {
10099 llfatalbug( message("sRef_unsetNT passed a invalid sRef\n"));
10103 void sRef_setLen(sRef p_s, int len) {
10104 if (sRef_isReasonable (p_s) && sRef_isNullTerminated(p_s))
10106 p_s->bufinfo.len = len;
10108 else
10110 llfatalbug( message("sRef_setLen passed an invalid sRef\n"));
10115 void sRef_setSize(sRef p_s, int size) {
10116 if( sRef_isValid(p_s))
10118 p_s->bufinfo.size = size;
10120 else
10122 llfatalbug( message("sRef_setSize passed a invalid sRef\n"));
10126 void sRef_resetLen(sRef p_s) {
10127 if (sRef_isReasonable (p_s))
10129 p_s->bufinfo.len = 0;
10131 else
10133 llfatalbug (message ("sRef_setLen passed an invalid sRef\n"));
10137 /*drl7x 11/28/2000 */
10139 bool sRef_isFixedArray (sRef p_s) /*@*/ {
10140 ctype c;
10141 c = sRef_getType (p_s);
10142 return ( ctype_isFixedArray (c) );
10145 size_t sRef_getArraySize (sRef p_s) /*@*/
10147 ctype c;
10148 llassert (sRef_isFixedArray(p_s) );
10149 DPRINTF (( message ("sRef_getArraySize getting array size for %s", sRef_unparse(p_s) ) ));
10151 c = sRef_getType (p_s);
10152 return (ctype_getArraySize (c));
10155 void sRef_setValue (sRef s, multiVal val)
10157 if (!sRef_isReasonable (s))
10159 llcontbuglit ("Unreasonable sRef");
10160 llcontbug (message ("sRef: %s", sRef_unparse (s)));
10161 return;
10164 multiVal_free (s->val);
10165 s->val = val;
10168 bool sRef_hasValue (sRef s)
10170 return (sRef_isReasonable (s)
10171 && multiVal_isDefined (s->val));
10174 multiVal sRef_getValue (sRef s)
10176 if (sRef_isReasonable (s))
10178 return s->val;
10181 return multiVal_undefined;