2 ** LCLint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2001 University of Virginia,
4 ** Massachusetts Institute of Technology
6 ** This program is free software; you can redistribute it and/or modify it
7 ** under the terms of the GNU General Public License as published by the
8 ** Free Software Foundation; either version 2 of the License, or (at your
9 ** option) any later version.
11 ** This program is distributed in the hope that it will be useful, but
12 ** WITHOUT ANY WARRANTY; without even the implied warranty of
13 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 ** General Public License for more details.
16 ** The GNU General Public License is available from http://www.gnu.org/ or
17 ** the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
18 ** MA 02111-1307, USA.
20 ** For information on lclint: lclint-request@cs.virginia.edu
21 ** To report a bug: lclint-bug@cs.virginia.edu
22 ** For more information: http://lclint.cs.virginia.edu
28 ** storeRef's are kept in allRefs for each function scope, and all are
29 ** free'd at the end of the function. This relies on the constraint that
30 ** no storeRef created while checking a function is used outside that
33 ** storeRefs in the file and global scopes are free'd by the uentry.
37 # include "lclintMacros.nf"
39 # include "exprChecks.h"
40 # include "transferChecks.h"
41 # include "sRefTable.h"
42 # include "structNames.h"
45 ** Predicate functions that evaluate both arguments in order.
49 # define OR(a,b) (a ? (b, TRUE) : b)
52 # define AND(a,b) (a ? b : (b, FALSE))
54 static void sRef_checkValidAux (sRef p_s, sRefSet p_checkedsofar) /*@modifies p_checkedsofar@*/ ;
56 static bool sRef_isDerived (sRef p_s) /*@*/ ;
58 static /*@exposed@*/ sRef sRef_fixDirectBase (sRef p_s, sRef p_base)
59 /*@modifies p_base@*/ ;
61 static void sRef_updateNullState (sRef p_res, sRef p_other) /*@modifies p_res@*/ ;
63 static bool sRef_isAllocatedStorage (sRef p_s) /*@*/ ;
64 static void sRef_setNullErrorLoc (sRef p_s, fileloc) /*@*/ ;
67 sRef_aliasSetComplete (void (p_predf) (sRef, fileloc), sRef p_s, fileloc p_loc)
70 static int sRef_depth (sRef p_s) /*@*/ ;
73 sRef_innerAliasSetComplete (void (p_predf) (sRef, fileloc), sRef p_s,
78 sRef_innerAliasSetCompleteParam (void (p_predf) (sRef, sRef), sRef p_s, sRef p_t)
82 sRef_aliasSetCompleteParam (void (p_predf) (sRef, alkind, fileloc), sRef p_s,
83 alkind p_kind, fileloc p_loc)
86 static speckind speckind_fromInt (int p_i);
87 static bool sRef_equivalent (sRef p_s1, sRef p_s2);
88 static bool sRef_isDeepUnionField (sRef p_s);
89 static void sRef_addDeriv (/*@notnull@*/ sRef p_s, /*@notnull@*/ /*@exposed@*/ sRef p_t);
90 static /*@dependent@*/ sRef sRef_makeResultType (ctype p_ct) /*@*/ ;
91 static bool sRef_checkModify (sRef p_s, sRefSet p_sl) /*@*/ ;
93 static void sRef_checkMutable (/*@unused@*/ sRef s)
96 if (sRef_isValid (s) && s->immut)
98 llcontbug (message ("Modification to sRef marked immutable: %q",
99 sRef_unparseFull (s)));
103 static bool skind_isSimple (skind sk)
107 case SK_PARAM: case SK_CVAR: case SK_CONST:
108 case SK_OBJECT: case SK_UNKNOWN: case SK_NEW:
115 static void sinfo_free (/*@special@*/ /*@temp@*/ /*@notnull@*/ sRef p_s)
116 /*@uses p_s->kind, p_s->info@*/
117 /*@releases p_s->info@*/ ;
119 static /*@null@*/ sinfo sinfo_copy (/*@notnull@*/ sRef p_s) /*@*/ ;
120 static void sRef_setPartsFromUentry (sRef p_s, uentry p_ue)
122 static bool checkDeadState (/*@notnull@*/ sRef p_el, bool p_tbranch, fileloc p_loc);
123 static /*@dependent@*/ sRef sRef_constructPointerAux (/*@notnull@*/ /*@exposed@*/ sRef p_t) /*@*/ ;
126 sRef_combineExKinds (/*@notnull@*/ sRef p_res, /*@notnull@*/ sRef p_other)
127 /*@modifies p_res@*/ ;
130 sRef_combineAliasKinds (/*@notnull@*/ sRef p_res, /*@notnull@*/ sRef p_other,
131 clause p_cl, fileloc p_loc)
132 /*@modifies p_res@*/ ;
135 sRef_combineNullState (/*@notnull@*/ sRef p_res, /*@notnull@*/ sRef p_other)
136 /*@modifies p_res@*/ ;
139 sRef_combineDefState (/*@notnull@*/ sRef p_res, /*@notnull@*/ sRef p_other)
140 /*@modifies p_res@*/ ;
142 static void sRef_setStateFromAbstractUentry (sRef p_s, uentry p_ue)
146 sinfo_update (/*@notnull@*/ /*@exposed@*/ sRef p_res,
147 /*@notnull@*/ /*@exposed@*/ sRef p_other);
148 static void sRef_setDefinedAux (sRef p_s, fileloc p_loc, bool p_clear)
150 static void sRef_setDefinedNoClear (sRef p_s, fileloc p_loc)
152 static void sRef_setStateAux (sRef p_s, sstate p_ss, fileloc p_loc)
155 static /*@exposed@*/ sRef
156 sRef_buildNCField (/*@exposed@*/ sRef p_rec, /*@exposed@*/ cstring p_f);
159 sRef_mergeStateAux (/*@notnull@*/ sRef p_res, /*@notnull@*/ sRef p_other,
160 clause p_cl, bool p_opt, fileloc p_loc,
162 /*@modifies p_res, p_other@*/ ;
164 static /*@null@*/ sinfo sinfo_fullCopy (/*@notnull@*/ sRef p_s);
165 static bool sRef_doModify (sRef p_s, sRefSet p_sl) /*@modifies p_s@*/ ;
166 static bool sRef_doModifyVal (sRef p_s, sRefSet p_sl) /*@modifies p_s@*/;
167 static bool sRef_checkModifyVal (sRef p_s, sRefSet p_sl) /*@*/ ;
169 static /*@only@*/ sRefSet
170 sRef_mergeDerivs (/*@only@*/ sRefSet p_res, sRefSet p_other,
171 bool p_opt, clause p_cl, fileloc p_loc);
173 static /*@only@*/ sRefSet
174 sRef_mergeUnionDerivs (/*@only@*/ sRefSet p_res,
175 /*@exposed@*/ sRefSet p_other,
176 bool p_opt, clause p_cl, fileloc p_loc);
178 static /*@only@*/ sRefSet
179 sRef_mergePdefinedDerivs (/*@only@*/ sRefSet p_res, sRefSet p_other, bool p_opt,
180 clause p_cl, fileloc p_loc);
182 static /*@only@*/ cstring sRef_unparseWithArgs (sRef p_s, uentryList p_args);
183 static /*@only@*/ cstring sRef_unparseNoArgs (sRef p_s);
185 static /*@exposed@*/ sRef sRef_findDerivedPointer (sRef p_s);
186 static /*@exposed@*/ sRef sRef_findDerivedField (/*@notnull@*/ sRef p_rec, cstring p_f);
187 static /*@exposed@*/ sRef
188 sRef_getDeriv (/*@notnull@*/ /*@returned@*/ sRef p_set, sRef p_guide);
190 static bool inFunction = FALSE;
191 static /*@only@*/ sRefTable allRefs;
193 /* # define DEBUGREFS */
197 static totnsrefs = 0;
198 static maxnsrefs = 0;
199 static ntotrefers = 0;
203 static /*@checked@*/ bool protectDerivs = FALSE;
206 ** Result of sRef_alloc is dependent since allRefs may
207 ** reference it. It is only if !inFunction.
210 static /*@dependent@*/ /*@out@*/ /*@notnull@*/ sRef
213 sRef s = (sRef) dmalloc (sizeof (*s));
217 DPRINTF (("Alloc sref: [%p]", s));
221 allRefs = sRefTable_add (allRefs, s);
226 DPRINTF (("Not in function!"));
232 if (nsrefs >= maxnsrefs)
241 /*@-mustfree@*/ /*@-freshtrans@*/
243 /*@=mustfree@*/ /*@=freshtrans@*/
246 static void sRef_checkValidAux (sRef s, sRefSet checkedsofar)
250 if (!sRef_isValid (s)) return;
252 if (sRefSet_containsSameObject (checkedsofar, s))
258 checkedsofar = sRefSet_insert (checkedsofar, s);
259 /*@=temptrans@*/ /* checksofar will be destroyed before checkValid returns */
263 case SK_UNCONSTRAINED:
264 llassert (cstring_length (s->info->fname) < 100);
268 llassert (s->info->cvar->lexlevel >= 0);
269 /* llassert (s->info->cvar->lexlevel <= usymtab_getCurrentDepth ()); */
273 llassert (s->info->paramno >= -1);
274 llassert (s->info->paramno <= 50); /*@i32 bogus...*/
278 sRef_checkValidAux (s->info->arrayfetch->arr, checkedsofar);
282 sRef_checkValidAux (s->info->field->rec, checkedsofar);
283 llassert (cstring_length (s->info->field->field) < 100);
287 sRef_checkValidAux (s->info->ref, checkedsofar);
291 sRef_checkValidAux (s->info->ref, checkedsofar);
295 /* check ctype s->info->object */
299 sRef_checkValidAux (s->info->conj->a, checkedsofar);
300 sRef_checkValidAux (s->info->conj->b, checkedsofar);
304 llassert (cstring_length (s->info->fname) < 100);
308 sRef_checkValidAux (s->info->ref, checkedsofar);
312 sRef_checkValidAux (s->info->ref, checkedsofar);
318 /* check ctyp s->type */
322 llassert (s->info->spec == SR_NOTHING
323 || s->info->spec == SR_INTERNAL
324 || s->info->spec == SR_SPECSTATE
325 || s->info->spec == SR_SYSTEM);
335 sRefSet_elements (s->deriv, el)
337 sRef_checkValidAux (el, checkedsofar);
338 } end_sRefSet_elements ;
341 void sRef_checkValid (/*@unused@*/ sRef s)
345 sRefSet checkedsofar = sRefSet_new ();
346 sRef_checkValidAux (s, checkedsofar);
350 static /*@dependent@*/ /*@notnull@*/ /*@special@*/ sRef
353 /*@ensures isnull result->aliasinfo, result->definfo,
354 result->expinfo, result->info, result->deriv, result->state@*/
356 sRef s = sRef_alloc ();
358 s->kind = SK_UNKNOWN;
363 s->type = ctype_unknown;
364 s->defstate = SS_UNKNOWN;
366 /* start modifications */
367 s->bufinfo.bufstate = BB_NOTNULLTERMINATED;
368 /* end modifications */
370 s->aliaskind = AK_UNKNOWN;
371 s->oaliaskind = AK_UNKNOWN;
373 s->nullstate = NS_UNKNOWN;
375 s->expkind = XO_UNKNOWN;
376 s->oexpkind = XO_UNKNOWN;
378 s->aliasinfo = stateInfo_undefined;
379 s->definfo = stateInfo_undefined;
380 s->nullinfo = stateInfo_undefined;
381 s->expinfo = stateInfo_undefined;
384 s->deriv = sRefSet_undefined;
386 s->state = valueTable_undefined;
391 static /*@dependent@*/ /*@notnull@*/ /*@special@*/ sRef
394 /*@ensures isnull result->aliasinfo, result->definfo,
395 result->expinfo, result->info, result->deriv@*/
397 sRef res = sRef_new ();
399 res->state = valueTable_undefined;
404 void sRef_protectDerivs (void) /*@modifies protectDerivs@*/
406 llassert (!protectDerivs);
407 protectDerivs = TRUE;
410 void sRef_clearProtectDerivs (void) /*@modifies protectDerivs@*/
412 llassert (protectDerivs);
413 protectDerivs = FALSE;
417 ** hmmm...here be kind of a hack. This function mysteriously appeared
418 ** in my code, but I'm sure I didn't write it.
422 sRef_isRecursiveField (sRef s)
424 if (sRef_isField (s))
426 if (sRef_depth (s) > 13)
431 fieldname = sRef_getField (s);
432 base = sRef_getBase (s);
434 while (sRef_isValid (base))
436 if (sRef_isField (base))
438 if (cstring_equal (fieldname, sRef_getField (base)))
444 base = sRef_getBaseSafe (base);
453 sRef_addDeriv (/*@notnull@*/ sRef s, /*@notnull@*/ /*@exposed@*/ sRef t)
455 if (!context_inProtectVars ()
459 && !sRef_isConst (s))
461 int sd = sRef_depth (s);
462 int td = sRef_depth (t);
469 if (sRef_isFileOrGlobalScope (s))
471 if (context_inFunctionLike ()
472 && ctype_isKnown (sRef_getType (s))
473 && !ctype_isFunction (sRef_getType (s)))
475 globSet g = context_getUsedGlobs ();
477 if (!globSet_member (g, s))
480 ** don't report as a bug
484 (message ("sRef_addDeriv: global variable not in used "
485 "globs: %q / %s / %q",
487 ctype_unparse (sRef_getType (s)),
488 sRefSet_unparse (s->deriv)));
493 s->deriv = sRefSet_insert (s->deriv, t);
499 DPRINTF (("Add deriv: [%p] %s / [%p] %s",
501 t, sRef_unparse (t)));
503 s->deriv = sRefSet_insert (s->deriv, t);
509 sRef_deepPred (bool (predf) (sRef), sRef s)
511 if (sRef_isValid (s))
513 if ((*predf)(s)) return TRUE;
518 return (sRef_deepPred (predf, s->info->ref));
520 return (sRef_deepPred (predf, s->info->arrayfetch->arr));
522 return (sRef_deepPred (predf, s->info->field->rec));
524 return (sRef_deepPred (predf, s->info->conj->a)
525 || sRef_deepPred (predf, s->info->conj->b));
534 bool sRef_modInFunction (void)
539 void sRef_setStateFromType (sRef s, ctype ct)
541 if (sRef_isValid (s))
543 if (ctype_isUser (ct))
545 DPRINTF (("Here we are: %s", sRef_unparseFull (s)));
546 sRef_setStateFromUentry
547 (s, usymtab_getTypeEntry (ctype_typeId (ct)));
549 else if (ctype_isAbstract (ct))
551 DPRINTF (("Here we are: %s", sRef_unparseFull (s)));
552 sRef_setStateFromAbstractUentry
553 (s, usymtab_getTypeEntry (ctype_typeId (ct)));
557 ; /* not a user type */
562 static void sRef_setTypeState (sRef s)
564 if (sRef_isValid (s))
566 sRef_setStateFromType (s, s->type);
571 sRef_hasAliasInfoLoc (sRef s)
573 return (sRef_isValid (s) && (s->aliasinfo != NULL)
574 && (fileloc_isDefined (s->aliasinfo->loc)));
577 static /*@falsenull@*/ bool
578 sRef_hasStateInfoLoc (sRef s)
580 return (sRef_isValid (s) && (s->definfo != NULL)
581 && (fileloc_isDefined (s->definfo->loc)));
584 static /*@falsenull@*/ bool
585 sRef_hasExpInfoLoc (sRef s)
587 return (sRef_isValid (s)
588 && (s->expinfo != NULL) && (fileloc_isDefined (s->expinfo->loc)));
591 static /*@observer@*/ /*@unused@*/ stateInfo sRef_getInfo (sRef s, cstring key)
595 if (!sRef_isValid (s)) {
596 return stateInfo_undefined;
599 sv = valueTable_lookup (s->state, key);
601 if (stateValue_isDefined (sv))
603 return stateValue_getInfo (sv);
606 return stateInfo_undefined;
611 sRef_hasNullInfoLoc (sRef s)
613 return (sRef_isValid (s) && s->nullinfo != NULL
614 && (fileloc_isDefined (s->nullinfo->loc)));
618 sRef_hasAliasInfoRef (sRef s)
620 return (sRef_isValid (s) && (s->aliasinfo != NULL)
621 && (sRef_isValid (s->aliasinfo->ref)));
624 static /*@observer@*/ fileloc
625 sRef_getAliasInfoLoc (/*@exposed@*/ sRef s)
627 llassert (sRef_isValid (s) && s->aliasinfo != NULL
628 && (fileloc_isDefined (s->aliasinfo->loc)));
629 return (s->aliasinfo->loc);
632 static /*@observer@*/ fileloc
633 sRef_getStateInfoLoc (/*@exposed@*/ sRef s)
635 llassert (sRef_isValid (s) && s->definfo != NULL
636 && (fileloc_isDefined (s->definfo->loc)));
637 return (s->definfo->loc);
640 static /*@observer@*/ fileloc
641 sRef_getExpInfoLoc (/*@exposed@*/ sRef s)
643 llassert (sRef_isValid (s) && s->expinfo != NULL
644 && (fileloc_isDefined (s->expinfo->loc)));
645 return (s->expinfo->loc);
648 static /*@observer@*/ fileloc
649 sRef_getNullInfoLoc (/*@exposed@*/ sRef s)
651 llassert (sRef_isValid (s) && s->nullinfo != NULL
652 && (fileloc_isDefined (s->nullinfo->loc)));
653 return (s->nullinfo->loc);
657 sRef_getAliasInfoRef (/*@temp@*/ sRef s)
659 llassert (sRef_isValid (s) && s->aliasinfo != NULL);
660 return (s->aliasinfo->ref);
663 bool sRef_inGlobalScope ()
669 ** This function should be called before new sRefs are created
670 ** somewhere where they will have a lifetime greater than the
671 ** current function scope.
674 void sRef_setGlobalScope ()
676 llassert (inFunction);
677 DPRINTF (("leave function"));
681 void sRef_clearGlobalScope ()
683 llassert (!inFunction);
684 DPRINTF (("enter function"));
688 static bool oldInFunction = FALSE;
689 static int nestedScope = 0;
691 void sRef_setGlobalScopeSafe ()
693 if (nestedScope == 0)
695 oldInFunction = inFunction;
699 DPRINTF (("leave function safe"));
703 void sRef_clearGlobalScopeSafe ()
706 llassert (nestedScope >= 0);
708 if (nestedScope == 0)
710 inFunction = oldInFunction;
713 DPRINTF (("clear function: %s", bool_unparse (inFunction)));
716 void sRef_enterFunctionScope ()
718 llassert (!inFunction);
719 llassert (sRefTable_isEmpty (allRefs));
721 DPRINTF (("enter function"));
724 void sRef_exitFunctionScope ()
728 DPRINTF (("Exit function scope."));
729 sRefTable_clear (allRefs);
734 llbuglit ("sRef_exitFunctionScope: not in function");
738 void sRef_destroyMod () /*@globals killed allRefs;@*/
741 llmsg (message ("Live: %d / %d ", nsrefs, totnsrefs));
744 sRefTable_free (allRefs);
748 static /*@notnull@*/ /*@exposed@*/ sRef
749 sRef_fixConj (/*@notnull@*/ sRef s)
754 s = sRef_getConjA (s);
755 } while (sRef_isConj (s));
757 llassert (sRef_isValid (s));
758 return s; /* don't need to ref */
767 sRef_isExternallyVisibleAux (sRef s)
770 sRef base = sRef_getRootBase (s);
772 if (sRef_isValid (base))
774 res = sRef_isParam (base) || sRef_isFileOrGlobalScope (base) || sRef_isExternal (base);
781 sRef_isExternallyVisible (sRef s)
783 return (sRef_aliasCheckSimplePred (sRef_isExternallyVisibleAux, s));
787 sRef_getBaseUentry (sRef s)
789 sRef base = sRef_getRootBase (s);
790 uentry res = uentry_undefined;
792 if (sRef_isValid (base))
797 res = usymtab_getRefQuiet (paramsScope, base->info->paramno);
801 res = usymtab_getRefQuiet (base->info->cvar->lexlevel,
802 base->info->cvar->index);
814 ** lookup the current uentry corresponding to s, and return the corresponding sRef.
815 ** yuk yuk yuk yuk yuk yuk yuk yuk
819 sRef_updateSref (sRef s)
825 if (!sRef_isValid (s)) return sRef_undefined;
834 case SK_UNCONSTRAINED:
841 sRef r = sRef_updateSref (s->info->ref);
843 if (r != s->info->ref)
845 return sRef_makeExternal (r);
855 uentry ue = sRef_getUentry (s);
857 /* must be raw name! (need the marker) */
858 ue = usymtab_lookupSafe (uentry_rawName (ue));
860 if (uentry_isUndefined (ue))
866 DPRINTF (("Update sref: %s", uentry_unparseFull (ue)));
867 return (uentry_getSref (ue));
871 /* special case if ind known */
872 inner = s->info->arrayfetch->arr;
873 ret = sRef_updateSref (inner);
881 res = sRef_makeArrayFetch (ret);
887 inner = s->info->field->rec;
888 ret = sRef_updateSref (inner);
896 res = (sRef_makeField (ret, s->info->field->field));
901 inner = s->info->ref;
902 ret = sRef_updateSref (inner);
909 res = sRef_makePointer (ret);
915 inner = s->info->ref;
916 ret = sRef_updateSref (inner);
924 res = sRef_makeAddress (ret);
931 sRef innera = s->info->conj->a;
932 sRef innerb = s->info->conj->b;
933 sRef reta = sRef_updateSref (innera);
934 sRef retb = sRef_updateSref (innerb);
936 if (innera == reta && innerb == retb)
942 res = sRef_makeConj (reta, retb);
953 sRef_getUentry (sRef s)
955 llassert (sRef_isValid (s));
960 return (usymtab_getRefQuiet (paramsScope, s->info->paramno));
962 return (usymtab_getRefQuiet (s->info->cvar->lexlevel, s->info->cvar->index));
965 if (sRef_isCvar (s->info->conj->a) || sRef_isParam (s->info->conj->a)
966 || sRef_isConj (s->info->conj->a))
968 return sRef_getUentry (s->info->conj->a);
972 return sRef_getUentry (s->info->conj->b);
977 return uentry_undefined;
983 sRef_getParam (sRef s)
985 llassert (sRef_isValid (s));
986 llassert (s->kind == SK_PARAM);
988 return s->info->paramno;
992 sRef_isModified (sRef s)
994 return (!sRef_isValid (s) || s->modified);
997 void sRef_setModified (sRef s)
999 if (sRef_isValid (s))
1004 if (sRef_isRefsField (s))
1006 sRef base = sRef_getBase (s);
1009 llassert (s->kind == SK_FIELD);
1012 if (sRef_isPointer (base))
1014 base = sRef_getBase (base);
1017 if (sRef_isRefCounted (base))
1019 base->aliaskind = AK_NEWREF;
1026 ** note: this side-effects sRefSet to set modified to TRUE
1027 ** for any sRef similar to s.
1031 sRef_canModifyVal (sRef s, sRefSet sl)
1033 if (context_getFlag (FLG_MUSTMOD))
1035 return (sRef_doModifyVal (s, sl));
1039 return (sRef_checkModifyVal (s, sl));
1044 sRef_canModify (sRef s, sRefSet sl)
1047 if (context_getFlag (FLG_MUSTMOD))
1049 return (sRef_doModify (s, sl));
1053 return (sRef_checkModify (s, sl));
1062 bool sRef_checkModifyVal (sRef s, sRefSet sl)
1064 DPRINTF (("Check modify val: %s", sRef_unparse (s)));
1066 if (sRef_isInvalid (s))
1073 case SK_UNCONSTRAINED:
1077 DPRINTF (("Modify var: %s", sRef_unparse (s)));
1079 if (sRef_isFileOrGlobalScope (s))
1081 if (context_checkGlobMod (s))
1083 return (sRefSet_member (sl, s));
1093 return (sRefSet_member (sl, s)
1094 || alkind_isOnly (sRef_getOrigAliasKind (s)));
1096 /* special case if ind known */
1097 return (sRefSet_member (sl, s) ||
1098 sRef_checkModifyVal (s->info->arrayfetch->arr, sl));
1100 return (sRefSet_member (sl, s) || sRef_checkModifyVal (s->info->field->rec, sl));
1102 return (sRefSet_member (sl, s) || sRef_checkModifyVal (s->info->ref, sl));
1104 return (sRefSet_member (sl, s) || sRef_checkModifyVal (s->info->ref, sl));
1106 return ((sRef_checkModifyVal (s->info->conj->a, sl)) &&
1107 (sRef_checkModifyVal (s->info->conj->b, sl)));
1118 switch (s->info->spec)
1120 case SR_NOTHING: return TRUE;
1122 if (context_getFlag (FLG_INTERNALGLOBS))
1124 return (sRefSet_member (sl, s));
1130 case SR_SPECSTATE: return TRUE;
1131 case SR_SYSTEM: return (sRefSet_member (sl, s));
1132 case SR_GLOBALMARKER: BADBRANCH;
1135 case SK_RESULT: BADBRANCH;
1141 ** this should probably be elsewhere...
1143 ** returns TRUE iff sl indicates that s can be modified
1146 static bool sRef_checkModify (sRef s, sRefSet sl)
1148 llassert (sRef_isValid (s));
1152 case SK_UNCONSTRAINED:
1156 if (sRef_isFileOrGlobalScope (s))
1158 if (context_checkGlobMod (s))
1160 return (sRefSet_member (sl, s));
1172 return (sRefSet_member (sl, s) ||
1173 sRef_checkModifyVal (s->info->arrayfetch->arr, sl));
1176 sRef sr = s->info->field->rec;
1178 if (sr->kind == SK_PARAM)
1179 return TRUE; /* structs are copied on call */
1181 return (sRefSet_member (sl, s) || sRef_checkModifyVal (s->info->field->rec, sl));
1187 sm = sRefSet_member (sl, s);
1192 return (sRef_checkModifyVal (s->info->ref, sl));
1195 return (sRefSet_member (sl, s) || sRef_checkModifyVal (s->info->ref, sl));
1197 return ((sRef_checkModify (s->info->conj->a, sl)) &&
1198 (sRef_checkModify (s->info->conj->b, sl)));
1208 switch (s->info->spec)
1210 case SR_NOTHING: return TRUE;
1212 if (context_getFlag (FLG_INTERNALGLOBS))
1214 return (sRefSet_member (sl, s));
1220 case SR_SPECSTATE: return TRUE;
1221 case SR_SYSTEM: return (sRefSet_member (sl, s));
1222 case SR_GLOBALMARKER: BADBRANCH;
1225 case SK_RESULT: BADBRANCH;
1230 cstring sRef_stateVerb (sRef s)
1232 if (sRef_isDead (s))
1234 return cstring_makeLiteralTemp ("released");
1236 else if (sRef_isKept (s))
1238 return cstring_makeLiteralTemp ("kept");
1240 else if (sRef_isDependent (s))
1242 return cstring_makeLiteralTemp ("dependent");
1250 cstring sRef_stateAltVerb (sRef s)
1252 if (sRef_isDead (s))
1254 return cstring_makeLiteralTemp ("live");
1256 else if (sRef_isKept (s))
1258 return cstring_makeLiteralTemp ("not kept");
1260 else if (sRef_isDependent (s))
1262 return cstring_makeLiteralTemp ("independent");
1271 bool sRef_doModifyVal (sRef s, sRefSet sl)
1273 llassert (sRef_isValid (s));
1278 case SK_UNCONSTRAINED:
1282 if (sRef_isFileOrGlobalScope (s))
1285 if (context_checkGlobMod (s))
1287 return (sRefSet_modifyMember (sl, s));
1291 (void) sRefSet_modifyMember (sl, s);
1301 return (sRefSet_modifyMember (sl, s)
1302 || alkind_isOnly (sRef_getOrigAliasKind (s)));
1304 /* special case if ind known */
1305 /* unconditional OR, need side effect */
1306 return (OR (sRefSet_modifyMember (sl, s),
1307 sRef_doModifyVal (s->info->arrayfetch->arr, sl)));
1309 return (OR (sRefSet_modifyMember (sl, s),
1310 sRef_doModifyVal (s->info->field->rec, sl)));
1312 return (OR (sRefSet_modifyMember (sl, s),
1313 sRef_doModifyVal (s->info->ref, sl)));
1315 return (OR (sRefSet_modifyMember (sl, s),
1316 sRef_doModifyVal (s->info->ref, sl)));
1318 return (AND (sRef_doModifyVal (s->info->conj->a, sl) ,
1319 sRef_doModifyVal (s->info->conj->b, sl)));
1329 switch (s->info->spec)
1331 case SR_NOTHING: return TRUE;
1333 if (context_getFlag (FLG_INTERNALGLOBS))
1335 return (sRefSet_modifyMember (sl, s));
1339 (void) sRefSet_modifyMember (sl, s);
1342 case SR_SPECSTATE: return TRUE;
1343 case SR_SYSTEM: return (sRefSet_modifyMember (sl, s));
1344 case SR_GLOBALMARKER: BADBRANCH;
1348 case SK_RESULT: BADBRANCH;
1354 ** this should probably be elsewhere...
1356 ** returns TRUE iff sl indicates that s can be modified
1360 bool sRef_doModify (sRef s, sRefSet sl)
1362 llassert (sRef_isValid (s));
1366 case SK_UNCONSTRAINED:
1370 if (sRef_isFileOrGlobalScope (s))
1372 if (context_checkGlobMod (s))
1374 return (sRefSet_modifyMember (sl, s));
1378 (void) sRefSet_modifyMember (sl, s);
1390 return (OR (sRefSet_modifyMember (sl, s),
1391 sRef_doModifyVal (s->info->arrayfetch->arr, sl)));
1394 sRef sr = s->info->field->rec;
1396 if (sr->kind == SK_PARAM)
1398 return TRUE; /* structs are shallow-copied on call */
1401 return (OR (sRefSet_modifyMember (sl, s),
1402 sRef_doModifyVal (s->info->field->rec, sl)));
1406 return (OR (sRefSet_modifyMember (sl, s),
1407 sRef_doModifyVal (s->info->ref, sl)));
1410 return (OR (sRefSet_modifyMember (sl, s),
1411 sRef_doModifyVal (s->info->ref, sl)));
1413 return (AND (sRef_doModify (s->info->conj->a, sl),
1414 (sRef_doModify (s->info->conj->b, sl))));
1425 switch (s->info->spec)
1427 case SR_NOTHING: return TRUE;
1428 case SR_INTERNAL: return TRUE;
1429 case SR_SPECSTATE: return TRUE;
1430 case SR_SYSTEM: return (sRefSet_modifyMember (sl, s));
1431 case SR_GLOBALMARKER: BADBRANCH;
1434 case SK_RESULT: BADBRANCH;
1439 static /*@exposed@*/ sRef
1440 sRef_leastCommon (/*@exposed@*/ sRef s1, sRef s2)
1442 llassert (sRef_similar (s1, s2));
1444 if (!sRef_isValid (s1)) return s1;
1445 if (!sRef_isValid (s2)) return s1;
1447 sRef_combineDefState (s1, s2);
1448 sRef_combineNullState (s1, s2);
1449 sRef_combineExKinds (s1, s2);
1451 if (s1->aliaskind != s2->aliaskind)
1453 if (s1->aliaskind == AK_UNKNOWN)
1455 s1->aliaskind = s2->aliaskind;
1457 else if (s2->aliaskind == AK_UNKNOWN)
1463 s1->aliaskind = AK_ERROR;
1470 int sRef_compare (sRef s1, sRef s2)
1472 if (s1 == s2) return 0;
1474 if (sRef_isInvalid (s1)) return -1;
1475 if (sRef_isInvalid (s2)) return 1;
1477 INTCOMPARERETURN (s1->kind, s2->kind);
1478 INTCOMPARERETURN (s1->defstate, s2->defstate);
1479 INTCOMPARERETURN (s1->aliaskind, s2->aliaskind);
1481 DPRINTF (("Compare null state: %s / %s",
1482 sRef_unparseFull (s1),
1483 sRef_unparseFull (s2)));
1485 COMPARERETURN (nstate_compare (sRef_getNullState (s1),
1486 sRef_getNullState (s2)));
1491 return (int_compare (s1->info->paramno, s2->info->paramno));
1494 COMPARERETURN (sRef_compare (s1->info->arrayfetch->arr,
1495 s2->info->arrayfetch->arr));
1497 if (s1->info->arrayfetch->indknown && s2->info->arrayfetch->indknown)
1499 return (int_compare (s1->info->arrayfetch->ind,
1500 s2->info->arrayfetch->ind));
1502 if (!s1->info->arrayfetch->indknown && !s2->info->arrayfetch->indknown)
1509 COMPARERETURN (sRef_compare (s1->info->field->rec, s2->info->field->rec));
1511 if (cstring_equal (s1->info->field->field, s2->info->field->field))
1518 return (sRef_compare (s1->info->ref, s2->info->ref));
1520 COMPARERETURN (sRef_compare (s1->info->conj->a, s2->info->conj->a));
1521 return (sRef_compare (s1->info->conj->b, s2->info->conj->b));
1522 case SK_UNCONSTRAINED:
1523 return (cstring_compare (s1->info->fname, s2->info->fname));
1535 return (generic_compare (s1->info->spec, s2->info->spec));
1540 static bool cref_equal (cref c1, cref c2)
1542 return ((c1->lexlevel == c2->lexlevel) &&
1543 (usymId_equal (c1->index, c2->index)));
1547 ** returns true if s1 could be the same storage as s2.
1548 ** i.e., a[?] ~ a[3]. Note its not symmetric ... s1
1549 ** should be more specific.
1553 ** like similar, but matches objects <-> non-objects
1557 sRef_uniqueReference (sRef s)
1559 return (sRef_isFresh (s) || sRef_isUnique (s)
1560 || sRef_isOnly (s) || sRef_isStack (s)
1561 || sRef_isAddress (s));
1565 sRef_similarRelaxedAux (sRef s1, sRef s2)
1569 if (sRef_isUnknownArrayFetch (s1))
1579 if (sRef_isInvalid (s1) || sRef_isInvalid (s2)) return FALSE;
1581 if (sRef_isConj (s2))
1582 return (sRef_similarRelaxedAux (s1, sRef_getConjA (s2)) ||
1583 sRef_similarRelaxedAux (s1, sRef_getConjB (s2)));
1588 return ((s2->kind == SK_CVAR)
1589 && (cref_equal (s1->info->cvar, s2->info->cvar)));
1591 return ((s2->kind == SK_PARAM)
1592 && (s1->info->paramno == s2->info->paramno));
1594 if (s2->kind == SK_ARRAYFETCH)
1596 if (sRef_similarRelaxedAux (s1->info->arrayfetch->arr,
1597 s2->info->arrayfetch->arr))
1599 if (s1->info->arrayfetch->indknown)
1601 if (s2->info->arrayfetch->indknown)
1603 return (s1->info->arrayfetch->ind == s2->info->arrayfetch->ind);
1618 return ((s2->kind == SK_FIELD
1619 && (sRef_similarRelaxedAux (s1->info->field->rec,
1620 s2->info->field->rec)
1621 && cstring_equal (s1->info->field->field,
1622 s2->info->field->field))));
1624 return ((s2->kind == SK_PTR)
1625 && sRef_similarRelaxedAux (s1->info->ref, s2->info->ref));
1627 return ((s2->kind == SK_ADR)
1628 && sRef_similarRelaxedAux (s1->info->ref, s2->info->ref));
1630 return ((sRef_similarRelaxedAux (s1->info->conj->a, s2) ||
1631 (sRef_similarRelaxedAux (s1->info->conj->b, s2))));
1633 return (s1->info->spec == s2->info->spec);
1634 case SK_UNCONSTRAINED:
1635 return (cstring_equal (s1->info->fname, s2->info->fname));
1650 sRef_similarRelaxed (sRef s1, sRef s2)
1656 if (sRef_isThroughArrayFetch (s1))
1666 if (sRef_isInvalid (s1) || sRef_isInvalid (s2)) return FALSE;
1668 us1 = sRef_uniqueReference (s1);
1669 us2 = sRef_uniqueReference (s2);
1671 if ((s1->kind == SK_EXTERNAL && (s2->kind != SK_EXTERNAL && !us2))
1672 || (s2->kind == SK_EXTERNAL && (s1->kind != SK_EXTERNAL && !us1)))
1675 ** Previously, also:
1676 ** || (sRef_isExposed (s1) && !us2) || (sRef_isExposed (s2) && !us1)) ????
1678 ** No clue why this was there?!
1682 if (sRef_isExposed (s1) && sRef_isCvar (s1))
1684 uentry ue1 = sRef_getUentry (s1);
1686 if (uentry_isRefParam (ue1))
1688 return sRef_similarRelaxedAux (s1, s2);
1692 if (sRef_isExposed (s2) && sRef_isCvar (s2))
1694 uentry ue2 = sRef_getUentry (s2);
1696 if (uentry_isRefParam (ue2))
1698 return sRef_similarRelaxedAux (s1, s2);
1702 return (ctype_match (s1->type, s2->type));
1706 return sRef_similarRelaxedAux (s1, s2);
1711 sRef_similar (sRef s1, sRef s2)
1713 if (s1 == s2) return TRUE;
1714 if (sRef_isInvalid (s1) || sRef_isInvalid (s2)) return FALSE;
1716 if (sRef_isConj (s2))
1718 return (sRef_similar (s1, sRef_getConjA (s2)) ||
1719 sRef_similar (s1, sRef_getConjB (s2)));
1722 if (sRef_isDerived (s2))
1724 return (sRef_includedBy (s1, s2->info->ref));
1730 return ((s2->kind == SK_CVAR)
1731 && (cref_equal (s1->info->cvar, s2->info->cvar)));
1733 return ((s2->kind == SK_PARAM)
1734 && (s1->info->paramno == s2->info->paramno));
1736 if (s2->kind == SK_ARRAYFETCH)
1738 if (sRef_similar (s1->info->arrayfetch->arr,
1739 s2->info->arrayfetch->arr))
1741 if (s1->info->arrayfetch->indknown)
1743 if (s2->info->arrayfetch->indknown)
1745 return (s1->info->arrayfetch->ind == s2->info->arrayfetch->ind);
1760 if (s2->kind == SK_PTR)
1762 if (sRef_similar (s1->info->arrayfetch->arr,
1772 return ((s2->kind == SK_FIELD
1773 && (sRef_similar (s1->info->field->rec,
1774 s2->info->field->rec)
1775 && cstring_equal (s1->info->field->field,
1776 s2->info->field->field))));
1778 if (s2->kind == SK_PTR)
1780 return sRef_similar (s1->info->ref, s2->info->ref);
1784 if (s2->kind == SK_ARRAYFETCH)
1786 if (sRef_similar (s2->info->arrayfetch->arr,
1796 return ((s2->kind == SK_ADR)
1797 && sRef_similar (s1->info->ref, s2->info->ref));
1799 return ((sRef_similar (s1->info->conj->a, s2) ||
1800 (sRef_similar (s1->info->conj->b, s2))));
1802 return (sRef_includedBy (s2, s1->info->ref));
1803 case SK_UNCONSTRAINED:
1804 return (s2->kind == SK_UNCONSTRAINED
1805 && cstring_equal (s1->info->fname, s2->info->fname));
1815 return (s2->kind == SK_SPECIAL
1816 && (s1->info->spec == s2->info->spec));
1819 /*@notreached@*/ DPRINTF (("Fell through for: %s / %s", sRef_unparse (s1), sRef_unparse (s2)));
1824 ** return TRUE iff small can be derived from big.
1826 ** (e.g. x, x.a is includedBy x;
1827 ** x.a is included By x.a;
1831 sRef_includedBy (sRef small, sRef big)
1833 if (small == big) return TRUE;
1834 if (sRef_isInvalid (small) || sRef_isInvalid (big)) return FALSE;
1836 if (sRef_isConj (big))
1837 return (sRef_similar (small, sRef_getConjA (big)) ||
1838 sRef_similar (small, sRef_getConjB (big)));
1840 switch (small->kind)
1844 return (sRef_same (small, big));
1846 if (big->kind == SK_ARRAYFETCH)
1848 if (sRef_same (small->info->arrayfetch->arr, big->info->arrayfetch->arr))
1850 if (small->info->arrayfetch->indknown)
1852 if (big->info->arrayfetch->indknown)
1854 return (small->info->arrayfetch->ind == big->info->arrayfetch->ind);
1867 return (sRef_includedBy (small->info->arrayfetch->arr, big));
1869 if (big->kind == SK_FIELD)
1872 (sRef_same (small->info->field->rec, big->info->field->rec) &&
1873 cstring_equal (small->info->field->field, big->info->field->field));
1877 return (sRef_includedBy (small->info->field->rec, big));
1881 if (big->kind == SK_PTR)
1883 return sRef_same (small->info->ref, big->info->ref);
1887 return (sRef_includedBy (small->info->ref, big));
1891 return ((big->kind == SK_ADR) && sRef_similar (small->info->ref, big->info->ref));
1893 return ((sRef_includedBy (small->info->conj->a, big) ||
1894 (sRef_includedBy (small->info->conj->b, big))));
1896 return (sRef_includedBy (small->info->ref, big));
1897 case SK_UNCONSTRAINED:
1907 switch (small->info->spec)
1909 case SR_NOTHING: return TRUE;
1911 case SR_INTERNAL: return (sRef_isSpecInternalState (big) ||
1912 sRef_isFileStatic (big));
1913 case SR_SYSTEM: return (sRef_isSystemState (big));
1914 case SR_GLOBALMARKER: BADBRANCH;
1921 ** Same is similar to similar, but not quite the same.
1922 ** same and realSame aren't the same, but they are really similar.
1923 ** similarly, same is the same as same. but realSame is
1924 ** not really the same as same, or similar to similar.
1926 ** Similarly to similar, same checks if two sRefs are the same.
1927 ** The similarities end, however, when same compares arrays
1928 ** with unknown indexes. Similar returns false; same returns true.
1930 ** Similarly to similar and same, realSame is the same as same,
1931 ** except they do not behave the same when face with unknown
1932 ** sRefs. Same thinks they are not the same, but realSame thinks
1938 sRef_realSame (sRef s1, sRef s2)
1940 if (s1 == s2) return TRUE;
1941 if (sRef_isInvalid (s1) || sRef_isInvalid (s2)) return FALSE;
1946 return ((s2->kind == SK_CVAR) && (cref_equal (s1->info->cvar, s2->info->cvar)));
1948 return ((s2->kind == SK_PARAM) && (s1->info->paramno == s2->info->paramno));
1950 if (s2->kind == SK_ARRAYFETCH)
1952 if (sRef_realSame (s1->info->arrayfetch->arr, s2->info->arrayfetch->arr))
1954 if (s1->info->arrayfetch->indknown && s2->info->arrayfetch->indknown)
1956 return (s1->info->arrayfetch->ind == s2->info->arrayfetch->ind);
1958 if (!s1->info->arrayfetch->indknown && !s2->info->arrayfetch->indknown)
1967 return ((s2->kind == SK_FIELD &&
1968 (sRef_realSame (s1->info->field->rec, s2->info->field->rec) &&
1969 cstring_equal (s1->info->field->field, s2->info->field->field))));
1971 return ((s2->kind == SK_PTR) && sRef_realSame (s1->info->ref, s2->info->ref));
1973 return ((s2->kind == SK_ADR) && sRef_realSame (s1->info->ref, s2->info->ref));
1975 return ((sRef_realSame (s1->info->conj->a, s2) ||
1976 (sRef_realSame (s1->info->conj->b, s2))));
1978 return ((s2->kind == SK_OBJECT)
1979 && ctype_match (s1->info->object, s2->info->object));
1981 return ((s2->kind == SK_EXTERNAL)
1982 && sRef_realSame (s1->info->ref, s2->info->ref));
1984 return ((s2->kind == SK_SPECIAL) && s1->info->spec == s2->info->spec);
1986 return ((s2->kind == SK_DERIVED) && sRef_realSame (s1->info->ref, s2->info->ref));
1987 case SK_UNCONSTRAINED:
1988 return ((s2->kind == SK_UNCONSTRAINED)
1989 && (cstring_equal (s1->info->fname, s2->info->fname)));
1995 return TRUE; /* changed this! was false */
2001 sRef_sameObject (sRef s1, sRef s2)
2007 ** same is similar to similar, but not quite the same.
2009 ** Similarly to similar, same checks is two sRefs are the same.
2010 ** The similarities end, however, when same compares arrays
2011 ** with unknown indexes. Similar returns false; same returns true.
2015 sRef_same (sRef s1, sRef s2)
2017 if (s1 == s2) return TRUE;
2018 if (sRef_isInvalid (s1) || sRef_isInvalid (s2)) return FALSE;
2023 return ((s2->kind == SK_CVAR) && (cref_equal (s1->info->cvar, s2->info->cvar)));
2025 return ((s2->kind == SK_PARAM) && (s1->info->paramno == s2->info->paramno));
2027 if (s2->kind == SK_ARRAYFETCH)
2029 llassert (s1->info->field->rec != s1);
2030 if (sRef_same (s1->info->arrayfetch->arr, s2->info->arrayfetch->arr))
2032 if (s1->info->arrayfetch->indknown && s2->info->arrayfetch->indknown)
2034 return (s1->info->arrayfetch->ind == s2->info->arrayfetch->ind);
2042 llassert (s1->info->field->rec != s1);
2043 return ((s2->kind == SK_FIELD &&
2044 (sRef_same (s1->info->field->rec, s2->info->field->rec) &&
2045 cstring_equal (s1->info->field->field, s2->info->field->field))));
2049 llassert (s1->info->ref != s1);
2050 return ((s2->kind == SK_PTR) && sRef_same (s1->info->ref, s2->info->ref));
2054 llassert (s1->info->ref != s1);
2055 return ((s2->kind == SK_ADR) && sRef_same (s1->info->ref, s2->info->ref));
2058 llassert (s1->info->conj->a != s1);
2059 llassert (s1->info->conj->b != s1);
2060 return ((sRef_same (s1->info->conj->a, s2)) && /* or or and? */
2061 (sRef_same (s1->info->conj->b, s2)));
2063 return ((s2->kind == SK_SPECIAL) && s1->info->spec == s2->info->spec);
2065 llassert (s1->info->ref != s1);
2066 return ((s2->kind == SK_DERIVED) && sRef_same (s1->info->ref, s2->info->ref));
2068 case SK_UNCONSTRAINED:
2081 ** sort of similar, for use in def/use
2085 sRef_closeEnough (sRef s1, sRef s2)
2087 if (s1 == s2) return TRUE;
2088 if (sRef_isInvalid (s1) || sRef_isInvalid (s2)) return FALSE;
2093 return (((s2->kind == SK_CVAR) &&
2094 (cref_equal (s1->info->cvar, s2->info->cvar))) ||
2095 (s2->kind == SK_UNCONSTRAINED && s1->info->cvar->lexlevel == 0));
2096 case SK_UNCONSTRAINED:
2097 return (s2->kind == SK_UNCONSTRAINED
2098 || ((s2->kind == SK_CVAR) && (s2->info->cvar->lexlevel == 0)));
2100 return ((s2->kind == SK_PARAM)
2101 && (s1->info->paramno == s2->info->paramno));
2103 if (s2->kind == SK_ARRAYFETCH)
2105 if (sRef_closeEnough (s1->info->arrayfetch->arr, s2->info->arrayfetch->arr))
2107 if (s1->info->arrayfetch->indknown && s2->info->arrayfetch->indknown)
2109 return (s1->info->arrayfetch->ind == s2->info->arrayfetch->ind);
2116 return ((s2->kind == SK_FIELD &&
2117 (sRef_closeEnough (s1->info->field->rec, s2->info->field->rec) &&
2118 cstring_equal (s1->info->field->field, s2->info->field->field))));
2120 return ((s2->kind == SK_PTR) && sRef_closeEnough (s1->info->ref, s2->info->ref));
2122 return ((s2->kind == SK_ADR) && sRef_closeEnough (s1->info->ref, s2->info->ref));
2124 return ((s2->kind == SK_DERIVED) && sRef_closeEnough (s1->info->ref, s2->info->ref));
2126 return ((sRef_closeEnough (s1->info->conj->a, s2)) ||
2127 (sRef_closeEnough (s1->info->conj->b, s2)));
2129 return ((s2->kind == SK_SPECIAL) && s1->info->spec == s2->info->spec);
2145 s is an sRef of a formal paramenter in a function call constraint
2146 we trys to return a constraint expression derived from the actual parementer of a function call.
2148 /*@only@*/ constraintExpr sRef_fixConstraintParam (/*@observer@*/ sRef s, /*@observer@*/ /*@temp@*/ exprNodeList args)
2152 if (sRef_isInvalid (s))
2153 llfatalbug((message("Invalid sRef")));
2159 // s = sRef_saveCopy(s);
2160 ce = constraintExpr_makeTermsRef (s);
2167 temp = (sRef_makeField (sRef_fixBaseParam (s->info->field->rec, args),
2168 s->info->field->field));
2169 ce = constraintExpr_makeTermsRef (temp);
2175 temp = (sRef_makePointer (sRef_fixBaseParam (s->info->ref, args)));
2176 //temp = sRef_saveCopy(temp);
2177 ce = constraintExpr_makeTermsRef (temp);
2184 temp = sRef_saveCopy(s);
2185 temp = sRef_fixBaseParam (temp, args);
2186 ce = constraintExpr_makeTermsRef (temp);
2194 temp = sRef_saveCopy(s);
2195 ce = constraintExpr_makeTermsRef (temp);
2200 llassert(exprNodeList_size (args) > s->info->paramno);
2202 exprNode e = exprNodeList_nth (args, s->info->paramno);
2204 llassert( !(exprNode_isError (e)) );
2205 ce = constraintExpr_makeExprNode (e);
2212 llcontbug ((message("Trying to do fixConstraintParam on nonparam, nonglobal: %q for function with arguments %q", sRef_unparse (s), exprNodeList_unparse(args) ) ));
2213 temp = sRef_saveCopy(s);
2214 ce = constraintExpr_makeTermsRef (temp);
2226 sRef_fixBaseParam (/*@returned@*/ sRef s, exprNodeList args)
2228 if (sRef_isInvalid (s)) return (sRef_undefined);
2232 case SK_UNCONSTRAINED:
2237 if (exprNodeList_size (args) > s->info->paramno)
2239 exprNode e = exprNodeList_nth (args, s->info->paramno);
2241 if (exprNode_isError (e))
2243 return sRef_makeUnknown ();
2246 return (exprNode_getSref (e));
2250 return sRef_makeUnknown ();
2255 if (s->info->arrayfetch->indknown)
2257 return (sRef_makeArrayFetchKnown
2258 (sRef_fixBaseParam (s->info->arrayfetch->arr, args),
2259 s->info->arrayfetch->ind));
2263 return (sRef_makeArrayFetch
2264 (sRef_fixBaseParam (s->info->arrayfetch->arr, args)));
2267 return (sRef_makeField (sRef_fixBaseParam (s->info->field->rec, args),
2268 s->info->field->field));
2271 return (sRef_makePointer (sRef_fixBaseParam (s->info->ref, args)));
2274 return (sRef_makeAddress (sRef_fixBaseParam (s->info->ref, args)));
2277 return (sRef_makeConj (sRef_fixBaseParam (s->info->conj->a, args),
2278 sRef_fixBaseParam (s->info->conj->b, args)));
2294 sRef_undumpGlobal (char **c)
2304 usymId uid = usymId_fromInt (reader_getInt (c));
2309 reader_checkChar (c, '@');
2310 defstate = sstate_fromInt (reader_getInt (c));
2312 reader_checkChar (c, '@');
2313 nullstate = nstate_fromInt (reader_getInt (c));
2315 ret = sRef_makeGlobal (uid, ctype_unknown);
2316 sRef_setNullStateN (ret, nullstate);
2317 ret->defstate = defstate;
2322 int i = reader_getInt (c);
2323 speckind sk = speckind_fromInt (i);
2327 case SR_NOTHING: return (sRef_makeNothing ());
2328 case SR_INTERNAL: return (sRef_makeInternalState ());
2329 case SR_SPECSTATE: return (sRef_makeSpecState ());
2330 case SR_SYSTEM: return (sRef_makeSystemState ());
2331 case SR_GLOBALMARKER: BADBRANCH;
2336 return sRef_undefined;
2338 return sRef_makeUnknown ();
2340 return sRef_makeUnknown ();
2342 llfatalerror (message ("sRef_undumpGlobal: bad line: %s",
2343 cstring_fromChars (*c)));
2349 sRef_undump (char **c)
2358 return (sRef_makeGlobal (usymId_fromInt (reader_getInt (c)), ctype_unknown));
2360 return (sRef_makeParam (reader_getInt (c), ctype_unknown));
2362 return (sRef_makeResultType (ctype_undump (c)));
2365 if ((**c >= '0' && **c <= '9') || **c == '-')
2367 int i = reader_getInt (c);
2368 sRef arr = sRef_undump (c);
2369 sRef ret = sRef_buildArrayFetchKnown (arr, i);
2375 sRef arr = sRef_undump (c);
2376 sRef ret = sRef_buildArrayFetch (arr);
2383 cstring fname = cstring_undefined;
2388 fname = cstring_appendChar (fname, **c);
2393 ret = sRef_buildField (sRef_undump (c), fname);
2394 cstring_markOwned (fname);
2399 int i = reader_getInt (c);
2400 speckind sk = speckind_fromInt (i);
2404 case SR_NOTHING: return (sRef_makeNothing ());
2405 case SR_INTERNAL: return (sRef_makeInternalState ());
2406 case SR_SPECSTATE: return (sRef_makeSpecState ());
2407 case SR_SYSTEM: return (sRef_makeSystemState ());
2408 case SR_GLOBALMARKER: BADBRANCH;
2414 sRef ptr = sRef_undump (c);
2415 sRef ret = sRef_makePointer (ptr);
2421 sRef adr = sRef_undump (c);
2422 sRef ret = sRef_makeAddress (adr);
2428 return (sRef_makeObject (ctype_undump (c)));
2432 sRef s1 = sRef_undump (c);
2433 sRef s2 = ((*c)++, sRef_undump (c));
2434 sRef ret = sRef_makeConj (s1, s2);
2439 return sRef_undefined;
2441 return sRef_makeUnknown ();
2443 return sRef_makeUnknown ();
2445 llfatalerror (message ("sRef_undump: bad line: %s", cstring_fromChars (*c)));
2453 if (sRef_isInvalid (s))
2455 return (cstring_makeLiteral ("-"));
2462 return (message ("p%d", s->info->paramno));
2464 if (s->info->arrayfetch->indknown)
2466 return (message ("a%d%q", s->info->arrayfetch->ind,
2467 sRef_dump (s->info->arrayfetch->arr)));
2471 return (message ("a%q", sRef_dump (s->info->arrayfetch->arr)));
2474 return (message ("f%s.%q", s->info->field->field,
2475 sRef_dump (s->info->field->rec)));
2477 return (message ("t%q", sRef_dump (s->info->ref)));
2479 return (message ("d%q", sRef_dump (s->info->ref)));
2481 return (message ("o%q", ctype_dump (s->info->object)));
2483 return (message ("s%d", (int) s->info->spec));
2485 return (message ("c%q.%q",
2486 sRef_dump (s->info->conj->a),
2487 sRef_dump (s->info->conj->b)));
2489 if (sRef_isFileOrGlobalScope (s))
2491 return (message ("g%d",
2492 usymtab_convertId (s->info->cvar->index)));
2496 llcontbug (message ("Dumping local variable: %q",
2497 sRef_unparseDebug (s)));
2498 return (cstring_makeLiteral ("u"));
2501 return (cstring_makeLiteral ("u"));
2503 return (message ("r%q", ctype_dump (s->type)));
2509 case SK_UNCONSTRAINED:
2510 llcontbug (message ("sRef_dump: bad kind: %q",
2511 sRef_unparseFull (s)));
2512 return (cstring_makeLiteral ("x"));
2519 cstring sRef_dumpGlobal (sRef s)
2521 if (sRef_isInvalid (s))
2523 return (cstring_makeLiteral ("-"));
2530 if (sRef_isFileOrGlobalScope (s))
2532 return (message ("g%d@%d@%d",
2533 usymtab_convertId (s->info->cvar->index),
2535 (int) sRef_getNullState (s)));
2539 llcontbug (message ("Dumping local variable: %q",
2540 sRef_unparseDebug (s)));
2541 return (cstring_makeLiteral ("u"));
2544 return (cstring_makeLiteral ("u"));
2546 return (message ("s%d", (int) s->info->spec));
2548 llcontbug (message ("sRef_dumpGlobal: bad kind: %q",
2549 sRef_unparseFull (s)));
2550 return (cstring_makeLiteral ("x"));
2558 sRef_deriveType (sRef s, uentryList cl)
2560 if (sRef_isInvalid (s)) return ctype_unknown;
2565 return (uentry_getType (usymtab_getRefQuiet (s->info->cvar->lexlevel,
2566 s->info->cvar->index)));
2567 case SK_UNCONSTRAINED:
2568 return (ctype_unknown);
2570 if (s->info->paramno >= 0)
2572 return uentry_getType (uentryList_getN (cl, s->info->paramno));
2576 return ctype_unknown;
2580 ctype ca = sRef_deriveType (s->info->arrayfetch->arr, cl);
2582 if (ctype_isArray (ca))
2584 return (ctype_baseArrayPtr (ca));
2586 else if (ctype_isUnknown (ca))
2592 llcontbuglit ("sRef_deriveType: inconsistent array type");
2598 ctype ct = sRef_deriveType (s->info->field->rec, cl);
2600 if (ctype_isStructorUnion (ct))
2602 uentry ue = uentryList_lookupField (ctype_getFields (ct),
2603 s->info->field->field);
2605 if (uentry_isValid (ue))
2607 return (uentry_getType (ue));
2611 llcontbuglit ("sRef_deriveType: bad field");
2612 return ctype_unknown;
2615 else if (ctype_isUnknown (ct))
2621 llcontbuglit ("sRef_deriveType: inconsistent field type");
2627 ctype ct = sRef_deriveType (s->info->ref, cl);
2629 if (ctype_isUnknown (ct)) return ct;
2630 if (ctype_isPointer (ct)) return (ctype_baseArrayPtr (ct));
2633 llcontbuglit ("sRef_deriveType: inconsistent pointer type");
2639 ctype ct = sRef_deriveType (s->info->ref, cl);
2641 if (ctype_isUnknown (ct)) return ct;
2642 return ctype_makePointer (ct);
2646 return sRef_deriveType (s->info->ref, cl);
2650 return (s->info->object);
2654 return (ctype_makeConj (sRef_deriveType (s->info->conj->a, cl),
2655 sRef_deriveType (s->info->conj->b, cl)));
2667 return ctype_unknown;
2673 sRef_getType (sRef s)
2675 if (sRef_isInvalid (s)) return ctype_unknown;
2681 sRef_unparseOpt (sRef s)
2683 sRef rb = sRef_getRootBase (s);
2685 if (sRef_isMeaningful (rb) && !sRef_isConst (rb))
2687 cstring ret = sRef_unparse (s);
2689 llassertprint (!cstring_equalLit (ret, "?"), ("print: %s", sRef_unparseDebug (s)));
2691 if (!cstring_isEmpty (ret))
2693 return (cstring_appendChar (ret, ' '));
2701 return cstring_undefined;
2705 sRef_unparsePreOpt (sRef s)
2707 sRef rb = sRef_getRootBase (s);
2709 if (sRef_isMeaningful (rb) && !sRef_isConst (rb))
2711 cstring ret = sRef_unparse (s);
2713 llassertprint (!cstring_equalLit (ret, "?"), ("print: %s", sRef_unparseDebug (s)));
2714 return (cstring_prependCharO (' ', ret));
2717 return cstring_undefined;
2721 sRef_unparse (sRef s)
2723 if (sRef_isInvalid (s)) return (cstring_makeLiteral ("?"));
2725 if (context_inFunctionLike ())
2727 return (sRef_unparseWithArgs (s, context_getParams ()));
2731 DPRINTF (("Not in function like: %s", context_unparse ()));
2732 return (sRef_unparseNoArgs (s));
2736 static /*@only@*/ cstring
2737 sRef_unparseWithArgs (sRef s, uentryList args)
2739 if (sRef_isInvalid (s))
2741 return (cstring_makeLiteral ("?"));
2747 return (uentry_getName (usymtab_getRefQuiet (s->info->cvar->lexlevel,
2748 s->info->cvar->index)));
2749 case SK_UNCONSTRAINED:
2750 return (cstring_copy (s->info->fname));
2753 if (s->info->paramno < uentryList_size (args)
2754 && s->info->paramno >= 0)
2756 uentry ue = uentryList_getN (args, s->info->paramno);
2758 if (uentry_isValid (ue))
2759 return uentry_getName (ue);
2762 return (message ("<bad param: %q / args %q",
2763 sRef_unparseDebug (s),
2764 uentryList_unparse (args)));
2767 if (s->info->arrayfetch->indknown)
2769 return (message ("%q[%d]", sRef_unparseWithArgs (s->info->arrayfetch->arr, args),
2770 s->info->arrayfetch->ind));
2774 return (message ("%q[]", sRef_unparseWithArgs (s->info->arrayfetch->arr, args)));
2777 if (s->info->field->rec->kind == SK_PTR)
2779 sRef ptr = s->info->field->rec;
2781 return (message ("%q->%s", sRef_unparseWithArgs (ptr->info->ref, args),
2782 s->info->field->field));
2784 return (message ("%q.%s", sRef_unparseWithArgs (s->info->field->rec, args),
2785 s->info->field->field));
2789 sRef ref = sRef_fixConj (s->info->ref);
2790 skind sk = ref->kind;
2795 ret = message ("storage pointed to by %q",
2796 sRef_unparseWithArgs (ref, args));
2798 else if (skind_isSimple (sk) || sk == SK_PTR)
2800 ret = message ("*%q", sRef_unparseWithArgs (ref, args));
2804 ret = message ("*(%q)", sRef_unparseWithArgs (ref, args));
2810 return (message ("&%q", sRef_unparseWithArgs (s->info->ref, args)));
2812 return (cstring_copy (ctype_unparse (s->info->object)));
2814 return (sRef_unparseWithArgs (sRef_getConjA (s), args));
2816 if (cstring_isDefined (s->info->fname))
2818 return (message ("[result of %s]", s->info->fname));
2822 return (cstring_makeLiteral ("<new>"));
2825 return (cstring_makeLiteral ("?"));
2827 return (message ("<derived %q>", sRef_unparse (s->info->ref)));
2829 return (message ("<external %q>", sRef_unparse (s->info->ref)));
2831 return (message ("<type %s>", ctype_unparse (s->type)));
2833 return (message ("<const %s>", ctype_unparse (s->type)));
2835 switch (s->info->spec)
2837 case SR_NOTHING: return cstring_makeLiteral ("nothing");
2838 case SR_INTERNAL: return cstring_makeLiteral ("internal state");
2839 case SR_SPECSTATE: return cstring_makeLiteral ("spec state");
2840 case SR_SYSTEM: return cstring_makeLiteral ("file system state");
2841 case SR_GLOBALMARKER: return cstring_makeLiteral ("<global marker>");
2845 return cstring_makeLiteral ("result");
2848 llbug (message ("Bad sref, kind = %d", (int) s->kind));
2856 sRef_unparseDebug (sRef s)
2858 if (sRef_isInvalid (s))
2860 return (cstring_makeLiteral ("<undef>"));
2866 case SK_UNCONSTRAINED:
2867 return (message ("<unconstrained %s>", s->info->fname));
2872 ce = usymtab_getRefQuiet (s->info->cvar->lexlevel, s->info->cvar->index);
2874 if (uentry_isInvalid (ce))
2876 return (message ("<scope: %d.%d *invalid*>",
2877 s->info->cvar->lexlevel,
2878 s->info->cvar->index));
2882 return (message ("<scope: %d.%d *%q*>",
2883 s->info->cvar->lexlevel,
2884 s->info->cvar->index,
2885 uentry_getName (ce)));
2891 return (message ("<parameter %d>", s->info->paramno + 1));
2894 if (s->info->arrayfetch->indknown)
2896 return (message ("%q[%d]", sRef_unparseDebug (s->info->arrayfetch->arr),
2897 s->info->arrayfetch->ind));
2901 return (message ("%q[]", sRef_unparseDebug (s->info->arrayfetch->arr)));
2904 return (message ("%q.%s", sRef_unparseDebug (s->info->field->rec),
2905 s->info->field->field));
2907 if (sRef_isField (s->info->ref))
2909 sRef fld = s->info->ref;
2911 return (message ("%q->%s", sRef_unparseDebug (fld->info->field->rec),
2912 fld->info->field->field));
2916 return (message ("*(%q)", sRef_unparseDebug (s->info->ref)));
2919 return (message ("&%q", sRef_unparseDebug (s->info->ref)));
2921 return (message ("<object type %s>", ctype_unparse (s->info->object)));
2923 return (message ("%q | %q", sRef_unparseDebug (s->info->conj->a),
2924 sRef_unparseDebug (s->info->conj->b)));
2926 return message ("<new: %s>", s->info->fname);
2928 return (message ("<derived %q>", sRef_unparseDebug (s->info->ref)));
2930 return (message ("<external %q>", sRef_unparseDebug (s->info->ref)));
2932 return (message ("<type %s>", ctype_unparse (s->type)));
2934 return (message ("<const %s>", ctype_unparse (s->type)));
2936 return (message ("<result %s>", ctype_unparse (s->type)));
2938 return (message ("<spec %s>",
2939 cstring_makeLiteralTemp
2940 (s->info->spec == SR_NOTHING ? "nothing"
2941 : s->info->spec == SR_INTERNAL ? "internalState"
2942 : s->info->spec == SR_SPECSTATE ? "spec state"
2943 : s->info->spec == SR_SYSTEM ? "fileSystem"
2946 return cstring_makeLiteral ("<unknown>");
2952 static /*@only@*/ cstring
2953 sRef_unparseNoArgs (sRef s)
2955 if (sRef_isInvalid (s)) return (cstring_makeLiteral ("?"));
2959 case SK_UNCONSTRAINED:
2960 return (cstring_copy (s->info->fname));
2963 uentry ce = usymtab_getRefQuiet (s->info->cvar->lexlevel,
2964 s->info->cvar->index);
2966 if (uentry_isInvalid (ce))
2968 llcontbug (message ("sRef_unparseNoArgs: bad cvar: %q",
2969 sRef_unparseDebug (s)));
2970 return (sRef_unparseDebug (s));
2974 return (uentry_getName (ce));
2978 if (s->info->arrayfetch->indknown)
2980 return (message ("%q[%d]", sRef_unparseNoArgs (s->info->arrayfetch->arr),
2981 s->info->arrayfetch->ind));
2985 return (message ("%q[]", sRef_unparseNoArgs (s->info->arrayfetch->arr)));
2988 return (message ("%q.%s", sRef_unparseNoArgs (s->info->field->rec),
2989 s->info->field->field));
2992 sRef ref = sRef_fixConj (s->info->ref);
2993 skind sk = ref->kind;
2996 if (skind_isSimple (sk) || sk == SK_PTR)
2998 ret = message ("*%q", sRef_unparseNoArgs (ref));
3002 ret = message ("*(%q)", sRef_unparseNoArgs (ref));
3008 return (message ("&%q", sRef_unparseNoArgs (s->info->ref)));
3010 return (cstring_copy (ctype_unparse (s->info->object)));
3012 return (sRef_unparseNoArgs (s->info->conj->a));
3014 return (message ("result of %s", s->info->fname));
3016 return (message ("<der %q>", sRef_unparseNoArgs (s->info->ref)));
3018 return message ("<ext %q>", sRef_unparseNoArgs (s->info->ref));
3020 return (cstring_makeLiteral
3021 (s->info->spec == SR_NOTHING ? "nothing"
3022 : s->info->spec == SR_INTERNAL ? "internal state"
3023 : s->info->spec == SR_SPECSTATE ? "spec state"
3024 : s->info->spec == SR_SYSTEM ? "file system state"
3027 return cstring_makeLiteral ("result");
3031 return cstring_makeLiteral ("?");
3033 /* llcontbug (message ("sRef_unparseNoArgs: bad case: %q", sRef_unparseDebug (s))); */
3034 return (sRef_unparseDebug (s));
3039 /*@dependent@*/ sRef sRef_makeUnconstrained (cstring fname)
3041 sRef s = sRef_new ();
3043 s->kind = SK_UNCONSTRAINED;
3044 s->info = (sinfo) dmalloc (sizeof (*s->info));
3045 s->info->fname = fname;
3050 cstring sRef_unconstrainedName (sRef s)
3052 llassert (sRef_isUnconstrained (s));
3054 return s->info->fname;
3057 bool sRef_isUnconstrained (sRef s)
3059 return (sRef_isValid(s) && s->kind == SK_UNCONSTRAINED);
3062 static /*@dependent@*/ /*@notnull@*/ sRef
3063 sRef_makeCvarAux (int level, usymId index, ctype ct)
3065 sRef s = sRef_newRef ();
3068 s->info = (sinfo) dmalloc (sizeof (*s->info));
3070 s->info->cvar = (cref) dmalloc (sizeof (*s->info->cvar));
3071 s->info->cvar->lexlevel = level;
3072 s->info->cvar->index = index;
3074 /* for now, all globals are defined; all locals, aren't */
3076 if (level <= fileScope)
3078 s->defstate = SS_UNKNOWN;
3082 ctype rct = ctype_realType (ct);
3084 if (level != paramsScope
3085 && (ctype_isStructorUnion (rct) || ctype_isRealArray (rct)))
3087 s->defstate = SS_ALLOCATED;
3088 s->oaliaskind = s->aliaskind = AK_STACK;
3092 s->defstate = SS_UNDEFINED;
3093 s->oaliaskind = s->aliaskind = AK_LOCAL;
3099 llassert (level >= globScope);
3100 llassert (usymId_isValid (index));
3102 DPRINTF (("Made cvar: [%p] %s", s, sRef_unparseDebug (s)));
3103 llassert (valueTable_isUndefined (s->state));
3104 s->state = context_createValueTable (s);
3108 /*@dependent@*/ sRef sRef_makeCvar (int level, usymId index, ctype ct)
3110 return (sRef_makeCvarAux (level, index, ct));
3113 int sRef_lexLevel (sRef s)
3115 if (sRef_isValid (s))
3119 conj = sRef_fixConj (s);
3120 s = sRef_getRootBase (conj);
3122 if (sRef_isValid (s) && s->kind == SK_CVAR)
3124 return (s->info->cvar->lexlevel);
3132 sRef_makeGlobal (usymId l, ctype ct)
3134 return (sRef_makeCvar (globScope, l, ct));
3138 sRef_setParamNo (sRef s, int l)
3140 llassert (sRef_isValid (s) && s->kind == SK_PARAM);
3141 s->info->paramno = l;
3145 /*@dependent@*/ sRef
3146 sRef_makeParam (int l, ctype ct)
3148 sRef s = sRef_new ();
3153 s->info = (sinfo) dmalloc (sizeof (*s->info));
3154 s->info->paramno = l;
3156 s->defstate = SS_UNKNOWN;
3157 /* (probably defined, unless its an out parameter) */
3159 llassert (valueTable_isUndefined (s->state));
3160 s->state = context_createValueTable (s);
3165 sRef_isIndexKnown (sRef arr)
3169 llassert (sRef_isValid (arr));
3170 arr = sRef_fixConj (arr);
3172 llassert (arr->kind == SK_ARRAYFETCH);
3173 res = arr->info->arrayfetch->indknown;
3178 sRef_getIndex (sRef arr)
3182 llassert (sRef_isValid (arr));
3183 arr = sRef_fixConj (arr);
3185 llassert (arr->kind == SK_ARRAYFETCH);
3187 if (!arr->info->arrayfetch->indknown)
3189 llcontbug (message ("sRef_getIndex: unknown: %q", sRef_unparse (arr)));
3194 result = arr->info->arrayfetch->ind;
3200 static bool sRef_isZerothArrayFetch (/*@notnull@*/ sRef s)
3202 return (s->kind == SK_ARRAYFETCH
3203 && s->info->arrayfetch->indknown
3204 && (s->info->arrayfetch->ind == 0));
3207 /*@exposed@*/ sRef sRef_makeAddress (/*@exposed@*/ sRef t)
3210 if (sRef_isInvalid (t)) return sRef_undefined;
3212 if (sRef_isPointer (t))
3214 return (t->info->ref);
3216 else if (sRef_isZerothArrayFetch (t))
3218 return (t->info->arrayfetch->arr);
3222 sRef s = sRef_newRef ();
3225 s->type = ctype_makePointer (t->type);
3226 s->info = (sinfo) dmalloc (sizeof (*s->info));
3227 s->info->ref = t; /* sRef_copy (t); */ /*@i32@*/
3229 if (t->defstate == SS_UNDEFINED)
3230 /* no! it is allocated even still: && !ctype_isPointer (t->type)) */
3232 s->defstate = SS_ALLOCATED;
3236 s->defstate = t->defstate;
3239 if (t->aliaskind == AK_LOCAL)
3241 if (sRef_isLocalVar (t))
3243 s->aliaskind = AK_STACK;
3247 llassert (valueTable_isUndefined (s->state));
3248 s->state = context_createValueTable (s);
3253 cstring sRef_getField (sRef s)
3257 llassert (sRef_isValid (s));
3258 s = sRef_fixConj (s);
3260 llassertprint (sRef_isValid (s) && (s->kind == SK_FIELD),
3261 ("s = %s", sRef_unparseDebug (s)));
3263 res = s->info->field->field;
3267 sRef sRef_getBase (sRef s)
3271 if (sRef_isInvalid (s)) return (sRef_undefined);
3273 s = sRef_fixConj (s);
3284 res = s->info->field->rec;
3288 res = s->info->arrayfetch->arr;
3292 res = sRef_undefined; /* shouldn't need it */
3299 ** same as getBase, except returns invalid
3300 ** (and doesn't use adr's)
3304 sRef_getBaseSafe (sRef s)
3308 if (sRef_isInvalid (s)) { return sRef_undefined; }
3310 s = sRef_fixConj (s);
3318 res = s->info->field->rec; break;
3320 res = s->info->arrayfetch->arr;
3323 res = sRef_undefined; break;
3329 /*@constant int MAXBASEDEPTH;@*/
3330 # define MAXBASEDEPTH 25
3332 static /*@exposed@*/ sRef
3333 sRef_getRootBaseAux (sRef s, int depth)
3335 if (sRef_isInvalid (s)) return sRef_undefined;
3337 if (depth > MAXBASEDEPTH)
3340 ("Warning: reference base limit exceeded for %q. "
3341 "This either means there is a variable with at least "
3342 "%d indirections from this reference, or "
3343 "there is a bug in LCLint.",
3348 return sRef_undefined;
3355 return (sRef_getRootBaseAux (s->info->ref, depth + 1));
3357 return (sRef_getRootBaseAux (s->info->field->rec, depth + 1));
3359 return (sRef_getRootBaseAux (s->info->arrayfetch->arr, depth + 1));
3361 return (sRef_getRootBaseAux (sRef_fixConj (s), depth + 1));
3367 sRef sRef_getRootBase (sRef s)
3369 return (sRef_getRootBaseAux (s, 0));
3372 static bool sRef_isDeep (sRef s)
3374 if (sRef_isInvalid (s)) return FALSE;
3384 return (sRef_isDeep (sRef_fixConj (s)));
3390 static int sRef_depth (sRef s)
3392 if (sRef_isInvalid (s)) return 0;
3400 return 1 + sRef_depth (s->info->ref);
3402 return 1 + sRef_depth (s->info->field->rec);
3404 return 1 + sRef_depth (s->info->arrayfetch->arr);
3406 return (sRef_depth (sRef_fixConj (s)));
3413 sRef_makeObject (ctype o)
3415 sRef s = sRef_newRef (); /*@i423 same line is bad...@*/
3417 s->kind = SK_OBJECT;
3418 s->info = (sinfo) dmalloc (sizeof (*s->info));
3419 s->info->object = o;
3420 llassert (valueTable_isUndefined (s->state));
3421 s->state = context_createValueTable (s);
3426 ** This is used to represent storage referenced by a parameter.
3429 sRef sRef_makeExternal (sRef t)
3431 sRef s = sRef_newRef ();
3433 llassert (sRef_isValid (t));
3435 s->kind = SK_EXTERNAL;
3436 s->info = (sinfo) dmalloc (sizeof (*s->info));
3438 s->info->ref = t; /* sRef_copy (t); */ /*@i32 was exposed@*/
3439 llassert (valueTable_isUndefined (s->state));
3440 s->state = context_createValueTable (s);
3444 /*@dependent@*/ sRef sRef_makeDerived (/*@exposed@*/ sRef t)
3446 if (sRef_isValid (t))
3448 sRef s = sRef_newRef ();
3450 s->kind = SK_DERIVED;
3451 s->info = (sinfo) dmalloc (sizeof (*s->info));
3452 s->info->ref = t; /* sRef_copy (t); */ /*@i32@*/
3455 llassert (valueTable_isUndefined (s->state));
3456 s->state = context_createValueTable (s);
3461 return sRef_undefined;
3466 ** definitely NOT symmetric:
3468 ** res fills in unknown state information from other
3472 sRef_mergeStateQuiet (sRef res, sRef other)
3474 llassert (sRef_isValid (res));
3475 llassert (sRef_isValid (other));
3477 res->modified = res->modified || other->modified;
3478 res->safe = res->safe && other->safe;
3480 if (res->defstate == SS_UNKNOWN)
3482 res->defstate = other->defstate;
3483 res->definfo = stateInfo_update (res->definfo, other->definfo);
3486 if (res->aliaskind == AK_UNKNOWN ||
3487 (res->aliaskind == AK_LOCAL && alkind_isKnown (other->aliaskind)))
3489 res->aliaskind = other->aliaskind;
3490 res->oaliaskind = other->oaliaskind;
3491 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
3494 if (res->expkind == XO_UNKNOWN)
3496 res->expkind = other->expkind;
3497 res->oexpkind = other->oexpkind;
3498 res->expinfo = stateInfo_update (res->expinfo, other->expinfo);
3501 /* out takes precedence over implicitly defined */
3502 if (res->defstate == SS_DEFINED && other->defstate != SS_UNKNOWN)
3504 res->defstate = other->defstate;
3505 res->definfo = stateInfo_update (res->definfo, other->definfo);
3508 if (sRef_getNullState (other) == NS_ERROR || sRef_getNullState (res) == NS_ERROR)
3510 sRef_setNullState (res, NS_ERROR, fileloc_undefined);
3514 if (sRef_getNullState (other) != NS_UNKNOWN
3515 && (sRef_getNullState (res) == NS_UNKNOWN || sRef_getNullState (res) == NS_NOTNULL
3516 || sRef_getNullState (res) == NS_MNOTNULL))
3518 sRef_updateNullState (res, other);
3524 ** definitely NOT symmetric:
3526 ** res fills in known state information from other
3530 sRef_mergeStateQuietReverse (/*@dependent@*/ sRef res, /*@dependent@*/ sRef other)
3532 bool changed = FALSE;
3534 llassert (sRef_isValid (res));
3535 llassert (sRef_isValid (other));
3536 sRef_checkMutable (res);
3538 if (res->kind != other->kind)
3544 res->kind = other->kind;
3545 res->type = other->type;
3546 res->info = sinfo_fullCopy (other);
3550 if (!ctype_equal (res->type, other->type))
3553 res->type = other->type;
3556 sinfo_update (res, other);
3559 res->modified = res->modified || other->modified;
3560 res->safe = res->safe && other->safe;
3562 if (res->aliaskind != other->aliaskind
3563 && (res->aliaskind == AK_UNKNOWN
3564 || ((res->aliaskind == AK_LOCAL
3565 || (res->aliaskind == AK_REFCOUNTED
3566 && other->aliaskind != AK_LOCAL))
3567 && other->aliaskind != AK_UNKNOWN)))
3570 res->aliaskind = other->aliaskind;
3571 res->oaliaskind = other->oaliaskind;
3572 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
3575 if (other->expkind != XO_UNKNOWN && other->expkind != res->expkind)
3578 res->expkind = other->expkind;
3579 res->expinfo = stateInfo_update (res->expinfo, other->expinfo);
3582 if (other->oexpkind != XO_UNKNOWN)
3584 res->oexpkind = other->oexpkind;
3587 /* out takes precedence over implicitly defined */
3589 if (res->defstate != other->defstate)
3591 if (other->defstate != SS_UNKNOWN)
3593 res->defstate = other->defstate;
3597 if (sRef_getNullState (other) == NS_ERROR || sRef_getNullState (res) == NS_ERROR)
3599 if (sRef_getNullState (res) != NS_ERROR)
3601 sRef_setNullStateN (res, NS_ERROR);
3607 if (sRef_getNullState (other) != NS_UNKNOWN && sRef_getNullState (other) != sRef_getNullState (res))
3610 sRef_updateNullState (res, other);
3616 sRef_clearDerived (res);
3621 sRef_mergeState (sRef res, sRef other, clause cl, fileloc loc)
3623 if (sRef_isValid (res) && sRef_isValid (other))
3625 sRef_mergeStateAux (res, other, cl, FALSE, loc, TRUE);
3629 if (sRef_isInvalid (res))
3631 llbug (message ("sRef_mergeState: invalid res sRef: %q",
3632 sRef_unparseDebug (other)));
3636 llbug (message ("sRef_mergeState: invalid other sRef: %q",
3637 sRef_unparseDebug (res)));
3643 sRef_mergeOptState (sRef res, sRef other, clause cl, fileloc loc)
3645 if (sRef_isValid (res) && sRef_isValid (other))
3647 sRef_mergeStateAux (res, other, cl, TRUE, loc, TRUE);
3651 if (sRef_isInvalid (res))
3653 llbug (message ("sRef_mergeOptState: invalid res sRef: %q",
3654 sRef_unparseDebug (other)));
3658 llbug (message ("sRef_mergeOptState: invalid other sRef: %q",
3659 sRef_unparseDebug (res)));
3665 sRef_mergeStateAux (/*@notnull@*/ sRef res, /*@notnull@*/ sRef other,
3666 clause cl, bool opt, fileloc loc,
3670 llassertfatal (sRef_isValid (res));
3671 llassertfatal (sRef_isValid (other));
3673 sRef_checkMutable (res);
3674 sRef_checkMutable (other);
3676 res->modified = res->modified || other->modified;
3678 if (res->kind == other->kind
3679 || (other->kind == SK_UNKNOWN || res->kind == SK_UNKNOWN))
3681 sstate odef = other->defstate;
3682 sstate rdef = res->defstate;
3683 nstate onull = sRef_getNullState (other);
3686 ** yucky stuff to handle
3691 if (other->defstate == SS_DEAD
3692 && ((sRef_isOnly (res) && sRef_definitelyNull (res))
3693 || (res->defstate == SS_UNDEFINED
3694 || res->defstate == SS_UNUSEABLE)))
3696 if (res->defstate == SS_UNDEFINED
3697 || res->defstate == SS_UNUSEABLE)
3699 res->defstate = SS_UNUSEABLE;
3703 res->defstate = SS_DEAD;
3706 res->definfo = stateInfo_update (res->definfo, other->definfo);
3707 sRef_clearDerived (other);
3708 sRef_clearDerived (res);
3710 else if (res->defstate == SS_DEAD
3711 && ((sRef_isOnly (other) && sRef_definitelyNull (other))
3712 || (other->defstate == SS_UNDEFINED
3713 || other->defstate == SS_UNUSEABLE)))
3715 if (other->defstate == SS_UNDEFINED
3716 || other->defstate == SS_UNUSEABLE)
3718 res->defstate = SS_UNUSEABLE;
3722 res->defstate = SS_DEAD;
3725 sRef_clearDerived (other);
3726 sRef_clearDerived (res);
3728 else if (res->defstate == SS_DEFINED
3729 && (other->defstate == SS_ALLOCATED
3730 && sRef_definitelyNull (other)))
3732 other->defstate = SS_DEFINED; /* definitely null! */
3734 else if (other->defstate == SS_DEFINED
3735 && (res->defstate == SS_ALLOCATED && sRef_definitelyNull (res)))
3737 res->defstate = SS_DEFINED;
3738 res->definfo = stateInfo_update (res->definfo, other->definfo);
3745 if (res->defstate == SS_DEAD && other->defstate == SS_DEAD)
3747 sRef_clearDerived (other);
3748 sRef_clearDerived (res);
3752 ** only & dead isn't really an only!
3755 if (alkind_isOnly (other->aliaskind) && other->defstate == SS_DEAD)
3757 other->aliaskind = AK_UNKNOWN;
3760 if (alkind_isOnly (res->aliaskind) && res->defstate == SS_DEAD)
3762 res->aliaskind = AK_UNKNOWN;
3766 ** Dead and dependent -> dead
3769 if (alkind_isDependent (other->aliaskind) && res->defstate == SS_DEAD)
3771 other->aliaskind = AK_UNKNOWN;
3772 other->defstate = SS_DEAD;
3773 sRef_clearDerived (res);
3774 sRef_clearDerived (other);
3777 if (alkind_isDependent (res->aliaskind) && other->defstate == SS_DEAD)
3779 res->aliaskind = AK_UNKNOWN;
3780 res->defstate = SS_DEAD;
3781 sRef_clearDerived (res);
3782 sRef_clearDerived (other);
3786 ** must do alias combine first, since it depends on
3787 ** original values of state and null.
3790 sRef_combineAliasKinds (res, other, cl, loc);
3791 sRef_combineDefState (res, other);
3792 sRef_combineNullState (res, other);
3794 if (rdef == SS_ALLOCATED || rdef == SS_SPECIAL)
3796 if (odef == SS_DEFINED)
3798 if (onull == NS_DEFNULL || onull == NS_CONSTNULL)
3800 res->deriv = sRefSet_copyInto (res->deriv, other->deriv);
3801 DPRINTF (("Copy derivs: %s", sRef_unparseFull (res)));
3804 else if (odef == SS_ALLOCATED || odef == SS_SPECIAL)
3809 if (ctype_isUnion (ctype_realType (sRef_getType (res))))
3811 res->deriv = sRef_mergeUnionDerivs (res->deriv,
3814 DPRINTF (("Copy derivs: %s", sRef_unparseFull (res)));
3818 res->deriv = sRef_mergeDerivs (res->deriv, other->deriv,
3820 DPRINTF (("Copy derivs: %s", sRef_unparseFull (res)));
3828 res->deriv = sRef_mergeDerivs (res->deriv, other->deriv,
3830 DPRINTF (("Copy derivs: %s", sRef_unparseFull (res)));
3840 if (rdef == SS_PDEFINED
3841 || (rdef == SS_DEFINED && odef == SS_PDEFINED))
3845 res->deriv = sRef_mergePdefinedDerivs (res->deriv, other->deriv,
3847 DPRINTF (("Copy derivs: %s", sRef_unparseFull (res)));
3852 if ((rdef == SS_DEFINED || rdef == SS_UNKNOWN)
3853 && res->defstate == SS_ALLOCATED)
3855 res->deriv = sRefSet_copyInto (res->deriv, other->deriv);
3861 res->deriv = sRef_mergeDerivs (res->deriv, other->deriv,
3863 DPRINTF (("Copy derivs: %s", sRef_unparseFull (res)));
3870 sRef_combineExKinds (res, other);
3874 if (res->kind == SK_ARRAYFETCH && other->kind == SK_PTR)
3876 sRef nother = sRef_buildArrayFetchKnown (sRef_getBase (other), 0);
3878 sRef_copyState (nother, other);
3879 sRef_mergeStateAux (res, nother, cl, opt, loc, doDerivs);
3881 else if (res->kind == SK_PTR && other->kind == SK_ARRAYFETCH)
3883 sRef nother = sRef_buildPointer (sRef_getBase (other));
3885 if (sRef_isValid (nother))
3887 sRef_copyState (nother, other);
3888 sRef_mergeStateAux (res, nother, cl, opt, loc, doDerivs);
3893 llcontbug (message ("merge conj: %q / %q", sRef_unparseFull (res),
3894 sRef_unparseFull (other)));
3900 ** Merge value table states
3907 ** This doesn't do anything. And its broken too...
3910 valueTable_elements (res->state, key, sv)
3912 stateValue os = valueTable_lookup (other->state, key);
3913 /*@unused@*/ int val;
3914 /*@unused@*/ char *msg;
3916 llassert (stateValue_isDefined (os));
3918 DPRINTF (("Merge state: %s / %s",
3919 cstring_toCharsSafe (stateValue_unparse (sv)),
3920 cstring_toCharsSafe (stateValue_unparse (os))));
3922 val = valueMatix_lookup (key,
3923 stateValue_getValue (os),
3924 stateValue_getValue (sv),
3926 DPRINTF (("Val: %d / %s", val, msg));
3928 } end_valueTable_elements ;
3934 sRef_mergeUnionDerivs (/*@only@*/ sRefSet res,
3935 /*@exposed@*/ sRefSet other, bool opt,
3936 clause cl, fileloc loc)
3938 if (sRefSet_isEmpty (res))
3940 return sRefSet_copyInto (res, other);
3944 sRefSet_allElements (other, el)
3946 if (sRef_isValid (el))
3948 sRef e2 = sRefSet_lookupMember (other, el);
3950 if (sRef_isValid (e2))
3952 sRef_mergeStateAux (el, e2, cl, opt, loc, FALSE);
3956 res = sRefSet_insert (res, el);
3959 } end_sRefSet_allElements ;
3965 static /*@only@*/ sRefSet
3966 sRef_mergeDerivs (/*@only@*/ sRefSet res, sRefSet other,
3967 bool opt, clause cl, fileloc loc)
3969 sRefSet ret = sRefSet_new ();
3971 sRefSet_allElements (res, el)
3973 if (sRef_isValid (el))
3975 sRef e2 = sRefSet_lookupMember (other, el);
3977 if (sRef_isValid (e2))
3979 if (el->defstate == SS_ALLOCATED &&
3980 e2->defstate == SS_PDEFINED)
3982 e2->defstate = SS_ALLOCATED;
3984 else if (e2->defstate == SS_ALLOCATED &&
3985 el->defstate == SS_PDEFINED)
3987 el->defstate = SS_ALLOCATED;
3988 sRef_clearDerived (el);
3990 else if ((el->defstate == SS_DEAD || sRef_isKept (el)) &&
3991 (e2->defstate == SS_DEFINED && !sRef_isKept (e2)))
3994 if (checkDeadState (el, TRUE, loc))
3996 if (sRef_isThroughArrayFetch (el))
3998 sRef_maybeKill (el, loc);
3999 sRef_maybeKill (e2, loc);
4003 else if ((e2->defstate == SS_DEAD || sRef_isKept (e2)) &&
4004 (el->defstate == SS_DEFINED && !sRef_isKept (el)))
4007 if (checkDeadState (e2, FALSE, loc))
4009 if (sRef_isThroughArrayFetch (el))
4011 sRef_maybeKill (el, loc);
4012 sRef_maybeKill (e2, loc);
4016 else if (el->defstate == SS_DEFINED &&
4017 e2->defstate == SS_PDEFINED)
4019 DPRINTF (("set pdefined: %s", sRef_unparseFull (el)));
4020 el->defstate = SS_PDEFINED;
4022 else if (e2->defstate == SS_DEFINED &&
4023 el->defstate == SS_PDEFINED)
4025 DPRINTF (("set pdefined: %s", sRef_unparseFull (e2)));
4026 e2->defstate = SS_PDEFINED;
4033 if (ctype_isUnion (ctype_realType (sRef_getType (el))))
4035 el->deriv = sRef_mergeUnionDerivs (el->deriv, e2->deriv,
4040 el->deriv = sRef_mergeDerivs (el->deriv, e2->deriv, opt, cl, loc);
4043 if (sRef_equivalent (el, e2))
4045 ret = sRefSet_insert (ret, el);
4049 sRef sr = sRef_leastCommon (el, e2);
4051 if (sRef_isValid (sr))
4053 ret = sRefSet_insert (ret, sr);
4061 (void) sRefSet_delete (other, e2);
4063 else /* not defined */
4065 (void) checkDeadState (el, TRUE, loc);
4068 } end_sRefSet_allElements;
4070 sRefSet_allElements (other, el)
4072 if (sRef_isValid (el))
4074 (void) checkDeadState (el, FALSE, loc);
4076 } end_sRefSet_allElements;
4083 ** Returns TRUE is there is an error.
4086 static bool checkDeadState (/*@notnull@*/ sRef el, bool tbranch, fileloc loc)
4089 ** usymtab_isGuarded --- the utab should still be in the
4090 ** state of the alternate branch.
4092 ** tbranch TRUE means el is released in the last branch, e.g.
4093 ** if (x != NULL) { ; } else { sfree (x); }
4094 ** so, if x is null in the other branch no error is reported.
4096 ** tbranch FALSE means this is the other branch:
4097 ** if (x != NULL) { sfree (x); } else { ; }
4098 ** so, if x is null in this branch there is no error.
4102 if ((sRef_isDead (el) || sRef_isKept (el))
4103 && !sRef_isDeepUnionField (el) && !sRef_isThroughArrayFetch (el))
4108 if (usymtab_isDefinitelyNullDeep (el))
4115 if (usymtab_isAltDefinitelyNullDeep (el))
4123 message ("Storage %q is %q in one path, but live in another.",
4125 cstring_makeLiteral (sRef_isKept (el)
4126 ? "kept" : "released")),
4130 if (sRef_isKept (el))
4132 sRef_showAliasInfo (el);
4136 sRef_showStateInfo (el);
4139 /* prevent further errors */
4140 el->defstate = SS_UNKNOWN;
4141 sRef_setAliasKind (el, AK_ERROR, fileloc_undefined);
4151 checkDerivDeadState (/*@notnull@*/ sRef el, bool tbranch, fileloc loc)
4154 if (checkDeadState (el, tbranch, loc))
4156 sRefSet_allElements (el->deriv, t)
4158 if (sRef_isValid (t))
4160 checkDerivDeadState (t, tbranch, loc);
4162 } end_sRefSet_allElements;
4167 sRef_mergePdefinedDerivs (sRefSet res, sRefSet other, bool opt,
4168 clause cl, fileloc loc)
4170 sRefSet ret = sRefSet_new ();
4172 sRefSet_allElements (res, el)
4174 if (sRef_isValid (el))
4176 sRef e2 = sRefSet_lookupMember (other, el);
4178 if (sRef_isValid (e2))
4180 if (sRef_isAllocated (el) && !sRef_isAllocated (e2))
4184 else if (sRef_isAllocated (e2) && !sRef_isAllocated (el))
4186 el->deriv = sRefSet_copyInto (el->deriv, e2->deriv);
4190 el->deriv = sRef_mergePdefinedDerivs (el->deriv, e2->deriv,
4194 sRef_mergeStateAux (el, e2, cl, opt, loc, FALSE);
4196 ret = sRefSet_insert (ret, el);
4197 (void) sRefSet_delete (other, e2);
4203 checkDerivDeadState (el, (cl == FALSECLAUSE), loc);
4206 ret = sRefSet_insert (ret, el);
4209 } end_sRefSet_allElements;
4211 sRefSet_allElements (other, el)
4213 if (sRef_isValid (el))
4215 if (!sRefSet_member (ret, el))
4217 /* was cl == FALSECLAUSE */
4218 checkDerivDeadState (el, FALSE, loc);
4219 ret = sRefSet_insert (ret, el);
4224 ** it's okay --- member is a different equality test
4228 } end_sRefSet_allElements;
4234 sRef sRef_makeConj (/*@exposed@*/ /*@returned@*/ sRef a, /*@exposed@*/ sRef b)
4236 llassert (sRef_isValid (a));
4237 llassert (sRef_isValid (b));
4239 if (!sRef_equivalent (a, b))
4241 sRef s = sRef_newRef ();
4244 s->info = (sinfo) dmalloc (sizeof (*s->info));
4245 s->info->conj = (cjinfo) dmalloc (sizeof (*s->info->conj));
4246 s->info->conj->a = a; /* sRef_copy (a) */ /*@i32*/ ;
4247 s->info->conj->b = b; /* sRef_copy (b);*/ /*@i32@*/ ;
4249 if (ctype_equal (a->type, b->type)) s->type = a->type;
4250 else s->type = ctype_makeConj (a->type, b->type);
4252 if (a->defstate == b->defstate)
4254 s->defstate = a->defstate;
4258 s->defstate = SS_UNKNOWN;
4261 sRef_setNullStateN (s, NS_UNKNOWN);
4263 s->safe = a->safe && b->safe;
4264 s->aliaskind = alkind_resolve (a->aliaskind, b->aliaskind);
4266 llassert (valueTable_isUndefined (s->state));
4267 s->state = context_createValueTable (s);
4272 /*@-exposetrans@*/ return a; /*@=exposetrans@*/
4276 /*@dependent@*/ sRef
4279 sRef s = sRef_new ();
4281 s->kind = SK_UNKNOWN;
4285 static /*@owned@*/ sRef
4286 sRef_makeSpecial (speckind sk) /*@*/
4288 sRef s = sRef_new ();
4290 s->kind = SK_SPECIAL;
4291 s->info = (sinfo) dmalloc (sizeof (*s->info));
4293 /*@-dependenttrans@*/
4295 /*@=dependenttrans@*/
4298 static /*@owned@*/ sRef srnothing = sRef_undefined;
4299 static /*@owned@*/ sRef srinternal = sRef_undefined;
4300 static /*@owned@*/ sRef srsystem = sRef_undefined;
4301 static /*@owned@*/ sRef srspec = sRef_undefined;
4303 /*@dependent@*/ sRef
4304 sRef_makeNothing (void)
4306 if (sRef_isInvalid (srnothing))
4308 srnothing = sRef_makeSpecial (SR_NOTHING);
4315 sRef_makeInternalState (void)
4317 if (sRef_isInvalid (srinternal))
4319 srinternal = sRef_makeSpecial (SR_INTERNAL);
4326 sRef_makeSpecState (void)
4328 if (sRef_isInvalid (srspec))
4330 srspec = sRef_makeSpecial (SR_SPECSTATE);
4337 sRef_makeSystemState (void)
4339 if (sRef_isInvalid (srsystem))
4341 srsystem = sRef_makeSpecial (SR_SYSTEM);
4348 sRef_makeGlobalMarker (void)
4350 sRef s = sRef_makeSpecial (SR_GLOBALMARKER);
4351 llassert (valueTable_isUndefined (s->state));
4352 s->state = context_createGlobalMarkerValueTable ();
4357 sRef_makeResultType (ctype ct)
4359 sRef res = sRef_makeResult ();
4368 sRef s = sRef_newRef ();
4370 s->kind = SK_RESULT;
4371 s->type = ctype_unknown;
4372 s->defstate = SS_UNKNOWN;
4373 s->aliaskind = AK_UNKNOWN;
4374 sRef_setNullStateN (s, NS_UNKNOWN);
4375 llassert (valueTable_isUndefined (s->state));
4376 s->state = context_createValueTable (s);
4378 DPRINTF (("Result: [%p] %s", s, sRef_unparseFull (s)));
4384 sRef_isNothing (sRef s)
4386 return (sRef_isKindSpecial (s) && s->info->spec == SR_NOTHING);
4390 sRef_isInternalState (sRef s)
4392 return (sRef_isKindSpecial (s) && s->info->spec == SR_INTERNAL);
4396 sRef_isSpecInternalState (sRef s)
4398 return (sRef_isKindSpecial (s)
4399 && (s->info->spec == SR_INTERNAL || s->info->spec == SR_SPECSTATE));
4403 sRef_isSpecState (sRef s)
4405 return (sRef_isKindSpecial (s) && s->info->spec == SR_SPECSTATE);
4409 sRef_isResult (sRef s)
4411 return (sRef_isValid (s) && s->kind == SK_RESULT);
4415 sRef_isSystemState (sRef s)
4417 return (sRef_isKindSpecial (s) && s->info->spec == SR_SYSTEM);
4421 sRef_isGlobalMarker (sRef s)
4423 return (sRef_isKindSpecial (s) && s->info->spec == SR_GLOBALMARKER);
4427 sRef_getScopeIndex (sRef s)
4429 llassert (sRef_isValid (s));
4430 llassert (sRef_isCvar (s));
4432 return (s->info->cvar->index);
4436 sRef_makeSafe (sRef s)
4438 if (sRef_isValid (s))
4445 sRef_makeUnsafe (sRef s)
4447 if (sRef_isValid (s))
4454 ** memory state operations
4457 /*@only@*/ cstring sRef_unparseFull (sRef s)
4459 if (sRef_isInvalid (s)) return (cstring_undefined);
4461 return (message ("[%d] %q - %q [%s] { %q } < %q >",
4463 sRef_unparseDebug (s),
4464 sRef_unparseState (s),
4465 exkind_unparse (s->oexpkind),
4466 sRefSet_unparseDebug (s->deriv),
4467 valueTable_unparse (s->state)));
4470 /*@unused@*/ cstring sRef_unparseDeep (sRef s)
4472 cstring st = cstring_undefined;
4474 st = message ("%q:", sRef_unparseFull (s));
4476 if (sRef_isValid (s))
4478 sRefSet_allElements (s->deriv, el)
4480 st = message("%q\n%q", st, sRef_unparseDeep (el));
4481 } end_sRefSet_allElements ;
4487 /*@only@*/ cstring sRef_unparseState (sRef s)
4489 if (sRef_isConj (s))
4491 return (message ("%q | %q",
4492 sRef_unparseState (s->info->conj->a),
4493 sRef_unparseState (s->info->conj->b)));
4496 if (sRef_isInvalid (s))
4498 return (cstring_makeLiteral ("<invalid>"));
4501 return (message ("%s.%s.%s.%s",
4502 alkind_unparse (s->aliaskind),
4503 nstate_unparse (sRef_getNullState (s)),
4504 exkind_unparse (s->expkind),
4505 sstate_unparse (s->defstate)));
4508 bool sRef_isNotUndefined (sRef s)
4510 return (sRef_isInvalid (s)
4511 || (s->defstate != SS_UNDEFINED
4512 && s->defstate != SS_UNUSEABLE
4513 && s->defstate != SS_DEAD));
4516 ynm sRef_isWriteable (sRef s)
4518 if (sRef_isInvalid (s)) return MAYBE;
4520 if (sRef_isConj (s) && s->defstate == SS_UNKNOWN)
4522 if (ynm_toBoolStrict (sRef_isWriteable (sRef_getConjA (s))))
4524 if (ynm_toBoolStrict (sRef_isWriteable (sRef_getConjB (s))))
4532 if (ynm_toBoolStrict (sRef_isWriteable (sRef_getConjB (s))))
4540 return (ynm_fromBool (s->defstate != SS_UNUSEABLE));
4543 bool sRef_hasNoStorage (sRef s)
4545 return (!sRef_isAllocatedStorage (s) || sRef_isDefinitelyNull (s));
4548 bool sRef_isStrictReadable (sRef s)
4550 return (ynm_toBoolStrict (sRef_isReadable (s)));
4553 ynm sRef_isReadable (sRef s)
4557 if (sRef_isInvalid (s)) return YES;
4561 if (sRef_isConj (s) && s->defstate == SS_UNKNOWN)
4563 if (ynm_toBoolStrict (sRef_isReadable (sRef_getConjA (s))))
4565 if (ynm_toBoolStrict (sRef_isReadable (sRef_getConjB (s))))
4573 if (ynm_toBoolStrict (sRef_isReadable (sRef_getConjB (s))))
4580 else if (ss == SS_HOFFA)
4582 if (context_getFlag (FLG_STRICTUSERELEASED))
4593 return (ynm_fromBool (ss == SS_DEFINED
4596 || ss == SS_PDEFINED
4599 || ss == SS_ALLOCATED
4600 || ss == SS_KILLED /* evans 2001-05-26: added this for killed globals */
4601 || ss == SS_UNKNOWN));
4605 static /*@exposed@*/ sRef whatUndefined (/*@exposed@*/ sRef fref, int depth)
4610 if (depth > MAXDEPTH)
4613 ("Warning: check definition limit exceeded, checking %q. "
4614 "This either means there is a variable with at least "
4615 "%d indirections apparent in the program text, or "
4616 "there is a bug in LCLint.",
4617 sRef_unparse (fref),
4621 return sRef_undefined;
4624 if (!sRef_isKnown (fref) || sRef_isAnyDefined (fref))
4626 return sRef_undefined;
4629 if (sRef_isUnuseable (fref) || sRef_isStateUndefined (fref))
4634 ct = ctype_realType (sRef_getType (fref));
4636 if (ctype_isUnknown (ct))
4638 return sRef_undefined;
4640 else if (ctype_isPointer (ct) || ctype_isArray (ct))
4642 if (sRef_isStateUnknown (fref))
4644 return sRef_undefined;
4648 sRef fptr = sRef_constructDeref (fref);
4650 return (whatUndefined (fptr, depth + 1));
4653 else if (ctype_isStruct (ct))
4655 bool hasOneDefined = FALSE;
4657 if (sRef_isStateUnknown (fref))
4662 if (sRef_isPdefined (fref) || sRef_isAnyDefined (fref))
4664 sRefSet_realElements (sRef_derivedFields (fref), sr)
4666 hasOneDefined = TRUE;
4668 if (sRef_isField (sr))
4670 cstring fieldname = sRef_getField (sr);
4671 sRef fldref = sRef_makeField (fref, fieldname);
4672 bool shouldCheck = !sRef_isRecursiveField (fldref);
4676 sRef wdef = whatUndefined (fldref, depth + 1);
4678 if (sRef_isValid (wdef))
4684 } end_sRefSet_realElements;
4686 else if (sRef_isAllocated (fref))
4689 ** for structures, each field must be completely defined
4692 uentryList fields = ctype_getFields (ct);
4694 uentryList_elements (fields, ue)
4696 cstring name = uentry_getRealName (ue);
4697 sRef ffield = sRef_makeField (fref, name);
4698 bool shouldCheck = !sRef_isRecursiveField (ffield);
4700 if (sRef_isRelDef (uentry_getSref (ue)))
4708 sRef wdef = whatUndefined (ffield, depth + 1);
4710 if (sRef_isInvalid (wdef))
4716 } end_uentryList_elements;
4723 else if (ctype_isUnion (ct))
4732 return sRef_undefined;
4735 static bool checkDefined (/*@temp@*/ sRef sr)
4737 /*@-temptrans@*/ /* the result from whatUndefined is lost */
4738 return (sRef_isInvalid (whatUndefined (sr, 0)));
4742 bool sRef_isReallyDefined (sRef s)
4744 if (sRef_isValid (s))
4746 if (sRef_isAnyDefined (s))
4752 if (sRef_isAllocated (s) || sRef_isPdefined (s))
4754 return checkDefined (s);
4768 void sRef_showNotReallyDefined (sRef s)
4770 if (sRef_isValid (s))
4772 if (sRef_isAnyDefined (s))
4778 if (sRef_isAllocated (s) || sRef_isPdefined (s))
4780 /*@-temptrans@*/ /* the result of whatUndefined is lost */
4781 sRef ref = whatUndefined (s, 0);
4783 llassert (sRef_isValid (ref));
4788 (message ("This sub-reference is %s: %q",
4789 sstate_unparse (sRef_getDefState (ref)),
4790 sRef_unparse (ref)));
4805 sstate sRef_getDefState (sRef s)
4807 if (sRef_isInvalid (s)) return (SS_UNKNOWN);
4808 return (s->defstate);
4811 void sRef_setDefState (sRef s, sstate defstate, fileloc loc)
4813 sRef_checkMutable (s);
4814 sRef_setStateAux (s, defstate, loc);
4817 static void sRef_clearAliasStateAux (sRef s, fileloc loc)
4819 sRef_checkMutable (s);
4820 sRef_setAliasKind (s, AK_ERROR, loc);
4823 void sRef_clearAliasState (sRef s, fileloc loc)
4825 sRef_checkMutable (s);
4826 sRef_aliasSetComplete (sRef_clearAliasStateAux, s, loc);
4829 void sRef_setAliasKindComplete (sRef s, alkind kind, fileloc loc)
4831 sRef_checkMutable (s);
4832 sRef_aliasSetCompleteParam (sRef_setAliasKind, s, kind, loc);
4835 void sRef_setAliasKind (sRef s, alkind kind, fileloc loc)
4837 sRef_checkMutable (s);
4839 if (sRef_isValid (s))
4841 sRef_clearDerived (s);
4843 if ((kind != s->aliaskind && kind != s->oaliaskind)
4844 && fileloc_isDefined (loc))
4846 s->aliasinfo = stateInfo_updateLoc (s->aliasinfo, loc);
4849 s->aliaskind = kind;
4853 void sRef_setOrigAliasKind (sRef s, alkind kind)
4855 sRef_checkMutable (s);
4857 if (sRef_isValid (s))
4859 s->oaliaskind = kind;
4863 exkind sRef_getExKind (sRef s)
4865 if (sRef_isValid (s))
4867 return (s->expkind);
4875 exkind sRef_getOrigExKind (sRef s)
4877 if (sRef_isValid (s))
4879 return (s->oexpkind);
4887 static void sRef_clearExKindAux (sRef s, fileloc loc)
4889 sRef_checkMutable (s);
4890 sRef_setExKind (s, XO_UNKNOWN, loc);
4893 void sRef_setObserver (sRef s, fileloc loc)
4895 sRef_checkMutable (s);
4896 sRef_setExKind (s, XO_OBSERVER, loc);
4899 void sRef_setExposed (sRef s, fileloc loc)
4901 sRef_checkMutable (s);
4902 sRef_setExKind (s, XO_EXPOSED, loc);
4905 void sRef_clearExKindComplete (sRef s, fileloc loc)
4907 (void) sRef_aliasSetComplete (sRef_clearExKindAux, s, loc);
4910 void sRef_setExKind (sRef s, exkind exp, fileloc loc)
4912 sRef_checkMutable (s);
4914 if (sRef_isValid (s))
4916 if (s->expkind != exp)
4918 s->expinfo = stateInfo_updateLoc (s->expinfo, loc);
4926 ** s1->derived = s2->derived
4929 static void sRef_copyRealDerived (sRef s1, sRef s2)
4931 DPRINTF (("Copy real: %s / %s", sRef_unparse (s1), sRef_unparse (s2)));
4932 sRef_checkMutable (s1);
4934 if (sRef_isValid (s1) && sRef_isValid (s2))
4936 sRef sb = sRef_getRootBase (s1);
4938 sRefSet_clear (s1->deriv);
4940 sRefSet_allElements (s2->deriv, el)
4942 if (sRef_isValid (el))
4944 sRef rb = sRef_getRootBase (el);
4946 if (!sRef_same (rb, sb))
4948 sRef fb = sRef_fixDirectBase (el, s1);
4950 if (sRef_isValid (fb))
4952 sRef_copyRealDerived (fb, el);
4953 sRef_addDeriv (s1, fb);
4958 sRef_addDeriv (s1, el);
4961 } end_sRefSet_allElements ;
4966 void sRef_copyRealDerivedComplete (sRef s1, sRef s2)
4968 sRef_innerAliasSetCompleteParam (sRef_copyRealDerived, s1, s2);
4971 void sRef_setUndefined (sRef s, fileloc loc)
4973 sRef_checkMutable (s);
4975 if (sRef_isValid (s))
4977 s->defstate = SS_UNDEFINED;
4979 if (fileloc_isDefined (loc))
4981 s->definfo = stateInfo_updateLoc (s->definfo, loc);
4984 sRef_clearDerived (s);
4988 static void sRef_setDefinedAux (sRef s, fileloc loc, bool clear)
4990 sRef_checkMutable (s);
4991 if (sRef_isInvalid (s)) return;
4993 if (s->defstate != SS_DEFINED && fileloc_isDefined (loc))
4995 s->definfo = stateInfo_updateLoc (s->definfo, loc);
4998 s->defstate = SS_DEFINED;
5000 /* e.g., if x is allocated, *x = 3 defines x */
5002 if (s->kind == SK_PTR)
5004 sRef p = s->info->ref;
5006 if (p->defstate == SS_ALLOCATED)
5008 sRef_setDefinedAux (p, loc, clear);
5011 else if (s->kind == SK_ARRAYFETCH)
5013 if (!s->info->arrayfetch->indknown
5014 || (s->info->arrayfetch->ind == 0))
5016 sRef p = s->info->arrayfetch->arr;
5017 sRef ptr = sRef_constructPointer (p);
5019 if (sRef_isValid (ptr))
5021 if (ptr->defstate == SS_ALLOCATED
5022 || ptr->defstate == SS_UNDEFINED)
5024 sRef_setDefinedAux (ptr, loc, clear);
5028 if (p->defstate == SS_RELDEF)
5032 else if (p->defstate == SS_ALLOCATED || p->defstate == SS_PDEFINED)
5034 p->defstate = SS_DEFINED;
5041 else if (s->kind == SK_FIELD)
5043 sRef parent = s->info->field->rec;
5045 if (sRef_isValid (parent))
5047 if (ctype_isUnion (ctype_realType (parent->type)))
5050 ** Should not clear derived from here.
5053 sRef_setDefinedNoClear (parent, loc);
5057 ; /* Nothing to do for structures. */
5069 sRef_clearDerived (s);
5073 static void sRef_setPartialDefined (sRef s, fileloc loc)
5075 sRef_checkMutable (s);
5077 if (!sRef_isPartial (s))
5079 sRef_setDefined (s, loc);
5083 void sRef_setPartialDefinedComplete (sRef s, fileloc loc)
5085 sRef_innerAliasSetComplete (sRef_setPartialDefined, s, loc);
5088 void sRef_setDefinedComplete (sRef s, fileloc loc)
5090 sRef_innerAliasSetComplete (sRef_setDefined, s, loc);
5093 void sRef_setDefined (sRef s, fileloc loc)
5095 sRef_checkMutable (s);
5096 sRef_setDefinedAux (s, loc, TRUE);
5099 static void sRef_setDefinedNoClear (sRef s, fileloc loc)
5101 sRef_checkMutable (s);
5102 DPRINTF (("Defining: %s", sRef_unparseFull (s)));
5103 sRef_setDefinedAux (s, loc, FALSE);
5104 DPRINTF (("==> %s", sRef_unparseFull (s)));
5107 void sRef_setDefinedNCComplete (sRef s, fileloc loc)
5109 sRef_checkMutable (s);
5110 DPRINTF (("Set Defined Complete: %s", sRef_unparseFull (s)));
5111 sRef_innerAliasSetComplete (sRef_setDefinedNoClear, s, loc);
5112 DPRINTF (("==> %s", sRef_unparseFull (s)));
5115 static bool sRef_isDeepUnionField (sRef s)
5117 return (sRef_deepPred (sRef_isUnionField, s));
5120 bool sRef_isUnionField (sRef s)
5122 if (sRef_isValid (s) && s->kind == SK_FIELD)
5125 ** defining one field of a union defines the union
5128 sRef base = s->info->field->rec;
5130 if (sRef_isValid (base))
5132 return (ctype_isUnion (ctype_realType (base->type)));
5139 void sRef_setPdefined (sRef s, fileloc loc)
5141 sRef_checkMutable (s);
5142 if (sRef_isValid (s) && !sRef_isPartial (s))
5144 sRef base = sRef_getBaseSafe (s);
5146 if (s->defstate == SS_ALLOCATED)
5151 if (s->defstate != SS_PDEFINED && fileloc_isDefined (loc))
5153 s->definfo = stateInfo_updateLoc (s->definfo, loc);
5156 DPRINTF (("set pdefined: %s", sRef_unparseFull (s)));
5157 s->defstate = SS_PDEFINED;
5159 /* e.g., if x is allocated, *x = 3 defines x */
5161 while (sRef_isValid (base) && sRef_isKnown (base))
5163 if (base->defstate == SS_DEFINED)
5167 base->defstate = SS_PDEFINED;
5168 nb = sRef_getBaseSafe (base);
5179 static void sRef_setStateAux (sRef s, sstate ss, fileloc loc)
5181 sRef_checkMutable (s);
5183 if (sRef_isValid (s))
5185 /* if (s->defstate == SS_RELDEF) return; */
5187 if (s->defstate != ss && fileloc_isDefined (loc))
5189 s->definfo = stateInfo_updateLoc (s->definfo, loc);
5193 sRef_clearDerived (s);
5195 if (ss == SS_ALLOCATED)
5197 sRef base = sRef_getBaseSafe (s);
5199 while (sRef_isValid (base) && sRef_isKnown (base))
5201 if (base->defstate == SS_DEFINED)
5205 base->defstate = SS_PDEFINED;
5207 nb = sRef_getBaseSafe (base);
5220 void sRef_setAllocatedComplete (sRef s, fileloc loc)
5222 sRef_innerAliasSetComplete (sRef_setAllocated, s, loc);
5225 static void sRef_setAllocatedShallow (sRef s, fileloc loc)
5227 sRef_checkMutable (s);
5229 if (sRef_isValid (s))
5231 if (s->defstate == SS_DEAD || s->defstate == SS_UNDEFINED)
5233 s->defstate = SS_ALLOCATED;
5235 if (fileloc_isDefined (loc))
5237 s->definfo = stateInfo_updateLoc (s->definfo, loc);
5243 void sRef_setAllocatedShallowComplete (sRef s, fileloc loc)
5245 sRef_innerAliasSetComplete (sRef_setAllocatedShallow, s, loc);
5248 void sRef_setAllocated (sRef s, fileloc loc)
5250 sRef_checkMutable (s);
5251 sRef_setStateAux (s, SS_ALLOCATED, loc);
5254 void sRef_setPartial (sRef s, fileloc loc)
5256 sRef_checkMutable (s);
5257 sRef_setStateAux (s, SS_PARTIAL, loc);
5260 void sRef_setShared (sRef s, fileloc loc)
5262 sRef_checkMutable (s);
5264 if (sRef_isValid (s))
5266 if (s->aliaskind != AK_SHARED && fileloc_isDefined (loc))
5268 s->aliasinfo = stateInfo_updateLoc (s->aliasinfo, loc);
5271 s->aliaskind = AK_SHARED;
5272 /* don't! sRef_clearDerived (s); */
5276 void sRef_setLastReference (sRef s, /*@exposed@*/ sRef ref, fileloc loc)
5278 sRef_checkMutable (s);
5280 if (sRef_isValid (s))
5282 s->aliaskind = sRef_getAliasKind (ref);
5283 s->aliasinfo = stateInfo_updateRefLoc (s->aliasinfo, ref, loc);
5288 void sRef_setNullStateAux (/*@notnull@*/ sRef s, nstate ns, fileloc loc)
5290 DPRINTF (("Set null state: %s / %s", sRef_unparse (s), nstate_unparse (ns)));
5291 sRef_checkMutable (s);
5294 if (fileloc_isDefined (loc))
5296 s->nullinfo = stateInfo_updateLoc (s->nullinfo, loc);
5300 void sRef_setNotNull (sRef s, fileloc loc)
5302 if (sRef_isValid (s))
5304 sRef_setNullStateAux (s, NS_NOTNULL, loc);
5308 void sRef_setNullStateN (sRef s, nstate n)
5310 sRef_checkMutable (s);
5314 void sRef_setNullState (sRef s, nstate n, fileloc loc)
5316 if (sRef_isValid (s))
5318 sRef_setNullStateAux (s, n, loc);
5322 void sRef_setNullTerminatedStateInnerComplete (sRef s, struct s_bbufinfo b, /*@unused@*/ fileloc loc) {
5324 switch (b.bufstate) {
5325 case BB_NULLTERMINATED:
5326 sRef_setNullTerminatedState (s);
5327 sRef_setLen (s, b.len);
5329 case BB_POSSIBLYNULLTERMINATED:
5330 sRef_setPossiblyNullTerminatedState(s);
5332 case BB_NOTNULLTERMINATED:
5333 sRef_setNotNullTerminatedState (s);
5336 sRef_setSize (s, b.size);
5338 /* PL: TO BE DONE : Aliases are not modified right now, have to be similar to
5339 * setNullStateInnerComplete.
5343 void sRef_setNullStateInnerComplete (sRef s, nstate n, fileloc loc)
5345 DPRINTF (("Set null state: %s", nstate_unparse (n)));
5347 sRef_setNullState (s, n, loc);
5352 sRef_innerAliasSetComplete (sRef_setPosNull, s, loc);
5355 sRef_innerAliasSetComplete (sRef_setDefNull, s, loc);
5358 sRef_innerAliasSetComplete (sRef_setNullUnknown, s, loc);
5361 sRef_innerAliasSetComplete (sRef_setNotNull, s, loc);
5364 sRef_innerAliasSetComplete (sRef_setNotNull, s, loc);
5367 sRef_innerAliasSetComplete (sRef_setNullUnknown, s, loc);
5370 sRef_innerAliasSetComplete (sRef_setDefNull, s, loc);
5373 sRef_innerAliasSetComplete (sRef_setNullUnknown, s, loc);
5376 sRef_innerAliasSetComplete (sRef_setNullErrorLoc, s, loc);
5381 void sRef_setPosNull (sRef s, fileloc loc)
5383 if (sRef_isValid (s))
5385 sRef_setNullStateAux (s, NS_POSNULL, loc);
5389 void sRef_setDefNull (sRef s, fileloc loc)
5391 if (sRef_isValid (s))
5393 sRef_setNullStateAux (s, NS_DEFNULL, loc);
5397 void sRef_setNullUnknown (sRef s, fileloc loc)
5399 if (sRef_isValid (s))
5401 sRef_setNullStateAux (s, NS_UNKNOWN, loc);
5405 void sRef_setNullError (sRef s)
5407 if (sRef_isValid (s))
5409 sRef_setNullStateAux (s, NS_UNKNOWN, fileloc_undefined);
5413 void sRef_setNullErrorLoc (sRef s, /*@unused@*/ fileloc loc)
5415 sRef_setNullError (s);
5418 void sRef_setOnly (sRef s, fileloc loc)
5420 sRef_checkMutable (s);
5422 if (sRef_isValid (s) && s->aliaskind != AK_ONLY)
5424 s->aliaskind = AK_ONLY;
5425 s->aliasinfo = stateInfo_updateLoc (s->aliasinfo, loc);
5429 void sRef_setDependent (sRef s, fileloc loc)
5431 sRef_checkMutable (s);
5433 if (sRef_isValid (s) && !sRef_isConst (s) && (s->aliaskind != AK_DEPENDENT))
5435 DPRINTF (("Setting dependent: %s", sRef_unparseFull (s)));
5436 s->aliaskind = AK_DEPENDENT;
5437 s->aliasinfo = stateInfo_updateLoc (s->aliasinfo, loc);
5441 void sRef_setOwned (sRef s, fileloc loc)
5443 sRef_checkMutable (s);
5445 if (sRef_isValid (s) && !sRef_isConst (s) && (s->aliaskind != AK_OWNED))
5447 s->aliaskind = AK_OWNED;
5448 s->aliasinfo = stateInfo_updateLoc (s->aliasinfo, loc);
5452 void sRef_setKept (sRef s, fileloc loc)
5454 sRef_checkMutable (s);
5456 if (sRef_isValid (s) && !sRef_isConst (s) && (s->aliaskind != AK_KEPT))
5458 sRef base = sRef_getBaseSafe (s);
5460 while (sRef_isValid (base) && sRef_isKnown (base))
5462 if (base->defstate == SS_DEFINED)
5464 base->defstate = SS_PDEFINED;
5465 base = sRef_getBaseSafe (base);
5474 s->aliaskind = AK_KEPT;
5475 s->aliasinfo = stateInfo_updateLoc (s->aliasinfo, loc);
5479 static void sRef_setKeptAux (sRef s, fileloc loc)
5481 if (!sRef_isShared (s))
5483 sRef_setKept (s, loc);
5487 static void sRef_setDependentAux (sRef s, fileloc loc)
5489 if (!sRef_isShared (s))
5491 sRef_setDependent (s, loc);
5495 void sRef_setKeptComplete (sRef s, fileloc loc)
5497 sRef_aliasSetComplete (sRef_setKeptAux, s, loc);
5500 void sRef_setDependentComplete (sRef s, fileloc loc)
5502 sRef_aliasSetComplete (sRef_setDependentAux, s, loc);
5505 void sRef_setFresh (sRef s, fileloc loc)
5507 sRef_checkMutable (s);
5509 if (sRef_isValid (s))
5511 s->aliaskind = AK_FRESH;
5512 s->aliasinfo = stateInfo_updateLoc (s->aliasinfo, loc);
5516 void sRef_kill (sRef s, fileloc loc)
5518 DPRINTF (("Kill: %s", sRef_unparseFull (s)));
5519 sRef_checkMutable (s);
5521 if (sRef_isValid (s) && !sRef_isShared (s) && !sRef_isConst (s))
5523 sRef base = sRef_getBaseSafe (s);
5525 while (sRef_isValid (base) && sRef_isKnown (base))
5527 if (base->defstate == SS_DEFINED)
5529 base->defstate = SS_PDEFINED;
5530 base = sRef_getBaseSafe (base);
5538 s->aliaskind = s->oaliaskind;
5539 s->defstate = SS_DEAD;
5540 s->definfo = stateInfo_updateLoc (s->definfo, loc);
5542 sRef_clearDerived (s);
5546 void sRef_maybeKill (sRef s, fileloc loc)
5548 sRef_checkMutable (s);
5550 if (sRef_isValid (s))
5552 sRef base = sRef_getBaseSafe (s);
5555 while (sRef_isValid (base) && sRef_isKnown (base))
5557 if (base->defstate == SS_DEFINED || base->defstate == SS_RELDEF)
5559 base->defstate = SS_PDEFINED;
5560 base = sRef_getBaseSafe (base);
5569 s->aliaskind = s->oaliaskind;
5570 s->defstate = SS_HOFFA;
5571 s->definfo = stateInfo_updateLoc (s->definfo, loc);
5572 sRef_clearDerived (s);
5578 ** just for type checking...
5581 static void sRef_killAux (sRef s, fileloc loc)
5583 if (sRef_isValid (s) && !sRef_isShared (s))
5585 if (sRef_isUnknownArrayFetch (s))
5587 sRef_maybeKill (s, loc);
5597 ** kills s and all aliases to s
5600 void sRef_killComplete (sRef s, fileloc loc)
5602 DPRINTF (("Kill complete: %s", sRef_unparseFull (s)));
5603 sRef_aliasSetComplete (sRef_killAux, s, loc);
5606 static bool sRef_equivalent (sRef s1, sRef s2)
5608 return (sRef_compare (s1, s2) == 0);
5612 ** returns an sRef that will not be free'd on function exit.
5615 /*@only@*/ sRef sRef_saveCopy (sRef s)
5619 if (sRef_isValid (s))
5621 bool old = inFunction;
5624 ** Exit the function scope, so this sRef is not
5625 ** stored in the deallocation table.
5629 DPRINTF (("Copying sref: %s", sRef_unparseFull(s)));
5630 ret = sRef_copy (s);
5631 DPRINTF (("Copying ===>: %s", sRef_unparseFull(ret)));
5636 ret = sRef_undefined;
5639 /*@-dependenttrans@*/
5641 /*@=dependenttrans@*/
5644 sRef sRef_copy (sRef s)
5646 if (sRef_isKindSpecial (s) && !sRef_isGlobalMarker (s))
5649 return s; /* don't copy specials (except for global markers) */
5653 if (sRef_isValid (s))
5655 sRef t = sRef_alloc ();
5657 DPRINTF (("Copying: [%p] %s", s, sRef_unparse (s)));
5658 DPRINTF (("Full: %s", sRef_unparseFull (s)));
5662 t->modified = s->modified;
5663 t->immut = FALSE; /* Note mutability is not copied. */
5666 t->info = sinfo_copy (s);
5667 t->defstate = s->defstate;
5668 t->nullstate = s->nullstate;
5670 /* start modifications */
5671 t->bufinfo.bufstate = s->bufinfo.bufstate;
5672 t->bufinfo.len = s->bufinfo.len;
5673 t->bufinfo.size = s->bufinfo.size;
5674 /* end modifications */
5676 t->aliaskind = s->aliaskind;
5677 t->oaliaskind = s->oaliaskind;
5679 t->expkind = s->expkind;
5680 t->oexpkind = s->oexpkind;
5682 t->nullinfo = stateInfo_copy (s->nullinfo);
5683 t->aliasinfo = stateInfo_copy (s->aliasinfo);
5684 t->definfo = stateInfo_copy (s->definfo);
5685 t->expinfo = stateInfo_copy (s->expinfo);
5687 t->deriv = sRefSet_newDeepCopy (s->deriv);
5688 t->state = valueTable_copy (s->state);
5690 DPRINTF (("Made copy: [%p] %s", t, sRef_unparse (t)));
5695 return sRef_undefined;
5700 # define PREDTEST(func,s) \
5701 do { if (sRef_isInvalid (s)) { return FALSE; } \
5702 else { if (sRef_isConj (s)) \
5703 { return (func (sRef_getConjA (s)) \
5704 || func (sRef_getConjB (s))); }}} while (FALSE);
5706 bool sRef_isAddress (sRef s)
5708 PREDTEST (sRef_isAddress, s);
5709 return (s->kind == SK_ADR);
5713 ** pretty weak... maybe a flag should control this.
5716 bool sRef_isThroughArrayFetch (sRef s)
5718 if (sRef_isValid (s))
5726 if (sRef_isArrayFetch (tref))
5731 lt = sRef_getBase (tref);
5733 } while (sRef_isValid (tref));
5739 bool sRef_isArrayFetch (sRef s)
5741 PREDTEST (sRef_isArrayFetch, s);
5742 return (s->kind == SK_ARRAYFETCH);
5745 bool sRef_isMacroParamRef (sRef s)
5747 if (context_inMacro () && sRef_isCvar (s))
5749 uentry ue = sRef_getUentry (s);
5750 cstring pname = makeParam (uentry_rawName (ue));
5751 uentry mac = usymtab_lookupSafe (pname);
5753 cstring_free (pname);
5754 return (uentry_isValid (mac));
5760 bool sRef_isCvar (sRef s)
5762 PREDTEST (sRef_isCvar, s);
5763 return (s->kind == SK_CVAR);
5766 bool sRef_isConst (sRef s)
5768 PREDTEST (sRef_isConst, s);
5769 return (s->kind == SK_CONST);
5772 bool sRef_isObject (sRef s)
5774 PREDTEST (sRef_isObject, s);
5775 return (s->kind == SK_OBJECT);
5778 bool sRef_isExternal (sRef s)
5780 PREDTEST (sRef_isExternal, s);
5781 return (s->kind == SK_EXTERNAL);
5784 static bool sRef_isDerived (sRef s)
5786 PREDTEST (sRef_isDerived, s);
5787 return (s->kind == SK_DERIVED);
5790 bool sRef_isField (sRef s)
5792 PREDTEST (sRef_isField, s);
5793 return (s->kind == SK_FIELD);
5796 static bool sRef_isIndex (sRef s)
5798 PREDTEST (sRef_isIndex, s);
5799 return (s->kind == SK_ARRAYFETCH);
5802 bool sRef_isAnyParam (sRef s)
5804 PREDTEST (sRef_isAnyParam, s);
5805 return (s->kind == SK_PARAM);
5808 bool sRef_isParam (sRef s)
5810 PREDTEST (sRef_isParam, s);
5811 return (s->kind == SK_PARAM);
5814 bool sRef_isDirectParam (sRef s)
5816 PREDTEST (sRef_isDirectParam, s);
5818 return ((s->kind == SK_CVAR) &&
5819 (s->info->cvar->lexlevel == functionScope) &&
5820 (context_inFunction () &&
5821 (s->info->cvar->index <= uentryList_size (context_getParams ()))));
5824 bool sRef_isPointer (sRef s)
5826 PREDTEST (sRef_isPointer, s);
5827 return (s->kind == SK_PTR);
5831 ** returns true if storage referenced by s is visible
5834 bool sRef_isReference (sRef s)
5836 PREDTEST (sRef_isReference, s);
5838 return (sRef_isPointer (s) || sRef_isIndex (s) || sRef_isFileOrGlobalScope (s)
5839 || (sRef_isField (s) && (sRef_isReference (s->info->field->rec))));
5842 bool sRef_isIReference (sRef s)
5844 return (sRef_isPointer (s) || sRef_isAddress (s) || sRef_isIndex (s)
5845 || sRef_isField (s) || sRef_isArrayFetch (s));
5848 bool sRef_isFileOrGlobalScope (sRef s)
5850 return (sRef_isCvar (s) && (s->info->cvar->lexlevel <= fileScope));
5853 bool sRef_isRealGlobal (sRef s)
5855 return (sRef_isCvar (s) && (s->info->cvar->lexlevel == globScope));
5858 bool sRef_isFileStatic (sRef s)
5860 return (sRef_isCvar (s) && (s->info->cvar->lexlevel == fileScope));
5863 bool sRef_isAliasCheckedGlobal (sRef s)
5865 if (sRef_isFileOrGlobalScope (s))
5867 uentry ue = sRef_getUentry (s);
5869 return context_checkAliasGlob (ue);
5877 void sRef_free (/*@only@*/ sRef s)
5879 if (s != sRef_undefined && s->kind != SK_SPECIAL)
5881 DPRINTF (("Free sref: [%p]", s));
5883 sRef_checkValid (s);
5885 stateInfo_free (s->expinfo);
5886 stateInfo_free (s->aliasinfo);
5887 stateInfo_free (s->definfo);
5888 stateInfo_free (s->nullinfo);
5890 sRefSet_free (s->deriv);
5891 s->deriv = sRefSet_undefined;
5893 /*@i43@*/ /* valueTable_free (s->state); */
5897 /* drl added to help locate use after release*/
5898 s->expinfo = stateInfo_undefined;
5899 s->aliasinfo = stateInfo_undefined;
5900 s->definfo = stateInfo_undefined;
5901 s->nullinfo = stateInfo_undefined;
5903 /*@i32@*/ sfree (s);
5907 void sRef_setType (sRef s, ctype t)
5909 sRef_checkMutable (s);
5911 if (sRef_isValid (s))
5917 void sRef_setTypeFull (sRef s, ctype t)
5919 sRef_checkMutable (s);
5921 if (sRef_isValid (s))
5925 sRefSet_allElements (s->deriv, current)
5927 sRef_setTypeFull (current, ctype_unknown);
5928 } end_sRefSet_allElements ;
5933 sRef_buildField (/*@exposed@*/ sRef rec, /*@dependent@*/ cstring f)
5935 return (sRef_buildNCField (rec, f));
5938 static /*@exposed@*/ sRef
5939 sRef_findDerivedField (/*@notnull@*/ sRef rec, cstring f)
5941 sRefSet_allElements (rec->deriv, sr)
5943 if (sRef_isValid (sr))
5945 if (sr->info != NULL)
5947 if (sr->kind == SK_FIELD && cstring_equal (sr->info->field->field, f))
5953 } end_sRefSet_allElements;
5955 return sRef_undefined;
5958 /*@dependent@*/ /*@observer@*/ sRefSet sRef_derivedFields (/*@temp@*/ sRef rec)
5960 if (sRef_isValid (rec))
5968 return (sRefSet_undefined);
5972 static /*@exposed@*/ sRef
5973 sRef_findDerivedPointer (sRef s)
5975 if (sRef_isValid (s))
5977 sRefSet_realElements (s->deriv, sr)
5979 if (sRef_isValid (sr) && sr->kind == SK_PTR)
5983 } end_sRefSet_realElements;
5986 return sRef_undefined;
5990 sRef_isUnknownArrayFetch (sRef s)
5992 return (sRef_isValid (s)
5993 && s->kind == SK_ARRAYFETCH
5994 && !s->info->arrayfetch->indknown);
5997 static /*@exposed@*/ sRef
5998 sRef_findDerivedArrayFetch (/*@notnull@*/ sRef s, bool isknown, int idx, bool dead)
6003 sRefSet_realElements (s->deriv, sr)
6005 if (sRef_isValid (sr)
6006 && sr->kind == SK_ARRAYFETCH
6007 && sr->info->arrayfetch->indknown
6008 && (sr->info->arrayfetch->ind == idx))
6012 } end_sRefSet_realElements;
6016 sRefSet_realElements (s->deriv, sr)
6018 if (sRef_isValid (sr)
6019 && sr->kind == SK_ARRAYFETCH
6020 && (!sr->info->arrayfetch->indknown
6021 || (sr->info->arrayfetch->indknown &&
6022 sr->info->arrayfetch->ind == 0)))
6024 if (sRef_isDead (sr) || sRef_isKept (sr))
6026 if (dead || context_getFlag (FLG_STRICTUSERELEASED))
6036 } end_sRefSet_realElements;
6039 return sRef_undefined;
6042 static /*@exposed@*/ sRef
6043 sRef_buildNCField (/*@exposed@*/ sRef rec, /*@exposed@*/ cstring f)
6047 DPRINTF (("Build nc field: %s / %s",
6048 sRef_unparseFull (rec), f));
6050 if (sRef_isInvalid (rec))
6052 return sRef_undefined;
6056 ** check if the field already has been referenced
6059 s = sRef_findDerivedField (rec, f);
6061 if (sRef_isValid (s))
6067 ctype ct = ctype_realType (rec->type);
6069 DPRINTF (("Field of: %s", sRef_unparse (rec)));
6073 s->info = (sinfo) dmalloc (sizeof (*s->info));
6074 s->info->field = (fldinfo) dmalloc (sizeof (*s->info->field));
6075 s->info->field->rec = rec; /* sRef_copy (rec); */ /*@i32@*/
6076 s->info->field->field = f; /* doesn't copy f */
6078 if (ctype_isKnown (ct) && ctype_isSU (ct))
6080 uentry ue = uentryList_lookupField (ctype_getFields (ct), f);
6082 if (!uentry_isUndefined (ue))
6084 DPRINTF (("lookup: %s for %s", uentry_unparseFull (ue),
6085 ctype_unparse (ct)));
6087 s->type = uentry_getType (ue);
6089 if (ctype_isMutable (s->type)
6090 && rec->aliaskind != AK_STACK
6091 && !alkind_isStatic (rec->aliaskind))
6093 s->aliaskind = rec->aliaskind;
6097 s->aliaskind = AK_UNKNOWN;
6100 if (sRef_isStateDefined (rec) || sRef_isStateUnknown (rec)
6101 || sRef_isPdefined (rec))
6103 sRef_setStateFromUentry (s, ue);
6107 sRef_setPartsFromUentry (s, ue);
6110 s->oaliaskind = s->aliaskind;
6111 s->oexpkind = s->expkind;
6113 DPRINTF (("sref: %s", sRef_unparseFull (s)));
6118 Never report this as an error. It can happen whenever there
6119 is casting involved.
6123 llcontbug (message ("buildNCField --- no field %s: %q / %s",
6124 f, sRef_unparse (s), ctype_unparse (ct)));
6128 return sRef_undefined;
6132 if (rec->defstate == SS_DEFINED
6133 && (s->defstate == SS_UNDEFINED || s->defstate == SS_UNKNOWN))
6135 s->defstate = SS_DEFINED;
6137 else if (rec->defstate == SS_PARTIAL)
6139 s->defstate = SS_PARTIAL;
6141 else if (rec->defstate == SS_ALLOCATED)
6143 if (ctype_isStackAllocated (ct) && ctype_isStackAllocated (s->type))
6145 s->defstate = SS_ALLOCATED;
6149 s->defstate = SS_UNDEFINED;
6152 else if (s->defstate == SS_UNKNOWN)
6154 s->defstate = rec->defstate;
6161 if (s->defstate == SS_UNDEFINED)
6163 ctype rt = ctype_realType (s->type);
6165 if (ctype_isArray (rt) || ctype_isSU (rt))
6167 s->defstate = SS_ALLOCATED;
6171 sRef_addDeriv (rec, s);
6172 DPRINTF (("Add deriv: %s", sRef_unparseFull (rec)));
6174 if (ctype_isInt (s->type) && cstring_equal (f, REFSNAME))
6176 s->aliaskind = AK_REFS;
6177 s->oaliaskind = AK_REFS;
6180 DPRINTF (("Build field ==> %s", sRef_unparseFull (s)));
6186 sRef_isStackAllocated (sRef s)
6188 return (sRef_isValid(s)
6189 && s->defstate == SS_ALLOCATED && ctype_isStackAllocated (s->type));
6193 void sRef_setArrayFetchState (/*@notnull@*/ /*@exposed@*/ sRef s,
6194 /*@notnull@*/ /*@exposed@*/ sRef arr)
6196 sRef_checkMutable (s);
6198 if (ctype_isRealAP (arr->type))
6200 s->type = ctype_baseArrayPtr (arr->type);
6203 /* a hack, methinks... makeArrayFetch (&a[0]) ==> a[] */
6204 if (sRef_isAddress (arr))
6206 sRef t = arr->info->ref;
6208 if (sRef_isArrayFetch (t))
6210 s->info->arrayfetch->arr = t->info->arrayfetch->arr;
6213 else if (ctype_isRealPointer (arr->type))
6215 sRef sp = sRef_findDerivedPointer (arr);
6217 if (sRef_isValid (sp))
6220 if (ctype_isMutable (s->type))
6222 sRef_setExKind (s, sRef_getExKind (sp), fileloc_undefined);
6224 s->aliaskind = sp->aliaskind;
6227 s->defstate = sp->defstate;
6229 if (s->defstate == SS_DEFINED)
6231 if (!context_getFlag (FLG_STRICTDESTROY))
6233 s->defstate = SS_PARTIAL;
6237 sRef_setNullStateN (s, sRef_getNullState (sp));
6241 if (arr->defstate == SS_UNDEFINED)
6243 s->defstate = SS_UNUSEABLE;
6245 else if ((arr->defstate == SS_ALLOCATED) && !ctype_isSU (s->type))
6247 s->defstate = SS_UNDEFINED;
6251 if (!context_getFlag (FLG_STRICTDESTROY))
6253 s->defstate = SS_PARTIAL;
6257 s->defstate = SS_DEFINED;
6261 ** Very weak checking for array elements.
6263 ** s->defstate = arr->defstate;
6267 sRef_setExKind (s, sRef_getExKind (arr), g_currentloc);
6269 if (arr->aliaskind == AK_LOCAL || arr->aliaskind == AK_FRESH)
6271 s->aliaskind = AK_LOCAL;
6275 s->aliaskind = AK_UNKNOWN;
6278 sRef_setTypeState (s);
6283 if (arr->defstate == SS_DEFINED)
6286 ** Very weak checking for array elements.
6288 ** s->defstate = arr->defstate;
6291 if (context_getFlag (FLG_STRICTDESTROY))
6293 s->defstate = SS_DEFINED;
6297 s->defstate = SS_PARTIAL;
6300 else if (arr->defstate == SS_ALLOCATED)
6302 if (ctype_isRealArray (s->type))
6304 s->defstate = SS_ALLOCATED;
6308 if (!s->info->arrayfetch->indknown)
6311 ** is index is unknown, elements is defined or
6312 ** allocated is any element is!
6315 s->defstate = SS_UNDEFINED;
6317 sRefSet_allElements (arr->deriv, sr)
6319 if (sRef_isValid (sr))
6321 if (sr->defstate == SS_ALLOCATED)
6323 s->defstate = SS_ALLOCATED;
6327 if (sr->defstate == SS_DEFINED)
6329 if (context_getFlag (FLG_STRICTDESTROY))
6331 s->defstate = SS_DEFINED;
6335 s->defstate = SS_PARTIAL;
6342 } end_sRefSet_allElements;
6347 s->defstate = SS_UNDEFINED;
6353 s->defstate = arr->defstate;
6358 ** kludgey way to guess where aliaskind applies
6361 if (ctype_isMutable (s->type)
6362 && !ctype_isPointer (arr->type)
6363 && !alkind_isStatic (arr->aliaskind)
6364 && !alkind_isStack (arr->aliaskind)) /* evs - 2000-06-20: don't pass stack allocation to members */
6366 s->aliaskind = arr->aliaskind;
6370 s->aliaskind = AK_UNKNOWN;
6373 sRef_setTypeState (s);
6376 if (sRef_isObserver (arr))
6378 s->expkind = XO_OBSERVER;
6382 /*@exposed@*/ sRef sRef_buildArrayFetch (/*@exposed@*/ sRef arr)
6386 if (!sRef_isValid (arr)) {
6387 /*@-nullret@*/ return arr /*@=nullret@*/;
6390 if (ctype_isRealPointer (arr->type))
6392 (void) sRef_buildPointer (arr); /* do this to define arr! */
6395 s = sRef_findDerivedArrayFetch (arr, FALSE, 0, FALSE);
6397 if (sRef_isValid (s))
6399 sRef_setExKind (s, sRef_getExKind (arr), g_currentloc);
6406 s->kind = SK_ARRAYFETCH;
6407 s->info = (sinfo) dmalloc (sizeof (*s->info));
6408 s->info->arrayfetch = (ainfo) dmalloc (sizeof (*s->info->arrayfetch));
6409 s->info->arrayfetch->indknown = FALSE;
6410 s->info->arrayfetch->ind = 0;
6411 s->info->arrayfetch->arr = arr; /* sRef_copy (arr); */ /*@i32@*/
6412 sRef_setArrayFetchState (s, arr);
6413 s->oaliaskind = s->aliaskind;
6414 s->oexpkind = s->expkind;
6416 if (!context_inProtectVars ())
6418 sRef_addDeriv (arr, s);
6421 llassert (valueTable_isUndefined (s->state));
6422 s->state = context_createValueTable (s);
6429 sRef_buildArrayFetchKnown (/*@exposed@*/ sRef arr, int i)
6433 if (!sRef_isValid (arr)) {
6434 /*@-nullret@*/ return arr /*@=nullret@*/;
6437 if (ctype_isRealPointer (arr->type))
6439 (void) sRef_buildPointer (arr); /* do this to define arr! */
6442 s = sRef_findDerivedArrayFetch (arr, TRUE, i, FALSE);
6444 if (sRef_isValid (s))
6446 sRef_setExKind (s, sRef_getExKind (arr), g_currentloc);
6453 s->kind = SK_ARRAYFETCH;
6454 s->info = (sinfo) dmalloc (sizeof (*s->info));
6455 s->info->arrayfetch = (ainfo) dmalloc (sizeof (*s->info->arrayfetch));
6456 s->info->arrayfetch->arr = arr; /* sRef_copy (arr); */ /*@i32@*/
6457 s->info->arrayfetch->indknown = TRUE;
6458 s->info->arrayfetch->ind = i;
6460 sRef_setArrayFetchState (s, arr);
6462 s->oaliaskind = s->aliaskind;
6463 s->oexpkind = s->expkind;
6464 sRef_addDeriv (arr, s);
6466 llassert (valueTable_isUndefined (s->state));
6467 s->state = context_createValueTable (s);
6474 ** sets everything except for defstate
6478 sRef_setPartsFromUentry (sRef s, uentry ue)
6480 sRef uref = uentry_getSref (ue);
6482 llassert (sRef_isValid (s));
6484 s->aliaskind = alkind_derive (s->aliaskind, uentry_getAliasKind (ue));
6485 s->oaliaskind = s->aliaskind;
6487 if (s->expkind == XO_UNKNOWN)
6489 s->expkind = uentry_getExpKind (ue);
6492 s->oexpkind = s->expkind;
6494 if (sRef_getNullState (s) == NS_UNKNOWN)
6496 DPRINTF (("Setting null state!"));
6497 sRef_setNullStateN (s, sRef_getNullState (uentry_getSref (ue)));
6501 DPRINTF (("Skipping null null state!"));
6504 if (s->aliaskind == AK_IMPONLY && (sRef_isExposed (s) || sRef_isObserver (s)))
6506 s->oaliaskind = s->aliaskind = AK_IMPDEPENDENT;
6509 if (sRef_isValid (uref))
6511 valueTable utable = uref->state;
6512 valueTable_free (s->state);
6513 s->state = valueTable_copy (utable);
6518 sRef_setStateFromAbstractUentry (sRef s, uentry ue)
6520 llassert (sRef_isValid (s));
6521 sRef_checkMutable (s);
6523 sRef_setPartsFromUentry (s, ue);
6525 s->aliaskind = alkind_derive (s->aliaskind, uentry_getAliasKind (ue));
6526 s->oaliaskind = s->aliaskind;
6528 if (s->expkind == XO_UNKNOWN)
6530 s->expkind = uentry_getExpKind (ue);
6533 s->oexpkind = s->expkind;
6537 sRef_setStateFromUentry (sRef s, uentry ue)
6541 sRef_checkMutable (s);
6542 llassert (sRef_isValid (s));
6544 sRef_setPartsFromUentry (s, ue);
6546 defstate = uentry_getDefState (ue);
6548 if (sstate_isKnown (defstate))
6550 s->defstate = defstate;
6559 sRef_buildPointer (/*@exposed@*/ sRef t)
6561 DPRINTF (("build pointer: %s", sRef_unparse (t)));
6563 if (sRef_isInvalid (t)) return sRef_undefined;
6565 if (sRef_isAddress (t))
6567 DPRINTF (("Return ref: %s", sRef_unparse (t->info->ref)));
6568 return (t->info->ref);
6572 sRef s = sRef_findDerivedPointer (t);
6574 DPRINTF (("find derived: %s", sRef_unparse (s)));
6576 if (sRef_isValid (s))
6579 sRef_setExKind (s, sRef_getExKind (t), g_currentloc);
6580 s->oaliaskind = s->aliaskind;
6581 s->oexpkind = s->expkind;
6587 s = sRef_constructPointerAux (t);
6589 DPRINTF (("construct: %s", sRef_unparse (s)));
6591 if (sRef_isValid (s))
6593 sRef_addDeriv (t, s);
6595 s->oaliaskind = s->aliaskind;
6596 s->oexpkind = s->expkind;
6605 sRef_constructPointer (/*@exposed@*/ sRef t)
6608 return sRef_buildPointer (t);
6611 static /*@exposed@*/ sRef sRef_constructDerefAux (sRef t, bool isdead)
6613 if (sRef_isValid (t))
6618 ** if there is a derived t[?], return that. Otherwise, *t.
6621 s = sRef_findDerivedArrayFetch (t, FALSE, 0, isdead);
6623 if (sRef_isValid (s))
6629 sRef ret = sRef_constructPointer (t);
6632 ** This is necessary to prevent infinite depth
6633 ** in checking complete destruction.
6638 /* ret->defstate = SS_UNKNOWN; */
6649 return sRef_undefined;
6653 sRef sRef_constructDeref (sRef t)
6655 return sRef_constructDerefAux (t, FALSE);
6658 sRef sRef_constructDeadDeref (sRef t)
6660 return sRef_constructDerefAux (t, TRUE);
6664 sRef_constructPointerAux (/*@notnull@*/ /*@exposed@*/ sRef t)
6666 sRef s = sRef_newRef ();
6671 s->info = (sinfo) dmalloc (sizeof (*s->info));
6672 s->info->ref = t; /* sRef_copy (t); */ /*@i32*/
6674 if (ctype_isRealAP (rt))
6676 s->type = ctype_baseArrayPtr (rt);
6679 st = ctype_realType (s->type);
6681 if (t->defstate == SS_UNDEFINED)
6683 s->defstate = SS_UNUSEABLE;
6685 else if ((t->defstate == SS_ALLOCATED) && !ctype_isSU (st))
6687 s->defstate = SS_UNDEFINED;
6691 s->defstate = t->defstate;
6694 if (t->aliaskind == AK_LOCAL || t->aliaskind == AK_FRESH)
6696 s->aliaskind = AK_LOCAL;
6700 s->aliaskind = AK_UNKNOWN;
6703 sRef_setExKind (s, sRef_getExKind (t), fileloc_undefined);
6704 sRef_setTypeState (s);
6706 s->oaliaskind = s->aliaskind;
6707 s->oexpkind = s->expkind;
6709 llassert (valueTable_isUndefined (s->state));
6710 s->state = context_createValueTable (s);
6714 bool sRef_hasDerived (sRef s)
6716 return (sRef_isValid (s) && !sRefSet_isEmpty (s->deriv));
6720 sRef_clearDerived (sRef s)
6722 if (sRef_isValid (s))
6724 sRefSet_clear (s->deriv);
6729 sRef_clearDerivedComplete (sRef s)
6732 if (sRef_isValid (s))
6734 sRef base = sRef_getBaseSafe (s);
6736 while (sRef_isValid (base))
6738 sRefSet_clear (base->deriv);
6739 base = sRef_getBaseSafe (base);
6742 sRefSet_clear (s->deriv);
6746 /*@exposed@*/ sRef sRef_makePointer (/*@exposed@*/ sRef s)
6749 sRef res = sRef_buildPointer (s);
6751 DPRINTF (("Res: %s", sRef_unparse (res)));
6756 ** &a[] => a (this is for out params)
6760 sRef_makeAnyArrayFetch (/*@exposed@*/ sRef arr)
6763 if (sRef_isAddress (arr))
6765 return (arr->info->ref);
6769 return (sRef_buildArrayFetch (arr));
6774 sRef_makeArrayFetch (/*@exposed@*/ sRef arr)
6776 return (sRef_buildArrayFetch (arr));
6780 sRef_makeArrayFetchKnown (/*@exposed@*/ sRef arr, int i)
6782 return (sRef_buildArrayFetchKnown (arr, i));
6786 sRef_makeField (sRef rec, /*@dependent@*/ cstring f)
6789 ret = sRef_buildField (rec, f);
6794 sRef_makeNCField (/*@exposed@*/ sRef rec, /*@dependent@*/ cstring f)
6796 return (sRef_buildNCField (rec, f));
6800 sRef_unparseKindName (sRef s)
6804 if (s == sRef_undefined) return cstring_makeLiteral ("<invalid>");
6806 s = sRef_fixConj (s);
6811 if (sRef_isLocalVar (s))
6813 result = cstring_makeLiteral ("Variable");
6817 result = cstring_makeLiteral ("Undef global");
6821 result = cstring_makeLiteral ("Out parameter");
6824 if (sRef_isAnyParam (s->info->arrayfetch->arr))
6826 result = cstring_makeLiteral ("Out parameter");
6828 else if (sRef_isIndexKnown (s))
6830 result = cstring_makeLiteral ("Array element");
6834 result = cstring_makeLiteral ("Value");
6838 if (sRef_isAnyParam (s->info->ref))
6840 result = cstring_makeLiteral ("Out parameter");
6844 result = cstring_makeLiteral ("Value");
6848 result = cstring_makeLiteral ("Value");
6851 result = cstring_makeLiteral ("Field");
6854 result = cstring_makeLiteral ("Object");
6856 case SK_UNCONSTRAINED:
6857 result = cstring_makeLiteral ("<anything>");
6866 result = cstring_makeLiteral ("<unknown>");
6869 result = cstring_makeLiteral ("<conj>");
6872 result = cstring_makeLiteral ("Storage");
6880 sRef_unparseKindNamePlain (sRef s)
6884 if (s == sRef_undefined) return cstring_makeLiteral ("<invalid>");
6886 s = sRef_fixConj (s);
6891 if (sRef_isLocalVar (s))
6893 result = cstring_makeLiteral ("Variable");
6897 result = cstring_makeLiteral ("Global");
6901 result = cstring_makeLiteral ("Parameter");
6904 if (sRef_isAnyParam (s->info->arrayfetch->arr))
6906 result = cstring_makeLiteral ("Parameter");
6908 else if (sRef_isIndexKnown (s))
6910 result = cstring_makeLiteral ("Array element");
6914 result = cstring_makeLiteral ("Value");
6918 if (sRef_isAnyParam (s->info->ref))
6920 result = cstring_makeLiteral ("Parameter");
6924 result = cstring_makeLiteral ("Value");
6928 result = cstring_makeLiteral ("Value");
6931 result = cstring_makeLiteral ("Field");
6934 result = cstring_makeLiteral ("Object");
6937 result = cstring_makeLiteral ("Storage");
6939 case SK_UNCONSTRAINED:
6940 result = cstring_makeLiteral ("<anything>");
6949 result = cstring_makeLiteral ("<unknown>");
6952 result = cstring_makeLiteral ("<conj>");
6964 sRef_copyState (sRef s1, sRef s2)
6966 if (sRef_isValid (s1) && sRef_isValid (s2))
6968 s1->defstate = s2->defstate;
6970 /* start modifications */
6971 s1->bufinfo.bufstate = s2->bufinfo.bufstate;
6972 s1->bufinfo.len = s2->bufinfo.len;
6973 s1->bufinfo.size = s2->bufinfo.size;
6974 /* end modifications */
6976 s1->aliaskind = s2->aliaskind;
6977 s1->aliasinfo = stateInfo_update (s1->aliasinfo, s2->aliasinfo);
6979 s1->expkind = s2->expkind;
6980 s1->expinfo = stateInfo_update (s1->expinfo, s2->expinfo);
6982 s1->nullstate = s2->nullstate;
6983 s1->nullinfo = stateInfo_update (s1->nullinfo, s2->nullinfo);
6986 /*@i834 don't free it: valueTable_free (s1->state); */
6987 /*@i32@*/ s1->state = valueTable_copy (s2->state);
6989 s1->safe = s2->safe;
6994 sRef_makeNew (ctype ct, sRef t, cstring name)
6996 sRef s = sRef_newRef ();
7001 llassert (sRef_isValid (t));
7002 s->defstate = t->defstate;
7004 s->aliaskind = t->aliaskind;
7005 s->oaliaskind = s->aliaskind;
7006 s->nullstate = t->nullstate;
7008 s->expkind = t->expkind;
7009 s->oexpkind = s->expkind;
7011 s->info = (sinfo) dmalloc (sizeof (*s->info));
7012 s->info->fname = name;
7014 /* start modifications */
7015 s->bufinfo.bufstate = t->bufinfo.bufstate;
7016 /* end modifications */
7018 llassert (valueTable_isUndefined (s->state));
7019 s->state = valueTable_copy (t->state);
7021 DPRINTF (("==> Copying state: %s", valueTable_unparse (s->state)));
7022 DPRINTF (("==> new: %s", sRef_unparseFull (s)));
7027 sRef_makeType (ctype ct)
7029 sRef s = sRef_newRef ();
7031 sRef_checkMutable (s);
7036 s->defstate = SS_UNKNOWN;
7037 s->aliaskind = AK_UNKNOWN;
7038 sRef_setNullStateN (s, NS_UNKNOWN);
7040 /* start modification */
7041 s->bufinfo.bufstate = BB_NOTNULLTERMINATED;
7042 /* end modification */
7045 if (ctype_isUA (ct))
7047 typeId uid = ctype_typeId (ct);
7048 uentry ue = usymtab_getTypeEntrySafe (uid);
7050 if (uentry_isValid (ue))
7052 sRef_mergeStateQuiet (s, uentry_getSref (ue));
7056 s->oaliaskind = s->aliaskind;
7057 s->oexpkind = s->expkind;
7058 llassert (valueTable_isUndefined (s->state));
7059 s->state = context_createValueTable (s);
7061 DPRINTF (("Create: %s", sRef_unparseFull (s)));
7066 sRef_makeConst (ctype ct)
7068 sRef s = sRef_newRef ();
7073 s->defstate = SS_UNKNOWN;
7074 s->aliaskind = AK_UNKNOWN;
7075 sRef_setNullStateN (s, NS_UNKNOWN);
7077 /* start modification */
7078 s->bufinfo.bufstate = BB_NULLTERMINATED;
7079 /* end modification */
7082 if (ctype_isUA (ct))
7084 typeId uid = ctype_typeId (ct);
7085 uentry te = usymtab_getTypeEntrySafe (uid);
7087 if (uentry_isValid (te))
7089 sRef_mergeStateQuiet (s, uentry_getSref (te));
7094 s->oaliaskind = s->aliaskind;
7095 s->oexpkind = s->expkind;
7097 llassert (valueTable_isUndefined (s->state));
7098 s->state = context_createValueTable (s);
7103 bool sRef_hasName (sRef s)
7105 if (sRef_isInvalid (s))
7114 uentry u = usymtab_getRefQuiet (s->info->cvar->lexlevel,
7115 s->info->cvar->index);
7116 return (uentry_hasName (u));
7120 if (s->info->paramno >= 0)
7122 uentry u = uentryList_getN (context_getParams (),
7125 return (uentry_hasName (u));
7129 llassert (s->info->paramno == PARAMUNKNOWN);
7139 sRef_sameName (sRef s1, sRef s2)
7141 if (sRef_isInvalid (s1))
7143 return sRef_isInvalid (s2);
7146 if (sRef_isInvalid (s2))
7154 if (s2->kind == SK_CVAR)
7156 return (s1->info->cvar->lexlevel == s2->info->cvar->lexlevel
7157 && s1->info->cvar->index == s2->info->cvar->index);
7159 else if (s2->kind == SK_PARAM)
7161 if (context_inFunctionLike ())
7163 if (s2->info->paramno != PARAMUNKNOWN)
7165 uentry u1 = usymtab_getRefQuiet (s1->info->cvar->lexlevel,
7166 s1->info->cvar->index);
7167 uentry u2 = uentryList_getN (context_getParams (),
7170 return (cstring_equalFree (uentry_getName (u1),
7171 uentry_getName (u2)));
7175 return s1->info->paramno == PARAMUNKNOWN;
7189 if (s2->kind == SK_PARAM)
7191 return (s1->info->paramno == s2->info->paramno);
7193 else if (s2->kind == SK_CVAR)
7195 if (context_inFunctionLike ())
7197 if (s1->info->paramno == PARAMUNKNOWN)
7203 uentry u1 = uentryList_getN (context_getParams (),
7205 uentry u2 = usymtab_getRefQuiet (s2->info->cvar->lexlevel,
7206 s2->info->cvar->index);
7209 return (cstring_equalFree (uentry_getName (u1),
7210 uentry_getName (u2)));
7224 case SK_UNCONSTRAINED:
7228 if (s2->kind == SK_ARRAYFETCH)
7230 if (bool_equal (s1->info->arrayfetch->indknown,
7231 s2->info->arrayfetch->indknown))
7233 if (!s1->info->arrayfetch->indknown
7234 || (s1->info->arrayfetch->ind == s2->info->arrayfetch->ind))
7236 return sRef_sameName (s1->info->arrayfetch->arr,
7237 s2->info->arrayfetch->arr);
7244 if (s2->kind == SK_FIELD)
7246 if (cstring_equal (s1->info->field->field,
7247 s2->info->field->field))
7249 return sRef_sameName (s1->info->field->rec,
7250 s2->info->field->rec);
7259 if (s2->kind == s1->kind)
7261 return sRef_sameName (s1->info->ref,
7269 return sRef_sameName (sRef_getConjA (s1), s2);
7273 return (s2->kind == SK_UNKNOWN);
7276 if (s2->kind == s1->kind)
7278 return (ctype_equal (s1->type, s2->type));
7283 if (s2->kind == SK_SPECIAL)
7285 return (s1->info->spec == s2->info->spec);
7289 return (s2->kind == SK_RESULT);
7297 sRef_fixOuterRef (/*@returned@*/ sRef s)
7299 sRef root = sRef_getRootBase (s);
7301 if (sRef_isCvar (root))
7303 uentry ue = usymtab_getRefQuiet (root->info->cvar->lexlevel,
7304 root->info->cvar->index);
7306 if (uentry_isValid (ue))
7308 sRef uref = uentry_getSref (ue);
7309 sRef sr = sRef_fixBase (s, uref);
7315 llcontbug (message ("sRef_fixOuterRef: undefined: %q", sRef_unparseDebug (s)));
7324 sRef_storeState (sRef s)
7326 if (sRef_isInvalid (s)) return;
7328 sRef_checkMutable (s);
7329 s->oaliaskind = s->aliaskind;
7330 s->oexpkind = s->expkind;
7333 static void sRef_resetStateAux (sRef s, /*@unused@*/ fileloc loc)
7335 sRef_resetState (s);
7339 sRef_resetState (sRef s)
7341 bool changed = FALSE;
7342 if (sRef_isInvalid (s)) return;
7345 if (s->oaliaskind == AK_KILLREF && !sRef_isParam (s))
7348 ** killref is used in a kludgey way, to save having to add
7349 ** another alias kind (see usymtab_handleParams)
7352 if (s->expkind != s->oexpkind)
7355 s->expkind = s->oexpkind;
7360 if (s->expkind != s->oexpkind)
7363 s->expkind = s->oexpkind;
7366 if (s->aliaskind != s->oaliaskind
7367 && s->aliaskind != AK_REFCOUNTED
7368 && s->aliaskind != AK_REFS)
7371 s->aliaskind = s->oaliaskind;
7377 sRef_clearDerived (s);
7383 sRef_resetStateComplete (sRef s)
7385 sRef_innerAliasSetComplete (sRef_resetStateAux, s, fileloc_undefined);
7389 sRef_fixBase (/*@returned@*/ sRef s, /*@returned@*/ sRef base)
7391 sRef tmp = sRef_undefined;
7394 if (sRef_isInvalid (s)) return s;
7395 if (sRef_isInvalid (base)) return base;
7405 tmp = sRef_fixBase (s->info->arrayfetch->arr, base);
7407 if (s->info->arrayfetch->indknown)
7409 ret = sRef_makeArrayFetchKnown (tmp, s->info->arrayfetch->ind);
7413 ret = sRef_makeArrayFetch (tmp);
7417 tmp = sRef_fixBase (s->info->field->rec, base);
7418 ret = sRef_buildNCField (tmp, s->info->field->field);
7421 tmp = sRef_fixBase (s->info->ref, base);
7422 ret = sRef_makePointer (tmp);
7425 tmp = sRef_fixBase (s->info->ref, base);
7426 ret = sRef_makeAddress (tmp);
7432 tmp = sRef_fixBase (s->info->conj->a, base);
7433 tmpb = sRef_fixBase (s->info->conj->b, base);
7435 ret = sRef_makeConj (tmp, tmpb);
7444 static /*@exposed@*/ sRef
7445 sRef_fixDirectBase (sRef s, sRef base)
7450 if (sRef_isInvalid (s))
7452 return sRef_undefined;
7458 if (s->info->arrayfetch->indknown)
7460 ret = sRef_makeArrayFetchKnown (base, s->info->arrayfetch->ind);
7464 ret = sRef_makeArrayFetch (base);
7468 ret = sRef_buildNCField (base, s->info->field->field);
7471 ret = sRef_makePointer (base);
7474 ret = sRef_makeAddress (base);
7480 tmpa = sRef_fixDirectBase (s->info->conj->a, base);
7481 tmpb = sRef_fixDirectBase (s->info->conj->b, base);
7483 ret = sRef_makeConj (tmpa, tmpb);
7489 sRef_copyState (ret, s);
7494 sRef_isAllocIndexRef (sRef s)
7496 return (sRef_isArrayFetch (s) && !(s->info->arrayfetch->indknown)
7497 && sRef_isAllocated (s->info->arrayfetch->arr));
7501 sRef_showRefLost (sRef s)
7503 if (sRef_hasAliasInfoLoc (s))
7505 llgenindentmsg (cstring_makeLiteral ("Original reference lost"),
7506 sRef_getAliasInfoLoc (s));
7511 sRef_showRefKilled (sRef s)
7513 if (sRef_hasStateInfoLoc (s))
7515 llgenindentmsg (message ("Storage %q released",
7516 sRef_unparse (s)), sRef_getStateInfoLoc (s));
7521 sRef_showStateInconsistent (sRef s)
7523 if (sRef_hasStateInfoLoc (s))
7526 (message ("Storage %qbecomes inconsistent (released on one branch)",
7527 sRef_unparseOpt (s)),
7528 sRef_getStateInfoLoc (s));
7533 sRef_showStateInfo (sRef s)
7535 if (sRef_hasStateInfoLoc (s))
7537 if (s->defstate == SS_DEAD)
7540 (message ("Storage %qis released", sRef_unparseOpt (s)),
7541 sRef_getStateInfoLoc (s));
7543 else if (s->defstate == SS_ALLOCATED || s->defstate == SS_DEFINED)
7546 (message ("Storage %qis %s", sRef_unparseOpt (s),
7547 sstate_unparse (s->defstate)),
7548 sRef_getStateInfoLoc (s));
7550 else if (s->defstate == SS_UNUSEABLE)
7553 (message ("Storage %qbecomes inconsistent (clauses merge with"
7554 "%qreleased on one branch)",
7555 sRef_unparseOpt (s),
7556 sRef_unparseOpt (s)),
7557 sRef_getStateInfoLoc (s));
7561 llgenindentmsg (message ("Storage %qbecomes %s",
7562 sRef_unparseOpt (s),
7563 sstate_unparse (s->defstate)),
7564 sRef_getStateInfoLoc (s));
7570 sRef_showExpInfo (sRef s)
7572 if (sRef_hasExpInfoLoc (s))
7574 llgenindentmsg (message ("Storage %qbecomes %s", sRef_unparseOpt (s),
7575 exkind_unparse (s->expkind)),
7576 sRef_getExpInfoLoc (s));
7581 sRef_showMetaStateInfo (sRef s, cstring key)
7584 metaStateInfo minfo = context_lookupMetaStateInfo (key);
7586 llassert (sRef_isValid (s));
7587 llassert (valueTable_isDefined (s->state));
7588 llassert (metaStateInfo_isDefined (minfo));
7590 val = valueTable_lookup (s->state, key);
7592 if (stateValue_hasLoc (val))
7595 (message ("Meta state %qbecomes %q", sRef_unparseOpt (s),
7596 stateValue_unparseValue (val, minfo)),
7597 stateValue_getLoc (val));
7602 sRef_showNullInfo (sRef s)
7604 DPRINTF (("Show null info: %s", sRef_unparseFull (s)));
7606 if (sRef_hasNullInfoLoc (s) && sRef_isKnown (s))
7608 DPRINTF (("has null info: %s",
7609 fileloc_unparse (sRef_getNullInfoLoc (s))));
7611 switch (sRef_getNullState (s))
7615 fileloc loc = sRef_getNullInfoLoc (s);
7617 if (fileloc_isDefined (loc) && !fileloc_isLib (loc))
7620 (message ("Storage %qbecomes null", sRef_unparseOpt (s)),
7627 fileloc loc = sRef_getNullInfoLoc (s);
7629 if (fileloc_isDefined (loc) && !fileloc_isLib (loc))
7631 llgenindentmsg (message ("Storage %qbecomes null", sRef_unparseOpt (s)),
7639 (message ("Storage %qmay become null", sRef_unparseOpt (s)),
7640 sRef_getNullInfoLoc (s));
7645 (message ("Storage %qbecomes not null", sRef_unparseOpt (s)),
7646 sRef_getNullInfoLoc (s));
7650 (message ("Storage %qnull state becomes unknown",
7651 sRef_unparseOpt (s)),
7652 sRef_getNullInfoLoc (s));
7661 (message ("<error case> Storage %q becomes %s",
7663 nstate_unparse (sRef_getNullState (s))),
7664 sRef_getNullInfoLoc (s));
7672 sRef_showAliasInfo (sRef s)
7674 if (sRef_hasAliasInfoLoc (s))
7676 if (sRef_isFresh (s))
7679 (message ("Fresh storage %qallocated", sRef_unparseOpt (s)),
7680 sRef_getAliasInfoLoc (s));
7684 if (!sRef_isRefCounted (s))
7687 (message ("Storage %qbecomes %s",
7688 sRef_unparseOpt (s),
7689 alkind_unparse (sRef_getAliasKind (s))),
7690 sRef_getAliasInfoLoc (s));
7697 sRef_mergeNullState (sRef s, nstate n)
7699 if (sRef_isValid (s))
7703 old = sRef_getNullState (s);
7705 if (n != old && n != NS_UNKNOWN)
7707 sRef_setNullState (s, n, g_currentloc);
7712 llbuglit ("sRef_mergeNullState: invalid");
7717 sRef_possiblyNull (sRef s)
7719 if (sRef_isValid (s))
7721 if (sRef_getNullState (s) == NS_ABSNULL)
7723 ctype rct = ctype_realType (s->type);
7725 if (ctype_isAbstract (rct))
7731 if (ctype_isUser (rct))
7733 uentry ue = usymtab_getTypeEntry (ctype_typeId (rct));
7735 return (nstate_possiblyNull
7736 (sRef_getNullState (uentry_getSref (ue))));
7746 return nstate_possiblyNull (sRef_getNullState (s));
7754 sRef_getScopeName (sRef s)
7756 sRef base = sRef_getRootBase (s);
7758 if (sRef_isRealGlobal (base))
7760 return (cstring_makeLiteralTemp ("Global"));
7762 else if (sRef_isFileStatic (base))
7764 return (cstring_makeLiteralTemp ("Static"));
7768 return (cstring_makeLiteralTemp ("Local"));
7773 sRef_unparseScope (sRef s)
7775 sRef base = sRef_getRootBase (s);
7777 if (sRef_isRealGlobal (base))
7779 return (cstring_makeLiteralTemp ("global"));
7781 else if (sRef_isFileStatic (base))
7783 return (cstring_makeLiteralTemp ("file static"));
7792 sRef_getScope (sRef s)
7794 llassert (sRef_isValid (s));
7796 if (sRef_isCvar (s))
7798 return s->info->cvar->lexlevel;
7800 else if (sRef_isParam (s))
7811 sRef_isDead (sRef s)
7813 return (sRef_isValid (s) && (s)->defstate == SS_DEAD);
7817 sRef_isDeadStorage (sRef s)
7819 if (sRef_isValid (s))
7821 if (s->defstate == SS_DEAD
7822 || s->defstate == SS_UNUSEABLE
7823 || s->defstate == SS_UNDEFINED
7824 || s->defstate == SS_UNKNOWN)
7830 return (sRef_isDefinitelyNull (s));
7840 sRef_isPossiblyDead (sRef s)
7842 return (sRef_isValid (s) && s->defstate == SS_HOFFA);
7845 bool sRef_isStateLive (sRef s)
7847 if (sRef_isValid (s))
7849 sstate ds = s->defstate;
7851 return (!(ds == SS_UNDEFINED
7853 || ds == SS_UNUSEABLE
7854 || ds == SS_HOFFA));
7863 bool sRef_isStateUndefined (sRef s)
7865 return ((sRef_isValid(s)) && ((s)->defstate == SS_UNDEFINED));
7868 bool sRef_isJustAllocated (sRef s)
7870 if (sRef_isAllocated (s))
7872 sRefSet_allElements (s->deriv, el)
7874 if (!(sRef_isStateUndefined (el) || sRef_isUnuseable (el)))
7878 } end_sRefSet_allElements ;
7887 sRef_isAllocatedStorage (sRef s)
7889 if (sRef_isValid (s) && ynm_toBoolStrict (sRef_isReadable (s)))
7891 return (ctype_isVisiblySharable (sRef_getType (s)));
7900 sRef_isUnuseable (sRef s)
7902 return ((sRef_isValid(s)) && ((s)->defstate == SS_UNUSEABLE));
7906 sRef_perhapsNull (sRef s)
7908 if (sRef_isValid (s))
7910 if (sRef_getNullState (s) == NS_ABSNULL)
7912 ctype rct = ctype_realType (s->type);
7914 if (ctype_isAbstract (rct))
7920 if (ctype_isUser (rct))
7922 uentry ue = usymtab_getTypeEntry (ctype_typeId (rct));
7924 return (nstate_perhapsNull
7925 (sRef_getNullState (uentry_getSref (ue))));
7935 return nstate_perhapsNull (sRef_getNullState (s));
7943 ** definitelyNull --- called when TRUE is good
7947 sRef_definitelyNull (sRef s)
7949 return (sRef_isValid (s)
7950 && (sRef_getNullState (s) == NS_DEFNULL || sRef_getNullState (s) == NS_CONSTNULL));
7954 ** based on sRef_similar
7958 sRef_setDerivNullState (sRef set, sRef guide, nstate ns)
7960 if (sRef_isValid (set))
7962 sRef deriv = sRef_getDeriv (set, guide);
7964 if (sRef_isValid (deriv))
7966 sRef_setNullStateN (deriv, ns);
7971 static /*@exposed@*/ sRef
7972 sRef_getDeriv (/*@returned@*/ /*@notnull@*/ sRef set, sRef guide)
7974 llassert (sRef_isValid (set));
7975 llassert (sRef_isValid (guide));
7977 switch (guide->kind)
7980 llassert (set->kind == SK_CVAR);
7985 llassert (set->kind == guide->kind);
7986 llassert (set->info->paramno == guide->info->paramno);
7992 if (set->kind == SK_ARRAYFETCH
7993 && (sRef_similar (set->info->arrayfetch->arr,
7994 guide->info->arrayfetch->arr)))
8000 return (sRef_makeAnyArrayFetch
8001 (sRef_getDeriv (set, guide->info->arrayfetch->arr)));
8006 if (set->kind == SK_PTR && sRef_similar (set->info->ref, guide->info->ref))
8012 return (sRef_makePointer (sRef_getDeriv (set, guide->info->ref)));
8017 if ((set->kind == SK_FIELD &&
8018 (sRef_similar (set->info->field->rec, guide->info->field->rec) &&
8019 cstring_equal (set->info->field->field, guide->info->field->field))))
8025 return (sRef_makeField (sRef_getDeriv (set, guide->info->field->rec),
8026 guide->info->field->field));
8030 if ((set->kind == SK_ADR) && sRef_similar (set->info->ref, guide->info->ref))
8036 return (sRef_makeAddress (sRef_getDeriv (set, guide->info->ref)));
8041 return sRef_undefined;
8045 case SK_UNCONSTRAINED:
8053 return sRef_undefined;
8060 ** sRef_aliasCheckPred
8062 ** A confusing but spiffy function:
8064 ** Calls predf (s, e, text, <alias>) on s and all of s's aliases
8065 ** (unless checkAliases (s) is FALSE).
8067 ** For alias calls, calls as
8068 ** predf (alias, e, text, s)
8072 sRef_aliasCheckPred (bool (predf) (sRef, exprNode, sRef, exprNode),
8073 /*@null@*/ bool (checkAliases) (sRef),
8074 sRef s, exprNode e, exprNode err)
8076 bool error = (*predf)(s, e, sRef_undefined, err);
8079 if (checkAliases != NULL && !(checkAliases (s)))
8081 /* don't check aliases */
8085 sRefSet aliases = usymtab_allAliases (s);
8088 sRefSet_realElements (aliases, current)
8090 if (sRef_isValid (current))
8092 if (!sRef_similar (current, s)
8093 || (error && sRef_sameName (current, s)))
8095 (void) (*predf)(current, e, s, err);
8098 } end_sRefSet_realElements;
8100 sRefSet_free (aliases);
8105 ** return TRUE iff predf (s) is true for s or any alias of s
8109 sRef_aliasCheckSimplePred (sRefTest predf, sRef s)
8120 aliases = usymtab_allAliases (s);
8122 sRefSet_realElements (aliases, current)
8124 if (sRef_isValid (current))
8126 sRef cref = sRef_updateSref (current);
8128 /* Whoa! a very kludgey way to make sure the right sref is used
8129 ** where there is a conditional symbol table. I am beginning
8130 ** to think that having a conditional symbol table wasn't such
8136 DPRINTF (("Checking alias: %s", sRef_unparseFull (cref)));
8137 sRefSet_free (aliases);
8141 } end_sRefSet_realElements;
8143 sRefSet_free (aliases);
8149 sRef_aliasCompleteSimplePred (bool (predf) (sRef), sRef s)
8152 bool result = FALSE;
8155 aliases = usymtab_allAliases (s);
8157 if ((*predf)(s)) result = TRUE;
8160 sRefSet_realElements (aliases, current)
8162 if (sRef_isValid (current))
8164 current = sRef_updateSref (current);
8165 if ((*predf)(current)) result = TRUE;
8167 } end_sRefSet_realElements;
8169 sRefSet_free (aliases);
8174 sRef_aliasSetComplete (void (predf) (sRef, fileloc), sRef s, fileloc loc)
8178 aliases = usymtab_allAliases (s);
8180 DPRINTF (("All aliases: %s", sRefSet_unparseFull (aliases)));
8184 sRefSet_realElements (aliases, current)
8186 if (sRef_isValid (current))
8188 current = sRef_updateSref (current);
8189 ((*predf)(current, loc));
8191 } end_sRefSet_realElements;
8193 sRefSet_free (aliases);
8197 sRef_aliasSetCompleteParam (void (predf) (sRef, alkind, fileloc), sRef s,
8198 alkind kind, fileloc loc)
8203 if (sRef_isDeep (s))
8205 aliases = usymtab_allAliases (s);
8209 aliases = usymtab_aliasedBy (s);
8212 (*predf)(s, kind, loc);
8214 sRefSet_realElements (aliases, current)
8216 if (sRef_isValid (current))
8218 current = sRef_updateSref (current);
8219 ((*predf)(current, kind, loc));
8221 } end_sRefSet_realElements;
8223 sRefSet_free (aliases);
8227 sRef_innerAliasSetComplete (void (predf) (sRef, fileloc), sRef s, fileloc loc)
8233 if (!sRef_isValid (s)) return;
8237 ** Type equivalence checking is necessary --- there might be casting.
8244 case SK_UNCONSTRAINED:
8249 inner = s->info->ref;
8250 aliases = usymtab_allAliases (inner);
8251 ct = sRef_getType (inner);
8254 sRefSet_realElements (aliases, current)
8256 if (sRef_isValid (current))
8258 current = sRef_updateSref (current);
8260 if (ctype_equal (ct, sRef_getType (current)))
8262 sRef ptr = sRef_makePointer (current);
8263 ((*predf)(ptr, loc));
8266 } end_sRefSet_realElements;
8268 sRefSet_free (aliases);
8271 inner = s->info->arrayfetch->arr;
8272 aliases = usymtab_allAliases (inner);
8273 ct = sRef_getType (inner);
8275 sRefSet_realElements (aliases, current)
8277 if (sRef_isValid (current))
8279 current = sRef_updateSref (current);
8281 if (ctype_equal (ct, sRef_getType (current)))
8284 if (s->info->arrayfetch->indknown)
8286 sRef af = sRef_makeArrayFetchKnown (current, s->info->arrayfetch->ind);
8288 ((*predf)(af, loc));
8292 sRef af = sRef_makeArrayFetch (current);
8294 ((*predf)(af, loc));
8298 } end_sRefSet_realElements;
8300 sRefSet_free (aliases);
8303 inner = s->info->field->rec;
8304 aliases = usymtab_allAliases (inner);
8305 ct = sRef_getType (inner);
8308 sRefSet_realElements (aliases, current)
8310 if (sRef_isValid (current))
8312 current = sRef_updateSref (current);
8314 if (ctype_equal (ct, sRef_getType (current)))
8316 sRef f = sRef_makeField (current, s->info->field->field);
8321 } end_sRefSet_realElements;
8323 sRefSet_free (aliases);
8326 sRef_innerAliasSetComplete (predf, s->info->conj->a, loc);
8327 sRef_innerAliasSetComplete (predf, s->info->conj->b, loc);
8344 sRef_innerAliasSetCompleteParam (void (predf) (sRef, sRef), sRef s, sRef t)
8350 if (!sRef_isValid (s)) return;
8354 ** Type equivalence checking is necessary --- there might be casting.
8361 case SK_UNCONSTRAINED:
8366 inner = s->info->ref;
8367 aliases = usymtab_allAliases (inner);
8368 ct = sRef_getType (inner);
8371 sRefSet_realElements (aliases, current)
8373 if (sRef_isValid (current))
8375 current = sRef_updateSref (current);
8377 if (ctype_equal (ct, sRef_getType (current)))
8379 sRef ptr = sRef_makePointer (current);
8384 } end_sRefSet_realElements;
8386 sRefSet_free (aliases);
8389 inner = s->info->arrayfetch->arr;
8390 aliases = usymtab_allAliases (inner);
8391 ct = sRef_getType (inner);
8393 sRefSet_realElements (aliases, current)
8395 if (sRef_isValid (current))
8397 current = sRef_updateSref (current);
8399 if (ctype_equal (ct, sRef_getType (current)))
8402 if (s->info->arrayfetch->indknown)
8404 sRef af = sRef_makeArrayFetchKnown (current, s->info->arrayfetch->ind);
8410 sRef af = sRef_makeArrayFetch (current);
8416 } end_sRefSet_realElements;
8418 sRefSet_free (aliases);
8421 inner = s->info->field->rec;
8422 aliases = usymtab_allAliases (inner);
8423 ct = sRef_getType (inner);
8426 sRefSet_realElements (aliases, current)
8428 if (sRef_isValid (current))
8430 current = sRef_updateSref (current);
8432 if (ctype_equal (ct, sRef_getType (current)))
8434 sRef f = sRef_makeField (current, s->info->field->field);
8439 } end_sRefSet_realElements;
8441 sRefSet_free (aliases);
8444 sRef_innerAliasSetCompleteParam (predf, s->info->conj->a, t);
8445 sRef_innerAliasSetCompleteParam (predf, s->info->conj->b, t);
8461 static void sRef_combineExKinds (/*@notnull@*/ sRef res, /*@notnull@*/ sRef other)
8463 exkind a1 = sRef_getExKind (res);
8464 exkind a2 = sRef_getExKind (other);
8466 if (a1 == a2 || a2 == XO_UNKNOWN)
8470 else if (a1 == XO_UNKNOWN)
8472 res->expinfo = stateInfo_update (res->expinfo, other->expinfo);
8477 res->expkind = XO_OBSERVER;
8482 ** Currently, this is a very ad hoc implementation, with lots of fixes to
8483 ** make real code work okay. I need to come up with some more general
8484 ** rules or principles here.
8488 sRef_combineAliasKindsError (/*@notnull@*/ sRef res,
8489 /*@notnull@*/ sRef other,
8490 clause cl, fileloc loc)
8492 bool hasError = FALSE;
8493 alkind ares = sRef_getAliasKind (res);
8494 alkind aother = sRef_getAliasKind (other);
8496 sRef_checkMutable (res);
8498 if (alkind_isDependent (ares))
8500 if (aother == AK_KEPT)
8502 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8503 res->aliaskind = AK_KEPT;
8507 if (aother == AK_LOCAL || aother == AK_STATIC
8508 || alkind_isTemp (aother))
8510 DPRINTF (("Setting dependent: %s", sRef_unparseFull (res)));
8511 res->aliaskind = AK_DEPENDENT;
8515 else if (alkind_isDependent (aother))
8517 if (ares == AK_KEPT)
8519 res->aliaskind = AK_KEPT;
8523 if (ares == AK_LOCAL || ares == AK_STATIC || alkind_isTemp (ares))
8525 DPRINTF (("Setting dependent: %s", sRef_unparseFull (res)));
8526 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8527 res->aliaskind = AK_DEPENDENT;
8531 else if ((ares == AK_LOCAL || ares == AK_UNIQUE
8532 || ares == AK_STATIC || alkind_isTemp (ares))
8533 && sRef_isFresh (other))
8536 ** cases like: if (s == NULL) s = malloc...;
8537 ** don't generate errors
8540 if (usymtab_isAltDefinitelyNullDeep (res))
8542 res->aliaskind = ares;
8549 else if ((aother == AK_LOCAL || aother == AK_UNIQUE
8550 || aother == AK_STATIC || alkind_isTemp (aother))
8551 && sRef_isFresh (res))
8554 ** cases like: if (s == NULL) s = malloc...;
8555 ** don't generate errors
8558 if (usymtab_isDefinitelyNullDeep (other))
8560 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8561 res->aliaskind = aother;
8568 else if (ares == AK_NEWREF && aother == AK_REFCOUNTED
8569 && sRef_isConst (other))
8571 res->aliaskind = AK_NEWREF;
8573 else if (aother == AK_NEWREF && ares == AK_REFCOUNTED
8574 && sRef_isConst (res))
8576 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8577 res->aliaskind = AK_NEWREF;
8579 else if (sRef_isLocalVar (res)
8580 && ((ares == AK_KEPT && aother == AK_LOCAL)
8581 || (aother == AK_KEPT && ares == AK_LOCAL)))
8583 res->aliaskind = AK_KEPT;
8592 if (sRef_isThroughArrayFetch (res))
8595 (FLG_BRANCHSTATE, FLG_STRICTBRANCHSTATE,
8597 ("Clauses exit with %q possibly referencing %s storage %s, "
8600 alkind_unparse (aother),
8601 clause_nameTaken (cl),
8602 alkind_unparse (ares),
8603 clause_nameAlternate (cl)),
8606 sRef_showAliasInfo (res);
8607 sRef_showAliasInfo (other);
8608 res->aliaskind = AK_ERROR;
8612 if (ares == AK_KEPT || aother == AK_KEPT)
8614 sRef_maybeKill (res, loc);
8622 message ("Clauses exit with %q referencing %s storage %s, "
8625 alkind_unparse (aother),
8626 clause_nameTaken (cl),
8627 alkind_unparse (ares),
8628 clause_nameAlternate (cl)),
8631 sRef_showAliasInfo (res);
8632 sRef_showAliasInfo (other);
8634 res->aliaskind = AK_ERROR;
8638 res->aliaskind = (sRef_isLocalVar (res) ? AK_LOCAL : AK_UNKNOWN);
8643 sRef_combineAliasKinds (/*@notnull@*/ sRef res, /*@notnull@*/ sRef other,
8644 clause cl, fileloc loc)
8646 alkind ares = sRef_getAliasKind (res);
8647 alkind aother = sRef_getAliasKind (other);
8649 sRef_checkMutable (res);
8651 if (alkind_equal (ares, aother)
8652 || aother == AK_UNKNOWN
8653 || aother == AK_ERROR)
8655 ; /* keep current state */
8657 else if (sRef_isDead (res) || sRef_isDead (other))
8659 /* dead error reported (or storage is dead) */
8660 res ->aliaskind = AK_ERROR;
8662 else if (ares == AK_UNKNOWN || ares == AK_ERROR
8663 || sRef_isStateUndefined (res))
8665 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8666 res->aliaskind = aother;
8668 else if (sRef_isStateUndefined (other))
8672 else if (((ares == AK_UNIQUE || alkind_isTemp (ares))
8673 && aother == AK_LOCAL)
8674 || ((aother == AK_UNIQUE || alkind_isTemp (aother))
8675 && ares == AK_LOCAL))
8677 if (ares != AK_LOCAL)
8679 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8682 res->aliaskind = AK_LOCAL;
8684 else if ((ares == AK_OWNED && aother == AK_FRESH)
8685 || (aother == AK_OWNED && ares == AK_FRESH))
8687 if (ares != AK_FRESH)
8689 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8692 res->aliaskind = AK_FRESH;
8694 else if ((ares == AK_KEEP && aother == AK_FRESH) ||
8695 (aother == AK_KEEP && ares == AK_FRESH))
8697 if (ares != AK_KEEP)
8699 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8702 res->aliaskind = AK_KEEP;
8704 else if ((ares == AK_LOCAL && aother == AK_STACK) ||
8705 (aother == AK_LOCAL && ares == AK_STACK))
8707 if (ares != AK_STACK)
8709 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8712 res->aliaskind = AK_STACK;
8714 else if ((ares == AK_LOCAL
8715 && (aother == AK_OWNED && sRef_isLocalVar (other)))
8716 || (aother == AK_LOCAL
8717 && (ares == AK_OWNED && sRef_isLocalVar (res))))
8719 if (ares != AK_LOCAL)
8721 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8724 res->aliaskind = AK_LOCAL;
8726 else if ((ares == AK_FRESH && alkind_isOnly (aother))
8727 || (aother == AK_FRESH && alkind_isOnly (ares)))
8729 res->aliaskind = AK_FRESH;
8731 else if ((aother == AK_FRESH && sRef_definitelyNull (res))
8732 || (ares == AK_FRESH && sRef_definitelyNull (other)))
8734 if (ares != AK_FRESH)
8736 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8737 res->aliaskind = AK_FRESH;
8740 else if ((sRef_isFresh (res) && sRef_isConst (other))
8741 || (sRef_isFresh (other) && sRef_isConst (res)))
8744 ** for NULL constantants
8748 if (!sRef_isFresh (res))
8750 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8753 res->aliaskind = AK_FRESH;
8755 else if ((alkind_isStatic (aother) && sRef_isConst (res))
8756 || (alkind_isStatic (ares) && sRef_isConst (other)))
8758 if (!alkind_isStatic (ares))
8760 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8761 res->aliaskind = AK_STATIC;
8766 sRef_combineAliasKindsError (res, other, cl, loc);
8770 static void sRef_combineDefState (/*@notnull@*/ sRef res,
8771 /*@notnull@*/ sRef other)
8773 sstate s1 = res->defstate;
8774 sstate s2 = other->defstate;
8777 sRef_checkMutable (res);
8779 if (s1 == s2 || s2 == SS_UNKNOWN)
8783 else if (s1 == SS_UNKNOWN)
8792 if (s2 == SS_DEFINED)
8798 llcontbuglit ("ssfixed: not implemented");
8807 flip = (s2 != SS_DEFINED);
8825 res->definfo = stateInfo_update (res->definfo, other->definfo);
8830 extern /*@notnull@*/ sRef sRef_getConjA (sRef s)
8833 llassert (sRef_isConj (s));
8835 ret = s->info->conj->a;
8836 llassert (ret != NULL);
8840 extern /*@notnull@*/ sRef sRef_getConjB (sRef s)
8843 llassert (sRef_isConj (s));
8845 ret = s->info->conj->b;
8846 llassert (ret != NULL);
8850 extern /*@exposed@*/ sRef sRef_makeArrow (sRef s, /*@dependent@*/ cstring f)
8855 p = sRef_makePointer (s);
8856 ret = sRef_makeField (p, f);
8860 extern /*@exposed@*/ sRef sRef_buildArrow (sRef s, cstring f)
8865 p = sRef_buildPointer (s);
8866 ret = sRef_buildField (p, f);
8871 static /*@null@*/ sinfo sinfo_copy (/*@notnull@*/ sRef s)
8878 ret = (sinfo) dmalloc (sizeof (*ret));
8879 ret->cvar = (cref) dmalloc (sizeof (*ret->cvar));
8880 ret->cvar->lexlevel = s->info->cvar->lexlevel;
8881 ret->cvar->index = s->info->cvar->index;
8885 ret = (sinfo) dmalloc (sizeof (*ret));
8886 ret->paramno = s->info->paramno;
8887 llassert (ret->paramno >= -1);
8891 ret = (sinfo) dmalloc (sizeof (*ret));
8892 ret->arrayfetch = (ainfo) dmalloc (sizeof (*ret->arrayfetch));
8893 ret->arrayfetch->indknown = s->info->arrayfetch->indknown;
8894 ret->arrayfetch->ind = s->info->arrayfetch->ind;
8895 ret->arrayfetch->arr = s->info->arrayfetch->arr; /* sRef_copy (s->info->arrayfetch->arr); */ /*@i32@*/
8899 ret = (sinfo) dmalloc (sizeof (*ret));
8900 ret->field = (fldinfo) dmalloc (sizeof (*ret->field));
8901 ret->field->rec = s->info->field->rec; /* sRef_copy (s->info->field->rec); */ /*@i32@*/
8902 ret->field->field = s->info->field->field;
8906 ret = (sinfo) dmalloc (sizeof (*ret));
8907 ret->object = s->info->object;
8914 ret = (sinfo) dmalloc (sizeof (*ret));
8915 ret->ref = s->info->ref; /* Ref_copy (s->info->ref); */
8919 ret = (sinfo) dmalloc (sizeof (*ret));
8920 ret->conj = (cjinfo) dmalloc (sizeof (*ret->conj));
8921 ret->conj->a = s->info->conj->a; /* sRef_copy (s->info->conj->a); */
8922 ret->conj->b = s->info->conj->b; /* sRef_copy (s->info->conj->b);*/
8925 ret = (sinfo) dmalloc (sizeof (*ret));
8926 ret->spec = s->info->spec;
8928 case SK_UNCONSTRAINED:
8930 ret = (sinfo) dmalloc (sizeof (*ret));
8931 ret->fname = s->info->fname;
8937 llassertprint (s->info == NULL, ("s = %s", sRef_unparse (s)));
8945 static /*@null@*/ sinfo sinfo_fullCopy (/*@notnull@*/ sRef s)
8950 ** Since its a full copy, only storage is assigned
8951 ** to dependent fields.
8958 ret = (sinfo) dmalloc (sizeof (*ret));
8959 ret->cvar = (cref) dmalloc (sizeof (*ret->cvar));
8960 ret->cvar->lexlevel = s->info->cvar->lexlevel;
8961 ret->cvar->index = s->info->cvar->index;
8965 ret = (sinfo) dmalloc (sizeof (*ret));
8966 ret->paramno = s->info->paramno;
8967 llassert (ret->paramno >= -1);
8971 ret = (sinfo) dmalloc (sizeof (*ret));
8972 ret->arrayfetch = (ainfo) dmalloc (sizeof (*ret->arrayfetch));
8973 ret->arrayfetch->indknown = s->info->arrayfetch->indknown;
8974 ret->arrayfetch->ind = s->info->arrayfetch->ind;
8975 ret->arrayfetch->arr = sRef_saveCopy (s->info->arrayfetch->arr);
8979 ret = (sinfo) dmalloc (sizeof (*ret));
8980 ret->field = (fldinfo) dmalloc (sizeof (*ret->field));
8981 ret->field->rec = sRef_saveCopy (s->info->field->rec);
8982 ret->field->field = s->info->field->field;
8986 ret = (sinfo) dmalloc (sizeof (*ret));
8987 ret->object = s->info->object;
8994 ret = (sinfo) dmalloc (sizeof (*ret));
8995 ret->ref = sRef_saveCopy (s->info->ref);
8999 ret = (sinfo) dmalloc (sizeof (*ret));
9000 ret->conj = (cjinfo) dmalloc (sizeof (*ret->conj));
9001 ret->conj->a = sRef_saveCopy (s->info->conj->a);
9002 ret->conj->b = sRef_saveCopy (s->info->conj->b);
9005 ret = (sinfo) dmalloc (sizeof (*ret));
9006 ret->spec = s->info->spec;
9009 case SK_UNCONSTRAINED:
9010 ret = (sinfo) dmalloc (sizeof (*ret));
9011 ret->fname = s->info->fname;
9017 llassert (s->info == NULL);
9027 sinfo_update (/*@notnull@*/ /*@exposed@*/ sRef res,
9028 /*@notnull@*/ /*@exposed@*/ sRef other)
9030 llassert (res->kind == other->kind);
9035 res->info->cvar->lexlevel = other->info->cvar->lexlevel;
9036 res->info->cvar->index = other->info->cvar->index;
9040 res->info->paramno = other->info->paramno;
9041 llassert (res->info->paramno >= -1);
9045 res->info->arrayfetch->indknown = other->info->arrayfetch->indknown;
9046 res->info->arrayfetch->ind = other->info->arrayfetch->ind;
9047 res->info->arrayfetch->arr = other->info->arrayfetch->arr;
9051 res->info->field->rec = other->info->field->rec;
9052 res->info->field->field = other->info->field->field;
9056 res->info->object = other->info->object;
9063 res->info->ref = other->info->ref;
9067 res->info->conj->a = other->info->conj->a;
9068 res->info->conj->b = other->info->conj->b;
9072 res->info->spec = other->info->spec;
9076 case SK_UNCONSTRAINED:
9077 res->info->fname = other->info->fname;
9084 llassert (res->info == NULL);
9089 static void sinfo_free (/*@special@*/ /*@temp@*/ /*@notnull@*/ sRef s)
9090 /*@uses s->kind, s->info@*/
9091 /*@releases s->info@*/
9096 DPRINTF (("Free sinfo: [%p]", s->info->cvar));
9097 sfree (s->info->cvar);
9104 DPRINTF (("Free sinfo: [%p]", s->info->arrayfetch));
9105 sfree (s->info->arrayfetch);
9109 DPRINTF (("Free sinfo: [%p]", s->info->field));
9110 sfree (s->info->field);
9119 case SK_EXTERNAL: /*@i32 is copy now! */
9123 DPRINTF (("Free sinfo: [%p]", s->info->conj));
9124 sfree (s->info->conj);
9127 case SK_UNCONSTRAINED:
9137 if (s->info != NULL) {
9138 DPRINTF (("Free sinfo: [%p]", s->info));
9144 bool sRef_isNSLocalVar (sRef s)
9146 if (sRef_isLocalVar (s))
9148 uentry ue = sRef_getUentry (s);
9150 return (!uentry_isStatic (ue));
9158 bool sRef_isLocalVar (sRef s)
9160 if (sRef_isValid(s))
9162 return (s->kind == SK_CVAR
9163 && (s->info->cvar->lexlevel > fileScope));
9169 bool sRef_isRealLocalVar (sRef s)
9171 if (sRef_isValid(s))
9173 if (s->kind == SK_CVAR)
9175 if (s->info->cvar->lexlevel == functionScope)
9177 uentry ue = sRef_getUentry (s);
9179 if (uentry_isAnyParam (ue)
9180 || uentry_isRefParam (ue))
9191 return (s->info->cvar->lexlevel > functionScope);
9199 bool sRef_isLocalParamVar (sRef s)
9201 if (sRef_isValid(s))
9203 return (s->kind == SK_PARAM
9204 || (s->kind == SK_CVAR
9205 && (s->info->cvar->lexlevel > fileScope)));
9211 static speckind speckind_fromInt (int i)
9214 llassert (i >= SR_NOTHING && i <= SR_SYSTEM);
9217 return ((speckind) i);
9221 static void sRef_updateNullState (sRef res, sRef other)
9224 res->nullstate = other->nullstate;
9225 res->nullinfo = stateInfo_update (res->nullinfo, other->nullinfo);
9228 void sRef_combineNullState (/*@notnull@*/ sRef res, /*@notnull@*/ sRef other)
9230 nstate n1 = sRef_getNullState (res);
9231 nstate n2 = sRef_getNullState (other);
9235 if (n1 == n2 || n2 == NS_UNKNOWN)
9241 /* note: n2 is not unknown or defnull */
9245 case NS_ERROR: nn = NS_ERROR; break;
9246 case NS_UNKNOWN: flip = TRUE; nn = n2; break;
9247 case NS_POSNULL: break;
9248 case NS_DEFNULL: nn = NS_POSNULL; break;
9249 case NS_RELNULL: break;
9251 if (n2 == NS_MNOTNULL)
9262 if (n2 == NS_NOTNULL)
9281 res->nullinfo = stateInfo_update (res->nullinfo, other->nullinfo);
9284 res->nullstate = nn;
9287 cstring sRef_nullMessage (sRef s)
9289 llassert (sRef_isValid (s));
9291 switch (sRef_getNullState (s))
9295 return (cstring_makeLiteralTemp ("null"));
9297 return (cstring_makeLiteralTemp ("possibly null"));
9302 /*@observer@*/ cstring sRef_ntMessage (sRef s)
9304 llassert (sRef_isValid (s));
9306 switch (s->nullstate)
9310 return (cstring_makeLiteralTemp ("not nullterminated"));
9312 return (cstring_makeLiteralTemp ("possibly non-nullterminated"));
9319 sRef sRef_fixResultType (/*@returned@*/ sRef s, ctype typ, uentry ue)
9321 sRef tmp = sRef_undefined;
9324 llassert (sRef_isValid (s));
9335 tmp = sRef_fixResultType (s->info->arrayfetch->arr, typ, ue);
9337 ct = ctype_realType (sRef_getType (tmp));
9340 if (ctype_isKnown (ct))
9342 if (ctype_isAP (ct))
9351 ("Special clause indexes non-array (%t): *%q",
9352 ct, sRef_unparse (s->info->arrayfetch->arr)),
9353 uentry_whereLast (ue));
9357 tmp = sRef_fixResultType (s->info->arrayfetch->arr, typ, ue);
9359 if (s->info->arrayfetch->indknown)
9361 ret = sRef_makeArrayFetchKnown (tmp, s->info->arrayfetch->ind);
9365 ret = sRef_makeArrayFetch (tmp);
9371 sRef rec = sRef_fixResultType (s->info->field->rec, typ, ue);
9372 ctype ct = ctype_realType (sRef_getType (rec));
9374 if (ctype_isKnown (ct))
9376 if (ctype_isSU (ct))
9378 if (uentry_isValid (uentryList_lookupField (ctype_getFields (ct),
9379 s->info->field->field)))
9388 ("Special clause accesses non-existent field of result: %q.%s",
9389 sRef_unparse (rec), s->info->field->field),
9390 uentry_whereLast (ue));
9398 ("Special clause accesses field of non-struct or union result (%t): %q.%s",
9399 ct, sRef_unparse (rec), s->info->field->field),
9400 uentry_whereLast (ue));
9404 ret = sRef_makeField (tmp, s->info->field->field);
9410 tmp = sRef_fixResultType (s->info->ref, typ, ue);
9412 ct = ctype_realType (sRef_getType (tmp));
9414 if (ctype_isKnown (ct))
9416 if (ctype_isAP (ct))
9425 ("Special clause dereferences non-pointer (%t): *%q",
9426 ct, sRef_unparse (s->info->ref)),
9427 uentry_whereLast (ue));
9431 ret = sRef_makePointer (tmp);
9438 ("Special clause uses & operator (not allowed): &%q", sRef_unparse (s->info->ref)),
9439 uentry_whereLast (ue));
9448 bool sRef_isOnly (sRef s)
9450 return (sRef_isValid(s) && alkind_isOnly (s->aliaskind));
9453 bool sRef_isDependent (sRef s)
9455 return (sRef_isValid(s) && alkind_isDependent (s->aliaskind));
9458 bool sRef_isOwned (sRef s)
9460 return (sRef_isValid (s) && (s->aliaskind == AK_OWNED));
9463 bool sRef_isKeep (sRef s)
9465 return (sRef_isValid (s) && (s->aliaskind == AK_KEEP));
9468 bool sRef_isTemp (sRef s)
9470 return (sRef_isValid (s) && alkind_isTemp (s->aliaskind));
9473 bool sRef_isLocalState (sRef s)
9475 return (sRef_isValid (s) && (s->aliaskind == AK_LOCAL));
9478 bool sRef_isUnique (sRef s)
9480 return (sRef_isValid (s) && (s->aliaskind == AK_UNIQUE));
9483 bool sRef_isShared (sRef s)
9485 return (sRef_isValid (s) && (s->aliaskind == AK_SHARED));
9488 bool sRef_isExposed (sRef s)
9490 return (sRef_isValid (s) && (s->expkind == XO_EXPOSED));
9493 bool sRef_isObserver (sRef s)
9495 return (sRef_isValid (s) && (s->expkind == XO_OBSERVER));
9498 bool sRef_isFresh (sRef s)
9500 return (sRef_isValid (s) && (s->aliaskind == AK_FRESH));
9503 bool sRef_isDefinitelyNull (sRef s)
9505 return (sRef_isValid (s) && (sRef_getNullState (s) == NS_DEFNULL
9506 || sRef_getNullState (s) == NS_CONSTNULL));
9509 bool sRef_isAllocated (sRef s)
9511 return (sRef_isValid (s) && (s->defstate == SS_ALLOCATED));
9514 bool sRef_isStack (sRef s)
9516 return (sRef_isValid (s) && (s->aliaskind == AK_STACK));
9519 bool sRef_isNotNull (sRef s)
9521 return (sRef_isValid(s) && (sRef_getNullState (s) == NS_MNOTNULL
9522 || sRef_getNullState (s) == NS_NOTNULL));
9525 alkind sRef_getAliasKind (sRef s)
9527 if (sRef_isValid(s)) {
9528 llassert (alkind_isValid (s->aliaskind));
9529 return s->aliaskind;
9535 nstate sRef_getNullState (sRef s)
9537 if (sRef_isValid (s)) {
9538 llassert (nstate_isValid (s->nullstate));
9539 return s->nullstate;
9545 void sRef_reflectAnnotation (sRef s, annotationInfo a, fileloc loc)
9547 if (sRef_isValid (s))
9549 if (!valueTable_isDefined (s->state))
9551 s->state = valueTable_create (1);
9552 valueTable_insert (s->state,
9553 cstring_copy (metaStateInfo_getName (annotationInfo_getState (a))),
9554 stateValue_create (annotationInfo_getValue (a), stateInfo_makeLoc (loc)));
9558 DPRINTF (("reflect loc: %s", fileloc_unparse (loc)));
9561 metaStateInfo_getName (annotationInfo_getState (a)),
9562 stateValue_create (annotationInfo_getValue (a), stateInfo_makeLoc (loc)));
9563 DPRINTF (("state info: %s", stateInfo_unparse (stateInfo_makeLoc (loc))));
9564 DPRINTF (("sref: %s", sRef_unparse (s)));
9565 DPRINTF (("sref: %s", sRef_unparseFull (s)));
9570 void sRef_setMetaStateValueComplete (sRef s, cstring key, int value, fileloc loc)
9572 sRefSet aliases = usymtab_allAliases (s);
9574 sRef_setMetaStateValue (s, key, value, loc);
9576 sRefSet_realElements (aliases, current)
9578 if (sRef_isValid (current))
9580 current = sRef_updateSref (current);
9581 sRef_setMetaStateValue (current, key, value, loc);
9583 } end_sRefSet_realElements ;
9585 sRefSet_free (aliases);
9588 void sRef_setMetaStateValue (sRef s, cstring key, int value, fileloc loc)
9590 sRef_checkMutable (s);
9592 if (sRef_isValid (s))
9594 if (!valueTable_isDefined (s->state))
9596 DPRINTF (("inserting state: %s: %s %d", sRef_unparse (s), key, value));
9597 s->state = valueTable_create (1);
9598 valueTable_insert (s->state, cstring_copy (key),
9599 stateValue_create (value, stateInfo_makeLoc (loc)));
9603 DPRINTF (("Updating state: %s: %s %d / %s", sRef_unparse (s), key, value,
9604 fileloc_unparse (loc)));
9605 if (valueTable_contains (s->state, key))
9608 (s->state, key, stateValue_create (value, stateInfo_makeLoc (loc)));
9613 (s->state, cstring_copy (key), stateValue_create (value, stateInfo_makeLoc (loc)));
9616 DPRINTF (("After: %s", sRef_unparseFull (s)));
9621 bool sRef_checkMetaStateValue (sRef s, cstring key, int value)
9623 if (sRef_isValid (s))
9625 if (valueTable_isDefined (s->state))
9629 DPRINTF (("check state: %s: %s %d", sRef_unparse (s), key, value));
9631 val = valueTable_lookup (s->state, key);
9632 llassert (stateValue_isDefined (val));
9633 return (stateValue_isError (val)
9634 || stateValue_getValue (val) == value);
9647 /*@observer@*/ stateValue sRef_getMetaStateValue (sRef s, cstring key)
9649 if (sRef_isValid (s))
9651 if (valueTable_isDefined (s->state))
9655 val = valueTable_lookup (s->state, key);
9656 /* Okay if its not defined, just returns stateValue_undefined */
9661 return stateValue_undefined;
9666 return stateValue_undefined;
9670 /*@observer@*/ valueTable sRef_getValueTable (sRef s)
9672 DPRINTF (("Get value table: %s", sRef_unparse (s)));
9674 if (sRef_isValid (s))
9676 llassert (sRef_isValid (s));
9677 DPRINTF (("Value table: %s", valueTable_unparse (s->state)));
9682 DPRINTF (("No value table!"));
9683 return valueTable_undefined;
9687 bool sRef_makeStateSpecial (sRef s)
9690 ** Default defined state can be made special.
9693 llassert (sRef_isValid (s)); /*@i523 why doesn't null-checking work!??? */
9695 if (s->defstate == SS_UNKNOWN || s->defstate == SS_DEFINED || s->defstate == SS_SPECIAL)
9697 s->aliaskind = AK_IMPTEMP;
9698 s->defstate = SS_SPECIAL;
9699 DPRINTF (("Made special: %s", sRef_unparseFull (s)));
9704 s->aliaskind = AK_IMPTEMP;
9705 s->defstate = SS_SPECIAL;
9710 void sRef_markImmutable (sRef s)
9712 if (sRef_isValid (s))
9714 DPRINTF (("Mark immutable: %s", sRef_unparseFull (s)));
9719 bool sRef_definitelyNullContext (sRef s)
9721 return (sRef_definitelyNull (s)
9722 || usymtab_isDefinitelyNullDeep (s));
9725 bool sRef_definitelyNullAltContext (sRef s)
9727 return (sRef_definitelyNull (s)
9728 || usymtab_isAltDefinitelyNullDeep (s));
9732 /* start modifications */
9733 struct s_bbufinfo sRef_getNullTerminatedState (sRef p_s) {
9734 struct s_bbufinfo BUFSTATE_UNKNOWN;
9735 BUFSTATE_UNKNOWN.bufstate = BB_NOTNULLTERMINATED;
9736 BUFSTATE_UNKNOWN.size = 0;
9737 BUFSTATE_UNKNOWN.len = 0;
9739 if (sRef_isValid(p_s))
9740 return p_s->bufinfo;
9741 return BUFSTATE_UNKNOWN;
9744 void sRef_setNullTerminatedState(sRef p_s) {
9745 if(sRef_isValid (p_s)) {
9746 p_s->bufinfo.bufstate = BB_NULLTERMINATED;
9748 llfatalbug( message("sRef_setNT passed a invalid sRef\n"));
9753 void sRef_setPossiblyNullTerminatedState(sRef p_s) {
9754 if( sRef_isValid (p_s)) {
9755 p_s->bufinfo.bufstate = BB_POSSIBLYNULLTERMINATED;
9757 llfatalbug( message("sRef_setPossNT passed a invalid sRef\n"));
9761 void sRef_setNotNullTerminatedState(sRef p_s) {
9762 if( sRef_isValid (p_s)) {
9763 p_s->bufinfo.bufstate = BB_NOTNULLTERMINATED;
9765 llfatalbug( message("sRef_unsetNT passed a invalid sRef\n"));
9769 void sRef_setLen(sRef p_s, int len) {
9770 if( sRef_isValid (p_s) && sRef_isNullTerminated(p_s)) {
9771 p_s->bufinfo.len = len;
9773 llfatalbug( message("sRef_setLen passed a invalid sRef\n"));
9778 void sRef_setSize(sRef p_s, int size) {
9779 if( sRef_isValid(p_s)) {
9780 p_s->bufinfo.size = size;
9782 llfatalbug( message("sRef_setSize passed a invalid sRef\n"));
9786 void sRef_resetLen(sRef p_s) {
9787 if (sRef_isValid (p_s)) {
9788 p_s->bufinfo.len = 0;
9790 llfatalbug (message ("sRef_setLen passed an invalid sRef\n"));
9794 /*drl7x 11/28/2000 */
9796 bool sRef_isFixedArray (sRef p_s) /*@*/ {
9798 c = sRef_getType (p_s);
9799 return ( ctype_isFixedArray (c) );
9802 long int sRef_getArraySize (sRef p_s) /*@*/ {
9804 llassert (sRef_isFixedArray(p_s) );
9805 DPRINTF (( message ("sRef_getArraySize getting array size for %s", sRef_unparse(p_s) ) ));
9807 c = sRef_getType (p_s);
9809 return (ctype_getArraySize (c) );