2 ** Splint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2002 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) /*@*/ ;
84 ** If s is definitely null, it has no memory state.
87 static void sRef_resetAliasKind (/*@notnull@*/ sRef s) /*@modifies s->aliaskind@*/
89 if (s->nullstate == NS_DEFNULL)
91 /* s->aliaskind = AK_ERROR; */
95 static void sRef_checkMutable (/*@unused@*/ sRef s)
98 if (sRef_isValid (s) && s->immut)
100 llcontbug (message ("Modification to sRef marked immutable: %q",
101 sRef_unparseFull (s)));
105 static bool skind_isSimple (skind sk)
109 case SK_PARAM: case SK_CVAR: case SK_CONST:
110 case SK_OBJECT: case SK_UNKNOWN: case SK_NEW:
117 static void sinfo_free (/*@special@*/ /*@temp@*/ /*@notnull@*/ sRef p_s)
118 /*@uses p_s->kind, p_s->info@*/
119 /*@releases p_s->info@*/ ;
121 static /*@null@*/ sinfo sinfo_copy (/*@notnull@*/ sRef p_s) /*@*/ ;
122 static void sRef_setPartsFromUentry (sRef p_s, uentry p_ue)
124 static bool checkDeadState (/*@notnull@*/ sRef p_el, bool p_tbranch, fileloc p_loc);
125 static /*@dependent@*/ sRef sRef_constructPointerAux (/*@notnull@*/ /*@exposed@*/ sRef p_t) /*@*/ ;
128 sRef_combineExKinds (/*@notnull@*/ sRef p_res, /*@notnull@*/ sRef p_other)
129 /*@modifies p_res@*/ ;
132 sRef_combineAliasKinds (/*@notnull@*/ sRef p_res, /*@notnull@*/ sRef p_other,
133 clause p_cl, fileloc p_loc)
134 /*@modifies p_res@*/ ;
137 sRef_combineNullState (/*@notnull@*/ sRef p_res, /*@notnull@*/ sRef p_other)
138 /*@modifies p_res@*/ ;
141 sRef_combineDefState (/*@notnull@*/ sRef p_res, /*@notnull@*/ sRef p_other)
142 /*@modifies p_res@*/ ;
144 static void sRef_setStateFromAbstractUentry (sRef p_s, uentry p_ue)
148 sinfo_update (/*@notnull@*/ /*@exposed@*/ sRef p_res,
149 /*@notnull@*/ /*@exposed@*/ sRef p_other);
150 static void sRef_setDefinedAux (sRef p_s, fileloc p_loc, bool p_clear)
152 static void sRef_setDefinedNoClear (sRef p_s, fileloc p_loc)
154 static void sRef_setStateAux (sRef p_s, sstate p_ss, fileloc p_loc)
157 static /*@exposed@*/ sRef
158 sRef_buildNCField (/*@exposed@*/ sRef p_rec, /*@exposed@*/ cstring p_f);
161 sRef_mergeStateAux (/*@notnull@*/ sRef p_res, /*@notnull@*/ sRef p_other,
162 clause p_cl, bool p_opt, fileloc p_loc,
164 /*@modifies p_res, p_other@*/ ;
166 static /*@null@*/ sinfo sinfo_fullCopy (/*@notnull@*/ sRef p_s);
167 static bool sRef_doModify (sRef p_s, sRefSet p_sl) /*@modifies p_s@*/ ;
168 static bool sRef_doModifyVal (sRef p_s, sRefSet p_sl) /*@modifies p_s@*/;
169 static bool sRef_checkModifyVal (sRef p_s, sRefSet p_sl) /*@*/ ;
171 static /*@only@*/ sRefSet
172 sRef_mergeDerivs (/*@only@*/ sRefSet p_res, sRefSet p_other,
173 bool p_opt, clause p_cl, fileloc p_loc);
175 static /*@only@*/ sRefSet
176 sRef_mergeUnionDerivs (/*@only@*/ sRefSet p_res,
177 /*@exposed@*/ sRefSet p_other,
178 bool p_opt, clause p_cl, fileloc p_loc);
180 static /*@only@*/ sRefSet
181 sRef_mergePdefinedDerivs (/*@only@*/ sRefSet p_res, sRefSet p_other, bool p_opt,
182 clause p_cl, fileloc p_loc);
184 static /*@only@*/ cstring sRef_unparseWithArgs (sRef p_s, uentryList p_args);
185 static /*@only@*/ cstring sRef_unparseNoArgs (sRef p_s);
187 static /*@exposed@*/ sRef sRef_findDerivedPointer (sRef p_s);
188 static /*@exposed@*/ sRef sRef_findDerivedArrayFetch (/*@notnull@*/ sRef, bool, int, bool) ;
189 static /*@exposed@*/ sRef sRef_findDerivedField (/*@notnull@*/ sRef p_rec, cstring p_f);
190 static /*@exposed@*/ sRef
191 sRef_getDeriv (/*@notnull@*/ /*@returned@*/ sRef p_set, sRef p_guide);
193 static bool inFunction = FALSE;
194 static /*@only@*/ sRefTable allRefs;
196 /* # define DEBUGREFS */
200 static totnsrefs = 0;
201 static maxnsrefs = 0;
202 static ntotrefers = 0;
206 static /*@checked@*/ bool protectDerivs = FALSE;
209 ** Result of sRef_alloc is dependent since allRefs may
210 ** reference it. It is only if !inFunction.
213 static /*@dependent@*/ /*@out@*/ /*@notnull@*/ sRef
216 sRef s = (sRef) dmalloc (sizeof (*s));
220 DPRINTF (("Alloc sref: [%p]", s));
224 allRefs = sRefTable_add (allRefs, s);
229 DPRINTF (("Not in function!"));
235 if (nsrefs >= maxnsrefs)
244 /*@-mustfree@*/ /*@-freshtrans@*/
246 /*@=mustfree@*/ /*@=freshtrans@*/
249 static void sRef_checkValidAux (sRef s, sRefSet checkedsofar)
253 if (!sRef_isValid (s)) return;
255 if (sRefSet_containsSameObject (checkedsofar, s))
261 checkedsofar = sRefSet_insert (checkedsofar, s);
262 /*@=temptrans@*/ /* checksofar will be destroyed before checkValid returns */
266 case SK_UNCONSTRAINED:
267 llassert (cstring_length (s->info->fname) < 100);
271 llassert (s->info->cvar->lexlevel >= 0);
272 /* llassert (s->info->cvar->lexlevel <= usymtab_getCurrentDepth ()); */
276 llassert (s->info->paramno >= -1);
277 llassert (s->info->paramno <= 50); /*@i32 bogus...*/
281 sRef_checkValidAux (s->info->arrayfetch->arr, checkedsofar);
285 sRef_checkValidAux (s->info->field->rec, checkedsofar);
286 llassert (cstring_length (s->info->field->field) < 100);
290 sRef_checkValidAux (s->info->ref, checkedsofar);
294 sRef_checkValidAux (s->info->ref, checkedsofar);
298 /* check ctype s->info->object */
302 sRef_checkValidAux (s->info->conj->a, checkedsofar);
303 sRef_checkValidAux (s->info->conj->b, checkedsofar);
307 llassert (cstring_length (s->info->fname) < 100);
311 sRef_checkValidAux (s->info->ref, checkedsofar);
315 sRef_checkValidAux (s->info->ref, checkedsofar);
321 /* check ctyp s->type */
325 llassert (s->info->spec == SR_NOTHING
326 || s->info->spec == SR_INTERNAL
327 || s->info->spec == SR_SPECSTATE
328 || s->info->spec == SR_SYSTEM);
338 sRefSet_elements (s->deriv, el)
340 sRef_checkValidAux (el, checkedsofar);
341 } end_sRefSet_elements ;
344 void sRef_checkValid (/*@unused@*/ sRef s)
348 sRefSet checkedsofar = sRefSet_new ();
349 sRef_checkValidAux (s, checkedsofar);
353 static /*@dependent@*/ /*@notnull@*/ /*@special@*/ sRef
356 /*@ensures isnull result->aliasinfo, result->definfo,
357 result->expinfo, result->info, result->deriv, result->state@*/
359 sRef s = sRef_alloc ();
361 s->kind = SK_UNKNOWN;
365 s->val = multiVal_undefined;
367 s->type = ctype_unknown;
368 s->defstate = SS_UNKNOWN;
370 /* start modifications */
371 s->bufinfo.bufstate = BB_NOTNULLTERMINATED;
372 /* end modifications */
374 s->aliaskind = AK_UNKNOWN;
375 s->oaliaskind = AK_UNKNOWN;
377 s->nullstate = NS_UNKNOWN;
379 s->expkind = XO_UNKNOWN;
380 s->oexpkind = XO_UNKNOWN;
382 s->aliasinfo = stateInfo_undefined;
383 s->definfo = stateInfo_undefined;
384 s->nullinfo = stateInfo_undefined;
385 s->expinfo = stateInfo_undefined;
388 s->deriv = sRefSet_undefined;
390 s->state = valueTable_undefined;
395 static /*@dependent@*/ /*@notnull@*/ /*@special@*/ sRef
398 /*@ensures isnull result->aliasinfo, result->definfo,
399 result->expinfo, result->info, result->deriv@*/
401 sRef res = sRef_new ();
403 res->state = valueTable_undefined;
408 void sRef_protectDerivs (void) /*@modifies protectDerivs@*/
410 llassert (!protectDerivs);
411 protectDerivs = TRUE;
414 void sRef_clearProtectDerivs (void) /*@modifies protectDerivs@*/
416 llassert (protectDerivs);
417 protectDerivs = FALSE;
421 ** hmmm...here be kind of a hack. This function mysteriously appeared
422 ** in my code, but I'm sure I didn't write it.
426 sRef_isRecursiveField (sRef s)
428 if (sRef_isField (s))
430 if (sRef_depth (s) > 13)
435 fieldname = sRef_getField (s);
436 base = sRef_getBase (s);
438 while (sRef_isValid (base))
440 if (sRef_isField (base))
442 if (cstring_equal (fieldname, sRef_getField (base)))
448 base = sRef_getBaseSafe (base);
457 sRef_addDeriv (/*@notnull@*/ sRef s, /*@notnull@*/ /*@exposed@*/ sRef t)
459 if (!context_inProtectVars ()
463 && !sRef_isConst (s))
465 int sd = sRef_depth (s);
466 int td = sRef_depth (t);
473 /* This sometimes fails: (evans 2001-07-12)
474 if (sRef_isArrayFetch (t))
476 DPRINTF (("Derived fetch: %s / %s / %s",
477 sRef_unparseFull (s), sRef_unparseFull (t),
478 sRef_unparseFull (t->info->arrayfetch->arr)));
479 llassert (t->info->arrayfetch->arr == s);
483 if (sRef_isFileOrGlobalScope (s))
485 if (context_inFunctionLike ()
486 && ctype_isKnown (sRef_getType (s))
487 && !ctype_isFunction (sRef_getType (s)))
489 globSet g = context_getUsedGlobs ();
491 if (!globSet_member (g, s))
494 ** don't report as a bug
498 (message ("sRef_addDeriv: global variable not in used "
499 "globs: %q / %s / %q",
501 ctype_unparse (sRef_getType (s)),
502 sRefSet_unparse (s->deriv)));
507 s->deriv = sRefSet_insert (s->deriv, t);
513 DPRINTF (("Add deriv: [%p] %s / [%p] %s",
515 t, sRef_unparse (t)));
517 s->deriv = sRefSet_insert (s->deriv, t);
523 sRef_deepPred (bool (predf) (sRef), sRef s)
525 if (sRef_isValid (s))
527 if ((*predf)(s)) return TRUE;
532 return (sRef_deepPred (predf, s->info->ref));
534 return (sRef_deepPred (predf, s->info->arrayfetch->arr));
536 return (sRef_deepPred (predf, s->info->field->rec));
538 return (sRef_deepPred (predf, s->info->conj->a)
539 || sRef_deepPred (predf, s->info->conj->b));
548 bool sRef_modInFunction (void)
553 void sRef_setStateFromType (sRef s, ctype ct)
555 if (sRef_isValid (s))
557 if (ctype_isUser (ct))
559 DPRINTF (("Here we are: %s", sRef_unparseFull (s)));
560 sRef_setStateFromUentry
561 (s, usymtab_getTypeEntry (ctype_typeId (ct)));
563 else if (ctype_isAbstract (ct))
565 DPRINTF (("Here we are: %s", sRef_unparseFull (s)));
566 sRef_setStateFromAbstractUentry
567 (s, usymtab_getTypeEntry (ctype_typeId (ct)));
571 ; /* not a user type */
576 static void sRef_setTypeState (sRef s)
578 if (sRef_isValid (s))
580 sRef_setStateFromType (s, s->type);
585 sRef_hasAliasInfoLoc (sRef s)
587 return (sRef_isValid (s) && (s->aliasinfo != NULL)
588 && (fileloc_isDefined (s->aliasinfo->loc)));
591 static /*@falsenull@*/ bool
592 sRef_hasStateInfoLoc (sRef s)
594 return (sRef_isValid (s) && (s->definfo != NULL)
595 && (fileloc_isDefined (s->definfo->loc)));
598 static /*@falsenull@*/ bool
599 sRef_hasExpInfoLoc (sRef s)
601 return (sRef_isValid (s)
602 && (s->expinfo != NULL) && (fileloc_isDefined (s->expinfo->loc)));
606 static /*@observer@*/ /*@unused@*/ stateInfo sRef_getInfo (sRef s, cstring key)
610 if (!sRef_isValid (s)) {
611 return stateInfo_undefined;
614 sv = valueTable_lookup (s->state, key);
616 if (stateValue_isDefined (sv))
618 return stateValue_getInfo (sv);
621 return stateInfo_undefined;
626 sRef_hasNullInfoLoc (sRef s)
628 return (sRef_isValid (s) && s->nullinfo != NULL
629 && (fileloc_isDefined (s->nullinfo->loc)));
633 sRef_hasAliasInfoRef (sRef s)
635 return (sRef_isValid (s) && (s->aliasinfo != NULL)
636 && (sRef_isValid (s->aliasinfo->ref)));
639 static /*@observer@*/ fileloc
640 sRef_getAliasInfoLoc (/*@exposed@*/ sRef s)
642 llassert (sRef_isValid (s) && s->aliasinfo != NULL
643 && (fileloc_isDefined (s->aliasinfo->loc)));
644 return (s->aliasinfo->loc);
647 static /*@observer@*/ fileloc
648 sRef_getStateInfoLoc (/*@exposed@*/ sRef s)
650 llassert (sRef_isValid (s) && s->definfo != NULL
651 && (fileloc_isDefined (s->definfo->loc)));
652 return (s->definfo->loc);
655 static /*@observer@*/ fileloc
656 sRef_getExpInfoLoc (/*@exposed@*/ sRef s)
658 llassert (sRef_isValid (s) && s->expinfo != NULL
659 && (fileloc_isDefined (s->expinfo->loc)));
660 return (s->expinfo->loc);
663 static /*@observer@*/ fileloc
664 sRef_getNullInfoLoc (/*@exposed@*/ sRef s)
666 llassert (sRef_isValid (s) && s->nullinfo != NULL
667 && (fileloc_isDefined (s->nullinfo->loc)));
668 return (s->nullinfo->loc);
672 sRef_getAliasInfoRef (/*@temp@*/ sRef s)
674 llassert (sRef_isValid (s) && s->aliasinfo != NULL);
675 return (s->aliasinfo->ref);
678 bool sRef_inGlobalScope ()
684 ** This function should be called before new sRefs are created
685 ** somewhere where they will have a lifetime greater than the
686 ** current function scope.
689 void sRef_setGlobalScope ()
691 llassert (inFunction);
692 DPRINTF (("leave function"));
696 void sRef_clearGlobalScope ()
698 llassert (!inFunction);
699 DPRINTF (("enter function"));
703 static bool oldInFunction = FALSE;
704 static int nestedScope = 0;
706 void sRef_setGlobalScopeSafe ()
708 if (nestedScope == 0)
710 oldInFunction = inFunction;
714 DPRINTF (("leave function safe"));
718 void sRef_clearGlobalScopeSafe ()
721 llassert (nestedScope >= 0);
723 if (nestedScope == 0)
725 inFunction = oldInFunction;
728 DPRINTF (("clear function: %s", bool_unparse (inFunction)));
731 void sRef_enterFunctionScope ()
733 /* evans 2001-09-09 - cleanup if we are in a macro! */
734 if (context_inMacro ())
737 sRef_exitFunctionScope ();
741 llassert (!inFunction);
742 llassert (sRefTable_isEmpty (allRefs));
744 DPRINTF (("enter function"));
747 void sRef_exitFunctionScope ()
751 DPRINTF (("Exit function scope."));
752 sRefTable_clear (allRefs);
757 llbuglit ("sRef_exitFunctionScope: not in function");
761 void sRef_destroyMod () /*@globals killed allRefs;@*/
764 llmsg (message ("Live: %d / %d ", nsrefs, totnsrefs));
767 sRefTable_free (allRefs);
771 static /*@notnull@*/ /*@exposed@*/ sRef
772 sRef_fixConj (/*@notnull@*/ sRef s)
777 s = sRef_getConjA (s);
778 } while (sRef_isConj (s));
780 llassert (sRef_isValid (s));
781 return s; /* don't need to ref */
790 sRef_isExternallyVisibleAux (sRef s)
793 sRef base = sRef_getRootBase (s);
795 if (sRef_isValid (base))
797 res = sRef_isParam (base) || sRef_isFileOrGlobalScope (base) || sRef_isExternal (base);
804 sRef_isExternallyVisible (sRef s)
806 return (sRef_aliasCheckSimplePred (sRef_isExternallyVisibleAux, s));
810 sRef_getBaseUentry (sRef s)
812 sRef base = sRef_getRootBase (s);
813 uentry res = uentry_undefined;
815 if (sRef_isValid (base))
820 res = usymtab_getRefQuiet (paramsScope, base->info->paramno);
824 res = usymtab_getRefQuiet (base->info->cvar->lexlevel,
825 base->info->cvar->index);
837 ** lookup the current uentry corresponding to s, and return the corresponding sRef.
838 ** yuk yuk yuk yuk yuk yuk yuk yuk
842 sRef_updateSref (sRef s)
848 if (!sRef_isValid (s)) return sRef_undefined;
857 case SK_UNCONSTRAINED:
864 sRef r = sRef_updateSref (s->info->ref);
866 if (r != s->info->ref)
868 return sRef_makeExternal (r);
878 uentry ue = sRef_getUentry (s);
880 /* must be raw name! (need the marker) */
881 ue = usymtab_lookupSafe (uentry_rawName (ue));
883 if (uentry_isUndefined (ue))
889 DPRINTF (("Update sref: %s", uentry_unparseFull (ue)));
890 return (uentry_getSref (ue));
894 /* special case if ind known */
895 inner = s->info->arrayfetch->arr;
896 ret = sRef_updateSref (inner);
904 res = sRef_makeArrayFetch (ret);
910 inner = s->info->field->rec;
911 ret = sRef_updateSref (inner);
919 res = (sRef_makeField (ret, s->info->field->field));
924 inner = s->info->ref;
925 ret = sRef_updateSref (inner);
932 res = sRef_makePointer (ret);
938 inner = s->info->ref;
939 ret = sRef_updateSref (inner);
947 res = sRef_makeAddress (ret);
954 sRef innera = s->info->conj->a;
955 sRef innerb = s->info->conj->b;
956 sRef reta = sRef_updateSref (innera);
957 sRef retb = sRef_updateSref (innerb);
959 if (innera == reta && innerb == retb)
965 res = sRef_makeConj (reta, retb);
976 sRef_getUentry (sRef s)
978 llassert (sRef_isValid (s));
983 return (usymtab_getRefQuiet (paramsScope, s->info->paramno));
985 return (usymtab_getRefQuiet (s->info->cvar->lexlevel, s->info->cvar->index));
988 if (sRef_isCvar (s->info->conj->a) || sRef_isParam (s->info->conj->a)
989 || sRef_isConj (s->info->conj->a))
991 return sRef_getUentry (s->info->conj->a);
995 return sRef_getUentry (s->info->conj->b);
1000 return uentry_undefined;
1006 sRef_getParam (sRef s)
1008 llassert (sRef_isValid (s));
1009 llassert (s->kind == SK_PARAM);
1011 return s->info->paramno;
1015 sRef_isModified (sRef s)
1017 return (!sRef_isValid (s) || s->modified);
1020 void sRef_setModified (sRef s)
1022 if (sRef_isValid (s))
1027 if (sRef_isRefsField (s))
1029 sRef base = sRef_getBase (s);
1032 llassert (s->kind == SK_FIELD);
1035 if (sRef_isPointer (base))
1037 base = sRef_getBase (base);
1040 if (sRef_isRefCounted (base))
1042 base->aliaskind = AK_NEWREF;
1049 ** note: this side-effects sRefSet to set modified to TRUE
1050 ** for any sRef similar to s.
1054 sRef_canModifyVal (sRef s, sRefSet sl)
1056 if (context_getFlag (FLG_MUSTMOD))
1058 return (sRef_doModifyVal (s, sl));
1062 return (sRef_checkModifyVal (s, sl));
1067 sRef_canModify (sRef s, sRefSet sl)
1070 if (context_getFlag (FLG_MUSTMOD))
1072 return (sRef_doModify (s, sl));
1076 return (sRef_checkModify (s, sl));
1085 bool sRef_checkModifyVal (sRef s, sRefSet sl)
1087 DPRINTF (("Check modify val: %s", sRef_unparse (s)));
1089 if (sRef_isInvalid (s))
1096 case SK_UNCONSTRAINED:
1100 DPRINTF (("Modify var: %s", sRef_unparse (s)));
1102 if (sRef_isFileOrGlobalScope (s))
1104 if (context_checkGlobMod (s))
1106 return (sRefSet_member (sl, s));
1116 return (sRefSet_member (sl, s)
1117 || alkind_isOnly (sRef_getOrigAliasKind (s)));
1119 /* special case if ind known */
1120 return (sRefSet_member (sl, s) ||
1121 sRef_checkModifyVal (s->info->arrayfetch->arr, sl));
1123 return (sRefSet_member (sl, s) || sRef_checkModifyVal (s->info->field->rec, sl));
1125 return (sRefSet_member (sl, s) || sRef_checkModifyVal (s->info->ref, sl));
1127 return (sRefSet_member (sl, s) || sRef_checkModifyVal (s->info->ref, sl));
1129 return ((sRef_checkModifyVal (s->info->conj->a, sl)) &&
1130 (sRef_checkModifyVal (s->info->conj->b, sl)));
1141 switch (s->info->spec)
1143 case SR_NOTHING: return TRUE;
1145 if (context_getFlag (FLG_INTERNALGLOBS))
1147 return (sRefSet_member (sl, s));
1153 case SR_SPECSTATE: return TRUE;
1154 case SR_SYSTEM: return (sRefSet_member (sl, s));
1155 case SR_GLOBALMARKER: BADBRANCH;
1158 case SK_RESULT: BADBRANCH;
1164 ** this should probably be elsewhere...
1166 ** returns TRUE iff sl indicates that s can be modified
1169 static bool sRef_checkModify (sRef s, sRefSet sl)
1171 llassert (sRef_isValid (s));
1175 case SK_UNCONSTRAINED:
1179 if (sRef_isFileOrGlobalScope (s))
1181 if (context_checkGlobMod (s))
1183 return (sRefSet_member (sl, s));
1195 return (sRefSet_member (sl, s) ||
1196 sRef_checkModifyVal (s->info->arrayfetch->arr, sl));
1199 sRef sr = s->info->field->rec;
1201 if (sr->kind == SK_PARAM)
1202 return TRUE; /* structs are copied on call */
1204 return (sRefSet_member (sl, s) || sRef_checkModifyVal (s->info->field->rec, sl));
1210 sm = sRefSet_member (sl, s);
1215 return (sRef_checkModifyVal (s->info->ref, sl));
1218 return (sRefSet_member (sl, s) || sRef_checkModifyVal (s->info->ref, sl));
1220 return ((sRef_checkModify (s->info->conj->a, sl)) &&
1221 (sRef_checkModify (s->info->conj->b, sl)));
1231 switch (s->info->spec)
1233 case SR_NOTHING: return TRUE;
1235 if (context_getFlag (FLG_INTERNALGLOBS))
1237 return (sRefSet_member (sl, s));
1243 case SR_SPECSTATE: return TRUE;
1244 case SR_SYSTEM: return (sRefSet_member (sl, s));
1245 case SR_GLOBALMARKER: BADBRANCH;
1248 case SK_RESULT: BADBRANCH;
1253 cstring sRef_stateVerb (sRef s)
1255 if (sRef_isDead (s))
1257 return cstring_makeLiteralTemp ("released");
1259 else if (sRef_isKept (s))
1261 return cstring_makeLiteralTemp ("kept");
1263 else if (sRef_isDependent (s))
1265 return cstring_makeLiteralTemp ("dependent");
1273 cstring sRef_stateAltVerb (sRef s)
1275 if (sRef_isDead (s))
1277 return cstring_makeLiteralTemp ("live");
1279 else if (sRef_isKept (s))
1281 return cstring_makeLiteralTemp ("not kept");
1283 else if (sRef_isDependent (s))
1285 return cstring_makeLiteralTemp ("independent");
1294 bool sRef_doModifyVal (sRef s, sRefSet sl)
1296 llassert (sRef_isValid (s));
1301 case SK_UNCONSTRAINED:
1305 if (sRef_isFileOrGlobalScope (s))
1308 if (context_checkGlobMod (s))
1310 return (sRefSet_modifyMember (sl, s));
1314 (void) sRefSet_modifyMember (sl, s);
1324 return (sRefSet_modifyMember (sl, s)
1325 || alkind_isOnly (sRef_getOrigAliasKind (s)));
1327 /* special case if ind known */
1328 /* unconditional OR, need side effect */
1329 return (OR (sRefSet_modifyMember (sl, s),
1330 sRef_doModifyVal (s->info->arrayfetch->arr, sl)));
1332 return (OR (sRefSet_modifyMember (sl, s),
1333 sRef_doModifyVal (s->info->field->rec, sl)));
1335 return (OR (sRefSet_modifyMember (sl, s),
1336 sRef_doModifyVal (s->info->ref, sl)));
1338 return (OR (sRefSet_modifyMember (sl, s),
1339 sRef_doModifyVal (s->info->ref, sl)));
1341 return (AND (sRef_doModifyVal (s->info->conj->a, sl) ,
1342 sRef_doModifyVal (s->info->conj->b, sl)));
1352 switch (s->info->spec)
1354 case SR_NOTHING: return TRUE;
1356 if (context_getFlag (FLG_INTERNALGLOBS))
1358 return (sRefSet_modifyMember (sl, s));
1362 (void) sRefSet_modifyMember (sl, s);
1365 case SR_SPECSTATE: return TRUE;
1366 case SR_SYSTEM: return (sRefSet_modifyMember (sl, s));
1367 case SR_GLOBALMARKER: BADBRANCH;
1371 case SK_RESULT: BADBRANCH;
1377 ** this should probably be elsewhere...
1379 ** returns TRUE iff sl indicates that s can be modified
1383 bool sRef_doModify (sRef s, sRefSet sl)
1385 llassert (sRef_isValid (s));
1389 case SK_UNCONSTRAINED:
1393 if (sRef_isFileOrGlobalScope (s))
1395 if (context_checkGlobMod (s))
1397 return (sRefSet_modifyMember (sl, s));
1401 (void) sRefSet_modifyMember (sl, s);
1413 return (OR (sRefSet_modifyMember (sl, s),
1414 sRef_doModifyVal (s->info->arrayfetch->arr, sl)));
1417 sRef sr = s->info->field->rec;
1419 if (sr->kind == SK_PARAM)
1421 return TRUE; /* structs are shallow-copied on call */
1424 return (OR (sRefSet_modifyMember (sl, s),
1425 sRef_doModifyVal (s->info->field->rec, sl)));
1429 return (OR (sRefSet_modifyMember (sl, s),
1430 sRef_doModifyVal (s->info->ref, sl)));
1433 return (OR (sRefSet_modifyMember (sl, s),
1434 sRef_doModifyVal (s->info->ref, sl)));
1436 return (AND (sRef_doModify (s->info->conj->a, sl),
1437 (sRef_doModify (s->info->conj->b, sl))));
1448 switch (s->info->spec)
1450 case SR_NOTHING: return TRUE;
1451 case SR_INTERNAL: return TRUE;
1452 case SR_SPECSTATE: return TRUE;
1453 case SR_SYSTEM: return (sRefSet_modifyMember (sl, s));
1454 case SR_GLOBALMARKER: BADBRANCH;
1457 case SK_RESULT: BADBRANCH;
1462 static /*@exposed@*/ sRef
1463 sRef_leastCommon (/*@exposed@*/ sRef s1, sRef s2)
1465 llassert (sRef_similar (s1, s2));
1467 if (!sRef_isValid (s1)) return s1;
1468 if (!sRef_isValid (s2)) return s1;
1470 sRef_combineDefState (s1, s2);
1471 sRef_combineNullState (s1, s2);
1472 sRef_combineExKinds (s1, s2);
1474 if (s1->aliaskind != s2->aliaskind)
1476 if (s1->aliaskind == AK_UNKNOWN)
1478 s1->aliaskind = s2->aliaskind;
1480 else if (s2->aliaskind == AK_UNKNOWN)
1486 s1->aliaskind = AK_ERROR;
1493 int sRef_compare (sRef s1, sRef s2)
1495 if (s1 == s2) return 0;
1497 if (sRef_isInvalid (s1)) return -1;
1498 if (sRef_isInvalid (s2)) return 1;
1500 INTCOMPARERETURN (s1->kind, s2->kind);
1501 INTCOMPARERETURN (s1->defstate, s2->defstate);
1502 INTCOMPARERETURN (s1->aliaskind, s2->aliaskind);
1504 DPRINTF (("Compare null state: %s / %s",
1505 sRef_unparseFull (s1),
1506 sRef_unparseFull (s2)));
1508 COMPARERETURN (nstate_compare (sRef_getNullState (s1),
1509 sRef_getNullState (s2)));
1514 return (int_compare (s1->info->paramno, s2->info->paramno));
1517 COMPARERETURN (sRef_compare (s1->info->arrayfetch->arr,
1518 s2->info->arrayfetch->arr));
1520 if (s1->info->arrayfetch->indknown && s2->info->arrayfetch->indknown)
1522 return (int_compare (s1->info->arrayfetch->ind,
1523 s2->info->arrayfetch->ind));
1525 if (!s1->info->arrayfetch->indknown && !s2->info->arrayfetch->indknown)
1532 COMPARERETURN (sRef_compare (s1->info->field->rec, s2->info->field->rec));
1534 if (cstring_equal (s1->info->field->field, s2->info->field->field))
1541 return (sRef_compare (s1->info->ref, s2->info->ref));
1543 COMPARERETURN (sRef_compare (s1->info->conj->a, s2->info->conj->a));
1544 return (sRef_compare (s1->info->conj->b, s2->info->conj->b));
1545 case SK_UNCONSTRAINED:
1546 return (cstring_compare (s1->info->fname, s2->info->fname));
1558 return (generic_compare (s1->info->spec, s2->info->spec));
1563 static bool cref_equal (cref c1, cref c2)
1565 return ((c1->lexlevel == c2->lexlevel) &&
1566 (usymId_equal (c1->index, c2->index)));
1570 ** returns true if s1 could be the same storage as s2.
1571 ** i.e., a[?] ~ a[3]. Note its not symmetric ... s1
1572 ** should be more specific.
1576 ** like similar, but matches objects <-> non-objects
1580 sRef_uniqueReference (sRef s)
1582 return (sRef_isFresh (s) || sRef_isUnique (s)
1583 || sRef_isOnly (s) || sRef_isStack (s)
1584 || sRef_isAddress (s));
1588 sRef_similarRelaxedAux (sRef s1, sRef s2)
1592 if (sRef_isUnknownArrayFetch (s1))
1602 if (sRef_isInvalid (s1) || sRef_isInvalid (s2)) return FALSE;
1604 if (sRef_isConj (s2))
1605 return (sRef_similarRelaxedAux (s1, sRef_getConjA (s2)) ||
1606 sRef_similarRelaxedAux (s1, sRef_getConjB (s2)));
1611 return ((s2->kind == SK_CVAR)
1612 && (cref_equal (s1->info->cvar, s2->info->cvar)));
1614 return ((s2->kind == SK_PARAM)
1615 && (s1->info->paramno == s2->info->paramno));
1617 if (s2->kind == SK_ARRAYFETCH)
1619 if (sRef_similarRelaxedAux (s1->info->arrayfetch->arr,
1620 s2->info->arrayfetch->arr))
1622 if (s1->info->arrayfetch->indknown)
1624 if (s2->info->arrayfetch->indknown)
1626 return (s1->info->arrayfetch->ind == s2->info->arrayfetch->ind);
1641 return ((s2->kind == SK_FIELD
1642 && (sRef_similarRelaxedAux (s1->info->field->rec,
1643 s2->info->field->rec)
1644 && cstring_equal (s1->info->field->field,
1645 s2->info->field->field))));
1647 return ((s2->kind == SK_PTR)
1648 && sRef_similarRelaxedAux (s1->info->ref, s2->info->ref));
1650 return ((s2->kind == SK_ADR)
1651 && sRef_similarRelaxedAux (s1->info->ref, s2->info->ref));
1653 return ((sRef_similarRelaxedAux (s1->info->conj->a, s2) ||
1654 (sRef_similarRelaxedAux (s1->info->conj->b, s2))));
1656 return (s1->info->spec == s2->info->spec);
1657 case SK_UNCONSTRAINED:
1658 return (cstring_equal (s1->info->fname, s2->info->fname));
1673 sRef_similarRelaxed (sRef s1, sRef s2)
1679 if (sRef_isThroughArrayFetch (s1))
1689 if (sRef_isInvalid (s1) || sRef_isInvalid (s2)) return FALSE;
1691 us1 = sRef_uniqueReference (s1);
1692 us2 = sRef_uniqueReference (s2);
1694 if ((s1->kind == SK_EXTERNAL && (s2->kind != SK_EXTERNAL && !us2))
1695 || (s2->kind == SK_EXTERNAL && (s1->kind != SK_EXTERNAL && !us1)))
1698 ** Previously, also:
1699 ** || (sRef_isExposed (s1) && !us2) || (sRef_isExposed (s2) && !us1)) ????
1701 ** No clue why this was there?!
1705 if (sRef_isExposed (s1) && sRef_isCvar (s1))
1707 uentry ue1 = sRef_getUentry (s1);
1709 if (uentry_isRefParam (ue1))
1711 return sRef_similarRelaxedAux (s1, s2);
1715 if (sRef_isExposed (s2) && sRef_isCvar (s2))
1717 uentry ue2 = sRef_getUentry (s2);
1719 if (uentry_isRefParam (ue2))
1721 return sRef_similarRelaxedAux (s1, s2);
1725 return (ctype_match (s1->type, s2->type));
1729 return sRef_similarRelaxedAux (s1, s2);
1734 sRef_similar (sRef s1, sRef s2)
1736 if (s1 == s2) return TRUE;
1737 if (sRef_isInvalid (s1) || sRef_isInvalid (s2)) return FALSE;
1739 if (sRef_isConj (s2))
1741 return (sRef_similar (s1, sRef_getConjA (s2)) ||
1742 sRef_similar (s1, sRef_getConjB (s2)));
1745 if (sRef_isDerived (s2))
1747 return (sRef_includedBy (s1, s2->info->ref));
1753 return ((s2->kind == SK_CVAR)
1754 && (cref_equal (s1->info->cvar, s2->info->cvar)));
1756 return ((s2->kind == SK_PARAM)
1757 && (s1->info->paramno == s2->info->paramno));
1759 if (s2->kind == SK_ARRAYFETCH)
1761 if (sRef_similar (s1->info->arrayfetch->arr,
1762 s2->info->arrayfetch->arr))
1764 if (s1->info->arrayfetch->indknown)
1766 if (s2->info->arrayfetch->indknown)
1768 return (s1->info->arrayfetch->ind == s2->info->arrayfetch->ind);
1783 if (s2->kind == SK_PTR)
1785 if (sRef_similar (s1->info->arrayfetch->arr,
1795 return ((s2->kind == SK_FIELD
1796 && (sRef_similar (s1->info->field->rec,
1797 s2->info->field->rec)
1798 && cstring_equal (s1->info->field->field,
1799 s2->info->field->field))));
1801 if (s2->kind == SK_PTR)
1803 return sRef_similar (s1->info->ref, s2->info->ref);
1807 if (s2->kind == SK_ARRAYFETCH)
1809 if (sRef_similar (s2->info->arrayfetch->arr,
1819 return ((s2->kind == SK_ADR)
1820 && sRef_similar (s1->info->ref, s2->info->ref));
1822 return ((sRef_similar (s1->info->conj->a, s2) ||
1823 (sRef_similar (s1->info->conj->b, s2))));
1825 return (sRef_includedBy (s2, s1->info->ref));
1826 case SK_UNCONSTRAINED:
1827 return (s2->kind == SK_UNCONSTRAINED
1828 && cstring_equal (s1->info->fname, s2->info->fname));
1838 return (s2->kind == SK_SPECIAL
1839 && (s1->info->spec == s2->info->spec));
1842 /*@notreached@*/ DPRINTF (("Fell through for: %s / %s", sRef_unparse (s1), sRef_unparse (s2)));
1847 ** return TRUE iff small can be derived from big.
1849 ** (e.g. x, x.a is includedBy x;
1850 ** x.a is included By x.a;
1854 sRef_includedBy (sRef small, sRef big)
1856 if (small == big) return TRUE;
1857 if (sRef_isInvalid (small) || sRef_isInvalid (big)) return FALSE;
1859 if (sRef_isConj (big))
1860 return (sRef_similar (small, sRef_getConjA (big)) ||
1861 sRef_similar (small, sRef_getConjB (big)));
1863 switch (small->kind)
1867 return (sRef_same (small, big));
1869 if (big->kind == SK_ARRAYFETCH)
1871 if (sRef_same (small->info->arrayfetch->arr, big->info->arrayfetch->arr))
1873 if (small->info->arrayfetch->indknown)
1875 if (big->info->arrayfetch->indknown)
1877 return (small->info->arrayfetch->ind == big->info->arrayfetch->ind);
1890 return (sRef_includedBy (small->info->arrayfetch->arr, big));
1892 if (big->kind == SK_FIELD)
1895 (sRef_same (small->info->field->rec, big->info->field->rec) &&
1896 cstring_equal (small->info->field->field, big->info->field->field));
1900 return (sRef_includedBy (small->info->field->rec, big));
1904 if (big->kind == SK_PTR)
1906 return sRef_same (small->info->ref, big->info->ref);
1910 return (sRef_includedBy (small->info->ref, big));
1914 return ((big->kind == SK_ADR) && sRef_similar (small->info->ref, big->info->ref));
1916 return ((sRef_includedBy (small->info->conj->a, big) ||
1917 (sRef_includedBy (small->info->conj->b, big))));
1919 return (sRef_includedBy (small->info->ref, big));
1920 case SK_UNCONSTRAINED:
1930 switch (small->info->spec)
1932 case SR_NOTHING: return TRUE;
1934 case SR_INTERNAL: return (sRef_isSpecInternalState (big) ||
1935 sRef_isFileStatic (big));
1936 case SR_SYSTEM: return (sRef_isSystemState (big));
1937 case SR_GLOBALMARKER: BADBRANCH;
1944 ** Same is similar to similar, but not quite the same.
1945 ** same and realSame aren't the same, but they are really similar.
1946 ** similarly, same is the same as same. but realSame is
1947 ** not really the same as same, or similar to similar.
1949 ** Similarly to similar, same checks if two sRefs are the same.
1950 ** The similarities end, however, when same compares arrays
1951 ** with unknown indexes. Similar returns false; same returns true.
1953 ** Similarly to similar and same, realSame is the same as same,
1954 ** except they do not behave the same when face with unknown
1955 ** sRefs. Same thinks they are not the same, but realSame thinks
1961 sRef_realSame (sRef s1, sRef s2)
1963 if (s1 == s2) return TRUE;
1964 if (sRef_isInvalid (s1) || sRef_isInvalid (s2)) return FALSE;
1969 return ((s2->kind == SK_CVAR) && (cref_equal (s1->info->cvar, s2->info->cvar)));
1971 return ((s2->kind == SK_PARAM) && (s1->info->paramno == s2->info->paramno));
1973 if (s2->kind == SK_ARRAYFETCH)
1975 if (sRef_realSame (s1->info->arrayfetch->arr, s2->info->arrayfetch->arr))
1977 if (s1->info->arrayfetch->indknown && s2->info->arrayfetch->indknown)
1979 return (s1->info->arrayfetch->ind == s2->info->arrayfetch->ind);
1981 if (!s1->info->arrayfetch->indknown && !s2->info->arrayfetch->indknown)
1990 return ((s2->kind == SK_FIELD &&
1991 (sRef_realSame (s1->info->field->rec, s2->info->field->rec) &&
1992 cstring_equal (s1->info->field->field, s2->info->field->field))));
1994 return ((s2->kind == SK_PTR) && sRef_realSame (s1->info->ref, s2->info->ref));
1996 return ((s2->kind == SK_ADR) && sRef_realSame (s1->info->ref, s2->info->ref));
1998 return ((sRef_realSame (s1->info->conj->a, s2) ||
1999 (sRef_realSame (s1->info->conj->b, s2))));
2001 return ((s2->kind == SK_OBJECT)
2002 && ctype_match (s1->info->object, s2->info->object));
2004 return ((s2->kind == SK_EXTERNAL)
2005 && sRef_realSame (s1->info->ref, s2->info->ref));
2007 return ((s2->kind == SK_SPECIAL) && s1->info->spec == s2->info->spec);
2009 return ((s2->kind == SK_DERIVED) && sRef_realSame (s1->info->ref, s2->info->ref));
2010 case SK_UNCONSTRAINED:
2011 return ((s2->kind == SK_UNCONSTRAINED)
2012 && (cstring_equal (s1->info->fname, s2->info->fname)));
2018 return TRUE; /* changed this! was false */
2024 sRef_sameObject (sRef s1, sRef s2)
2030 ** same is similar to similar, but not quite the same.
2032 ** Similarly to similar, same checks is two sRefs are the same.
2033 ** The similarities end, however, when same compares arrays
2034 ** with unknown indexes. Similar returns false; same returns true.
2038 sRef_same (sRef s1, sRef s2)
2040 if (s1 == s2) return TRUE;
2041 if (sRef_isInvalid (s1) || sRef_isInvalid (s2)) return FALSE;
2046 return ((s2->kind == SK_CVAR) && (cref_equal (s1->info->cvar, s2->info->cvar)));
2048 return ((s2->kind == SK_PARAM) && (s1->info->paramno == s2->info->paramno));
2050 if (s2->kind == SK_ARRAYFETCH)
2052 llassert (s1->info->field->rec != s1);
2053 if (sRef_same (s1->info->arrayfetch->arr, s2->info->arrayfetch->arr))
2055 if (s1->info->arrayfetch->indknown && s2->info->arrayfetch->indknown)
2057 return (s1->info->arrayfetch->ind == s2->info->arrayfetch->ind);
2065 llassert (s1->info->field->rec != s1);
2066 return ((s2->kind == SK_FIELD &&
2067 (sRef_same (s1->info->field->rec, s2->info->field->rec) &&
2068 cstring_equal (s1->info->field->field, s2->info->field->field))));
2072 llassert (s1->info->ref != s1);
2073 return ((s2->kind == SK_PTR) && sRef_same (s1->info->ref, s2->info->ref));
2077 llassert (s1->info->ref != s1);
2078 return ((s2->kind == SK_ADR) && sRef_same (s1->info->ref, s2->info->ref));
2081 llassert (s1->info->conj->a != s1);
2082 llassert (s1->info->conj->b != s1);
2083 return ((sRef_same (s1->info->conj->a, s2)) && /* or or and? */
2084 (sRef_same (s1->info->conj->b, s2)));
2086 return ((s2->kind == SK_SPECIAL) && s1->info->spec == s2->info->spec);
2088 llassert (s1->info->ref != s1);
2089 return ((s2->kind == SK_DERIVED) && sRef_same (s1->info->ref, s2->info->ref));
2091 case SK_UNCONSTRAINED:
2104 ** sort of similar, for use in def/use
2108 sRef_closeEnough (sRef s1, sRef s2)
2110 if (s1 == s2) return TRUE;
2111 if (sRef_isInvalid (s1) || sRef_isInvalid (s2)) return FALSE;
2116 return (((s2->kind == SK_CVAR) &&
2117 (cref_equal (s1->info->cvar, s2->info->cvar))) ||
2118 (s2->kind == SK_UNCONSTRAINED && s1->info->cvar->lexlevel == 0));
2119 case SK_UNCONSTRAINED:
2120 return (s2->kind == SK_UNCONSTRAINED
2121 || ((s2->kind == SK_CVAR) && (s2->info->cvar->lexlevel == 0)));
2123 return ((s2->kind == SK_PARAM)
2124 && (s1->info->paramno == s2->info->paramno));
2126 if (s2->kind == SK_ARRAYFETCH)
2128 if (sRef_closeEnough (s1->info->arrayfetch->arr, s2->info->arrayfetch->arr))
2130 if (s1->info->arrayfetch->indknown && s2->info->arrayfetch->indknown)
2132 return (s1->info->arrayfetch->ind == s2->info->arrayfetch->ind);
2139 return ((s2->kind == SK_FIELD &&
2140 (sRef_closeEnough (s1->info->field->rec, s2->info->field->rec) &&
2141 cstring_equal (s1->info->field->field, s2->info->field->field))));
2143 return ((s2->kind == SK_PTR) && sRef_closeEnough (s1->info->ref, s2->info->ref));
2145 return ((s2->kind == SK_ADR) && sRef_closeEnough (s1->info->ref, s2->info->ref));
2147 return ((s2->kind == SK_DERIVED) && sRef_closeEnough (s1->info->ref, s2->info->ref));
2149 return ((sRef_closeEnough (s1->info->conj->a, s2)) ||
2150 (sRef_closeEnough (s1->info->conj->b, s2)));
2152 return ((s2->kind == SK_SPECIAL) && s1->info->spec == s2->info->spec);
2168 s is an sRef of a formal paramenter in a function call constraint
2169 we trys to return a constraint expression derived from the actual parementer of a function call.
2172 /*@only@*/ constraintExpr sRef_fixConstraintParam (/*@observer@*/ sRef s, /*@observer@*/ /*@temp@*/ exprNodeList args)
2176 if (sRef_isInvalid (s))
2177 llfatalbug((message("Invalid sRef")));
2183 /* s = sRef_saveCopy(s); */ /*@i523@*/
2184 ce = constraintExpr_makeTermsRef (s);
2191 temp = (sRef_makeField (sRef_fixBaseParam (s->info->field->rec, args),
2192 s->info->field->field));
2193 ce = constraintExpr_makeTermsRef (temp);
2199 temp = (sRef_makePointer (sRef_fixBaseParam (s->info->ref, args)));
2200 /* temp = sRef_saveCopy(temp); */ /*@i523@*/
2201 ce = constraintExpr_makeTermsRef (temp);
2208 temp = sRef_saveCopy(s);
2209 temp = sRef_fixBaseParam (temp, args);
2210 ce = constraintExpr_makeTermsRef (temp);
2218 temp = sRef_saveCopy(s);
2219 ce = constraintExpr_makeTermsRef (temp);
2224 llassert(exprNodeList_size (args) > s->info->paramno);
2226 exprNode e = exprNodeList_nth (args, s->info->paramno);
2228 llassert( !(exprNode_isError (e)) );
2229 ce = constraintExpr_makeExprNode (e);
2236 llcontbug (message ("Trying to do fixConstraintParam on nonparam, nonglobal: %q for function with arguments %q",
2237 sRef_unparse (s), exprNodeList_unparse(args)));
2238 temp = sRef_saveCopy(s);
2239 ce = constraintExpr_makeTermsRef (temp);
2251 sRef_fixBaseParam (/*@returned@*/ sRef s, exprNodeList args)
2253 if (sRef_isInvalid (s)) return (sRef_undefined);
2257 case SK_UNCONSTRAINED:
2262 if (exprNodeList_size (args) > s->info->paramno)
2264 exprNode e = exprNodeList_nth (args, s->info->paramno);
2266 if (exprNode_isError (e))
2268 return sRef_makeUnknown ();
2271 return (exprNode_getSref (e));
2275 return sRef_makeUnknown ();
2280 if (s->info->arrayfetch->indknown)
2282 return (sRef_makeArrayFetchKnown
2283 (sRef_fixBaseParam (s->info->arrayfetch->arr, args),
2284 s->info->arrayfetch->ind));
2288 return (sRef_makeArrayFetch
2289 (sRef_fixBaseParam (s->info->arrayfetch->arr, args)));
2292 return (sRef_makeField (sRef_fixBaseParam (s->info->field->rec, args),
2293 s->info->field->field));
2296 return (sRef_makePointer (sRef_fixBaseParam (s->info->ref, args)));
2299 return (sRef_makeAddress (sRef_fixBaseParam (s->info->ref, args)));
2302 return (sRef_makeConj (sRef_fixBaseParam (s->info->conj->a, args),
2303 sRef_fixBaseParam (s->info->conj->b, args)));
2319 sRef_undumpGlobal (char **c)
2329 usymId uid = usymId_fromInt (reader_getInt (c));
2334 reader_checkChar (c, '@');
2335 defstate = sstate_fromInt (reader_getInt (c));
2337 reader_checkChar (c, '@');
2338 nullstate = nstate_fromInt (reader_getInt (c));
2340 ret = sRef_makeGlobal (uid, ctype_unknown, stateInfo_currentLoc ());
2341 sRef_setNullStateN (ret, nullstate);
2342 ret->defstate = defstate;
2347 int i = reader_getInt (c);
2348 speckind sk = speckind_fromInt (i);
2352 case SR_NOTHING: return (sRef_makeNothing ());
2353 case SR_INTERNAL: return (sRef_makeInternalState ());
2354 case SR_SPECSTATE: return (sRef_makeSpecState ());
2355 case SR_SYSTEM: return (sRef_makeSystemState ());
2356 case SR_GLOBALMARKER: BADBRANCH;
2361 return sRef_undefined;
2363 return sRef_makeUnknown ();
2365 return sRef_makeUnknown ();
2367 llfatalerror (message ("sRef_undumpGlobal: bad line: %s",
2368 cstring_fromChars (*c)));
2373 static /*@exposed@*/ sRef sRef_undumpBody (char **c)
2382 return (sRef_makeGlobal (usymId_fromInt (reader_getInt (c)), ctype_unknown, stateInfo_currentLoc ()));
2384 return (sRef_makeParam (reader_getInt (c), ctype_unknown, stateInfo_makeLoc (g_currentloc)));
2386 return (sRef_makeResult (ctype_undump (c)));
2389 if ((**c >= '0' && **c <= '9') || **c == '-')
2391 int i = reader_getInt (c);
2392 sRef arr = sRef_undump (c);
2393 sRef ret = sRef_buildArrayFetchKnown (arr, i);
2399 sRef arr = sRef_undump (c);
2400 sRef ret = sRef_buildArrayFetch (arr);
2407 cstring fname = cstring_undefined;
2412 fname = cstring_appendChar (fname, **c);
2417 ret = sRef_buildField (sRef_undump (c), fname);
2418 cstring_markOwned (fname);
2423 int i = reader_getInt (c);
2424 speckind sk = speckind_fromInt (i);
2428 case SR_NOTHING: return (sRef_makeNothing ());
2429 case SR_INTERNAL: return (sRef_makeInternalState ());
2430 case SR_SPECSTATE: return (sRef_makeSpecState ());
2431 case SR_SYSTEM: return (sRef_makeSystemState ());
2432 case SR_GLOBALMARKER: BADBRANCH;
2438 sRef ptr = sRef_undump (c);
2439 sRef ret = sRef_makePointer (ptr);
2445 sRef adr = sRef_undump (c);
2446 sRef ret = sRef_makeAddress (adr);
2452 return (sRef_makeObject (ctype_undump (c)));
2456 sRef s1 = sRef_undump (c);
2457 sRef s2 = ((*c)++, sRef_undump (c));
2458 sRef ret = sRef_makeConj (s1, s2);
2463 return sRef_undefined;
2465 return sRef_makeUnknown ();
2467 return sRef_makeUnknown ();
2469 llfatalerror (message ("sRef_undump: bad line: %s", cstring_fromChars (*c)));
2474 /*@exposed@*/ sRef sRef_undump (char **c)
2476 sRef res = sRef_undumpBody (c);
2478 if (reader_optCheckChar (c, '='))
2480 multiVal mv = multiVal_undump (c);
2481 sRef_setValue (res, mv);
2482 reader_checkChar (c, '=');
2488 static /*@only@*/ cstring sRef_dumpBody (sRef s)
2490 if (sRef_isInvalid (s))
2492 return (cstring_makeLiteral ("-"));
2499 return (message ("p%d", s->info->paramno));
2501 if (s->info->arrayfetch->indknown)
2503 return (message ("a%d%q", s->info->arrayfetch->ind,
2504 sRef_dump (s->info->arrayfetch->arr)));
2508 return (message ("a%q", sRef_dump (s->info->arrayfetch->arr)));
2511 return (message ("f%s.%q", s->info->field->field,
2512 sRef_dump (s->info->field->rec)));
2514 return (message ("t%q", sRef_dump (s->info->ref)));
2516 return (message ("d%q", sRef_dump (s->info->ref)));
2518 return (message ("o%q", ctype_dump (s->info->object)));
2520 return (message ("s%d", (int) s->info->spec));
2522 return (message ("c%q.%q",
2523 sRef_dump (s->info->conj->a),
2524 sRef_dump (s->info->conj->b)));
2526 if (sRef_isFileOrGlobalScope (s))
2528 return (message ("g%d",
2529 usymtab_convertId (s->info->cvar->index)));
2533 llcontbug (message ("Dumping local variable: %q",
2534 sRef_unparseDebug (s)));
2535 return (cstring_makeLiteral ("u"));
2538 return (cstring_makeLiteral ("u"));
2540 return (message ("r%q", ctype_dump (s->type)));
2546 case SK_UNCONSTRAINED:
2547 llcontbug (message ("sRef_dump: bad kind: %q",
2548 sRef_unparseFull (s)));
2549 return (cstring_makeLiteral ("x"));
2556 /*@only@*/ cstring sRef_dump (sRef s)
2558 cstring res = sRef_dumpBody (s);
2560 if (sRef_hasValue (s))
2562 res = message ("%q=%q=", res, multiVal_dump (sRef_getValue (s)));
2568 cstring sRef_dumpGlobal (sRef s)
2570 llassert (!sRef_hasValue (s));
2572 if (sRef_isInvalid (s))
2574 return (cstring_makeLiteral ("-"));
2581 if (sRef_isFileOrGlobalScope (s))
2583 return (message ("g%d@%d@%d",
2584 usymtab_convertId (s->info->cvar->index),
2586 (int) sRef_getNullState (s)));
2590 llcontbug (message ("Dumping local variable: %q",
2591 sRef_unparseDebug (s)));
2592 return (cstring_makeLiteral ("u"));
2595 return (cstring_makeLiteral ("u"));
2597 return (message ("s%d", (int) s->info->spec));
2599 llcontbug (message ("sRef_dumpGlobal: bad kind: %q",
2600 sRef_unparseFull (s)));
2601 return (cstring_makeLiteral ("x"));
2609 sRef_deriveType (sRef s, uentryList cl)
2611 if (sRef_isInvalid (s)) return ctype_unknown;
2616 return (uentry_getType (usymtab_getRefQuiet (s->info->cvar->lexlevel,
2617 s->info->cvar->index)));
2618 case SK_UNCONSTRAINED:
2619 return (ctype_unknown);
2621 if (s->info->paramno >= 0)
2623 return uentry_getType (uentryList_getN (cl, s->info->paramno));
2627 return ctype_unknown;
2631 ctype ca = sRef_deriveType (s->info->arrayfetch->arr, cl);
2633 if (ctype_isArray (ca))
2635 return (ctype_baseArrayPtr (ca));
2637 else if (ctype_isUnknown (ca))
2643 llcontbuglit ("sRef_deriveType: inconsistent array type");
2649 ctype ct = sRef_deriveType (s->info->field->rec, cl);
2651 if (ctype_isStructorUnion (ct))
2653 uentry ue = uentryList_lookupField (ctype_getFields (ct),
2654 s->info->field->field);
2656 if (uentry_isValid (ue))
2658 return (uentry_getType (ue));
2662 llcontbuglit ("sRef_deriveType: bad field");
2663 return ctype_unknown;
2666 else if (ctype_isUnknown (ct))
2672 llcontbuglit ("sRef_deriveType: inconsistent field type");
2678 ctype ct = sRef_deriveType (s->info->ref, cl);
2680 if (ctype_isUnknown (ct)) return ct;
2681 if (ctype_isPointer (ct)) return (ctype_baseArrayPtr (ct));
2684 llcontbuglit ("sRef_deriveType: inconsistent pointer type");
2690 ctype ct = sRef_deriveType (s->info->ref, cl);
2692 if (ctype_isUnknown (ct)) return ct;
2693 return ctype_makePointer (ct);
2697 return sRef_deriveType (s->info->ref, cl);
2701 return (s->info->object);
2705 return (ctype_makeConj (sRef_deriveType (s->info->conj->a, cl),
2706 sRef_deriveType (s->info->conj->b, cl)));
2718 return ctype_unknown;
2724 sRef_getType (sRef s)
2726 if (sRef_isInvalid (s)) return ctype_unknown;
2732 sRef_unparseOpt (sRef s)
2734 sRef rb = sRef_getRootBase (s);
2736 if (sRef_isMeaningful (rb) && !sRef_isConst (rb))
2738 cstring ret = sRef_unparse (s);
2740 llassertprint (!cstring_equalLit (ret, "?"), ("print: %s", sRef_unparseDebug (s)));
2742 if (!cstring_isEmpty (ret))
2744 return (cstring_appendChar (ret, ' '));
2752 return cstring_undefined;
2756 sRef_unparsePreOpt (sRef s)
2758 sRef rb = sRef_getRootBase (s);
2760 if (sRef_isMeaningful (rb) && !sRef_isConst (rb))
2762 cstring ret = sRef_unparse (s);
2764 llassertprint (!cstring_equalLit (ret, "?"), ("print: %s", sRef_unparseDebug (s)));
2765 return (cstring_prependCharO (' ', ret));
2768 return cstring_undefined;
2772 sRef_unparse (sRef s)
2774 if (sRef_isInvalid (s)) return (cstring_makeLiteral ("?"));
2776 if (context_inFunctionLike ())
2778 return (sRef_unparseWithArgs (s, context_getParams ()));
2782 DPRINTF (("Not in function like: %s", context_unparse ()));
2783 return (sRef_unparseNoArgs (s));
2787 static /*@only@*/ cstring
2788 sRef_unparseWithArgs (sRef s, uentryList args)
2790 if (sRef_isInvalid (s))
2792 return (cstring_makeLiteral ("?"));
2798 return (uentry_getName (usymtab_getRefQuiet (s->info->cvar->lexlevel,
2799 s->info->cvar->index)));
2800 case SK_UNCONSTRAINED:
2801 return (cstring_copy (s->info->fname));
2804 if (s->info->paramno < uentryList_size (args)
2805 && s->info->paramno >= 0)
2807 uentry ue = uentryList_getN (args, s->info->paramno);
2809 if (uentry_isValid (ue))
2810 return uentry_getName (ue);
2813 return (message ("parameter %d", s->info->paramno + 1));
2816 if (s->info->arrayfetch->indknown)
2818 return (message ("%q[%d]", sRef_unparseWithArgs (s->info->arrayfetch->arr, args),
2819 s->info->arrayfetch->ind));
2823 return (message ("%q[]", sRef_unparseWithArgs (s->info->arrayfetch->arr, args)));
2826 if (s->info->field->rec->kind == SK_PTR)
2828 sRef ptr = s->info->field->rec;
2830 return (message ("%q->%s", sRef_unparseWithArgs (ptr->info->ref, args),
2831 s->info->field->field));
2833 return (message ("%q.%s", sRef_unparseWithArgs (s->info->field->rec, args),
2834 s->info->field->field));
2838 sRef ref = sRef_fixConj (s->info->ref);
2839 skind sk = ref->kind;
2844 ret = message ("storage pointed to by %q",
2845 sRef_unparseWithArgs (ref, args));
2847 else if (skind_isSimple (sk) || sk == SK_PTR)
2849 ret = message ("*%q", sRef_unparseWithArgs (ref, args));
2853 ret = message ("*(%q)", sRef_unparseWithArgs (ref, args));
2859 return (message ("&%q", sRef_unparseWithArgs (s->info->ref, args)));
2861 return (cstring_copy (ctype_unparse (s->info->object)));
2863 return (sRef_unparseWithArgs (sRef_getConjA (s), args));
2865 if (cstring_isDefined (s->info->fname))
2867 return (message ("[result of %s]", s->info->fname));
2871 return (cstring_makeLiteral ("<new>"));
2874 return (cstring_makeLiteral ("?"));
2876 return (message ("<derived %q>", sRef_unparse (s->info->ref)));
2878 return (message ("<external %q>", sRef_unparse (s->info->ref)));
2880 return (message ("<type %s>", ctype_unparse (s->type)));
2882 return (message ("<const %s>", ctype_unparse (s->type)));
2884 switch (s->info->spec)
2886 case SR_NOTHING: return cstring_makeLiteral ("nothing");
2887 case SR_INTERNAL: return cstring_makeLiteral ("internal state");
2888 case SR_SPECSTATE: return cstring_makeLiteral ("spec state");
2889 case SR_SYSTEM: return cstring_makeLiteral ("file system state");
2890 case SR_GLOBALMARKER: return cstring_makeLiteral ("<global marker>");
2894 return cstring_makeLiteral ("result");
2897 llbug (message ("Bad sref, kind = %d", (int) s->kind));
2905 sRef_unparseDebug (sRef s)
2907 if (sRef_isInvalid (s))
2909 return (cstring_makeLiteral ("<undef>"));
2915 case SK_UNCONSTRAINED:
2916 return (message ("<unconstrained %s>", s->info->fname));
2921 ce = usymtab_getRefQuiet (s->info->cvar->lexlevel, s->info->cvar->index);
2923 if (uentry_isInvalid (ce))
2925 return (message ("<scope: %d.%d *invalid*>",
2926 s->info->cvar->lexlevel,
2927 s->info->cvar->index));
2931 return (message ("<scope: %d.%d *%q*>",
2932 s->info->cvar->lexlevel,
2933 s->info->cvar->index,
2934 uentry_getName (ce)));
2940 return (message ("<parameter %d>", s->info->paramno + 1));
2943 if (s->info->arrayfetch->indknown)
2945 return (message ("%q[%d]", sRef_unparseDebug (s->info->arrayfetch->arr),
2946 s->info->arrayfetch->ind));
2950 return (message ("%q[]", sRef_unparseDebug (s->info->arrayfetch->arr)));
2953 return (message ("%q.%s", sRef_unparseDebug (s->info->field->rec),
2954 s->info->field->field));
2956 if (sRef_isField (s->info->ref))
2958 sRef fld = s->info->ref;
2960 return (message ("%q->%s", sRef_unparseDebug (fld->info->field->rec),
2961 fld->info->field->field));
2965 return (message ("*(%q)", sRef_unparseDebug (s->info->ref)));
2968 return (message ("&%q", sRef_unparseDebug (s->info->ref)));
2970 return (message ("<object type %s>", ctype_unparse (s->info->object)));
2972 return (message ("%q | %q", sRef_unparseDebug (s->info->conj->a),
2973 sRef_unparseDebug (s->info->conj->b)));
2975 return message ("<new: %s>", s->info->fname);
2977 return (message ("<derived %q>", sRef_unparseDebug (s->info->ref)));
2979 return (message ("<external %q>", sRef_unparseDebug (s->info->ref)));
2981 return (message ("<type %s>", ctype_unparse (s->type)));
2983 if (sRef_hasValue (s))
2985 return (message ("<const %s=%q>", ctype_unparse (s->type), multiVal_unparse (sRef_getValue (s))));
2989 return (message ("<const %s>", ctype_unparse (s->type)));
2992 return (message ("<result %s>", ctype_unparse (s->type)));
2994 return (message ("<spec %s>",
2995 cstring_makeLiteralTemp
2996 (s->info->spec == SR_NOTHING ? "nothing"
2997 : s->info->spec == SR_INTERNAL ? "internalState"
2998 : s->info->spec == SR_SPECSTATE ? "spec state"
2999 : s->info->spec == SR_SYSTEM ? "fileSystem"
3002 return cstring_makeLiteral ("<unknown>");
3008 static /*@only@*/ cstring
3009 sRef_unparseNoArgs (sRef s)
3011 if (sRef_isInvalid (s)) return (cstring_makeLiteral ("?"));
3015 case SK_UNCONSTRAINED:
3016 return (cstring_copy (s->info->fname));
3019 uentry ce = usymtab_getRefQuiet (s->info->cvar->lexlevel,
3020 s->info->cvar->index);
3022 if (uentry_isInvalid (ce))
3024 llcontbug (message ("sRef_unparseNoArgs: bad cvar: %q",
3025 sRef_unparseDebug (s)));
3026 return (sRef_unparseDebug (s));
3030 return (uentry_getName (ce));
3034 if (s->info->arrayfetch->indknown)
3036 return (message ("%q[%d]", sRef_unparseNoArgs (s->info->arrayfetch->arr),
3037 s->info->arrayfetch->ind));
3041 return (message ("%q[]", sRef_unparseNoArgs (s->info->arrayfetch->arr)));
3044 return (message ("%q.%s", sRef_unparseNoArgs (s->info->field->rec),
3045 s->info->field->field));
3048 sRef ref = sRef_fixConj (s->info->ref);
3049 skind sk = ref->kind;
3052 if (skind_isSimple (sk) || sk == SK_PTR)
3054 ret = message ("*%q", sRef_unparseNoArgs (ref));
3058 ret = message ("*(%q)", sRef_unparseNoArgs (ref));
3064 return (message ("&%q", sRef_unparseNoArgs (s->info->ref)));
3066 return (cstring_copy (ctype_unparse (s->info->object)));
3068 return (sRef_unparseNoArgs (s->info->conj->a));
3070 return (message ("result of %s", s->info->fname));
3072 return (message ("<der %q>", sRef_unparseNoArgs (s->info->ref)));
3074 return message ("<ext %q>", sRef_unparseNoArgs (s->info->ref));
3076 return (cstring_makeLiteral
3077 (s->info->spec == SR_NOTHING ? "nothing"
3078 : s->info->spec == SR_INTERNAL ? "internal state"
3079 : s->info->spec == SR_SPECSTATE ? "spec state"
3080 : s->info->spec == SR_SYSTEM ? "file system state"
3083 return cstring_makeLiteral ("result");
3087 return cstring_makeLiteral ("?");
3089 /* llcontbug (message ("sRef_unparseNoArgs: bad case: %q", sRef_unparseDebug (s))); */
3090 return (sRef_unparseDebug (s));
3095 /*@dependent@*/ sRef sRef_makeUnconstrained (cstring fname)
3097 sRef s = sRef_new ();
3099 s->kind = SK_UNCONSTRAINED;
3100 s->info = (sinfo) dmalloc (sizeof (*s->info));
3101 s->info->fname = fname;
3106 cstring sRef_unconstrainedName (sRef s)
3108 llassert (sRef_isUnconstrained (s));
3110 return s->info->fname;
3113 bool sRef_isUnconstrained (sRef s)
3115 return (sRef_isValid(s) && s->kind == SK_UNCONSTRAINED);
3118 static /*@dependent@*/ /*@notnull@*/ sRef
3119 sRef_makeCvarAux (int level, usymId index, ctype ct, /*@only@*/ stateInfo stinfo)
3121 sRef s = sRef_newRef ();
3124 s->info = (sinfo) dmalloc (sizeof (*s->info));
3126 s->info->cvar = (cref) dmalloc (sizeof (*s->info->cvar));
3127 s->info->cvar->lexlevel = level;
3128 s->info->cvar->index = index;
3130 /* for now, all globals are defined; all locals, aren't */
3132 if (level <= fileScope)
3134 s->defstate = SS_UNKNOWN;
3138 ctype rct = ctype_realType (ct);
3140 if (level != paramsScope
3141 && (ctype_isStructorUnion (rct) || ctype_isRealArray (rct)))
3143 s->defstate = SS_ALLOCATED;
3144 s->oaliaskind = s->aliaskind = AK_STACK;
3148 s->defstate = SS_UNDEFINED;
3149 s->oaliaskind = s->aliaskind = AK_LOCAL;
3155 llassert (level >= globScope);
3156 llassert (usymId_isValid (index));
3158 DPRINTF (("Made cvar: [%p] %s", s, sRef_unparseDebug (s)));
3159 llassert (valueTable_isUndefined (s->state));
3160 s->state = context_createValueTable (s, stinfo);
3164 /*@dependent@*/ sRef sRef_makeCvar (int level, usymId index, ctype ct, /*@only@*/ stateInfo stinfo)
3166 return (sRef_makeCvarAux (level, index, ct, stinfo));
3169 int sRef_lexLevel (sRef s)
3171 if (sRef_isValid (s))
3175 conj = sRef_fixConj (s);
3176 s = sRef_getRootBase (conj);
3178 if (sRef_isValid (s) && s->kind == SK_CVAR)
3180 return (s->info->cvar->lexlevel);
3188 sRef_makeGlobal (usymId l, ctype ct, /*@only@*/ stateInfo stinfo)
3190 return (sRef_makeCvar (globScope, l, ct, stinfo));
3194 sRef_setParamNo (sRef s, int l)
3196 llassert (sRef_isValid (s) && s->kind == SK_PARAM);
3197 s->info->paramno = l;
3201 /*@dependent@*/ sRef
3202 sRef_makeParam (int l, ctype ct, stateInfo stinfo)
3204 sRef s = sRef_new ();
3209 s->info = (sinfo) dmalloc (sizeof (*s->info));
3210 s->info->paramno = l;
3212 s->defstate = SS_UNKNOWN;
3213 /* (probably defined, unless its an out parameter) */
3215 llassert (valueTable_isUndefined (s->state));
3216 s->state = context_createValueTable (s, stinfo);
3221 sRef_isIndexKnown (sRef arr)
3225 llassert (sRef_isValid (arr));
3226 arr = sRef_fixConj (arr);
3228 llassert (arr->kind == SK_ARRAYFETCH);
3229 res = arr->info->arrayfetch->indknown;
3234 sRef_getIndex (sRef arr)
3238 llassert (sRef_isValid (arr));
3239 arr = sRef_fixConj (arr);
3241 llassert (arr->kind == SK_ARRAYFETCH);
3243 if (!arr->info->arrayfetch->indknown)
3245 llcontbug (message ("sRef_getIndex: unknown: %q", sRef_unparse (arr)));
3250 result = arr->info->arrayfetch->ind;
3256 static bool sRef_isZerothArrayFetch (/*@notnull@*/ sRef s)
3258 return (s->kind == SK_ARRAYFETCH
3259 && s->info->arrayfetch->indknown
3260 && (s->info->arrayfetch->ind == 0));
3263 /*@exposed@*/ sRef sRef_makeAddress (/*@exposed@*/ sRef t)
3266 if (sRef_isInvalid (t)) return sRef_undefined;
3268 if (sRef_isPointer (t))
3270 return (t->info->ref);
3272 else if (sRef_isZerothArrayFetch (t))
3274 return (t->info->arrayfetch->arr);
3278 sRef s = sRef_newRef ();
3281 s->type = ctype_makePointer (t->type);
3282 s->info = (sinfo) dmalloc (sizeof (*s->info));
3283 s->info->ref = t; /* sRef_copy (t); */ /*@i32@*/
3285 if (t->defstate == SS_UNDEFINED)
3286 /* no! it is allocated even still: && !ctype_isPointer (t->type)) */
3288 s->defstate = SS_ALLOCATED;
3292 s->defstate = t->defstate;
3295 if (t->aliaskind == AK_LOCAL)
3297 if (sRef_isLocalVar (t))
3299 s->aliaskind = AK_STACK;
3303 llassert (valueTable_isUndefined (s->state));
3304 s->state = context_createValueTable (s, stateInfo_makeLoc (g_currentloc));
3309 cstring sRef_getField (sRef s)
3313 llassert (sRef_isValid (s));
3314 s = sRef_fixConj (s);
3316 llassertprint (sRef_isValid (s) && (s->kind == SK_FIELD),
3317 ("s = %s", sRef_unparseDebug (s)));
3319 res = s->info->field->field;
3323 sRef sRef_getBase (sRef s)
3327 if (sRef_isInvalid (s)) return (sRef_undefined);
3329 s = sRef_fixConj (s);
3340 res = s->info->field->rec;
3344 res = s->info->arrayfetch->arr;
3348 res = sRef_undefined; /* shouldn't need it */
3355 ** same as getBase, except returns invalid
3356 ** (and doesn't use adr's)
3360 sRef_getBaseSafe (sRef s)
3364 if (sRef_isInvalid (s)) { return sRef_undefined; }
3366 s = sRef_fixConj (s);
3374 res = s->info->field->rec; break;
3376 res = s->info->arrayfetch->arr;
3379 res = sRef_undefined; break;
3385 /*@constant int MAXBASEDEPTH;@*/
3386 # define MAXBASEDEPTH 25
3388 static /*@exposed@*/ sRef
3389 sRef_getRootBaseAux (sRef s, int depth)
3391 if (sRef_isInvalid (s)) return sRef_undefined;
3393 if (depth > MAXBASEDEPTH)
3396 ("Warning: reference base limit exceeded for %q. "
3397 "This either means there is a variable with at least "
3398 "%d indirections from this reference, or "
3399 "there is a bug in Splint.",
3404 return sRef_undefined;
3411 return (sRef_getRootBaseAux (s->info->ref, depth + 1));
3413 return (sRef_getRootBaseAux (s->info->field->rec, depth + 1));
3415 return (sRef_getRootBaseAux (s->info->arrayfetch->arr, depth + 1));
3417 return (sRef_getRootBaseAux (sRef_fixConj (s), depth + 1));
3423 sRef sRef_getRootBase (sRef s)
3425 return (sRef_getRootBaseAux (s, 0));
3428 static bool sRef_isDeep (sRef s)
3430 if (sRef_isInvalid (s)) return FALSE;
3440 return (sRef_isDeep (sRef_fixConj (s)));
3446 static int sRef_depth (sRef s)
3448 if (sRef_isInvalid (s)) return 0;
3456 return 1 + sRef_depth (s->info->ref);
3458 return 1 + sRef_depth (s->info->field->rec);
3460 return 1 + sRef_depth (s->info->arrayfetch->arr);
3462 return (sRef_depth (sRef_fixConj (s)));
3469 sRef_makeObject (ctype o)
3471 sRef s = sRef_newRef (); /*@i423 same line is bad...@*/
3473 s->kind = SK_OBJECT;
3474 s->info = (sinfo) dmalloc (sizeof (*s->info));
3475 s->info->object = o;
3476 llassert (valueTable_isUndefined (s->state));
3477 s->state = context_createValueTable (s, stateInfo_makeLoc (g_currentloc));
3482 ** This is used to represent storage referenced by a parameter.
3485 sRef sRef_makeExternal (sRef t)
3487 sRef s = sRef_newRef ();
3489 llassert (sRef_isValid (t));
3491 s->kind = SK_EXTERNAL;
3492 s->info = (sinfo) dmalloc (sizeof (*s->info));
3494 s->info->ref = t; /* sRef_copy (t); */ /*@i32 was exposed@*/
3495 llassert (valueTable_isUndefined (s->state));
3496 s->state = context_createValueTable (s, stateInfo_makeLoc (g_currentloc));
3500 /*@dependent@*/ sRef sRef_makeDerived (/*@exposed@*/ sRef t)
3502 if (sRef_isValid (t))
3504 sRef s = sRef_newRef ();
3506 s->kind = SK_DERIVED;
3507 s->info = (sinfo) dmalloc (sizeof (*s->info));
3508 s->info->ref = t; /* sRef_copy (t); */ /*@i32@*/
3511 llassert (valueTable_isUndefined (s->state));
3512 s->state = context_createValueTable (s, stateInfo_makeLoc (g_currentloc));
3517 return sRef_undefined;
3522 ** definitely NOT symmetric:
3524 ** res fills in unknown state information from other
3528 sRef_mergeStateQuiet (sRef res, sRef other)
3530 llassert (sRef_isValid (res));
3531 llassert (sRef_isValid (other));
3533 res->modified = res->modified || other->modified;
3534 res->safe = res->safe && other->safe;
3536 if (res->defstate == SS_UNKNOWN)
3538 res->defstate = other->defstate;
3539 res->definfo = stateInfo_update (res->definfo, other->definfo);
3542 if (res->aliaskind == AK_UNKNOWN ||
3543 (res->aliaskind == AK_LOCAL && alkind_isKnown (other->aliaskind)))
3545 res->aliaskind = other->aliaskind;
3546 res->oaliaskind = other->oaliaskind;
3547 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
3550 if (res->expkind == XO_UNKNOWN)
3552 res->expkind = other->expkind;
3553 res->oexpkind = other->oexpkind;
3554 res->expinfo = stateInfo_update (res->expinfo, other->expinfo);
3557 /* out takes precedence over implicitly defined */
3558 if (res->defstate == SS_DEFINED && other->defstate != SS_UNKNOWN)
3560 res->defstate = other->defstate;
3561 res->definfo = stateInfo_update (res->definfo, other->definfo);
3564 if (sRef_getNullState (other) == NS_ERROR || sRef_getNullState (res) == NS_ERROR)
3566 sRef_setNullState (res, NS_ERROR, fileloc_undefined);
3570 if (sRef_getNullState (other) != NS_UNKNOWN
3571 && (sRef_getNullState (res) == NS_UNKNOWN || sRef_getNullState (res) == NS_NOTNULL
3572 || sRef_getNullState (res) == NS_MNOTNULL))
3574 sRef_updateNullState (res, other);
3580 ** definitely NOT symmetric:
3582 ** res fills in known state information from other
3586 sRef_mergeStateQuietReverse (/*@dependent@*/ sRef res, /*@dependent@*/ sRef other)
3588 bool changed = FALSE;
3590 llassert (sRef_isValid (res));
3591 llassert (sRef_isValid (other));
3592 sRef_checkMutable (res);
3594 if (res->kind != other->kind)
3600 res->kind = other->kind;
3601 res->type = other->type;
3602 res->info = sinfo_fullCopy (other);
3606 if (!ctype_equal (res->type, other->type))
3609 res->type = other->type;
3612 sinfo_update (res, other);
3615 res->modified = res->modified || other->modified;
3616 res->safe = res->safe && other->safe;
3618 if (res->aliaskind != other->aliaskind
3619 && (res->aliaskind == AK_UNKNOWN
3620 || ((res->aliaskind == AK_LOCAL
3621 || (res->aliaskind == AK_REFCOUNTED
3622 && other->aliaskind != AK_LOCAL))
3623 && other->aliaskind != AK_UNKNOWN)))
3626 res->aliaskind = other->aliaskind;
3627 res->oaliaskind = other->oaliaskind;
3628 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
3631 if (other->expkind != XO_UNKNOWN && other->expkind != res->expkind)
3634 res->expkind = other->expkind;
3635 res->expinfo = stateInfo_update (res->expinfo, other->expinfo);
3638 if (other->oexpkind != XO_UNKNOWN)
3640 res->oexpkind = other->oexpkind;
3643 /* out takes precedence over implicitly defined */
3645 if (res->defstate != other->defstate)
3647 if (other->defstate != SS_UNKNOWN)
3649 res->defstate = other->defstate;
3653 if (sRef_getNullState (other) == NS_ERROR || sRef_getNullState (res) == NS_ERROR)
3655 if (sRef_getNullState (res) != NS_ERROR)
3657 sRef_setNullStateN (res, NS_ERROR);
3663 if (sRef_getNullState (other) != NS_UNKNOWN && sRef_getNullState (other) != sRef_getNullState (res))
3666 sRef_updateNullState (res, other);
3672 sRef_clearDerived (res);
3677 sRef_mergeState (sRef res, sRef other, clause cl, fileloc loc)
3679 if (sRef_isValid (res) && sRef_isValid (other))
3681 sRef_mergeStateAux (res, other, cl, FALSE, loc, TRUE);
3685 if (sRef_isInvalid (res))
3687 llbug (message ("sRef_mergeState: invalid res sRef: %q",
3688 sRef_unparseDebug (other)));
3692 llbug (message ("sRef_mergeState: invalid other sRef: %q",
3693 sRef_unparseDebug (res)));
3699 sRef_mergeOptState (sRef res, sRef other, clause cl, fileloc loc)
3701 if (sRef_isValid (res) && sRef_isValid (other))
3703 sRef_mergeStateAux (res, other, cl, TRUE, loc, TRUE);
3707 if (sRef_isInvalid (res))
3709 llbug (message ("sRef_mergeOptState: invalid res sRef: %q",
3710 sRef_unparseDebug (other)));
3714 llbug (message ("sRef_mergeOptState: invalid other sRef: %q",
3715 sRef_unparseDebug (res)));
3721 sRef_mergeStateAux (/*@notnull@*/ sRef res, /*@notnull@*/ sRef other,
3722 clause cl, bool opt, fileloc loc,
3726 llassertfatal (sRef_isValid (res));
3727 llassertfatal (sRef_isValid (other));
3729 DPRINTF (("Merge aux: %s / %s",
3730 bool_unparse (sRef_isDefinitelyNull (res)),
3731 bool_unparse (sRef_isDefinitelyNull (other))));
3733 sRef_checkMutable (res);
3734 sRef_checkMutable (other);
3736 res->modified = res->modified || other->modified;
3738 if (res->kind == other->kind
3739 || (other->kind == SK_UNKNOWN || res->kind == SK_UNKNOWN))
3741 sstate odef = other->defstate;
3742 sstate rdef = res->defstate;
3743 nstate onull = sRef_getNullState (other);
3746 ** yucky stuff to handle
3751 if (other->defstate == SS_DEAD
3752 && ((sRef_isOnly (res) && sRef_definitelyNull (res))
3753 || (res->defstate == SS_UNDEFINED
3754 || res->defstate == SS_UNUSEABLE)))
3756 if (res->defstate == SS_UNDEFINED
3757 || res->defstate == SS_UNUSEABLE)
3759 res->defstate = SS_UNUSEABLE;
3763 res->defstate = SS_DEAD;
3766 res->definfo = stateInfo_update (res->definfo, other->definfo);
3767 sRef_clearDerived (other);
3768 sRef_clearDerived (res);
3770 else if (res->defstate == SS_DEAD
3771 && ((sRef_isOnly (other) && sRef_definitelyNull (other))
3772 || (other->defstate == SS_UNDEFINED
3773 || other->defstate == SS_UNUSEABLE)))
3775 if (other->defstate == SS_UNDEFINED
3776 || other->defstate == SS_UNUSEABLE)
3778 res->defstate = SS_UNUSEABLE;
3782 res->defstate = SS_DEAD;
3785 sRef_clearDerived (other);
3786 sRef_clearDerived (res);
3788 else if (res->defstate == SS_DEFINED
3789 && (other->defstate == SS_ALLOCATED
3790 && sRef_definitelyNull (other)))
3792 other->defstate = SS_DEFINED; /* definitely null! */
3794 else if (other->defstate == SS_DEFINED
3795 && (res->defstate == SS_ALLOCATED && sRef_definitelyNull (res)))
3797 res->defstate = SS_DEFINED;
3798 res->definfo = stateInfo_update (res->definfo, other->definfo);
3805 if (res->defstate == SS_DEAD && other->defstate == SS_DEAD)
3807 sRef_clearDerived (other);
3808 sRef_clearDerived (res);
3812 ** only & dead isn't really an only!
3815 if (alkind_isOnly (other->aliaskind) && other->defstate == SS_DEAD)
3817 other->aliaskind = AK_UNKNOWN;
3820 if (alkind_isOnly (res->aliaskind) && res->defstate == SS_DEAD)
3822 res->aliaskind = AK_UNKNOWN;
3826 ** Dead and dependent -> dead
3829 if (alkind_isDependent (other->aliaskind) && res->defstate == SS_DEAD)
3831 other->aliaskind = AK_UNKNOWN;
3832 other->defstate = SS_DEAD;
3833 sRef_clearDerived (res);
3834 sRef_clearDerived (other);
3837 if (alkind_isDependent (res->aliaskind) && other->defstate == SS_DEAD)
3839 res->aliaskind = AK_UNKNOWN;
3840 res->defstate = SS_DEAD;
3841 sRef_clearDerived (res);
3842 sRef_clearDerived (other);
3846 ** must do alias combine first, since it depends on
3847 ** original values of state and null.
3850 sRef_combineAliasKinds (res, other, cl, loc);
3851 sRef_combineDefState (res, other);
3852 sRef_combineNullState (res, other);
3854 if (rdef == SS_ALLOCATED || rdef == SS_SPECIAL)
3856 if (odef == SS_DEFINED)
3858 if (onull == NS_DEFNULL || onull == NS_CONSTNULL)
3860 res->deriv = sRefSet_copyInto (res->deriv, other->deriv);
3861 DPRINTF (("Copy derivs: %s", sRef_unparseFull (res)));
3864 else if (odef == SS_ALLOCATED || odef == SS_SPECIAL)
3869 if (ctype_isUnion (ctype_realType (sRef_getType (res))))
3871 res->deriv = sRef_mergeUnionDerivs (res->deriv,
3874 DPRINTF (("Copy derivs: %s", sRef_unparseFull (res)));
3878 res->deriv = sRef_mergeDerivs (res->deriv, other->deriv,
3880 DPRINTF (("Copy derivs: %s", sRef_unparseFull (res)));
3888 res->deriv = sRef_mergeDerivs (res->deriv, other->deriv,
3890 DPRINTF (("Copy derivs: %s", sRef_unparseFull (res)));
3900 if (rdef == SS_PDEFINED
3901 || (rdef == SS_DEFINED && odef == SS_PDEFINED))
3905 res->deriv = sRef_mergePdefinedDerivs (res->deriv, other->deriv,
3907 DPRINTF (("Copy derivs: %s", sRef_unparseFull (res)));
3912 if ((rdef == SS_DEFINED || rdef == SS_UNKNOWN)
3913 && res->defstate == SS_ALLOCATED)
3915 res->deriv = sRefSet_copyInto (res->deriv, other->deriv);
3921 res->deriv = sRef_mergeDerivs (res->deriv, other->deriv,
3923 DPRINTF (("Copy derivs: %s", sRef_unparseFull (res)));
3930 sRef_combineExKinds (res, other);
3934 if (res->kind == SK_ARRAYFETCH && other->kind == SK_PTR)
3936 sRef nother = sRef_buildArrayFetchKnown (sRef_getBase (other), 0);
3938 sRef_copyState (nother, other);
3939 sRef_mergeStateAux (res, nother, cl, opt, loc, doDerivs);
3941 else if (res->kind == SK_PTR && other->kind == SK_ARRAYFETCH)
3943 sRef nother = sRef_buildPointer (sRef_getBase (other));
3945 if (sRef_isValid (nother))
3947 sRef_copyState (nother, other);
3948 sRef_mergeStateAux (res, nother, cl, opt, loc, doDerivs);
3953 llcontbug (message ("merge conj: %q / %q", sRef_unparseFull (res),
3954 sRef_unparseFull (other)));
3960 ** Merge value table states
3967 ** This doesn't do anything. And its broken too...
3970 valueTable_elements (res->state, key, sv)
3972 stateValue os = valueTable_lookup (other->state, key);
3973 /*@unused@*/ int val;
3974 /*@unused@*/ char *msg;
3976 llassert (stateValue_isDefined (os));
3978 DPRINTF (("Merge state: %s / %s",
3979 cstring_toCharsSafe (stateValue_unparse (sv)),
3980 cstring_toCharsSafe (stateValue_unparse (os))));
3982 val = valueMatix_lookup (key,
3983 stateValue_getValue (os),
3984 stateValue_getValue (sv),
3986 DPRINTF (("Val: %d / %s", val, msg));
3988 } end_valueTable_elements ;
3994 sRef_mergeUnionDerivs (/*@only@*/ sRefSet res,
3995 /*@exposed@*/ sRefSet other, bool opt,
3996 clause cl, fileloc loc)
3998 if (sRefSet_isEmpty (res))
4000 return sRefSet_copyInto (res, other);
4004 sRefSet_allElements (other, el)
4006 if (sRef_isValid (el))
4008 sRef e2 = sRefSet_lookupMember (other, el);
4010 if (sRef_isValid (e2))
4012 sRef_mergeStateAux (el, e2, cl, opt, loc, FALSE);
4016 res = sRefSet_insert (res, el);
4019 } end_sRefSet_allElements ;
4025 static /*@only@*/ sRefSet
4026 sRef_mergeDerivs (/*@only@*/ sRefSet res, sRefSet other,
4027 bool opt, clause cl, fileloc loc)
4029 sRefSet ret = sRefSet_new ();
4031 sRefSet_allElements (res, el)
4033 if (sRef_isValid (el))
4035 sRef e2 = sRefSet_lookupMember (other, el);
4037 if (sRef_isValid (e2))
4039 if (el->defstate == SS_ALLOCATED &&
4040 e2->defstate == SS_PDEFINED)
4042 e2->defstate = SS_ALLOCATED;
4044 else if (e2->defstate == SS_ALLOCATED &&
4045 el->defstate == SS_PDEFINED)
4047 el->defstate = SS_ALLOCATED;
4048 sRef_clearDerived (el);
4050 else if ((el->defstate == SS_DEAD || sRef_isKept (el)) &&
4051 (e2->defstate == SS_DEFINED && !sRef_isKept (e2)))
4054 if (checkDeadState (el, TRUE, loc))
4056 if (sRef_isThroughArrayFetch (el))
4058 sRef_maybeKill (el, loc);
4059 sRef_maybeKill (e2, loc);
4063 else if ((e2->defstate == SS_DEAD || sRef_isKept (e2)) &&
4064 (el->defstate == SS_DEFINED && !sRef_isKept (el)))
4067 if (checkDeadState (e2, FALSE, loc))
4069 if (sRef_isThroughArrayFetch (el))
4071 sRef_maybeKill (el, loc);
4072 sRef_maybeKill (e2, loc);
4076 else if (el->defstate == SS_DEFINED &&
4077 e2->defstate == SS_PDEFINED)
4079 DPRINTF (("set pdefined: %s", sRef_unparseFull (el)));
4080 el->defstate = SS_PDEFINED;
4082 else if (e2->defstate == SS_DEFINED &&
4083 el->defstate == SS_PDEFINED)
4085 DPRINTF (("set pdefined: %s", sRef_unparseFull (e2)));
4086 e2->defstate = SS_PDEFINED;
4093 if (ctype_isUnion (ctype_realType (sRef_getType (el))))
4095 el->deriv = sRef_mergeUnionDerivs (el->deriv, e2->deriv,
4100 el->deriv = sRef_mergeDerivs (el->deriv, e2->deriv, opt, cl, loc);
4103 if (sRef_equivalent (el, e2))
4105 ret = sRefSet_insert (ret, el);
4109 sRef sr = sRef_leastCommon (el, e2);
4111 if (sRef_isValid (sr))
4113 ret = sRefSet_insert (ret, sr);
4121 (void) sRefSet_delete (other, e2);
4123 else /* not defined */
4125 (void) checkDeadState (el, TRUE, loc);
4128 } end_sRefSet_allElements;
4130 sRefSet_allElements (other, el)
4132 if (sRef_isValid (el))
4134 (void) checkDeadState (el, FALSE, loc);
4136 } end_sRefSet_allElements;
4143 ** Returns TRUE is there is an error.
4146 static bool checkDeadState (/*@notnull@*/ sRef el, bool tbranch, fileloc loc)
4149 ** usymtab_isGuarded --- the utab should still be in the
4150 ** state of the alternate branch.
4152 ** tbranch TRUE means el is released in the last branch, e.g.
4153 ** if (x != NULL) { ; } else { sfree (x); }
4154 ** so, if x is null in the other branch no error is reported.
4156 ** tbranch FALSE means this is the other branch:
4157 ** if (x != NULL) { sfree (x); } else { ; }
4158 ** so, if x is null in this branch there is no error.
4162 if ((sRef_isDead (el) || sRef_isKept (el))
4163 && !sRef_isDeepUnionField (el) && !sRef_isThroughArrayFetch (el))
4168 if (usymtab_isDefinitelyNullDeep (el))
4175 if (usymtab_isAltDefinitelyNullDeep (el))
4183 message ("Storage %q is %q in one path, but live in another.",
4185 cstring_makeLiteral (sRef_isKept (el)
4186 ? "kept" : "released")),
4189 if (sRef_isKept (el))
4191 sRef_showAliasInfo (el);
4195 sRef_showStateInfo (el);
4198 /* prevent further errors */
4199 el->defstate = SS_UNKNOWN;
4200 sRef_setAliasKind (el, AK_ERROR, fileloc_undefined);
4210 checkDerivDeadState (/*@notnull@*/ sRef el, bool tbranch, fileloc loc)
4213 if (checkDeadState (el, tbranch, loc))
4215 sRefSet_allElements (el->deriv, t)
4217 if (sRef_isValid (t))
4219 checkDerivDeadState (t, tbranch, loc);
4221 } end_sRefSet_allElements;
4226 sRef_mergePdefinedDerivs (sRefSet res, sRefSet other, bool opt,
4227 clause cl, fileloc loc)
4229 sRefSet ret = sRefSet_new ();
4231 sRefSet_allElements (res, el)
4233 if (sRef_isValid (el))
4235 sRef e2 = sRefSet_lookupMember (other, el);
4237 if (sRef_isValid (e2))
4239 if (sRef_isAllocated (el) && !sRef_isAllocated (e2))
4243 else if (sRef_isAllocated (e2) && !sRef_isAllocated (el))
4245 el->deriv = sRefSet_copyInto (el->deriv, e2->deriv);
4249 el->deriv = sRef_mergePdefinedDerivs (el->deriv, e2->deriv,
4253 sRef_mergeStateAux (el, e2, cl, opt, loc, FALSE);
4255 ret = sRefSet_insert (ret, el);
4256 (void) sRefSet_delete (other, e2);
4262 checkDerivDeadState (el, (cl == FALSECLAUSE), loc);
4265 ret = sRefSet_insert (ret, el);
4268 } end_sRefSet_allElements;
4270 sRefSet_allElements (other, el)
4272 if (sRef_isValid (el))
4274 if (!sRefSet_member (ret, el))
4276 /* was cl == FALSECLAUSE */
4277 checkDerivDeadState (el, FALSE, loc);
4278 ret = sRefSet_insert (ret, el);
4283 ** it's okay --- member is a different equality test
4287 } end_sRefSet_allElements;
4293 sRef sRef_makeConj (/*@exposed@*/ /*@returned@*/ sRef a, /*@exposed@*/ sRef b)
4295 llassert (sRef_isValid (a));
4296 llassert (sRef_isValid (b));
4298 if (!sRef_equivalent (a, b))
4300 sRef s = sRef_newRef ();
4303 s->info = (sinfo) dmalloc (sizeof (*s->info));
4304 s->info->conj = (cjinfo) dmalloc (sizeof (*s->info->conj));
4305 s->info->conj->a = a; /* sRef_copy (a) */ /*@i32*/ ;
4306 s->info->conj->b = b; /* sRef_copy (b);*/ /*@i32@*/ ;
4308 if (ctype_equal (a->type, b->type)) s->type = a->type;
4309 else s->type = ctype_makeConj (a->type, b->type);
4311 if (a->defstate == b->defstate)
4313 s->defstate = a->defstate;
4317 s->defstate = SS_UNKNOWN;
4320 sRef_setNullStateN (s, NS_UNKNOWN);
4322 s->safe = a->safe && b->safe;
4323 s->aliaskind = alkind_resolve (a->aliaskind, b->aliaskind);
4325 llassert (valueTable_isUndefined (s->state));
4326 s->state = context_createValueTable (s, stateInfo_makeLoc (g_currentloc));
4331 /*@-exposetrans@*/ return a; /*@=exposetrans@*/
4335 /*@dependent@*/ sRef
4338 sRef s = sRef_new ();
4340 s->kind = SK_UNKNOWN;
4344 static /*@owned@*/ sRef
4345 sRef_makeSpecial (speckind sk) /*@*/
4347 sRef s = sRef_new ();
4349 s->kind = SK_SPECIAL;
4350 s->info = (sinfo) dmalloc (sizeof (*s->info));
4352 /*@-dependenttrans@*/
4354 /*@=dependenttrans@*/
4357 static /*@owned@*/ sRef srnothing = sRef_undefined;
4358 static /*@owned@*/ sRef srinternal = sRef_undefined;
4359 static /*@owned@*/ sRef srsystem = sRef_undefined;
4360 static /*@owned@*/ sRef srspec = sRef_undefined;
4362 /*@dependent@*/ sRef
4363 sRef_makeNothing (void)
4365 if (sRef_isInvalid (srnothing))
4367 srnothing = sRef_makeSpecial (SR_NOTHING);
4374 sRef_makeInternalState (void)
4376 if (sRef_isInvalid (srinternal))
4378 srinternal = sRef_makeSpecial (SR_INTERNAL);
4385 sRef_makeSpecState (void)
4387 if (sRef_isInvalid (srspec))
4389 srspec = sRef_makeSpecial (SR_SPECSTATE);
4396 sRef_makeSystemState (void)
4398 if (sRef_isInvalid (srsystem))
4400 srsystem = sRef_makeSpecial (SR_SYSTEM);
4407 sRef_makeGlobalMarker (void)
4409 sRef s = sRef_makeSpecial (SR_GLOBALMARKER);
4410 llassert (valueTable_isUndefined (s->state));
4411 s->state = context_createGlobalMarkerValueTable (stateInfo_undefined);
4416 sRef_makeResult (ctype c)
4418 sRef s = sRef_newRef ();
4420 s->kind = SK_RESULT;
4422 s->defstate = SS_UNKNOWN;
4423 s->aliaskind = AK_UNKNOWN;
4424 sRef_setNullStateN (s, NS_UNKNOWN);
4425 llassert (valueTable_isUndefined (s->state));
4426 s->state = context_createValueTable (s, stateInfo_makeLoc (g_currentloc));
4428 DPRINTF (("Result: [%p] %s", s, sRef_unparseFull (s)));
4434 sRef_isNothing (sRef s)
4436 return (sRef_isKindSpecial (s) && s->info->spec == SR_NOTHING);
4440 sRef_isInternalState (sRef s)
4442 return (sRef_isKindSpecial (s) && s->info->spec == SR_INTERNAL);
4446 sRef_isSpecInternalState (sRef s)
4448 return (sRef_isKindSpecial (s)
4449 && (s->info->spec == SR_INTERNAL || s->info->spec == SR_SPECSTATE));
4453 sRef_isSpecState (sRef s)
4455 return (sRef_isKindSpecial (s) && s->info->spec == SR_SPECSTATE);
4459 sRef_isResult (sRef s)
4461 return (sRef_isValid (s) && s->kind == SK_RESULT);
4465 sRef_isSystemState (sRef s)
4467 return (sRef_isKindSpecial (s) && s->info->spec == SR_SYSTEM);
4471 sRef_isGlobalMarker (sRef s)
4473 return (sRef_isKindSpecial (s) && s->info->spec == SR_GLOBALMARKER);
4477 sRef_getScopeIndex (sRef s)
4479 llassert (sRef_isValid (s));
4480 llassert (sRef_isCvar (s));
4482 return (s->info->cvar->index);
4486 sRef_makeSafe (sRef s)
4488 if (sRef_isValid (s))
4495 sRef_makeUnsafe (sRef s)
4497 if (sRef_isValid (s))
4504 ** memory state operations
4507 /*@only@*/ cstring sRef_unparseFull (sRef s)
4509 if (sRef_isInvalid (s)) return (cstring_undefined);
4511 return (message ("[%d] %q - %q [%s] { %q } < %q >",
4513 sRef_unparseDebug (s),
4514 sRef_unparseState (s),
4515 exkind_unparse (s->oexpkind),
4516 sRefSet_unparseDebug (s->deriv),
4517 valueTable_unparse (s->state)));
4520 /*@unused@*/ cstring sRef_unparseDeep (sRef s)
4522 cstring st = cstring_undefined;
4524 st = message ("%q:", sRef_unparseFull (s));
4526 if (sRef_isValid (s))
4528 sRefSet_allElements (s->deriv, el)
4530 st = message("%q\n%q", st, sRef_unparseDeep (el));
4531 } end_sRefSet_allElements ;
4537 /*@only@*/ cstring sRef_unparseState (sRef s)
4539 if (sRef_isConj (s))
4541 return (message ("%q | %q",
4542 sRef_unparseState (s->info->conj->a),
4543 sRef_unparseState (s->info->conj->b)));
4546 if (sRef_isInvalid (s))
4548 return (cstring_makeLiteral ("<invalid>"));
4551 return (message ("%s.%s.%s.%s",
4552 alkind_unparse (s->aliaskind),
4553 nstate_unparse (sRef_getNullState (s)),
4554 exkind_unparse (s->expkind),
4555 sstate_unparse (s->defstate)));
4558 bool sRef_isNotUndefined (sRef s)
4560 return (sRef_isInvalid (s)
4561 || (s->defstate != SS_UNDEFINED
4562 && s->defstate != SS_UNUSEABLE
4563 && s->defstate != SS_DEAD));
4566 ynm sRef_isWriteable (sRef s)
4568 if (sRef_isInvalid (s)) return MAYBE;
4570 if (sRef_isConj (s) && s->defstate == SS_UNKNOWN)
4572 if (ynm_toBoolStrict (sRef_isWriteable (sRef_getConjA (s))))
4574 if (ynm_toBoolStrict (sRef_isWriteable (sRef_getConjB (s))))
4582 if (ynm_toBoolStrict (sRef_isWriteable (sRef_getConjB (s))))
4590 return (ynm_fromBool (s->defstate != SS_UNUSEABLE));
4593 bool sRef_hasNoStorage (sRef s)
4595 return (!sRef_isAllocatedStorage (s) || sRef_isDefinitelyNull (s));
4598 bool sRef_isStrictReadable (sRef s)
4600 return (ynm_toBoolStrict (sRef_isValidLvalue (s)));
4604 ** Is this what is does?
4605 ** Returns YES if s can be used as an rvalue,
4606 ** MAYBE if its not clear
4607 ** NO if s cannot be safely used as an rvalue.
4610 ynm sRef_isValidLvalue (sRef s)
4614 if (sRef_isInvalid (s)) return YES;
4618 if (sRef_isConj (s) && s->defstate == SS_UNKNOWN)
4620 if (ynm_toBoolStrict (sRef_isValidLvalue (sRef_getConjA (s))))
4622 if (ynm_toBoolStrict (sRef_isValidLvalue (sRef_getConjB (s))))
4630 if (ynm_toBoolStrict (sRef_isValidLvalue (sRef_getConjB (s))))
4637 else if (ss == SS_HOFFA)
4639 if (context_getFlag (FLG_STRICTUSERELEASED))
4650 return (ynm_fromBool (ss == SS_DEFINED
4653 || ss == SS_PDEFINED
4656 || ss == SS_ALLOCATED
4657 || ss == SS_KILLED /* evans 2001-05-26: added this for killed globals */
4658 || ss == SS_UNKNOWN));
4662 static /*@exposed@*/ sRef whatUndefined (/*@exposed@*/ sRef fref, int depth)
4667 if (depth > MAXDEPTH)
4670 ("Warning: check definition limit exceeded, checking %q. "
4671 "This either means there is a variable with at least "
4672 "%d indirections apparent in the program text, or "
4673 "there is a bug in Splint.",
4674 sRef_unparse (fref),
4678 return sRef_undefined;
4681 if (!sRef_isKnown (fref) || sRef_isAnyDefined (fref))
4683 return sRef_undefined;
4686 if (sRef_isUnuseable (fref) || sRef_isStateUndefined (fref))
4691 ct = ctype_realType (sRef_getType (fref));
4693 if (ctype_isUnknown (ct))
4695 return sRef_undefined;
4697 else if (ctype_isPointer (ct) || ctype_isArray (ct))
4699 if (sRef_isStateUnknown (fref))
4701 return sRef_undefined;
4705 sRef fptr = sRef_constructDeref (fref);
4707 return (whatUndefined (fptr, depth + 1));
4710 else if (ctype_isStruct (ct))
4712 bool hasOneDefined = FALSE;
4714 if (sRef_isStateUnknown (fref))
4719 if (sRef_isPdefined (fref) || sRef_isAnyDefined (fref))
4721 sRefSet_realElements (sRef_derivedFields (fref), sr)
4723 hasOneDefined = TRUE;
4725 if (sRef_isField (sr))
4727 cstring fieldname = sRef_getField (sr);
4728 sRef fldref = sRef_makeField (fref, fieldname);
4729 bool shouldCheck = !sRef_isRecursiveField (fldref);
4733 sRef wdef = whatUndefined (fldref, depth + 1);
4735 if (sRef_isValid (wdef))
4741 } end_sRefSet_realElements;
4743 else if (sRef_isAllocated (fref))
4746 ** for structures, each field must be completely defined
4749 uentryList fields = ctype_getFields (ct);
4751 uentryList_elements (fields, ue)
4753 cstring name = uentry_getRealName (ue);
4754 sRef ffield = sRef_makeField (fref, name);
4755 bool shouldCheck = !sRef_isRecursiveField (ffield);
4757 if (sRef_isRelDef (uentry_getSref (ue)))
4765 sRef wdef = whatUndefined (ffield, depth + 1);
4767 if (sRef_isInvalid (wdef))
4773 } end_uentryList_elements;
4780 else if (ctype_isUnion (ct))
4789 return sRef_undefined;
4792 static bool checkDefined (/*@temp@*/ sRef sr)
4794 /*@-temptrans@*/ /* the result from whatUndefined is lost */
4795 return (sRef_isInvalid (whatUndefined (sr, 0)));
4799 bool sRef_isReallyDefined (sRef s)
4801 if (sRef_isValid (s))
4803 if (sRef_isAnyDefined (s))
4809 if (sRef_isAllocated (s) || sRef_isPdefined (s))
4811 return checkDefined (s);
4825 void sRef_showNotReallyDefined (sRef s)
4827 if (sRef_isValid (s))
4829 if (sRef_isAnyDefined (s))
4835 if (sRef_isAllocated (s) || sRef_isPdefined (s))
4837 /*@-temptrans@*/ /* the result of whatUndefined is lost */
4838 sRef ref = whatUndefined (s, 0);
4840 llassert (sRef_isValid (ref));
4845 (message ("This sub-reference is %s: %q",
4846 sstate_unparse (sRef_getDefState (ref)),
4847 sRef_unparse (ref)));
4862 sstate sRef_getDefState (sRef s)
4864 if (sRef_isInvalid (s)) return (SS_UNKNOWN);
4865 return (s->defstate);
4868 void sRef_setDefState (sRef s, sstate defstate, fileloc loc)
4870 sRef_checkMutable (s);
4871 sRef_setStateAux (s, defstate, loc);
4874 static void sRef_clearAliasStateAux (sRef s, fileloc loc)
4876 sRef_checkMutable (s);
4877 sRef_setAliasKind (s, AK_ERROR, loc);
4880 void sRef_clearAliasState (sRef s, fileloc loc)
4882 sRef_checkMutable (s);
4883 sRef_aliasSetComplete (sRef_clearAliasStateAux, s, loc);
4886 void sRef_setAliasKindComplete (sRef s, alkind kind, fileloc loc)
4888 sRef_checkMutable (s);
4889 sRef_aliasSetCompleteAlkParam (sRef_setAliasKind, s, kind, loc);
4892 void sRef_setAliasKind (sRef s, alkind kind, fileloc loc)
4894 sRef_checkMutable (s);
4896 if (sRef_isValid (s))
4898 sRef_clearDerived (s);
4900 if ((kind != s->aliaskind && kind != s->oaliaskind)
4901 && fileloc_isDefined (loc))
4903 s->aliasinfo = stateInfo_updateLoc (s->aliasinfo, loc);
4906 s->aliaskind = kind;
4910 void sRef_setOrigAliasKind (sRef s, alkind kind)
4912 sRef_checkMutable (s);
4914 if (sRef_isValid (s))
4916 s->oaliaskind = kind;
4920 exkind sRef_getExKind (sRef s)
4922 if (sRef_isValid (s))
4924 return (s->expkind);
4932 exkind sRef_getOrigExKind (sRef s)
4934 if (sRef_isValid (s))
4936 return (s->oexpkind);
4944 static void sRef_clearExKindAux (sRef s, fileloc loc)
4946 sRef_checkMutable (s);
4947 sRef_setExKind (s, XO_UNKNOWN, loc);
4950 void sRef_setObserver (sRef s, fileloc loc)
4952 sRef_checkMutable (s);
4953 sRef_setExKind (s, XO_OBSERVER, loc);
4956 void sRef_setExposed (sRef s, fileloc loc)
4958 sRef_checkMutable (s);
4959 sRef_setExKind (s, XO_EXPOSED, loc);
4962 void sRef_clearExKindComplete (sRef s, fileloc loc)
4964 (void) sRef_aliasSetComplete (sRef_clearExKindAux, s, loc);
4967 void sRef_setExKind (sRef s, exkind exp, fileloc loc)
4969 sRef_checkMutable (s);
4971 if (sRef_isValid (s))
4973 if (s->expkind != exp)
4975 s->expinfo = stateInfo_updateLoc (s->expinfo, loc);
4983 ** s1->derived = s2->derived
4986 static void sRef_copyRealDerived (sRef s1, sRef s2)
4988 DPRINTF (("Copy real: %s / %s", sRef_unparse (s1), sRef_unparse (s2)));
4989 sRef_checkMutable (s1);
4991 if (sRef_isValid (s1) && sRef_isValid (s2))
4993 sRef sb = sRef_getRootBase (s1);
4995 sRefSet_clear (s1->deriv);
4997 sRefSet_allElements (s2->deriv, el)
4999 if (sRef_isValid (el))
5001 sRef rb = sRef_getRootBase (el);
5003 if (!sRef_same (rb, sb))
5005 sRef fb = sRef_fixDirectBase (el, s1);
5007 if (sRef_isValid (fb))
5009 sRef_copyRealDerived (fb, el);
5010 sRef_addDeriv (s1, fb);
5015 sRef_addDeriv (s1, el);
5018 } end_sRefSet_allElements ;
5023 void sRef_copyRealDerivedComplete (sRef s1, sRef s2)
5025 sRef_innerAliasSetCompleteParam (sRef_copyRealDerived, s1, s2);
5028 void sRef_setUndefined (sRef s, fileloc loc)
5030 sRef_checkMutable (s);
5032 if (sRef_isValid (s))
5034 s->defstate = SS_UNDEFINED;
5036 if (fileloc_isDefined (loc))
5038 s->definfo = stateInfo_updateLoc (s->definfo, loc);
5041 sRef_clearDerived (s);
5045 static void sRef_setDefinedAux (sRef s, fileloc loc, bool clear)
5047 sRef_checkMutable (s);
5048 if (sRef_isInvalid (s)) return;
5050 DPRINTF (("Set defined: %s", sRef_unparseFull (s)));
5052 if (s->defstate != SS_DEFINED && fileloc_isDefined (loc))
5054 s->definfo = stateInfo_updateLoc (s->definfo, loc);
5057 s->defstate = SS_DEFINED;
5059 DPRINTF (("Set defined: %s", sRef_unparseFull (s)));
5061 /* e.g., if x is allocated, *x = 3 defines x */
5063 if (s->kind == SK_PTR)
5065 sRef p = s->info->ref;
5068 if (p->defstate == SS_ALLOCATED
5069 || p->defstate == SS_SPECIAL) /* evans 2001-07-12: shouldn't need this */
5071 sRef_setDefinedAux (p, loc, clear);
5075 ** Defines a[0] also:
5078 arr = sRef_findDerivedArrayFetch (p, FALSE, 0, FALSE);
5080 if (sRef_isValid (arr))
5082 sRef_setDefinedAux (arr, loc, clear);
5085 else if (s->kind == SK_ARRAYFETCH)
5087 if (!s->info->arrayfetch->indknown
5088 || (s->info->arrayfetch->ind == 0))
5090 sRef p = s->info->arrayfetch->arr;
5091 sRef ptr = sRef_constructPointer (p);
5093 if (sRef_isValid (ptr))
5095 if (ptr->defstate == SS_ALLOCATED
5096 || ptr->defstate == SS_UNDEFINED
5097 || ptr->defstate == SS_SPECIAL) /* evans 2001-07-12: shouldn't need this */
5099 sRef_setDefinedAux (ptr, loc, clear);
5103 if (p->defstate == SS_RELDEF)
5107 else if (p->defstate == SS_ALLOCATED || p->defstate == SS_PDEFINED
5108 || p->defstate == SS_SPECIAL) /* evans 2001-07-12: shouldn't need this */
5110 p->defstate = SS_DEFINED;
5117 else if (s->kind == SK_FIELD)
5119 sRef parent = s->info->field->rec;
5121 if (sRef_isValid (parent))
5123 if (ctype_isUnion (ctype_realType (parent->type)))
5126 ** Should not clear derived from here.
5129 sRef_setDefinedNoClear (parent, loc);
5133 ; /* Nothing to do for structures. */
5145 sRef_clearDerived (s);
5149 /* evans 2001-07-12: need to define the derived references */
5150 sRefSet_elements (s->deriv, el)
5152 el->defstate = SS_DEFINED;
5153 } end_sRefSet_elements ;
5156 DPRINTF (("Set defined: %s", sRef_unparseFull (s)));
5159 static void sRef_setPartialDefined (sRef s, fileloc loc)
5161 sRef_checkMutable (s);
5163 if (!sRef_isPartial (s))
5165 sRef_setDefined (s, loc);
5169 void sRef_setPartialDefinedComplete (sRef s, fileloc loc)
5171 sRef_innerAliasSetComplete (sRef_setPartialDefined, s, loc);
5174 void sRef_setDefinedComplete (sRef s, fileloc loc)
5176 DPRINTF (("Set defined complete: %s", sRef_unparseFull (s)));
5177 sRef_innerAliasSetComplete (sRef_setDefined, s, loc);
5180 void sRef_setDefined (sRef s, fileloc loc)
5182 sRef_checkMutable (s);
5183 sRef_setDefinedAux (s, loc, TRUE);
5186 static void sRef_setDefinedNoClear (sRef s, fileloc loc)
5188 sRef_checkMutable (s);
5189 DPRINTF (("Defining: %s", sRef_unparseFull (s)));
5190 sRef_setDefinedAux (s, loc, FALSE);
5191 DPRINTF (("==> %s", sRef_unparseFull (s)));
5194 void sRef_setDefinedNCComplete (sRef s, fileloc loc)
5196 sRef_checkMutable (s);
5197 DPRINTF (("Set Defined Complete: %s", sRef_unparseFull (s)));
5198 sRef_innerAliasSetComplete (sRef_setDefinedNoClear, s, loc);
5199 DPRINTF (("==> %s", sRef_unparseFull (s)));
5202 static bool sRef_isDeepUnionField (sRef s)
5204 return (sRef_deepPred (sRef_isUnionField, s));
5207 bool sRef_isUnionField (sRef s)
5209 if (sRef_isValid (s) && s->kind == SK_FIELD)
5212 ** defining one field of a union defines the union
5215 sRef base = s->info->field->rec;
5217 if (sRef_isValid (base))
5219 return (ctype_isUnion (ctype_realType (base->type)));
5226 void sRef_setPdefined (sRef s, fileloc loc)
5228 sRef_checkMutable (s);
5229 if (sRef_isValid (s) && !sRef_isPartial (s))
5231 sRef base = sRef_getBaseSafe (s);
5233 if (s->defstate == SS_ALLOCATED)
5238 if (s->defstate != SS_PDEFINED && fileloc_isDefined (loc))
5240 s->definfo = stateInfo_updateLoc (s->definfo, loc);
5243 DPRINTF (("set pdefined: %s", sRef_unparseFull (s)));
5244 s->defstate = SS_PDEFINED;
5246 /* e.g., if x is allocated, *x = 3 defines x */
5248 while (sRef_isValid (base) && sRef_isKnown (base))
5250 if (base->defstate == SS_DEFINED)
5254 base->defstate = SS_PDEFINED;
5255 nb = sRef_getBaseSafe (base);
5266 static void sRef_setStateAux (sRef s, sstate ss, fileloc loc)
5268 sRef_checkMutable (s);
5270 if (sRef_isValid (s))
5272 /* if (s->defstate == SS_RELDEF) return; */
5274 if (s->defstate != ss && fileloc_isDefined (loc))
5276 s->definfo = stateInfo_updateLoc (s->definfo, loc);
5280 sRef_clearDerived (s);
5282 if (ss == SS_ALLOCATED)
5284 sRef base = sRef_getBaseSafe (s);
5286 while (sRef_isValid (base) && sRef_isKnown (base))
5288 if (base->defstate == SS_DEFINED)
5292 base->defstate = SS_PDEFINED;
5294 nb = sRef_getBaseSafe (base);
5307 void sRef_setAllocatedComplete (sRef s, fileloc loc)
5309 sRef_innerAliasSetComplete (sRef_setAllocated, s, loc);
5312 static void sRef_setAllocatedShallow (sRef s, fileloc loc)
5314 sRef_checkMutable (s);
5316 if (sRef_isValid (s))
5318 if (s->defstate == SS_DEAD || s->defstate == SS_UNDEFINED)
5320 s->defstate = SS_ALLOCATED;
5322 if (fileloc_isDefined (loc))
5324 s->definfo = stateInfo_updateLoc (s->definfo, loc);
5330 void sRef_setAllocatedShallowComplete (sRef s, fileloc loc)
5332 sRef_innerAliasSetComplete (sRef_setAllocatedShallow, s, loc);
5335 void sRef_setAllocated (sRef s, fileloc loc)
5337 sRef_checkMutable (s);
5338 sRef_setStateAux (s, SS_ALLOCATED, loc);
5341 void sRef_setPartial (sRef s, fileloc loc)
5343 sRef_checkMutable (s);
5344 sRef_setStateAux (s, SS_PARTIAL, loc);
5347 void sRef_setShared (sRef s, fileloc loc)
5349 sRef_checkMutable (s);
5351 if (sRef_isValid (s))
5353 if (s->aliaskind != AK_SHARED && fileloc_isDefined (loc))
5355 s->aliasinfo = stateInfo_updateLoc (s->aliasinfo, loc);
5358 s->aliaskind = AK_SHARED;
5359 /* don't! sRef_clearDerived (s); */
5363 void sRef_setLastReference (sRef s, /*@exposed@*/ sRef ref, fileloc loc)
5365 sRef_checkMutable (s);
5367 if (sRef_isValid (s))
5369 s->aliaskind = sRef_getAliasKind (ref);
5370 s->aliasinfo = stateInfo_updateRefLoc (s->aliasinfo, ref, loc);
5375 void sRef_setNullStateAux (/*@notnull@*/ sRef s, nstate ns, fileloc loc)
5377 DPRINTF (("Set null state: %s / %s", sRef_unparse (s), nstate_unparse (ns)));
5378 sRef_checkMutable (s);
5380 sRef_resetAliasKind (s);
5382 if (fileloc_isDefined (loc))
5384 s->nullinfo = stateInfo_updateLoc (s->nullinfo, loc);
5388 void sRef_setNotNull (sRef s, fileloc loc)
5390 if (sRef_isValid (s))
5392 sRef_setNullStateAux (s, NS_NOTNULL, loc);
5396 void sRef_setNullStateN (sRef s, nstate n)
5398 sRef_checkMutable (s);
5400 sRef_resetAliasKind (s);
5403 void sRef_setNullState (sRef s, nstate n, fileloc loc)
5405 if (sRef_isValid (s))
5407 sRef_setNullStateAux (s, n, loc);
5411 void sRef_setNullTerminatedStateInnerComplete (sRef s, struct s_bbufinfo b, /*@unused@*/ fileloc loc) {
5413 switch (b.bufstate) {
5414 case BB_NULLTERMINATED:
5415 sRef_setNullTerminatedState (s);
5416 sRef_setLen (s, b.len);
5418 case BB_POSSIBLYNULLTERMINATED:
5419 sRef_setPossiblyNullTerminatedState(s);
5421 case BB_NOTNULLTERMINATED:
5422 sRef_setNotNullTerminatedState (s);
5425 sRef_setSize (s, b.size);
5427 /* PL: TO BE DONE : Aliases are not modified right now, have to be similar to
5428 * setNullStateInnerComplete.
5432 void sRef_setNullStateInnerComplete (sRef s, nstate n, fileloc loc)
5434 DPRINTF (("Set null state: %s", nstate_unparse (n)));
5436 sRef_setNullState (s, n, loc);
5441 sRef_innerAliasSetComplete (sRef_setPosNull, s, loc);
5444 sRef_innerAliasSetComplete (sRef_setDefNull, s, loc);
5447 sRef_innerAliasSetComplete (sRef_setNullUnknown, s, loc);
5450 sRef_innerAliasSetComplete (sRef_setNotNull, s, loc);
5453 sRef_innerAliasSetComplete (sRef_setNotNull, s, loc);
5456 sRef_innerAliasSetComplete (sRef_setNullUnknown, s, loc);
5459 sRef_innerAliasSetComplete (sRef_setDefNull, s, loc);
5462 sRef_innerAliasSetComplete (sRef_setNullUnknown, s, loc);
5465 sRef_innerAliasSetComplete (sRef_setNullErrorLoc, s, loc);
5470 void sRef_setPosNull (sRef s, fileloc loc)
5472 if (sRef_isValid (s))
5474 sRef_setNullStateAux (s, NS_POSNULL, loc);
5478 void sRef_setDefNull (sRef s, fileloc loc)
5480 if (sRef_isValid (s))
5482 sRef_setNullStateAux (s, NS_DEFNULL, loc);
5486 void sRef_setNullUnknown (sRef s, fileloc loc)
5488 if (sRef_isValid (s))
5490 sRef_setNullStateAux (s, NS_UNKNOWN, loc);
5494 void sRef_setNullError (sRef s)
5496 if (sRef_isValid (s))
5498 sRef_setNullStateAux (s, NS_UNKNOWN, fileloc_undefined);
5502 void sRef_setNullErrorLoc (sRef s, /*@unused@*/ fileloc loc)
5504 sRef_setNullError (s);
5507 void sRef_setOnly (sRef s, fileloc loc)
5509 sRef_checkMutable (s);
5511 if (sRef_isValid (s) && s->aliaskind != AK_ONLY)
5513 s->aliaskind = AK_ONLY;
5514 s->aliasinfo = stateInfo_updateLoc (s->aliasinfo, loc);
5518 void sRef_setDependent (sRef s, fileloc loc)
5520 sRef_checkMutable (s);
5522 if (sRef_isValid (s) && !sRef_isConst (s) && (s->aliaskind != AK_DEPENDENT))
5524 DPRINTF (("Setting dependent: %s", sRef_unparseFull (s)));
5525 s->aliaskind = AK_DEPENDENT;
5526 s->aliasinfo = stateInfo_updateLoc (s->aliasinfo, loc);
5530 void sRef_setOwned (sRef s, fileloc loc)
5532 sRef_checkMutable (s);
5534 if (sRef_isValid (s) && !sRef_isConst (s) && (s->aliaskind != AK_OWNED))
5536 s->aliaskind = AK_OWNED;
5537 s->aliasinfo = stateInfo_updateLoc (s->aliasinfo, loc);
5541 void sRef_setKept (sRef s, fileloc loc)
5543 sRef_checkMutable (s);
5545 if (sRef_isValid (s) && !sRef_isConst (s) && (s->aliaskind != AK_KEPT))
5547 sRef base = sRef_getBaseSafe (s);
5549 while (sRef_isValid (base) && sRef_isKnown (base))
5551 if (base->defstate == SS_DEFINED)
5553 base->defstate = SS_PDEFINED;
5554 base = sRef_getBaseSafe (base);
5563 s->aliaskind = AK_KEPT;
5564 s->aliasinfo = stateInfo_updateLoc (s->aliasinfo, loc);
5568 static void sRef_setKeptAux (sRef s, fileloc loc)
5570 if (!sRef_isShared (s))
5572 sRef_setKept (s, loc);
5576 static void sRef_setDependentAux (sRef s, fileloc loc)
5578 if (!sRef_isShared (s))
5580 sRef_setDependent (s, loc);
5584 void sRef_setKeptComplete (sRef s, fileloc loc)
5586 sRef_aliasSetComplete (sRef_setKeptAux, s, loc);
5589 void sRef_setDependentComplete (sRef s, fileloc loc)
5591 sRef_aliasSetComplete (sRef_setDependentAux, s, loc);
5594 void sRef_setFresh (sRef s, fileloc loc)
5596 sRef_checkMutable (s);
5598 if (sRef_isValid (s))
5600 s->aliaskind = AK_FRESH;
5601 s->aliasinfo = stateInfo_updateLoc (s->aliasinfo, loc);
5605 void sRef_kill (sRef s, fileloc loc)
5607 DPRINTF (("Kill: %s", sRef_unparseFull (s)));
5608 sRef_checkMutable (s);
5610 if (sRef_isValid (s) && !sRef_isShared (s) && !sRef_isConst (s))
5612 sRef base = sRef_getBaseSafe (s);
5614 while (sRef_isValid (base) && sRef_isKnown (base))
5616 if (base->defstate == SS_DEFINED)
5618 base->defstate = SS_PDEFINED;
5619 base = sRef_getBaseSafe (base);
5627 s->aliaskind = s->oaliaskind;
5628 s->defstate = SS_DEAD;
5629 s->definfo = stateInfo_updateLoc (s->definfo, loc);
5631 sRef_clearDerived (s);
5635 void sRef_maybeKill (sRef s, fileloc loc)
5637 sRef_checkMutable (s);
5639 if (sRef_isValid (s))
5641 sRef base = sRef_getBaseSafe (s);
5644 while (sRef_isValid (base) && sRef_isKnown (base))
5646 if (base->defstate == SS_DEFINED || base->defstate == SS_RELDEF)
5648 base->defstate = SS_PDEFINED;
5649 base = sRef_getBaseSafe (base);
5658 s->aliaskind = s->oaliaskind;
5659 s->defstate = SS_HOFFA;
5660 s->definfo = stateInfo_updateLoc (s->definfo, loc);
5661 sRef_clearDerived (s);
5667 ** just for type checking...
5670 static void sRef_killAux (sRef s, fileloc loc)
5672 if (sRef_isValid (s) && !sRef_isShared (s))
5674 if (sRef_isUnknownArrayFetch (s))
5676 sRef_maybeKill (s, loc);
5686 ** kills s and all aliases to s
5689 void sRef_killComplete (sRef s, fileloc loc)
5691 DPRINTF (("Kill complete: %s", sRef_unparseFull (s)));
5692 sRef_aliasSetComplete (sRef_killAux, s, loc);
5695 static bool sRef_equivalent (sRef s1, sRef s2)
5697 return (sRef_compare (s1, s2) == 0);
5701 ** returns an sRef that will not be free'd on function exit.
5704 /*@only@*/ sRef sRef_saveCopy (sRef s)
5708 if (sRef_isValid (s))
5710 bool old = inFunction;
5713 ** Exit the function scope, so this sRef is not
5714 ** stored in the deallocation table.
5718 DPRINTF (("Copying sref: %s", sRef_unparseFull(s)));
5719 ret = sRef_copy (s);
5720 DPRINTF (("Copying ===>: %s", sRef_unparseFull(ret)));
5725 ret = sRef_undefined;
5728 /*@-dependenttrans@*/
5730 /*@=dependenttrans@*/
5733 sRef sRef_copy (sRef s)
5735 if (sRef_isKindSpecial (s) && !sRef_isGlobalMarker (s))
5738 return s; /* don't copy specials (except for global markers) */
5742 if (sRef_isValid (s))
5744 sRef t = sRef_alloc ();
5746 DPRINTF (("Copying: [%p] %s", s, sRef_unparse (s)));
5747 DPRINTF (("Full: %s", sRef_unparseFull (s)));
5751 t->modified = s->modified;
5752 t->immut = FALSE; /* Note mutability is not copied. */
5754 t->val = multiVal_copy (s->val);
5756 t->info = sinfo_copy (s);
5757 t->defstate = s->defstate;
5758 t->nullstate = s->nullstate;
5760 /* start modifications */
5761 t->bufinfo.bufstate = s->bufinfo.bufstate;
5762 t->bufinfo.len = s->bufinfo.len;
5763 t->bufinfo.size = s->bufinfo.size;
5764 /* end modifications */
5766 t->aliaskind = s->aliaskind;
5767 t->oaliaskind = s->oaliaskind;
5769 t->expkind = s->expkind;
5770 t->oexpkind = s->oexpkind;
5772 t->nullinfo = stateInfo_copy (s->nullinfo);
5773 t->aliasinfo = stateInfo_copy (s->aliasinfo);
5774 t->definfo = stateInfo_copy (s->definfo);
5775 t->expinfo = stateInfo_copy (s->expinfo);
5777 t->deriv = sRefSet_newDeepCopy (s->deriv);
5778 t->state = valueTable_copy (s->state);
5780 DPRINTF (("Made copy: [%p] %s", t, sRef_unparse (t)));
5785 return sRef_undefined;
5790 # define PREDTEST(func,s) \
5791 do { if (sRef_isInvalid (s)) { return FALSE; } \
5792 else { if (sRef_isConj (s)) \
5793 { return (func (sRef_getConjA (s)) \
5794 || func (sRef_getConjB (s))); }}} while (FALSE);
5796 bool sRef_isAddress (sRef s)
5798 PREDTEST (sRef_isAddress, s);
5799 return (s->kind == SK_ADR);
5803 ** pretty weak... maybe a flag should control this.
5806 bool sRef_isThroughArrayFetch (sRef s)
5808 if (sRef_isValid (s))
5816 if (sRef_isArrayFetch (tref))
5821 lt = sRef_getBase (tref);
5823 } while (sRef_isValid (tref));
5829 bool sRef_isArrayFetch (sRef s)
5831 PREDTEST (sRef_isArrayFetch, s);
5832 return (s->kind == SK_ARRAYFETCH);
5835 bool sRef_isMacroParamRef (sRef s)
5837 if (context_inMacro () && sRef_isCvar (s))
5839 uentry ue = sRef_getUentry (s);
5840 cstring pname = makeParam (uentry_rawName (ue));
5841 uentry mac = usymtab_lookupSafe (pname);
5843 cstring_free (pname);
5844 return (uentry_isValid (mac));
5850 bool sRef_isCvar (sRef s)
5852 PREDTEST (sRef_isCvar, s);
5853 return (s->kind == SK_CVAR);
5856 bool sRef_isConst (sRef s)
5858 PREDTEST (sRef_isConst, s);
5859 return (s->kind == SK_CONST);
5862 bool sRef_isObject (sRef s)
5864 PREDTEST (sRef_isObject, s);
5865 return (s->kind == SK_OBJECT);
5868 bool sRef_isExternal (sRef s)
5870 PREDTEST (sRef_isExternal, s);
5871 return (s->kind == SK_EXTERNAL);
5874 static bool sRef_isDerived (sRef s)
5876 PREDTEST (sRef_isDerived, s);
5877 return (s->kind == SK_DERIVED);
5880 bool sRef_isField (sRef s)
5882 PREDTEST (sRef_isField, s);
5883 return (s->kind == SK_FIELD);
5886 static bool sRef_isIndex (sRef s)
5888 PREDTEST (sRef_isIndex, s);
5889 return (s->kind == SK_ARRAYFETCH);
5892 bool sRef_isAnyParam (sRef s)
5894 PREDTEST (sRef_isAnyParam, s);
5895 return (s->kind == SK_PARAM);
5898 bool sRef_isParam (sRef s)
5900 PREDTEST (sRef_isParam, s);
5901 return (s->kind == SK_PARAM);
5904 bool sRef_isDirectParam (sRef s)
5906 PREDTEST (sRef_isDirectParam, s);
5908 return ((s->kind == SK_CVAR) &&
5909 (s->info->cvar->lexlevel == functionScope) &&
5910 (context_inFunction () &&
5911 (s->info->cvar->index <= uentryList_size (context_getParams ()))));
5914 bool sRef_isPointer (sRef s)
5916 PREDTEST (sRef_isPointer, s);
5917 return (s->kind == SK_PTR);
5921 ** returns true if storage referenced by s is visible
5924 bool sRef_isReference (sRef s)
5926 PREDTEST (sRef_isReference, s);
5928 return (sRef_isPointer (s) || sRef_isIndex (s) || sRef_isFileOrGlobalScope (s)
5929 || (sRef_isField (s) && (sRef_isReference (s->info->field->rec))));
5932 bool sRef_isIReference (sRef s)
5934 return (sRef_isPointer (s) || sRef_isAddress (s) || sRef_isIndex (s)
5935 || sRef_isField (s) || sRef_isArrayFetch (s));
5938 bool sRef_isFileOrGlobalScope (sRef s)
5940 return (sRef_isCvar (s) && (s->info->cvar->lexlevel <= fileScope));
5943 bool sRef_isRealGlobal (sRef s)
5945 return (sRef_isCvar (s) && (s->info->cvar->lexlevel == globScope));
5948 bool sRef_isFileStatic (sRef s)
5950 return (sRef_isCvar (s) && (s->info->cvar->lexlevel == fileScope));
5953 bool sRef_isAliasCheckedGlobal (sRef s)
5955 if (sRef_isFileOrGlobalScope (s))
5957 uentry ue = sRef_getUentry (s);
5959 return context_checkAliasGlob (ue);
5967 void sRef_free (/*@only@*/ sRef s)
5969 if (s != sRef_undefined && s->kind != SK_SPECIAL)
5971 DPRINTF (("Free sref: [%p]", s));
5973 sRef_checkValid (s);
5975 stateInfo_free (s->expinfo);
5976 stateInfo_free (s->aliasinfo);
5977 stateInfo_free (s->definfo);
5978 stateInfo_free (s->nullinfo);
5980 sRefSet_free (s->deriv);
5981 s->deriv = sRefSet_undefined;
5983 /*@i43@*/ /* valueTable_free (s->state); */
5987 /* drl added to help locate use after release*/
5988 s->expinfo = stateInfo_undefined;
5989 s->aliasinfo = stateInfo_undefined;
5990 s->definfo = stateInfo_undefined;
5991 s->nullinfo = stateInfo_undefined;
5993 /*@i32@*/ sfree (s);
5997 void sRef_setType (sRef s, ctype t)
5999 sRef_checkMutable (s);
6001 if (sRef_isValid (s))
6007 void sRef_setTypeFull (sRef s, ctype t)
6009 sRef_checkMutable (s);
6011 if (sRef_isValid (s))
6015 sRefSet_allElements (s->deriv, current)
6017 sRef_setTypeFull (current, ctype_unknown);
6018 } end_sRefSet_allElements ;
6023 sRef_buildField (/*@exposed@*/ sRef rec, /*@dependent@*/ cstring f)
6025 return (sRef_buildNCField (rec, f));
6028 static /*@exposed@*/ sRef
6029 sRef_findDerivedField (/*@notnull@*/ sRef rec, cstring f)
6031 sRefSet_allElements (rec->deriv, sr)
6033 if (sRef_isValid (sr))
6035 if (sr->info != NULL)
6037 if (sr->kind == SK_FIELD && cstring_equal (sr->info->field->field, f))
6043 } end_sRefSet_allElements;
6045 return sRef_undefined;
6048 /*@dependent@*/ /*@observer@*/ sRefSet sRef_derivedFields (/*@temp@*/ sRef rec)
6050 if (sRef_isValid (rec))
6058 return (sRefSet_undefined);
6062 static /*@exposed@*/ sRef
6063 sRef_findDerivedPointer (sRef s)
6065 if (sRef_isValid (s))
6067 sRefSet_realElements (s->deriv, sr)
6069 if (sRef_isValid (sr) && sr->kind == SK_PTR)
6073 } end_sRefSet_realElements;
6076 return sRef_undefined;
6080 sRef_isUnknownArrayFetch (sRef s)
6082 return (sRef_isValid (s)
6083 && s->kind == SK_ARRAYFETCH
6084 && !s->info->arrayfetch->indknown);
6087 static /*@exposed@*/ sRef
6088 sRef_findDerivedArrayFetch (/*@notnull@*/ sRef s, bool isknown, int idx, bool dead)
6093 sRefSet_realElements (s->deriv, sr)
6095 if (sRef_isValid (sr)
6096 && sr->kind == SK_ARRAYFETCH
6097 && sr->info->arrayfetch->indknown
6098 && (sr->info->arrayfetch->ind == idx))
6102 } end_sRefSet_realElements;
6106 sRefSet_realElements (s->deriv, sr)
6108 if (sRef_isValid (sr)
6109 && sr->kind == SK_ARRAYFETCH
6110 && (!sr->info->arrayfetch->indknown
6111 || (sr->info->arrayfetch->indknown &&
6112 sr->info->arrayfetch->ind == 0)))
6114 if (sRef_isDead (sr) || sRef_isKept (sr))
6116 if (dead || context_getFlag (FLG_STRICTUSERELEASED))
6126 } end_sRefSet_realElements;
6129 return sRef_undefined;
6132 static /*@exposed@*/ sRef
6133 sRef_buildNCField (/*@exposed@*/ sRef rec, /*@exposed@*/ cstring f)
6137 DPRINTF (("Build nc field: %s / %s",
6138 sRef_unparseFull (rec), f));
6140 if (sRef_isInvalid (rec))
6142 return sRef_undefined;
6146 ** check if the field already has been referenced
6149 s = sRef_findDerivedField (rec, f);
6151 if (sRef_isValid (s))
6157 ctype ct = ctype_realType (rec->type);
6159 DPRINTF (("Field of: %s", sRef_unparse (rec)));
6163 s->info = (sinfo) dmalloc (sizeof (*s->info));
6164 s->info->field = (fldinfo) dmalloc (sizeof (*s->info->field));
6165 s->info->field->rec = rec; /* sRef_copy (rec); */ /*@i32@*/
6166 s->info->field->field = f; /* doesn't copy f */
6168 if (ctype_isKnown (ct) && ctype_isSU (ct))
6170 uentry ue = uentryList_lookupField (ctype_getFields (ct), f);
6172 if (!uentry_isUndefined (ue))
6174 DPRINTF (("lookup: %s for %s", uentry_unparseFull (ue),
6175 ctype_unparse (ct)));
6177 s->type = uentry_getType (ue);
6179 if (ctype_isMutable (s->type)
6180 && rec->aliaskind != AK_STACK
6181 && !alkind_isStatic (rec->aliaskind))
6183 s->aliaskind = rec->aliaskind;
6187 s->aliaskind = AK_UNKNOWN;
6190 if (sRef_isStateDefined (rec) || sRef_isStateUnknown (rec)
6191 || sRef_isPdefined (rec))
6193 sRef_setStateFromUentry (s, ue);
6197 sRef_setPartsFromUentry (s, ue);
6200 s->oaliaskind = s->aliaskind;
6201 s->oexpkind = s->expkind;
6203 DPRINTF (("sref: %s", sRef_unparseFull (s)));
6208 Never report this as an error. It can happen whenever there
6209 is casting involved.
6213 llcontbug (message ("buildNCField --- no field %s: %q / %s",
6214 f, sRef_unparse (s), ctype_unparse (ct)));
6218 return sRef_undefined;
6222 if (rec->defstate == SS_DEFINED
6223 && (s->defstate == SS_UNDEFINED || s->defstate == SS_UNKNOWN))
6225 s->defstate = SS_DEFINED;
6227 else if (rec->defstate == SS_PARTIAL)
6229 s->defstate = SS_PARTIAL;
6231 else if (rec->defstate == SS_ALLOCATED)
6233 if (ctype_isStackAllocated (ct) && ctype_isStackAllocated (s->type))
6235 s->defstate = SS_ALLOCATED;
6239 s->defstate = SS_UNDEFINED;
6242 else if (s->defstate == SS_UNKNOWN)
6244 s->defstate = rec->defstate;
6251 if (s->defstate == SS_UNDEFINED)
6253 ctype rt = ctype_realType (s->type);
6255 if (ctype_isArray (rt) || ctype_isSU (rt))
6257 s->defstate = SS_ALLOCATED;
6261 sRef_addDeriv (rec, s);
6262 DPRINTF (("Add deriv: %s", sRef_unparseFull (rec)));
6264 if (ctype_isInt (s->type) && cstring_equal (f, REFSNAME))
6266 s->aliaskind = AK_REFS;
6267 s->oaliaskind = AK_REFS;
6270 DPRINTF (("Build field ==> %s", sRef_unparseFull (s)));
6276 sRef_isStackAllocated (sRef s)
6278 return (sRef_isValid(s)
6279 && s->defstate == SS_ALLOCATED && ctype_isStackAllocated (s->type));
6283 void sRef_setArrayFetchState (/*@notnull@*/ /*@exposed@*/ sRef s,
6284 /*@notnull@*/ /*@exposed@*/ sRef arr)
6286 sRef_checkMutable (s);
6288 if (ctype_isRealAP (arr->type))
6290 s->type = ctype_baseArrayPtr (arr->type);
6293 /* a hack, methinks... makeArrayFetch (&a[0]) ==> a[] */
6294 /* evans - 2001-08-27: not sure where this was necessary - it
6295 ** causes an assertion in in aliasCheckPred to fail.
6298 if (sRef_isAddress (arr))
6300 sRef t = arr->info->ref;
6302 if (sRef_isArrayFetch (t))
6304 s->info->arrayfetch->arr = t->info->arrayfetch->arr;
6307 else if (ctype_isRealPointer (arr->type))
6309 sRef sp = sRef_findDerivedPointer (arr);
6311 if (sRef_isValid (sp))
6314 if (ctype_isMutable (s->type))
6316 sRef_setExKind (s, sRef_getExKind (sp), fileloc_undefined);
6318 s->aliaskind = sp->aliaskind;
6321 s->defstate = sp->defstate;
6323 if (s->defstate == SS_DEFINED)
6325 if (!context_getFlag (FLG_STRICTDESTROY))
6327 s->defstate = SS_PARTIAL;
6331 sRef_setNullStateN (s, sRef_getNullState (sp));
6335 if (arr->defstate == SS_UNDEFINED)
6337 s->defstate = SS_UNUSEABLE;
6339 else if ((arr->defstate == SS_ALLOCATED) && !ctype_isSU (s->type))
6341 s->defstate = SS_UNDEFINED;
6345 if (!context_getFlag (FLG_STRICTDESTROY))
6347 s->defstate = SS_PARTIAL;
6351 s->defstate = SS_DEFINED;
6355 ** Very weak checking for array elements.
6357 ** s->defstate = arr->defstate;
6361 sRef_setExKind (s, sRef_getExKind (arr), g_currentloc);
6363 if (arr->aliaskind == AK_LOCAL || arr->aliaskind == AK_FRESH)
6365 s->aliaskind = AK_LOCAL;
6369 s->aliaskind = AK_UNKNOWN;
6372 sRef_setTypeState (s);
6377 if (arr->defstate == SS_DEFINED)
6380 ** Very weak checking for array elements.
6382 ** s->defstate = arr->defstate;
6385 if (context_getFlag (FLG_STRICTDESTROY))
6387 s->defstate = SS_DEFINED;
6391 s->defstate = SS_PARTIAL;
6394 else if (arr->defstate == SS_ALLOCATED)
6396 if (ctype_isRealArray (s->type))
6398 s->defstate = SS_ALLOCATED;
6402 if (!s->info->arrayfetch->indknown)
6405 ** is index is unknown, elements is defined or
6406 ** allocated is any element is!
6409 s->defstate = SS_UNDEFINED;
6411 sRefSet_allElements (arr->deriv, sr)
6413 if (sRef_isValid (sr))
6415 if (sr->defstate == SS_ALLOCATED)
6417 s->defstate = SS_ALLOCATED;
6421 if (sr->defstate == SS_DEFINED)
6423 if (context_getFlag (FLG_STRICTDESTROY))
6425 s->defstate = SS_DEFINED;
6429 s->defstate = SS_PARTIAL;
6436 } end_sRefSet_allElements;
6441 s->defstate = SS_UNDEFINED;
6447 s->defstate = arr->defstate;
6452 ** kludgey way to guess where aliaskind applies
6455 if (ctype_isMutable (s->type)
6456 && !ctype_isPointer (arr->type)
6457 && !alkind_isStatic (arr->aliaskind)
6458 && !alkind_isStack (arr->aliaskind)) /* evs - 2000-06-20: don't pass stack allocation to members */
6460 s->aliaskind = arr->aliaskind;
6464 s->aliaskind = AK_UNKNOWN;
6467 sRef_setTypeState (s);
6470 if (sRef_isObserver (arr))
6472 s->expkind = XO_OBSERVER;
6476 /*@exposed@*/ sRef sRef_buildArrayFetch (/*@exposed@*/ sRef arr)
6480 if (!sRef_isValid (arr)) {
6481 /*@-nullret@*/ return arr /*@=nullret@*/;
6484 if (ctype_isRealPointer (arr->type))
6486 (void) sRef_buildPointer (arr); /* do this to define arr! */
6489 s = sRef_findDerivedArrayFetch (arr, FALSE, 0, FALSE);
6491 if (sRef_isValid (s))
6493 /* evans 2001-07-12: this is bogus, clean-up hack */
6494 if (s->info->arrayfetch->arr != arr)
6497 check (sRefSet_delete (arr->deriv, s));
6498 res = sRef_buildArrayFetch (arr);
6499 sRef_copyState (res, s);
6500 llassert (res->info->arrayfetch->arr == arr);
6504 sRef_setExKind (s, sRef_getExKind (arr), g_currentloc);
6511 s->kind = SK_ARRAYFETCH;
6512 s->info = (sinfo) dmalloc (sizeof (*s->info));
6513 s->info->arrayfetch = (ainfo) dmalloc (sizeof (*s->info->arrayfetch));
6514 s->info->arrayfetch->indknown = FALSE;
6515 s->info->arrayfetch->ind = 0;
6516 s->info->arrayfetch->arr = arr; /* sRef_copy (arr); */ /*@i32@*/
6517 sRef_setArrayFetchState (s, arr);
6518 s->oaliaskind = s->aliaskind;
6519 s->oexpkind = s->expkind;
6521 if (!context_inProtectVars ())
6523 sRef_addDeriv (arr, s);
6526 if (valueTable_isUndefined (s->state))
6528 s->state = context_createValueTable (s, stateInfo_makeLoc (g_currentloc));
6536 sRef_buildArrayFetchKnown (/*@exposed@*/ sRef arr, int i)
6540 if (!sRef_isValid (arr)) {
6541 /*@-nullret@*/ return arr /*@=nullret@*/;
6544 if (ctype_isRealPointer (arr->type))
6546 (void) sRef_buildPointer (arr); /* do this to define arr! */
6549 s = sRef_findDerivedArrayFetch (arr, TRUE, i, FALSE);
6551 if (sRef_isValid (s))
6553 /* evans 2001-07-12: this is bogus, clean-up hack */
6554 if (s->info->arrayfetch->arr != arr)
6558 check (sRefSet_delete (arr->deriv, s));
6559 res = sRef_buildArrayFetchKnown (arr, i);
6561 llassert (res->info->arrayfetch->arr == arr);
6562 sRef_copyState (res, s);
6563 llassert (res->info->arrayfetch->arr == arr);
6567 sRef_setExKind (s, sRef_getExKind (arr), g_currentloc);
6568 llassert (s->info->arrayfetch->arr == arr);
6575 s->kind = SK_ARRAYFETCH;
6576 s->info = (sinfo) dmalloc (sizeof (*s->info));
6577 s->info->arrayfetch = (ainfo) dmalloc (sizeof (*s->info->arrayfetch));
6578 s->info->arrayfetch->arr = arr; /* sRef_copy (arr); */ /*@i32@*/
6579 s->info->arrayfetch->indknown = TRUE;
6580 s->info->arrayfetch->ind = i;
6582 sRef_setArrayFetchState (s, arr);
6583 /* evans 2001-08-27 no: can change this - llassert (s->info->arrayfetch->arr == arr); */
6585 s->oaliaskind = s->aliaskind;
6586 s->oexpkind = s->expkind;
6587 sRef_addDeriv (arr, s);
6589 llassert (valueTable_isUndefined (s->state));
6590 s->state = context_createValueTable (s, stateInfo_makeLoc (g_currentloc));
6596 ** sets everything except for defstate
6600 sRef_setPartsFromUentry (sRef s, uentry ue)
6602 sRef uref = uentry_getSref (ue);
6604 llassert (sRef_isValid (s));
6606 s->aliaskind = alkind_derive (s->aliaskind, uentry_getAliasKind (ue));
6607 s->oaliaskind = s->aliaskind;
6609 if (s->expkind == XO_UNKNOWN)
6611 s->expkind = uentry_getExpKind (ue);
6614 s->oexpkind = s->expkind;
6616 if (sRef_getNullState (s) == NS_UNKNOWN)
6618 DPRINTF (("Setting null state!"));
6619 sRef_setNullStateN (s, sRef_getNullState (uentry_getSref (ue)));
6623 DPRINTF (("Skipping null null state!"));
6626 if (s->aliaskind == AK_IMPONLY && (sRef_isExposed (s) || sRef_isObserver (s)))
6628 s->oaliaskind = s->aliaskind = AK_IMPDEPENDENT;
6631 if (sRef_isValid (uref))
6633 valueTable utable = uref->state;
6634 valueTable_free (s->state);
6635 s->state = valueTable_copy (utable);
6640 sRef_setStateFromAbstractUentry (sRef s, uentry ue)
6642 llassert (sRef_isValid (s));
6643 sRef_checkMutable (s);
6645 sRef_setPartsFromUentry (s, ue);
6647 s->aliaskind = alkind_derive (s->aliaskind, uentry_getAliasKind (ue));
6648 s->oaliaskind = s->aliaskind;
6650 if (s->expkind == XO_UNKNOWN)
6652 s->expkind = uentry_getExpKind (ue);
6655 s->oexpkind = s->expkind;
6659 sRef_setStateFromUentry (sRef s, uentry ue)
6663 sRef_checkMutable (s);
6664 llassert (sRef_isValid (s));
6666 sRef_setPartsFromUentry (s, ue);
6668 defstate = uentry_getDefState (ue);
6670 if (sstate_isKnown (defstate))
6672 s->defstate = defstate;
6681 sRef_buildPointer (/*@exposed@*/ sRef t)
6683 DPRINTF (("build pointer: %s", sRef_unparse (t)));
6685 if (sRef_isInvalid (t)) return sRef_undefined;
6687 if (sRef_isAddress (t))
6689 DPRINTF (("Return ref: %s", sRef_unparse (t->info->ref)));
6690 return (t->info->ref);
6694 sRef s = sRef_findDerivedPointer (t);
6696 DPRINTF (("find derived: %s", sRef_unparse (s)));
6698 if (sRef_isValid (s))
6701 sRef_setExKind (s, sRef_getExKind (t), g_currentloc);
6702 s->oaliaskind = s->aliaskind;
6703 s->oexpkind = s->expkind;
6709 s = sRef_constructPointerAux (t);
6711 DPRINTF (("construct: %s", sRef_unparse (s)));
6713 if (sRef_isValid (s))
6715 sRef_addDeriv (t, s);
6717 s->oaliaskind = s->aliaskind;
6718 s->oexpkind = s->expkind;
6727 sRef_constructPointer (/*@exposed@*/ sRef t)
6730 return sRef_buildPointer (t);
6733 static /*@exposed@*/ sRef sRef_constructDerefAux (sRef t, bool isdead)
6735 if (sRef_isValid (t))
6740 ** if there is a derived t[?], return that. Otherwise, *t.
6743 s = sRef_findDerivedArrayFetch (t, FALSE, 0, isdead);
6745 if (sRef_isValid (s))
6747 DPRINTF (("Found array fetch: %s", sRef_unparseFull (s)));
6752 sRef ret = sRef_constructPointer (t);
6754 DPRINTF (("Constructed pointer: %s", sRef_unparseFull (ret)));
6761 return sRef_undefined;
6765 sRef sRef_constructDeref (sRef t)
6767 return sRef_constructDerefAux (t, FALSE);
6770 sRef sRef_constructDeadDeref (sRef t)
6772 return sRef_constructDerefAux (t, TRUE);
6776 sRef_constructPointerAux (/*@notnull@*/ /*@exposed@*/ sRef t)
6778 sRef s = sRef_newRef ();
6782 llassert (valueTable_isUndefined (s->state));
6785 s->info = (sinfo) dmalloc (sizeof (*s->info));
6786 s->info->ref = t; /* sRef_copy (t); */ /*@i32*/
6788 if (ctype_isRealAP (rt))
6790 s->type = ctype_baseArrayPtr (rt);
6793 st = ctype_realType (s->type);
6795 if (t->defstate == SS_UNDEFINED)
6797 s->defstate = SS_UNUSEABLE;
6799 else if ((t->defstate == SS_ALLOCATED) && !ctype_isSU (st))
6801 s->defstate = SS_UNDEFINED;
6805 s->defstate = t->defstate;
6808 if (t->aliaskind == AK_LOCAL || t->aliaskind == AK_FRESH)
6810 s->aliaskind = AK_LOCAL;
6814 s->aliaskind = AK_UNKNOWN;
6817 sRef_setExKind (s, sRef_getExKind (t), fileloc_undefined);
6818 sRef_setTypeState (s);
6820 s->oaliaskind = s->aliaskind;
6821 s->oexpkind = s->expkind;
6823 if (valueTable_isUndefined (s->state))
6825 s->state = context_createValueTable (s, stateInfo_makeLoc (g_currentloc));
6831 bool sRef_hasDerived (sRef s)
6833 return (sRef_isValid (s) && !sRefSet_isEmpty (s->deriv));
6837 sRef_clearDerived (sRef s)
6839 if (sRef_isValid (s))
6841 sRefSet_clear (s->deriv);
6846 sRef_clearDerivedComplete (sRef s)
6849 if (sRef_isValid (s))
6851 sRef base = sRef_getBaseSafe (s);
6853 while (sRef_isValid (base))
6855 sRefSet_clear (base->deriv);
6856 base = sRef_getBaseSafe (base);
6859 sRefSet_clear (s->deriv);
6863 /*@exposed@*/ sRef sRef_makePointer (/*@exposed@*/ sRef s)
6866 sRef res = sRef_buildPointer (s);
6868 DPRINTF (("Res: %s", sRef_unparse (res)));
6873 ** &a[] => a (this is for out params)
6877 sRef_makeAnyArrayFetch (/*@exposed@*/ sRef arr)
6880 if (sRef_isAddress (arr))
6882 return (arr->info->ref);
6886 return (sRef_buildArrayFetch (arr));
6891 sRef_makeArrayFetch (/*@exposed@*/ sRef arr)
6893 return (sRef_buildArrayFetch (arr));
6897 sRef_makeArrayFetchKnown (/*@exposed@*/ sRef arr, int i)
6899 return (sRef_buildArrayFetchKnown (arr, i));
6903 sRef_makeField (sRef rec, /*@dependent@*/ cstring f)
6906 ret = sRef_buildField (rec, f);
6911 sRef_makeNCField (/*@exposed@*/ sRef rec, /*@dependent@*/ cstring f)
6913 return (sRef_buildNCField (rec, f));
6917 sRef_unparseKindName (sRef s)
6921 if (s == sRef_undefined) return cstring_makeLiteral ("<invalid>");
6923 s = sRef_fixConj (s);
6928 if (sRef_isLocalVar (s))
6930 result = cstring_makeLiteral ("Variable");
6934 result = cstring_makeLiteral ("Undef global");
6938 result = cstring_makeLiteral ("Out parameter");
6941 if (sRef_isAnyParam (s->info->arrayfetch->arr))
6943 result = cstring_makeLiteral ("Out parameter");
6945 else if (sRef_isIndexKnown (s))
6947 result = cstring_makeLiteral ("Array element");
6951 result = cstring_makeLiteral ("Value");
6955 if (sRef_isAnyParam (s->info->ref))
6957 result = cstring_makeLiteral ("Out parameter");
6961 result = cstring_makeLiteral ("Value");
6965 result = cstring_makeLiteral ("Value");
6968 result = cstring_makeLiteral ("Field");
6971 result = cstring_makeLiteral ("Object");
6973 case SK_UNCONSTRAINED:
6974 result = cstring_makeLiteral ("<anything>");
6983 result = cstring_makeLiteral ("<unknown>");
6986 result = cstring_makeLiteral ("<conj>");
6989 result = cstring_makeLiteral ("Storage");
6997 sRef_unparseKindNamePlain (sRef s)
7001 if (s == sRef_undefined) return cstring_makeLiteral ("<invalid>");
7003 s = sRef_fixConj (s);
7008 if (sRef_isLocalVar (s))
7010 result = cstring_makeLiteral ("Variable");
7014 result = cstring_makeLiteral ("Global");
7018 result = cstring_makeLiteral ("Parameter");
7021 if (sRef_isAnyParam (s->info->arrayfetch->arr))
7023 result = cstring_makeLiteral ("Parameter");
7025 else if (sRef_isIndexKnown (s))
7027 result = cstring_makeLiteral ("Array element");
7031 result = cstring_makeLiteral ("Value");
7035 if (sRef_isAnyParam (s->info->ref))
7037 result = cstring_makeLiteral ("Parameter");
7041 result = cstring_makeLiteral ("Value");
7045 result = cstring_makeLiteral ("Value");
7048 result = cstring_makeLiteral ("Field");
7051 result = cstring_makeLiteral ("Object");
7054 result = cstring_makeLiteral ("Storage");
7056 case SK_UNCONSTRAINED:
7057 result = cstring_makeLiteral ("<anything>");
7066 result = cstring_makeLiteral ("<unknown>");
7069 result = cstring_makeLiteral ("<conj>");
7081 sRef_copyState (sRef s1, sRef s2)
7083 if (sRef_isValid (s1) && sRef_isValid (s2))
7085 s1->defstate = s2->defstate;
7087 /* start modifications */
7088 s1->bufinfo.bufstate = s2->bufinfo.bufstate;
7089 s1->bufinfo.len = s2->bufinfo.len;
7090 s1->bufinfo.size = s2->bufinfo.size;
7091 /* end modifications */
7093 s1->aliaskind = s2->aliaskind;
7094 s1->aliasinfo = stateInfo_update (s1->aliasinfo, s2->aliasinfo);
7096 s1->expkind = s2->expkind;
7097 s1->expinfo = stateInfo_update (s1->expinfo, s2->expinfo);
7099 s1->nullstate = s2->nullstate;
7100 s1->nullinfo = stateInfo_update (s1->nullinfo, s2->nullinfo);
7103 /*@i834 don't free it: valueTable_free (s1->state); */
7104 /*@i32@*/ s1->state = valueTable_copy (s2->state);
7106 s1->safe = s2->safe;
7111 sRef_makeNew (ctype ct, sRef t, cstring name)
7113 sRef s = sRef_newRef ();
7118 llassert (sRef_isValid (t));
7119 s->defstate = t->defstate;
7121 s->aliaskind = t->aliaskind;
7122 s->oaliaskind = s->aliaskind;
7123 s->nullstate = t->nullstate;
7125 s->expkind = t->expkind;
7126 s->oexpkind = s->expkind;
7128 s->info = (sinfo) dmalloc (sizeof (*s->info));
7129 s->info->fname = name;
7131 /* start modifications */
7132 s->bufinfo.bufstate = t->bufinfo.bufstate;
7133 /* end modifications */
7135 llassert (valueTable_isUndefined (s->state));
7136 s->state = valueTable_copy (t->state);
7138 DPRINTF (("==> Copying state: %s", valueTable_unparse (s->state)));
7139 DPRINTF (("==> new: %s", sRef_unparseFull (s)));
7144 sRef_makeType (ctype ct)
7146 sRef s = sRef_newRef ();
7148 sRef_checkMutable (s);
7153 s->defstate = SS_UNKNOWN;
7154 s->aliaskind = AK_UNKNOWN;
7155 sRef_setNullStateN (s, NS_UNKNOWN);
7157 /* start modification */
7158 s->bufinfo.bufstate = BB_NOTNULLTERMINATED;
7159 /* end modification */
7162 if (ctype_isUA (ct))
7164 typeId uid = ctype_typeId (ct);
7165 uentry ue = usymtab_getTypeEntrySafe (uid);
7167 if (uentry_isValid (ue))
7169 sRef_mergeStateQuiet (s, uentry_getSref (ue));
7173 s->oaliaskind = s->aliaskind;
7174 s->oexpkind = s->expkind;
7175 llassert (valueTable_isUndefined (s->state));
7176 s->state = context_createValueTable (s, stateInfo_makeLoc (g_currentloc));
7178 DPRINTF (("Create: %s", sRef_unparseFull (s)));
7183 sRef_makeConst (ctype ct)
7185 sRef s = sRef_newRef ();
7190 s->defstate = SS_UNKNOWN;
7191 s->aliaskind = AK_UNKNOWN;
7192 sRef_setNullStateN (s, NS_UNKNOWN);
7194 /* start modification */
7195 s->bufinfo.bufstate = BB_NULLTERMINATED;
7196 /* end modification */
7197 if (ctype_isUA (ct))
7199 typeId uid = ctype_typeId (ct);
7200 uentry te = usymtab_getTypeEntrySafe (uid);
7202 if (uentry_isValid (te))
7204 sRef_mergeStateQuiet (s, uentry_getSref (te));
7209 s->oaliaskind = s->aliaskind;
7210 s->oexpkind = s->expkind;
7212 llassert (valueTable_isUndefined (s->state));
7213 s->state = context_createValueTable (s, stateInfo_makeLoc (g_currentloc));
7218 bool sRef_hasName (sRef s)
7220 if (sRef_isInvalid (s))
7229 uentry u = usymtab_getRefQuiet (s->info->cvar->lexlevel,
7230 s->info->cvar->index);
7231 return (uentry_hasName (u));
7235 if (s->info->paramno >= 0)
7237 uentry u = uentryList_getN (context_getParams (),
7240 return (uentry_hasName (u));
7244 llassert (s->info->paramno == PARAMUNKNOWN);
7254 sRef_sameName (sRef s1, sRef s2)
7256 if (sRef_isInvalid (s1))
7258 return sRef_isInvalid (s2);
7261 if (sRef_isInvalid (s2))
7269 if (s2->kind == SK_CVAR)
7271 return (s1->info->cvar->lexlevel == s2->info->cvar->lexlevel
7272 && s1->info->cvar->index == s2->info->cvar->index);
7274 else if (s2->kind == SK_PARAM)
7276 if (context_inFunctionLike ())
7278 if (s2->info->paramno != PARAMUNKNOWN)
7280 uentry u1 = usymtab_getRefQuiet (s1->info->cvar->lexlevel,
7281 s1->info->cvar->index);
7282 uentry u2 = uentryList_getN (context_getParams (),
7285 return (cstring_equalFree (uentry_getName (u1),
7286 uentry_getName (u2)));
7290 return s1->info->paramno == PARAMUNKNOWN;
7304 if (s2->kind == SK_PARAM)
7306 return (s1->info->paramno == s2->info->paramno);
7308 else if (s2->kind == SK_CVAR)
7310 if (context_inFunctionLike ())
7312 if (s1->info->paramno == PARAMUNKNOWN)
7318 uentry u1 = uentryList_getN (context_getParams (),
7320 uentry u2 = usymtab_getRefQuiet (s2->info->cvar->lexlevel,
7321 s2->info->cvar->index);
7324 return (cstring_equalFree (uentry_getName (u1),
7325 uentry_getName (u2)));
7339 case SK_UNCONSTRAINED:
7343 if (s2->kind == SK_ARRAYFETCH)
7345 if (bool_equal (s1->info->arrayfetch->indknown,
7346 s2->info->arrayfetch->indknown))
7348 if (!s1->info->arrayfetch->indknown
7349 || (s1->info->arrayfetch->ind == s2->info->arrayfetch->ind))
7351 return sRef_sameName (s1->info->arrayfetch->arr,
7352 s2->info->arrayfetch->arr);
7359 if (s2->kind == SK_FIELD)
7361 if (cstring_equal (s1->info->field->field,
7362 s2->info->field->field))
7364 return sRef_sameName (s1->info->field->rec,
7365 s2->info->field->rec);
7374 if (s2->kind == s1->kind)
7376 return sRef_sameName (s1->info->ref,
7384 return sRef_sameName (sRef_getConjA (s1), s2);
7388 return (s2->kind == SK_UNKNOWN);
7391 if (s2->kind == s1->kind)
7393 return (ctype_equal (s1->type, s2->type));
7398 if (s2->kind == SK_SPECIAL)
7400 return (s1->info->spec == s2->info->spec);
7404 return (s2->kind == SK_RESULT);
7412 sRef_fixOuterRef (/*@returned@*/ sRef s)
7414 sRef root = sRef_getRootBase (s);
7416 if (sRef_isCvar (root))
7418 uentry ue = usymtab_getRefQuiet (root->info->cvar->lexlevel,
7419 root->info->cvar->index);
7421 if (uentry_isValid (ue))
7423 sRef uref = uentry_getSref (ue);
7424 sRef sr = sRef_fixBase (s, uref);
7430 llcontbug (message ("sRef_fixOuterRef: undefined: %q", sRef_unparseDebug (s)));
7439 sRef_storeState (sRef s)
7441 if (sRef_isInvalid (s)) return;
7443 sRef_checkMutable (s);
7444 s->oaliaskind = s->aliaskind;
7445 s->oexpkind = s->expkind;
7448 static void sRef_resetStateAux (sRef s, /*@unused@*/ fileloc loc)
7450 sRef_resetState (s);
7454 sRef_resetState (sRef s)
7456 bool changed = FALSE;
7457 if (sRef_isInvalid (s)) return;
7460 if (s->oaliaskind == AK_KILLREF && !sRef_isParam (s))
7463 ** killref is used in a kludgey way, to save having to add
7464 ** another alias kind (see usymtab_handleParams)
7467 if (s->expkind != s->oexpkind)
7470 s->expkind = s->oexpkind;
7475 if (s->expkind != s->oexpkind)
7478 s->expkind = s->oexpkind;
7481 if (s->aliaskind != s->oaliaskind
7482 && s->aliaskind != AK_REFCOUNTED
7483 && s->aliaskind != AK_REFS)
7486 s->aliaskind = s->oaliaskind;
7492 sRef_clearDerived (s);
7498 sRef_resetStateComplete (sRef s)
7500 sRef_innerAliasSetComplete (sRef_resetStateAux, s, fileloc_undefined);
7504 sRef_fixBase (/*@returned@*/ sRef s, /*@returned@*/ sRef base)
7506 sRef tmp = sRef_undefined;
7509 if (sRef_isInvalid (s)) return s;
7510 if (sRef_isInvalid (base)) return base;
7520 tmp = sRef_fixBase (s->info->arrayfetch->arr, base);
7522 if (s->info->arrayfetch->indknown)
7524 ret = sRef_makeArrayFetchKnown (tmp, s->info->arrayfetch->ind);
7528 ret = sRef_makeArrayFetch (tmp);
7532 tmp = sRef_fixBase (s->info->field->rec, base);
7533 ret = sRef_buildNCField (tmp, s->info->field->field);
7536 tmp = sRef_fixBase (s->info->ref, base);
7537 ret = sRef_makePointer (tmp);
7540 tmp = sRef_fixBase (s->info->ref, base);
7541 ret = sRef_makeAddress (tmp);
7547 tmp = sRef_fixBase (s->info->conj->a, base);
7548 tmpb = sRef_fixBase (s->info->conj->b, base);
7550 ret = sRef_makeConj (tmp, tmpb);
7559 static /*@exposed@*/ sRef
7560 sRef_fixDirectBase (sRef s, sRef base)
7565 if (sRef_isInvalid (s))
7567 return sRef_undefined;
7573 if (s->info->arrayfetch->indknown)
7575 ret = sRef_makeArrayFetchKnown (base, s->info->arrayfetch->ind);
7579 ret = sRef_makeArrayFetch (base);
7583 ret = sRef_buildNCField (base, s->info->field->field);
7586 ret = sRef_makePointer (base);
7589 ret = sRef_makeAddress (base);
7595 tmpa = sRef_fixDirectBase (s->info->conj->a, base);
7596 tmpb = sRef_fixDirectBase (s->info->conj->b, base);
7598 ret = sRef_makeConj (tmpa, tmpb);
7604 sRef_copyState (ret, s);
7609 sRef_isAllocIndexRef (sRef s)
7611 return (sRef_isArrayFetch (s) && !(s->info->arrayfetch->indknown)
7612 && sRef_isAllocated (s->info->arrayfetch->arr));
7616 sRef_showRefLost (sRef s)
7618 if (sRef_hasAliasInfoLoc (s))
7620 llgenindentmsg (cstring_makeLiteral ("Original reference lost"),
7621 sRef_getAliasInfoLoc (s));
7626 sRef_showRefKilled (sRef s)
7628 if (sRef_hasStateInfoLoc (s))
7630 llgenindentmsg (message ("Storage %q released",
7631 sRef_unparse (s)), sRef_getStateInfoLoc (s));
7636 sRef_showStateInconsistent (sRef s)
7638 if (sRef_hasStateInfoLoc (s))
7641 (message ("Storage %qbecomes inconsistent (released on one branch)",
7642 sRef_unparseOpt (s)),
7643 sRef_getStateInfoLoc (s));
7648 sRef_showStateInfo (sRef s)
7650 if (sRef_hasStateInfoLoc (s))
7652 if (s->defstate == SS_DEAD)
7655 (message ("Storage %qis released", sRef_unparseOpt (s)),
7656 sRef_getStateInfoLoc (s));
7658 else if (s->defstate == SS_ALLOCATED || s->defstate == SS_DEFINED)
7661 (message ("Storage %qis %s", sRef_unparseOpt (s),
7662 sstate_unparse (s->defstate)),
7663 sRef_getStateInfoLoc (s));
7665 else if (s->defstate == SS_UNUSEABLE)
7668 (message ("Storage %qbecomes inconsistent (clauses merge with"
7669 "%qreleased on one branch)",
7670 sRef_unparseOpt (s),
7671 sRef_unparseOpt (s)),
7672 sRef_getStateInfoLoc (s));
7676 llgenindentmsg (message ("Storage %qbecomes %s",
7677 sRef_unparseOpt (s),
7678 sstate_unparse (s->defstate)),
7679 sRef_getStateInfoLoc (s));
7685 sRef_showExpInfo (sRef s)
7687 if (sRef_hasExpInfoLoc (s))
7689 llgenindentmsg (message ("Storage %qbecomes %s", sRef_unparseOpt (s),
7690 exkind_unparse (s->expkind)),
7691 sRef_getExpInfoLoc (s));
7696 sRef_showMetaStateInfo (sRef s, cstring key)
7699 metaStateInfo minfo = context_lookupMetaStateInfo (key);
7701 llassert (sRef_isValid (s));
7702 llassert (valueTable_isDefined (s->state));
7703 llassert (metaStateInfo_isDefined (minfo));
7705 val = valueTable_lookup (s->state, key);
7707 if (stateValue_hasLoc (val))
7710 (message ("%qbecomes %q", sRef_unparseOpt (s),
7711 stateValue_unparseValue (val, minfo)),
7712 stateValue_getLoc (val));
7717 sRef_showNullInfo (sRef s)
7719 DPRINTF (("Show null info: %s", sRef_unparseFull (s)));
7721 if (sRef_hasNullInfoLoc (s) && sRef_isKnown (s))
7723 DPRINTF (("has null info: %s",
7724 fileloc_unparse (sRef_getNullInfoLoc (s))));
7726 switch (sRef_getNullState (s))
7730 fileloc loc = sRef_getNullInfoLoc (s);
7732 if (fileloc_isDefined (loc) && !fileloc_isLib (loc))
7735 (message ("Storage %qbecomes null", sRef_unparseOpt (s)),
7742 fileloc loc = sRef_getNullInfoLoc (s);
7744 if (fileloc_isDefined (loc) && !fileloc_isLib (loc))
7746 llgenindentmsg (message ("Storage %qbecomes null", sRef_unparseOpt (s)),
7754 (message ("Storage %qmay become null", sRef_unparseOpt (s)),
7755 sRef_getNullInfoLoc (s));
7760 (message ("Storage %qbecomes not null", sRef_unparseOpt (s)),
7761 sRef_getNullInfoLoc (s));
7765 (message ("Storage %qnull state becomes unknown",
7766 sRef_unparseOpt (s)),
7767 sRef_getNullInfoLoc (s));
7776 (message ("<error case> Storage %q becomes %s",
7778 nstate_unparse (sRef_getNullState (s))),
7779 sRef_getNullInfoLoc (s));
7787 sRef_showAliasInfo (sRef s)
7789 if (sRef_hasAliasInfoLoc (s))
7791 if (sRef_isFresh (s))
7794 (message ("Fresh storage %qallocated", sRef_unparseOpt (s)),
7795 sRef_getAliasInfoLoc (s));
7799 if (!sRef_isRefCounted (s))
7802 (message ("Storage %qbecomes %s",
7803 sRef_unparseOpt (s),
7804 alkind_unparse (sRef_getAliasKind (s))),
7805 sRef_getAliasInfoLoc (s));
7812 sRef_mergeNullState (sRef s, nstate n)
7814 if (sRef_isValid (s))
7818 old = sRef_getNullState (s);
7820 if (n != old && n != NS_UNKNOWN)
7822 sRef_setNullState (s, n, g_currentloc);
7827 llbuglit ("sRef_mergeNullState: invalid");
7832 sRef_possiblyNull (sRef s)
7834 if (sRef_isValid (s))
7836 if (sRef_getNullState (s) == NS_ABSNULL)
7838 ctype rct = ctype_realType (s->type);
7840 if (ctype_isAbstract (rct))
7846 if (ctype_isUser (rct))
7848 uentry ue = usymtab_getTypeEntry (ctype_typeId (rct));
7850 return (nstate_possiblyNull
7851 (sRef_getNullState (uentry_getSref (ue))));
7861 return nstate_possiblyNull (sRef_getNullState (s));
7869 sRef_getScopeName (sRef s)
7871 sRef base = sRef_getRootBase (s);
7873 if (sRef_isRealGlobal (base))
7875 return (cstring_makeLiteralTemp ("Global"));
7877 else if (sRef_isFileStatic (base))
7879 return (cstring_makeLiteralTemp ("Static"));
7883 return (cstring_makeLiteralTemp ("Local"));
7888 sRef_unparseScope (sRef s)
7890 sRef base = sRef_getRootBase (s);
7892 if (sRef_isRealGlobal (base))
7894 return (cstring_makeLiteralTemp ("global"));
7896 else if (sRef_isFileStatic (base))
7898 return (cstring_makeLiteralTemp ("file static"));
7907 sRef_getScope (sRef s)
7909 llassert (sRef_isValid (s));
7911 if (sRef_isCvar (s))
7913 return s->info->cvar->lexlevel;
7915 else if (sRef_isParam (s))
7926 sRef_isDead (sRef s)
7928 return (sRef_isValid (s) && (s)->defstate == SS_DEAD);
7932 sRef_isDeadStorage (sRef s)
7934 if (sRef_isValid (s))
7936 if (s->defstate == SS_DEAD
7937 || s->defstate == SS_UNUSEABLE
7938 || s->defstate == SS_UNDEFINED
7939 || s->defstate == SS_UNKNOWN)
7945 return (sRef_isDefinitelyNull (s));
7955 sRef_isPossiblyDead (sRef s)
7957 return (sRef_isValid (s) && s->defstate == SS_HOFFA);
7960 bool sRef_isStateLive (sRef s)
7962 if (sRef_isValid (s))
7964 sstate ds = s->defstate;
7966 return (!(ds == SS_UNDEFINED
7968 || ds == SS_UNUSEABLE
7969 || ds == SS_HOFFA));
7978 bool sRef_isStateUndefined (sRef s)
7980 return ((sRef_isValid(s)) && ((s)->defstate == SS_UNDEFINED));
7983 bool sRef_isJustAllocated (sRef s)
7985 if (sRef_isAllocated (s))
7987 sRefSet_allElements (s->deriv, el)
7989 if (!(sRef_isStateUndefined (el) || sRef_isUnuseable (el)))
7993 } end_sRefSet_allElements ;
8002 sRef_isAllocatedStorage (sRef s)
8004 if (sRef_isValid (s) && ynm_toBoolStrict (sRef_isValidLvalue (s)))
8006 return (ctype_isVisiblySharable (sRef_getType (s)));
8015 sRef_isUnuseable (sRef s)
8017 return ((sRef_isValid(s)) && ((s)->defstate == SS_UNUSEABLE));
8021 sRef_perhapsNull (sRef s)
8023 if (sRef_isValid (s))
8025 if (sRef_getNullState (s) == NS_ABSNULL)
8027 ctype rct = ctype_realType (s->type);
8029 if (ctype_isAbstract (rct))
8035 if (ctype_isUser (rct))
8037 uentry ue = usymtab_getTypeEntry (ctype_typeId (rct));
8039 return (nstate_perhapsNull
8040 (sRef_getNullState (uentry_getSref (ue))));
8050 return nstate_perhapsNull (sRef_getNullState (s));
8058 ** definitelyNull --- called when TRUE is good
8062 sRef_definitelyNull (sRef s)
8064 return (sRef_isValid (s)
8065 && (sRef_getNullState (s) == NS_DEFNULL || sRef_getNullState (s) == NS_CONSTNULL));
8069 ** based on sRef_similar
8073 sRef_setDerivNullState (sRef set, sRef guide, nstate ns)
8075 if (sRef_isValid (set))
8077 sRef deriv = sRef_getDeriv (set, guide);
8079 if (sRef_isValid (deriv))
8081 sRef_setNullStateN (deriv, ns);
8086 static /*@exposed@*/ sRef
8087 sRef_getDeriv (/*@returned@*/ /*@notnull@*/ sRef set, sRef guide)
8089 llassert (sRef_isValid (set));
8090 llassert (sRef_isValid (guide));
8092 switch (guide->kind)
8095 llassert (set->kind == SK_CVAR);
8100 llassert (set->kind == guide->kind);
8101 llassert (set->info->paramno == guide->info->paramno);
8107 if (set->kind == SK_ARRAYFETCH
8108 && (sRef_similar (set->info->arrayfetch->arr,
8109 guide->info->arrayfetch->arr)))
8115 return (sRef_makeAnyArrayFetch
8116 (sRef_getDeriv (set, guide->info->arrayfetch->arr)));
8121 if (set->kind == SK_PTR && sRef_similar (set->info->ref, guide->info->ref))
8127 return (sRef_makePointer (sRef_getDeriv (set, guide->info->ref)));
8132 if ((set->kind == SK_FIELD &&
8133 (sRef_similar (set->info->field->rec, guide->info->field->rec) &&
8134 cstring_equal (set->info->field->field, guide->info->field->field))))
8140 return (sRef_makeField (sRef_getDeriv (set, guide->info->field->rec),
8141 guide->info->field->field));
8145 if ((set->kind == SK_ADR) && sRef_similar (set->info->ref, guide->info->ref))
8151 return (sRef_makeAddress (sRef_getDeriv (set, guide->info->ref)));
8156 return sRef_undefined;
8160 case SK_UNCONSTRAINED:
8168 return sRef_undefined;
8175 ** sRef_aliasCheckPred
8177 ** A confusing but spiffy function:
8179 ** Calls predf (s, e, text, <alias>) on s and all of s's aliases
8180 ** (unless checkAliases (s) is FALSE).
8182 ** For alias calls, calls as
8183 ** predf (alias, e, text, s)
8187 sRef_aliasCheckPred (bool (predf) (sRef, exprNode, sRef, exprNode),
8188 /*@null@*/ bool (checkAliases) (sRef),
8189 sRef s, exprNode e, exprNode err)
8191 bool error = (*predf)(s, e, sRef_undefined, err);
8194 if (checkAliases != NULL && !(checkAliases (s)))
8196 /* don't check aliases */
8200 sRefSet aliases = usymtab_allAliases (s);
8202 sRefSet_realElements (aliases, current)
8204 if (sRef_isValid (current))
8206 if (!sRef_similar (current, s)
8207 || (error && sRef_sameName (current, s)))
8209 (void) (*predf)(current, e, s, err);
8212 } end_sRefSet_realElements;
8214 sRefSet_free (aliases);
8219 ** return TRUE iff predf (s) is true for s or any alias of s
8223 sRef_aliasCheckSimplePred (sRefTest predf, sRef s)
8234 aliases = usymtab_allAliases (s);
8236 sRefSet_realElements (aliases, current)
8238 if (sRef_isValid (current))
8240 sRef cref = sRef_updateSref (current);
8242 /* Whoa! a very kludgey way to make sure the right sref is used
8243 ** where there is a conditional symbol table. I am beginning
8244 ** to think that having a conditional symbol table wasn't such
8250 DPRINTF (("Checking alias: %s", sRef_unparseFull (cref)));
8251 sRefSet_free (aliases);
8255 } end_sRefSet_realElements;
8257 sRefSet_free (aliases);
8263 sRef_aliasCompleteSimplePred (bool (predf) (sRef), sRef s)
8266 bool result = FALSE;
8269 aliases = usymtab_allAliases (s);
8271 if ((*predf)(s)) result = TRUE;
8274 sRefSet_realElements (aliases, current)
8276 if (sRef_isValid (current))
8278 current = sRef_updateSref (current);
8279 if ((*predf)(current)) result = TRUE;
8281 } end_sRefSet_realElements;
8283 sRefSet_free (aliases);
8288 sRef_aliasSetComplete (void (predf) (sRef, fileloc), sRef s, fileloc loc)
8292 aliases = usymtab_allAliases (s);
8294 DPRINTF (("All aliases: %s", sRefSet_unparseFull (aliases)));
8298 sRefSet_realElements (aliases, current)
8300 if (sRef_isValid (current))
8302 current = sRef_updateSref (current);
8303 ((*predf)(current, loc));
8305 } end_sRefSet_realElements;
8307 sRefSet_free (aliases);
8311 sRef_aliasSetCompleteParam (void (predf) (sRef, int, fileloc), sRef s,
8312 int kind, fileloc loc)
8316 if (sRef_isDeep (s))
8318 aliases = usymtab_allAliases (s);
8322 aliases = usymtab_aliasedBy (s);
8325 (*predf)(s, kind, loc);
8327 sRefSet_realElements (aliases, current)
8329 if (sRef_isValid (current))
8331 current = sRef_updateSref (current);
8332 ((*predf)(current, kind, loc));
8334 } end_sRefSet_realElements;
8336 sRefSet_free (aliases);
8340 ** Version of aliasSetCompleteParam for alkind parameters
8344 sRef_aliasSetCompleteAlkParam (void (predf) (sRef, alkind, fileloc), sRef s,
8345 alkind kind, fileloc loc)
8349 if (sRef_isDeep (s))
8351 aliases = usymtab_allAliases (s);
8355 aliases = usymtab_aliasedBy (s);
8358 (*predf)(s, kind, loc);
8360 sRefSet_realElements (aliases, current)
8362 if (sRef_isValid (current))
8364 current = sRef_updateSref (current);
8365 ((*predf)(current, kind, loc));
8367 } end_sRefSet_realElements;
8369 sRefSet_free (aliases);
8373 sRef_innerAliasSetComplete (void (predf) (sRef, fileloc), sRef s, fileloc loc)
8379 if (!sRef_isValid (s)) return;
8382 ** Type equivalence checking is necessary --- there might be casting.
8389 case SK_UNCONSTRAINED:
8394 inner = s->info->ref;
8395 aliases = usymtab_allAliases (inner);
8396 ct = sRef_getType (inner);
8398 sRefSet_realElements (aliases, current)
8400 if (sRef_isValid (current))
8402 current = sRef_updateSref (current);
8404 if (ctype_equal (ct, sRef_getType (current)))
8406 sRef ptr = sRef_makePointer (current);
8407 ((*predf)(ptr, loc));
8410 } end_sRefSet_realElements;
8412 sRefSet_free (aliases);
8415 inner = s->info->arrayfetch->arr;
8416 aliases = usymtab_allAliases (inner);
8417 ct = sRef_getType (inner);
8419 DPRINTF (("Array fetch: %s", sRefSet_unparse (aliases)));
8421 sRefSet_realElements (aliases, current)
8423 if (sRef_isValid (current))
8425 current = sRef_updateSref (current);
8426 DPRINTF (("Current: %s", sRef_unparseFull (current)));
8428 if (ctype_equal (ct, sRef_getType (current)))
8430 if (s->info->arrayfetch->indknown)
8432 sRef af = sRef_makeArrayFetchKnown (current, s->info->arrayfetch->ind);
8433 DPRINTF (("Defining: %s", sRef_unparseFull (af)));
8434 /* evans 2001-08-27 This isn't true:
8435 llassert (af->info->arrayfetch->arr == current);
8436 see comments in buildArrayFetchKnown
8438 ((*predf)(af, loc));
8442 sRef af = sRef_makeArrayFetch (current);
8443 /* evans 2001-08-27 This isn't true:
8444 llassert (af->info->arrayfetch->arr == current);
8445 see comments in buildArrayFetch
8447 DPRINTF (("Defining: %s", sRef_unparseFull (af)));
8448 ((*predf)(af, loc));
8453 DPRINTF (("Type mismatch: %s / %s",
8455 ctype_unparse (sRef_getType (current))));
8458 } end_sRefSet_realElements;
8460 sRefSet_free (aliases);
8463 inner = s->info->field->rec;
8464 aliases = usymtab_allAliases (inner);
8465 ct = sRef_getType (inner);
8468 sRefSet_realElements (aliases, current)
8470 if (sRef_isValid (current))
8472 current = sRef_updateSref (current);
8474 if (ctype_equal (ct, sRef_getType (current)))
8476 sRef f = sRef_makeField (current, s->info->field->field);
8481 } end_sRefSet_realElements;
8483 sRefSet_free (aliases);
8486 sRef_innerAliasSetComplete (predf, s->info->conj->a, loc);
8487 sRef_innerAliasSetComplete (predf, s->info->conj->b, loc);
8504 sRef_innerAliasSetCompleteParam (void (predf) (sRef, sRef), sRef s, sRef t)
8510 if (!sRef_isValid (s)) return;
8513 ** Type equivalence checking is necessary --- there might be casting.
8520 case SK_UNCONSTRAINED:
8525 inner = s->info->ref;
8526 aliases = usymtab_allAliases (inner);
8527 ct = sRef_getType (inner);
8530 sRefSet_realElements (aliases, current)
8532 if (sRef_isValid (current))
8534 current = sRef_updateSref (current);
8536 if (ctype_equal (ct, sRef_getType (current)))
8538 sRef ptr = sRef_makePointer (current);
8543 } end_sRefSet_realElements;
8545 sRefSet_free (aliases);
8548 inner = s->info->arrayfetch->arr;
8549 aliases = usymtab_allAliases (inner);
8550 ct = sRef_getType (inner);
8552 sRefSet_realElements (aliases, current)
8554 if (sRef_isValid (current))
8556 current = sRef_updateSref (current);
8558 if (ctype_equal (ct, sRef_getType (current)))
8561 if (s->info->arrayfetch->indknown)
8563 sRef af = sRef_makeArrayFetchKnown (current, s->info->arrayfetch->ind);
8569 sRef af = sRef_makeArrayFetch (current);
8575 } end_sRefSet_realElements;
8577 sRefSet_free (aliases);
8580 inner = s->info->field->rec;
8581 aliases = usymtab_allAliases (inner);
8582 ct = sRef_getType (inner);
8585 sRefSet_realElements (aliases, current)
8587 if (sRef_isValid (current))
8589 current = sRef_updateSref (current);
8591 if (ctype_equal (ct, sRef_getType (current)))
8593 sRef f = sRef_makeField (current, s->info->field->field);
8598 } end_sRefSet_realElements;
8600 sRefSet_free (aliases);
8603 sRef_innerAliasSetCompleteParam (predf, s->info->conj->a, t);
8604 sRef_innerAliasSetCompleteParam (predf, s->info->conj->b, t);
8620 static void sRef_combineExKinds (/*@notnull@*/ sRef res, /*@notnull@*/ sRef other)
8622 exkind a1 = sRef_getExKind (res);
8623 exkind a2 = sRef_getExKind (other);
8625 if (a1 == a2 || a2 == XO_UNKNOWN)
8629 else if (a1 == XO_UNKNOWN)
8631 res->expinfo = stateInfo_update (res->expinfo, other->expinfo);
8636 res->expkind = XO_OBSERVER;
8641 ** Currently, this is a very ad hoc implementation, with lots of fixes to
8642 ** make real code work okay. I need to come up with some more general
8643 ** rules or principles here.
8647 sRef_combineAliasKindsError (/*@notnull@*/ sRef res,
8648 /*@notnull@*/ sRef other,
8649 clause cl, fileloc loc)
8651 bool hasError = FALSE;
8652 alkind ares = sRef_getAliasKind (res);
8653 alkind aother = sRef_getAliasKind (other);
8655 sRef_checkMutable (res);
8657 if (alkind_isDependent (ares))
8659 if (aother == AK_KEPT)
8661 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8662 res->aliaskind = AK_KEPT;
8666 if (aother == AK_LOCAL || aother == AK_STATIC
8667 || alkind_isTemp (aother))
8669 DPRINTF (("Setting dependent: %s", sRef_unparseFull (res)));
8670 res->aliaskind = AK_DEPENDENT;
8674 else if (alkind_isDependent (aother))
8676 if (ares == AK_KEPT)
8678 res->aliaskind = AK_KEPT;
8682 if (ares == AK_LOCAL || ares == AK_STATIC || alkind_isTemp (ares))
8684 DPRINTF (("Setting dependent: %s", sRef_unparseFull (res)));
8685 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8686 res->aliaskind = AK_DEPENDENT;
8690 else if ((ares == AK_LOCAL || ares == AK_UNIQUE
8691 || ares == AK_STATIC || alkind_isTemp (ares))
8692 && sRef_isFresh (other))
8695 ** cases like: if (s == NULL) s = malloc...;
8696 ** don't generate errors
8699 if (usymtab_isAltDefinitelyNullDeep (res))
8701 res->aliaskind = ares;
8708 else if ((aother == AK_LOCAL || aother == AK_UNIQUE
8709 || aother == AK_STATIC || alkind_isTemp (aother))
8710 && sRef_isFresh (res))
8713 ** cases like: if (s == NULL) s = malloc...;
8714 ** don't generate errors
8717 if (usymtab_isDefinitelyNullDeep (other))
8719 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8720 res->aliaskind = aother;
8727 else if (ares == AK_NEWREF && aother == AK_REFCOUNTED
8728 && sRef_isConst (other))
8730 res->aliaskind = AK_NEWREF;
8732 else if (aother == AK_NEWREF && ares == AK_REFCOUNTED
8733 && sRef_isConst (res))
8735 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8736 res->aliaskind = AK_NEWREF;
8738 else if (sRef_isLocalVar (res)
8739 && ((ares == AK_KEPT && aother == AK_LOCAL)
8740 || (aother == AK_KEPT && ares == AK_LOCAL)))
8742 res->aliaskind = AK_KEPT;
8751 if (sRef_isThroughArrayFetch (res))
8754 (FLG_BRANCHSTATE, FLG_STRICTBRANCHSTATE,
8756 ("Clauses exit with %q possibly 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);
8767 res->aliaskind = AK_ERROR;
8771 if (ares == AK_KEPT || aother == AK_KEPT)
8773 sRef_maybeKill (res, loc);
8781 message ("Clauses exit with %q referencing %s storage %s, "
8784 alkind_unparse (aother),
8785 clause_nameTaken (cl),
8786 alkind_unparse (ares),
8787 clause_nameAlternate (cl)),
8790 sRef_showAliasInfo (res);
8791 sRef_showAliasInfo (other);
8793 res->aliaskind = AK_ERROR;
8797 res->aliaskind = (sRef_isLocalVar (res) ? AK_LOCAL : AK_UNKNOWN);
8802 sRef_combineAliasKinds (/*@notnull@*/ sRef res, /*@notnull@*/ sRef other,
8803 clause cl, fileloc loc)
8805 alkind ares = sRef_getAliasKind (res);
8806 alkind aother = sRef_getAliasKind (other);
8808 sRef_checkMutable (res);
8810 DPRINTF (("Combine alias kinds: \n\t%s / \n\t%s",
8811 sRef_unparseFull (res), sRef_unparseFull (other)));
8812 if (alkind_equal (ares, aother)
8813 || aother == AK_UNKNOWN
8814 || aother == AK_ERROR)
8816 ; /* keep current state */
8818 else if (sRef_isDead (res) || sRef_isDead (other))
8820 /* dead error reported (or storage is dead) */
8821 res ->aliaskind = AK_ERROR;
8823 else if (ares == AK_UNKNOWN || ares == AK_ERROR
8824 || sRef_isStateUndefined (res)
8825 || sRef_isDefinitelyNull (res))
8827 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8828 res->aliaskind = aother;
8830 else if (sRef_isStateUndefined (other)
8831 || sRef_isDefinitelyNull (other))
8835 else if (((ares == AK_UNIQUE || alkind_isTemp (ares))
8836 && aother == AK_LOCAL)
8837 || ((aother == AK_UNIQUE || alkind_isTemp (aother))
8838 && ares == AK_LOCAL))
8840 if (ares != AK_LOCAL)
8842 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8845 res->aliaskind = AK_LOCAL;
8847 else if ((ares == AK_OWNED && aother == AK_FRESH)
8848 || (aother == AK_OWNED && ares == AK_FRESH))
8850 if (ares != AK_FRESH)
8852 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8855 res->aliaskind = AK_FRESH;
8857 else if ((ares == AK_KEEP && aother == AK_FRESH) ||
8858 (aother == AK_KEEP && ares == AK_FRESH))
8860 if (ares != AK_KEEP)
8862 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8865 res->aliaskind = AK_KEEP;
8867 else if ((ares == AK_LOCAL && aother == AK_STACK) ||
8868 (aother == AK_LOCAL && ares == AK_STACK))
8870 if (ares != AK_STACK)
8872 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8875 res->aliaskind = AK_STACK;
8877 else if ((ares == AK_LOCAL
8878 && (aother == AK_OWNED && sRef_isLocalVar (other)))
8879 || (aother == AK_LOCAL
8880 && (ares == AK_OWNED && sRef_isLocalVar (res))))
8882 if (ares != AK_LOCAL)
8884 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8887 res->aliaskind = AK_LOCAL;
8889 else if ((ares == AK_FRESH && alkind_isOnly (aother))
8890 || (aother == AK_FRESH && alkind_isOnly (ares)))
8892 res->aliaskind = AK_FRESH;
8894 else if ((aother == AK_FRESH && sRef_definitelyNull (res))
8895 || (ares == AK_FRESH && sRef_definitelyNull (other)))
8897 if (ares != AK_FRESH)
8899 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8900 res->aliaskind = AK_FRESH;
8903 else if ((sRef_isFresh (res) && sRef_isConst (other))
8904 || (sRef_isFresh (other) && sRef_isConst (res)))
8907 ** for NULL constantants
8911 if (!sRef_isFresh (res))
8913 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8916 res->aliaskind = AK_FRESH;
8918 else if ((alkind_isStatic (aother) && sRef_isConst (res))
8919 || (alkind_isStatic (ares) && sRef_isConst (other)))
8921 if (!alkind_isStatic (ares))
8923 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8924 res->aliaskind = AK_STATIC;
8929 sRef_combineAliasKindsError (res, other, cl, loc);
8933 static void sRef_combineDefState (/*@notnull@*/ sRef res,
8934 /*@notnull@*/ sRef other)
8936 sstate s1 = res->defstate;
8937 sstate s2 = other->defstate;
8940 sRef_checkMutable (res);
8942 if (s1 == s2 || s2 == SS_UNKNOWN)
8946 else if (s1 == SS_UNKNOWN)
8955 if (s2 == SS_DEFINED)
8961 llcontbuglit ("ssfixed: not implemented");
8970 flip = (s2 != SS_DEFINED);
8988 res->definfo = stateInfo_update (res->definfo, other->definfo);
8993 extern /*@notnull@*/ sRef sRef_getConjA (sRef s)
8996 llassert (sRef_isConj (s));
8998 ret = s->info->conj->a;
8999 llassert (ret != NULL);
9003 extern /*@notnull@*/ sRef sRef_getConjB (sRef s)
9006 llassert (sRef_isConj (s));
9008 ret = s->info->conj->b;
9009 llassert (ret != NULL);
9013 extern /*@exposed@*/ sRef sRef_makeArrow (sRef s, /*@dependent@*/ cstring f)
9018 p = sRef_makePointer (s);
9019 ret = sRef_makeField (p, f);
9020 DPRINTF (("Arrow: %s => %s",
9021 sRef_unparseFull (s), sRef_unparseFull (ret)));
9025 extern /*@exposed@*/ sRef sRef_buildArrow (sRef s, cstring f)
9030 p = sRef_buildPointer (s);
9031 ret = sRef_buildField (p, f);
9036 static /*@null@*/ sinfo sinfo_copy (/*@notnull@*/ sRef s)
9043 ret = (sinfo) dmalloc (sizeof (*ret));
9044 ret->cvar = (cref) dmalloc (sizeof (*ret->cvar));
9045 ret->cvar->lexlevel = s->info->cvar->lexlevel;
9046 ret->cvar->index = s->info->cvar->index;
9050 ret = (sinfo) dmalloc (sizeof (*ret));
9051 ret->paramno = s->info->paramno;
9052 llassert (ret->paramno >= -1);
9056 ret = (sinfo) dmalloc (sizeof (*ret));
9057 ret->arrayfetch = (ainfo) dmalloc (sizeof (*ret->arrayfetch));
9058 ret->arrayfetch->indknown = s->info->arrayfetch->indknown;
9059 ret->arrayfetch->ind = s->info->arrayfetch->ind;
9060 ret->arrayfetch->arr = s->info->arrayfetch->arr; /* sRef_copy (s->info->arrayfetch->arr); */ /*@i32@*/
9064 ret = (sinfo) dmalloc (sizeof (*ret));
9065 ret->field = (fldinfo) dmalloc (sizeof (*ret->field));
9066 ret->field->rec = s->info->field->rec; /* sRef_copy (s->info->field->rec); */ /*@i32@*/
9067 ret->field->field = s->info->field->field;
9071 ret = (sinfo) dmalloc (sizeof (*ret));
9072 ret->object = s->info->object;
9079 ret = (sinfo) dmalloc (sizeof (*ret));
9080 ret->ref = s->info->ref; /* Ref_copy (s->info->ref); */
9084 ret = (sinfo) dmalloc (sizeof (*ret));
9085 ret->conj = (cjinfo) dmalloc (sizeof (*ret->conj));
9086 ret->conj->a = s->info->conj->a; /* sRef_copy (s->info->conj->a); */
9087 ret->conj->b = s->info->conj->b; /* sRef_copy (s->info->conj->b);*/
9090 ret = (sinfo) dmalloc (sizeof (*ret));
9091 ret->spec = s->info->spec;
9093 case SK_UNCONSTRAINED:
9095 ret = (sinfo) dmalloc (sizeof (*ret));
9096 ret->fname = s->info->fname;
9102 llassertprint (s->info == NULL, ("s = %s", sRef_unparse (s)));
9110 static /*@null@*/ sinfo sinfo_fullCopy (/*@notnull@*/ sRef s)
9115 ** Since its a full copy, only storage is assigned
9116 ** to dependent fields.
9123 ret = (sinfo) dmalloc (sizeof (*ret));
9124 ret->cvar = (cref) dmalloc (sizeof (*ret->cvar));
9125 ret->cvar->lexlevel = s->info->cvar->lexlevel;
9126 ret->cvar->index = s->info->cvar->index;
9130 ret = (sinfo) dmalloc (sizeof (*ret));
9131 ret->paramno = s->info->paramno;
9132 llassert (ret->paramno >= -1);
9136 ret = (sinfo) dmalloc (sizeof (*ret));
9137 ret->arrayfetch = (ainfo) dmalloc (sizeof (*ret->arrayfetch));
9138 ret->arrayfetch->indknown = s->info->arrayfetch->indknown;
9139 ret->arrayfetch->ind = s->info->arrayfetch->ind;
9140 ret->arrayfetch->arr = sRef_saveCopy (s->info->arrayfetch->arr);
9144 ret = (sinfo) dmalloc (sizeof (*ret));
9145 ret->field = (fldinfo) dmalloc (sizeof (*ret->field));
9146 ret->field->rec = sRef_saveCopy (s->info->field->rec);
9147 ret->field->field = s->info->field->field;
9151 ret = (sinfo) dmalloc (sizeof (*ret));
9152 ret->object = s->info->object;
9159 ret = (sinfo) dmalloc (sizeof (*ret));
9160 ret->ref = sRef_saveCopy (s->info->ref);
9164 ret = (sinfo) dmalloc (sizeof (*ret));
9165 ret->conj = (cjinfo) dmalloc (sizeof (*ret->conj));
9166 ret->conj->a = sRef_saveCopy (s->info->conj->a);
9167 ret->conj->b = sRef_saveCopy (s->info->conj->b);
9170 ret = (sinfo) dmalloc (sizeof (*ret));
9171 ret->spec = s->info->spec;
9174 case SK_UNCONSTRAINED:
9175 ret = (sinfo) dmalloc (sizeof (*ret));
9176 ret->fname = s->info->fname;
9182 llassert (s->info == NULL);
9192 sinfo_update (/*@notnull@*/ /*@exposed@*/ sRef res,
9193 /*@notnull@*/ /*@exposed@*/ sRef other)
9195 llassert (res->kind == other->kind);
9200 res->info->cvar->lexlevel = other->info->cvar->lexlevel;
9201 res->info->cvar->index = other->info->cvar->index;
9205 res->info->paramno = other->info->paramno;
9206 llassert (res->info->paramno >= -1);
9210 res->info->arrayfetch->indknown = other->info->arrayfetch->indknown;
9211 res->info->arrayfetch->ind = other->info->arrayfetch->ind;
9212 res->info->arrayfetch->arr = other->info->arrayfetch->arr;
9216 res->info->field->rec = other->info->field->rec;
9217 res->info->field->field = other->info->field->field;
9221 res->info->object = other->info->object;
9228 res->info->ref = other->info->ref;
9232 res->info->conj->a = other->info->conj->a;
9233 res->info->conj->b = other->info->conj->b;
9237 res->info->spec = other->info->spec;
9241 case SK_UNCONSTRAINED:
9242 res->info->fname = other->info->fname;
9249 llassert (res->info == NULL);
9254 static void sinfo_free (/*@special@*/ /*@temp@*/ /*@notnull@*/ sRef s)
9255 /*@uses s->kind, s->info@*/
9256 /*@releases s->info@*/
9261 DPRINTF (("Free sinfo: [%p]", s->info->cvar));
9262 sfree (s->info->cvar);
9269 DPRINTF (("Free sinfo: [%p]", s->info->arrayfetch));
9270 sfree (s->info->arrayfetch);
9274 DPRINTF (("Free sinfo: [%p]", s->info->field));
9275 sfree (s->info->field);
9284 case SK_EXTERNAL: /*@i32 is copy now! */
9288 DPRINTF (("Free sinfo: [%p]", s->info->conj));
9289 sfree (s->info->conj);
9292 case SK_UNCONSTRAINED:
9302 if (s->info != NULL) {
9303 DPRINTF (("Free sinfo: [%p]", s->info));
9309 bool sRef_isNSLocalVar (sRef s)
9311 if (sRef_isLocalVar (s))
9313 uentry ue = sRef_getUentry (s);
9315 return (!uentry_isStatic (ue));
9323 bool sRef_isLocalVar (sRef s)
9325 if (sRef_isValid(s))
9327 return (s->kind == SK_CVAR
9328 && (s->info->cvar->lexlevel > fileScope));
9334 bool sRef_isRealLocalVar (sRef s)
9336 if (sRef_isValid(s))
9338 if (s->kind == SK_CVAR)
9340 if (s->info->cvar->lexlevel == functionScope)
9342 uentry ue = sRef_getUentry (s);
9344 if (uentry_isAnyParam (ue)
9345 || uentry_isRefParam (ue))
9356 return (s->info->cvar->lexlevel > functionScope);
9364 bool sRef_isLocalParamVar (sRef s)
9366 if (sRef_isValid(s))
9368 return (s->kind == SK_PARAM
9369 || (s->kind == SK_CVAR
9370 && (s->info->cvar->lexlevel > fileScope)));
9376 static speckind speckind_fromInt (int i)
9379 llassert (i >= SR_NOTHING && i <= SR_SYSTEM);
9382 return ((speckind) i);
9386 static void sRef_updateNullState (sRef res, sRef other)
9389 res->nullstate = other->nullstate;
9390 res->nullinfo = stateInfo_update (res->nullinfo, other->nullinfo);
9391 sRef_resetAliasKind (res);
9394 void sRef_combineNullState (/*@notnull@*/ sRef res, /*@notnull@*/ sRef other)
9396 nstate n1 = sRef_getNullState (res);
9397 nstate n2 = sRef_getNullState (other);
9401 if (n1 == n2 || n2 == NS_UNKNOWN)
9407 /* note: n2 is not unknown or defnull */
9411 case NS_ERROR: nn = NS_ERROR; break;
9412 case NS_UNKNOWN: flip = TRUE; nn = n2; break;
9413 case NS_POSNULL: break;
9414 case NS_DEFNULL: nn = NS_POSNULL; break;
9415 case NS_RELNULL: break;
9417 if (n2 == NS_MNOTNULL)
9428 if (n2 == NS_NOTNULL)
9447 res->nullinfo = stateInfo_update (res->nullinfo, other->nullinfo);
9450 res->nullstate = nn;
9451 sRef_resetAliasKind (res);
9454 cstring sRef_nullMessage (sRef s)
9456 llassert (sRef_isValid (s));
9458 switch (sRef_getNullState (s))
9462 return (cstring_makeLiteralTemp ("null"));
9464 return (cstring_makeLiteralTemp ("possibly null"));
9469 /*@observer@*/ cstring sRef_ntMessage (sRef s)
9471 llassert (sRef_isValid (s));
9473 switch (s->nullstate)
9477 return (cstring_makeLiteralTemp ("not nullterminated"));
9479 return (cstring_makeLiteralTemp ("possibly non-nullterminated"));
9486 sRef sRef_fixResultType (/*@returned@*/ sRef s, ctype typ, uentry ue)
9488 sRef tmp = sRef_undefined;
9491 llassert (sRef_isValid (s));
9502 tmp = sRef_fixResultType (s->info->arrayfetch->arr, typ, ue);
9504 ct = ctype_realType (sRef_getType (tmp));
9507 if (ctype_isKnown (ct))
9509 if (ctype_isAP (ct))
9518 ("Special clause indexes non-array (%t): *%q",
9519 ct, sRef_unparse (s->info->arrayfetch->arr)),
9520 uentry_whereLast (ue));
9524 tmp = sRef_fixResultType (s->info->arrayfetch->arr, typ, ue);
9526 if (s->info->arrayfetch->indknown)
9528 ret = sRef_makeArrayFetchKnown (tmp, s->info->arrayfetch->ind);
9532 ret = sRef_makeArrayFetch (tmp);
9538 sRef rec = sRef_fixResultType (s->info->field->rec, typ, ue);
9539 ctype ct = ctype_realType (sRef_getType (rec));
9541 if (ctype_isKnown (ct))
9543 if (ctype_isSU (ct))
9545 if (uentry_isValid (uentryList_lookupField (ctype_getFields (ct),
9546 s->info->field->field)))
9555 ("Special clause accesses non-existent field of result: %q.%s",
9556 sRef_unparse (rec), s->info->field->field),
9557 uentry_whereLast (ue));
9565 ("Special clause accesses field of non-struct or union result (%t): %q.%s",
9566 ct, sRef_unparse (rec), s->info->field->field),
9567 uentry_whereLast (ue));
9571 ret = sRef_makeField (tmp, s->info->field->field);
9577 tmp = sRef_fixResultType (s->info->ref, typ, ue);
9579 ct = ctype_realType (sRef_getType (tmp));
9581 if (ctype_isKnown (ct))
9583 if (ctype_isAP (ct))
9592 ("Special clause dereferences non-pointer (%t): *%q",
9593 ct, sRef_unparse (s->info->ref)),
9594 uentry_whereLast (ue));
9598 ret = sRef_makePointer (tmp);
9605 ("Special clause uses & operator (not allowed): &%q", sRef_unparse (s->info->ref)),
9606 uentry_whereLast (ue));
9615 bool sRef_isOnly (sRef s)
9617 return (sRef_isValid(s) && alkind_isOnly (s->aliaskind));
9620 bool sRef_isDependent (sRef s)
9622 return (sRef_isValid(s) && alkind_isDependent (s->aliaskind));
9625 bool sRef_isOwned (sRef s)
9627 return (sRef_isValid (s) && (s->aliaskind == AK_OWNED));
9630 bool sRef_isKeep (sRef s)
9632 return (sRef_isValid (s) && (s->aliaskind == AK_KEEP));
9635 bool sRef_isTemp (sRef s)
9637 return (sRef_isValid (s) && alkind_isTemp (s->aliaskind));
9640 bool sRef_isLocalState (sRef s)
9642 return (sRef_isValid (s) && (s->aliaskind == AK_LOCAL));
9645 bool sRef_isUnique (sRef s)
9647 return (sRef_isValid (s) && (s->aliaskind == AK_UNIQUE));
9650 bool sRef_isShared (sRef s)
9652 return (sRef_isValid (s) && (s->aliaskind == AK_SHARED));
9655 bool sRef_isExposed (sRef s)
9657 return (sRef_isValid (s) && (s->expkind == XO_EXPOSED));
9660 bool sRef_isObserver (sRef s)
9662 return (sRef_isValid (s) && (s->expkind == XO_OBSERVER));
9665 bool sRef_isFresh (sRef s)
9667 return (sRef_isValid (s) && (s->aliaskind == AK_FRESH));
9670 bool sRef_isDefinitelyNull (sRef s)
9672 return (sRef_isValid (s) && (sRef_getNullState (s) == NS_DEFNULL
9673 || sRef_getNullState (s) == NS_CONSTNULL));
9676 bool sRef_isAllocated (sRef s)
9678 return (sRef_isValid (s) && (s->defstate == SS_ALLOCATED));
9681 bool sRef_isStack (sRef s)
9683 return (sRef_isValid (s) && (s->aliaskind == AK_STACK));
9686 bool sRef_isNotNull (sRef s)
9688 return (sRef_isValid(s) && (sRef_getNullState (s) == NS_MNOTNULL
9689 || sRef_getNullState (s) == NS_NOTNULL));
9692 alkind sRef_getAliasKind (sRef s)
9694 if (sRef_isValid(s)) {
9695 llassert (alkind_isValid (s->aliaskind));
9696 return s->aliaskind;
9702 nstate sRef_getNullState (sRef s)
9704 if (sRef_isValid (s)) {
9705 llassert (nstate_isValid (s->nullstate));
9706 return s->nullstate;
9712 void sRef_reflectAnnotation (sRef s, annotationInfo a, fileloc loc)
9714 if (sRef_isValid (s))
9716 if (!valueTable_isDefined (s->state))
9718 s->state = valueTable_create (1);
9719 valueTable_insert (s->state,
9720 cstring_copy (metaStateInfo_getName (annotationInfo_getState (a))),
9721 stateValue_create (annotationInfo_getValue (a), stateInfo_makeLoc (loc)));
9725 DPRINTF (("reflect loc: %s", fileloc_unparse (loc)));
9728 metaStateInfo_getName (annotationInfo_getState (a)),
9729 stateValue_create (annotationInfo_getValue (a), stateInfo_makeLoc (loc)));
9730 DPRINTF (("state info: %s", stateInfo_unparse (stateInfo_makeLoc (loc))));
9731 DPRINTF (("sref: %s", sRef_unparse (s)));
9732 DPRINTF (("sref: %s", sRef_unparseFull (s)));
9737 void sRef_setMetaStateValueComplete (sRef s, cstring key, int value, fileloc loc)
9739 sRefSet aliases = usymtab_allAliases (s);
9741 sRef_setMetaStateValue (s, key, value, loc);
9743 sRefSet_realElements (aliases, current)
9745 if (sRef_isValid (current))
9747 current = sRef_updateSref (current);
9748 sRef_setMetaStateValue (current, key, value, loc);
9750 } end_sRefSet_realElements ;
9752 sRefSet_free (aliases);
9755 void sRef_setMetaStateValue (sRef s, cstring key, int value, fileloc loc)
9757 sRef_checkMutable (s);
9759 if (sRef_isValid (s))
9761 if (!valueTable_isDefined (s->state))
9763 DPRINTF (("inserting state: %s: %s %d", sRef_unparse (s), key, value));
9764 s->state = valueTable_create (1);
9765 valueTable_insert (s->state, cstring_copy (key),
9766 stateValue_create (value, stateInfo_makeLoc (loc)));
9770 DPRINTF (("Updating state: %s: %s %d / %s", sRef_unparse (s), key, value,
9771 fileloc_unparse (loc)));
9772 if (valueTable_contains (s->state, key))
9775 (s->state, key, stateValue_create (value, stateInfo_makeLoc (loc)));
9780 (s->state, cstring_copy (key), stateValue_create (value, stateInfo_makeLoc (loc)));
9783 DPRINTF (("After: %s", sRef_unparseFull (s)));
9788 bool sRef_checkMetaStateValue (sRef s, cstring key, int value)
9790 if (sRef_isValid (s))
9792 if (valueTable_isDefined (s->state))
9796 DPRINTF (("check state: %s: %s %d", sRef_unparse (s), key, value));
9798 val = valueTable_lookup (s->state, key);
9799 llassert (stateValue_isDefined (val));
9800 return (stateValue_isError (val)
9801 || stateValue_getValue (val) == value);
9814 /*@observer@*/ stateValue sRef_getMetaStateValue (sRef s, cstring key)
9816 if (sRef_isValid (s))
9818 if (valueTable_isDefined (s->state))
9822 val = valueTable_lookup (s->state, key);
9823 /* Okay if its not defined, just returns stateValue_undefined */
9828 return stateValue_undefined;
9833 return stateValue_undefined;
9837 /*@observer@*/ valueTable sRef_getValueTable (sRef s)
9839 DPRINTF (("Get value table: %s", sRef_unparse (s)));
9841 if (sRef_isValid (s))
9843 llassert (sRef_isValid (s));
9844 DPRINTF (("Value table: %s", valueTable_unparse (s->state)));
9849 DPRINTF (("No value table!"));
9850 return valueTable_undefined;
9854 bool sRef_makeStateSpecial (sRef s)
9857 ** Default defined state can be made special.
9860 llassert (sRef_isValid (s)); /*@i523 why doesn't null-checking work!??? */
9862 if (s->defstate == SS_UNKNOWN || s->defstate == SS_DEFINED || s->defstate == SS_SPECIAL)
9864 /* s->aliaskind = AK_IMPTEMP; */ /* evans 2001-07-23 shouldn't effect alias state */
9865 s->defstate = SS_SPECIAL;
9866 DPRINTF (("Made special: %s", sRef_unparseFull (s)));
9871 /* s->aliaskind = AK_IMPTEMP; */
9872 s->defstate = SS_SPECIAL;
9877 void sRef_markImmutable (sRef s)
9879 if (sRef_isValid (s))
9881 DPRINTF (("Mark immutable: %s", sRef_unparseFull (s)));
9886 bool sRef_definitelyNullContext (sRef s)
9888 return (sRef_definitelyNull (s)
9889 || usymtab_isDefinitelyNullDeep (s));
9892 bool sRef_definitelyNullAltContext (sRef s)
9894 return (sRef_definitelyNull (s)
9895 || usymtab_isAltDefinitelyNullDeep (s));
9899 /* start modifications */
9900 struct s_bbufinfo sRef_getNullTerminatedState (sRef p_s) {
9901 struct s_bbufinfo BUFSTATE_UNKNOWN;
9902 BUFSTATE_UNKNOWN.bufstate = BB_NOTNULLTERMINATED;
9903 BUFSTATE_UNKNOWN.size = 0;
9904 BUFSTATE_UNKNOWN.len = 0;
9906 if (sRef_isValid(p_s))
9907 return p_s->bufinfo;
9908 return BUFSTATE_UNKNOWN;
9911 void sRef_setNullTerminatedState(sRef p_s) {
9912 if(sRef_isValid (p_s)) {
9913 p_s->bufinfo.bufstate = BB_NULLTERMINATED;
9915 llfatalbug( message("sRef_setNT passed a invalid sRef\n"));
9920 void sRef_setPossiblyNullTerminatedState(sRef p_s) {
9921 if( sRef_isValid (p_s)) {
9922 p_s->bufinfo.bufstate = BB_POSSIBLYNULLTERMINATED;
9924 llfatalbug( message("sRef_setPossNT passed a invalid sRef\n"));
9928 void sRef_setNotNullTerminatedState(sRef p_s) {
9929 if( sRef_isValid (p_s)) {
9930 p_s->bufinfo.bufstate = BB_NOTNULLTERMINATED;
9932 llfatalbug( message("sRef_unsetNT passed a invalid sRef\n"));
9936 void sRef_setLen(sRef p_s, int len) {
9937 if( sRef_isValid (p_s) && sRef_isNullTerminated(p_s)) {
9938 p_s->bufinfo.len = len;
9940 llfatalbug( message("sRef_setLen passed a invalid sRef\n"));
9945 void sRef_setSize(sRef p_s, int size) {
9946 if( sRef_isValid(p_s)) {
9947 p_s->bufinfo.size = size;
9949 llfatalbug( message("sRef_setSize passed a invalid sRef\n"));
9953 void sRef_resetLen(sRef p_s) {
9954 if (sRef_isValid (p_s)) {
9955 p_s->bufinfo.len = 0;
9957 llfatalbug (message ("sRef_setLen passed an invalid sRef\n"));
9961 /*drl7x 11/28/2000 */
9963 bool sRef_isFixedArray (sRef p_s) /*@*/ {
9965 c = sRef_getType (p_s);
9966 return ( ctype_isFixedArray (c) );
9969 long int sRef_getArraySize (sRef p_s) /*@*/ {
9971 llassert (sRef_isFixedArray(p_s) );
9972 DPRINTF (( message ("sRef_getArraySize getting array size for %s", sRef_unparse(p_s) ) ));
9974 c = sRef_getType (p_s);
9976 return (ctype_getArraySize (c) );
9979 void sRef_setValue (sRef s, multiVal val)
9981 llassert (sRef_isValid (s));
9982 multiVal_free (s->val);
9986 bool sRef_hasValue (sRef s)
9988 return (sRef_isValid (s)
9989 && multiVal_isDefined (s->val));
9992 multiVal sRef_getValue (sRef s)
9994 if (sRef_isValid (s))
9999 return multiVal_undefined;