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_findDerivedArrayFetch (/*@notnull@*/ sRef, bool, int, bool) ;
187 static /*@exposed@*/ sRef sRef_findDerivedField (/*@notnull@*/ sRef p_rec, cstring p_f);
188 static /*@exposed@*/ sRef
189 sRef_getDeriv (/*@notnull@*/ /*@returned@*/ sRef p_set, sRef p_guide);
191 static bool inFunction = FALSE;
192 static /*@only@*/ sRefTable allRefs;
194 /* # define DEBUGREFS */
198 static totnsrefs = 0;
199 static maxnsrefs = 0;
200 static ntotrefers = 0;
204 static /*@checked@*/ bool protectDerivs = FALSE;
207 ** Result of sRef_alloc is dependent since allRefs may
208 ** reference it. It is only if !inFunction.
211 static /*@dependent@*/ /*@out@*/ /*@notnull@*/ sRef
214 sRef s = (sRef) dmalloc (sizeof (*s));
218 DPRINTF (("Alloc sref: [%p]", s));
222 allRefs = sRefTable_add (allRefs, s);
227 DPRINTF (("Not in function!"));
233 if (nsrefs >= maxnsrefs)
242 /*@-mustfree@*/ /*@-freshtrans@*/
244 /*@=mustfree@*/ /*@=freshtrans@*/
247 static void sRef_checkValidAux (sRef s, sRefSet checkedsofar)
251 if (!sRef_isValid (s)) return;
253 if (sRefSet_containsSameObject (checkedsofar, s))
259 checkedsofar = sRefSet_insert (checkedsofar, s);
260 /*@=temptrans@*/ /* checksofar will be destroyed before checkValid returns */
264 case SK_UNCONSTRAINED:
265 llassert (cstring_length (s->info->fname) < 100);
269 llassert (s->info->cvar->lexlevel >= 0);
270 /* llassert (s->info->cvar->lexlevel <= usymtab_getCurrentDepth ()); */
274 llassert (s->info->paramno >= -1);
275 llassert (s->info->paramno <= 50); /*@i32 bogus...*/
279 sRef_checkValidAux (s->info->arrayfetch->arr, checkedsofar);
283 sRef_checkValidAux (s->info->field->rec, checkedsofar);
284 llassert (cstring_length (s->info->field->field) < 100);
288 sRef_checkValidAux (s->info->ref, checkedsofar);
292 sRef_checkValidAux (s->info->ref, checkedsofar);
296 /* check ctype s->info->object */
300 sRef_checkValidAux (s->info->conj->a, checkedsofar);
301 sRef_checkValidAux (s->info->conj->b, checkedsofar);
305 llassert (cstring_length (s->info->fname) < 100);
309 sRef_checkValidAux (s->info->ref, checkedsofar);
313 sRef_checkValidAux (s->info->ref, checkedsofar);
319 /* check ctyp s->type */
323 llassert (s->info->spec == SR_NOTHING
324 || s->info->spec == SR_INTERNAL
325 || s->info->spec == SR_SPECSTATE
326 || s->info->spec == SR_SYSTEM);
336 sRefSet_elements (s->deriv, el)
338 sRef_checkValidAux (el, checkedsofar);
339 } end_sRefSet_elements ;
342 void sRef_checkValid (/*@unused@*/ sRef s)
346 sRefSet checkedsofar = sRefSet_new ();
347 sRef_checkValidAux (s, checkedsofar);
351 static /*@dependent@*/ /*@notnull@*/ /*@special@*/ sRef
354 /*@ensures isnull result->aliasinfo, result->definfo,
355 result->expinfo, result->info, result->deriv, result->state@*/
357 sRef s = sRef_alloc ();
359 s->kind = SK_UNKNOWN;
364 s->type = ctype_unknown;
365 s->defstate = SS_UNKNOWN;
367 /* start modifications */
368 s->bufinfo.bufstate = BB_NOTNULLTERMINATED;
369 /* end modifications */
371 s->aliaskind = AK_UNKNOWN;
372 s->oaliaskind = AK_UNKNOWN;
374 s->nullstate = NS_UNKNOWN;
376 s->expkind = XO_UNKNOWN;
377 s->oexpkind = XO_UNKNOWN;
379 s->aliasinfo = stateInfo_undefined;
380 s->definfo = stateInfo_undefined;
381 s->nullinfo = stateInfo_undefined;
382 s->expinfo = stateInfo_undefined;
385 s->deriv = sRefSet_undefined;
387 s->state = valueTable_undefined;
392 static /*@dependent@*/ /*@notnull@*/ /*@special@*/ sRef
395 /*@ensures isnull result->aliasinfo, result->definfo,
396 result->expinfo, result->info, result->deriv@*/
398 sRef res = sRef_new ();
400 res->state = valueTable_undefined;
405 void sRef_protectDerivs (void) /*@modifies protectDerivs@*/
407 llassert (!protectDerivs);
408 protectDerivs = TRUE;
411 void sRef_clearProtectDerivs (void) /*@modifies protectDerivs@*/
413 llassert (protectDerivs);
414 protectDerivs = FALSE;
418 ** hmmm...here be kind of a hack. This function mysteriously appeared
419 ** in my code, but I'm sure I didn't write it.
423 sRef_isRecursiveField (sRef s)
425 if (sRef_isField (s))
427 if (sRef_depth (s) > 13)
432 fieldname = sRef_getField (s);
433 base = sRef_getBase (s);
435 while (sRef_isValid (base))
437 if (sRef_isField (base))
439 if (cstring_equal (fieldname, sRef_getField (base)))
445 base = sRef_getBaseSafe (base);
454 sRef_addDeriv (/*@notnull@*/ sRef s, /*@notnull@*/ /*@exposed@*/ sRef t)
456 if (!context_inProtectVars ()
460 && !sRef_isConst (s))
462 int sd = sRef_depth (s);
463 int td = sRef_depth (t);
470 /* This sometimes fails: (evans 2001-07-12)
471 if (sRef_isArrayFetch (t))
473 DPRINTF (("Derived fetch: %s / %s / %s",
474 sRef_unparseFull (s), sRef_unparseFull (t),
475 sRef_unparseFull (t->info->arrayfetch->arr)));
476 llassert (t->info->arrayfetch->arr == s);
480 if (sRef_isFileOrGlobalScope (s))
482 if (context_inFunctionLike ()
483 && ctype_isKnown (sRef_getType (s))
484 && !ctype_isFunction (sRef_getType (s)))
486 globSet g = context_getUsedGlobs ();
488 if (!globSet_member (g, s))
491 ** don't report as a bug
495 (message ("sRef_addDeriv: global variable not in used "
496 "globs: %q / %s / %q",
498 ctype_unparse (sRef_getType (s)),
499 sRefSet_unparse (s->deriv)));
504 s->deriv = sRefSet_insert (s->deriv, t);
510 DPRINTF (("Add deriv: [%p] %s / [%p] %s",
512 t, sRef_unparse (t)));
514 s->deriv = sRefSet_insert (s->deriv, t);
520 sRef_deepPred (bool (predf) (sRef), sRef s)
522 if (sRef_isValid (s))
524 if ((*predf)(s)) return TRUE;
529 return (sRef_deepPred (predf, s->info->ref));
531 return (sRef_deepPred (predf, s->info->arrayfetch->arr));
533 return (sRef_deepPred (predf, s->info->field->rec));
535 return (sRef_deepPred (predf, s->info->conj->a)
536 || sRef_deepPred (predf, s->info->conj->b));
545 bool sRef_modInFunction (void)
550 void sRef_setStateFromType (sRef s, ctype ct)
552 if (sRef_isValid (s))
554 if (ctype_isUser (ct))
556 DPRINTF (("Here we are: %s", sRef_unparseFull (s)));
557 sRef_setStateFromUentry
558 (s, usymtab_getTypeEntry (ctype_typeId (ct)));
560 else if (ctype_isAbstract (ct))
562 DPRINTF (("Here we are: %s", sRef_unparseFull (s)));
563 sRef_setStateFromAbstractUentry
564 (s, usymtab_getTypeEntry (ctype_typeId (ct)));
568 ; /* not a user type */
573 static void sRef_setTypeState (sRef s)
575 if (sRef_isValid (s))
577 sRef_setStateFromType (s, s->type);
582 sRef_hasAliasInfoLoc (sRef s)
584 return (sRef_isValid (s) && (s->aliasinfo != NULL)
585 && (fileloc_isDefined (s->aliasinfo->loc)));
588 static /*@falsenull@*/ bool
589 sRef_hasStateInfoLoc (sRef s)
591 return (sRef_isValid (s) && (s->definfo != NULL)
592 && (fileloc_isDefined (s->definfo->loc)));
595 static /*@falsenull@*/ bool
596 sRef_hasExpInfoLoc (sRef s)
598 return (sRef_isValid (s)
599 && (s->expinfo != NULL) && (fileloc_isDefined (s->expinfo->loc)));
602 static /*@observer@*/ /*@unused@*/ stateInfo sRef_getInfo (sRef s, cstring key)
606 if (!sRef_isValid (s)) {
607 return stateInfo_undefined;
610 sv = valueTable_lookup (s->state, key);
612 if (stateValue_isDefined (sv))
614 return stateValue_getInfo (sv);
617 return stateInfo_undefined;
622 sRef_hasNullInfoLoc (sRef s)
624 return (sRef_isValid (s) && s->nullinfo != NULL
625 && (fileloc_isDefined (s->nullinfo->loc)));
629 sRef_hasAliasInfoRef (sRef s)
631 return (sRef_isValid (s) && (s->aliasinfo != NULL)
632 && (sRef_isValid (s->aliasinfo->ref)));
635 static /*@observer@*/ fileloc
636 sRef_getAliasInfoLoc (/*@exposed@*/ sRef s)
638 llassert (sRef_isValid (s) && s->aliasinfo != NULL
639 && (fileloc_isDefined (s->aliasinfo->loc)));
640 return (s->aliasinfo->loc);
643 static /*@observer@*/ fileloc
644 sRef_getStateInfoLoc (/*@exposed@*/ sRef s)
646 llassert (sRef_isValid (s) && s->definfo != NULL
647 && (fileloc_isDefined (s->definfo->loc)));
648 return (s->definfo->loc);
651 static /*@observer@*/ fileloc
652 sRef_getExpInfoLoc (/*@exposed@*/ sRef s)
654 llassert (sRef_isValid (s) && s->expinfo != NULL
655 && (fileloc_isDefined (s->expinfo->loc)));
656 return (s->expinfo->loc);
659 static /*@observer@*/ fileloc
660 sRef_getNullInfoLoc (/*@exposed@*/ sRef s)
662 llassert (sRef_isValid (s) && s->nullinfo != NULL
663 && (fileloc_isDefined (s->nullinfo->loc)));
664 return (s->nullinfo->loc);
668 sRef_getAliasInfoRef (/*@temp@*/ sRef s)
670 llassert (sRef_isValid (s) && s->aliasinfo != NULL);
671 return (s->aliasinfo->ref);
674 bool sRef_inGlobalScope ()
680 ** This function should be called before new sRefs are created
681 ** somewhere where they will have a lifetime greater than the
682 ** current function scope.
685 void sRef_setGlobalScope ()
687 llassert (inFunction);
688 DPRINTF (("leave function"));
692 void sRef_clearGlobalScope ()
694 llassert (!inFunction);
695 DPRINTF (("enter function"));
699 static bool oldInFunction = FALSE;
700 static int nestedScope = 0;
702 void sRef_setGlobalScopeSafe ()
704 if (nestedScope == 0)
706 oldInFunction = inFunction;
710 DPRINTF (("leave function safe"));
714 void sRef_clearGlobalScopeSafe ()
717 llassert (nestedScope >= 0);
719 if (nestedScope == 0)
721 inFunction = oldInFunction;
724 DPRINTF (("clear function: %s", bool_unparse (inFunction)));
727 void sRef_enterFunctionScope ()
729 llassert (!inFunction);
730 llassert (sRefTable_isEmpty (allRefs));
732 DPRINTF (("enter function"));
735 void sRef_exitFunctionScope ()
739 DPRINTF (("Exit function scope."));
740 sRefTable_clear (allRefs);
745 llbuglit ("sRef_exitFunctionScope: not in function");
749 void sRef_destroyMod () /*@globals killed allRefs;@*/
752 llmsg (message ("Live: %d / %d ", nsrefs, totnsrefs));
755 sRefTable_free (allRefs);
759 static /*@notnull@*/ /*@exposed@*/ sRef
760 sRef_fixConj (/*@notnull@*/ sRef s)
765 s = sRef_getConjA (s);
766 } while (sRef_isConj (s));
768 llassert (sRef_isValid (s));
769 return s; /* don't need to ref */
778 sRef_isExternallyVisibleAux (sRef s)
781 sRef base = sRef_getRootBase (s);
783 if (sRef_isValid (base))
785 res = sRef_isParam (base) || sRef_isFileOrGlobalScope (base) || sRef_isExternal (base);
792 sRef_isExternallyVisible (sRef s)
794 return (sRef_aliasCheckSimplePred (sRef_isExternallyVisibleAux, s));
798 sRef_getBaseUentry (sRef s)
800 sRef base = sRef_getRootBase (s);
801 uentry res = uentry_undefined;
803 if (sRef_isValid (base))
808 res = usymtab_getRefQuiet (paramsScope, base->info->paramno);
812 res = usymtab_getRefQuiet (base->info->cvar->lexlevel,
813 base->info->cvar->index);
825 ** lookup the current uentry corresponding to s, and return the corresponding sRef.
826 ** yuk yuk yuk yuk yuk yuk yuk yuk
830 sRef_updateSref (sRef s)
836 if (!sRef_isValid (s)) return sRef_undefined;
845 case SK_UNCONSTRAINED:
852 sRef r = sRef_updateSref (s->info->ref);
854 if (r != s->info->ref)
856 return sRef_makeExternal (r);
866 uentry ue = sRef_getUentry (s);
868 /* must be raw name! (need the marker) */
869 ue = usymtab_lookupSafe (uentry_rawName (ue));
871 if (uentry_isUndefined (ue))
877 DPRINTF (("Update sref: %s", uentry_unparseFull (ue)));
878 return (uentry_getSref (ue));
882 /* special case if ind known */
883 inner = s->info->arrayfetch->arr;
884 ret = sRef_updateSref (inner);
892 res = sRef_makeArrayFetch (ret);
898 inner = s->info->field->rec;
899 ret = sRef_updateSref (inner);
907 res = (sRef_makeField (ret, s->info->field->field));
912 inner = s->info->ref;
913 ret = sRef_updateSref (inner);
920 res = sRef_makePointer (ret);
926 inner = s->info->ref;
927 ret = sRef_updateSref (inner);
935 res = sRef_makeAddress (ret);
942 sRef innera = s->info->conj->a;
943 sRef innerb = s->info->conj->b;
944 sRef reta = sRef_updateSref (innera);
945 sRef retb = sRef_updateSref (innerb);
947 if (innera == reta && innerb == retb)
953 res = sRef_makeConj (reta, retb);
964 sRef_getUentry (sRef s)
966 llassert (sRef_isValid (s));
971 return (usymtab_getRefQuiet (paramsScope, s->info->paramno));
973 return (usymtab_getRefQuiet (s->info->cvar->lexlevel, s->info->cvar->index));
976 if (sRef_isCvar (s->info->conj->a) || sRef_isParam (s->info->conj->a)
977 || sRef_isConj (s->info->conj->a))
979 return sRef_getUentry (s->info->conj->a);
983 return sRef_getUentry (s->info->conj->b);
988 return uentry_undefined;
994 sRef_getParam (sRef s)
996 llassert (sRef_isValid (s));
997 llassert (s->kind == SK_PARAM);
999 return s->info->paramno;
1003 sRef_isModified (sRef s)
1005 return (!sRef_isValid (s) || s->modified);
1008 void sRef_setModified (sRef s)
1010 if (sRef_isValid (s))
1015 if (sRef_isRefsField (s))
1017 sRef base = sRef_getBase (s);
1020 llassert (s->kind == SK_FIELD);
1023 if (sRef_isPointer (base))
1025 base = sRef_getBase (base);
1028 if (sRef_isRefCounted (base))
1030 base->aliaskind = AK_NEWREF;
1037 ** note: this side-effects sRefSet to set modified to TRUE
1038 ** for any sRef similar to s.
1042 sRef_canModifyVal (sRef s, sRefSet sl)
1044 if (context_getFlag (FLG_MUSTMOD))
1046 return (sRef_doModifyVal (s, sl));
1050 return (sRef_checkModifyVal (s, sl));
1055 sRef_canModify (sRef s, sRefSet sl)
1058 if (context_getFlag (FLG_MUSTMOD))
1060 return (sRef_doModify (s, sl));
1064 return (sRef_checkModify (s, sl));
1073 bool sRef_checkModifyVal (sRef s, sRefSet sl)
1075 DPRINTF (("Check modify val: %s", sRef_unparse (s)));
1077 if (sRef_isInvalid (s))
1084 case SK_UNCONSTRAINED:
1088 DPRINTF (("Modify var: %s", sRef_unparse (s)));
1090 if (sRef_isFileOrGlobalScope (s))
1092 if (context_checkGlobMod (s))
1094 return (sRefSet_member (sl, s));
1104 return (sRefSet_member (sl, s)
1105 || alkind_isOnly (sRef_getOrigAliasKind (s)));
1107 /* special case if ind known */
1108 return (sRefSet_member (sl, s) ||
1109 sRef_checkModifyVal (s->info->arrayfetch->arr, sl));
1111 return (sRefSet_member (sl, s) || sRef_checkModifyVal (s->info->field->rec, sl));
1113 return (sRefSet_member (sl, s) || sRef_checkModifyVal (s->info->ref, sl));
1115 return (sRefSet_member (sl, s) || sRef_checkModifyVal (s->info->ref, sl));
1117 return ((sRef_checkModifyVal (s->info->conj->a, sl)) &&
1118 (sRef_checkModifyVal (s->info->conj->b, sl)));
1129 switch (s->info->spec)
1131 case SR_NOTHING: return TRUE;
1133 if (context_getFlag (FLG_INTERNALGLOBS))
1135 return (sRefSet_member (sl, s));
1141 case SR_SPECSTATE: return TRUE;
1142 case SR_SYSTEM: return (sRefSet_member (sl, s));
1143 case SR_GLOBALMARKER: BADBRANCH;
1146 case SK_RESULT: BADBRANCH;
1152 ** this should probably be elsewhere...
1154 ** returns TRUE iff sl indicates that s can be modified
1157 static bool sRef_checkModify (sRef s, sRefSet sl)
1159 llassert (sRef_isValid (s));
1163 case SK_UNCONSTRAINED:
1167 if (sRef_isFileOrGlobalScope (s))
1169 if (context_checkGlobMod (s))
1171 return (sRefSet_member (sl, s));
1183 return (sRefSet_member (sl, s) ||
1184 sRef_checkModifyVal (s->info->arrayfetch->arr, sl));
1187 sRef sr = s->info->field->rec;
1189 if (sr->kind == SK_PARAM)
1190 return TRUE; /* structs are copied on call */
1192 return (sRefSet_member (sl, s) || sRef_checkModifyVal (s->info->field->rec, sl));
1198 sm = sRefSet_member (sl, s);
1203 return (sRef_checkModifyVal (s->info->ref, sl));
1206 return (sRefSet_member (sl, s) || sRef_checkModifyVal (s->info->ref, sl));
1208 return ((sRef_checkModify (s->info->conj->a, sl)) &&
1209 (sRef_checkModify (s->info->conj->b, sl)));
1219 switch (s->info->spec)
1221 case SR_NOTHING: return TRUE;
1223 if (context_getFlag (FLG_INTERNALGLOBS))
1225 return (sRefSet_member (sl, s));
1231 case SR_SPECSTATE: return TRUE;
1232 case SR_SYSTEM: return (sRefSet_member (sl, s));
1233 case SR_GLOBALMARKER: BADBRANCH;
1236 case SK_RESULT: BADBRANCH;
1241 cstring sRef_stateVerb (sRef s)
1243 if (sRef_isDead (s))
1245 return cstring_makeLiteralTemp ("released");
1247 else if (sRef_isKept (s))
1249 return cstring_makeLiteralTemp ("kept");
1251 else if (sRef_isDependent (s))
1253 return cstring_makeLiteralTemp ("dependent");
1261 cstring sRef_stateAltVerb (sRef s)
1263 if (sRef_isDead (s))
1265 return cstring_makeLiteralTemp ("live");
1267 else if (sRef_isKept (s))
1269 return cstring_makeLiteralTemp ("not kept");
1271 else if (sRef_isDependent (s))
1273 return cstring_makeLiteralTemp ("independent");
1282 bool sRef_doModifyVal (sRef s, sRefSet sl)
1284 llassert (sRef_isValid (s));
1289 case SK_UNCONSTRAINED:
1293 if (sRef_isFileOrGlobalScope (s))
1296 if (context_checkGlobMod (s))
1298 return (sRefSet_modifyMember (sl, s));
1302 (void) sRefSet_modifyMember (sl, s);
1312 return (sRefSet_modifyMember (sl, s)
1313 || alkind_isOnly (sRef_getOrigAliasKind (s)));
1315 /* special case if ind known */
1316 /* unconditional OR, need side effect */
1317 return (OR (sRefSet_modifyMember (sl, s),
1318 sRef_doModifyVal (s->info->arrayfetch->arr, sl)));
1320 return (OR (sRefSet_modifyMember (sl, s),
1321 sRef_doModifyVal (s->info->field->rec, sl)));
1323 return (OR (sRefSet_modifyMember (sl, s),
1324 sRef_doModifyVal (s->info->ref, sl)));
1326 return (OR (sRefSet_modifyMember (sl, s),
1327 sRef_doModifyVal (s->info->ref, sl)));
1329 return (AND (sRef_doModifyVal (s->info->conj->a, sl) ,
1330 sRef_doModifyVal (s->info->conj->b, sl)));
1340 switch (s->info->spec)
1342 case SR_NOTHING: return TRUE;
1344 if (context_getFlag (FLG_INTERNALGLOBS))
1346 return (sRefSet_modifyMember (sl, s));
1350 (void) sRefSet_modifyMember (sl, s);
1353 case SR_SPECSTATE: return TRUE;
1354 case SR_SYSTEM: return (sRefSet_modifyMember (sl, s));
1355 case SR_GLOBALMARKER: BADBRANCH;
1359 case SK_RESULT: BADBRANCH;
1365 ** this should probably be elsewhere...
1367 ** returns TRUE iff sl indicates that s can be modified
1371 bool sRef_doModify (sRef s, sRefSet sl)
1373 llassert (sRef_isValid (s));
1377 case SK_UNCONSTRAINED:
1381 if (sRef_isFileOrGlobalScope (s))
1383 if (context_checkGlobMod (s))
1385 return (sRefSet_modifyMember (sl, s));
1389 (void) sRefSet_modifyMember (sl, s);
1401 return (OR (sRefSet_modifyMember (sl, s),
1402 sRef_doModifyVal (s->info->arrayfetch->arr, sl)));
1405 sRef sr = s->info->field->rec;
1407 if (sr->kind == SK_PARAM)
1409 return TRUE; /* structs are shallow-copied on call */
1412 return (OR (sRefSet_modifyMember (sl, s),
1413 sRef_doModifyVal (s->info->field->rec, sl)));
1417 return (OR (sRefSet_modifyMember (sl, s),
1418 sRef_doModifyVal (s->info->ref, sl)));
1421 return (OR (sRefSet_modifyMember (sl, s),
1422 sRef_doModifyVal (s->info->ref, sl)));
1424 return (AND (sRef_doModify (s->info->conj->a, sl),
1425 (sRef_doModify (s->info->conj->b, sl))));
1436 switch (s->info->spec)
1438 case SR_NOTHING: return TRUE;
1439 case SR_INTERNAL: return TRUE;
1440 case SR_SPECSTATE: return TRUE;
1441 case SR_SYSTEM: return (sRefSet_modifyMember (sl, s));
1442 case SR_GLOBALMARKER: BADBRANCH;
1445 case SK_RESULT: BADBRANCH;
1450 static /*@exposed@*/ sRef
1451 sRef_leastCommon (/*@exposed@*/ sRef s1, sRef s2)
1453 llassert (sRef_similar (s1, s2));
1455 if (!sRef_isValid (s1)) return s1;
1456 if (!sRef_isValid (s2)) return s1;
1458 sRef_combineDefState (s1, s2);
1459 sRef_combineNullState (s1, s2);
1460 sRef_combineExKinds (s1, s2);
1462 if (s1->aliaskind != s2->aliaskind)
1464 if (s1->aliaskind == AK_UNKNOWN)
1466 s1->aliaskind = s2->aliaskind;
1468 else if (s2->aliaskind == AK_UNKNOWN)
1474 s1->aliaskind = AK_ERROR;
1481 int sRef_compare (sRef s1, sRef s2)
1483 if (s1 == s2) return 0;
1485 if (sRef_isInvalid (s1)) return -1;
1486 if (sRef_isInvalid (s2)) return 1;
1488 INTCOMPARERETURN (s1->kind, s2->kind);
1489 INTCOMPARERETURN (s1->defstate, s2->defstate);
1490 INTCOMPARERETURN (s1->aliaskind, s2->aliaskind);
1492 DPRINTF (("Compare null state: %s / %s",
1493 sRef_unparseFull (s1),
1494 sRef_unparseFull (s2)));
1496 COMPARERETURN (nstate_compare (sRef_getNullState (s1),
1497 sRef_getNullState (s2)));
1502 return (int_compare (s1->info->paramno, s2->info->paramno));
1505 COMPARERETURN (sRef_compare (s1->info->arrayfetch->arr,
1506 s2->info->arrayfetch->arr));
1508 if (s1->info->arrayfetch->indknown && s2->info->arrayfetch->indknown)
1510 return (int_compare (s1->info->arrayfetch->ind,
1511 s2->info->arrayfetch->ind));
1513 if (!s1->info->arrayfetch->indknown && !s2->info->arrayfetch->indknown)
1520 COMPARERETURN (sRef_compare (s1->info->field->rec, s2->info->field->rec));
1522 if (cstring_equal (s1->info->field->field, s2->info->field->field))
1529 return (sRef_compare (s1->info->ref, s2->info->ref));
1531 COMPARERETURN (sRef_compare (s1->info->conj->a, s2->info->conj->a));
1532 return (sRef_compare (s1->info->conj->b, s2->info->conj->b));
1533 case SK_UNCONSTRAINED:
1534 return (cstring_compare (s1->info->fname, s2->info->fname));
1546 return (generic_compare (s1->info->spec, s2->info->spec));
1551 static bool cref_equal (cref c1, cref c2)
1553 return ((c1->lexlevel == c2->lexlevel) &&
1554 (usymId_equal (c1->index, c2->index)));
1558 ** returns true if s1 could be the same storage as s2.
1559 ** i.e., a[?] ~ a[3]. Note its not symmetric ... s1
1560 ** should be more specific.
1564 ** like similar, but matches objects <-> non-objects
1568 sRef_uniqueReference (sRef s)
1570 return (sRef_isFresh (s) || sRef_isUnique (s)
1571 || sRef_isOnly (s) || sRef_isStack (s)
1572 || sRef_isAddress (s));
1576 sRef_similarRelaxedAux (sRef s1, sRef s2)
1580 if (sRef_isUnknownArrayFetch (s1))
1590 if (sRef_isInvalid (s1) || sRef_isInvalid (s2)) return FALSE;
1592 if (sRef_isConj (s2))
1593 return (sRef_similarRelaxedAux (s1, sRef_getConjA (s2)) ||
1594 sRef_similarRelaxedAux (s1, sRef_getConjB (s2)));
1599 return ((s2->kind == SK_CVAR)
1600 && (cref_equal (s1->info->cvar, s2->info->cvar)));
1602 return ((s2->kind == SK_PARAM)
1603 && (s1->info->paramno == s2->info->paramno));
1605 if (s2->kind == SK_ARRAYFETCH)
1607 if (sRef_similarRelaxedAux (s1->info->arrayfetch->arr,
1608 s2->info->arrayfetch->arr))
1610 if (s1->info->arrayfetch->indknown)
1612 if (s2->info->arrayfetch->indknown)
1614 return (s1->info->arrayfetch->ind == s2->info->arrayfetch->ind);
1629 return ((s2->kind == SK_FIELD
1630 && (sRef_similarRelaxedAux (s1->info->field->rec,
1631 s2->info->field->rec)
1632 && cstring_equal (s1->info->field->field,
1633 s2->info->field->field))));
1635 return ((s2->kind == SK_PTR)
1636 && sRef_similarRelaxedAux (s1->info->ref, s2->info->ref));
1638 return ((s2->kind == SK_ADR)
1639 && sRef_similarRelaxedAux (s1->info->ref, s2->info->ref));
1641 return ((sRef_similarRelaxedAux (s1->info->conj->a, s2) ||
1642 (sRef_similarRelaxedAux (s1->info->conj->b, s2))));
1644 return (s1->info->spec == s2->info->spec);
1645 case SK_UNCONSTRAINED:
1646 return (cstring_equal (s1->info->fname, s2->info->fname));
1661 sRef_similarRelaxed (sRef s1, sRef s2)
1667 if (sRef_isThroughArrayFetch (s1))
1677 if (sRef_isInvalid (s1) || sRef_isInvalid (s2)) return FALSE;
1679 us1 = sRef_uniqueReference (s1);
1680 us2 = sRef_uniqueReference (s2);
1682 if ((s1->kind == SK_EXTERNAL && (s2->kind != SK_EXTERNAL && !us2))
1683 || (s2->kind == SK_EXTERNAL && (s1->kind != SK_EXTERNAL && !us1)))
1686 ** Previously, also:
1687 ** || (sRef_isExposed (s1) && !us2) || (sRef_isExposed (s2) && !us1)) ????
1689 ** No clue why this was there?!
1693 if (sRef_isExposed (s1) && sRef_isCvar (s1))
1695 uentry ue1 = sRef_getUentry (s1);
1697 if (uentry_isRefParam (ue1))
1699 return sRef_similarRelaxedAux (s1, s2);
1703 if (sRef_isExposed (s2) && sRef_isCvar (s2))
1705 uentry ue2 = sRef_getUentry (s2);
1707 if (uentry_isRefParam (ue2))
1709 return sRef_similarRelaxedAux (s1, s2);
1713 return (ctype_match (s1->type, s2->type));
1717 return sRef_similarRelaxedAux (s1, s2);
1722 sRef_similar (sRef s1, sRef s2)
1724 if (s1 == s2) return TRUE;
1725 if (sRef_isInvalid (s1) || sRef_isInvalid (s2)) return FALSE;
1727 if (sRef_isConj (s2))
1729 return (sRef_similar (s1, sRef_getConjA (s2)) ||
1730 sRef_similar (s1, sRef_getConjB (s2)));
1733 if (sRef_isDerived (s2))
1735 return (sRef_includedBy (s1, s2->info->ref));
1741 return ((s2->kind == SK_CVAR)
1742 && (cref_equal (s1->info->cvar, s2->info->cvar)));
1744 return ((s2->kind == SK_PARAM)
1745 && (s1->info->paramno == s2->info->paramno));
1747 if (s2->kind == SK_ARRAYFETCH)
1749 if (sRef_similar (s1->info->arrayfetch->arr,
1750 s2->info->arrayfetch->arr))
1752 if (s1->info->arrayfetch->indknown)
1754 if (s2->info->arrayfetch->indknown)
1756 return (s1->info->arrayfetch->ind == s2->info->arrayfetch->ind);
1771 if (s2->kind == SK_PTR)
1773 if (sRef_similar (s1->info->arrayfetch->arr,
1783 return ((s2->kind == SK_FIELD
1784 && (sRef_similar (s1->info->field->rec,
1785 s2->info->field->rec)
1786 && cstring_equal (s1->info->field->field,
1787 s2->info->field->field))));
1789 if (s2->kind == SK_PTR)
1791 return sRef_similar (s1->info->ref, s2->info->ref);
1795 if (s2->kind == SK_ARRAYFETCH)
1797 if (sRef_similar (s2->info->arrayfetch->arr,
1807 return ((s2->kind == SK_ADR)
1808 && sRef_similar (s1->info->ref, s2->info->ref));
1810 return ((sRef_similar (s1->info->conj->a, s2) ||
1811 (sRef_similar (s1->info->conj->b, s2))));
1813 return (sRef_includedBy (s2, s1->info->ref));
1814 case SK_UNCONSTRAINED:
1815 return (s2->kind == SK_UNCONSTRAINED
1816 && cstring_equal (s1->info->fname, s2->info->fname));
1826 return (s2->kind == SK_SPECIAL
1827 && (s1->info->spec == s2->info->spec));
1830 /*@notreached@*/ DPRINTF (("Fell through for: %s / %s", sRef_unparse (s1), sRef_unparse (s2)));
1835 ** return TRUE iff small can be derived from big.
1837 ** (e.g. x, x.a is includedBy x;
1838 ** x.a is included By x.a;
1842 sRef_includedBy (sRef small, sRef big)
1844 if (small == big) return TRUE;
1845 if (sRef_isInvalid (small) || sRef_isInvalid (big)) return FALSE;
1847 if (sRef_isConj (big))
1848 return (sRef_similar (small, sRef_getConjA (big)) ||
1849 sRef_similar (small, sRef_getConjB (big)));
1851 switch (small->kind)
1855 return (sRef_same (small, big));
1857 if (big->kind == SK_ARRAYFETCH)
1859 if (sRef_same (small->info->arrayfetch->arr, big->info->arrayfetch->arr))
1861 if (small->info->arrayfetch->indknown)
1863 if (big->info->arrayfetch->indknown)
1865 return (small->info->arrayfetch->ind == big->info->arrayfetch->ind);
1878 return (sRef_includedBy (small->info->arrayfetch->arr, big));
1880 if (big->kind == SK_FIELD)
1883 (sRef_same (small->info->field->rec, big->info->field->rec) &&
1884 cstring_equal (small->info->field->field, big->info->field->field));
1888 return (sRef_includedBy (small->info->field->rec, big));
1892 if (big->kind == SK_PTR)
1894 return sRef_same (small->info->ref, big->info->ref);
1898 return (sRef_includedBy (small->info->ref, big));
1902 return ((big->kind == SK_ADR) && sRef_similar (small->info->ref, big->info->ref));
1904 return ((sRef_includedBy (small->info->conj->a, big) ||
1905 (sRef_includedBy (small->info->conj->b, big))));
1907 return (sRef_includedBy (small->info->ref, big));
1908 case SK_UNCONSTRAINED:
1918 switch (small->info->spec)
1920 case SR_NOTHING: return TRUE;
1922 case SR_INTERNAL: return (sRef_isSpecInternalState (big) ||
1923 sRef_isFileStatic (big));
1924 case SR_SYSTEM: return (sRef_isSystemState (big));
1925 case SR_GLOBALMARKER: BADBRANCH;
1932 ** Same is similar to similar, but not quite the same.
1933 ** same and realSame aren't the same, but they are really similar.
1934 ** similarly, same is the same as same. but realSame is
1935 ** not really the same as same, or similar to similar.
1937 ** Similarly to similar, same checks if two sRefs are the same.
1938 ** The similarities end, however, when same compares arrays
1939 ** with unknown indexes. Similar returns false; same returns true.
1941 ** Similarly to similar and same, realSame is the same as same,
1942 ** except they do not behave the same when face with unknown
1943 ** sRefs. Same thinks they are not the same, but realSame thinks
1949 sRef_realSame (sRef s1, sRef s2)
1951 if (s1 == s2) return TRUE;
1952 if (sRef_isInvalid (s1) || sRef_isInvalid (s2)) return FALSE;
1957 return ((s2->kind == SK_CVAR) && (cref_equal (s1->info->cvar, s2->info->cvar)));
1959 return ((s2->kind == SK_PARAM) && (s1->info->paramno == s2->info->paramno));
1961 if (s2->kind == SK_ARRAYFETCH)
1963 if (sRef_realSame (s1->info->arrayfetch->arr, s2->info->arrayfetch->arr))
1965 if (s1->info->arrayfetch->indknown && s2->info->arrayfetch->indknown)
1967 return (s1->info->arrayfetch->ind == s2->info->arrayfetch->ind);
1969 if (!s1->info->arrayfetch->indknown && !s2->info->arrayfetch->indknown)
1978 return ((s2->kind == SK_FIELD &&
1979 (sRef_realSame (s1->info->field->rec, s2->info->field->rec) &&
1980 cstring_equal (s1->info->field->field, s2->info->field->field))));
1982 return ((s2->kind == SK_PTR) && sRef_realSame (s1->info->ref, s2->info->ref));
1984 return ((s2->kind == SK_ADR) && sRef_realSame (s1->info->ref, s2->info->ref));
1986 return ((sRef_realSame (s1->info->conj->a, s2) ||
1987 (sRef_realSame (s1->info->conj->b, s2))));
1989 return ((s2->kind == SK_OBJECT)
1990 && ctype_match (s1->info->object, s2->info->object));
1992 return ((s2->kind == SK_EXTERNAL)
1993 && sRef_realSame (s1->info->ref, s2->info->ref));
1995 return ((s2->kind == SK_SPECIAL) && s1->info->spec == s2->info->spec);
1997 return ((s2->kind == SK_DERIVED) && sRef_realSame (s1->info->ref, s2->info->ref));
1998 case SK_UNCONSTRAINED:
1999 return ((s2->kind == SK_UNCONSTRAINED)
2000 && (cstring_equal (s1->info->fname, s2->info->fname)));
2006 return TRUE; /* changed this! was false */
2012 sRef_sameObject (sRef s1, sRef s2)
2018 ** same is similar to similar, but not quite the same.
2020 ** Similarly to similar, same checks is two sRefs are the same.
2021 ** The similarities end, however, when same compares arrays
2022 ** with unknown indexes. Similar returns false; same returns true.
2026 sRef_same (sRef s1, sRef s2)
2028 if (s1 == s2) return TRUE;
2029 if (sRef_isInvalid (s1) || sRef_isInvalid (s2)) return FALSE;
2034 return ((s2->kind == SK_CVAR) && (cref_equal (s1->info->cvar, s2->info->cvar)));
2036 return ((s2->kind == SK_PARAM) && (s1->info->paramno == s2->info->paramno));
2038 if (s2->kind == SK_ARRAYFETCH)
2040 llassert (s1->info->field->rec != s1);
2041 if (sRef_same (s1->info->arrayfetch->arr, s2->info->arrayfetch->arr))
2043 if (s1->info->arrayfetch->indknown && s2->info->arrayfetch->indknown)
2045 return (s1->info->arrayfetch->ind == s2->info->arrayfetch->ind);
2053 llassert (s1->info->field->rec != s1);
2054 return ((s2->kind == SK_FIELD &&
2055 (sRef_same (s1->info->field->rec, s2->info->field->rec) &&
2056 cstring_equal (s1->info->field->field, s2->info->field->field))));
2060 llassert (s1->info->ref != s1);
2061 return ((s2->kind == SK_PTR) && sRef_same (s1->info->ref, s2->info->ref));
2065 llassert (s1->info->ref != s1);
2066 return ((s2->kind == SK_ADR) && sRef_same (s1->info->ref, s2->info->ref));
2069 llassert (s1->info->conj->a != s1);
2070 llassert (s1->info->conj->b != s1);
2071 return ((sRef_same (s1->info->conj->a, s2)) && /* or or and? */
2072 (sRef_same (s1->info->conj->b, s2)));
2074 return ((s2->kind == SK_SPECIAL) && s1->info->spec == s2->info->spec);
2076 llassert (s1->info->ref != s1);
2077 return ((s2->kind == SK_DERIVED) && sRef_same (s1->info->ref, s2->info->ref));
2079 case SK_UNCONSTRAINED:
2092 ** sort of similar, for use in def/use
2096 sRef_closeEnough (sRef s1, sRef s2)
2098 if (s1 == s2) return TRUE;
2099 if (sRef_isInvalid (s1) || sRef_isInvalid (s2)) return FALSE;
2104 return (((s2->kind == SK_CVAR) &&
2105 (cref_equal (s1->info->cvar, s2->info->cvar))) ||
2106 (s2->kind == SK_UNCONSTRAINED && s1->info->cvar->lexlevel == 0));
2107 case SK_UNCONSTRAINED:
2108 return (s2->kind == SK_UNCONSTRAINED
2109 || ((s2->kind == SK_CVAR) && (s2->info->cvar->lexlevel == 0)));
2111 return ((s2->kind == SK_PARAM)
2112 && (s1->info->paramno == s2->info->paramno));
2114 if (s2->kind == SK_ARRAYFETCH)
2116 if (sRef_closeEnough (s1->info->arrayfetch->arr, s2->info->arrayfetch->arr))
2118 if (s1->info->arrayfetch->indknown && s2->info->arrayfetch->indknown)
2120 return (s1->info->arrayfetch->ind == s2->info->arrayfetch->ind);
2127 return ((s2->kind == SK_FIELD &&
2128 (sRef_closeEnough (s1->info->field->rec, s2->info->field->rec) &&
2129 cstring_equal (s1->info->field->field, s2->info->field->field))));
2131 return ((s2->kind == SK_PTR) && sRef_closeEnough (s1->info->ref, s2->info->ref));
2133 return ((s2->kind == SK_ADR) && sRef_closeEnough (s1->info->ref, s2->info->ref));
2135 return ((s2->kind == SK_DERIVED) && sRef_closeEnough (s1->info->ref, s2->info->ref));
2137 return ((sRef_closeEnough (s1->info->conj->a, s2)) ||
2138 (sRef_closeEnough (s1->info->conj->b, s2)));
2140 return ((s2->kind == SK_SPECIAL) && s1->info->spec == s2->info->spec);
2156 s is an sRef of a formal paramenter in a function call constraint
2157 we trys to return a constraint expression derived from the actual parementer of a function call.
2159 /*@only@*/ constraintExpr sRef_fixConstraintParam (/*@observer@*/ sRef s, /*@observer@*/ /*@temp@*/ exprNodeList args)
2163 if (sRef_isInvalid (s))
2164 llfatalbug((message("Invalid sRef")));
2170 // s = sRef_saveCopy(s);
2171 ce = constraintExpr_makeTermsRef (s);
2178 temp = (sRef_makeField (sRef_fixBaseParam (s->info->field->rec, args),
2179 s->info->field->field));
2180 ce = constraintExpr_makeTermsRef (temp);
2186 temp = (sRef_makePointer (sRef_fixBaseParam (s->info->ref, args)));
2187 //temp = sRef_saveCopy(temp);
2188 ce = constraintExpr_makeTermsRef (temp);
2195 temp = sRef_saveCopy(s);
2196 temp = sRef_fixBaseParam (temp, args);
2197 ce = constraintExpr_makeTermsRef (temp);
2205 temp = sRef_saveCopy(s);
2206 ce = constraintExpr_makeTermsRef (temp);
2211 llassert(exprNodeList_size (args) > s->info->paramno);
2213 exprNode e = exprNodeList_nth (args, s->info->paramno);
2215 llassert( !(exprNode_isError (e)) );
2216 ce = constraintExpr_makeExprNode (e);
2223 llcontbug ((message("Trying to do fixConstraintParam on nonparam, nonglobal: %q for function with arguments %q", sRef_unparse (s), exprNodeList_unparse(args) ) ));
2224 temp = sRef_saveCopy(s);
2225 ce = constraintExpr_makeTermsRef (temp);
2237 sRef_fixBaseParam (/*@returned@*/ sRef s, exprNodeList args)
2239 if (sRef_isInvalid (s)) return (sRef_undefined);
2243 case SK_UNCONSTRAINED:
2248 if (exprNodeList_size (args) > s->info->paramno)
2250 exprNode e = exprNodeList_nth (args, s->info->paramno);
2252 if (exprNode_isError (e))
2254 return sRef_makeUnknown ();
2257 return (exprNode_getSref (e));
2261 return sRef_makeUnknown ();
2266 if (s->info->arrayfetch->indknown)
2268 return (sRef_makeArrayFetchKnown
2269 (sRef_fixBaseParam (s->info->arrayfetch->arr, args),
2270 s->info->arrayfetch->ind));
2274 return (sRef_makeArrayFetch
2275 (sRef_fixBaseParam (s->info->arrayfetch->arr, args)));
2278 return (sRef_makeField (sRef_fixBaseParam (s->info->field->rec, args),
2279 s->info->field->field));
2282 return (sRef_makePointer (sRef_fixBaseParam (s->info->ref, args)));
2285 return (sRef_makeAddress (sRef_fixBaseParam (s->info->ref, args)));
2288 return (sRef_makeConj (sRef_fixBaseParam (s->info->conj->a, args),
2289 sRef_fixBaseParam (s->info->conj->b, args)));
2305 sRef_undumpGlobal (char **c)
2315 usymId uid = usymId_fromInt (reader_getInt (c));
2320 reader_checkChar (c, '@');
2321 defstate = sstate_fromInt (reader_getInt (c));
2323 reader_checkChar (c, '@');
2324 nullstate = nstate_fromInt (reader_getInt (c));
2326 ret = sRef_makeGlobal (uid, ctype_unknown);
2327 sRef_setNullStateN (ret, nullstate);
2328 ret->defstate = defstate;
2333 int i = reader_getInt (c);
2334 speckind sk = speckind_fromInt (i);
2338 case SR_NOTHING: return (sRef_makeNothing ());
2339 case SR_INTERNAL: return (sRef_makeInternalState ());
2340 case SR_SPECSTATE: return (sRef_makeSpecState ());
2341 case SR_SYSTEM: return (sRef_makeSystemState ());
2342 case SR_GLOBALMARKER: BADBRANCH;
2347 return sRef_undefined;
2349 return sRef_makeUnknown ();
2351 return sRef_makeUnknown ();
2353 llfatalerror (message ("sRef_undumpGlobal: bad line: %s",
2354 cstring_fromChars (*c)));
2360 sRef_undump (char **c)
2369 return (sRef_makeGlobal (usymId_fromInt (reader_getInt (c)), ctype_unknown));
2371 return (sRef_makeParam (reader_getInt (c), ctype_unknown));
2373 return (sRef_makeResultType (ctype_undump (c)));
2376 if ((**c >= '0' && **c <= '9') || **c == '-')
2378 int i = reader_getInt (c);
2379 sRef arr = sRef_undump (c);
2380 sRef ret = sRef_buildArrayFetchKnown (arr, i);
2386 sRef arr = sRef_undump (c);
2387 sRef ret = sRef_buildArrayFetch (arr);
2394 cstring fname = cstring_undefined;
2399 fname = cstring_appendChar (fname, **c);
2404 ret = sRef_buildField (sRef_undump (c), fname);
2405 cstring_markOwned (fname);
2410 int i = reader_getInt (c);
2411 speckind sk = speckind_fromInt (i);
2415 case SR_NOTHING: return (sRef_makeNothing ());
2416 case SR_INTERNAL: return (sRef_makeInternalState ());
2417 case SR_SPECSTATE: return (sRef_makeSpecState ());
2418 case SR_SYSTEM: return (sRef_makeSystemState ());
2419 case SR_GLOBALMARKER: BADBRANCH;
2425 sRef ptr = sRef_undump (c);
2426 sRef ret = sRef_makePointer (ptr);
2432 sRef adr = sRef_undump (c);
2433 sRef ret = sRef_makeAddress (adr);
2439 return (sRef_makeObject (ctype_undump (c)));
2443 sRef s1 = sRef_undump (c);
2444 sRef s2 = ((*c)++, sRef_undump (c));
2445 sRef ret = sRef_makeConj (s1, s2);
2450 return sRef_undefined;
2452 return sRef_makeUnknown ();
2454 return sRef_makeUnknown ();
2456 llfatalerror (message ("sRef_undump: bad line: %s", cstring_fromChars (*c)));
2464 if (sRef_isInvalid (s))
2466 return (cstring_makeLiteral ("-"));
2473 return (message ("p%d", s->info->paramno));
2475 if (s->info->arrayfetch->indknown)
2477 return (message ("a%d%q", s->info->arrayfetch->ind,
2478 sRef_dump (s->info->arrayfetch->arr)));
2482 return (message ("a%q", sRef_dump (s->info->arrayfetch->arr)));
2485 return (message ("f%s.%q", s->info->field->field,
2486 sRef_dump (s->info->field->rec)));
2488 return (message ("t%q", sRef_dump (s->info->ref)));
2490 return (message ("d%q", sRef_dump (s->info->ref)));
2492 return (message ("o%q", ctype_dump (s->info->object)));
2494 return (message ("s%d", (int) s->info->spec));
2496 return (message ("c%q.%q",
2497 sRef_dump (s->info->conj->a),
2498 sRef_dump (s->info->conj->b)));
2500 if (sRef_isFileOrGlobalScope (s))
2502 return (message ("g%d",
2503 usymtab_convertId (s->info->cvar->index)));
2507 llcontbug (message ("Dumping local variable: %q",
2508 sRef_unparseDebug (s)));
2509 return (cstring_makeLiteral ("u"));
2512 return (cstring_makeLiteral ("u"));
2514 return (message ("r%q", ctype_dump (s->type)));
2520 case SK_UNCONSTRAINED:
2521 llcontbug (message ("sRef_dump: bad kind: %q",
2522 sRef_unparseFull (s)));
2523 return (cstring_makeLiteral ("x"));
2530 cstring sRef_dumpGlobal (sRef s)
2532 if (sRef_isInvalid (s))
2534 return (cstring_makeLiteral ("-"));
2541 if (sRef_isFileOrGlobalScope (s))
2543 return (message ("g%d@%d@%d",
2544 usymtab_convertId (s->info->cvar->index),
2546 (int) sRef_getNullState (s)));
2550 llcontbug (message ("Dumping local variable: %q",
2551 sRef_unparseDebug (s)));
2552 return (cstring_makeLiteral ("u"));
2555 return (cstring_makeLiteral ("u"));
2557 return (message ("s%d", (int) s->info->spec));
2559 llcontbug (message ("sRef_dumpGlobal: bad kind: %q",
2560 sRef_unparseFull (s)));
2561 return (cstring_makeLiteral ("x"));
2569 sRef_deriveType (sRef s, uentryList cl)
2571 if (sRef_isInvalid (s)) return ctype_unknown;
2576 return (uentry_getType (usymtab_getRefQuiet (s->info->cvar->lexlevel,
2577 s->info->cvar->index)));
2578 case SK_UNCONSTRAINED:
2579 return (ctype_unknown);
2581 if (s->info->paramno >= 0)
2583 return uentry_getType (uentryList_getN (cl, s->info->paramno));
2587 return ctype_unknown;
2591 ctype ca = sRef_deriveType (s->info->arrayfetch->arr, cl);
2593 if (ctype_isArray (ca))
2595 return (ctype_baseArrayPtr (ca));
2597 else if (ctype_isUnknown (ca))
2603 llcontbuglit ("sRef_deriveType: inconsistent array type");
2609 ctype ct = sRef_deriveType (s->info->field->rec, cl);
2611 if (ctype_isStructorUnion (ct))
2613 uentry ue = uentryList_lookupField (ctype_getFields (ct),
2614 s->info->field->field);
2616 if (uentry_isValid (ue))
2618 return (uentry_getType (ue));
2622 llcontbuglit ("sRef_deriveType: bad field");
2623 return ctype_unknown;
2626 else if (ctype_isUnknown (ct))
2632 llcontbuglit ("sRef_deriveType: inconsistent field type");
2638 ctype ct = sRef_deriveType (s->info->ref, cl);
2640 if (ctype_isUnknown (ct)) return ct;
2641 if (ctype_isPointer (ct)) return (ctype_baseArrayPtr (ct));
2644 llcontbuglit ("sRef_deriveType: inconsistent pointer type");
2650 ctype ct = sRef_deriveType (s->info->ref, cl);
2652 if (ctype_isUnknown (ct)) return ct;
2653 return ctype_makePointer (ct);
2657 return sRef_deriveType (s->info->ref, cl);
2661 return (s->info->object);
2665 return (ctype_makeConj (sRef_deriveType (s->info->conj->a, cl),
2666 sRef_deriveType (s->info->conj->b, cl)));
2678 return ctype_unknown;
2684 sRef_getType (sRef s)
2686 if (sRef_isInvalid (s)) return ctype_unknown;
2692 sRef_unparseOpt (sRef s)
2694 sRef rb = sRef_getRootBase (s);
2696 if (sRef_isMeaningful (rb) && !sRef_isConst (rb))
2698 cstring ret = sRef_unparse (s);
2700 llassertprint (!cstring_equalLit (ret, "?"), ("print: %s", sRef_unparseDebug (s)));
2702 if (!cstring_isEmpty (ret))
2704 return (cstring_appendChar (ret, ' '));
2712 return cstring_undefined;
2716 sRef_unparsePreOpt (sRef s)
2718 sRef rb = sRef_getRootBase (s);
2720 if (sRef_isMeaningful (rb) && !sRef_isConst (rb))
2722 cstring ret = sRef_unparse (s);
2724 llassertprint (!cstring_equalLit (ret, "?"), ("print: %s", sRef_unparseDebug (s)));
2725 return (cstring_prependCharO (' ', ret));
2728 return cstring_undefined;
2732 sRef_unparse (sRef s)
2734 if (sRef_isInvalid (s)) return (cstring_makeLiteral ("?"));
2736 if (context_inFunctionLike ())
2738 return (sRef_unparseWithArgs (s, context_getParams ()));
2742 DPRINTF (("Not in function like: %s", context_unparse ()));
2743 return (sRef_unparseNoArgs (s));
2747 static /*@only@*/ cstring
2748 sRef_unparseWithArgs (sRef s, uentryList args)
2750 if (sRef_isInvalid (s))
2752 return (cstring_makeLiteral ("?"));
2758 return (uentry_getName (usymtab_getRefQuiet (s->info->cvar->lexlevel,
2759 s->info->cvar->index)));
2760 case SK_UNCONSTRAINED:
2761 return (cstring_copy (s->info->fname));
2764 if (s->info->paramno < uentryList_size (args)
2765 && s->info->paramno >= 0)
2767 uentry ue = uentryList_getN (args, s->info->paramno);
2769 if (uentry_isValid (ue))
2770 return uentry_getName (ue);
2773 return (message ("<bad param: %q / args %q",
2774 sRef_unparseDebug (s),
2775 uentryList_unparse (args)));
2778 if (s->info->arrayfetch->indknown)
2780 return (message ("%q[%d]", sRef_unparseWithArgs (s->info->arrayfetch->arr, args),
2781 s->info->arrayfetch->ind));
2785 return (message ("%q[]", sRef_unparseWithArgs (s->info->arrayfetch->arr, args)));
2788 if (s->info->field->rec->kind == SK_PTR)
2790 sRef ptr = s->info->field->rec;
2792 return (message ("%q->%s", sRef_unparseWithArgs (ptr->info->ref, args),
2793 s->info->field->field));
2795 return (message ("%q.%s", sRef_unparseWithArgs (s->info->field->rec, args),
2796 s->info->field->field));
2800 sRef ref = sRef_fixConj (s->info->ref);
2801 skind sk = ref->kind;
2806 ret = message ("storage pointed to by %q",
2807 sRef_unparseWithArgs (ref, args));
2809 else if (skind_isSimple (sk) || sk == SK_PTR)
2811 ret = message ("*%q", sRef_unparseWithArgs (ref, args));
2815 ret = message ("*(%q)", sRef_unparseWithArgs (ref, args));
2821 return (message ("&%q", sRef_unparseWithArgs (s->info->ref, args)));
2823 return (cstring_copy (ctype_unparse (s->info->object)));
2825 return (sRef_unparseWithArgs (sRef_getConjA (s), args));
2827 if (cstring_isDefined (s->info->fname))
2829 return (message ("[result of %s]", s->info->fname));
2833 return (cstring_makeLiteral ("<new>"));
2836 return (cstring_makeLiteral ("?"));
2838 return (message ("<derived %q>", sRef_unparse (s->info->ref)));
2840 return (message ("<external %q>", sRef_unparse (s->info->ref)));
2842 return (message ("<type %s>", ctype_unparse (s->type)));
2844 return (message ("<const %s>", ctype_unparse (s->type)));
2846 switch (s->info->spec)
2848 case SR_NOTHING: return cstring_makeLiteral ("nothing");
2849 case SR_INTERNAL: return cstring_makeLiteral ("internal state");
2850 case SR_SPECSTATE: return cstring_makeLiteral ("spec state");
2851 case SR_SYSTEM: return cstring_makeLiteral ("file system state");
2852 case SR_GLOBALMARKER: return cstring_makeLiteral ("<global marker>");
2856 return cstring_makeLiteral ("result");
2859 llbug (message ("Bad sref, kind = %d", (int) s->kind));
2867 sRef_unparseDebug (sRef s)
2869 if (sRef_isInvalid (s))
2871 return (cstring_makeLiteral ("<undef>"));
2877 case SK_UNCONSTRAINED:
2878 return (message ("<unconstrained %s>", s->info->fname));
2883 ce = usymtab_getRefQuiet (s->info->cvar->lexlevel, s->info->cvar->index);
2885 if (uentry_isInvalid (ce))
2887 return (message ("<scope: %d.%d *invalid*>",
2888 s->info->cvar->lexlevel,
2889 s->info->cvar->index));
2893 return (message ("<scope: %d.%d *%q*>",
2894 s->info->cvar->lexlevel,
2895 s->info->cvar->index,
2896 uentry_getName (ce)));
2902 return (message ("<parameter %d>", s->info->paramno + 1));
2905 if (s->info->arrayfetch->indknown)
2907 return (message ("%q[%d]", sRef_unparseDebug (s->info->arrayfetch->arr),
2908 s->info->arrayfetch->ind));
2912 return (message ("%q[]", sRef_unparseDebug (s->info->arrayfetch->arr)));
2915 return (message ("%q.%s", sRef_unparseDebug (s->info->field->rec),
2916 s->info->field->field));
2918 if (sRef_isField (s->info->ref))
2920 sRef fld = s->info->ref;
2922 return (message ("%q->%s", sRef_unparseDebug (fld->info->field->rec),
2923 fld->info->field->field));
2927 return (message ("*(%q)", sRef_unparseDebug (s->info->ref)));
2930 return (message ("&%q", sRef_unparseDebug (s->info->ref)));
2932 return (message ("<object type %s>", ctype_unparse (s->info->object)));
2934 return (message ("%q | %q", sRef_unparseDebug (s->info->conj->a),
2935 sRef_unparseDebug (s->info->conj->b)));
2937 return message ("<new: %s>", s->info->fname);
2939 return (message ("<derived %q>", sRef_unparseDebug (s->info->ref)));
2941 return (message ("<external %q>", sRef_unparseDebug (s->info->ref)));
2943 return (message ("<type %s>", ctype_unparse (s->type)));
2945 return (message ("<const %s>", ctype_unparse (s->type)));
2947 return (message ("<result %s>", ctype_unparse (s->type)));
2949 return (message ("<spec %s>",
2950 cstring_makeLiteralTemp
2951 (s->info->spec == SR_NOTHING ? "nothing"
2952 : s->info->spec == SR_INTERNAL ? "internalState"
2953 : s->info->spec == SR_SPECSTATE ? "spec state"
2954 : s->info->spec == SR_SYSTEM ? "fileSystem"
2957 return cstring_makeLiteral ("<unknown>");
2963 static /*@only@*/ cstring
2964 sRef_unparseNoArgs (sRef s)
2966 if (sRef_isInvalid (s)) return (cstring_makeLiteral ("?"));
2970 case SK_UNCONSTRAINED:
2971 return (cstring_copy (s->info->fname));
2974 uentry ce = usymtab_getRefQuiet (s->info->cvar->lexlevel,
2975 s->info->cvar->index);
2977 if (uentry_isInvalid (ce))
2979 llcontbug (message ("sRef_unparseNoArgs: bad cvar: %q",
2980 sRef_unparseDebug (s)));
2981 return (sRef_unparseDebug (s));
2985 return (uentry_getName (ce));
2989 if (s->info->arrayfetch->indknown)
2991 return (message ("%q[%d]", sRef_unparseNoArgs (s->info->arrayfetch->arr),
2992 s->info->arrayfetch->ind));
2996 return (message ("%q[]", sRef_unparseNoArgs (s->info->arrayfetch->arr)));
2999 return (message ("%q.%s", sRef_unparseNoArgs (s->info->field->rec),
3000 s->info->field->field));
3003 sRef ref = sRef_fixConj (s->info->ref);
3004 skind sk = ref->kind;
3007 if (skind_isSimple (sk) || sk == SK_PTR)
3009 ret = message ("*%q", sRef_unparseNoArgs (ref));
3013 ret = message ("*(%q)", sRef_unparseNoArgs (ref));
3019 return (message ("&%q", sRef_unparseNoArgs (s->info->ref)));
3021 return (cstring_copy (ctype_unparse (s->info->object)));
3023 return (sRef_unparseNoArgs (s->info->conj->a));
3025 return (message ("result of %s", s->info->fname));
3027 return (message ("<der %q>", sRef_unparseNoArgs (s->info->ref)));
3029 return message ("<ext %q>", sRef_unparseNoArgs (s->info->ref));
3031 return (cstring_makeLiteral
3032 (s->info->spec == SR_NOTHING ? "nothing"
3033 : s->info->spec == SR_INTERNAL ? "internal state"
3034 : s->info->spec == SR_SPECSTATE ? "spec state"
3035 : s->info->spec == SR_SYSTEM ? "file system state"
3038 return cstring_makeLiteral ("result");
3042 return cstring_makeLiteral ("?");
3044 /* llcontbug (message ("sRef_unparseNoArgs: bad case: %q", sRef_unparseDebug (s))); */
3045 return (sRef_unparseDebug (s));
3050 /*@dependent@*/ sRef sRef_makeUnconstrained (cstring fname)
3052 sRef s = sRef_new ();
3054 s->kind = SK_UNCONSTRAINED;
3055 s->info = (sinfo) dmalloc (sizeof (*s->info));
3056 s->info->fname = fname;
3061 cstring sRef_unconstrainedName (sRef s)
3063 llassert (sRef_isUnconstrained (s));
3065 return s->info->fname;
3068 bool sRef_isUnconstrained (sRef s)
3070 return (sRef_isValid(s) && s->kind == SK_UNCONSTRAINED);
3073 static /*@dependent@*/ /*@notnull@*/ sRef
3074 sRef_makeCvarAux (int level, usymId index, ctype ct)
3076 sRef s = sRef_newRef ();
3079 s->info = (sinfo) dmalloc (sizeof (*s->info));
3081 s->info->cvar = (cref) dmalloc (sizeof (*s->info->cvar));
3082 s->info->cvar->lexlevel = level;
3083 s->info->cvar->index = index;
3085 /* for now, all globals are defined; all locals, aren't */
3087 if (level <= fileScope)
3089 s->defstate = SS_UNKNOWN;
3093 ctype rct = ctype_realType (ct);
3095 if (level != paramsScope
3096 && (ctype_isStructorUnion (rct) || ctype_isRealArray (rct)))
3098 s->defstate = SS_ALLOCATED;
3099 s->oaliaskind = s->aliaskind = AK_STACK;
3103 s->defstate = SS_UNDEFINED;
3104 s->oaliaskind = s->aliaskind = AK_LOCAL;
3110 llassert (level >= globScope);
3111 llassert (usymId_isValid (index));
3113 DPRINTF (("Made cvar: [%p] %s", s, sRef_unparseDebug (s)));
3114 llassert (valueTable_isUndefined (s->state));
3115 s->state = context_createValueTable (s);
3119 /*@dependent@*/ sRef sRef_makeCvar (int level, usymId index, ctype ct)
3121 return (sRef_makeCvarAux (level, index, ct));
3124 int sRef_lexLevel (sRef s)
3126 if (sRef_isValid (s))
3130 conj = sRef_fixConj (s);
3131 s = sRef_getRootBase (conj);
3133 if (sRef_isValid (s) && s->kind == SK_CVAR)
3135 return (s->info->cvar->lexlevel);
3143 sRef_makeGlobal (usymId l, ctype ct)
3145 return (sRef_makeCvar (globScope, l, ct));
3149 sRef_setParamNo (sRef s, int l)
3151 llassert (sRef_isValid (s) && s->kind == SK_PARAM);
3152 s->info->paramno = l;
3156 /*@dependent@*/ sRef
3157 sRef_makeParam (int l, ctype ct)
3159 sRef s = sRef_new ();
3164 s->info = (sinfo) dmalloc (sizeof (*s->info));
3165 s->info->paramno = l;
3167 s->defstate = SS_UNKNOWN;
3168 /* (probably defined, unless its an out parameter) */
3170 llassert (valueTable_isUndefined (s->state));
3171 s->state = context_createValueTable (s);
3176 sRef_isIndexKnown (sRef arr)
3180 llassert (sRef_isValid (arr));
3181 arr = sRef_fixConj (arr);
3183 llassert (arr->kind == SK_ARRAYFETCH);
3184 res = arr->info->arrayfetch->indknown;
3189 sRef_getIndex (sRef arr)
3193 llassert (sRef_isValid (arr));
3194 arr = sRef_fixConj (arr);
3196 llassert (arr->kind == SK_ARRAYFETCH);
3198 if (!arr->info->arrayfetch->indknown)
3200 llcontbug (message ("sRef_getIndex: unknown: %q", sRef_unparse (arr)));
3205 result = arr->info->arrayfetch->ind;
3211 static bool sRef_isZerothArrayFetch (/*@notnull@*/ sRef s)
3213 return (s->kind == SK_ARRAYFETCH
3214 && s->info->arrayfetch->indknown
3215 && (s->info->arrayfetch->ind == 0));
3218 /*@exposed@*/ sRef sRef_makeAddress (/*@exposed@*/ sRef t)
3221 if (sRef_isInvalid (t)) return sRef_undefined;
3223 if (sRef_isPointer (t))
3225 return (t->info->ref);
3227 else if (sRef_isZerothArrayFetch (t))
3229 return (t->info->arrayfetch->arr);
3233 sRef s = sRef_newRef ();
3236 s->type = ctype_makePointer (t->type);
3237 s->info = (sinfo) dmalloc (sizeof (*s->info));
3238 s->info->ref = t; /* sRef_copy (t); */ /*@i32@*/
3240 if (t->defstate == SS_UNDEFINED)
3241 /* no! it is allocated even still: && !ctype_isPointer (t->type)) */
3243 s->defstate = SS_ALLOCATED;
3247 s->defstate = t->defstate;
3250 if (t->aliaskind == AK_LOCAL)
3252 if (sRef_isLocalVar (t))
3254 s->aliaskind = AK_STACK;
3258 llassert (valueTable_isUndefined (s->state));
3259 s->state = context_createValueTable (s);
3264 cstring sRef_getField (sRef s)
3268 llassert (sRef_isValid (s));
3269 s = sRef_fixConj (s);
3271 llassertprint (sRef_isValid (s) && (s->kind == SK_FIELD),
3272 ("s = %s", sRef_unparseDebug (s)));
3274 res = s->info->field->field;
3278 sRef sRef_getBase (sRef s)
3282 if (sRef_isInvalid (s)) return (sRef_undefined);
3284 s = sRef_fixConj (s);
3295 res = s->info->field->rec;
3299 res = s->info->arrayfetch->arr;
3303 res = sRef_undefined; /* shouldn't need it */
3310 ** same as getBase, except returns invalid
3311 ** (and doesn't use adr's)
3315 sRef_getBaseSafe (sRef s)
3319 if (sRef_isInvalid (s)) { return sRef_undefined; }
3321 s = sRef_fixConj (s);
3329 res = s->info->field->rec; break;
3331 res = s->info->arrayfetch->arr;
3334 res = sRef_undefined; break;
3340 /*@constant int MAXBASEDEPTH;@*/
3341 # define MAXBASEDEPTH 25
3343 static /*@exposed@*/ sRef
3344 sRef_getRootBaseAux (sRef s, int depth)
3346 if (sRef_isInvalid (s)) return sRef_undefined;
3348 if (depth > MAXBASEDEPTH)
3351 ("Warning: reference base limit exceeded for %q. "
3352 "This either means there is a variable with at least "
3353 "%d indirections from this reference, or "
3354 "there is a bug in LCLint.",
3359 return sRef_undefined;
3366 return (sRef_getRootBaseAux (s->info->ref, depth + 1));
3368 return (sRef_getRootBaseAux (s->info->field->rec, depth + 1));
3370 return (sRef_getRootBaseAux (s->info->arrayfetch->arr, depth + 1));
3372 return (sRef_getRootBaseAux (sRef_fixConj (s), depth + 1));
3378 sRef sRef_getRootBase (sRef s)
3380 return (sRef_getRootBaseAux (s, 0));
3383 static bool sRef_isDeep (sRef s)
3385 if (sRef_isInvalid (s)) return FALSE;
3395 return (sRef_isDeep (sRef_fixConj (s)));
3401 static int sRef_depth (sRef s)
3403 if (sRef_isInvalid (s)) return 0;
3411 return 1 + sRef_depth (s->info->ref);
3413 return 1 + sRef_depth (s->info->field->rec);
3415 return 1 + sRef_depth (s->info->arrayfetch->arr);
3417 return (sRef_depth (sRef_fixConj (s)));
3424 sRef_makeObject (ctype o)
3426 sRef s = sRef_newRef (); /*@i423 same line is bad...@*/
3428 s->kind = SK_OBJECT;
3429 s->info = (sinfo) dmalloc (sizeof (*s->info));
3430 s->info->object = o;
3431 llassert (valueTable_isUndefined (s->state));
3432 s->state = context_createValueTable (s);
3437 ** This is used to represent storage referenced by a parameter.
3440 sRef sRef_makeExternal (sRef t)
3442 sRef s = sRef_newRef ();
3444 llassert (sRef_isValid (t));
3446 s->kind = SK_EXTERNAL;
3447 s->info = (sinfo) dmalloc (sizeof (*s->info));
3449 s->info->ref = t; /* sRef_copy (t); */ /*@i32 was exposed@*/
3450 llassert (valueTable_isUndefined (s->state));
3451 s->state = context_createValueTable (s);
3455 /*@dependent@*/ sRef sRef_makeDerived (/*@exposed@*/ sRef t)
3457 if (sRef_isValid (t))
3459 sRef s = sRef_newRef ();
3461 s->kind = SK_DERIVED;
3462 s->info = (sinfo) dmalloc (sizeof (*s->info));
3463 s->info->ref = t; /* sRef_copy (t); */ /*@i32@*/
3466 llassert (valueTable_isUndefined (s->state));
3467 s->state = context_createValueTable (s);
3472 return sRef_undefined;
3477 ** definitely NOT symmetric:
3479 ** res fills in unknown state information from other
3483 sRef_mergeStateQuiet (sRef res, sRef other)
3485 llassert (sRef_isValid (res));
3486 llassert (sRef_isValid (other));
3488 res->modified = res->modified || other->modified;
3489 res->safe = res->safe && other->safe;
3491 if (res->defstate == SS_UNKNOWN)
3493 res->defstate = other->defstate;
3494 res->definfo = stateInfo_update (res->definfo, other->definfo);
3497 if (res->aliaskind == AK_UNKNOWN ||
3498 (res->aliaskind == AK_LOCAL && alkind_isKnown (other->aliaskind)))
3500 res->aliaskind = other->aliaskind;
3501 res->oaliaskind = other->oaliaskind;
3502 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
3505 if (res->expkind == XO_UNKNOWN)
3507 res->expkind = other->expkind;
3508 res->oexpkind = other->oexpkind;
3509 res->expinfo = stateInfo_update (res->expinfo, other->expinfo);
3512 /* out takes precedence over implicitly defined */
3513 if (res->defstate == SS_DEFINED && other->defstate != SS_UNKNOWN)
3515 res->defstate = other->defstate;
3516 res->definfo = stateInfo_update (res->definfo, other->definfo);
3519 if (sRef_getNullState (other) == NS_ERROR || sRef_getNullState (res) == NS_ERROR)
3521 sRef_setNullState (res, NS_ERROR, fileloc_undefined);
3525 if (sRef_getNullState (other) != NS_UNKNOWN
3526 && (sRef_getNullState (res) == NS_UNKNOWN || sRef_getNullState (res) == NS_NOTNULL
3527 || sRef_getNullState (res) == NS_MNOTNULL))
3529 sRef_updateNullState (res, other);
3535 ** definitely NOT symmetric:
3537 ** res fills in known state information from other
3541 sRef_mergeStateQuietReverse (/*@dependent@*/ sRef res, /*@dependent@*/ sRef other)
3543 bool changed = FALSE;
3545 llassert (sRef_isValid (res));
3546 llassert (sRef_isValid (other));
3547 sRef_checkMutable (res);
3549 if (res->kind != other->kind)
3555 res->kind = other->kind;
3556 res->type = other->type;
3557 res->info = sinfo_fullCopy (other);
3561 if (!ctype_equal (res->type, other->type))
3564 res->type = other->type;
3567 sinfo_update (res, other);
3570 res->modified = res->modified || other->modified;
3571 res->safe = res->safe && other->safe;
3573 if (res->aliaskind != other->aliaskind
3574 && (res->aliaskind == AK_UNKNOWN
3575 || ((res->aliaskind == AK_LOCAL
3576 || (res->aliaskind == AK_REFCOUNTED
3577 && other->aliaskind != AK_LOCAL))
3578 && other->aliaskind != AK_UNKNOWN)))
3581 res->aliaskind = other->aliaskind;
3582 res->oaliaskind = other->oaliaskind;
3583 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
3586 if (other->expkind != XO_UNKNOWN && other->expkind != res->expkind)
3589 res->expkind = other->expkind;
3590 res->expinfo = stateInfo_update (res->expinfo, other->expinfo);
3593 if (other->oexpkind != XO_UNKNOWN)
3595 res->oexpkind = other->oexpkind;
3598 /* out takes precedence over implicitly defined */
3600 if (res->defstate != other->defstate)
3602 if (other->defstate != SS_UNKNOWN)
3604 res->defstate = other->defstate;
3608 if (sRef_getNullState (other) == NS_ERROR || sRef_getNullState (res) == NS_ERROR)
3610 if (sRef_getNullState (res) != NS_ERROR)
3612 sRef_setNullStateN (res, NS_ERROR);
3618 if (sRef_getNullState (other) != NS_UNKNOWN && sRef_getNullState (other) != sRef_getNullState (res))
3621 sRef_updateNullState (res, other);
3627 sRef_clearDerived (res);
3632 sRef_mergeState (sRef res, sRef other, clause cl, fileloc loc)
3634 if (sRef_isValid (res) && sRef_isValid (other))
3636 sRef_mergeStateAux (res, other, cl, FALSE, loc, TRUE);
3640 if (sRef_isInvalid (res))
3642 llbug (message ("sRef_mergeState: invalid res sRef: %q",
3643 sRef_unparseDebug (other)));
3647 llbug (message ("sRef_mergeState: invalid other sRef: %q",
3648 sRef_unparseDebug (res)));
3654 sRef_mergeOptState (sRef res, sRef other, clause cl, fileloc loc)
3656 if (sRef_isValid (res) && sRef_isValid (other))
3658 sRef_mergeStateAux (res, other, cl, TRUE, loc, TRUE);
3662 if (sRef_isInvalid (res))
3664 llbug (message ("sRef_mergeOptState: invalid res sRef: %q",
3665 sRef_unparseDebug (other)));
3669 llbug (message ("sRef_mergeOptState: invalid other sRef: %q",
3670 sRef_unparseDebug (res)));
3676 sRef_mergeStateAux (/*@notnull@*/ sRef res, /*@notnull@*/ sRef other,
3677 clause cl, bool opt, fileloc loc,
3681 llassertfatal (sRef_isValid (res));
3682 llassertfatal (sRef_isValid (other));
3684 sRef_checkMutable (res);
3685 sRef_checkMutable (other);
3687 res->modified = res->modified || other->modified;
3689 if (res->kind == other->kind
3690 || (other->kind == SK_UNKNOWN || res->kind == SK_UNKNOWN))
3692 sstate odef = other->defstate;
3693 sstate rdef = res->defstate;
3694 nstate onull = sRef_getNullState (other);
3697 ** yucky stuff to handle
3702 if (other->defstate == SS_DEAD
3703 && ((sRef_isOnly (res) && sRef_definitelyNull (res))
3704 || (res->defstate == SS_UNDEFINED
3705 || res->defstate == SS_UNUSEABLE)))
3707 if (res->defstate == SS_UNDEFINED
3708 || res->defstate == SS_UNUSEABLE)
3710 res->defstate = SS_UNUSEABLE;
3714 res->defstate = SS_DEAD;
3717 res->definfo = stateInfo_update (res->definfo, other->definfo);
3718 sRef_clearDerived (other);
3719 sRef_clearDerived (res);
3721 else if (res->defstate == SS_DEAD
3722 && ((sRef_isOnly (other) && sRef_definitelyNull (other))
3723 || (other->defstate == SS_UNDEFINED
3724 || other->defstate == SS_UNUSEABLE)))
3726 if (other->defstate == SS_UNDEFINED
3727 || other->defstate == SS_UNUSEABLE)
3729 res->defstate = SS_UNUSEABLE;
3733 res->defstate = SS_DEAD;
3736 sRef_clearDerived (other);
3737 sRef_clearDerived (res);
3739 else if (res->defstate == SS_DEFINED
3740 && (other->defstate == SS_ALLOCATED
3741 && sRef_definitelyNull (other)))
3743 other->defstate = SS_DEFINED; /* definitely null! */
3745 else if (other->defstate == SS_DEFINED
3746 && (res->defstate == SS_ALLOCATED && sRef_definitelyNull (res)))
3748 res->defstate = SS_DEFINED;
3749 res->definfo = stateInfo_update (res->definfo, other->definfo);
3756 if (res->defstate == SS_DEAD && other->defstate == SS_DEAD)
3758 sRef_clearDerived (other);
3759 sRef_clearDerived (res);
3763 ** only & dead isn't really an only!
3766 if (alkind_isOnly (other->aliaskind) && other->defstate == SS_DEAD)
3768 other->aliaskind = AK_UNKNOWN;
3771 if (alkind_isOnly (res->aliaskind) && res->defstate == SS_DEAD)
3773 res->aliaskind = AK_UNKNOWN;
3777 ** Dead and dependent -> dead
3780 if (alkind_isDependent (other->aliaskind) && res->defstate == SS_DEAD)
3782 other->aliaskind = AK_UNKNOWN;
3783 other->defstate = SS_DEAD;
3784 sRef_clearDerived (res);
3785 sRef_clearDerived (other);
3788 if (alkind_isDependent (res->aliaskind) && other->defstate == SS_DEAD)
3790 res->aliaskind = AK_UNKNOWN;
3791 res->defstate = SS_DEAD;
3792 sRef_clearDerived (res);
3793 sRef_clearDerived (other);
3797 ** must do alias combine first, since it depends on
3798 ** original values of state and null.
3801 sRef_combineAliasKinds (res, other, cl, loc);
3802 sRef_combineDefState (res, other);
3803 sRef_combineNullState (res, other);
3805 if (rdef == SS_ALLOCATED || rdef == SS_SPECIAL)
3807 if (odef == SS_DEFINED)
3809 if (onull == NS_DEFNULL || onull == NS_CONSTNULL)
3811 res->deriv = sRefSet_copyInto (res->deriv, other->deriv);
3812 DPRINTF (("Copy derivs: %s", sRef_unparseFull (res)));
3815 else if (odef == SS_ALLOCATED || odef == SS_SPECIAL)
3820 if (ctype_isUnion (ctype_realType (sRef_getType (res))))
3822 res->deriv = sRef_mergeUnionDerivs (res->deriv,
3825 DPRINTF (("Copy derivs: %s", sRef_unparseFull (res)));
3829 res->deriv = sRef_mergeDerivs (res->deriv, other->deriv,
3831 DPRINTF (("Copy derivs: %s", sRef_unparseFull (res)));
3839 res->deriv = sRef_mergeDerivs (res->deriv, other->deriv,
3841 DPRINTF (("Copy derivs: %s", sRef_unparseFull (res)));
3851 if (rdef == SS_PDEFINED
3852 || (rdef == SS_DEFINED && odef == SS_PDEFINED))
3856 res->deriv = sRef_mergePdefinedDerivs (res->deriv, other->deriv,
3858 DPRINTF (("Copy derivs: %s", sRef_unparseFull (res)));
3863 if ((rdef == SS_DEFINED || rdef == SS_UNKNOWN)
3864 && res->defstate == SS_ALLOCATED)
3866 res->deriv = sRefSet_copyInto (res->deriv, other->deriv);
3872 res->deriv = sRef_mergeDerivs (res->deriv, other->deriv,
3874 DPRINTF (("Copy derivs: %s", sRef_unparseFull (res)));
3881 sRef_combineExKinds (res, other);
3885 if (res->kind == SK_ARRAYFETCH && other->kind == SK_PTR)
3887 sRef nother = sRef_buildArrayFetchKnown (sRef_getBase (other), 0);
3889 sRef_copyState (nother, other);
3890 sRef_mergeStateAux (res, nother, cl, opt, loc, doDerivs);
3892 else if (res->kind == SK_PTR && other->kind == SK_ARRAYFETCH)
3894 sRef nother = sRef_buildPointer (sRef_getBase (other));
3896 if (sRef_isValid (nother))
3898 sRef_copyState (nother, other);
3899 sRef_mergeStateAux (res, nother, cl, opt, loc, doDerivs);
3904 llcontbug (message ("merge conj: %q / %q", sRef_unparseFull (res),
3905 sRef_unparseFull (other)));
3911 ** Merge value table states
3918 ** This doesn't do anything. And its broken too...
3921 valueTable_elements (res->state, key, sv)
3923 stateValue os = valueTable_lookup (other->state, key);
3924 /*@unused@*/ int val;
3925 /*@unused@*/ char *msg;
3927 llassert (stateValue_isDefined (os));
3929 DPRINTF (("Merge state: %s / %s",
3930 cstring_toCharsSafe (stateValue_unparse (sv)),
3931 cstring_toCharsSafe (stateValue_unparse (os))));
3933 val = valueMatix_lookup (key,
3934 stateValue_getValue (os),
3935 stateValue_getValue (sv),
3937 DPRINTF (("Val: %d / %s", val, msg));
3939 } end_valueTable_elements ;
3945 sRef_mergeUnionDerivs (/*@only@*/ sRefSet res,
3946 /*@exposed@*/ sRefSet other, bool opt,
3947 clause cl, fileloc loc)
3949 if (sRefSet_isEmpty (res))
3951 return sRefSet_copyInto (res, other);
3955 sRefSet_allElements (other, el)
3957 if (sRef_isValid (el))
3959 sRef e2 = sRefSet_lookupMember (other, el);
3961 if (sRef_isValid (e2))
3963 sRef_mergeStateAux (el, e2, cl, opt, loc, FALSE);
3967 res = sRefSet_insert (res, el);
3970 } end_sRefSet_allElements ;
3976 static /*@only@*/ sRefSet
3977 sRef_mergeDerivs (/*@only@*/ sRefSet res, sRefSet other,
3978 bool opt, clause cl, fileloc loc)
3980 sRefSet ret = sRefSet_new ();
3982 sRefSet_allElements (res, el)
3984 if (sRef_isValid (el))
3986 sRef e2 = sRefSet_lookupMember (other, el);
3988 if (sRef_isValid (e2))
3990 if (el->defstate == SS_ALLOCATED &&
3991 e2->defstate == SS_PDEFINED)
3993 e2->defstate = SS_ALLOCATED;
3995 else if (e2->defstate == SS_ALLOCATED &&
3996 el->defstate == SS_PDEFINED)
3998 el->defstate = SS_ALLOCATED;
3999 sRef_clearDerived (el);
4001 else if ((el->defstate == SS_DEAD || sRef_isKept (el)) &&
4002 (e2->defstate == SS_DEFINED && !sRef_isKept (e2)))
4005 if (checkDeadState (el, TRUE, loc))
4007 if (sRef_isThroughArrayFetch (el))
4009 sRef_maybeKill (el, loc);
4010 sRef_maybeKill (e2, loc);
4014 else if ((e2->defstate == SS_DEAD || sRef_isKept (e2)) &&
4015 (el->defstate == SS_DEFINED && !sRef_isKept (el)))
4018 if (checkDeadState (e2, FALSE, loc))
4020 if (sRef_isThroughArrayFetch (el))
4022 sRef_maybeKill (el, loc);
4023 sRef_maybeKill (e2, loc);
4027 else if (el->defstate == SS_DEFINED &&
4028 e2->defstate == SS_PDEFINED)
4030 DPRINTF (("set pdefined: %s", sRef_unparseFull (el)));
4031 el->defstate = SS_PDEFINED;
4033 else if (e2->defstate == SS_DEFINED &&
4034 el->defstate == SS_PDEFINED)
4036 DPRINTF (("set pdefined: %s", sRef_unparseFull (e2)));
4037 e2->defstate = SS_PDEFINED;
4044 if (ctype_isUnion (ctype_realType (sRef_getType (el))))
4046 el->deriv = sRef_mergeUnionDerivs (el->deriv, e2->deriv,
4051 el->deriv = sRef_mergeDerivs (el->deriv, e2->deriv, opt, cl, loc);
4054 if (sRef_equivalent (el, e2))
4056 ret = sRefSet_insert (ret, el);
4060 sRef sr = sRef_leastCommon (el, e2);
4062 if (sRef_isValid (sr))
4064 ret = sRefSet_insert (ret, sr);
4072 (void) sRefSet_delete (other, e2);
4074 else /* not defined */
4076 (void) checkDeadState (el, TRUE, loc);
4079 } end_sRefSet_allElements;
4081 sRefSet_allElements (other, el)
4083 if (sRef_isValid (el))
4085 (void) checkDeadState (el, FALSE, loc);
4087 } end_sRefSet_allElements;
4094 ** Returns TRUE is there is an error.
4097 static bool checkDeadState (/*@notnull@*/ sRef el, bool tbranch, fileloc loc)
4100 ** usymtab_isGuarded --- the utab should still be in the
4101 ** state of the alternate branch.
4103 ** tbranch TRUE means el is released in the last branch, e.g.
4104 ** if (x != NULL) { ; } else { sfree (x); }
4105 ** so, if x is null in the other branch no error is reported.
4107 ** tbranch FALSE means this is the other branch:
4108 ** if (x != NULL) { sfree (x); } else { ; }
4109 ** so, if x is null in this branch there is no error.
4113 if ((sRef_isDead (el) || sRef_isKept (el))
4114 && !sRef_isDeepUnionField (el) && !sRef_isThroughArrayFetch (el))
4119 if (usymtab_isDefinitelyNullDeep (el))
4126 if (usymtab_isAltDefinitelyNullDeep (el))
4134 message ("Storage %q is %q in one path, but live in another.",
4136 cstring_makeLiteral (sRef_isKept (el)
4137 ? "kept" : "released")),
4141 if (sRef_isKept (el))
4143 sRef_showAliasInfo (el);
4147 sRef_showStateInfo (el);
4150 /* prevent further errors */
4151 el->defstate = SS_UNKNOWN;
4152 sRef_setAliasKind (el, AK_ERROR, fileloc_undefined);
4162 checkDerivDeadState (/*@notnull@*/ sRef el, bool tbranch, fileloc loc)
4165 if (checkDeadState (el, tbranch, loc))
4167 sRefSet_allElements (el->deriv, t)
4169 if (sRef_isValid (t))
4171 checkDerivDeadState (t, tbranch, loc);
4173 } end_sRefSet_allElements;
4178 sRef_mergePdefinedDerivs (sRefSet res, sRefSet other, bool opt,
4179 clause cl, fileloc loc)
4181 sRefSet ret = sRefSet_new ();
4183 sRefSet_allElements (res, el)
4185 if (sRef_isValid (el))
4187 sRef e2 = sRefSet_lookupMember (other, el);
4189 if (sRef_isValid (e2))
4191 if (sRef_isAllocated (el) && !sRef_isAllocated (e2))
4195 else if (sRef_isAllocated (e2) && !sRef_isAllocated (el))
4197 el->deriv = sRefSet_copyInto (el->deriv, e2->deriv);
4201 el->deriv = sRef_mergePdefinedDerivs (el->deriv, e2->deriv,
4205 sRef_mergeStateAux (el, e2, cl, opt, loc, FALSE);
4207 ret = sRefSet_insert (ret, el);
4208 (void) sRefSet_delete (other, e2);
4214 checkDerivDeadState (el, (cl == FALSECLAUSE), loc);
4217 ret = sRefSet_insert (ret, el);
4220 } end_sRefSet_allElements;
4222 sRefSet_allElements (other, el)
4224 if (sRef_isValid (el))
4226 if (!sRefSet_member (ret, el))
4228 /* was cl == FALSECLAUSE */
4229 checkDerivDeadState (el, FALSE, loc);
4230 ret = sRefSet_insert (ret, el);
4235 ** it's okay --- member is a different equality test
4239 } end_sRefSet_allElements;
4245 sRef sRef_makeConj (/*@exposed@*/ /*@returned@*/ sRef a, /*@exposed@*/ sRef b)
4247 llassert (sRef_isValid (a));
4248 llassert (sRef_isValid (b));
4250 if (!sRef_equivalent (a, b))
4252 sRef s = sRef_newRef ();
4255 s->info = (sinfo) dmalloc (sizeof (*s->info));
4256 s->info->conj = (cjinfo) dmalloc (sizeof (*s->info->conj));
4257 s->info->conj->a = a; /* sRef_copy (a) */ /*@i32*/ ;
4258 s->info->conj->b = b; /* sRef_copy (b);*/ /*@i32@*/ ;
4260 if (ctype_equal (a->type, b->type)) s->type = a->type;
4261 else s->type = ctype_makeConj (a->type, b->type);
4263 if (a->defstate == b->defstate)
4265 s->defstate = a->defstate;
4269 s->defstate = SS_UNKNOWN;
4272 sRef_setNullStateN (s, NS_UNKNOWN);
4274 s->safe = a->safe && b->safe;
4275 s->aliaskind = alkind_resolve (a->aliaskind, b->aliaskind);
4277 llassert (valueTable_isUndefined (s->state));
4278 s->state = context_createValueTable (s);
4283 /*@-exposetrans@*/ return a; /*@=exposetrans@*/
4287 /*@dependent@*/ sRef
4290 sRef s = sRef_new ();
4292 s->kind = SK_UNKNOWN;
4296 static /*@owned@*/ sRef
4297 sRef_makeSpecial (speckind sk) /*@*/
4299 sRef s = sRef_new ();
4301 s->kind = SK_SPECIAL;
4302 s->info = (sinfo) dmalloc (sizeof (*s->info));
4304 /*@-dependenttrans@*/
4306 /*@=dependenttrans@*/
4309 static /*@owned@*/ sRef srnothing = sRef_undefined;
4310 static /*@owned@*/ sRef srinternal = sRef_undefined;
4311 static /*@owned@*/ sRef srsystem = sRef_undefined;
4312 static /*@owned@*/ sRef srspec = sRef_undefined;
4314 /*@dependent@*/ sRef
4315 sRef_makeNothing (void)
4317 if (sRef_isInvalid (srnothing))
4319 srnothing = sRef_makeSpecial (SR_NOTHING);
4326 sRef_makeInternalState (void)
4328 if (sRef_isInvalid (srinternal))
4330 srinternal = sRef_makeSpecial (SR_INTERNAL);
4337 sRef_makeSpecState (void)
4339 if (sRef_isInvalid (srspec))
4341 srspec = sRef_makeSpecial (SR_SPECSTATE);
4348 sRef_makeSystemState (void)
4350 if (sRef_isInvalid (srsystem))
4352 srsystem = sRef_makeSpecial (SR_SYSTEM);
4359 sRef_makeGlobalMarker (void)
4361 sRef s = sRef_makeSpecial (SR_GLOBALMARKER);
4362 llassert (valueTable_isUndefined (s->state));
4363 s->state = context_createGlobalMarkerValueTable ();
4368 sRef_makeResultType (ctype ct)
4370 sRef res = sRef_makeResult ();
4379 sRef s = sRef_newRef ();
4381 s->kind = SK_RESULT;
4382 s->type = ctype_unknown;
4383 s->defstate = SS_UNKNOWN;
4384 s->aliaskind = AK_UNKNOWN;
4385 sRef_setNullStateN (s, NS_UNKNOWN);
4386 llassert (valueTable_isUndefined (s->state));
4387 s->state = context_createValueTable (s);
4389 DPRINTF (("Result: [%p] %s", s, sRef_unparseFull (s)));
4395 sRef_isNothing (sRef s)
4397 return (sRef_isKindSpecial (s) && s->info->spec == SR_NOTHING);
4401 sRef_isInternalState (sRef s)
4403 return (sRef_isKindSpecial (s) && s->info->spec == SR_INTERNAL);
4407 sRef_isSpecInternalState (sRef s)
4409 return (sRef_isKindSpecial (s)
4410 && (s->info->spec == SR_INTERNAL || s->info->spec == SR_SPECSTATE));
4414 sRef_isSpecState (sRef s)
4416 return (sRef_isKindSpecial (s) && s->info->spec == SR_SPECSTATE);
4420 sRef_isResult (sRef s)
4422 return (sRef_isValid (s) && s->kind == SK_RESULT);
4426 sRef_isSystemState (sRef s)
4428 return (sRef_isKindSpecial (s) && s->info->spec == SR_SYSTEM);
4432 sRef_isGlobalMarker (sRef s)
4434 return (sRef_isKindSpecial (s) && s->info->spec == SR_GLOBALMARKER);
4438 sRef_getScopeIndex (sRef s)
4440 llassert (sRef_isValid (s));
4441 llassert (sRef_isCvar (s));
4443 return (s->info->cvar->index);
4447 sRef_makeSafe (sRef s)
4449 if (sRef_isValid (s))
4456 sRef_makeUnsafe (sRef s)
4458 if (sRef_isValid (s))
4465 ** memory state operations
4468 /*@only@*/ cstring sRef_unparseFull (sRef s)
4470 if (sRef_isInvalid (s)) return (cstring_undefined);
4472 return (message ("[%d] %q - %q [%s] { %q } < %q >",
4474 sRef_unparseDebug (s),
4475 sRef_unparseState (s),
4476 exkind_unparse (s->oexpkind),
4477 sRefSet_unparseDebug (s->deriv),
4478 valueTable_unparse (s->state)));
4481 /*@unused@*/ cstring sRef_unparseDeep (sRef s)
4483 cstring st = cstring_undefined;
4485 st = message ("%q:", sRef_unparseFull (s));
4487 if (sRef_isValid (s))
4489 sRefSet_allElements (s->deriv, el)
4491 st = message("%q\n%q", st, sRef_unparseDeep (el));
4492 } end_sRefSet_allElements ;
4498 /*@only@*/ cstring sRef_unparseState (sRef s)
4500 if (sRef_isConj (s))
4502 return (message ("%q | %q",
4503 sRef_unparseState (s->info->conj->a),
4504 sRef_unparseState (s->info->conj->b)));
4507 if (sRef_isInvalid (s))
4509 return (cstring_makeLiteral ("<invalid>"));
4512 return (message ("%s.%s.%s.%s",
4513 alkind_unparse (s->aliaskind),
4514 nstate_unparse (sRef_getNullState (s)),
4515 exkind_unparse (s->expkind),
4516 sstate_unparse (s->defstate)));
4519 bool sRef_isNotUndefined (sRef s)
4521 return (sRef_isInvalid (s)
4522 || (s->defstate != SS_UNDEFINED
4523 && s->defstate != SS_UNUSEABLE
4524 && s->defstate != SS_DEAD));
4527 ynm sRef_isWriteable (sRef s)
4529 if (sRef_isInvalid (s)) return MAYBE;
4531 if (sRef_isConj (s) && s->defstate == SS_UNKNOWN)
4533 if (ynm_toBoolStrict (sRef_isWriteable (sRef_getConjA (s))))
4535 if (ynm_toBoolStrict (sRef_isWriteable (sRef_getConjB (s))))
4543 if (ynm_toBoolStrict (sRef_isWriteable (sRef_getConjB (s))))
4551 return (ynm_fromBool (s->defstate != SS_UNUSEABLE));
4554 bool sRef_hasNoStorage (sRef s)
4556 return (!sRef_isAllocatedStorage (s) || sRef_isDefinitelyNull (s));
4559 bool sRef_isStrictReadable (sRef s)
4561 return (ynm_toBoolStrict (sRef_isReadable (s)));
4564 ynm sRef_isReadable (sRef s)
4568 if (sRef_isInvalid (s)) return YES;
4572 if (sRef_isConj (s) && s->defstate == SS_UNKNOWN)
4574 if (ynm_toBoolStrict (sRef_isReadable (sRef_getConjA (s))))
4576 if (ynm_toBoolStrict (sRef_isReadable (sRef_getConjB (s))))
4584 if (ynm_toBoolStrict (sRef_isReadable (sRef_getConjB (s))))
4591 else if (ss == SS_HOFFA)
4593 if (context_getFlag (FLG_STRICTUSERELEASED))
4604 return (ynm_fromBool (ss == SS_DEFINED
4607 || ss == SS_PDEFINED
4610 || ss == SS_ALLOCATED
4611 || ss == SS_KILLED /* evans 2001-05-26: added this for killed globals */
4612 || ss == SS_UNKNOWN));
4616 static /*@exposed@*/ sRef whatUndefined (/*@exposed@*/ sRef fref, int depth)
4621 if (depth > MAXDEPTH)
4624 ("Warning: check definition limit exceeded, checking %q. "
4625 "This either means there is a variable with at least "
4626 "%d indirections apparent in the program text, or "
4627 "there is a bug in LCLint.",
4628 sRef_unparse (fref),
4632 return sRef_undefined;
4635 if (!sRef_isKnown (fref) || sRef_isAnyDefined (fref))
4637 return sRef_undefined;
4640 if (sRef_isUnuseable (fref) || sRef_isStateUndefined (fref))
4645 ct = ctype_realType (sRef_getType (fref));
4647 if (ctype_isUnknown (ct))
4649 return sRef_undefined;
4651 else if (ctype_isPointer (ct) || ctype_isArray (ct))
4653 if (sRef_isStateUnknown (fref))
4655 return sRef_undefined;
4659 sRef fptr = sRef_constructDeref (fref);
4661 return (whatUndefined (fptr, depth + 1));
4664 else if (ctype_isStruct (ct))
4666 bool hasOneDefined = FALSE;
4668 if (sRef_isStateUnknown (fref))
4673 if (sRef_isPdefined (fref) || sRef_isAnyDefined (fref))
4675 sRefSet_realElements (sRef_derivedFields (fref), sr)
4677 hasOneDefined = TRUE;
4679 if (sRef_isField (sr))
4681 cstring fieldname = sRef_getField (sr);
4682 sRef fldref = sRef_makeField (fref, fieldname);
4683 bool shouldCheck = !sRef_isRecursiveField (fldref);
4687 sRef wdef = whatUndefined (fldref, depth + 1);
4689 if (sRef_isValid (wdef))
4695 } end_sRefSet_realElements;
4697 else if (sRef_isAllocated (fref))
4700 ** for structures, each field must be completely defined
4703 uentryList fields = ctype_getFields (ct);
4705 uentryList_elements (fields, ue)
4707 cstring name = uentry_getRealName (ue);
4708 sRef ffield = sRef_makeField (fref, name);
4709 bool shouldCheck = !sRef_isRecursiveField (ffield);
4711 if (sRef_isRelDef (uentry_getSref (ue)))
4719 sRef wdef = whatUndefined (ffield, depth + 1);
4721 if (sRef_isInvalid (wdef))
4727 } end_uentryList_elements;
4734 else if (ctype_isUnion (ct))
4743 return sRef_undefined;
4746 static bool checkDefined (/*@temp@*/ sRef sr)
4748 /*@-temptrans@*/ /* the result from whatUndefined is lost */
4749 return (sRef_isInvalid (whatUndefined (sr, 0)));
4753 bool sRef_isReallyDefined (sRef s)
4755 if (sRef_isValid (s))
4757 if (sRef_isAnyDefined (s))
4763 if (sRef_isAllocated (s) || sRef_isPdefined (s))
4765 return checkDefined (s);
4779 void sRef_showNotReallyDefined (sRef s)
4781 if (sRef_isValid (s))
4783 if (sRef_isAnyDefined (s))
4789 if (sRef_isAllocated (s) || sRef_isPdefined (s))
4791 /*@-temptrans@*/ /* the result of whatUndefined is lost */
4792 sRef ref = whatUndefined (s, 0);
4794 llassert (sRef_isValid (ref));
4799 (message ("This sub-reference is %s: %q",
4800 sstate_unparse (sRef_getDefState (ref)),
4801 sRef_unparse (ref)));
4816 sstate sRef_getDefState (sRef s)
4818 if (sRef_isInvalid (s)) return (SS_UNKNOWN);
4819 return (s->defstate);
4822 void sRef_setDefState (sRef s, sstate defstate, fileloc loc)
4824 sRef_checkMutable (s);
4825 sRef_setStateAux (s, defstate, loc);
4828 static void sRef_clearAliasStateAux (sRef s, fileloc loc)
4830 sRef_checkMutable (s);
4831 sRef_setAliasKind (s, AK_ERROR, loc);
4834 void sRef_clearAliasState (sRef s, fileloc loc)
4836 sRef_checkMutable (s);
4837 sRef_aliasSetComplete (sRef_clearAliasStateAux, s, loc);
4840 void sRef_setAliasKindComplete (sRef s, alkind kind, fileloc loc)
4842 sRef_checkMutable (s);
4843 sRef_aliasSetCompleteParam (sRef_setAliasKind, s, kind, loc);
4846 void sRef_setAliasKind (sRef s, alkind kind, fileloc loc)
4848 sRef_checkMutable (s);
4850 if (sRef_isValid (s))
4852 sRef_clearDerived (s);
4854 if ((kind != s->aliaskind && kind != s->oaliaskind)
4855 && fileloc_isDefined (loc))
4857 s->aliasinfo = stateInfo_updateLoc (s->aliasinfo, loc);
4860 s->aliaskind = kind;
4864 void sRef_setOrigAliasKind (sRef s, alkind kind)
4866 sRef_checkMutable (s);
4868 if (sRef_isValid (s))
4870 s->oaliaskind = kind;
4874 exkind sRef_getExKind (sRef s)
4876 if (sRef_isValid (s))
4878 return (s->expkind);
4886 exkind sRef_getOrigExKind (sRef s)
4888 if (sRef_isValid (s))
4890 return (s->oexpkind);
4898 static void sRef_clearExKindAux (sRef s, fileloc loc)
4900 sRef_checkMutable (s);
4901 sRef_setExKind (s, XO_UNKNOWN, loc);
4904 void sRef_setObserver (sRef s, fileloc loc)
4906 sRef_checkMutable (s);
4907 sRef_setExKind (s, XO_OBSERVER, loc);
4910 void sRef_setExposed (sRef s, fileloc loc)
4912 sRef_checkMutable (s);
4913 sRef_setExKind (s, XO_EXPOSED, loc);
4916 void sRef_clearExKindComplete (sRef s, fileloc loc)
4918 (void) sRef_aliasSetComplete (sRef_clearExKindAux, s, loc);
4921 void sRef_setExKind (sRef s, exkind exp, fileloc loc)
4923 sRef_checkMutable (s);
4925 if (sRef_isValid (s))
4927 if (s->expkind != exp)
4929 s->expinfo = stateInfo_updateLoc (s->expinfo, loc);
4937 ** s1->derived = s2->derived
4940 static void sRef_copyRealDerived (sRef s1, sRef s2)
4942 DPRINTF (("Copy real: %s / %s", sRef_unparse (s1), sRef_unparse (s2)));
4943 sRef_checkMutable (s1);
4945 if (sRef_isValid (s1) && sRef_isValid (s2))
4947 sRef sb = sRef_getRootBase (s1);
4949 sRefSet_clear (s1->deriv);
4951 sRefSet_allElements (s2->deriv, el)
4953 if (sRef_isValid (el))
4955 sRef rb = sRef_getRootBase (el);
4957 if (!sRef_same (rb, sb))
4959 sRef fb = sRef_fixDirectBase (el, s1);
4961 if (sRef_isValid (fb))
4963 sRef_copyRealDerived (fb, el);
4964 sRef_addDeriv (s1, fb);
4969 sRef_addDeriv (s1, el);
4972 } end_sRefSet_allElements ;
4977 void sRef_copyRealDerivedComplete (sRef s1, sRef s2)
4979 sRef_innerAliasSetCompleteParam (sRef_copyRealDerived, s1, s2);
4982 void sRef_setUndefined (sRef s, fileloc loc)
4984 sRef_checkMutable (s);
4986 if (sRef_isValid (s))
4988 s->defstate = SS_UNDEFINED;
4990 if (fileloc_isDefined (loc))
4992 s->definfo = stateInfo_updateLoc (s->definfo, loc);
4995 sRef_clearDerived (s);
4999 static void sRef_setDefinedAux (sRef s, fileloc loc, bool clear)
5001 sRef_checkMutable (s);
5002 if (sRef_isInvalid (s)) return;
5004 DPRINTF (("Set defined: %s", sRef_unparseFull (s)));
5006 if (s->defstate != SS_DEFINED && fileloc_isDefined (loc))
5008 s->definfo = stateInfo_updateLoc (s->definfo, loc);
5011 s->defstate = SS_DEFINED;
5013 DPRINTF (("Set defined: %s", sRef_unparseFull (s)));
5015 /* e.g., if x is allocated, *x = 3 defines x */
5017 if (s->kind == SK_PTR)
5019 sRef p = s->info->ref;
5022 if (p->defstate == SS_ALLOCATED
5023 || p->defstate == SS_SPECIAL) /* evans 2001-07-12: shouldn't need this */
5025 sRef_setDefinedAux (p, loc, clear);
5029 ** Defines a[0] also:
5032 arr = sRef_findDerivedArrayFetch (p, FALSE, 0, FALSE);
5034 if (sRef_isValid (arr))
5036 sRef_setDefinedAux (arr, loc, clear);
5039 else if (s->kind == SK_ARRAYFETCH)
5041 if (!s->info->arrayfetch->indknown
5042 || (s->info->arrayfetch->ind == 0))
5044 sRef p = s->info->arrayfetch->arr;
5045 sRef ptr = sRef_constructPointer (p);
5047 if (sRef_isValid (ptr))
5049 if (ptr->defstate == SS_ALLOCATED
5050 || ptr->defstate == SS_UNDEFINED
5051 || ptr->defstate == SS_SPECIAL) /* evans 2001-07-12: shouldn't need this */
5053 sRef_setDefinedAux (ptr, loc, clear);
5057 if (p->defstate == SS_RELDEF)
5061 else if (p->defstate == SS_ALLOCATED || p->defstate == SS_PDEFINED
5062 || p->defstate == SS_SPECIAL) /* evans 2001-07-12: shouldn't need this */
5064 p->defstate = SS_DEFINED;
5071 else if (s->kind == SK_FIELD)
5073 sRef parent = s->info->field->rec;
5075 if (sRef_isValid (parent))
5077 if (ctype_isUnion (ctype_realType (parent->type)))
5080 ** Should not clear derived from here.
5083 sRef_setDefinedNoClear (parent, loc);
5087 ; /* Nothing to do for structures. */
5099 sRef_clearDerived (s);
5103 /* evans 2001-07-12: need to define the derived references */
5104 sRefSet_elements (s->deriv, el)
5106 el->defstate = SS_DEFINED;
5107 } end_sRefSet_elements ;
5110 DPRINTF (("Set defined: %s", sRef_unparseFull (s)));
5113 static void sRef_setPartialDefined (sRef s, fileloc loc)
5115 sRef_checkMutable (s);
5117 if (!sRef_isPartial (s))
5119 sRef_setDefined (s, loc);
5123 void sRef_setPartialDefinedComplete (sRef s, fileloc loc)
5125 sRef_innerAliasSetComplete (sRef_setPartialDefined, s, loc);
5128 void sRef_setDefinedComplete (sRef s, fileloc loc)
5130 DPRINTF (("Set defined complete: %s", sRef_unparseFull (s)));
5131 sRef_innerAliasSetComplete (sRef_setDefined, s, loc);
5134 void sRef_setDefined (sRef s, fileloc loc)
5136 sRef_checkMutable (s);
5137 sRef_setDefinedAux (s, loc, TRUE);
5140 static void sRef_setDefinedNoClear (sRef s, fileloc loc)
5142 sRef_checkMutable (s);
5143 DPRINTF (("Defining: %s", sRef_unparseFull (s)));
5144 sRef_setDefinedAux (s, loc, FALSE);
5145 DPRINTF (("==> %s", sRef_unparseFull (s)));
5148 void sRef_setDefinedNCComplete (sRef s, fileloc loc)
5150 sRef_checkMutable (s);
5151 DPRINTF (("Set Defined Complete: %s", sRef_unparseFull (s)));
5152 sRef_innerAliasSetComplete (sRef_setDefinedNoClear, s, loc);
5153 DPRINTF (("==> %s", sRef_unparseFull (s)));
5156 static bool sRef_isDeepUnionField (sRef s)
5158 return (sRef_deepPred (sRef_isUnionField, s));
5161 bool sRef_isUnionField (sRef s)
5163 if (sRef_isValid (s) && s->kind == SK_FIELD)
5166 ** defining one field of a union defines the union
5169 sRef base = s->info->field->rec;
5171 if (sRef_isValid (base))
5173 return (ctype_isUnion (ctype_realType (base->type)));
5180 void sRef_setPdefined (sRef s, fileloc loc)
5182 sRef_checkMutable (s);
5183 if (sRef_isValid (s) && !sRef_isPartial (s))
5185 sRef base = sRef_getBaseSafe (s);
5187 if (s->defstate == SS_ALLOCATED)
5192 if (s->defstate != SS_PDEFINED && fileloc_isDefined (loc))
5194 s->definfo = stateInfo_updateLoc (s->definfo, loc);
5197 DPRINTF (("set pdefined: %s", sRef_unparseFull (s)));
5198 s->defstate = SS_PDEFINED;
5200 /* e.g., if x is allocated, *x = 3 defines x */
5202 while (sRef_isValid (base) && sRef_isKnown (base))
5204 if (base->defstate == SS_DEFINED)
5208 base->defstate = SS_PDEFINED;
5209 nb = sRef_getBaseSafe (base);
5220 static void sRef_setStateAux (sRef s, sstate ss, fileloc loc)
5222 sRef_checkMutable (s);
5224 if (sRef_isValid (s))
5226 /* if (s->defstate == SS_RELDEF) return; */
5228 if (s->defstate != ss && fileloc_isDefined (loc))
5230 s->definfo = stateInfo_updateLoc (s->definfo, loc);
5234 sRef_clearDerived (s);
5236 if (ss == SS_ALLOCATED)
5238 sRef base = sRef_getBaseSafe (s);
5240 while (sRef_isValid (base) && sRef_isKnown (base))
5242 if (base->defstate == SS_DEFINED)
5246 base->defstate = SS_PDEFINED;
5248 nb = sRef_getBaseSafe (base);
5261 void sRef_setAllocatedComplete (sRef s, fileloc loc)
5263 sRef_innerAliasSetComplete (sRef_setAllocated, s, loc);
5266 static void sRef_setAllocatedShallow (sRef s, fileloc loc)
5268 sRef_checkMutable (s);
5270 if (sRef_isValid (s))
5272 if (s->defstate == SS_DEAD || s->defstate == SS_UNDEFINED)
5274 s->defstate = SS_ALLOCATED;
5276 if (fileloc_isDefined (loc))
5278 s->definfo = stateInfo_updateLoc (s->definfo, loc);
5284 void sRef_setAllocatedShallowComplete (sRef s, fileloc loc)
5286 sRef_innerAliasSetComplete (sRef_setAllocatedShallow, s, loc);
5289 void sRef_setAllocated (sRef s, fileloc loc)
5291 sRef_checkMutable (s);
5292 sRef_setStateAux (s, SS_ALLOCATED, loc);
5295 void sRef_setPartial (sRef s, fileloc loc)
5297 sRef_checkMutable (s);
5298 sRef_setStateAux (s, SS_PARTIAL, loc);
5301 void sRef_setShared (sRef s, fileloc loc)
5303 sRef_checkMutable (s);
5305 if (sRef_isValid (s))
5307 if (s->aliaskind != AK_SHARED && fileloc_isDefined (loc))
5309 s->aliasinfo = stateInfo_updateLoc (s->aliasinfo, loc);
5312 s->aliaskind = AK_SHARED;
5313 /* don't! sRef_clearDerived (s); */
5317 void sRef_setLastReference (sRef s, /*@exposed@*/ sRef ref, fileloc loc)
5319 sRef_checkMutable (s);
5321 if (sRef_isValid (s))
5323 s->aliaskind = sRef_getAliasKind (ref);
5324 s->aliasinfo = stateInfo_updateRefLoc (s->aliasinfo, ref, loc);
5329 void sRef_setNullStateAux (/*@notnull@*/ sRef s, nstate ns, fileloc loc)
5331 DPRINTF (("Set null state: %s / %s", sRef_unparse (s), nstate_unparse (ns)));
5332 sRef_checkMutable (s);
5335 if (fileloc_isDefined (loc))
5337 s->nullinfo = stateInfo_updateLoc (s->nullinfo, loc);
5341 void sRef_setNotNull (sRef s, fileloc loc)
5343 if (sRef_isValid (s))
5345 sRef_setNullStateAux (s, NS_NOTNULL, loc);
5349 void sRef_setNullStateN (sRef s, nstate n)
5351 sRef_checkMutable (s);
5355 void sRef_setNullState (sRef s, nstate n, fileloc loc)
5357 if (sRef_isValid (s))
5359 sRef_setNullStateAux (s, n, loc);
5363 void sRef_setNullTerminatedStateInnerComplete (sRef s, struct s_bbufinfo b, /*@unused@*/ fileloc loc) {
5365 switch (b.bufstate) {
5366 case BB_NULLTERMINATED:
5367 sRef_setNullTerminatedState (s);
5368 sRef_setLen (s, b.len);
5370 case BB_POSSIBLYNULLTERMINATED:
5371 sRef_setPossiblyNullTerminatedState(s);
5373 case BB_NOTNULLTERMINATED:
5374 sRef_setNotNullTerminatedState (s);
5377 sRef_setSize (s, b.size);
5379 /* PL: TO BE DONE : Aliases are not modified right now, have to be similar to
5380 * setNullStateInnerComplete.
5384 void sRef_setNullStateInnerComplete (sRef s, nstate n, fileloc loc)
5386 DPRINTF (("Set null state: %s", nstate_unparse (n)));
5388 sRef_setNullState (s, n, loc);
5393 sRef_innerAliasSetComplete (sRef_setPosNull, s, loc);
5396 sRef_innerAliasSetComplete (sRef_setDefNull, s, loc);
5399 sRef_innerAliasSetComplete (sRef_setNullUnknown, s, loc);
5402 sRef_innerAliasSetComplete (sRef_setNotNull, s, loc);
5405 sRef_innerAliasSetComplete (sRef_setNotNull, s, loc);
5408 sRef_innerAliasSetComplete (sRef_setNullUnknown, s, loc);
5411 sRef_innerAliasSetComplete (sRef_setDefNull, s, loc);
5414 sRef_innerAliasSetComplete (sRef_setNullUnknown, s, loc);
5417 sRef_innerAliasSetComplete (sRef_setNullErrorLoc, s, loc);
5422 void sRef_setPosNull (sRef s, fileloc loc)
5424 if (sRef_isValid (s))
5426 sRef_setNullStateAux (s, NS_POSNULL, loc);
5430 void sRef_setDefNull (sRef s, fileloc loc)
5432 if (sRef_isValid (s))
5434 sRef_setNullStateAux (s, NS_DEFNULL, loc);
5438 void sRef_setNullUnknown (sRef s, fileloc loc)
5440 if (sRef_isValid (s))
5442 sRef_setNullStateAux (s, NS_UNKNOWN, loc);
5446 void sRef_setNullError (sRef s)
5448 if (sRef_isValid (s))
5450 sRef_setNullStateAux (s, NS_UNKNOWN, fileloc_undefined);
5454 void sRef_setNullErrorLoc (sRef s, /*@unused@*/ fileloc loc)
5456 sRef_setNullError (s);
5459 void sRef_setOnly (sRef s, fileloc loc)
5461 sRef_checkMutable (s);
5463 if (sRef_isValid (s) && s->aliaskind != AK_ONLY)
5465 s->aliaskind = AK_ONLY;
5466 s->aliasinfo = stateInfo_updateLoc (s->aliasinfo, loc);
5470 void sRef_setDependent (sRef s, fileloc loc)
5472 sRef_checkMutable (s);
5474 if (sRef_isValid (s) && !sRef_isConst (s) && (s->aliaskind != AK_DEPENDENT))
5476 DPRINTF (("Setting dependent: %s", sRef_unparseFull (s)));
5477 s->aliaskind = AK_DEPENDENT;
5478 s->aliasinfo = stateInfo_updateLoc (s->aliasinfo, loc);
5482 void sRef_setOwned (sRef s, fileloc loc)
5484 sRef_checkMutable (s);
5486 if (sRef_isValid (s) && !sRef_isConst (s) && (s->aliaskind != AK_OWNED))
5488 s->aliaskind = AK_OWNED;
5489 s->aliasinfo = stateInfo_updateLoc (s->aliasinfo, loc);
5493 void sRef_setKept (sRef s, fileloc loc)
5495 sRef_checkMutable (s);
5497 if (sRef_isValid (s) && !sRef_isConst (s) && (s->aliaskind != AK_KEPT))
5499 sRef base = sRef_getBaseSafe (s);
5501 while (sRef_isValid (base) && sRef_isKnown (base))
5503 if (base->defstate == SS_DEFINED)
5505 base->defstate = SS_PDEFINED;
5506 base = sRef_getBaseSafe (base);
5515 s->aliaskind = AK_KEPT;
5516 s->aliasinfo = stateInfo_updateLoc (s->aliasinfo, loc);
5520 static void sRef_setKeptAux (sRef s, fileloc loc)
5522 if (!sRef_isShared (s))
5524 sRef_setKept (s, loc);
5528 static void sRef_setDependentAux (sRef s, fileloc loc)
5530 if (!sRef_isShared (s))
5532 sRef_setDependent (s, loc);
5536 void sRef_setKeptComplete (sRef s, fileloc loc)
5538 sRef_aliasSetComplete (sRef_setKeptAux, s, loc);
5541 void sRef_setDependentComplete (sRef s, fileloc loc)
5543 sRef_aliasSetComplete (sRef_setDependentAux, s, loc);
5546 void sRef_setFresh (sRef s, fileloc loc)
5548 sRef_checkMutable (s);
5550 if (sRef_isValid (s))
5552 s->aliaskind = AK_FRESH;
5553 s->aliasinfo = stateInfo_updateLoc (s->aliasinfo, loc);
5557 void sRef_kill (sRef s, fileloc loc)
5559 DPRINTF (("Kill: %s", sRef_unparseFull (s)));
5560 sRef_checkMutable (s);
5562 if (sRef_isValid (s) && !sRef_isShared (s) && !sRef_isConst (s))
5564 sRef base = sRef_getBaseSafe (s);
5566 while (sRef_isValid (base) && sRef_isKnown (base))
5568 if (base->defstate == SS_DEFINED)
5570 base->defstate = SS_PDEFINED;
5571 base = sRef_getBaseSafe (base);
5579 s->aliaskind = s->oaliaskind;
5580 s->defstate = SS_DEAD;
5581 s->definfo = stateInfo_updateLoc (s->definfo, loc);
5583 sRef_clearDerived (s);
5587 void sRef_maybeKill (sRef s, fileloc loc)
5589 sRef_checkMutable (s);
5591 if (sRef_isValid (s))
5593 sRef base = sRef_getBaseSafe (s);
5596 while (sRef_isValid (base) && sRef_isKnown (base))
5598 if (base->defstate == SS_DEFINED || base->defstate == SS_RELDEF)
5600 base->defstate = SS_PDEFINED;
5601 base = sRef_getBaseSafe (base);
5610 s->aliaskind = s->oaliaskind;
5611 s->defstate = SS_HOFFA;
5612 s->definfo = stateInfo_updateLoc (s->definfo, loc);
5613 sRef_clearDerived (s);
5619 ** just for type checking...
5622 static void sRef_killAux (sRef s, fileloc loc)
5624 if (sRef_isValid (s) && !sRef_isShared (s))
5626 if (sRef_isUnknownArrayFetch (s))
5628 sRef_maybeKill (s, loc);
5638 ** kills s and all aliases to s
5641 void sRef_killComplete (sRef s, fileloc loc)
5643 DPRINTF (("Kill complete: %s", sRef_unparseFull (s)));
5644 sRef_aliasSetComplete (sRef_killAux, s, loc);
5647 static bool sRef_equivalent (sRef s1, sRef s2)
5649 return (sRef_compare (s1, s2) == 0);
5653 ** returns an sRef that will not be free'd on function exit.
5656 /*@only@*/ sRef sRef_saveCopy (sRef s)
5660 if (sRef_isValid (s))
5662 bool old = inFunction;
5665 ** Exit the function scope, so this sRef is not
5666 ** stored in the deallocation table.
5670 DPRINTF (("Copying sref: %s", sRef_unparseFull(s)));
5671 ret = sRef_copy (s);
5672 DPRINTF (("Copying ===>: %s", sRef_unparseFull(ret)));
5677 ret = sRef_undefined;
5680 /*@-dependenttrans@*/
5682 /*@=dependenttrans@*/
5685 sRef sRef_copy (sRef s)
5687 if (sRef_isKindSpecial (s) && !sRef_isGlobalMarker (s))
5690 return s; /* don't copy specials (except for global markers) */
5694 if (sRef_isValid (s))
5696 sRef t = sRef_alloc ();
5698 DPRINTF (("Copying: [%p] %s", s, sRef_unparse (s)));
5699 DPRINTF (("Full: %s", sRef_unparseFull (s)));
5703 t->modified = s->modified;
5704 t->immut = FALSE; /* Note mutability is not copied. */
5707 t->info = sinfo_copy (s);
5708 t->defstate = s->defstate;
5709 t->nullstate = s->nullstate;
5711 /* start modifications */
5712 t->bufinfo.bufstate = s->bufinfo.bufstate;
5713 t->bufinfo.len = s->bufinfo.len;
5714 t->bufinfo.size = s->bufinfo.size;
5715 /* end modifications */
5717 t->aliaskind = s->aliaskind;
5718 t->oaliaskind = s->oaliaskind;
5720 t->expkind = s->expkind;
5721 t->oexpkind = s->oexpkind;
5723 t->nullinfo = stateInfo_copy (s->nullinfo);
5724 t->aliasinfo = stateInfo_copy (s->aliasinfo);
5725 t->definfo = stateInfo_copy (s->definfo);
5726 t->expinfo = stateInfo_copy (s->expinfo);
5728 t->deriv = sRefSet_newDeepCopy (s->deriv);
5729 t->state = valueTable_copy (s->state);
5731 DPRINTF (("Made copy: [%p] %s", t, sRef_unparse (t)));
5736 return sRef_undefined;
5741 # define PREDTEST(func,s) \
5742 do { if (sRef_isInvalid (s)) { return FALSE; } \
5743 else { if (sRef_isConj (s)) \
5744 { return (func (sRef_getConjA (s)) \
5745 || func (sRef_getConjB (s))); }}} while (FALSE);
5747 bool sRef_isAddress (sRef s)
5749 PREDTEST (sRef_isAddress, s);
5750 return (s->kind == SK_ADR);
5754 ** pretty weak... maybe a flag should control this.
5757 bool sRef_isThroughArrayFetch (sRef s)
5759 if (sRef_isValid (s))
5767 if (sRef_isArrayFetch (tref))
5772 lt = sRef_getBase (tref);
5774 } while (sRef_isValid (tref));
5780 bool sRef_isArrayFetch (sRef s)
5782 PREDTEST (sRef_isArrayFetch, s);
5783 return (s->kind == SK_ARRAYFETCH);
5786 bool sRef_isMacroParamRef (sRef s)
5788 if (context_inMacro () && sRef_isCvar (s))
5790 uentry ue = sRef_getUentry (s);
5791 cstring pname = makeParam (uentry_rawName (ue));
5792 uentry mac = usymtab_lookupSafe (pname);
5794 cstring_free (pname);
5795 return (uentry_isValid (mac));
5801 bool sRef_isCvar (sRef s)
5803 PREDTEST (sRef_isCvar, s);
5804 return (s->kind == SK_CVAR);
5807 bool sRef_isConst (sRef s)
5809 PREDTEST (sRef_isConst, s);
5810 return (s->kind == SK_CONST);
5813 bool sRef_isObject (sRef s)
5815 PREDTEST (sRef_isObject, s);
5816 return (s->kind == SK_OBJECT);
5819 bool sRef_isExternal (sRef s)
5821 PREDTEST (sRef_isExternal, s);
5822 return (s->kind == SK_EXTERNAL);
5825 static bool sRef_isDerived (sRef s)
5827 PREDTEST (sRef_isDerived, s);
5828 return (s->kind == SK_DERIVED);
5831 bool sRef_isField (sRef s)
5833 PREDTEST (sRef_isField, s);
5834 return (s->kind == SK_FIELD);
5837 static bool sRef_isIndex (sRef s)
5839 PREDTEST (sRef_isIndex, s);
5840 return (s->kind == SK_ARRAYFETCH);
5843 bool sRef_isAnyParam (sRef s)
5845 PREDTEST (sRef_isAnyParam, s);
5846 return (s->kind == SK_PARAM);
5849 bool sRef_isParam (sRef s)
5851 PREDTEST (sRef_isParam, s);
5852 return (s->kind == SK_PARAM);
5855 bool sRef_isDirectParam (sRef s)
5857 PREDTEST (sRef_isDirectParam, s);
5859 return ((s->kind == SK_CVAR) &&
5860 (s->info->cvar->lexlevel == functionScope) &&
5861 (context_inFunction () &&
5862 (s->info->cvar->index <= uentryList_size (context_getParams ()))));
5865 bool sRef_isPointer (sRef s)
5867 PREDTEST (sRef_isPointer, s);
5868 return (s->kind == SK_PTR);
5872 ** returns true if storage referenced by s is visible
5875 bool sRef_isReference (sRef s)
5877 PREDTEST (sRef_isReference, s);
5879 return (sRef_isPointer (s) || sRef_isIndex (s) || sRef_isFileOrGlobalScope (s)
5880 || (sRef_isField (s) && (sRef_isReference (s->info->field->rec))));
5883 bool sRef_isIReference (sRef s)
5885 return (sRef_isPointer (s) || sRef_isAddress (s) || sRef_isIndex (s)
5886 || sRef_isField (s) || sRef_isArrayFetch (s));
5889 bool sRef_isFileOrGlobalScope (sRef s)
5891 return (sRef_isCvar (s) && (s->info->cvar->lexlevel <= fileScope));
5894 bool sRef_isRealGlobal (sRef s)
5896 return (sRef_isCvar (s) && (s->info->cvar->lexlevel == globScope));
5899 bool sRef_isFileStatic (sRef s)
5901 return (sRef_isCvar (s) && (s->info->cvar->lexlevel == fileScope));
5904 bool sRef_isAliasCheckedGlobal (sRef s)
5906 if (sRef_isFileOrGlobalScope (s))
5908 uentry ue = sRef_getUentry (s);
5910 return context_checkAliasGlob (ue);
5918 void sRef_free (/*@only@*/ sRef s)
5920 if (s != sRef_undefined && s->kind != SK_SPECIAL)
5922 DPRINTF (("Free sref: [%p]", s));
5924 sRef_checkValid (s);
5926 stateInfo_free (s->expinfo);
5927 stateInfo_free (s->aliasinfo);
5928 stateInfo_free (s->definfo);
5929 stateInfo_free (s->nullinfo);
5931 sRefSet_free (s->deriv);
5932 s->deriv = sRefSet_undefined;
5934 /*@i43@*/ /* valueTable_free (s->state); */
5938 /* drl added to help locate use after release*/
5939 s->expinfo = stateInfo_undefined;
5940 s->aliasinfo = stateInfo_undefined;
5941 s->definfo = stateInfo_undefined;
5942 s->nullinfo = stateInfo_undefined;
5944 /*@i32@*/ sfree (s);
5948 void sRef_setType (sRef s, ctype t)
5950 sRef_checkMutable (s);
5952 if (sRef_isValid (s))
5958 void sRef_setTypeFull (sRef s, ctype t)
5960 sRef_checkMutable (s);
5962 if (sRef_isValid (s))
5966 sRefSet_allElements (s->deriv, current)
5968 sRef_setTypeFull (current, ctype_unknown);
5969 } end_sRefSet_allElements ;
5974 sRef_buildField (/*@exposed@*/ sRef rec, /*@dependent@*/ cstring f)
5976 return (sRef_buildNCField (rec, f));
5979 static /*@exposed@*/ sRef
5980 sRef_findDerivedField (/*@notnull@*/ sRef rec, cstring f)
5982 sRefSet_allElements (rec->deriv, sr)
5984 if (sRef_isValid (sr))
5986 if (sr->info != NULL)
5988 if (sr->kind == SK_FIELD && cstring_equal (sr->info->field->field, f))
5994 } end_sRefSet_allElements;
5996 return sRef_undefined;
5999 /*@dependent@*/ /*@observer@*/ sRefSet sRef_derivedFields (/*@temp@*/ sRef rec)
6001 if (sRef_isValid (rec))
6009 return (sRefSet_undefined);
6013 static /*@exposed@*/ sRef
6014 sRef_findDerivedPointer (sRef s)
6016 if (sRef_isValid (s))
6018 sRefSet_realElements (s->deriv, sr)
6020 if (sRef_isValid (sr) && sr->kind == SK_PTR)
6024 } end_sRefSet_realElements;
6027 return sRef_undefined;
6031 sRef_isUnknownArrayFetch (sRef s)
6033 return (sRef_isValid (s)
6034 && s->kind == SK_ARRAYFETCH
6035 && !s->info->arrayfetch->indknown);
6038 static /*@exposed@*/ sRef
6039 sRef_findDerivedArrayFetch (/*@notnull@*/ sRef s, bool isknown, int idx, bool dead)
6044 sRefSet_realElements (s->deriv, sr)
6046 if (sRef_isValid (sr)
6047 && sr->kind == SK_ARRAYFETCH
6048 && sr->info->arrayfetch->indknown
6049 && (sr->info->arrayfetch->ind == idx))
6053 } end_sRefSet_realElements;
6057 sRefSet_realElements (s->deriv, sr)
6059 if (sRef_isValid (sr)
6060 && sr->kind == SK_ARRAYFETCH
6061 && (!sr->info->arrayfetch->indknown
6062 || (sr->info->arrayfetch->indknown &&
6063 sr->info->arrayfetch->ind == 0)))
6065 if (sRef_isDead (sr) || sRef_isKept (sr))
6067 if (dead || context_getFlag (FLG_STRICTUSERELEASED))
6077 } end_sRefSet_realElements;
6080 return sRef_undefined;
6083 static /*@exposed@*/ sRef
6084 sRef_buildNCField (/*@exposed@*/ sRef rec, /*@exposed@*/ cstring f)
6088 DPRINTF (("Build nc field: %s / %s",
6089 sRef_unparseFull (rec), f));
6091 if (sRef_isInvalid (rec))
6093 return sRef_undefined;
6097 ** check if the field already has been referenced
6100 s = sRef_findDerivedField (rec, f);
6102 if (sRef_isValid (s))
6108 ctype ct = ctype_realType (rec->type);
6110 DPRINTF (("Field of: %s", sRef_unparse (rec)));
6114 s->info = (sinfo) dmalloc (sizeof (*s->info));
6115 s->info->field = (fldinfo) dmalloc (sizeof (*s->info->field));
6116 s->info->field->rec = rec; /* sRef_copy (rec); */ /*@i32@*/
6117 s->info->field->field = f; /* doesn't copy f */
6119 if (ctype_isKnown (ct) && ctype_isSU (ct))
6121 uentry ue = uentryList_lookupField (ctype_getFields (ct), f);
6123 if (!uentry_isUndefined (ue))
6125 DPRINTF (("lookup: %s for %s", uentry_unparseFull (ue),
6126 ctype_unparse (ct)));
6128 s->type = uentry_getType (ue);
6130 if (ctype_isMutable (s->type)
6131 && rec->aliaskind != AK_STACK
6132 && !alkind_isStatic (rec->aliaskind))
6134 s->aliaskind = rec->aliaskind;
6138 s->aliaskind = AK_UNKNOWN;
6141 if (sRef_isStateDefined (rec) || sRef_isStateUnknown (rec)
6142 || sRef_isPdefined (rec))
6144 sRef_setStateFromUentry (s, ue);
6148 sRef_setPartsFromUentry (s, ue);
6151 s->oaliaskind = s->aliaskind;
6152 s->oexpkind = s->expkind;
6154 DPRINTF (("sref: %s", sRef_unparseFull (s)));
6159 Never report this as an error. It can happen whenever there
6160 is casting involved.
6164 llcontbug (message ("buildNCField --- no field %s: %q / %s",
6165 f, sRef_unparse (s), ctype_unparse (ct)));
6169 return sRef_undefined;
6173 if (rec->defstate == SS_DEFINED
6174 && (s->defstate == SS_UNDEFINED || s->defstate == SS_UNKNOWN))
6176 s->defstate = SS_DEFINED;
6178 else if (rec->defstate == SS_PARTIAL)
6180 s->defstate = SS_PARTIAL;
6182 else if (rec->defstate == SS_ALLOCATED)
6184 if (ctype_isStackAllocated (ct) && ctype_isStackAllocated (s->type))
6186 s->defstate = SS_ALLOCATED;
6190 s->defstate = SS_UNDEFINED;
6193 else if (s->defstate == SS_UNKNOWN)
6195 s->defstate = rec->defstate;
6202 if (s->defstate == SS_UNDEFINED)
6204 ctype rt = ctype_realType (s->type);
6206 if (ctype_isArray (rt) || ctype_isSU (rt))
6208 s->defstate = SS_ALLOCATED;
6212 sRef_addDeriv (rec, s);
6213 DPRINTF (("Add deriv: %s", sRef_unparseFull (rec)));
6215 if (ctype_isInt (s->type) && cstring_equal (f, REFSNAME))
6217 s->aliaskind = AK_REFS;
6218 s->oaliaskind = AK_REFS;
6221 DPRINTF (("Build field ==> %s", sRef_unparseFull (s)));
6227 sRef_isStackAllocated (sRef s)
6229 return (sRef_isValid(s)
6230 && s->defstate == SS_ALLOCATED && ctype_isStackAllocated (s->type));
6234 void sRef_setArrayFetchState (/*@notnull@*/ /*@exposed@*/ sRef s,
6235 /*@notnull@*/ /*@exposed@*/ sRef arr)
6237 sRef_checkMutable (s);
6239 if (ctype_isRealAP (arr->type))
6241 s->type = ctype_baseArrayPtr (arr->type);
6244 /* a hack, methinks... makeArrayFetch (&a[0]) ==> a[] */
6245 if (sRef_isAddress (arr))
6247 sRef t = arr->info->ref;
6249 if (sRef_isArrayFetch (t))
6251 s->info->arrayfetch->arr = t->info->arrayfetch->arr;
6254 else if (ctype_isRealPointer (arr->type))
6256 sRef sp = sRef_findDerivedPointer (arr);
6258 if (sRef_isValid (sp))
6261 if (ctype_isMutable (s->type))
6263 sRef_setExKind (s, sRef_getExKind (sp), fileloc_undefined);
6265 s->aliaskind = sp->aliaskind;
6268 s->defstate = sp->defstate;
6270 if (s->defstate == SS_DEFINED)
6272 if (!context_getFlag (FLG_STRICTDESTROY))
6274 s->defstate = SS_PARTIAL;
6278 sRef_setNullStateN (s, sRef_getNullState (sp));
6282 if (arr->defstate == SS_UNDEFINED)
6284 s->defstate = SS_UNUSEABLE;
6286 else if ((arr->defstate == SS_ALLOCATED) && !ctype_isSU (s->type))
6288 s->defstate = SS_UNDEFINED;
6292 if (!context_getFlag (FLG_STRICTDESTROY))
6294 s->defstate = SS_PARTIAL;
6298 s->defstate = SS_DEFINED;
6302 ** Very weak checking for array elements.
6304 ** s->defstate = arr->defstate;
6308 sRef_setExKind (s, sRef_getExKind (arr), g_currentloc);
6310 if (arr->aliaskind == AK_LOCAL || arr->aliaskind == AK_FRESH)
6312 s->aliaskind = AK_LOCAL;
6316 s->aliaskind = AK_UNKNOWN;
6319 sRef_setTypeState (s);
6324 if (arr->defstate == SS_DEFINED)
6327 ** Very weak checking for array elements.
6329 ** s->defstate = arr->defstate;
6332 if (context_getFlag (FLG_STRICTDESTROY))
6334 s->defstate = SS_DEFINED;
6338 s->defstate = SS_PARTIAL;
6341 else if (arr->defstate == SS_ALLOCATED)
6343 if (ctype_isRealArray (s->type))
6345 s->defstate = SS_ALLOCATED;
6349 if (!s->info->arrayfetch->indknown)
6352 ** is index is unknown, elements is defined or
6353 ** allocated is any element is!
6356 s->defstate = SS_UNDEFINED;
6358 sRefSet_allElements (arr->deriv, sr)
6360 if (sRef_isValid (sr))
6362 if (sr->defstate == SS_ALLOCATED)
6364 s->defstate = SS_ALLOCATED;
6368 if (sr->defstate == SS_DEFINED)
6370 if (context_getFlag (FLG_STRICTDESTROY))
6372 s->defstate = SS_DEFINED;
6376 s->defstate = SS_PARTIAL;
6383 } end_sRefSet_allElements;
6388 s->defstate = SS_UNDEFINED;
6394 s->defstate = arr->defstate;
6399 ** kludgey way to guess where aliaskind applies
6402 if (ctype_isMutable (s->type)
6403 && !ctype_isPointer (arr->type)
6404 && !alkind_isStatic (arr->aliaskind)
6405 && !alkind_isStack (arr->aliaskind)) /* evs - 2000-06-20: don't pass stack allocation to members */
6407 s->aliaskind = arr->aliaskind;
6411 s->aliaskind = AK_UNKNOWN;
6414 sRef_setTypeState (s);
6417 if (sRef_isObserver (arr))
6419 s->expkind = XO_OBSERVER;
6423 /*@exposed@*/ sRef sRef_buildArrayFetch (/*@exposed@*/ sRef arr)
6427 if (!sRef_isValid (arr)) {
6428 /*@-nullret@*/ return arr /*@=nullret@*/;
6431 if (ctype_isRealPointer (arr->type))
6433 (void) sRef_buildPointer (arr); /* do this to define arr! */
6436 s = sRef_findDerivedArrayFetch (arr, FALSE, 0, FALSE);
6438 if (sRef_isValid (s))
6440 /* evans 2001-07-12: this is bogus, clean-up hack */
6441 if (s->info->arrayfetch->arr != arr)
6444 check (sRefSet_delete (arr->deriv, s));
6445 res = sRef_buildArrayFetch (arr);
6446 sRef_copyState (res, s);
6450 sRef_setExKind (s, sRef_getExKind (arr), g_currentloc);
6457 s->kind = SK_ARRAYFETCH;
6458 s->info = (sinfo) dmalloc (sizeof (*s->info));
6459 s->info->arrayfetch = (ainfo) dmalloc (sizeof (*s->info->arrayfetch));
6460 s->info->arrayfetch->indknown = FALSE;
6461 s->info->arrayfetch->ind = 0;
6462 s->info->arrayfetch->arr = arr; /* sRef_copy (arr); */ /*@i32@*/
6463 sRef_setArrayFetchState (s, arr);
6464 s->oaliaskind = s->aliaskind;
6465 s->oexpkind = s->expkind;
6467 if (!context_inProtectVars ())
6469 sRef_addDeriv (arr, s);
6472 llassert (valueTable_isUndefined (s->state));
6473 s->state = context_createValueTable (s);
6480 sRef_buildArrayFetchKnown (/*@exposed@*/ sRef arr, int i)
6484 if (!sRef_isValid (arr)) {
6485 /*@-nullret@*/ return arr /*@=nullret@*/;
6488 if (ctype_isRealPointer (arr->type))
6490 (void) sRef_buildPointer (arr); /* do this to define arr! */
6493 s = sRef_findDerivedArrayFetch (arr, TRUE, i, FALSE);
6495 if (sRef_isValid (s))
6497 /* evans 2001-07-12: this is bogus, clean-up hack */
6498 if (s->info->arrayfetch->arr != arr)
6501 check (sRefSet_delete (arr->deriv, s));
6502 res = sRef_buildArrayFetchKnown (arr, i);
6503 sRef_copyState (res, s);
6507 sRef_setExKind (s, sRef_getExKind (arr), g_currentloc);
6509 llassert (s->info->arrayfetch->arr == arr);
6516 s->kind = SK_ARRAYFETCH;
6517 s->info = (sinfo) dmalloc (sizeof (*s->info));
6518 s->info->arrayfetch = (ainfo) dmalloc (sizeof (*s->info->arrayfetch));
6519 s->info->arrayfetch->arr = arr; /* sRef_copy (arr); */ /*@i32@*/
6520 s->info->arrayfetch->indknown = TRUE;
6521 s->info->arrayfetch->ind = i;
6523 sRef_setArrayFetchState (s, arr);
6525 s->oaliaskind = s->aliaskind;
6526 s->oexpkind = s->expkind;
6527 sRef_addDeriv (arr, s);
6529 llassert (valueTable_isUndefined (s->state));
6530 s->state = context_createValueTable (s);
6537 ** sets everything except for defstate
6541 sRef_setPartsFromUentry (sRef s, uentry ue)
6543 sRef uref = uentry_getSref (ue);
6545 llassert (sRef_isValid (s));
6547 s->aliaskind = alkind_derive (s->aliaskind, uentry_getAliasKind (ue));
6548 s->oaliaskind = s->aliaskind;
6550 if (s->expkind == XO_UNKNOWN)
6552 s->expkind = uentry_getExpKind (ue);
6555 s->oexpkind = s->expkind;
6557 if (sRef_getNullState (s) == NS_UNKNOWN)
6559 DPRINTF (("Setting null state!"));
6560 sRef_setNullStateN (s, sRef_getNullState (uentry_getSref (ue)));
6564 DPRINTF (("Skipping null null state!"));
6567 if (s->aliaskind == AK_IMPONLY && (sRef_isExposed (s) || sRef_isObserver (s)))
6569 s->oaliaskind = s->aliaskind = AK_IMPDEPENDENT;
6572 if (sRef_isValid (uref))
6574 valueTable utable = uref->state;
6575 valueTable_free (s->state);
6576 s->state = valueTable_copy (utable);
6581 sRef_setStateFromAbstractUentry (sRef s, uentry ue)
6583 llassert (sRef_isValid (s));
6584 sRef_checkMutable (s);
6586 sRef_setPartsFromUentry (s, ue);
6588 s->aliaskind = alkind_derive (s->aliaskind, uentry_getAliasKind (ue));
6589 s->oaliaskind = s->aliaskind;
6591 if (s->expkind == XO_UNKNOWN)
6593 s->expkind = uentry_getExpKind (ue);
6596 s->oexpkind = s->expkind;
6600 sRef_setStateFromUentry (sRef s, uentry ue)
6604 sRef_checkMutable (s);
6605 llassert (sRef_isValid (s));
6607 sRef_setPartsFromUentry (s, ue);
6609 defstate = uentry_getDefState (ue);
6611 if (sstate_isKnown (defstate))
6613 s->defstate = defstate;
6622 sRef_buildPointer (/*@exposed@*/ sRef t)
6624 DPRINTF (("build pointer: %s", sRef_unparse (t)));
6626 if (sRef_isInvalid (t)) return sRef_undefined;
6628 if (sRef_isAddress (t))
6630 DPRINTF (("Return ref: %s", sRef_unparse (t->info->ref)));
6631 return (t->info->ref);
6635 sRef s = sRef_findDerivedPointer (t);
6637 DPRINTF (("find derived: %s", sRef_unparse (s)));
6639 if (sRef_isValid (s))
6642 sRef_setExKind (s, sRef_getExKind (t), g_currentloc);
6643 s->oaliaskind = s->aliaskind;
6644 s->oexpkind = s->expkind;
6650 s = sRef_constructPointerAux (t);
6652 DPRINTF (("construct: %s", sRef_unparse (s)));
6654 if (sRef_isValid (s))
6656 sRef_addDeriv (t, s);
6658 s->oaliaskind = s->aliaskind;
6659 s->oexpkind = s->expkind;
6668 sRef_constructPointer (/*@exposed@*/ sRef t)
6671 return sRef_buildPointer (t);
6674 static /*@exposed@*/ sRef sRef_constructDerefAux (sRef t, bool isdead)
6676 if (sRef_isValid (t))
6681 ** if there is a derived t[?], return that. Otherwise, *t.
6684 s = sRef_findDerivedArrayFetch (t, FALSE, 0, isdead);
6686 if (sRef_isValid (s))
6688 DPRINTF (("Found array fetch: %s", sRef_unparseFull (s)));
6693 sRef ret = sRef_constructPointer (t);
6695 DPRINTF (("Constructed pointer: %s", sRef_unparseFull (ret)));
6702 return sRef_undefined;
6706 sRef sRef_constructDeref (sRef t)
6708 return sRef_constructDerefAux (t, FALSE);
6711 sRef sRef_constructDeadDeref (sRef t)
6713 return sRef_constructDerefAux (t, TRUE);
6717 sRef_constructPointerAux (/*@notnull@*/ /*@exposed@*/ sRef t)
6719 sRef s = sRef_newRef ();
6724 s->info = (sinfo) dmalloc (sizeof (*s->info));
6725 s->info->ref = t; /* sRef_copy (t); */ /*@i32*/
6727 if (ctype_isRealAP (rt))
6729 s->type = ctype_baseArrayPtr (rt);
6732 st = ctype_realType (s->type);
6734 if (t->defstate == SS_UNDEFINED)
6736 s->defstate = SS_UNUSEABLE;
6738 else if ((t->defstate == SS_ALLOCATED) && !ctype_isSU (st))
6740 s->defstate = SS_UNDEFINED;
6744 s->defstate = t->defstate;
6747 if (t->aliaskind == AK_LOCAL || t->aliaskind == AK_FRESH)
6749 s->aliaskind = AK_LOCAL;
6753 s->aliaskind = AK_UNKNOWN;
6756 sRef_setExKind (s, sRef_getExKind (t), fileloc_undefined);
6757 sRef_setTypeState (s);
6759 s->oaliaskind = s->aliaskind;
6760 s->oexpkind = s->expkind;
6762 llassert (valueTable_isUndefined (s->state));
6763 s->state = context_createValueTable (s);
6767 bool sRef_hasDerived (sRef s)
6769 return (sRef_isValid (s) && !sRefSet_isEmpty (s->deriv));
6773 sRef_clearDerived (sRef s)
6775 if (sRef_isValid (s))
6777 sRefSet_clear (s->deriv);
6782 sRef_clearDerivedComplete (sRef s)
6785 if (sRef_isValid (s))
6787 sRef base = sRef_getBaseSafe (s);
6789 while (sRef_isValid (base))
6791 sRefSet_clear (base->deriv);
6792 base = sRef_getBaseSafe (base);
6795 sRefSet_clear (s->deriv);
6799 /*@exposed@*/ sRef sRef_makePointer (/*@exposed@*/ sRef s)
6802 sRef res = sRef_buildPointer (s);
6804 DPRINTF (("Res: %s", sRef_unparse (res)));
6809 ** &a[] => a (this is for out params)
6813 sRef_makeAnyArrayFetch (/*@exposed@*/ sRef arr)
6816 if (sRef_isAddress (arr))
6818 return (arr->info->ref);
6822 return (sRef_buildArrayFetch (arr));
6827 sRef_makeArrayFetch (/*@exposed@*/ sRef arr)
6829 return (sRef_buildArrayFetch (arr));
6833 sRef_makeArrayFetchKnown (/*@exposed@*/ sRef arr, int i)
6835 return (sRef_buildArrayFetchKnown (arr, i));
6839 sRef_makeField (sRef rec, /*@dependent@*/ cstring f)
6842 ret = sRef_buildField (rec, f);
6847 sRef_makeNCField (/*@exposed@*/ sRef rec, /*@dependent@*/ cstring f)
6849 return (sRef_buildNCField (rec, f));
6853 sRef_unparseKindName (sRef s)
6857 if (s == sRef_undefined) return cstring_makeLiteral ("<invalid>");
6859 s = sRef_fixConj (s);
6864 if (sRef_isLocalVar (s))
6866 result = cstring_makeLiteral ("Variable");
6870 result = cstring_makeLiteral ("Undef global");
6874 result = cstring_makeLiteral ("Out parameter");
6877 if (sRef_isAnyParam (s->info->arrayfetch->arr))
6879 result = cstring_makeLiteral ("Out parameter");
6881 else if (sRef_isIndexKnown (s))
6883 result = cstring_makeLiteral ("Array element");
6887 result = cstring_makeLiteral ("Value");
6891 if (sRef_isAnyParam (s->info->ref))
6893 result = cstring_makeLiteral ("Out parameter");
6897 result = cstring_makeLiteral ("Value");
6901 result = cstring_makeLiteral ("Value");
6904 result = cstring_makeLiteral ("Field");
6907 result = cstring_makeLiteral ("Object");
6909 case SK_UNCONSTRAINED:
6910 result = cstring_makeLiteral ("<anything>");
6919 result = cstring_makeLiteral ("<unknown>");
6922 result = cstring_makeLiteral ("<conj>");
6925 result = cstring_makeLiteral ("Storage");
6933 sRef_unparseKindNamePlain (sRef s)
6937 if (s == sRef_undefined) return cstring_makeLiteral ("<invalid>");
6939 s = sRef_fixConj (s);
6944 if (sRef_isLocalVar (s))
6946 result = cstring_makeLiteral ("Variable");
6950 result = cstring_makeLiteral ("Global");
6954 result = cstring_makeLiteral ("Parameter");
6957 if (sRef_isAnyParam (s->info->arrayfetch->arr))
6959 result = cstring_makeLiteral ("Parameter");
6961 else if (sRef_isIndexKnown (s))
6963 result = cstring_makeLiteral ("Array element");
6967 result = cstring_makeLiteral ("Value");
6971 if (sRef_isAnyParam (s->info->ref))
6973 result = cstring_makeLiteral ("Parameter");
6977 result = cstring_makeLiteral ("Value");
6981 result = cstring_makeLiteral ("Value");
6984 result = cstring_makeLiteral ("Field");
6987 result = cstring_makeLiteral ("Object");
6990 result = cstring_makeLiteral ("Storage");
6992 case SK_UNCONSTRAINED:
6993 result = cstring_makeLiteral ("<anything>");
7002 result = cstring_makeLiteral ("<unknown>");
7005 result = cstring_makeLiteral ("<conj>");
7017 sRef_copyState (sRef s1, sRef s2)
7019 if (sRef_isValid (s1) && sRef_isValid (s2))
7021 s1->defstate = s2->defstate;
7023 /* start modifications */
7024 s1->bufinfo.bufstate = s2->bufinfo.bufstate;
7025 s1->bufinfo.len = s2->bufinfo.len;
7026 s1->bufinfo.size = s2->bufinfo.size;
7027 /* end modifications */
7029 s1->aliaskind = s2->aliaskind;
7030 s1->aliasinfo = stateInfo_update (s1->aliasinfo, s2->aliasinfo);
7032 s1->expkind = s2->expkind;
7033 s1->expinfo = stateInfo_update (s1->expinfo, s2->expinfo);
7035 s1->nullstate = s2->nullstate;
7036 s1->nullinfo = stateInfo_update (s1->nullinfo, s2->nullinfo);
7039 /*@i834 don't free it: valueTable_free (s1->state); */
7040 /*@i32@*/ s1->state = valueTable_copy (s2->state);
7042 s1->safe = s2->safe;
7047 sRef_makeNew (ctype ct, sRef t, cstring name)
7049 sRef s = sRef_newRef ();
7054 llassert (sRef_isValid (t));
7055 s->defstate = t->defstate;
7057 s->aliaskind = t->aliaskind;
7058 s->oaliaskind = s->aliaskind;
7059 s->nullstate = t->nullstate;
7061 s->expkind = t->expkind;
7062 s->oexpkind = s->expkind;
7064 s->info = (sinfo) dmalloc (sizeof (*s->info));
7065 s->info->fname = name;
7067 /* start modifications */
7068 s->bufinfo.bufstate = t->bufinfo.bufstate;
7069 /* end modifications */
7071 llassert (valueTable_isUndefined (s->state));
7072 s->state = valueTable_copy (t->state);
7074 DPRINTF (("==> Copying state: %s", valueTable_unparse (s->state)));
7075 DPRINTF (("==> new: %s", sRef_unparseFull (s)));
7080 sRef_makeType (ctype ct)
7082 sRef s = sRef_newRef ();
7084 sRef_checkMutable (s);
7089 s->defstate = SS_UNKNOWN;
7090 s->aliaskind = AK_UNKNOWN;
7091 sRef_setNullStateN (s, NS_UNKNOWN);
7093 /* start modification */
7094 s->bufinfo.bufstate = BB_NOTNULLTERMINATED;
7095 /* end modification */
7098 if (ctype_isUA (ct))
7100 typeId uid = ctype_typeId (ct);
7101 uentry ue = usymtab_getTypeEntrySafe (uid);
7103 if (uentry_isValid (ue))
7105 sRef_mergeStateQuiet (s, uentry_getSref (ue));
7109 s->oaliaskind = s->aliaskind;
7110 s->oexpkind = s->expkind;
7111 llassert (valueTable_isUndefined (s->state));
7112 s->state = context_createValueTable (s);
7114 DPRINTF (("Create: %s", sRef_unparseFull (s)));
7119 sRef_makeConst (ctype ct)
7121 sRef s = sRef_newRef ();
7126 s->defstate = SS_UNKNOWN;
7127 s->aliaskind = AK_UNKNOWN;
7128 sRef_setNullStateN (s, NS_UNKNOWN);
7130 /* start modification */
7131 s->bufinfo.bufstate = BB_NULLTERMINATED;
7132 /* end modification */
7135 if (ctype_isUA (ct))
7137 typeId uid = ctype_typeId (ct);
7138 uentry te = usymtab_getTypeEntrySafe (uid);
7140 if (uentry_isValid (te))
7142 sRef_mergeStateQuiet (s, uentry_getSref (te));
7147 s->oaliaskind = s->aliaskind;
7148 s->oexpkind = s->expkind;
7150 llassert (valueTable_isUndefined (s->state));
7151 s->state = context_createValueTable (s);
7156 bool sRef_hasName (sRef s)
7158 if (sRef_isInvalid (s))
7167 uentry u = usymtab_getRefQuiet (s->info->cvar->lexlevel,
7168 s->info->cvar->index);
7169 return (uentry_hasName (u));
7173 if (s->info->paramno >= 0)
7175 uentry u = uentryList_getN (context_getParams (),
7178 return (uentry_hasName (u));
7182 llassert (s->info->paramno == PARAMUNKNOWN);
7192 sRef_sameName (sRef s1, sRef s2)
7194 if (sRef_isInvalid (s1))
7196 return sRef_isInvalid (s2);
7199 if (sRef_isInvalid (s2))
7207 if (s2->kind == SK_CVAR)
7209 return (s1->info->cvar->lexlevel == s2->info->cvar->lexlevel
7210 && s1->info->cvar->index == s2->info->cvar->index);
7212 else if (s2->kind == SK_PARAM)
7214 if (context_inFunctionLike ())
7216 if (s2->info->paramno != PARAMUNKNOWN)
7218 uentry u1 = usymtab_getRefQuiet (s1->info->cvar->lexlevel,
7219 s1->info->cvar->index);
7220 uentry u2 = uentryList_getN (context_getParams (),
7223 return (cstring_equalFree (uentry_getName (u1),
7224 uentry_getName (u2)));
7228 return s1->info->paramno == PARAMUNKNOWN;
7242 if (s2->kind == SK_PARAM)
7244 return (s1->info->paramno == s2->info->paramno);
7246 else if (s2->kind == SK_CVAR)
7248 if (context_inFunctionLike ())
7250 if (s1->info->paramno == PARAMUNKNOWN)
7256 uentry u1 = uentryList_getN (context_getParams (),
7258 uentry u2 = usymtab_getRefQuiet (s2->info->cvar->lexlevel,
7259 s2->info->cvar->index);
7262 return (cstring_equalFree (uentry_getName (u1),
7263 uentry_getName (u2)));
7277 case SK_UNCONSTRAINED:
7281 if (s2->kind == SK_ARRAYFETCH)
7283 if (bool_equal (s1->info->arrayfetch->indknown,
7284 s2->info->arrayfetch->indknown))
7286 if (!s1->info->arrayfetch->indknown
7287 || (s1->info->arrayfetch->ind == s2->info->arrayfetch->ind))
7289 return sRef_sameName (s1->info->arrayfetch->arr,
7290 s2->info->arrayfetch->arr);
7297 if (s2->kind == SK_FIELD)
7299 if (cstring_equal (s1->info->field->field,
7300 s2->info->field->field))
7302 return sRef_sameName (s1->info->field->rec,
7303 s2->info->field->rec);
7312 if (s2->kind == s1->kind)
7314 return sRef_sameName (s1->info->ref,
7322 return sRef_sameName (sRef_getConjA (s1), s2);
7326 return (s2->kind == SK_UNKNOWN);
7329 if (s2->kind == s1->kind)
7331 return (ctype_equal (s1->type, s2->type));
7336 if (s2->kind == SK_SPECIAL)
7338 return (s1->info->spec == s2->info->spec);
7342 return (s2->kind == SK_RESULT);
7350 sRef_fixOuterRef (/*@returned@*/ sRef s)
7352 sRef root = sRef_getRootBase (s);
7354 if (sRef_isCvar (root))
7356 uentry ue = usymtab_getRefQuiet (root->info->cvar->lexlevel,
7357 root->info->cvar->index);
7359 if (uentry_isValid (ue))
7361 sRef uref = uentry_getSref (ue);
7362 sRef sr = sRef_fixBase (s, uref);
7368 llcontbug (message ("sRef_fixOuterRef: undefined: %q", sRef_unparseDebug (s)));
7377 sRef_storeState (sRef s)
7379 if (sRef_isInvalid (s)) return;
7381 sRef_checkMutable (s);
7382 s->oaliaskind = s->aliaskind;
7383 s->oexpkind = s->expkind;
7386 static void sRef_resetStateAux (sRef s, /*@unused@*/ fileloc loc)
7388 sRef_resetState (s);
7392 sRef_resetState (sRef s)
7394 bool changed = FALSE;
7395 if (sRef_isInvalid (s)) return;
7398 if (s->oaliaskind == AK_KILLREF && !sRef_isParam (s))
7401 ** killref is used in a kludgey way, to save having to add
7402 ** another alias kind (see usymtab_handleParams)
7405 if (s->expkind != s->oexpkind)
7408 s->expkind = s->oexpkind;
7413 if (s->expkind != s->oexpkind)
7416 s->expkind = s->oexpkind;
7419 if (s->aliaskind != s->oaliaskind
7420 && s->aliaskind != AK_REFCOUNTED
7421 && s->aliaskind != AK_REFS)
7424 s->aliaskind = s->oaliaskind;
7430 sRef_clearDerived (s);
7436 sRef_resetStateComplete (sRef s)
7438 sRef_innerAliasSetComplete (sRef_resetStateAux, s, fileloc_undefined);
7442 sRef_fixBase (/*@returned@*/ sRef s, /*@returned@*/ sRef base)
7444 sRef tmp = sRef_undefined;
7447 if (sRef_isInvalid (s)) return s;
7448 if (sRef_isInvalid (base)) return base;
7458 tmp = sRef_fixBase (s->info->arrayfetch->arr, base);
7460 if (s->info->arrayfetch->indknown)
7462 ret = sRef_makeArrayFetchKnown (tmp, s->info->arrayfetch->ind);
7466 ret = sRef_makeArrayFetch (tmp);
7470 tmp = sRef_fixBase (s->info->field->rec, base);
7471 ret = sRef_buildNCField (tmp, s->info->field->field);
7474 tmp = sRef_fixBase (s->info->ref, base);
7475 ret = sRef_makePointer (tmp);
7478 tmp = sRef_fixBase (s->info->ref, base);
7479 ret = sRef_makeAddress (tmp);
7485 tmp = sRef_fixBase (s->info->conj->a, base);
7486 tmpb = sRef_fixBase (s->info->conj->b, base);
7488 ret = sRef_makeConj (tmp, tmpb);
7497 static /*@exposed@*/ sRef
7498 sRef_fixDirectBase (sRef s, sRef base)
7503 if (sRef_isInvalid (s))
7505 return sRef_undefined;
7511 if (s->info->arrayfetch->indknown)
7513 ret = sRef_makeArrayFetchKnown (base, s->info->arrayfetch->ind);
7517 ret = sRef_makeArrayFetch (base);
7521 ret = sRef_buildNCField (base, s->info->field->field);
7524 ret = sRef_makePointer (base);
7527 ret = sRef_makeAddress (base);
7533 tmpa = sRef_fixDirectBase (s->info->conj->a, base);
7534 tmpb = sRef_fixDirectBase (s->info->conj->b, base);
7536 ret = sRef_makeConj (tmpa, tmpb);
7542 sRef_copyState (ret, s);
7547 sRef_isAllocIndexRef (sRef s)
7549 return (sRef_isArrayFetch (s) && !(s->info->arrayfetch->indknown)
7550 && sRef_isAllocated (s->info->arrayfetch->arr));
7554 sRef_showRefLost (sRef s)
7556 if (sRef_hasAliasInfoLoc (s))
7558 llgenindentmsg (cstring_makeLiteral ("Original reference lost"),
7559 sRef_getAliasInfoLoc (s));
7564 sRef_showRefKilled (sRef s)
7566 if (sRef_hasStateInfoLoc (s))
7568 llgenindentmsg (message ("Storage %q released",
7569 sRef_unparse (s)), sRef_getStateInfoLoc (s));
7574 sRef_showStateInconsistent (sRef s)
7576 if (sRef_hasStateInfoLoc (s))
7579 (message ("Storage %qbecomes inconsistent (released on one branch)",
7580 sRef_unparseOpt (s)),
7581 sRef_getStateInfoLoc (s));
7586 sRef_showStateInfo (sRef s)
7588 if (sRef_hasStateInfoLoc (s))
7590 if (s->defstate == SS_DEAD)
7593 (message ("Storage %qis released", sRef_unparseOpt (s)),
7594 sRef_getStateInfoLoc (s));
7596 else if (s->defstate == SS_ALLOCATED || s->defstate == SS_DEFINED)
7599 (message ("Storage %qis %s", sRef_unparseOpt (s),
7600 sstate_unparse (s->defstate)),
7601 sRef_getStateInfoLoc (s));
7603 else if (s->defstate == SS_UNUSEABLE)
7606 (message ("Storage %qbecomes inconsistent (clauses merge with"
7607 "%qreleased on one branch)",
7608 sRef_unparseOpt (s),
7609 sRef_unparseOpt (s)),
7610 sRef_getStateInfoLoc (s));
7614 llgenindentmsg (message ("Storage %qbecomes %s",
7615 sRef_unparseOpt (s),
7616 sstate_unparse (s->defstate)),
7617 sRef_getStateInfoLoc (s));
7623 sRef_showExpInfo (sRef s)
7625 if (sRef_hasExpInfoLoc (s))
7627 llgenindentmsg (message ("Storage %qbecomes %s", sRef_unparseOpt (s),
7628 exkind_unparse (s->expkind)),
7629 sRef_getExpInfoLoc (s));
7634 sRef_showMetaStateInfo (sRef s, cstring key)
7637 metaStateInfo minfo = context_lookupMetaStateInfo (key);
7639 llassert (sRef_isValid (s));
7640 llassert (valueTable_isDefined (s->state));
7641 llassert (metaStateInfo_isDefined (minfo));
7643 val = valueTable_lookup (s->state, key);
7645 if (stateValue_hasLoc (val))
7648 (message ("Meta state %qbecomes %q", sRef_unparseOpt (s),
7649 stateValue_unparseValue (val, minfo)),
7650 stateValue_getLoc (val));
7655 sRef_showNullInfo (sRef s)
7657 DPRINTF (("Show null info: %s", sRef_unparseFull (s)));
7659 if (sRef_hasNullInfoLoc (s) && sRef_isKnown (s))
7661 DPRINTF (("has null info: %s",
7662 fileloc_unparse (sRef_getNullInfoLoc (s))));
7664 switch (sRef_getNullState (s))
7668 fileloc loc = sRef_getNullInfoLoc (s);
7670 if (fileloc_isDefined (loc) && !fileloc_isLib (loc))
7673 (message ("Storage %qbecomes null", sRef_unparseOpt (s)),
7680 fileloc loc = sRef_getNullInfoLoc (s);
7682 if (fileloc_isDefined (loc) && !fileloc_isLib (loc))
7684 llgenindentmsg (message ("Storage %qbecomes null", sRef_unparseOpt (s)),
7692 (message ("Storage %qmay become null", sRef_unparseOpt (s)),
7693 sRef_getNullInfoLoc (s));
7698 (message ("Storage %qbecomes not null", sRef_unparseOpt (s)),
7699 sRef_getNullInfoLoc (s));
7703 (message ("Storage %qnull state becomes unknown",
7704 sRef_unparseOpt (s)),
7705 sRef_getNullInfoLoc (s));
7714 (message ("<error case> Storage %q becomes %s",
7716 nstate_unparse (sRef_getNullState (s))),
7717 sRef_getNullInfoLoc (s));
7725 sRef_showAliasInfo (sRef s)
7727 if (sRef_hasAliasInfoLoc (s))
7729 if (sRef_isFresh (s))
7732 (message ("Fresh storage %qallocated", sRef_unparseOpt (s)),
7733 sRef_getAliasInfoLoc (s));
7737 if (!sRef_isRefCounted (s))
7740 (message ("Storage %qbecomes %s",
7741 sRef_unparseOpt (s),
7742 alkind_unparse (sRef_getAliasKind (s))),
7743 sRef_getAliasInfoLoc (s));
7750 sRef_mergeNullState (sRef s, nstate n)
7752 if (sRef_isValid (s))
7756 old = sRef_getNullState (s);
7758 if (n != old && n != NS_UNKNOWN)
7760 sRef_setNullState (s, n, g_currentloc);
7765 llbuglit ("sRef_mergeNullState: invalid");
7770 sRef_possiblyNull (sRef s)
7772 if (sRef_isValid (s))
7774 if (sRef_getNullState (s) == NS_ABSNULL)
7776 ctype rct = ctype_realType (s->type);
7778 if (ctype_isAbstract (rct))
7784 if (ctype_isUser (rct))
7786 uentry ue = usymtab_getTypeEntry (ctype_typeId (rct));
7788 return (nstate_possiblyNull
7789 (sRef_getNullState (uentry_getSref (ue))));
7799 return nstate_possiblyNull (sRef_getNullState (s));
7807 sRef_getScopeName (sRef s)
7809 sRef base = sRef_getRootBase (s);
7811 if (sRef_isRealGlobal (base))
7813 return (cstring_makeLiteralTemp ("Global"));
7815 else if (sRef_isFileStatic (base))
7817 return (cstring_makeLiteralTemp ("Static"));
7821 return (cstring_makeLiteralTemp ("Local"));
7826 sRef_unparseScope (sRef s)
7828 sRef base = sRef_getRootBase (s);
7830 if (sRef_isRealGlobal (base))
7832 return (cstring_makeLiteralTemp ("global"));
7834 else if (sRef_isFileStatic (base))
7836 return (cstring_makeLiteralTemp ("file static"));
7845 sRef_getScope (sRef s)
7847 llassert (sRef_isValid (s));
7849 if (sRef_isCvar (s))
7851 return s->info->cvar->lexlevel;
7853 else if (sRef_isParam (s))
7864 sRef_isDead (sRef s)
7866 return (sRef_isValid (s) && (s)->defstate == SS_DEAD);
7870 sRef_isDeadStorage (sRef s)
7872 if (sRef_isValid (s))
7874 if (s->defstate == SS_DEAD
7875 || s->defstate == SS_UNUSEABLE
7876 || s->defstate == SS_UNDEFINED
7877 || s->defstate == SS_UNKNOWN)
7883 return (sRef_isDefinitelyNull (s));
7893 sRef_isPossiblyDead (sRef s)
7895 return (sRef_isValid (s) && s->defstate == SS_HOFFA);
7898 bool sRef_isStateLive (sRef s)
7900 if (sRef_isValid (s))
7902 sstate ds = s->defstate;
7904 return (!(ds == SS_UNDEFINED
7906 || ds == SS_UNUSEABLE
7907 || ds == SS_HOFFA));
7916 bool sRef_isStateUndefined (sRef s)
7918 return ((sRef_isValid(s)) && ((s)->defstate == SS_UNDEFINED));
7921 bool sRef_isJustAllocated (sRef s)
7923 if (sRef_isAllocated (s))
7925 sRefSet_allElements (s->deriv, el)
7927 if (!(sRef_isStateUndefined (el) || sRef_isUnuseable (el)))
7931 } end_sRefSet_allElements ;
7940 sRef_isAllocatedStorage (sRef s)
7942 if (sRef_isValid (s) && ynm_toBoolStrict (sRef_isReadable (s)))
7944 return (ctype_isVisiblySharable (sRef_getType (s)));
7953 sRef_isUnuseable (sRef s)
7955 return ((sRef_isValid(s)) && ((s)->defstate == SS_UNUSEABLE));
7959 sRef_perhapsNull (sRef s)
7961 if (sRef_isValid (s))
7963 if (sRef_getNullState (s) == NS_ABSNULL)
7965 ctype rct = ctype_realType (s->type);
7967 if (ctype_isAbstract (rct))
7973 if (ctype_isUser (rct))
7975 uentry ue = usymtab_getTypeEntry (ctype_typeId (rct));
7977 return (nstate_perhapsNull
7978 (sRef_getNullState (uentry_getSref (ue))));
7988 return nstate_perhapsNull (sRef_getNullState (s));
7996 ** definitelyNull --- called when TRUE is good
8000 sRef_definitelyNull (sRef s)
8002 return (sRef_isValid (s)
8003 && (sRef_getNullState (s) == NS_DEFNULL || sRef_getNullState (s) == NS_CONSTNULL));
8007 ** based on sRef_similar
8011 sRef_setDerivNullState (sRef set, sRef guide, nstate ns)
8013 if (sRef_isValid (set))
8015 sRef deriv = sRef_getDeriv (set, guide);
8017 if (sRef_isValid (deriv))
8019 sRef_setNullStateN (deriv, ns);
8024 static /*@exposed@*/ sRef
8025 sRef_getDeriv (/*@returned@*/ /*@notnull@*/ sRef set, sRef guide)
8027 llassert (sRef_isValid (set));
8028 llassert (sRef_isValid (guide));
8030 switch (guide->kind)
8033 llassert (set->kind == SK_CVAR);
8038 llassert (set->kind == guide->kind);
8039 llassert (set->info->paramno == guide->info->paramno);
8045 if (set->kind == SK_ARRAYFETCH
8046 && (sRef_similar (set->info->arrayfetch->arr,
8047 guide->info->arrayfetch->arr)))
8053 return (sRef_makeAnyArrayFetch
8054 (sRef_getDeriv (set, guide->info->arrayfetch->arr)));
8059 if (set->kind == SK_PTR && sRef_similar (set->info->ref, guide->info->ref))
8065 return (sRef_makePointer (sRef_getDeriv (set, guide->info->ref)));
8070 if ((set->kind == SK_FIELD &&
8071 (sRef_similar (set->info->field->rec, guide->info->field->rec) &&
8072 cstring_equal (set->info->field->field, guide->info->field->field))))
8078 return (sRef_makeField (sRef_getDeriv (set, guide->info->field->rec),
8079 guide->info->field->field));
8083 if ((set->kind == SK_ADR) && sRef_similar (set->info->ref, guide->info->ref))
8089 return (sRef_makeAddress (sRef_getDeriv (set, guide->info->ref)));
8094 return sRef_undefined;
8098 case SK_UNCONSTRAINED:
8106 return sRef_undefined;
8113 ** sRef_aliasCheckPred
8115 ** A confusing but spiffy function:
8117 ** Calls predf (s, e, text, <alias>) on s and all of s's aliases
8118 ** (unless checkAliases (s) is FALSE).
8120 ** For alias calls, calls as
8121 ** predf (alias, e, text, s)
8125 sRef_aliasCheckPred (bool (predf) (sRef, exprNode, sRef, exprNode),
8126 /*@null@*/ bool (checkAliases) (sRef),
8127 sRef s, exprNode e, exprNode err)
8129 bool error = (*predf)(s, e, sRef_undefined, err);
8132 if (checkAliases != NULL && !(checkAliases (s)))
8134 /* don't check aliases */
8138 sRefSet aliases = usymtab_allAliases (s);
8141 sRefSet_realElements (aliases, current)
8143 if (sRef_isValid (current))
8145 if (!sRef_similar (current, s)
8146 || (error && sRef_sameName (current, s)))
8148 (void) (*predf)(current, e, s, err);
8151 } end_sRefSet_realElements;
8153 sRefSet_free (aliases);
8158 ** return TRUE iff predf (s) is true for s or any alias of s
8162 sRef_aliasCheckSimplePred (sRefTest predf, sRef s)
8173 aliases = usymtab_allAliases (s);
8175 sRefSet_realElements (aliases, current)
8177 if (sRef_isValid (current))
8179 sRef cref = sRef_updateSref (current);
8181 /* Whoa! a very kludgey way to make sure the right sref is used
8182 ** where there is a conditional symbol table. I am beginning
8183 ** to think that having a conditional symbol table wasn't such
8189 DPRINTF (("Checking alias: %s", sRef_unparseFull (cref)));
8190 sRefSet_free (aliases);
8194 } end_sRefSet_realElements;
8196 sRefSet_free (aliases);
8202 sRef_aliasCompleteSimplePred (bool (predf) (sRef), sRef s)
8205 bool result = FALSE;
8208 aliases = usymtab_allAliases (s);
8210 if ((*predf)(s)) result = TRUE;
8213 sRefSet_realElements (aliases, current)
8215 if (sRef_isValid (current))
8217 current = sRef_updateSref (current);
8218 if ((*predf)(current)) result = TRUE;
8220 } end_sRefSet_realElements;
8222 sRefSet_free (aliases);
8227 sRef_aliasSetComplete (void (predf) (sRef, fileloc), sRef s, fileloc loc)
8231 aliases = usymtab_allAliases (s);
8233 DPRINTF (("All aliases: %s", sRefSet_unparseFull (aliases)));
8237 sRefSet_realElements (aliases, current)
8239 if (sRef_isValid (current))
8241 current = sRef_updateSref (current);
8242 ((*predf)(current, loc));
8244 } end_sRefSet_realElements;
8246 sRefSet_free (aliases);
8250 sRef_aliasSetCompleteParam (void (predf) (sRef, alkind, fileloc), sRef s,
8251 alkind kind, fileloc loc)
8256 if (sRef_isDeep (s))
8258 aliases = usymtab_allAliases (s);
8262 aliases = usymtab_aliasedBy (s);
8265 (*predf)(s, kind, loc);
8267 sRefSet_realElements (aliases, current)
8269 if (sRef_isValid (current))
8271 current = sRef_updateSref (current);
8272 ((*predf)(current, kind, loc));
8274 } end_sRefSet_realElements;
8276 sRefSet_free (aliases);
8280 sRef_innerAliasSetComplete (void (predf) (sRef, fileloc), sRef s, fileloc loc)
8286 if (!sRef_isValid (s)) return;
8290 ** Type equivalence checking is necessary --- there might be casting.
8297 case SK_UNCONSTRAINED:
8302 inner = s->info->ref;
8303 aliases = usymtab_allAliases (inner);
8304 ct = sRef_getType (inner);
8306 sRefSet_realElements (aliases, current)
8308 if (sRef_isValid (current))
8310 current = sRef_updateSref (current);
8312 if (ctype_equal (ct, sRef_getType (current)))
8314 sRef ptr = sRef_makePointer (current);
8315 ((*predf)(ptr, loc));
8318 } end_sRefSet_realElements;
8320 sRefSet_free (aliases);
8323 inner = s->info->arrayfetch->arr;
8324 aliases = usymtab_allAliases (inner);
8325 ct = sRef_getType (inner);
8327 DPRINTF (("Array fetch: %s", sRefSet_unparse (aliases)));
8329 sRefSet_realElements (aliases, current)
8331 if (sRef_isValid (current))
8333 current = sRef_updateSref (current);
8334 DPRINTF (("Current: %s", sRef_unparseFull (current)));
8336 if (ctype_equal (ct, sRef_getType (current)))
8338 if (s->info->arrayfetch->indknown)
8340 sRef af = sRef_makeArrayFetchKnown (current, s->info->arrayfetch->ind);
8341 DPRINTF (("Defining: %s", sRef_unparseFull (af)));
8342 llassert (af->info->arrayfetch->arr == current);
8343 ((*predf)(af, loc));
8347 sRef af = sRef_makeArrayFetch (current);
8348 llassert (af->info->arrayfetch->arr == current);
8349 DPRINTF (("Defining: %s", sRef_unparseFull (af)));
8350 ((*predf)(af, loc));
8355 DPRINTF (("Type mismatch: %s / %s",
8357 ctype_unparse (sRef_getType (current))));
8360 } end_sRefSet_realElements;
8362 sRefSet_free (aliases);
8365 inner = s->info->field->rec;
8366 aliases = usymtab_allAliases (inner);
8367 ct = sRef_getType (inner);
8370 sRefSet_realElements (aliases, current)
8372 if (sRef_isValid (current))
8374 current = sRef_updateSref (current);
8376 if (ctype_equal (ct, sRef_getType (current)))
8378 sRef f = sRef_makeField (current, s->info->field->field);
8383 } end_sRefSet_realElements;
8385 sRefSet_free (aliases);
8388 sRef_innerAliasSetComplete (predf, s->info->conj->a, loc);
8389 sRef_innerAliasSetComplete (predf, s->info->conj->b, loc);
8406 sRef_innerAliasSetCompleteParam (void (predf) (sRef, sRef), sRef s, sRef t)
8412 if (!sRef_isValid (s)) return;
8416 ** Type equivalence checking is necessary --- there might be casting.
8423 case SK_UNCONSTRAINED:
8428 inner = s->info->ref;
8429 aliases = usymtab_allAliases (inner);
8430 ct = sRef_getType (inner);
8433 sRefSet_realElements (aliases, current)
8435 if (sRef_isValid (current))
8437 current = sRef_updateSref (current);
8439 if (ctype_equal (ct, sRef_getType (current)))
8441 sRef ptr = sRef_makePointer (current);
8446 } end_sRefSet_realElements;
8448 sRefSet_free (aliases);
8451 inner = s->info->arrayfetch->arr;
8452 aliases = usymtab_allAliases (inner);
8453 ct = sRef_getType (inner);
8455 sRefSet_realElements (aliases, current)
8457 if (sRef_isValid (current))
8459 current = sRef_updateSref (current);
8461 if (ctype_equal (ct, sRef_getType (current)))
8464 if (s->info->arrayfetch->indknown)
8466 sRef af = sRef_makeArrayFetchKnown (current, s->info->arrayfetch->ind);
8472 sRef af = sRef_makeArrayFetch (current);
8478 } end_sRefSet_realElements;
8480 sRefSet_free (aliases);
8483 inner = s->info->field->rec;
8484 aliases = usymtab_allAliases (inner);
8485 ct = sRef_getType (inner);
8488 sRefSet_realElements (aliases, current)
8490 if (sRef_isValid (current))
8492 current = sRef_updateSref (current);
8494 if (ctype_equal (ct, sRef_getType (current)))
8496 sRef f = sRef_makeField (current, s->info->field->field);
8501 } end_sRefSet_realElements;
8503 sRefSet_free (aliases);
8506 sRef_innerAliasSetCompleteParam (predf, s->info->conj->a, t);
8507 sRef_innerAliasSetCompleteParam (predf, s->info->conj->b, t);
8523 static void sRef_combineExKinds (/*@notnull@*/ sRef res, /*@notnull@*/ sRef other)
8525 exkind a1 = sRef_getExKind (res);
8526 exkind a2 = sRef_getExKind (other);
8528 if (a1 == a2 || a2 == XO_UNKNOWN)
8532 else if (a1 == XO_UNKNOWN)
8534 res->expinfo = stateInfo_update (res->expinfo, other->expinfo);
8539 res->expkind = XO_OBSERVER;
8544 ** Currently, this is a very ad hoc implementation, with lots of fixes to
8545 ** make real code work okay. I need to come up with some more general
8546 ** rules or principles here.
8550 sRef_combineAliasKindsError (/*@notnull@*/ sRef res,
8551 /*@notnull@*/ sRef other,
8552 clause cl, fileloc loc)
8554 bool hasError = FALSE;
8555 alkind ares = sRef_getAliasKind (res);
8556 alkind aother = sRef_getAliasKind (other);
8558 sRef_checkMutable (res);
8560 if (alkind_isDependent (ares))
8562 if (aother == AK_KEPT)
8564 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8565 res->aliaskind = AK_KEPT;
8569 if (aother == AK_LOCAL || aother == AK_STATIC
8570 || alkind_isTemp (aother))
8572 DPRINTF (("Setting dependent: %s", sRef_unparseFull (res)));
8573 res->aliaskind = AK_DEPENDENT;
8577 else if (alkind_isDependent (aother))
8579 if (ares == AK_KEPT)
8581 res->aliaskind = AK_KEPT;
8585 if (ares == AK_LOCAL || ares == AK_STATIC || alkind_isTemp (ares))
8587 DPRINTF (("Setting dependent: %s", sRef_unparseFull (res)));
8588 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8589 res->aliaskind = AK_DEPENDENT;
8593 else if ((ares == AK_LOCAL || ares == AK_UNIQUE
8594 || ares == AK_STATIC || alkind_isTemp (ares))
8595 && sRef_isFresh (other))
8598 ** cases like: if (s == NULL) s = malloc...;
8599 ** don't generate errors
8602 if (usymtab_isAltDefinitelyNullDeep (res))
8604 res->aliaskind = ares;
8611 else if ((aother == AK_LOCAL || aother == AK_UNIQUE
8612 || aother == AK_STATIC || alkind_isTemp (aother))
8613 && sRef_isFresh (res))
8616 ** cases like: if (s == NULL) s = malloc...;
8617 ** don't generate errors
8620 if (usymtab_isDefinitelyNullDeep (other))
8622 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8623 res->aliaskind = aother;
8630 else if (ares == AK_NEWREF && aother == AK_REFCOUNTED
8631 && sRef_isConst (other))
8633 res->aliaskind = AK_NEWREF;
8635 else if (aother == AK_NEWREF && ares == AK_REFCOUNTED
8636 && sRef_isConst (res))
8638 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8639 res->aliaskind = AK_NEWREF;
8641 else if (sRef_isLocalVar (res)
8642 && ((ares == AK_KEPT && aother == AK_LOCAL)
8643 || (aother == AK_KEPT && ares == AK_LOCAL)))
8645 res->aliaskind = AK_KEPT;
8654 if (sRef_isThroughArrayFetch (res))
8657 (FLG_BRANCHSTATE, FLG_STRICTBRANCHSTATE,
8659 ("Clauses exit with %q possibly referencing %s storage %s, "
8662 alkind_unparse (aother),
8663 clause_nameTaken (cl),
8664 alkind_unparse (ares),
8665 clause_nameAlternate (cl)),
8668 sRef_showAliasInfo (res);
8669 sRef_showAliasInfo (other);
8670 res->aliaskind = AK_ERROR;
8674 if (ares == AK_KEPT || aother == AK_KEPT)
8676 sRef_maybeKill (res, loc);
8684 message ("Clauses exit with %q referencing %s storage %s, "
8687 alkind_unparse (aother),
8688 clause_nameTaken (cl),
8689 alkind_unparse (ares),
8690 clause_nameAlternate (cl)),
8693 sRef_showAliasInfo (res);
8694 sRef_showAliasInfo (other);
8696 res->aliaskind = AK_ERROR;
8700 res->aliaskind = (sRef_isLocalVar (res) ? AK_LOCAL : AK_UNKNOWN);
8705 sRef_combineAliasKinds (/*@notnull@*/ sRef res, /*@notnull@*/ sRef other,
8706 clause cl, fileloc loc)
8708 alkind ares = sRef_getAliasKind (res);
8709 alkind aother = sRef_getAliasKind (other);
8711 sRef_checkMutable (res);
8713 if (alkind_equal (ares, aother)
8714 || aother == AK_UNKNOWN
8715 || aother == AK_ERROR)
8717 ; /* keep current state */
8719 else if (sRef_isDead (res) || sRef_isDead (other))
8721 /* dead error reported (or storage is dead) */
8722 res ->aliaskind = AK_ERROR;
8724 else if (ares == AK_UNKNOWN || ares == AK_ERROR
8725 || sRef_isStateUndefined (res))
8727 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8728 res->aliaskind = aother;
8730 else if (sRef_isStateUndefined (other))
8734 else if (((ares == AK_UNIQUE || alkind_isTemp (ares))
8735 && aother == AK_LOCAL)
8736 || ((aother == AK_UNIQUE || alkind_isTemp (aother))
8737 && ares == AK_LOCAL))
8739 if (ares != AK_LOCAL)
8741 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8744 res->aliaskind = AK_LOCAL;
8746 else if ((ares == AK_OWNED && aother == AK_FRESH)
8747 || (aother == AK_OWNED && ares == AK_FRESH))
8749 if (ares != AK_FRESH)
8751 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8754 res->aliaskind = AK_FRESH;
8756 else if ((ares == AK_KEEP && aother == AK_FRESH) ||
8757 (aother == AK_KEEP && ares == AK_FRESH))
8759 if (ares != AK_KEEP)
8761 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8764 res->aliaskind = AK_KEEP;
8766 else if ((ares == AK_LOCAL && aother == AK_STACK) ||
8767 (aother == AK_LOCAL && ares == AK_STACK))
8769 if (ares != AK_STACK)
8771 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8774 res->aliaskind = AK_STACK;
8776 else if ((ares == AK_LOCAL
8777 && (aother == AK_OWNED && sRef_isLocalVar (other)))
8778 || (aother == AK_LOCAL
8779 && (ares == AK_OWNED && sRef_isLocalVar (res))))
8781 if (ares != AK_LOCAL)
8783 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8786 res->aliaskind = AK_LOCAL;
8788 else if ((ares == AK_FRESH && alkind_isOnly (aother))
8789 || (aother == AK_FRESH && alkind_isOnly (ares)))
8791 res->aliaskind = AK_FRESH;
8793 else if ((aother == AK_FRESH && sRef_definitelyNull (res))
8794 || (ares == AK_FRESH && sRef_definitelyNull (other)))
8796 if (ares != AK_FRESH)
8798 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8799 res->aliaskind = AK_FRESH;
8802 else if ((sRef_isFresh (res) && sRef_isConst (other))
8803 || (sRef_isFresh (other) && sRef_isConst (res)))
8806 ** for NULL constantants
8810 if (!sRef_isFresh (res))
8812 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8815 res->aliaskind = AK_FRESH;
8817 else if ((alkind_isStatic (aother) && sRef_isConst (res))
8818 || (alkind_isStatic (ares) && sRef_isConst (other)))
8820 if (!alkind_isStatic (ares))
8822 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8823 res->aliaskind = AK_STATIC;
8828 sRef_combineAliasKindsError (res, other, cl, loc);
8832 static void sRef_combineDefState (/*@notnull@*/ sRef res,
8833 /*@notnull@*/ sRef other)
8835 sstate s1 = res->defstate;
8836 sstate s2 = other->defstate;
8839 sRef_checkMutable (res);
8841 if (s1 == s2 || s2 == SS_UNKNOWN)
8845 else if (s1 == SS_UNKNOWN)
8854 if (s2 == SS_DEFINED)
8860 llcontbuglit ("ssfixed: not implemented");
8869 flip = (s2 != SS_DEFINED);
8887 res->definfo = stateInfo_update (res->definfo, other->definfo);
8892 extern /*@notnull@*/ sRef sRef_getConjA (sRef s)
8895 llassert (sRef_isConj (s));
8897 ret = s->info->conj->a;
8898 llassert (ret != NULL);
8902 extern /*@notnull@*/ sRef sRef_getConjB (sRef s)
8905 llassert (sRef_isConj (s));
8907 ret = s->info->conj->b;
8908 llassert (ret != NULL);
8912 extern /*@exposed@*/ sRef sRef_makeArrow (sRef s, /*@dependent@*/ cstring f)
8917 p = sRef_makePointer (s);
8918 ret = sRef_makeField (p, f);
8922 extern /*@exposed@*/ sRef sRef_buildArrow (sRef s, cstring f)
8927 p = sRef_buildPointer (s);
8928 ret = sRef_buildField (p, f);
8933 static /*@null@*/ sinfo sinfo_copy (/*@notnull@*/ sRef s)
8940 ret = (sinfo) dmalloc (sizeof (*ret));
8941 ret->cvar = (cref) dmalloc (sizeof (*ret->cvar));
8942 ret->cvar->lexlevel = s->info->cvar->lexlevel;
8943 ret->cvar->index = s->info->cvar->index;
8947 ret = (sinfo) dmalloc (sizeof (*ret));
8948 ret->paramno = s->info->paramno;
8949 llassert (ret->paramno >= -1);
8953 ret = (sinfo) dmalloc (sizeof (*ret));
8954 ret->arrayfetch = (ainfo) dmalloc (sizeof (*ret->arrayfetch));
8955 ret->arrayfetch->indknown = s->info->arrayfetch->indknown;
8956 ret->arrayfetch->ind = s->info->arrayfetch->ind;
8957 ret->arrayfetch->arr = s->info->arrayfetch->arr; /* sRef_copy (s->info->arrayfetch->arr); */ /*@i32@*/
8961 ret = (sinfo) dmalloc (sizeof (*ret));
8962 ret->field = (fldinfo) dmalloc (sizeof (*ret->field));
8963 ret->field->rec = s->info->field->rec; /* sRef_copy (s->info->field->rec); */ /*@i32@*/
8964 ret->field->field = s->info->field->field;
8968 ret = (sinfo) dmalloc (sizeof (*ret));
8969 ret->object = s->info->object;
8976 ret = (sinfo) dmalloc (sizeof (*ret));
8977 ret->ref = s->info->ref; /* Ref_copy (s->info->ref); */
8981 ret = (sinfo) dmalloc (sizeof (*ret));
8982 ret->conj = (cjinfo) dmalloc (sizeof (*ret->conj));
8983 ret->conj->a = s->info->conj->a; /* sRef_copy (s->info->conj->a); */
8984 ret->conj->b = s->info->conj->b; /* sRef_copy (s->info->conj->b);*/
8987 ret = (sinfo) dmalloc (sizeof (*ret));
8988 ret->spec = s->info->spec;
8990 case SK_UNCONSTRAINED:
8992 ret = (sinfo) dmalloc (sizeof (*ret));
8993 ret->fname = s->info->fname;
8999 llassertprint (s->info == NULL, ("s = %s", sRef_unparse (s)));
9007 static /*@null@*/ sinfo sinfo_fullCopy (/*@notnull@*/ sRef s)
9012 ** Since its a full copy, only storage is assigned
9013 ** to dependent fields.
9020 ret = (sinfo) dmalloc (sizeof (*ret));
9021 ret->cvar = (cref) dmalloc (sizeof (*ret->cvar));
9022 ret->cvar->lexlevel = s->info->cvar->lexlevel;
9023 ret->cvar->index = s->info->cvar->index;
9027 ret = (sinfo) dmalloc (sizeof (*ret));
9028 ret->paramno = s->info->paramno;
9029 llassert (ret->paramno >= -1);
9033 ret = (sinfo) dmalloc (sizeof (*ret));
9034 ret->arrayfetch = (ainfo) dmalloc (sizeof (*ret->arrayfetch));
9035 ret->arrayfetch->indknown = s->info->arrayfetch->indknown;
9036 ret->arrayfetch->ind = s->info->arrayfetch->ind;
9037 ret->arrayfetch->arr = sRef_saveCopy (s->info->arrayfetch->arr);
9041 ret = (sinfo) dmalloc (sizeof (*ret));
9042 ret->field = (fldinfo) dmalloc (sizeof (*ret->field));
9043 ret->field->rec = sRef_saveCopy (s->info->field->rec);
9044 ret->field->field = s->info->field->field;
9048 ret = (sinfo) dmalloc (sizeof (*ret));
9049 ret->object = s->info->object;
9056 ret = (sinfo) dmalloc (sizeof (*ret));
9057 ret->ref = sRef_saveCopy (s->info->ref);
9061 ret = (sinfo) dmalloc (sizeof (*ret));
9062 ret->conj = (cjinfo) dmalloc (sizeof (*ret->conj));
9063 ret->conj->a = sRef_saveCopy (s->info->conj->a);
9064 ret->conj->b = sRef_saveCopy (s->info->conj->b);
9067 ret = (sinfo) dmalloc (sizeof (*ret));
9068 ret->spec = s->info->spec;
9071 case SK_UNCONSTRAINED:
9072 ret = (sinfo) dmalloc (sizeof (*ret));
9073 ret->fname = s->info->fname;
9079 llassert (s->info == NULL);
9089 sinfo_update (/*@notnull@*/ /*@exposed@*/ sRef res,
9090 /*@notnull@*/ /*@exposed@*/ sRef other)
9092 llassert (res->kind == other->kind);
9097 res->info->cvar->lexlevel = other->info->cvar->lexlevel;
9098 res->info->cvar->index = other->info->cvar->index;
9102 res->info->paramno = other->info->paramno;
9103 llassert (res->info->paramno >= -1);
9107 res->info->arrayfetch->indknown = other->info->arrayfetch->indknown;
9108 res->info->arrayfetch->ind = other->info->arrayfetch->ind;
9109 res->info->arrayfetch->arr = other->info->arrayfetch->arr;
9113 res->info->field->rec = other->info->field->rec;
9114 res->info->field->field = other->info->field->field;
9118 res->info->object = other->info->object;
9125 res->info->ref = other->info->ref;
9129 res->info->conj->a = other->info->conj->a;
9130 res->info->conj->b = other->info->conj->b;
9134 res->info->spec = other->info->spec;
9138 case SK_UNCONSTRAINED:
9139 res->info->fname = other->info->fname;
9146 llassert (res->info == NULL);
9151 static void sinfo_free (/*@special@*/ /*@temp@*/ /*@notnull@*/ sRef s)
9152 /*@uses s->kind, s->info@*/
9153 /*@releases s->info@*/
9158 DPRINTF (("Free sinfo: [%p]", s->info->cvar));
9159 sfree (s->info->cvar);
9166 DPRINTF (("Free sinfo: [%p]", s->info->arrayfetch));
9167 sfree (s->info->arrayfetch);
9171 DPRINTF (("Free sinfo: [%p]", s->info->field));
9172 sfree (s->info->field);
9181 case SK_EXTERNAL: /*@i32 is copy now! */
9185 DPRINTF (("Free sinfo: [%p]", s->info->conj));
9186 sfree (s->info->conj);
9189 case SK_UNCONSTRAINED:
9199 if (s->info != NULL) {
9200 DPRINTF (("Free sinfo: [%p]", s->info));
9206 bool sRef_isNSLocalVar (sRef s)
9208 if (sRef_isLocalVar (s))
9210 uentry ue = sRef_getUentry (s);
9212 return (!uentry_isStatic (ue));
9220 bool sRef_isLocalVar (sRef s)
9222 if (sRef_isValid(s))
9224 return (s->kind == SK_CVAR
9225 && (s->info->cvar->lexlevel > fileScope));
9231 bool sRef_isRealLocalVar (sRef s)
9233 if (sRef_isValid(s))
9235 if (s->kind == SK_CVAR)
9237 if (s->info->cvar->lexlevel == functionScope)
9239 uentry ue = sRef_getUentry (s);
9241 if (uentry_isAnyParam (ue)
9242 || uentry_isRefParam (ue))
9253 return (s->info->cvar->lexlevel > functionScope);
9261 bool sRef_isLocalParamVar (sRef s)
9263 if (sRef_isValid(s))
9265 return (s->kind == SK_PARAM
9266 || (s->kind == SK_CVAR
9267 && (s->info->cvar->lexlevel > fileScope)));
9273 static speckind speckind_fromInt (int i)
9276 llassert (i >= SR_NOTHING && i <= SR_SYSTEM);
9279 return ((speckind) i);
9283 static void sRef_updateNullState (sRef res, sRef other)
9286 res->nullstate = other->nullstate;
9287 res->nullinfo = stateInfo_update (res->nullinfo, other->nullinfo);
9290 void sRef_combineNullState (/*@notnull@*/ sRef res, /*@notnull@*/ sRef other)
9292 nstate n1 = sRef_getNullState (res);
9293 nstate n2 = sRef_getNullState (other);
9297 if (n1 == n2 || n2 == NS_UNKNOWN)
9303 /* note: n2 is not unknown or defnull */
9307 case NS_ERROR: nn = NS_ERROR; break;
9308 case NS_UNKNOWN: flip = TRUE; nn = n2; break;
9309 case NS_POSNULL: break;
9310 case NS_DEFNULL: nn = NS_POSNULL; break;
9311 case NS_RELNULL: break;
9313 if (n2 == NS_MNOTNULL)
9324 if (n2 == NS_NOTNULL)
9343 res->nullinfo = stateInfo_update (res->nullinfo, other->nullinfo);
9346 res->nullstate = nn;
9349 cstring sRef_nullMessage (sRef s)
9351 llassert (sRef_isValid (s));
9353 switch (sRef_getNullState (s))
9357 return (cstring_makeLiteralTemp ("null"));
9359 return (cstring_makeLiteralTemp ("possibly null"));
9364 /*@observer@*/ cstring sRef_ntMessage (sRef s)
9366 llassert (sRef_isValid (s));
9368 switch (s->nullstate)
9372 return (cstring_makeLiteralTemp ("not nullterminated"));
9374 return (cstring_makeLiteralTemp ("possibly non-nullterminated"));
9381 sRef sRef_fixResultType (/*@returned@*/ sRef s, ctype typ, uentry ue)
9383 sRef tmp = sRef_undefined;
9386 llassert (sRef_isValid (s));
9397 tmp = sRef_fixResultType (s->info->arrayfetch->arr, typ, ue);
9399 ct = ctype_realType (sRef_getType (tmp));
9402 if (ctype_isKnown (ct))
9404 if (ctype_isAP (ct))
9413 ("Special clause indexes non-array (%t): *%q",
9414 ct, sRef_unparse (s->info->arrayfetch->arr)),
9415 uentry_whereLast (ue));
9419 tmp = sRef_fixResultType (s->info->arrayfetch->arr, typ, ue);
9421 if (s->info->arrayfetch->indknown)
9423 ret = sRef_makeArrayFetchKnown (tmp, s->info->arrayfetch->ind);
9427 ret = sRef_makeArrayFetch (tmp);
9433 sRef rec = sRef_fixResultType (s->info->field->rec, typ, ue);
9434 ctype ct = ctype_realType (sRef_getType (rec));
9436 if (ctype_isKnown (ct))
9438 if (ctype_isSU (ct))
9440 if (uentry_isValid (uentryList_lookupField (ctype_getFields (ct),
9441 s->info->field->field)))
9450 ("Special clause accesses non-existent field of result: %q.%s",
9451 sRef_unparse (rec), s->info->field->field),
9452 uentry_whereLast (ue));
9460 ("Special clause accesses field of non-struct or union result (%t): %q.%s",
9461 ct, sRef_unparse (rec), s->info->field->field),
9462 uentry_whereLast (ue));
9466 ret = sRef_makeField (tmp, s->info->field->field);
9472 tmp = sRef_fixResultType (s->info->ref, typ, ue);
9474 ct = ctype_realType (sRef_getType (tmp));
9476 if (ctype_isKnown (ct))
9478 if (ctype_isAP (ct))
9487 ("Special clause dereferences non-pointer (%t): *%q",
9488 ct, sRef_unparse (s->info->ref)),
9489 uentry_whereLast (ue));
9493 ret = sRef_makePointer (tmp);
9500 ("Special clause uses & operator (not allowed): &%q", sRef_unparse (s->info->ref)),
9501 uentry_whereLast (ue));
9510 bool sRef_isOnly (sRef s)
9512 return (sRef_isValid(s) && alkind_isOnly (s->aliaskind));
9515 bool sRef_isDependent (sRef s)
9517 return (sRef_isValid(s) && alkind_isDependent (s->aliaskind));
9520 bool sRef_isOwned (sRef s)
9522 return (sRef_isValid (s) && (s->aliaskind == AK_OWNED));
9525 bool sRef_isKeep (sRef s)
9527 return (sRef_isValid (s) && (s->aliaskind == AK_KEEP));
9530 bool sRef_isTemp (sRef s)
9532 return (sRef_isValid (s) && alkind_isTemp (s->aliaskind));
9535 bool sRef_isLocalState (sRef s)
9537 return (sRef_isValid (s) && (s->aliaskind == AK_LOCAL));
9540 bool sRef_isUnique (sRef s)
9542 return (sRef_isValid (s) && (s->aliaskind == AK_UNIQUE));
9545 bool sRef_isShared (sRef s)
9547 return (sRef_isValid (s) && (s->aliaskind == AK_SHARED));
9550 bool sRef_isExposed (sRef s)
9552 return (sRef_isValid (s) && (s->expkind == XO_EXPOSED));
9555 bool sRef_isObserver (sRef s)
9557 return (sRef_isValid (s) && (s->expkind == XO_OBSERVER));
9560 bool sRef_isFresh (sRef s)
9562 return (sRef_isValid (s) && (s->aliaskind == AK_FRESH));
9565 bool sRef_isDefinitelyNull (sRef s)
9567 return (sRef_isValid (s) && (sRef_getNullState (s) == NS_DEFNULL
9568 || sRef_getNullState (s) == NS_CONSTNULL));
9571 bool sRef_isAllocated (sRef s)
9573 return (sRef_isValid (s) && (s->defstate == SS_ALLOCATED));
9576 bool sRef_isStack (sRef s)
9578 return (sRef_isValid (s) && (s->aliaskind == AK_STACK));
9581 bool sRef_isNotNull (sRef s)
9583 return (sRef_isValid(s) && (sRef_getNullState (s) == NS_MNOTNULL
9584 || sRef_getNullState (s) == NS_NOTNULL));
9587 alkind sRef_getAliasKind (sRef s)
9589 if (sRef_isValid(s)) {
9590 llassert (alkind_isValid (s->aliaskind));
9591 return s->aliaskind;
9597 nstate sRef_getNullState (sRef s)
9599 if (sRef_isValid (s)) {
9600 llassert (nstate_isValid (s->nullstate));
9601 return s->nullstate;
9607 void sRef_reflectAnnotation (sRef s, annotationInfo a, fileloc loc)
9609 if (sRef_isValid (s))
9611 if (!valueTable_isDefined (s->state))
9613 s->state = valueTable_create (1);
9614 valueTable_insert (s->state,
9615 cstring_copy (metaStateInfo_getName (annotationInfo_getState (a))),
9616 stateValue_create (annotationInfo_getValue (a), stateInfo_makeLoc (loc)));
9620 DPRINTF (("reflect loc: %s", fileloc_unparse (loc)));
9623 metaStateInfo_getName (annotationInfo_getState (a)),
9624 stateValue_create (annotationInfo_getValue (a), stateInfo_makeLoc (loc)));
9625 DPRINTF (("state info: %s", stateInfo_unparse (stateInfo_makeLoc (loc))));
9626 DPRINTF (("sref: %s", sRef_unparse (s)));
9627 DPRINTF (("sref: %s", sRef_unparseFull (s)));
9632 void sRef_setMetaStateValueComplete (sRef s, cstring key, int value, fileloc loc)
9634 sRefSet aliases = usymtab_allAliases (s);
9636 sRef_setMetaStateValue (s, key, value, loc);
9638 sRefSet_realElements (aliases, current)
9640 if (sRef_isValid (current))
9642 current = sRef_updateSref (current);
9643 sRef_setMetaStateValue (current, key, value, loc);
9645 } end_sRefSet_realElements ;
9647 sRefSet_free (aliases);
9650 void sRef_setMetaStateValue (sRef s, cstring key, int value, fileloc loc)
9652 sRef_checkMutable (s);
9654 if (sRef_isValid (s))
9656 if (!valueTable_isDefined (s->state))
9658 DPRINTF (("inserting state: %s: %s %d", sRef_unparse (s), key, value));
9659 s->state = valueTable_create (1);
9660 valueTable_insert (s->state, cstring_copy (key),
9661 stateValue_create (value, stateInfo_makeLoc (loc)));
9665 DPRINTF (("Updating state: %s: %s %d / %s", sRef_unparse (s), key, value,
9666 fileloc_unparse (loc)));
9667 if (valueTable_contains (s->state, key))
9670 (s->state, key, stateValue_create (value, stateInfo_makeLoc (loc)));
9675 (s->state, cstring_copy (key), stateValue_create (value, stateInfo_makeLoc (loc)));
9678 DPRINTF (("After: %s", sRef_unparseFull (s)));
9683 bool sRef_checkMetaStateValue (sRef s, cstring key, int value)
9685 if (sRef_isValid (s))
9687 if (valueTable_isDefined (s->state))
9691 DPRINTF (("check state: %s: %s %d", sRef_unparse (s), key, value));
9693 val = valueTable_lookup (s->state, key);
9694 llassert (stateValue_isDefined (val));
9695 return (stateValue_isError (val)
9696 || stateValue_getValue (val) == value);
9709 /*@observer@*/ stateValue sRef_getMetaStateValue (sRef s, cstring key)
9711 if (sRef_isValid (s))
9713 if (valueTable_isDefined (s->state))
9717 val = valueTable_lookup (s->state, key);
9718 /* Okay if its not defined, just returns stateValue_undefined */
9723 return stateValue_undefined;
9728 return stateValue_undefined;
9732 /*@observer@*/ valueTable sRef_getValueTable (sRef s)
9734 DPRINTF (("Get value table: %s", sRef_unparse (s)));
9736 if (sRef_isValid (s))
9738 llassert (sRef_isValid (s));
9739 DPRINTF (("Value table: %s", valueTable_unparse (s->state)));
9744 DPRINTF (("No value table!"));
9745 return valueTable_undefined;
9749 bool sRef_makeStateSpecial (sRef s)
9752 ** Default defined state can be made special.
9755 llassert (sRef_isValid (s)); /*@i523 why doesn't null-checking work!??? */
9757 if (s->defstate == SS_UNKNOWN || s->defstate == SS_DEFINED || s->defstate == SS_SPECIAL)
9759 s->aliaskind = AK_IMPTEMP;
9760 s->defstate = SS_SPECIAL;
9761 DPRINTF (("Made special: %s", sRef_unparseFull (s)));
9766 s->aliaskind = AK_IMPTEMP;
9767 s->defstate = SS_SPECIAL;
9772 void sRef_markImmutable (sRef s)
9774 if (sRef_isValid (s))
9776 DPRINTF (("Mark immutable: %s", sRef_unparseFull (s)));
9781 bool sRef_definitelyNullContext (sRef s)
9783 return (sRef_definitelyNull (s)
9784 || usymtab_isDefinitelyNullDeep (s));
9787 bool sRef_definitelyNullAltContext (sRef s)
9789 return (sRef_definitelyNull (s)
9790 || usymtab_isAltDefinitelyNullDeep (s));
9794 /* start modifications */
9795 struct s_bbufinfo sRef_getNullTerminatedState (sRef p_s) {
9796 struct s_bbufinfo BUFSTATE_UNKNOWN;
9797 BUFSTATE_UNKNOWN.bufstate = BB_NOTNULLTERMINATED;
9798 BUFSTATE_UNKNOWN.size = 0;
9799 BUFSTATE_UNKNOWN.len = 0;
9801 if (sRef_isValid(p_s))
9802 return p_s->bufinfo;
9803 return BUFSTATE_UNKNOWN;
9806 void sRef_setNullTerminatedState(sRef p_s) {
9807 if(sRef_isValid (p_s)) {
9808 p_s->bufinfo.bufstate = BB_NULLTERMINATED;
9810 llfatalbug( message("sRef_setNT passed a invalid sRef\n"));
9815 void sRef_setPossiblyNullTerminatedState(sRef p_s) {
9816 if( sRef_isValid (p_s)) {
9817 p_s->bufinfo.bufstate = BB_POSSIBLYNULLTERMINATED;
9819 llfatalbug( message("sRef_setPossNT passed a invalid sRef\n"));
9823 void sRef_setNotNullTerminatedState(sRef p_s) {
9824 if( sRef_isValid (p_s)) {
9825 p_s->bufinfo.bufstate = BB_NOTNULLTERMINATED;
9827 llfatalbug( message("sRef_unsetNT passed a invalid sRef\n"));
9831 void sRef_setLen(sRef p_s, int len) {
9832 if( sRef_isValid (p_s) && sRef_isNullTerminated(p_s)) {
9833 p_s->bufinfo.len = len;
9835 llfatalbug( message("sRef_setLen passed a invalid sRef\n"));
9840 void sRef_setSize(sRef p_s, int size) {
9841 if( sRef_isValid(p_s)) {
9842 p_s->bufinfo.size = size;
9844 llfatalbug( message("sRef_setSize passed a invalid sRef\n"));
9848 void sRef_resetLen(sRef p_s) {
9849 if (sRef_isValid (p_s)) {
9850 p_s->bufinfo.len = 0;
9852 llfatalbug (message ("sRef_setLen passed an invalid sRef\n"));
9856 /*drl7x 11/28/2000 */
9858 bool sRef_isFixedArray (sRef p_s) /*@*/ {
9860 c = sRef_getType (p_s);
9861 return ( ctype_isFixedArray (c) );
9864 long int sRef_getArraySize (sRef p_s) /*@*/ {
9866 llassert (sRef_isFixedArray(p_s) );
9867 DPRINTF (( message ("sRef_getArraySize getting array size for %s", sRef_unparse(p_s) ) ));
9869 c = sRef_getType (p_s);
9871 return (ctype_getArraySize (c) );