2 ** LCLint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2001 University of Virginia,
4 ** Massachusetts Institute of Technology
6 ** This program is free software; you can redistribute it and/or modify it
7 ** under the terms of the GNU General Public License as published by the
8 ** Free Software Foundation; either version 2 of the License, or (at your
9 ** option) any later version.
11 ** This program is distributed in the hope that it will be useful, but
12 ** WITHOUT ANY WARRANTY; without even the implied warranty of
13 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 ** General Public License for more details.
16 ** The GNU General Public License is available from http://www.gnu.org/ or
17 ** the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
18 ** MA 02111-1307, USA.
20 ** For information on lclint: lclint-request@cs.virginia.edu
21 ** To report a bug: lclint-bug@cs.virginia.edu
22 ** For more information: http://lclint.cs.virginia.edu
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) /*@*/ ;
67 sRef_aliasSetComplete (void (p_predf) (sRef, fileloc), sRef p_s, fileloc p_loc)
70 static int sRef_depth (sRef p_s) /*@*/ ;
73 sRef_innerAliasSetComplete (void (p_predf) (sRef, fileloc), sRef p_s,
78 sRef_innerAliasSetCompleteParam (void (p_predf) (sRef, sRef), sRef p_s, sRef p_t)
82 sRef_aliasSetCompleteParam (void (p_predf) (sRef, alkind, fileloc), sRef p_s,
83 alkind p_kind, fileloc p_loc)
86 static speckind speckind_fromInt (int p_i);
87 static bool sRef_equivalent (sRef p_s1, sRef p_s2);
88 static bool sRef_isDeepUnionField (sRef p_s);
89 static void sRef_addDeriv (/*@notnull@*/ sRef p_s, /*@notnull@*/ /*@exposed@*/ sRef p_t);
90 static /*@dependent@*/ sRef sRef_makeResultType (ctype p_ct) /*@*/ ;
91 static bool sRef_checkModify (sRef p_s, sRefSet p_sl) /*@*/ ;
93 static void sRef_checkMutable (/*@unused@*/ sRef s)
96 if (sRef_isValid (s) && s->immut)
98 llcontbug (message ("Modification to sRef marked immutable: %q",
99 sRef_unparseFull (s)));
103 static bool skind_isSimple (skind sk)
107 case SK_PARAM: case SK_CVAR: case SK_CONST:
108 case SK_OBJECT: case SK_UNKNOWN: case SK_NEW:
115 static void sinfo_free (/*@special@*/ /*@temp@*/ /*@notnull@*/ sRef p_s)
116 /*@uses p_s->kind, p_s->info@*/
117 /*@releases p_s->info@*/ ;
119 static /*@null@*/ sinfo sinfo_copy (/*@notnull@*/ sRef p_s) /*@*/ ;
120 static void sRef_setPartsFromUentry (sRef p_s, uentry p_ue)
122 static bool checkDeadState (/*@notnull@*/ sRef p_el, bool p_tbranch, fileloc p_loc);
123 static /*@dependent@*/ sRef sRef_constructPointerAux (/*@notnull@*/ /*@exposed@*/ sRef p_t) /*@*/ ;
126 sRef_combineExKinds (/*@notnull@*/ sRef p_res, /*@notnull@*/ sRef p_other)
127 /*@modifies p_res@*/ ;
130 sRef_combineAliasKinds (/*@notnull@*/ sRef p_res, /*@notnull@*/ sRef p_other,
131 clause p_cl, fileloc p_loc)
132 /*@modifies p_res@*/ ;
135 sRef_combineNullState (/*@notnull@*/ sRef p_res, /*@notnull@*/ sRef p_other)
136 /*@modifies p_res@*/ ;
139 sRef_combineDefState (/*@notnull@*/ sRef p_res, /*@notnull@*/ sRef p_other)
140 /*@modifies p_res@*/ ;
142 static void sRef_setStateFromAbstractUentry (sRef p_s, uentry p_ue)
146 sinfo_update (/*@notnull@*/ /*@exposed@*/ sRef p_res,
147 /*@notnull@*/ /*@exposed@*/ sRef p_other);
148 static void sRef_setDefinedAux (sRef p_s, fileloc p_loc, bool p_clear)
150 static void sRef_setDefinedNoClear (sRef p_s, fileloc p_loc)
152 static void sRef_setStateAux (sRef p_s, sstate p_ss, fileloc p_loc)
155 static /*@exposed@*/ sRef
156 sRef_buildNCField (/*@exposed@*/ sRef p_rec, /*@exposed@*/ cstring p_f);
159 sRef_mergeStateAux (/*@notnull@*/ sRef p_res, /*@notnull@*/ sRef p_other,
160 clause p_cl, bool p_opt, fileloc p_loc,
162 /*@modifies p_res, p_other@*/ ;
164 static /*@null@*/ sinfo sinfo_fullCopy (/*@notnull@*/ sRef p_s);
165 static bool sRef_doModify (sRef p_s, sRefSet p_sl) /*@modifies p_s@*/ ;
166 static bool sRef_doModifyVal (sRef p_s, sRefSet p_sl) /*@modifies p_s@*/;
167 static bool sRef_checkModifyVal (sRef p_s, sRefSet p_sl) /*@*/ ;
169 static /*@only@*/ sRefSet
170 sRef_mergeDerivs (/*@only@*/ sRefSet p_res, sRefSet p_other,
171 bool p_opt, clause p_cl, fileloc p_loc);
173 static /*@only@*/ sRefSet
174 sRef_mergeUnionDerivs (/*@only@*/ sRefSet p_res,
175 /*@exposed@*/ sRefSet p_other,
176 bool p_opt, clause p_cl, fileloc p_loc);
178 static /*@only@*/ sRefSet
179 sRef_mergePdefinedDerivs (/*@only@*/ sRefSet p_res, sRefSet p_other, bool p_opt,
180 clause p_cl, fileloc p_loc);
182 static /*@only@*/ cstring sRef_unparseWithArgs (sRef p_s, uentryList p_args);
183 static /*@only@*/ cstring sRef_unparseNoArgs (sRef p_s);
185 static /*@exposed@*/ sRef sRef_findDerivedPointer (sRef p_s);
186 static /*@exposed@*/ sRef sRef_findDerivedField (/*@notnull@*/ sRef p_rec, cstring p_f);
187 static /*@exposed@*/ sRef
188 sRef_getDeriv (/*@notnull@*/ /*@returned@*/ sRef p_set, sRef p_guide);
190 static bool inFunction = FALSE;
191 static /*@only@*/ sRefTable allRefs;
193 /* # define DEBUGREFS */
197 static totnsrefs = 0;
198 static maxnsrefs = 0;
199 static ntotrefers = 0;
203 static /*@checked@*/ bool protectDerivs = FALSE;
206 ** Result of sRef_alloc is dependent since allRefs may
207 ** reference it. It is only if !inFunction.
210 static /*@dependent@*/ /*@out@*/ /*@notnull@*/ sRef
213 sRef s = (sRef) dmalloc (sizeof (*s));
217 DPRINTF (("Alloc sref: [%p]", s));
221 allRefs = sRefTable_add (allRefs, s);
226 DPRINTF (("Not in function!"));
232 if (nsrefs >= maxnsrefs)
241 /*@-mustfree@*/ /*@-freshtrans@*/
243 /*@=mustfree@*/ /*@=freshtrans@*/
246 static void sRef_checkValidAux (sRef s, sRefSet checkedsofar)
250 if (!sRef_isValid (s)) return;
252 if (sRefSet_containsSameObject (checkedsofar, s))
258 checkedsofar = sRefSet_insert (checkedsofar, s);
259 /*@=temptrans@*/ /* checksofar will be destroyed before checkValid returns */
263 case SK_UNCONSTRAINED:
264 llassert (cstring_length (s->info->fname) < 100);
268 llassert (s->info->cvar->lexlevel >= 0);
269 /* llassert (s->info->cvar->lexlevel <= usymtab_getCurrentDepth ()); */
273 llassert (s->info->paramno >= -1);
274 llassert (s->info->paramno <= 50); /*@i32 bogus...*/
278 sRef_checkValidAux (s->info->arrayfetch->arr, checkedsofar);
282 sRef_checkValidAux (s->info->field->rec, checkedsofar);
283 llassert (cstring_length (s->info->field->field) < 100);
287 sRef_checkValidAux (s->info->ref, checkedsofar);
291 sRef_checkValidAux (s->info->ref, checkedsofar);
295 /* check ctype s->info->object */
299 sRef_checkValidAux (s->info->conj->a, checkedsofar);
300 sRef_checkValidAux (s->info->conj->b, checkedsofar);
304 llassert (cstring_length (s->info->fname) < 100);
308 sRef_checkValidAux (s->info->ref, checkedsofar);
312 sRef_checkValidAux (s->info->ref, checkedsofar);
318 /* check ctyp s->type */
322 llassert (s->info->spec == SR_NOTHING
323 || s->info->spec == SR_INTERNAL
324 || s->info->spec == SR_SPECSTATE
325 || s->info->spec == SR_SYSTEM);
335 sRefSet_elements (s->deriv, el)
337 sRef_checkValidAux (el, checkedsofar);
338 } end_sRefSet_elements ;
341 void sRef_checkValid (/*@unused@*/ sRef s)
345 sRefSet checkedsofar = sRefSet_new ();
346 sRef_checkValidAux (s, checkedsofar);
350 static /*@dependent@*/ /*@notnull@*/ /*@special@*/ sRef
353 /*@ensures isnull result->aliasinfo, result->definfo,
354 result->expinfo, result->info, result->deriv, result->state@*/
356 sRef s = sRef_alloc ();
358 s->kind = SK_UNKNOWN;
363 s->type = ctype_unknown;
364 s->defstate = SS_UNKNOWN;
366 /* start modifications */
367 s->bufinfo.bufstate = BB_NOTNULLTERMINATED;
368 /* end modifications */
370 s->aliaskind = AK_UNKNOWN;
371 s->oaliaskind = AK_UNKNOWN;
373 s->nullstate = NS_UNKNOWN;
375 s->expkind = XO_UNKNOWN;
376 s->oexpkind = XO_UNKNOWN;
378 s->aliasinfo = stateInfo_undefined;
379 s->definfo = stateInfo_undefined;
380 s->nullinfo = stateInfo_undefined;
381 s->expinfo = stateInfo_undefined;
384 s->deriv = sRefSet_undefined;
386 s->state = valueTable_undefined;
391 static /*@dependent@*/ /*@notnull@*/ /*@special@*/ sRef
394 /*@ensures isnull result->aliasinfo, result->definfo,
395 result->expinfo, result->info, result->deriv@*/
397 sRef res = sRef_new ();
399 res->state = valueTable_undefined;
404 void sRef_protectDerivs (void) /*@modifies protectDerivs@*/
406 llassert (!protectDerivs);
407 protectDerivs = TRUE;
410 void sRef_clearProtectDerivs (void) /*@modifies protectDerivs@*/
412 llassert (protectDerivs);
413 protectDerivs = FALSE;
417 ** hmmm...here be kind of a hack. This function mysteriously appeared
418 ** in my code, but I'm sure I didn't write it.
422 sRef_isRecursiveField (sRef s)
424 if (sRef_isField (s))
426 if (sRef_depth (s) > 13)
431 fieldname = sRef_getField (s);
432 base = sRef_getBase (s);
434 while (sRef_isValid (base))
436 if (sRef_isField (base))
438 if (cstring_equal (fieldname, sRef_getField (base)))
444 base = sRef_getBaseSafe (base);
453 sRef_addDeriv (/*@notnull@*/ sRef s, /*@notnull@*/ /*@exposed@*/ sRef t)
455 if (!context_inProtectVars ()
459 && !sRef_isConst (s))
461 int sd = sRef_depth (s);
462 int td = sRef_depth (t);
469 if (sRef_isFileOrGlobalScope (s))
471 if (context_inFunctionLike ()
472 && ctype_isKnown (sRef_getType (s))
473 && !ctype_isFunction (sRef_getType (s)))
475 globSet g = context_getUsedGlobs ();
477 if (!globSet_member (g, s))
480 ** don't report as a bug
484 (message ("sRef_addDeriv: global variable not in used "
485 "globs: %q / %s / %q",
487 ctype_unparse (sRef_getType (s)),
488 sRefSet_unparse (s->deriv)));
493 s->deriv = sRefSet_insert (s->deriv, t);
499 DPRINTF (("Add deriv: [%p] %s / [%p] %s",
501 t, sRef_unparse (t)));
503 s->deriv = sRefSet_insert (s->deriv, t);
509 sRef_deepPred (bool (predf) (sRef), sRef s)
511 if (sRef_isValid (s))
513 if ((*predf)(s)) return TRUE;
518 return (sRef_deepPred (predf, s->info->ref));
520 return (sRef_deepPred (predf, s->info->arrayfetch->arr));
522 return (sRef_deepPred (predf, s->info->field->rec));
524 return (sRef_deepPred (predf, s->info->conj->a)
525 || sRef_deepPred (predf, s->info->conj->b));
534 bool sRef_modInFunction (void)
539 void sRef_setStateFromType (sRef s, ctype ct)
541 if (sRef_isValid (s))
543 if (ctype_isUser (ct))
545 DPRINTF (("Here we are: %s", sRef_unparseFull (s)));
546 sRef_setStateFromUentry
547 (s, usymtab_getTypeEntry (ctype_typeId (ct)));
549 else if (ctype_isAbstract (ct))
551 DPRINTF (("Here we are: %s", sRef_unparseFull (s)));
552 sRef_setStateFromAbstractUentry
553 (s, usymtab_getTypeEntry (ctype_typeId (ct)));
557 ; /* not a user type */
562 static void sRef_setTypeState (sRef s)
564 if (sRef_isValid (s))
566 sRef_setStateFromType (s, s->type);
571 sRef_hasAliasInfoLoc (sRef s)
573 return (sRef_isValid (s) && (s->aliasinfo != NULL)
574 && (fileloc_isDefined (s->aliasinfo->loc)));
577 static /*@falsenull@*/ bool
578 sRef_hasStateInfoLoc (sRef s)
580 return (sRef_isValid (s) && (s->definfo != NULL)
581 && (fileloc_isDefined (s->definfo->loc)));
584 static /*@falsenull@*/ bool
585 sRef_hasExpInfoLoc (sRef s)
587 return (sRef_isValid (s)
588 && (s->expinfo != NULL) && (fileloc_isDefined (s->expinfo->loc)));
591 static /*@observer@*/ /*@unused@*/ stateInfo sRef_getInfo (sRef s, cstring key)
595 if (!sRef_isValid (s)) {
596 return stateInfo_undefined;
599 sv = valueTable_lookup (s->state, key);
601 if (stateValue_isDefined (sv))
603 return stateValue_getInfo (sv);
606 return stateInfo_undefined;
611 sRef_hasNullInfoLoc (sRef s)
613 return (sRef_isValid (s) && s->nullinfo != NULL
614 && (fileloc_isDefined (s->nullinfo->loc)));
618 sRef_hasAliasInfoRef (sRef s)
620 return (sRef_isValid (s) && (s->aliasinfo != NULL)
621 && (sRef_isValid (s->aliasinfo->ref)));
624 static /*@observer@*/ fileloc
625 sRef_getAliasInfoLoc (/*@exposed@*/ sRef s)
627 llassert (sRef_isValid (s) && s->aliasinfo != NULL
628 && (fileloc_isDefined (s->aliasinfo->loc)));
629 return (s->aliasinfo->loc);
632 static /*@observer@*/ fileloc
633 sRef_getStateInfoLoc (/*@exposed@*/ sRef s)
635 llassert (sRef_isValid (s) && s->definfo != NULL
636 && (fileloc_isDefined (s->definfo->loc)));
637 return (s->definfo->loc);
640 static /*@observer@*/ fileloc
641 sRef_getExpInfoLoc (/*@exposed@*/ sRef s)
643 llassert (sRef_isValid (s) && s->expinfo != NULL
644 && (fileloc_isDefined (s->expinfo->loc)));
645 return (s->expinfo->loc);
648 static /*@observer@*/ fileloc
649 sRef_getNullInfoLoc (/*@exposed@*/ sRef s)
651 llassert (sRef_isValid (s) && s->nullinfo != NULL
652 && (fileloc_isDefined (s->nullinfo->loc)));
653 return (s->nullinfo->loc);
657 sRef_getAliasInfoRef (/*@temp@*/ sRef s)
659 llassert (sRef_isValid (s) && s->aliasinfo != NULL);
660 return (s->aliasinfo->ref);
663 bool sRef_inGlobalScope ()
669 ** This function should be called before new sRefs are created
670 ** somewhere where they will have a lifetime greater than the
671 ** current function scope.
674 void sRef_setGlobalScope ()
676 llassert (inFunction);
677 DPRINTF (("leave function"));
681 void sRef_clearGlobalScope ()
683 llassert (!inFunction);
684 DPRINTF (("enter function"));
688 static bool oldInFunction = FALSE;
690 void sRef_setGlobalScopeSafe ()
692 oldInFunction = inFunction;
693 DPRINTF (("leave function"));
697 void sRef_clearGlobalScopeSafe ()
699 inFunction = oldInFunction;
700 DPRINTF (("clear function: %s", bool_unparse (inFunction)));
703 void sRef_enterFunctionScope ()
705 llassert (!inFunction);
706 llassert (sRefTable_isEmpty (allRefs));
708 DPRINTF (("enter function"));
711 void sRef_exitFunctionScope ()
716 DPRINTF (("Exit function scope."));
717 sRefTable_clear (allRefs);
722 llbuglit ("sRef_exitFunctionScope: not in function");
726 void sRef_destroyMod () /*@globals killed allRefs;@*/
729 llmsg (message ("Live: %d / %d ", nsrefs, totnsrefs));
732 sRefTable_free (allRefs);
736 static /*@notnull@*/ /*@exposed@*/ sRef
737 sRef_fixConj (/*@notnull@*/ sRef s)
742 s = sRef_getConjA (s);
743 } while (sRef_isConj (s));
745 llassert (sRef_isValid (s));
746 return s; /* don't need to ref */
755 sRef_isExternallyVisibleAux (sRef s)
758 sRef base = sRef_getRootBase (s);
760 if (sRef_isValid (base))
762 res = sRef_isParam (base) || sRef_isFileOrGlobalScope (base) || sRef_isExternal (base);
769 sRef_isExternallyVisible (sRef s)
771 return (sRef_aliasCheckSimplePred (sRef_isExternallyVisibleAux, s));
775 sRef_getBaseUentry (sRef s)
777 sRef base = sRef_getRootBase (s);
778 uentry res = uentry_undefined;
780 if (sRef_isValid (base))
785 res = usymtab_getRefQuiet (paramsScope, base->info->paramno);
789 res = usymtab_getRefQuiet (base->info->cvar->lexlevel,
790 base->info->cvar->index);
802 ** lookup the current uentry corresponding to s, and return the corresponding sRef.
803 ** yuk yuk yuk yuk yuk yuk yuk yuk
807 sRef_updateSref (sRef s)
813 if (!sRef_isValid (s)) return sRef_undefined;
822 case SK_UNCONSTRAINED:
829 sRef r = sRef_updateSref (s->info->ref);
831 if (r != s->info->ref)
833 return sRef_makeExternal (r);
843 uentry ue = sRef_getUentry (s);
845 /* must be raw name! (need the marker) */
846 ue = usymtab_lookupSafe (uentry_rawName (ue));
848 if (uentry_isUndefined (ue))
854 DPRINTF (("Update sref: %s", uentry_unparseFull (ue)));
855 return (uentry_getSref (ue));
859 /* special case if ind known */
860 inner = s->info->arrayfetch->arr;
861 ret = sRef_updateSref (inner);
869 res = sRef_makeArrayFetch (ret);
875 inner = s->info->field->rec;
876 ret = sRef_updateSref (inner);
884 res = (sRef_makeField (ret, s->info->field->field));
889 inner = s->info->ref;
890 ret = sRef_updateSref (inner);
897 res = sRef_makePointer (ret);
903 inner = s->info->ref;
904 ret = sRef_updateSref (inner);
912 res = sRef_makeAddress (ret);
919 sRef innera = s->info->conj->a;
920 sRef innerb = s->info->conj->b;
921 sRef reta = sRef_updateSref (innera);
922 sRef retb = sRef_updateSref (innerb);
924 if (innera == reta && innerb == retb)
930 res = sRef_makeConj (reta, retb);
941 sRef_getUentry (sRef s)
943 llassert (sRef_isValid (s));
948 return (usymtab_getRefQuiet (paramsScope, s->info->paramno));
950 return (usymtab_getRefQuiet (s->info->cvar->lexlevel, s->info->cvar->index));
953 if (sRef_isCvar (s->info->conj->a) || sRef_isParam (s->info->conj->a)
954 || sRef_isConj (s->info->conj->a))
956 return sRef_getUentry (s->info->conj->a);
960 return sRef_getUentry (s->info->conj->b);
965 return uentry_undefined;
971 sRef_getParam (sRef s)
973 llassert (sRef_isValid (s));
974 llassert (s->kind == SK_PARAM);
976 return s->info->paramno;
980 sRef_isModified (sRef s)
982 return (!sRef_isValid (s) || s->modified);
985 void sRef_setModified (sRef s)
987 if (sRef_isValid (s))
992 if (sRef_isRefsField (s))
994 sRef base = sRef_getBase (s);
997 llassert (s->kind == SK_FIELD);
1000 if (sRef_isPointer (base))
1002 base = sRef_getBase (base);
1005 if (sRef_isRefCounted (base))
1007 base->aliaskind = AK_NEWREF;
1014 ** note: this side-effects sRefSet to set modified to TRUE
1015 ** for any sRef similar to s.
1019 sRef_canModifyVal (sRef s, sRefSet sl)
1021 if (context_getFlag (FLG_MUSTMOD))
1023 return (sRef_doModifyVal (s, sl));
1027 return (sRef_checkModifyVal (s, sl));
1032 sRef_canModify (sRef s, sRefSet sl)
1035 if (context_getFlag (FLG_MUSTMOD))
1037 return (sRef_doModify (s, sl));
1041 return (sRef_checkModify (s, sl));
1050 bool sRef_checkModifyVal (sRef s, sRefSet sl)
1052 DPRINTF (("Check modify val: %s", sRef_unparse (s)));
1054 if (sRef_isInvalid (s))
1061 case SK_UNCONSTRAINED:
1065 DPRINTF (("Modify var: %s", sRef_unparse (s)));
1067 if (sRef_isFileOrGlobalScope (s))
1069 if (context_checkGlobMod (s))
1071 return (sRefSet_member (sl, s));
1081 return (sRefSet_member (sl, s)
1082 || alkind_isOnly (sRef_getOrigAliasKind (s)));
1084 /* special case if ind known */
1085 return (sRefSet_member (sl, s) ||
1086 sRef_checkModifyVal (s->info->arrayfetch->arr, sl));
1088 return (sRefSet_member (sl, s) || sRef_checkModifyVal (s->info->field->rec, sl));
1090 return (sRefSet_member (sl, s) || sRef_checkModifyVal (s->info->ref, sl));
1092 return (sRefSet_member (sl, s) || sRef_checkModifyVal (s->info->ref, sl));
1094 return ((sRef_checkModifyVal (s->info->conj->a, sl)) &&
1095 (sRef_checkModifyVal (s->info->conj->b, sl)));
1106 switch (s->info->spec)
1108 case SR_NOTHING: return TRUE;
1110 if (context_getFlag (FLG_INTERNALGLOBS))
1112 return (sRefSet_member (sl, s));
1118 case SR_SPECSTATE: return TRUE;
1119 case SR_SYSTEM: return (sRefSet_member (sl, s));
1120 case SR_GLOBALMARKER: BADBRANCH;
1123 case SK_RESULT: BADBRANCH;
1129 ** this should probably be elsewhere...
1131 ** returns TRUE iff sl indicates that s can be modified
1134 static bool sRef_checkModify (sRef s, sRefSet sl)
1136 llassert (sRef_isValid (s));
1140 case SK_UNCONSTRAINED:
1144 if (sRef_isFileOrGlobalScope (s))
1146 if (context_checkGlobMod (s))
1148 return (sRefSet_member (sl, s));
1160 return (sRefSet_member (sl, s) ||
1161 sRef_checkModifyVal (s->info->arrayfetch->arr, sl));
1164 sRef sr = s->info->field->rec;
1166 if (sr->kind == SK_PARAM)
1167 return TRUE; /* structs are copied on call */
1169 return (sRefSet_member (sl, s) || sRef_checkModifyVal (s->info->field->rec, sl));
1175 sm = sRefSet_member (sl, s);
1180 return (sRef_checkModifyVal (s->info->ref, sl));
1183 return (sRefSet_member (sl, s) || sRef_checkModifyVal (s->info->ref, sl));
1185 return ((sRef_checkModify (s->info->conj->a, sl)) &&
1186 (sRef_checkModify (s->info->conj->b, sl)));
1196 switch (s->info->spec)
1198 case SR_NOTHING: return TRUE;
1200 if (context_getFlag (FLG_INTERNALGLOBS))
1202 return (sRefSet_member (sl, s));
1208 case SR_SPECSTATE: return TRUE;
1209 case SR_SYSTEM: return (sRefSet_member (sl, s));
1210 case SR_GLOBALMARKER: BADBRANCH;
1213 case SK_RESULT: BADBRANCH;
1218 cstring sRef_stateVerb (sRef s)
1220 if (sRef_isDead (s))
1222 return cstring_makeLiteralTemp ("released");
1224 else if (sRef_isKept (s))
1226 return cstring_makeLiteralTemp ("kept");
1228 else if (sRef_isDependent (s))
1230 return cstring_makeLiteralTemp ("dependent");
1238 cstring sRef_stateAltVerb (sRef s)
1240 if (sRef_isDead (s))
1242 return cstring_makeLiteralTemp ("live");
1244 else if (sRef_isKept (s))
1246 return cstring_makeLiteralTemp ("not kept");
1248 else if (sRef_isDependent (s))
1250 return cstring_makeLiteralTemp ("independent");
1259 bool sRef_doModifyVal (sRef s, sRefSet sl)
1261 llassert (sRef_isValid (s));
1266 case SK_UNCONSTRAINED:
1270 if (sRef_isFileOrGlobalScope (s))
1273 if (context_checkGlobMod (s))
1275 return (sRefSet_modifyMember (sl, s));
1279 (void) sRefSet_modifyMember (sl, s);
1289 return (sRefSet_modifyMember (sl, s)
1290 || alkind_isOnly (sRef_getOrigAliasKind (s)));
1292 /* special case if ind known */
1293 /* unconditional OR, need side effect */
1294 return (OR (sRefSet_modifyMember (sl, s),
1295 sRef_doModifyVal (s->info->arrayfetch->arr, sl)));
1297 return (OR (sRefSet_modifyMember (sl, s),
1298 sRef_doModifyVal (s->info->field->rec, sl)));
1300 return (OR (sRefSet_modifyMember (sl, s),
1301 sRef_doModifyVal (s->info->ref, sl)));
1303 return (OR (sRefSet_modifyMember (sl, s),
1304 sRef_doModifyVal (s->info->ref, sl)));
1306 return (AND (sRef_doModifyVal (s->info->conj->a, sl) ,
1307 sRef_doModifyVal (s->info->conj->b, sl)));
1317 switch (s->info->spec)
1319 case SR_NOTHING: return TRUE;
1321 if (context_getFlag (FLG_INTERNALGLOBS))
1323 return (sRefSet_modifyMember (sl, s));
1327 (void) sRefSet_modifyMember (sl, s);
1330 case SR_SPECSTATE: return TRUE;
1331 case SR_SYSTEM: return (sRefSet_modifyMember (sl, s));
1332 case SR_GLOBALMARKER: BADBRANCH;
1336 case SK_RESULT: BADBRANCH;
1342 ** this should probably be elsewhere...
1344 ** returns TRUE iff sl indicates that s can be modified
1348 bool sRef_doModify (sRef s, sRefSet sl)
1350 llassert (sRef_isValid (s));
1354 case SK_UNCONSTRAINED:
1358 if (sRef_isFileOrGlobalScope (s))
1360 if (context_checkGlobMod (s))
1362 return (sRefSet_modifyMember (sl, s));
1366 (void) sRefSet_modifyMember (sl, s);
1378 return (OR (sRefSet_modifyMember (sl, s),
1379 sRef_doModifyVal (s->info->arrayfetch->arr, sl)));
1382 sRef sr = s->info->field->rec;
1384 if (sr->kind == SK_PARAM)
1386 return TRUE; /* structs are shallow-copied on call */
1389 return (OR (sRefSet_modifyMember (sl, s),
1390 sRef_doModifyVal (s->info->field->rec, sl)));
1394 return (OR (sRefSet_modifyMember (sl, s),
1395 sRef_doModifyVal (s->info->ref, sl)));
1398 return (OR (sRefSet_modifyMember (sl, s),
1399 sRef_doModifyVal (s->info->ref, sl)));
1401 return (AND (sRef_doModify (s->info->conj->a, sl),
1402 (sRef_doModify (s->info->conj->b, sl))));
1413 switch (s->info->spec)
1415 case SR_NOTHING: return TRUE;
1416 case SR_INTERNAL: return TRUE;
1417 case SR_SPECSTATE: return TRUE;
1418 case SR_SYSTEM: return (sRefSet_modifyMember (sl, s));
1419 case SR_GLOBALMARKER: BADBRANCH;
1422 case SK_RESULT: BADBRANCH;
1427 static /*@exposed@*/ sRef
1428 sRef_leastCommon (/*@exposed@*/ sRef s1, sRef s2)
1430 llassert (sRef_similar (s1, s2));
1432 if (!sRef_isValid (s1)) return s1;
1433 if (!sRef_isValid (s2)) return s1;
1435 sRef_combineDefState (s1, s2);
1436 sRef_combineNullState (s1, s2);
1437 sRef_combineExKinds (s1, s2);
1439 if (s1->aliaskind != s2->aliaskind)
1441 if (s1->aliaskind == AK_UNKNOWN)
1443 s1->aliaskind = s2->aliaskind;
1445 else if (s2->aliaskind == AK_UNKNOWN)
1451 s1->aliaskind = AK_ERROR;
1458 int sRef_compare (sRef s1, sRef s2)
1460 if (s1 == s2) return 0;
1462 if (sRef_isInvalid (s1)) return -1;
1463 if (sRef_isInvalid (s2)) return 1;
1465 INTCOMPARERETURN (s1->kind, s2->kind);
1466 INTCOMPARERETURN (s1->defstate, s2->defstate);
1467 INTCOMPARERETURN (s1->aliaskind, s2->aliaskind);
1469 DPRINTF (("Compare null state: %s / %s",
1470 sRef_unparseFull (s1),
1471 sRef_unparseFull (s2)));
1473 COMPARERETURN (nstate_compare (sRef_getNullState (s1),
1474 sRef_getNullState (s2)));
1479 return (int_compare (s1->info->paramno, s2->info->paramno));
1482 COMPARERETURN (sRef_compare (s1->info->arrayfetch->arr,
1483 s2->info->arrayfetch->arr));
1485 if (s1->info->arrayfetch->indknown && s2->info->arrayfetch->indknown)
1487 return (int_compare (s1->info->arrayfetch->ind,
1488 s2->info->arrayfetch->ind));
1490 if (!s1->info->arrayfetch->indknown && !s2->info->arrayfetch->indknown)
1497 COMPARERETURN (sRef_compare (s1->info->field->rec, s2->info->field->rec));
1499 if (cstring_equal (s1->info->field->field, s2->info->field->field))
1506 return (sRef_compare (s1->info->ref, s2->info->ref));
1508 COMPARERETURN (sRef_compare (s1->info->conj->a, s2->info->conj->a));
1509 return (sRef_compare (s1->info->conj->b, s2->info->conj->b));
1510 case SK_UNCONSTRAINED:
1511 return (cstring_compare (s1->info->fname, s2->info->fname));
1523 return (generic_compare (s1->info->spec, s2->info->spec));
1528 static bool cref_equal (cref c1, cref c2)
1530 return ((c1->lexlevel == c2->lexlevel) &&
1531 (usymId_equal (c1->index, c2->index)));
1535 ** returns true if s1 could be the same storage as s2.
1536 ** i.e., a[?] ~ a[3]. Note its not symmetric ... s1
1537 ** should be more specific.
1541 ** like similar, but matches objects <-> non-objects
1545 sRef_uniqueReference (sRef s)
1547 return (sRef_isFresh (s) || sRef_isUnique (s)
1548 || sRef_isOnly (s) || sRef_isStack (s)
1549 || sRef_isAddress (s));
1553 sRef_similarRelaxedAux (sRef s1, sRef s2)
1557 if (sRef_isUnknownArrayFetch (s1))
1567 if (sRef_isInvalid (s1) || sRef_isInvalid (s2)) return FALSE;
1569 if (sRef_isConj (s2))
1570 return (sRef_similarRelaxedAux (s1, sRef_getConjA (s2)) ||
1571 sRef_similarRelaxedAux (s1, sRef_getConjB (s2)));
1576 return ((s2->kind == SK_CVAR)
1577 && (cref_equal (s1->info->cvar, s2->info->cvar)));
1579 return ((s2->kind == SK_PARAM)
1580 && (s1->info->paramno == s2->info->paramno));
1582 if (s2->kind == SK_ARRAYFETCH)
1584 if (sRef_similarRelaxedAux (s1->info->arrayfetch->arr,
1585 s2->info->arrayfetch->arr))
1587 if (s1->info->arrayfetch->indknown)
1589 if (s2->info->arrayfetch->indknown)
1591 return (s1->info->arrayfetch->ind == s2->info->arrayfetch->ind);
1606 return ((s2->kind == SK_FIELD
1607 && (sRef_similarRelaxedAux (s1->info->field->rec,
1608 s2->info->field->rec)
1609 && cstring_equal (s1->info->field->field,
1610 s2->info->field->field))));
1612 return ((s2->kind == SK_PTR)
1613 && sRef_similarRelaxedAux (s1->info->ref, s2->info->ref));
1615 return ((s2->kind == SK_ADR)
1616 && sRef_similarRelaxedAux (s1->info->ref, s2->info->ref));
1618 return ((sRef_similarRelaxedAux (s1->info->conj->a, s2) ||
1619 (sRef_similarRelaxedAux (s1->info->conj->b, s2))));
1621 return (s1->info->spec == s2->info->spec);
1622 case SK_UNCONSTRAINED:
1623 return (cstring_equal (s1->info->fname, s2->info->fname));
1638 sRef_similarRelaxed (sRef s1, sRef s2)
1644 if (sRef_isThroughArrayFetch (s1))
1654 if (sRef_isInvalid (s1) || sRef_isInvalid (s2)) return FALSE;
1656 us1 = sRef_uniqueReference (s1);
1657 us2 = sRef_uniqueReference (s2);
1659 if ((s1->kind == SK_EXTERNAL && (s2->kind != SK_EXTERNAL && !us2))
1660 || (s2->kind == SK_EXTERNAL && (s1->kind != SK_EXTERNAL && !us1)))
1663 ** Previously, also:
1664 ** || (sRef_isExposed (s1) && !us2) || (sRef_isExposed (s2) && !us1)) ????
1666 ** No clue why this was there?!
1670 if (sRef_isExposed (s1) && sRef_isCvar (s1))
1672 uentry ue1 = sRef_getUentry (s1);
1674 if (uentry_isRefParam (ue1))
1676 return sRef_similarRelaxedAux (s1, s2);
1680 if (sRef_isExposed (s2) && sRef_isCvar (s2))
1682 uentry ue2 = sRef_getUentry (s2);
1684 if (uentry_isRefParam (ue2))
1686 return sRef_similarRelaxedAux (s1, s2);
1690 return (ctype_match (s1->type, s2->type));
1694 return sRef_similarRelaxedAux (s1, s2);
1699 sRef_similar (sRef s1, sRef s2)
1701 if (s1 == s2) return TRUE;
1702 if (sRef_isInvalid (s1) || sRef_isInvalid (s2)) return FALSE;
1704 if (sRef_isConj (s2))
1706 return (sRef_similar (s1, sRef_getConjA (s2)) ||
1707 sRef_similar (s1, sRef_getConjB (s2)));
1710 if (sRef_isDerived (s2))
1712 return (sRef_includedBy (s1, s2->info->ref));
1718 return ((s2->kind == SK_CVAR)
1719 && (cref_equal (s1->info->cvar, s2->info->cvar)));
1721 return ((s2->kind == SK_PARAM)
1722 && (s1->info->paramno == s2->info->paramno));
1724 if (s2->kind == SK_ARRAYFETCH)
1726 if (sRef_similar (s1->info->arrayfetch->arr,
1727 s2->info->arrayfetch->arr))
1729 if (s1->info->arrayfetch->indknown)
1731 if (s2->info->arrayfetch->indknown)
1733 return (s1->info->arrayfetch->ind == s2->info->arrayfetch->ind);
1748 if (s2->kind == SK_PTR)
1750 if (sRef_similar (s1->info->arrayfetch->arr,
1760 return ((s2->kind == SK_FIELD
1761 && (sRef_similar (s1->info->field->rec,
1762 s2->info->field->rec)
1763 && cstring_equal (s1->info->field->field,
1764 s2->info->field->field))));
1766 if (s2->kind == SK_PTR)
1768 return sRef_similar (s1->info->ref, s2->info->ref);
1772 if (s2->kind == SK_ARRAYFETCH)
1774 if (sRef_similar (s2->info->arrayfetch->arr,
1784 return ((s2->kind == SK_ADR)
1785 && sRef_similar (s1->info->ref, s2->info->ref));
1787 return ((sRef_similar (s1->info->conj->a, s2) ||
1788 (sRef_similar (s1->info->conj->b, s2))));
1790 return (sRef_includedBy (s2, s1->info->ref));
1791 case SK_UNCONSTRAINED:
1792 return (s2->kind == SK_UNCONSTRAINED
1793 && cstring_equal (s1->info->fname, s2->info->fname));
1803 return (s2->kind == SK_SPECIAL
1804 && (s1->info->spec == s2->info->spec));
1807 /*@notreached@*/ DPRINTF (("Fell through for: %s / %s", sRef_unparse (s1), sRef_unparse (s2)));
1812 ** return TRUE iff small can be derived from big.
1814 ** (e.g. x, x.a is includedBy x;
1815 ** x.a is included By x.a;
1819 sRef_includedBy (sRef small, sRef big)
1821 if (small == big) return TRUE;
1822 if (sRef_isInvalid (small) || sRef_isInvalid (big)) return FALSE;
1824 if (sRef_isConj (big))
1825 return (sRef_similar (small, sRef_getConjA (big)) ||
1826 sRef_similar (small, sRef_getConjB (big)));
1828 switch (small->kind)
1832 return (sRef_same (small, big));
1834 if (big->kind == SK_ARRAYFETCH)
1836 if (sRef_same (small->info->arrayfetch->arr, big->info->arrayfetch->arr))
1838 if (small->info->arrayfetch->indknown)
1840 if (big->info->arrayfetch->indknown)
1842 return (small->info->arrayfetch->ind == big->info->arrayfetch->ind);
1855 return (sRef_includedBy (small->info->arrayfetch->arr, big));
1857 if (big->kind == SK_FIELD)
1860 (sRef_same (small->info->field->rec, big->info->field->rec) &&
1861 cstring_equal (small->info->field->field, big->info->field->field));
1865 return (sRef_includedBy (small->info->field->rec, big));
1869 if (big->kind == SK_PTR)
1871 return sRef_same (small->info->ref, big->info->ref);
1875 return (sRef_includedBy (small->info->ref, big));
1879 return ((big->kind == SK_ADR) && sRef_similar (small->info->ref, big->info->ref));
1881 return ((sRef_includedBy (small->info->conj->a, big) ||
1882 (sRef_includedBy (small->info->conj->b, big))));
1884 return (sRef_includedBy (small->info->ref, big));
1885 case SK_UNCONSTRAINED:
1895 switch (small->info->spec)
1897 case SR_NOTHING: return TRUE;
1899 case SR_INTERNAL: return (sRef_isSpecInternalState (big) ||
1900 sRef_isFileStatic (big));
1901 case SR_SYSTEM: return (sRef_isSystemState (big));
1902 case SR_GLOBALMARKER: BADBRANCH;
1909 ** Same is similar to similar, but not quite the same.
1910 ** same and realSame aren't the same, but they are really similar.
1911 ** similarly, same is the same as same. but realSame is
1912 ** not really the same as same, or similar to similar.
1914 ** Similarly to similar, same checks if two sRefs are the same.
1915 ** The similarities end, however, when same compares arrays
1916 ** with unknown indexes. Similar returns false; same returns true.
1918 ** Similarly to similar and same, realSame is the same as same,
1919 ** except they do not behave the same when face with unknown
1920 ** sRefs. Same thinks they are not the same, but realSame thinks
1926 sRef_realSame (sRef s1, sRef s2)
1928 if (s1 == s2) return TRUE;
1929 if (sRef_isInvalid (s1) || sRef_isInvalid (s2)) return FALSE;
1934 return ((s2->kind == SK_CVAR) && (cref_equal (s1->info->cvar, s2->info->cvar)));
1936 return ((s2->kind == SK_PARAM) && (s1->info->paramno == s2->info->paramno));
1938 if (s2->kind == SK_ARRAYFETCH)
1940 if (sRef_realSame (s1->info->arrayfetch->arr, s2->info->arrayfetch->arr))
1942 if (s1->info->arrayfetch->indknown && s2->info->arrayfetch->indknown)
1944 return (s1->info->arrayfetch->ind == s2->info->arrayfetch->ind);
1946 if (!s1->info->arrayfetch->indknown && !s2->info->arrayfetch->indknown)
1955 return ((s2->kind == SK_FIELD &&
1956 (sRef_realSame (s1->info->field->rec, s2->info->field->rec) &&
1957 cstring_equal (s1->info->field->field, s2->info->field->field))));
1959 return ((s2->kind == SK_PTR) && sRef_realSame (s1->info->ref, s2->info->ref));
1961 return ((s2->kind == SK_ADR) && sRef_realSame (s1->info->ref, s2->info->ref));
1963 return ((sRef_realSame (s1->info->conj->a, s2) ||
1964 (sRef_realSame (s1->info->conj->b, s2))));
1966 return ((s2->kind == SK_OBJECT)
1967 && ctype_match (s1->info->object, s2->info->object));
1969 return ((s2->kind == SK_EXTERNAL)
1970 && sRef_realSame (s1->info->ref, s2->info->ref));
1972 return ((s2->kind == SK_SPECIAL) && s1->info->spec == s2->info->spec);
1974 return ((s2->kind == SK_DERIVED) && sRef_realSame (s1->info->ref, s2->info->ref));
1975 case SK_UNCONSTRAINED:
1976 return ((s2->kind == SK_UNCONSTRAINED)
1977 && (cstring_equal (s1->info->fname, s2->info->fname)));
1983 return TRUE; /* changed this! was false */
1989 sRef_sameObject (sRef s1, sRef s2)
1995 ** same is similar to similar, but not quite the same.
1997 ** Similarly to similar, same checks is two sRefs are the same.
1998 ** The similarities end, however, when same compares arrays
1999 ** with unknown indexes. Similar returns false; same returns true.
2003 sRef_same (sRef s1, sRef s2)
2005 if (s1 == s2) return TRUE;
2006 if (sRef_isInvalid (s1) || sRef_isInvalid (s2)) return FALSE;
2011 return ((s2->kind == SK_CVAR) && (cref_equal (s1->info->cvar, s2->info->cvar)));
2013 return ((s2->kind == SK_PARAM) && (s1->info->paramno == s2->info->paramno));
2015 if (s2->kind == SK_ARRAYFETCH)
2017 llassert (s1->info->field->rec != s1);
2018 if (sRef_same (s1->info->arrayfetch->arr, s2->info->arrayfetch->arr))
2020 if (s1->info->arrayfetch->indknown && s2->info->arrayfetch->indknown)
2022 return (s1->info->arrayfetch->ind == s2->info->arrayfetch->ind);
2030 llassert (s1->info->field->rec != s1);
2031 return ((s2->kind == SK_FIELD &&
2032 (sRef_same (s1->info->field->rec, s2->info->field->rec) &&
2033 cstring_equal (s1->info->field->field, s2->info->field->field))));
2037 llassert (s1->info->ref != s1);
2038 return ((s2->kind == SK_PTR) && sRef_same (s1->info->ref, s2->info->ref));
2042 llassert (s1->info->ref != s1);
2043 return ((s2->kind == SK_ADR) && sRef_same (s1->info->ref, s2->info->ref));
2046 llassert (s1->info->conj->a != s1);
2047 llassert (s1->info->conj->b != s1);
2048 return ((sRef_same (s1->info->conj->a, s2)) && /* or or and? */
2049 (sRef_same (s1->info->conj->b, s2)));
2051 return ((s2->kind == SK_SPECIAL) && s1->info->spec == s2->info->spec);
2053 llassert (s1->info->ref != s1);
2054 return ((s2->kind == SK_DERIVED) && sRef_same (s1->info->ref, s2->info->ref));
2056 case SK_UNCONSTRAINED:
2069 ** sort of similar, for use in def/use
2073 sRef_closeEnough (sRef s1, sRef s2)
2075 if (s1 == s2) return TRUE;
2076 if (sRef_isInvalid (s1) || sRef_isInvalid (s2)) return FALSE;
2081 return (((s2->kind == SK_CVAR) &&
2082 (cref_equal (s1->info->cvar, s2->info->cvar))) ||
2083 (s2->kind == SK_UNCONSTRAINED && s1->info->cvar->lexlevel == 0));
2084 case SK_UNCONSTRAINED:
2085 return (s2->kind == SK_UNCONSTRAINED
2086 || ((s2->kind == SK_CVAR) && (s2->info->cvar->lexlevel == 0)));
2088 return ((s2->kind == SK_PARAM)
2089 && (s1->info->paramno == s2->info->paramno));
2091 if (s2->kind == SK_ARRAYFETCH)
2093 if (sRef_closeEnough (s1->info->arrayfetch->arr, s2->info->arrayfetch->arr))
2095 if (s1->info->arrayfetch->indknown && s2->info->arrayfetch->indknown)
2097 return (s1->info->arrayfetch->ind == s2->info->arrayfetch->ind);
2104 return ((s2->kind == SK_FIELD &&
2105 (sRef_closeEnough (s1->info->field->rec, s2->info->field->rec) &&
2106 cstring_equal (s1->info->field->field, s2->info->field->field))));
2108 return ((s2->kind == SK_PTR) && sRef_closeEnough (s1->info->ref, s2->info->ref));
2110 return ((s2->kind == SK_ADR) && sRef_closeEnough (s1->info->ref, s2->info->ref));
2112 return ((s2->kind == SK_DERIVED) && sRef_closeEnough (s1->info->ref, s2->info->ref));
2114 return ((sRef_closeEnough (s1->info->conj->a, s2)) ||
2115 (sRef_closeEnough (s1->info->conj->b, s2)));
2117 return ((s2->kind == SK_SPECIAL) && s1->info->spec == s2->info->spec);
2133 s is an sRef of a formal paramenter in a function call constraint
2134 we trys to return a constraint expression derived from the actual parementer of a function call.
2136 /*@only@*/ constraintExpr sRef_fixConstraintParam (/*@observer@*/ sRef s, /*@observer@*/ /*@temp@*/ exprNodeList args)
2140 if (sRef_isInvalid (s))
2141 llfatalbug((message("Invalid sRef")));
2147 // s = sRef_saveCopy(s);
2148 ce = constraintExpr_makeTermsRef (s);
2155 temp = (sRef_makeField (sRef_fixBaseParam (s->info->field->rec, args),
2156 s->info->field->field));
2157 ce = constraintExpr_makeTermsRef (temp);
2163 temp = (sRef_makePointer (sRef_fixBaseParam (s->info->ref, args)));
2164 //temp = sRef_saveCopy(temp);
2165 ce = constraintExpr_makeTermsRef (temp);
2172 temp = sRef_saveCopy(s);
2173 temp = sRef_fixBaseParam (temp, args);
2174 ce = constraintExpr_makeTermsRef (temp);
2182 temp = sRef_saveCopy(s);
2183 ce = constraintExpr_makeTermsRef (temp);
2188 llassert(exprNodeList_size (args) > s->info->paramno);
2190 exprNode e = exprNodeList_nth (args, s->info->paramno);
2192 llassert( !(exprNode_isError (e)) );
2193 ce = constraintExpr_makeExprNode (e);
2200 llcontbug ((message("Trying to do fixConstraintParam on nonparam, nonglobal: %q for function with arguments %q", sRef_unparse (s), exprNodeList_unparse(args) ) ));
2201 temp = sRef_saveCopy(s);
2202 ce = constraintExpr_makeTermsRef (temp);
2214 sRef_fixBaseParam (/*@returned@*/ sRef s, exprNodeList args)
2216 if (sRef_isInvalid (s)) return (sRef_undefined);
2220 case SK_UNCONSTRAINED:
2225 if (exprNodeList_size (args) > s->info->paramno)
2227 exprNode e = exprNodeList_nth (args, s->info->paramno);
2229 if (exprNode_isError (e))
2231 return sRef_makeUnknown ();
2234 return (exprNode_getSref (e));
2238 return sRef_makeUnknown ();
2243 if (s->info->arrayfetch->indknown)
2245 return (sRef_makeArrayFetchKnown
2246 (sRef_fixBaseParam (s->info->arrayfetch->arr, args),
2247 s->info->arrayfetch->ind));
2251 return (sRef_makeArrayFetch
2252 (sRef_fixBaseParam (s->info->arrayfetch->arr, args)));
2255 return (sRef_makeField (sRef_fixBaseParam (s->info->field->rec, args),
2256 s->info->field->field));
2259 return (sRef_makePointer (sRef_fixBaseParam (s->info->ref, args)));
2262 return (sRef_makeAddress (sRef_fixBaseParam (s->info->ref, args)));
2265 return (sRef_makeConj (sRef_fixBaseParam (s->info->conj->a, args),
2266 sRef_fixBaseParam (s->info->conj->b, args)));
2282 sRef_undumpGlobal (char **c)
2292 usymId uid = usymId_fromInt (reader_getInt (c));
2297 reader_checkChar (c, '@');
2298 defstate = sstate_fromInt (reader_getInt (c));
2300 reader_checkChar (c, '@');
2301 nullstate = nstate_fromInt (reader_getInt (c));
2303 ret = sRef_makeGlobal (uid, ctype_unknown);
2304 sRef_setNullStateN (ret, nullstate);
2305 ret->defstate = defstate;
2310 int i = reader_getInt (c);
2311 speckind sk = speckind_fromInt (i);
2315 case SR_NOTHING: return (sRef_makeNothing ());
2316 case SR_INTERNAL: return (sRef_makeInternalState ());
2317 case SR_SPECSTATE: return (sRef_makeSpecState ());
2318 case SR_SYSTEM: return (sRef_makeSystemState ());
2319 case SR_GLOBALMARKER: BADBRANCH;
2324 return sRef_undefined;
2326 return sRef_makeUnknown ();
2328 return sRef_makeUnknown ();
2330 llfatalerror (message ("sRef_undumpGlobal: bad line: %s",
2331 cstring_fromChars (*c)));
2337 sRef_undump (char **c)
2346 return (sRef_makeGlobal (usymId_fromInt (reader_getInt (c)), ctype_unknown));
2348 return (sRef_makeParam (reader_getInt (c), ctype_unknown));
2350 return (sRef_makeResultType (ctype_undump (c)));
2353 if ((**c >= '0' && **c <= '9') || **c == '-')
2355 int i = reader_getInt (c);
2356 sRef arr = sRef_undump (c);
2357 sRef ret = sRef_buildArrayFetchKnown (arr, i);
2363 sRef arr = sRef_undump (c);
2364 sRef ret = sRef_buildArrayFetch (arr);
2371 cstring fname = cstring_undefined;
2376 fname = cstring_appendChar (fname, **c);
2381 ret = sRef_buildField (sRef_undump (c), fname);
2382 cstring_markOwned (fname);
2387 int i = reader_getInt (c);
2388 speckind sk = speckind_fromInt (i);
2392 case SR_NOTHING: return (sRef_makeNothing ());
2393 case SR_INTERNAL: return (sRef_makeInternalState ());
2394 case SR_SPECSTATE: return (sRef_makeSpecState ());
2395 case SR_SYSTEM: return (sRef_makeSystemState ());
2396 case SR_GLOBALMARKER: BADBRANCH;
2402 sRef ptr = sRef_undump (c);
2403 sRef ret = sRef_makePointer (ptr);
2409 sRef adr = sRef_undump (c);
2410 sRef ret = sRef_makeAddress (adr);
2416 return (sRef_makeObject (ctype_undump (c)));
2420 sRef s1 = sRef_undump (c);
2421 sRef s2 = ((*c)++, sRef_undump (c));
2422 sRef ret = sRef_makeConj (s1, s2);
2427 return sRef_undefined;
2429 return sRef_makeUnknown ();
2431 return sRef_makeUnknown ();
2433 llfatalerror (message ("sRef_undump: bad line: %s", cstring_fromChars (*c)));
2441 if (sRef_isInvalid (s))
2443 return (cstring_makeLiteral ("-"));
2450 return (message ("p%d", s->info->paramno));
2452 if (s->info->arrayfetch->indknown)
2454 return (message ("a%d%q", s->info->arrayfetch->ind,
2455 sRef_dump (s->info->arrayfetch->arr)));
2459 return (message ("a%q", sRef_dump (s->info->arrayfetch->arr)));
2462 return (message ("f%s.%q", s->info->field->field,
2463 sRef_dump (s->info->field->rec)));
2465 return (message ("t%q", sRef_dump (s->info->ref)));
2467 return (message ("d%q", sRef_dump (s->info->ref)));
2469 return (message ("o%q", ctype_dump (s->info->object)));
2471 return (message ("s%d", (int) s->info->spec));
2473 return (message ("c%q.%q",
2474 sRef_dump (s->info->conj->a),
2475 sRef_dump (s->info->conj->b)));
2477 if (sRef_isFileOrGlobalScope (s))
2479 return (message ("g%d",
2480 usymtab_convertId (s->info->cvar->index)));
2484 llcontbug (message ("Dumping local variable: %q",
2485 sRef_unparseDebug (s)));
2486 return (cstring_makeLiteral ("u"));
2489 return (cstring_makeLiteral ("u"));
2491 return (message ("r%q", ctype_dump (s->type)));
2497 case SK_UNCONSTRAINED:
2498 llcontbug (message ("sRef_dump: bad kind: %q",
2499 sRef_unparseFull (s)));
2500 return (cstring_makeLiteral ("x"));
2507 cstring sRef_dumpGlobal (sRef s)
2509 if (sRef_isInvalid (s))
2511 return (cstring_makeLiteral ("-"));
2518 if (sRef_isFileOrGlobalScope (s))
2520 return (message ("g%d@%d@%d",
2521 usymtab_convertId (s->info->cvar->index),
2523 (int) sRef_getNullState (s)));
2527 llcontbug (message ("Dumping local variable: %q",
2528 sRef_unparseDebug (s)));
2529 return (cstring_makeLiteral ("u"));
2532 return (cstring_makeLiteral ("u"));
2534 return (message ("s%d", (int) s->info->spec));
2536 llcontbug (message ("sRef_dumpGlobal: bad kind: %q",
2537 sRef_unparseFull (s)));
2538 return (cstring_makeLiteral ("x"));
2546 sRef_deriveType (sRef s, uentryList cl)
2548 if (sRef_isInvalid (s)) return ctype_unknown;
2553 return (uentry_getType (usymtab_getRefQuiet (s->info->cvar->lexlevel,
2554 s->info->cvar->index)));
2555 case SK_UNCONSTRAINED:
2556 return (ctype_unknown);
2558 if (s->info->paramno >= 0)
2560 return uentry_getType (uentryList_getN (cl, s->info->paramno));
2564 return ctype_unknown;
2568 ctype ca = sRef_deriveType (s->info->arrayfetch->arr, cl);
2570 if (ctype_isArray (ca))
2572 return (ctype_baseArrayPtr (ca));
2574 else if (ctype_isUnknown (ca))
2580 llcontbuglit ("sRef_deriveType: inconsistent array type");
2586 ctype ct = sRef_deriveType (s->info->field->rec, cl);
2588 if (ctype_isStructorUnion (ct))
2590 uentry ue = uentryList_lookupField (ctype_getFields (ct),
2591 s->info->field->field);
2593 if (uentry_isValid (ue))
2595 return (uentry_getType (ue));
2599 llcontbuglit ("sRef_deriveType: bad field");
2600 return ctype_unknown;
2603 else if (ctype_isUnknown (ct))
2609 llcontbuglit ("sRef_deriveType: inconsistent field type");
2615 ctype ct = sRef_deriveType (s->info->ref, cl);
2617 if (ctype_isUnknown (ct)) return ct;
2618 if (ctype_isPointer (ct)) return (ctype_baseArrayPtr (ct));
2621 llcontbuglit ("sRef_deriveType: inconsistent pointer type");
2627 ctype ct = sRef_deriveType (s->info->ref, cl);
2629 if (ctype_isUnknown (ct)) return ct;
2630 return ctype_makePointer (ct);
2634 return sRef_deriveType (s->info->ref, cl);
2638 return (s->info->object);
2642 return (ctype_makeConj (sRef_deriveType (s->info->conj->a, cl),
2643 sRef_deriveType (s->info->conj->b, cl)));
2655 return ctype_unknown;
2661 sRef_getType (sRef s)
2663 if (sRef_isInvalid (s)) return ctype_unknown;
2669 sRef_unparseOpt (sRef s)
2671 sRef rb = sRef_getRootBase (s);
2673 if (sRef_isMeaningful (rb) && !sRef_isConst (rb))
2675 cstring ret = sRef_unparse (s);
2677 llassertprint (!cstring_equalLit (ret, "?"), ("print: %s", sRef_unparseDebug (s)));
2679 if (!cstring_isEmpty (ret))
2681 return (cstring_appendChar (ret, ' '));
2689 return cstring_undefined;
2693 sRef_unparsePreOpt (sRef s)
2695 sRef rb = sRef_getRootBase (s);
2697 if (sRef_isMeaningful (rb) && !sRef_isConst (rb))
2699 cstring ret = sRef_unparse (s);
2701 llassertprint (!cstring_equalLit (ret, "?"), ("print: %s", sRef_unparseDebug (s)));
2702 return (cstring_prependCharO (' ', ret));
2705 return cstring_undefined;
2709 sRef_unparse (sRef s)
2711 if (sRef_isInvalid (s)) return (cstring_makeLiteral ("?"));
2713 if (context_inFunctionLike ())
2715 return (sRef_unparseWithArgs (s, context_getParams ()));
2719 DPRINTF (("Not in function like: %s", context_unparse ()));
2720 return (sRef_unparseNoArgs (s));
2724 static /*@only@*/ cstring
2725 sRef_unparseWithArgs (sRef s, uentryList args)
2727 if (sRef_isInvalid (s))
2729 return (cstring_makeLiteral ("?"));
2735 return (uentry_getName (usymtab_getRefQuiet (s->info->cvar->lexlevel,
2736 s->info->cvar->index)));
2737 case SK_UNCONSTRAINED:
2738 return (cstring_copy (s->info->fname));
2741 if (s->info->paramno < uentryList_size (args)
2742 && s->info->paramno >= 0)
2744 uentry ue = uentryList_getN (args, s->info->paramno);
2746 if (uentry_isValid (ue))
2747 return uentry_getName (ue);
2750 return (message ("<bad param: %q / args %q",
2751 sRef_unparseDebug (s),
2752 uentryList_unparse (args)));
2755 if (s->info->arrayfetch->indknown)
2757 return (message ("%q[%d]", sRef_unparseWithArgs (s->info->arrayfetch->arr, args),
2758 s->info->arrayfetch->ind));
2762 return (message ("%q[]", sRef_unparseWithArgs (s->info->arrayfetch->arr, args)));
2765 if (s->info->field->rec->kind == SK_PTR)
2767 sRef ptr = s->info->field->rec;
2769 return (message ("%q->%s", sRef_unparseWithArgs (ptr->info->ref, args),
2770 s->info->field->field));
2772 return (message ("%q.%s", sRef_unparseWithArgs (s->info->field->rec, args),
2773 s->info->field->field));
2777 sRef ref = sRef_fixConj (s->info->ref);
2778 skind sk = ref->kind;
2783 ret = message ("storage pointed to by %q",
2784 sRef_unparseWithArgs (ref, args));
2786 else if (skind_isSimple (sk) || sk == SK_PTR)
2788 ret = message ("*%q", sRef_unparseWithArgs (ref, args));
2792 ret = message ("*(%q)", sRef_unparseWithArgs (ref, args));
2798 return (message ("&%q", sRef_unparseWithArgs (s->info->ref, args)));
2800 return (cstring_copy (ctype_unparse (s->info->object)));
2802 return (sRef_unparseWithArgs (sRef_getConjA (s), args));
2804 if (cstring_isDefined (s->info->fname))
2806 return (message ("[result of %s]", s->info->fname));
2810 return (cstring_makeLiteral ("<new>"));
2813 return (cstring_makeLiteral ("?"));
2815 return (message ("<derived %q>", sRef_unparse (s->info->ref)));
2817 return (message ("<external %q>", sRef_unparse (s->info->ref)));
2819 return (message ("<type %s>", ctype_unparse (s->type)));
2821 return (message ("<const %s>", ctype_unparse (s->type)));
2823 switch (s->info->spec)
2825 case SR_NOTHING: return cstring_makeLiteral ("nothing");
2826 case SR_INTERNAL: return cstring_makeLiteral ("internal state");
2827 case SR_SPECSTATE: return cstring_makeLiteral ("spec state");
2828 case SR_SYSTEM: return cstring_makeLiteral ("file system state");
2829 case SR_GLOBALMARKER: return cstring_makeLiteral ("<global marker>");
2833 return cstring_makeLiteral ("result");
2836 llbug (message ("Bad sref, kind = %d", (int) s->kind));
2844 sRef_unparseDebug (sRef s)
2846 if (sRef_isInvalid (s))
2848 return (cstring_makeLiteral ("<undef>"));
2854 case SK_UNCONSTRAINED:
2855 return (message ("<unconstrained %s>", s->info->fname));
2860 ce = usymtab_getRefQuiet (s->info->cvar->lexlevel, s->info->cvar->index);
2862 if (uentry_isInvalid (ce))
2864 return (message ("<scope: %d.%d *invalid*>",
2865 s->info->cvar->lexlevel,
2866 s->info->cvar->index));
2870 return (message ("<scope: %d.%d *%q*>",
2871 s->info->cvar->lexlevel,
2872 s->info->cvar->index,
2873 uentry_getName (ce)));
2879 return (message ("<parameter %d>", s->info->paramno + 1));
2882 if (s->info->arrayfetch->indknown)
2884 return (message ("%q[%d]", sRef_unparseDebug (s->info->arrayfetch->arr),
2885 s->info->arrayfetch->ind));
2889 return (message ("%q[]", sRef_unparseDebug (s->info->arrayfetch->arr)));
2892 return (message ("%q.%s", sRef_unparseDebug (s->info->field->rec),
2893 s->info->field->field));
2895 if (sRef_isField (s->info->ref))
2897 sRef fld = s->info->ref;
2899 return (message ("%q->%s", sRef_unparseDebug (fld->info->field->rec),
2900 fld->info->field->field));
2904 return (message ("*(%q)", sRef_unparseDebug (s->info->ref)));
2907 return (message ("&%q", sRef_unparseDebug (s->info->ref)));
2909 return (message ("<object type %s>", ctype_unparse (s->info->object)));
2911 return (message ("%q | %q", sRef_unparseDebug (s->info->conj->a),
2912 sRef_unparseDebug (s->info->conj->b)));
2914 return message ("<new: %s>", s->info->fname);
2916 return (message ("<derived %q>", sRef_unparseDebug (s->info->ref)));
2918 return (message ("<external %q>", sRef_unparseDebug (s->info->ref)));
2920 return (message ("<type %s>", ctype_unparse (s->type)));
2922 return (message ("<const %s>", ctype_unparse (s->type)));
2924 return (message ("<result %s>", ctype_unparse (s->type)));
2926 return (message ("<spec %s>",
2927 cstring_makeLiteralTemp
2928 (s->info->spec == SR_NOTHING ? "nothing"
2929 : s->info->spec == SR_INTERNAL ? "internalState"
2930 : s->info->spec == SR_SPECSTATE ? "spec state"
2931 : s->info->spec == SR_SYSTEM ? "fileSystem"
2934 return cstring_makeLiteral ("<unknown>");
2940 static /*@only@*/ cstring
2941 sRef_unparseNoArgs (sRef s)
2943 if (sRef_isInvalid (s)) return (cstring_makeLiteral ("?"));
2947 case SK_UNCONSTRAINED:
2948 return (cstring_copy (s->info->fname));
2951 uentry ce = usymtab_getRefQuiet (s->info->cvar->lexlevel,
2952 s->info->cvar->index);
2954 if (uentry_isInvalid (ce))
2956 llcontbug (message ("sRef_unparseNoArgs: bad cvar: %q",
2957 sRef_unparseDebug (s)));
2958 return (sRef_unparseDebug (s));
2962 return (uentry_getName (ce));
2966 if (s->info->arrayfetch->indknown)
2968 return (message ("%q[%d]", sRef_unparseNoArgs (s->info->arrayfetch->arr),
2969 s->info->arrayfetch->ind));
2973 return (message ("%q[]", sRef_unparseNoArgs (s->info->arrayfetch->arr)));
2976 return (message ("%q.%s", sRef_unparseNoArgs (s->info->field->rec),
2977 s->info->field->field));
2980 sRef ref = sRef_fixConj (s->info->ref);
2981 skind sk = ref->kind;
2984 if (skind_isSimple (sk) || sk == SK_PTR)
2986 ret = message ("*%q", sRef_unparseNoArgs (ref));
2990 ret = message ("*(%q)", sRef_unparseNoArgs (ref));
2996 return (message ("&%q", sRef_unparseNoArgs (s->info->ref)));
2998 return (cstring_copy (ctype_unparse (s->info->object)));
3000 return (sRef_unparseNoArgs (s->info->conj->a));
3002 return (message ("result of %s", s->info->fname));
3004 return (message ("<der %q>", sRef_unparseNoArgs (s->info->ref)));
3006 return message ("<ext %q>", sRef_unparseNoArgs (s->info->ref));
3008 return (cstring_makeLiteral
3009 (s->info->spec == SR_NOTHING ? "nothing"
3010 : s->info->spec == SR_INTERNAL ? "internal state"
3011 : s->info->spec == SR_SPECSTATE ? "spec state"
3012 : s->info->spec == SR_SYSTEM ? "file system state"
3015 return cstring_makeLiteral ("result");
3019 return cstring_makeLiteral ("?");
3021 /* llcontbug (message ("sRef_unparseNoArgs: bad case: %q", sRef_unparseDebug (s))); */
3022 return (sRef_unparseDebug (s));
3027 /*@dependent@*/ sRef sRef_makeUnconstrained (cstring fname)
3029 sRef s = sRef_new ();
3031 s->kind = SK_UNCONSTRAINED;
3032 s->info = (sinfo) dmalloc (sizeof (*s->info));
3033 s->info->fname = fname;
3038 cstring sRef_unconstrainedName (sRef s)
3040 llassert (sRef_isUnconstrained (s));
3042 return s->info->fname;
3045 bool sRef_isUnconstrained (sRef s)
3047 return (sRef_isValid(s) && s->kind == SK_UNCONSTRAINED);
3050 static /*@dependent@*/ /*@notnull@*/ sRef
3051 sRef_makeCvarAux (int level, usymId index, ctype ct)
3053 sRef s = sRef_newRef ();
3056 s->info = (sinfo) dmalloc (sizeof (*s->info));
3058 s->info->cvar = (cref) dmalloc (sizeof (*s->info->cvar));
3059 s->info->cvar->lexlevel = level;
3060 s->info->cvar->index = index;
3062 /* for now, all globals are defined; all locals, aren't */
3064 if (level <= fileScope)
3066 s->defstate = SS_UNKNOWN;
3070 ctype rct = ctype_realType (ct);
3072 if (level != paramsScope
3073 && (ctype_isStructorUnion (rct) || ctype_isRealArray (rct)))
3075 s->defstate = SS_ALLOCATED;
3076 s->oaliaskind = s->aliaskind = AK_STACK;
3080 s->defstate = SS_UNDEFINED;
3081 s->oaliaskind = s->aliaskind = AK_LOCAL;
3087 llassert (level >= globScope);
3088 llassert (usymId_isValid (index));
3090 DPRINTF (("Made cvar: [%p] %s", s, sRef_unparseDebug (s)));
3091 llassert (valueTable_isUndefined (s->state));
3092 s->state = context_createValueTable (s);
3096 /*@dependent@*/ sRef sRef_makeCvar (int level, usymId index, ctype ct)
3098 return (sRef_makeCvarAux (level, index, ct));
3101 int sRef_lexLevel (sRef s)
3103 if (sRef_isValid (s))
3107 conj = sRef_fixConj (s);
3108 s = sRef_getRootBase (conj);
3110 if (sRef_isValid (s) && s->kind == SK_CVAR)
3112 return (s->info->cvar->lexlevel);
3120 sRef_makeGlobal (usymId l, ctype ct)
3122 return (sRef_makeCvar (globScope, l, ct));
3126 sRef_setParamNo (sRef s, int l)
3128 llassert (sRef_isValid (s) && s->kind == SK_PARAM);
3129 s->info->paramno = l;
3133 /*@dependent@*/ sRef
3134 sRef_makeParam (int l, ctype ct)
3136 sRef s = sRef_new ();
3141 s->info = (sinfo) dmalloc (sizeof (*s->info));
3142 s->info->paramno = l;
3144 s->defstate = SS_UNKNOWN;
3145 /* (probably defined, unless its an out parameter) */
3147 llassert (valueTable_isUndefined (s->state));
3148 s->state = context_createValueTable (s);
3153 sRef_isIndexKnown (sRef arr)
3157 llassert (sRef_isValid (arr));
3158 arr = sRef_fixConj (arr);
3160 llassert (arr->kind == SK_ARRAYFETCH);
3161 res = arr->info->arrayfetch->indknown;
3166 sRef_getIndex (sRef arr)
3170 llassert (sRef_isValid (arr));
3171 arr = sRef_fixConj (arr);
3173 llassert (arr->kind == SK_ARRAYFETCH);
3175 if (!arr->info->arrayfetch->indknown)
3177 llcontbug (message ("sRef_getIndex: unknown: %q", sRef_unparse (arr)));
3182 result = arr->info->arrayfetch->ind;
3188 static bool sRef_isZerothArrayFetch (/*@notnull@*/ sRef s)
3190 return (s->kind == SK_ARRAYFETCH
3191 && s->info->arrayfetch->indknown
3192 && (s->info->arrayfetch->ind == 0));
3195 /*@exposed@*/ sRef sRef_makeAddress (/*@exposed@*/ sRef t)
3198 if (sRef_isInvalid (t)) return sRef_undefined;
3200 if (sRef_isPointer (t))
3202 return (t->info->ref);
3204 else if (sRef_isZerothArrayFetch (t))
3206 return (t->info->arrayfetch->arr);
3210 sRef s = sRef_newRef ();
3213 s->type = ctype_makePointer (t->type);
3214 s->info = (sinfo) dmalloc (sizeof (*s->info));
3215 s->info->ref = t; /* sRef_copy (t); */ /*@i32@*/
3217 if (t->defstate == SS_UNDEFINED)
3218 /* no! it is allocated even still: && !ctype_isPointer (t->type)) */
3220 s->defstate = SS_ALLOCATED;
3224 s->defstate = t->defstate;
3227 if (t->aliaskind == AK_LOCAL)
3229 if (sRef_isLocalVar (t))
3231 s->aliaskind = AK_STACK;
3235 llassert (valueTable_isUndefined (s->state));
3236 s->state = context_createValueTable (s);
3241 cstring sRef_getField (sRef s)
3245 llassert (sRef_isValid (s));
3246 s = sRef_fixConj (s);
3248 llassertprint (sRef_isValid (s) && (s->kind == SK_FIELD),
3249 ("s = %s", sRef_unparseDebug (s)));
3251 res = s->info->field->field;
3255 sRef sRef_getBase (sRef s)
3259 if (sRef_isInvalid (s)) return (sRef_undefined);
3261 s = sRef_fixConj (s);
3272 res = s->info->field->rec;
3276 res = s->info->arrayfetch->arr;
3280 res = sRef_undefined; /* shouldn't need it */
3287 ** same as getBase, except returns invalid
3288 ** (and doesn't use adr's)
3292 sRef_getBaseSafe (sRef s)
3296 if (sRef_isInvalid (s)) { return sRef_undefined; }
3298 s = sRef_fixConj (s);
3306 res = s->info->field->rec; break;
3308 res = s->info->arrayfetch->arr;
3311 res = sRef_undefined; break;
3317 /*@constant int MAXBASEDEPTH;@*/
3318 # define MAXBASEDEPTH 25
3320 static /*@exposed@*/ sRef
3321 sRef_getRootBaseAux (sRef s, int depth)
3323 if (sRef_isInvalid (s)) return sRef_undefined;
3325 if (depth > MAXBASEDEPTH)
3328 ("Warning: reference base limit exceeded for %q. "
3329 "This either means there is a variable with at least "
3330 "%d indirections from this reference, or "
3331 "there is a bug in LCLint.",
3336 return sRef_undefined;
3343 return (sRef_getRootBaseAux (s->info->ref, depth + 1));
3345 return (sRef_getRootBaseAux (s->info->field->rec, depth + 1));
3347 return (sRef_getRootBaseAux (s->info->arrayfetch->arr, depth + 1));
3349 return (sRef_getRootBaseAux (sRef_fixConj (s), depth + 1));
3355 sRef sRef_getRootBase (sRef s)
3357 return (sRef_getRootBaseAux (s, 0));
3360 static bool sRef_isDeep (sRef s)
3362 if (sRef_isInvalid (s)) return FALSE;
3372 return (sRef_isDeep (sRef_fixConj (s)));
3378 static int sRef_depth (sRef s)
3380 if (sRef_isInvalid (s)) return 0;
3388 return 1 + sRef_depth (s->info->ref);
3390 return 1 + sRef_depth (s->info->field->rec);
3392 return 1 + sRef_depth (s->info->arrayfetch->arr);
3394 return (sRef_depth (sRef_fixConj (s)));
3401 sRef_makeObject (ctype o)
3403 sRef s = sRef_newRef (); /*@i423 same line is bad...@*/
3405 s->kind = SK_OBJECT;
3406 s->info = (sinfo) dmalloc (sizeof (*s->info));
3407 s->info->object = o;
3408 llassert (valueTable_isUndefined (s->state));
3409 s->state = context_createValueTable (s);
3414 ** This is used to represent storage referenced by a parameter.
3417 sRef sRef_makeExternal (sRef t)
3419 sRef s = sRef_newRef ();
3421 llassert (sRef_isValid (t));
3423 s->kind = SK_EXTERNAL;
3424 s->info = (sinfo) dmalloc (sizeof (*s->info));
3426 s->info->ref = t; /* sRef_copy (t); */ /*@i32 was exposed@*/
3427 llassert (valueTable_isUndefined (s->state));
3428 s->state = context_createValueTable (s);
3432 /*@dependent@*/ sRef sRef_makeDerived (/*@exposed@*/ sRef t)
3434 if (sRef_isValid (t))
3436 sRef s = sRef_newRef ();
3438 s->kind = SK_DERIVED;
3439 s->info = (sinfo) dmalloc (sizeof (*s->info));
3440 s->info->ref = t; /* sRef_copy (t); */ /*@i32@*/
3443 llassert (valueTable_isUndefined (s->state));
3444 s->state = context_createValueTable (s);
3449 return sRef_undefined;
3454 ** definitely NOT symmetric:
3456 ** res fills in unknown state information from other
3460 sRef_mergeStateQuiet (sRef res, sRef other)
3462 llassert (sRef_isValid (res));
3463 llassert (sRef_isValid (other));
3465 res->modified = res->modified || other->modified;
3466 res->safe = res->safe && other->safe;
3468 if (res->defstate == SS_UNKNOWN)
3470 res->defstate = other->defstate;
3471 res->definfo = stateInfo_update (res->definfo, other->definfo);
3474 if (res->aliaskind == AK_UNKNOWN ||
3475 (res->aliaskind == AK_LOCAL && alkind_isKnown (other->aliaskind)))
3477 res->aliaskind = other->aliaskind;
3478 res->oaliaskind = other->oaliaskind;
3479 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
3482 if (res->expkind == XO_UNKNOWN)
3484 res->expkind = other->expkind;
3485 res->oexpkind = other->oexpkind;
3486 res->expinfo = stateInfo_update (res->expinfo, other->expinfo);
3489 /* out takes precedence over implicitly defined */
3490 if (res->defstate == SS_DEFINED && other->defstate != SS_UNKNOWN)
3492 res->defstate = other->defstate;
3493 res->definfo = stateInfo_update (res->definfo, other->definfo);
3496 if (sRef_getNullState (other) == NS_ERROR || sRef_getNullState (res) == NS_ERROR)
3498 sRef_setNullState (res, NS_ERROR, fileloc_undefined);
3502 if (sRef_getNullState (other) != NS_UNKNOWN
3503 && (sRef_getNullState (res) == NS_UNKNOWN || sRef_getNullState (res) == NS_NOTNULL
3504 || sRef_getNullState (res) == NS_MNOTNULL))
3506 sRef_updateNullState (res, other);
3512 ** definitely NOT symmetric:
3514 ** res fills in known state information from other
3518 sRef_mergeStateQuietReverse (/*@dependent@*/ sRef res, /*@dependent@*/ sRef other)
3520 bool changed = FALSE;
3522 llassert (sRef_isValid (res));
3523 llassert (sRef_isValid (other));
3524 sRef_checkMutable (res);
3526 if (res->kind != other->kind)
3532 res->kind = other->kind;
3533 res->type = other->type;
3534 res->info = sinfo_fullCopy (other);
3538 if (!ctype_equal (res->type, other->type))
3541 res->type = other->type;
3544 sinfo_update (res, other);
3547 res->modified = res->modified || other->modified;
3548 res->safe = res->safe && other->safe;
3550 if (res->aliaskind != other->aliaskind
3551 && (res->aliaskind == AK_UNKNOWN
3552 || ((res->aliaskind == AK_LOCAL
3553 || (res->aliaskind == AK_REFCOUNTED
3554 && other->aliaskind != AK_LOCAL))
3555 && other->aliaskind != AK_UNKNOWN)))
3558 res->aliaskind = other->aliaskind;
3559 res->oaliaskind = other->oaliaskind;
3560 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
3563 if (other->expkind != XO_UNKNOWN && other->expkind != res->expkind)
3566 res->expkind = other->expkind;
3567 res->expinfo = stateInfo_update (res->expinfo, other->expinfo);
3570 if (other->oexpkind != XO_UNKNOWN)
3572 res->oexpkind = other->oexpkind;
3575 /* out takes precedence over implicitly defined */
3577 if (res->defstate != other->defstate)
3579 if (other->defstate != SS_UNKNOWN)
3581 res->defstate = other->defstate;
3585 if (sRef_getNullState (other) == NS_ERROR || sRef_getNullState (res) == NS_ERROR)
3587 if (sRef_getNullState (res) != NS_ERROR)
3589 sRef_setNullStateN (res, NS_ERROR);
3595 if (sRef_getNullState (other) != NS_UNKNOWN && sRef_getNullState (other) != sRef_getNullState (res))
3598 sRef_updateNullState (res, other);
3604 sRef_clearDerived (res);
3609 sRef_mergeState (sRef res, sRef other, clause cl, fileloc loc)
3611 if (sRef_isValid (res) && sRef_isValid (other))
3613 sRef_mergeStateAux (res, other, cl, FALSE, loc, TRUE);
3617 if (sRef_isInvalid (res))
3619 llbug (message ("sRef_mergeState: invalid res sRef: %q",
3620 sRef_unparseDebug (other)));
3624 llbug (message ("sRef_mergeState: invalid other sRef: %q",
3625 sRef_unparseDebug (res)));
3631 sRef_mergeOptState (sRef res, sRef other, clause cl, fileloc loc)
3633 if (sRef_isValid (res) && sRef_isValid (other))
3635 sRef_mergeStateAux (res, other, cl, TRUE, loc, TRUE);
3639 if (sRef_isInvalid (res))
3641 llbug (message ("sRef_mergeOptState: invalid res sRef: %q",
3642 sRef_unparseDebug (other)));
3646 llbug (message ("sRef_mergeOptState: invalid other sRef: %q",
3647 sRef_unparseDebug (res)));
3653 sRef_mergeStateAux (/*@notnull@*/ sRef res, /*@notnull@*/ sRef other,
3654 clause cl, bool opt, fileloc loc,
3658 llassertfatal (sRef_isValid (res));
3659 llassertfatal (sRef_isValid (other));
3661 sRef_checkMutable (res);
3662 sRef_checkMutable (other);
3664 res->modified = res->modified || other->modified;
3666 if (res->kind == other->kind
3667 || (other->kind == SK_UNKNOWN || res->kind == SK_UNKNOWN))
3669 sstate odef = other->defstate;
3670 sstate rdef = res->defstate;
3671 nstate onull = sRef_getNullState (other);
3674 ** yucky stuff to handle
3679 if (other->defstate == SS_DEAD
3680 && ((sRef_isOnly (res) && sRef_definitelyNull (res))
3681 || (res->defstate == SS_UNDEFINED
3682 || res->defstate == SS_UNUSEABLE)))
3684 if (res->defstate == SS_UNDEFINED
3685 || res->defstate == SS_UNUSEABLE)
3687 res->defstate = SS_UNUSEABLE;
3691 res->defstate = SS_DEAD;
3694 res->definfo = stateInfo_update (res->definfo, other->definfo);
3695 sRef_clearDerived (other);
3696 sRef_clearDerived (res);
3698 else if (res->defstate == SS_DEAD
3699 && ((sRef_isOnly (other) && sRef_definitelyNull (other))
3700 || (other->defstate == SS_UNDEFINED
3701 || other->defstate == SS_UNUSEABLE)))
3703 if (other->defstate == SS_UNDEFINED
3704 || other->defstate == SS_UNUSEABLE)
3706 res->defstate = SS_UNUSEABLE;
3710 res->defstate = SS_DEAD;
3713 sRef_clearDerived (other);
3714 sRef_clearDerived (res);
3716 else if (res->defstate == SS_DEFINED
3717 && (other->defstate == SS_ALLOCATED
3718 && sRef_definitelyNull (other)))
3720 other->defstate = SS_DEFINED; /* definitely null! */
3722 else if (other->defstate == SS_DEFINED
3723 && (res->defstate == SS_ALLOCATED && sRef_definitelyNull (res)))
3725 res->defstate = SS_DEFINED;
3726 res->definfo = stateInfo_update (res->definfo, other->definfo);
3733 if (res->defstate == SS_DEAD && other->defstate == SS_DEAD)
3735 sRef_clearDerived (other);
3736 sRef_clearDerived (res);
3740 ** only & dead isn't really an only!
3743 if (alkind_isOnly (other->aliaskind) && other->defstate == SS_DEAD)
3745 other->aliaskind = AK_UNKNOWN;
3748 if (alkind_isOnly (res->aliaskind) && res->defstate == SS_DEAD)
3750 res->aliaskind = AK_UNKNOWN;
3754 ** Dead and dependent -> dead
3757 if (alkind_isDependent (other->aliaskind) && res->defstate == SS_DEAD)
3759 other->aliaskind = AK_UNKNOWN;
3760 other->defstate = SS_DEAD;
3761 sRef_clearDerived (res);
3762 sRef_clearDerived (other);
3765 if (alkind_isDependent (res->aliaskind) && other->defstate == SS_DEAD)
3767 res->aliaskind = AK_UNKNOWN;
3768 res->defstate = SS_DEAD;
3769 sRef_clearDerived (res);
3770 sRef_clearDerived (other);
3774 ** must do alias combine first, since it depends on
3775 ** original values of state and null.
3778 sRef_combineAliasKinds (res, other, cl, loc);
3779 sRef_combineDefState (res, other);
3780 sRef_combineNullState (res, other);
3782 if (rdef == SS_ALLOCATED || rdef == SS_SPECIAL)
3784 if (odef == SS_DEFINED)
3786 if (onull == NS_DEFNULL || onull == NS_CONSTNULL)
3788 res->deriv = sRefSet_copyInto (res->deriv, other->deriv);
3789 DPRINTF (("Copy derivs: %s", sRef_unparseFull (res)));
3792 else if (odef == SS_ALLOCATED || odef == SS_SPECIAL)
3797 if (ctype_isUnion (ctype_realType (sRef_getType (res))))
3799 res->deriv = sRef_mergeUnionDerivs (res->deriv,
3802 DPRINTF (("Copy derivs: %s", sRef_unparseFull (res)));
3806 res->deriv = sRef_mergeDerivs (res->deriv, other->deriv,
3808 DPRINTF (("Copy derivs: %s", sRef_unparseFull (res)));
3816 res->deriv = sRef_mergeDerivs (res->deriv, other->deriv,
3818 DPRINTF (("Copy derivs: %s", sRef_unparseFull (res)));
3828 if (rdef == SS_PDEFINED
3829 || (rdef == SS_DEFINED && odef == SS_PDEFINED))
3833 res->deriv = sRef_mergePdefinedDerivs (res->deriv, other->deriv,
3835 DPRINTF (("Copy derivs: %s", sRef_unparseFull (res)));
3840 if ((rdef == SS_DEFINED || rdef == SS_UNKNOWN)
3841 && res->defstate == SS_ALLOCATED)
3843 res->deriv = sRefSet_copyInto (res->deriv, other->deriv);
3849 res->deriv = sRef_mergeDerivs (res->deriv, other->deriv,
3851 DPRINTF (("Copy derivs: %s", sRef_unparseFull (res)));
3858 sRef_combineExKinds (res, other);
3862 if (res->kind == SK_ARRAYFETCH && other->kind == SK_PTR)
3864 sRef nother = sRef_buildArrayFetchKnown (sRef_getBase (other), 0);
3866 sRef_copyState (nother, other);
3867 sRef_mergeStateAux (res, nother, cl, opt, loc, doDerivs);
3869 else if (res->kind == SK_PTR && other->kind == SK_ARRAYFETCH)
3871 sRef nother = sRef_buildPointer (sRef_getBase (other));
3873 if (sRef_isValid (nother))
3875 sRef_copyState (nother, other);
3876 sRef_mergeStateAux (res, nother, cl, opt, loc, doDerivs);
3881 llcontbug (message ("merge conj: %q / %q", sRef_unparseFull (res),
3882 sRef_unparseFull (other)));
3888 ** Merge value table states
3895 ** This doesn't do anything. And its broken too...
3898 valueTable_elements (res->state, key, sv)
3900 stateValue os = valueTable_lookup (other->state, key);
3901 /*@unused@*/ int val;
3902 /*@unused@*/ char *msg;
3904 llassert (stateValue_isDefined (os));
3906 DPRINTF (("Merge state: %s / %s",
3907 cstring_toCharsSafe (stateValue_unparse (sv)),
3908 cstring_toCharsSafe (stateValue_unparse (os))));
3910 val = valueMatix_lookup (key,
3911 stateValue_getValue (os),
3912 stateValue_getValue (sv),
3914 DPRINTF (("Val: %d / %s", val, msg));
3916 } end_valueTable_elements ;
3922 sRef_mergeUnionDerivs (/*@only@*/ sRefSet res,
3923 /*@exposed@*/ sRefSet other, bool opt,
3924 clause cl, fileloc loc)
3926 if (sRefSet_isEmpty (res))
3928 return sRefSet_copyInto (res, other);
3932 sRefSet_allElements (other, el)
3934 if (sRef_isValid (el))
3936 sRef e2 = sRefSet_lookupMember (other, el);
3938 if (sRef_isValid (e2))
3940 sRef_mergeStateAux (el, e2, cl, opt, loc, FALSE);
3944 res = sRefSet_insert (res, el);
3947 } end_sRefSet_allElements ;
3953 static /*@only@*/ sRefSet
3954 sRef_mergeDerivs (/*@only@*/ sRefSet res, sRefSet other,
3955 bool opt, clause cl, fileloc loc)
3957 sRefSet ret = sRefSet_new ();
3959 sRefSet_allElements (res, el)
3961 if (sRef_isValid (el))
3963 sRef e2 = sRefSet_lookupMember (other, el);
3965 if (sRef_isValid (e2))
3967 if (el->defstate == SS_ALLOCATED &&
3968 e2->defstate == SS_PDEFINED)
3970 e2->defstate = SS_ALLOCATED;
3972 else if (e2->defstate == SS_ALLOCATED &&
3973 el->defstate == SS_PDEFINED)
3975 el->defstate = SS_ALLOCATED;
3976 sRef_clearDerived (el);
3978 else if ((el->defstate == SS_DEAD || sRef_isKept (el)) &&
3979 (e2->defstate == SS_DEFINED && !sRef_isKept (e2)))
3982 if (checkDeadState (el, TRUE, loc))
3984 if (sRef_isThroughArrayFetch (el))
3986 sRef_maybeKill (el, loc);
3987 sRef_maybeKill (e2, loc);
3991 else if ((e2->defstate == SS_DEAD || sRef_isKept (e2)) &&
3992 (el->defstate == SS_DEFINED && !sRef_isKept (el)))
3995 if (checkDeadState (e2, FALSE, loc))
3997 if (sRef_isThroughArrayFetch (el))
3999 sRef_maybeKill (el, loc);
4000 sRef_maybeKill (e2, loc);
4004 else if (el->defstate == SS_DEFINED &&
4005 e2->defstate == SS_PDEFINED)
4007 DPRINTF (("set pdefined: %s", sRef_unparseFull (el)));
4008 el->defstate = SS_PDEFINED;
4010 else if (e2->defstate == SS_DEFINED &&
4011 el->defstate == SS_PDEFINED)
4013 DPRINTF (("set pdefined: %s", sRef_unparseFull (e2)));
4014 e2->defstate = SS_PDEFINED;
4021 if (ctype_isUnion (ctype_realType (sRef_getType (el))))
4023 el->deriv = sRef_mergeUnionDerivs (el->deriv, e2->deriv,
4028 el->deriv = sRef_mergeDerivs (el->deriv, e2->deriv, opt, cl, loc);
4031 if (sRef_equivalent (el, e2))
4033 ret = sRefSet_insert (ret, el);
4037 sRef sr = sRef_leastCommon (el, e2);
4039 if (sRef_isValid (sr))
4041 ret = sRefSet_insert (ret, sr);
4049 (void) sRefSet_delete (other, e2);
4051 else /* not defined */
4053 (void) checkDeadState (el, TRUE, loc);
4056 } end_sRefSet_allElements;
4058 sRefSet_allElements (other, el)
4060 if (sRef_isValid (el))
4062 (void) checkDeadState (el, FALSE, loc);
4064 } end_sRefSet_allElements;
4071 ** Returns TRUE is there is an error.
4074 static bool checkDeadState (/*@notnull@*/ sRef el, bool tbranch, fileloc loc)
4077 ** usymtab_isGuarded --- the utab should still be in the
4078 ** state of the alternate branch.
4080 ** tbranch TRUE means el is released in the last branch, e.g.
4081 ** if (x != NULL) { ; } else { sfree (x); }
4082 ** so, if x is null in the other branch no error is reported.
4084 ** tbranch FALSE means this is the other branch:
4085 ** if (x != NULL) { sfree (x); } else { ; }
4086 ** so, if x is null in this branch there is no error.
4090 if ((sRef_isDead (el) || sRef_isKept (el))
4091 && !sRef_isDeepUnionField (el) && !sRef_isThroughArrayFetch (el))
4096 if (usymtab_isDefinitelyNullDeep (el))
4103 if (usymtab_isAltDefinitelyNullDeep (el))
4111 message ("Storage %q is %q in one path, but live in another.",
4113 cstring_makeLiteral (sRef_isKept (el)
4114 ? "kept" : "released")),
4118 if (sRef_isKept (el))
4120 sRef_showAliasInfo (el);
4124 sRef_showStateInfo (el);
4127 /* prevent further errors */
4128 el->defstate = SS_UNKNOWN;
4129 sRef_setAliasKind (el, AK_ERROR, fileloc_undefined);
4139 checkDerivDeadState (/*@notnull@*/ sRef el, bool tbranch, fileloc loc)
4142 if (checkDeadState (el, tbranch, loc))
4144 sRefSet_allElements (el->deriv, t)
4146 if (sRef_isValid (t))
4148 checkDerivDeadState (t, tbranch, loc);
4150 } end_sRefSet_allElements;
4155 sRef_mergePdefinedDerivs (sRefSet res, sRefSet other, bool opt,
4156 clause cl, fileloc loc)
4158 sRefSet ret = sRefSet_new ();
4160 sRefSet_allElements (res, el)
4162 if (sRef_isValid (el))
4164 sRef e2 = sRefSet_lookupMember (other, el);
4166 if (sRef_isValid (e2))
4168 if (sRef_isAllocated (el) && !sRef_isAllocated (e2))
4172 else if (sRef_isAllocated (e2) && !sRef_isAllocated (el))
4174 el->deriv = sRefSet_copyInto (el->deriv, e2->deriv);
4178 el->deriv = sRef_mergePdefinedDerivs (el->deriv, e2->deriv,
4182 sRef_mergeStateAux (el, e2, cl, opt, loc, FALSE);
4184 ret = sRefSet_insert (ret, el);
4185 (void) sRefSet_delete (other, e2);
4191 checkDerivDeadState (el, (cl == FALSECLAUSE), loc);
4194 ret = sRefSet_insert (ret, el);
4197 } end_sRefSet_allElements;
4199 sRefSet_allElements (other, el)
4201 if (sRef_isValid (el))
4203 if (!sRefSet_member (ret, el))
4205 /* was cl == FALSECLAUSE */
4206 checkDerivDeadState (el, FALSE, loc);
4207 ret = sRefSet_insert (ret, el);
4212 ** it's okay --- member is a different equality test
4216 } end_sRefSet_allElements;
4222 sRef sRef_makeConj (/*@exposed@*/ /*@returned@*/ sRef a, /*@exposed@*/ sRef b)
4224 llassert (sRef_isValid (a));
4225 llassert (sRef_isValid (b));
4227 if (!sRef_equivalent (a, b))
4229 sRef s = sRef_newRef ();
4232 s->info = (sinfo) dmalloc (sizeof (*s->info));
4233 s->info->conj = (cjinfo) dmalloc (sizeof (*s->info->conj));
4234 s->info->conj->a = a; /* sRef_copy (a) */ /*@i32*/ ;
4235 s->info->conj->b = b; /* sRef_copy (b);*/ /*@i32@*/ ;
4237 if (ctype_equal (a->type, b->type)) s->type = a->type;
4238 else s->type = ctype_makeConj (a->type, b->type);
4240 if (a->defstate == b->defstate)
4242 s->defstate = a->defstate;
4246 s->defstate = SS_UNKNOWN;
4249 sRef_setNullStateN (s, NS_UNKNOWN);
4251 s->safe = a->safe && b->safe;
4252 s->aliaskind = alkind_resolve (a->aliaskind, b->aliaskind);
4254 llassert (valueTable_isUndefined (s->state));
4255 s->state = context_createValueTable (s);
4260 /*@-exposetrans@*/ return a; /*@=exposetrans@*/
4264 /*@dependent@*/ sRef
4267 sRef s = sRef_new ();
4269 s->kind = SK_UNKNOWN;
4273 static /*@owned@*/ sRef
4274 sRef_makeSpecial (speckind sk) /*@*/
4276 sRef s = sRef_new ();
4278 s->kind = SK_SPECIAL;
4279 s->info = (sinfo) dmalloc (sizeof (*s->info));
4281 /*@-dependenttrans@*/
4283 /*@=dependenttrans@*/
4286 static /*@owned@*/ sRef srnothing = sRef_undefined;
4287 static /*@owned@*/ sRef srinternal = sRef_undefined;
4288 static /*@owned@*/ sRef srsystem = sRef_undefined;
4289 static /*@owned@*/ sRef srspec = sRef_undefined;
4291 /*@dependent@*/ sRef
4292 sRef_makeNothing (void)
4294 if (sRef_isInvalid (srnothing))
4296 srnothing = sRef_makeSpecial (SR_NOTHING);
4303 sRef_makeInternalState (void)
4305 if (sRef_isInvalid (srinternal))
4307 srinternal = sRef_makeSpecial (SR_INTERNAL);
4314 sRef_makeSpecState (void)
4316 if (sRef_isInvalid (srspec))
4318 srspec = sRef_makeSpecial (SR_SPECSTATE);
4325 sRef_makeSystemState (void)
4327 if (sRef_isInvalid (srsystem))
4329 srsystem = sRef_makeSpecial (SR_SYSTEM);
4336 sRef_makeGlobalMarker (void)
4338 sRef s = sRef_makeSpecial (SR_GLOBALMARKER);
4339 llassert (valueTable_isUndefined (s->state));
4340 s->state = context_createGlobalMarkerValueTable ();
4345 sRef_makeResultType (ctype ct)
4347 sRef res = sRef_makeResult ();
4356 sRef s = sRef_newRef ();
4358 s->kind = SK_RESULT;
4359 s->type = ctype_unknown;
4360 s->defstate = SS_UNKNOWN;
4361 s->aliaskind = AK_UNKNOWN;
4362 sRef_setNullStateN (s, NS_UNKNOWN);
4363 llassert (valueTable_isUndefined (s->state));
4364 s->state = context_createValueTable (s);
4366 DPRINTF (("Result: [%p] %s", s, sRef_unparseFull (s)));
4372 sRef_isNothing (sRef s)
4374 return (sRef_isKindSpecial (s) && s->info->spec == SR_NOTHING);
4378 sRef_isInternalState (sRef s)
4380 return (sRef_isKindSpecial (s) && s->info->spec == SR_INTERNAL);
4384 sRef_isSpecInternalState (sRef s)
4386 return (sRef_isKindSpecial (s)
4387 && (s->info->spec == SR_INTERNAL || s->info->spec == SR_SPECSTATE));
4391 sRef_isSpecState (sRef s)
4393 return (sRef_isKindSpecial (s) && s->info->spec == SR_SPECSTATE);
4397 sRef_isResult (sRef s)
4399 return (sRef_isValid (s) && s->kind == SK_RESULT);
4403 sRef_isSystemState (sRef s)
4405 return (sRef_isKindSpecial (s) && s->info->spec == SR_SYSTEM);
4409 sRef_isGlobalMarker (sRef s)
4411 return (sRef_isKindSpecial (s) && s->info->spec == SR_GLOBALMARKER);
4415 sRef_getScopeIndex (sRef s)
4417 llassert (sRef_isValid (s));
4418 llassert (sRef_isCvar (s));
4420 return (s->info->cvar->index);
4424 sRef_makeSafe (sRef s)
4426 if (sRef_isValid (s))
4433 sRef_makeUnsafe (sRef s)
4435 if (sRef_isValid (s))
4442 ** memory state operations
4445 /*@only@*/ cstring sRef_unparseFull (sRef s)
4447 if (sRef_isInvalid (s)) return (cstring_undefined);
4449 return (message ("[%d] %q - %q [%s] { %q } < %q >",
4451 sRef_unparseDebug (s),
4452 sRef_unparseState (s),
4453 exkind_unparse (s->oexpkind),
4454 sRefSet_unparseDebug (s->deriv),
4455 valueTable_unparse (s->state)));
4458 /*@unused@*/ cstring sRef_unparseDeep (sRef s)
4460 cstring st = cstring_undefined;
4462 st = message ("%q:", sRef_unparseFull (s));
4464 if (sRef_isValid (s))
4466 sRefSet_allElements (s->deriv, el)
4468 st = message("%q\n%q", st, sRef_unparseDeep (el));
4469 } end_sRefSet_allElements ;
4475 /*@only@*/ cstring sRef_unparseState (sRef s)
4477 if (sRef_isConj (s))
4479 return (message ("%q | %q",
4480 sRef_unparseState (s->info->conj->a),
4481 sRef_unparseState (s->info->conj->b)));
4484 if (sRef_isInvalid (s))
4486 return (cstring_makeLiteral ("<invalid>"));
4489 return (message ("%s.%s.%s.%s",
4490 alkind_unparse (s->aliaskind),
4491 nstate_unparse (sRef_getNullState (s)),
4492 exkind_unparse (s->expkind),
4493 sstate_unparse (s->defstate)));
4496 bool sRef_isNotUndefined (sRef s)
4498 return (sRef_isInvalid (s)
4499 || (s->defstate != SS_UNDEFINED
4500 && s->defstate != SS_UNUSEABLE
4501 && s->defstate != SS_DEAD));
4504 ynm sRef_isWriteable (sRef s)
4506 if (sRef_isInvalid (s)) return MAYBE;
4508 if (sRef_isConj (s) && s->defstate == SS_UNKNOWN)
4510 if (ynm_toBoolStrict (sRef_isWriteable (sRef_getConjA (s))))
4512 if (ynm_toBoolStrict (sRef_isWriteable (sRef_getConjB (s))))
4520 if (ynm_toBoolStrict (sRef_isWriteable (sRef_getConjB (s))))
4528 return (ynm_fromBool (s->defstate != SS_UNUSEABLE));
4531 bool sRef_hasNoStorage (sRef s)
4533 return (!sRef_isAllocatedStorage (s) || sRef_isDefinitelyNull (s));
4536 bool sRef_isStrictReadable (sRef s)
4538 return (ynm_toBoolStrict (sRef_isReadable (s)));
4541 ynm sRef_isReadable (sRef s)
4545 if (sRef_isInvalid (s)) return YES;
4549 if (sRef_isConj (s) && s->defstate == SS_UNKNOWN)
4551 if (ynm_toBoolStrict (sRef_isReadable (sRef_getConjA (s))))
4553 if (ynm_toBoolStrict (sRef_isReadable (sRef_getConjB (s))))
4561 if (ynm_toBoolStrict (sRef_isReadable (sRef_getConjB (s))))
4568 else if (ss == SS_HOFFA)
4570 if (context_getFlag (FLG_STRICTUSERELEASED))
4581 return (ynm_fromBool (ss == SS_DEFINED
4584 || ss == SS_PDEFINED
4587 || ss == SS_ALLOCATED
4588 || ss == SS_KILLED /* evans 2001-05-26: added this for killed globals */
4589 || ss == SS_UNKNOWN));
4593 static /*@exposed@*/ sRef whatUndefined (/*@exposed@*/ sRef fref, int depth)
4598 if (depth > MAXDEPTH)
4601 ("Warning: check definition limit exceeded, checking %q. "
4602 "This either means there is a variable with at least "
4603 "%d indirections apparent in the program text, or "
4604 "there is a bug in LCLint.",
4605 sRef_unparse (fref),
4609 return sRef_undefined;
4612 if (!sRef_isKnown (fref) || sRef_isAnyDefined (fref))
4614 return sRef_undefined;
4617 if (sRef_isUnuseable (fref) || sRef_isStateUndefined (fref))
4622 ct = ctype_realType (sRef_getType (fref));
4624 if (ctype_isUnknown (ct))
4626 return sRef_undefined;
4628 else if (ctype_isPointer (ct) || ctype_isArray (ct))
4630 if (sRef_isStateUnknown (fref))
4632 return sRef_undefined;
4636 sRef fptr = sRef_constructDeref (fref);
4638 return (whatUndefined (fptr, depth + 1));
4641 else if (ctype_isStruct (ct))
4643 bool hasOneDefined = FALSE;
4645 if (sRef_isStateUnknown (fref))
4650 if (sRef_isPdefined (fref) || sRef_isAnyDefined (fref))
4652 sRefSet_realElements (sRef_derivedFields (fref), sr)
4654 hasOneDefined = TRUE;
4656 if (sRef_isField (sr))
4658 cstring fieldname = sRef_getField (sr);
4659 sRef fldref = sRef_makeField (fref, fieldname);
4660 bool shouldCheck = !sRef_isRecursiveField (fldref);
4664 sRef wdef = whatUndefined (fldref, depth + 1);
4666 if (sRef_isValid (wdef))
4672 } end_sRefSet_realElements;
4674 else if (sRef_isAllocated (fref))
4677 ** for structures, each field must be completely defined
4680 uentryList fields = ctype_getFields (ct);
4682 uentryList_elements (fields, ue)
4684 cstring name = uentry_getRealName (ue);
4685 sRef ffield = sRef_makeField (fref, name);
4686 bool shouldCheck = !sRef_isRecursiveField (ffield);
4688 if (sRef_isRelDef (uentry_getSref (ue)))
4696 sRef wdef = whatUndefined (ffield, depth + 1);
4698 if (sRef_isInvalid (wdef))
4704 } end_uentryList_elements;
4711 else if (ctype_isUnion (ct))
4720 return sRef_undefined;
4723 static bool checkDefined (/*@temp@*/ sRef sr)
4725 /*@-temptrans@*/ /* the result from whatUndefined is lost */
4726 return (sRef_isInvalid (whatUndefined (sr, 0)));
4730 bool sRef_isReallyDefined (sRef s)
4732 if (sRef_isValid (s))
4734 if (sRef_isAnyDefined (s))
4740 if (sRef_isAllocated (s) || sRef_isPdefined (s))
4742 return checkDefined (s);
4756 void sRef_showNotReallyDefined (sRef s)
4758 if (sRef_isValid (s))
4760 if (sRef_isAnyDefined (s))
4766 if (sRef_isAllocated (s) || sRef_isPdefined (s))
4768 /*@-temptrans@*/ /* the result of whatUndefined is lost */
4769 sRef ref = whatUndefined (s, 0);
4771 llassert (sRef_isValid (ref));
4776 (message ("This sub-reference is %s: %q",
4777 sstate_unparse (sRef_getDefState (ref)),
4778 sRef_unparse (ref)));
4793 sstate sRef_getDefState (sRef s)
4795 if (sRef_isInvalid (s)) return (SS_UNKNOWN);
4796 return (s->defstate);
4799 void sRef_setDefState (sRef s, sstate defstate, fileloc loc)
4801 sRef_checkMutable (s);
4802 sRef_setStateAux (s, defstate, loc);
4805 static void sRef_clearAliasStateAux (sRef s, fileloc loc)
4807 sRef_checkMutable (s);
4808 sRef_setAliasKind (s, AK_ERROR, loc);
4811 void sRef_clearAliasState (sRef s, fileloc loc)
4813 sRef_checkMutable (s);
4814 sRef_aliasSetComplete (sRef_clearAliasStateAux, s, loc);
4817 void sRef_setAliasKindComplete (sRef s, alkind kind, fileloc loc)
4819 sRef_checkMutable (s);
4820 sRef_aliasSetCompleteParam (sRef_setAliasKind, s, kind, loc);
4823 void sRef_setAliasKind (sRef s, alkind kind, fileloc loc)
4825 sRef_checkMutable (s);
4827 if (sRef_isValid (s))
4829 sRef_clearDerived (s);
4831 if ((kind != s->aliaskind && kind != s->oaliaskind)
4832 && fileloc_isDefined (loc))
4834 s->aliasinfo = stateInfo_updateLoc (s->aliasinfo, loc);
4837 s->aliaskind = kind;
4841 void sRef_setOrigAliasKind (sRef s, alkind kind)
4843 sRef_checkMutable (s);
4845 if (sRef_isValid (s))
4847 s->oaliaskind = kind;
4851 exkind sRef_getExKind (sRef s)
4853 if (sRef_isValid (s))
4855 return (s->expkind);
4863 exkind sRef_getOrigExKind (sRef s)
4865 if (sRef_isValid (s))
4867 return (s->oexpkind);
4875 static void sRef_clearExKindAux (sRef s, fileloc loc)
4877 sRef_checkMutable (s);
4878 sRef_setExKind (s, XO_UNKNOWN, loc);
4881 void sRef_setObserver (sRef s, fileloc loc)
4883 sRef_checkMutable (s);
4884 sRef_setExKind (s, XO_OBSERVER, loc);
4887 void sRef_setExposed (sRef s, fileloc loc)
4889 sRef_checkMutable (s);
4890 sRef_setExKind (s, XO_EXPOSED, loc);
4893 void sRef_clearExKindComplete (sRef s, fileloc loc)
4895 (void) sRef_aliasSetComplete (sRef_clearExKindAux, s, loc);
4898 void sRef_setExKind (sRef s, exkind exp, fileloc loc)
4900 sRef_checkMutable (s);
4902 if (sRef_isValid (s))
4904 if (s->expkind != exp)
4906 s->expinfo = stateInfo_updateLoc (s->expinfo, loc);
4914 ** s1->derived = s2->derived
4917 static void sRef_copyRealDerived (sRef s1, sRef s2)
4919 DPRINTF (("Copy real: %s / %s", sRef_unparse (s1), sRef_unparse (s2)));
4920 sRef_checkMutable (s1);
4922 if (sRef_isValid (s1) && sRef_isValid (s2))
4924 sRef sb = sRef_getRootBase (s1);
4926 sRefSet_clear (s1->deriv);
4928 sRefSet_allElements (s2->deriv, el)
4930 if (sRef_isValid (el))
4932 sRef rb = sRef_getRootBase (el);
4934 if (!sRef_same (rb, sb))
4936 sRef fb = sRef_fixDirectBase (el, s1);
4938 if (sRef_isValid (fb))
4940 sRef_copyRealDerived (fb, el);
4941 sRef_addDeriv (s1, fb);
4946 sRef_addDeriv (s1, el);
4949 } end_sRefSet_allElements ;
4954 void sRef_copyRealDerivedComplete (sRef s1, sRef s2)
4956 sRef_innerAliasSetCompleteParam (sRef_copyRealDerived, s1, s2);
4959 void sRef_setUndefined (sRef s, fileloc loc)
4961 sRef_checkMutable (s);
4963 if (sRef_isValid (s))
4965 s->defstate = SS_UNDEFINED;
4967 if (fileloc_isDefined (loc))
4969 s->definfo = stateInfo_updateLoc (s->definfo, loc);
4972 sRef_clearDerived (s);
4976 static void sRef_setDefinedAux (sRef s, fileloc loc, bool clear)
4978 sRef_checkMutable (s);
4979 if (sRef_isInvalid (s)) return;
4981 if (s->defstate != SS_DEFINED && fileloc_isDefined (loc))
4983 s->definfo = stateInfo_updateLoc (s->definfo, loc);
4986 s->defstate = SS_DEFINED;
4988 /* e.g., if x is allocated, *x = 3 defines x */
4990 if (s->kind == SK_PTR)
4992 sRef p = s->info->ref;
4994 if (p->defstate == SS_ALLOCATED)
4996 sRef_setDefinedAux (p, loc, clear);
4999 else if (s->kind == SK_ARRAYFETCH)
5001 if (!s->info->arrayfetch->indknown
5002 || (s->info->arrayfetch->ind == 0))
5004 sRef p = s->info->arrayfetch->arr;
5005 sRef ptr = sRef_constructPointer (p);
5007 if (sRef_isValid (ptr))
5009 if (ptr->defstate == SS_ALLOCATED
5010 || ptr->defstate == SS_UNDEFINED)
5012 sRef_setDefinedAux (ptr, loc, clear);
5016 if (p->defstate == SS_RELDEF)
5020 else if (p->defstate == SS_ALLOCATED || p->defstate == SS_PDEFINED)
5022 p->defstate = SS_DEFINED;
5029 else if (s->kind == SK_FIELD)
5031 sRef parent = s->info->field->rec;
5033 if (sRef_isValid (parent))
5035 if (ctype_isUnion (ctype_realType (parent->type)))
5038 ** Should not clear derived from here.
5041 sRef_setDefinedNoClear (parent, loc);
5045 ; /* Nothing to do for structures. */
5057 sRef_clearDerived (s);
5061 static void sRef_setPartialDefined (sRef s, fileloc loc)
5063 sRef_checkMutable (s);
5065 if (!sRef_isPartial (s))
5067 sRef_setDefined (s, loc);
5071 void sRef_setPartialDefinedComplete (sRef s, fileloc loc)
5073 sRef_innerAliasSetComplete (sRef_setPartialDefined, s, loc);
5076 void sRef_setDefinedComplete (sRef s, fileloc loc)
5078 sRef_innerAliasSetComplete (sRef_setDefined, s, loc);
5081 void sRef_setDefined (sRef s, fileloc loc)
5083 sRef_checkMutable (s);
5084 sRef_setDefinedAux (s, loc, TRUE);
5087 static void sRef_setDefinedNoClear (sRef s, fileloc loc)
5089 sRef_checkMutable (s);
5090 DPRINTF (("Defining: %s", sRef_unparseFull (s)));
5091 sRef_setDefinedAux (s, loc, FALSE);
5092 DPRINTF (("==> %s", sRef_unparseFull (s)));
5095 void sRef_setDefinedNCComplete (sRef s, fileloc loc)
5097 sRef_checkMutable (s);
5098 DPRINTF (("Set Defined Complete: %s", sRef_unparseFull (s)));
5099 sRef_innerAliasSetComplete (sRef_setDefinedNoClear, s, loc);
5100 DPRINTF (("==> %s", sRef_unparseFull (s)));
5103 static bool sRef_isDeepUnionField (sRef s)
5105 return (sRef_deepPred (sRef_isUnionField, s));
5108 bool sRef_isUnionField (sRef s)
5110 if (sRef_isValid (s) && s->kind == SK_FIELD)
5113 ** defining one field of a union defines the union
5116 sRef base = s->info->field->rec;
5118 if (sRef_isValid (base))
5120 return (ctype_isUnion (ctype_realType (base->type)));
5127 void sRef_setPdefined (sRef s, fileloc loc)
5129 sRef_checkMutable (s);
5130 if (sRef_isValid (s) && !sRef_isPartial (s))
5132 sRef base = sRef_getBaseSafe (s);
5134 if (s->defstate == SS_ALLOCATED)
5139 if (s->defstate != SS_PDEFINED && fileloc_isDefined (loc))
5141 s->definfo = stateInfo_updateLoc (s->definfo, loc);
5144 DPRINTF (("set pdefined: %s", sRef_unparseFull (s)));
5145 s->defstate = SS_PDEFINED;
5147 /* e.g., if x is allocated, *x = 3 defines x */
5149 while (sRef_isValid (base) && sRef_isKnown (base))
5151 if (base->defstate == SS_DEFINED)
5155 base->defstate = SS_PDEFINED;
5156 nb = sRef_getBaseSafe (base);
5167 static void sRef_setStateAux (sRef s, sstate ss, fileloc loc)
5169 sRef_checkMutable (s);
5171 if (sRef_isValid (s))
5173 /* if (s->defstate == SS_RELDEF) return; */
5175 if (s->defstate != ss && fileloc_isDefined (loc))
5177 s->definfo = stateInfo_updateLoc (s->definfo, loc);
5181 sRef_clearDerived (s);
5183 if (ss == SS_ALLOCATED)
5185 sRef base = sRef_getBaseSafe (s);
5187 while (sRef_isValid (base) && sRef_isKnown (base))
5189 if (base->defstate == SS_DEFINED)
5193 base->defstate = SS_PDEFINED;
5195 nb = sRef_getBaseSafe (base);
5208 void sRef_setAllocatedComplete (sRef s, fileloc loc)
5210 sRef_innerAliasSetComplete (sRef_setAllocated, s, loc);
5213 static void sRef_setAllocatedShallow (sRef s, fileloc loc)
5215 sRef_checkMutable (s);
5217 if (sRef_isValid (s))
5219 if (s->defstate == SS_DEAD || s->defstate == SS_UNDEFINED)
5221 s->defstate = SS_ALLOCATED;
5223 if (fileloc_isDefined (loc))
5225 s->definfo = stateInfo_updateLoc (s->definfo, loc);
5231 void sRef_setAllocatedShallowComplete (sRef s, fileloc loc)
5233 sRef_innerAliasSetComplete (sRef_setAllocatedShallow, s, loc);
5236 void sRef_setAllocated (sRef s, fileloc loc)
5238 sRef_checkMutable (s);
5239 sRef_setStateAux (s, SS_ALLOCATED, loc);
5242 void sRef_setPartial (sRef s, fileloc loc)
5244 sRef_checkMutable (s);
5245 sRef_setStateAux (s, SS_PARTIAL, loc);
5248 void sRef_setShared (sRef s, fileloc loc)
5250 sRef_checkMutable (s);
5252 if (sRef_isValid (s))
5254 if (s->aliaskind != AK_SHARED && fileloc_isDefined (loc))
5256 s->aliasinfo = stateInfo_updateLoc (s->aliasinfo, loc);
5259 s->aliaskind = AK_SHARED;
5260 /* don't! sRef_clearDerived (s); */
5264 void sRef_setLastReference (sRef s, /*@exposed@*/ sRef ref, fileloc loc)
5266 sRef_checkMutable (s);
5268 if (sRef_isValid (s))
5270 s->aliaskind = sRef_getAliasKind (ref);
5271 s->aliasinfo = stateInfo_updateRefLoc (s->aliasinfo, ref, loc);
5276 void sRef_setNullStateAux (/*@notnull@*/ sRef s, nstate ns, fileloc loc)
5278 DPRINTF (("Set null state: %s / %s", sRef_unparse (s), nstate_unparse (ns)));
5279 sRef_checkMutable (s);
5282 if (fileloc_isDefined (loc))
5284 s->nullinfo = stateInfo_updateLoc (s->nullinfo, loc);
5288 void sRef_setNotNull (sRef s, fileloc loc)
5290 if (sRef_isValid (s))
5292 sRef_setNullStateAux (s, NS_NOTNULL, loc);
5296 void sRef_setNullStateN (sRef s, nstate n)
5298 sRef_checkMutable (s);
5302 void sRef_setNullState (sRef s, nstate n, fileloc loc)
5304 if (sRef_isValid (s))
5306 sRef_setNullStateAux (s, n, loc);
5310 void sRef_setNullTerminatedStateInnerComplete (sRef s, struct s_bbufinfo b, /*@unused@*/ fileloc loc) {
5312 switch (b.bufstate) {
5313 case BB_NULLTERMINATED:
5314 sRef_setNullTerminatedState (s);
5315 sRef_setLen (s, b.len);
5317 case BB_POSSIBLYNULLTERMINATED:
5318 sRef_setPossiblyNullTerminatedState(s);
5320 case BB_NOTNULLTERMINATED:
5321 sRef_setNotNullTerminatedState (s);
5324 sRef_setSize (s, b.size);
5326 /* PL: TO BE DONE : Aliases are not modified right now, have to be similar to
5327 * setNullStateInnerComplete.
5331 void sRef_setNullStateInnerComplete (sRef s, nstate n, fileloc loc)
5333 DPRINTF (("Set null state: %s", nstate_unparse (n)));
5335 sRef_setNullState (s, n, loc);
5340 sRef_innerAliasSetComplete (sRef_setPosNull, s, loc);
5343 sRef_innerAliasSetComplete (sRef_setDefNull, s, loc);
5346 sRef_innerAliasSetComplete (sRef_setNullUnknown, s, loc);
5349 sRef_innerAliasSetComplete (sRef_setNotNull, s, loc);
5352 sRef_innerAliasSetComplete (sRef_setNotNull, s, loc);
5355 sRef_innerAliasSetComplete (sRef_setNullUnknown, s, loc);
5358 sRef_innerAliasSetComplete (sRef_setDefNull, s, loc);
5361 sRef_innerAliasSetComplete (sRef_setNullUnknown, s, loc);
5364 sRef_innerAliasSetComplete (sRef_setNullErrorLoc, s, loc);
5369 void sRef_setPosNull (sRef s, fileloc loc)
5371 if (sRef_isValid (s))
5373 sRef_setNullStateAux (s, NS_POSNULL, loc);
5377 void sRef_setDefNull (sRef s, fileloc loc)
5379 if (sRef_isValid (s))
5381 sRef_setNullStateAux (s, NS_DEFNULL, loc);
5385 void sRef_setNullUnknown (sRef s, fileloc loc)
5387 if (sRef_isValid (s))
5389 sRef_setNullStateAux (s, NS_UNKNOWN, loc);
5393 void sRef_setNullError (sRef s)
5395 if (sRef_isValid (s))
5397 sRef_setNullStateAux (s, NS_UNKNOWN, fileloc_undefined);
5401 void sRef_setNullErrorLoc (sRef s, /*@unused@*/ fileloc loc)
5403 sRef_setNullError (s);
5406 void sRef_setOnly (sRef s, fileloc loc)
5408 sRef_checkMutable (s);
5410 if (sRef_isValid (s) && s->aliaskind != AK_ONLY)
5412 s->aliaskind = AK_ONLY;
5413 s->aliasinfo = stateInfo_updateLoc (s->aliasinfo, loc);
5417 void sRef_setDependent (sRef s, fileloc loc)
5419 sRef_checkMutable (s);
5421 if (sRef_isValid (s) && !sRef_isConst (s) && (s->aliaskind != AK_DEPENDENT))
5423 DPRINTF (("Setting dependent: %s", sRef_unparseFull (s)));
5424 s->aliaskind = AK_DEPENDENT;
5425 s->aliasinfo = stateInfo_updateLoc (s->aliasinfo, loc);
5429 void sRef_setOwned (sRef s, fileloc loc)
5431 sRef_checkMutable (s);
5433 if (sRef_isValid (s) && !sRef_isConst (s) && (s->aliaskind != AK_OWNED))
5435 s->aliaskind = AK_OWNED;
5436 s->aliasinfo = stateInfo_updateLoc (s->aliasinfo, loc);
5440 void sRef_setKept (sRef s, fileloc loc)
5442 sRef_checkMutable (s);
5444 if (sRef_isValid (s) && !sRef_isConst (s) && (s->aliaskind != AK_KEPT))
5446 sRef base = sRef_getBaseSafe (s);
5448 while (sRef_isValid (base) && sRef_isKnown (base))
5450 if (base->defstate == SS_DEFINED)
5452 base->defstate = SS_PDEFINED;
5453 base = sRef_getBaseSafe (base);
5462 s->aliaskind = AK_KEPT;
5463 s->aliasinfo = stateInfo_updateLoc (s->aliasinfo, loc);
5467 static void sRef_setKeptAux (sRef s, fileloc loc)
5469 if (!sRef_isShared (s))
5471 sRef_setKept (s, loc);
5475 static void sRef_setDependentAux (sRef s, fileloc loc)
5477 if (!sRef_isShared (s))
5479 sRef_setDependent (s, loc);
5483 void sRef_setKeptComplete (sRef s, fileloc loc)
5485 sRef_aliasSetComplete (sRef_setKeptAux, s, loc);
5488 void sRef_setDependentComplete (sRef s, fileloc loc)
5490 sRef_aliasSetComplete (sRef_setDependentAux, s, loc);
5493 void sRef_setFresh (sRef s, fileloc loc)
5495 sRef_checkMutable (s);
5497 if (sRef_isValid (s))
5499 s->aliaskind = AK_FRESH;
5500 s->aliasinfo = stateInfo_updateLoc (s->aliasinfo, loc);
5504 void sRef_kill (sRef s, fileloc loc)
5506 DPRINTF (("Kill: %s", sRef_unparseFull (s)));
5507 sRef_checkMutable (s);
5509 if (sRef_isValid (s) && !sRef_isShared (s) && !sRef_isConst (s))
5511 sRef base = sRef_getBaseSafe (s);
5513 while (sRef_isValid (base) && sRef_isKnown (base))
5515 if (base->defstate == SS_DEFINED)
5517 base->defstate = SS_PDEFINED;
5518 base = sRef_getBaseSafe (base);
5526 s->aliaskind = s->oaliaskind;
5527 s->defstate = SS_DEAD;
5528 s->definfo = stateInfo_updateLoc (s->definfo, loc);
5530 sRef_clearDerived (s);
5534 void sRef_maybeKill (sRef s, fileloc loc)
5536 sRef_checkMutable (s);
5538 if (sRef_isValid (s))
5540 sRef base = sRef_getBaseSafe (s);
5543 while (sRef_isValid (base) && sRef_isKnown (base))
5545 if (base->defstate == SS_DEFINED || base->defstate == SS_RELDEF)
5547 base->defstate = SS_PDEFINED;
5548 base = sRef_getBaseSafe (base);
5557 s->aliaskind = s->oaliaskind;
5558 s->defstate = SS_HOFFA;
5559 s->definfo = stateInfo_updateLoc (s->definfo, loc);
5560 sRef_clearDerived (s);
5566 ** just for type checking...
5569 static void sRef_killAux (sRef s, fileloc loc)
5571 if (sRef_isValid (s) && !sRef_isShared (s))
5573 if (sRef_isUnknownArrayFetch (s))
5575 sRef_maybeKill (s, loc);
5585 ** kills s and all aliases to s
5588 void sRef_killComplete (sRef s, fileloc loc)
5590 DPRINTF (("Kill complete: %s", sRef_unparseFull (s)));
5591 sRef_aliasSetComplete (sRef_killAux, s, loc);
5594 static bool sRef_equivalent (sRef s1, sRef s2)
5596 return (sRef_compare (s1, s2) == 0);
5600 ** returns an sRef that will not be free'd on function exit.
5603 /*@only@*/ sRef sRef_saveCopy (sRef s)
5607 if (sRef_isValid (s))
5609 bool old = inFunction;
5612 ** Exit the function scope, so this sRef is not
5613 ** stored in the deallocation table.
5617 DPRINTF (("Copying sref: %s", sRef_unparseFull(s)));
5618 ret = sRef_copy (s);
5619 DPRINTF (("Copying ===>: %s", sRef_unparseFull(ret)));
5624 ret = sRef_undefined;
5627 /*@-dependenttrans@*/
5629 /*@=dependenttrans@*/
5632 sRef sRef_copy (sRef s)
5634 if (sRef_isKindSpecial (s) && !sRef_isGlobalMarker (s))
5637 return s; /* don't copy specials (except for global markers) */
5641 if (sRef_isValid (s))
5643 sRef t = sRef_alloc ();
5645 DPRINTF (("Copying: [%p] %s", s, sRef_unparse (s)));
5646 DPRINTF (("Full: %s", sRef_unparseFull (s)));
5650 t->modified = s->modified;
5651 t->immut = FALSE; /* Note mutability is not copied. */
5654 t->info = sinfo_copy (s);
5655 t->defstate = s->defstate;
5656 t->nullstate = s->nullstate;
5658 /* start modifications */
5659 t->bufinfo.bufstate = s->bufinfo.bufstate;
5660 t->bufinfo.len = s->bufinfo.len;
5661 t->bufinfo.size = s->bufinfo.size;
5662 /* end modifications */
5664 t->aliaskind = s->aliaskind;
5665 t->oaliaskind = s->oaliaskind;
5667 t->expkind = s->expkind;
5668 t->oexpkind = s->oexpkind;
5670 t->nullinfo = stateInfo_copy (s->nullinfo);
5671 t->aliasinfo = stateInfo_copy (s->aliasinfo);
5672 t->definfo = stateInfo_copy (s->definfo);
5673 t->expinfo = stateInfo_copy (s->expinfo);
5675 t->deriv = sRefSet_newDeepCopy (s->deriv);
5676 t->state = valueTable_copy (s->state);
5678 DPRINTF (("Made copy: [%p] %s", t, sRef_unparse (t)));
5683 return sRef_undefined;
5688 # define PREDTEST(func,s) \
5689 do { if (sRef_isInvalid (s)) { return FALSE; } \
5690 else { if (sRef_isConj (s)) \
5691 { return (func (sRef_getConjA (s)) \
5692 || func (sRef_getConjB (s))); }}} while (FALSE);
5694 bool sRef_isAddress (sRef s)
5696 PREDTEST (sRef_isAddress, s);
5697 return (s->kind == SK_ADR);
5701 ** pretty weak... maybe a flag should control this.
5704 bool sRef_isThroughArrayFetch (sRef s)
5706 if (sRef_isValid (s))
5714 if (sRef_isArrayFetch (tref))
5719 lt = sRef_getBase (tref);
5721 } while (sRef_isValid (tref));
5727 bool sRef_isArrayFetch (sRef s)
5729 PREDTEST (sRef_isArrayFetch, s);
5730 return (s->kind == SK_ARRAYFETCH);
5733 bool sRef_isMacroParamRef (sRef s)
5735 if (context_inMacro () && sRef_isCvar (s))
5737 uentry ue = sRef_getUentry (s);
5738 cstring pname = makeParam (uentry_rawName (ue));
5739 uentry mac = usymtab_lookupSafe (pname);
5741 cstring_free (pname);
5742 return (uentry_isValid (mac));
5748 bool sRef_isCvar (sRef s)
5750 PREDTEST (sRef_isCvar, s);
5751 return (s->kind == SK_CVAR);
5754 bool sRef_isConst (sRef s)
5756 PREDTEST (sRef_isConst, s);
5757 return (s->kind == SK_CONST);
5760 bool sRef_isObject (sRef s)
5762 PREDTEST (sRef_isObject, s);
5763 return (s->kind == SK_OBJECT);
5766 bool sRef_isExternal (sRef s)
5768 PREDTEST (sRef_isExternal, s);
5769 return (s->kind == SK_EXTERNAL);
5772 static bool sRef_isDerived (sRef s)
5774 PREDTEST (sRef_isDerived, s);
5775 return (s->kind == SK_DERIVED);
5778 bool sRef_isField (sRef s)
5780 PREDTEST (sRef_isField, s);
5781 return (s->kind == SK_FIELD);
5784 static bool sRef_isIndex (sRef s)
5786 PREDTEST (sRef_isIndex, s);
5787 return (s->kind == SK_ARRAYFETCH);
5790 bool sRef_isAnyParam (sRef s)
5792 PREDTEST (sRef_isAnyParam, s);
5793 return (s->kind == SK_PARAM);
5796 bool sRef_isParam (sRef s)
5798 PREDTEST (sRef_isParam, s);
5799 return (s->kind == SK_PARAM);
5802 bool sRef_isDirectParam (sRef s)
5804 PREDTEST (sRef_isDirectParam, s);
5806 return ((s->kind == SK_CVAR) &&
5807 (s->info->cvar->lexlevel == functionScope) &&
5808 (context_inFunction () &&
5809 (s->info->cvar->index <= uentryList_size (context_getParams ()))));
5812 bool sRef_isPointer (sRef s)
5814 PREDTEST (sRef_isPointer, s);
5815 return (s->kind == SK_PTR);
5819 ** returns true if storage referenced by s is visible
5822 bool sRef_isReference (sRef s)
5824 PREDTEST (sRef_isReference, s);
5826 return (sRef_isPointer (s) || sRef_isIndex (s) || sRef_isFileOrGlobalScope (s)
5827 || (sRef_isField (s) && (sRef_isReference (s->info->field->rec))));
5830 bool sRef_isIReference (sRef s)
5832 return (sRef_isPointer (s) || sRef_isAddress (s) || sRef_isIndex (s)
5833 || sRef_isField (s) || sRef_isArrayFetch (s));
5836 bool sRef_isFileOrGlobalScope (sRef s)
5838 return (sRef_isCvar (s) && (s->info->cvar->lexlevel <= fileScope));
5841 bool sRef_isRealGlobal (sRef s)
5843 return (sRef_isCvar (s) && (s->info->cvar->lexlevel == globScope));
5846 bool sRef_isFileStatic (sRef s)
5848 return (sRef_isCvar (s) && (s->info->cvar->lexlevel == fileScope));
5851 bool sRef_isAliasCheckedGlobal (sRef s)
5853 if (sRef_isFileOrGlobalScope (s))
5855 uentry ue = sRef_getUentry (s);
5857 return context_checkAliasGlob (ue);
5865 void sRef_free (/*@only@*/ sRef s)
5867 if (s != sRef_undefined && s->kind != SK_SPECIAL)
5869 DPRINTF (("Free sref: [%p]", s));
5871 sRef_checkValid (s);
5873 stateInfo_free (s->expinfo);
5874 stateInfo_free (s->aliasinfo);
5875 stateInfo_free (s->definfo);
5876 stateInfo_free (s->nullinfo);
5878 sRefSet_free (s->deriv);
5879 s->deriv = sRefSet_undefined;
5881 /*@i43@*/ /* valueTable_free (s->state); */
5885 /* drl added to help locate use after release*/
5886 s->expinfo = stateInfo_undefined;
5887 s->aliasinfo = stateInfo_undefined;
5888 s->definfo = stateInfo_undefined;
5889 s->nullinfo = stateInfo_undefined;
5891 /*@i32@*/ sfree (s);
5895 void sRef_setType (sRef s, ctype t)
5897 sRef_checkMutable (s);
5899 if (sRef_isValid (s))
5905 void sRef_setTypeFull (sRef s, ctype t)
5907 sRef_checkMutable (s);
5909 if (sRef_isValid (s))
5913 sRefSet_allElements (s->deriv, current)
5915 sRef_setTypeFull (current, ctype_unknown);
5916 } end_sRefSet_allElements ;
5921 sRef_buildField (/*@exposed@*/ sRef rec, /*@dependent@*/ cstring f)
5923 return (sRef_buildNCField (rec, f));
5926 static /*@exposed@*/ sRef
5927 sRef_findDerivedField (/*@notnull@*/ sRef rec, cstring f)
5929 sRefSet_allElements (rec->deriv, sr)
5931 if (sRef_isValid (sr))
5933 if (sr->info != NULL)
5935 if (sr->kind == SK_FIELD && cstring_equal (sr->info->field->field, f))
5941 } end_sRefSet_allElements;
5943 return sRef_undefined;
5946 /*@dependent@*/ /*@observer@*/ sRefSet sRef_derivedFields (/*@temp@*/ sRef rec)
5948 if (sRef_isValid (rec))
5956 return (sRefSet_undefined);
5960 static /*@exposed@*/ sRef
5961 sRef_findDerivedPointer (sRef s)
5963 if (sRef_isValid (s))
5965 sRefSet_realElements (s->deriv, sr)
5967 if (sRef_isValid (sr) && sr->kind == SK_PTR)
5971 } end_sRefSet_realElements;
5974 return sRef_undefined;
5978 sRef_isUnknownArrayFetch (sRef s)
5980 return (sRef_isValid (s)
5981 && s->kind == SK_ARRAYFETCH
5982 && !s->info->arrayfetch->indknown);
5985 static /*@exposed@*/ sRef
5986 sRef_findDerivedArrayFetch (/*@notnull@*/ sRef s, bool isknown, int idx, bool dead)
5991 sRefSet_realElements (s->deriv, sr)
5993 if (sRef_isValid (sr)
5994 && sr->kind == SK_ARRAYFETCH
5995 && sr->info->arrayfetch->indknown
5996 && (sr->info->arrayfetch->ind == idx))
6000 } end_sRefSet_realElements;
6004 sRefSet_realElements (s->deriv, sr)
6006 if (sRef_isValid (sr)
6007 && sr->kind == SK_ARRAYFETCH
6008 && (!sr->info->arrayfetch->indknown
6009 || (sr->info->arrayfetch->indknown &&
6010 sr->info->arrayfetch->ind == 0)))
6012 if (sRef_isDead (sr) || sRef_isKept (sr))
6014 if (dead || context_getFlag (FLG_STRICTUSERELEASED))
6024 } end_sRefSet_realElements;
6027 return sRef_undefined;
6030 static /*@exposed@*/ sRef
6031 sRef_buildNCField (/*@exposed@*/ sRef rec, /*@exposed@*/ cstring f)
6035 DPRINTF (("Build nc field: %s / %s",
6036 sRef_unparseFull (rec), f));
6038 if (sRef_isInvalid (rec))
6040 return sRef_undefined;
6044 ** check if the field already has been referenced
6047 s = sRef_findDerivedField (rec, f);
6049 if (sRef_isValid (s))
6055 ctype ct = ctype_realType (rec->type);
6057 DPRINTF (("Field of: %s", sRef_unparse (rec)));
6061 s->info = (sinfo) dmalloc (sizeof (*s->info));
6062 s->info->field = (fldinfo) dmalloc (sizeof (*s->info->field));
6063 s->info->field->rec = rec; /* sRef_copy (rec); */ /*@i32@*/
6064 s->info->field->field = f; /* doesn't copy f */
6066 if (ctype_isKnown (ct) && ctype_isSU (ct))
6068 uentry ue = uentryList_lookupField (ctype_getFields (ct), f);
6070 if (!uentry_isUndefined (ue))
6072 DPRINTF (("lookup: %s for %s", uentry_unparseFull (ue),
6073 ctype_unparse (ct)));
6075 s->type = uentry_getType (ue);
6077 if (ctype_isMutable (s->type)
6078 && rec->aliaskind != AK_STACK
6079 && !alkind_isStatic (rec->aliaskind))
6081 s->aliaskind = rec->aliaskind;
6085 s->aliaskind = AK_UNKNOWN;
6088 if (sRef_isStateDefined (rec) || sRef_isStateUnknown (rec)
6089 || sRef_isPdefined (rec))
6091 sRef_setStateFromUentry (s, ue);
6095 sRef_setPartsFromUentry (s, ue);
6098 s->oaliaskind = s->aliaskind;
6099 s->oexpkind = s->expkind;
6101 DPRINTF (("sref: %s", sRef_unparseFull (s)));
6106 Never report this as an error. It can happen whenever there
6107 is casting involved.
6111 llcontbug (message ("buildNCField --- no field %s: %q / %s",
6112 f, sRef_unparse (s), ctype_unparse (ct)));
6116 return sRef_undefined;
6120 if (rec->defstate == SS_DEFINED
6121 && (s->defstate == SS_UNDEFINED || s->defstate == SS_UNKNOWN))
6123 s->defstate = SS_DEFINED;
6125 else if (rec->defstate == SS_PARTIAL)
6127 s->defstate = SS_PARTIAL;
6129 else if (rec->defstate == SS_ALLOCATED)
6131 if (ctype_isStackAllocated (ct) && ctype_isStackAllocated (s->type))
6133 s->defstate = SS_ALLOCATED;
6137 s->defstate = SS_UNDEFINED;
6140 else if (s->defstate == SS_UNKNOWN)
6142 s->defstate = rec->defstate;
6149 if (s->defstate == SS_UNDEFINED)
6151 ctype rt = ctype_realType (s->type);
6153 if (ctype_isArray (rt) || ctype_isSU (rt))
6155 s->defstate = SS_ALLOCATED;
6159 sRef_addDeriv (rec, s);
6160 DPRINTF (("Add deriv: %s", sRef_unparseFull (rec)));
6162 if (ctype_isInt (s->type) && cstring_equal (f, REFSNAME))
6164 s->aliaskind = AK_REFS;
6165 s->oaliaskind = AK_REFS;
6168 DPRINTF (("Build field ==> %s", sRef_unparseFull (s)));
6174 sRef_isStackAllocated (sRef s)
6176 return (sRef_isValid(s)
6177 && s->defstate == SS_ALLOCATED && ctype_isStackAllocated (s->type));
6181 void sRef_setArrayFetchState (/*@notnull@*/ /*@exposed@*/ sRef s,
6182 /*@notnull@*/ /*@exposed@*/ sRef arr)
6184 sRef_checkMutable (s);
6186 if (ctype_isRealAP (arr->type))
6188 s->type = ctype_baseArrayPtr (arr->type);
6191 /* a hack, methinks... makeArrayFetch (&a[0]) ==> a[] */
6192 if (sRef_isAddress (arr))
6194 sRef t = arr->info->ref;
6196 if (sRef_isArrayFetch (t))
6198 s->info->arrayfetch->arr = t->info->arrayfetch->arr;
6201 else if (ctype_isRealPointer (arr->type))
6203 sRef sp = sRef_findDerivedPointer (arr);
6205 if (sRef_isValid (sp))
6208 if (ctype_isMutable (s->type))
6210 sRef_setExKind (s, sRef_getExKind (sp), fileloc_undefined);
6212 s->aliaskind = sp->aliaskind;
6215 s->defstate = sp->defstate;
6217 if (s->defstate == SS_DEFINED)
6219 if (!context_getFlag (FLG_STRICTDESTROY))
6221 s->defstate = SS_PARTIAL;
6225 sRef_setNullStateN (s, sRef_getNullState (sp));
6229 if (arr->defstate == SS_UNDEFINED)
6231 s->defstate = SS_UNUSEABLE;
6233 else if ((arr->defstate == SS_ALLOCATED) && !ctype_isSU (s->type))
6235 s->defstate = SS_UNDEFINED;
6239 if (!context_getFlag (FLG_STRICTDESTROY))
6241 s->defstate = SS_PARTIAL;
6245 s->defstate = SS_DEFINED;
6249 ** Very weak checking for array elements.
6251 ** s->defstate = arr->defstate;
6255 sRef_setExKind (s, sRef_getExKind (arr), g_currentloc);
6257 if (arr->aliaskind == AK_LOCAL || arr->aliaskind == AK_FRESH)
6259 s->aliaskind = AK_LOCAL;
6263 s->aliaskind = AK_UNKNOWN;
6266 sRef_setTypeState (s);
6271 if (arr->defstate == SS_DEFINED)
6274 ** Very weak checking for array elements.
6276 ** s->defstate = arr->defstate;
6279 if (context_getFlag (FLG_STRICTDESTROY))
6281 s->defstate = SS_DEFINED;
6285 s->defstate = SS_PARTIAL;
6288 else if (arr->defstate == SS_ALLOCATED)
6290 if (ctype_isRealArray (s->type))
6292 s->defstate = SS_ALLOCATED;
6296 if (!s->info->arrayfetch->indknown)
6299 ** is index is unknown, elements is defined or
6300 ** allocated is any element is!
6303 s->defstate = SS_UNDEFINED;
6305 sRefSet_allElements (arr->deriv, sr)
6307 if (sRef_isValid (sr))
6309 if (sr->defstate == SS_ALLOCATED)
6311 s->defstate = SS_ALLOCATED;
6315 if (sr->defstate == SS_DEFINED)
6317 if (context_getFlag (FLG_STRICTDESTROY))
6319 s->defstate = SS_DEFINED;
6323 s->defstate = SS_PARTIAL;
6330 } end_sRefSet_allElements;
6335 s->defstate = SS_UNDEFINED;
6341 s->defstate = arr->defstate;
6346 ** kludgey way to guess where aliaskind applies
6349 if (ctype_isMutable (s->type)
6350 && !ctype_isPointer (arr->type)
6351 && !alkind_isStatic (arr->aliaskind)
6352 && !alkind_isStack (arr->aliaskind)) /* evs - 2000-06-20: don't pass stack allocation to members */
6354 s->aliaskind = arr->aliaskind;
6358 s->aliaskind = AK_UNKNOWN;
6361 sRef_setTypeState (s);
6364 if (sRef_isObserver (arr))
6366 s->expkind = XO_OBSERVER;
6370 /*@exposed@*/ sRef sRef_buildArrayFetch (/*@exposed@*/ sRef arr)
6374 if (!sRef_isValid (arr)) {
6375 /*@-nullret@*/ return arr /*@=nullret@*/;
6378 if (ctype_isRealPointer (arr->type))
6380 (void) sRef_buildPointer (arr); /* do this to define arr! */
6383 s = sRef_findDerivedArrayFetch (arr, FALSE, 0, FALSE);
6385 if (sRef_isValid (s))
6387 sRef_setExKind (s, sRef_getExKind (arr), g_currentloc);
6394 s->kind = SK_ARRAYFETCH;
6395 s->info = (sinfo) dmalloc (sizeof (*s->info));
6396 s->info->arrayfetch = (ainfo) dmalloc (sizeof (*s->info->arrayfetch));
6397 s->info->arrayfetch->indknown = FALSE;
6398 s->info->arrayfetch->ind = 0;
6399 s->info->arrayfetch->arr = arr; /* sRef_copy (arr); */ /*@i32@*/
6400 sRef_setArrayFetchState (s, arr);
6401 s->oaliaskind = s->aliaskind;
6402 s->oexpkind = s->expkind;
6404 if (!context_inProtectVars ())
6406 sRef_addDeriv (arr, s);
6409 llassert (valueTable_isUndefined (s->state));
6410 s->state = context_createValueTable (s);
6417 sRef_buildArrayFetchKnown (/*@exposed@*/ sRef arr, int i)
6421 if (!sRef_isValid (arr)) {
6422 /*@-nullret@*/ return arr /*@=nullret@*/;
6425 if (ctype_isRealPointer (arr->type))
6427 (void) sRef_buildPointer (arr); /* do this to define arr! */
6430 s = sRef_findDerivedArrayFetch (arr, TRUE, i, FALSE);
6432 if (sRef_isValid (s))
6434 sRef_setExKind (s, sRef_getExKind (arr), g_currentloc);
6441 s->kind = SK_ARRAYFETCH;
6442 s->info = (sinfo) dmalloc (sizeof (*s->info));
6443 s->info->arrayfetch = (ainfo) dmalloc (sizeof (*s->info->arrayfetch));
6444 s->info->arrayfetch->arr = arr; /* sRef_copy (arr); */ /*@i32@*/
6445 s->info->arrayfetch->indknown = TRUE;
6446 s->info->arrayfetch->ind = i;
6448 sRef_setArrayFetchState (s, arr);
6450 s->oaliaskind = s->aliaskind;
6451 s->oexpkind = s->expkind;
6452 sRef_addDeriv (arr, s);
6454 llassert (valueTable_isUndefined (s->state));
6455 s->state = context_createValueTable (s);
6462 ** sets everything except for defstate
6466 sRef_setPartsFromUentry (sRef s, uentry ue)
6468 sRef uref = uentry_getSref (ue);
6470 llassert (sRef_isValid (s));
6472 s->aliaskind = alkind_derive (s->aliaskind, uentry_getAliasKind (ue));
6473 s->oaliaskind = s->aliaskind;
6475 if (s->expkind == XO_UNKNOWN)
6477 s->expkind = uentry_getExpKind (ue);
6480 s->oexpkind = s->expkind;
6482 if (sRef_getNullState (s) == NS_UNKNOWN)
6484 DPRINTF (("Setting null state!"));
6485 sRef_setNullStateN (s, sRef_getNullState (uentry_getSref (ue)));
6489 DPRINTF (("Skipping null null state!"));
6492 if (s->aliaskind == AK_IMPONLY && (sRef_isExposed (s) || sRef_isObserver (s)))
6494 s->oaliaskind = s->aliaskind = AK_IMPDEPENDENT;
6497 if (sRef_isValid (uref))
6499 valueTable utable = uref->state;
6500 valueTable_free (s->state);
6501 s->state = valueTable_copy (utable);
6506 sRef_setStateFromAbstractUentry (sRef s, uentry ue)
6508 llassert (sRef_isValid (s));
6509 sRef_checkMutable (s);
6511 sRef_setPartsFromUentry (s, ue);
6513 s->aliaskind = alkind_derive (s->aliaskind, uentry_getAliasKind (ue));
6514 s->oaliaskind = s->aliaskind;
6516 if (s->expkind == XO_UNKNOWN)
6518 s->expkind = uentry_getExpKind (ue);
6521 s->oexpkind = s->expkind;
6525 sRef_setStateFromUentry (sRef s, uentry ue)
6529 sRef_checkMutable (s);
6530 llassert (sRef_isValid (s));
6532 sRef_setPartsFromUentry (s, ue);
6534 defstate = uentry_getDefState (ue);
6536 if (sstate_isKnown (defstate))
6538 s->defstate = defstate;
6547 sRef_buildPointer (/*@exposed@*/ sRef t)
6549 DPRINTF (("build pointer: %s", sRef_unparse (t)));
6551 if (sRef_isInvalid (t)) return sRef_undefined;
6553 if (sRef_isAddress (t))
6555 DPRINTF (("Return ref: %s", sRef_unparse (t->info->ref)));
6556 return (t->info->ref);
6560 sRef s = sRef_findDerivedPointer (t);
6562 DPRINTF (("find derived: %s", sRef_unparse (s)));
6564 if (sRef_isValid (s))
6567 sRef_setExKind (s, sRef_getExKind (t), g_currentloc);
6568 s->oaliaskind = s->aliaskind;
6569 s->oexpkind = s->expkind;
6575 s = sRef_constructPointerAux (t);
6577 DPRINTF (("construct: %s", sRef_unparse (s)));
6579 if (sRef_isValid (s))
6581 sRef_addDeriv (t, s);
6583 s->oaliaskind = s->aliaskind;
6584 s->oexpkind = s->expkind;
6593 sRef_constructPointer (/*@exposed@*/ sRef t)
6596 return sRef_buildPointer (t);
6599 static /*@exposed@*/ sRef sRef_constructDerefAux (sRef t, bool isdead)
6601 if (sRef_isValid (t))
6606 ** if there is a derived t[?], return that. Otherwise, *t.
6609 s = sRef_findDerivedArrayFetch (t, FALSE, 0, isdead);
6611 if (sRef_isValid (s))
6617 sRef ret = sRef_constructPointer (t);
6620 ** This is necessary to prevent infinite depth
6621 ** in checking complete destruction.
6626 /* ret->defstate = SS_UNKNOWN; */
6637 return sRef_undefined;
6641 sRef sRef_constructDeref (sRef t)
6643 return sRef_constructDerefAux (t, FALSE);
6646 sRef sRef_constructDeadDeref (sRef t)
6648 return sRef_constructDerefAux (t, TRUE);
6652 sRef_constructPointerAux (/*@notnull@*/ /*@exposed@*/ sRef t)
6654 sRef s = sRef_newRef ();
6659 s->info = (sinfo) dmalloc (sizeof (*s->info));
6660 s->info->ref = t; /* sRef_copy (t); */ /*@i32*/
6662 if (ctype_isRealAP (rt))
6664 s->type = ctype_baseArrayPtr (rt);
6667 st = ctype_realType (s->type);
6669 if (t->defstate == SS_UNDEFINED)
6671 s->defstate = SS_UNUSEABLE;
6673 else if ((t->defstate == SS_ALLOCATED) && !ctype_isSU (st))
6675 s->defstate = SS_UNDEFINED;
6679 s->defstate = t->defstate;
6682 if (t->aliaskind == AK_LOCAL || t->aliaskind == AK_FRESH)
6684 s->aliaskind = AK_LOCAL;
6688 s->aliaskind = AK_UNKNOWN;
6691 sRef_setExKind (s, sRef_getExKind (t), fileloc_undefined);
6692 sRef_setTypeState (s);
6694 s->oaliaskind = s->aliaskind;
6695 s->oexpkind = s->expkind;
6697 llassert (valueTable_isUndefined (s->state));
6698 s->state = context_createValueTable (s);
6702 bool sRef_hasDerived (sRef s)
6704 return (sRef_isValid (s) && !sRefSet_isEmpty (s->deriv));
6708 sRef_clearDerived (sRef s)
6710 if (sRef_isValid (s))
6712 sRefSet_clear (s->deriv);
6717 sRef_clearDerivedComplete (sRef s)
6720 if (sRef_isValid (s))
6722 sRef base = sRef_getBaseSafe (s);
6724 while (sRef_isValid (base))
6726 sRefSet_clear (base->deriv);
6727 base = sRef_getBaseSafe (base);
6730 sRefSet_clear (s->deriv);
6734 /*@exposed@*/ sRef sRef_makePointer (/*@exposed@*/ sRef s)
6737 sRef res = sRef_buildPointer (s);
6739 DPRINTF (("Res: %s", sRef_unparse (res)));
6744 ** &a[] => a (this is for out params)
6748 sRef_makeAnyArrayFetch (/*@exposed@*/ sRef arr)
6751 if (sRef_isAddress (arr))
6753 return (arr->info->ref);
6757 return (sRef_buildArrayFetch (arr));
6762 sRef_makeArrayFetch (/*@exposed@*/ sRef arr)
6764 return (sRef_buildArrayFetch (arr));
6768 sRef_makeArrayFetchKnown (/*@exposed@*/ sRef arr, int i)
6770 return (sRef_buildArrayFetchKnown (arr, i));
6774 sRef_makeField (sRef rec, /*@dependent@*/ cstring f)
6777 ret = sRef_buildField (rec, f);
6782 sRef_makeNCField (/*@exposed@*/ sRef rec, /*@dependent@*/ cstring f)
6784 return (sRef_buildNCField (rec, f));
6788 sRef_unparseKindName (sRef s)
6792 if (s == sRef_undefined) return cstring_makeLiteral ("<invalid>");
6794 s = sRef_fixConj (s);
6799 if (sRef_isLocalVar (s))
6801 result = cstring_makeLiteral ("Variable");
6805 result = cstring_makeLiteral ("Undef global");
6809 result = cstring_makeLiteral ("Out parameter");
6812 if (sRef_isAnyParam (s->info->arrayfetch->arr))
6814 result = cstring_makeLiteral ("Out parameter");
6816 else if (sRef_isIndexKnown (s))
6818 result = cstring_makeLiteral ("Array element");
6822 result = cstring_makeLiteral ("Value");
6826 if (sRef_isAnyParam (s->info->ref))
6828 result = cstring_makeLiteral ("Out parameter");
6832 result = cstring_makeLiteral ("Value");
6836 result = cstring_makeLiteral ("Value");
6839 result = cstring_makeLiteral ("Field");
6842 result = cstring_makeLiteral ("Object");
6844 case SK_UNCONSTRAINED:
6845 result = cstring_makeLiteral ("<anything>");
6854 result = cstring_makeLiteral ("<unknown>");
6857 result = cstring_makeLiteral ("<conj>");
6860 result = cstring_makeLiteral ("Storage");
6868 sRef_unparseKindNamePlain (sRef s)
6872 if (s == sRef_undefined) return cstring_makeLiteral ("<invalid>");
6874 s = sRef_fixConj (s);
6879 if (sRef_isLocalVar (s))
6881 result = cstring_makeLiteral ("Variable");
6885 result = cstring_makeLiteral ("Global");
6889 result = cstring_makeLiteral ("Parameter");
6892 if (sRef_isAnyParam (s->info->arrayfetch->arr))
6894 result = cstring_makeLiteral ("Parameter");
6896 else if (sRef_isIndexKnown (s))
6898 result = cstring_makeLiteral ("Array element");
6902 result = cstring_makeLiteral ("Value");
6906 if (sRef_isAnyParam (s->info->ref))
6908 result = cstring_makeLiteral ("Parameter");
6912 result = cstring_makeLiteral ("Value");
6916 result = cstring_makeLiteral ("Value");
6919 result = cstring_makeLiteral ("Field");
6922 result = cstring_makeLiteral ("Object");
6925 result = cstring_makeLiteral ("Storage");
6927 case SK_UNCONSTRAINED:
6928 result = cstring_makeLiteral ("<anything>");
6937 result = cstring_makeLiteral ("<unknown>");
6940 result = cstring_makeLiteral ("<conj>");
6952 sRef_copyState (sRef s1, sRef s2)
6954 if (sRef_isValid (s1) && sRef_isValid (s2))
6956 s1->defstate = s2->defstate;
6958 /* start modifications */
6959 s1->bufinfo.bufstate = s2->bufinfo.bufstate;
6960 s1->bufinfo.len = s2->bufinfo.len;
6961 s1->bufinfo.size = s2->bufinfo.size;
6962 /* end modifications */
6964 s1->aliaskind = s2->aliaskind;
6965 s1->aliasinfo = stateInfo_update (s1->aliasinfo, s2->aliasinfo);
6967 s1->expkind = s2->expkind;
6968 s1->expinfo = stateInfo_update (s1->expinfo, s2->expinfo);
6970 s1->nullstate = s2->nullstate;
6971 s1->nullinfo = stateInfo_update (s1->nullinfo, s2->nullinfo);
6974 /*@i834 don't free it: valueTable_free (s1->state); */
6975 /*@i32@*/ s1->state = valueTable_copy (s2->state);
6977 s1->safe = s2->safe;
6982 sRef_makeNew (ctype ct, sRef t, cstring name)
6984 sRef s = sRef_newRef ();
6989 llassert (sRef_isValid (t));
6990 s->defstate = t->defstate;
6992 s->aliaskind = t->aliaskind;
6993 s->oaliaskind = s->aliaskind;
6994 s->nullstate = t->nullstate;
6996 s->expkind = t->expkind;
6997 s->oexpkind = s->expkind;
6999 s->info = (sinfo) dmalloc (sizeof (*s->info));
7000 s->info->fname = name;
7002 /* start modifications */
7003 s->bufinfo.bufstate = t->bufinfo.bufstate;
7004 /* end modifications */
7006 llassert (valueTable_isUndefined (s->state));
7007 s->state = valueTable_copy (t->state);
7009 DPRINTF (("==> Copying state: %s", valueTable_unparse (s->state)));
7010 DPRINTF (("==> new: %s", sRef_unparseFull (s)));
7015 sRef_makeType (ctype ct)
7017 sRef s = sRef_newRef ();
7019 sRef_checkMutable (s);
7024 s->defstate = SS_UNKNOWN;
7025 s->aliaskind = AK_UNKNOWN;
7026 sRef_setNullStateN (s, NS_UNKNOWN);
7028 /* start modification */
7029 s->bufinfo.bufstate = BB_NOTNULLTERMINATED;
7030 /* end modification */
7033 if (ctype_isUA (ct))
7035 typeId uid = ctype_typeId (ct);
7036 uentry ue = usymtab_getTypeEntrySafe (uid);
7038 if (uentry_isValid (ue))
7040 sRef_mergeStateQuiet (s, uentry_getSref (ue));
7044 s->oaliaskind = s->aliaskind;
7045 s->oexpkind = s->expkind;
7046 llassert (valueTable_isUndefined (s->state));
7047 s->state = context_createValueTable (s);
7049 DPRINTF (("Create: %s", sRef_unparseFull (s)));
7054 sRef_makeConst (ctype ct)
7056 sRef s = sRef_newRef ();
7061 s->defstate = SS_UNKNOWN;
7062 s->aliaskind = AK_UNKNOWN;
7063 sRef_setNullStateN (s, NS_UNKNOWN);
7065 /* start modification */
7066 s->bufinfo.bufstate = BB_NULLTERMINATED;
7067 /* end modification */
7070 if (ctype_isUA (ct))
7072 typeId uid = ctype_typeId (ct);
7073 uentry te = usymtab_getTypeEntrySafe (uid);
7075 if (uentry_isValid (te))
7077 sRef_mergeStateQuiet (s, uentry_getSref (te));
7082 s->oaliaskind = s->aliaskind;
7083 s->oexpkind = s->expkind;
7085 llassert (valueTable_isUndefined (s->state));
7086 s->state = context_createValueTable (s);
7091 bool sRef_hasName (sRef s)
7093 if (sRef_isInvalid (s))
7102 uentry u = usymtab_getRefQuiet (s->info->cvar->lexlevel,
7103 s->info->cvar->index);
7104 return (uentry_hasName (u));
7108 if (s->info->paramno >= 0)
7110 uentry u = uentryList_getN (context_getParams (),
7113 return (uentry_hasName (u));
7117 llassert (s->info->paramno == PARAMUNKNOWN);
7127 sRef_sameName (sRef s1, sRef s2)
7129 if (sRef_isInvalid (s1))
7131 return sRef_isInvalid (s2);
7134 if (sRef_isInvalid (s2))
7142 if (s2->kind == SK_CVAR)
7144 return (s1->info->cvar->lexlevel == s2->info->cvar->lexlevel
7145 && s1->info->cvar->index == s2->info->cvar->index);
7147 else if (s2->kind == SK_PARAM)
7149 if (context_inFunctionLike ())
7151 if (s2->info->paramno != PARAMUNKNOWN)
7153 uentry u1 = usymtab_getRefQuiet (s1->info->cvar->lexlevel,
7154 s1->info->cvar->index);
7155 uentry u2 = uentryList_getN (context_getParams (),
7158 return (cstring_equalFree (uentry_getName (u1),
7159 uentry_getName (u2)));
7163 return s1->info->paramno == PARAMUNKNOWN;
7177 if (s2->kind == SK_PARAM)
7179 return (s1->info->paramno == s2->info->paramno);
7181 else if (s2->kind == SK_CVAR)
7183 if (context_inFunctionLike ())
7185 if (s1->info->paramno == PARAMUNKNOWN)
7191 uentry u1 = uentryList_getN (context_getParams (),
7193 uentry u2 = usymtab_getRefQuiet (s2->info->cvar->lexlevel,
7194 s2->info->cvar->index);
7197 return (cstring_equalFree (uentry_getName (u1),
7198 uentry_getName (u2)));
7212 case SK_UNCONSTRAINED:
7216 if (s2->kind == SK_ARRAYFETCH)
7218 if (bool_equal (s1->info->arrayfetch->indknown,
7219 s2->info->arrayfetch->indknown))
7221 if (!s1->info->arrayfetch->indknown
7222 || (s1->info->arrayfetch->ind == s2->info->arrayfetch->ind))
7224 return sRef_sameName (s1->info->arrayfetch->arr,
7225 s2->info->arrayfetch->arr);
7232 if (s2->kind == SK_FIELD)
7234 if (cstring_equal (s1->info->field->field,
7235 s2->info->field->field))
7237 return sRef_sameName (s1->info->field->rec,
7238 s2->info->field->rec);
7247 if (s2->kind == s1->kind)
7249 return sRef_sameName (s1->info->ref,
7257 return sRef_sameName (sRef_getConjA (s1), s2);
7261 return (s2->kind == SK_UNKNOWN);
7264 if (s2->kind == s1->kind)
7266 return (ctype_equal (s1->type, s2->type));
7271 if (s2->kind == SK_SPECIAL)
7273 return (s1->info->spec == s2->info->spec);
7277 return (s2->kind == SK_RESULT);
7285 sRef_fixOuterRef (/*@returned@*/ sRef s)
7287 sRef root = sRef_getRootBase (s);
7289 if (sRef_isCvar (root))
7291 uentry ue = usymtab_getRefQuiet (root->info->cvar->lexlevel,
7292 root->info->cvar->index);
7294 if (uentry_isValid (ue))
7296 sRef uref = uentry_getSref (ue);
7297 sRef sr = sRef_fixBase (s, uref);
7303 llcontbug (message ("sRef_fixOuterRef: undefined: %q", sRef_unparseDebug (s)));
7312 sRef_storeState (sRef s)
7314 if (sRef_isInvalid (s)) return;
7316 sRef_checkMutable (s);
7317 s->oaliaskind = s->aliaskind;
7318 s->oexpkind = s->expkind;
7321 static void sRef_resetStateAux (sRef s, /*@unused@*/ fileloc loc)
7323 sRef_resetState (s);
7327 sRef_resetState (sRef s)
7329 bool changed = FALSE;
7330 if (sRef_isInvalid (s)) return;
7333 if (s->oaliaskind == AK_KILLREF && !sRef_isParam (s))
7336 ** killref is used in a kludgey way, to save having to add
7337 ** another alias kind (see usymtab_handleParams)
7340 if (s->expkind != s->oexpkind)
7343 s->expkind = s->oexpkind;
7348 if (s->expkind != s->oexpkind)
7351 s->expkind = s->oexpkind;
7354 if (s->aliaskind != s->oaliaskind
7355 && s->aliaskind != AK_REFCOUNTED
7356 && s->aliaskind != AK_REFS)
7359 s->aliaskind = s->oaliaskind;
7365 sRef_clearDerived (s);
7371 sRef_resetStateComplete (sRef s)
7373 sRef_innerAliasSetComplete (sRef_resetStateAux, s, fileloc_undefined);
7377 sRef_fixBase (/*@returned@*/ sRef s, /*@returned@*/ sRef base)
7379 sRef tmp = sRef_undefined;
7382 if (sRef_isInvalid (s)) return s;
7383 if (sRef_isInvalid (base)) return base;
7393 tmp = sRef_fixBase (s->info->arrayfetch->arr, base);
7395 if (s->info->arrayfetch->indknown)
7397 ret = sRef_makeArrayFetchKnown (tmp, s->info->arrayfetch->ind);
7401 ret = sRef_makeArrayFetch (tmp);
7405 tmp = sRef_fixBase (s->info->field->rec, base);
7406 ret = sRef_buildNCField (tmp, s->info->field->field);
7409 tmp = sRef_fixBase (s->info->ref, base);
7410 ret = sRef_makePointer (tmp);
7413 tmp = sRef_fixBase (s->info->ref, base);
7414 ret = sRef_makeAddress (tmp);
7420 tmp = sRef_fixBase (s->info->conj->a, base);
7421 tmpb = sRef_fixBase (s->info->conj->b, base);
7423 ret = sRef_makeConj (tmp, tmpb);
7432 static /*@exposed@*/ sRef
7433 sRef_fixDirectBase (sRef s, sRef base)
7438 if (sRef_isInvalid (s))
7440 return sRef_undefined;
7446 if (s->info->arrayfetch->indknown)
7448 ret = sRef_makeArrayFetchKnown (base, s->info->arrayfetch->ind);
7452 ret = sRef_makeArrayFetch (base);
7456 ret = sRef_buildNCField (base, s->info->field->field);
7459 ret = sRef_makePointer (base);
7462 ret = sRef_makeAddress (base);
7468 tmpa = sRef_fixDirectBase (s->info->conj->a, base);
7469 tmpb = sRef_fixDirectBase (s->info->conj->b, base);
7471 ret = sRef_makeConj (tmpa, tmpb);
7477 sRef_copyState (ret, s);
7482 sRef_isAllocIndexRef (sRef s)
7484 return (sRef_isArrayFetch (s) && !(s->info->arrayfetch->indknown)
7485 && sRef_isAllocated (s->info->arrayfetch->arr));
7489 sRef_showRefLost (sRef s)
7491 if (sRef_hasAliasInfoLoc (s))
7493 llgenindentmsg (cstring_makeLiteral ("Original reference lost"),
7494 sRef_getAliasInfoLoc (s));
7499 sRef_showRefKilled (sRef s)
7501 if (sRef_hasStateInfoLoc (s))
7503 llgenindentmsg (message ("Storage %q released",
7504 sRef_unparse (s)), sRef_getStateInfoLoc (s));
7509 sRef_showStateInconsistent (sRef s)
7511 if (sRef_hasStateInfoLoc (s))
7514 (message ("Storage %qbecomes inconsistent (released on one branch)",
7515 sRef_unparseOpt (s)),
7516 sRef_getStateInfoLoc (s));
7521 sRef_showStateInfo (sRef s)
7523 if (sRef_hasStateInfoLoc (s))
7525 if (s->defstate == SS_DEAD)
7528 (message ("Storage %qis released", sRef_unparseOpt (s)),
7529 sRef_getStateInfoLoc (s));
7531 else if (s->defstate == SS_ALLOCATED || s->defstate == SS_DEFINED)
7534 (message ("Storage %qis %s", sRef_unparseOpt (s),
7535 sstate_unparse (s->defstate)),
7536 sRef_getStateInfoLoc (s));
7538 else if (s->defstate == SS_UNUSEABLE)
7541 (message ("Storage %qbecomes inconsistent (clauses merge with"
7542 "%qreleased on one branch)",
7543 sRef_unparseOpt (s),
7544 sRef_unparseOpt (s)),
7545 sRef_getStateInfoLoc (s));
7549 llgenindentmsg (message ("Storage %qbecomes %s",
7550 sRef_unparseOpt (s),
7551 sstate_unparse (s->defstate)),
7552 sRef_getStateInfoLoc (s));
7558 sRef_showExpInfo (sRef s)
7560 if (sRef_hasExpInfoLoc (s))
7562 llgenindentmsg (message ("Storage %qbecomes %s", sRef_unparseOpt (s),
7563 exkind_unparse (s->expkind)),
7564 sRef_getExpInfoLoc (s));
7569 sRef_showMetaStateInfo (sRef s, cstring key)
7572 metaStateInfo minfo = context_lookupMetaStateInfo (key);
7574 llassert (sRef_isValid (s));
7575 llassert (valueTable_isDefined (s->state));
7576 llassert (metaStateInfo_isDefined (minfo));
7578 val = valueTable_lookup (s->state, key);
7580 if (stateValue_hasLoc (val))
7583 (message ("Meta state %qbecomes %q", sRef_unparseOpt (s),
7584 stateValue_unparseValue (val, minfo)),
7585 stateValue_getLoc (val));
7590 sRef_showNullInfo (sRef s)
7592 DPRINTF (("Show null info: %s", sRef_unparseFull (s)));
7594 if (sRef_hasNullInfoLoc (s) && sRef_isKnown (s))
7596 DPRINTF (("has null info: %s",
7597 fileloc_unparse (sRef_getNullInfoLoc (s))));
7599 switch (sRef_getNullState (s))
7603 fileloc loc = sRef_getNullInfoLoc (s);
7605 if (fileloc_isDefined (loc) && !fileloc_isLib (loc))
7608 (message ("Storage %qbecomes null", sRef_unparseOpt (s)),
7615 fileloc loc = sRef_getNullInfoLoc (s);
7617 if (fileloc_isDefined (loc) && !fileloc_isLib (loc))
7619 llgenindentmsg (message ("Storage %qbecomes null", sRef_unparseOpt (s)),
7627 (message ("Storage %qmay become null", sRef_unparseOpt (s)),
7628 sRef_getNullInfoLoc (s));
7633 (message ("Storage %qbecomes not null", sRef_unparseOpt (s)),
7634 sRef_getNullInfoLoc (s));
7638 (message ("Storage %qnull state becomes unknown",
7639 sRef_unparseOpt (s)),
7640 sRef_getNullInfoLoc (s));
7649 (message ("<error case> Storage %q becomes %s",
7651 nstate_unparse (sRef_getNullState (s))),
7652 sRef_getNullInfoLoc (s));
7660 sRef_showAliasInfo (sRef s)
7662 if (sRef_hasAliasInfoLoc (s))
7664 if (sRef_isFresh (s))
7667 (message ("Fresh storage %qallocated", sRef_unparseOpt (s)),
7668 sRef_getAliasInfoLoc (s));
7672 if (!sRef_isRefCounted (s))
7675 (message ("Storage %qbecomes %s",
7676 sRef_unparseOpt (s),
7677 alkind_unparse (sRef_getAliasKind (s))),
7678 sRef_getAliasInfoLoc (s));
7685 sRef_mergeNullState (sRef s, nstate n)
7687 if (sRef_isValid (s))
7691 old = sRef_getNullState (s);
7693 if (n != old && n != NS_UNKNOWN)
7695 sRef_setNullState (s, n, g_currentloc);
7700 llbuglit ("sRef_mergeNullState: invalid");
7705 sRef_possiblyNull (sRef s)
7707 if (sRef_isValid (s))
7709 if (sRef_getNullState (s) == NS_ABSNULL)
7711 ctype rct = ctype_realType (s->type);
7713 if (ctype_isAbstract (rct))
7719 if (ctype_isUser (rct))
7721 uentry ue = usymtab_getTypeEntry (ctype_typeId (rct));
7723 return (nstate_possiblyNull
7724 (sRef_getNullState (uentry_getSref (ue))));
7734 return nstate_possiblyNull (sRef_getNullState (s));
7742 sRef_getScopeName (sRef s)
7744 sRef base = sRef_getRootBase (s);
7746 if (sRef_isRealGlobal (base))
7748 return (cstring_makeLiteralTemp ("Global"));
7750 else if (sRef_isFileStatic (base))
7752 return (cstring_makeLiteralTemp ("Static"));
7756 return (cstring_makeLiteralTemp ("Local"));
7761 sRef_unparseScope (sRef s)
7763 sRef base = sRef_getRootBase (s);
7765 if (sRef_isRealGlobal (base))
7767 return (cstring_makeLiteralTemp ("global"));
7769 else if (sRef_isFileStatic (base))
7771 return (cstring_makeLiteralTemp ("file static"));
7780 sRef_getScope (sRef s)
7782 llassert (sRef_isValid (s));
7784 if (sRef_isCvar (s))
7786 return s->info->cvar->lexlevel;
7788 else if (sRef_isParam (s))
7799 sRef_isDead (sRef s)
7801 return (sRef_isValid (s) && (s)->defstate == SS_DEAD);
7805 sRef_isDeadStorage (sRef s)
7807 if (sRef_isValid (s))
7809 if (s->defstate == SS_DEAD
7810 || s->defstate == SS_UNUSEABLE
7811 || s->defstate == SS_UNDEFINED
7812 || s->defstate == SS_UNKNOWN)
7818 return (sRef_isDefinitelyNull (s));
7828 sRef_isPossiblyDead (sRef s)
7830 return (sRef_isValid (s) && s->defstate == SS_HOFFA);
7833 bool sRef_isStateLive (sRef s)
7835 if (sRef_isValid (s))
7837 sstate ds = s->defstate;
7839 return (!(ds == SS_UNDEFINED
7841 || ds == SS_UNUSEABLE
7842 || ds == SS_HOFFA));
7851 bool sRef_isStateUndefined (sRef s)
7853 return ((sRef_isValid(s)) && ((s)->defstate == SS_UNDEFINED));
7856 bool sRef_isJustAllocated (sRef s)
7858 if (sRef_isAllocated (s))
7860 sRefSet_allElements (s->deriv, el)
7862 if (!(sRef_isStateUndefined (el) || sRef_isUnuseable (el)))
7866 } end_sRefSet_allElements ;
7875 sRef_isAllocatedStorage (sRef s)
7877 if (sRef_isValid (s) && ynm_toBoolStrict (sRef_isReadable (s)))
7879 return (ctype_isVisiblySharable (sRef_getType (s)));
7888 sRef_isUnuseable (sRef s)
7890 return ((sRef_isValid(s)) && ((s)->defstate == SS_UNUSEABLE));
7894 sRef_perhapsNull (sRef s)
7896 if (sRef_isValid (s))
7898 if (sRef_getNullState (s) == NS_ABSNULL)
7900 ctype rct = ctype_realType (s->type);
7902 if (ctype_isAbstract (rct))
7908 if (ctype_isUser (rct))
7910 uentry ue = usymtab_getTypeEntry (ctype_typeId (rct));
7912 return (nstate_perhapsNull
7913 (sRef_getNullState (uentry_getSref (ue))));
7923 return nstate_perhapsNull (sRef_getNullState (s));
7931 ** definitelyNull --- called when TRUE is good
7935 sRef_definitelyNull (sRef s)
7937 return (sRef_isValid (s)
7938 && (sRef_getNullState (s) == NS_DEFNULL || sRef_getNullState (s) == NS_CONSTNULL));
7942 ** based on sRef_similar
7946 sRef_setDerivNullState (sRef set, sRef guide, nstate ns)
7948 if (sRef_isValid (set))
7950 sRef deriv = sRef_getDeriv (set, guide);
7952 if (sRef_isValid (deriv))
7954 sRef_setNullStateN (deriv, ns);
7959 static /*@exposed@*/ sRef
7960 sRef_getDeriv (/*@returned@*/ /*@notnull@*/ sRef set, sRef guide)
7962 llassert (sRef_isValid (set));
7963 llassert (sRef_isValid (guide));
7965 switch (guide->kind)
7968 llassert (set->kind == SK_CVAR);
7973 llassert (set->kind == guide->kind);
7974 llassert (set->info->paramno == guide->info->paramno);
7980 if (set->kind == SK_ARRAYFETCH
7981 && (sRef_similar (set->info->arrayfetch->arr,
7982 guide->info->arrayfetch->arr)))
7988 return (sRef_makeAnyArrayFetch
7989 (sRef_getDeriv (set, guide->info->arrayfetch->arr)));
7994 if (set->kind == SK_PTR && sRef_similar (set->info->ref, guide->info->ref))
8000 return (sRef_makePointer (sRef_getDeriv (set, guide->info->ref)));
8005 if ((set->kind == SK_FIELD &&
8006 (sRef_similar (set->info->field->rec, guide->info->field->rec) &&
8007 cstring_equal (set->info->field->field, guide->info->field->field))))
8013 return (sRef_makeField (sRef_getDeriv (set, guide->info->field->rec),
8014 guide->info->field->field));
8018 if ((set->kind == SK_ADR) && sRef_similar (set->info->ref, guide->info->ref))
8024 return (sRef_makeAddress (sRef_getDeriv (set, guide->info->ref)));
8029 return sRef_undefined;
8033 case SK_UNCONSTRAINED:
8041 return sRef_undefined;
8048 ** sRef_aliasCheckPred
8050 ** A confusing but spiffy function:
8052 ** Calls predf (s, e, text, <alias>) on s and all of s's aliases
8053 ** (unless checkAliases (s) is FALSE).
8055 ** For alias calls, calls as
8056 ** predf (alias, e, text, s)
8060 sRef_aliasCheckPred (bool (predf) (sRef, exprNode, sRef, exprNode),
8061 /*@null@*/ bool (checkAliases) (sRef),
8062 sRef s, exprNode e, exprNode err)
8064 bool error = (*predf)(s, e, sRef_undefined, err);
8067 if (checkAliases != NULL && !(checkAliases (s)))
8069 /* don't check aliases */
8073 sRefSet aliases = usymtab_allAliases (s);
8076 sRefSet_realElements (aliases, current)
8078 if (sRef_isValid (current))
8080 if (!sRef_similar (current, s)
8081 || (error && sRef_sameName (current, s)))
8083 (void) (*predf)(current, e, s, err);
8086 } end_sRefSet_realElements;
8088 sRefSet_free (aliases);
8093 ** return TRUE iff predf (s) is true for s or any alias of s
8097 sRef_aliasCheckSimplePred (sRefTest predf, sRef s)
8108 aliases = usymtab_allAliases (s);
8110 sRefSet_realElements (aliases, current)
8112 if (sRef_isValid (current))
8114 sRef cref = sRef_updateSref (current);
8116 /* Whoa! a very kludgey way to make sure the right sref is used
8117 ** where there is a conditional symbol table. I am beginning
8118 ** to think that having a conditional symbol table wasn't such
8124 DPRINTF (("Checking alias: %s", sRef_unparseFull (cref)));
8125 sRefSet_free (aliases);
8129 } end_sRefSet_realElements;
8131 sRefSet_free (aliases);
8137 sRef_aliasCompleteSimplePred (bool (predf) (sRef), sRef s)
8140 bool result = FALSE;
8143 aliases = usymtab_allAliases (s);
8145 if ((*predf)(s)) result = TRUE;
8148 sRefSet_realElements (aliases, current)
8150 if (sRef_isValid (current))
8152 current = sRef_updateSref (current);
8153 if ((*predf)(current)) result = TRUE;
8155 } end_sRefSet_realElements;
8157 sRefSet_free (aliases);
8162 sRef_aliasSetComplete (void (predf) (sRef, fileloc), sRef s, fileloc loc)
8166 aliases = usymtab_allAliases (s);
8168 DPRINTF (("All aliases: %s", sRefSet_unparseFull (aliases)));
8172 sRefSet_realElements (aliases, current)
8174 if (sRef_isValid (current))
8176 current = sRef_updateSref (current);
8177 ((*predf)(current, loc));
8179 } end_sRefSet_realElements;
8181 sRefSet_free (aliases);
8185 sRef_aliasSetCompleteParam (void (predf) (sRef, alkind, fileloc), sRef s,
8186 alkind kind, fileloc loc)
8191 if (sRef_isDeep (s))
8193 aliases = usymtab_allAliases (s);
8197 aliases = usymtab_aliasedBy (s);
8200 (*predf)(s, kind, loc);
8202 sRefSet_realElements (aliases, current)
8204 if (sRef_isValid (current))
8206 current = sRef_updateSref (current);
8207 ((*predf)(current, kind, loc));
8209 } end_sRefSet_realElements;
8211 sRefSet_free (aliases);
8215 sRef_innerAliasSetComplete (void (predf) (sRef, fileloc), sRef s, fileloc loc)
8221 if (!sRef_isValid (s)) return;
8225 ** Type equivalence checking is necessary --- there might be casting.
8232 case SK_UNCONSTRAINED:
8237 inner = s->info->ref;
8238 aliases = usymtab_allAliases (inner);
8239 ct = sRef_getType (inner);
8242 sRefSet_realElements (aliases, current)
8244 if (sRef_isValid (current))
8246 current = sRef_updateSref (current);
8248 if (ctype_equal (ct, sRef_getType (current)))
8250 sRef ptr = sRef_makePointer (current);
8251 ((*predf)(ptr, loc));
8254 } end_sRefSet_realElements;
8256 sRefSet_free (aliases);
8259 inner = s->info->arrayfetch->arr;
8260 aliases = usymtab_allAliases (inner);
8261 ct = sRef_getType (inner);
8263 sRefSet_realElements (aliases, current)
8265 if (sRef_isValid (current))
8267 current = sRef_updateSref (current);
8269 if (ctype_equal (ct, sRef_getType (current)))
8272 if (s->info->arrayfetch->indknown)
8274 sRef af = sRef_makeArrayFetchKnown (current, s->info->arrayfetch->ind);
8276 ((*predf)(af, loc));
8280 sRef af = sRef_makeArrayFetch (current);
8282 ((*predf)(af, loc));
8286 } end_sRefSet_realElements;
8288 sRefSet_free (aliases);
8291 inner = s->info->field->rec;
8292 aliases = usymtab_allAliases (inner);
8293 ct = sRef_getType (inner);
8296 sRefSet_realElements (aliases, current)
8298 if (sRef_isValid (current))
8300 current = sRef_updateSref (current);
8302 if (ctype_equal (ct, sRef_getType (current)))
8304 sRef f = sRef_makeField (current, s->info->field->field);
8309 } end_sRefSet_realElements;
8311 sRefSet_free (aliases);
8314 sRef_innerAliasSetComplete (predf, s->info->conj->a, loc);
8315 sRef_innerAliasSetComplete (predf, s->info->conj->b, loc);
8332 sRef_innerAliasSetCompleteParam (void (predf) (sRef, sRef), sRef s, sRef t)
8338 if (!sRef_isValid (s)) return;
8342 ** Type equivalence checking is necessary --- there might be casting.
8349 case SK_UNCONSTRAINED:
8354 inner = s->info->ref;
8355 aliases = usymtab_allAliases (inner);
8356 ct = sRef_getType (inner);
8359 sRefSet_realElements (aliases, current)
8361 if (sRef_isValid (current))
8363 current = sRef_updateSref (current);
8365 if (ctype_equal (ct, sRef_getType (current)))
8367 sRef ptr = sRef_makePointer (current);
8372 } end_sRefSet_realElements;
8374 sRefSet_free (aliases);
8377 inner = s->info->arrayfetch->arr;
8378 aliases = usymtab_allAliases (inner);
8379 ct = sRef_getType (inner);
8381 sRefSet_realElements (aliases, current)
8383 if (sRef_isValid (current))
8385 current = sRef_updateSref (current);
8387 if (ctype_equal (ct, sRef_getType (current)))
8390 if (s->info->arrayfetch->indknown)
8392 sRef af = sRef_makeArrayFetchKnown (current, s->info->arrayfetch->ind);
8398 sRef af = sRef_makeArrayFetch (current);
8404 } end_sRefSet_realElements;
8406 sRefSet_free (aliases);
8409 inner = s->info->field->rec;
8410 aliases = usymtab_allAliases (inner);
8411 ct = sRef_getType (inner);
8414 sRefSet_realElements (aliases, current)
8416 if (sRef_isValid (current))
8418 current = sRef_updateSref (current);
8420 if (ctype_equal (ct, sRef_getType (current)))
8422 sRef f = sRef_makeField (current, s->info->field->field);
8427 } end_sRefSet_realElements;
8429 sRefSet_free (aliases);
8432 sRef_innerAliasSetCompleteParam (predf, s->info->conj->a, t);
8433 sRef_innerAliasSetCompleteParam (predf, s->info->conj->b, t);
8449 static void sRef_combineExKinds (/*@notnull@*/ sRef res, /*@notnull@*/ sRef other)
8451 exkind a1 = sRef_getExKind (res);
8452 exkind a2 = sRef_getExKind (other);
8454 if (a1 == a2 || a2 == XO_UNKNOWN)
8458 else if (a1 == XO_UNKNOWN)
8460 res->expinfo = stateInfo_update (res->expinfo, other->expinfo);
8465 res->expkind = XO_OBSERVER;
8470 ** Currently, this is a very ad hoc implementation, with lots of fixes to
8471 ** make real code work okay. I need to come up with some more general
8472 ** rules or principles here.
8476 sRef_combineAliasKindsError (/*@notnull@*/ sRef res,
8477 /*@notnull@*/ sRef other,
8478 clause cl, fileloc loc)
8480 bool hasError = FALSE;
8481 alkind ares = sRef_getAliasKind (res);
8482 alkind aother = sRef_getAliasKind (other);
8484 sRef_checkMutable (res);
8486 if (alkind_isDependent (ares))
8488 if (aother == AK_KEPT)
8490 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8491 res->aliaskind = AK_KEPT;
8495 if (aother == AK_LOCAL || aother == AK_STATIC
8496 || alkind_isTemp (aother))
8498 DPRINTF (("Setting dependent: %s", sRef_unparseFull (res)));
8499 res->aliaskind = AK_DEPENDENT;
8503 else if (alkind_isDependent (aother))
8505 if (ares == AK_KEPT)
8507 res->aliaskind = AK_KEPT;
8511 if (ares == AK_LOCAL || ares == AK_STATIC || alkind_isTemp (ares))
8513 DPRINTF (("Setting dependent: %s", sRef_unparseFull (res)));
8514 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8515 res->aliaskind = AK_DEPENDENT;
8519 else if ((ares == AK_LOCAL || ares == AK_UNIQUE
8520 || ares == AK_STATIC || alkind_isTemp (ares))
8521 && sRef_isFresh (other))
8524 ** cases like: if (s == NULL) s = malloc...;
8525 ** don't generate errors
8528 if (usymtab_isAltDefinitelyNullDeep (res))
8530 res->aliaskind = ares;
8537 else if ((aother == AK_LOCAL || aother == AK_UNIQUE
8538 || aother == AK_STATIC || alkind_isTemp (aother))
8539 && sRef_isFresh (res))
8542 ** cases like: if (s == NULL) s = malloc...;
8543 ** don't generate errors
8546 if (usymtab_isDefinitelyNullDeep (other))
8548 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8549 res->aliaskind = aother;
8556 else if (ares == AK_NEWREF && aother == AK_REFCOUNTED
8557 && sRef_isConst (other))
8559 res->aliaskind = AK_NEWREF;
8561 else if (aother == AK_NEWREF && ares == AK_REFCOUNTED
8562 && sRef_isConst (res))
8564 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8565 res->aliaskind = AK_NEWREF;
8567 else if (sRef_isLocalVar (res)
8568 && ((ares == AK_KEPT && aother == AK_LOCAL)
8569 || (aother == AK_KEPT && ares == AK_LOCAL)))
8571 res->aliaskind = AK_KEPT;
8580 if (sRef_isThroughArrayFetch (res))
8583 (FLG_BRANCHSTATE, FLG_STRICTBRANCHSTATE,
8585 ("Clauses exit with %q possibly referencing %s storage %s, "
8588 alkind_unparse (aother),
8589 clause_nameTaken (cl),
8590 alkind_unparse (ares),
8591 clause_nameAlternate (cl)),
8594 sRef_showAliasInfo (res);
8595 sRef_showAliasInfo (other);
8596 res->aliaskind = AK_ERROR;
8600 if (ares == AK_KEPT || aother == AK_KEPT)
8602 sRef_maybeKill (res, loc);
8610 message ("Clauses exit with %q referencing %s storage %s, "
8613 alkind_unparse (aother),
8614 clause_nameTaken (cl),
8615 alkind_unparse (ares),
8616 clause_nameAlternate (cl)),
8619 sRef_showAliasInfo (res);
8620 sRef_showAliasInfo (other);
8622 res->aliaskind = AK_ERROR;
8626 res->aliaskind = (sRef_isLocalVar (res) ? AK_LOCAL : AK_UNKNOWN);
8631 sRef_combineAliasKinds (/*@notnull@*/ sRef res, /*@notnull@*/ sRef other,
8632 clause cl, fileloc loc)
8634 alkind ares = sRef_getAliasKind (res);
8635 alkind aother = sRef_getAliasKind (other);
8637 sRef_checkMutable (res);
8639 if (alkind_equal (ares, aother)
8640 || aother == AK_UNKNOWN
8641 || aother == AK_ERROR)
8643 ; /* keep current state */
8645 else if (sRef_isDead (res) || sRef_isDead (other))
8647 /* dead error reported (or storage is dead) */
8648 res ->aliaskind = AK_ERROR;
8650 else if (ares == AK_UNKNOWN || ares == AK_ERROR
8651 || sRef_isStateUndefined (res))
8653 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8654 res->aliaskind = aother;
8656 else if (sRef_isStateUndefined (other))
8660 else if (((ares == AK_UNIQUE || alkind_isTemp (ares))
8661 && aother == AK_LOCAL)
8662 || ((aother == AK_UNIQUE || alkind_isTemp (aother))
8663 && ares == AK_LOCAL))
8665 if (ares != AK_LOCAL)
8667 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8670 res->aliaskind = AK_LOCAL;
8672 else if ((ares == AK_OWNED && aother == AK_FRESH)
8673 || (aother == AK_OWNED && ares == AK_FRESH))
8675 if (ares != AK_FRESH)
8677 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8680 res->aliaskind = AK_FRESH;
8682 else if ((ares == AK_KEEP && aother == AK_FRESH) ||
8683 (aother == AK_KEEP && ares == AK_FRESH))
8685 if (ares != AK_KEEP)
8687 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8690 res->aliaskind = AK_KEEP;
8692 else if ((ares == AK_LOCAL && aother == AK_STACK) ||
8693 (aother == AK_LOCAL && ares == AK_STACK))
8695 if (ares != AK_STACK)
8697 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8700 res->aliaskind = AK_STACK;
8702 else if ((ares == AK_LOCAL
8703 && (aother == AK_OWNED && sRef_isLocalVar (other)))
8704 || (aother == AK_LOCAL
8705 && (ares == AK_OWNED && sRef_isLocalVar (res))))
8707 if (ares != AK_LOCAL)
8709 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8712 res->aliaskind = AK_LOCAL;
8714 else if ((ares == AK_FRESH && alkind_isOnly (aother))
8715 || (aother == AK_FRESH && alkind_isOnly (ares)))
8717 res->aliaskind = AK_FRESH;
8719 else if ((aother == AK_FRESH && sRef_definitelyNull (res))
8720 || (ares == AK_FRESH && sRef_definitelyNull (other)))
8722 if (ares != AK_FRESH)
8724 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8725 res->aliaskind = AK_FRESH;
8728 else if ((sRef_isFresh (res) && sRef_isConst (other))
8729 || (sRef_isFresh (other) && sRef_isConst (res)))
8732 ** for NULL constantants
8736 if (!sRef_isFresh (res))
8738 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8741 res->aliaskind = AK_FRESH;
8743 else if ((alkind_isStatic (aother) && sRef_isConst (res))
8744 || (alkind_isStatic (ares) && sRef_isConst (other)))
8746 if (!alkind_isStatic (ares))
8748 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8749 res->aliaskind = AK_STATIC;
8754 sRef_combineAliasKindsError (res, other, cl, loc);
8758 static void sRef_combineDefState (/*@notnull@*/ sRef res,
8759 /*@notnull@*/ sRef other)
8761 sstate s1 = res->defstate;
8762 sstate s2 = other->defstate;
8765 sRef_checkMutable (res);
8767 if (s1 == s2 || s2 == SS_UNKNOWN)
8771 else if (s1 == SS_UNKNOWN)
8780 if (s2 == SS_DEFINED)
8786 llcontbuglit ("ssfixed: not implemented");
8795 flip = (s2 != SS_DEFINED);
8813 res->definfo = stateInfo_update (res->definfo, other->definfo);
8818 extern /*@notnull@*/ sRef sRef_getConjA (sRef s)
8821 llassert (sRef_isConj (s));
8823 ret = s->info->conj->a;
8824 llassert (ret != NULL);
8828 extern /*@notnull@*/ sRef sRef_getConjB (sRef s)
8831 llassert (sRef_isConj (s));
8833 ret = s->info->conj->b;
8834 llassert (ret != NULL);
8838 extern /*@exposed@*/ sRef sRef_makeArrow (sRef s, /*@dependent@*/ cstring f)
8843 p = sRef_makePointer (s);
8844 ret = sRef_makeField (p, f);
8848 extern /*@exposed@*/ sRef sRef_buildArrow (sRef s, cstring f)
8853 p = sRef_buildPointer (s);
8854 ret = sRef_buildField (p, f);
8859 static /*@null@*/ sinfo sinfo_copy (/*@notnull@*/ sRef s)
8866 ret = (sinfo) dmalloc (sizeof (*ret));
8867 ret->cvar = (cref) dmalloc (sizeof (*ret->cvar));
8868 ret->cvar->lexlevel = s->info->cvar->lexlevel;
8869 ret->cvar->index = s->info->cvar->index;
8873 ret = (sinfo) dmalloc (sizeof (*ret));
8874 ret->paramno = s->info->paramno;
8875 llassert (ret->paramno >= -1);
8879 ret = (sinfo) dmalloc (sizeof (*ret));
8880 ret->arrayfetch = (ainfo) dmalloc (sizeof (*ret->arrayfetch));
8881 ret->arrayfetch->indknown = s->info->arrayfetch->indknown;
8882 ret->arrayfetch->ind = s->info->arrayfetch->ind;
8883 ret->arrayfetch->arr = s->info->arrayfetch->arr; /* sRef_copy (s->info->arrayfetch->arr); */ /*@i32@*/
8887 ret = (sinfo) dmalloc (sizeof (*ret));
8888 ret->field = (fldinfo) dmalloc (sizeof (*ret->field));
8889 ret->field->rec = s->info->field->rec; /* sRef_copy (s->info->field->rec); */ /*@i32@*/
8890 ret->field->field = s->info->field->field;
8894 ret = (sinfo) dmalloc (sizeof (*ret));
8895 ret->object = s->info->object;
8902 ret = (sinfo) dmalloc (sizeof (*ret));
8903 ret->ref = s->info->ref; /* Ref_copy (s->info->ref); */
8907 ret = (sinfo) dmalloc (sizeof (*ret));
8908 ret->conj = (cjinfo) dmalloc (sizeof (*ret->conj));
8909 ret->conj->a = s->info->conj->a; /* sRef_copy (s->info->conj->a); */
8910 ret->conj->b = s->info->conj->b; /* sRef_copy (s->info->conj->b);*/
8913 ret = (sinfo) dmalloc (sizeof (*ret));
8914 ret->spec = s->info->spec;
8916 case SK_UNCONSTRAINED:
8918 ret = (sinfo) dmalloc (sizeof (*ret));
8919 ret->fname = s->info->fname;
8925 llassertprint (s->info == NULL, ("s = %s", sRef_unparse (s)));
8933 static /*@null@*/ sinfo sinfo_fullCopy (/*@notnull@*/ sRef s)
8938 ** Since its a full copy, only storage is assigned
8939 ** to dependent fields.
8946 ret = (sinfo) dmalloc (sizeof (*ret));
8947 ret->cvar = (cref) dmalloc (sizeof (*ret->cvar));
8948 ret->cvar->lexlevel = s->info->cvar->lexlevel;
8949 ret->cvar->index = s->info->cvar->index;
8953 ret = (sinfo) dmalloc (sizeof (*ret));
8954 ret->paramno = s->info->paramno;
8955 llassert (ret->paramno >= -1);
8959 ret = (sinfo) dmalloc (sizeof (*ret));
8960 ret->arrayfetch = (ainfo) dmalloc (sizeof (*ret->arrayfetch));
8961 ret->arrayfetch->indknown = s->info->arrayfetch->indknown;
8962 ret->arrayfetch->ind = s->info->arrayfetch->ind;
8963 ret->arrayfetch->arr = sRef_saveCopy (s->info->arrayfetch->arr);
8967 ret = (sinfo) dmalloc (sizeof (*ret));
8968 ret->field = (fldinfo) dmalloc (sizeof (*ret->field));
8969 ret->field->rec = sRef_saveCopy (s->info->field->rec);
8970 ret->field->field = s->info->field->field;
8974 ret = (sinfo) dmalloc (sizeof (*ret));
8975 ret->object = s->info->object;
8982 ret = (sinfo) dmalloc (sizeof (*ret));
8983 ret->ref = sRef_saveCopy (s->info->ref);
8987 ret = (sinfo) dmalloc (sizeof (*ret));
8988 ret->conj = (cjinfo) dmalloc (sizeof (*ret->conj));
8989 ret->conj->a = sRef_saveCopy (s->info->conj->a);
8990 ret->conj->b = sRef_saveCopy (s->info->conj->b);
8993 ret = (sinfo) dmalloc (sizeof (*ret));
8994 ret->spec = s->info->spec;
8997 case SK_UNCONSTRAINED:
8998 ret = (sinfo) dmalloc (sizeof (*ret));
8999 ret->fname = s->info->fname;
9005 llassert (s->info == NULL);
9015 sinfo_update (/*@notnull@*/ /*@exposed@*/ sRef res,
9016 /*@notnull@*/ /*@exposed@*/ sRef other)
9018 llassert (res->kind == other->kind);
9023 res->info->cvar->lexlevel = other->info->cvar->lexlevel;
9024 res->info->cvar->index = other->info->cvar->index;
9028 res->info->paramno = other->info->paramno;
9029 llassert (res->info->paramno >= -1);
9033 res->info->arrayfetch->indknown = other->info->arrayfetch->indknown;
9034 res->info->arrayfetch->ind = other->info->arrayfetch->ind;
9035 res->info->arrayfetch->arr = other->info->arrayfetch->arr;
9039 res->info->field->rec = other->info->field->rec;
9040 res->info->field->field = other->info->field->field;
9044 res->info->object = other->info->object;
9051 res->info->ref = other->info->ref;
9055 res->info->conj->a = other->info->conj->a;
9056 res->info->conj->b = other->info->conj->b;
9060 res->info->spec = other->info->spec;
9064 case SK_UNCONSTRAINED:
9065 res->info->fname = other->info->fname;
9072 llassert (res->info == NULL);
9077 static void sinfo_free (/*@special@*/ /*@temp@*/ /*@notnull@*/ sRef s)
9078 /*@uses s->kind, s->info@*/
9079 /*@releases s->info@*/
9084 DPRINTF (("Free sinfo: [%p]", s->info->cvar));
9085 sfree (s->info->cvar);
9092 DPRINTF (("Free sinfo: [%p]", s->info->arrayfetch));
9093 sfree (s->info->arrayfetch);
9097 DPRINTF (("Free sinfo: [%p]", s->info->field));
9098 sfree (s->info->field);
9107 case SK_EXTERNAL: /*@i32 is copy now! */
9111 DPRINTF (("Free sinfo: [%p]", s->info->conj));
9112 sfree (s->info->conj);
9115 case SK_UNCONSTRAINED:
9125 if (s->info != NULL) {
9126 DPRINTF (("Free sinfo: [%p]", s->info));
9132 bool sRef_isNSLocalVar (sRef s)
9134 if (sRef_isLocalVar (s))
9136 uentry ue = sRef_getUentry (s);
9138 return (!uentry_isStatic (ue));
9146 bool sRef_isLocalVar (sRef s)
9148 if (sRef_isValid(s))
9150 return (s->kind == SK_CVAR
9151 && (s->info->cvar->lexlevel > fileScope));
9157 bool sRef_isRealLocalVar (sRef s)
9159 if (sRef_isValid(s))
9161 if (s->kind == SK_CVAR)
9163 if (s->info->cvar->lexlevel == functionScope)
9165 uentry ue = sRef_getUentry (s);
9167 if (uentry_isAnyParam (ue)
9168 || uentry_isRefParam (ue))
9179 return (s->info->cvar->lexlevel > functionScope);
9187 bool sRef_isLocalParamVar (sRef s)
9189 if (sRef_isValid(s))
9191 return (s->kind == SK_PARAM
9192 || (s->kind == SK_CVAR
9193 && (s->info->cvar->lexlevel > fileScope)));
9199 static speckind speckind_fromInt (int i)
9202 llassert (i >= SR_NOTHING && i <= SR_SYSTEM);
9205 return ((speckind) i);
9209 static void sRef_updateNullState (sRef res, sRef other)
9212 res->nullstate = other->nullstate;
9213 res->nullinfo = stateInfo_update (res->nullinfo, other->nullinfo);
9216 void sRef_combineNullState (/*@notnull@*/ sRef res, /*@notnull@*/ sRef other)
9218 nstate n1 = sRef_getNullState (res);
9219 nstate n2 = sRef_getNullState (other);
9223 if (n1 == n2 || n2 == NS_UNKNOWN)
9229 /* note: n2 is not unknown or defnull */
9233 case NS_ERROR: nn = NS_ERROR; break;
9234 case NS_UNKNOWN: flip = TRUE; nn = n2; break;
9235 case NS_POSNULL: break;
9236 case NS_DEFNULL: nn = NS_POSNULL; break;
9237 case NS_RELNULL: break;
9239 if (n2 == NS_MNOTNULL)
9250 if (n2 == NS_NOTNULL)
9269 res->nullinfo = stateInfo_update (res->nullinfo, other->nullinfo);
9272 res->nullstate = nn;
9275 cstring sRef_nullMessage (sRef s)
9277 llassert (sRef_isValid (s));
9279 switch (sRef_getNullState (s))
9283 return (cstring_makeLiteralTemp ("null"));
9285 return (cstring_makeLiteralTemp ("possibly null"));
9290 /*@observer@*/ cstring sRef_ntMessage (sRef s)
9292 llassert (sRef_isValid (s));
9294 switch (s->nullstate)
9298 return (cstring_makeLiteralTemp ("not nullterminated"));
9300 return (cstring_makeLiteralTemp ("possibly non-nullterminated"));
9307 sRef sRef_fixResultType (/*@returned@*/ sRef s, ctype typ, uentry ue)
9309 sRef tmp = sRef_undefined;
9312 llassert (sRef_isValid (s));
9323 tmp = sRef_fixResultType (s->info->arrayfetch->arr, typ, ue);
9325 ct = ctype_realType (sRef_getType (tmp));
9328 if (ctype_isKnown (ct))
9330 if (ctype_isAP (ct))
9339 ("Special clause indexes non-array (%t): *%q",
9340 ct, sRef_unparse (s->info->arrayfetch->arr)),
9341 uentry_whereLast (ue));
9345 tmp = sRef_fixResultType (s->info->arrayfetch->arr, typ, ue);
9347 if (s->info->arrayfetch->indknown)
9349 ret = sRef_makeArrayFetchKnown (tmp, s->info->arrayfetch->ind);
9353 ret = sRef_makeArrayFetch (tmp);
9359 sRef rec = sRef_fixResultType (s->info->field->rec, typ, ue);
9360 ctype ct = ctype_realType (sRef_getType (rec));
9362 if (ctype_isKnown (ct))
9364 if (ctype_isSU (ct))
9366 if (uentry_isValid (uentryList_lookupField (ctype_getFields (ct),
9367 s->info->field->field)))
9376 ("Special clause accesses non-existent field of result: %q.%s",
9377 sRef_unparse (rec), s->info->field->field),
9378 uentry_whereLast (ue));
9386 ("Special clause accesses field of non-struct or union result (%t): %q.%s",
9387 ct, sRef_unparse (rec), s->info->field->field),
9388 uentry_whereLast (ue));
9392 ret = sRef_makeField (tmp, s->info->field->field);
9398 tmp = sRef_fixResultType (s->info->ref, typ, ue);
9400 ct = ctype_realType (sRef_getType (tmp));
9402 if (ctype_isKnown (ct))
9404 if (ctype_isAP (ct))
9413 ("Special clause dereferences non-pointer (%t): *%q",
9414 ct, sRef_unparse (s->info->ref)),
9415 uentry_whereLast (ue));
9419 ret = sRef_makePointer (tmp);
9426 ("Special clause uses & operator (not allowed): &%q", sRef_unparse (s->info->ref)),
9427 uentry_whereLast (ue));
9436 bool sRef_isOnly (sRef s)
9438 return (sRef_isValid(s) && alkind_isOnly (s->aliaskind));
9441 bool sRef_isDependent (sRef s)
9443 return (sRef_isValid(s) && alkind_isDependent (s->aliaskind));
9446 bool sRef_isOwned (sRef s)
9448 return (sRef_isValid (s) && (s->aliaskind == AK_OWNED));
9451 bool sRef_isKeep (sRef s)
9453 return (sRef_isValid (s) && (s->aliaskind == AK_KEEP));
9456 bool sRef_isTemp (sRef s)
9458 return (sRef_isValid (s) && alkind_isTemp (s->aliaskind));
9461 bool sRef_isLocalState (sRef s)
9463 return (sRef_isValid (s) && (s->aliaskind == AK_LOCAL));
9466 bool sRef_isUnique (sRef s)
9468 return (sRef_isValid (s) && (s->aliaskind == AK_UNIQUE));
9471 bool sRef_isShared (sRef s)
9473 return (sRef_isValid (s) && (s->aliaskind == AK_SHARED));
9476 bool sRef_isExposed (sRef s)
9478 return (sRef_isValid (s) && (s->expkind == XO_EXPOSED));
9481 bool sRef_isObserver (sRef s)
9483 return (sRef_isValid (s) && (s->expkind == XO_OBSERVER));
9486 bool sRef_isFresh (sRef s)
9488 return (sRef_isValid (s) && (s->aliaskind == AK_FRESH));
9491 bool sRef_isDefinitelyNull (sRef s)
9493 return (sRef_isValid (s) && (sRef_getNullState (s) == NS_DEFNULL
9494 || sRef_getNullState (s) == NS_CONSTNULL));
9497 bool sRef_isAllocated (sRef s)
9499 return (sRef_isValid (s) && (s->defstate == SS_ALLOCATED));
9502 bool sRef_isStack (sRef s)
9504 return (sRef_isValid (s) && (s->aliaskind == AK_STACK));
9507 bool sRef_isNotNull (sRef s)
9509 return (sRef_isValid(s) && (sRef_getNullState (s) == NS_MNOTNULL
9510 || sRef_getNullState (s) == NS_NOTNULL));
9513 alkind sRef_getAliasKind (sRef s)
9515 if (sRef_isValid(s)) {
9516 llassert (alkind_isValid (s->aliaskind));
9517 return s->aliaskind;
9523 nstate sRef_getNullState (sRef s)
9525 if (sRef_isValid (s)) {
9526 llassert (nstate_isValid (s->nullstate));
9527 return s->nullstate;
9533 void sRef_reflectAnnotation (sRef s, annotationInfo a, fileloc loc)
9535 if (sRef_isValid (s))
9537 if (!valueTable_isDefined (s->state))
9539 s->state = valueTable_create (1);
9540 valueTable_insert (s->state,
9541 cstring_copy (metaStateInfo_getName (annotationInfo_getState (a))),
9542 stateValue_create (annotationInfo_getValue (a), stateInfo_makeLoc (loc)));
9546 DPRINTF (("reflect loc: %s", fileloc_unparse (loc)));
9549 metaStateInfo_getName (annotationInfo_getState (a)),
9550 stateValue_create (annotationInfo_getValue (a), stateInfo_makeLoc (loc)));
9551 DPRINTF (("state info: %s", stateInfo_unparse (stateInfo_makeLoc (loc))));
9552 DPRINTF (("sref: %s", sRef_unparse (s)));
9553 DPRINTF (("sref: %s", sRef_unparseFull (s)));
9558 void sRef_setMetaStateValueComplete (sRef s, cstring key, int value, fileloc loc)
9560 sRefSet aliases = usymtab_allAliases (s);
9562 sRef_setMetaStateValue (s, key, value, loc);
9564 sRefSet_realElements (aliases, current)
9566 if (sRef_isValid (current))
9568 current = sRef_updateSref (current);
9569 sRef_setMetaStateValue (current, key, value, loc);
9571 } end_sRefSet_realElements ;
9573 sRefSet_free (aliases);
9576 void sRef_setMetaStateValue (sRef s, cstring key, int value, fileloc loc)
9578 sRef_checkMutable (s);
9580 if (sRef_isValid (s))
9582 if (!valueTable_isDefined (s->state))
9584 DPRINTF (("inserting state: %s: %s %d", sRef_unparse (s), key, value));
9585 s->state = valueTable_create (1);
9586 valueTable_insert (s->state, cstring_copy (key),
9587 stateValue_create (value, stateInfo_makeLoc (loc)));
9591 DPRINTF (("Updating state: %s: %s %d / %s", sRef_unparse (s), key, value,
9592 fileloc_unparse (loc)));
9593 if (valueTable_contains (s->state, key))
9596 (s->state, key, stateValue_create (value, stateInfo_makeLoc (loc)));
9601 (s->state, cstring_copy (key), stateValue_create (value, stateInfo_makeLoc (loc)));
9604 DPRINTF (("After: %s", sRef_unparseFull (s)));
9609 bool sRef_checkMetaStateValue (sRef s, cstring key, int value)
9611 if (sRef_isValid (s))
9613 if (valueTable_isDefined (s->state))
9617 DPRINTF (("check state: %s: %s %d", sRef_unparse (s), key, value));
9619 val = valueTable_lookup (s->state, key);
9620 llassert (stateValue_isDefined (val));
9621 return (stateValue_isError (val)
9622 || stateValue_getValue (val) == value);
9635 /*@observer@*/ stateValue sRef_getMetaStateValue (sRef s, cstring key)
9637 if (sRef_isValid (s))
9639 if (valueTable_isDefined (s->state))
9643 val = valueTable_lookup (s->state, key);
9644 /* Okay if its not defined, just returns stateValue_undefined */
9649 return stateValue_undefined;
9654 return stateValue_undefined;
9658 /*@observer@*/ valueTable sRef_getValueTable (sRef s)
9660 DPRINTF (("Get value table: %s", sRef_unparse (s)));
9662 if (sRef_isValid (s))
9664 llassert (sRef_isValid (s));
9665 DPRINTF (("Value table: %s", valueTable_unparse (s->state)));
9670 DPRINTF (("No value table!"));
9671 return valueTable_undefined;
9675 bool sRef_makeStateSpecial (sRef s)
9678 ** Default defined state can be made special.
9681 llassert (sRef_isValid (s)); /*@i523 why doesn't null-checking work!??? */
9683 if (s->defstate == SS_UNKNOWN || s->defstate == SS_DEFINED || s->defstate == SS_SPECIAL)
9685 s->aliaskind = AK_IMPTEMP;
9686 s->defstate = SS_SPECIAL;
9687 DPRINTF (("Made special: %s", sRef_unparseFull (s)));
9692 s->aliaskind = AK_IMPTEMP;
9693 s->defstate = SS_SPECIAL;
9698 void sRef_markImmutable (sRef s)
9700 if (sRef_isValid (s))
9702 DPRINTF (("Mark immutable: %s", sRef_unparseFull (s)));
9707 bool sRef_definitelyNullContext (sRef s)
9709 return (sRef_definitelyNull (s)
9710 || usymtab_isDefinitelyNullDeep (s));
9713 bool sRef_definitelyNullAltContext (sRef s)
9715 return (sRef_definitelyNull (s)
9716 || usymtab_isAltDefinitelyNullDeep (s));
9720 /* start modifications */
9721 struct s_bbufinfo sRef_getNullTerminatedState (sRef p_s) {
9722 struct s_bbufinfo BUFSTATE_UNKNOWN;
9723 BUFSTATE_UNKNOWN.bufstate = BB_NOTNULLTERMINATED;
9724 BUFSTATE_UNKNOWN.size = 0;
9725 BUFSTATE_UNKNOWN.len = 0;
9727 if (sRef_isValid(p_s))
9728 return p_s->bufinfo;
9729 return BUFSTATE_UNKNOWN;
9732 void sRef_setNullTerminatedState(sRef p_s) {
9733 if(sRef_isValid (p_s)) {
9734 p_s->bufinfo.bufstate = BB_NULLTERMINATED;
9736 llfatalbug( message("sRef_setNT passed a invalid sRef\n"));
9741 void sRef_setPossiblyNullTerminatedState(sRef p_s) {
9742 if( sRef_isValid (p_s)) {
9743 p_s->bufinfo.bufstate = BB_POSSIBLYNULLTERMINATED;
9745 llfatalbug( message("sRef_setPossNT passed a invalid sRef\n"));
9749 void sRef_setNotNullTerminatedState(sRef p_s) {
9750 if( sRef_isValid (p_s)) {
9751 p_s->bufinfo.bufstate = BB_NOTNULLTERMINATED;
9753 llfatalbug( message("sRef_unsetNT passed a invalid sRef\n"));
9757 void sRef_setLen(sRef p_s, int len) {
9758 if( sRef_isValid (p_s) && sRef_isNullTerminated(p_s)) {
9759 p_s->bufinfo.len = len;
9761 llfatalbug( message("sRef_setLen passed a invalid sRef\n"));
9766 void sRef_setSize(sRef p_s, int size) {
9767 if( sRef_isValid(p_s)) {
9768 p_s->bufinfo.size = size;
9770 llfatalbug( message("sRef_setSize passed a invalid sRef\n"));
9774 void sRef_resetLen(sRef p_s) {
9775 if (sRef_isValid (p_s)) {
9776 p_s->bufinfo.len = 0;
9778 llfatalbug (message ("sRef_setLen passed an invalid sRef\n"));
9782 /*drl7x 11/28/2000 */
9784 bool sRef_isFixedArray (sRef p_s) /*@*/ {
9786 c = sRef_getType (p_s);
9787 return ( ctype_isFixedArray (c) );
9790 long int sRef_getArraySize (sRef p_s) /*@*/ {
9792 llassert (sRef_isFixedArray(p_s) );
9793 DPRINTF (( message ("sRef_getArraySize getting array size for %s", sRef_unparse(p_s) ) ));
9795 c = sRef_getType (p_s);
9797 return (ctype_getArraySize (c) );