2 ** Splint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2001 University of Virginia,
4 ** Massachusetts Institute of Technology
6 ** This program is free software; you can redistribute it and/or modify it
7 ** under the terms of the GNU General Public License as published by the
8 ** Free Software Foundation; either version 2 of the License, or (at your
9 ** option) any later version.
11 ** This program is distributed in the hope that it will be useful, but
12 ** WITHOUT ANY WARRANTY; without even the implied warranty of
13 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 ** General Public License for more details.
16 ** The GNU General Public License is available from http://www.gnu.org/ or
17 ** the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
18 ** MA 02111-1307, USA.
20 ** For information on lclint: lclint-request@cs.virginia.edu
21 ** To report a bug: lclint-bug@cs.virginia.edu
22 ** For more information: http://www.splint.org
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
33 ** storeRefs in the file and global scopes are free'd by the uentry.
37 # include "lclintMacros.nf"
39 # include "exprChecks.h"
40 # include "transferChecks.h"
41 # include "sRefTable.h"
42 # include "structNames.h"
45 ** Predicate functions that evaluate both arguments in order.
49 # define OR(a,b) (a ? (b, TRUE) : b)
52 # define AND(a,b) (a ? b : (b, FALSE))
54 static void sRef_checkValidAux (sRef p_s, sRefSet p_checkedsofar) /*@modifies p_checkedsofar@*/ ;
56 static bool sRef_isDerived (sRef p_s) /*@*/ ;
58 static /*@exposed@*/ sRef sRef_fixDirectBase (sRef p_s, sRef p_base)
59 /*@modifies p_base@*/ ;
61 static void sRef_updateNullState (sRef p_res, sRef p_other) /*@modifies p_res@*/ ;
63 static bool sRef_isAllocatedStorage (sRef p_s) /*@*/ ;
64 static void sRef_setNullErrorLoc (sRef p_s, fileloc) /*@*/ ;
66 static int sRef_depth (sRef p_s) /*@*/ ;
69 sRef_innerAliasSetComplete (void (p_predf) (sRef, fileloc), sRef p_s,
74 sRef_innerAliasSetCompleteParam (void (p_predf) (sRef, sRef), sRef p_s, sRef p_t)
77 static speckind speckind_fromInt (int p_i);
78 static bool sRef_equivalent (sRef p_s1, sRef p_s2);
79 static bool sRef_isDeepUnionField (sRef p_s);
80 static void sRef_addDeriv (/*@notnull@*/ sRef p_s, /*@notnull@*/ /*@exposed@*/ sRef p_t);
81 static bool sRef_checkModify (sRef p_s, sRefSet p_sl) /*@*/ ;
83 static void sRef_checkMutable (/*@unused@*/ sRef s)
86 if (sRef_isValid (s) && s->immut)
88 llcontbug (message ("Modification to sRef marked immutable: %q",
89 sRef_unparseFull (s)));
93 static bool skind_isSimple (skind sk)
97 case SK_PARAM: case SK_CVAR: case SK_CONST:
98 case SK_OBJECT: case SK_UNKNOWN: case SK_NEW:
105 static void sinfo_free (/*@special@*/ /*@temp@*/ /*@notnull@*/ sRef p_s)
106 /*@uses p_s->kind, p_s->info@*/
107 /*@releases p_s->info@*/ ;
109 static /*@null@*/ sinfo sinfo_copy (/*@notnull@*/ sRef p_s) /*@*/ ;
110 static void sRef_setPartsFromUentry (sRef p_s, uentry p_ue)
112 static bool checkDeadState (/*@notnull@*/ sRef p_el, bool p_tbranch, fileloc p_loc);
113 static /*@dependent@*/ sRef sRef_constructPointerAux (/*@notnull@*/ /*@exposed@*/ sRef p_t) /*@*/ ;
116 sRef_combineExKinds (/*@notnull@*/ sRef p_res, /*@notnull@*/ sRef p_other)
117 /*@modifies p_res@*/ ;
120 sRef_combineAliasKinds (/*@notnull@*/ sRef p_res, /*@notnull@*/ sRef p_other,
121 clause p_cl, fileloc p_loc)
122 /*@modifies p_res@*/ ;
125 sRef_combineNullState (/*@notnull@*/ sRef p_res, /*@notnull@*/ sRef p_other)
126 /*@modifies p_res@*/ ;
129 sRef_combineDefState (/*@notnull@*/ sRef p_res, /*@notnull@*/ sRef p_other)
130 /*@modifies p_res@*/ ;
132 static void sRef_setStateFromAbstractUentry (sRef p_s, uentry p_ue)
136 sinfo_update (/*@notnull@*/ /*@exposed@*/ sRef p_res,
137 /*@notnull@*/ /*@exposed@*/ sRef p_other);
138 static void sRef_setDefinedAux (sRef p_s, fileloc p_loc, bool p_clear)
140 static void sRef_setDefinedNoClear (sRef p_s, fileloc p_loc)
142 static void sRef_setStateAux (sRef p_s, sstate p_ss, fileloc p_loc)
145 static /*@exposed@*/ sRef
146 sRef_buildNCField (/*@exposed@*/ sRef p_rec, /*@exposed@*/ cstring p_f);
149 sRef_mergeStateAux (/*@notnull@*/ sRef p_res, /*@notnull@*/ sRef p_other,
150 clause p_cl, bool p_opt, fileloc p_loc,
152 /*@modifies p_res, p_other@*/ ;
154 static /*@null@*/ sinfo sinfo_fullCopy (/*@notnull@*/ sRef p_s);
155 static bool sRef_doModify (sRef p_s, sRefSet p_sl) /*@modifies p_s@*/ ;
156 static bool sRef_doModifyVal (sRef p_s, sRefSet p_sl) /*@modifies p_s@*/;
157 static bool sRef_checkModifyVal (sRef p_s, sRefSet p_sl) /*@*/ ;
159 static /*@only@*/ sRefSet
160 sRef_mergeDerivs (/*@only@*/ sRefSet p_res, sRefSet p_other,
161 bool p_opt, clause p_cl, fileloc p_loc);
163 static /*@only@*/ sRefSet
164 sRef_mergeUnionDerivs (/*@only@*/ sRefSet p_res,
165 /*@exposed@*/ sRefSet p_other,
166 bool p_opt, clause p_cl, fileloc p_loc);
168 static /*@only@*/ sRefSet
169 sRef_mergePdefinedDerivs (/*@only@*/ sRefSet p_res, sRefSet p_other, bool p_opt,
170 clause p_cl, fileloc p_loc);
172 static /*@only@*/ cstring sRef_unparseWithArgs (sRef p_s, uentryList p_args);
173 static /*@only@*/ cstring sRef_unparseNoArgs (sRef p_s);
175 static /*@exposed@*/ sRef sRef_findDerivedPointer (sRef p_s);
176 static /*@exposed@*/ sRef sRef_findDerivedArrayFetch (/*@notnull@*/ sRef, bool, int, bool) ;
177 static /*@exposed@*/ sRef sRef_findDerivedField (/*@notnull@*/ sRef p_rec, cstring p_f);
178 static /*@exposed@*/ sRef
179 sRef_getDeriv (/*@notnull@*/ /*@returned@*/ sRef p_set, sRef p_guide);
181 static bool inFunction = FALSE;
182 static /*@only@*/ sRefTable allRefs;
184 /* # define DEBUGREFS */
188 static totnsrefs = 0;
189 static maxnsrefs = 0;
190 static ntotrefers = 0;
194 static /*@checked@*/ bool protectDerivs = FALSE;
197 ** Result of sRef_alloc is dependent since allRefs may
198 ** reference it. It is only if !inFunction.
201 static /*@dependent@*/ /*@out@*/ /*@notnull@*/ sRef
204 sRef s = (sRef) dmalloc (sizeof (*s));
208 DPRINTF (("Alloc sref: [%p]", s));
212 allRefs = sRefTable_add (allRefs, s);
217 DPRINTF (("Not in function!"));
223 if (nsrefs >= maxnsrefs)
232 /*@-mustfree@*/ /*@-freshtrans@*/
234 /*@=mustfree@*/ /*@=freshtrans@*/
237 static void sRef_checkValidAux (sRef s, sRefSet checkedsofar)
241 if (!sRef_isValid (s)) return;
243 if (sRefSet_containsSameObject (checkedsofar, s))
249 checkedsofar = sRefSet_insert (checkedsofar, s);
250 /*@=temptrans@*/ /* checksofar will be destroyed before checkValid returns */
254 case SK_UNCONSTRAINED:
255 llassert (cstring_length (s->info->fname) < 100);
259 llassert (s->info->cvar->lexlevel >= 0);
260 /* llassert (s->info->cvar->lexlevel <= usymtab_getCurrentDepth ()); */
264 llassert (s->info->paramno >= -1);
265 llassert (s->info->paramno <= 50); /*@i32 bogus...*/
269 sRef_checkValidAux (s->info->arrayfetch->arr, checkedsofar);
273 sRef_checkValidAux (s->info->field->rec, checkedsofar);
274 llassert (cstring_length (s->info->field->field) < 100);
278 sRef_checkValidAux (s->info->ref, checkedsofar);
282 sRef_checkValidAux (s->info->ref, checkedsofar);
286 /* check ctype s->info->object */
290 sRef_checkValidAux (s->info->conj->a, checkedsofar);
291 sRef_checkValidAux (s->info->conj->b, checkedsofar);
295 llassert (cstring_length (s->info->fname) < 100);
299 sRef_checkValidAux (s->info->ref, checkedsofar);
303 sRef_checkValidAux (s->info->ref, checkedsofar);
309 /* check ctyp s->type */
313 llassert (s->info->spec == SR_NOTHING
314 || s->info->spec == SR_INTERNAL
315 || s->info->spec == SR_SPECSTATE
316 || s->info->spec == SR_SYSTEM);
326 sRefSet_elements (s->deriv, el)
328 sRef_checkValidAux (el, checkedsofar);
329 } end_sRefSet_elements ;
332 void sRef_checkValid (/*@unused@*/ sRef s)
336 sRefSet checkedsofar = sRefSet_new ();
337 sRef_checkValidAux (s, checkedsofar);
341 static /*@dependent@*/ /*@notnull@*/ /*@special@*/ sRef
344 /*@ensures isnull result->aliasinfo, result->definfo,
345 result->expinfo, result->info, result->deriv, result->state@*/
347 sRef s = sRef_alloc ();
349 s->kind = SK_UNKNOWN;
353 s->val = multiVal_undefined;
355 s->type = ctype_unknown;
356 s->defstate = SS_UNKNOWN;
358 /* start modifications */
359 s->bufinfo.bufstate = BB_NOTNULLTERMINATED;
360 /* end modifications */
362 s->aliaskind = AK_UNKNOWN;
363 s->oaliaskind = AK_UNKNOWN;
365 s->nullstate = NS_UNKNOWN;
367 s->expkind = XO_UNKNOWN;
368 s->oexpkind = XO_UNKNOWN;
370 s->aliasinfo = stateInfo_undefined;
371 s->definfo = stateInfo_undefined;
372 s->nullinfo = stateInfo_undefined;
373 s->expinfo = stateInfo_undefined;
376 s->deriv = sRefSet_undefined;
378 s->state = valueTable_undefined;
383 static /*@dependent@*/ /*@notnull@*/ /*@special@*/ sRef
386 /*@ensures isnull result->aliasinfo, result->definfo,
387 result->expinfo, result->info, result->deriv@*/
389 sRef res = sRef_new ();
391 res->state = valueTable_undefined;
396 void sRef_protectDerivs (void) /*@modifies protectDerivs@*/
398 llassert (!protectDerivs);
399 protectDerivs = TRUE;
402 void sRef_clearProtectDerivs (void) /*@modifies protectDerivs@*/
404 llassert (protectDerivs);
405 protectDerivs = FALSE;
409 ** hmmm...here be kind of a hack. This function mysteriously appeared
410 ** in my code, but I'm sure I didn't write it.
414 sRef_isRecursiveField (sRef s)
416 if (sRef_isField (s))
418 if (sRef_depth (s) > 13)
423 fieldname = sRef_getField (s);
424 base = sRef_getBase (s);
426 while (sRef_isValid (base))
428 if (sRef_isField (base))
430 if (cstring_equal (fieldname, sRef_getField (base)))
436 base = sRef_getBaseSafe (base);
445 sRef_addDeriv (/*@notnull@*/ sRef s, /*@notnull@*/ /*@exposed@*/ sRef t)
447 if (!context_inProtectVars ()
451 && !sRef_isConst (s))
453 int sd = sRef_depth (s);
454 int td = sRef_depth (t);
461 /* This sometimes fails: (evans 2001-07-12)
462 if (sRef_isArrayFetch (t))
464 DPRINTF (("Derived fetch: %s / %s / %s",
465 sRef_unparseFull (s), sRef_unparseFull (t),
466 sRef_unparseFull (t->info->arrayfetch->arr)));
467 llassert (t->info->arrayfetch->arr == s);
471 if (sRef_isFileOrGlobalScope (s))
473 if (context_inFunctionLike ()
474 && ctype_isKnown (sRef_getType (s))
475 && !ctype_isFunction (sRef_getType (s)))
477 globSet g = context_getUsedGlobs ();
479 if (!globSet_member (g, s))
482 ** don't report as a bug
486 (message ("sRef_addDeriv: global variable not in used "
487 "globs: %q / %s / %q",
489 ctype_unparse (sRef_getType (s)),
490 sRefSet_unparse (s->deriv)));
495 s->deriv = sRefSet_insert (s->deriv, t);
501 DPRINTF (("Add deriv: [%p] %s / [%p] %s",
503 t, sRef_unparse (t)));
505 s->deriv = sRefSet_insert (s->deriv, t);
511 sRef_deepPred (bool (predf) (sRef), sRef s)
513 if (sRef_isValid (s))
515 if ((*predf)(s)) return TRUE;
520 return (sRef_deepPred (predf, s->info->ref));
522 return (sRef_deepPred (predf, s->info->arrayfetch->arr));
524 return (sRef_deepPred (predf, s->info->field->rec));
526 return (sRef_deepPred (predf, s->info->conj->a)
527 || sRef_deepPred (predf, s->info->conj->b));
536 bool sRef_modInFunction (void)
541 void sRef_setStateFromType (sRef s, ctype ct)
543 if (sRef_isValid (s))
545 if (ctype_isUser (ct))
547 DPRINTF (("Here we are: %s", sRef_unparseFull (s)));
548 sRef_setStateFromUentry
549 (s, usymtab_getTypeEntry (ctype_typeId (ct)));
551 else if (ctype_isAbstract (ct))
553 DPRINTF (("Here we are: %s", sRef_unparseFull (s)));
554 sRef_setStateFromAbstractUentry
555 (s, usymtab_getTypeEntry (ctype_typeId (ct)));
559 ; /* not a user type */
564 static void sRef_setTypeState (sRef s)
566 if (sRef_isValid (s))
568 sRef_setStateFromType (s, s->type);
573 sRef_hasAliasInfoLoc (sRef s)
575 return (sRef_isValid (s) && (s->aliasinfo != NULL)
576 && (fileloc_isDefined (s->aliasinfo->loc)));
579 static /*@falsenull@*/ bool
580 sRef_hasStateInfoLoc (sRef s)
582 return (sRef_isValid (s) && (s->definfo != NULL)
583 && (fileloc_isDefined (s->definfo->loc)));
586 static /*@falsenull@*/ bool
587 sRef_hasExpInfoLoc (sRef s)
589 return (sRef_isValid (s)
590 && (s->expinfo != NULL) && (fileloc_isDefined (s->expinfo->loc)));
594 static /*@observer@*/ /*@unused@*/ stateInfo sRef_getInfo (sRef s, cstring key)
598 if (!sRef_isValid (s)) {
599 return stateInfo_undefined;
602 sv = valueTable_lookup (s->state, key);
604 if (stateValue_isDefined (sv))
606 return stateValue_getInfo (sv);
609 return stateInfo_undefined;
614 sRef_hasNullInfoLoc (sRef s)
616 return (sRef_isValid (s) && s->nullinfo != NULL
617 && (fileloc_isDefined (s->nullinfo->loc)));
621 sRef_hasAliasInfoRef (sRef s)
623 return (sRef_isValid (s) && (s->aliasinfo != NULL)
624 && (sRef_isValid (s->aliasinfo->ref)));
627 static /*@observer@*/ fileloc
628 sRef_getAliasInfoLoc (/*@exposed@*/ sRef s)
630 llassert (sRef_isValid (s) && s->aliasinfo != NULL
631 && (fileloc_isDefined (s->aliasinfo->loc)));
632 return (s->aliasinfo->loc);
635 static /*@observer@*/ fileloc
636 sRef_getStateInfoLoc (/*@exposed@*/ sRef s)
638 llassert (sRef_isValid (s) && s->definfo != NULL
639 && (fileloc_isDefined (s->definfo->loc)));
640 return (s->definfo->loc);
643 static /*@observer@*/ fileloc
644 sRef_getExpInfoLoc (/*@exposed@*/ sRef s)
646 llassert (sRef_isValid (s) && s->expinfo != NULL
647 && (fileloc_isDefined (s->expinfo->loc)));
648 return (s->expinfo->loc);
651 static /*@observer@*/ fileloc
652 sRef_getNullInfoLoc (/*@exposed@*/ sRef s)
654 llassert (sRef_isValid (s) && s->nullinfo != NULL
655 && (fileloc_isDefined (s->nullinfo->loc)));
656 return (s->nullinfo->loc);
660 sRef_getAliasInfoRef (/*@temp@*/ sRef s)
662 llassert (sRef_isValid (s) && s->aliasinfo != NULL);
663 return (s->aliasinfo->ref);
666 bool sRef_inGlobalScope ()
672 ** This function should be called before new sRefs are created
673 ** somewhere where they will have a lifetime greater than the
674 ** current function scope.
677 void sRef_setGlobalScope ()
679 llassert (inFunction);
680 DPRINTF (("leave function"));
684 void sRef_clearGlobalScope ()
686 llassert (!inFunction);
687 DPRINTF (("enter function"));
691 static bool oldInFunction = FALSE;
692 static int nestedScope = 0;
694 void sRef_setGlobalScopeSafe ()
696 if (nestedScope == 0)
698 oldInFunction = inFunction;
702 DPRINTF (("leave function safe"));
706 void sRef_clearGlobalScopeSafe ()
709 llassert (nestedScope >= 0);
711 if (nestedScope == 0)
713 inFunction = oldInFunction;
716 DPRINTF (("clear function: %s", bool_unparse (inFunction)));
719 void sRef_enterFunctionScope ()
721 /* evans 2001-09-09 - cleanup if we are in a macro! */
722 if (context_inMacro ())
725 sRef_exitFunctionScope ();
729 llassert (!inFunction);
730 llassert (sRefTable_isEmpty (allRefs));
732 DPRINTF (("enter function"));
735 void sRef_exitFunctionScope ()
739 DPRINTF (("Exit function scope."));
740 sRefTable_clear (allRefs);
745 llbuglit ("sRef_exitFunctionScope: not in function");
749 void sRef_destroyMod () /*@globals killed allRefs;@*/
752 llmsg (message ("Live: %d / %d ", nsrefs, totnsrefs));
755 sRefTable_free (allRefs);
759 static /*@notnull@*/ /*@exposed@*/ sRef
760 sRef_fixConj (/*@notnull@*/ sRef s)
765 s = sRef_getConjA (s);
766 } while (sRef_isConj (s));
768 llassert (sRef_isValid (s));
769 return s; /* don't need to ref */
778 sRef_isExternallyVisibleAux (sRef s)
781 sRef base = sRef_getRootBase (s);
783 if (sRef_isValid (base))
785 res = sRef_isParam (base) || sRef_isFileOrGlobalScope (base) || sRef_isExternal (base);
792 sRef_isExternallyVisible (sRef s)
794 return (sRef_aliasCheckSimplePred (sRef_isExternallyVisibleAux, s));
798 sRef_getBaseUentry (sRef s)
800 sRef base = sRef_getRootBase (s);
801 uentry res = uentry_undefined;
803 if (sRef_isValid (base))
808 res = usymtab_getRefQuiet (paramsScope, base->info->paramno);
812 res = usymtab_getRefQuiet (base->info->cvar->lexlevel,
813 base->info->cvar->index);
825 ** lookup the current uentry corresponding to s, and return the corresponding sRef.
826 ** yuk yuk yuk yuk yuk yuk yuk yuk
830 sRef_updateSref (sRef s)
836 if (!sRef_isValid (s)) return sRef_undefined;
845 case SK_UNCONSTRAINED:
852 sRef r = sRef_updateSref (s->info->ref);
854 if (r != s->info->ref)
856 return sRef_makeExternal (r);
866 uentry ue = sRef_getUentry (s);
868 /* must be raw name! (need the marker) */
869 ue = usymtab_lookupSafe (uentry_rawName (ue));
871 if (uentry_isUndefined (ue))
877 DPRINTF (("Update sref: %s", uentry_unparseFull (ue)));
878 return (uentry_getSref (ue));
882 /* special case if ind known */
883 inner = s->info->arrayfetch->arr;
884 ret = sRef_updateSref (inner);
892 res = sRef_makeArrayFetch (ret);
898 inner = s->info->field->rec;
899 ret = sRef_updateSref (inner);
907 res = (sRef_makeField (ret, s->info->field->field));
912 inner = s->info->ref;
913 ret = sRef_updateSref (inner);
920 res = sRef_makePointer (ret);
926 inner = s->info->ref;
927 ret = sRef_updateSref (inner);
935 res = sRef_makeAddress (ret);
942 sRef innera = s->info->conj->a;
943 sRef innerb = s->info->conj->b;
944 sRef reta = sRef_updateSref (innera);
945 sRef retb = sRef_updateSref (innerb);
947 if (innera == reta && innerb == retb)
953 res = sRef_makeConj (reta, retb);
964 sRef_getUentry (sRef s)
966 llassert (sRef_isValid (s));
971 return (usymtab_getRefQuiet (paramsScope, s->info->paramno));
973 return (usymtab_getRefQuiet (s->info->cvar->lexlevel, s->info->cvar->index));
976 if (sRef_isCvar (s->info->conj->a) || sRef_isParam (s->info->conj->a)
977 || sRef_isConj (s->info->conj->a))
979 return sRef_getUentry (s->info->conj->a);
983 return sRef_getUentry (s->info->conj->b);
988 return uentry_undefined;
994 sRef_getParam (sRef s)
996 llassert (sRef_isValid (s));
997 llassert (s->kind == SK_PARAM);
999 return s->info->paramno;
1003 sRef_isModified (sRef s)
1005 return (!sRef_isValid (s) || s->modified);
1008 void sRef_setModified (sRef s)
1010 if (sRef_isValid (s))
1015 if (sRef_isRefsField (s))
1017 sRef base = sRef_getBase (s);
1020 llassert (s->kind == SK_FIELD);
1023 if (sRef_isPointer (base))
1025 base = sRef_getBase (base);
1028 if (sRef_isRefCounted (base))
1030 base->aliaskind = AK_NEWREF;
1037 ** note: this side-effects sRefSet to set modified to TRUE
1038 ** for any sRef similar to s.
1042 sRef_canModifyVal (sRef s, sRefSet sl)
1044 if (context_getFlag (FLG_MUSTMOD))
1046 return (sRef_doModifyVal (s, sl));
1050 return (sRef_checkModifyVal (s, sl));
1055 sRef_canModify (sRef s, sRefSet sl)
1058 if (context_getFlag (FLG_MUSTMOD))
1060 return (sRef_doModify (s, sl));
1064 return (sRef_checkModify (s, sl));
1073 bool sRef_checkModifyVal (sRef s, sRefSet sl)
1075 DPRINTF (("Check modify val: %s", sRef_unparse (s)));
1077 if (sRef_isInvalid (s))
1084 case SK_UNCONSTRAINED:
1088 DPRINTF (("Modify var: %s", sRef_unparse (s)));
1090 if (sRef_isFileOrGlobalScope (s))
1092 if (context_checkGlobMod (s))
1094 return (sRefSet_member (sl, s));
1104 return (sRefSet_member (sl, s)
1105 || alkind_isOnly (sRef_getOrigAliasKind (s)));
1107 /* special case if ind known */
1108 return (sRefSet_member (sl, s) ||
1109 sRef_checkModifyVal (s->info->arrayfetch->arr, sl));
1111 return (sRefSet_member (sl, s) || sRef_checkModifyVal (s->info->field->rec, sl));
1113 return (sRefSet_member (sl, s) || sRef_checkModifyVal (s->info->ref, sl));
1115 return (sRefSet_member (sl, s) || sRef_checkModifyVal (s->info->ref, sl));
1117 return ((sRef_checkModifyVal (s->info->conj->a, sl)) &&
1118 (sRef_checkModifyVal (s->info->conj->b, sl)));
1129 switch (s->info->spec)
1131 case SR_NOTHING: return TRUE;
1133 if (context_getFlag (FLG_INTERNALGLOBS))
1135 return (sRefSet_member (sl, s));
1141 case SR_SPECSTATE: return TRUE;
1142 case SR_SYSTEM: return (sRefSet_member (sl, s));
1143 case SR_GLOBALMARKER: BADBRANCH;
1146 case SK_RESULT: BADBRANCH;
1152 ** this should probably be elsewhere...
1154 ** returns TRUE iff sl indicates that s can be modified
1157 static bool sRef_checkModify (sRef s, sRefSet sl)
1159 llassert (sRef_isValid (s));
1163 case SK_UNCONSTRAINED:
1167 if (sRef_isFileOrGlobalScope (s))
1169 if (context_checkGlobMod (s))
1171 return (sRefSet_member (sl, s));
1183 return (sRefSet_member (sl, s) ||
1184 sRef_checkModifyVal (s->info->arrayfetch->arr, sl));
1187 sRef sr = s->info->field->rec;
1189 if (sr->kind == SK_PARAM)
1190 return TRUE; /* structs are copied on call */
1192 return (sRefSet_member (sl, s) || sRef_checkModifyVal (s->info->field->rec, sl));
1198 sm = sRefSet_member (sl, s);
1203 return (sRef_checkModifyVal (s->info->ref, sl));
1206 return (sRefSet_member (sl, s) || sRef_checkModifyVal (s->info->ref, sl));
1208 return ((sRef_checkModify (s->info->conj->a, sl)) &&
1209 (sRef_checkModify (s->info->conj->b, sl)));
1219 switch (s->info->spec)
1221 case SR_NOTHING: return TRUE;
1223 if (context_getFlag (FLG_INTERNALGLOBS))
1225 return (sRefSet_member (sl, s));
1231 case SR_SPECSTATE: return TRUE;
1232 case SR_SYSTEM: return (sRefSet_member (sl, s));
1233 case SR_GLOBALMARKER: BADBRANCH;
1236 case SK_RESULT: BADBRANCH;
1241 cstring sRef_stateVerb (sRef s)
1243 if (sRef_isDead (s))
1245 return cstring_makeLiteralTemp ("released");
1247 else if (sRef_isKept (s))
1249 return cstring_makeLiteralTemp ("kept");
1251 else if (sRef_isDependent (s))
1253 return cstring_makeLiteralTemp ("dependent");
1261 cstring sRef_stateAltVerb (sRef s)
1263 if (sRef_isDead (s))
1265 return cstring_makeLiteralTemp ("live");
1267 else if (sRef_isKept (s))
1269 return cstring_makeLiteralTemp ("not kept");
1271 else if (sRef_isDependent (s))
1273 return cstring_makeLiteralTemp ("independent");
1282 bool sRef_doModifyVal (sRef s, sRefSet sl)
1284 llassert (sRef_isValid (s));
1289 case SK_UNCONSTRAINED:
1293 if (sRef_isFileOrGlobalScope (s))
1296 if (context_checkGlobMod (s))
1298 return (sRefSet_modifyMember (sl, s));
1302 (void) sRefSet_modifyMember (sl, s);
1312 return (sRefSet_modifyMember (sl, s)
1313 || alkind_isOnly (sRef_getOrigAliasKind (s)));
1315 /* special case if ind known */
1316 /* unconditional OR, need side effect */
1317 return (OR (sRefSet_modifyMember (sl, s),
1318 sRef_doModifyVal (s->info->arrayfetch->arr, sl)));
1320 return (OR (sRefSet_modifyMember (sl, s),
1321 sRef_doModifyVal (s->info->field->rec, sl)));
1323 return (OR (sRefSet_modifyMember (sl, s),
1324 sRef_doModifyVal (s->info->ref, sl)));
1326 return (OR (sRefSet_modifyMember (sl, s),
1327 sRef_doModifyVal (s->info->ref, sl)));
1329 return (AND (sRef_doModifyVal (s->info->conj->a, sl) ,
1330 sRef_doModifyVal (s->info->conj->b, sl)));
1340 switch (s->info->spec)
1342 case SR_NOTHING: return TRUE;
1344 if (context_getFlag (FLG_INTERNALGLOBS))
1346 return (sRefSet_modifyMember (sl, s));
1350 (void) sRefSet_modifyMember (sl, s);
1353 case SR_SPECSTATE: return TRUE;
1354 case SR_SYSTEM: return (sRefSet_modifyMember (sl, s));
1355 case SR_GLOBALMARKER: BADBRANCH;
1359 case SK_RESULT: BADBRANCH;
1365 ** this should probably be elsewhere...
1367 ** returns TRUE iff sl indicates that s can be modified
1371 bool sRef_doModify (sRef s, sRefSet sl)
1373 llassert (sRef_isValid (s));
1377 case SK_UNCONSTRAINED:
1381 if (sRef_isFileOrGlobalScope (s))
1383 if (context_checkGlobMod (s))
1385 return (sRefSet_modifyMember (sl, s));
1389 (void) sRefSet_modifyMember (sl, s);
1401 return (OR (sRefSet_modifyMember (sl, s),
1402 sRef_doModifyVal (s->info->arrayfetch->arr, sl)));
1405 sRef sr = s->info->field->rec;
1407 if (sr->kind == SK_PARAM)
1409 return TRUE; /* structs are shallow-copied on call */
1412 return (OR (sRefSet_modifyMember (sl, s),
1413 sRef_doModifyVal (s->info->field->rec, sl)));
1417 return (OR (sRefSet_modifyMember (sl, s),
1418 sRef_doModifyVal (s->info->ref, sl)));
1421 return (OR (sRefSet_modifyMember (sl, s),
1422 sRef_doModifyVal (s->info->ref, sl)));
1424 return (AND (sRef_doModify (s->info->conj->a, sl),
1425 (sRef_doModify (s->info->conj->b, sl))));
1436 switch (s->info->spec)
1438 case SR_NOTHING: return TRUE;
1439 case SR_INTERNAL: return TRUE;
1440 case SR_SPECSTATE: return TRUE;
1441 case SR_SYSTEM: return (sRefSet_modifyMember (sl, s));
1442 case SR_GLOBALMARKER: BADBRANCH;
1445 case SK_RESULT: BADBRANCH;
1450 static /*@exposed@*/ sRef
1451 sRef_leastCommon (/*@exposed@*/ sRef s1, sRef s2)
1453 llassert (sRef_similar (s1, s2));
1455 if (!sRef_isValid (s1)) return s1;
1456 if (!sRef_isValid (s2)) return s1;
1458 sRef_combineDefState (s1, s2);
1459 sRef_combineNullState (s1, s2);
1460 sRef_combineExKinds (s1, s2);
1462 if (s1->aliaskind != s2->aliaskind)
1464 if (s1->aliaskind == AK_UNKNOWN)
1466 s1->aliaskind = s2->aliaskind;
1468 else if (s2->aliaskind == AK_UNKNOWN)
1474 s1->aliaskind = AK_ERROR;
1481 int sRef_compare (sRef s1, sRef s2)
1483 if (s1 == s2) return 0;
1485 if (sRef_isInvalid (s1)) return -1;
1486 if (sRef_isInvalid (s2)) return 1;
1488 INTCOMPARERETURN (s1->kind, s2->kind);
1489 INTCOMPARERETURN (s1->defstate, s2->defstate);
1490 INTCOMPARERETURN (s1->aliaskind, s2->aliaskind);
1492 DPRINTF (("Compare null state: %s / %s",
1493 sRef_unparseFull (s1),
1494 sRef_unparseFull (s2)));
1496 COMPARERETURN (nstate_compare (sRef_getNullState (s1),
1497 sRef_getNullState (s2)));
1502 return (int_compare (s1->info->paramno, s2->info->paramno));
1505 COMPARERETURN (sRef_compare (s1->info->arrayfetch->arr,
1506 s2->info->arrayfetch->arr));
1508 if (s1->info->arrayfetch->indknown && s2->info->arrayfetch->indknown)
1510 return (int_compare (s1->info->arrayfetch->ind,
1511 s2->info->arrayfetch->ind));
1513 if (!s1->info->arrayfetch->indknown && !s2->info->arrayfetch->indknown)
1520 COMPARERETURN (sRef_compare (s1->info->field->rec, s2->info->field->rec));
1522 if (cstring_equal (s1->info->field->field, s2->info->field->field))
1529 return (sRef_compare (s1->info->ref, s2->info->ref));
1531 COMPARERETURN (sRef_compare (s1->info->conj->a, s2->info->conj->a));
1532 return (sRef_compare (s1->info->conj->b, s2->info->conj->b));
1533 case SK_UNCONSTRAINED:
1534 return (cstring_compare (s1->info->fname, s2->info->fname));
1546 return (generic_compare (s1->info->spec, s2->info->spec));
1551 static bool cref_equal (cref c1, cref c2)
1553 return ((c1->lexlevel == c2->lexlevel) &&
1554 (usymId_equal (c1->index, c2->index)));
1558 ** returns true if s1 could be the same storage as s2.
1559 ** i.e., a[?] ~ a[3]. Note its not symmetric ... s1
1560 ** should be more specific.
1564 ** like similar, but matches objects <-> non-objects
1568 sRef_uniqueReference (sRef s)
1570 return (sRef_isFresh (s) || sRef_isUnique (s)
1571 || sRef_isOnly (s) || sRef_isStack (s)
1572 || sRef_isAddress (s));
1576 sRef_similarRelaxedAux (sRef s1, sRef s2)
1580 if (sRef_isUnknownArrayFetch (s1))
1590 if (sRef_isInvalid (s1) || sRef_isInvalid (s2)) return FALSE;
1592 if (sRef_isConj (s2))
1593 return (sRef_similarRelaxedAux (s1, sRef_getConjA (s2)) ||
1594 sRef_similarRelaxedAux (s1, sRef_getConjB (s2)));
1599 return ((s2->kind == SK_CVAR)
1600 && (cref_equal (s1->info->cvar, s2->info->cvar)));
1602 return ((s2->kind == SK_PARAM)
1603 && (s1->info->paramno == s2->info->paramno));
1605 if (s2->kind == SK_ARRAYFETCH)
1607 if (sRef_similarRelaxedAux (s1->info->arrayfetch->arr,
1608 s2->info->arrayfetch->arr))
1610 if (s1->info->arrayfetch->indknown)
1612 if (s2->info->arrayfetch->indknown)
1614 return (s1->info->arrayfetch->ind == s2->info->arrayfetch->ind);
1629 return ((s2->kind == SK_FIELD
1630 && (sRef_similarRelaxedAux (s1->info->field->rec,
1631 s2->info->field->rec)
1632 && cstring_equal (s1->info->field->field,
1633 s2->info->field->field))));
1635 return ((s2->kind == SK_PTR)
1636 && sRef_similarRelaxedAux (s1->info->ref, s2->info->ref));
1638 return ((s2->kind == SK_ADR)
1639 && sRef_similarRelaxedAux (s1->info->ref, s2->info->ref));
1641 return ((sRef_similarRelaxedAux (s1->info->conj->a, s2) ||
1642 (sRef_similarRelaxedAux (s1->info->conj->b, s2))));
1644 return (s1->info->spec == s2->info->spec);
1645 case SK_UNCONSTRAINED:
1646 return (cstring_equal (s1->info->fname, s2->info->fname));
1661 sRef_similarRelaxed (sRef s1, sRef s2)
1667 if (sRef_isThroughArrayFetch (s1))
1677 if (sRef_isInvalid (s1) || sRef_isInvalid (s2)) return FALSE;
1679 us1 = sRef_uniqueReference (s1);
1680 us2 = sRef_uniqueReference (s2);
1682 if ((s1->kind == SK_EXTERNAL && (s2->kind != SK_EXTERNAL && !us2))
1683 || (s2->kind == SK_EXTERNAL && (s1->kind != SK_EXTERNAL && !us1)))
1686 ** Previously, also:
1687 ** || (sRef_isExposed (s1) && !us2) || (sRef_isExposed (s2) && !us1)) ????
1689 ** No clue why this was there?!
1693 if (sRef_isExposed (s1) && sRef_isCvar (s1))
1695 uentry ue1 = sRef_getUentry (s1);
1697 if (uentry_isRefParam (ue1))
1699 return sRef_similarRelaxedAux (s1, s2);
1703 if (sRef_isExposed (s2) && sRef_isCvar (s2))
1705 uentry ue2 = sRef_getUentry (s2);
1707 if (uentry_isRefParam (ue2))
1709 return sRef_similarRelaxedAux (s1, s2);
1713 return (ctype_match (s1->type, s2->type));
1717 return sRef_similarRelaxedAux (s1, s2);
1722 sRef_similar (sRef s1, sRef s2)
1724 if (s1 == s2) return TRUE;
1725 if (sRef_isInvalid (s1) || sRef_isInvalid (s2)) return FALSE;
1727 if (sRef_isConj (s2))
1729 return (sRef_similar (s1, sRef_getConjA (s2)) ||
1730 sRef_similar (s1, sRef_getConjB (s2)));
1733 if (sRef_isDerived (s2))
1735 return (sRef_includedBy (s1, s2->info->ref));
1741 return ((s2->kind == SK_CVAR)
1742 && (cref_equal (s1->info->cvar, s2->info->cvar)));
1744 return ((s2->kind == SK_PARAM)
1745 && (s1->info->paramno == s2->info->paramno));
1747 if (s2->kind == SK_ARRAYFETCH)
1749 if (sRef_similar (s1->info->arrayfetch->arr,
1750 s2->info->arrayfetch->arr))
1752 if (s1->info->arrayfetch->indknown)
1754 if (s2->info->arrayfetch->indknown)
1756 return (s1->info->arrayfetch->ind == s2->info->arrayfetch->ind);
1771 if (s2->kind == SK_PTR)
1773 if (sRef_similar (s1->info->arrayfetch->arr,
1783 return ((s2->kind == SK_FIELD
1784 && (sRef_similar (s1->info->field->rec,
1785 s2->info->field->rec)
1786 && cstring_equal (s1->info->field->field,
1787 s2->info->field->field))));
1789 if (s2->kind == SK_PTR)
1791 return sRef_similar (s1->info->ref, s2->info->ref);
1795 if (s2->kind == SK_ARRAYFETCH)
1797 if (sRef_similar (s2->info->arrayfetch->arr,
1807 return ((s2->kind == SK_ADR)
1808 && sRef_similar (s1->info->ref, s2->info->ref));
1810 return ((sRef_similar (s1->info->conj->a, s2) ||
1811 (sRef_similar (s1->info->conj->b, s2))));
1813 return (sRef_includedBy (s2, s1->info->ref));
1814 case SK_UNCONSTRAINED:
1815 return (s2->kind == SK_UNCONSTRAINED
1816 && cstring_equal (s1->info->fname, s2->info->fname));
1826 return (s2->kind == SK_SPECIAL
1827 && (s1->info->spec == s2->info->spec));
1830 /*@notreached@*/ DPRINTF (("Fell through for: %s / %s", sRef_unparse (s1), sRef_unparse (s2)));
1835 ** return TRUE iff small can be derived from big.
1837 ** (e.g. x, x.a is includedBy x;
1838 ** x.a is included By x.a;
1842 sRef_includedBy (sRef small, sRef big)
1844 if (small == big) return TRUE;
1845 if (sRef_isInvalid (small) || sRef_isInvalid (big)) return FALSE;
1847 if (sRef_isConj (big))
1848 return (sRef_similar (small, sRef_getConjA (big)) ||
1849 sRef_similar (small, sRef_getConjB (big)));
1851 switch (small->kind)
1855 return (sRef_same (small, big));
1857 if (big->kind == SK_ARRAYFETCH)
1859 if (sRef_same (small->info->arrayfetch->arr, big->info->arrayfetch->arr))
1861 if (small->info->arrayfetch->indknown)
1863 if (big->info->arrayfetch->indknown)
1865 return (small->info->arrayfetch->ind == big->info->arrayfetch->ind);
1878 return (sRef_includedBy (small->info->arrayfetch->arr, big));
1880 if (big->kind == SK_FIELD)
1883 (sRef_same (small->info->field->rec, big->info->field->rec) &&
1884 cstring_equal (small->info->field->field, big->info->field->field));
1888 return (sRef_includedBy (small->info->field->rec, big));
1892 if (big->kind == SK_PTR)
1894 return sRef_same (small->info->ref, big->info->ref);
1898 return (sRef_includedBy (small->info->ref, big));
1902 return ((big->kind == SK_ADR) && sRef_similar (small->info->ref, big->info->ref));
1904 return ((sRef_includedBy (small->info->conj->a, big) ||
1905 (sRef_includedBy (small->info->conj->b, big))));
1907 return (sRef_includedBy (small->info->ref, big));
1908 case SK_UNCONSTRAINED:
1918 switch (small->info->spec)
1920 case SR_NOTHING: return TRUE;
1922 case SR_INTERNAL: return (sRef_isSpecInternalState (big) ||
1923 sRef_isFileStatic (big));
1924 case SR_SYSTEM: return (sRef_isSystemState (big));
1925 case SR_GLOBALMARKER: BADBRANCH;
1932 ** Same is similar to similar, but not quite the same.
1933 ** same and realSame aren't the same, but they are really similar.
1934 ** similarly, same is the same as same. but realSame is
1935 ** not really the same as same, or similar to similar.
1937 ** Similarly to similar, same checks if two sRefs are the same.
1938 ** The similarities end, however, when same compares arrays
1939 ** with unknown indexes. Similar returns false; same returns true.
1941 ** Similarly to similar and same, realSame is the same as same,
1942 ** except they do not behave the same when face with unknown
1943 ** sRefs. Same thinks they are not the same, but realSame thinks
1949 sRef_realSame (sRef s1, sRef s2)
1951 if (s1 == s2) return TRUE;
1952 if (sRef_isInvalid (s1) || sRef_isInvalid (s2)) return FALSE;
1957 return ((s2->kind == SK_CVAR) && (cref_equal (s1->info->cvar, s2->info->cvar)));
1959 return ((s2->kind == SK_PARAM) && (s1->info->paramno == s2->info->paramno));
1961 if (s2->kind == SK_ARRAYFETCH)
1963 if (sRef_realSame (s1->info->arrayfetch->arr, s2->info->arrayfetch->arr))
1965 if (s1->info->arrayfetch->indknown && s2->info->arrayfetch->indknown)
1967 return (s1->info->arrayfetch->ind == s2->info->arrayfetch->ind);
1969 if (!s1->info->arrayfetch->indknown && !s2->info->arrayfetch->indknown)
1978 return ((s2->kind == SK_FIELD &&
1979 (sRef_realSame (s1->info->field->rec, s2->info->field->rec) &&
1980 cstring_equal (s1->info->field->field, s2->info->field->field))));
1982 return ((s2->kind == SK_PTR) && sRef_realSame (s1->info->ref, s2->info->ref));
1984 return ((s2->kind == SK_ADR) && sRef_realSame (s1->info->ref, s2->info->ref));
1986 return ((sRef_realSame (s1->info->conj->a, s2) ||
1987 (sRef_realSame (s1->info->conj->b, s2))));
1989 return ((s2->kind == SK_OBJECT)
1990 && ctype_match (s1->info->object, s2->info->object));
1992 return ((s2->kind == SK_EXTERNAL)
1993 && sRef_realSame (s1->info->ref, s2->info->ref));
1995 return ((s2->kind == SK_SPECIAL) && s1->info->spec == s2->info->spec);
1997 return ((s2->kind == SK_DERIVED) && sRef_realSame (s1->info->ref, s2->info->ref));
1998 case SK_UNCONSTRAINED:
1999 return ((s2->kind == SK_UNCONSTRAINED)
2000 && (cstring_equal (s1->info->fname, s2->info->fname)));
2006 return TRUE; /* changed this! was false */
2012 sRef_sameObject (sRef s1, sRef s2)
2018 ** same is similar to similar, but not quite the same.
2020 ** Similarly to similar, same checks is two sRefs are the same.
2021 ** The similarities end, however, when same compares arrays
2022 ** with unknown indexes. Similar returns false; same returns true.
2026 sRef_same (sRef s1, sRef s2)
2028 if (s1 == s2) return TRUE;
2029 if (sRef_isInvalid (s1) || sRef_isInvalid (s2)) return FALSE;
2034 return ((s2->kind == SK_CVAR) && (cref_equal (s1->info->cvar, s2->info->cvar)));
2036 return ((s2->kind == SK_PARAM) && (s1->info->paramno == s2->info->paramno));
2038 if (s2->kind == SK_ARRAYFETCH)
2040 llassert (s1->info->field->rec != s1);
2041 if (sRef_same (s1->info->arrayfetch->arr, s2->info->arrayfetch->arr))
2043 if (s1->info->arrayfetch->indknown && s2->info->arrayfetch->indknown)
2045 return (s1->info->arrayfetch->ind == s2->info->arrayfetch->ind);
2053 llassert (s1->info->field->rec != s1);
2054 return ((s2->kind == SK_FIELD &&
2055 (sRef_same (s1->info->field->rec, s2->info->field->rec) &&
2056 cstring_equal (s1->info->field->field, s2->info->field->field))));
2060 llassert (s1->info->ref != s1);
2061 return ((s2->kind == SK_PTR) && sRef_same (s1->info->ref, s2->info->ref));
2065 llassert (s1->info->ref != s1);
2066 return ((s2->kind == SK_ADR) && sRef_same (s1->info->ref, s2->info->ref));
2069 llassert (s1->info->conj->a != s1);
2070 llassert (s1->info->conj->b != s1);
2071 return ((sRef_same (s1->info->conj->a, s2)) && /* or or and? */
2072 (sRef_same (s1->info->conj->b, s2)));
2074 return ((s2->kind == SK_SPECIAL) && s1->info->spec == s2->info->spec);
2076 llassert (s1->info->ref != s1);
2077 return ((s2->kind == SK_DERIVED) && sRef_same (s1->info->ref, s2->info->ref));
2079 case SK_UNCONSTRAINED:
2092 ** sort of similar, for use in def/use
2096 sRef_closeEnough (sRef s1, sRef s2)
2098 if (s1 == s2) return TRUE;
2099 if (sRef_isInvalid (s1) || sRef_isInvalid (s2)) return FALSE;
2104 return (((s2->kind == SK_CVAR) &&
2105 (cref_equal (s1->info->cvar, s2->info->cvar))) ||
2106 (s2->kind == SK_UNCONSTRAINED && s1->info->cvar->lexlevel == 0));
2107 case SK_UNCONSTRAINED:
2108 return (s2->kind == SK_UNCONSTRAINED
2109 || ((s2->kind == SK_CVAR) && (s2->info->cvar->lexlevel == 0)));
2111 return ((s2->kind == SK_PARAM)
2112 && (s1->info->paramno == s2->info->paramno));
2114 if (s2->kind == SK_ARRAYFETCH)
2116 if (sRef_closeEnough (s1->info->arrayfetch->arr, s2->info->arrayfetch->arr))
2118 if (s1->info->arrayfetch->indknown && s2->info->arrayfetch->indknown)
2120 return (s1->info->arrayfetch->ind == s2->info->arrayfetch->ind);
2127 return ((s2->kind == SK_FIELD &&
2128 (sRef_closeEnough (s1->info->field->rec, s2->info->field->rec) &&
2129 cstring_equal (s1->info->field->field, s2->info->field->field))));
2131 return ((s2->kind == SK_PTR) && sRef_closeEnough (s1->info->ref, s2->info->ref));
2133 return ((s2->kind == SK_ADR) && sRef_closeEnough (s1->info->ref, s2->info->ref));
2135 return ((s2->kind == SK_DERIVED) && sRef_closeEnough (s1->info->ref, s2->info->ref));
2137 return ((sRef_closeEnough (s1->info->conj->a, s2)) ||
2138 (sRef_closeEnough (s1->info->conj->b, s2)));
2140 return ((s2->kind == SK_SPECIAL) && s1->info->spec == s2->info->spec);
2156 s is an sRef of a formal paramenter in a function call constraint
2157 we trys to return a constraint expression derived from the actual parementer of a function call.
2160 /*@only@*/ constraintExpr sRef_fixConstraintParam (/*@observer@*/ sRef s, /*@observer@*/ /*@temp@*/ exprNodeList args)
2164 if (sRef_isInvalid (s))
2165 llfatalbug((message("Invalid sRef")));
2171 /* s = sRef_saveCopy(s); */ /*@i523@*/
2172 ce = constraintExpr_makeTermsRef (s);
2179 temp = (sRef_makeField (sRef_fixBaseParam (s->info->field->rec, args),
2180 s->info->field->field));
2181 ce = constraintExpr_makeTermsRef (temp);
2187 temp = (sRef_makePointer (sRef_fixBaseParam (s->info->ref, args)));
2188 /* temp = sRef_saveCopy(temp); */ /*@i523@*/
2189 ce = constraintExpr_makeTermsRef (temp);
2196 temp = sRef_saveCopy(s);
2197 temp = sRef_fixBaseParam (temp, args);
2198 ce = constraintExpr_makeTermsRef (temp);
2206 temp = sRef_saveCopy(s);
2207 ce = constraintExpr_makeTermsRef (temp);
2212 llassert(exprNodeList_size (args) > s->info->paramno);
2214 exprNode e = exprNodeList_nth (args, s->info->paramno);
2216 llassert( !(exprNode_isError (e)) );
2217 ce = constraintExpr_makeExprNode (e);
2224 llcontbug (message ("Trying to do fixConstraintParam on nonparam, nonglobal: %q for function with arguments %q",
2225 sRef_unparse (s), exprNodeList_unparse(args)));
2226 temp = sRef_saveCopy(s);
2227 ce = constraintExpr_makeTermsRef (temp);
2239 sRef_fixBaseParam (/*@returned@*/ sRef s, exprNodeList args)
2241 if (sRef_isInvalid (s)) return (sRef_undefined);
2245 case SK_UNCONSTRAINED:
2250 if (exprNodeList_size (args) > s->info->paramno)
2252 exprNode e = exprNodeList_nth (args, s->info->paramno);
2254 if (exprNode_isError (e))
2256 return sRef_makeUnknown ();
2259 return (exprNode_getSref (e));
2263 return sRef_makeUnknown ();
2268 if (s->info->arrayfetch->indknown)
2270 return (sRef_makeArrayFetchKnown
2271 (sRef_fixBaseParam (s->info->arrayfetch->arr, args),
2272 s->info->arrayfetch->ind));
2276 return (sRef_makeArrayFetch
2277 (sRef_fixBaseParam (s->info->arrayfetch->arr, args)));
2280 return (sRef_makeField (sRef_fixBaseParam (s->info->field->rec, args),
2281 s->info->field->field));
2284 return (sRef_makePointer (sRef_fixBaseParam (s->info->ref, args)));
2287 return (sRef_makeAddress (sRef_fixBaseParam (s->info->ref, args)));
2290 return (sRef_makeConj (sRef_fixBaseParam (s->info->conj->a, args),
2291 sRef_fixBaseParam (s->info->conj->b, args)));
2307 sRef_undumpGlobal (char **c)
2317 usymId uid = usymId_fromInt (reader_getInt (c));
2322 reader_checkChar (c, '@');
2323 defstate = sstate_fromInt (reader_getInt (c));
2325 reader_checkChar (c, '@');
2326 nullstate = nstate_fromInt (reader_getInt (c));
2328 ret = sRef_makeGlobal (uid, ctype_unknown, stateInfo_currentLoc ());
2329 sRef_setNullStateN (ret, nullstate);
2330 ret->defstate = defstate;
2335 int i = reader_getInt (c);
2336 speckind sk = speckind_fromInt (i);
2340 case SR_NOTHING: return (sRef_makeNothing ());
2341 case SR_INTERNAL: return (sRef_makeInternalState ());
2342 case SR_SPECSTATE: return (sRef_makeSpecState ());
2343 case SR_SYSTEM: return (sRef_makeSystemState ());
2344 case SR_GLOBALMARKER: BADBRANCH;
2349 return sRef_undefined;
2351 return sRef_makeUnknown ();
2353 return sRef_makeUnknown ();
2355 llfatalerror (message ("sRef_undumpGlobal: bad line: %s",
2356 cstring_fromChars (*c)));
2361 static /*@exposed@*/ sRef sRef_undumpBody (char **c)
2370 return (sRef_makeGlobal (usymId_fromInt (reader_getInt (c)), ctype_unknown, stateInfo_currentLoc ()));
2372 return (sRef_makeParam (reader_getInt (c), ctype_unknown, stateInfo_makeLoc (g_currentloc)));
2374 return (sRef_makeResult (ctype_undump (c)));
2377 if ((**c >= '0' && **c <= '9') || **c == '-')
2379 int i = reader_getInt (c);
2380 sRef arr = sRef_undump (c);
2381 sRef ret = sRef_buildArrayFetchKnown (arr, i);
2387 sRef arr = sRef_undump (c);
2388 sRef ret = sRef_buildArrayFetch (arr);
2395 cstring fname = cstring_undefined;
2400 fname = cstring_appendChar (fname, **c);
2405 ret = sRef_buildField (sRef_undump (c), fname);
2406 cstring_markOwned (fname);
2411 int i = reader_getInt (c);
2412 speckind sk = speckind_fromInt (i);
2416 case SR_NOTHING: return (sRef_makeNothing ());
2417 case SR_INTERNAL: return (sRef_makeInternalState ());
2418 case SR_SPECSTATE: return (sRef_makeSpecState ());
2419 case SR_SYSTEM: return (sRef_makeSystemState ());
2420 case SR_GLOBALMARKER: BADBRANCH;
2426 sRef ptr = sRef_undump (c);
2427 sRef ret = sRef_makePointer (ptr);
2433 sRef adr = sRef_undump (c);
2434 sRef ret = sRef_makeAddress (adr);
2440 return (sRef_makeObject (ctype_undump (c)));
2444 sRef s1 = sRef_undump (c);
2445 sRef s2 = ((*c)++, sRef_undump (c));
2446 sRef ret = sRef_makeConj (s1, s2);
2451 return sRef_undefined;
2453 return sRef_makeUnknown ();
2455 return sRef_makeUnknown ();
2457 llfatalerror (message ("sRef_undump: bad line: %s", cstring_fromChars (*c)));
2462 /*@exposed@*/ sRef sRef_undump (char **c)
2464 sRef res = sRef_undumpBody (c);
2466 if (reader_optCheckChar (c, '='))
2468 multiVal mv = multiVal_undump (c);
2469 sRef_setValue (res, mv);
2470 reader_checkChar (c, '=');
2476 static /*@only@*/ cstring sRef_dumpBody (sRef s)
2478 if (sRef_isInvalid (s))
2480 return (cstring_makeLiteral ("-"));
2487 return (message ("p%d", s->info->paramno));
2489 if (s->info->arrayfetch->indknown)
2491 return (message ("a%d%q", s->info->arrayfetch->ind,
2492 sRef_dump (s->info->arrayfetch->arr)));
2496 return (message ("a%q", sRef_dump (s->info->arrayfetch->arr)));
2499 return (message ("f%s.%q", s->info->field->field,
2500 sRef_dump (s->info->field->rec)));
2502 return (message ("t%q", sRef_dump (s->info->ref)));
2504 return (message ("d%q", sRef_dump (s->info->ref)));
2506 return (message ("o%q", ctype_dump (s->info->object)));
2508 return (message ("s%d", (int) s->info->spec));
2510 return (message ("c%q.%q",
2511 sRef_dump (s->info->conj->a),
2512 sRef_dump (s->info->conj->b)));
2514 if (sRef_isFileOrGlobalScope (s))
2516 return (message ("g%d",
2517 usymtab_convertId (s->info->cvar->index)));
2521 llcontbug (message ("Dumping local variable: %q",
2522 sRef_unparseDebug (s)));
2523 return (cstring_makeLiteral ("u"));
2526 return (cstring_makeLiteral ("u"));
2528 return (message ("r%q", ctype_dump (s->type)));
2534 case SK_UNCONSTRAINED:
2535 llcontbug (message ("sRef_dump: bad kind: %q",
2536 sRef_unparseFull (s)));
2537 return (cstring_makeLiteral ("x"));
2544 /*@only@*/ cstring sRef_dump (sRef s)
2546 cstring res = sRef_dumpBody (s);
2548 if (sRef_hasValue (s))
2550 res = message ("%q=%q=", res, multiVal_dump (sRef_getValue (s)));
2556 cstring sRef_dumpGlobal (sRef s)
2558 llassert (!sRef_hasValue (s));
2560 if (sRef_isInvalid (s))
2562 return (cstring_makeLiteral ("-"));
2569 if (sRef_isFileOrGlobalScope (s))
2571 return (message ("g%d@%d@%d",
2572 usymtab_convertId (s->info->cvar->index),
2574 (int) sRef_getNullState (s)));
2578 llcontbug (message ("Dumping local variable: %q",
2579 sRef_unparseDebug (s)));
2580 return (cstring_makeLiteral ("u"));
2583 return (cstring_makeLiteral ("u"));
2585 return (message ("s%d", (int) s->info->spec));
2587 llcontbug (message ("sRef_dumpGlobal: bad kind: %q",
2588 sRef_unparseFull (s)));
2589 return (cstring_makeLiteral ("x"));
2597 sRef_deriveType (sRef s, uentryList cl)
2599 if (sRef_isInvalid (s)) return ctype_unknown;
2604 return (uentry_getType (usymtab_getRefQuiet (s->info->cvar->lexlevel,
2605 s->info->cvar->index)));
2606 case SK_UNCONSTRAINED:
2607 return (ctype_unknown);
2609 if (s->info->paramno >= 0)
2611 return uentry_getType (uentryList_getN (cl, s->info->paramno));
2615 return ctype_unknown;
2619 ctype ca = sRef_deriveType (s->info->arrayfetch->arr, cl);
2621 if (ctype_isArray (ca))
2623 return (ctype_baseArrayPtr (ca));
2625 else if (ctype_isUnknown (ca))
2631 llcontbuglit ("sRef_deriveType: inconsistent array type");
2637 ctype ct = sRef_deriveType (s->info->field->rec, cl);
2639 if (ctype_isStructorUnion (ct))
2641 uentry ue = uentryList_lookupField (ctype_getFields (ct),
2642 s->info->field->field);
2644 if (uentry_isValid (ue))
2646 return (uentry_getType (ue));
2650 llcontbuglit ("sRef_deriveType: bad field");
2651 return ctype_unknown;
2654 else if (ctype_isUnknown (ct))
2660 llcontbuglit ("sRef_deriveType: inconsistent field type");
2666 ctype ct = sRef_deriveType (s->info->ref, cl);
2668 if (ctype_isUnknown (ct)) return ct;
2669 if (ctype_isPointer (ct)) return (ctype_baseArrayPtr (ct));
2672 llcontbuglit ("sRef_deriveType: inconsistent pointer type");
2678 ctype ct = sRef_deriveType (s->info->ref, cl);
2680 if (ctype_isUnknown (ct)) return ct;
2681 return ctype_makePointer (ct);
2685 return sRef_deriveType (s->info->ref, cl);
2689 return (s->info->object);
2693 return (ctype_makeConj (sRef_deriveType (s->info->conj->a, cl),
2694 sRef_deriveType (s->info->conj->b, cl)));
2706 return ctype_unknown;
2712 sRef_getType (sRef s)
2714 if (sRef_isInvalid (s)) return ctype_unknown;
2720 sRef_unparseOpt (sRef s)
2722 sRef rb = sRef_getRootBase (s);
2724 if (sRef_isMeaningful (rb) && !sRef_isConst (rb))
2726 cstring ret = sRef_unparse (s);
2728 llassertprint (!cstring_equalLit (ret, "?"), ("print: %s", sRef_unparseDebug (s)));
2730 if (!cstring_isEmpty (ret))
2732 return (cstring_appendChar (ret, ' '));
2740 return cstring_undefined;
2744 sRef_unparsePreOpt (sRef s)
2746 sRef rb = sRef_getRootBase (s);
2748 if (sRef_isMeaningful (rb) && !sRef_isConst (rb))
2750 cstring ret = sRef_unparse (s);
2752 llassertprint (!cstring_equalLit (ret, "?"), ("print: %s", sRef_unparseDebug (s)));
2753 return (cstring_prependCharO (' ', ret));
2756 return cstring_undefined;
2760 sRef_unparse (sRef s)
2762 if (sRef_isInvalid (s)) return (cstring_makeLiteral ("?"));
2764 if (context_inFunctionLike ())
2766 return (sRef_unparseWithArgs (s, context_getParams ()));
2770 DPRINTF (("Not in function like: %s", context_unparse ()));
2771 return (sRef_unparseNoArgs (s));
2775 static /*@only@*/ cstring
2776 sRef_unparseWithArgs (sRef s, uentryList args)
2778 if (sRef_isInvalid (s))
2780 return (cstring_makeLiteral ("?"));
2786 return (uentry_getName (usymtab_getRefQuiet (s->info->cvar->lexlevel,
2787 s->info->cvar->index)));
2788 case SK_UNCONSTRAINED:
2789 return (cstring_copy (s->info->fname));
2792 if (s->info->paramno < uentryList_size (args)
2793 && s->info->paramno >= 0)
2795 uentry ue = uentryList_getN (args, s->info->paramno);
2797 if (uentry_isValid (ue))
2798 return uentry_getName (ue);
2801 return (message ("parameter %d", s->info->paramno + 1));
2804 if (s->info->arrayfetch->indknown)
2806 return (message ("%q[%d]", sRef_unparseWithArgs (s->info->arrayfetch->arr, args),
2807 s->info->arrayfetch->ind));
2811 return (message ("%q[]", sRef_unparseWithArgs (s->info->arrayfetch->arr, args)));
2814 if (s->info->field->rec->kind == SK_PTR)
2816 sRef ptr = s->info->field->rec;
2818 return (message ("%q->%s", sRef_unparseWithArgs (ptr->info->ref, args),
2819 s->info->field->field));
2821 return (message ("%q.%s", sRef_unparseWithArgs (s->info->field->rec, args),
2822 s->info->field->field));
2826 sRef ref = sRef_fixConj (s->info->ref);
2827 skind sk = ref->kind;
2832 ret = message ("storage pointed to by %q",
2833 sRef_unparseWithArgs (ref, args));
2835 else if (skind_isSimple (sk) || sk == SK_PTR)
2837 ret = message ("*%q", sRef_unparseWithArgs (ref, args));
2841 ret = message ("*(%q)", sRef_unparseWithArgs (ref, args));
2847 return (message ("&%q", sRef_unparseWithArgs (s->info->ref, args)));
2849 return (cstring_copy (ctype_unparse (s->info->object)));
2851 return (sRef_unparseWithArgs (sRef_getConjA (s), args));
2853 if (cstring_isDefined (s->info->fname))
2855 return (message ("[result of %s]", s->info->fname));
2859 return (cstring_makeLiteral ("<new>"));
2862 return (cstring_makeLiteral ("?"));
2864 return (message ("<derived %q>", sRef_unparse (s->info->ref)));
2866 return (message ("<external %q>", sRef_unparse (s->info->ref)));
2868 return (message ("<type %s>", ctype_unparse (s->type)));
2870 return (message ("<const %s>", ctype_unparse (s->type)));
2872 switch (s->info->spec)
2874 case SR_NOTHING: return cstring_makeLiteral ("nothing");
2875 case SR_INTERNAL: return cstring_makeLiteral ("internal state");
2876 case SR_SPECSTATE: return cstring_makeLiteral ("spec state");
2877 case SR_SYSTEM: return cstring_makeLiteral ("file system state");
2878 case SR_GLOBALMARKER: return cstring_makeLiteral ("<global marker>");
2882 return cstring_makeLiteral ("result");
2885 llbug (message ("Bad sref, kind = %d", (int) s->kind));
2893 sRef_unparseDebug (sRef s)
2895 if (sRef_isInvalid (s))
2897 return (cstring_makeLiteral ("<undef>"));
2903 case SK_UNCONSTRAINED:
2904 return (message ("<unconstrained %s>", s->info->fname));
2909 ce = usymtab_getRefQuiet (s->info->cvar->lexlevel, s->info->cvar->index);
2911 if (uentry_isInvalid (ce))
2913 return (message ("<scope: %d.%d *invalid*>",
2914 s->info->cvar->lexlevel,
2915 s->info->cvar->index));
2919 return (message ("<scope: %d.%d *%q*>",
2920 s->info->cvar->lexlevel,
2921 s->info->cvar->index,
2922 uentry_getName (ce)));
2928 return (message ("<parameter %d>", s->info->paramno + 1));
2931 if (s->info->arrayfetch->indknown)
2933 return (message ("%q[%d]", sRef_unparseDebug (s->info->arrayfetch->arr),
2934 s->info->arrayfetch->ind));
2938 return (message ("%q[]", sRef_unparseDebug (s->info->arrayfetch->arr)));
2941 return (message ("%q.%s", sRef_unparseDebug (s->info->field->rec),
2942 s->info->field->field));
2944 if (sRef_isField (s->info->ref))
2946 sRef fld = s->info->ref;
2948 return (message ("%q->%s", sRef_unparseDebug (fld->info->field->rec),
2949 fld->info->field->field));
2953 return (message ("*(%q)", sRef_unparseDebug (s->info->ref)));
2956 return (message ("&%q", sRef_unparseDebug (s->info->ref)));
2958 return (message ("<object type %s>", ctype_unparse (s->info->object)));
2960 return (message ("%q | %q", sRef_unparseDebug (s->info->conj->a),
2961 sRef_unparseDebug (s->info->conj->b)));
2963 return message ("<new: %s>", s->info->fname);
2965 return (message ("<derived %q>", sRef_unparseDebug (s->info->ref)));
2967 return (message ("<external %q>", sRef_unparseDebug (s->info->ref)));
2969 return (message ("<type %s>", ctype_unparse (s->type)));
2971 if (sRef_hasValue (s))
2973 return (message ("<const %s=%q>", ctype_unparse (s->type), multiVal_unparse (sRef_getValue (s))));
2977 return (message ("<const %s>", ctype_unparse (s->type)));
2980 return (message ("<result %s>", ctype_unparse (s->type)));
2982 return (message ("<spec %s>",
2983 cstring_makeLiteralTemp
2984 (s->info->spec == SR_NOTHING ? "nothing"
2985 : s->info->spec == SR_INTERNAL ? "internalState"
2986 : s->info->spec == SR_SPECSTATE ? "spec state"
2987 : s->info->spec == SR_SYSTEM ? "fileSystem"
2990 return cstring_makeLiteral ("<unknown>");
2996 static /*@only@*/ cstring
2997 sRef_unparseNoArgs (sRef s)
2999 if (sRef_isInvalid (s)) return (cstring_makeLiteral ("?"));
3003 case SK_UNCONSTRAINED:
3004 return (cstring_copy (s->info->fname));
3007 uentry ce = usymtab_getRefQuiet (s->info->cvar->lexlevel,
3008 s->info->cvar->index);
3010 if (uentry_isInvalid (ce))
3012 llcontbug (message ("sRef_unparseNoArgs: bad cvar: %q",
3013 sRef_unparseDebug (s)));
3014 return (sRef_unparseDebug (s));
3018 return (uentry_getName (ce));
3022 if (s->info->arrayfetch->indknown)
3024 return (message ("%q[%d]", sRef_unparseNoArgs (s->info->arrayfetch->arr),
3025 s->info->arrayfetch->ind));
3029 return (message ("%q[]", sRef_unparseNoArgs (s->info->arrayfetch->arr)));
3032 return (message ("%q.%s", sRef_unparseNoArgs (s->info->field->rec),
3033 s->info->field->field));
3036 sRef ref = sRef_fixConj (s->info->ref);
3037 skind sk = ref->kind;
3040 if (skind_isSimple (sk) || sk == SK_PTR)
3042 ret = message ("*%q", sRef_unparseNoArgs (ref));
3046 ret = message ("*(%q)", sRef_unparseNoArgs (ref));
3052 return (message ("&%q", sRef_unparseNoArgs (s->info->ref)));
3054 return (cstring_copy (ctype_unparse (s->info->object)));
3056 return (sRef_unparseNoArgs (s->info->conj->a));
3058 return (message ("result of %s", s->info->fname));
3060 return (message ("<der %q>", sRef_unparseNoArgs (s->info->ref)));
3062 return message ("<ext %q>", sRef_unparseNoArgs (s->info->ref));
3064 return (cstring_makeLiteral
3065 (s->info->spec == SR_NOTHING ? "nothing"
3066 : s->info->spec == SR_INTERNAL ? "internal state"
3067 : s->info->spec == SR_SPECSTATE ? "spec state"
3068 : s->info->spec == SR_SYSTEM ? "file system state"
3071 return cstring_makeLiteral ("result");
3075 return cstring_makeLiteral ("?");
3077 /* llcontbug (message ("sRef_unparseNoArgs: bad case: %q", sRef_unparseDebug (s))); */
3078 return (sRef_unparseDebug (s));
3083 /*@dependent@*/ sRef sRef_makeUnconstrained (cstring fname)
3085 sRef s = sRef_new ();
3087 s->kind = SK_UNCONSTRAINED;
3088 s->info = (sinfo) dmalloc (sizeof (*s->info));
3089 s->info->fname = fname;
3094 cstring sRef_unconstrainedName (sRef s)
3096 llassert (sRef_isUnconstrained (s));
3098 return s->info->fname;
3101 bool sRef_isUnconstrained (sRef s)
3103 return (sRef_isValid(s) && s->kind == SK_UNCONSTRAINED);
3106 static /*@dependent@*/ /*@notnull@*/ sRef
3107 sRef_makeCvarAux (int level, usymId index, ctype ct, /*@only@*/ stateInfo stinfo)
3109 sRef s = sRef_newRef ();
3112 s->info = (sinfo) dmalloc (sizeof (*s->info));
3114 s->info->cvar = (cref) dmalloc (sizeof (*s->info->cvar));
3115 s->info->cvar->lexlevel = level;
3116 s->info->cvar->index = index;
3118 /* for now, all globals are defined; all locals, aren't */
3120 if (level <= fileScope)
3122 s->defstate = SS_UNKNOWN;
3126 ctype rct = ctype_realType (ct);
3128 if (level != paramsScope
3129 && (ctype_isStructorUnion (rct) || ctype_isRealArray (rct)))
3131 s->defstate = SS_ALLOCATED;
3132 s->oaliaskind = s->aliaskind = AK_STACK;
3136 s->defstate = SS_UNDEFINED;
3137 s->oaliaskind = s->aliaskind = AK_LOCAL;
3143 llassert (level >= globScope);
3144 llassert (usymId_isValid (index));
3146 DPRINTF (("Made cvar: [%p] %s", s, sRef_unparseDebug (s)));
3147 llassert (valueTable_isUndefined (s->state));
3148 s->state = context_createValueTable (s, stinfo);
3152 /*@dependent@*/ sRef sRef_makeCvar (int level, usymId index, ctype ct, /*@only@*/ stateInfo stinfo)
3154 return (sRef_makeCvarAux (level, index, ct, stinfo));
3157 int sRef_lexLevel (sRef s)
3159 if (sRef_isValid (s))
3163 conj = sRef_fixConj (s);
3164 s = sRef_getRootBase (conj);
3166 if (sRef_isValid (s) && s->kind == SK_CVAR)
3168 return (s->info->cvar->lexlevel);
3176 sRef_makeGlobal (usymId l, ctype ct, /*@only@*/ stateInfo stinfo)
3178 return (sRef_makeCvar (globScope, l, ct, stinfo));
3182 sRef_setParamNo (sRef s, int l)
3184 llassert (sRef_isValid (s) && s->kind == SK_PARAM);
3185 s->info->paramno = l;
3189 /*@dependent@*/ sRef
3190 sRef_makeParam (int l, ctype ct, stateInfo stinfo)
3192 sRef s = sRef_new ();
3197 s->info = (sinfo) dmalloc (sizeof (*s->info));
3198 s->info->paramno = l;
3200 s->defstate = SS_UNKNOWN;
3201 /* (probably defined, unless its an out parameter) */
3203 llassert (valueTable_isUndefined (s->state));
3204 s->state = context_createValueTable (s, stinfo);
3209 sRef_isIndexKnown (sRef arr)
3213 llassert (sRef_isValid (arr));
3214 arr = sRef_fixConj (arr);
3216 llassert (arr->kind == SK_ARRAYFETCH);
3217 res = arr->info->arrayfetch->indknown;
3222 sRef_getIndex (sRef arr)
3226 llassert (sRef_isValid (arr));
3227 arr = sRef_fixConj (arr);
3229 llassert (arr->kind == SK_ARRAYFETCH);
3231 if (!arr->info->arrayfetch->indknown)
3233 llcontbug (message ("sRef_getIndex: unknown: %q", sRef_unparse (arr)));
3238 result = arr->info->arrayfetch->ind;
3244 static bool sRef_isZerothArrayFetch (/*@notnull@*/ sRef s)
3246 return (s->kind == SK_ARRAYFETCH
3247 && s->info->arrayfetch->indknown
3248 && (s->info->arrayfetch->ind == 0));
3251 /*@exposed@*/ sRef sRef_makeAddress (/*@exposed@*/ sRef t)
3254 if (sRef_isInvalid (t)) return sRef_undefined;
3256 if (sRef_isPointer (t))
3258 return (t->info->ref);
3260 else if (sRef_isZerothArrayFetch (t))
3262 return (t->info->arrayfetch->arr);
3266 sRef s = sRef_newRef ();
3269 s->type = ctype_makePointer (t->type);
3270 s->info = (sinfo) dmalloc (sizeof (*s->info));
3271 s->info->ref = t; /* sRef_copy (t); */ /*@i32@*/
3273 if (t->defstate == SS_UNDEFINED)
3274 /* no! it is allocated even still: && !ctype_isPointer (t->type)) */
3276 s->defstate = SS_ALLOCATED;
3280 s->defstate = t->defstate;
3283 if (t->aliaskind == AK_LOCAL)
3285 if (sRef_isLocalVar (t))
3287 s->aliaskind = AK_STACK;
3291 llassert (valueTable_isUndefined (s->state));
3292 s->state = context_createValueTable (s, stateInfo_makeLoc (g_currentloc));
3297 cstring sRef_getField (sRef s)
3301 llassert (sRef_isValid (s));
3302 s = sRef_fixConj (s);
3304 llassertprint (sRef_isValid (s) && (s->kind == SK_FIELD),
3305 ("s = %s", sRef_unparseDebug (s)));
3307 res = s->info->field->field;
3311 sRef sRef_getBase (sRef s)
3315 if (sRef_isInvalid (s)) return (sRef_undefined);
3317 s = sRef_fixConj (s);
3328 res = s->info->field->rec;
3332 res = s->info->arrayfetch->arr;
3336 res = sRef_undefined; /* shouldn't need it */
3343 ** same as getBase, except returns invalid
3344 ** (and doesn't use adr's)
3348 sRef_getBaseSafe (sRef s)
3352 if (sRef_isInvalid (s)) { return sRef_undefined; }
3354 s = sRef_fixConj (s);
3362 res = s->info->field->rec; break;
3364 res = s->info->arrayfetch->arr;
3367 res = sRef_undefined; break;
3373 /*@constant int MAXBASEDEPTH;@*/
3374 # define MAXBASEDEPTH 25
3376 static /*@exposed@*/ sRef
3377 sRef_getRootBaseAux (sRef s, int depth)
3379 if (sRef_isInvalid (s)) return sRef_undefined;
3381 if (depth > MAXBASEDEPTH)
3384 ("Warning: reference base limit exceeded for %q. "
3385 "This either means there is a variable with at least "
3386 "%d indirections from this reference, or "
3387 "there is a bug in Splint.",
3392 return sRef_undefined;
3399 return (sRef_getRootBaseAux (s->info->ref, depth + 1));
3401 return (sRef_getRootBaseAux (s->info->field->rec, depth + 1));
3403 return (sRef_getRootBaseAux (s->info->arrayfetch->arr, depth + 1));
3405 return (sRef_getRootBaseAux (sRef_fixConj (s), depth + 1));
3411 sRef sRef_getRootBase (sRef s)
3413 return (sRef_getRootBaseAux (s, 0));
3416 static bool sRef_isDeep (sRef s)
3418 if (sRef_isInvalid (s)) return FALSE;
3428 return (sRef_isDeep (sRef_fixConj (s)));
3434 static int sRef_depth (sRef s)
3436 if (sRef_isInvalid (s)) return 0;
3444 return 1 + sRef_depth (s->info->ref);
3446 return 1 + sRef_depth (s->info->field->rec);
3448 return 1 + sRef_depth (s->info->arrayfetch->arr);
3450 return (sRef_depth (sRef_fixConj (s)));
3457 sRef_makeObject (ctype o)
3459 sRef s = sRef_newRef (); /*@i423 same line is bad...@*/
3461 s->kind = SK_OBJECT;
3462 s->info = (sinfo) dmalloc (sizeof (*s->info));
3463 s->info->object = o;
3464 llassert (valueTable_isUndefined (s->state));
3465 s->state = context_createValueTable (s, stateInfo_makeLoc (g_currentloc));
3470 ** This is used to represent storage referenced by a parameter.
3473 sRef sRef_makeExternal (sRef t)
3475 sRef s = sRef_newRef ();
3477 llassert (sRef_isValid (t));
3479 s->kind = SK_EXTERNAL;
3480 s->info = (sinfo) dmalloc (sizeof (*s->info));
3482 s->info->ref = t; /* sRef_copy (t); */ /*@i32 was exposed@*/
3483 llassert (valueTable_isUndefined (s->state));
3484 s->state = context_createValueTable (s, stateInfo_makeLoc (g_currentloc));
3488 /*@dependent@*/ sRef sRef_makeDerived (/*@exposed@*/ sRef t)
3490 if (sRef_isValid (t))
3492 sRef s = sRef_newRef ();
3494 s->kind = SK_DERIVED;
3495 s->info = (sinfo) dmalloc (sizeof (*s->info));
3496 s->info->ref = t; /* sRef_copy (t); */ /*@i32@*/
3499 llassert (valueTable_isUndefined (s->state));
3500 s->state = context_createValueTable (s, stateInfo_makeLoc (g_currentloc));
3505 return sRef_undefined;
3510 ** definitely NOT symmetric:
3512 ** res fills in unknown state information from other
3516 sRef_mergeStateQuiet (sRef res, sRef other)
3518 llassert (sRef_isValid (res));
3519 llassert (sRef_isValid (other));
3521 res->modified = res->modified || other->modified;
3522 res->safe = res->safe && other->safe;
3524 if (res->defstate == SS_UNKNOWN)
3526 res->defstate = other->defstate;
3527 res->definfo = stateInfo_update (res->definfo, other->definfo);
3530 if (res->aliaskind == AK_UNKNOWN ||
3531 (res->aliaskind == AK_LOCAL && alkind_isKnown (other->aliaskind)))
3533 res->aliaskind = other->aliaskind;
3534 res->oaliaskind = other->oaliaskind;
3535 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
3538 if (res->expkind == XO_UNKNOWN)
3540 res->expkind = other->expkind;
3541 res->oexpkind = other->oexpkind;
3542 res->expinfo = stateInfo_update (res->expinfo, other->expinfo);
3545 /* out takes precedence over implicitly defined */
3546 if (res->defstate == SS_DEFINED && other->defstate != SS_UNKNOWN)
3548 res->defstate = other->defstate;
3549 res->definfo = stateInfo_update (res->definfo, other->definfo);
3552 if (sRef_getNullState (other) == NS_ERROR || sRef_getNullState (res) == NS_ERROR)
3554 sRef_setNullState (res, NS_ERROR, fileloc_undefined);
3558 if (sRef_getNullState (other) != NS_UNKNOWN
3559 && (sRef_getNullState (res) == NS_UNKNOWN || sRef_getNullState (res) == NS_NOTNULL
3560 || sRef_getNullState (res) == NS_MNOTNULL))
3562 sRef_updateNullState (res, other);
3568 ** definitely NOT symmetric:
3570 ** res fills in known state information from other
3574 sRef_mergeStateQuietReverse (/*@dependent@*/ sRef res, /*@dependent@*/ sRef other)
3576 bool changed = FALSE;
3578 llassert (sRef_isValid (res));
3579 llassert (sRef_isValid (other));
3580 sRef_checkMutable (res);
3582 if (res->kind != other->kind)
3588 res->kind = other->kind;
3589 res->type = other->type;
3590 res->info = sinfo_fullCopy (other);
3594 if (!ctype_equal (res->type, other->type))
3597 res->type = other->type;
3600 sinfo_update (res, other);
3603 res->modified = res->modified || other->modified;
3604 res->safe = res->safe && other->safe;
3606 if (res->aliaskind != other->aliaskind
3607 && (res->aliaskind == AK_UNKNOWN
3608 || ((res->aliaskind == AK_LOCAL
3609 || (res->aliaskind == AK_REFCOUNTED
3610 && other->aliaskind != AK_LOCAL))
3611 && other->aliaskind != AK_UNKNOWN)))
3614 res->aliaskind = other->aliaskind;
3615 res->oaliaskind = other->oaliaskind;
3616 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
3619 if (other->expkind != XO_UNKNOWN && other->expkind != res->expkind)
3622 res->expkind = other->expkind;
3623 res->expinfo = stateInfo_update (res->expinfo, other->expinfo);
3626 if (other->oexpkind != XO_UNKNOWN)
3628 res->oexpkind = other->oexpkind;
3631 /* out takes precedence over implicitly defined */
3633 if (res->defstate != other->defstate)
3635 if (other->defstate != SS_UNKNOWN)
3637 res->defstate = other->defstate;
3641 if (sRef_getNullState (other) == NS_ERROR || sRef_getNullState (res) == NS_ERROR)
3643 if (sRef_getNullState (res) != NS_ERROR)
3645 sRef_setNullStateN (res, NS_ERROR);
3651 if (sRef_getNullState (other) != NS_UNKNOWN && sRef_getNullState (other) != sRef_getNullState (res))
3654 sRef_updateNullState (res, other);
3660 sRef_clearDerived (res);
3665 sRef_mergeState (sRef res, sRef other, clause cl, fileloc loc)
3667 if (sRef_isValid (res) && sRef_isValid (other))
3669 sRef_mergeStateAux (res, other, cl, FALSE, loc, TRUE);
3673 if (sRef_isInvalid (res))
3675 llbug (message ("sRef_mergeState: invalid res sRef: %q",
3676 sRef_unparseDebug (other)));
3680 llbug (message ("sRef_mergeState: invalid other sRef: %q",
3681 sRef_unparseDebug (res)));
3687 sRef_mergeOptState (sRef res, sRef other, clause cl, fileloc loc)
3689 if (sRef_isValid (res) && sRef_isValid (other))
3691 sRef_mergeStateAux (res, other, cl, TRUE, loc, TRUE);
3695 if (sRef_isInvalid (res))
3697 llbug (message ("sRef_mergeOptState: invalid res sRef: %q",
3698 sRef_unparseDebug (other)));
3702 llbug (message ("sRef_mergeOptState: invalid other sRef: %q",
3703 sRef_unparseDebug (res)));
3709 sRef_mergeStateAux (/*@notnull@*/ sRef res, /*@notnull@*/ sRef other,
3710 clause cl, bool opt, fileloc loc,
3714 llassertfatal (sRef_isValid (res));
3715 llassertfatal (sRef_isValid (other));
3717 sRef_checkMutable (res);
3718 sRef_checkMutable (other);
3720 res->modified = res->modified || other->modified;
3722 if (res->kind == other->kind
3723 || (other->kind == SK_UNKNOWN || res->kind == SK_UNKNOWN))
3725 sstate odef = other->defstate;
3726 sstate rdef = res->defstate;
3727 nstate onull = sRef_getNullState (other);
3730 ** yucky stuff to handle
3735 if (other->defstate == SS_DEAD
3736 && ((sRef_isOnly (res) && sRef_definitelyNull (res))
3737 || (res->defstate == SS_UNDEFINED
3738 || res->defstate == SS_UNUSEABLE)))
3740 if (res->defstate == SS_UNDEFINED
3741 || res->defstate == SS_UNUSEABLE)
3743 res->defstate = SS_UNUSEABLE;
3747 res->defstate = SS_DEAD;
3750 res->definfo = stateInfo_update (res->definfo, other->definfo);
3751 sRef_clearDerived (other);
3752 sRef_clearDerived (res);
3754 else if (res->defstate == SS_DEAD
3755 && ((sRef_isOnly (other) && sRef_definitelyNull (other))
3756 || (other->defstate == SS_UNDEFINED
3757 || other->defstate == SS_UNUSEABLE)))
3759 if (other->defstate == SS_UNDEFINED
3760 || other->defstate == SS_UNUSEABLE)
3762 res->defstate = SS_UNUSEABLE;
3766 res->defstate = SS_DEAD;
3769 sRef_clearDerived (other);
3770 sRef_clearDerived (res);
3772 else if (res->defstate == SS_DEFINED
3773 && (other->defstate == SS_ALLOCATED
3774 && sRef_definitelyNull (other)))
3776 other->defstate = SS_DEFINED; /* definitely null! */
3778 else if (other->defstate == SS_DEFINED
3779 && (res->defstate == SS_ALLOCATED && sRef_definitelyNull (res)))
3781 res->defstate = SS_DEFINED;
3782 res->definfo = stateInfo_update (res->definfo, other->definfo);
3789 if (res->defstate == SS_DEAD && other->defstate == SS_DEAD)
3791 sRef_clearDerived (other);
3792 sRef_clearDerived (res);
3796 ** only & dead isn't really an only!
3799 if (alkind_isOnly (other->aliaskind) && other->defstate == SS_DEAD)
3801 other->aliaskind = AK_UNKNOWN;
3804 if (alkind_isOnly (res->aliaskind) && res->defstate == SS_DEAD)
3806 res->aliaskind = AK_UNKNOWN;
3810 ** Dead and dependent -> dead
3813 if (alkind_isDependent (other->aliaskind) && res->defstate == SS_DEAD)
3815 other->aliaskind = AK_UNKNOWN;
3816 other->defstate = SS_DEAD;
3817 sRef_clearDerived (res);
3818 sRef_clearDerived (other);
3821 if (alkind_isDependent (res->aliaskind) && other->defstate == SS_DEAD)
3823 res->aliaskind = AK_UNKNOWN;
3824 res->defstate = SS_DEAD;
3825 sRef_clearDerived (res);
3826 sRef_clearDerived (other);
3830 ** must do alias combine first, since it depends on
3831 ** original values of state and null.
3834 sRef_combineAliasKinds (res, other, cl, loc);
3835 sRef_combineDefState (res, other);
3836 sRef_combineNullState (res, other);
3838 if (rdef == SS_ALLOCATED || rdef == SS_SPECIAL)
3840 if (odef == SS_DEFINED)
3842 if (onull == NS_DEFNULL || onull == NS_CONSTNULL)
3844 res->deriv = sRefSet_copyInto (res->deriv, other->deriv);
3845 DPRINTF (("Copy derivs: %s", sRef_unparseFull (res)));
3848 else if (odef == SS_ALLOCATED || odef == SS_SPECIAL)
3853 if (ctype_isUnion (ctype_realType (sRef_getType (res))))
3855 res->deriv = sRef_mergeUnionDerivs (res->deriv,
3858 DPRINTF (("Copy derivs: %s", sRef_unparseFull (res)));
3862 res->deriv = sRef_mergeDerivs (res->deriv, other->deriv,
3864 DPRINTF (("Copy derivs: %s", sRef_unparseFull (res)));
3872 res->deriv = sRef_mergeDerivs (res->deriv, other->deriv,
3874 DPRINTF (("Copy derivs: %s", sRef_unparseFull (res)));
3884 if (rdef == SS_PDEFINED
3885 || (rdef == SS_DEFINED && odef == SS_PDEFINED))
3889 res->deriv = sRef_mergePdefinedDerivs (res->deriv, other->deriv,
3891 DPRINTF (("Copy derivs: %s", sRef_unparseFull (res)));
3896 if ((rdef == SS_DEFINED || rdef == SS_UNKNOWN)
3897 && res->defstate == SS_ALLOCATED)
3899 res->deriv = sRefSet_copyInto (res->deriv, other->deriv);
3905 res->deriv = sRef_mergeDerivs (res->deriv, other->deriv,
3907 DPRINTF (("Copy derivs: %s", sRef_unparseFull (res)));
3914 sRef_combineExKinds (res, other);
3918 if (res->kind == SK_ARRAYFETCH && other->kind == SK_PTR)
3920 sRef nother = sRef_buildArrayFetchKnown (sRef_getBase (other), 0);
3922 sRef_copyState (nother, other);
3923 sRef_mergeStateAux (res, nother, cl, opt, loc, doDerivs);
3925 else if (res->kind == SK_PTR && other->kind == SK_ARRAYFETCH)
3927 sRef nother = sRef_buildPointer (sRef_getBase (other));
3929 if (sRef_isValid (nother))
3931 sRef_copyState (nother, other);
3932 sRef_mergeStateAux (res, nother, cl, opt, loc, doDerivs);
3937 llcontbug (message ("merge conj: %q / %q", sRef_unparseFull (res),
3938 sRef_unparseFull (other)));
3944 ** Merge value table states
3951 ** This doesn't do anything. And its broken too...
3954 valueTable_elements (res->state, key, sv)
3956 stateValue os = valueTable_lookup (other->state, key);
3957 /*@unused@*/ int val;
3958 /*@unused@*/ char *msg;
3960 llassert (stateValue_isDefined (os));
3962 DPRINTF (("Merge state: %s / %s",
3963 cstring_toCharsSafe (stateValue_unparse (sv)),
3964 cstring_toCharsSafe (stateValue_unparse (os))));
3966 val = valueMatix_lookup (key,
3967 stateValue_getValue (os),
3968 stateValue_getValue (sv),
3970 DPRINTF (("Val: %d / %s", val, msg));
3972 } end_valueTable_elements ;
3978 sRef_mergeUnionDerivs (/*@only@*/ sRefSet res,
3979 /*@exposed@*/ sRefSet other, bool opt,
3980 clause cl, fileloc loc)
3982 if (sRefSet_isEmpty (res))
3984 return sRefSet_copyInto (res, other);
3988 sRefSet_allElements (other, el)
3990 if (sRef_isValid (el))
3992 sRef e2 = sRefSet_lookupMember (other, el);
3994 if (sRef_isValid (e2))
3996 sRef_mergeStateAux (el, e2, cl, opt, loc, FALSE);
4000 res = sRefSet_insert (res, el);
4003 } end_sRefSet_allElements ;
4009 static /*@only@*/ sRefSet
4010 sRef_mergeDerivs (/*@only@*/ sRefSet res, sRefSet other,
4011 bool opt, clause cl, fileloc loc)
4013 sRefSet ret = sRefSet_new ();
4015 sRefSet_allElements (res, el)
4017 if (sRef_isValid (el))
4019 sRef e2 = sRefSet_lookupMember (other, el);
4021 if (sRef_isValid (e2))
4023 if (el->defstate == SS_ALLOCATED &&
4024 e2->defstate == SS_PDEFINED)
4026 e2->defstate = SS_ALLOCATED;
4028 else if (e2->defstate == SS_ALLOCATED &&
4029 el->defstate == SS_PDEFINED)
4031 el->defstate = SS_ALLOCATED;
4032 sRef_clearDerived (el);
4034 else if ((el->defstate == SS_DEAD || sRef_isKept (el)) &&
4035 (e2->defstate == SS_DEFINED && !sRef_isKept (e2)))
4038 if (checkDeadState (el, TRUE, loc))
4040 if (sRef_isThroughArrayFetch (el))
4042 sRef_maybeKill (el, loc);
4043 sRef_maybeKill (e2, loc);
4047 else if ((e2->defstate == SS_DEAD || sRef_isKept (e2)) &&
4048 (el->defstate == SS_DEFINED && !sRef_isKept (el)))
4051 if (checkDeadState (e2, FALSE, loc))
4053 if (sRef_isThroughArrayFetch (el))
4055 sRef_maybeKill (el, loc);
4056 sRef_maybeKill (e2, loc);
4060 else if (el->defstate == SS_DEFINED &&
4061 e2->defstate == SS_PDEFINED)
4063 DPRINTF (("set pdefined: %s", sRef_unparseFull (el)));
4064 el->defstate = SS_PDEFINED;
4066 else if (e2->defstate == SS_DEFINED &&
4067 el->defstate == SS_PDEFINED)
4069 DPRINTF (("set pdefined: %s", sRef_unparseFull (e2)));
4070 e2->defstate = SS_PDEFINED;
4077 if (ctype_isUnion (ctype_realType (sRef_getType (el))))
4079 el->deriv = sRef_mergeUnionDerivs (el->deriv, e2->deriv,
4084 el->deriv = sRef_mergeDerivs (el->deriv, e2->deriv, opt, cl, loc);
4087 if (sRef_equivalent (el, e2))
4089 ret = sRefSet_insert (ret, el);
4093 sRef sr = sRef_leastCommon (el, e2);
4095 if (sRef_isValid (sr))
4097 ret = sRefSet_insert (ret, sr);
4105 (void) sRefSet_delete (other, e2);
4107 else /* not defined */
4109 (void) checkDeadState (el, TRUE, loc);
4112 } end_sRefSet_allElements;
4114 sRefSet_allElements (other, el)
4116 if (sRef_isValid (el))
4118 (void) checkDeadState (el, FALSE, loc);
4120 } end_sRefSet_allElements;
4127 ** Returns TRUE is there is an error.
4130 static bool checkDeadState (/*@notnull@*/ sRef el, bool tbranch, fileloc loc)
4133 ** usymtab_isGuarded --- the utab should still be in the
4134 ** state of the alternate branch.
4136 ** tbranch TRUE means el is released in the last branch, e.g.
4137 ** if (x != NULL) { ; } else { sfree (x); }
4138 ** so, if x is null in the other branch no error is reported.
4140 ** tbranch FALSE means this is the other branch:
4141 ** if (x != NULL) { sfree (x); } else { ; }
4142 ** so, if x is null in this branch there is no error.
4146 if ((sRef_isDead (el) || sRef_isKept (el))
4147 && !sRef_isDeepUnionField (el) && !sRef_isThroughArrayFetch (el))
4152 if (usymtab_isDefinitelyNullDeep (el))
4159 if (usymtab_isAltDefinitelyNullDeep (el))
4167 message ("Storage %q is %q in one path, but live in another.",
4169 cstring_makeLiteral (sRef_isKept (el)
4170 ? "kept" : "released")),
4173 if (sRef_isKept (el))
4175 sRef_showAliasInfo (el);
4179 sRef_showStateInfo (el);
4182 /* prevent further errors */
4183 el->defstate = SS_UNKNOWN;
4184 sRef_setAliasKind (el, AK_ERROR, fileloc_undefined);
4194 checkDerivDeadState (/*@notnull@*/ sRef el, bool tbranch, fileloc loc)
4197 if (checkDeadState (el, tbranch, loc))
4199 sRefSet_allElements (el->deriv, t)
4201 if (sRef_isValid (t))
4203 checkDerivDeadState (t, tbranch, loc);
4205 } end_sRefSet_allElements;
4210 sRef_mergePdefinedDerivs (sRefSet res, sRefSet other, bool opt,
4211 clause cl, fileloc loc)
4213 sRefSet ret = sRefSet_new ();
4215 sRefSet_allElements (res, el)
4217 if (sRef_isValid (el))
4219 sRef e2 = sRefSet_lookupMember (other, el);
4221 if (sRef_isValid (e2))
4223 if (sRef_isAllocated (el) && !sRef_isAllocated (e2))
4227 else if (sRef_isAllocated (e2) && !sRef_isAllocated (el))
4229 el->deriv = sRefSet_copyInto (el->deriv, e2->deriv);
4233 el->deriv = sRef_mergePdefinedDerivs (el->deriv, e2->deriv,
4237 sRef_mergeStateAux (el, e2, cl, opt, loc, FALSE);
4239 ret = sRefSet_insert (ret, el);
4240 (void) sRefSet_delete (other, e2);
4246 checkDerivDeadState (el, (cl == FALSECLAUSE), loc);
4249 ret = sRefSet_insert (ret, el);
4252 } end_sRefSet_allElements;
4254 sRefSet_allElements (other, el)
4256 if (sRef_isValid (el))
4258 if (!sRefSet_member (ret, el))
4260 /* was cl == FALSECLAUSE */
4261 checkDerivDeadState (el, FALSE, loc);
4262 ret = sRefSet_insert (ret, el);
4267 ** it's okay --- member is a different equality test
4271 } end_sRefSet_allElements;
4277 sRef sRef_makeConj (/*@exposed@*/ /*@returned@*/ sRef a, /*@exposed@*/ sRef b)
4279 llassert (sRef_isValid (a));
4280 llassert (sRef_isValid (b));
4282 if (!sRef_equivalent (a, b))
4284 sRef s = sRef_newRef ();
4287 s->info = (sinfo) dmalloc (sizeof (*s->info));
4288 s->info->conj = (cjinfo) dmalloc (sizeof (*s->info->conj));
4289 s->info->conj->a = a; /* sRef_copy (a) */ /*@i32*/ ;
4290 s->info->conj->b = b; /* sRef_copy (b);*/ /*@i32@*/ ;
4292 if (ctype_equal (a->type, b->type)) s->type = a->type;
4293 else s->type = ctype_makeConj (a->type, b->type);
4295 if (a->defstate == b->defstate)
4297 s->defstate = a->defstate;
4301 s->defstate = SS_UNKNOWN;
4304 sRef_setNullStateN (s, NS_UNKNOWN);
4306 s->safe = a->safe && b->safe;
4307 s->aliaskind = alkind_resolve (a->aliaskind, b->aliaskind);
4309 llassert (valueTable_isUndefined (s->state));
4310 s->state = context_createValueTable (s, stateInfo_makeLoc (g_currentloc));
4315 /*@-exposetrans@*/ return a; /*@=exposetrans@*/
4319 /*@dependent@*/ sRef
4322 sRef s = sRef_new ();
4324 s->kind = SK_UNKNOWN;
4328 static /*@owned@*/ sRef
4329 sRef_makeSpecial (speckind sk) /*@*/
4331 sRef s = sRef_new ();
4333 s->kind = SK_SPECIAL;
4334 s->info = (sinfo) dmalloc (sizeof (*s->info));
4336 /*@-dependenttrans@*/
4338 /*@=dependenttrans@*/
4341 static /*@owned@*/ sRef srnothing = sRef_undefined;
4342 static /*@owned@*/ sRef srinternal = sRef_undefined;
4343 static /*@owned@*/ sRef srsystem = sRef_undefined;
4344 static /*@owned@*/ sRef srspec = sRef_undefined;
4346 /*@dependent@*/ sRef
4347 sRef_makeNothing (void)
4349 if (sRef_isInvalid (srnothing))
4351 srnothing = sRef_makeSpecial (SR_NOTHING);
4358 sRef_makeInternalState (void)
4360 if (sRef_isInvalid (srinternal))
4362 srinternal = sRef_makeSpecial (SR_INTERNAL);
4369 sRef_makeSpecState (void)
4371 if (sRef_isInvalid (srspec))
4373 srspec = sRef_makeSpecial (SR_SPECSTATE);
4380 sRef_makeSystemState (void)
4382 if (sRef_isInvalid (srsystem))
4384 srsystem = sRef_makeSpecial (SR_SYSTEM);
4391 sRef_makeGlobalMarker (void)
4393 sRef s = sRef_makeSpecial (SR_GLOBALMARKER);
4394 llassert (valueTable_isUndefined (s->state));
4395 s->state = context_createGlobalMarkerValueTable (stateInfo_undefined);
4400 sRef_makeResult (ctype c)
4402 sRef s = sRef_newRef ();
4404 s->kind = SK_RESULT;
4406 s->defstate = SS_UNKNOWN;
4407 s->aliaskind = AK_UNKNOWN;
4408 sRef_setNullStateN (s, NS_UNKNOWN);
4409 llassert (valueTable_isUndefined (s->state));
4410 s->state = context_createValueTable (s, stateInfo_makeLoc (g_currentloc));
4412 DPRINTF (("Result: [%p] %s", s, sRef_unparseFull (s)));
4418 sRef_isNothing (sRef s)
4420 return (sRef_isKindSpecial (s) && s->info->spec == SR_NOTHING);
4424 sRef_isInternalState (sRef s)
4426 return (sRef_isKindSpecial (s) && s->info->spec == SR_INTERNAL);
4430 sRef_isSpecInternalState (sRef s)
4432 return (sRef_isKindSpecial (s)
4433 && (s->info->spec == SR_INTERNAL || s->info->spec == SR_SPECSTATE));
4437 sRef_isSpecState (sRef s)
4439 return (sRef_isKindSpecial (s) && s->info->spec == SR_SPECSTATE);
4443 sRef_isResult (sRef s)
4445 return (sRef_isValid (s) && s->kind == SK_RESULT);
4449 sRef_isSystemState (sRef s)
4451 return (sRef_isKindSpecial (s) && s->info->spec == SR_SYSTEM);
4455 sRef_isGlobalMarker (sRef s)
4457 return (sRef_isKindSpecial (s) && s->info->spec == SR_GLOBALMARKER);
4461 sRef_getScopeIndex (sRef s)
4463 llassert (sRef_isValid (s));
4464 llassert (sRef_isCvar (s));
4466 return (s->info->cvar->index);
4470 sRef_makeSafe (sRef s)
4472 if (sRef_isValid (s))
4479 sRef_makeUnsafe (sRef s)
4481 if (sRef_isValid (s))
4488 ** memory state operations
4491 /*@only@*/ cstring sRef_unparseFull (sRef s)
4493 if (sRef_isInvalid (s)) return (cstring_undefined);
4495 return (message ("[%d] %q - %q [%s] { %q } < %q >",
4497 sRef_unparseDebug (s),
4498 sRef_unparseState (s),
4499 exkind_unparse (s->oexpkind),
4500 sRefSet_unparseDebug (s->deriv),
4501 valueTable_unparse (s->state)));
4504 /*@unused@*/ cstring sRef_unparseDeep (sRef s)
4506 cstring st = cstring_undefined;
4508 st = message ("%q:", sRef_unparseFull (s));
4510 if (sRef_isValid (s))
4512 sRefSet_allElements (s->deriv, el)
4514 st = message("%q\n%q", st, sRef_unparseDeep (el));
4515 } end_sRefSet_allElements ;
4521 /*@only@*/ cstring sRef_unparseState (sRef s)
4523 if (sRef_isConj (s))
4525 return (message ("%q | %q",
4526 sRef_unparseState (s->info->conj->a),
4527 sRef_unparseState (s->info->conj->b)));
4530 if (sRef_isInvalid (s))
4532 return (cstring_makeLiteral ("<invalid>"));
4535 return (message ("%s.%s.%s.%s",
4536 alkind_unparse (s->aliaskind),
4537 nstate_unparse (sRef_getNullState (s)),
4538 exkind_unparse (s->expkind),
4539 sstate_unparse (s->defstate)));
4542 bool sRef_isNotUndefined (sRef s)
4544 return (sRef_isInvalid (s)
4545 || (s->defstate != SS_UNDEFINED
4546 && s->defstate != SS_UNUSEABLE
4547 && s->defstate != SS_DEAD));
4550 ynm sRef_isWriteable (sRef s)
4552 if (sRef_isInvalid (s)) return MAYBE;
4554 if (sRef_isConj (s) && s->defstate == SS_UNKNOWN)
4556 if (ynm_toBoolStrict (sRef_isWriteable (sRef_getConjA (s))))
4558 if (ynm_toBoolStrict (sRef_isWriteable (sRef_getConjB (s))))
4566 if (ynm_toBoolStrict (sRef_isWriteable (sRef_getConjB (s))))
4574 return (ynm_fromBool (s->defstate != SS_UNUSEABLE));
4577 bool sRef_hasNoStorage (sRef s)
4579 return (!sRef_isAllocatedStorage (s) || sRef_isDefinitelyNull (s));
4582 bool sRef_isStrictReadable (sRef s)
4584 return (ynm_toBoolStrict (sRef_isReadable (s)));
4587 ynm sRef_isReadable (sRef s)
4591 if (sRef_isInvalid (s)) return YES;
4595 if (sRef_isConj (s) && s->defstate == SS_UNKNOWN)
4597 if (ynm_toBoolStrict (sRef_isReadable (sRef_getConjA (s))))
4599 if (ynm_toBoolStrict (sRef_isReadable (sRef_getConjB (s))))
4607 if (ynm_toBoolStrict (sRef_isReadable (sRef_getConjB (s))))
4614 else if (ss == SS_HOFFA)
4616 if (context_getFlag (FLG_STRICTUSERELEASED))
4627 return (ynm_fromBool (ss == SS_DEFINED
4630 || ss == SS_PDEFINED
4633 || ss == SS_ALLOCATED
4634 || ss == SS_KILLED /* evans 2001-05-26: added this for killed globals */
4635 || ss == SS_UNKNOWN));
4639 static /*@exposed@*/ sRef whatUndefined (/*@exposed@*/ sRef fref, int depth)
4644 if (depth > MAXDEPTH)
4647 ("Warning: check definition limit exceeded, checking %q. "
4648 "This either means there is a variable with at least "
4649 "%d indirections apparent in the program text, or "
4650 "there is a bug in Splint.",
4651 sRef_unparse (fref),
4655 return sRef_undefined;
4658 if (!sRef_isKnown (fref) || sRef_isAnyDefined (fref))
4660 return sRef_undefined;
4663 if (sRef_isUnuseable (fref) || sRef_isStateUndefined (fref))
4668 ct = ctype_realType (sRef_getType (fref));
4670 if (ctype_isUnknown (ct))
4672 return sRef_undefined;
4674 else if (ctype_isPointer (ct) || ctype_isArray (ct))
4676 if (sRef_isStateUnknown (fref))
4678 return sRef_undefined;
4682 sRef fptr = sRef_constructDeref (fref);
4684 return (whatUndefined (fptr, depth + 1));
4687 else if (ctype_isStruct (ct))
4689 bool hasOneDefined = FALSE;
4691 if (sRef_isStateUnknown (fref))
4696 if (sRef_isPdefined (fref) || sRef_isAnyDefined (fref))
4698 sRefSet_realElements (sRef_derivedFields (fref), sr)
4700 hasOneDefined = TRUE;
4702 if (sRef_isField (sr))
4704 cstring fieldname = sRef_getField (sr);
4705 sRef fldref = sRef_makeField (fref, fieldname);
4706 bool shouldCheck = !sRef_isRecursiveField (fldref);
4710 sRef wdef = whatUndefined (fldref, depth + 1);
4712 if (sRef_isValid (wdef))
4718 } end_sRefSet_realElements;
4720 else if (sRef_isAllocated (fref))
4723 ** for structures, each field must be completely defined
4726 uentryList fields = ctype_getFields (ct);
4728 uentryList_elements (fields, ue)
4730 cstring name = uentry_getRealName (ue);
4731 sRef ffield = sRef_makeField (fref, name);
4732 bool shouldCheck = !sRef_isRecursiveField (ffield);
4734 if (sRef_isRelDef (uentry_getSref (ue)))
4742 sRef wdef = whatUndefined (ffield, depth + 1);
4744 if (sRef_isInvalid (wdef))
4750 } end_uentryList_elements;
4757 else if (ctype_isUnion (ct))
4766 return sRef_undefined;
4769 static bool checkDefined (/*@temp@*/ sRef sr)
4771 /*@-temptrans@*/ /* the result from whatUndefined is lost */
4772 return (sRef_isInvalid (whatUndefined (sr, 0)));
4776 bool sRef_isReallyDefined (sRef s)
4778 if (sRef_isValid (s))
4780 if (sRef_isAnyDefined (s))
4786 if (sRef_isAllocated (s) || sRef_isPdefined (s))
4788 return checkDefined (s);
4802 void sRef_showNotReallyDefined (sRef s)
4804 if (sRef_isValid (s))
4806 if (sRef_isAnyDefined (s))
4812 if (sRef_isAllocated (s) || sRef_isPdefined (s))
4814 /*@-temptrans@*/ /* the result of whatUndefined is lost */
4815 sRef ref = whatUndefined (s, 0);
4817 llassert (sRef_isValid (ref));
4822 (message ("This sub-reference is %s: %q",
4823 sstate_unparse (sRef_getDefState (ref)),
4824 sRef_unparse (ref)));
4839 sstate sRef_getDefState (sRef s)
4841 if (sRef_isInvalid (s)) return (SS_UNKNOWN);
4842 return (s->defstate);
4845 void sRef_setDefState (sRef s, sstate defstate, fileloc loc)
4847 sRef_checkMutable (s);
4848 sRef_setStateAux (s, defstate, loc);
4851 static void sRef_clearAliasStateAux (sRef s, fileloc loc)
4853 sRef_checkMutable (s);
4854 sRef_setAliasKind (s, AK_ERROR, loc);
4857 void sRef_clearAliasState (sRef s, fileloc loc)
4859 sRef_checkMutable (s);
4860 sRef_aliasSetComplete (sRef_clearAliasStateAux, s, loc);
4863 void sRef_setAliasKindComplete (sRef s, alkind kind, fileloc loc)
4865 sRef_checkMutable (s);
4866 sRef_aliasSetCompleteAlkParam (sRef_setAliasKind, s, kind, loc);
4869 void sRef_setAliasKind (sRef s, alkind kind, fileloc loc)
4871 sRef_checkMutable (s);
4873 if (sRef_isValid (s))
4875 sRef_clearDerived (s);
4877 if ((kind != s->aliaskind && kind != s->oaliaskind)
4878 && fileloc_isDefined (loc))
4880 s->aliasinfo = stateInfo_updateLoc (s->aliasinfo, loc);
4883 s->aliaskind = kind;
4887 void sRef_setOrigAliasKind (sRef s, alkind kind)
4889 sRef_checkMutable (s);
4891 if (sRef_isValid (s))
4893 s->oaliaskind = kind;
4897 exkind sRef_getExKind (sRef s)
4899 if (sRef_isValid (s))
4901 return (s->expkind);
4909 exkind sRef_getOrigExKind (sRef s)
4911 if (sRef_isValid (s))
4913 return (s->oexpkind);
4921 static void sRef_clearExKindAux (sRef s, fileloc loc)
4923 sRef_checkMutable (s);
4924 sRef_setExKind (s, XO_UNKNOWN, loc);
4927 void sRef_setObserver (sRef s, fileloc loc)
4929 sRef_checkMutable (s);
4930 sRef_setExKind (s, XO_OBSERVER, loc);
4933 void sRef_setExposed (sRef s, fileloc loc)
4935 sRef_checkMutable (s);
4936 sRef_setExKind (s, XO_EXPOSED, loc);
4939 void sRef_clearExKindComplete (sRef s, fileloc loc)
4941 (void) sRef_aliasSetComplete (sRef_clearExKindAux, s, loc);
4944 void sRef_setExKind (sRef s, exkind exp, fileloc loc)
4946 sRef_checkMutable (s);
4948 if (sRef_isValid (s))
4950 if (s->expkind != exp)
4952 s->expinfo = stateInfo_updateLoc (s->expinfo, loc);
4960 ** s1->derived = s2->derived
4963 static void sRef_copyRealDerived (sRef s1, sRef s2)
4965 DPRINTF (("Copy real: %s / %s", sRef_unparse (s1), sRef_unparse (s2)));
4966 sRef_checkMutable (s1);
4968 if (sRef_isValid (s1) && sRef_isValid (s2))
4970 sRef sb = sRef_getRootBase (s1);
4972 sRefSet_clear (s1->deriv);
4974 sRefSet_allElements (s2->deriv, el)
4976 if (sRef_isValid (el))
4978 sRef rb = sRef_getRootBase (el);
4980 if (!sRef_same (rb, sb))
4982 sRef fb = sRef_fixDirectBase (el, s1);
4984 if (sRef_isValid (fb))
4986 sRef_copyRealDerived (fb, el);
4987 sRef_addDeriv (s1, fb);
4992 sRef_addDeriv (s1, el);
4995 } end_sRefSet_allElements ;
5000 void sRef_copyRealDerivedComplete (sRef s1, sRef s2)
5002 sRef_innerAliasSetCompleteParam (sRef_copyRealDerived, s1, s2);
5005 void sRef_setUndefined (sRef s, fileloc loc)
5007 sRef_checkMutable (s);
5009 if (sRef_isValid (s))
5011 s->defstate = SS_UNDEFINED;
5013 if (fileloc_isDefined (loc))
5015 s->definfo = stateInfo_updateLoc (s->definfo, loc);
5018 sRef_clearDerived (s);
5022 static void sRef_setDefinedAux (sRef s, fileloc loc, bool clear)
5024 sRef_checkMutable (s);
5025 if (sRef_isInvalid (s)) return;
5027 DPRINTF (("Set defined: %s", sRef_unparseFull (s)));
5029 if (s->defstate != SS_DEFINED && fileloc_isDefined (loc))
5031 s->definfo = stateInfo_updateLoc (s->definfo, loc);
5034 s->defstate = SS_DEFINED;
5036 DPRINTF (("Set defined: %s", sRef_unparseFull (s)));
5038 /* e.g., if x is allocated, *x = 3 defines x */
5040 if (s->kind == SK_PTR)
5042 sRef p = s->info->ref;
5045 if (p->defstate == SS_ALLOCATED
5046 || p->defstate == SS_SPECIAL) /* evans 2001-07-12: shouldn't need this */
5048 sRef_setDefinedAux (p, loc, clear);
5052 ** Defines a[0] also:
5055 arr = sRef_findDerivedArrayFetch (p, FALSE, 0, FALSE);
5057 if (sRef_isValid (arr))
5059 sRef_setDefinedAux (arr, loc, clear);
5062 else if (s->kind == SK_ARRAYFETCH)
5064 if (!s->info->arrayfetch->indknown
5065 || (s->info->arrayfetch->ind == 0))
5067 sRef p = s->info->arrayfetch->arr;
5068 sRef ptr = sRef_constructPointer (p);
5070 if (sRef_isValid (ptr))
5072 if (ptr->defstate == SS_ALLOCATED
5073 || ptr->defstate == SS_UNDEFINED
5074 || ptr->defstate == SS_SPECIAL) /* evans 2001-07-12: shouldn't need this */
5076 sRef_setDefinedAux (ptr, loc, clear);
5080 if (p->defstate == SS_RELDEF)
5084 else if (p->defstate == SS_ALLOCATED || p->defstate == SS_PDEFINED
5085 || p->defstate == SS_SPECIAL) /* evans 2001-07-12: shouldn't need this */
5087 p->defstate = SS_DEFINED;
5094 else if (s->kind == SK_FIELD)
5096 sRef parent = s->info->field->rec;
5098 if (sRef_isValid (parent))
5100 if (ctype_isUnion (ctype_realType (parent->type)))
5103 ** Should not clear derived from here.
5106 sRef_setDefinedNoClear (parent, loc);
5110 ; /* Nothing to do for structures. */
5122 sRef_clearDerived (s);
5126 /* evans 2001-07-12: need to define the derived references */
5127 sRefSet_elements (s->deriv, el)
5129 el->defstate = SS_DEFINED;
5130 } end_sRefSet_elements ;
5133 DPRINTF (("Set defined: %s", sRef_unparseFull (s)));
5136 static void sRef_setPartialDefined (sRef s, fileloc loc)
5138 sRef_checkMutable (s);
5140 if (!sRef_isPartial (s))
5142 sRef_setDefined (s, loc);
5146 void sRef_setPartialDefinedComplete (sRef s, fileloc loc)
5148 sRef_innerAliasSetComplete (sRef_setPartialDefined, s, loc);
5151 void sRef_setDefinedComplete (sRef s, fileloc loc)
5153 DPRINTF (("Set defined complete: %s", sRef_unparseFull (s)));
5154 sRef_innerAliasSetComplete (sRef_setDefined, s, loc);
5157 void sRef_setDefined (sRef s, fileloc loc)
5159 sRef_checkMutable (s);
5160 sRef_setDefinedAux (s, loc, TRUE);
5163 static void sRef_setDefinedNoClear (sRef s, fileloc loc)
5165 sRef_checkMutable (s);
5166 DPRINTF (("Defining: %s", sRef_unparseFull (s)));
5167 sRef_setDefinedAux (s, loc, FALSE);
5168 DPRINTF (("==> %s", sRef_unparseFull (s)));
5171 void sRef_setDefinedNCComplete (sRef s, fileloc loc)
5173 sRef_checkMutable (s);
5174 DPRINTF (("Set Defined Complete: %s", sRef_unparseFull (s)));
5175 sRef_innerAliasSetComplete (sRef_setDefinedNoClear, s, loc);
5176 DPRINTF (("==> %s", sRef_unparseFull (s)));
5179 static bool sRef_isDeepUnionField (sRef s)
5181 return (sRef_deepPred (sRef_isUnionField, s));
5184 bool sRef_isUnionField (sRef s)
5186 if (sRef_isValid (s) && s->kind == SK_FIELD)
5189 ** defining one field of a union defines the union
5192 sRef base = s->info->field->rec;
5194 if (sRef_isValid (base))
5196 return (ctype_isUnion (ctype_realType (base->type)));
5203 void sRef_setPdefined (sRef s, fileloc loc)
5205 sRef_checkMutable (s);
5206 if (sRef_isValid (s) && !sRef_isPartial (s))
5208 sRef base = sRef_getBaseSafe (s);
5210 if (s->defstate == SS_ALLOCATED)
5215 if (s->defstate != SS_PDEFINED && fileloc_isDefined (loc))
5217 s->definfo = stateInfo_updateLoc (s->definfo, loc);
5220 DPRINTF (("set pdefined: %s", sRef_unparseFull (s)));
5221 s->defstate = SS_PDEFINED;
5223 /* e.g., if x is allocated, *x = 3 defines x */
5225 while (sRef_isValid (base) && sRef_isKnown (base))
5227 if (base->defstate == SS_DEFINED)
5231 base->defstate = SS_PDEFINED;
5232 nb = sRef_getBaseSafe (base);
5243 static void sRef_setStateAux (sRef s, sstate ss, fileloc loc)
5245 sRef_checkMutable (s);
5247 if (sRef_isValid (s))
5249 /* if (s->defstate == SS_RELDEF) return; */
5251 if (s->defstate != ss && fileloc_isDefined (loc))
5253 s->definfo = stateInfo_updateLoc (s->definfo, loc);
5257 sRef_clearDerived (s);
5259 if (ss == SS_ALLOCATED)
5261 sRef base = sRef_getBaseSafe (s);
5263 while (sRef_isValid (base) && sRef_isKnown (base))
5265 if (base->defstate == SS_DEFINED)
5269 base->defstate = SS_PDEFINED;
5271 nb = sRef_getBaseSafe (base);
5284 void sRef_setAllocatedComplete (sRef s, fileloc loc)
5286 sRef_innerAliasSetComplete (sRef_setAllocated, s, loc);
5289 static void sRef_setAllocatedShallow (sRef s, fileloc loc)
5291 sRef_checkMutable (s);
5293 if (sRef_isValid (s))
5295 if (s->defstate == SS_DEAD || s->defstate == SS_UNDEFINED)
5297 s->defstate = SS_ALLOCATED;
5299 if (fileloc_isDefined (loc))
5301 s->definfo = stateInfo_updateLoc (s->definfo, loc);
5307 void sRef_setAllocatedShallowComplete (sRef s, fileloc loc)
5309 sRef_innerAliasSetComplete (sRef_setAllocatedShallow, s, loc);
5312 void sRef_setAllocated (sRef s, fileloc loc)
5314 sRef_checkMutable (s);
5315 sRef_setStateAux (s, SS_ALLOCATED, loc);
5318 void sRef_setPartial (sRef s, fileloc loc)
5320 sRef_checkMutable (s);
5321 sRef_setStateAux (s, SS_PARTIAL, loc);
5324 void sRef_setShared (sRef s, fileloc loc)
5326 sRef_checkMutable (s);
5328 if (sRef_isValid (s))
5330 if (s->aliaskind != AK_SHARED && fileloc_isDefined (loc))
5332 s->aliasinfo = stateInfo_updateLoc (s->aliasinfo, loc);
5335 s->aliaskind = AK_SHARED;
5336 /* don't! sRef_clearDerived (s); */
5340 void sRef_setLastReference (sRef s, /*@exposed@*/ sRef ref, fileloc loc)
5342 sRef_checkMutable (s);
5344 if (sRef_isValid (s))
5346 s->aliaskind = sRef_getAliasKind (ref);
5347 s->aliasinfo = stateInfo_updateRefLoc (s->aliasinfo, ref, loc);
5352 void sRef_setNullStateAux (/*@notnull@*/ sRef s, nstate ns, fileloc loc)
5354 DPRINTF (("Set null state: %s / %s", sRef_unparse (s), nstate_unparse (ns)));
5355 sRef_checkMutable (s);
5358 if (fileloc_isDefined (loc))
5360 s->nullinfo = stateInfo_updateLoc (s->nullinfo, loc);
5364 void sRef_setNotNull (sRef s, fileloc loc)
5366 if (sRef_isValid (s))
5368 sRef_setNullStateAux (s, NS_NOTNULL, loc);
5372 void sRef_setNullStateN (sRef s, nstate n)
5374 sRef_checkMutable (s);
5378 void sRef_setNullState (sRef s, nstate n, fileloc loc)
5380 if (sRef_isValid (s))
5382 sRef_setNullStateAux (s, n, loc);
5386 void sRef_setNullTerminatedStateInnerComplete (sRef s, struct s_bbufinfo b, /*@unused@*/ fileloc loc) {
5388 switch (b.bufstate) {
5389 case BB_NULLTERMINATED:
5390 sRef_setNullTerminatedState (s);
5391 sRef_setLen (s, b.len);
5393 case BB_POSSIBLYNULLTERMINATED:
5394 sRef_setPossiblyNullTerminatedState(s);
5396 case BB_NOTNULLTERMINATED:
5397 sRef_setNotNullTerminatedState (s);
5400 sRef_setSize (s, b.size);
5402 /* PL: TO BE DONE : Aliases are not modified right now, have to be similar to
5403 * setNullStateInnerComplete.
5407 void sRef_setNullStateInnerComplete (sRef s, nstate n, fileloc loc)
5409 DPRINTF (("Set null state: %s", nstate_unparse (n)));
5411 sRef_setNullState (s, n, loc);
5416 sRef_innerAliasSetComplete (sRef_setPosNull, s, loc);
5419 sRef_innerAliasSetComplete (sRef_setDefNull, s, loc);
5422 sRef_innerAliasSetComplete (sRef_setNullUnknown, s, loc);
5425 sRef_innerAliasSetComplete (sRef_setNotNull, s, loc);
5428 sRef_innerAliasSetComplete (sRef_setNotNull, s, loc);
5431 sRef_innerAliasSetComplete (sRef_setNullUnknown, s, loc);
5434 sRef_innerAliasSetComplete (sRef_setDefNull, s, loc);
5437 sRef_innerAliasSetComplete (sRef_setNullUnknown, s, loc);
5440 sRef_innerAliasSetComplete (sRef_setNullErrorLoc, s, loc);
5445 void sRef_setPosNull (sRef s, fileloc loc)
5447 if (sRef_isValid (s))
5449 sRef_setNullStateAux (s, NS_POSNULL, loc);
5453 void sRef_setDefNull (sRef s, fileloc loc)
5455 if (sRef_isValid (s))
5457 sRef_setNullStateAux (s, NS_DEFNULL, loc);
5461 void sRef_setNullUnknown (sRef s, fileloc loc)
5463 if (sRef_isValid (s))
5465 sRef_setNullStateAux (s, NS_UNKNOWN, loc);
5469 void sRef_setNullError (sRef s)
5471 if (sRef_isValid (s))
5473 sRef_setNullStateAux (s, NS_UNKNOWN, fileloc_undefined);
5477 void sRef_setNullErrorLoc (sRef s, /*@unused@*/ fileloc loc)
5479 sRef_setNullError (s);
5482 void sRef_setOnly (sRef s, fileloc loc)
5484 sRef_checkMutable (s);
5486 if (sRef_isValid (s) && s->aliaskind != AK_ONLY)
5488 s->aliaskind = AK_ONLY;
5489 s->aliasinfo = stateInfo_updateLoc (s->aliasinfo, loc);
5493 void sRef_setDependent (sRef s, fileloc loc)
5495 sRef_checkMutable (s);
5497 if (sRef_isValid (s) && !sRef_isConst (s) && (s->aliaskind != AK_DEPENDENT))
5499 DPRINTF (("Setting dependent: %s", sRef_unparseFull (s)));
5500 s->aliaskind = AK_DEPENDENT;
5501 s->aliasinfo = stateInfo_updateLoc (s->aliasinfo, loc);
5505 void sRef_setOwned (sRef s, fileloc loc)
5507 sRef_checkMutable (s);
5509 if (sRef_isValid (s) && !sRef_isConst (s) && (s->aliaskind != AK_OWNED))
5511 s->aliaskind = AK_OWNED;
5512 s->aliasinfo = stateInfo_updateLoc (s->aliasinfo, loc);
5516 void sRef_setKept (sRef s, fileloc loc)
5518 sRef_checkMutable (s);
5520 if (sRef_isValid (s) && !sRef_isConst (s) && (s->aliaskind != AK_KEPT))
5522 sRef base = sRef_getBaseSafe (s);
5524 while (sRef_isValid (base) && sRef_isKnown (base))
5526 if (base->defstate == SS_DEFINED)
5528 base->defstate = SS_PDEFINED;
5529 base = sRef_getBaseSafe (base);
5538 s->aliaskind = AK_KEPT;
5539 s->aliasinfo = stateInfo_updateLoc (s->aliasinfo, loc);
5543 static void sRef_setKeptAux (sRef s, fileloc loc)
5545 if (!sRef_isShared (s))
5547 sRef_setKept (s, loc);
5551 static void sRef_setDependentAux (sRef s, fileloc loc)
5553 if (!sRef_isShared (s))
5555 sRef_setDependent (s, loc);
5559 void sRef_setKeptComplete (sRef s, fileloc loc)
5561 sRef_aliasSetComplete (sRef_setKeptAux, s, loc);
5564 void sRef_setDependentComplete (sRef s, fileloc loc)
5566 sRef_aliasSetComplete (sRef_setDependentAux, s, loc);
5569 void sRef_setFresh (sRef s, fileloc loc)
5571 sRef_checkMutable (s);
5573 if (sRef_isValid (s))
5575 s->aliaskind = AK_FRESH;
5576 s->aliasinfo = stateInfo_updateLoc (s->aliasinfo, loc);
5580 void sRef_kill (sRef s, fileloc loc)
5582 DPRINTF (("Kill: %s", sRef_unparseFull (s)));
5583 sRef_checkMutable (s);
5585 if (sRef_isValid (s) && !sRef_isShared (s) && !sRef_isConst (s))
5587 sRef base = sRef_getBaseSafe (s);
5589 while (sRef_isValid (base) && sRef_isKnown (base))
5591 if (base->defstate == SS_DEFINED)
5593 base->defstate = SS_PDEFINED;
5594 base = sRef_getBaseSafe (base);
5602 s->aliaskind = s->oaliaskind;
5603 s->defstate = SS_DEAD;
5604 s->definfo = stateInfo_updateLoc (s->definfo, loc);
5606 sRef_clearDerived (s);
5610 void sRef_maybeKill (sRef s, fileloc loc)
5612 sRef_checkMutable (s);
5614 if (sRef_isValid (s))
5616 sRef base = sRef_getBaseSafe (s);
5619 while (sRef_isValid (base) && sRef_isKnown (base))
5621 if (base->defstate == SS_DEFINED || base->defstate == SS_RELDEF)
5623 base->defstate = SS_PDEFINED;
5624 base = sRef_getBaseSafe (base);
5633 s->aliaskind = s->oaliaskind;
5634 s->defstate = SS_HOFFA;
5635 s->definfo = stateInfo_updateLoc (s->definfo, loc);
5636 sRef_clearDerived (s);
5642 ** just for type checking...
5645 static void sRef_killAux (sRef s, fileloc loc)
5647 if (sRef_isValid (s) && !sRef_isShared (s))
5649 if (sRef_isUnknownArrayFetch (s))
5651 sRef_maybeKill (s, loc);
5661 ** kills s and all aliases to s
5664 void sRef_killComplete (sRef s, fileloc loc)
5666 DPRINTF (("Kill complete: %s", sRef_unparseFull (s)));
5667 sRef_aliasSetComplete (sRef_killAux, s, loc);
5670 static bool sRef_equivalent (sRef s1, sRef s2)
5672 return (sRef_compare (s1, s2) == 0);
5676 ** returns an sRef that will not be free'd on function exit.
5679 /*@only@*/ sRef sRef_saveCopy (sRef s)
5683 if (sRef_isValid (s))
5685 bool old = inFunction;
5688 ** Exit the function scope, so this sRef is not
5689 ** stored in the deallocation table.
5693 DPRINTF (("Copying sref: %s", sRef_unparseFull(s)));
5694 ret = sRef_copy (s);
5695 DPRINTF (("Copying ===>: %s", sRef_unparseFull(ret)));
5700 ret = sRef_undefined;
5703 /*@-dependenttrans@*/
5705 /*@=dependenttrans@*/
5708 sRef sRef_copy (sRef s)
5710 if (sRef_isKindSpecial (s) && !sRef_isGlobalMarker (s))
5713 return s; /* don't copy specials (except for global markers) */
5717 if (sRef_isValid (s))
5719 sRef t = sRef_alloc ();
5721 DPRINTF (("Copying: [%p] %s", s, sRef_unparse (s)));
5722 DPRINTF (("Full: %s", sRef_unparseFull (s)));
5726 t->modified = s->modified;
5727 t->immut = FALSE; /* Note mutability is not copied. */
5729 t->val = multiVal_copy (s->val);
5731 t->info = sinfo_copy (s);
5732 t->defstate = s->defstate;
5733 t->nullstate = s->nullstate;
5735 /* start modifications */
5736 t->bufinfo.bufstate = s->bufinfo.bufstate;
5737 t->bufinfo.len = s->bufinfo.len;
5738 t->bufinfo.size = s->bufinfo.size;
5739 /* end modifications */
5741 t->aliaskind = s->aliaskind;
5742 t->oaliaskind = s->oaliaskind;
5744 t->expkind = s->expkind;
5745 t->oexpkind = s->oexpkind;
5747 t->nullinfo = stateInfo_copy (s->nullinfo);
5748 t->aliasinfo = stateInfo_copy (s->aliasinfo);
5749 t->definfo = stateInfo_copy (s->definfo);
5750 t->expinfo = stateInfo_copy (s->expinfo);
5752 t->deriv = sRefSet_newDeepCopy (s->deriv);
5753 t->state = valueTable_copy (s->state);
5755 DPRINTF (("Made copy: [%p] %s", t, sRef_unparse (t)));
5760 return sRef_undefined;
5765 # define PREDTEST(func,s) \
5766 do { if (sRef_isInvalid (s)) { return FALSE; } \
5767 else { if (sRef_isConj (s)) \
5768 { return (func (sRef_getConjA (s)) \
5769 || func (sRef_getConjB (s))); }}} while (FALSE);
5771 bool sRef_isAddress (sRef s)
5773 PREDTEST (sRef_isAddress, s);
5774 return (s->kind == SK_ADR);
5778 ** pretty weak... maybe a flag should control this.
5781 bool sRef_isThroughArrayFetch (sRef s)
5783 if (sRef_isValid (s))
5791 if (sRef_isArrayFetch (tref))
5796 lt = sRef_getBase (tref);
5798 } while (sRef_isValid (tref));
5804 bool sRef_isArrayFetch (sRef s)
5806 PREDTEST (sRef_isArrayFetch, s);
5807 return (s->kind == SK_ARRAYFETCH);
5810 bool sRef_isMacroParamRef (sRef s)
5812 if (context_inMacro () && sRef_isCvar (s))
5814 uentry ue = sRef_getUentry (s);
5815 cstring pname = makeParam (uentry_rawName (ue));
5816 uentry mac = usymtab_lookupSafe (pname);
5818 cstring_free (pname);
5819 return (uentry_isValid (mac));
5825 bool sRef_isCvar (sRef s)
5827 PREDTEST (sRef_isCvar, s);
5828 return (s->kind == SK_CVAR);
5831 bool sRef_isConst (sRef s)
5833 PREDTEST (sRef_isConst, s);
5834 return (s->kind == SK_CONST);
5837 bool sRef_isObject (sRef s)
5839 PREDTEST (sRef_isObject, s);
5840 return (s->kind == SK_OBJECT);
5843 bool sRef_isExternal (sRef s)
5845 PREDTEST (sRef_isExternal, s);
5846 return (s->kind == SK_EXTERNAL);
5849 static bool sRef_isDerived (sRef s)
5851 PREDTEST (sRef_isDerived, s);
5852 return (s->kind == SK_DERIVED);
5855 bool sRef_isField (sRef s)
5857 PREDTEST (sRef_isField, s);
5858 return (s->kind == SK_FIELD);
5861 static bool sRef_isIndex (sRef s)
5863 PREDTEST (sRef_isIndex, s);
5864 return (s->kind == SK_ARRAYFETCH);
5867 bool sRef_isAnyParam (sRef s)
5869 PREDTEST (sRef_isAnyParam, s);
5870 return (s->kind == SK_PARAM);
5873 bool sRef_isParam (sRef s)
5875 PREDTEST (sRef_isParam, s);
5876 return (s->kind == SK_PARAM);
5879 bool sRef_isDirectParam (sRef s)
5881 PREDTEST (sRef_isDirectParam, s);
5883 return ((s->kind == SK_CVAR) &&
5884 (s->info->cvar->lexlevel == functionScope) &&
5885 (context_inFunction () &&
5886 (s->info->cvar->index <= uentryList_size (context_getParams ()))));
5889 bool sRef_isPointer (sRef s)
5891 PREDTEST (sRef_isPointer, s);
5892 return (s->kind == SK_PTR);
5896 ** returns true if storage referenced by s is visible
5899 bool sRef_isReference (sRef s)
5901 PREDTEST (sRef_isReference, s);
5903 return (sRef_isPointer (s) || sRef_isIndex (s) || sRef_isFileOrGlobalScope (s)
5904 || (sRef_isField (s) && (sRef_isReference (s->info->field->rec))));
5907 bool sRef_isIReference (sRef s)
5909 return (sRef_isPointer (s) || sRef_isAddress (s) || sRef_isIndex (s)
5910 || sRef_isField (s) || sRef_isArrayFetch (s));
5913 bool sRef_isFileOrGlobalScope (sRef s)
5915 return (sRef_isCvar (s) && (s->info->cvar->lexlevel <= fileScope));
5918 bool sRef_isRealGlobal (sRef s)
5920 return (sRef_isCvar (s) && (s->info->cvar->lexlevel == globScope));
5923 bool sRef_isFileStatic (sRef s)
5925 return (sRef_isCvar (s) && (s->info->cvar->lexlevel == fileScope));
5928 bool sRef_isAliasCheckedGlobal (sRef s)
5930 if (sRef_isFileOrGlobalScope (s))
5932 uentry ue = sRef_getUentry (s);
5934 return context_checkAliasGlob (ue);
5942 void sRef_free (/*@only@*/ sRef s)
5944 if (s != sRef_undefined && s->kind != SK_SPECIAL)
5946 DPRINTF (("Free sref: [%p]", s));
5948 sRef_checkValid (s);
5950 stateInfo_free (s->expinfo);
5951 stateInfo_free (s->aliasinfo);
5952 stateInfo_free (s->definfo);
5953 stateInfo_free (s->nullinfo);
5955 sRefSet_free (s->deriv);
5956 s->deriv = sRefSet_undefined;
5958 /*@i43@*/ /* valueTable_free (s->state); */
5962 /* drl added to help locate use after release*/
5963 s->expinfo = stateInfo_undefined;
5964 s->aliasinfo = stateInfo_undefined;
5965 s->definfo = stateInfo_undefined;
5966 s->nullinfo = stateInfo_undefined;
5968 /*@i32@*/ sfree (s);
5972 void sRef_setType (sRef s, ctype t)
5974 sRef_checkMutable (s);
5976 if (sRef_isValid (s))
5982 void sRef_setTypeFull (sRef s, ctype t)
5984 sRef_checkMutable (s);
5986 if (sRef_isValid (s))
5990 sRefSet_allElements (s->deriv, current)
5992 sRef_setTypeFull (current, ctype_unknown);
5993 } end_sRefSet_allElements ;
5998 sRef_buildField (/*@exposed@*/ sRef rec, /*@dependent@*/ cstring f)
6000 return (sRef_buildNCField (rec, f));
6003 static /*@exposed@*/ sRef
6004 sRef_findDerivedField (/*@notnull@*/ sRef rec, cstring f)
6006 sRefSet_allElements (rec->deriv, sr)
6008 if (sRef_isValid (sr))
6010 if (sr->info != NULL)
6012 if (sr->kind == SK_FIELD && cstring_equal (sr->info->field->field, f))
6018 } end_sRefSet_allElements;
6020 return sRef_undefined;
6023 /*@dependent@*/ /*@observer@*/ sRefSet sRef_derivedFields (/*@temp@*/ sRef rec)
6025 if (sRef_isValid (rec))
6033 return (sRefSet_undefined);
6037 static /*@exposed@*/ sRef
6038 sRef_findDerivedPointer (sRef s)
6040 if (sRef_isValid (s))
6042 sRefSet_realElements (s->deriv, sr)
6044 if (sRef_isValid (sr) && sr->kind == SK_PTR)
6048 } end_sRefSet_realElements;
6051 return sRef_undefined;
6055 sRef_isUnknownArrayFetch (sRef s)
6057 return (sRef_isValid (s)
6058 && s->kind == SK_ARRAYFETCH
6059 && !s->info->arrayfetch->indknown);
6062 static /*@exposed@*/ sRef
6063 sRef_findDerivedArrayFetch (/*@notnull@*/ sRef s, bool isknown, int idx, bool dead)
6068 sRefSet_realElements (s->deriv, sr)
6070 if (sRef_isValid (sr)
6071 && sr->kind == SK_ARRAYFETCH
6072 && sr->info->arrayfetch->indknown
6073 && (sr->info->arrayfetch->ind == idx))
6077 } end_sRefSet_realElements;
6081 sRefSet_realElements (s->deriv, sr)
6083 if (sRef_isValid (sr)
6084 && sr->kind == SK_ARRAYFETCH
6085 && (!sr->info->arrayfetch->indknown
6086 || (sr->info->arrayfetch->indknown &&
6087 sr->info->arrayfetch->ind == 0)))
6089 if (sRef_isDead (sr) || sRef_isKept (sr))
6091 if (dead || context_getFlag (FLG_STRICTUSERELEASED))
6101 } end_sRefSet_realElements;
6104 return sRef_undefined;
6107 static /*@exposed@*/ sRef
6108 sRef_buildNCField (/*@exposed@*/ sRef rec, /*@exposed@*/ cstring f)
6112 DPRINTF (("Build nc field: %s / %s",
6113 sRef_unparseFull (rec), f));
6115 if (sRef_isInvalid (rec))
6117 return sRef_undefined;
6121 ** check if the field already has been referenced
6124 s = sRef_findDerivedField (rec, f);
6126 if (sRef_isValid (s))
6132 ctype ct = ctype_realType (rec->type);
6134 DPRINTF (("Field of: %s", sRef_unparse (rec)));
6138 s->info = (sinfo) dmalloc (sizeof (*s->info));
6139 s->info->field = (fldinfo) dmalloc (sizeof (*s->info->field));
6140 s->info->field->rec = rec; /* sRef_copy (rec); */ /*@i32@*/
6141 s->info->field->field = f; /* doesn't copy f */
6143 if (ctype_isKnown (ct) && ctype_isSU (ct))
6145 uentry ue = uentryList_lookupField (ctype_getFields (ct), f);
6147 if (!uentry_isUndefined (ue))
6149 DPRINTF (("lookup: %s for %s", uentry_unparseFull (ue),
6150 ctype_unparse (ct)));
6152 s->type = uentry_getType (ue);
6154 if (ctype_isMutable (s->type)
6155 && rec->aliaskind != AK_STACK
6156 && !alkind_isStatic (rec->aliaskind))
6158 s->aliaskind = rec->aliaskind;
6162 s->aliaskind = AK_UNKNOWN;
6165 if (sRef_isStateDefined (rec) || sRef_isStateUnknown (rec)
6166 || sRef_isPdefined (rec))
6168 sRef_setStateFromUentry (s, ue);
6172 sRef_setPartsFromUentry (s, ue);
6175 s->oaliaskind = s->aliaskind;
6176 s->oexpkind = s->expkind;
6178 DPRINTF (("sref: %s", sRef_unparseFull (s)));
6183 Never report this as an error. It can happen whenever there
6184 is casting involved.
6188 llcontbug (message ("buildNCField --- no field %s: %q / %s",
6189 f, sRef_unparse (s), ctype_unparse (ct)));
6193 return sRef_undefined;
6197 if (rec->defstate == SS_DEFINED
6198 && (s->defstate == SS_UNDEFINED || s->defstate == SS_UNKNOWN))
6200 s->defstate = SS_DEFINED;
6202 else if (rec->defstate == SS_PARTIAL)
6204 s->defstate = SS_PARTIAL;
6206 else if (rec->defstate == SS_ALLOCATED)
6208 if (ctype_isStackAllocated (ct) && ctype_isStackAllocated (s->type))
6210 s->defstate = SS_ALLOCATED;
6214 s->defstate = SS_UNDEFINED;
6217 else if (s->defstate == SS_UNKNOWN)
6219 s->defstate = rec->defstate;
6226 if (s->defstate == SS_UNDEFINED)
6228 ctype rt = ctype_realType (s->type);
6230 if (ctype_isArray (rt) || ctype_isSU (rt))
6232 s->defstate = SS_ALLOCATED;
6236 sRef_addDeriv (rec, s);
6237 DPRINTF (("Add deriv: %s", sRef_unparseFull (rec)));
6239 if (ctype_isInt (s->type) && cstring_equal (f, REFSNAME))
6241 s->aliaskind = AK_REFS;
6242 s->oaliaskind = AK_REFS;
6245 DPRINTF (("Build field ==> %s", sRef_unparseFull (s)));
6251 sRef_isStackAllocated (sRef s)
6253 return (sRef_isValid(s)
6254 && s->defstate == SS_ALLOCATED && ctype_isStackAllocated (s->type));
6258 void sRef_setArrayFetchState (/*@notnull@*/ /*@exposed@*/ sRef s,
6259 /*@notnull@*/ /*@exposed@*/ sRef arr)
6261 sRef_checkMutable (s);
6263 if (ctype_isRealAP (arr->type))
6265 s->type = ctype_baseArrayPtr (arr->type);
6268 /* a hack, methinks... makeArrayFetch (&a[0]) ==> a[] */
6269 /* evans - 2001-08-27: not sure where this was necessary - it
6270 ** causes an assertion in in aliasCheckPred to fail.
6273 if (sRef_isAddress (arr))
6275 sRef t = arr->info->ref;
6277 if (sRef_isArrayFetch (t))
6279 s->info->arrayfetch->arr = t->info->arrayfetch->arr;
6282 else if (ctype_isRealPointer (arr->type))
6284 sRef sp = sRef_findDerivedPointer (arr);
6286 if (sRef_isValid (sp))
6289 if (ctype_isMutable (s->type))
6291 sRef_setExKind (s, sRef_getExKind (sp), fileloc_undefined);
6293 s->aliaskind = sp->aliaskind;
6296 s->defstate = sp->defstate;
6298 if (s->defstate == SS_DEFINED)
6300 if (!context_getFlag (FLG_STRICTDESTROY))
6302 s->defstate = SS_PARTIAL;
6306 sRef_setNullStateN (s, sRef_getNullState (sp));
6310 if (arr->defstate == SS_UNDEFINED)
6312 s->defstate = SS_UNUSEABLE;
6314 else if ((arr->defstate == SS_ALLOCATED) && !ctype_isSU (s->type))
6316 s->defstate = SS_UNDEFINED;
6320 if (!context_getFlag (FLG_STRICTDESTROY))
6322 s->defstate = SS_PARTIAL;
6326 s->defstate = SS_DEFINED;
6330 ** Very weak checking for array elements.
6332 ** s->defstate = arr->defstate;
6336 sRef_setExKind (s, sRef_getExKind (arr), g_currentloc);
6338 if (arr->aliaskind == AK_LOCAL || arr->aliaskind == AK_FRESH)
6340 s->aliaskind = AK_LOCAL;
6344 s->aliaskind = AK_UNKNOWN;
6347 sRef_setTypeState (s);
6352 if (arr->defstate == SS_DEFINED)
6355 ** Very weak checking for array elements.
6357 ** s->defstate = arr->defstate;
6360 if (context_getFlag (FLG_STRICTDESTROY))
6362 s->defstate = SS_DEFINED;
6366 s->defstate = SS_PARTIAL;
6369 else if (arr->defstate == SS_ALLOCATED)
6371 if (ctype_isRealArray (s->type))
6373 s->defstate = SS_ALLOCATED;
6377 if (!s->info->arrayfetch->indknown)
6380 ** is index is unknown, elements is defined or
6381 ** allocated is any element is!
6384 s->defstate = SS_UNDEFINED;
6386 sRefSet_allElements (arr->deriv, sr)
6388 if (sRef_isValid (sr))
6390 if (sr->defstate == SS_ALLOCATED)
6392 s->defstate = SS_ALLOCATED;
6396 if (sr->defstate == SS_DEFINED)
6398 if (context_getFlag (FLG_STRICTDESTROY))
6400 s->defstate = SS_DEFINED;
6404 s->defstate = SS_PARTIAL;
6411 } end_sRefSet_allElements;
6416 s->defstate = SS_UNDEFINED;
6422 s->defstate = arr->defstate;
6427 ** kludgey way to guess where aliaskind applies
6430 if (ctype_isMutable (s->type)
6431 && !ctype_isPointer (arr->type)
6432 && !alkind_isStatic (arr->aliaskind)
6433 && !alkind_isStack (arr->aliaskind)) /* evs - 2000-06-20: don't pass stack allocation to members */
6435 s->aliaskind = arr->aliaskind;
6439 s->aliaskind = AK_UNKNOWN;
6442 sRef_setTypeState (s);
6445 if (sRef_isObserver (arr))
6447 s->expkind = XO_OBSERVER;
6451 /*@exposed@*/ sRef sRef_buildArrayFetch (/*@exposed@*/ sRef arr)
6455 if (!sRef_isValid (arr)) {
6456 /*@-nullret@*/ return arr /*@=nullret@*/;
6459 if (ctype_isRealPointer (arr->type))
6461 (void) sRef_buildPointer (arr); /* do this to define arr! */
6464 s = sRef_findDerivedArrayFetch (arr, FALSE, 0, FALSE);
6466 if (sRef_isValid (s))
6468 /* evans 2001-07-12: this is bogus, clean-up hack */
6469 if (s->info->arrayfetch->arr != arr)
6472 check (sRefSet_delete (arr->deriv, s));
6473 res = sRef_buildArrayFetch (arr);
6474 sRef_copyState (res, s);
6475 llassert (res->info->arrayfetch->arr == arr);
6479 sRef_setExKind (s, sRef_getExKind (arr), g_currentloc);
6486 s->kind = SK_ARRAYFETCH;
6487 s->info = (sinfo) dmalloc (sizeof (*s->info));
6488 s->info->arrayfetch = (ainfo) dmalloc (sizeof (*s->info->arrayfetch));
6489 s->info->arrayfetch->indknown = FALSE;
6490 s->info->arrayfetch->ind = 0;
6491 s->info->arrayfetch->arr = arr; /* sRef_copy (arr); */ /*@i32@*/
6492 sRef_setArrayFetchState (s, arr);
6493 s->oaliaskind = s->aliaskind;
6494 s->oexpkind = s->expkind;
6496 if (!context_inProtectVars ())
6498 sRef_addDeriv (arr, s);
6501 if (valueTable_isUndefined (s->state))
6503 s->state = context_createValueTable (s, stateInfo_makeLoc (g_currentloc));
6511 sRef_buildArrayFetchKnown (/*@exposed@*/ sRef arr, int i)
6515 if (!sRef_isValid (arr)) {
6516 /*@-nullret@*/ return arr /*@=nullret@*/;
6519 if (ctype_isRealPointer (arr->type))
6521 (void) sRef_buildPointer (arr); /* do this to define arr! */
6524 s = sRef_findDerivedArrayFetch (arr, TRUE, i, FALSE);
6526 if (sRef_isValid (s))
6528 /* evans 2001-07-12: this is bogus, clean-up hack */
6529 if (s->info->arrayfetch->arr != arr)
6533 check (sRefSet_delete (arr->deriv, s));
6534 res = sRef_buildArrayFetchKnown (arr, i);
6536 llassert (res->info->arrayfetch->arr == arr);
6537 sRef_copyState (res, s);
6538 llassert (res->info->arrayfetch->arr == arr);
6542 sRef_setExKind (s, sRef_getExKind (arr), g_currentloc);
6543 llassert (s->info->arrayfetch->arr == arr);
6550 s->kind = SK_ARRAYFETCH;
6551 s->info = (sinfo) dmalloc (sizeof (*s->info));
6552 s->info->arrayfetch = (ainfo) dmalloc (sizeof (*s->info->arrayfetch));
6553 s->info->arrayfetch->arr = arr; /* sRef_copy (arr); */ /*@i32@*/
6554 s->info->arrayfetch->indknown = TRUE;
6555 s->info->arrayfetch->ind = i;
6557 sRef_setArrayFetchState (s, arr);
6558 /* evans 2001-08-27 no: can change this - llassert (s->info->arrayfetch->arr == arr); */
6560 s->oaliaskind = s->aliaskind;
6561 s->oexpkind = s->expkind;
6562 sRef_addDeriv (arr, s);
6564 llassert (valueTable_isUndefined (s->state));
6565 s->state = context_createValueTable (s, stateInfo_makeLoc (g_currentloc));
6571 ** sets everything except for defstate
6575 sRef_setPartsFromUentry (sRef s, uentry ue)
6577 sRef uref = uentry_getSref (ue);
6579 llassert (sRef_isValid (s));
6581 s->aliaskind = alkind_derive (s->aliaskind, uentry_getAliasKind (ue));
6582 s->oaliaskind = s->aliaskind;
6584 if (s->expkind == XO_UNKNOWN)
6586 s->expkind = uentry_getExpKind (ue);
6589 s->oexpkind = s->expkind;
6591 if (sRef_getNullState (s) == NS_UNKNOWN)
6593 DPRINTF (("Setting null state!"));
6594 sRef_setNullStateN (s, sRef_getNullState (uentry_getSref (ue)));
6598 DPRINTF (("Skipping null null state!"));
6601 if (s->aliaskind == AK_IMPONLY && (sRef_isExposed (s) || sRef_isObserver (s)))
6603 s->oaliaskind = s->aliaskind = AK_IMPDEPENDENT;
6606 if (sRef_isValid (uref))
6608 valueTable utable = uref->state;
6609 valueTable_free (s->state);
6610 s->state = valueTable_copy (utable);
6615 sRef_setStateFromAbstractUentry (sRef s, uentry ue)
6617 llassert (sRef_isValid (s));
6618 sRef_checkMutable (s);
6620 sRef_setPartsFromUentry (s, ue);
6622 s->aliaskind = alkind_derive (s->aliaskind, uentry_getAliasKind (ue));
6623 s->oaliaskind = s->aliaskind;
6625 if (s->expkind == XO_UNKNOWN)
6627 s->expkind = uentry_getExpKind (ue);
6630 s->oexpkind = s->expkind;
6634 sRef_setStateFromUentry (sRef s, uentry ue)
6638 sRef_checkMutable (s);
6639 llassert (sRef_isValid (s));
6641 sRef_setPartsFromUentry (s, ue);
6643 defstate = uentry_getDefState (ue);
6645 if (sstate_isKnown (defstate))
6647 s->defstate = defstate;
6656 sRef_buildPointer (/*@exposed@*/ sRef t)
6658 DPRINTF (("build pointer: %s", sRef_unparse (t)));
6660 if (sRef_isInvalid (t)) return sRef_undefined;
6662 if (sRef_isAddress (t))
6664 DPRINTF (("Return ref: %s", sRef_unparse (t->info->ref)));
6665 return (t->info->ref);
6669 sRef s = sRef_findDerivedPointer (t);
6671 DPRINTF (("find derived: %s", sRef_unparse (s)));
6673 if (sRef_isValid (s))
6676 sRef_setExKind (s, sRef_getExKind (t), g_currentloc);
6677 s->oaliaskind = s->aliaskind;
6678 s->oexpkind = s->expkind;
6684 s = sRef_constructPointerAux (t);
6686 DPRINTF (("construct: %s", sRef_unparse (s)));
6688 if (sRef_isValid (s))
6690 sRef_addDeriv (t, s);
6692 s->oaliaskind = s->aliaskind;
6693 s->oexpkind = s->expkind;
6702 sRef_constructPointer (/*@exposed@*/ sRef t)
6705 return sRef_buildPointer (t);
6708 static /*@exposed@*/ sRef sRef_constructDerefAux (sRef t, bool isdead)
6710 if (sRef_isValid (t))
6715 ** if there is a derived t[?], return that. Otherwise, *t.
6718 s = sRef_findDerivedArrayFetch (t, FALSE, 0, isdead);
6720 if (sRef_isValid (s))
6722 DPRINTF (("Found array fetch: %s", sRef_unparseFull (s)));
6727 sRef ret = sRef_constructPointer (t);
6729 DPRINTF (("Constructed pointer: %s", sRef_unparseFull (ret)));
6736 return sRef_undefined;
6740 sRef sRef_constructDeref (sRef t)
6742 return sRef_constructDerefAux (t, FALSE);
6745 sRef sRef_constructDeadDeref (sRef t)
6747 return sRef_constructDerefAux (t, TRUE);
6751 sRef_constructPointerAux (/*@notnull@*/ /*@exposed@*/ sRef t)
6753 sRef s = sRef_newRef ();
6757 llassert (valueTable_isUndefined (s->state));
6760 s->info = (sinfo) dmalloc (sizeof (*s->info));
6761 s->info->ref = t; /* sRef_copy (t); */ /*@i32*/
6763 if (ctype_isRealAP (rt))
6765 s->type = ctype_baseArrayPtr (rt);
6768 st = ctype_realType (s->type);
6770 if (t->defstate == SS_UNDEFINED)
6772 s->defstate = SS_UNUSEABLE;
6774 else if ((t->defstate == SS_ALLOCATED) && !ctype_isSU (st))
6776 s->defstate = SS_UNDEFINED;
6780 s->defstate = t->defstate;
6783 if (t->aliaskind == AK_LOCAL || t->aliaskind == AK_FRESH)
6785 s->aliaskind = AK_LOCAL;
6789 s->aliaskind = AK_UNKNOWN;
6792 sRef_setExKind (s, sRef_getExKind (t), fileloc_undefined);
6793 sRef_setTypeState (s);
6795 s->oaliaskind = s->aliaskind;
6796 s->oexpkind = s->expkind;
6798 if (valueTable_isUndefined (s->state))
6800 s->state = context_createValueTable (s, stateInfo_makeLoc (g_currentloc));
6806 bool sRef_hasDerived (sRef s)
6808 return (sRef_isValid (s) && !sRefSet_isEmpty (s->deriv));
6812 sRef_clearDerived (sRef s)
6814 if (sRef_isValid (s))
6816 sRefSet_clear (s->deriv);
6821 sRef_clearDerivedComplete (sRef s)
6824 if (sRef_isValid (s))
6826 sRef base = sRef_getBaseSafe (s);
6828 while (sRef_isValid (base))
6830 sRefSet_clear (base->deriv);
6831 base = sRef_getBaseSafe (base);
6834 sRefSet_clear (s->deriv);
6838 /*@exposed@*/ sRef sRef_makePointer (/*@exposed@*/ sRef s)
6841 sRef res = sRef_buildPointer (s);
6843 DPRINTF (("Res: %s", sRef_unparse (res)));
6848 ** &a[] => a (this is for out params)
6852 sRef_makeAnyArrayFetch (/*@exposed@*/ sRef arr)
6855 if (sRef_isAddress (arr))
6857 return (arr->info->ref);
6861 return (sRef_buildArrayFetch (arr));
6866 sRef_makeArrayFetch (/*@exposed@*/ sRef arr)
6868 return (sRef_buildArrayFetch (arr));
6872 sRef_makeArrayFetchKnown (/*@exposed@*/ sRef arr, int i)
6874 return (sRef_buildArrayFetchKnown (arr, i));
6878 sRef_makeField (sRef rec, /*@dependent@*/ cstring f)
6881 ret = sRef_buildField (rec, f);
6886 sRef_makeNCField (/*@exposed@*/ sRef rec, /*@dependent@*/ cstring f)
6888 return (sRef_buildNCField (rec, f));
6892 sRef_unparseKindName (sRef s)
6896 if (s == sRef_undefined) return cstring_makeLiteral ("<invalid>");
6898 s = sRef_fixConj (s);
6903 if (sRef_isLocalVar (s))
6905 result = cstring_makeLiteral ("Variable");
6909 result = cstring_makeLiteral ("Undef global");
6913 result = cstring_makeLiteral ("Out parameter");
6916 if (sRef_isAnyParam (s->info->arrayfetch->arr))
6918 result = cstring_makeLiteral ("Out parameter");
6920 else if (sRef_isIndexKnown (s))
6922 result = cstring_makeLiteral ("Array element");
6926 result = cstring_makeLiteral ("Value");
6930 if (sRef_isAnyParam (s->info->ref))
6932 result = cstring_makeLiteral ("Out parameter");
6936 result = cstring_makeLiteral ("Value");
6940 result = cstring_makeLiteral ("Value");
6943 result = cstring_makeLiteral ("Field");
6946 result = cstring_makeLiteral ("Object");
6948 case SK_UNCONSTRAINED:
6949 result = cstring_makeLiteral ("<anything>");
6958 result = cstring_makeLiteral ("<unknown>");
6961 result = cstring_makeLiteral ("<conj>");
6964 result = cstring_makeLiteral ("Storage");
6972 sRef_unparseKindNamePlain (sRef s)
6976 if (s == sRef_undefined) return cstring_makeLiteral ("<invalid>");
6978 s = sRef_fixConj (s);
6983 if (sRef_isLocalVar (s))
6985 result = cstring_makeLiteral ("Variable");
6989 result = cstring_makeLiteral ("Global");
6993 result = cstring_makeLiteral ("Parameter");
6996 if (sRef_isAnyParam (s->info->arrayfetch->arr))
6998 result = cstring_makeLiteral ("Parameter");
7000 else if (sRef_isIndexKnown (s))
7002 result = cstring_makeLiteral ("Array element");
7006 result = cstring_makeLiteral ("Value");
7010 if (sRef_isAnyParam (s->info->ref))
7012 result = cstring_makeLiteral ("Parameter");
7016 result = cstring_makeLiteral ("Value");
7020 result = cstring_makeLiteral ("Value");
7023 result = cstring_makeLiteral ("Field");
7026 result = cstring_makeLiteral ("Object");
7029 result = cstring_makeLiteral ("Storage");
7031 case SK_UNCONSTRAINED:
7032 result = cstring_makeLiteral ("<anything>");
7041 result = cstring_makeLiteral ("<unknown>");
7044 result = cstring_makeLiteral ("<conj>");
7056 sRef_copyState (sRef s1, sRef s2)
7058 if (sRef_isValid (s1) && sRef_isValid (s2))
7060 s1->defstate = s2->defstate;
7062 /* start modifications */
7063 s1->bufinfo.bufstate = s2->bufinfo.bufstate;
7064 s1->bufinfo.len = s2->bufinfo.len;
7065 s1->bufinfo.size = s2->bufinfo.size;
7066 /* end modifications */
7068 s1->aliaskind = s2->aliaskind;
7069 s1->aliasinfo = stateInfo_update (s1->aliasinfo, s2->aliasinfo);
7071 s1->expkind = s2->expkind;
7072 s1->expinfo = stateInfo_update (s1->expinfo, s2->expinfo);
7074 s1->nullstate = s2->nullstate;
7075 s1->nullinfo = stateInfo_update (s1->nullinfo, s2->nullinfo);
7078 /*@i834 don't free it: valueTable_free (s1->state); */
7079 /*@i32@*/ s1->state = valueTable_copy (s2->state);
7081 s1->safe = s2->safe;
7086 sRef_makeNew (ctype ct, sRef t, cstring name)
7088 sRef s = sRef_newRef ();
7093 llassert (sRef_isValid (t));
7094 s->defstate = t->defstate;
7096 s->aliaskind = t->aliaskind;
7097 s->oaliaskind = s->aliaskind;
7098 s->nullstate = t->nullstate;
7100 s->expkind = t->expkind;
7101 s->oexpkind = s->expkind;
7103 s->info = (sinfo) dmalloc (sizeof (*s->info));
7104 s->info->fname = name;
7106 /* start modifications */
7107 s->bufinfo.bufstate = t->bufinfo.bufstate;
7108 /* end modifications */
7110 llassert (valueTable_isUndefined (s->state));
7111 s->state = valueTable_copy (t->state);
7113 DPRINTF (("==> Copying state: %s", valueTable_unparse (s->state)));
7114 DPRINTF (("==> new: %s", sRef_unparseFull (s)));
7119 sRef_makeType (ctype ct)
7121 sRef s = sRef_newRef ();
7123 sRef_checkMutable (s);
7128 s->defstate = SS_UNKNOWN;
7129 s->aliaskind = AK_UNKNOWN;
7130 sRef_setNullStateN (s, NS_UNKNOWN);
7132 /* start modification */
7133 s->bufinfo.bufstate = BB_NOTNULLTERMINATED;
7134 /* end modification */
7137 if (ctype_isUA (ct))
7139 typeId uid = ctype_typeId (ct);
7140 uentry ue = usymtab_getTypeEntrySafe (uid);
7142 if (uentry_isValid (ue))
7144 sRef_mergeStateQuiet (s, uentry_getSref (ue));
7148 s->oaliaskind = s->aliaskind;
7149 s->oexpkind = s->expkind;
7150 llassert (valueTable_isUndefined (s->state));
7151 s->state = context_createValueTable (s, stateInfo_makeLoc (g_currentloc));
7153 DPRINTF (("Create: %s", sRef_unparseFull (s)));
7158 sRef_makeConst (ctype ct)
7160 sRef s = sRef_newRef ();
7165 s->defstate = SS_UNKNOWN;
7166 s->aliaskind = AK_UNKNOWN;
7167 sRef_setNullStateN (s, NS_UNKNOWN);
7169 /* start modification */
7170 s->bufinfo.bufstate = BB_NULLTERMINATED;
7171 /* end modification */
7172 if (ctype_isUA (ct))
7174 typeId uid = ctype_typeId (ct);
7175 uentry te = usymtab_getTypeEntrySafe (uid);
7177 if (uentry_isValid (te))
7179 sRef_mergeStateQuiet (s, uentry_getSref (te));
7184 s->oaliaskind = s->aliaskind;
7185 s->oexpkind = s->expkind;
7187 llassert (valueTable_isUndefined (s->state));
7188 s->state = context_createValueTable (s, stateInfo_makeLoc (g_currentloc));
7193 bool sRef_hasName (sRef s)
7195 if (sRef_isInvalid (s))
7204 uentry u = usymtab_getRefQuiet (s->info->cvar->lexlevel,
7205 s->info->cvar->index);
7206 return (uentry_hasName (u));
7210 if (s->info->paramno >= 0)
7212 uentry u = uentryList_getN (context_getParams (),
7215 return (uentry_hasName (u));
7219 llassert (s->info->paramno == PARAMUNKNOWN);
7229 sRef_sameName (sRef s1, sRef s2)
7231 if (sRef_isInvalid (s1))
7233 return sRef_isInvalid (s2);
7236 if (sRef_isInvalid (s2))
7244 if (s2->kind == SK_CVAR)
7246 return (s1->info->cvar->lexlevel == s2->info->cvar->lexlevel
7247 && s1->info->cvar->index == s2->info->cvar->index);
7249 else if (s2->kind == SK_PARAM)
7251 if (context_inFunctionLike ())
7253 if (s2->info->paramno != PARAMUNKNOWN)
7255 uentry u1 = usymtab_getRefQuiet (s1->info->cvar->lexlevel,
7256 s1->info->cvar->index);
7257 uentry u2 = uentryList_getN (context_getParams (),
7260 return (cstring_equalFree (uentry_getName (u1),
7261 uentry_getName (u2)));
7265 return s1->info->paramno == PARAMUNKNOWN;
7279 if (s2->kind == SK_PARAM)
7281 return (s1->info->paramno == s2->info->paramno);
7283 else if (s2->kind == SK_CVAR)
7285 if (context_inFunctionLike ())
7287 if (s1->info->paramno == PARAMUNKNOWN)
7293 uentry u1 = uentryList_getN (context_getParams (),
7295 uentry u2 = usymtab_getRefQuiet (s2->info->cvar->lexlevel,
7296 s2->info->cvar->index);
7299 return (cstring_equalFree (uentry_getName (u1),
7300 uentry_getName (u2)));
7314 case SK_UNCONSTRAINED:
7318 if (s2->kind == SK_ARRAYFETCH)
7320 if (bool_equal (s1->info->arrayfetch->indknown,
7321 s2->info->arrayfetch->indknown))
7323 if (!s1->info->arrayfetch->indknown
7324 || (s1->info->arrayfetch->ind == s2->info->arrayfetch->ind))
7326 return sRef_sameName (s1->info->arrayfetch->arr,
7327 s2->info->arrayfetch->arr);
7334 if (s2->kind == SK_FIELD)
7336 if (cstring_equal (s1->info->field->field,
7337 s2->info->field->field))
7339 return sRef_sameName (s1->info->field->rec,
7340 s2->info->field->rec);
7349 if (s2->kind == s1->kind)
7351 return sRef_sameName (s1->info->ref,
7359 return sRef_sameName (sRef_getConjA (s1), s2);
7363 return (s2->kind == SK_UNKNOWN);
7366 if (s2->kind == s1->kind)
7368 return (ctype_equal (s1->type, s2->type));
7373 if (s2->kind == SK_SPECIAL)
7375 return (s1->info->spec == s2->info->spec);
7379 return (s2->kind == SK_RESULT);
7387 sRef_fixOuterRef (/*@returned@*/ sRef s)
7389 sRef root = sRef_getRootBase (s);
7391 if (sRef_isCvar (root))
7393 uentry ue = usymtab_getRefQuiet (root->info->cvar->lexlevel,
7394 root->info->cvar->index);
7396 if (uentry_isValid (ue))
7398 sRef uref = uentry_getSref (ue);
7399 sRef sr = sRef_fixBase (s, uref);
7405 llcontbug (message ("sRef_fixOuterRef: undefined: %q", sRef_unparseDebug (s)));
7414 sRef_storeState (sRef s)
7416 if (sRef_isInvalid (s)) return;
7418 sRef_checkMutable (s);
7419 s->oaliaskind = s->aliaskind;
7420 s->oexpkind = s->expkind;
7423 static void sRef_resetStateAux (sRef s, /*@unused@*/ fileloc loc)
7425 sRef_resetState (s);
7429 sRef_resetState (sRef s)
7431 bool changed = FALSE;
7432 if (sRef_isInvalid (s)) return;
7435 if (s->oaliaskind == AK_KILLREF && !sRef_isParam (s))
7438 ** killref is used in a kludgey way, to save having to add
7439 ** another alias kind (see usymtab_handleParams)
7442 if (s->expkind != s->oexpkind)
7445 s->expkind = s->oexpkind;
7450 if (s->expkind != s->oexpkind)
7453 s->expkind = s->oexpkind;
7456 if (s->aliaskind != s->oaliaskind
7457 && s->aliaskind != AK_REFCOUNTED
7458 && s->aliaskind != AK_REFS)
7461 s->aliaskind = s->oaliaskind;
7467 sRef_clearDerived (s);
7473 sRef_resetStateComplete (sRef s)
7475 sRef_innerAliasSetComplete (sRef_resetStateAux, s, fileloc_undefined);
7479 sRef_fixBase (/*@returned@*/ sRef s, /*@returned@*/ sRef base)
7481 sRef tmp = sRef_undefined;
7484 if (sRef_isInvalid (s)) return s;
7485 if (sRef_isInvalid (base)) return base;
7495 tmp = sRef_fixBase (s->info->arrayfetch->arr, base);
7497 if (s->info->arrayfetch->indknown)
7499 ret = sRef_makeArrayFetchKnown (tmp, s->info->arrayfetch->ind);
7503 ret = sRef_makeArrayFetch (tmp);
7507 tmp = sRef_fixBase (s->info->field->rec, base);
7508 ret = sRef_buildNCField (tmp, s->info->field->field);
7511 tmp = sRef_fixBase (s->info->ref, base);
7512 ret = sRef_makePointer (tmp);
7515 tmp = sRef_fixBase (s->info->ref, base);
7516 ret = sRef_makeAddress (tmp);
7522 tmp = sRef_fixBase (s->info->conj->a, base);
7523 tmpb = sRef_fixBase (s->info->conj->b, base);
7525 ret = sRef_makeConj (tmp, tmpb);
7534 static /*@exposed@*/ sRef
7535 sRef_fixDirectBase (sRef s, sRef base)
7540 if (sRef_isInvalid (s))
7542 return sRef_undefined;
7548 if (s->info->arrayfetch->indknown)
7550 ret = sRef_makeArrayFetchKnown (base, s->info->arrayfetch->ind);
7554 ret = sRef_makeArrayFetch (base);
7558 ret = sRef_buildNCField (base, s->info->field->field);
7561 ret = sRef_makePointer (base);
7564 ret = sRef_makeAddress (base);
7570 tmpa = sRef_fixDirectBase (s->info->conj->a, base);
7571 tmpb = sRef_fixDirectBase (s->info->conj->b, base);
7573 ret = sRef_makeConj (tmpa, tmpb);
7579 sRef_copyState (ret, s);
7584 sRef_isAllocIndexRef (sRef s)
7586 return (sRef_isArrayFetch (s) && !(s->info->arrayfetch->indknown)
7587 && sRef_isAllocated (s->info->arrayfetch->arr));
7591 sRef_showRefLost (sRef s)
7593 if (sRef_hasAliasInfoLoc (s))
7595 llgenindentmsg (cstring_makeLiteral ("Original reference lost"),
7596 sRef_getAliasInfoLoc (s));
7601 sRef_showRefKilled (sRef s)
7603 if (sRef_hasStateInfoLoc (s))
7605 llgenindentmsg (message ("Storage %q released",
7606 sRef_unparse (s)), sRef_getStateInfoLoc (s));
7611 sRef_showStateInconsistent (sRef s)
7613 if (sRef_hasStateInfoLoc (s))
7616 (message ("Storage %qbecomes inconsistent (released on one branch)",
7617 sRef_unparseOpt (s)),
7618 sRef_getStateInfoLoc (s));
7623 sRef_showStateInfo (sRef s)
7625 if (sRef_hasStateInfoLoc (s))
7627 if (s->defstate == SS_DEAD)
7630 (message ("Storage %qis released", sRef_unparseOpt (s)),
7631 sRef_getStateInfoLoc (s));
7633 else if (s->defstate == SS_ALLOCATED || s->defstate == SS_DEFINED)
7636 (message ("Storage %qis %s", sRef_unparseOpt (s),
7637 sstate_unparse (s->defstate)),
7638 sRef_getStateInfoLoc (s));
7640 else if (s->defstate == SS_UNUSEABLE)
7643 (message ("Storage %qbecomes inconsistent (clauses merge with"
7644 "%qreleased on one branch)",
7645 sRef_unparseOpt (s),
7646 sRef_unparseOpt (s)),
7647 sRef_getStateInfoLoc (s));
7651 llgenindentmsg (message ("Storage %qbecomes %s",
7652 sRef_unparseOpt (s),
7653 sstate_unparse (s->defstate)),
7654 sRef_getStateInfoLoc (s));
7660 sRef_showExpInfo (sRef s)
7662 if (sRef_hasExpInfoLoc (s))
7664 llgenindentmsg (message ("Storage %qbecomes %s", sRef_unparseOpt (s),
7665 exkind_unparse (s->expkind)),
7666 sRef_getExpInfoLoc (s));
7671 sRef_showMetaStateInfo (sRef s, cstring key)
7674 metaStateInfo minfo = context_lookupMetaStateInfo (key);
7676 llassert (sRef_isValid (s));
7677 llassert (valueTable_isDefined (s->state));
7678 llassert (metaStateInfo_isDefined (minfo));
7680 val = valueTable_lookup (s->state, key);
7682 if (stateValue_hasLoc (val))
7685 (message ("%qbecomes %q", sRef_unparseOpt (s),
7686 stateValue_unparseValue (val, minfo)),
7687 stateValue_getLoc (val));
7692 sRef_showNullInfo (sRef s)
7694 DPRINTF (("Show null info: %s", sRef_unparseFull (s)));
7696 if (sRef_hasNullInfoLoc (s) && sRef_isKnown (s))
7698 DPRINTF (("has null info: %s",
7699 fileloc_unparse (sRef_getNullInfoLoc (s))));
7701 switch (sRef_getNullState (s))
7705 fileloc loc = sRef_getNullInfoLoc (s);
7707 if (fileloc_isDefined (loc) && !fileloc_isLib (loc))
7710 (message ("Storage %qbecomes null", sRef_unparseOpt (s)),
7717 fileloc loc = sRef_getNullInfoLoc (s);
7719 if (fileloc_isDefined (loc) && !fileloc_isLib (loc))
7721 llgenindentmsg (message ("Storage %qbecomes null", sRef_unparseOpt (s)),
7729 (message ("Storage %qmay become null", sRef_unparseOpt (s)),
7730 sRef_getNullInfoLoc (s));
7735 (message ("Storage %qbecomes not null", sRef_unparseOpt (s)),
7736 sRef_getNullInfoLoc (s));
7740 (message ("Storage %qnull state becomes unknown",
7741 sRef_unparseOpt (s)),
7742 sRef_getNullInfoLoc (s));
7751 (message ("<error case> Storage %q becomes %s",
7753 nstate_unparse (sRef_getNullState (s))),
7754 sRef_getNullInfoLoc (s));
7762 sRef_showAliasInfo (sRef s)
7764 if (sRef_hasAliasInfoLoc (s))
7766 if (sRef_isFresh (s))
7769 (message ("Fresh storage %qallocated", sRef_unparseOpt (s)),
7770 sRef_getAliasInfoLoc (s));
7774 if (!sRef_isRefCounted (s))
7777 (message ("Storage %qbecomes %s",
7778 sRef_unparseOpt (s),
7779 alkind_unparse (sRef_getAliasKind (s))),
7780 sRef_getAliasInfoLoc (s));
7787 sRef_mergeNullState (sRef s, nstate n)
7789 if (sRef_isValid (s))
7793 old = sRef_getNullState (s);
7795 if (n != old && n != NS_UNKNOWN)
7797 sRef_setNullState (s, n, g_currentloc);
7802 llbuglit ("sRef_mergeNullState: invalid");
7807 sRef_possiblyNull (sRef s)
7809 if (sRef_isValid (s))
7811 if (sRef_getNullState (s) == NS_ABSNULL)
7813 ctype rct = ctype_realType (s->type);
7815 if (ctype_isAbstract (rct))
7821 if (ctype_isUser (rct))
7823 uentry ue = usymtab_getTypeEntry (ctype_typeId (rct));
7825 return (nstate_possiblyNull
7826 (sRef_getNullState (uentry_getSref (ue))));
7836 return nstate_possiblyNull (sRef_getNullState (s));
7844 sRef_getScopeName (sRef s)
7846 sRef base = sRef_getRootBase (s);
7848 if (sRef_isRealGlobal (base))
7850 return (cstring_makeLiteralTemp ("Global"));
7852 else if (sRef_isFileStatic (base))
7854 return (cstring_makeLiteralTemp ("Static"));
7858 return (cstring_makeLiteralTemp ("Local"));
7863 sRef_unparseScope (sRef s)
7865 sRef base = sRef_getRootBase (s);
7867 if (sRef_isRealGlobal (base))
7869 return (cstring_makeLiteralTemp ("global"));
7871 else if (sRef_isFileStatic (base))
7873 return (cstring_makeLiteralTemp ("file static"));
7882 sRef_getScope (sRef s)
7884 llassert (sRef_isValid (s));
7886 if (sRef_isCvar (s))
7888 return s->info->cvar->lexlevel;
7890 else if (sRef_isParam (s))
7901 sRef_isDead (sRef s)
7903 return (sRef_isValid (s) && (s)->defstate == SS_DEAD);
7907 sRef_isDeadStorage (sRef s)
7909 if (sRef_isValid (s))
7911 if (s->defstate == SS_DEAD
7912 || s->defstate == SS_UNUSEABLE
7913 || s->defstate == SS_UNDEFINED
7914 || s->defstate == SS_UNKNOWN)
7920 return (sRef_isDefinitelyNull (s));
7930 sRef_isPossiblyDead (sRef s)
7932 return (sRef_isValid (s) && s->defstate == SS_HOFFA);
7935 bool sRef_isStateLive (sRef s)
7937 if (sRef_isValid (s))
7939 sstate ds = s->defstate;
7941 return (!(ds == SS_UNDEFINED
7943 || ds == SS_UNUSEABLE
7944 || ds == SS_HOFFA));
7953 bool sRef_isStateUndefined (sRef s)
7955 return ((sRef_isValid(s)) && ((s)->defstate == SS_UNDEFINED));
7958 bool sRef_isJustAllocated (sRef s)
7960 if (sRef_isAllocated (s))
7962 sRefSet_allElements (s->deriv, el)
7964 if (!(sRef_isStateUndefined (el) || sRef_isUnuseable (el)))
7968 } end_sRefSet_allElements ;
7977 sRef_isAllocatedStorage (sRef s)
7979 if (sRef_isValid (s) && ynm_toBoolStrict (sRef_isReadable (s)))
7981 return (ctype_isVisiblySharable (sRef_getType (s)));
7990 sRef_isUnuseable (sRef s)
7992 return ((sRef_isValid(s)) && ((s)->defstate == SS_UNUSEABLE));
7996 sRef_perhapsNull (sRef s)
7998 if (sRef_isValid (s))
8000 if (sRef_getNullState (s) == NS_ABSNULL)
8002 ctype rct = ctype_realType (s->type);
8004 if (ctype_isAbstract (rct))
8010 if (ctype_isUser (rct))
8012 uentry ue = usymtab_getTypeEntry (ctype_typeId (rct));
8014 return (nstate_perhapsNull
8015 (sRef_getNullState (uentry_getSref (ue))));
8025 return nstate_perhapsNull (sRef_getNullState (s));
8033 ** definitelyNull --- called when TRUE is good
8037 sRef_definitelyNull (sRef s)
8039 return (sRef_isValid (s)
8040 && (sRef_getNullState (s) == NS_DEFNULL || sRef_getNullState (s) == NS_CONSTNULL));
8044 ** based on sRef_similar
8048 sRef_setDerivNullState (sRef set, sRef guide, nstate ns)
8050 if (sRef_isValid (set))
8052 sRef deriv = sRef_getDeriv (set, guide);
8054 if (sRef_isValid (deriv))
8056 sRef_setNullStateN (deriv, ns);
8061 static /*@exposed@*/ sRef
8062 sRef_getDeriv (/*@returned@*/ /*@notnull@*/ sRef set, sRef guide)
8064 llassert (sRef_isValid (set));
8065 llassert (sRef_isValid (guide));
8067 switch (guide->kind)
8070 llassert (set->kind == SK_CVAR);
8075 llassert (set->kind == guide->kind);
8076 llassert (set->info->paramno == guide->info->paramno);
8082 if (set->kind == SK_ARRAYFETCH
8083 && (sRef_similar (set->info->arrayfetch->arr,
8084 guide->info->arrayfetch->arr)))
8090 return (sRef_makeAnyArrayFetch
8091 (sRef_getDeriv (set, guide->info->arrayfetch->arr)));
8096 if (set->kind == SK_PTR && sRef_similar (set->info->ref, guide->info->ref))
8102 return (sRef_makePointer (sRef_getDeriv (set, guide->info->ref)));
8107 if ((set->kind == SK_FIELD &&
8108 (sRef_similar (set->info->field->rec, guide->info->field->rec) &&
8109 cstring_equal (set->info->field->field, guide->info->field->field))))
8115 return (sRef_makeField (sRef_getDeriv (set, guide->info->field->rec),
8116 guide->info->field->field));
8120 if ((set->kind == SK_ADR) && sRef_similar (set->info->ref, guide->info->ref))
8126 return (sRef_makeAddress (sRef_getDeriv (set, guide->info->ref)));
8131 return sRef_undefined;
8135 case SK_UNCONSTRAINED:
8143 return sRef_undefined;
8150 ** sRef_aliasCheckPred
8152 ** A confusing but spiffy function:
8154 ** Calls predf (s, e, text, <alias>) on s and all of s's aliases
8155 ** (unless checkAliases (s) is FALSE).
8157 ** For alias calls, calls as
8158 ** predf (alias, e, text, s)
8162 sRef_aliasCheckPred (bool (predf) (sRef, exprNode, sRef, exprNode),
8163 /*@null@*/ bool (checkAliases) (sRef),
8164 sRef s, exprNode e, exprNode err)
8166 bool error = (*predf)(s, e, sRef_undefined, err);
8169 if (checkAliases != NULL && !(checkAliases (s)))
8171 /* don't check aliases */
8175 sRefSet aliases = usymtab_allAliases (s);
8177 sRefSet_realElements (aliases, current)
8179 if (sRef_isValid (current))
8181 if (!sRef_similar (current, s)
8182 || (error && sRef_sameName (current, s)))
8184 (void) (*predf)(current, e, s, err);
8187 } end_sRefSet_realElements;
8189 sRefSet_free (aliases);
8194 ** return TRUE iff predf (s) is true for s or any alias of s
8198 sRef_aliasCheckSimplePred (sRefTest predf, sRef s)
8209 aliases = usymtab_allAliases (s);
8211 sRefSet_realElements (aliases, current)
8213 if (sRef_isValid (current))
8215 sRef cref = sRef_updateSref (current);
8217 /* Whoa! a very kludgey way to make sure the right sref is used
8218 ** where there is a conditional symbol table. I am beginning
8219 ** to think that having a conditional symbol table wasn't such
8225 DPRINTF (("Checking alias: %s", sRef_unparseFull (cref)));
8226 sRefSet_free (aliases);
8230 } end_sRefSet_realElements;
8232 sRefSet_free (aliases);
8238 sRef_aliasCompleteSimplePred (bool (predf) (sRef), sRef s)
8241 bool result = FALSE;
8244 aliases = usymtab_allAliases (s);
8246 if ((*predf)(s)) result = TRUE;
8249 sRefSet_realElements (aliases, current)
8251 if (sRef_isValid (current))
8253 current = sRef_updateSref (current);
8254 if ((*predf)(current)) result = TRUE;
8256 } end_sRefSet_realElements;
8258 sRefSet_free (aliases);
8263 sRef_aliasSetComplete (void (predf) (sRef, fileloc), sRef s, fileloc loc)
8267 aliases = usymtab_allAliases (s);
8269 DPRINTF (("All aliases: %s", sRefSet_unparseFull (aliases)));
8273 sRefSet_realElements (aliases, current)
8275 if (sRef_isValid (current))
8277 current = sRef_updateSref (current);
8278 ((*predf)(current, loc));
8280 } end_sRefSet_realElements;
8282 sRefSet_free (aliases);
8286 sRef_aliasSetCompleteParam (void (predf) (sRef, int, fileloc), sRef s,
8287 int kind, fileloc loc)
8291 if (sRef_isDeep (s))
8293 aliases = usymtab_allAliases (s);
8297 aliases = usymtab_aliasedBy (s);
8300 (*predf)(s, kind, loc);
8302 sRefSet_realElements (aliases, current)
8304 if (sRef_isValid (current))
8306 current = sRef_updateSref (current);
8307 ((*predf)(current, kind, loc));
8309 } end_sRefSet_realElements;
8311 sRefSet_free (aliases);
8315 ** Version of aliasSetCompleteParam for alkind parameters
8319 sRef_aliasSetCompleteAlkParam (void (predf) (sRef, alkind, fileloc), sRef s,
8320 alkind kind, fileloc loc)
8324 if (sRef_isDeep (s))
8326 aliases = usymtab_allAliases (s);
8330 aliases = usymtab_aliasedBy (s);
8333 (*predf)(s, kind, loc);
8335 sRefSet_realElements (aliases, current)
8337 if (sRef_isValid (current))
8339 current = sRef_updateSref (current);
8340 ((*predf)(current, kind, loc));
8342 } end_sRefSet_realElements;
8344 sRefSet_free (aliases);
8348 sRef_innerAliasSetComplete (void (predf) (sRef, fileloc), sRef s, fileloc loc)
8354 if (!sRef_isValid (s)) return;
8357 ** Type equivalence checking is necessary --- there might be casting.
8364 case SK_UNCONSTRAINED:
8369 inner = s->info->ref;
8370 aliases = usymtab_allAliases (inner);
8371 ct = sRef_getType (inner);
8373 sRefSet_realElements (aliases, current)
8375 if (sRef_isValid (current))
8377 current = sRef_updateSref (current);
8379 if (ctype_equal (ct, sRef_getType (current)))
8381 sRef ptr = sRef_makePointer (current);
8382 ((*predf)(ptr, loc));
8385 } end_sRefSet_realElements;
8387 sRefSet_free (aliases);
8390 inner = s->info->arrayfetch->arr;
8391 aliases = usymtab_allAliases (inner);
8392 ct = sRef_getType (inner);
8394 DPRINTF (("Array fetch: %s", sRefSet_unparse (aliases)));
8396 sRefSet_realElements (aliases, current)
8398 if (sRef_isValid (current))
8400 current = sRef_updateSref (current);
8401 DPRINTF (("Current: %s", sRef_unparseFull (current)));
8403 if (ctype_equal (ct, sRef_getType (current)))
8405 if (s->info->arrayfetch->indknown)
8407 sRef af = sRef_makeArrayFetchKnown (current, s->info->arrayfetch->ind);
8408 DPRINTF (("Defining: %s", sRef_unparseFull (af)));
8409 /* evans 2001-08-27 This isn't true:
8410 llassert (af->info->arrayfetch->arr == current);
8411 see comments in buildArrayFetchKnown
8413 ((*predf)(af, loc));
8417 sRef af = sRef_makeArrayFetch (current);
8418 /* evans 2001-08-27 This isn't true:
8419 llassert (af->info->arrayfetch->arr == current);
8420 see comments in buildArrayFetch
8422 DPRINTF (("Defining: %s", sRef_unparseFull (af)));
8423 ((*predf)(af, loc));
8428 DPRINTF (("Type mismatch: %s / %s",
8430 ctype_unparse (sRef_getType (current))));
8433 } end_sRefSet_realElements;
8435 sRefSet_free (aliases);
8438 inner = s->info->field->rec;
8439 aliases = usymtab_allAliases (inner);
8440 ct = sRef_getType (inner);
8443 sRefSet_realElements (aliases, current)
8445 if (sRef_isValid (current))
8447 current = sRef_updateSref (current);
8449 if (ctype_equal (ct, sRef_getType (current)))
8451 sRef f = sRef_makeField (current, s->info->field->field);
8456 } end_sRefSet_realElements;
8458 sRefSet_free (aliases);
8461 sRef_innerAliasSetComplete (predf, s->info->conj->a, loc);
8462 sRef_innerAliasSetComplete (predf, s->info->conj->b, loc);
8479 sRef_innerAliasSetCompleteParam (void (predf) (sRef, sRef), sRef s, sRef t)
8485 if (!sRef_isValid (s)) return;
8488 ** Type equivalence checking is necessary --- there might be casting.
8495 case SK_UNCONSTRAINED:
8500 inner = s->info->ref;
8501 aliases = usymtab_allAliases (inner);
8502 ct = sRef_getType (inner);
8505 sRefSet_realElements (aliases, current)
8507 if (sRef_isValid (current))
8509 current = sRef_updateSref (current);
8511 if (ctype_equal (ct, sRef_getType (current)))
8513 sRef ptr = sRef_makePointer (current);
8518 } end_sRefSet_realElements;
8520 sRefSet_free (aliases);
8523 inner = s->info->arrayfetch->arr;
8524 aliases = usymtab_allAliases (inner);
8525 ct = sRef_getType (inner);
8527 sRefSet_realElements (aliases, current)
8529 if (sRef_isValid (current))
8531 current = sRef_updateSref (current);
8533 if (ctype_equal (ct, sRef_getType (current)))
8536 if (s->info->arrayfetch->indknown)
8538 sRef af = sRef_makeArrayFetchKnown (current, s->info->arrayfetch->ind);
8544 sRef af = sRef_makeArrayFetch (current);
8550 } end_sRefSet_realElements;
8552 sRefSet_free (aliases);
8555 inner = s->info->field->rec;
8556 aliases = usymtab_allAliases (inner);
8557 ct = sRef_getType (inner);
8560 sRefSet_realElements (aliases, current)
8562 if (sRef_isValid (current))
8564 current = sRef_updateSref (current);
8566 if (ctype_equal (ct, sRef_getType (current)))
8568 sRef f = sRef_makeField (current, s->info->field->field);
8573 } end_sRefSet_realElements;
8575 sRefSet_free (aliases);
8578 sRef_innerAliasSetCompleteParam (predf, s->info->conj->a, t);
8579 sRef_innerAliasSetCompleteParam (predf, s->info->conj->b, t);
8595 static void sRef_combineExKinds (/*@notnull@*/ sRef res, /*@notnull@*/ sRef other)
8597 exkind a1 = sRef_getExKind (res);
8598 exkind a2 = sRef_getExKind (other);
8600 if (a1 == a2 || a2 == XO_UNKNOWN)
8604 else if (a1 == XO_UNKNOWN)
8606 res->expinfo = stateInfo_update (res->expinfo, other->expinfo);
8611 res->expkind = XO_OBSERVER;
8616 ** Currently, this is a very ad hoc implementation, with lots of fixes to
8617 ** make real code work okay. I need to come up with some more general
8618 ** rules or principles here.
8622 sRef_combineAliasKindsError (/*@notnull@*/ sRef res,
8623 /*@notnull@*/ sRef other,
8624 clause cl, fileloc loc)
8626 bool hasError = FALSE;
8627 alkind ares = sRef_getAliasKind (res);
8628 alkind aother = sRef_getAliasKind (other);
8630 sRef_checkMutable (res);
8632 if (alkind_isDependent (ares))
8634 if (aother == AK_KEPT)
8636 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8637 res->aliaskind = AK_KEPT;
8641 if (aother == AK_LOCAL || aother == AK_STATIC
8642 || alkind_isTemp (aother))
8644 DPRINTF (("Setting dependent: %s", sRef_unparseFull (res)));
8645 res->aliaskind = AK_DEPENDENT;
8649 else if (alkind_isDependent (aother))
8651 if (ares == AK_KEPT)
8653 res->aliaskind = AK_KEPT;
8657 if (ares == AK_LOCAL || ares == AK_STATIC || alkind_isTemp (ares))
8659 DPRINTF (("Setting dependent: %s", sRef_unparseFull (res)));
8660 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8661 res->aliaskind = AK_DEPENDENT;
8665 else if ((ares == AK_LOCAL || ares == AK_UNIQUE
8666 || ares == AK_STATIC || alkind_isTemp (ares))
8667 && sRef_isFresh (other))
8670 ** cases like: if (s == NULL) s = malloc...;
8671 ** don't generate errors
8674 if (usymtab_isAltDefinitelyNullDeep (res))
8676 res->aliaskind = ares;
8683 else if ((aother == AK_LOCAL || aother == AK_UNIQUE
8684 || aother == AK_STATIC || alkind_isTemp (aother))
8685 && sRef_isFresh (res))
8688 ** cases like: if (s == NULL) s = malloc...;
8689 ** don't generate errors
8692 if (usymtab_isDefinitelyNullDeep (other))
8694 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8695 res->aliaskind = aother;
8702 else if (ares == AK_NEWREF && aother == AK_REFCOUNTED
8703 && sRef_isConst (other))
8705 res->aliaskind = AK_NEWREF;
8707 else if (aother == AK_NEWREF && ares == AK_REFCOUNTED
8708 && sRef_isConst (res))
8710 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8711 res->aliaskind = AK_NEWREF;
8713 else if (sRef_isLocalVar (res)
8714 && ((ares == AK_KEPT && aother == AK_LOCAL)
8715 || (aother == AK_KEPT && ares == AK_LOCAL)))
8717 res->aliaskind = AK_KEPT;
8726 if (sRef_isThroughArrayFetch (res))
8729 (FLG_BRANCHSTATE, FLG_STRICTBRANCHSTATE,
8731 ("Clauses exit with %q possibly referencing %s storage %s, "
8734 alkind_unparse (aother),
8735 clause_nameTaken (cl),
8736 alkind_unparse (ares),
8737 clause_nameAlternate (cl)),
8740 sRef_showAliasInfo (res);
8741 sRef_showAliasInfo (other);
8742 res->aliaskind = AK_ERROR;
8746 if (ares == AK_KEPT || aother == AK_KEPT)
8748 sRef_maybeKill (res, loc);
8756 message ("Clauses exit with %q referencing %s storage %s, "
8759 alkind_unparse (aother),
8760 clause_nameTaken (cl),
8761 alkind_unparse (ares),
8762 clause_nameAlternate (cl)),
8765 sRef_showAliasInfo (res);
8766 sRef_showAliasInfo (other);
8768 res->aliaskind = AK_ERROR;
8772 res->aliaskind = (sRef_isLocalVar (res) ? AK_LOCAL : AK_UNKNOWN);
8777 sRef_combineAliasKinds (/*@notnull@*/ sRef res, /*@notnull@*/ sRef other,
8778 clause cl, fileloc loc)
8780 alkind ares = sRef_getAliasKind (res);
8781 alkind aother = sRef_getAliasKind (other);
8783 sRef_checkMutable (res);
8785 if (alkind_equal (ares, aother)
8786 || aother == AK_UNKNOWN
8787 || aother == AK_ERROR)
8789 ; /* keep current state */
8791 else if (sRef_isDead (res) || sRef_isDead (other))
8793 /* dead error reported (or storage is dead) */
8794 res ->aliaskind = AK_ERROR;
8796 else if (ares == AK_UNKNOWN || ares == AK_ERROR
8797 || sRef_isStateUndefined (res))
8799 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8800 res->aliaskind = aother;
8802 else if (sRef_isStateUndefined (other))
8806 else if (((ares == AK_UNIQUE || alkind_isTemp (ares))
8807 && aother == AK_LOCAL)
8808 || ((aother == AK_UNIQUE || alkind_isTemp (aother))
8809 && ares == AK_LOCAL))
8811 if (ares != AK_LOCAL)
8813 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8816 res->aliaskind = AK_LOCAL;
8818 else if ((ares == AK_OWNED && aother == AK_FRESH)
8819 || (aother == AK_OWNED && ares == AK_FRESH))
8821 if (ares != AK_FRESH)
8823 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8826 res->aliaskind = AK_FRESH;
8828 else if ((ares == AK_KEEP && aother == AK_FRESH) ||
8829 (aother == AK_KEEP && ares == AK_FRESH))
8831 if (ares != AK_KEEP)
8833 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8836 res->aliaskind = AK_KEEP;
8838 else if ((ares == AK_LOCAL && aother == AK_STACK) ||
8839 (aother == AK_LOCAL && ares == AK_STACK))
8841 if (ares != AK_STACK)
8843 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8846 res->aliaskind = AK_STACK;
8848 else if ((ares == AK_LOCAL
8849 && (aother == AK_OWNED && sRef_isLocalVar (other)))
8850 || (aother == AK_LOCAL
8851 && (ares == AK_OWNED && sRef_isLocalVar (res))))
8853 if (ares != AK_LOCAL)
8855 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8858 res->aliaskind = AK_LOCAL;
8860 else if ((ares == AK_FRESH && alkind_isOnly (aother))
8861 || (aother == AK_FRESH && alkind_isOnly (ares)))
8863 res->aliaskind = AK_FRESH;
8865 else if ((aother == AK_FRESH && sRef_definitelyNull (res))
8866 || (ares == AK_FRESH && sRef_definitelyNull (other)))
8868 if (ares != AK_FRESH)
8870 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8871 res->aliaskind = AK_FRESH;
8874 else if ((sRef_isFresh (res) && sRef_isConst (other))
8875 || (sRef_isFresh (other) && sRef_isConst (res)))
8878 ** for NULL constantants
8882 if (!sRef_isFresh (res))
8884 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8887 res->aliaskind = AK_FRESH;
8889 else if ((alkind_isStatic (aother) && sRef_isConst (res))
8890 || (alkind_isStatic (ares) && sRef_isConst (other)))
8892 if (!alkind_isStatic (ares))
8894 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8895 res->aliaskind = AK_STATIC;
8900 sRef_combineAliasKindsError (res, other, cl, loc);
8904 static void sRef_combineDefState (/*@notnull@*/ sRef res,
8905 /*@notnull@*/ sRef other)
8907 sstate s1 = res->defstate;
8908 sstate s2 = other->defstate;
8911 sRef_checkMutable (res);
8913 if (s1 == s2 || s2 == SS_UNKNOWN)
8917 else if (s1 == SS_UNKNOWN)
8926 if (s2 == SS_DEFINED)
8932 llcontbuglit ("ssfixed: not implemented");
8941 flip = (s2 != SS_DEFINED);
8959 res->definfo = stateInfo_update (res->definfo, other->definfo);
8964 extern /*@notnull@*/ sRef sRef_getConjA (sRef s)
8967 llassert (sRef_isConj (s));
8969 ret = s->info->conj->a;
8970 llassert (ret != NULL);
8974 extern /*@notnull@*/ sRef sRef_getConjB (sRef s)
8977 llassert (sRef_isConj (s));
8979 ret = s->info->conj->b;
8980 llassert (ret != NULL);
8984 extern /*@exposed@*/ sRef sRef_makeArrow (sRef s, /*@dependent@*/ cstring f)
8989 p = sRef_makePointer (s);
8990 ret = sRef_makeField (p, f);
8991 DPRINTF (("Arrow: %s => %s",
8992 sRef_unparseFull (s), sRef_unparseFull (ret)));
8996 extern /*@exposed@*/ sRef sRef_buildArrow (sRef s, cstring f)
9001 p = sRef_buildPointer (s);
9002 ret = sRef_buildField (p, f);
9007 static /*@null@*/ sinfo sinfo_copy (/*@notnull@*/ sRef s)
9014 ret = (sinfo) dmalloc (sizeof (*ret));
9015 ret->cvar = (cref) dmalloc (sizeof (*ret->cvar));
9016 ret->cvar->lexlevel = s->info->cvar->lexlevel;
9017 ret->cvar->index = s->info->cvar->index;
9021 ret = (sinfo) dmalloc (sizeof (*ret));
9022 ret->paramno = s->info->paramno;
9023 llassert (ret->paramno >= -1);
9027 ret = (sinfo) dmalloc (sizeof (*ret));
9028 ret->arrayfetch = (ainfo) dmalloc (sizeof (*ret->arrayfetch));
9029 ret->arrayfetch->indknown = s->info->arrayfetch->indknown;
9030 ret->arrayfetch->ind = s->info->arrayfetch->ind;
9031 ret->arrayfetch->arr = s->info->arrayfetch->arr; /* sRef_copy (s->info->arrayfetch->arr); */ /*@i32@*/
9035 ret = (sinfo) dmalloc (sizeof (*ret));
9036 ret->field = (fldinfo) dmalloc (sizeof (*ret->field));
9037 ret->field->rec = s->info->field->rec; /* sRef_copy (s->info->field->rec); */ /*@i32@*/
9038 ret->field->field = s->info->field->field;
9042 ret = (sinfo) dmalloc (sizeof (*ret));
9043 ret->object = s->info->object;
9050 ret = (sinfo) dmalloc (sizeof (*ret));
9051 ret->ref = s->info->ref; /* Ref_copy (s->info->ref); */
9055 ret = (sinfo) dmalloc (sizeof (*ret));
9056 ret->conj = (cjinfo) dmalloc (sizeof (*ret->conj));
9057 ret->conj->a = s->info->conj->a; /* sRef_copy (s->info->conj->a); */
9058 ret->conj->b = s->info->conj->b; /* sRef_copy (s->info->conj->b);*/
9061 ret = (sinfo) dmalloc (sizeof (*ret));
9062 ret->spec = s->info->spec;
9064 case SK_UNCONSTRAINED:
9066 ret = (sinfo) dmalloc (sizeof (*ret));
9067 ret->fname = s->info->fname;
9073 llassertprint (s->info == NULL, ("s = %s", sRef_unparse (s)));
9081 static /*@null@*/ sinfo sinfo_fullCopy (/*@notnull@*/ sRef s)
9086 ** Since its a full copy, only storage is assigned
9087 ** to dependent fields.
9094 ret = (sinfo) dmalloc (sizeof (*ret));
9095 ret->cvar = (cref) dmalloc (sizeof (*ret->cvar));
9096 ret->cvar->lexlevel = s->info->cvar->lexlevel;
9097 ret->cvar->index = s->info->cvar->index;
9101 ret = (sinfo) dmalloc (sizeof (*ret));
9102 ret->paramno = s->info->paramno;
9103 llassert (ret->paramno >= -1);
9107 ret = (sinfo) dmalloc (sizeof (*ret));
9108 ret->arrayfetch = (ainfo) dmalloc (sizeof (*ret->arrayfetch));
9109 ret->arrayfetch->indknown = s->info->arrayfetch->indknown;
9110 ret->arrayfetch->ind = s->info->arrayfetch->ind;
9111 ret->arrayfetch->arr = sRef_saveCopy (s->info->arrayfetch->arr);
9115 ret = (sinfo) dmalloc (sizeof (*ret));
9116 ret->field = (fldinfo) dmalloc (sizeof (*ret->field));
9117 ret->field->rec = sRef_saveCopy (s->info->field->rec);
9118 ret->field->field = s->info->field->field;
9122 ret = (sinfo) dmalloc (sizeof (*ret));
9123 ret->object = s->info->object;
9130 ret = (sinfo) dmalloc (sizeof (*ret));
9131 ret->ref = sRef_saveCopy (s->info->ref);
9135 ret = (sinfo) dmalloc (sizeof (*ret));
9136 ret->conj = (cjinfo) dmalloc (sizeof (*ret->conj));
9137 ret->conj->a = sRef_saveCopy (s->info->conj->a);
9138 ret->conj->b = sRef_saveCopy (s->info->conj->b);
9141 ret = (sinfo) dmalloc (sizeof (*ret));
9142 ret->spec = s->info->spec;
9145 case SK_UNCONSTRAINED:
9146 ret = (sinfo) dmalloc (sizeof (*ret));
9147 ret->fname = s->info->fname;
9153 llassert (s->info == NULL);
9163 sinfo_update (/*@notnull@*/ /*@exposed@*/ sRef res,
9164 /*@notnull@*/ /*@exposed@*/ sRef other)
9166 llassert (res->kind == other->kind);
9171 res->info->cvar->lexlevel = other->info->cvar->lexlevel;
9172 res->info->cvar->index = other->info->cvar->index;
9176 res->info->paramno = other->info->paramno;
9177 llassert (res->info->paramno >= -1);
9181 res->info->arrayfetch->indknown = other->info->arrayfetch->indknown;
9182 res->info->arrayfetch->ind = other->info->arrayfetch->ind;
9183 res->info->arrayfetch->arr = other->info->arrayfetch->arr;
9187 res->info->field->rec = other->info->field->rec;
9188 res->info->field->field = other->info->field->field;
9192 res->info->object = other->info->object;
9199 res->info->ref = other->info->ref;
9203 res->info->conj->a = other->info->conj->a;
9204 res->info->conj->b = other->info->conj->b;
9208 res->info->spec = other->info->spec;
9212 case SK_UNCONSTRAINED:
9213 res->info->fname = other->info->fname;
9220 llassert (res->info == NULL);
9225 static void sinfo_free (/*@special@*/ /*@temp@*/ /*@notnull@*/ sRef s)
9226 /*@uses s->kind, s->info@*/
9227 /*@releases s->info@*/
9232 DPRINTF (("Free sinfo: [%p]", s->info->cvar));
9233 sfree (s->info->cvar);
9240 DPRINTF (("Free sinfo: [%p]", s->info->arrayfetch));
9241 sfree (s->info->arrayfetch);
9245 DPRINTF (("Free sinfo: [%p]", s->info->field));
9246 sfree (s->info->field);
9255 case SK_EXTERNAL: /*@i32 is copy now! */
9259 DPRINTF (("Free sinfo: [%p]", s->info->conj));
9260 sfree (s->info->conj);
9263 case SK_UNCONSTRAINED:
9273 if (s->info != NULL) {
9274 DPRINTF (("Free sinfo: [%p]", s->info));
9280 bool sRef_isNSLocalVar (sRef s)
9282 if (sRef_isLocalVar (s))
9284 uentry ue = sRef_getUentry (s);
9286 return (!uentry_isStatic (ue));
9294 bool sRef_isLocalVar (sRef s)
9296 if (sRef_isValid(s))
9298 return (s->kind == SK_CVAR
9299 && (s->info->cvar->lexlevel > fileScope));
9305 bool sRef_isRealLocalVar (sRef s)
9307 if (sRef_isValid(s))
9309 if (s->kind == SK_CVAR)
9311 if (s->info->cvar->lexlevel == functionScope)
9313 uentry ue = sRef_getUentry (s);
9315 if (uentry_isAnyParam (ue)
9316 || uentry_isRefParam (ue))
9327 return (s->info->cvar->lexlevel > functionScope);
9335 bool sRef_isLocalParamVar (sRef s)
9337 if (sRef_isValid(s))
9339 return (s->kind == SK_PARAM
9340 || (s->kind == SK_CVAR
9341 && (s->info->cvar->lexlevel > fileScope)));
9347 static speckind speckind_fromInt (int i)
9350 llassert (i >= SR_NOTHING && i <= SR_SYSTEM);
9353 return ((speckind) i);
9357 static void sRef_updateNullState (sRef res, sRef other)
9360 res->nullstate = other->nullstate;
9361 res->nullinfo = stateInfo_update (res->nullinfo, other->nullinfo);
9364 void sRef_combineNullState (/*@notnull@*/ sRef res, /*@notnull@*/ sRef other)
9366 nstate n1 = sRef_getNullState (res);
9367 nstate n2 = sRef_getNullState (other);
9371 if (n1 == n2 || n2 == NS_UNKNOWN)
9377 /* note: n2 is not unknown or defnull */
9381 case NS_ERROR: nn = NS_ERROR; break;
9382 case NS_UNKNOWN: flip = TRUE; nn = n2; break;
9383 case NS_POSNULL: break;
9384 case NS_DEFNULL: nn = NS_POSNULL; break;
9385 case NS_RELNULL: break;
9387 if (n2 == NS_MNOTNULL)
9398 if (n2 == NS_NOTNULL)
9417 res->nullinfo = stateInfo_update (res->nullinfo, other->nullinfo);
9420 res->nullstate = nn;
9423 cstring sRef_nullMessage (sRef s)
9425 llassert (sRef_isValid (s));
9427 switch (sRef_getNullState (s))
9431 return (cstring_makeLiteralTemp ("null"));
9433 return (cstring_makeLiteralTemp ("possibly null"));
9438 /*@observer@*/ cstring sRef_ntMessage (sRef s)
9440 llassert (sRef_isValid (s));
9442 switch (s->nullstate)
9446 return (cstring_makeLiteralTemp ("not nullterminated"));
9448 return (cstring_makeLiteralTemp ("possibly non-nullterminated"));
9455 sRef sRef_fixResultType (/*@returned@*/ sRef s, ctype typ, uentry ue)
9457 sRef tmp = sRef_undefined;
9460 llassert (sRef_isValid (s));
9471 tmp = sRef_fixResultType (s->info->arrayfetch->arr, typ, ue);
9473 ct = ctype_realType (sRef_getType (tmp));
9476 if (ctype_isKnown (ct))
9478 if (ctype_isAP (ct))
9487 ("Special clause indexes non-array (%t): *%q",
9488 ct, sRef_unparse (s->info->arrayfetch->arr)),
9489 uentry_whereLast (ue));
9493 tmp = sRef_fixResultType (s->info->arrayfetch->arr, typ, ue);
9495 if (s->info->arrayfetch->indknown)
9497 ret = sRef_makeArrayFetchKnown (tmp, s->info->arrayfetch->ind);
9501 ret = sRef_makeArrayFetch (tmp);
9507 sRef rec = sRef_fixResultType (s->info->field->rec, typ, ue);
9508 ctype ct = ctype_realType (sRef_getType (rec));
9510 if (ctype_isKnown (ct))
9512 if (ctype_isSU (ct))
9514 if (uentry_isValid (uentryList_lookupField (ctype_getFields (ct),
9515 s->info->field->field)))
9524 ("Special clause accesses non-existent field of result: %q.%s",
9525 sRef_unparse (rec), s->info->field->field),
9526 uentry_whereLast (ue));
9534 ("Special clause accesses field of non-struct or union result (%t): %q.%s",
9535 ct, sRef_unparse (rec), s->info->field->field),
9536 uentry_whereLast (ue));
9540 ret = sRef_makeField (tmp, s->info->field->field);
9546 tmp = sRef_fixResultType (s->info->ref, typ, ue);
9548 ct = ctype_realType (sRef_getType (tmp));
9550 if (ctype_isKnown (ct))
9552 if (ctype_isAP (ct))
9561 ("Special clause dereferences non-pointer (%t): *%q",
9562 ct, sRef_unparse (s->info->ref)),
9563 uentry_whereLast (ue));
9567 ret = sRef_makePointer (tmp);
9574 ("Special clause uses & operator (not allowed): &%q", sRef_unparse (s->info->ref)),
9575 uentry_whereLast (ue));
9584 bool sRef_isOnly (sRef s)
9586 return (sRef_isValid(s) && alkind_isOnly (s->aliaskind));
9589 bool sRef_isDependent (sRef s)
9591 return (sRef_isValid(s) && alkind_isDependent (s->aliaskind));
9594 bool sRef_isOwned (sRef s)
9596 return (sRef_isValid (s) && (s->aliaskind == AK_OWNED));
9599 bool sRef_isKeep (sRef s)
9601 return (sRef_isValid (s) && (s->aliaskind == AK_KEEP));
9604 bool sRef_isTemp (sRef s)
9606 return (sRef_isValid (s) && alkind_isTemp (s->aliaskind));
9609 bool sRef_isLocalState (sRef s)
9611 return (sRef_isValid (s) && (s->aliaskind == AK_LOCAL));
9614 bool sRef_isUnique (sRef s)
9616 return (sRef_isValid (s) && (s->aliaskind == AK_UNIQUE));
9619 bool sRef_isShared (sRef s)
9621 return (sRef_isValid (s) && (s->aliaskind == AK_SHARED));
9624 bool sRef_isExposed (sRef s)
9626 return (sRef_isValid (s) && (s->expkind == XO_EXPOSED));
9629 bool sRef_isObserver (sRef s)
9631 return (sRef_isValid (s) && (s->expkind == XO_OBSERVER));
9634 bool sRef_isFresh (sRef s)
9636 return (sRef_isValid (s) && (s->aliaskind == AK_FRESH));
9639 bool sRef_isDefinitelyNull (sRef s)
9641 return (sRef_isValid (s) && (sRef_getNullState (s) == NS_DEFNULL
9642 || sRef_getNullState (s) == NS_CONSTNULL));
9645 bool sRef_isAllocated (sRef s)
9647 return (sRef_isValid (s) && (s->defstate == SS_ALLOCATED));
9650 bool sRef_isStack (sRef s)
9652 return (sRef_isValid (s) && (s->aliaskind == AK_STACK));
9655 bool sRef_isNotNull (sRef s)
9657 return (sRef_isValid(s) && (sRef_getNullState (s) == NS_MNOTNULL
9658 || sRef_getNullState (s) == NS_NOTNULL));
9661 alkind sRef_getAliasKind (sRef s)
9663 if (sRef_isValid(s)) {
9664 llassert (alkind_isValid (s->aliaskind));
9665 return s->aliaskind;
9671 nstate sRef_getNullState (sRef s)
9673 if (sRef_isValid (s)) {
9674 llassert (nstate_isValid (s->nullstate));
9675 return s->nullstate;
9681 void sRef_reflectAnnotation (sRef s, annotationInfo a, fileloc loc)
9683 if (sRef_isValid (s))
9685 if (!valueTable_isDefined (s->state))
9687 s->state = valueTable_create (1);
9688 valueTable_insert (s->state,
9689 cstring_copy (metaStateInfo_getName (annotationInfo_getState (a))),
9690 stateValue_create (annotationInfo_getValue (a), stateInfo_makeLoc (loc)));
9694 DPRINTF (("reflect loc: %s", fileloc_unparse (loc)));
9697 metaStateInfo_getName (annotationInfo_getState (a)),
9698 stateValue_create (annotationInfo_getValue (a), stateInfo_makeLoc (loc)));
9699 DPRINTF (("state info: %s", stateInfo_unparse (stateInfo_makeLoc (loc))));
9700 DPRINTF (("sref: %s", sRef_unparse (s)));
9701 DPRINTF (("sref: %s", sRef_unparseFull (s)));
9706 void sRef_setMetaStateValueComplete (sRef s, cstring key, int value, fileloc loc)
9708 sRefSet aliases = usymtab_allAliases (s);
9710 sRef_setMetaStateValue (s, key, value, loc);
9712 sRefSet_realElements (aliases, current)
9714 if (sRef_isValid (current))
9716 current = sRef_updateSref (current);
9717 sRef_setMetaStateValue (current, key, value, loc);
9719 } end_sRefSet_realElements ;
9721 sRefSet_free (aliases);
9724 void sRef_setMetaStateValue (sRef s, cstring key, int value, fileloc loc)
9726 sRef_checkMutable (s);
9728 if (sRef_isValid (s))
9730 if (!valueTable_isDefined (s->state))
9732 DPRINTF (("inserting state: %s: %s %d", sRef_unparse (s), key, value));
9733 s->state = valueTable_create (1);
9734 valueTable_insert (s->state, cstring_copy (key),
9735 stateValue_create (value, stateInfo_makeLoc (loc)));
9739 DPRINTF (("Updating state: %s: %s %d / %s", sRef_unparse (s), key, value,
9740 fileloc_unparse (loc)));
9741 if (valueTable_contains (s->state, key))
9744 (s->state, key, stateValue_create (value, stateInfo_makeLoc (loc)));
9749 (s->state, cstring_copy (key), stateValue_create (value, stateInfo_makeLoc (loc)));
9752 DPRINTF (("After: %s", sRef_unparseFull (s)));
9757 bool sRef_checkMetaStateValue (sRef s, cstring key, int value)
9759 if (sRef_isValid (s))
9761 if (valueTable_isDefined (s->state))
9765 DPRINTF (("check state: %s: %s %d", sRef_unparse (s), key, value));
9767 val = valueTable_lookup (s->state, key);
9768 llassert (stateValue_isDefined (val));
9769 return (stateValue_isError (val)
9770 || stateValue_getValue (val) == value);
9783 /*@observer@*/ stateValue sRef_getMetaStateValue (sRef s, cstring key)
9785 if (sRef_isValid (s))
9787 if (valueTable_isDefined (s->state))
9791 val = valueTable_lookup (s->state, key);
9792 /* Okay if its not defined, just returns stateValue_undefined */
9797 return stateValue_undefined;
9802 return stateValue_undefined;
9806 /*@observer@*/ valueTable sRef_getValueTable (sRef s)
9808 DPRINTF (("Get value table: %s", sRef_unparse (s)));
9810 if (sRef_isValid (s))
9812 llassert (sRef_isValid (s));
9813 DPRINTF (("Value table: %s", valueTable_unparse (s->state)));
9818 DPRINTF (("No value table!"));
9819 return valueTable_undefined;
9823 bool sRef_makeStateSpecial (sRef s)
9826 ** Default defined state can be made special.
9829 llassert (sRef_isValid (s)); /*@i523 why doesn't null-checking work!??? */
9831 if (s->defstate == SS_UNKNOWN || s->defstate == SS_DEFINED || s->defstate == SS_SPECIAL)
9833 /* s->aliaskind = AK_IMPTEMP; */ /* evans 2001-07-23 shouldn't effect alias state */
9834 s->defstate = SS_SPECIAL;
9835 DPRINTF (("Made special: %s", sRef_unparseFull (s)));
9840 /* s->aliaskind = AK_IMPTEMP; */
9841 s->defstate = SS_SPECIAL;
9846 void sRef_markImmutable (sRef s)
9848 if (sRef_isValid (s))
9850 DPRINTF (("Mark immutable: %s", sRef_unparseFull (s)));
9855 bool sRef_definitelyNullContext (sRef s)
9857 return (sRef_definitelyNull (s)
9858 || usymtab_isDefinitelyNullDeep (s));
9861 bool sRef_definitelyNullAltContext (sRef s)
9863 return (sRef_definitelyNull (s)
9864 || usymtab_isAltDefinitelyNullDeep (s));
9868 /* start modifications */
9869 struct s_bbufinfo sRef_getNullTerminatedState (sRef p_s) {
9870 struct s_bbufinfo BUFSTATE_UNKNOWN;
9871 BUFSTATE_UNKNOWN.bufstate = BB_NOTNULLTERMINATED;
9872 BUFSTATE_UNKNOWN.size = 0;
9873 BUFSTATE_UNKNOWN.len = 0;
9875 if (sRef_isValid(p_s))
9876 return p_s->bufinfo;
9877 return BUFSTATE_UNKNOWN;
9880 void sRef_setNullTerminatedState(sRef p_s) {
9881 if(sRef_isValid (p_s)) {
9882 p_s->bufinfo.bufstate = BB_NULLTERMINATED;
9884 llfatalbug( message("sRef_setNT passed a invalid sRef\n"));
9889 void sRef_setPossiblyNullTerminatedState(sRef p_s) {
9890 if( sRef_isValid (p_s)) {
9891 p_s->bufinfo.bufstate = BB_POSSIBLYNULLTERMINATED;
9893 llfatalbug( message("sRef_setPossNT passed a invalid sRef\n"));
9897 void sRef_setNotNullTerminatedState(sRef p_s) {
9898 if( sRef_isValid (p_s)) {
9899 p_s->bufinfo.bufstate = BB_NOTNULLTERMINATED;
9901 llfatalbug( message("sRef_unsetNT passed a invalid sRef\n"));
9905 void sRef_setLen(sRef p_s, int len) {
9906 if( sRef_isValid (p_s) && sRef_isNullTerminated(p_s)) {
9907 p_s->bufinfo.len = len;
9909 llfatalbug( message("sRef_setLen passed a invalid sRef\n"));
9914 void sRef_setSize(sRef p_s, int size) {
9915 if( sRef_isValid(p_s)) {
9916 p_s->bufinfo.size = size;
9918 llfatalbug( message("sRef_setSize passed a invalid sRef\n"));
9922 void sRef_resetLen(sRef p_s) {
9923 if (sRef_isValid (p_s)) {
9924 p_s->bufinfo.len = 0;
9926 llfatalbug (message ("sRef_setLen passed an invalid sRef\n"));
9930 /*drl7x 11/28/2000 */
9932 bool sRef_isFixedArray (sRef p_s) /*@*/ {
9934 c = sRef_getType (p_s);
9935 return ( ctype_isFixedArray (c) );
9938 long int sRef_getArraySize (sRef p_s) /*@*/ {
9940 llassert (sRef_isFixedArray(p_s) );
9941 DPRINTF (( message ("sRef_getArraySize getting array size for %s", sRef_unparse(p_s) ) ));
9943 c = sRef_getType (p_s);
9945 return (ctype_getArraySize (c) );
9948 void sRef_setValue (sRef s, multiVal val)
9950 llassert (sRef_isValid (s));
9951 multiVal_free (s->val);
9955 bool sRef_hasValue (sRef s)
9957 return (sRef_isValid (s)
9958 && multiVal_isDefined (s->val));
9961 multiVal sRef_getValue (sRef s)
9963 if (sRef_isValid (s))
9968 return multiVal_undefined;