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) /*@*/ ;
66 static int sRef_depth (sRef p_s) /*@*/ ;
69 sRef_innerAliasSetComplete (void (p_predf) (sRef, fileloc), sRef p_s,
74 sRef_innerAliasSetCompleteParam (void (p_predf) (sRef, sRef), sRef p_s, sRef p_t)
77 static speckind speckind_fromInt (int p_i);
78 static bool sRef_equivalent (sRef p_s1, sRef p_s2);
79 static bool sRef_isDeepUnionField (sRef p_s);
80 static void sRef_addDeriv (/*@notnull@*/ sRef p_s, /*@notnull@*/ /*@exposed@*/ sRef p_t);
81 static bool sRef_checkModify (sRef p_s, sRefSet p_sl) /*@*/ ;
83 static void sRef_checkMutable (/*@unused@*/ sRef s)
86 if (sRef_isValid (s) && s->immut)
88 llcontbug (message ("Modification to sRef marked immutable: %q",
89 sRef_unparseFull (s)));
93 static bool skind_isSimple (skind sk)
97 case SK_PARAM: case SK_CVAR: case SK_CONST:
98 case SK_OBJECT: case SK_UNKNOWN: case SK_NEW:
105 static void sinfo_free (/*@special@*/ /*@temp@*/ /*@notnull@*/ sRef p_s)
106 /*@uses p_s->kind, p_s->info@*/
107 /*@releases p_s->info@*/ ;
109 static /*@null@*/ sinfo sinfo_copy (/*@notnull@*/ sRef p_s) /*@*/ ;
110 static void sRef_setPartsFromUentry (sRef p_s, uentry p_ue)
112 static bool checkDeadState (/*@notnull@*/ sRef p_el, bool p_tbranch, fileloc p_loc);
113 static /*@dependent@*/ sRef sRef_constructPointerAux (/*@notnull@*/ /*@exposed@*/ sRef p_t) /*@*/ ;
116 sRef_combineExKinds (/*@notnull@*/ sRef p_res, /*@notnull@*/ sRef p_other)
117 /*@modifies p_res@*/ ;
120 sRef_combineAliasKinds (/*@notnull@*/ sRef p_res, /*@notnull@*/ sRef p_other,
121 clause p_cl, fileloc p_loc)
122 /*@modifies p_res@*/ ;
125 sRef_combineNullState (/*@notnull@*/ sRef p_res, /*@notnull@*/ sRef p_other)
126 /*@modifies p_res@*/ ;
129 sRef_combineDefState (/*@notnull@*/ sRef p_res, /*@notnull@*/ sRef p_other)
130 /*@modifies p_res@*/ ;
132 static void sRef_setStateFromAbstractUentry (sRef p_s, uentry p_ue)
136 sinfo_update (/*@notnull@*/ /*@exposed@*/ sRef p_res,
137 /*@notnull@*/ /*@exposed@*/ sRef p_other);
138 static void sRef_setDefinedAux (sRef p_s, fileloc p_loc, bool p_clear)
140 static void sRef_setDefinedNoClear (sRef p_s, fileloc p_loc)
142 static void sRef_setStateAux (sRef p_s, sstate p_ss, fileloc p_loc)
145 static /*@exposed@*/ sRef
146 sRef_buildNCField (/*@exposed@*/ sRef p_rec, /*@exposed@*/ cstring p_f);
149 sRef_mergeStateAux (/*@notnull@*/ sRef p_res, /*@notnull@*/ sRef p_other,
150 clause p_cl, bool p_opt, fileloc p_loc,
152 /*@modifies p_res, p_other@*/ ;
154 static /*@null@*/ sinfo sinfo_fullCopy (/*@notnull@*/ sRef p_s);
155 static bool sRef_doModify (sRef p_s, sRefSet p_sl) /*@modifies p_s@*/ ;
156 static bool sRef_doModifyVal (sRef p_s, sRefSet p_sl) /*@modifies p_s@*/;
157 static bool sRef_checkModifyVal (sRef p_s, sRefSet p_sl) /*@*/ ;
159 static /*@only@*/ sRefSet
160 sRef_mergeDerivs (/*@only@*/ sRefSet p_res, sRefSet p_other,
161 bool p_opt, clause p_cl, fileloc p_loc);
163 static /*@only@*/ sRefSet
164 sRef_mergeUnionDerivs (/*@only@*/ sRefSet p_res,
165 /*@exposed@*/ sRefSet p_other,
166 bool p_opt, clause p_cl, fileloc p_loc);
168 static /*@only@*/ sRefSet
169 sRef_mergePdefinedDerivs (/*@only@*/ sRefSet p_res, sRefSet p_other, bool p_opt,
170 clause p_cl, fileloc p_loc);
172 static /*@only@*/ cstring sRef_unparseWithArgs (sRef p_s, uentryList p_args);
173 static /*@only@*/ cstring sRef_unparseNoArgs (sRef p_s);
175 static /*@exposed@*/ sRef sRef_findDerivedPointer (sRef p_s);
176 static /*@exposed@*/ sRef sRef_findDerivedArrayFetch (/*@notnull@*/ sRef, bool, int, bool) ;
177 static /*@exposed@*/ sRef sRef_findDerivedField (/*@notnull@*/ sRef p_rec, cstring p_f);
178 static /*@exposed@*/ sRef
179 sRef_getDeriv (/*@notnull@*/ /*@returned@*/ sRef p_set, sRef p_guide);
181 static bool inFunction = FALSE;
182 static /*@only@*/ sRefTable allRefs;
184 /* # define DEBUGREFS */
188 static totnsrefs = 0;
189 static maxnsrefs = 0;
190 static ntotrefers = 0;
194 static /*@checked@*/ bool protectDerivs = FALSE;
197 ** Result of sRef_alloc is dependent since allRefs may
198 ** reference it. It is only if !inFunction.
201 static /*@dependent@*/ /*@out@*/ /*@notnull@*/ sRef
204 sRef s = (sRef) dmalloc (sizeof (*s));
208 DPRINTF (("Alloc sref: [%p]", s));
212 allRefs = sRefTable_add (allRefs, s);
217 DPRINTF (("Not in function!"));
223 if (nsrefs >= maxnsrefs)
232 /*@-mustfree@*/ /*@-freshtrans@*/
234 /*@=mustfree@*/ /*@=freshtrans@*/
237 static void sRef_checkValidAux (sRef s, sRefSet checkedsofar)
241 if (!sRef_isValid (s)) return;
243 if (sRefSet_containsSameObject (checkedsofar, s))
249 checkedsofar = sRefSet_insert (checkedsofar, s);
250 /*@=temptrans@*/ /* checksofar will be destroyed before checkValid returns */
254 case SK_UNCONSTRAINED:
255 llassert (cstring_length (s->info->fname) < 100);
259 llassert (s->info->cvar->lexlevel >= 0);
260 /* llassert (s->info->cvar->lexlevel <= usymtab_getCurrentDepth ()); */
264 llassert (s->info->paramno >= -1);
265 llassert (s->info->paramno <= 50); /*@i32 bogus...*/
269 sRef_checkValidAux (s->info->arrayfetch->arr, checkedsofar);
273 sRef_checkValidAux (s->info->field->rec, checkedsofar);
274 llassert (cstring_length (s->info->field->field) < 100);
278 sRef_checkValidAux (s->info->ref, checkedsofar);
282 sRef_checkValidAux (s->info->ref, checkedsofar);
286 /* check ctype s->info->object */
290 sRef_checkValidAux (s->info->conj->a, checkedsofar);
291 sRef_checkValidAux (s->info->conj->b, checkedsofar);
295 llassert (cstring_length (s->info->fname) < 100);
299 sRef_checkValidAux (s->info->ref, checkedsofar);
303 sRef_checkValidAux (s->info->ref, checkedsofar);
309 /* check ctyp s->type */
313 llassert (s->info->spec == SR_NOTHING
314 || s->info->spec == SR_INTERNAL
315 || s->info->spec == SR_SPECSTATE
316 || s->info->spec == SR_SYSTEM);
326 sRefSet_elements (s->deriv, el)
328 sRef_checkValidAux (el, checkedsofar);
329 } end_sRefSet_elements ;
332 void sRef_checkValid (/*@unused@*/ sRef s)
336 sRefSet checkedsofar = sRefSet_new ();
337 sRef_checkValidAux (s, checkedsofar);
341 static /*@dependent@*/ /*@notnull@*/ /*@special@*/ sRef
344 /*@ensures isnull result->aliasinfo, result->definfo,
345 result->expinfo, result->info, result->deriv, result->state@*/
347 sRef s = sRef_alloc ();
349 s->kind = SK_UNKNOWN;
353 s->val = multiVal_undefined;
355 s->type = ctype_unknown;
356 s->defstate = SS_UNKNOWN;
358 /* start modifications */
359 s->bufinfo.bufstate = BB_NOTNULLTERMINATED;
360 /* end modifications */
362 s->aliaskind = AK_UNKNOWN;
363 s->oaliaskind = AK_UNKNOWN;
365 s->nullstate = NS_UNKNOWN;
367 s->expkind = XO_UNKNOWN;
368 s->oexpkind = XO_UNKNOWN;
370 s->aliasinfo = stateInfo_undefined;
371 s->definfo = stateInfo_undefined;
372 s->nullinfo = stateInfo_undefined;
373 s->expinfo = stateInfo_undefined;
376 s->deriv = sRefSet_undefined;
378 s->state = valueTable_undefined;
383 static /*@dependent@*/ /*@notnull@*/ /*@special@*/ sRef
386 /*@ensures isnull result->aliasinfo, result->definfo,
387 result->expinfo, result->info, result->deriv@*/
389 sRef res = sRef_new ();
391 res->state = valueTable_undefined;
396 void sRef_protectDerivs (void) /*@modifies protectDerivs@*/
398 llassert (!protectDerivs);
399 protectDerivs = TRUE;
402 void sRef_clearProtectDerivs (void) /*@modifies protectDerivs@*/
404 llassert (protectDerivs);
405 protectDerivs = FALSE;
409 ** hmmm...here be kind of a hack. This function mysteriously appeared
410 ** in my code, but I'm sure I didn't write it.
414 sRef_isRecursiveField (sRef s)
416 if (sRef_isField (s))
418 if (sRef_depth (s) > 13)
423 fieldname = sRef_getField (s);
424 base = sRef_getBase (s);
426 while (sRef_isValid (base))
428 if (sRef_isField (base))
430 if (cstring_equal (fieldname, sRef_getField (base)))
436 base = sRef_getBaseSafe (base);
445 sRef_addDeriv (/*@notnull@*/ sRef s, /*@notnull@*/ /*@exposed@*/ sRef t)
447 if (!context_inProtectVars ()
451 && !sRef_isConst (s))
453 int sd = sRef_depth (s);
454 int td = sRef_depth (t);
461 /* This sometimes fails: (evans 2001-07-12)
462 if (sRef_isArrayFetch (t))
464 DPRINTF (("Derived fetch: %s / %s / %s",
465 sRef_unparseFull (s), sRef_unparseFull (t),
466 sRef_unparseFull (t->info->arrayfetch->arr)));
467 llassert (t->info->arrayfetch->arr == s);
471 if (sRef_isFileOrGlobalScope (s))
473 if (context_inFunctionLike ()
474 && ctype_isKnown (sRef_getType (s))
475 && !ctype_isFunction (sRef_getType (s)))
477 globSet g = context_getUsedGlobs ();
479 if (!globSet_member (g, s))
482 ** don't report as a bug
486 (message ("sRef_addDeriv: global variable not in used "
487 "globs: %q / %s / %q",
489 ctype_unparse (sRef_getType (s)),
490 sRefSet_unparse (s->deriv)));
495 s->deriv = sRefSet_insert (s->deriv, t);
501 DPRINTF (("Add deriv: [%p] %s / [%p] %s",
503 t, sRef_unparse (t)));
505 s->deriv = sRefSet_insert (s->deriv, t);
511 sRef_deepPred (bool (predf) (sRef), sRef s)
513 if (sRef_isValid (s))
515 if ((*predf)(s)) return TRUE;
520 return (sRef_deepPred (predf, s->info->ref));
522 return (sRef_deepPred (predf, s->info->arrayfetch->arr));
524 return (sRef_deepPred (predf, s->info->field->rec));
526 return (sRef_deepPred (predf, s->info->conj->a)
527 || sRef_deepPred (predf, s->info->conj->b));
536 bool sRef_modInFunction (void)
541 void sRef_setStateFromType (sRef s, ctype ct)
543 if (sRef_isValid (s))
545 if (ctype_isUser (ct))
547 DPRINTF (("Here we are: %s", sRef_unparseFull (s)));
548 sRef_setStateFromUentry
549 (s, usymtab_getTypeEntry (ctype_typeId (ct)));
551 else if (ctype_isAbstract (ct))
553 DPRINTF (("Here we are: %s", sRef_unparseFull (s)));
554 sRef_setStateFromAbstractUentry
555 (s, usymtab_getTypeEntry (ctype_typeId (ct)));
559 ; /* not a user type */
564 static void sRef_setTypeState (sRef s)
566 if (sRef_isValid (s))
568 sRef_setStateFromType (s, s->type);
573 sRef_hasAliasInfoLoc (sRef s)
575 return (sRef_isValid (s) && (s->aliasinfo != NULL)
576 && (fileloc_isDefined (s->aliasinfo->loc)));
579 static /*@falsenull@*/ bool
580 sRef_hasStateInfoLoc (sRef s)
582 return (sRef_isValid (s) && (s->definfo != NULL)
583 && (fileloc_isDefined (s->definfo->loc)));
586 static /*@falsenull@*/ bool
587 sRef_hasExpInfoLoc (sRef s)
589 return (sRef_isValid (s)
590 && (s->expinfo != NULL) && (fileloc_isDefined (s->expinfo->loc)));
593 static /*@observer@*/ /*@unused@*/ stateInfo sRef_getInfo (sRef s, cstring key)
597 if (!sRef_isValid (s)) {
598 return stateInfo_undefined;
601 sv = valueTable_lookup (s->state, key);
603 if (stateValue_isDefined (sv))
605 return stateValue_getInfo (sv);
608 return stateInfo_undefined;
613 sRef_hasNullInfoLoc (sRef s)
615 return (sRef_isValid (s) && s->nullinfo != NULL
616 && (fileloc_isDefined (s->nullinfo->loc)));
620 sRef_hasAliasInfoRef (sRef s)
622 return (sRef_isValid (s) && (s->aliasinfo != NULL)
623 && (sRef_isValid (s->aliasinfo->ref)));
626 static /*@observer@*/ fileloc
627 sRef_getAliasInfoLoc (/*@exposed@*/ sRef s)
629 llassert (sRef_isValid (s) && s->aliasinfo != NULL
630 && (fileloc_isDefined (s->aliasinfo->loc)));
631 return (s->aliasinfo->loc);
634 static /*@observer@*/ fileloc
635 sRef_getStateInfoLoc (/*@exposed@*/ sRef s)
637 llassert (sRef_isValid (s) && s->definfo != NULL
638 && (fileloc_isDefined (s->definfo->loc)));
639 return (s->definfo->loc);
642 static /*@observer@*/ fileloc
643 sRef_getExpInfoLoc (/*@exposed@*/ sRef s)
645 llassert (sRef_isValid (s) && s->expinfo != NULL
646 && (fileloc_isDefined (s->expinfo->loc)));
647 return (s->expinfo->loc);
650 static /*@observer@*/ fileloc
651 sRef_getNullInfoLoc (/*@exposed@*/ sRef s)
653 llassert (sRef_isValid (s) && s->nullinfo != NULL
654 && (fileloc_isDefined (s->nullinfo->loc)));
655 return (s->nullinfo->loc);
659 sRef_getAliasInfoRef (/*@temp@*/ sRef s)
661 llassert (sRef_isValid (s) && s->aliasinfo != NULL);
662 return (s->aliasinfo->ref);
665 bool sRef_inGlobalScope ()
671 ** This function should be called before new sRefs are created
672 ** somewhere where they will have a lifetime greater than the
673 ** current function scope.
676 void sRef_setGlobalScope ()
678 llassert (inFunction);
679 DPRINTF (("leave function"));
683 void sRef_clearGlobalScope ()
685 llassert (!inFunction);
686 DPRINTF (("enter function"));
690 static bool oldInFunction = FALSE;
691 static int nestedScope = 0;
693 void sRef_setGlobalScopeSafe ()
695 if (nestedScope == 0)
697 oldInFunction = inFunction;
701 DPRINTF (("leave function safe"));
705 void sRef_clearGlobalScopeSafe ()
708 llassert (nestedScope >= 0);
710 if (nestedScope == 0)
712 inFunction = oldInFunction;
715 DPRINTF (("clear function: %s", bool_unparse (inFunction)));
718 void sRef_enterFunctionScope ()
720 llassert (!inFunction);
721 llassert (sRefTable_isEmpty (allRefs));
723 DPRINTF (("enter function"));
726 void sRef_exitFunctionScope ()
730 DPRINTF (("Exit function scope."));
731 sRefTable_clear (allRefs);
736 llbuglit ("sRef_exitFunctionScope: not in function");
740 void sRef_destroyMod () /*@globals killed allRefs;@*/
743 llmsg (message ("Live: %d / %d ", nsrefs, totnsrefs));
746 sRefTable_free (allRefs);
750 static /*@notnull@*/ /*@exposed@*/ sRef
751 sRef_fixConj (/*@notnull@*/ sRef s)
756 s = sRef_getConjA (s);
757 } while (sRef_isConj (s));
759 llassert (sRef_isValid (s));
760 return s; /* don't need to ref */
769 sRef_isExternallyVisibleAux (sRef s)
772 sRef base = sRef_getRootBase (s);
774 if (sRef_isValid (base))
776 res = sRef_isParam (base) || sRef_isFileOrGlobalScope (base) || sRef_isExternal (base);
783 sRef_isExternallyVisible (sRef s)
785 return (sRef_aliasCheckSimplePred (sRef_isExternallyVisibleAux, s));
789 sRef_getBaseUentry (sRef s)
791 sRef base = sRef_getRootBase (s);
792 uentry res = uentry_undefined;
794 if (sRef_isValid (base))
799 res = usymtab_getRefQuiet (paramsScope, base->info->paramno);
803 res = usymtab_getRefQuiet (base->info->cvar->lexlevel,
804 base->info->cvar->index);
816 ** lookup the current uentry corresponding to s, and return the corresponding sRef.
817 ** yuk yuk yuk yuk yuk yuk yuk yuk
821 sRef_updateSref (sRef s)
827 if (!sRef_isValid (s)) return sRef_undefined;
836 case SK_UNCONSTRAINED:
843 sRef r = sRef_updateSref (s->info->ref);
845 if (r != s->info->ref)
847 return sRef_makeExternal (r);
857 uentry ue = sRef_getUentry (s);
859 /* must be raw name! (need the marker) */
860 ue = usymtab_lookupSafe (uentry_rawName (ue));
862 if (uentry_isUndefined (ue))
868 DPRINTF (("Update sref: %s", uentry_unparseFull (ue)));
869 return (uentry_getSref (ue));
873 /* special case if ind known */
874 inner = s->info->arrayfetch->arr;
875 ret = sRef_updateSref (inner);
883 res = sRef_makeArrayFetch (ret);
889 inner = s->info->field->rec;
890 ret = sRef_updateSref (inner);
898 res = (sRef_makeField (ret, s->info->field->field));
903 inner = s->info->ref;
904 ret = sRef_updateSref (inner);
911 res = sRef_makePointer (ret);
917 inner = s->info->ref;
918 ret = sRef_updateSref (inner);
926 res = sRef_makeAddress (ret);
933 sRef innera = s->info->conj->a;
934 sRef innerb = s->info->conj->b;
935 sRef reta = sRef_updateSref (innera);
936 sRef retb = sRef_updateSref (innerb);
938 if (innera == reta && innerb == retb)
944 res = sRef_makeConj (reta, retb);
955 sRef_getUentry (sRef s)
957 llassert (sRef_isValid (s));
962 return (usymtab_getRefQuiet (paramsScope, s->info->paramno));
964 return (usymtab_getRefQuiet (s->info->cvar->lexlevel, s->info->cvar->index));
967 if (sRef_isCvar (s->info->conj->a) || sRef_isParam (s->info->conj->a)
968 || sRef_isConj (s->info->conj->a))
970 return sRef_getUentry (s->info->conj->a);
974 return sRef_getUentry (s->info->conj->b);
979 return uentry_undefined;
985 sRef_getParam (sRef s)
987 llassert (sRef_isValid (s));
988 llassert (s->kind == SK_PARAM);
990 return s->info->paramno;
994 sRef_isModified (sRef s)
996 return (!sRef_isValid (s) || s->modified);
999 void sRef_setModified (sRef s)
1001 if (sRef_isValid (s))
1006 if (sRef_isRefsField (s))
1008 sRef base = sRef_getBase (s);
1011 llassert (s->kind == SK_FIELD);
1014 if (sRef_isPointer (base))
1016 base = sRef_getBase (base);
1019 if (sRef_isRefCounted (base))
1021 base->aliaskind = AK_NEWREF;
1028 ** note: this side-effects sRefSet to set modified to TRUE
1029 ** for any sRef similar to s.
1033 sRef_canModifyVal (sRef s, sRefSet sl)
1035 if (context_getFlag (FLG_MUSTMOD))
1037 return (sRef_doModifyVal (s, sl));
1041 return (sRef_checkModifyVal (s, sl));
1046 sRef_canModify (sRef s, sRefSet sl)
1049 if (context_getFlag (FLG_MUSTMOD))
1051 return (sRef_doModify (s, sl));
1055 return (sRef_checkModify (s, sl));
1064 bool sRef_checkModifyVal (sRef s, sRefSet sl)
1066 DPRINTF (("Check modify val: %s", sRef_unparse (s)));
1068 if (sRef_isInvalid (s))
1075 case SK_UNCONSTRAINED:
1079 DPRINTF (("Modify var: %s", sRef_unparse (s)));
1081 if (sRef_isFileOrGlobalScope (s))
1083 if (context_checkGlobMod (s))
1085 return (sRefSet_member (sl, s));
1095 return (sRefSet_member (sl, s)
1096 || alkind_isOnly (sRef_getOrigAliasKind (s)));
1098 /* special case if ind known */
1099 return (sRefSet_member (sl, s) ||
1100 sRef_checkModifyVal (s->info->arrayfetch->arr, sl));
1102 return (sRefSet_member (sl, s) || sRef_checkModifyVal (s->info->field->rec, sl));
1104 return (sRefSet_member (sl, s) || sRef_checkModifyVal (s->info->ref, sl));
1106 return (sRefSet_member (sl, s) || sRef_checkModifyVal (s->info->ref, sl));
1108 return ((sRef_checkModifyVal (s->info->conj->a, sl)) &&
1109 (sRef_checkModifyVal (s->info->conj->b, sl)));
1120 switch (s->info->spec)
1122 case SR_NOTHING: return TRUE;
1124 if (context_getFlag (FLG_INTERNALGLOBS))
1126 return (sRefSet_member (sl, s));
1132 case SR_SPECSTATE: return TRUE;
1133 case SR_SYSTEM: return (sRefSet_member (sl, s));
1134 case SR_GLOBALMARKER: BADBRANCH;
1137 case SK_RESULT: BADBRANCH;
1143 ** this should probably be elsewhere...
1145 ** returns TRUE iff sl indicates that s can be modified
1148 static bool sRef_checkModify (sRef s, sRefSet sl)
1150 llassert (sRef_isValid (s));
1154 case SK_UNCONSTRAINED:
1158 if (sRef_isFileOrGlobalScope (s))
1160 if (context_checkGlobMod (s))
1162 return (sRefSet_member (sl, s));
1174 return (sRefSet_member (sl, s) ||
1175 sRef_checkModifyVal (s->info->arrayfetch->arr, sl));
1178 sRef sr = s->info->field->rec;
1180 if (sr->kind == SK_PARAM)
1181 return TRUE; /* structs are copied on call */
1183 return (sRefSet_member (sl, s) || sRef_checkModifyVal (s->info->field->rec, sl));
1189 sm = sRefSet_member (sl, s);
1194 return (sRef_checkModifyVal (s->info->ref, sl));
1197 return (sRefSet_member (sl, s) || sRef_checkModifyVal (s->info->ref, sl));
1199 return ((sRef_checkModify (s->info->conj->a, sl)) &&
1200 (sRef_checkModify (s->info->conj->b, sl)));
1210 switch (s->info->spec)
1212 case SR_NOTHING: return TRUE;
1214 if (context_getFlag (FLG_INTERNALGLOBS))
1216 return (sRefSet_member (sl, s));
1222 case SR_SPECSTATE: return TRUE;
1223 case SR_SYSTEM: return (sRefSet_member (sl, s));
1224 case SR_GLOBALMARKER: BADBRANCH;
1227 case SK_RESULT: BADBRANCH;
1232 cstring sRef_stateVerb (sRef s)
1234 if (sRef_isDead (s))
1236 return cstring_makeLiteralTemp ("released");
1238 else if (sRef_isKept (s))
1240 return cstring_makeLiteralTemp ("kept");
1242 else if (sRef_isDependent (s))
1244 return cstring_makeLiteralTemp ("dependent");
1252 cstring sRef_stateAltVerb (sRef s)
1254 if (sRef_isDead (s))
1256 return cstring_makeLiteralTemp ("live");
1258 else if (sRef_isKept (s))
1260 return cstring_makeLiteralTemp ("not kept");
1262 else if (sRef_isDependent (s))
1264 return cstring_makeLiteralTemp ("independent");
1273 bool sRef_doModifyVal (sRef s, sRefSet sl)
1275 llassert (sRef_isValid (s));
1280 case SK_UNCONSTRAINED:
1284 if (sRef_isFileOrGlobalScope (s))
1287 if (context_checkGlobMod (s))
1289 return (sRefSet_modifyMember (sl, s));
1293 (void) sRefSet_modifyMember (sl, s);
1303 return (sRefSet_modifyMember (sl, s)
1304 || alkind_isOnly (sRef_getOrigAliasKind (s)));
1306 /* special case if ind known */
1307 /* unconditional OR, need side effect */
1308 return (OR (sRefSet_modifyMember (sl, s),
1309 sRef_doModifyVal (s->info->arrayfetch->arr, sl)));
1311 return (OR (sRefSet_modifyMember (sl, s),
1312 sRef_doModifyVal (s->info->field->rec, sl)));
1314 return (OR (sRefSet_modifyMember (sl, s),
1315 sRef_doModifyVal (s->info->ref, sl)));
1317 return (OR (sRefSet_modifyMember (sl, s),
1318 sRef_doModifyVal (s->info->ref, sl)));
1320 return (AND (sRef_doModifyVal (s->info->conj->a, sl) ,
1321 sRef_doModifyVal (s->info->conj->b, sl)));
1331 switch (s->info->spec)
1333 case SR_NOTHING: return TRUE;
1335 if (context_getFlag (FLG_INTERNALGLOBS))
1337 return (sRefSet_modifyMember (sl, s));
1341 (void) sRefSet_modifyMember (sl, s);
1344 case SR_SPECSTATE: return TRUE;
1345 case SR_SYSTEM: return (sRefSet_modifyMember (sl, s));
1346 case SR_GLOBALMARKER: BADBRANCH;
1350 case SK_RESULT: BADBRANCH;
1356 ** this should probably be elsewhere...
1358 ** returns TRUE iff sl indicates that s can be modified
1362 bool sRef_doModify (sRef s, sRefSet sl)
1364 llassert (sRef_isValid (s));
1368 case SK_UNCONSTRAINED:
1372 if (sRef_isFileOrGlobalScope (s))
1374 if (context_checkGlobMod (s))
1376 return (sRefSet_modifyMember (sl, s));
1380 (void) sRefSet_modifyMember (sl, s);
1392 return (OR (sRefSet_modifyMember (sl, s),
1393 sRef_doModifyVal (s->info->arrayfetch->arr, sl)));
1396 sRef sr = s->info->field->rec;
1398 if (sr->kind == SK_PARAM)
1400 return TRUE; /* structs are shallow-copied on call */
1403 return (OR (sRefSet_modifyMember (sl, s),
1404 sRef_doModifyVal (s->info->field->rec, sl)));
1408 return (OR (sRefSet_modifyMember (sl, s),
1409 sRef_doModifyVal (s->info->ref, sl)));
1412 return (OR (sRefSet_modifyMember (sl, s),
1413 sRef_doModifyVal (s->info->ref, sl)));
1415 return (AND (sRef_doModify (s->info->conj->a, sl),
1416 (sRef_doModify (s->info->conj->b, sl))));
1427 switch (s->info->spec)
1429 case SR_NOTHING: return TRUE;
1430 case SR_INTERNAL: return TRUE;
1431 case SR_SPECSTATE: return TRUE;
1432 case SR_SYSTEM: return (sRefSet_modifyMember (sl, s));
1433 case SR_GLOBALMARKER: BADBRANCH;
1436 case SK_RESULT: BADBRANCH;
1441 static /*@exposed@*/ sRef
1442 sRef_leastCommon (/*@exposed@*/ sRef s1, sRef s2)
1444 llassert (sRef_similar (s1, s2));
1446 if (!sRef_isValid (s1)) return s1;
1447 if (!sRef_isValid (s2)) return s1;
1449 sRef_combineDefState (s1, s2);
1450 sRef_combineNullState (s1, s2);
1451 sRef_combineExKinds (s1, s2);
1453 if (s1->aliaskind != s2->aliaskind)
1455 if (s1->aliaskind == AK_UNKNOWN)
1457 s1->aliaskind = s2->aliaskind;
1459 else if (s2->aliaskind == AK_UNKNOWN)
1465 s1->aliaskind = AK_ERROR;
1472 int sRef_compare (sRef s1, sRef s2)
1474 if (s1 == s2) return 0;
1476 if (sRef_isInvalid (s1)) return -1;
1477 if (sRef_isInvalid (s2)) return 1;
1479 INTCOMPARERETURN (s1->kind, s2->kind);
1480 INTCOMPARERETURN (s1->defstate, s2->defstate);
1481 INTCOMPARERETURN (s1->aliaskind, s2->aliaskind);
1483 DPRINTF (("Compare null state: %s / %s",
1484 sRef_unparseFull (s1),
1485 sRef_unparseFull (s2)));
1487 COMPARERETURN (nstate_compare (sRef_getNullState (s1),
1488 sRef_getNullState (s2)));
1493 return (int_compare (s1->info->paramno, s2->info->paramno));
1496 COMPARERETURN (sRef_compare (s1->info->arrayfetch->arr,
1497 s2->info->arrayfetch->arr));
1499 if (s1->info->arrayfetch->indknown && s2->info->arrayfetch->indknown)
1501 return (int_compare (s1->info->arrayfetch->ind,
1502 s2->info->arrayfetch->ind));
1504 if (!s1->info->arrayfetch->indknown && !s2->info->arrayfetch->indknown)
1511 COMPARERETURN (sRef_compare (s1->info->field->rec, s2->info->field->rec));
1513 if (cstring_equal (s1->info->field->field, s2->info->field->field))
1520 return (sRef_compare (s1->info->ref, s2->info->ref));
1522 COMPARERETURN (sRef_compare (s1->info->conj->a, s2->info->conj->a));
1523 return (sRef_compare (s1->info->conj->b, s2->info->conj->b));
1524 case SK_UNCONSTRAINED:
1525 return (cstring_compare (s1->info->fname, s2->info->fname));
1537 return (generic_compare (s1->info->spec, s2->info->spec));
1542 static bool cref_equal (cref c1, cref c2)
1544 return ((c1->lexlevel == c2->lexlevel) &&
1545 (usymId_equal (c1->index, c2->index)));
1549 ** returns true if s1 could be the same storage as s2.
1550 ** i.e., a[?] ~ a[3]. Note its not symmetric ... s1
1551 ** should be more specific.
1555 ** like similar, but matches objects <-> non-objects
1559 sRef_uniqueReference (sRef s)
1561 return (sRef_isFresh (s) || sRef_isUnique (s)
1562 || sRef_isOnly (s) || sRef_isStack (s)
1563 || sRef_isAddress (s));
1567 sRef_similarRelaxedAux (sRef s1, sRef s2)
1571 if (sRef_isUnknownArrayFetch (s1))
1581 if (sRef_isInvalid (s1) || sRef_isInvalid (s2)) return FALSE;
1583 if (sRef_isConj (s2))
1584 return (sRef_similarRelaxedAux (s1, sRef_getConjA (s2)) ||
1585 sRef_similarRelaxedAux (s1, sRef_getConjB (s2)));
1590 return ((s2->kind == SK_CVAR)
1591 && (cref_equal (s1->info->cvar, s2->info->cvar)));
1593 return ((s2->kind == SK_PARAM)
1594 && (s1->info->paramno == s2->info->paramno));
1596 if (s2->kind == SK_ARRAYFETCH)
1598 if (sRef_similarRelaxedAux (s1->info->arrayfetch->arr,
1599 s2->info->arrayfetch->arr))
1601 if (s1->info->arrayfetch->indknown)
1603 if (s2->info->arrayfetch->indknown)
1605 return (s1->info->arrayfetch->ind == s2->info->arrayfetch->ind);
1620 return ((s2->kind == SK_FIELD
1621 && (sRef_similarRelaxedAux (s1->info->field->rec,
1622 s2->info->field->rec)
1623 && cstring_equal (s1->info->field->field,
1624 s2->info->field->field))));
1626 return ((s2->kind == SK_PTR)
1627 && sRef_similarRelaxedAux (s1->info->ref, s2->info->ref));
1629 return ((s2->kind == SK_ADR)
1630 && sRef_similarRelaxedAux (s1->info->ref, s2->info->ref));
1632 return ((sRef_similarRelaxedAux (s1->info->conj->a, s2) ||
1633 (sRef_similarRelaxedAux (s1->info->conj->b, s2))));
1635 return (s1->info->spec == s2->info->spec);
1636 case SK_UNCONSTRAINED:
1637 return (cstring_equal (s1->info->fname, s2->info->fname));
1652 sRef_similarRelaxed (sRef s1, sRef s2)
1658 if (sRef_isThroughArrayFetch (s1))
1668 if (sRef_isInvalid (s1) || sRef_isInvalid (s2)) return FALSE;
1670 us1 = sRef_uniqueReference (s1);
1671 us2 = sRef_uniqueReference (s2);
1673 if ((s1->kind == SK_EXTERNAL && (s2->kind != SK_EXTERNAL && !us2))
1674 || (s2->kind == SK_EXTERNAL && (s1->kind != SK_EXTERNAL && !us1)))
1677 ** Previously, also:
1678 ** || (sRef_isExposed (s1) && !us2) || (sRef_isExposed (s2) && !us1)) ????
1680 ** No clue why this was there?!
1684 if (sRef_isExposed (s1) && sRef_isCvar (s1))
1686 uentry ue1 = sRef_getUentry (s1);
1688 if (uentry_isRefParam (ue1))
1690 return sRef_similarRelaxedAux (s1, s2);
1694 if (sRef_isExposed (s2) && sRef_isCvar (s2))
1696 uentry ue2 = sRef_getUentry (s2);
1698 if (uentry_isRefParam (ue2))
1700 return sRef_similarRelaxedAux (s1, s2);
1704 return (ctype_match (s1->type, s2->type));
1708 return sRef_similarRelaxedAux (s1, s2);
1713 sRef_similar (sRef s1, sRef s2)
1715 if (s1 == s2) return TRUE;
1716 if (sRef_isInvalid (s1) || sRef_isInvalid (s2)) return FALSE;
1718 if (sRef_isConj (s2))
1720 return (sRef_similar (s1, sRef_getConjA (s2)) ||
1721 sRef_similar (s1, sRef_getConjB (s2)));
1724 if (sRef_isDerived (s2))
1726 return (sRef_includedBy (s1, s2->info->ref));
1732 return ((s2->kind == SK_CVAR)
1733 && (cref_equal (s1->info->cvar, s2->info->cvar)));
1735 return ((s2->kind == SK_PARAM)
1736 && (s1->info->paramno == s2->info->paramno));
1738 if (s2->kind == SK_ARRAYFETCH)
1740 if (sRef_similar (s1->info->arrayfetch->arr,
1741 s2->info->arrayfetch->arr))
1743 if (s1->info->arrayfetch->indknown)
1745 if (s2->info->arrayfetch->indknown)
1747 return (s1->info->arrayfetch->ind == s2->info->arrayfetch->ind);
1762 if (s2->kind == SK_PTR)
1764 if (sRef_similar (s1->info->arrayfetch->arr,
1774 return ((s2->kind == SK_FIELD
1775 && (sRef_similar (s1->info->field->rec,
1776 s2->info->field->rec)
1777 && cstring_equal (s1->info->field->field,
1778 s2->info->field->field))));
1780 if (s2->kind == SK_PTR)
1782 return sRef_similar (s1->info->ref, s2->info->ref);
1786 if (s2->kind == SK_ARRAYFETCH)
1788 if (sRef_similar (s2->info->arrayfetch->arr,
1798 return ((s2->kind == SK_ADR)
1799 && sRef_similar (s1->info->ref, s2->info->ref));
1801 return ((sRef_similar (s1->info->conj->a, s2) ||
1802 (sRef_similar (s1->info->conj->b, s2))));
1804 return (sRef_includedBy (s2, s1->info->ref));
1805 case SK_UNCONSTRAINED:
1806 return (s2->kind == SK_UNCONSTRAINED
1807 && cstring_equal (s1->info->fname, s2->info->fname));
1817 return (s2->kind == SK_SPECIAL
1818 && (s1->info->spec == s2->info->spec));
1821 /*@notreached@*/ DPRINTF (("Fell through for: %s / %s", sRef_unparse (s1), sRef_unparse (s2)));
1826 ** return TRUE iff small can be derived from big.
1828 ** (e.g. x, x.a is includedBy x;
1829 ** x.a is included By x.a;
1833 sRef_includedBy (sRef small, sRef big)
1835 if (small == big) return TRUE;
1836 if (sRef_isInvalid (small) || sRef_isInvalid (big)) return FALSE;
1838 if (sRef_isConj (big))
1839 return (sRef_similar (small, sRef_getConjA (big)) ||
1840 sRef_similar (small, sRef_getConjB (big)));
1842 switch (small->kind)
1846 return (sRef_same (small, big));
1848 if (big->kind == SK_ARRAYFETCH)
1850 if (sRef_same (small->info->arrayfetch->arr, big->info->arrayfetch->arr))
1852 if (small->info->arrayfetch->indknown)
1854 if (big->info->arrayfetch->indknown)
1856 return (small->info->arrayfetch->ind == big->info->arrayfetch->ind);
1869 return (sRef_includedBy (small->info->arrayfetch->arr, big));
1871 if (big->kind == SK_FIELD)
1874 (sRef_same (small->info->field->rec, big->info->field->rec) &&
1875 cstring_equal (small->info->field->field, big->info->field->field));
1879 return (sRef_includedBy (small->info->field->rec, big));
1883 if (big->kind == SK_PTR)
1885 return sRef_same (small->info->ref, big->info->ref);
1889 return (sRef_includedBy (small->info->ref, big));
1893 return ((big->kind == SK_ADR) && sRef_similar (small->info->ref, big->info->ref));
1895 return ((sRef_includedBy (small->info->conj->a, big) ||
1896 (sRef_includedBy (small->info->conj->b, big))));
1898 return (sRef_includedBy (small->info->ref, big));
1899 case SK_UNCONSTRAINED:
1909 switch (small->info->spec)
1911 case SR_NOTHING: return TRUE;
1913 case SR_INTERNAL: return (sRef_isSpecInternalState (big) ||
1914 sRef_isFileStatic (big));
1915 case SR_SYSTEM: return (sRef_isSystemState (big));
1916 case SR_GLOBALMARKER: BADBRANCH;
1923 ** Same is similar to similar, but not quite the same.
1924 ** same and realSame aren't the same, but they are really similar.
1925 ** similarly, same is the same as same. but realSame is
1926 ** not really the same as same, or similar to similar.
1928 ** Similarly to similar, same checks if two sRefs are the same.
1929 ** The similarities end, however, when same compares arrays
1930 ** with unknown indexes. Similar returns false; same returns true.
1932 ** Similarly to similar and same, realSame is the same as same,
1933 ** except they do not behave the same when face with unknown
1934 ** sRefs. Same thinks they are not the same, but realSame thinks
1940 sRef_realSame (sRef s1, sRef s2)
1942 if (s1 == s2) return TRUE;
1943 if (sRef_isInvalid (s1) || sRef_isInvalid (s2)) return FALSE;
1948 return ((s2->kind == SK_CVAR) && (cref_equal (s1->info->cvar, s2->info->cvar)));
1950 return ((s2->kind == SK_PARAM) && (s1->info->paramno == s2->info->paramno));
1952 if (s2->kind == SK_ARRAYFETCH)
1954 if (sRef_realSame (s1->info->arrayfetch->arr, s2->info->arrayfetch->arr))
1956 if (s1->info->arrayfetch->indknown && s2->info->arrayfetch->indknown)
1958 return (s1->info->arrayfetch->ind == s2->info->arrayfetch->ind);
1960 if (!s1->info->arrayfetch->indknown && !s2->info->arrayfetch->indknown)
1969 return ((s2->kind == SK_FIELD &&
1970 (sRef_realSame (s1->info->field->rec, s2->info->field->rec) &&
1971 cstring_equal (s1->info->field->field, s2->info->field->field))));
1973 return ((s2->kind == SK_PTR) && sRef_realSame (s1->info->ref, s2->info->ref));
1975 return ((s2->kind == SK_ADR) && sRef_realSame (s1->info->ref, s2->info->ref));
1977 return ((sRef_realSame (s1->info->conj->a, s2) ||
1978 (sRef_realSame (s1->info->conj->b, s2))));
1980 return ((s2->kind == SK_OBJECT)
1981 && ctype_match (s1->info->object, s2->info->object));
1983 return ((s2->kind == SK_EXTERNAL)
1984 && sRef_realSame (s1->info->ref, s2->info->ref));
1986 return ((s2->kind == SK_SPECIAL) && s1->info->spec == s2->info->spec);
1988 return ((s2->kind == SK_DERIVED) && sRef_realSame (s1->info->ref, s2->info->ref));
1989 case SK_UNCONSTRAINED:
1990 return ((s2->kind == SK_UNCONSTRAINED)
1991 && (cstring_equal (s1->info->fname, s2->info->fname)));
1997 return TRUE; /* changed this! was false */
2003 sRef_sameObject (sRef s1, sRef s2)
2009 ** same is similar to similar, but not quite the same.
2011 ** Similarly to similar, same checks is two sRefs are the same.
2012 ** The similarities end, however, when same compares arrays
2013 ** with unknown indexes. Similar returns false; same returns true.
2017 sRef_same (sRef s1, sRef s2)
2019 if (s1 == s2) return TRUE;
2020 if (sRef_isInvalid (s1) || sRef_isInvalid (s2)) return FALSE;
2025 return ((s2->kind == SK_CVAR) && (cref_equal (s1->info->cvar, s2->info->cvar)));
2027 return ((s2->kind == SK_PARAM) && (s1->info->paramno == s2->info->paramno));
2029 if (s2->kind == SK_ARRAYFETCH)
2031 llassert (s1->info->field->rec != s1);
2032 if (sRef_same (s1->info->arrayfetch->arr, s2->info->arrayfetch->arr))
2034 if (s1->info->arrayfetch->indknown && s2->info->arrayfetch->indknown)
2036 return (s1->info->arrayfetch->ind == s2->info->arrayfetch->ind);
2044 llassert (s1->info->field->rec != s1);
2045 return ((s2->kind == SK_FIELD &&
2046 (sRef_same (s1->info->field->rec, s2->info->field->rec) &&
2047 cstring_equal (s1->info->field->field, s2->info->field->field))));
2051 llassert (s1->info->ref != s1);
2052 return ((s2->kind == SK_PTR) && sRef_same (s1->info->ref, s2->info->ref));
2056 llassert (s1->info->ref != s1);
2057 return ((s2->kind == SK_ADR) && sRef_same (s1->info->ref, s2->info->ref));
2060 llassert (s1->info->conj->a != s1);
2061 llassert (s1->info->conj->b != s1);
2062 return ((sRef_same (s1->info->conj->a, s2)) && /* or or and? */
2063 (sRef_same (s1->info->conj->b, s2)));
2065 return ((s2->kind == SK_SPECIAL) && s1->info->spec == s2->info->spec);
2067 llassert (s1->info->ref != s1);
2068 return ((s2->kind == SK_DERIVED) && sRef_same (s1->info->ref, s2->info->ref));
2070 case SK_UNCONSTRAINED:
2083 ** sort of similar, for use in def/use
2087 sRef_closeEnough (sRef s1, sRef s2)
2089 if (s1 == s2) return TRUE;
2090 if (sRef_isInvalid (s1) || sRef_isInvalid (s2)) return FALSE;
2095 return (((s2->kind == SK_CVAR) &&
2096 (cref_equal (s1->info->cvar, s2->info->cvar))) ||
2097 (s2->kind == SK_UNCONSTRAINED && s1->info->cvar->lexlevel == 0));
2098 case SK_UNCONSTRAINED:
2099 return (s2->kind == SK_UNCONSTRAINED
2100 || ((s2->kind == SK_CVAR) && (s2->info->cvar->lexlevel == 0)));
2102 return ((s2->kind == SK_PARAM)
2103 && (s1->info->paramno == s2->info->paramno));
2105 if (s2->kind == SK_ARRAYFETCH)
2107 if (sRef_closeEnough (s1->info->arrayfetch->arr, s2->info->arrayfetch->arr))
2109 if (s1->info->arrayfetch->indknown && s2->info->arrayfetch->indknown)
2111 return (s1->info->arrayfetch->ind == s2->info->arrayfetch->ind);
2118 return ((s2->kind == SK_FIELD &&
2119 (sRef_closeEnough (s1->info->field->rec, s2->info->field->rec) &&
2120 cstring_equal (s1->info->field->field, s2->info->field->field))));
2122 return ((s2->kind == SK_PTR) && sRef_closeEnough (s1->info->ref, s2->info->ref));
2124 return ((s2->kind == SK_ADR) && sRef_closeEnough (s1->info->ref, s2->info->ref));
2126 return ((s2->kind == SK_DERIVED) && sRef_closeEnough (s1->info->ref, s2->info->ref));
2128 return ((sRef_closeEnough (s1->info->conj->a, s2)) ||
2129 (sRef_closeEnough (s1->info->conj->b, s2)));
2131 return ((s2->kind == SK_SPECIAL) && s1->info->spec == s2->info->spec);
2147 s is an sRef of a formal paramenter in a function call constraint
2148 we trys to return a constraint expression derived from the actual parementer of a function call.
2151 /*@only@*/ constraintExpr sRef_fixConstraintParam (/*@observer@*/ sRef s, /*@observer@*/ /*@temp@*/ exprNodeList args)
2155 if (sRef_isInvalid (s))
2156 llfatalbug((message("Invalid sRef")));
2162 /* s = sRef_saveCopy(s); */ /*@i523@*/
2163 ce = constraintExpr_makeTermsRef (s);
2170 temp = (sRef_makeField (sRef_fixBaseParam (s->info->field->rec, args),
2171 s->info->field->field));
2172 ce = constraintExpr_makeTermsRef (temp);
2178 temp = (sRef_makePointer (sRef_fixBaseParam (s->info->ref, args)));
2179 /* temp = sRef_saveCopy(temp); */ /*@i523@*/
2180 ce = constraintExpr_makeTermsRef (temp);
2187 temp = sRef_saveCopy(s);
2188 temp = sRef_fixBaseParam (temp, args);
2189 ce = constraintExpr_makeTermsRef (temp);
2197 temp = sRef_saveCopy(s);
2198 ce = constraintExpr_makeTermsRef (temp);
2203 llassert(exprNodeList_size (args) > s->info->paramno);
2205 exprNode e = exprNodeList_nth (args, s->info->paramno);
2207 llassert( !(exprNode_isError (e)) );
2208 ce = constraintExpr_makeExprNode (e);
2215 llcontbug (message ("Trying to do fixConstraintParam on nonparam, nonglobal: %q for function with arguments %q",
2216 sRef_unparse (s), exprNodeList_unparse(args)));
2217 temp = sRef_saveCopy(s);
2218 ce = constraintExpr_makeTermsRef (temp);
2230 sRef_fixBaseParam (/*@returned@*/ sRef s, exprNodeList args)
2232 if (sRef_isInvalid (s)) return (sRef_undefined);
2236 case SK_UNCONSTRAINED:
2241 if (exprNodeList_size (args) > s->info->paramno)
2243 exprNode e = exprNodeList_nth (args, s->info->paramno);
2245 if (exprNode_isError (e))
2247 return sRef_makeUnknown ();
2250 return (exprNode_getSref (e));
2254 return sRef_makeUnknown ();
2259 if (s->info->arrayfetch->indknown)
2261 return (sRef_makeArrayFetchKnown
2262 (sRef_fixBaseParam (s->info->arrayfetch->arr, args),
2263 s->info->arrayfetch->ind));
2267 return (sRef_makeArrayFetch
2268 (sRef_fixBaseParam (s->info->arrayfetch->arr, args)));
2271 return (sRef_makeField (sRef_fixBaseParam (s->info->field->rec, args),
2272 s->info->field->field));
2275 return (sRef_makePointer (sRef_fixBaseParam (s->info->ref, args)));
2278 return (sRef_makeAddress (sRef_fixBaseParam (s->info->ref, args)));
2281 return (sRef_makeConj (sRef_fixBaseParam (s->info->conj->a, args),
2282 sRef_fixBaseParam (s->info->conj->b, args)));
2298 sRef_undumpGlobal (char **c)
2308 usymId uid = usymId_fromInt (reader_getInt (c));
2313 reader_checkChar (c, '@');
2314 defstate = sstate_fromInt (reader_getInt (c));
2316 reader_checkChar (c, '@');
2317 nullstate = nstate_fromInt (reader_getInt (c));
2319 ret = sRef_makeGlobal (uid, ctype_unknown, stateInfo_currentLoc ());
2320 sRef_setNullStateN (ret, nullstate);
2321 ret->defstate = defstate;
2326 int i = reader_getInt (c);
2327 speckind sk = speckind_fromInt (i);
2331 case SR_NOTHING: return (sRef_makeNothing ());
2332 case SR_INTERNAL: return (sRef_makeInternalState ());
2333 case SR_SPECSTATE: return (sRef_makeSpecState ());
2334 case SR_SYSTEM: return (sRef_makeSystemState ());
2335 case SR_GLOBALMARKER: BADBRANCH;
2340 return sRef_undefined;
2342 return sRef_makeUnknown ();
2344 return sRef_makeUnknown ();
2346 llfatalerror (message ("sRef_undumpGlobal: bad line: %s",
2347 cstring_fromChars (*c)));
2352 static /*@exposed@*/ sRef sRef_undumpBody (char **c)
2361 return (sRef_makeGlobal (usymId_fromInt (reader_getInt (c)), ctype_unknown, stateInfo_currentLoc ()));
2363 return (sRef_makeParam (reader_getInt (c), ctype_unknown, stateInfo_makeLoc (g_currentloc)));
2365 return (sRef_makeResult (ctype_undump (c)));
2368 if ((**c >= '0' && **c <= '9') || **c == '-')
2370 int i = reader_getInt (c);
2371 sRef arr = sRef_undump (c);
2372 sRef ret = sRef_buildArrayFetchKnown (arr, i);
2378 sRef arr = sRef_undump (c);
2379 sRef ret = sRef_buildArrayFetch (arr);
2386 cstring fname = cstring_undefined;
2391 fname = cstring_appendChar (fname, **c);
2396 ret = sRef_buildField (sRef_undump (c), fname);
2397 cstring_markOwned (fname);
2402 int i = reader_getInt (c);
2403 speckind sk = speckind_fromInt (i);
2407 case SR_NOTHING: return (sRef_makeNothing ());
2408 case SR_INTERNAL: return (sRef_makeInternalState ());
2409 case SR_SPECSTATE: return (sRef_makeSpecState ());
2410 case SR_SYSTEM: return (sRef_makeSystemState ());
2411 case SR_GLOBALMARKER: BADBRANCH;
2417 sRef ptr = sRef_undump (c);
2418 sRef ret = sRef_makePointer (ptr);
2424 sRef adr = sRef_undump (c);
2425 sRef ret = sRef_makeAddress (adr);
2431 return (sRef_makeObject (ctype_undump (c)));
2435 sRef s1 = sRef_undump (c);
2436 sRef s2 = ((*c)++, sRef_undump (c));
2437 sRef ret = sRef_makeConj (s1, s2);
2442 return sRef_undefined;
2444 return sRef_makeUnknown ();
2446 return sRef_makeUnknown ();
2448 llfatalerror (message ("sRef_undump: bad line: %s", cstring_fromChars (*c)));
2453 /*@exposed@*/ sRef sRef_undump (char **c)
2455 sRef res = sRef_undumpBody (c);
2457 if (reader_optCheckChar (c, '='))
2459 multiVal mv = multiVal_undump (c);
2460 sRef_setValue (res, mv);
2461 reader_checkChar (c, '=');
2467 static /*@only@*/ cstring sRef_dumpBody (sRef s)
2469 if (sRef_isInvalid (s))
2471 return (cstring_makeLiteral ("-"));
2478 return (message ("p%d", s->info->paramno));
2480 if (s->info->arrayfetch->indknown)
2482 return (message ("a%d%q", s->info->arrayfetch->ind,
2483 sRef_dump (s->info->arrayfetch->arr)));
2487 return (message ("a%q", sRef_dump (s->info->arrayfetch->arr)));
2490 return (message ("f%s.%q", s->info->field->field,
2491 sRef_dump (s->info->field->rec)));
2493 return (message ("t%q", sRef_dump (s->info->ref)));
2495 return (message ("d%q", sRef_dump (s->info->ref)));
2497 return (message ("o%q", ctype_dump (s->info->object)));
2499 return (message ("s%d", (int) s->info->spec));
2501 return (message ("c%q.%q",
2502 sRef_dump (s->info->conj->a),
2503 sRef_dump (s->info->conj->b)));
2505 if (sRef_isFileOrGlobalScope (s))
2507 return (message ("g%d",
2508 usymtab_convertId (s->info->cvar->index)));
2512 llcontbug (message ("Dumping local variable: %q",
2513 sRef_unparseDebug (s)));
2514 return (cstring_makeLiteral ("u"));
2517 return (cstring_makeLiteral ("u"));
2519 return (message ("r%q", ctype_dump (s->type)));
2525 case SK_UNCONSTRAINED:
2526 llcontbug (message ("sRef_dump: bad kind: %q",
2527 sRef_unparseFull (s)));
2528 return (cstring_makeLiteral ("x"));
2535 /*@only@*/ cstring sRef_dump (sRef s)
2537 cstring res = sRef_dumpBody (s);
2539 if (sRef_hasValue (s))
2541 res = message ("%q=%q=", res, multiVal_dump (sRef_getValue (s)));
2547 cstring sRef_dumpGlobal (sRef s)
2549 llassert (!sRef_hasValue (s));
2551 if (sRef_isInvalid (s))
2553 return (cstring_makeLiteral ("-"));
2560 if (sRef_isFileOrGlobalScope (s))
2562 return (message ("g%d@%d@%d",
2563 usymtab_convertId (s->info->cvar->index),
2565 (int) sRef_getNullState (s)));
2569 llcontbug (message ("Dumping local variable: %q",
2570 sRef_unparseDebug (s)));
2571 return (cstring_makeLiteral ("u"));
2574 return (cstring_makeLiteral ("u"));
2576 return (message ("s%d", (int) s->info->spec));
2578 llcontbug (message ("sRef_dumpGlobal: bad kind: %q",
2579 sRef_unparseFull (s)));
2580 return (cstring_makeLiteral ("x"));
2588 sRef_deriveType (sRef s, uentryList cl)
2590 if (sRef_isInvalid (s)) return ctype_unknown;
2595 return (uentry_getType (usymtab_getRefQuiet (s->info->cvar->lexlevel,
2596 s->info->cvar->index)));
2597 case SK_UNCONSTRAINED:
2598 return (ctype_unknown);
2600 if (s->info->paramno >= 0)
2602 return uentry_getType (uentryList_getN (cl, s->info->paramno));
2606 return ctype_unknown;
2610 ctype ca = sRef_deriveType (s->info->arrayfetch->arr, cl);
2612 if (ctype_isArray (ca))
2614 return (ctype_baseArrayPtr (ca));
2616 else if (ctype_isUnknown (ca))
2622 llcontbuglit ("sRef_deriveType: inconsistent array type");
2628 ctype ct = sRef_deriveType (s->info->field->rec, cl);
2630 if (ctype_isStructorUnion (ct))
2632 uentry ue = uentryList_lookupField (ctype_getFields (ct),
2633 s->info->field->field);
2635 if (uentry_isValid (ue))
2637 return (uentry_getType (ue));
2641 llcontbuglit ("sRef_deriveType: bad field");
2642 return ctype_unknown;
2645 else if (ctype_isUnknown (ct))
2651 llcontbuglit ("sRef_deriveType: inconsistent field type");
2657 ctype ct = sRef_deriveType (s->info->ref, cl);
2659 if (ctype_isUnknown (ct)) return ct;
2660 if (ctype_isPointer (ct)) return (ctype_baseArrayPtr (ct));
2663 llcontbuglit ("sRef_deriveType: inconsistent pointer type");
2669 ctype ct = sRef_deriveType (s->info->ref, cl);
2671 if (ctype_isUnknown (ct)) return ct;
2672 return ctype_makePointer (ct);
2676 return sRef_deriveType (s->info->ref, cl);
2680 return (s->info->object);
2684 return (ctype_makeConj (sRef_deriveType (s->info->conj->a, cl),
2685 sRef_deriveType (s->info->conj->b, cl)));
2697 return ctype_unknown;
2703 sRef_getType (sRef s)
2705 if (sRef_isInvalid (s)) return ctype_unknown;
2711 sRef_unparseOpt (sRef s)
2713 sRef rb = sRef_getRootBase (s);
2715 if (sRef_isMeaningful (rb) && !sRef_isConst (rb))
2717 cstring ret = sRef_unparse (s);
2719 llassertprint (!cstring_equalLit (ret, "?"), ("print: %s", sRef_unparseDebug (s)));
2721 if (!cstring_isEmpty (ret))
2723 return (cstring_appendChar (ret, ' '));
2731 return cstring_undefined;
2735 sRef_unparsePreOpt (sRef s)
2737 sRef rb = sRef_getRootBase (s);
2739 if (sRef_isMeaningful (rb) && !sRef_isConst (rb))
2741 cstring ret = sRef_unparse (s);
2743 llassertprint (!cstring_equalLit (ret, "?"), ("print: %s", sRef_unparseDebug (s)));
2744 return (cstring_prependCharO (' ', ret));
2747 return cstring_undefined;
2751 sRef_unparse (sRef s)
2753 if (sRef_isInvalid (s)) return (cstring_makeLiteral ("?"));
2755 if (context_inFunctionLike ())
2757 return (sRef_unparseWithArgs (s, context_getParams ()));
2761 DPRINTF (("Not in function like: %s", context_unparse ()));
2762 return (sRef_unparseNoArgs (s));
2766 static /*@only@*/ cstring
2767 sRef_unparseWithArgs (sRef s, uentryList args)
2769 if (sRef_isInvalid (s))
2771 return (cstring_makeLiteral ("?"));
2777 return (uentry_getName (usymtab_getRefQuiet (s->info->cvar->lexlevel,
2778 s->info->cvar->index)));
2779 case SK_UNCONSTRAINED:
2780 return (cstring_copy (s->info->fname));
2783 if (s->info->paramno < uentryList_size (args)
2784 && s->info->paramno >= 0)
2786 uentry ue = uentryList_getN (args, s->info->paramno);
2788 if (uentry_isValid (ue))
2789 return uentry_getName (ue);
2792 return (message ("parameter %d", s->info->paramno + 1));
2795 if (s->info->arrayfetch->indknown)
2797 return (message ("%q[%d]", sRef_unparseWithArgs (s->info->arrayfetch->arr, args),
2798 s->info->arrayfetch->ind));
2802 return (message ("%q[]", sRef_unparseWithArgs (s->info->arrayfetch->arr, args)));
2805 if (s->info->field->rec->kind == SK_PTR)
2807 sRef ptr = s->info->field->rec;
2809 return (message ("%q->%s", sRef_unparseWithArgs (ptr->info->ref, args),
2810 s->info->field->field));
2812 return (message ("%q.%s", sRef_unparseWithArgs (s->info->field->rec, args),
2813 s->info->field->field));
2817 sRef ref = sRef_fixConj (s->info->ref);
2818 skind sk = ref->kind;
2823 ret = message ("storage pointed to by %q",
2824 sRef_unparseWithArgs (ref, args));
2826 else if (skind_isSimple (sk) || sk == SK_PTR)
2828 ret = message ("*%q", sRef_unparseWithArgs (ref, args));
2832 ret = message ("*(%q)", sRef_unparseWithArgs (ref, args));
2838 return (message ("&%q", sRef_unparseWithArgs (s->info->ref, args)));
2840 return (cstring_copy (ctype_unparse (s->info->object)));
2842 return (sRef_unparseWithArgs (sRef_getConjA (s), args));
2844 if (cstring_isDefined (s->info->fname))
2846 return (message ("[result of %s]", s->info->fname));
2850 return (cstring_makeLiteral ("<new>"));
2853 return (cstring_makeLiteral ("?"));
2855 return (message ("<derived %q>", sRef_unparse (s->info->ref)));
2857 return (message ("<external %q>", sRef_unparse (s->info->ref)));
2859 return (message ("<type %s>", ctype_unparse (s->type)));
2861 return (message ("<const %s>", ctype_unparse (s->type)));
2863 switch (s->info->spec)
2865 case SR_NOTHING: return cstring_makeLiteral ("nothing");
2866 case SR_INTERNAL: return cstring_makeLiteral ("internal state");
2867 case SR_SPECSTATE: return cstring_makeLiteral ("spec state");
2868 case SR_SYSTEM: return cstring_makeLiteral ("file system state");
2869 case SR_GLOBALMARKER: return cstring_makeLiteral ("<global marker>");
2873 return cstring_makeLiteral ("result");
2876 llbug (message ("Bad sref, kind = %d", (int) s->kind));
2884 sRef_unparseDebug (sRef s)
2886 if (sRef_isInvalid (s))
2888 return (cstring_makeLiteral ("<undef>"));
2894 case SK_UNCONSTRAINED:
2895 return (message ("<unconstrained %s>", s->info->fname));
2900 ce = usymtab_getRefQuiet (s->info->cvar->lexlevel, s->info->cvar->index);
2902 if (uentry_isInvalid (ce))
2904 return (message ("<scope: %d.%d *invalid*>",
2905 s->info->cvar->lexlevel,
2906 s->info->cvar->index));
2910 return (message ("<scope: %d.%d *%q*>",
2911 s->info->cvar->lexlevel,
2912 s->info->cvar->index,
2913 uentry_getName (ce)));
2919 return (message ("<parameter %d>", s->info->paramno + 1));
2922 if (s->info->arrayfetch->indknown)
2924 return (message ("%q[%d]", sRef_unparseDebug (s->info->arrayfetch->arr),
2925 s->info->arrayfetch->ind));
2929 return (message ("%q[]", sRef_unparseDebug (s->info->arrayfetch->arr)));
2932 return (message ("%q.%s", sRef_unparseDebug (s->info->field->rec),
2933 s->info->field->field));
2935 if (sRef_isField (s->info->ref))
2937 sRef fld = s->info->ref;
2939 return (message ("%q->%s", sRef_unparseDebug (fld->info->field->rec),
2940 fld->info->field->field));
2944 return (message ("*(%q)", sRef_unparseDebug (s->info->ref)));
2947 return (message ("&%q", sRef_unparseDebug (s->info->ref)));
2949 return (message ("<object type %s>", ctype_unparse (s->info->object)));
2951 return (message ("%q | %q", sRef_unparseDebug (s->info->conj->a),
2952 sRef_unparseDebug (s->info->conj->b)));
2954 return message ("<new: %s>", s->info->fname);
2956 return (message ("<derived %q>", sRef_unparseDebug (s->info->ref)));
2958 return (message ("<external %q>", sRef_unparseDebug (s->info->ref)));
2960 return (message ("<type %s>", ctype_unparse (s->type)));
2962 if (sRef_hasValue (s))
2964 return (message ("<const %s=%q>", ctype_unparse (s->type), multiVal_unparse (sRef_getValue (s))));
2968 return (message ("<const %s>", ctype_unparse (s->type)));
2971 return (message ("<result %s>", ctype_unparse (s->type)));
2973 return (message ("<spec %s>",
2974 cstring_makeLiteralTemp
2975 (s->info->spec == SR_NOTHING ? "nothing"
2976 : s->info->spec == SR_INTERNAL ? "internalState"
2977 : s->info->spec == SR_SPECSTATE ? "spec state"
2978 : s->info->spec == SR_SYSTEM ? "fileSystem"
2981 return cstring_makeLiteral ("<unknown>");
2987 static /*@only@*/ cstring
2988 sRef_unparseNoArgs (sRef s)
2990 if (sRef_isInvalid (s)) return (cstring_makeLiteral ("?"));
2994 case SK_UNCONSTRAINED:
2995 return (cstring_copy (s->info->fname));
2998 uentry ce = usymtab_getRefQuiet (s->info->cvar->lexlevel,
2999 s->info->cvar->index);
3001 if (uentry_isInvalid (ce))
3003 llcontbug (message ("sRef_unparseNoArgs: bad cvar: %q",
3004 sRef_unparseDebug (s)));
3005 return (sRef_unparseDebug (s));
3009 return (uentry_getName (ce));
3013 if (s->info->arrayfetch->indknown)
3015 return (message ("%q[%d]", sRef_unparseNoArgs (s->info->arrayfetch->arr),
3016 s->info->arrayfetch->ind));
3020 return (message ("%q[]", sRef_unparseNoArgs (s->info->arrayfetch->arr)));
3023 return (message ("%q.%s", sRef_unparseNoArgs (s->info->field->rec),
3024 s->info->field->field));
3027 sRef ref = sRef_fixConj (s->info->ref);
3028 skind sk = ref->kind;
3031 if (skind_isSimple (sk) || sk == SK_PTR)
3033 ret = message ("*%q", sRef_unparseNoArgs (ref));
3037 ret = message ("*(%q)", sRef_unparseNoArgs (ref));
3043 return (message ("&%q", sRef_unparseNoArgs (s->info->ref)));
3045 return (cstring_copy (ctype_unparse (s->info->object)));
3047 return (sRef_unparseNoArgs (s->info->conj->a));
3049 return (message ("result of %s", s->info->fname));
3051 return (message ("<der %q>", sRef_unparseNoArgs (s->info->ref)));
3053 return message ("<ext %q>", sRef_unparseNoArgs (s->info->ref));
3055 return (cstring_makeLiteral
3056 (s->info->spec == SR_NOTHING ? "nothing"
3057 : s->info->spec == SR_INTERNAL ? "internal state"
3058 : s->info->spec == SR_SPECSTATE ? "spec state"
3059 : s->info->spec == SR_SYSTEM ? "file system state"
3062 return cstring_makeLiteral ("result");
3066 return cstring_makeLiteral ("?");
3068 /* llcontbug (message ("sRef_unparseNoArgs: bad case: %q", sRef_unparseDebug (s))); */
3069 return (sRef_unparseDebug (s));
3074 /*@dependent@*/ sRef sRef_makeUnconstrained (cstring fname)
3076 sRef s = sRef_new ();
3078 s->kind = SK_UNCONSTRAINED;
3079 s->info = (sinfo) dmalloc (sizeof (*s->info));
3080 s->info->fname = fname;
3085 cstring sRef_unconstrainedName (sRef s)
3087 llassert (sRef_isUnconstrained (s));
3089 return s->info->fname;
3092 bool sRef_isUnconstrained (sRef s)
3094 return (sRef_isValid(s) && s->kind == SK_UNCONSTRAINED);
3097 static /*@dependent@*/ /*@notnull@*/ sRef
3098 sRef_makeCvarAux (int level, usymId index, ctype ct, /*@only@*/ stateInfo stinfo)
3100 sRef s = sRef_newRef ();
3103 s->info = (sinfo) dmalloc (sizeof (*s->info));
3105 s->info->cvar = (cref) dmalloc (sizeof (*s->info->cvar));
3106 s->info->cvar->lexlevel = level;
3107 s->info->cvar->index = index;
3109 /* for now, all globals are defined; all locals, aren't */
3111 if (level <= fileScope)
3113 s->defstate = SS_UNKNOWN;
3117 ctype rct = ctype_realType (ct);
3119 if (level != paramsScope
3120 && (ctype_isStructorUnion (rct) || ctype_isRealArray (rct)))
3122 s->defstate = SS_ALLOCATED;
3123 s->oaliaskind = s->aliaskind = AK_STACK;
3127 s->defstate = SS_UNDEFINED;
3128 s->oaliaskind = s->aliaskind = AK_LOCAL;
3134 llassert (level >= globScope);
3135 llassert (usymId_isValid (index));
3137 DPRINTF (("Made cvar: [%p] %s", s, sRef_unparseDebug (s)));
3138 llassert (valueTable_isUndefined (s->state));
3139 s->state = context_createValueTable (s, stinfo);
3143 /*@dependent@*/ sRef sRef_makeCvar (int level, usymId index, ctype ct, /*@only@*/ stateInfo stinfo)
3145 return (sRef_makeCvarAux (level, index, ct, stinfo));
3148 int sRef_lexLevel (sRef s)
3150 if (sRef_isValid (s))
3154 conj = sRef_fixConj (s);
3155 s = sRef_getRootBase (conj);
3157 if (sRef_isValid (s) && s->kind == SK_CVAR)
3159 return (s->info->cvar->lexlevel);
3167 sRef_makeGlobal (usymId l, ctype ct, /*@only@*/ stateInfo stinfo)
3169 return (sRef_makeCvar (globScope, l, ct, stinfo));
3173 sRef_setParamNo (sRef s, int l)
3175 llassert (sRef_isValid (s) && s->kind == SK_PARAM);
3176 s->info->paramno = l;
3180 /*@dependent@*/ sRef
3181 sRef_makeParam (int l, ctype ct, stateInfo stinfo)
3183 sRef s = sRef_new ();
3188 s->info = (sinfo) dmalloc (sizeof (*s->info));
3189 s->info->paramno = l;
3191 s->defstate = SS_UNKNOWN;
3192 /* (probably defined, unless its an out parameter) */
3194 llassert (valueTable_isUndefined (s->state));
3195 s->state = context_createValueTable (s, stinfo);
3200 sRef_isIndexKnown (sRef arr)
3204 llassert (sRef_isValid (arr));
3205 arr = sRef_fixConj (arr);
3207 llassert (arr->kind == SK_ARRAYFETCH);
3208 res = arr->info->arrayfetch->indknown;
3213 sRef_getIndex (sRef arr)
3217 llassert (sRef_isValid (arr));
3218 arr = sRef_fixConj (arr);
3220 llassert (arr->kind == SK_ARRAYFETCH);
3222 if (!arr->info->arrayfetch->indknown)
3224 llcontbug (message ("sRef_getIndex: unknown: %q", sRef_unparse (arr)));
3229 result = arr->info->arrayfetch->ind;
3235 static bool sRef_isZerothArrayFetch (/*@notnull@*/ sRef s)
3237 return (s->kind == SK_ARRAYFETCH
3238 && s->info->arrayfetch->indknown
3239 && (s->info->arrayfetch->ind == 0));
3242 /*@exposed@*/ sRef sRef_makeAddress (/*@exposed@*/ sRef t)
3245 if (sRef_isInvalid (t)) return sRef_undefined;
3247 if (sRef_isPointer (t))
3249 return (t->info->ref);
3251 else if (sRef_isZerothArrayFetch (t))
3253 return (t->info->arrayfetch->arr);
3257 sRef s = sRef_newRef ();
3260 s->type = ctype_makePointer (t->type);
3261 s->info = (sinfo) dmalloc (sizeof (*s->info));
3262 s->info->ref = t; /* sRef_copy (t); */ /*@i32@*/
3264 if (t->defstate == SS_UNDEFINED)
3265 /* no! it is allocated even still: && !ctype_isPointer (t->type)) */
3267 s->defstate = SS_ALLOCATED;
3271 s->defstate = t->defstate;
3274 if (t->aliaskind == AK_LOCAL)
3276 if (sRef_isLocalVar (t))
3278 s->aliaskind = AK_STACK;
3282 llassert (valueTable_isUndefined (s->state));
3283 s->state = context_createValueTable (s, stateInfo_makeLoc (g_currentloc));
3288 cstring sRef_getField (sRef s)
3292 llassert (sRef_isValid (s));
3293 s = sRef_fixConj (s);
3295 llassertprint (sRef_isValid (s) && (s->kind == SK_FIELD),
3296 ("s = %s", sRef_unparseDebug (s)));
3298 res = s->info->field->field;
3302 sRef sRef_getBase (sRef s)
3306 if (sRef_isInvalid (s)) return (sRef_undefined);
3308 s = sRef_fixConj (s);
3319 res = s->info->field->rec;
3323 res = s->info->arrayfetch->arr;
3327 res = sRef_undefined; /* shouldn't need it */
3334 ** same as getBase, except returns invalid
3335 ** (and doesn't use adr's)
3339 sRef_getBaseSafe (sRef s)
3343 if (sRef_isInvalid (s)) { return sRef_undefined; }
3345 s = sRef_fixConj (s);
3353 res = s->info->field->rec; break;
3355 res = s->info->arrayfetch->arr;
3358 res = sRef_undefined; break;
3364 /*@constant int MAXBASEDEPTH;@*/
3365 # define MAXBASEDEPTH 25
3367 static /*@exposed@*/ sRef
3368 sRef_getRootBaseAux (sRef s, int depth)
3370 if (sRef_isInvalid (s)) return sRef_undefined;
3372 if (depth > MAXBASEDEPTH)
3375 ("Warning: reference base limit exceeded for %q. "
3376 "This either means there is a variable with at least "
3377 "%d indirections from this reference, or "
3378 "there is a bug in LCLint.",
3383 return sRef_undefined;
3390 return (sRef_getRootBaseAux (s->info->ref, depth + 1));
3392 return (sRef_getRootBaseAux (s->info->field->rec, depth + 1));
3394 return (sRef_getRootBaseAux (s->info->arrayfetch->arr, depth + 1));
3396 return (sRef_getRootBaseAux (sRef_fixConj (s), depth + 1));
3402 sRef sRef_getRootBase (sRef s)
3404 return (sRef_getRootBaseAux (s, 0));
3407 static bool sRef_isDeep (sRef s)
3409 if (sRef_isInvalid (s)) return FALSE;
3419 return (sRef_isDeep (sRef_fixConj (s)));
3425 static int sRef_depth (sRef s)
3427 if (sRef_isInvalid (s)) return 0;
3435 return 1 + sRef_depth (s->info->ref);
3437 return 1 + sRef_depth (s->info->field->rec);
3439 return 1 + sRef_depth (s->info->arrayfetch->arr);
3441 return (sRef_depth (sRef_fixConj (s)));
3448 sRef_makeObject (ctype o)
3450 sRef s = sRef_newRef (); /*@i423 same line is bad...@*/
3452 s->kind = SK_OBJECT;
3453 s->info = (sinfo) dmalloc (sizeof (*s->info));
3454 s->info->object = o;
3455 llassert (valueTable_isUndefined (s->state));
3456 s->state = context_createValueTable (s, stateInfo_makeLoc (g_currentloc));
3461 ** This is used to represent storage referenced by a parameter.
3464 sRef sRef_makeExternal (sRef t)
3466 sRef s = sRef_newRef ();
3468 llassert (sRef_isValid (t));
3470 s->kind = SK_EXTERNAL;
3471 s->info = (sinfo) dmalloc (sizeof (*s->info));
3473 s->info->ref = t; /* sRef_copy (t); */ /*@i32 was exposed@*/
3474 llassert (valueTable_isUndefined (s->state));
3475 s->state = context_createValueTable (s, stateInfo_makeLoc (g_currentloc));
3479 /*@dependent@*/ sRef sRef_makeDerived (/*@exposed@*/ sRef t)
3481 if (sRef_isValid (t))
3483 sRef s = sRef_newRef ();
3485 s->kind = SK_DERIVED;
3486 s->info = (sinfo) dmalloc (sizeof (*s->info));
3487 s->info->ref = t; /* sRef_copy (t); */ /*@i32@*/
3490 llassert (valueTable_isUndefined (s->state));
3491 s->state = context_createValueTable (s, stateInfo_makeLoc (g_currentloc));
3496 return sRef_undefined;
3501 ** definitely NOT symmetric:
3503 ** res fills in unknown state information from other
3507 sRef_mergeStateQuiet (sRef res, sRef other)
3509 llassert (sRef_isValid (res));
3510 llassert (sRef_isValid (other));
3512 res->modified = res->modified || other->modified;
3513 res->safe = res->safe && other->safe;
3515 if (res->defstate == SS_UNKNOWN)
3517 res->defstate = other->defstate;
3518 res->definfo = stateInfo_update (res->definfo, other->definfo);
3521 if (res->aliaskind == AK_UNKNOWN ||
3522 (res->aliaskind == AK_LOCAL && alkind_isKnown (other->aliaskind)))
3524 res->aliaskind = other->aliaskind;
3525 res->oaliaskind = other->oaliaskind;
3526 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
3529 if (res->expkind == XO_UNKNOWN)
3531 res->expkind = other->expkind;
3532 res->oexpkind = other->oexpkind;
3533 res->expinfo = stateInfo_update (res->expinfo, other->expinfo);
3536 /* out takes precedence over implicitly defined */
3537 if (res->defstate == SS_DEFINED && other->defstate != SS_UNKNOWN)
3539 res->defstate = other->defstate;
3540 res->definfo = stateInfo_update (res->definfo, other->definfo);
3543 if (sRef_getNullState (other) == NS_ERROR || sRef_getNullState (res) == NS_ERROR)
3545 sRef_setNullState (res, NS_ERROR, fileloc_undefined);
3549 if (sRef_getNullState (other) != NS_UNKNOWN
3550 && (sRef_getNullState (res) == NS_UNKNOWN || sRef_getNullState (res) == NS_NOTNULL
3551 || sRef_getNullState (res) == NS_MNOTNULL))
3553 sRef_updateNullState (res, other);
3559 ** definitely NOT symmetric:
3561 ** res fills in known state information from other
3565 sRef_mergeStateQuietReverse (/*@dependent@*/ sRef res, /*@dependent@*/ sRef other)
3567 bool changed = FALSE;
3569 llassert (sRef_isValid (res));
3570 llassert (sRef_isValid (other));
3571 sRef_checkMutable (res);
3573 if (res->kind != other->kind)
3579 res->kind = other->kind;
3580 res->type = other->type;
3581 res->info = sinfo_fullCopy (other);
3585 if (!ctype_equal (res->type, other->type))
3588 res->type = other->type;
3591 sinfo_update (res, other);
3594 res->modified = res->modified || other->modified;
3595 res->safe = res->safe && other->safe;
3597 if (res->aliaskind != other->aliaskind
3598 && (res->aliaskind == AK_UNKNOWN
3599 || ((res->aliaskind == AK_LOCAL
3600 || (res->aliaskind == AK_REFCOUNTED
3601 && other->aliaskind != AK_LOCAL))
3602 && other->aliaskind != AK_UNKNOWN)))
3605 res->aliaskind = other->aliaskind;
3606 res->oaliaskind = other->oaliaskind;
3607 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
3610 if (other->expkind != XO_UNKNOWN && other->expkind != res->expkind)
3613 res->expkind = other->expkind;
3614 res->expinfo = stateInfo_update (res->expinfo, other->expinfo);
3617 if (other->oexpkind != XO_UNKNOWN)
3619 res->oexpkind = other->oexpkind;
3622 /* out takes precedence over implicitly defined */
3624 if (res->defstate != other->defstate)
3626 if (other->defstate != SS_UNKNOWN)
3628 res->defstate = other->defstate;
3632 if (sRef_getNullState (other) == NS_ERROR || sRef_getNullState (res) == NS_ERROR)
3634 if (sRef_getNullState (res) != NS_ERROR)
3636 sRef_setNullStateN (res, NS_ERROR);
3642 if (sRef_getNullState (other) != NS_UNKNOWN && sRef_getNullState (other) != sRef_getNullState (res))
3645 sRef_updateNullState (res, other);
3651 sRef_clearDerived (res);
3656 sRef_mergeState (sRef res, sRef other, clause cl, fileloc loc)
3658 if (sRef_isValid (res) && sRef_isValid (other))
3660 sRef_mergeStateAux (res, other, cl, FALSE, loc, TRUE);
3664 if (sRef_isInvalid (res))
3666 llbug (message ("sRef_mergeState: invalid res sRef: %q",
3667 sRef_unparseDebug (other)));
3671 llbug (message ("sRef_mergeState: invalid other sRef: %q",
3672 sRef_unparseDebug (res)));
3678 sRef_mergeOptState (sRef res, sRef other, clause cl, fileloc loc)
3680 if (sRef_isValid (res) && sRef_isValid (other))
3682 sRef_mergeStateAux (res, other, cl, TRUE, loc, TRUE);
3686 if (sRef_isInvalid (res))
3688 llbug (message ("sRef_mergeOptState: invalid res sRef: %q",
3689 sRef_unparseDebug (other)));
3693 llbug (message ("sRef_mergeOptState: invalid other sRef: %q",
3694 sRef_unparseDebug (res)));
3700 sRef_mergeStateAux (/*@notnull@*/ sRef res, /*@notnull@*/ sRef other,
3701 clause cl, bool opt, fileloc loc,
3705 llassertfatal (sRef_isValid (res));
3706 llassertfatal (sRef_isValid (other));
3708 sRef_checkMutable (res);
3709 sRef_checkMutable (other);
3711 res->modified = res->modified || other->modified;
3713 if (res->kind == other->kind
3714 || (other->kind == SK_UNKNOWN || res->kind == SK_UNKNOWN))
3716 sstate odef = other->defstate;
3717 sstate rdef = res->defstate;
3718 nstate onull = sRef_getNullState (other);
3721 ** yucky stuff to handle
3726 if (other->defstate == SS_DEAD
3727 && ((sRef_isOnly (res) && sRef_definitelyNull (res))
3728 || (res->defstate == SS_UNDEFINED
3729 || res->defstate == SS_UNUSEABLE)))
3731 if (res->defstate == SS_UNDEFINED
3732 || res->defstate == SS_UNUSEABLE)
3734 res->defstate = SS_UNUSEABLE;
3738 res->defstate = SS_DEAD;
3741 res->definfo = stateInfo_update (res->definfo, other->definfo);
3742 sRef_clearDerived (other);
3743 sRef_clearDerived (res);
3745 else if (res->defstate == SS_DEAD
3746 && ((sRef_isOnly (other) && sRef_definitelyNull (other))
3747 || (other->defstate == SS_UNDEFINED
3748 || other->defstate == SS_UNUSEABLE)))
3750 if (other->defstate == SS_UNDEFINED
3751 || other->defstate == SS_UNUSEABLE)
3753 res->defstate = SS_UNUSEABLE;
3757 res->defstate = SS_DEAD;
3760 sRef_clearDerived (other);
3761 sRef_clearDerived (res);
3763 else if (res->defstate == SS_DEFINED
3764 && (other->defstate == SS_ALLOCATED
3765 && sRef_definitelyNull (other)))
3767 other->defstate = SS_DEFINED; /* definitely null! */
3769 else if (other->defstate == SS_DEFINED
3770 && (res->defstate == SS_ALLOCATED && sRef_definitelyNull (res)))
3772 res->defstate = SS_DEFINED;
3773 res->definfo = stateInfo_update (res->definfo, other->definfo);
3780 if (res->defstate == SS_DEAD && other->defstate == SS_DEAD)
3782 sRef_clearDerived (other);
3783 sRef_clearDerived (res);
3787 ** only & dead isn't really an only!
3790 if (alkind_isOnly (other->aliaskind) && other->defstate == SS_DEAD)
3792 other->aliaskind = AK_UNKNOWN;
3795 if (alkind_isOnly (res->aliaskind) && res->defstate == SS_DEAD)
3797 res->aliaskind = AK_UNKNOWN;
3801 ** Dead and dependent -> dead
3804 if (alkind_isDependent (other->aliaskind) && res->defstate == SS_DEAD)
3806 other->aliaskind = AK_UNKNOWN;
3807 other->defstate = SS_DEAD;
3808 sRef_clearDerived (res);
3809 sRef_clearDerived (other);
3812 if (alkind_isDependent (res->aliaskind) && other->defstate == SS_DEAD)
3814 res->aliaskind = AK_UNKNOWN;
3815 res->defstate = SS_DEAD;
3816 sRef_clearDerived (res);
3817 sRef_clearDerived (other);
3821 ** must do alias combine first, since it depends on
3822 ** original values of state and null.
3825 sRef_combineAliasKinds (res, other, cl, loc);
3826 sRef_combineDefState (res, other);
3827 sRef_combineNullState (res, other);
3829 if (rdef == SS_ALLOCATED || rdef == SS_SPECIAL)
3831 if (odef == SS_DEFINED)
3833 if (onull == NS_DEFNULL || onull == NS_CONSTNULL)
3835 res->deriv = sRefSet_copyInto (res->deriv, other->deriv);
3836 DPRINTF (("Copy derivs: %s", sRef_unparseFull (res)));
3839 else if (odef == SS_ALLOCATED || odef == SS_SPECIAL)
3844 if (ctype_isUnion (ctype_realType (sRef_getType (res))))
3846 res->deriv = sRef_mergeUnionDerivs (res->deriv,
3849 DPRINTF (("Copy derivs: %s", sRef_unparseFull (res)));
3853 res->deriv = sRef_mergeDerivs (res->deriv, other->deriv,
3855 DPRINTF (("Copy derivs: %s", sRef_unparseFull (res)));
3863 res->deriv = sRef_mergeDerivs (res->deriv, other->deriv,
3865 DPRINTF (("Copy derivs: %s", sRef_unparseFull (res)));
3875 if (rdef == SS_PDEFINED
3876 || (rdef == SS_DEFINED && odef == SS_PDEFINED))
3880 res->deriv = sRef_mergePdefinedDerivs (res->deriv, other->deriv,
3882 DPRINTF (("Copy derivs: %s", sRef_unparseFull (res)));
3887 if ((rdef == SS_DEFINED || rdef == SS_UNKNOWN)
3888 && res->defstate == SS_ALLOCATED)
3890 res->deriv = sRefSet_copyInto (res->deriv, other->deriv);
3896 res->deriv = sRef_mergeDerivs (res->deriv, other->deriv,
3898 DPRINTF (("Copy derivs: %s", sRef_unparseFull (res)));
3905 sRef_combineExKinds (res, other);
3909 if (res->kind == SK_ARRAYFETCH && other->kind == SK_PTR)
3911 sRef nother = sRef_buildArrayFetchKnown (sRef_getBase (other), 0);
3913 sRef_copyState (nother, other);
3914 sRef_mergeStateAux (res, nother, cl, opt, loc, doDerivs);
3916 else if (res->kind == SK_PTR && other->kind == SK_ARRAYFETCH)
3918 sRef nother = sRef_buildPointer (sRef_getBase (other));
3920 if (sRef_isValid (nother))
3922 sRef_copyState (nother, other);
3923 sRef_mergeStateAux (res, nother, cl, opt, loc, doDerivs);
3928 llcontbug (message ("merge conj: %q / %q", sRef_unparseFull (res),
3929 sRef_unparseFull (other)));
3935 ** Merge value table states
3942 ** This doesn't do anything. And its broken too...
3945 valueTable_elements (res->state, key, sv)
3947 stateValue os = valueTable_lookup (other->state, key);
3948 /*@unused@*/ int val;
3949 /*@unused@*/ char *msg;
3951 llassert (stateValue_isDefined (os));
3953 DPRINTF (("Merge state: %s / %s",
3954 cstring_toCharsSafe (stateValue_unparse (sv)),
3955 cstring_toCharsSafe (stateValue_unparse (os))));
3957 val = valueMatix_lookup (key,
3958 stateValue_getValue (os),
3959 stateValue_getValue (sv),
3961 DPRINTF (("Val: %d / %s", val, msg));
3963 } end_valueTable_elements ;
3969 sRef_mergeUnionDerivs (/*@only@*/ sRefSet res,
3970 /*@exposed@*/ sRefSet other, bool opt,
3971 clause cl, fileloc loc)
3973 if (sRefSet_isEmpty (res))
3975 return sRefSet_copyInto (res, other);
3979 sRefSet_allElements (other, el)
3981 if (sRef_isValid (el))
3983 sRef e2 = sRefSet_lookupMember (other, el);
3985 if (sRef_isValid (e2))
3987 sRef_mergeStateAux (el, e2, cl, opt, loc, FALSE);
3991 res = sRefSet_insert (res, el);
3994 } end_sRefSet_allElements ;
4000 static /*@only@*/ sRefSet
4001 sRef_mergeDerivs (/*@only@*/ sRefSet res, sRefSet other,
4002 bool opt, clause cl, fileloc loc)
4004 sRefSet ret = sRefSet_new ();
4006 sRefSet_allElements (res, el)
4008 if (sRef_isValid (el))
4010 sRef e2 = sRefSet_lookupMember (other, el);
4012 if (sRef_isValid (e2))
4014 if (el->defstate == SS_ALLOCATED &&
4015 e2->defstate == SS_PDEFINED)
4017 e2->defstate = SS_ALLOCATED;
4019 else if (e2->defstate == SS_ALLOCATED &&
4020 el->defstate == SS_PDEFINED)
4022 el->defstate = SS_ALLOCATED;
4023 sRef_clearDerived (el);
4025 else if ((el->defstate == SS_DEAD || sRef_isKept (el)) &&
4026 (e2->defstate == SS_DEFINED && !sRef_isKept (e2)))
4029 if (checkDeadState (el, TRUE, loc))
4031 if (sRef_isThroughArrayFetch (el))
4033 sRef_maybeKill (el, loc);
4034 sRef_maybeKill (e2, loc);
4038 else if ((e2->defstate == SS_DEAD || sRef_isKept (e2)) &&
4039 (el->defstate == SS_DEFINED && !sRef_isKept (el)))
4042 if (checkDeadState (e2, FALSE, loc))
4044 if (sRef_isThroughArrayFetch (el))
4046 sRef_maybeKill (el, loc);
4047 sRef_maybeKill (e2, loc);
4051 else if (el->defstate == SS_DEFINED &&
4052 e2->defstate == SS_PDEFINED)
4054 DPRINTF (("set pdefined: %s", sRef_unparseFull (el)));
4055 el->defstate = SS_PDEFINED;
4057 else if (e2->defstate == SS_DEFINED &&
4058 el->defstate == SS_PDEFINED)
4060 DPRINTF (("set pdefined: %s", sRef_unparseFull (e2)));
4061 e2->defstate = SS_PDEFINED;
4068 if (ctype_isUnion (ctype_realType (sRef_getType (el))))
4070 el->deriv = sRef_mergeUnionDerivs (el->deriv, e2->deriv,
4075 el->deriv = sRef_mergeDerivs (el->deriv, e2->deriv, opt, cl, loc);
4078 if (sRef_equivalent (el, e2))
4080 ret = sRefSet_insert (ret, el);
4084 sRef sr = sRef_leastCommon (el, e2);
4086 if (sRef_isValid (sr))
4088 ret = sRefSet_insert (ret, sr);
4096 (void) sRefSet_delete (other, e2);
4098 else /* not defined */
4100 (void) checkDeadState (el, TRUE, loc);
4103 } end_sRefSet_allElements;
4105 sRefSet_allElements (other, el)
4107 if (sRef_isValid (el))
4109 (void) checkDeadState (el, FALSE, loc);
4111 } end_sRefSet_allElements;
4118 ** Returns TRUE is there is an error.
4121 static bool checkDeadState (/*@notnull@*/ sRef el, bool tbranch, fileloc loc)
4124 ** usymtab_isGuarded --- the utab should still be in the
4125 ** state of the alternate branch.
4127 ** tbranch TRUE means el is released in the last branch, e.g.
4128 ** if (x != NULL) { ; } else { sfree (x); }
4129 ** so, if x is null in the other branch no error is reported.
4131 ** tbranch FALSE means this is the other branch:
4132 ** if (x != NULL) { sfree (x); } else { ; }
4133 ** so, if x is null in this branch there is no error.
4137 if ((sRef_isDead (el) || sRef_isKept (el))
4138 && !sRef_isDeepUnionField (el) && !sRef_isThroughArrayFetch (el))
4143 if (usymtab_isDefinitelyNullDeep (el))
4150 if (usymtab_isAltDefinitelyNullDeep (el))
4158 message ("Storage %q is %q in one path, but live in another.",
4160 cstring_makeLiteral (sRef_isKept (el)
4161 ? "kept" : "released")),
4164 if (sRef_isKept (el))
4166 sRef_showAliasInfo (el);
4170 sRef_showStateInfo (el);
4173 /* prevent further errors */
4174 el->defstate = SS_UNKNOWN;
4175 sRef_setAliasKind (el, AK_ERROR, fileloc_undefined);
4185 checkDerivDeadState (/*@notnull@*/ sRef el, bool tbranch, fileloc loc)
4188 if (checkDeadState (el, tbranch, loc))
4190 sRefSet_allElements (el->deriv, t)
4192 if (sRef_isValid (t))
4194 checkDerivDeadState (t, tbranch, loc);
4196 } end_sRefSet_allElements;
4201 sRef_mergePdefinedDerivs (sRefSet res, sRefSet other, bool opt,
4202 clause cl, fileloc loc)
4204 sRefSet ret = sRefSet_new ();
4206 sRefSet_allElements (res, el)
4208 if (sRef_isValid (el))
4210 sRef e2 = sRefSet_lookupMember (other, el);
4212 if (sRef_isValid (e2))
4214 if (sRef_isAllocated (el) && !sRef_isAllocated (e2))
4218 else if (sRef_isAllocated (e2) && !sRef_isAllocated (el))
4220 el->deriv = sRefSet_copyInto (el->deriv, e2->deriv);
4224 el->deriv = sRef_mergePdefinedDerivs (el->deriv, e2->deriv,
4228 sRef_mergeStateAux (el, e2, cl, opt, loc, FALSE);
4230 ret = sRefSet_insert (ret, el);
4231 (void) sRefSet_delete (other, e2);
4237 checkDerivDeadState (el, (cl == FALSECLAUSE), loc);
4240 ret = sRefSet_insert (ret, el);
4243 } end_sRefSet_allElements;
4245 sRefSet_allElements (other, el)
4247 if (sRef_isValid (el))
4249 if (!sRefSet_member (ret, el))
4251 /* was cl == FALSECLAUSE */
4252 checkDerivDeadState (el, FALSE, loc);
4253 ret = sRefSet_insert (ret, el);
4258 ** it's okay --- member is a different equality test
4262 } end_sRefSet_allElements;
4268 sRef sRef_makeConj (/*@exposed@*/ /*@returned@*/ sRef a, /*@exposed@*/ sRef b)
4270 llassert (sRef_isValid (a));
4271 llassert (sRef_isValid (b));
4273 if (!sRef_equivalent (a, b))
4275 sRef s = sRef_newRef ();
4278 s->info = (sinfo) dmalloc (sizeof (*s->info));
4279 s->info->conj = (cjinfo) dmalloc (sizeof (*s->info->conj));
4280 s->info->conj->a = a; /* sRef_copy (a) */ /*@i32*/ ;
4281 s->info->conj->b = b; /* sRef_copy (b);*/ /*@i32@*/ ;
4283 if (ctype_equal (a->type, b->type)) s->type = a->type;
4284 else s->type = ctype_makeConj (a->type, b->type);
4286 if (a->defstate == b->defstate)
4288 s->defstate = a->defstate;
4292 s->defstate = SS_UNKNOWN;
4295 sRef_setNullStateN (s, NS_UNKNOWN);
4297 s->safe = a->safe && b->safe;
4298 s->aliaskind = alkind_resolve (a->aliaskind, b->aliaskind);
4300 llassert (valueTable_isUndefined (s->state));
4301 s->state = context_createValueTable (s, stateInfo_makeLoc (g_currentloc));
4306 /*@-exposetrans@*/ return a; /*@=exposetrans@*/
4310 /*@dependent@*/ sRef
4313 sRef s = sRef_new ();
4315 s->kind = SK_UNKNOWN;
4319 static /*@owned@*/ sRef
4320 sRef_makeSpecial (speckind sk) /*@*/
4322 sRef s = sRef_new ();
4324 s->kind = SK_SPECIAL;
4325 s->info = (sinfo) dmalloc (sizeof (*s->info));
4327 /*@-dependenttrans@*/
4329 /*@=dependenttrans@*/
4332 static /*@owned@*/ sRef srnothing = sRef_undefined;
4333 static /*@owned@*/ sRef srinternal = sRef_undefined;
4334 static /*@owned@*/ sRef srsystem = sRef_undefined;
4335 static /*@owned@*/ sRef srspec = sRef_undefined;
4337 /*@dependent@*/ sRef
4338 sRef_makeNothing (void)
4340 if (sRef_isInvalid (srnothing))
4342 srnothing = sRef_makeSpecial (SR_NOTHING);
4349 sRef_makeInternalState (void)
4351 if (sRef_isInvalid (srinternal))
4353 srinternal = sRef_makeSpecial (SR_INTERNAL);
4360 sRef_makeSpecState (void)
4362 if (sRef_isInvalid (srspec))
4364 srspec = sRef_makeSpecial (SR_SPECSTATE);
4371 sRef_makeSystemState (void)
4373 if (sRef_isInvalid (srsystem))
4375 srsystem = sRef_makeSpecial (SR_SYSTEM);
4382 sRef_makeGlobalMarker (void)
4384 sRef s = sRef_makeSpecial (SR_GLOBALMARKER);
4385 llassert (valueTable_isUndefined (s->state));
4386 s->state = context_createGlobalMarkerValueTable (stateInfo_undefined);
4391 sRef_makeResult (ctype c)
4393 sRef s = sRef_newRef ();
4395 s->kind = SK_RESULT;
4397 s->defstate = SS_UNKNOWN;
4398 s->aliaskind = AK_UNKNOWN;
4399 sRef_setNullStateN (s, NS_UNKNOWN);
4400 llassert (valueTable_isUndefined (s->state));
4401 s->state = context_createValueTable (s, stateInfo_makeLoc (g_currentloc));
4403 DPRINTF (("Result: [%p] %s", s, sRef_unparseFull (s)));
4409 sRef_isNothing (sRef s)
4411 return (sRef_isKindSpecial (s) && s->info->spec == SR_NOTHING);
4415 sRef_isInternalState (sRef s)
4417 return (sRef_isKindSpecial (s) && s->info->spec == SR_INTERNAL);
4421 sRef_isSpecInternalState (sRef s)
4423 return (sRef_isKindSpecial (s)
4424 && (s->info->spec == SR_INTERNAL || s->info->spec == SR_SPECSTATE));
4428 sRef_isSpecState (sRef s)
4430 return (sRef_isKindSpecial (s) && s->info->spec == SR_SPECSTATE);
4434 sRef_isResult (sRef s)
4436 return (sRef_isValid (s) && s->kind == SK_RESULT);
4440 sRef_isSystemState (sRef s)
4442 return (sRef_isKindSpecial (s) && s->info->spec == SR_SYSTEM);
4446 sRef_isGlobalMarker (sRef s)
4448 return (sRef_isKindSpecial (s) && s->info->spec == SR_GLOBALMARKER);
4452 sRef_getScopeIndex (sRef s)
4454 llassert (sRef_isValid (s));
4455 llassert (sRef_isCvar (s));
4457 return (s->info->cvar->index);
4461 sRef_makeSafe (sRef s)
4463 if (sRef_isValid (s))
4470 sRef_makeUnsafe (sRef s)
4472 if (sRef_isValid (s))
4479 ** memory state operations
4482 /*@only@*/ cstring sRef_unparseFull (sRef s)
4484 if (sRef_isInvalid (s)) return (cstring_undefined);
4486 return (message ("[%d] %q - %q [%s] { %q } < %q >",
4488 sRef_unparseDebug (s),
4489 sRef_unparseState (s),
4490 exkind_unparse (s->oexpkind),
4491 sRefSet_unparseDebug (s->deriv),
4492 valueTable_unparse (s->state)));
4495 /*@unused@*/ cstring sRef_unparseDeep (sRef s)
4497 cstring st = cstring_undefined;
4499 st = message ("%q:", sRef_unparseFull (s));
4501 if (sRef_isValid (s))
4503 sRefSet_allElements (s->deriv, el)
4505 st = message("%q\n%q", st, sRef_unparseDeep (el));
4506 } end_sRefSet_allElements ;
4512 /*@only@*/ cstring sRef_unparseState (sRef s)
4514 if (sRef_isConj (s))
4516 return (message ("%q | %q",
4517 sRef_unparseState (s->info->conj->a),
4518 sRef_unparseState (s->info->conj->b)));
4521 if (sRef_isInvalid (s))
4523 return (cstring_makeLiteral ("<invalid>"));
4526 return (message ("%s.%s.%s.%s",
4527 alkind_unparse (s->aliaskind),
4528 nstate_unparse (sRef_getNullState (s)),
4529 exkind_unparse (s->expkind),
4530 sstate_unparse (s->defstate)));
4533 bool sRef_isNotUndefined (sRef s)
4535 return (sRef_isInvalid (s)
4536 || (s->defstate != SS_UNDEFINED
4537 && s->defstate != SS_UNUSEABLE
4538 && s->defstate != SS_DEAD));
4541 ynm sRef_isWriteable (sRef s)
4543 if (sRef_isInvalid (s)) return MAYBE;
4545 if (sRef_isConj (s) && s->defstate == SS_UNKNOWN)
4547 if (ynm_toBoolStrict (sRef_isWriteable (sRef_getConjA (s))))
4549 if (ynm_toBoolStrict (sRef_isWriteable (sRef_getConjB (s))))
4557 if (ynm_toBoolStrict (sRef_isWriteable (sRef_getConjB (s))))
4565 return (ynm_fromBool (s->defstate != SS_UNUSEABLE));
4568 bool sRef_hasNoStorage (sRef s)
4570 return (!sRef_isAllocatedStorage (s) || sRef_isDefinitelyNull (s));
4573 bool sRef_isStrictReadable (sRef s)
4575 return (ynm_toBoolStrict (sRef_isReadable (s)));
4578 ynm sRef_isReadable (sRef s)
4582 if (sRef_isInvalid (s)) return YES;
4586 if (sRef_isConj (s) && s->defstate == SS_UNKNOWN)
4588 if (ynm_toBoolStrict (sRef_isReadable (sRef_getConjA (s))))
4590 if (ynm_toBoolStrict (sRef_isReadable (sRef_getConjB (s))))
4598 if (ynm_toBoolStrict (sRef_isReadable (sRef_getConjB (s))))
4605 else if (ss == SS_HOFFA)
4607 if (context_getFlag (FLG_STRICTUSERELEASED))
4618 return (ynm_fromBool (ss == SS_DEFINED
4621 || ss == SS_PDEFINED
4624 || ss == SS_ALLOCATED
4625 || ss == SS_KILLED /* evans 2001-05-26: added this for killed globals */
4626 || ss == SS_UNKNOWN));
4630 static /*@exposed@*/ sRef whatUndefined (/*@exposed@*/ sRef fref, int depth)
4635 if (depth > MAXDEPTH)
4638 ("Warning: check definition limit exceeded, checking %q. "
4639 "This either means there is a variable with at least "
4640 "%d indirections apparent in the program text, or "
4641 "there is a bug in LCLint.",
4642 sRef_unparse (fref),
4646 return sRef_undefined;
4649 if (!sRef_isKnown (fref) || sRef_isAnyDefined (fref))
4651 return sRef_undefined;
4654 if (sRef_isUnuseable (fref) || sRef_isStateUndefined (fref))
4659 ct = ctype_realType (sRef_getType (fref));
4661 if (ctype_isUnknown (ct))
4663 return sRef_undefined;
4665 else if (ctype_isPointer (ct) || ctype_isArray (ct))
4667 if (sRef_isStateUnknown (fref))
4669 return sRef_undefined;
4673 sRef fptr = sRef_constructDeref (fref);
4675 return (whatUndefined (fptr, depth + 1));
4678 else if (ctype_isStruct (ct))
4680 bool hasOneDefined = FALSE;
4682 if (sRef_isStateUnknown (fref))
4687 if (sRef_isPdefined (fref) || sRef_isAnyDefined (fref))
4689 sRefSet_realElements (sRef_derivedFields (fref), sr)
4691 hasOneDefined = TRUE;
4693 if (sRef_isField (sr))
4695 cstring fieldname = sRef_getField (sr);
4696 sRef fldref = sRef_makeField (fref, fieldname);
4697 bool shouldCheck = !sRef_isRecursiveField (fldref);
4701 sRef wdef = whatUndefined (fldref, depth + 1);
4703 if (sRef_isValid (wdef))
4709 } end_sRefSet_realElements;
4711 else if (sRef_isAllocated (fref))
4714 ** for structures, each field must be completely defined
4717 uentryList fields = ctype_getFields (ct);
4719 uentryList_elements (fields, ue)
4721 cstring name = uentry_getRealName (ue);
4722 sRef ffield = sRef_makeField (fref, name);
4723 bool shouldCheck = !sRef_isRecursiveField (ffield);
4725 if (sRef_isRelDef (uentry_getSref (ue)))
4733 sRef wdef = whatUndefined (ffield, depth + 1);
4735 if (sRef_isInvalid (wdef))
4741 } end_uentryList_elements;
4748 else if (ctype_isUnion (ct))
4757 return sRef_undefined;
4760 static bool checkDefined (/*@temp@*/ sRef sr)
4762 /*@-temptrans@*/ /* the result from whatUndefined is lost */
4763 return (sRef_isInvalid (whatUndefined (sr, 0)));
4767 bool sRef_isReallyDefined (sRef s)
4769 if (sRef_isValid (s))
4771 if (sRef_isAnyDefined (s))
4777 if (sRef_isAllocated (s) || sRef_isPdefined (s))
4779 return checkDefined (s);
4793 void sRef_showNotReallyDefined (sRef s)
4795 if (sRef_isValid (s))
4797 if (sRef_isAnyDefined (s))
4803 if (sRef_isAllocated (s) || sRef_isPdefined (s))
4805 /*@-temptrans@*/ /* the result of whatUndefined is lost */
4806 sRef ref = whatUndefined (s, 0);
4808 llassert (sRef_isValid (ref));
4813 (message ("This sub-reference is %s: %q",
4814 sstate_unparse (sRef_getDefState (ref)),
4815 sRef_unparse (ref)));
4830 sstate sRef_getDefState (sRef s)
4832 if (sRef_isInvalid (s)) return (SS_UNKNOWN);
4833 return (s->defstate);
4836 void sRef_setDefState (sRef s, sstate defstate, fileloc loc)
4838 sRef_checkMutable (s);
4839 sRef_setStateAux (s, defstate, loc);
4842 static void sRef_clearAliasStateAux (sRef s, fileloc loc)
4844 sRef_checkMutable (s);
4845 sRef_setAliasKind (s, AK_ERROR, loc);
4848 void sRef_clearAliasState (sRef s, fileloc loc)
4850 sRef_checkMutable (s);
4851 sRef_aliasSetComplete (sRef_clearAliasStateAux, s, loc);
4854 void sRef_setAliasKindComplete (sRef s, alkind kind, fileloc loc)
4856 sRef_checkMutable (s);
4857 /*@+enumint*/ /* we allow alkind to match int for this */
4858 sRef_aliasSetCompleteParam (sRef_setAliasKind, s, kind, loc);
4859 /* gcc give warning for this, should provide typesafe versions of aliasSetCompleteParam */
4863 void sRef_setAliasKind (sRef s, alkind kind, fileloc loc)
4865 sRef_checkMutable (s);
4867 if (sRef_isValid (s))
4869 sRef_clearDerived (s);
4871 if ((kind != s->aliaskind && kind != s->oaliaskind)
4872 && fileloc_isDefined (loc))
4874 s->aliasinfo = stateInfo_updateLoc (s->aliasinfo, loc);
4877 s->aliaskind = kind;
4881 void sRef_setOrigAliasKind (sRef s, alkind kind)
4883 sRef_checkMutable (s);
4885 if (sRef_isValid (s))
4887 s->oaliaskind = kind;
4891 exkind sRef_getExKind (sRef s)
4893 if (sRef_isValid (s))
4895 return (s->expkind);
4903 exkind sRef_getOrigExKind (sRef s)
4905 if (sRef_isValid (s))
4907 return (s->oexpkind);
4915 static void sRef_clearExKindAux (sRef s, fileloc loc)
4917 sRef_checkMutable (s);
4918 sRef_setExKind (s, XO_UNKNOWN, loc);
4921 void sRef_setObserver (sRef s, fileloc loc)
4923 sRef_checkMutable (s);
4924 sRef_setExKind (s, XO_OBSERVER, loc);
4927 void sRef_setExposed (sRef s, fileloc loc)
4929 sRef_checkMutable (s);
4930 sRef_setExKind (s, XO_EXPOSED, loc);
4933 void sRef_clearExKindComplete (sRef s, fileloc loc)
4935 (void) sRef_aliasSetComplete (sRef_clearExKindAux, s, loc);
4938 void sRef_setExKind (sRef s, exkind exp, fileloc loc)
4940 sRef_checkMutable (s);
4942 if (sRef_isValid (s))
4944 if (s->expkind != exp)
4946 s->expinfo = stateInfo_updateLoc (s->expinfo, loc);
4954 ** s1->derived = s2->derived
4957 static void sRef_copyRealDerived (sRef s1, sRef s2)
4959 DPRINTF (("Copy real: %s / %s", sRef_unparse (s1), sRef_unparse (s2)));
4960 sRef_checkMutable (s1);
4962 if (sRef_isValid (s1) && sRef_isValid (s2))
4964 sRef sb = sRef_getRootBase (s1);
4966 sRefSet_clear (s1->deriv);
4968 sRefSet_allElements (s2->deriv, el)
4970 if (sRef_isValid (el))
4972 sRef rb = sRef_getRootBase (el);
4974 if (!sRef_same (rb, sb))
4976 sRef fb = sRef_fixDirectBase (el, s1);
4978 if (sRef_isValid (fb))
4980 sRef_copyRealDerived (fb, el);
4981 sRef_addDeriv (s1, fb);
4986 sRef_addDeriv (s1, el);
4989 } end_sRefSet_allElements ;
4994 void sRef_copyRealDerivedComplete (sRef s1, sRef s2)
4996 sRef_innerAliasSetCompleteParam (sRef_copyRealDerived, s1, s2);
4999 void sRef_setUndefined (sRef s, fileloc loc)
5001 sRef_checkMutable (s);
5003 if (sRef_isValid (s))
5005 s->defstate = SS_UNDEFINED;
5007 if (fileloc_isDefined (loc))
5009 s->definfo = stateInfo_updateLoc (s->definfo, loc);
5012 sRef_clearDerived (s);
5016 static void sRef_setDefinedAux (sRef s, fileloc loc, bool clear)
5018 sRef_checkMutable (s);
5019 if (sRef_isInvalid (s)) return;
5021 DPRINTF (("Set defined: %s", sRef_unparseFull (s)));
5023 if (s->defstate != SS_DEFINED && fileloc_isDefined (loc))
5025 s->definfo = stateInfo_updateLoc (s->definfo, loc);
5028 s->defstate = SS_DEFINED;
5030 DPRINTF (("Set defined: %s", sRef_unparseFull (s)));
5032 /* e.g., if x is allocated, *x = 3 defines x */
5034 if (s->kind == SK_PTR)
5036 sRef p = s->info->ref;
5039 if (p->defstate == SS_ALLOCATED
5040 || p->defstate == SS_SPECIAL) /* evans 2001-07-12: shouldn't need this */
5042 sRef_setDefinedAux (p, loc, clear);
5046 ** Defines a[0] also:
5049 arr = sRef_findDerivedArrayFetch (p, FALSE, 0, FALSE);
5051 if (sRef_isValid (arr))
5053 sRef_setDefinedAux (arr, loc, clear);
5056 else if (s->kind == SK_ARRAYFETCH)
5058 if (!s->info->arrayfetch->indknown
5059 || (s->info->arrayfetch->ind == 0))
5061 sRef p = s->info->arrayfetch->arr;
5062 sRef ptr = sRef_constructPointer (p);
5064 if (sRef_isValid (ptr))
5066 if (ptr->defstate == SS_ALLOCATED
5067 || ptr->defstate == SS_UNDEFINED
5068 || ptr->defstate == SS_SPECIAL) /* evans 2001-07-12: shouldn't need this */
5070 sRef_setDefinedAux (ptr, loc, clear);
5074 if (p->defstate == SS_RELDEF)
5078 else if (p->defstate == SS_ALLOCATED || p->defstate == SS_PDEFINED
5079 || p->defstate == SS_SPECIAL) /* evans 2001-07-12: shouldn't need this */
5081 p->defstate = SS_DEFINED;
5088 else if (s->kind == SK_FIELD)
5090 sRef parent = s->info->field->rec;
5092 if (sRef_isValid (parent))
5094 if (ctype_isUnion (ctype_realType (parent->type)))
5097 ** Should not clear derived from here.
5100 sRef_setDefinedNoClear (parent, loc);
5104 ; /* Nothing to do for structures. */
5116 sRef_clearDerived (s);
5120 /* evans 2001-07-12: need to define the derived references */
5121 sRefSet_elements (s->deriv, el)
5123 el->defstate = SS_DEFINED;
5124 } end_sRefSet_elements ;
5127 DPRINTF (("Set defined: %s", sRef_unparseFull (s)));
5130 static void sRef_setPartialDefined (sRef s, fileloc loc)
5132 sRef_checkMutable (s);
5134 if (!sRef_isPartial (s))
5136 sRef_setDefined (s, loc);
5140 void sRef_setPartialDefinedComplete (sRef s, fileloc loc)
5142 sRef_innerAliasSetComplete (sRef_setPartialDefined, s, loc);
5145 void sRef_setDefinedComplete (sRef s, fileloc loc)
5147 DPRINTF (("Set defined complete: %s", sRef_unparseFull (s)));
5148 sRef_innerAliasSetComplete (sRef_setDefined, s, loc);
5151 void sRef_setDefined (sRef s, fileloc loc)
5153 sRef_checkMutable (s);
5154 sRef_setDefinedAux (s, loc, TRUE);
5157 static void sRef_setDefinedNoClear (sRef s, fileloc loc)
5159 sRef_checkMutable (s);
5160 DPRINTF (("Defining: %s", sRef_unparseFull (s)));
5161 sRef_setDefinedAux (s, loc, FALSE);
5162 DPRINTF (("==> %s", sRef_unparseFull (s)));
5165 void sRef_setDefinedNCComplete (sRef s, fileloc loc)
5167 sRef_checkMutable (s);
5168 DPRINTF (("Set Defined Complete: %s", sRef_unparseFull (s)));
5169 sRef_innerAliasSetComplete (sRef_setDefinedNoClear, s, loc);
5170 DPRINTF (("==> %s", sRef_unparseFull (s)));
5173 static bool sRef_isDeepUnionField (sRef s)
5175 return (sRef_deepPred (sRef_isUnionField, s));
5178 bool sRef_isUnionField (sRef s)
5180 if (sRef_isValid (s) && s->kind == SK_FIELD)
5183 ** defining one field of a union defines the union
5186 sRef base = s->info->field->rec;
5188 if (sRef_isValid (base))
5190 return (ctype_isUnion (ctype_realType (base->type)));
5197 void sRef_setPdefined (sRef s, fileloc loc)
5199 sRef_checkMutable (s);
5200 if (sRef_isValid (s) && !sRef_isPartial (s))
5202 sRef base = sRef_getBaseSafe (s);
5204 if (s->defstate == SS_ALLOCATED)
5209 if (s->defstate != SS_PDEFINED && fileloc_isDefined (loc))
5211 s->definfo = stateInfo_updateLoc (s->definfo, loc);
5214 DPRINTF (("set pdefined: %s", sRef_unparseFull (s)));
5215 s->defstate = SS_PDEFINED;
5217 /* e.g., if x is allocated, *x = 3 defines x */
5219 while (sRef_isValid (base) && sRef_isKnown (base))
5221 if (base->defstate == SS_DEFINED)
5225 base->defstate = SS_PDEFINED;
5226 nb = sRef_getBaseSafe (base);
5237 static void sRef_setStateAux (sRef s, sstate ss, fileloc loc)
5239 sRef_checkMutable (s);
5241 if (sRef_isValid (s))
5243 /* if (s->defstate == SS_RELDEF) return; */
5245 if (s->defstate != ss && fileloc_isDefined (loc))
5247 s->definfo = stateInfo_updateLoc (s->definfo, loc);
5251 sRef_clearDerived (s);
5253 if (ss == SS_ALLOCATED)
5255 sRef base = sRef_getBaseSafe (s);
5257 while (sRef_isValid (base) && sRef_isKnown (base))
5259 if (base->defstate == SS_DEFINED)
5263 base->defstate = SS_PDEFINED;
5265 nb = sRef_getBaseSafe (base);
5278 void sRef_setAllocatedComplete (sRef s, fileloc loc)
5280 sRef_innerAliasSetComplete (sRef_setAllocated, s, loc);
5283 static void sRef_setAllocatedShallow (sRef s, fileloc loc)
5285 sRef_checkMutable (s);
5287 if (sRef_isValid (s))
5289 if (s->defstate == SS_DEAD || s->defstate == SS_UNDEFINED)
5291 s->defstate = SS_ALLOCATED;
5293 if (fileloc_isDefined (loc))
5295 s->definfo = stateInfo_updateLoc (s->definfo, loc);
5301 void sRef_setAllocatedShallowComplete (sRef s, fileloc loc)
5303 sRef_innerAliasSetComplete (sRef_setAllocatedShallow, s, loc);
5306 void sRef_setAllocated (sRef s, fileloc loc)
5308 sRef_checkMutable (s);
5309 sRef_setStateAux (s, SS_ALLOCATED, loc);
5312 void sRef_setPartial (sRef s, fileloc loc)
5314 sRef_checkMutable (s);
5315 sRef_setStateAux (s, SS_PARTIAL, loc);
5318 void sRef_setShared (sRef s, fileloc loc)
5320 sRef_checkMutable (s);
5322 if (sRef_isValid (s))
5324 if (s->aliaskind != AK_SHARED && fileloc_isDefined (loc))
5326 s->aliasinfo = stateInfo_updateLoc (s->aliasinfo, loc);
5329 s->aliaskind = AK_SHARED;
5330 /* don't! sRef_clearDerived (s); */
5334 void sRef_setLastReference (sRef s, /*@exposed@*/ sRef ref, fileloc loc)
5336 sRef_checkMutable (s);
5338 if (sRef_isValid (s))
5340 s->aliaskind = sRef_getAliasKind (ref);
5341 s->aliasinfo = stateInfo_updateRefLoc (s->aliasinfo, ref, loc);
5346 void sRef_setNullStateAux (/*@notnull@*/ sRef s, nstate ns, fileloc loc)
5348 DPRINTF (("Set null state: %s / %s", sRef_unparse (s), nstate_unparse (ns)));
5349 sRef_checkMutable (s);
5352 if (fileloc_isDefined (loc))
5354 s->nullinfo = stateInfo_updateLoc (s->nullinfo, loc);
5358 void sRef_setNotNull (sRef s, fileloc loc)
5360 if (sRef_isValid (s))
5362 sRef_setNullStateAux (s, NS_NOTNULL, loc);
5366 void sRef_setNullStateN (sRef s, nstate n)
5368 sRef_checkMutable (s);
5372 void sRef_setNullState (sRef s, nstate n, fileloc loc)
5374 if (sRef_isValid (s))
5376 sRef_setNullStateAux (s, n, loc);
5380 void sRef_setNullTerminatedStateInnerComplete (sRef s, struct s_bbufinfo b, /*@unused@*/ fileloc loc) {
5382 switch (b.bufstate) {
5383 case BB_NULLTERMINATED:
5384 sRef_setNullTerminatedState (s);
5385 sRef_setLen (s, b.len);
5387 case BB_POSSIBLYNULLTERMINATED:
5388 sRef_setPossiblyNullTerminatedState(s);
5390 case BB_NOTNULLTERMINATED:
5391 sRef_setNotNullTerminatedState (s);
5394 sRef_setSize (s, b.size);
5396 /* PL: TO BE DONE : Aliases are not modified right now, have to be similar to
5397 * setNullStateInnerComplete.
5401 void sRef_setNullStateInnerComplete (sRef s, nstate n, fileloc loc)
5403 DPRINTF (("Set null state: %s", nstate_unparse (n)));
5405 sRef_setNullState (s, n, loc);
5410 sRef_innerAliasSetComplete (sRef_setPosNull, s, loc);
5413 sRef_innerAliasSetComplete (sRef_setDefNull, s, loc);
5416 sRef_innerAliasSetComplete (sRef_setNullUnknown, s, loc);
5419 sRef_innerAliasSetComplete (sRef_setNotNull, s, loc);
5422 sRef_innerAliasSetComplete (sRef_setNotNull, s, loc);
5425 sRef_innerAliasSetComplete (sRef_setNullUnknown, s, loc);
5428 sRef_innerAliasSetComplete (sRef_setDefNull, s, loc);
5431 sRef_innerAliasSetComplete (sRef_setNullUnknown, s, loc);
5434 sRef_innerAliasSetComplete (sRef_setNullErrorLoc, s, loc);
5439 void sRef_setPosNull (sRef s, fileloc loc)
5441 if (sRef_isValid (s))
5443 sRef_setNullStateAux (s, NS_POSNULL, loc);
5447 void sRef_setDefNull (sRef s, fileloc loc)
5449 if (sRef_isValid (s))
5451 sRef_setNullStateAux (s, NS_DEFNULL, loc);
5455 void sRef_setNullUnknown (sRef s, fileloc loc)
5457 if (sRef_isValid (s))
5459 sRef_setNullStateAux (s, NS_UNKNOWN, loc);
5463 void sRef_setNullError (sRef s)
5465 if (sRef_isValid (s))
5467 sRef_setNullStateAux (s, NS_UNKNOWN, fileloc_undefined);
5471 void sRef_setNullErrorLoc (sRef s, /*@unused@*/ fileloc loc)
5473 sRef_setNullError (s);
5476 void sRef_setOnly (sRef s, fileloc loc)
5478 sRef_checkMutable (s);
5480 if (sRef_isValid (s) && s->aliaskind != AK_ONLY)
5482 s->aliaskind = AK_ONLY;
5483 s->aliasinfo = stateInfo_updateLoc (s->aliasinfo, loc);
5487 void sRef_setDependent (sRef s, fileloc loc)
5489 sRef_checkMutable (s);
5491 if (sRef_isValid (s) && !sRef_isConst (s) && (s->aliaskind != AK_DEPENDENT))
5493 DPRINTF (("Setting dependent: %s", sRef_unparseFull (s)));
5494 s->aliaskind = AK_DEPENDENT;
5495 s->aliasinfo = stateInfo_updateLoc (s->aliasinfo, loc);
5499 void sRef_setOwned (sRef s, fileloc loc)
5501 sRef_checkMutable (s);
5503 if (sRef_isValid (s) && !sRef_isConst (s) && (s->aliaskind != AK_OWNED))
5505 s->aliaskind = AK_OWNED;
5506 s->aliasinfo = stateInfo_updateLoc (s->aliasinfo, loc);
5510 void sRef_setKept (sRef s, fileloc loc)
5512 sRef_checkMutable (s);
5514 if (sRef_isValid (s) && !sRef_isConst (s) && (s->aliaskind != AK_KEPT))
5516 sRef base = sRef_getBaseSafe (s);
5518 while (sRef_isValid (base) && sRef_isKnown (base))
5520 if (base->defstate == SS_DEFINED)
5522 base->defstate = SS_PDEFINED;
5523 base = sRef_getBaseSafe (base);
5532 s->aliaskind = AK_KEPT;
5533 s->aliasinfo = stateInfo_updateLoc (s->aliasinfo, loc);
5537 static void sRef_setKeptAux (sRef s, fileloc loc)
5539 if (!sRef_isShared (s))
5541 sRef_setKept (s, loc);
5545 static void sRef_setDependentAux (sRef s, fileloc loc)
5547 if (!sRef_isShared (s))
5549 sRef_setDependent (s, loc);
5553 void sRef_setKeptComplete (sRef s, fileloc loc)
5555 sRef_aliasSetComplete (sRef_setKeptAux, s, loc);
5558 void sRef_setDependentComplete (sRef s, fileloc loc)
5560 sRef_aliasSetComplete (sRef_setDependentAux, s, loc);
5563 void sRef_setFresh (sRef s, fileloc loc)
5565 sRef_checkMutable (s);
5567 if (sRef_isValid (s))
5569 s->aliaskind = AK_FRESH;
5570 s->aliasinfo = stateInfo_updateLoc (s->aliasinfo, loc);
5574 void sRef_kill (sRef s, fileloc loc)
5576 DPRINTF (("Kill: %s", sRef_unparseFull (s)));
5577 sRef_checkMutable (s);
5579 if (sRef_isValid (s) && !sRef_isShared (s) && !sRef_isConst (s))
5581 sRef base = sRef_getBaseSafe (s);
5583 while (sRef_isValid (base) && sRef_isKnown (base))
5585 if (base->defstate == SS_DEFINED)
5587 base->defstate = SS_PDEFINED;
5588 base = sRef_getBaseSafe (base);
5596 s->aliaskind = s->oaliaskind;
5597 s->defstate = SS_DEAD;
5598 s->definfo = stateInfo_updateLoc (s->definfo, loc);
5600 sRef_clearDerived (s);
5604 void sRef_maybeKill (sRef s, fileloc loc)
5606 sRef_checkMutable (s);
5608 if (sRef_isValid (s))
5610 sRef base = sRef_getBaseSafe (s);
5613 while (sRef_isValid (base) && sRef_isKnown (base))
5615 if (base->defstate == SS_DEFINED || base->defstate == SS_RELDEF)
5617 base->defstate = SS_PDEFINED;
5618 base = sRef_getBaseSafe (base);
5627 s->aliaskind = s->oaliaskind;
5628 s->defstate = SS_HOFFA;
5629 s->definfo = stateInfo_updateLoc (s->definfo, loc);
5630 sRef_clearDerived (s);
5636 ** just for type checking...
5639 static void sRef_killAux (sRef s, fileloc loc)
5641 if (sRef_isValid (s) && !sRef_isShared (s))
5643 if (sRef_isUnknownArrayFetch (s))
5645 sRef_maybeKill (s, loc);
5655 ** kills s and all aliases to s
5658 void sRef_killComplete (sRef s, fileloc loc)
5660 DPRINTF (("Kill complete: %s", sRef_unparseFull (s)));
5661 sRef_aliasSetComplete (sRef_killAux, s, loc);
5664 static bool sRef_equivalent (sRef s1, sRef s2)
5666 return (sRef_compare (s1, s2) == 0);
5670 ** returns an sRef that will not be free'd on function exit.
5673 /*@only@*/ sRef sRef_saveCopy (sRef s)
5677 if (sRef_isValid (s))
5679 bool old = inFunction;
5682 ** Exit the function scope, so this sRef is not
5683 ** stored in the deallocation table.
5687 DPRINTF (("Copying sref: %s", sRef_unparseFull(s)));
5688 ret = sRef_copy (s);
5689 DPRINTF (("Copying ===>: %s", sRef_unparseFull(ret)));
5694 ret = sRef_undefined;
5697 /*@-dependenttrans@*/
5699 /*@=dependenttrans@*/
5702 sRef sRef_copy (sRef s)
5704 if (sRef_isKindSpecial (s) && !sRef_isGlobalMarker (s))
5707 return s; /* don't copy specials (except for global markers) */
5711 if (sRef_isValid (s))
5713 sRef t = sRef_alloc ();
5715 DPRINTF (("Copying: [%p] %s", s, sRef_unparse (s)));
5716 DPRINTF (("Full: %s", sRef_unparseFull (s)));
5720 t->modified = s->modified;
5721 t->immut = FALSE; /* Note mutability is not copied. */
5723 t->val = multiVal_copy (s->val);
5725 t->info = sinfo_copy (s);
5726 t->defstate = s->defstate;
5727 t->nullstate = s->nullstate;
5729 /* start modifications */
5730 t->bufinfo.bufstate = s->bufinfo.bufstate;
5731 t->bufinfo.len = s->bufinfo.len;
5732 t->bufinfo.size = s->bufinfo.size;
5733 /* end modifications */
5735 t->aliaskind = s->aliaskind;
5736 t->oaliaskind = s->oaliaskind;
5738 t->expkind = s->expkind;
5739 t->oexpkind = s->oexpkind;
5741 t->nullinfo = stateInfo_copy (s->nullinfo);
5742 t->aliasinfo = stateInfo_copy (s->aliasinfo);
5743 t->definfo = stateInfo_copy (s->definfo);
5744 t->expinfo = stateInfo_copy (s->expinfo);
5746 t->deriv = sRefSet_newDeepCopy (s->deriv);
5747 t->state = valueTable_copy (s->state);
5749 DPRINTF (("Made copy: [%p] %s", t, sRef_unparse (t)));
5754 return sRef_undefined;
5759 # define PREDTEST(func,s) \
5760 do { if (sRef_isInvalid (s)) { return FALSE; } \
5761 else { if (sRef_isConj (s)) \
5762 { return (func (sRef_getConjA (s)) \
5763 || func (sRef_getConjB (s))); }}} while (FALSE);
5765 bool sRef_isAddress (sRef s)
5767 PREDTEST (sRef_isAddress, s);
5768 return (s->kind == SK_ADR);
5772 ** pretty weak... maybe a flag should control this.
5775 bool sRef_isThroughArrayFetch (sRef s)
5777 if (sRef_isValid (s))
5785 if (sRef_isArrayFetch (tref))
5790 lt = sRef_getBase (tref);
5792 } while (sRef_isValid (tref));
5798 bool sRef_isArrayFetch (sRef s)
5800 PREDTEST (sRef_isArrayFetch, s);
5801 return (s->kind == SK_ARRAYFETCH);
5804 bool sRef_isMacroParamRef (sRef s)
5806 if (context_inMacro () && sRef_isCvar (s))
5808 uentry ue = sRef_getUentry (s);
5809 cstring pname = makeParam (uentry_rawName (ue));
5810 uentry mac = usymtab_lookupSafe (pname);
5812 cstring_free (pname);
5813 return (uentry_isValid (mac));
5819 bool sRef_isCvar (sRef s)
5821 PREDTEST (sRef_isCvar, s);
5822 return (s->kind == SK_CVAR);
5825 bool sRef_isConst (sRef s)
5827 PREDTEST (sRef_isConst, s);
5828 return (s->kind == SK_CONST);
5831 bool sRef_isObject (sRef s)
5833 PREDTEST (sRef_isObject, s);
5834 return (s->kind == SK_OBJECT);
5837 bool sRef_isExternal (sRef s)
5839 PREDTEST (sRef_isExternal, s);
5840 return (s->kind == SK_EXTERNAL);
5843 static bool sRef_isDerived (sRef s)
5845 PREDTEST (sRef_isDerived, s);
5846 return (s->kind == SK_DERIVED);
5849 bool sRef_isField (sRef s)
5851 PREDTEST (sRef_isField, s);
5852 return (s->kind == SK_FIELD);
5855 static bool sRef_isIndex (sRef s)
5857 PREDTEST (sRef_isIndex, s);
5858 return (s->kind == SK_ARRAYFETCH);
5861 bool sRef_isAnyParam (sRef s)
5863 PREDTEST (sRef_isAnyParam, s);
5864 return (s->kind == SK_PARAM);
5867 bool sRef_isParam (sRef s)
5869 PREDTEST (sRef_isParam, s);
5870 return (s->kind == SK_PARAM);
5873 bool sRef_isDirectParam (sRef s)
5875 PREDTEST (sRef_isDirectParam, s);
5877 return ((s->kind == SK_CVAR) &&
5878 (s->info->cvar->lexlevel == functionScope) &&
5879 (context_inFunction () &&
5880 (s->info->cvar->index <= uentryList_size (context_getParams ()))));
5883 bool sRef_isPointer (sRef s)
5885 PREDTEST (sRef_isPointer, s);
5886 return (s->kind == SK_PTR);
5890 ** returns true if storage referenced by s is visible
5893 bool sRef_isReference (sRef s)
5895 PREDTEST (sRef_isReference, s);
5897 return (sRef_isPointer (s) || sRef_isIndex (s) || sRef_isFileOrGlobalScope (s)
5898 || (sRef_isField (s) && (sRef_isReference (s->info->field->rec))));
5901 bool sRef_isIReference (sRef s)
5903 return (sRef_isPointer (s) || sRef_isAddress (s) || sRef_isIndex (s)
5904 || sRef_isField (s) || sRef_isArrayFetch (s));
5907 bool sRef_isFileOrGlobalScope (sRef s)
5909 return (sRef_isCvar (s) && (s->info->cvar->lexlevel <= fileScope));
5912 bool sRef_isRealGlobal (sRef s)
5914 return (sRef_isCvar (s) && (s->info->cvar->lexlevel == globScope));
5917 bool sRef_isFileStatic (sRef s)
5919 return (sRef_isCvar (s) && (s->info->cvar->lexlevel == fileScope));
5922 bool sRef_isAliasCheckedGlobal (sRef s)
5924 if (sRef_isFileOrGlobalScope (s))
5926 uentry ue = sRef_getUentry (s);
5928 return context_checkAliasGlob (ue);
5936 void sRef_free (/*@only@*/ sRef s)
5938 if (s != sRef_undefined && s->kind != SK_SPECIAL)
5940 DPRINTF (("Free sref: [%p]", s));
5942 sRef_checkValid (s);
5944 stateInfo_free (s->expinfo);
5945 stateInfo_free (s->aliasinfo);
5946 stateInfo_free (s->definfo);
5947 stateInfo_free (s->nullinfo);
5949 sRefSet_free (s->deriv);
5950 s->deriv = sRefSet_undefined;
5952 /*@i43@*/ /* valueTable_free (s->state); */
5956 /* drl added to help locate use after release*/
5957 s->expinfo = stateInfo_undefined;
5958 s->aliasinfo = stateInfo_undefined;
5959 s->definfo = stateInfo_undefined;
5960 s->nullinfo = stateInfo_undefined;
5962 /*@i32@*/ sfree (s);
5966 void sRef_setType (sRef s, ctype t)
5968 sRef_checkMutable (s);
5970 if (sRef_isValid (s))
5976 void sRef_setTypeFull (sRef s, ctype t)
5978 sRef_checkMutable (s);
5980 if (sRef_isValid (s))
5984 sRefSet_allElements (s->deriv, current)
5986 sRef_setTypeFull (current, ctype_unknown);
5987 } end_sRefSet_allElements ;
5992 sRef_buildField (/*@exposed@*/ sRef rec, /*@dependent@*/ cstring f)
5994 return (sRef_buildNCField (rec, f));
5997 static /*@exposed@*/ sRef
5998 sRef_findDerivedField (/*@notnull@*/ sRef rec, cstring f)
6000 sRefSet_allElements (rec->deriv, sr)
6002 if (sRef_isValid (sr))
6004 if (sr->info != NULL)
6006 if (sr->kind == SK_FIELD && cstring_equal (sr->info->field->field, f))
6012 } end_sRefSet_allElements;
6014 return sRef_undefined;
6017 /*@dependent@*/ /*@observer@*/ sRefSet sRef_derivedFields (/*@temp@*/ sRef rec)
6019 if (sRef_isValid (rec))
6027 return (sRefSet_undefined);
6031 static /*@exposed@*/ sRef
6032 sRef_findDerivedPointer (sRef s)
6034 if (sRef_isValid (s))
6036 sRefSet_realElements (s->deriv, sr)
6038 if (sRef_isValid (sr) && sr->kind == SK_PTR)
6042 } end_sRefSet_realElements;
6045 return sRef_undefined;
6049 sRef_isUnknownArrayFetch (sRef s)
6051 return (sRef_isValid (s)
6052 && s->kind == SK_ARRAYFETCH
6053 && !s->info->arrayfetch->indknown);
6056 static /*@exposed@*/ sRef
6057 sRef_findDerivedArrayFetch (/*@notnull@*/ sRef s, bool isknown, int idx, bool dead)
6062 sRefSet_realElements (s->deriv, sr)
6064 if (sRef_isValid (sr)
6065 && sr->kind == SK_ARRAYFETCH
6066 && sr->info->arrayfetch->indknown
6067 && (sr->info->arrayfetch->ind == idx))
6071 } end_sRefSet_realElements;
6075 sRefSet_realElements (s->deriv, sr)
6077 if (sRef_isValid (sr)
6078 && sr->kind == SK_ARRAYFETCH
6079 && (!sr->info->arrayfetch->indknown
6080 || (sr->info->arrayfetch->indknown &&
6081 sr->info->arrayfetch->ind == 0)))
6083 if (sRef_isDead (sr) || sRef_isKept (sr))
6085 if (dead || context_getFlag (FLG_STRICTUSERELEASED))
6095 } end_sRefSet_realElements;
6098 return sRef_undefined;
6101 static /*@exposed@*/ sRef
6102 sRef_buildNCField (/*@exposed@*/ sRef rec, /*@exposed@*/ cstring f)
6106 DPRINTF (("Build nc field: %s / %s",
6107 sRef_unparseFull (rec), f));
6109 if (sRef_isInvalid (rec))
6111 return sRef_undefined;
6115 ** check if the field already has been referenced
6118 s = sRef_findDerivedField (rec, f);
6120 if (sRef_isValid (s))
6126 ctype ct = ctype_realType (rec->type);
6128 DPRINTF (("Field of: %s", sRef_unparse (rec)));
6132 s->info = (sinfo) dmalloc (sizeof (*s->info));
6133 s->info->field = (fldinfo) dmalloc (sizeof (*s->info->field));
6134 s->info->field->rec = rec; /* sRef_copy (rec); */ /*@i32@*/
6135 s->info->field->field = f; /* doesn't copy f */
6137 if (ctype_isKnown (ct) && ctype_isSU (ct))
6139 uentry ue = uentryList_lookupField (ctype_getFields (ct), f);
6141 if (!uentry_isUndefined (ue))
6143 DPRINTF (("lookup: %s for %s", uentry_unparseFull (ue),
6144 ctype_unparse (ct)));
6146 s->type = uentry_getType (ue);
6148 if (ctype_isMutable (s->type)
6149 && rec->aliaskind != AK_STACK
6150 && !alkind_isStatic (rec->aliaskind))
6152 s->aliaskind = rec->aliaskind;
6156 s->aliaskind = AK_UNKNOWN;
6159 if (sRef_isStateDefined (rec) || sRef_isStateUnknown (rec)
6160 || sRef_isPdefined (rec))
6162 sRef_setStateFromUentry (s, ue);
6166 sRef_setPartsFromUentry (s, ue);
6169 s->oaliaskind = s->aliaskind;
6170 s->oexpkind = s->expkind;
6172 DPRINTF (("sref: %s", sRef_unparseFull (s)));
6177 Never report this as an error. It can happen whenever there
6178 is casting involved.
6182 llcontbug (message ("buildNCField --- no field %s: %q / %s",
6183 f, sRef_unparse (s), ctype_unparse (ct)));
6187 return sRef_undefined;
6191 if (rec->defstate == SS_DEFINED
6192 && (s->defstate == SS_UNDEFINED || s->defstate == SS_UNKNOWN))
6194 s->defstate = SS_DEFINED;
6196 else if (rec->defstate == SS_PARTIAL)
6198 s->defstate = SS_PARTIAL;
6200 else if (rec->defstate == SS_ALLOCATED)
6202 if (ctype_isStackAllocated (ct) && ctype_isStackAllocated (s->type))
6204 s->defstate = SS_ALLOCATED;
6208 s->defstate = SS_UNDEFINED;
6211 else if (s->defstate == SS_UNKNOWN)
6213 s->defstate = rec->defstate;
6220 if (s->defstate == SS_UNDEFINED)
6222 ctype rt = ctype_realType (s->type);
6224 if (ctype_isArray (rt) || ctype_isSU (rt))
6226 s->defstate = SS_ALLOCATED;
6230 sRef_addDeriv (rec, s);
6231 DPRINTF (("Add deriv: %s", sRef_unparseFull (rec)));
6233 if (ctype_isInt (s->type) && cstring_equal (f, REFSNAME))
6235 s->aliaskind = AK_REFS;
6236 s->oaliaskind = AK_REFS;
6239 DPRINTF (("Build field ==> %s", sRef_unparseFull (s)));
6245 sRef_isStackAllocated (sRef s)
6247 return (sRef_isValid(s)
6248 && s->defstate == SS_ALLOCATED && ctype_isStackAllocated (s->type));
6252 void sRef_setArrayFetchState (/*@notnull@*/ /*@exposed@*/ sRef s,
6253 /*@notnull@*/ /*@exposed@*/ sRef arr)
6255 sRef_checkMutable (s);
6257 if (ctype_isRealAP (arr->type))
6259 s->type = ctype_baseArrayPtr (arr->type);
6262 /* a hack, methinks... makeArrayFetch (&a[0]) ==> a[] */
6263 /* evans - 2001-08-27: not sure where this was necessary - it
6264 ** causes an assertion in in aliasCheckPred to fail.
6267 if (sRef_isAddress (arr))
6269 sRef t = arr->info->ref;
6271 if (sRef_isArrayFetch (t))
6273 s->info->arrayfetch->arr = t->info->arrayfetch->arr;
6276 else if (ctype_isRealPointer (arr->type))
6278 sRef sp = sRef_findDerivedPointer (arr);
6280 if (sRef_isValid (sp))
6283 if (ctype_isMutable (s->type))
6285 sRef_setExKind (s, sRef_getExKind (sp), fileloc_undefined);
6287 s->aliaskind = sp->aliaskind;
6290 s->defstate = sp->defstate;
6292 if (s->defstate == SS_DEFINED)
6294 if (!context_getFlag (FLG_STRICTDESTROY))
6296 s->defstate = SS_PARTIAL;
6300 sRef_setNullStateN (s, sRef_getNullState (sp));
6304 if (arr->defstate == SS_UNDEFINED)
6306 s->defstate = SS_UNUSEABLE;
6308 else if ((arr->defstate == SS_ALLOCATED) && !ctype_isSU (s->type))
6310 s->defstate = SS_UNDEFINED;
6314 if (!context_getFlag (FLG_STRICTDESTROY))
6316 s->defstate = SS_PARTIAL;
6320 s->defstate = SS_DEFINED;
6324 ** Very weak checking for array elements.
6326 ** s->defstate = arr->defstate;
6330 sRef_setExKind (s, sRef_getExKind (arr), g_currentloc);
6332 if (arr->aliaskind == AK_LOCAL || arr->aliaskind == AK_FRESH)
6334 s->aliaskind = AK_LOCAL;
6338 s->aliaskind = AK_UNKNOWN;
6341 sRef_setTypeState (s);
6346 if (arr->defstate == SS_DEFINED)
6349 ** Very weak checking for array elements.
6351 ** s->defstate = arr->defstate;
6354 if (context_getFlag (FLG_STRICTDESTROY))
6356 s->defstate = SS_DEFINED;
6360 s->defstate = SS_PARTIAL;
6363 else if (arr->defstate == SS_ALLOCATED)
6365 if (ctype_isRealArray (s->type))
6367 s->defstate = SS_ALLOCATED;
6371 if (!s->info->arrayfetch->indknown)
6374 ** is index is unknown, elements is defined or
6375 ** allocated is any element is!
6378 s->defstate = SS_UNDEFINED;
6380 sRefSet_allElements (arr->deriv, sr)
6382 if (sRef_isValid (sr))
6384 if (sr->defstate == SS_ALLOCATED)
6386 s->defstate = SS_ALLOCATED;
6390 if (sr->defstate == SS_DEFINED)
6392 if (context_getFlag (FLG_STRICTDESTROY))
6394 s->defstate = SS_DEFINED;
6398 s->defstate = SS_PARTIAL;
6405 } end_sRefSet_allElements;
6410 s->defstate = SS_UNDEFINED;
6416 s->defstate = arr->defstate;
6421 ** kludgey way to guess where aliaskind applies
6424 if (ctype_isMutable (s->type)
6425 && !ctype_isPointer (arr->type)
6426 && !alkind_isStatic (arr->aliaskind)
6427 && !alkind_isStack (arr->aliaskind)) /* evs - 2000-06-20: don't pass stack allocation to members */
6429 s->aliaskind = arr->aliaskind;
6433 s->aliaskind = AK_UNKNOWN;
6436 sRef_setTypeState (s);
6439 if (sRef_isObserver (arr))
6441 s->expkind = XO_OBSERVER;
6445 /*@exposed@*/ sRef sRef_buildArrayFetch (/*@exposed@*/ sRef arr)
6449 if (!sRef_isValid (arr)) {
6450 /*@-nullret@*/ return arr /*@=nullret@*/;
6453 if (ctype_isRealPointer (arr->type))
6455 (void) sRef_buildPointer (arr); /* do this to define arr! */
6458 s = sRef_findDerivedArrayFetch (arr, FALSE, 0, FALSE);
6460 if (sRef_isValid (s))
6462 /* evans 2001-07-12: this is bogus, clean-up hack */
6463 if (s->info->arrayfetch->arr != arr)
6466 check (sRefSet_delete (arr->deriv, s));
6467 res = sRef_buildArrayFetch (arr);
6468 sRef_copyState (res, s);
6469 llassert (res->info->arrayfetch->arr == arr);
6473 sRef_setExKind (s, sRef_getExKind (arr), g_currentloc);
6480 s->kind = SK_ARRAYFETCH;
6481 s->info = (sinfo) dmalloc (sizeof (*s->info));
6482 s->info->arrayfetch = (ainfo) dmalloc (sizeof (*s->info->arrayfetch));
6483 s->info->arrayfetch->indknown = FALSE;
6484 s->info->arrayfetch->ind = 0;
6485 s->info->arrayfetch->arr = arr; /* sRef_copy (arr); */ /*@i32@*/
6486 sRef_setArrayFetchState (s, arr);
6487 s->oaliaskind = s->aliaskind;
6488 s->oexpkind = s->expkind;
6490 if (!context_inProtectVars ())
6492 sRef_addDeriv (arr, s);
6495 if (valueTable_isUndefined (s->state))
6497 s->state = context_createValueTable (s, stateInfo_makeLoc (g_currentloc));
6505 sRef_buildArrayFetchKnown (/*@exposed@*/ sRef arr, int i)
6509 if (!sRef_isValid (arr)) {
6510 /*@-nullret@*/ return arr /*@=nullret@*/;
6513 if (ctype_isRealPointer (arr->type))
6515 (void) sRef_buildPointer (arr); /* do this to define arr! */
6518 s = sRef_findDerivedArrayFetch (arr, TRUE, i, FALSE);
6520 if (sRef_isValid (s))
6522 /* evans 2001-07-12: this is bogus, clean-up hack */
6523 if (s->info->arrayfetch->arr != arr)
6527 check (sRefSet_delete (arr->deriv, s));
6528 res = sRef_buildArrayFetchKnown (arr, i);
6530 llassert (res->info->arrayfetch->arr == arr);
6531 sRef_copyState (res, s);
6532 llassert (res->info->arrayfetch->arr == arr);
6536 sRef_setExKind (s, sRef_getExKind (arr), g_currentloc);
6537 llassert (s->info->arrayfetch->arr == arr);
6544 s->kind = SK_ARRAYFETCH;
6545 s->info = (sinfo) dmalloc (sizeof (*s->info));
6546 s->info->arrayfetch = (ainfo) dmalloc (sizeof (*s->info->arrayfetch));
6547 s->info->arrayfetch->arr = arr; /* sRef_copy (arr); */ /*@i32@*/
6548 s->info->arrayfetch->indknown = TRUE;
6549 s->info->arrayfetch->ind = i;
6551 sRef_setArrayFetchState (s, arr);
6552 /* evans 2001-08-27 no: can change this - llassert (s->info->arrayfetch->arr == arr); */
6554 s->oaliaskind = s->aliaskind;
6555 s->oexpkind = s->expkind;
6556 sRef_addDeriv (arr, s);
6558 llassert (valueTable_isUndefined (s->state));
6559 s->state = context_createValueTable (s, stateInfo_makeLoc (g_currentloc));
6565 ** sets everything except for defstate
6569 sRef_setPartsFromUentry (sRef s, uentry ue)
6571 sRef uref = uentry_getSref (ue);
6573 llassert (sRef_isValid (s));
6575 s->aliaskind = alkind_derive (s->aliaskind, uentry_getAliasKind (ue));
6576 s->oaliaskind = s->aliaskind;
6578 if (s->expkind == XO_UNKNOWN)
6580 s->expkind = uentry_getExpKind (ue);
6583 s->oexpkind = s->expkind;
6585 if (sRef_getNullState (s) == NS_UNKNOWN)
6587 DPRINTF (("Setting null state!"));
6588 sRef_setNullStateN (s, sRef_getNullState (uentry_getSref (ue)));
6592 DPRINTF (("Skipping null null state!"));
6595 if (s->aliaskind == AK_IMPONLY && (sRef_isExposed (s) || sRef_isObserver (s)))
6597 s->oaliaskind = s->aliaskind = AK_IMPDEPENDENT;
6600 if (sRef_isValid (uref))
6602 valueTable utable = uref->state;
6603 valueTable_free (s->state);
6604 s->state = valueTable_copy (utable);
6609 sRef_setStateFromAbstractUentry (sRef s, uentry ue)
6611 llassert (sRef_isValid (s));
6612 sRef_checkMutable (s);
6614 sRef_setPartsFromUentry (s, ue);
6616 s->aliaskind = alkind_derive (s->aliaskind, uentry_getAliasKind (ue));
6617 s->oaliaskind = s->aliaskind;
6619 if (s->expkind == XO_UNKNOWN)
6621 s->expkind = uentry_getExpKind (ue);
6624 s->oexpkind = s->expkind;
6628 sRef_setStateFromUentry (sRef s, uentry ue)
6632 sRef_checkMutable (s);
6633 llassert (sRef_isValid (s));
6635 sRef_setPartsFromUentry (s, ue);
6637 defstate = uentry_getDefState (ue);
6639 if (sstate_isKnown (defstate))
6641 s->defstate = defstate;
6650 sRef_buildPointer (/*@exposed@*/ sRef t)
6652 DPRINTF (("build pointer: %s", sRef_unparse (t)));
6654 if (sRef_isInvalid (t)) return sRef_undefined;
6656 if (sRef_isAddress (t))
6658 DPRINTF (("Return ref: %s", sRef_unparse (t->info->ref)));
6659 return (t->info->ref);
6663 sRef s = sRef_findDerivedPointer (t);
6665 DPRINTF (("find derived: %s", sRef_unparse (s)));
6667 if (sRef_isValid (s))
6670 sRef_setExKind (s, sRef_getExKind (t), g_currentloc);
6671 s->oaliaskind = s->aliaskind;
6672 s->oexpkind = s->expkind;
6678 s = sRef_constructPointerAux (t);
6680 DPRINTF (("construct: %s", sRef_unparse (s)));
6682 if (sRef_isValid (s))
6684 sRef_addDeriv (t, s);
6686 s->oaliaskind = s->aliaskind;
6687 s->oexpkind = s->expkind;
6696 sRef_constructPointer (/*@exposed@*/ sRef t)
6699 return sRef_buildPointer (t);
6702 static /*@exposed@*/ sRef sRef_constructDerefAux (sRef t, bool isdead)
6704 if (sRef_isValid (t))
6709 ** if there is a derived t[?], return that. Otherwise, *t.
6712 s = sRef_findDerivedArrayFetch (t, FALSE, 0, isdead);
6714 if (sRef_isValid (s))
6716 DPRINTF (("Found array fetch: %s", sRef_unparseFull (s)));
6721 sRef ret = sRef_constructPointer (t);
6723 DPRINTF (("Constructed pointer: %s", sRef_unparseFull (ret)));
6730 return sRef_undefined;
6734 sRef sRef_constructDeref (sRef t)
6736 return sRef_constructDerefAux (t, FALSE);
6739 sRef sRef_constructDeadDeref (sRef t)
6741 return sRef_constructDerefAux (t, TRUE);
6745 sRef_constructPointerAux (/*@notnull@*/ /*@exposed@*/ sRef t)
6747 sRef s = sRef_newRef ();
6751 llassert (valueTable_isUndefined (s->state));
6754 s->info = (sinfo) dmalloc (sizeof (*s->info));
6755 s->info->ref = t; /* sRef_copy (t); */ /*@i32*/
6757 if (ctype_isRealAP (rt))
6759 s->type = ctype_baseArrayPtr (rt);
6762 st = ctype_realType (s->type);
6764 if (t->defstate == SS_UNDEFINED)
6766 s->defstate = SS_UNUSEABLE;
6768 else if ((t->defstate == SS_ALLOCATED) && !ctype_isSU (st))
6770 s->defstate = SS_UNDEFINED;
6774 s->defstate = t->defstate;
6777 if (t->aliaskind == AK_LOCAL || t->aliaskind == AK_FRESH)
6779 s->aliaskind = AK_LOCAL;
6783 s->aliaskind = AK_UNKNOWN;
6786 sRef_setExKind (s, sRef_getExKind (t), fileloc_undefined);
6787 sRef_setTypeState (s);
6789 s->oaliaskind = s->aliaskind;
6790 s->oexpkind = s->expkind;
6792 if (valueTable_isUndefined (s->state))
6794 s->state = context_createValueTable (s, stateInfo_makeLoc (g_currentloc));
6800 bool sRef_hasDerived (sRef s)
6802 return (sRef_isValid (s) && !sRefSet_isEmpty (s->deriv));
6806 sRef_clearDerived (sRef s)
6808 if (sRef_isValid (s))
6810 sRefSet_clear (s->deriv);
6815 sRef_clearDerivedComplete (sRef s)
6818 if (sRef_isValid (s))
6820 sRef base = sRef_getBaseSafe (s);
6822 while (sRef_isValid (base))
6824 sRefSet_clear (base->deriv);
6825 base = sRef_getBaseSafe (base);
6828 sRefSet_clear (s->deriv);
6832 /*@exposed@*/ sRef sRef_makePointer (/*@exposed@*/ sRef s)
6835 sRef res = sRef_buildPointer (s);
6837 DPRINTF (("Res: %s", sRef_unparse (res)));
6842 ** &a[] => a (this is for out params)
6846 sRef_makeAnyArrayFetch (/*@exposed@*/ sRef arr)
6849 if (sRef_isAddress (arr))
6851 return (arr->info->ref);
6855 return (sRef_buildArrayFetch (arr));
6860 sRef_makeArrayFetch (/*@exposed@*/ sRef arr)
6862 return (sRef_buildArrayFetch (arr));
6866 sRef_makeArrayFetchKnown (/*@exposed@*/ sRef arr, int i)
6868 return (sRef_buildArrayFetchKnown (arr, i));
6872 sRef_makeField (sRef rec, /*@dependent@*/ cstring f)
6875 ret = sRef_buildField (rec, f);
6880 sRef_makeNCField (/*@exposed@*/ sRef rec, /*@dependent@*/ cstring f)
6882 return (sRef_buildNCField (rec, f));
6886 sRef_unparseKindName (sRef s)
6890 if (s == sRef_undefined) return cstring_makeLiteral ("<invalid>");
6892 s = sRef_fixConj (s);
6897 if (sRef_isLocalVar (s))
6899 result = cstring_makeLiteral ("Variable");
6903 result = cstring_makeLiteral ("Undef global");
6907 result = cstring_makeLiteral ("Out parameter");
6910 if (sRef_isAnyParam (s->info->arrayfetch->arr))
6912 result = cstring_makeLiteral ("Out parameter");
6914 else if (sRef_isIndexKnown (s))
6916 result = cstring_makeLiteral ("Array element");
6920 result = cstring_makeLiteral ("Value");
6924 if (sRef_isAnyParam (s->info->ref))
6926 result = cstring_makeLiteral ("Out parameter");
6930 result = cstring_makeLiteral ("Value");
6934 result = cstring_makeLiteral ("Value");
6937 result = cstring_makeLiteral ("Field");
6940 result = cstring_makeLiteral ("Object");
6942 case SK_UNCONSTRAINED:
6943 result = cstring_makeLiteral ("<anything>");
6952 result = cstring_makeLiteral ("<unknown>");
6955 result = cstring_makeLiteral ("<conj>");
6958 result = cstring_makeLiteral ("Storage");
6966 sRef_unparseKindNamePlain (sRef s)
6970 if (s == sRef_undefined) return cstring_makeLiteral ("<invalid>");
6972 s = sRef_fixConj (s);
6977 if (sRef_isLocalVar (s))
6979 result = cstring_makeLiteral ("Variable");
6983 result = cstring_makeLiteral ("Global");
6987 result = cstring_makeLiteral ("Parameter");
6990 if (sRef_isAnyParam (s->info->arrayfetch->arr))
6992 result = cstring_makeLiteral ("Parameter");
6994 else if (sRef_isIndexKnown (s))
6996 result = cstring_makeLiteral ("Array element");
7000 result = cstring_makeLiteral ("Value");
7004 if (sRef_isAnyParam (s->info->ref))
7006 result = cstring_makeLiteral ("Parameter");
7010 result = cstring_makeLiteral ("Value");
7014 result = cstring_makeLiteral ("Value");
7017 result = cstring_makeLiteral ("Field");
7020 result = cstring_makeLiteral ("Object");
7023 result = cstring_makeLiteral ("Storage");
7025 case SK_UNCONSTRAINED:
7026 result = cstring_makeLiteral ("<anything>");
7035 result = cstring_makeLiteral ("<unknown>");
7038 result = cstring_makeLiteral ("<conj>");
7050 sRef_copyState (sRef s1, sRef s2)
7052 if (sRef_isValid (s1) && sRef_isValid (s2))
7054 s1->defstate = s2->defstate;
7056 /* start modifications */
7057 s1->bufinfo.bufstate = s2->bufinfo.bufstate;
7058 s1->bufinfo.len = s2->bufinfo.len;
7059 s1->bufinfo.size = s2->bufinfo.size;
7060 /* end modifications */
7062 s1->aliaskind = s2->aliaskind;
7063 s1->aliasinfo = stateInfo_update (s1->aliasinfo, s2->aliasinfo);
7065 s1->expkind = s2->expkind;
7066 s1->expinfo = stateInfo_update (s1->expinfo, s2->expinfo);
7068 s1->nullstate = s2->nullstate;
7069 s1->nullinfo = stateInfo_update (s1->nullinfo, s2->nullinfo);
7072 /*@i834 don't free it: valueTable_free (s1->state); */
7073 /*@i32@*/ s1->state = valueTable_copy (s2->state);
7075 s1->safe = s2->safe;
7080 sRef_makeNew (ctype ct, sRef t, cstring name)
7082 sRef s = sRef_newRef ();
7087 llassert (sRef_isValid (t));
7088 s->defstate = t->defstate;
7090 s->aliaskind = t->aliaskind;
7091 s->oaliaskind = s->aliaskind;
7092 s->nullstate = t->nullstate;
7094 s->expkind = t->expkind;
7095 s->oexpkind = s->expkind;
7097 s->info = (sinfo) dmalloc (sizeof (*s->info));
7098 s->info->fname = name;
7100 /* start modifications */
7101 s->bufinfo.bufstate = t->bufinfo.bufstate;
7102 /* end modifications */
7104 llassert (valueTable_isUndefined (s->state));
7105 s->state = valueTable_copy (t->state);
7107 DPRINTF (("==> Copying state: %s", valueTable_unparse (s->state)));
7108 DPRINTF (("==> new: %s", sRef_unparseFull (s)));
7113 sRef_makeType (ctype ct)
7115 sRef s = sRef_newRef ();
7117 sRef_checkMutable (s);
7122 s->defstate = SS_UNKNOWN;
7123 s->aliaskind = AK_UNKNOWN;
7124 sRef_setNullStateN (s, NS_UNKNOWN);
7126 /* start modification */
7127 s->bufinfo.bufstate = BB_NOTNULLTERMINATED;
7128 /* end modification */
7131 if (ctype_isUA (ct))
7133 typeId uid = ctype_typeId (ct);
7134 uentry ue = usymtab_getTypeEntrySafe (uid);
7136 if (uentry_isValid (ue))
7138 sRef_mergeStateQuiet (s, uentry_getSref (ue));
7142 s->oaliaskind = s->aliaskind;
7143 s->oexpkind = s->expkind;
7144 llassert (valueTable_isUndefined (s->state));
7145 s->state = context_createValueTable (s, stateInfo_makeLoc (g_currentloc));
7147 DPRINTF (("Create: %s", sRef_unparseFull (s)));
7152 sRef_makeConst (ctype ct)
7154 sRef s = sRef_newRef ();
7159 s->defstate = SS_UNKNOWN;
7160 s->aliaskind = AK_UNKNOWN;
7161 sRef_setNullStateN (s, NS_UNKNOWN);
7163 /* start modification */
7164 s->bufinfo.bufstate = BB_NULLTERMINATED;
7165 /* end modification */
7166 if (ctype_isUA (ct))
7168 typeId uid = ctype_typeId (ct);
7169 uentry te = usymtab_getTypeEntrySafe (uid);
7171 if (uentry_isValid (te))
7173 sRef_mergeStateQuiet (s, uentry_getSref (te));
7178 s->oaliaskind = s->aliaskind;
7179 s->oexpkind = s->expkind;
7181 llassert (valueTable_isUndefined (s->state));
7182 s->state = context_createValueTable (s, stateInfo_makeLoc (g_currentloc));
7187 bool sRef_hasName (sRef s)
7189 if (sRef_isInvalid (s))
7198 uentry u = usymtab_getRefQuiet (s->info->cvar->lexlevel,
7199 s->info->cvar->index);
7200 return (uentry_hasName (u));
7204 if (s->info->paramno >= 0)
7206 uentry u = uentryList_getN (context_getParams (),
7209 return (uentry_hasName (u));
7213 llassert (s->info->paramno == PARAMUNKNOWN);
7223 sRef_sameName (sRef s1, sRef s2)
7225 if (sRef_isInvalid (s1))
7227 return sRef_isInvalid (s2);
7230 if (sRef_isInvalid (s2))
7238 if (s2->kind == SK_CVAR)
7240 return (s1->info->cvar->lexlevel == s2->info->cvar->lexlevel
7241 && s1->info->cvar->index == s2->info->cvar->index);
7243 else if (s2->kind == SK_PARAM)
7245 if (context_inFunctionLike ())
7247 if (s2->info->paramno != PARAMUNKNOWN)
7249 uentry u1 = usymtab_getRefQuiet (s1->info->cvar->lexlevel,
7250 s1->info->cvar->index);
7251 uentry u2 = uentryList_getN (context_getParams (),
7254 return (cstring_equalFree (uentry_getName (u1),
7255 uentry_getName (u2)));
7259 return s1->info->paramno == PARAMUNKNOWN;
7273 if (s2->kind == SK_PARAM)
7275 return (s1->info->paramno == s2->info->paramno);
7277 else if (s2->kind == SK_CVAR)
7279 if (context_inFunctionLike ())
7281 if (s1->info->paramno == PARAMUNKNOWN)
7287 uentry u1 = uentryList_getN (context_getParams (),
7289 uentry u2 = usymtab_getRefQuiet (s2->info->cvar->lexlevel,
7290 s2->info->cvar->index);
7293 return (cstring_equalFree (uentry_getName (u1),
7294 uentry_getName (u2)));
7308 case SK_UNCONSTRAINED:
7312 if (s2->kind == SK_ARRAYFETCH)
7314 if (bool_equal (s1->info->arrayfetch->indknown,
7315 s2->info->arrayfetch->indknown))
7317 if (!s1->info->arrayfetch->indknown
7318 || (s1->info->arrayfetch->ind == s2->info->arrayfetch->ind))
7320 return sRef_sameName (s1->info->arrayfetch->arr,
7321 s2->info->arrayfetch->arr);
7328 if (s2->kind == SK_FIELD)
7330 if (cstring_equal (s1->info->field->field,
7331 s2->info->field->field))
7333 return sRef_sameName (s1->info->field->rec,
7334 s2->info->field->rec);
7343 if (s2->kind == s1->kind)
7345 return sRef_sameName (s1->info->ref,
7353 return sRef_sameName (sRef_getConjA (s1), s2);
7357 return (s2->kind == SK_UNKNOWN);
7360 if (s2->kind == s1->kind)
7362 return (ctype_equal (s1->type, s2->type));
7367 if (s2->kind == SK_SPECIAL)
7369 return (s1->info->spec == s2->info->spec);
7373 return (s2->kind == SK_RESULT);
7381 sRef_fixOuterRef (/*@returned@*/ sRef s)
7383 sRef root = sRef_getRootBase (s);
7385 if (sRef_isCvar (root))
7387 uentry ue = usymtab_getRefQuiet (root->info->cvar->lexlevel,
7388 root->info->cvar->index);
7390 if (uentry_isValid (ue))
7392 sRef uref = uentry_getSref (ue);
7393 sRef sr = sRef_fixBase (s, uref);
7399 llcontbug (message ("sRef_fixOuterRef: undefined: %q", sRef_unparseDebug (s)));
7408 sRef_storeState (sRef s)
7410 if (sRef_isInvalid (s)) return;
7412 sRef_checkMutable (s);
7413 s->oaliaskind = s->aliaskind;
7414 s->oexpkind = s->expkind;
7417 static void sRef_resetStateAux (sRef s, /*@unused@*/ fileloc loc)
7419 sRef_resetState (s);
7423 sRef_resetState (sRef s)
7425 bool changed = FALSE;
7426 if (sRef_isInvalid (s)) return;
7429 if (s->oaliaskind == AK_KILLREF && !sRef_isParam (s))
7432 ** killref is used in a kludgey way, to save having to add
7433 ** another alias kind (see usymtab_handleParams)
7436 if (s->expkind != s->oexpkind)
7439 s->expkind = s->oexpkind;
7444 if (s->expkind != s->oexpkind)
7447 s->expkind = s->oexpkind;
7450 if (s->aliaskind != s->oaliaskind
7451 && s->aliaskind != AK_REFCOUNTED
7452 && s->aliaskind != AK_REFS)
7455 s->aliaskind = s->oaliaskind;
7461 sRef_clearDerived (s);
7467 sRef_resetStateComplete (sRef s)
7469 sRef_innerAliasSetComplete (sRef_resetStateAux, s, fileloc_undefined);
7473 sRef_fixBase (/*@returned@*/ sRef s, /*@returned@*/ sRef base)
7475 sRef tmp = sRef_undefined;
7478 if (sRef_isInvalid (s)) return s;
7479 if (sRef_isInvalid (base)) return base;
7489 tmp = sRef_fixBase (s->info->arrayfetch->arr, base);
7491 if (s->info->arrayfetch->indknown)
7493 ret = sRef_makeArrayFetchKnown (tmp, s->info->arrayfetch->ind);
7497 ret = sRef_makeArrayFetch (tmp);
7501 tmp = sRef_fixBase (s->info->field->rec, base);
7502 ret = sRef_buildNCField (tmp, s->info->field->field);
7505 tmp = sRef_fixBase (s->info->ref, base);
7506 ret = sRef_makePointer (tmp);
7509 tmp = sRef_fixBase (s->info->ref, base);
7510 ret = sRef_makeAddress (tmp);
7516 tmp = sRef_fixBase (s->info->conj->a, base);
7517 tmpb = sRef_fixBase (s->info->conj->b, base);
7519 ret = sRef_makeConj (tmp, tmpb);
7528 static /*@exposed@*/ sRef
7529 sRef_fixDirectBase (sRef s, sRef base)
7534 if (sRef_isInvalid (s))
7536 return sRef_undefined;
7542 if (s->info->arrayfetch->indknown)
7544 ret = sRef_makeArrayFetchKnown (base, s->info->arrayfetch->ind);
7548 ret = sRef_makeArrayFetch (base);
7552 ret = sRef_buildNCField (base, s->info->field->field);
7555 ret = sRef_makePointer (base);
7558 ret = sRef_makeAddress (base);
7564 tmpa = sRef_fixDirectBase (s->info->conj->a, base);
7565 tmpb = sRef_fixDirectBase (s->info->conj->b, base);
7567 ret = sRef_makeConj (tmpa, tmpb);
7573 sRef_copyState (ret, s);
7578 sRef_isAllocIndexRef (sRef s)
7580 return (sRef_isArrayFetch (s) && !(s->info->arrayfetch->indknown)
7581 && sRef_isAllocated (s->info->arrayfetch->arr));
7585 sRef_showRefLost (sRef s)
7587 if (sRef_hasAliasInfoLoc (s))
7589 llgenindentmsg (cstring_makeLiteral ("Original reference lost"),
7590 sRef_getAliasInfoLoc (s));
7595 sRef_showRefKilled (sRef s)
7597 if (sRef_hasStateInfoLoc (s))
7599 llgenindentmsg (message ("Storage %q released",
7600 sRef_unparse (s)), sRef_getStateInfoLoc (s));
7605 sRef_showStateInconsistent (sRef s)
7607 if (sRef_hasStateInfoLoc (s))
7610 (message ("Storage %qbecomes inconsistent (released on one branch)",
7611 sRef_unparseOpt (s)),
7612 sRef_getStateInfoLoc (s));
7617 sRef_showStateInfo (sRef s)
7619 if (sRef_hasStateInfoLoc (s))
7621 if (s->defstate == SS_DEAD)
7624 (message ("Storage %qis released", sRef_unparseOpt (s)),
7625 sRef_getStateInfoLoc (s));
7627 else if (s->defstate == SS_ALLOCATED || s->defstate == SS_DEFINED)
7630 (message ("Storage %qis %s", sRef_unparseOpt (s),
7631 sstate_unparse (s->defstate)),
7632 sRef_getStateInfoLoc (s));
7634 else if (s->defstate == SS_UNUSEABLE)
7637 (message ("Storage %qbecomes inconsistent (clauses merge with"
7638 "%qreleased on one branch)",
7639 sRef_unparseOpt (s),
7640 sRef_unparseOpt (s)),
7641 sRef_getStateInfoLoc (s));
7645 llgenindentmsg (message ("Storage %qbecomes %s",
7646 sRef_unparseOpt (s),
7647 sstate_unparse (s->defstate)),
7648 sRef_getStateInfoLoc (s));
7654 sRef_showExpInfo (sRef s)
7656 if (sRef_hasExpInfoLoc (s))
7658 llgenindentmsg (message ("Storage %qbecomes %s", sRef_unparseOpt (s),
7659 exkind_unparse (s->expkind)),
7660 sRef_getExpInfoLoc (s));
7665 sRef_showMetaStateInfo (sRef s, cstring key)
7668 metaStateInfo minfo = context_lookupMetaStateInfo (key);
7670 llassert (sRef_isValid (s));
7671 llassert (valueTable_isDefined (s->state));
7672 llassert (metaStateInfo_isDefined (minfo));
7674 val = valueTable_lookup (s->state, key);
7676 if (stateValue_hasLoc (val))
7679 (message ("%qbecomes %q", sRef_unparseOpt (s),
7680 stateValue_unparseValue (val, minfo)),
7681 stateValue_getLoc (val));
7686 sRef_showNullInfo (sRef s)
7688 DPRINTF (("Show null info: %s", sRef_unparseFull (s)));
7690 if (sRef_hasNullInfoLoc (s) && sRef_isKnown (s))
7692 DPRINTF (("has null info: %s",
7693 fileloc_unparse (sRef_getNullInfoLoc (s))));
7695 switch (sRef_getNullState (s))
7699 fileloc loc = sRef_getNullInfoLoc (s);
7701 if (fileloc_isDefined (loc) && !fileloc_isLib (loc))
7704 (message ("Storage %qbecomes null", sRef_unparseOpt (s)),
7711 fileloc loc = sRef_getNullInfoLoc (s);
7713 if (fileloc_isDefined (loc) && !fileloc_isLib (loc))
7715 llgenindentmsg (message ("Storage %qbecomes null", sRef_unparseOpt (s)),
7723 (message ("Storage %qmay become null", sRef_unparseOpt (s)),
7724 sRef_getNullInfoLoc (s));
7729 (message ("Storage %qbecomes not null", sRef_unparseOpt (s)),
7730 sRef_getNullInfoLoc (s));
7734 (message ("Storage %qnull state becomes unknown",
7735 sRef_unparseOpt (s)),
7736 sRef_getNullInfoLoc (s));
7745 (message ("<error case> Storage %q becomes %s",
7747 nstate_unparse (sRef_getNullState (s))),
7748 sRef_getNullInfoLoc (s));
7756 sRef_showAliasInfo (sRef s)
7758 if (sRef_hasAliasInfoLoc (s))
7760 if (sRef_isFresh (s))
7763 (message ("Fresh storage %qallocated", sRef_unparseOpt (s)),
7764 sRef_getAliasInfoLoc (s));
7768 if (!sRef_isRefCounted (s))
7771 (message ("Storage %qbecomes %s",
7772 sRef_unparseOpt (s),
7773 alkind_unparse (sRef_getAliasKind (s))),
7774 sRef_getAliasInfoLoc (s));
7781 sRef_mergeNullState (sRef s, nstate n)
7783 if (sRef_isValid (s))
7787 old = sRef_getNullState (s);
7789 if (n != old && n != NS_UNKNOWN)
7791 sRef_setNullState (s, n, g_currentloc);
7796 llbuglit ("sRef_mergeNullState: invalid");
7801 sRef_possiblyNull (sRef s)
7803 if (sRef_isValid (s))
7805 if (sRef_getNullState (s) == NS_ABSNULL)
7807 ctype rct = ctype_realType (s->type);
7809 if (ctype_isAbstract (rct))
7815 if (ctype_isUser (rct))
7817 uentry ue = usymtab_getTypeEntry (ctype_typeId (rct));
7819 return (nstate_possiblyNull
7820 (sRef_getNullState (uentry_getSref (ue))));
7830 return nstate_possiblyNull (sRef_getNullState (s));
7838 sRef_getScopeName (sRef s)
7840 sRef base = sRef_getRootBase (s);
7842 if (sRef_isRealGlobal (base))
7844 return (cstring_makeLiteralTemp ("Global"));
7846 else if (sRef_isFileStatic (base))
7848 return (cstring_makeLiteralTemp ("Static"));
7852 return (cstring_makeLiteralTemp ("Local"));
7857 sRef_unparseScope (sRef s)
7859 sRef base = sRef_getRootBase (s);
7861 if (sRef_isRealGlobal (base))
7863 return (cstring_makeLiteralTemp ("global"));
7865 else if (sRef_isFileStatic (base))
7867 return (cstring_makeLiteralTemp ("file static"));
7876 sRef_getScope (sRef s)
7878 llassert (sRef_isValid (s));
7880 if (sRef_isCvar (s))
7882 return s->info->cvar->lexlevel;
7884 else if (sRef_isParam (s))
7895 sRef_isDead (sRef s)
7897 return (sRef_isValid (s) && (s)->defstate == SS_DEAD);
7901 sRef_isDeadStorage (sRef s)
7903 if (sRef_isValid (s))
7905 if (s->defstate == SS_DEAD
7906 || s->defstate == SS_UNUSEABLE
7907 || s->defstate == SS_UNDEFINED
7908 || s->defstate == SS_UNKNOWN)
7914 return (sRef_isDefinitelyNull (s));
7924 sRef_isPossiblyDead (sRef s)
7926 return (sRef_isValid (s) && s->defstate == SS_HOFFA);
7929 bool sRef_isStateLive (sRef s)
7931 if (sRef_isValid (s))
7933 sstate ds = s->defstate;
7935 return (!(ds == SS_UNDEFINED
7937 || ds == SS_UNUSEABLE
7938 || ds == SS_HOFFA));
7947 bool sRef_isStateUndefined (sRef s)
7949 return ((sRef_isValid(s)) && ((s)->defstate == SS_UNDEFINED));
7952 bool sRef_isJustAllocated (sRef s)
7954 if (sRef_isAllocated (s))
7956 sRefSet_allElements (s->deriv, el)
7958 if (!(sRef_isStateUndefined (el) || sRef_isUnuseable (el)))
7962 } end_sRefSet_allElements ;
7971 sRef_isAllocatedStorage (sRef s)
7973 if (sRef_isValid (s) && ynm_toBoolStrict (sRef_isReadable (s)))
7975 return (ctype_isVisiblySharable (sRef_getType (s)));
7984 sRef_isUnuseable (sRef s)
7986 return ((sRef_isValid(s)) && ((s)->defstate == SS_UNUSEABLE));
7990 sRef_perhapsNull (sRef s)
7992 if (sRef_isValid (s))
7994 if (sRef_getNullState (s) == NS_ABSNULL)
7996 ctype rct = ctype_realType (s->type);
7998 if (ctype_isAbstract (rct))
8004 if (ctype_isUser (rct))
8006 uentry ue = usymtab_getTypeEntry (ctype_typeId (rct));
8008 return (nstate_perhapsNull
8009 (sRef_getNullState (uentry_getSref (ue))));
8019 return nstate_perhapsNull (sRef_getNullState (s));
8027 ** definitelyNull --- called when TRUE is good
8031 sRef_definitelyNull (sRef s)
8033 return (sRef_isValid (s)
8034 && (sRef_getNullState (s) == NS_DEFNULL || sRef_getNullState (s) == NS_CONSTNULL));
8038 ** based on sRef_similar
8042 sRef_setDerivNullState (sRef set, sRef guide, nstate ns)
8044 if (sRef_isValid (set))
8046 sRef deriv = sRef_getDeriv (set, guide);
8048 if (sRef_isValid (deriv))
8050 sRef_setNullStateN (deriv, ns);
8055 static /*@exposed@*/ sRef
8056 sRef_getDeriv (/*@returned@*/ /*@notnull@*/ sRef set, sRef guide)
8058 llassert (sRef_isValid (set));
8059 llassert (sRef_isValid (guide));
8061 switch (guide->kind)
8064 llassert (set->kind == SK_CVAR);
8069 llassert (set->kind == guide->kind);
8070 llassert (set->info->paramno == guide->info->paramno);
8076 if (set->kind == SK_ARRAYFETCH
8077 && (sRef_similar (set->info->arrayfetch->arr,
8078 guide->info->arrayfetch->arr)))
8084 return (sRef_makeAnyArrayFetch
8085 (sRef_getDeriv (set, guide->info->arrayfetch->arr)));
8090 if (set->kind == SK_PTR && sRef_similar (set->info->ref, guide->info->ref))
8096 return (sRef_makePointer (sRef_getDeriv (set, guide->info->ref)));
8101 if ((set->kind == SK_FIELD &&
8102 (sRef_similar (set->info->field->rec, guide->info->field->rec) &&
8103 cstring_equal (set->info->field->field, guide->info->field->field))))
8109 return (sRef_makeField (sRef_getDeriv (set, guide->info->field->rec),
8110 guide->info->field->field));
8114 if ((set->kind == SK_ADR) && sRef_similar (set->info->ref, guide->info->ref))
8120 return (sRef_makeAddress (sRef_getDeriv (set, guide->info->ref)));
8125 return sRef_undefined;
8129 case SK_UNCONSTRAINED:
8137 return sRef_undefined;
8144 ** sRef_aliasCheckPred
8146 ** A confusing but spiffy function:
8148 ** Calls predf (s, e, text, <alias>) on s and all of s's aliases
8149 ** (unless checkAliases (s) is FALSE).
8151 ** For alias calls, calls as
8152 ** predf (alias, e, text, s)
8156 sRef_aliasCheckPred (bool (predf) (sRef, exprNode, sRef, exprNode),
8157 /*@null@*/ bool (checkAliases) (sRef),
8158 sRef s, exprNode e, exprNode err)
8160 bool error = (*predf)(s, e, sRef_undefined, err);
8163 if (checkAliases != NULL && !(checkAliases (s)))
8165 /* don't check aliases */
8169 sRefSet aliases = usymtab_allAliases (s);
8171 sRefSet_realElements (aliases, current)
8173 if (sRef_isValid (current))
8175 if (!sRef_similar (current, s)
8176 || (error && sRef_sameName (current, s)))
8178 (void) (*predf)(current, e, s, err);
8181 } end_sRefSet_realElements;
8183 sRefSet_free (aliases);
8188 ** return TRUE iff predf (s) is true for s or any alias of s
8192 sRef_aliasCheckSimplePred (sRefTest predf, sRef s)
8203 aliases = usymtab_allAliases (s);
8205 sRefSet_realElements (aliases, current)
8207 if (sRef_isValid (current))
8209 sRef cref = sRef_updateSref (current);
8211 /* Whoa! a very kludgey way to make sure the right sref is used
8212 ** where there is a conditional symbol table. I am beginning
8213 ** to think that having a conditional symbol table wasn't such
8219 DPRINTF (("Checking alias: %s", sRef_unparseFull (cref)));
8220 sRefSet_free (aliases);
8224 } end_sRefSet_realElements;
8226 sRefSet_free (aliases);
8232 sRef_aliasCompleteSimplePred (bool (predf) (sRef), sRef s)
8235 bool result = FALSE;
8238 aliases = usymtab_allAliases (s);
8240 if ((*predf)(s)) result = TRUE;
8243 sRefSet_realElements (aliases, current)
8245 if (sRef_isValid (current))
8247 current = sRef_updateSref (current);
8248 if ((*predf)(current)) result = TRUE;
8250 } end_sRefSet_realElements;
8252 sRefSet_free (aliases);
8257 sRef_aliasSetComplete (void (predf) (sRef, fileloc), sRef s, fileloc loc)
8261 aliases = usymtab_allAliases (s);
8263 DPRINTF (("All aliases: %s", sRefSet_unparseFull (aliases)));
8267 sRefSet_realElements (aliases, current)
8269 if (sRef_isValid (current))
8271 current = sRef_updateSref (current);
8272 ((*predf)(current, loc));
8274 } end_sRefSet_realElements;
8276 sRefSet_free (aliases);
8280 sRef_aliasSetCompleteParam (void (predf) (sRef, int, fileloc), sRef s,
8281 int kind, fileloc loc)
8286 if (sRef_isDeep (s))
8288 aliases = usymtab_allAliases (s);
8292 aliases = usymtab_aliasedBy (s);
8295 (*predf)(s, kind, loc);
8297 sRefSet_realElements (aliases, current)
8299 if (sRef_isValid (current))
8301 current = sRef_updateSref (current);
8302 ((*predf)(current, kind, loc));
8304 } end_sRefSet_realElements;
8306 sRefSet_free (aliases);
8310 sRef_innerAliasSetComplete (void (predf) (sRef, fileloc), sRef s, fileloc loc)
8316 if (!sRef_isValid (s)) return;
8319 ** Type equivalence checking is necessary --- there might be casting.
8326 case SK_UNCONSTRAINED:
8331 inner = s->info->ref;
8332 aliases = usymtab_allAliases (inner);
8333 ct = sRef_getType (inner);
8335 sRefSet_realElements (aliases, current)
8337 if (sRef_isValid (current))
8339 current = sRef_updateSref (current);
8341 if (ctype_equal (ct, sRef_getType (current)))
8343 sRef ptr = sRef_makePointer (current);
8344 ((*predf)(ptr, loc));
8347 } end_sRefSet_realElements;
8349 sRefSet_free (aliases);
8352 inner = s->info->arrayfetch->arr;
8353 aliases = usymtab_allAliases (inner);
8354 ct = sRef_getType (inner);
8356 DPRINTF (("Array fetch: %s", sRefSet_unparse (aliases)));
8358 sRefSet_realElements (aliases, current)
8360 if (sRef_isValid (current))
8362 current = sRef_updateSref (current);
8363 DPRINTF (("Current: %s", sRef_unparseFull (current)));
8365 if (ctype_equal (ct, sRef_getType (current)))
8367 if (s->info->arrayfetch->indknown)
8369 sRef af = sRef_makeArrayFetchKnown (current, s->info->arrayfetch->ind);
8370 DPRINTF (("Defining: %s", sRef_unparseFull (af)));
8371 /* evans 2001-08-27 This isn't true:
8372 llassert (af->info->arrayfetch->arr == current);
8373 see comments in buildArrayFetchKnown
8375 ((*predf)(af, loc));
8379 sRef af = sRef_makeArrayFetch (current);
8380 /* evans 2001-08-27 This isn't true:
8381 llassert (af->info->arrayfetch->arr == current);
8382 see comments in buildArrayFetch
8384 DPRINTF (("Defining: %s", sRef_unparseFull (af)));
8385 ((*predf)(af, loc));
8390 DPRINTF (("Type mismatch: %s / %s",
8392 ctype_unparse (sRef_getType (current))));
8395 } end_sRefSet_realElements;
8397 sRefSet_free (aliases);
8400 inner = s->info->field->rec;
8401 aliases = usymtab_allAliases (inner);
8402 ct = sRef_getType (inner);
8405 sRefSet_realElements (aliases, current)
8407 if (sRef_isValid (current))
8409 current = sRef_updateSref (current);
8411 if (ctype_equal (ct, sRef_getType (current)))
8413 sRef f = sRef_makeField (current, s->info->field->field);
8418 } end_sRefSet_realElements;
8420 sRefSet_free (aliases);
8423 sRef_innerAliasSetComplete (predf, s->info->conj->a, loc);
8424 sRef_innerAliasSetComplete (predf, s->info->conj->b, loc);
8441 sRef_innerAliasSetCompleteParam (void (predf) (sRef, sRef), sRef s, sRef t)
8447 if (!sRef_isValid (s)) return;
8450 ** Type equivalence checking is necessary --- there might be casting.
8457 case SK_UNCONSTRAINED:
8462 inner = s->info->ref;
8463 aliases = usymtab_allAliases (inner);
8464 ct = sRef_getType (inner);
8467 sRefSet_realElements (aliases, current)
8469 if (sRef_isValid (current))
8471 current = sRef_updateSref (current);
8473 if (ctype_equal (ct, sRef_getType (current)))
8475 sRef ptr = sRef_makePointer (current);
8480 } end_sRefSet_realElements;
8482 sRefSet_free (aliases);
8485 inner = s->info->arrayfetch->arr;
8486 aliases = usymtab_allAliases (inner);
8487 ct = sRef_getType (inner);
8489 sRefSet_realElements (aliases, current)
8491 if (sRef_isValid (current))
8493 current = sRef_updateSref (current);
8495 if (ctype_equal (ct, sRef_getType (current)))
8498 if (s->info->arrayfetch->indknown)
8500 sRef af = sRef_makeArrayFetchKnown (current, s->info->arrayfetch->ind);
8506 sRef af = sRef_makeArrayFetch (current);
8512 } end_sRefSet_realElements;
8514 sRefSet_free (aliases);
8517 inner = s->info->field->rec;
8518 aliases = usymtab_allAliases (inner);
8519 ct = sRef_getType (inner);
8522 sRefSet_realElements (aliases, current)
8524 if (sRef_isValid (current))
8526 current = sRef_updateSref (current);
8528 if (ctype_equal (ct, sRef_getType (current)))
8530 sRef f = sRef_makeField (current, s->info->field->field);
8535 } end_sRefSet_realElements;
8537 sRefSet_free (aliases);
8540 sRef_innerAliasSetCompleteParam (predf, s->info->conj->a, t);
8541 sRef_innerAliasSetCompleteParam (predf, s->info->conj->b, t);
8557 static void sRef_combineExKinds (/*@notnull@*/ sRef res, /*@notnull@*/ sRef other)
8559 exkind a1 = sRef_getExKind (res);
8560 exkind a2 = sRef_getExKind (other);
8562 if (a1 == a2 || a2 == XO_UNKNOWN)
8566 else if (a1 == XO_UNKNOWN)
8568 res->expinfo = stateInfo_update (res->expinfo, other->expinfo);
8573 res->expkind = XO_OBSERVER;
8578 ** Currently, this is a very ad hoc implementation, with lots of fixes to
8579 ** make real code work okay. I need to come up with some more general
8580 ** rules or principles here.
8584 sRef_combineAliasKindsError (/*@notnull@*/ sRef res,
8585 /*@notnull@*/ sRef other,
8586 clause cl, fileloc loc)
8588 bool hasError = FALSE;
8589 alkind ares = sRef_getAliasKind (res);
8590 alkind aother = sRef_getAliasKind (other);
8592 sRef_checkMutable (res);
8594 if (alkind_isDependent (ares))
8596 if (aother == AK_KEPT)
8598 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8599 res->aliaskind = AK_KEPT;
8603 if (aother == AK_LOCAL || aother == AK_STATIC
8604 || alkind_isTemp (aother))
8606 DPRINTF (("Setting dependent: %s", sRef_unparseFull (res)));
8607 res->aliaskind = AK_DEPENDENT;
8611 else if (alkind_isDependent (aother))
8613 if (ares == AK_KEPT)
8615 res->aliaskind = AK_KEPT;
8619 if (ares == AK_LOCAL || ares == AK_STATIC || alkind_isTemp (ares))
8621 DPRINTF (("Setting dependent: %s", sRef_unparseFull (res)));
8622 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8623 res->aliaskind = AK_DEPENDENT;
8627 else if ((ares == AK_LOCAL || ares == AK_UNIQUE
8628 || ares == AK_STATIC || alkind_isTemp (ares))
8629 && sRef_isFresh (other))
8632 ** cases like: if (s == NULL) s = malloc...;
8633 ** don't generate errors
8636 if (usymtab_isAltDefinitelyNullDeep (res))
8638 res->aliaskind = ares;
8645 else if ((aother == AK_LOCAL || aother == AK_UNIQUE
8646 || aother == AK_STATIC || alkind_isTemp (aother))
8647 && sRef_isFresh (res))
8650 ** cases like: if (s == NULL) s = malloc...;
8651 ** don't generate errors
8654 if (usymtab_isDefinitelyNullDeep (other))
8656 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8657 res->aliaskind = aother;
8664 else if (ares == AK_NEWREF && aother == AK_REFCOUNTED
8665 && sRef_isConst (other))
8667 res->aliaskind = AK_NEWREF;
8669 else if (aother == AK_NEWREF && ares == AK_REFCOUNTED
8670 && sRef_isConst (res))
8672 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8673 res->aliaskind = AK_NEWREF;
8675 else if (sRef_isLocalVar (res)
8676 && ((ares == AK_KEPT && aother == AK_LOCAL)
8677 || (aother == AK_KEPT && ares == AK_LOCAL)))
8679 res->aliaskind = AK_KEPT;
8688 if (sRef_isThroughArrayFetch (res))
8691 (FLG_BRANCHSTATE, FLG_STRICTBRANCHSTATE,
8693 ("Clauses exit with %q possibly referencing %s storage %s, "
8696 alkind_unparse (aother),
8697 clause_nameTaken (cl),
8698 alkind_unparse (ares),
8699 clause_nameAlternate (cl)),
8702 sRef_showAliasInfo (res);
8703 sRef_showAliasInfo (other);
8704 res->aliaskind = AK_ERROR;
8708 if (ares == AK_KEPT || aother == AK_KEPT)
8710 sRef_maybeKill (res, loc);
8718 message ("Clauses exit with %q referencing %s storage %s, "
8721 alkind_unparse (aother),
8722 clause_nameTaken (cl),
8723 alkind_unparse (ares),
8724 clause_nameAlternate (cl)),
8727 sRef_showAliasInfo (res);
8728 sRef_showAliasInfo (other);
8730 res->aliaskind = AK_ERROR;
8734 res->aliaskind = (sRef_isLocalVar (res) ? AK_LOCAL : AK_UNKNOWN);
8739 sRef_combineAliasKinds (/*@notnull@*/ sRef res, /*@notnull@*/ sRef other,
8740 clause cl, fileloc loc)
8742 alkind ares = sRef_getAliasKind (res);
8743 alkind aother = sRef_getAliasKind (other);
8745 sRef_checkMutable (res);
8747 if (alkind_equal (ares, aother)
8748 || aother == AK_UNKNOWN
8749 || aother == AK_ERROR)
8751 ; /* keep current state */
8753 else if (sRef_isDead (res) || sRef_isDead (other))
8755 /* dead error reported (or storage is dead) */
8756 res ->aliaskind = AK_ERROR;
8758 else if (ares == AK_UNKNOWN || ares == AK_ERROR
8759 || sRef_isStateUndefined (res))
8761 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8762 res->aliaskind = aother;
8764 else if (sRef_isStateUndefined (other))
8768 else if (((ares == AK_UNIQUE || alkind_isTemp (ares))
8769 && aother == AK_LOCAL)
8770 || ((aother == AK_UNIQUE || alkind_isTemp (aother))
8771 && ares == AK_LOCAL))
8773 if (ares != AK_LOCAL)
8775 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8778 res->aliaskind = AK_LOCAL;
8780 else if ((ares == AK_OWNED && aother == AK_FRESH)
8781 || (aother == AK_OWNED && ares == AK_FRESH))
8783 if (ares != AK_FRESH)
8785 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8788 res->aliaskind = AK_FRESH;
8790 else if ((ares == AK_KEEP && aother == AK_FRESH) ||
8791 (aother == AK_KEEP && ares == AK_FRESH))
8793 if (ares != AK_KEEP)
8795 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8798 res->aliaskind = AK_KEEP;
8800 else if ((ares == AK_LOCAL && aother == AK_STACK) ||
8801 (aother == AK_LOCAL && ares == AK_STACK))
8803 if (ares != AK_STACK)
8805 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8808 res->aliaskind = AK_STACK;
8810 else if ((ares == AK_LOCAL
8811 && (aother == AK_OWNED && sRef_isLocalVar (other)))
8812 || (aother == AK_LOCAL
8813 && (ares == AK_OWNED && sRef_isLocalVar (res))))
8815 if (ares != AK_LOCAL)
8817 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8820 res->aliaskind = AK_LOCAL;
8822 else if ((ares == AK_FRESH && alkind_isOnly (aother))
8823 || (aother == AK_FRESH && alkind_isOnly (ares)))
8825 res->aliaskind = AK_FRESH;
8827 else if ((aother == AK_FRESH && sRef_definitelyNull (res))
8828 || (ares == AK_FRESH && sRef_definitelyNull (other)))
8830 if (ares != AK_FRESH)
8832 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8833 res->aliaskind = AK_FRESH;
8836 else if ((sRef_isFresh (res) && sRef_isConst (other))
8837 || (sRef_isFresh (other) && sRef_isConst (res)))
8840 ** for NULL constantants
8844 if (!sRef_isFresh (res))
8846 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8849 res->aliaskind = AK_FRESH;
8851 else if ((alkind_isStatic (aother) && sRef_isConst (res))
8852 || (alkind_isStatic (ares) && sRef_isConst (other)))
8854 if (!alkind_isStatic (ares))
8856 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8857 res->aliaskind = AK_STATIC;
8862 sRef_combineAliasKindsError (res, other, cl, loc);
8866 static void sRef_combineDefState (/*@notnull@*/ sRef res,
8867 /*@notnull@*/ sRef other)
8869 sstate s1 = res->defstate;
8870 sstate s2 = other->defstate;
8873 sRef_checkMutable (res);
8875 if (s1 == s2 || s2 == SS_UNKNOWN)
8879 else if (s1 == SS_UNKNOWN)
8888 if (s2 == SS_DEFINED)
8894 llcontbuglit ("ssfixed: not implemented");
8903 flip = (s2 != SS_DEFINED);
8921 res->definfo = stateInfo_update (res->definfo, other->definfo);
8926 extern /*@notnull@*/ sRef sRef_getConjA (sRef s)
8929 llassert (sRef_isConj (s));
8931 ret = s->info->conj->a;
8932 llassert (ret != NULL);
8936 extern /*@notnull@*/ sRef sRef_getConjB (sRef s)
8939 llassert (sRef_isConj (s));
8941 ret = s->info->conj->b;
8942 llassert (ret != NULL);
8946 extern /*@exposed@*/ sRef sRef_makeArrow (sRef s, /*@dependent@*/ cstring f)
8951 p = sRef_makePointer (s);
8952 ret = sRef_makeField (p, f);
8956 extern /*@exposed@*/ sRef sRef_buildArrow (sRef s, cstring f)
8961 p = sRef_buildPointer (s);
8962 ret = sRef_buildField (p, f);
8967 static /*@null@*/ sinfo sinfo_copy (/*@notnull@*/ sRef s)
8974 ret = (sinfo) dmalloc (sizeof (*ret));
8975 ret->cvar = (cref) dmalloc (sizeof (*ret->cvar));
8976 ret->cvar->lexlevel = s->info->cvar->lexlevel;
8977 ret->cvar->index = s->info->cvar->index;
8981 ret = (sinfo) dmalloc (sizeof (*ret));
8982 ret->paramno = s->info->paramno;
8983 llassert (ret->paramno >= -1);
8987 ret = (sinfo) dmalloc (sizeof (*ret));
8988 ret->arrayfetch = (ainfo) dmalloc (sizeof (*ret->arrayfetch));
8989 ret->arrayfetch->indknown = s->info->arrayfetch->indknown;
8990 ret->arrayfetch->ind = s->info->arrayfetch->ind;
8991 ret->arrayfetch->arr = s->info->arrayfetch->arr; /* sRef_copy (s->info->arrayfetch->arr); */ /*@i32@*/
8995 ret = (sinfo) dmalloc (sizeof (*ret));
8996 ret->field = (fldinfo) dmalloc (sizeof (*ret->field));
8997 ret->field->rec = s->info->field->rec; /* sRef_copy (s->info->field->rec); */ /*@i32@*/
8998 ret->field->field = s->info->field->field;
9002 ret = (sinfo) dmalloc (sizeof (*ret));
9003 ret->object = s->info->object;
9010 ret = (sinfo) dmalloc (sizeof (*ret));
9011 ret->ref = s->info->ref; /* Ref_copy (s->info->ref); */
9015 ret = (sinfo) dmalloc (sizeof (*ret));
9016 ret->conj = (cjinfo) dmalloc (sizeof (*ret->conj));
9017 ret->conj->a = s->info->conj->a; /* sRef_copy (s->info->conj->a); */
9018 ret->conj->b = s->info->conj->b; /* sRef_copy (s->info->conj->b);*/
9021 ret = (sinfo) dmalloc (sizeof (*ret));
9022 ret->spec = s->info->spec;
9024 case SK_UNCONSTRAINED:
9026 ret = (sinfo) dmalloc (sizeof (*ret));
9027 ret->fname = s->info->fname;
9033 llassertprint (s->info == NULL, ("s = %s", sRef_unparse (s)));
9041 static /*@null@*/ sinfo sinfo_fullCopy (/*@notnull@*/ sRef s)
9046 ** Since its a full copy, only storage is assigned
9047 ** to dependent fields.
9054 ret = (sinfo) dmalloc (sizeof (*ret));
9055 ret->cvar = (cref) dmalloc (sizeof (*ret->cvar));
9056 ret->cvar->lexlevel = s->info->cvar->lexlevel;
9057 ret->cvar->index = s->info->cvar->index;
9061 ret = (sinfo) dmalloc (sizeof (*ret));
9062 ret->paramno = s->info->paramno;
9063 llassert (ret->paramno >= -1);
9067 ret = (sinfo) dmalloc (sizeof (*ret));
9068 ret->arrayfetch = (ainfo) dmalloc (sizeof (*ret->arrayfetch));
9069 ret->arrayfetch->indknown = s->info->arrayfetch->indknown;
9070 ret->arrayfetch->ind = s->info->arrayfetch->ind;
9071 ret->arrayfetch->arr = sRef_saveCopy (s->info->arrayfetch->arr);
9075 ret = (sinfo) dmalloc (sizeof (*ret));
9076 ret->field = (fldinfo) dmalloc (sizeof (*ret->field));
9077 ret->field->rec = sRef_saveCopy (s->info->field->rec);
9078 ret->field->field = s->info->field->field;
9082 ret = (sinfo) dmalloc (sizeof (*ret));
9083 ret->object = s->info->object;
9090 ret = (sinfo) dmalloc (sizeof (*ret));
9091 ret->ref = sRef_saveCopy (s->info->ref);
9095 ret = (sinfo) dmalloc (sizeof (*ret));
9096 ret->conj = (cjinfo) dmalloc (sizeof (*ret->conj));
9097 ret->conj->a = sRef_saveCopy (s->info->conj->a);
9098 ret->conj->b = sRef_saveCopy (s->info->conj->b);
9101 ret = (sinfo) dmalloc (sizeof (*ret));
9102 ret->spec = s->info->spec;
9105 case SK_UNCONSTRAINED:
9106 ret = (sinfo) dmalloc (sizeof (*ret));
9107 ret->fname = s->info->fname;
9113 llassert (s->info == NULL);
9123 sinfo_update (/*@notnull@*/ /*@exposed@*/ sRef res,
9124 /*@notnull@*/ /*@exposed@*/ sRef other)
9126 llassert (res->kind == other->kind);
9131 res->info->cvar->lexlevel = other->info->cvar->lexlevel;
9132 res->info->cvar->index = other->info->cvar->index;
9136 res->info->paramno = other->info->paramno;
9137 llassert (res->info->paramno >= -1);
9141 res->info->arrayfetch->indknown = other->info->arrayfetch->indknown;
9142 res->info->arrayfetch->ind = other->info->arrayfetch->ind;
9143 res->info->arrayfetch->arr = other->info->arrayfetch->arr;
9147 res->info->field->rec = other->info->field->rec;
9148 res->info->field->field = other->info->field->field;
9152 res->info->object = other->info->object;
9159 res->info->ref = other->info->ref;
9163 res->info->conj->a = other->info->conj->a;
9164 res->info->conj->b = other->info->conj->b;
9168 res->info->spec = other->info->spec;
9172 case SK_UNCONSTRAINED:
9173 res->info->fname = other->info->fname;
9180 llassert (res->info == NULL);
9185 static void sinfo_free (/*@special@*/ /*@temp@*/ /*@notnull@*/ sRef s)
9186 /*@uses s->kind, s->info@*/
9187 /*@releases s->info@*/
9192 DPRINTF (("Free sinfo: [%p]", s->info->cvar));
9193 sfree (s->info->cvar);
9200 DPRINTF (("Free sinfo: [%p]", s->info->arrayfetch));
9201 sfree (s->info->arrayfetch);
9205 DPRINTF (("Free sinfo: [%p]", s->info->field));
9206 sfree (s->info->field);
9215 case SK_EXTERNAL: /*@i32 is copy now! */
9219 DPRINTF (("Free sinfo: [%p]", s->info->conj));
9220 sfree (s->info->conj);
9223 case SK_UNCONSTRAINED:
9233 if (s->info != NULL) {
9234 DPRINTF (("Free sinfo: [%p]", s->info));
9240 bool sRef_isNSLocalVar (sRef s)
9242 if (sRef_isLocalVar (s))
9244 uentry ue = sRef_getUentry (s);
9246 return (!uentry_isStatic (ue));
9254 bool sRef_isLocalVar (sRef s)
9256 if (sRef_isValid(s))
9258 return (s->kind == SK_CVAR
9259 && (s->info->cvar->lexlevel > fileScope));
9265 bool sRef_isRealLocalVar (sRef s)
9267 if (sRef_isValid(s))
9269 if (s->kind == SK_CVAR)
9271 if (s->info->cvar->lexlevel == functionScope)
9273 uentry ue = sRef_getUentry (s);
9275 if (uentry_isAnyParam (ue)
9276 || uentry_isRefParam (ue))
9287 return (s->info->cvar->lexlevel > functionScope);
9295 bool sRef_isLocalParamVar (sRef s)
9297 if (sRef_isValid(s))
9299 return (s->kind == SK_PARAM
9300 || (s->kind == SK_CVAR
9301 && (s->info->cvar->lexlevel > fileScope)));
9307 static speckind speckind_fromInt (int i)
9310 llassert (i >= SR_NOTHING && i <= SR_SYSTEM);
9313 return ((speckind) i);
9317 static void sRef_updateNullState (sRef res, sRef other)
9320 res->nullstate = other->nullstate;
9321 res->nullinfo = stateInfo_update (res->nullinfo, other->nullinfo);
9324 void sRef_combineNullState (/*@notnull@*/ sRef res, /*@notnull@*/ sRef other)
9326 nstate n1 = sRef_getNullState (res);
9327 nstate n2 = sRef_getNullState (other);
9331 if (n1 == n2 || n2 == NS_UNKNOWN)
9337 /* note: n2 is not unknown or defnull */
9341 case NS_ERROR: nn = NS_ERROR; break;
9342 case NS_UNKNOWN: flip = TRUE; nn = n2; break;
9343 case NS_POSNULL: break;
9344 case NS_DEFNULL: nn = NS_POSNULL; break;
9345 case NS_RELNULL: break;
9347 if (n2 == NS_MNOTNULL)
9358 if (n2 == NS_NOTNULL)
9377 res->nullinfo = stateInfo_update (res->nullinfo, other->nullinfo);
9380 res->nullstate = nn;
9383 cstring sRef_nullMessage (sRef s)
9385 llassert (sRef_isValid (s));
9387 switch (sRef_getNullState (s))
9391 return (cstring_makeLiteralTemp ("null"));
9393 return (cstring_makeLiteralTemp ("possibly null"));
9398 /*@observer@*/ cstring sRef_ntMessage (sRef s)
9400 llassert (sRef_isValid (s));
9402 switch (s->nullstate)
9406 return (cstring_makeLiteralTemp ("not nullterminated"));
9408 return (cstring_makeLiteralTemp ("possibly non-nullterminated"));
9415 sRef sRef_fixResultType (/*@returned@*/ sRef s, ctype typ, uentry ue)
9417 sRef tmp = sRef_undefined;
9420 llassert (sRef_isValid (s));
9431 tmp = sRef_fixResultType (s->info->arrayfetch->arr, typ, ue);
9433 ct = ctype_realType (sRef_getType (tmp));
9436 if (ctype_isKnown (ct))
9438 if (ctype_isAP (ct))
9447 ("Special clause indexes non-array (%t): *%q",
9448 ct, sRef_unparse (s->info->arrayfetch->arr)),
9449 uentry_whereLast (ue));
9453 tmp = sRef_fixResultType (s->info->arrayfetch->arr, typ, ue);
9455 if (s->info->arrayfetch->indknown)
9457 ret = sRef_makeArrayFetchKnown (tmp, s->info->arrayfetch->ind);
9461 ret = sRef_makeArrayFetch (tmp);
9467 sRef rec = sRef_fixResultType (s->info->field->rec, typ, ue);
9468 ctype ct = ctype_realType (sRef_getType (rec));
9470 if (ctype_isKnown (ct))
9472 if (ctype_isSU (ct))
9474 if (uentry_isValid (uentryList_lookupField (ctype_getFields (ct),
9475 s->info->field->field)))
9484 ("Special clause accesses non-existent field of result: %q.%s",
9485 sRef_unparse (rec), s->info->field->field),
9486 uentry_whereLast (ue));
9494 ("Special clause accesses field of non-struct or union result (%t): %q.%s",
9495 ct, sRef_unparse (rec), s->info->field->field),
9496 uentry_whereLast (ue));
9500 ret = sRef_makeField (tmp, s->info->field->field);
9506 tmp = sRef_fixResultType (s->info->ref, typ, ue);
9508 ct = ctype_realType (sRef_getType (tmp));
9510 if (ctype_isKnown (ct))
9512 if (ctype_isAP (ct))
9521 ("Special clause dereferences non-pointer (%t): *%q",
9522 ct, sRef_unparse (s->info->ref)),
9523 uentry_whereLast (ue));
9527 ret = sRef_makePointer (tmp);
9534 ("Special clause uses & operator (not allowed): &%q", sRef_unparse (s->info->ref)),
9535 uentry_whereLast (ue));
9544 bool sRef_isOnly (sRef s)
9546 return (sRef_isValid(s) && alkind_isOnly (s->aliaskind));
9549 bool sRef_isDependent (sRef s)
9551 return (sRef_isValid(s) && alkind_isDependent (s->aliaskind));
9554 bool sRef_isOwned (sRef s)
9556 return (sRef_isValid (s) && (s->aliaskind == AK_OWNED));
9559 bool sRef_isKeep (sRef s)
9561 return (sRef_isValid (s) && (s->aliaskind == AK_KEEP));
9564 bool sRef_isTemp (sRef s)
9566 return (sRef_isValid (s) && alkind_isTemp (s->aliaskind));
9569 bool sRef_isLocalState (sRef s)
9571 return (sRef_isValid (s) && (s->aliaskind == AK_LOCAL));
9574 bool sRef_isUnique (sRef s)
9576 return (sRef_isValid (s) && (s->aliaskind == AK_UNIQUE));
9579 bool sRef_isShared (sRef s)
9581 return (sRef_isValid (s) && (s->aliaskind == AK_SHARED));
9584 bool sRef_isExposed (sRef s)
9586 return (sRef_isValid (s) && (s->expkind == XO_EXPOSED));
9589 bool sRef_isObserver (sRef s)
9591 return (sRef_isValid (s) && (s->expkind == XO_OBSERVER));
9594 bool sRef_isFresh (sRef s)
9596 return (sRef_isValid (s) && (s->aliaskind == AK_FRESH));
9599 bool sRef_isDefinitelyNull (sRef s)
9601 return (sRef_isValid (s) && (sRef_getNullState (s) == NS_DEFNULL
9602 || sRef_getNullState (s) == NS_CONSTNULL));
9605 bool sRef_isAllocated (sRef s)
9607 return (sRef_isValid (s) && (s->defstate == SS_ALLOCATED));
9610 bool sRef_isStack (sRef s)
9612 return (sRef_isValid (s) && (s->aliaskind == AK_STACK));
9615 bool sRef_isNotNull (sRef s)
9617 return (sRef_isValid(s) && (sRef_getNullState (s) == NS_MNOTNULL
9618 || sRef_getNullState (s) == NS_NOTNULL));
9621 alkind sRef_getAliasKind (sRef s)
9623 if (sRef_isValid(s)) {
9624 llassert (alkind_isValid (s->aliaskind));
9625 return s->aliaskind;
9631 nstate sRef_getNullState (sRef s)
9633 if (sRef_isValid (s)) {
9634 llassert (nstate_isValid (s->nullstate));
9635 return s->nullstate;
9641 void sRef_reflectAnnotation (sRef s, annotationInfo a, fileloc loc)
9643 if (sRef_isValid (s))
9645 if (!valueTable_isDefined (s->state))
9647 s->state = valueTable_create (1);
9648 valueTable_insert (s->state,
9649 cstring_copy (metaStateInfo_getName (annotationInfo_getState (a))),
9650 stateValue_create (annotationInfo_getValue (a), stateInfo_makeLoc (loc)));
9654 DPRINTF (("reflect loc: %s", fileloc_unparse (loc)));
9657 metaStateInfo_getName (annotationInfo_getState (a)),
9658 stateValue_create (annotationInfo_getValue (a), stateInfo_makeLoc (loc)));
9659 DPRINTF (("state info: %s", stateInfo_unparse (stateInfo_makeLoc (loc))));
9660 DPRINTF (("sref: %s", sRef_unparse (s)));
9661 DPRINTF (("sref: %s", sRef_unparseFull (s)));
9666 void sRef_setMetaStateValueComplete (sRef s, cstring key, int value, fileloc loc)
9668 sRefSet aliases = usymtab_allAliases (s);
9670 sRef_setMetaStateValue (s, key, value, loc);
9672 sRefSet_realElements (aliases, current)
9674 if (sRef_isValid (current))
9676 current = sRef_updateSref (current);
9677 sRef_setMetaStateValue (current, key, value, loc);
9679 } end_sRefSet_realElements ;
9681 sRefSet_free (aliases);
9684 void sRef_setMetaStateValue (sRef s, cstring key, int value, fileloc loc)
9686 sRef_checkMutable (s);
9688 if (sRef_isValid (s))
9690 if (!valueTable_isDefined (s->state))
9692 DPRINTF (("inserting state: %s: %s %d", sRef_unparse (s), key, value));
9693 s->state = valueTable_create (1);
9694 valueTable_insert (s->state, cstring_copy (key),
9695 stateValue_create (value, stateInfo_makeLoc (loc)));
9699 DPRINTF (("Updating state: %s: %s %d / %s", sRef_unparse (s), key, value,
9700 fileloc_unparse (loc)));
9701 if (valueTable_contains (s->state, key))
9704 (s->state, key, stateValue_create (value, stateInfo_makeLoc (loc)));
9709 (s->state, cstring_copy (key), stateValue_create (value, stateInfo_makeLoc (loc)));
9712 DPRINTF (("After: %s", sRef_unparseFull (s)));
9717 bool sRef_checkMetaStateValue (sRef s, cstring key, int value)
9719 if (sRef_isValid (s))
9721 if (valueTable_isDefined (s->state))
9725 DPRINTF (("check state: %s: %s %d", sRef_unparse (s), key, value));
9727 val = valueTable_lookup (s->state, key);
9728 llassert (stateValue_isDefined (val));
9729 return (stateValue_isError (val)
9730 || stateValue_getValue (val) == value);
9743 /*@observer@*/ stateValue sRef_getMetaStateValue (sRef s, cstring key)
9745 if (sRef_isValid (s))
9747 if (valueTable_isDefined (s->state))
9751 val = valueTable_lookup (s->state, key);
9752 /* Okay if its not defined, just returns stateValue_undefined */
9757 return stateValue_undefined;
9762 return stateValue_undefined;
9766 /*@observer@*/ valueTable sRef_getValueTable (sRef s)
9768 DPRINTF (("Get value table: %s", sRef_unparse (s)));
9770 if (sRef_isValid (s))
9772 llassert (sRef_isValid (s));
9773 DPRINTF (("Value table: %s", valueTable_unparse (s->state)));
9778 DPRINTF (("No value table!"));
9779 return valueTable_undefined;
9783 bool sRef_makeStateSpecial (sRef s)
9786 ** Default defined state can be made special.
9789 llassert (sRef_isValid (s)); /*@i523 why doesn't null-checking work!??? */
9791 if (s->defstate == SS_UNKNOWN || s->defstate == SS_DEFINED || s->defstate == SS_SPECIAL)
9793 /* s->aliaskind = AK_IMPTEMP; */ /* evans 2001-07-23 shouldn't effect alias state */
9794 s->defstate = SS_SPECIAL;
9795 DPRINTF (("Made special: %s", sRef_unparseFull (s)));
9800 /* s->aliaskind = AK_IMPTEMP; */
9801 s->defstate = SS_SPECIAL;
9806 void sRef_markImmutable (sRef s)
9808 if (sRef_isValid (s))
9810 DPRINTF (("Mark immutable: %s", sRef_unparseFull (s)));
9815 bool sRef_definitelyNullContext (sRef s)
9817 return (sRef_definitelyNull (s)
9818 || usymtab_isDefinitelyNullDeep (s));
9821 bool sRef_definitelyNullAltContext (sRef s)
9823 return (sRef_definitelyNull (s)
9824 || usymtab_isAltDefinitelyNullDeep (s));
9828 /* start modifications */
9829 struct s_bbufinfo sRef_getNullTerminatedState (sRef p_s) {
9830 struct s_bbufinfo BUFSTATE_UNKNOWN;
9831 BUFSTATE_UNKNOWN.bufstate = BB_NOTNULLTERMINATED;
9832 BUFSTATE_UNKNOWN.size = 0;
9833 BUFSTATE_UNKNOWN.len = 0;
9835 if (sRef_isValid(p_s))
9836 return p_s->bufinfo;
9837 return BUFSTATE_UNKNOWN;
9840 void sRef_setNullTerminatedState(sRef p_s) {
9841 if(sRef_isValid (p_s)) {
9842 p_s->bufinfo.bufstate = BB_NULLTERMINATED;
9844 llfatalbug( message("sRef_setNT passed a invalid sRef\n"));
9849 void sRef_setPossiblyNullTerminatedState(sRef p_s) {
9850 if( sRef_isValid (p_s)) {
9851 p_s->bufinfo.bufstate = BB_POSSIBLYNULLTERMINATED;
9853 llfatalbug( message("sRef_setPossNT passed a invalid sRef\n"));
9857 void sRef_setNotNullTerminatedState(sRef p_s) {
9858 if( sRef_isValid (p_s)) {
9859 p_s->bufinfo.bufstate = BB_NOTNULLTERMINATED;
9861 llfatalbug( message("sRef_unsetNT passed a invalid sRef\n"));
9865 void sRef_setLen(sRef p_s, int len) {
9866 if( sRef_isValid (p_s) && sRef_isNullTerminated(p_s)) {
9867 p_s->bufinfo.len = len;
9869 llfatalbug( message("sRef_setLen passed a invalid sRef\n"));
9874 void sRef_setSize(sRef p_s, int size) {
9875 if( sRef_isValid(p_s)) {
9876 p_s->bufinfo.size = size;
9878 llfatalbug( message("sRef_setSize passed a invalid sRef\n"));
9882 void sRef_resetLen(sRef p_s) {
9883 if (sRef_isValid (p_s)) {
9884 p_s->bufinfo.len = 0;
9886 llfatalbug (message ("sRef_setLen passed an invalid sRef\n"));
9890 /*drl7x 11/28/2000 */
9892 bool sRef_isFixedArray (sRef p_s) /*@*/ {
9894 c = sRef_getType (p_s);
9895 return ( ctype_isFixedArray (c) );
9898 long int sRef_getArraySize (sRef p_s) /*@*/ {
9900 llassert (sRef_isFixedArray(p_s) );
9901 DPRINTF (( message ("sRef_getArraySize getting array size for %s", sRef_unparse(p_s) ) ));
9903 c = sRef_getType (p_s);
9905 return (ctype_getArraySize (c) );
9908 void sRef_setValue (sRef s, multiVal val)
9910 llassert (sRef_isValid (s));
9911 multiVal_free (s->val);
9915 bool sRef_hasValue (sRef s)
9917 return (sRef_isValid (s)
9918 && multiVal_isDefined (s->val));
9921 multiVal sRef_getValue (sRef s)
9923 if (sRef_isValid (s))
9928 return multiVal_undefined;