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 bool sRef_checkModify (sRef p_s, sRefSet p_sl) /*@*/ ;
92 static void sRef_checkMutable (/*@unused@*/ sRef s)
95 if (sRef_isValid (s) && s->immut)
97 llcontbug (message ("Modification to sRef marked immutable: %q",
98 sRef_unparseFull (s)));
102 static bool skind_isSimple (skind sk)
106 case SK_PARAM: case SK_CVAR: case SK_CONST:
107 case SK_OBJECT: case SK_UNKNOWN: case SK_NEW:
114 static void sinfo_free (/*@special@*/ /*@temp@*/ /*@notnull@*/ sRef p_s)
115 /*@uses p_s->kind, p_s->info@*/
116 /*@releases p_s->info@*/ ;
118 static /*@null@*/ sinfo sinfo_copy (/*@notnull@*/ sRef p_s) /*@*/ ;
119 static void sRef_setPartsFromUentry (sRef p_s, uentry p_ue)
121 static bool checkDeadState (/*@notnull@*/ sRef p_el, bool p_tbranch, fileloc p_loc);
122 static /*@dependent@*/ sRef sRef_constructPointerAux (/*@notnull@*/ /*@exposed@*/ sRef p_t) /*@*/ ;
125 sRef_combineExKinds (/*@notnull@*/ sRef p_res, /*@notnull@*/ sRef p_other)
126 /*@modifies p_res@*/ ;
129 sRef_combineAliasKinds (/*@notnull@*/ sRef p_res, /*@notnull@*/ sRef p_other,
130 clause p_cl, fileloc p_loc)
131 /*@modifies p_res@*/ ;
134 sRef_combineNullState (/*@notnull@*/ sRef p_res, /*@notnull@*/ sRef p_other)
135 /*@modifies p_res@*/ ;
138 sRef_combineDefState (/*@notnull@*/ sRef p_res, /*@notnull@*/ sRef p_other)
139 /*@modifies p_res@*/ ;
141 static void sRef_setStateFromAbstractUentry (sRef p_s, uentry p_ue)
145 sinfo_update (/*@notnull@*/ /*@exposed@*/ sRef p_res,
146 /*@notnull@*/ /*@exposed@*/ sRef p_other);
147 static void sRef_setDefinedAux (sRef p_s, fileloc p_loc, bool p_clear)
149 static void sRef_setDefinedNoClear (sRef p_s, fileloc p_loc)
151 static void sRef_setStateAux (sRef p_s, sstate p_ss, fileloc p_loc)
154 static /*@exposed@*/ sRef
155 sRef_buildNCField (/*@exposed@*/ sRef p_rec, /*@exposed@*/ cstring p_f);
158 sRef_mergeStateAux (/*@notnull@*/ sRef p_res, /*@notnull@*/ sRef p_other,
159 clause p_cl, bool p_opt, fileloc p_loc,
161 /*@modifies p_res, p_other@*/ ;
163 static /*@null@*/ sinfo sinfo_fullCopy (/*@notnull@*/ sRef p_s);
164 static bool sRef_doModify (sRef p_s, sRefSet p_sl) /*@modifies p_s@*/ ;
165 static bool sRef_doModifyVal (sRef p_s, sRefSet p_sl) /*@modifies p_s@*/;
166 static bool sRef_checkModifyVal (sRef p_s, sRefSet p_sl) /*@*/ ;
168 static /*@only@*/ sRefSet
169 sRef_mergeDerivs (/*@only@*/ sRefSet p_res, sRefSet p_other,
170 bool p_opt, clause p_cl, fileloc p_loc);
172 static /*@only@*/ sRefSet
173 sRef_mergeUnionDerivs (/*@only@*/ sRefSet p_res,
174 /*@exposed@*/ sRefSet p_other,
175 bool p_opt, clause p_cl, fileloc p_loc);
177 static /*@only@*/ sRefSet
178 sRef_mergePdefinedDerivs (/*@only@*/ sRefSet p_res, sRefSet p_other, bool p_opt,
179 clause p_cl, fileloc p_loc);
181 static /*@only@*/ cstring sRef_unparseWithArgs (sRef p_s, uentryList p_args);
182 static /*@only@*/ cstring sRef_unparseNoArgs (sRef p_s);
184 static /*@exposed@*/ sRef sRef_findDerivedPointer (sRef p_s);
185 static /*@exposed@*/ sRef sRef_findDerivedArrayFetch (/*@notnull@*/ sRef, bool, int, bool) ;
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 /* This sometimes fails: (evans 2001-07-12)
470 if (sRef_isArrayFetch (t))
472 DPRINTF (("Derived fetch: %s / %s / %s",
473 sRef_unparseFull (s), sRef_unparseFull (t),
474 sRef_unparseFull (t->info->arrayfetch->arr)));
475 llassert (t->info->arrayfetch->arr == s);
479 if (sRef_isFileOrGlobalScope (s))
481 if (context_inFunctionLike ()
482 && ctype_isKnown (sRef_getType (s))
483 && !ctype_isFunction (sRef_getType (s)))
485 globSet g = context_getUsedGlobs ();
487 if (!globSet_member (g, s))
490 ** don't report as a bug
494 (message ("sRef_addDeriv: global variable not in used "
495 "globs: %q / %s / %q",
497 ctype_unparse (sRef_getType (s)),
498 sRefSet_unparse (s->deriv)));
503 s->deriv = sRefSet_insert (s->deriv, t);
509 DPRINTF (("Add deriv: [%p] %s / [%p] %s",
511 t, sRef_unparse (t)));
513 s->deriv = sRefSet_insert (s->deriv, t);
519 sRef_deepPred (bool (predf) (sRef), sRef s)
521 if (sRef_isValid (s))
523 if ((*predf)(s)) return TRUE;
528 return (sRef_deepPred (predf, s->info->ref));
530 return (sRef_deepPred (predf, s->info->arrayfetch->arr));
532 return (sRef_deepPred (predf, s->info->field->rec));
534 return (sRef_deepPred (predf, s->info->conj->a)
535 || sRef_deepPred (predf, s->info->conj->b));
544 bool sRef_modInFunction (void)
549 void sRef_setStateFromType (sRef s, ctype ct)
551 if (sRef_isValid (s))
553 if (ctype_isUser (ct))
555 DPRINTF (("Here we are: %s", sRef_unparseFull (s)));
556 sRef_setStateFromUentry
557 (s, usymtab_getTypeEntry (ctype_typeId (ct)));
559 else if (ctype_isAbstract (ct))
561 DPRINTF (("Here we are: %s", sRef_unparseFull (s)));
562 sRef_setStateFromAbstractUentry
563 (s, usymtab_getTypeEntry (ctype_typeId (ct)));
567 ; /* not a user type */
572 static void sRef_setTypeState (sRef s)
574 if (sRef_isValid (s))
576 sRef_setStateFromType (s, s->type);
581 sRef_hasAliasInfoLoc (sRef s)
583 return (sRef_isValid (s) && (s->aliasinfo != NULL)
584 && (fileloc_isDefined (s->aliasinfo->loc)));
587 static /*@falsenull@*/ bool
588 sRef_hasStateInfoLoc (sRef s)
590 return (sRef_isValid (s) && (s->definfo != NULL)
591 && (fileloc_isDefined (s->definfo->loc)));
594 static /*@falsenull@*/ bool
595 sRef_hasExpInfoLoc (sRef s)
597 return (sRef_isValid (s)
598 && (s->expinfo != NULL) && (fileloc_isDefined (s->expinfo->loc)));
601 static /*@observer@*/ /*@unused@*/ stateInfo sRef_getInfo (sRef s, cstring key)
605 if (!sRef_isValid (s)) {
606 return stateInfo_undefined;
609 sv = valueTable_lookup (s->state, key);
611 if (stateValue_isDefined (sv))
613 return stateValue_getInfo (sv);
616 return stateInfo_undefined;
621 sRef_hasNullInfoLoc (sRef s)
623 return (sRef_isValid (s) && s->nullinfo != NULL
624 && (fileloc_isDefined (s->nullinfo->loc)));
628 sRef_hasAliasInfoRef (sRef s)
630 return (sRef_isValid (s) && (s->aliasinfo != NULL)
631 && (sRef_isValid (s->aliasinfo->ref)));
634 static /*@observer@*/ fileloc
635 sRef_getAliasInfoLoc (/*@exposed@*/ sRef s)
637 llassert (sRef_isValid (s) && s->aliasinfo != NULL
638 && (fileloc_isDefined (s->aliasinfo->loc)));
639 return (s->aliasinfo->loc);
642 static /*@observer@*/ fileloc
643 sRef_getStateInfoLoc (/*@exposed@*/ sRef s)
645 llassert (sRef_isValid (s) && s->definfo != NULL
646 && (fileloc_isDefined (s->definfo->loc)));
647 return (s->definfo->loc);
650 static /*@observer@*/ fileloc
651 sRef_getExpInfoLoc (/*@exposed@*/ sRef s)
653 llassert (sRef_isValid (s) && s->expinfo != NULL
654 && (fileloc_isDefined (s->expinfo->loc)));
655 return (s->expinfo->loc);
658 static /*@observer@*/ fileloc
659 sRef_getNullInfoLoc (/*@exposed@*/ sRef s)
661 llassert (sRef_isValid (s) && s->nullinfo != NULL
662 && (fileloc_isDefined (s->nullinfo->loc)));
663 return (s->nullinfo->loc);
667 sRef_getAliasInfoRef (/*@temp@*/ sRef s)
669 llassert (sRef_isValid (s) && s->aliasinfo != NULL);
670 return (s->aliasinfo->ref);
673 bool sRef_inGlobalScope ()
679 ** This function should be called before new sRefs are created
680 ** somewhere where they will have a lifetime greater than the
681 ** current function scope.
684 void sRef_setGlobalScope ()
686 llassert (inFunction);
687 DPRINTF (("leave function"));
691 void sRef_clearGlobalScope ()
693 llassert (!inFunction);
694 DPRINTF (("enter function"));
698 static bool oldInFunction = FALSE;
699 static int nestedScope = 0;
701 void sRef_setGlobalScopeSafe ()
703 if (nestedScope == 0)
705 oldInFunction = inFunction;
709 DPRINTF (("leave function safe"));
713 void sRef_clearGlobalScopeSafe ()
716 llassert (nestedScope >= 0);
718 if (nestedScope == 0)
720 inFunction = oldInFunction;
723 DPRINTF (("clear function: %s", bool_unparse (inFunction)));
726 void sRef_enterFunctionScope ()
728 llassert (!inFunction);
729 llassert (sRefTable_isEmpty (allRefs));
731 DPRINTF (("enter function"));
734 void sRef_exitFunctionScope ()
738 DPRINTF (("Exit function scope."));
739 sRefTable_clear (allRefs);
744 llbuglit ("sRef_exitFunctionScope: not in function");
748 void sRef_destroyMod () /*@globals killed allRefs;@*/
751 llmsg (message ("Live: %d / %d ", nsrefs, totnsrefs));
754 sRefTable_free (allRefs);
758 static /*@notnull@*/ /*@exposed@*/ sRef
759 sRef_fixConj (/*@notnull@*/ sRef s)
764 s = sRef_getConjA (s);
765 } while (sRef_isConj (s));
767 llassert (sRef_isValid (s));
768 return s; /* don't need to ref */
777 sRef_isExternallyVisibleAux (sRef s)
780 sRef base = sRef_getRootBase (s);
782 if (sRef_isValid (base))
784 res = sRef_isParam (base) || sRef_isFileOrGlobalScope (base) || sRef_isExternal (base);
791 sRef_isExternallyVisible (sRef s)
793 return (sRef_aliasCheckSimplePred (sRef_isExternallyVisibleAux, s));
797 sRef_getBaseUentry (sRef s)
799 sRef base = sRef_getRootBase (s);
800 uentry res = uentry_undefined;
802 if (sRef_isValid (base))
807 res = usymtab_getRefQuiet (paramsScope, base->info->paramno);
811 res = usymtab_getRefQuiet (base->info->cvar->lexlevel,
812 base->info->cvar->index);
824 ** lookup the current uentry corresponding to s, and return the corresponding sRef.
825 ** yuk yuk yuk yuk yuk yuk yuk yuk
829 sRef_updateSref (sRef s)
835 if (!sRef_isValid (s)) return sRef_undefined;
844 case SK_UNCONSTRAINED:
851 sRef r = sRef_updateSref (s->info->ref);
853 if (r != s->info->ref)
855 return sRef_makeExternal (r);
865 uentry ue = sRef_getUentry (s);
867 /* must be raw name! (need the marker) */
868 ue = usymtab_lookupSafe (uentry_rawName (ue));
870 if (uentry_isUndefined (ue))
876 DPRINTF (("Update sref: %s", uentry_unparseFull (ue)));
877 return (uentry_getSref (ue));
881 /* special case if ind known */
882 inner = s->info->arrayfetch->arr;
883 ret = sRef_updateSref (inner);
891 res = sRef_makeArrayFetch (ret);
897 inner = s->info->field->rec;
898 ret = sRef_updateSref (inner);
906 res = (sRef_makeField (ret, s->info->field->field));
911 inner = s->info->ref;
912 ret = sRef_updateSref (inner);
919 res = sRef_makePointer (ret);
925 inner = s->info->ref;
926 ret = sRef_updateSref (inner);
934 res = sRef_makeAddress (ret);
941 sRef innera = s->info->conj->a;
942 sRef innerb = s->info->conj->b;
943 sRef reta = sRef_updateSref (innera);
944 sRef retb = sRef_updateSref (innerb);
946 if (innera == reta && innerb == retb)
952 res = sRef_makeConj (reta, retb);
963 sRef_getUentry (sRef s)
965 llassert (sRef_isValid (s));
970 return (usymtab_getRefQuiet (paramsScope, s->info->paramno));
972 return (usymtab_getRefQuiet (s->info->cvar->lexlevel, s->info->cvar->index));
975 if (sRef_isCvar (s->info->conj->a) || sRef_isParam (s->info->conj->a)
976 || sRef_isConj (s->info->conj->a))
978 return sRef_getUentry (s->info->conj->a);
982 return sRef_getUentry (s->info->conj->b);
987 return uentry_undefined;
993 sRef_getParam (sRef s)
995 llassert (sRef_isValid (s));
996 llassert (s->kind == SK_PARAM);
998 return s->info->paramno;
1002 sRef_isModified (sRef s)
1004 return (!sRef_isValid (s) || s->modified);
1007 void sRef_setModified (sRef s)
1009 if (sRef_isValid (s))
1014 if (sRef_isRefsField (s))
1016 sRef base = sRef_getBase (s);
1019 llassert (s->kind == SK_FIELD);
1022 if (sRef_isPointer (base))
1024 base = sRef_getBase (base);
1027 if (sRef_isRefCounted (base))
1029 base->aliaskind = AK_NEWREF;
1036 ** note: this side-effects sRefSet to set modified to TRUE
1037 ** for any sRef similar to s.
1041 sRef_canModifyVal (sRef s, sRefSet sl)
1043 if (context_getFlag (FLG_MUSTMOD))
1045 return (sRef_doModifyVal (s, sl));
1049 return (sRef_checkModifyVal (s, sl));
1054 sRef_canModify (sRef s, sRefSet sl)
1057 if (context_getFlag (FLG_MUSTMOD))
1059 return (sRef_doModify (s, sl));
1063 return (sRef_checkModify (s, sl));
1072 bool sRef_checkModifyVal (sRef s, sRefSet sl)
1074 DPRINTF (("Check modify val: %s", sRef_unparse (s)));
1076 if (sRef_isInvalid (s))
1083 case SK_UNCONSTRAINED:
1087 DPRINTF (("Modify var: %s", sRef_unparse (s)));
1089 if (sRef_isFileOrGlobalScope (s))
1091 if (context_checkGlobMod (s))
1093 return (sRefSet_member (sl, s));
1103 return (sRefSet_member (sl, s)
1104 || alkind_isOnly (sRef_getOrigAliasKind (s)));
1106 /* special case if ind known */
1107 return (sRefSet_member (sl, s) ||
1108 sRef_checkModifyVal (s->info->arrayfetch->arr, sl));
1110 return (sRefSet_member (sl, s) || sRef_checkModifyVal (s->info->field->rec, sl));
1112 return (sRefSet_member (sl, s) || sRef_checkModifyVal (s->info->ref, sl));
1114 return (sRefSet_member (sl, s) || sRef_checkModifyVal (s->info->ref, sl));
1116 return ((sRef_checkModifyVal (s->info->conj->a, sl)) &&
1117 (sRef_checkModifyVal (s->info->conj->b, sl)));
1128 switch (s->info->spec)
1130 case SR_NOTHING: return TRUE;
1132 if (context_getFlag (FLG_INTERNALGLOBS))
1134 return (sRefSet_member (sl, s));
1140 case SR_SPECSTATE: return TRUE;
1141 case SR_SYSTEM: return (sRefSet_member (sl, s));
1142 case SR_GLOBALMARKER: BADBRANCH;
1145 case SK_RESULT: BADBRANCH;
1151 ** this should probably be elsewhere...
1153 ** returns TRUE iff sl indicates that s can be modified
1156 static bool sRef_checkModify (sRef s, sRefSet sl)
1158 llassert (sRef_isValid (s));
1162 case SK_UNCONSTRAINED:
1166 if (sRef_isFileOrGlobalScope (s))
1168 if (context_checkGlobMod (s))
1170 return (sRefSet_member (sl, s));
1182 return (sRefSet_member (sl, s) ||
1183 sRef_checkModifyVal (s->info->arrayfetch->arr, sl));
1186 sRef sr = s->info->field->rec;
1188 if (sr->kind == SK_PARAM)
1189 return TRUE; /* structs are copied on call */
1191 return (sRefSet_member (sl, s) || sRef_checkModifyVal (s->info->field->rec, sl));
1197 sm = sRefSet_member (sl, s);
1202 return (sRef_checkModifyVal (s->info->ref, sl));
1205 return (sRefSet_member (sl, s) || sRef_checkModifyVal (s->info->ref, sl));
1207 return ((sRef_checkModify (s->info->conj->a, sl)) &&
1208 (sRef_checkModify (s->info->conj->b, sl)));
1218 switch (s->info->spec)
1220 case SR_NOTHING: return TRUE;
1222 if (context_getFlag (FLG_INTERNALGLOBS))
1224 return (sRefSet_member (sl, s));
1230 case SR_SPECSTATE: return TRUE;
1231 case SR_SYSTEM: return (sRefSet_member (sl, s));
1232 case SR_GLOBALMARKER: BADBRANCH;
1235 case SK_RESULT: BADBRANCH;
1240 cstring sRef_stateVerb (sRef s)
1242 if (sRef_isDead (s))
1244 return cstring_makeLiteralTemp ("released");
1246 else if (sRef_isKept (s))
1248 return cstring_makeLiteralTemp ("kept");
1250 else if (sRef_isDependent (s))
1252 return cstring_makeLiteralTemp ("dependent");
1260 cstring sRef_stateAltVerb (sRef s)
1262 if (sRef_isDead (s))
1264 return cstring_makeLiteralTemp ("live");
1266 else if (sRef_isKept (s))
1268 return cstring_makeLiteralTemp ("not kept");
1270 else if (sRef_isDependent (s))
1272 return cstring_makeLiteralTemp ("independent");
1281 bool sRef_doModifyVal (sRef s, sRefSet sl)
1283 llassert (sRef_isValid (s));
1288 case SK_UNCONSTRAINED:
1292 if (sRef_isFileOrGlobalScope (s))
1295 if (context_checkGlobMod (s))
1297 return (sRefSet_modifyMember (sl, s));
1301 (void) sRefSet_modifyMember (sl, s);
1311 return (sRefSet_modifyMember (sl, s)
1312 || alkind_isOnly (sRef_getOrigAliasKind (s)));
1314 /* special case if ind known */
1315 /* unconditional OR, need side effect */
1316 return (OR (sRefSet_modifyMember (sl, s),
1317 sRef_doModifyVal (s->info->arrayfetch->arr, sl)));
1319 return (OR (sRefSet_modifyMember (sl, s),
1320 sRef_doModifyVal (s->info->field->rec, sl)));
1322 return (OR (sRefSet_modifyMember (sl, s),
1323 sRef_doModifyVal (s->info->ref, sl)));
1325 return (OR (sRefSet_modifyMember (sl, s),
1326 sRef_doModifyVal (s->info->ref, sl)));
1328 return (AND (sRef_doModifyVal (s->info->conj->a, sl) ,
1329 sRef_doModifyVal (s->info->conj->b, sl)));
1339 switch (s->info->spec)
1341 case SR_NOTHING: return TRUE;
1343 if (context_getFlag (FLG_INTERNALGLOBS))
1345 return (sRefSet_modifyMember (sl, s));
1349 (void) sRefSet_modifyMember (sl, s);
1352 case SR_SPECSTATE: return TRUE;
1353 case SR_SYSTEM: return (sRefSet_modifyMember (sl, s));
1354 case SR_GLOBALMARKER: BADBRANCH;
1358 case SK_RESULT: BADBRANCH;
1364 ** this should probably be elsewhere...
1366 ** returns TRUE iff sl indicates that s can be modified
1370 bool sRef_doModify (sRef s, sRefSet sl)
1372 llassert (sRef_isValid (s));
1376 case SK_UNCONSTRAINED:
1380 if (sRef_isFileOrGlobalScope (s))
1382 if (context_checkGlobMod (s))
1384 return (sRefSet_modifyMember (sl, s));
1388 (void) sRefSet_modifyMember (sl, s);
1400 return (OR (sRefSet_modifyMember (sl, s),
1401 sRef_doModifyVal (s->info->arrayfetch->arr, sl)));
1404 sRef sr = s->info->field->rec;
1406 if (sr->kind == SK_PARAM)
1408 return TRUE; /* structs are shallow-copied on call */
1411 return (OR (sRefSet_modifyMember (sl, s),
1412 sRef_doModifyVal (s->info->field->rec, sl)));
1416 return (OR (sRefSet_modifyMember (sl, s),
1417 sRef_doModifyVal (s->info->ref, sl)));
1420 return (OR (sRefSet_modifyMember (sl, s),
1421 sRef_doModifyVal (s->info->ref, sl)));
1423 return (AND (sRef_doModify (s->info->conj->a, sl),
1424 (sRef_doModify (s->info->conj->b, sl))));
1435 switch (s->info->spec)
1437 case SR_NOTHING: return TRUE;
1438 case SR_INTERNAL: return TRUE;
1439 case SR_SPECSTATE: return TRUE;
1440 case SR_SYSTEM: return (sRefSet_modifyMember (sl, s));
1441 case SR_GLOBALMARKER: BADBRANCH;
1444 case SK_RESULT: BADBRANCH;
1449 static /*@exposed@*/ sRef
1450 sRef_leastCommon (/*@exposed@*/ sRef s1, sRef s2)
1452 llassert (sRef_similar (s1, s2));
1454 if (!sRef_isValid (s1)) return s1;
1455 if (!sRef_isValid (s2)) return s1;
1457 sRef_combineDefState (s1, s2);
1458 sRef_combineNullState (s1, s2);
1459 sRef_combineExKinds (s1, s2);
1461 if (s1->aliaskind != s2->aliaskind)
1463 if (s1->aliaskind == AK_UNKNOWN)
1465 s1->aliaskind = s2->aliaskind;
1467 else if (s2->aliaskind == AK_UNKNOWN)
1473 s1->aliaskind = AK_ERROR;
1480 int sRef_compare (sRef s1, sRef s2)
1482 if (s1 == s2) return 0;
1484 if (sRef_isInvalid (s1)) return -1;
1485 if (sRef_isInvalid (s2)) return 1;
1487 INTCOMPARERETURN (s1->kind, s2->kind);
1488 INTCOMPARERETURN (s1->defstate, s2->defstate);
1489 INTCOMPARERETURN (s1->aliaskind, s2->aliaskind);
1491 DPRINTF (("Compare null state: %s / %s",
1492 sRef_unparseFull (s1),
1493 sRef_unparseFull (s2)));
1495 COMPARERETURN (nstate_compare (sRef_getNullState (s1),
1496 sRef_getNullState (s2)));
1501 return (int_compare (s1->info->paramno, s2->info->paramno));
1504 COMPARERETURN (sRef_compare (s1->info->arrayfetch->arr,
1505 s2->info->arrayfetch->arr));
1507 if (s1->info->arrayfetch->indknown && s2->info->arrayfetch->indknown)
1509 return (int_compare (s1->info->arrayfetch->ind,
1510 s2->info->arrayfetch->ind));
1512 if (!s1->info->arrayfetch->indknown && !s2->info->arrayfetch->indknown)
1519 COMPARERETURN (sRef_compare (s1->info->field->rec, s2->info->field->rec));
1521 if (cstring_equal (s1->info->field->field, s2->info->field->field))
1528 return (sRef_compare (s1->info->ref, s2->info->ref));
1530 COMPARERETURN (sRef_compare (s1->info->conj->a, s2->info->conj->a));
1531 return (sRef_compare (s1->info->conj->b, s2->info->conj->b));
1532 case SK_UNCONSTRAINED:
1533 return (cstring_compare (s1->info->fname, s2->info->fname));
1545 return (generic_compare (s1->info->spec, s2->info->spec));
1550 static bool cref_equal (cref c1, cref c2)
1552 return ((c1->lexlevel == c2->lexlevel) &&
1553 (usymId_equal (c1->index, c2->index)));
1557 ** returns true if s1 could be the same storage as s2.
1558 ** i.e., a[?] ~ a[3]. Note its not symmetric ... s1
1559 ** should be more specific.
1563 ** like similar, but matches objects <-> non-objects
1567 sRef_uniqueReference (sRef s)
1569 return (sRef_isFresh (s) || sRef_isUnique (s)
1570 || sRef_isOnly (s) || sRef_isStack (s)
1571 || sRef_isAddress (s));
1575 sRef_similarRelaxedAux (sRef s1, sRef s2)
1579 if (sRef_isUnknownArrayFetch (s1))
1589 if (sRef_isInvalid (s1) || sRef_isInvalid (s2)) return FALSE;
1591 if (sRef_isConj (s2))
1592 return (sRef_similarRelaxedAux (s1, sRef_getConjA (s2)) ||
1593 sRef_similarRelaxedAux (s1, sRef_getConjB (s2)));
1598 return ((s2->kind == SK_CVAR)
1599 && (cref_equal (s1->info->cvar, s2->info->cvar)));
1601 return ((s2->kind == SK_PARAM)
1602 && (s1->info->paramno == s2->info->paramno));
1604 if (s2->kind == SK_ARRAYFETCH)
1606 if (sRef_similarRelaxedAux (s1->info->arrayfetch->arr,
1607 s2->info->arrayfetch->arr))
1609 if (s1->info->arrayfetch->indknown)
1611 if (s2->info->arrayfetch->indknown)
1613 return (s1->info->arrayfetch->ind == s2->info->arrayfetch->ind);
1628 return ((s2->kind == SK_FIELD
1629 && (sRef_similarRelaxedAux (s1->info->field->rec,
1630 s2->info->field->rec)
1631 && cstring_equal (s1->info->field->field,
1632 s2->info->field->field))));
1634 return ((s2->kind == SK_PTR)
1635 && sRef_similarRelaxedAux (s1->info->ref, s2->info->ref));
1637 return ((s2->kind == SK_ADR)
1638 && sRef_similarRelaxedAux (s1->info->ref, s2->info->ref));
1640 return ((sRef_similarRelaxedAux (s1->info->conj->a, s2) ||
1641 (sRef_similarRelaxedAux (s1->info->conj->b, s2))));
1643 return (s1->info->spec == s2->info->spec);
1644 case SK_UNCONSTRAINED:
1645 return (cstring_equal (s1->info->fname, s2->info->fname));
1660 sRef_similarRelaxed (sRef s1, sRef s2)
1666 if (sRef_isThroughArrayFetch (s1))
1676 if (sRef_isInvalid (s1) || sRef_isInvalid (s2)) return FALSE;
1678 us1 = sRef_uniqueReference (s1);
1679 us2 = sRef_uniqueReference (s2);
1681 if ((s1->kind == SK_EXTERNAL && (s2->kind != SK_EXTERNAL && !us2))
1682 || (s2->kind == SK_EXTERNAL && (s1->kind != SK_EXTERNAL && !us1)))
1685 ** Previously, also:
1686 ** || (sRef_isExposed (s1) && !us2) || (sRef_isExposed (s2) && !us1)) ????
1688 ** No clue why this was there?!
1692 if (sRef_isExposed (s1) && sRef_isCvar (s1))
1694 uentry ue1 = sRef_getUentry (s1);
1696 if (uentry_isRefParam (ue1))
1698 return sRef_similarRelaxedAux (s1, s2);
1702 if (sRef_isExposed (s2) && sRef_isCvar (s2))
1704 uentry ue2 = sRef_getUentry (s2);
1706 if (uentry_isRefParam (ue2))
1708 return sRef_similarRelaxedAux (s1, s2);
1712 return (ctype_match (s1->type, s2->type));
1716 return sRef_similarRelaxedAux (s1, s2);
1721 sRef_similar (sRef s1, sRef s2)
1723 if (s1 == s2) return TRUE;
1724 if (sRef_isInvalid (s1) || sRef_isInvalid (s2)) return FALSE;
1726 if (sRef_isConj (s2))
1728 return (sRef_similar (s1, sRef_getConjA (s2)) ||
1729 sRef_similar (s1, sRef_getConjB (s2)));
1732 if (sRef_isDerived (s2))
1734 return (sRef_includedBy (s1, s2->info->ref));
1740 return ((s2->kind == SK_CVAR)
1741 && (cref_equal (s1->info->cvar, s2->info->cvar)));
1743 return ((s2->kind == SK_PARAM)
1744 && (s1->info->paramno == s2->info->paramno));
1746 if (s2->kind == SK_ARRAYFETCH)
1748 if (sRef_similar (s1->info->arrayfetch->arr,
1749 s2->info->arrayfetch->arr))
1751 if (s1->info->arrayfetch->indknown)
1753 if (s2->info->arrayfetch->indknown)
1755 return (s1->info->arrayfetch->ind == s2->info->arrayfetch->ind);
1770 if (s2->kind == SK_PTR)
1772 if (sRef_similar (s1->info->arrayfetch->arr,
1782 return ((s2->kind == SK_FIELD
1783 && (sRef_similar (s1->info->field->rec,
1784 s2->info->field->rec)
1785 && cstring_equal (s1->info->field->field,
1786 s2->info->field->field))));
1788 if (s2->kind == SK_PTR)
1790 return sRef_similar (s1->info->ref, s2->info->ref);
1794 if (s2->kind == SK_ARRAYFETCH)
1796 if (sRef_similar (s2->info->arrayfetch->arr,
1806 return ((s2->kind == SK_ADR)
1807 && sRef_similar (s1->info->ref, s2->info->ref));
1809 return ((sRef_similar (s1->info->conj->a, s2) ||
1810 (sRef_similar (s1->info->conj->b, s2))));
1812 return (sRef_includedBy (s2, s1->info->ref));
1813 case SK_UNCONSTRAINED:
1814 return (s2->kind == SK_UNCONSTRAINED
1815 && cstring_equal (s1->info->fname, s2->info->fname));
1825 return (s2->kind == SK_SPECIAL
1826 && (s1->info->spec == s2->info->spec));
1829 /*@notreached@*/ DPRINTF (("Fell through for: %s / %s", sRef_unparse (s1), sRef_unparse (s2)));
1834 ** return TRUE iff small can be derived from big.
1836 ** (e.g. x, x.a is includedBy x;
1837 ** x.a is included By x.a;
1841 sRef_includedBy (sRef small, sRef big)
1843 if (small == big) return TRUE;
1844 if (sRef_isInvalid (small) || sRef_isInvalid (big)) return FALSE;
1846 if (sRef_isConj (big))
1847 return (sRef_similar (small, sRef_getConjA (big)) ||
1848 sRef_similar (small, sRef_getConjB (big)));
1850 switch (small->kind)
1854 return (sRef_same (small, big));
1856 if (big->kind == SK_ARRAYFETCH)
1858 if (sRef_same (small->info->arrayfetch->arr, big->info->arrayfetch->arr))
1860 if (small->info->arrayfetch->indknown)
1862 if (big->info->arrayfetch->indknown)
1864 return (small->info->arrayfetch->ind == big->info->arrayfetch->ind);
1877 return (sRef_includedBy (small->info->arrayfetch->arr, big));
1879 if (big->kind == SK_FIELD)
1882 (sRef_same (small->info->field->rec, big->info->field->rec) &&
1883 cstring_equal (small->info->field->field, big->info->field->field));
1887 return (sRef_includedBy (small->info->field->rec, big));
1891 if (big->kind == SK_PTR)
1893 return sRef_same (small->info->ref, big->info->ref);
1897 return (sRef_includedBy (small->info->ref, big));
1901 return ((big->kind == SK_ADR) && sRef_similar (small->info->ref, big->info->ref));
1903 return ((sRef_includedBy (small->info->conj->a, big) ||
1904 (sRef_includedBy (small->info->conj->b, big))));
1906 return (sRef_includedBy (small->info->ref, big));
1907 case SK_UNCONSTRAINED:
1917 switch (small->info->spec)
1919 case SR_NOTHING: return TRUE;
1921 case SR_INTERNAL: return (sRef_isSpecInternalState (big) ||
1922 sRef_isFileStatic (big));
1923 case SR_SYSTEM: return (sRef_isSystemState (big));
1924 case SR_GLOBALMARKER: BADBRANCH;
1931 ** Same is similar to similar, but not quite the same.
1932 ** same and realSame aren't the same, but they are really similar.
1933 ** similarly, same is the same as same. but realSame is
1934 ** not really the same as same, or similar to similar.
1936 ** Similarly to similar, same checks if two sRefs are the same.
1937 ** The similarities end, however, when same compares arrays
1938 ** with unknown indexes. Similar returns false; same returns true.
1940 ** Similarly to similar and same, realSame is the same as same,
1941 ** except they do not behave the same when face with unknown
1942 ** sRefs. Same thinks they are not the same, but realSame thinks
1948 sRef_realSame (sRef s1, sRef s2)
1950 if (s1 == s2) return TRUE;
1951 if (sRef_isInvalid (s1) || sRef_isInvalid (s2)) return FALSE;
1956 return ((s2->kind == SK_CVAR) && (cref_equal (s1->info->cvar, s2->info->cvar)));
1958 return ((s2->kind == SK_PARAM) && (s1->info->paramno == s2->info->paramno));
1960 if (s2->kind == SK_ARRAYFETCH)
1962 if (sRef_realSame (s1->info->arrayfetch->arr, s2->info->arrayfetch->arr))
1964 if (s1->info->arrayfetch->indknown && s2->info->arrayfetch->indknown)
1966 return (s1->info->arrayfetch->ind == s2->info->arrayfetch->ind);
1968 if (!s1->info->arrayfetch->indknown && !s2->info->arrayfetch->indknown)
1977 return ((s2->kind == SK_FIELD &&
1978 (sRef_realSame (s1->info->field->rec, s2->info->field->rec) &&
1979 cstring_equal (s1->info->field->field, s2->info->field->field))));
1981 return ((s2->kind == SK_PTR) && sRef_realSame (s1->info->ref, s2->info->ref));
1983 return ((s2->kind == SK_ADR) && sRef_realSame (s1->info->ref, s2->info->ref));
1985 return ((sRef_realSame (s1->info->conj->a, s2) ||
1986 (sRef_realSame (s1->info->conj->b, s2))));
1988 return ((s2->kind == SK_OBJECT)
1989 && ctype_match (s1->info->object, s2->info->object));
1991 return ((s2->kind == SK_EXTERNAL)
1992 && sRef_realSame (s1->info->ref, s2->info->ref));
1994 return ((s2->kind == SK_SPECIAL) && s1->info->spec == s2->info->spec);
1996 return ((s2->kind == SK_DERIVED) && sRef_realSame (s1->info->ref, s2->info->ref));
1997 case SK_UNCONSTRAINED:
1998 return ((s2->kind == SK_UNCONSTRAINED)
1999 && (cstring_equal (s1->info->fname, s2->info->fname)));
2005 return TRUE; /* changed this! was false */
2011 sRef_sameObject (sRef s1, sRef s2)
2017 ** same is similar to similar, but not quite the same.
2019 ** Similarly to similar, same checks is two sRefs are the same.
2020 ** The similarities end, however, when same compares arrays
2021 ** with unknown indexes. Similar returns false; same returns true.
2025 sRef_same (sRef s1, sRef s2)
2027 if (s1 == s2) return TRUE;
2028 if (sRef_isInvalid (s1) || sRef_isInvalid (s2)) return FALSE;
2033 return ((s2->kind == SK_CVAR) && (cref_equal (s1->info->cvar, s2->info->cvar)));
2035 return ((s2->kind == SK_PARAM) && (s1->info->paramno == s2->info->paramno));
2037 if (s2->kind == SK_ARRAYFETCH)
2039 llassert (s1->info->field->rec != s1);
2040 if (sRef_same (s1->info->arrayfetch->arr, s2->info->arrayfetch->arr))
2042 if (s1->info->arrayfetch->indknown && s2->info->arrayfetch->indknown)
2044 return (s1->info->arrayfetch->ind == s2->info->arrayfetch->ind);
2052 llassert (s1->info->field->rec != s1);
2053 return ((s2->kind == SK_FIELD &&
2054 (sRef_same (s1->info->field->rec, s2->info->field->rec) &&
2055 cstring_equal (s1->info->field->field, s2->info->field->field))));
2059 llassert (s1->info->ref != s1);
2060 return ((s2->kind == SK_PTR) && sRef_same (s1->info->ref, s2->info->ref));
2064 llassert (s1->info->ref != s1);
2065 return ((s2->kind == SK_ADR) && sRef_same (s1->info->ref, s2->info->ref));
2068 llassert (s1->info->conj->a != s1);
2069 llassert (s1->info->conj->b != s1);
2070 return ((sRef_same (s1->info->conj->a, s2)) && /* or or and? */
2071 (sRef_same (s1->info->conj->b, s2)));
2073 return ((s2->kind == SK_SPECIAL) && s1->info->spec == s2->info->spec);
2075 llassert (s1->info->ref != s1);
2076 return ((s2->kind == SK_DERIVED) && sRef_same (s1->info->ref, s2->info->ref));
2078 case SK_UNCONSTRAINED:
2091 ** sort of similar, for use in def/use
2095 sRef_closeEnough (sRef s1, sRef s2)
2097 if (s1 == s2) return TRUE;
2098 if (sRef_isInvalid (s1) || sRef_isInvalid (s2)) return FALSE;
2103 return (((s2->kind == SK_CVAR) &&
2104 (cref_equal (s1->info->cvar, s2->info->cvar))) ||
2105 (s2->kind == SK_UNCONSTRAINED && s1->info->cvar->lexlevel == 0));
2106 case SK_UNCONSTRAINED:
2107 return (s2->kind == SK_UNCONSTRAINED
2108 || ((s2->kind == SK_CVAR) && (s2->info->cvar->lexlevel == 0)));
2110 return ((s2->kind == SK_PARAM)
2111 && (s1->info->paramno == s2->info->paramno));
2113 if (s2->kind == SK_ARRAYFETCH)
2115 if (sRef_closeEnough (s1->info->arrayfetch->arr, s2->info->arrayfetch->arr))
2117 if (s1->info->arrayfetch->indknown && s2->info->arrayfetch->indknown)
2119 return (s1->info->arrayfetch->ind == s2->info->arrayfetch->ind);
2126 return ((s2->kind == SK_FIELD &&
2127 (sRef_closeEnough (s1->info->field->rec, s2->info->field->rec) &&
2128 cstring_equal (s1->info->field->field, s2->info->field->field))));
2130 return ((s2->kind == SK_PTR) && sRef_closeEnough (s1->info->ref, s2->info->ref));
2132 return ((s2->kind == SK_ADR) && sRef_closeEnough (s1->info->ref, s2->info->ref));
2134 return ((s2->kind == SK_DERIVED) && sRef_closeEnough (s1->info->ref, s2->info->ref));
2136 return ((sRef_closeEnough (s1->info->conj->a, s2)) ||
2137 (sRef_closeEnough (s1->info->conj->b, s2)));
2139 return ((s2->kind == SK_SPECIAL) && s1->info->spec == s2->info->spec);
2155 s is an sRef of a formal paramenter in a function call constraint
2156 we trys to return a constraint expression derived from the actual parementer of a function call.
2158 /*@only@*/ constraintExpr sRef_fixConstraintParam (/*@observer@*/ sRef s, /*@observer@*/ /*@temp@*/ exprNodeList args)
2162 if (sRef_isInvalid (s))
2163 llfatalbug((message("Invalid sRef")));
2169 // s = sRef_saveCopy(s);
2170 ce = constraintExpr_makeTermsRef (s);
2177 temp = (sRef_makeField (sRef_fixBaseParam (s->info->field->rec, args),
2178 s->info->field->field));
2179 ce = constraintExpr_makeTermsRef (temp);
2185 temp = (sRef_makePointer (sRef_fixBaseParam (s->info->ref, args)));
2186 //temp = sRef_saveCopy(temp);
2187 ce = constraintExpr_makeTermsRef (temp);
2194 temp = sRef_saveCopy(s);
2195 temp = sRef_fixBaseParam (temp, args);
2196 ce = constraintExpr_makeTermsRef (temp);
2204 temp = sRef_saveCopy(s);
2205 ce = constraintExpr_makeTermsRef (temp);
2210 llassert(exprNodeList_size (args) > s->info->paramno);
2212 exprNode e = exprNodeList_nth (args, s->info->paramno);
2214 llassert( !(exprNode_isError (e)) );
2215 ce = constraintExpr_makeExprNode (e);
2222 llcontbug ((message("Trying to do fixConstraintParam on nonparam, nonglobal: %q for function with arguments %q", sRef_unparse (s), exprNodeList_unparse(args) ) ));
2223 temp = sRef_saveCopy(s);
2224 ce = constraintExpr_makeTermsRef (temp);
2236 sRef_fixBaseParam (/*@returned@*/ sRef s, exprNodeList args)
2238 if (sRef_isInvalid (s)) return (sRef_undefined);
2242 case SK_UNCONSTRAINED:
2247 if (exprNodeList_size (args) > s->info->paramno)
2249 exprNode e = exprNodeList_nth (args, s->info->paramno);
2251 if (exprNode_isError (e))
2253 return sRef_makeUnknown ();
2256 return (exprNode_getSref (e));
2260 return sRef_makeUnknown ();
2265 if (s->info->arrayfetch->indknown)
2267 return (sRef_makeArrayFetchKnown
2268 (sRef_fixBaseParam (s->info->arrayfetch->arr, args),
2269 s->info->arrayfetch->ind));
2273 return (sRef_makeArrayFetch
2274 (sRef_fixBaseParam (s->info->arrayfetch->arr, args)));
2277 return (sRef_makeField (sRef_fixBaseParam (s->info->field->rec, args),
2278 s->info->field->field));
2281 return (sRef_makePointer (sRef_fixBaseParam (s->info->ref, args)));
2284 return (sRef_makeAddress (sRef_fixBaseParam (s->info->ref, args)));
2287 return (sRef_makeConj (sRef_fixBaseParam (s->info->conj->a, args),
2288 sRef_fixBaseParam (s->info->conj->b, args)));
2304 sRef_undumpGlobal (char **c)
2314 usymId uid = usymId_fromInt (reader_getInt (c));
2319 reader_checkChar (c, '@');
2320 defstate = sstate_fromInt (reader_getInt (c));
2322 reader_checkChar (c, '@');
2323 nullstate = nstate_fromInt (reader_getInt (c));
2325 ret = sRef_makeGlobal (uid, ctype_unknown);
2326 sRef_setNullStateN (ret, nullstate);
2327 ret->defstate = defstate;
2332 int i = reader_getInt (c);
2333 speckind sk = speckind_fromInt (i);
2337 case SR_NOTHING: return (sRef_makeNothing ());
2338 case SR_INTERNAL: return (sRef_makeInternalState ());
2339 case SR_SPECSTATE: return (sRef_makeSpecState ());
2340 case SR_SYSTEM: return (sRef_makeSystemState ());
2341 case SR_GLOBALMARKER: BADBRANCH;
2346 return sRef_undefined;
2348 return sRef_makeUnknown ();
2350 return sRef_makeUnknown ();
2352 llfatalerror (message ("sRef_undumpGlobal: bad line: %s",
2353 cstring_fromChars (*c)));
2359 sRef_undump (char **c)
2368 return (sRef_makeGlobal (usymId_fromInt (reader_getInt (c)), ctype_unknown));
2370 return (sRef_makeParam (reader_getInt (c), ctype_unknown));
2372 return (sRef_makeResult (ctype_undump (c)));
2375 if ((**c >= '0' && **c <= '9') || **c == '-')
2377 int i = reader_getInt (c);
2378 sRef arr = sRef_undump (c);
2379 sRef ret = sRef_buildArrayFetchKnown (arr, i);
2385 sRef arr = sRef_undump (c);
2386 sRef ret = sRef_buildArrayFetch (arr);
2393 cstring fname = cstring_undefined;
2398 fname = cstring_appendChar (fname, **c);
2403 ret = sRef_buildField (sRef_undump (c), fname);
2404 cstring_markOwned (fname);
2409 int i = reader_getInt (c);
2410 speckind sk = speckind_fromInt (i);
2414 case SR_NOTHING: return (sRef_makeNothing ());
2415 case SR_INTERNAL: return (sRef_makeInternalState ());
2416 case SR_SPECSTATE: return (sRef_makeSpecState ());
2417 case SR_SYSTEM: return (sRef_makeSystemState ());
2418 case SR_GLOBALMARKER: BADBRANCH;
2424 sRef ptr = sRef_undump (c);
2425 sRef ret = sRef_makePointer (ptr);
2431 sRef adr = sRef_undump (c);
2432 sRef ret = sRef_makeAddress (adr);
2438 return (sRef_makeObject (ctype_undump (c)));
2442 sRef s1 = sRef_undump (c);
2443 sRef s2 = ((*c)++, sRef_undump (c));
2444 sRef ret = sRef_makeConj (s1, s2);
2449 return sRef_undefined;
2451 return sRef_makeUnknown ();
2453 return sRef_makeUnknown ();
2455 llfatalerror (message ("sRef_undump: bad line: %s", cstring_fromChars (*c)));
2463 if (sRef_isInvalid (s))
2465 return (cstring_makeLiteral ("-"));
2472 return (message ("p%d", s->info->paramno));
2474 if (s->info->arrayfetch->indknown)
2476 return (message ("a%d%q", s->info->arrayfetch->ind,
2477 sRef_dump (s->info->arrayfetch->arr)));
2481 return (message ("a%q", sRef_dump (s->info->arrayfetch->arr)));
2484 return (message ("f%s.%q", s->info->field->field,
2485 sRef_dump (s->info->field->rec)));
2487 return (message ("t%q", sRef_dump (s->info->ref)));
2489 return (message ("d%q", sRef_dump (s->info->ref)));
2491 return (message ("o%q", ctype_dump (s->info->object)));
2493 return (message ("s%d", (int) s->info->spec));
2495 return (message ("c%q.%q",
2496 sRef_dump (s->info->conj->a),
2497 sRef_dump (s->info->conj->b)));
2499 if (sRef_isFileOrGlobalScope (s))
2501 return (message ("g%d",
2502 usymtab_convertId (s->info->cvar->index)));
2506 llcontbug (message ("Dumping local variable: %q",
2507 sRef_unparseDebug (s)));
2508 return (cstring_makeLiteral ("u"));
2511 return (cstring_makeLiteral ("u"));
2513 return (message ("r%q", ctype_dump (s->type)));
2519 case SK_UNCONSTRAINED:
2520 llcontbug (message ("sRef_dump: bad kind: %q",
2521 sRef_unparseFull (s)));
2522 return (cstring_makeLiteral ("x"));
2529 cstring sRef_dumpGlobal (sRef s)
2531 if (sRef_isInvalid (s))
2533 return (cstring_makeLiteral ("-"));
2540 if (sRef_isFileOrGlobalScope (s))
2542 return (message ("g%d@%d@%d",
2543 usymtab_convertId (s->info->cvar->index),
2545 (int) sRef_getNullState (s)));
2549 llcontbug (message ("Dumping local variable: %q",
2550 sRef_unparseDebug (s)));
2551 return (cstring_makeLiteral ("u"));
2554 return (cstring_makeLiteral ("u"));
2556 return (message ("s%d", (int) s->info->spec));
2558 llcontbug (message ("sRef_dumpGlobal: bad kind: %q",
2559 sRef_unparseFull (s)));
2560 return (cstring_makeLiteral ("x"));
2568 sRef_deriveType (sRef s, uentryList cl)
2570 if (sRef_isInvalid (s)) return ctype_unknown;
2575 return (uentry_getType (usymtab_getRefQuiet (s->info->cvar->lexlevel,
2576 s->info->cvar->index)));
2577 case SK_UNCONSTRAINED:
2578 return (ctype_unknown);
2580 if (s->info->paramno >= 0)
2582 return uentry_getType (uentryList_getN (cl, s->info->paramno));
2586 return ctype_unknown;
2590 ctype ca = sRef_deriveType (s->info->arrayfetch->arr, cl);
2592 if (ctype_isArray (ca))
2594 return (ctype_baseArrayPtr (ca));
2596 else if (ctype_isUnknown (ca))
2602 llcontbuglit ("sRef_deriveType: inconsistent array type");
2608 ctype ct = sRef_deriveType (s->info->field->rec, cl);
2610 if (ctype_isStructorUnion (ct))
2612 uentry ue = uentryList_lookupField (ctype_getFields (ct),
2613 s->info->field->field);
2615 if (uentry_isValid (ue))
2617 return (uentry_getType (ue));
2621 llcontbuglit ("sRef_deriveType: bad field");
2622 return ctype_unknown;
2625 else if (ctype_isUnknown (ct))
2631 llcontbuglit ("sRef_deriveType: inconsistent field type");
2637 ctype ct = sRef_deriveType (s->info->ref, cl);
2639 if (ctype_isUnknown (ct)) return ct;
2640 if (ctype_isPointer (ct)) return (ctype_baseArrayPtr (ct));
2643 llcontbuglit ("sRef_deriveType: inconsistent pointer type");
2649 ctype ct = sRef_deriveType (s->info->ref, cl);
2651 if (ctype_isUnknown (ct)) return ct;
2652 return ctype_makePointer (ct);
2656 return sRef_deriveType (s->info->ref, cl);
2660 return (s->info->object);
2664 return (ctype_makeConj (sRef_deriveType (s->info->conj->a, cl),
2665 sRef_deriveType (s->info->conj->b, cl)));
2677 return ctype_unknown;
2683 sRef_getType (sRef s)
2685 if (sRef_isInvalid (s)) return ctype_unknown;
2691 sRef_unparseOpt (sRef s)
2693 sRef rb = sRef_getRootBase (s);
2695 if (sRef_isMeaningful (rb) && !sRef_isConst (rb))
2697 cstring ret = sRef_unparse (s);
2699 llassertprint (!cstring_equalLit (ret, "?"), ("print: %s", sRef_unparseDebug (s)));
2701 if (!cstring_isEmpty (ret))
2703 return (cstring_appendChar (ret, ' '));
2711 return cstring_undefined;
2715 sRef_unparsePreOpt (sRef s)
2717 sRef rb = sRef_getRootBase (s);
2719 if (sRef_isMeaningful (rb) && !sRef_isConst (rb))
2721 cstring ret = sRef_unparse (s);
2723 llassertprint (!cstring_equalLit (ret, "?"), ("print: %s", sRef_unparseDebug (s)));
2724 return (cstring_prependCharO (' ', ret));
2727 return cstring_undefined;
2731 sRef_unparse (sRef s)
2733 if (sRef_isInvalid (s)) return (cstring_makeLiteral ("?"));
2735 if (context_inFunctionLike ())
2737 return (sRef_unparseWithArgs (s, context_getParams ()));
2741 DPRINTF (("Not in function like: %s", context_unparse ()));
2742 return (sRef_unparseNoArgs (s));
2746 static /*@only@*/ cstring
2747 sRef_unparseWithArgs (sRef s, uentryList args)
2749 if (sRef_isInvalid (s))
2751 return (cstring_makeLiteral ("?"));
2757 return (uentry_getName (usymtab_getRefQuiet (s->info->cvar->lexlevel,
2758 s->info->cvar->index)));
2759 case SK_UNCONSTRAINED:
2760 return (cstring_copy (s->info->fname));
2763 if (s->info->paramno < uentryList_size (args)
2764 && s->info->paramno >= 0)
2766 uentry ue = uentryList_getN (args, s->info->paramno);
2768 if (uentry_isValid (ue))
2769 return uentry_getName (ue);
2772 return (message ("<bad param: %q / args %q",
2773 sRef_unparseDebug (s),
2774 uentryList_unparse (args)));
2777 if (s->info->arrayfetch->indknown)
2779 return (message ("%q[%d]", sRef_unparseWithArgs (s->info->arrayfetch->arr, args),
2780 s->info->arrayfetch->ind));
2784 return (message ("%q[]", sRef_unparseWithArgs (s->info->arrayfetch->arr, args)));
2787 if (s->info->field->rec->kind == SK_PTR)
2789 sRef ptr = s->info->field->rec;
2791 return (message ("%q->%s", sRef_unparseWithArgs (ptr->info->ref, args),
2792 s->info->field->field));
2794 return (message ("%q.%s", sRef_unparseWithArgs (s->info->field->rec, args),
2795 s->info->field->field));
2799 sRef ref = sRef_fixConj (s->info->ref);
2800 skind sk = ref->kind;
2805 ret = message ("storage pointed to by %q",
2806 sRef_unparseWithArgs (ref, args));
2808 else if (skind_isSimple (sk) || sk == SK_PTR)
2810 ret = message ("*%q", sRef_unparseWithArgs (ref, args));
2814 ret = message ("*(%q)", sRef_unparseWithArgs (ref, args));
2820 return (message ("&%q", sRef_unparseWithArgs (s->info->ref, args)));
2822 return (cstring_copy (ctype_unparse (s->info->object)));
2824 return (sRef_unparseWithArgs (sRef_getConjA (s), args));
2826 if (cstring_isDefined (s->info->fname))
2828 return (message ("[result of %s]", s->info->fname));
2832 return (cstring_makeLiteral ("<new>"));
2835 return (cstring_makeLiteral ("?"));
2837 return (message ("<derived %q>", sRef_unparse (s->info->ref)));
2839 return (message ("<external %q>", sRef_unparse (s->info->ref)));
2841 return (message ("<type %s>", ctype_unparse (s->type)));
2843 return (message ("<const %s>", ctype_unparse (s->type)));
2845 switch (s->info->spec)
2847 case SR_NOTHING: return cstring_makeLiteral ("nothing");
2848 case SR_INTERNAL: return cstring_makeLiteral ("internal state");
2849 case SR_SPECSTATE: return cstring_makeLiteral ("spec state");
2850 case SR_SYSTEM: return cstring_makeLiteral ("file system state");
2851 case SR_GLOBALMARKER: return cstring_makeLiteral ("<global marker>");
2855 return cstring_makeLiteral ("result");
2858 llbug (message ("Bad sref, kind = %d", (int) s->kind));
2866 sRef_unparseDebug (sRef s)
2868 if (sRef_isInvalid (s))
2870 return (cstring_makeLiteral ("<undef>"));
2876 case SK_UNCONSTRAINED:
2877 return (message ("<unconstrained %s>", s->info->fname));
2882 ce = usymtab_getRefQuiet (s->info->cvar->lexlevel, s->info->cvar->index);
2884 if (uentry_isInvalid (ce))
2886 return (message ("<scope: %d.%d *invalid*>",
2887 s->info->cvar->lexlevel,
2888 s->info->cvar->index));
2892 return (message ("<scope: %d.%d *%q*>",
2893 s->info->cvar->lexlevel,
2894 s->info->cvar->index,
2895 uentry_getName (ce)));
2901 return (message ("<parameter %d>", s->info->paramno + 1));
2904 if (s->info->arrayfetch->indknown)
2906 return (message ("%q[%d]", sRef_unparseDebug (s->info->arrayfetch->arr),
2907 s->info->arrayfetch->ind));
2911 return (message ("%q[]", sRef_unparseDebug (s->info->arrayfetch->arr)));
2914 return (message ("%q.%s", sRef_unparseDebug (s->info->field->rec),
2915 s->info->field->field));
2917 if (sRef_isField (s->info->ref))
2919 sRef fld = s->info->ref;
2921 return (message ("%q->%s", sRef_unparseDebug (fld->info->field->rec),
2922 fld->info->field->field));
2926 return (message ("*(%q)", sRef_unparseDebug (s->info->ref)));
2929 return (message ("&%q", sRef_unparseDebug (s->info->ref)));
2931 return (message ("<object type %s>", ctype_unparse (s->info->object)));
2933 return (message ("%q | %q", sRef_unparseDebug (s->info->conj->a),
2934 sRef_unparseDebug (s->info->conj->b)));
2936 return message ("<new: %s>", s->info->fname);
2938 return (message ("<derived %q>", sRef_unparseDebug (s->info->ref)));
2940 return (message ("<external %q>", sRef_unparseDebug (s->info->ref)));
2942 return (message ("<type %s>", ctype_unparse (s->type)));
2944 return (message ("<const %s>", ctype_unparse (s->type)));
2946 return (message ("<result %s>", ctype_unparse (s->type)));
2948 return (message ("<spec %s>",
2949 cstring_makeLiteralTemp
2950 (s->info->spec == SR_NOTHING ? "nothing"
2951 : s->info->spec == SR_INTERNAL ? "internalState"
2952 : s->info->spec == SR_SPECSTATE ? "spec state"
2953 : s->info->spec == SR_SYSTEM ? "fileSystem"
2956 return cstring_makeLiteral ("<unknown>");
2962 static /*@only@*/ cstring
2963 sRef_unparseNoArgs (sRef s)
2965 if (sRef_isInvalid (s)) return (cstring_makeLiteral ("?"));
2969 case SK_UNCONSTRAINED:
2970 return (cstring_copy (s->info->fname));
2973 uentry ce = usymtab_getRefQuiet (s->info->cvar->lexlevel,
2974 s->info->cvar->index);
2976 if (uentry_isInvalid (ce))
2978 llcontbug (message ("sRef_unparseNoArgs: bad cvar: %q",
2979 sRef_unparseDebug (s)));
2980 return (sRef_unparseDebug (s));
2984 return (uentry_getName (ce));
2988 if (s->info->arrayfetch->indknown)
2990 return (message ("%q[%d]", sRef_unparseNoArgs (s->info->arrayfetch->arr),
2991 s->info->arrayfetch->ind));
2995 return (message ("%q[]", sRef_unparseNoArgs (s->info->arrayfetch->arr)));
2998 return (message ("%q.%s", sRef_unparseNoArgs (s->info->field->rec),
2999 s->info->field->field));
3002 sRef ref = sRef_fixConj (s->info->ref);
3003 skind sk = ref->kind;
3006 if (skind_isSimple (sk) || sk == SK_PTR)
3008 ret = message ("*%q", sRef_unparseNoArgs (ref));
3012 ret = message ("*(%q)", sRef_unparseNoArgs (ref));
3018 return (message ("&%q", sRef_unparseNoArgs (s->info->ref)));
3020 return (cstring_copy (ctype_unparse (s->info->object)));
3022 return (sRef_unparseNoArgs (s->info->conj->a));
3024 return (message ("result of %s", s->info->fname));
3026 return (message ("<der %q>", sRef_unparseNoArgs (s->info->ref)));
3028 return message ("<ext %q>", sRef_unparseNoArgs (s->info->ref));
3030 return (cstring_makeLiteral
3031 (s->info->spec == SR_NOTHING ? "nothing"
3032 : s->info->spec == SR_INTERNAL ? "internal state"
3033 : s->info->spec == SR_SPECSTATE ? "spec state"
3034 : s->info->spec == SR_SYSTEM ? "file system state"
3037 return cstring_makeLiteral ("result");
3041 return cstring_makeLiteral ("?");
3043 /* llcontbug (message ("sRef_unparseNoArgs: bad case: %q", sRef_unparseDebug (s))); */
3044 return (sRef_unparseDebug (s));
3049 /*@dependent@*/ sRef sRef_makeUnconstrained (cstring fname)
3051 sRef s = sRef_new ();
3053 s->kind = SK_UNCONSTRAINED;
3054 s->info = (sinfo) dmalloc (sizeof (*s->info));
3055 s->info->fname = fname;
3060 cstring sRef_unconstrainedName (sRef s)
3062 llassert (sRef_isUnconstrained (s));
3064 return s->info->fname;
3067 bool sRef_isUnconstrained (sRef s)
3069 return (sRef_isValid(s) && s->kind == SK_UNCONSTRAINED);
3072 static /*@dependent@*/ /*@notnull@*/ sRef
3073 sRef_makeCvarAux (int level, usymId index, ctype ct)
3075 sRef s = sRef_newRef ();
3078 s->info = (sinfo) dmalloc (sizeof (*s->info));
3080 s->info->cvar = (cref) dmalloc (sizeof (*s->info->cvar));
3081 s->info->cvar->lexlevel = level;
3082 s->info->cvar->index = index;
3084 /* for now, all globals are defined; all locals, aren't */
3086 if (level <= fileScope)
3088 s->defstate = SS_UNKNOWN;
3092 ctype rct = ctype_realType (ct);
3094 if (level != paramsScope
3095 && (ctype_isStructorUnion (rct) || ctype_isRealArray (rct)))
3097 s->defstate = SS_ALLOCATED;
3098 s->oaliaskind = s->aliaskind = AK_STACK;
3102 s->defstate = SS_UNDEFINED;
3103 s->oaliaskind = s->aliaskind = AK_LOCAL;
3109 llassert (level >= globScope);
3110 llassert (usymId_isValid (index));
3112 DPRINTF (("Made cvar: [%p] %s", s, sRef_unparseDebug (s)));
3113 llassert (valueTable_isUndefined (s->state));
3114 s->state = context_createValueTable (s);
3118 /*@dependent@*/ sRef sRef_makeCvar (int level, usymId index, ctype ct)
3120 return (sRef_makeCvarAux (level, index, ct));
3123 int sRef_lexLevel (sRef s)
3125 if (sRef_isValid (s))
3129 conj = sRef_fixConj (s);
3130 s = sRef_getRootBase (conj);
3132 if (sRef_isValid (s) && s->kind == SK_CVAR)
3134 return (s->info->cvar->lexlevel);
3142 sRef_makeGlobal (usymId l, ctype ct)
3144 return (sRef_makeCvar (globScope, l, ct));
3148 sRef_setParamNo (sRef s, int l)
3150 llassert (sRef_isValid (s) && s->kind == SK_PARAM);
3151 s->info->paramno = l;
3155 /*@dependent@*/ sRef
3156 sRef_makeParam (int l, ctype ct)
3158 sRef s = sRef_new ();
3163 s->info = (sinfo) dmalloc (sizeof (*s->info));
3164 s->info->paramno = l;
3166 s->defstate = SS_UNKNOWN;
3167 /* (probably defined, unless its an out parameter) */
3169 llassert (valueTable_isUndefined (s->state));
3170 s->state = context_createValueTable (s);
3175 sRef_isIndexKnown (sRef arr)
3179 llassert (sRef_isValid (arr));
3180 arr = sRef_fixConj (arr);
3182 llassert (arr->kind == SK_ARRAYFETCH);
3183 res = arr->info->arrayfetch->indknown;
3188 sRef_getIndex (sRef arr)
3192 llassert (sRef_isValid (arr));
3193 arr = sRef_fixConj (arr);
3195 llassert (arr->kind == SK_ARRAYFETCH);
3197 if (!arr->info->arrayfetch->indknown)
3199 llcontbug (message ("sRef_getIndex: unknown: %q", sRef_unparse (arr)));
3204 result = arr->info->arrayfetch->ind;
3210 static bool sRef_isZerothArrayFetch (/*@notnull@*/ sRef s)
3212 return (s->kind == SK_ARRAYFETCH
3213 && s->info->arrayfetch->indknown
3214 && (s->info->arrayfetch->ind == 0));
3217 /*@exposed@*/ sRef sRef_makeAddress (/*@exposed@*/ sRef t)
3220 if (sRef_isInvalid (t)) return sRef_undefined;
3222 if (sRef_isPointer (t))
3224 return (t->info->ref);
3226 else if (sRef_isZerothArrayFetch (t))
3228 return (t->info->arrayfetch->arr);
3232 sRef s = sRef_newRef ();
3235 s->type = ctype_makePointer (t->type);
3236 s->info = (sinfo) dmalloc (sizeof (*s->info));
3237 s->info->ref = t; /* sRef_copy (t); */ /*@i32@*/
3239 if (t->defstate == SS_UNDEFINED)
3240 /* no! it is allocated even still: && !ctype_isPointer (t->type)) */
3242 s->defstate = SS_ALLOCATED;
3246 s->defstate = t->defstate;
3249 if (t->aliaskind == AK_LOCAL)
3251 if (sRef_isLocalVar (t))
3253 s->aliaskind = AK_STACK;
3257 llassert (valueTable_isUndefined (s->state));
3258 s->state = context_createValueTable (s);
3263 cstring sRef_getField (sRef s)
3267 llassert (sRef_isValid (s));
3268 s = sRef_fixConj (s);
3270 llassertprint (sRef_isValid (s) && (s->kind == SK_FIELD),
3271 ("s = %s", sRef_unparseDebug (s)));
3273 res = s->info->field->field;
3277 sRef sRef_getBase (sRef s)
3281 if (sRef_isInvalid (s)) return (sRef_undefined);
3283 s = sRef_fixConj (s);
3294 res = s->info->field->rec;
3298 res = s->info->arrayfetch->arr;
3302 res = sRef_undefined; /* shouldn't need it */
3309 ** same as getBase, except returns invalid
3310 ** (and doesn't use adr's)
3314 sRef_getBaseSafe (sRef s)
3318 if (sRef_isInvalid (s)) { return sRef_undefined; }
3320 s = sRef_fixConj (s);
3328 res = s->info->field->rec; break;
3330 res = s->info->arrayfetch->arr;
3333 res = sRef_undefined; break;
3339 /*@constant int MAXBASEDEPTH;@*/
3340 # define MAXBASEDEPTH 25
3342 static /*@exposed@*/ sRef
3343 sRef_getRootBaseAux (sRef s, int depth)
3345 if (sRef_isInvalid (s)) return sRef_undefined;
3347 if (depth > MAXBASEDEPTH)
3350 ("Warning: reference base limit exceeded for %q. "
3351 "This either means there is a variable with at least "
3352 "%d indirections from this reference, or "
3353 "there is a bug in LCLint.",
3358 return sRef_undefined;
3365 return (sRef_getRootBaseAux (s->info->ref, depth + 1));
3367 return (sRef_getRootBaseAux (s->info->field->rec, depth + 1));
3369 return (sRef_getRootBaseAux (s->info->arrayfetch->arr, depth + 1));
3371 return (sRef_getRootBaseAux (sRef_fixConj (s), depth + 1));
3377 sRef sRef_getRootBase (sRef s)
3379 return (sRef_getRootBaseAux (s, 0));
3382 static bool sRef_isDeep (sRef s)
3384 if (sRef_isInvalid (s)) return FALSE;
3394 return (sRef_isDeep (sRef_fixConj (s)));
3400 static int sRef_depth (sRef s)
3402 if (sRef_isInvalid (s)) return 0;
3410 return 1 + sRef_depth (s->info->ref);
3412 return 1 + sRef_depth (s->info->field->rec);
3414 return 1 + sRef_depth (s->info->arrayfetch->arr);
3416 return (sRef_depth (sRef_fixConj (s)));
3423 sRef_makeObject (ctype o)
3425 sRef s = sRef_newRef (); /*@i423 same line is bad...@*/
3427 s->kind = SK_OBJECT;
3428 s->info = (sinfo) dmalloc (sizeof (*s->info));
3429 s->info->object = o;
3430 llassert (valueTable_isUndefined (s->state));
3431 s->state = context_createValueTable (s);
3436 ** This is used to represent storage referenced by a parameter.
3439 sRef sRef_makeExternal (sRef t)
3441 sRef s = sRef_newRef ();
3443 llassert (sRef_isValid (t));
3445 s->kind = SK_EXTERNAL;
3446 s->info = (sinfo) dmalloc (sizeof (*s->info));
3448 s->info->ref = t; /* sRef_copy (t); */ /*@i32 was exposed@*/
3449 llassert (valueTable_isUndefined (s->state));
3450 s->state = context_createValueTable (s);
3454 /*@dependent@*/ sRef sRef_makeDerived (/*@exposed@*/ sRef t)
3456 if (sRef_isValid (t))
3458 sRef s = sRef_newRef ();
3460 s->kind = SK_DERIVED;
3461 s->info = (sinfo) dmalloc (sizeof (*s->info));
3462 s->info->ref = t; /* sRef_copy (t); */ /*@i32@*/
3465 llassert (valueTable_isUndefined (s->state));
3466 s->state = context_createValueTable (s);
3471 return sRef_undefined;
3476 ** definitely NOT symmetric:
3478 ** res fills in unknown state information from other
3482 sRef_mergeStateQuiet (sRef res, sRef other)
3484 llassert (sRef_isValid (res));
3485 llassert (sRef_isValid (other));
3487 res->modified = res->modified || other->modified;
3488 res->safe = res->safe && other->safe;
3490 if (res->defstate == SS_UNKNOWN)
3492 res->defstate = other->defstate;
3493 res->definfo = stateInfo_update (res->definfo, other->definfo);
3496 if (res->aliaskind == AK_UNKNOWN ||
3497 (res->aliaskind == AK_LOCAL && alkind_isKnown (other->aliaskind)))
3499 res->aliaskind = other->aliaskind;
3500 res->oaliaskind = other->oaliaskind;
3501 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
3504 if (res->expkind == XO_UNKNOWN)
3506 res->expkind = other->expkind;
3507 res->oexpkind = other->oexpkind;
3508 res->expinfo = stateInfo_update (res->expinfo, other->expinfo);
3511 /* out takes precedence over implicitly defined */
3512 if (res->defstate == SS_DEFINED && other->defstate != SS_UNKNOWN)
3514 res->defstate = other->defstate;
3515 res->definfo = stateInfo_update (res->definfo, other->definfo);
3518 if (sRef_getNullState (other) == NS_ERROR || sRef_getNullState (res) == NS_ERROR)
3520 sRef_setNullState (res, NS_ERROR, fileloc_undefined);
3524 if (sRef_getNullState (other) != NS_UNKNOWN
3525 && (sRef_getNullState (res) == NS_UNKNOWN || sRef_getNullState (res) == NS_NOTNULL
3526 || sRef_getNullState (res) == NS_MNOTNULL))
3528 sRef_updateNullState (res, other);
3534 ** definitely NOT symmetric:
3536 ** res fills in known state information from other
3540 sRef_mergeStateQuietReverse (/*@dependent@*/ sRef res, /*@dependent@*/ sRef other)
3542 bool changed = FALSE;
3544 llassert (sRef_isValid (res));
3545 llassert (sRef_isValid (other));
3546 sRef_checkMutable (res);
3548 if (res->kind != other->kind)
3554 res->kind = other->kind;
3555 res->type = other->type;
3556 res->info = sinfo_fullCopy (other);
3560 if (!ctype_equal (res->type, other->type))
3563 res->type = other->type;
3566 sinfo_update (res, other);
3569 res->modified = res->modified || other->modified;
3570 res->safe = res->safe && other->safe;
3572 if (res->aliaskind != other->aliaskind
3573 && (res->aliaskind == AK_UNKNOWN
3574 || ((res->aliaskind == AK_LOCAL
3575 || (res->aliaskind == AK_REFCOUNTED
3576 && other->aliaskind != AK_LOCAL))
3577 && other->aliaskind != AK_UNKNOWN)))
3580 res->aliaskind = other->aliaskind;
3581 res->oaliaskind = other->oaliaskind;
3582 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
3585 if (other->expkind != XO_UNKNOWN && other->expkind != res->expkind)
3588 res->expkind = other->expkind;
3589 res->expinfo = stateInfo_update (res->expinfo, other->expinfo);
3592 if (other->oexpkind != XO_UNKNOWN)
3594 res->oexpkind = other->oexpkind;
3597 /* out takes precedence over implicitly defined */
3599 if (res->defstate != other->defstate)
3601 if (other->defstate != SS_UNKNOWN)
3603 res->defstate = other->defstate;
3607 if (sRef_getNullState (other) == NS_ERROR || sRef_getNullState (res) == NS_ERROR)
3609 if (sRef_getNullState (res) != NS_ERROR)
3611 sRef_setNullStateN (res, NS_ERROR);
3617 if (sRef_getNullState (other) != NS_UNKNOWN && sRef_getNullState (other) != sRef_getNullState (res))
3620 sRef_updateNullState (res, other);
3626 sRef_clearDerived (res);
3631 sRef_mergeState (sRef res, sRef other, clause cl, fileloc loc)
3633 if (sRef_isValid (res) && sRef_isValid (other))
3635 sRef_mergeStateAux (res, other, cl, FALSE, loc, TRUE);
3639 if (sRef_isInvalid (res))
3641 llbug (message ("sRef_mergeState: invalid res sRef: %q",
3642 sRef_unparseDebug (other)));
3646 llbug (message ("sRef_mergeState: invalid other sRef: %q",
3647 sRef_unparseDebug (res)));
3653 sRef_mergeOptState (sRef res, sRef other, clause cl, fileloc loc)
3655 if (sRef_isValid (res) && sRef_isValid (other))
3657 sRef_mergeStateAux (res, other, cl, TRUE, loc, TRUE);
3661 if (sRef_isInvalid (res))
3663 llbug (message ("sRef_mergeOptState: invalid res sRef: %q",
3664 sRef_unparseDebug (other)));
3668 llbug (message ("sRef_mergeOptState: invalid other sRef: %q",
3669 sRef_unparseDebug (res)));
3675 sRef_mergeStateAux (/*@notnull@*/ sRef res, /*@notnull@*/ sRef other,
3676 clause cl, bool opt, fileloc loc,
3680 llassertfatal (sRef_isValid (res));
3681 llassertfatal (sRef_isValid (other));
3683 sRef_checkMutable (res);
3684 sRef_checkMutable (other);
3686 res->modified = res->modified || other->modified;
3688 if (res->kind == other->kind
3689 || (other->kind == SK_UNKNOWN || res->kind == SK_UNKNOWN))
3691 sstate odef = other->defstate;
3692 sstate rdef = res->defstate;
3693 nstate onull = sRef_getNullState (other);
3696 ** yucky stuff to handle
3701 if (other->defstate == SS_DEAD
3702 && ((sRef_isOnly (res) && sRef_definitelyNull (res))
3703 || (res->defstate == SS_UNDEFINED
3704 || res->defstate == SS_UNUSEABLE)))
3706 if (res->defstate == SS_UNDEFINED
3707 || res->defstate == SS_UNUSEABLE)
3709 res->defstate = SS_UNUSEABLE;
3713 res->defstate = SS_DEAD;
3716 res->definfo = stateInfo_update (res->definfo, other->definfo);
3717 sRef_clearDerived (other);
3718 sRef_clearDerived (res);
3720 else if (res->defstate == SS_DEAD
3721 && ((sRef_isOnly (other) && sRef_definitelyNull (other))
3722 || (other->defstate == SS_UNDEFINED
3723 || other->defstate == SS_UNUSEABLE)))
3725 if (other->defstate == SS_UNDEFINED
3726 || other->defstate == SS_UNUSEABLE)
3728 res->defstate = SS_UNUSEABLE;
3732 res->defstate = SS_DEAD;
3735 sRef_clearDerived (other);
3736 sRef_clearDerived (res);
3738 else if (res->defstate == SS_DEFINED
3739 && (other->defstate == SS_ALLOCATED
3740 && sRef_definitelyNull (other)))
3742 other->defstate = SS_DEFINED; /* definitely null! */
3744 else if (other->defstate == SS_DEFINED
3745 && (res->defstate == SS_ALLOCATED && sRef_definitelyNull (res)))
3747 res->defstate = SS_DEFINED;
3748 res->definfo = stateInfo_update (res->definfo, other->definfo);
3755 if (res->defstate == SS_DEAD && other->defstate == SS_DEAD)
3757 sRef_clearDerived (other);
3758 sRef_clearDerived (res);
3762 ** only & dead isn't really an only!
3765 if (alkind_isOnly (other->aliaskind) && other->defstate == SS_DEAD)
3767 other->aliaskind = AK_UNKNOWN;
3770 if (alkind_isOnly (res->aliaskind) && res->defstate == SS_DEAD)
3772 res->aliaskind = AK_UNKNOWN;
3776 ** Dead and dependent -> dead
3779 if (alkind_isDependent (other->aliaskind) && res->defstate == SS_DEAD)
3781 other->aliaskind = AK_UNKNOWN;
3782 other->defstate = SS_DEAD;
3783 sRef_clearDerived (res);
3784 sRef_clearDerived (other);
3787 if (alkind_isDependent (res->aliaskind) && other->defstate == SS_DEAD)
3789 res->aliaskind = AK_UNKNOWN;
3790 res->defstate = SS_DEAD;
3791 sRef_clearDerived (res);
3792 sRef_clearDerived (other);
3796 ** must do alias combine first, since it depends on
3797 ** original values of state and null.
3800 sRef_combineAliasKinds (res, other, cl, loc);
3801 sRef_combineDefState (res, other);
3802 sRef_combineNullState (res, other);
3804 if (rdef == SS_ALLOCATED || rdef == SS_SPECIAL)
3806 if (odef == SS_DEFINED)
3808 if (onull == NS_DEFNULL || onull == NS_CONSTNULL)
3810 res->deriv = sRefSet_copyInto (res->deriv, other->deriv);
3811 DPRINTF (("Copy derivs: %s", sRef_unparseFull (res)));
3814 else if (odef == SS_ALLOCATED || odef == SS_SPECIAL)
3819 if (ctype_isUnion (ctype_realType (sRef_getType (res))))
3821 res->deriv = sRef_mergeUnionDerivs (res->deriv,
3824 DPRINTF (("Copy derivs: %s", sRef_unparseFull (res)));
3828 res->deriv = sRef_mergeDerivs (res->deriv, other->deriv,
3830 DPRINTF (("Copy derivs: %s", sRef_unparseFull (res)));
3838 res->deriv = sRef_mergeDerivs (res->deriv, other->deriv,
3840 DPRINTF (("Copy derivs: %s", sRef_unparseFull (res)));
3850 if (rdef == SS_PDEFINED
3851 || (rdef == SS_DEFINED && odef == SS_PDEFINED))
3855 res->deriv = sRef_mergePdefinedDerivs (res->deriv, other->deriv,
3857 DPRINTF (("Copy derivs: %s", sRef_unparseFull (res)));
3862 if ((rdef == SS_DEFINED || rdef == SS_UNKNOWN)
3863 && res->defstate == SS_ALLOCATED)
3865 res->deriv = sRefSet_copyInto (res->deriv, other->deriv);
3871 res->deriv = sRef_mergeDerivs (res->deriv, other->deriv,
3873 DPRINTF (("Copy derivs: %s", sRef_unparseFull (res)));
3880 sRef_combineExKinds (res, other);
3884 if (res->kind == SK_ARRAYFETCH && other->kind == SK_PTR)
3886 sRef nother = sRef_buildArrayFetchKnown (sRef_getBase (other), 0);
3888 sRef_copyState (nother, other);
3889 sRef_mergeStateAux (res, nother, cl, opt, loc, doDerivs);
3891 else if (res->kind == SK_PTR && other->kind == SK_ARRAYFETCH)
3893 sRef nother = sRef_buildPointer (sRef_getBase (other));
3895 if (sRef_isValid (nother))
3897 sRef_copyState (nother, other);
3898 sRef_mergeStateAux (res, nother, cl, opt, loc, doDerivs);
3903 llcontbug (message ("merge conj: %q / %q", sRef_unparseFull (res),
3904 sRef_unparseFull (other)));
3910 ** Merge value table states
3917 ** This doesn't do anything. And its broken too...
3920 valueTable_elements (res->state, key, sv)
3922 stateValue os = valueTable_lookup (other->state, key);
3923 /*@unused@*/ int val;
3924 /*@unused@*/ char *msg;
3926 llassert (stateValue_isDefined (os));
3928 DPRINTF (("Merge state: %s / %s",
3929 cstring_toCharsSafe (stateValue_unparse (sv)),
3930 cstring_toCharsSafe (stateValue_unparse (os))));
3932 val = valueMatix_lookup (key,
3933 stateValue_getValue (os),
3934 stateValue_getValue (sv),
3936 DPRINTF (("Val: %d / %s", val, msg));
3938 } end_valueTable_elements ;
3944 sRef_mergeUnionDerivs (/*@only@*/ sRefSet res,
3945 /*@exposed@*/ sRefSet other, bool opt,
3946 clause cl, fileloc loc)
3948 if (sRefSet_isEmpty (res))
3950 return sRefSet_copyInto (res, other);
3954 sRefSet_allElements (other, el)
3956 if (sRef_isValid (el))
3958 sRef e2 = sRefSet_lookupMember (other, el);
3960 if (sRef_isValid (e2))
3962 sRef_mergeStateAux (el, e2, cl, opt, loc, FALSE);
3966 res = sRefSet_insert (res, el);
3969 } end_sRefSet_allElements ;
3975 static /*@only@*/ sRefSet
3976 sRef_mergeDerivs (/*@only@*/ sRefSet res, sRefSet other,
3977 bool opt, clause cl, fileloc loc)
3979 sRefSet ret = sRefSet_new ();
3981 sRefSet_allElements (res, el)
3983 if (sRef_isValid (el))
3985 sRef e2 = sRefSet_lookupMember (other, el);
3987 if (sRef_isValid (e2))
3989 if (el->defstate == SS_ALLOCATED &&
3990 e2->defstate == SS_PDEFINED)
3992 e2->defstate = SS_ALLOCATED;
3994 else if (e2->defstate == SS_ALLOCATED &&
3995 el->defstate == SS_PDEFINED)
3997 el->defstate = SS_ALLOCATED;
3998 sRef_clearDerived (el);
4000 else if ((el->defstate == SS_DEAD || sRef_isKept (el)) &&
4001 (e2->defstate == SS_DEFINED && !sRef_isKept (e2)))
4004 if (checkDeadState (el, TRUE, loc))
4006 if (sRef_isThroughArrayFetch (el))
4008 sRef_maybeKill (el, loc);
4009 sRef_maybeKill (e2, loc);
4013 else if ((e2->defstate == SS_DEAD || sRef_isKept (e2)) &&
4014 (el->defstate == SS_DEFINED && !sRef_isKept (el)))
4017 if (checkDeadState (e2, FALSE, loc))
4019 if (sRef_isThroughArrayFetch (el))
4021 sRef_maybeKill (el, loc);
4022 sRef_maybeKill (e2, loc);
4026 else if (el->defstate == SS_DEFINED &&
4027 e2->defstate == SS_PDEFINED)
4029 DPRINTF (("set pdefined: %s", sRef_unparseFull (el)));
4030 el->defstate = SS_PDEFINED;
4032 else if (e2->defstate == SS_DEFINED &&
4033 el->defstate == SS_PDEFINED)
4035 DPRINTF (("set pdefined: %s", sRef_unparseFull (e2)));
4036 e2->defstate = SS_PDEFINED;
4043 if (ctype_isUnion (ctype_realType (sRef_getType (el))))
4045 el->deriv = sRef_mergeUnionDerivs (el->deriv, e2->deriv,
4050 el->deriv = sRef_mergeDerivs (el->deriv, e2->deriv, opt, cl, loc);
4053 if (sRef_equivalent (el, e2))
4055 ret = sRefSet_insert (ret, el);
4059 sRef sr = sRef_leastCommon (el, e2);
4061 if (sRef_isValid (sr))
4063 ret = sRefSet_insert (ret, sr);
4071 (void) sRefSet_delete (other, e2);
4073 else /* not defined */
4075 (void) checkDeadState (el, TRUE, loc);
4078 } end_sRefSet_allElements;
4080 sRefSet_allElements (other, el)
4082 if (sRef_isValid (el))
4084 (void) checkDeadState (el, FALSE, loc);
4086 } end_sRefSet_allElements;
4093 ** Returns TRUE is there is an error.
4096 static bool checkDeadState (/*@notnull@*/ sRef el, bool tbranch, fileloc loc)
4099 ** usymtab_isGuarded --- the utab should still be in the
4100 ** state of the alternate branch.
4102 ** tbranch TRUE means el is released in the last branch, e.g.
4103 ** if (x != NULL) { ; } else { sfree (x); }
4104 ** so, if x is null in the other branch no error is reported.
4106 ** tbranch FALSE means this is the other branch:
4107 ** if (x != NULL) { sfree (x); } else { ; }
4108 ** so, if x is null in this branch there is no error.
4112 if ((sRef_isDead (el) || sRef_isKept (el))
4113 && !sRef_isDeepUnionField (el) && !sRef_isThroughArrayFetch (el))
4118 if (usymtab_isDefinitelyNullDeep (el))
4125 if (usymtab_isAltDefinitelyNullDeep (el))
4133 message ("Storage %q is %q in one path, but live in another.",
4135 cstring_makeLiteral (sRef_isKept (el)
4136 ? "kept" : "released")),
4140 if (sRef_isKept (el))
4142 sRef_showAliasInfo (el);
4146 sRef_showStateInfo (el);
4149 /* prevent further errors */
4150 el->defstate = SS_UNKNOWN;
4151 sRef_setAliasKind (el, AK_ERROR, fileloc_undefined);
4161 checkDerivDeadState (/*@notnull@*/ sRef el, bool tbranch, fileloc loc)
4164 if (checkDeadState (el, tbranch, loc))
4166 sRefSet_allElements (el->deriv, t)
4168 if (sRef_isValid (t))
4170 checkDerivDeadState (t, tbranch, loc);
4172 } end_sRefSet_allElements;
4177 sRef_mergePdefinedDerivs (sRefSet res, sRefSet other, bool opt,
4178 clause cl, fileloc loc)
4180 sRefSet ret = sRefSet_new ();
4182 sRefSet_allElements (res, el)
4184 if (sRef_isValid (el))
4186 sRef e2 = sRefSet_lookupMember (other, el);
4188 if (sRef_isValid (e2))
4190 if (sRef_isAllocated (el) && !sRef_isAllocated (e2))
4194 else if (sRef_isAllocated (e2) && !sRef_isAllocated (el))
4196 el->deriv = sRefSet_copyInto (el->deriv, e2->deriv);
4200 el->deriv = sRef_mergePdefinedDerivs (el->deriv, e2->deriv,
4204 sRef_mergeStateAux (el, e2, cl, opt, loc, FALSE);
4206 ret = sRefSet_insert (ret, el);
4207 (void) sRefSet_delete (other, e2);
4213 checkDerivDeadState (el, (cl == FALSECLAUSE), loc);
4216 ret = sRefSet_insert (ret, el);
4219 } end_sRefSet_allElements;
4221 sRefSet_allElements (other, el)
4223 if (sRef_isValid (el))
4225 if (!sRefSet_member (ret, el))
4227 /* was cl == FALSECLAUSE */
4228 checkDerivDeadState (el, FALSE, loc);
4229 ret = sRefSet_insert (ret, el);
4234 ** it's okay --- member is a different equality test
4238 } end_sRefSet_allElements;
4244 sRef sRef_makeConj (/*@exposed@*/ /*@returned@*/ sRef a, /*@exposed@*/ sRef b)
4246 llassert (sRef_isValid (a));
4247 llassert (sRef_isValid (b));
4249 if (!sRef_equivalent (a, b))
4251 sRef s = sRef_newRef ();
4254 s->info = (sinfo) dmalloc (sizeof (*s->info));
4255 s->info->conj = (cjinfo) dmalloc (sizeof (*s->info->conj));
4256 s->info->conj->a = a; /* sRef_copy (a) */ /*@i32*/ ;
4257 s->info->conj->b = b; /* sRef_copy (b);*/ /*@i32@*/ ;
4259 if (ctype_equal (a->type, b->type)) s->type = a->type;
4260 else s->type = ctype_makeConj (a->type, b->type);
4262 if (a->defstate == b->defstate)
4264 s->defstate = a->defstate;
4268 s->defstate = SS_UNKNOWN;
4271 sRef_setNullStateN (s, NS_UNKNOWN);
4273 s->safe = a->safe && b->safe;
4274 s->aliaskind = alkind_resolve (a->aliaskind, b->aliaskind);
4276 llassert (valueTable_isUndefined (s->state));
4277 s->state = context_createValueTable (s);
4282 /*@-exposetrans@*/ return a; /*@=exposetrans@*/
4286 /*@dependent@*/ sRef
4289 sRef s = sRef_new ();
4291 s->kind = SK_UNKNOWN;
4295 static /*@owned@*/ sRef
4296 sRef_makeSpecial (speckind sk) /*@*/
4298 sRef s = sRef_new ();
4300 s->kind = SK_SPECIAL;
4301 s->info = (sinfo) dmalloc (sizeof (*s->info));
4303 /*@-dependenttrans@*/
4305 /*@=dependenttrans@*/
4308 static /*@owned@*/ sRef srnothing = sRef_undefined;
4309 static /*@owned@*/ sRef srinternal = sRef_undefined;
4310 static /*@owned@*/ sRef srsystem = sRef_undefined;
4311 static /*@owned@*/ sRef srspec = sRef_undefined;
4313 /*@dependent@*/ sRef
4314 sRef_makeNothing (void)
4316 if (sRef_isInvalid (srnothing))
4318 srnothing = sRef_makeSpecial (SR_NOTHING);
4325 sRef_makeInternalState (void)
4327 if (sRef_isInvalid (srinternal))
4329 srinternal = sRef_makeSpecial (SR_INTERNAL);
4336 sRef_makeSpecState (void)
4338 if (sRef_isInvalid (srspec))
4340 srspec = sRef_makeSpecial (SR_SPECSTATE);
4347 sRef_makeSystemState (void)
4349 if (sRef_isInvalid (srsystem))
4351 srsystem = sRef_makeSpecial (SR_SYSTEM);
4358 sRef_makeGlobalMarker (void)
4360 sRef s = sRef_makeSpecial (SR_GLOBALMARKER);
4361 llassert (valueTable_isUndefined (s->state));
4362 s->state = context_createGlobalMarkerValueTable ();
4367 sRef_makeResult (ctype c)
4369 sRef s = sRef_newRef ();
4371 s->kind = SK_RESULT;
4373 s->defstate = SS_UNKNOWN;
4374 s->aliaskind = AK_UNKNOWN;
4375 sRef_setNullStateN (s, NS_UNKNOWN);
4376 llassert (valueTable_isUndefined (s->state));
4377 s->state = context_createValueTable (s);
4379 DPRINTF (("Result: [%p] %s", s, sRef_unparseFull (s)));
4385 sRef_isNothing (sRef s)
4387 return (sRef_isKindSpecial (s) && s->info->spec == SR_NOTHING);
4391 sRef_isInternalState (sRef s)
4393 return (sRef_isKindSpecial (s) && s->info->spec == SR_INTERNAL);
4397 sRef_isSpecInternalState (sRef s)
4399 return (sRef_isKindSpecial (s)
4400 && (s->info->spec == SR_INTERNAL || s->info->spec == SR_SPECSTATE));
4404 sRef_isSpecState (sRef s)
4406 return (sRef_isKindSpecial (s) && s->info->spec == SR_SPECSTATE);
4410 sRef_isResult (sRef s)
4412 return (sRef_isValid (s) && s->kind == SK_RESULT);
4416 sRef_isSystemState (sRef s)
4418 return (sRef_isKindSpecial (s) && s->info->spec == SR_SYSTEM);
4422 sRef_isGlobalMarker (sRef s)
4424 return (sRef_isKindSpecial (s) && s->info->spec == SR_GLOBALMARKER);
4428 sRef_getScopeIndex (sRef s)
4430 llassert (sRef_isValid (s));
4431 llassert (sRef_isCvar (s));
4433 return (s->info->cvar->index);
4437 sRef_makeSafe (sRef s)
4439 if (sRef_isValid (s))
4446 sRef_makeUnsafe (sRef s)
4448 if (sRef_isValid (s))
4455 ** memory state operations
4458 /*@only@*/ cstring sRef_unparseFull (sRef s)
4460 if (sRef_isInvalid (s)) return (cstring_undefined);
4462 return (message ("[%d] %q - %q [%s] { %q } < %q >",
4464 sRef_unparseDebug (s),
4465 sRef_unparseState (s),
4466 exkind_unparse (s->oexpkind),
4467 sRefSet_unparseDebug (s->deriv),
4468 valueTable_unparse (s->state)));
4471 /*@unused@*/ cstring sRef_unparseDeep (sRef s)
4473 cstring st = cstring_undefined;
4475 st = message ("%q:", sRef_unparseFull (s));
4477 if (sRef_isValid (s))
4479 sRefSet_allElements (s->deriv, el)
4481 st = message("%q\n%q", st, sRef_unparseDeep (el));
4482 } end_sRefSet_allElements ;
4488 /*@only@*/ cstring sRef_unparseState (sRef s)
4490 if (sRef_isConj (s))
4492 return (message ("%q | %q",
4493 sRef_unparseState (s->info->conj->a),
4494 sRef_unparseState (s->info->conj->b)));
4497 if (sRef_isInvalid (s))
4499 return (cstring_makeLiteral ("<invalid>"));
4502 return (message ("%s.%s.%s.%s",
4503 alkind_unparse (s->aliaskind),
4504 nstate_unparse (sRef_getNullState (s)),
4505 exkind_unparse (s->expkind),
4506 sstate_unparse (s->defstate)));
4509 bool sRef_isNotUndefined (sRef s)
4511 return (sRef_isInvalid (s)
4512 || (s->defstate != SS_UNDEFINED
4513 && s->defstate != SS_UNUSEABLE
4514 && s->defstate != SS_DEAD));
4517 ynm sRef_isWriteable (sRef s)
4519 if (sRef_isInvalid (s)) return MAYBE;
4521 if (sRef_isConj (s) && s->defstate == SS_UNKNOWN)
4523 if (ynm_toBoolStrict (sRef_isWriteable (sRef_getConjA (s))))
4525 if (ynm_toBoolStrict (sRef_isWriteable (sRef_getConjB (s))))
4533 if (ynm_toBoolStrict (sRef_isWriteable (sRef_getConjB (s))))
4541 return (ynm_fromBool (s->defstate != SS_UNUSEABLE));
4544 bool sRef_hasNoStorage (sRef s)
4546 return (!sRef_isAllocatedStorage (s) || sRef_isDefinitelyNull (s));
4549 bool sRef_isStrictReadable (sRef s)
4551 return (ynm_toBoolStrict (sRef_isReadable (s)));
4554 ynm sRef_isReadable (sRef s)
4558 if (sRef_isInvalid (s)) return YES;
4562 if (sRef_isConj (s) && s->defstate == SS_UNKNOWN)
4564 if (ynm_toBoolStrict (sRef_isReadable (sRef_getConjA (s))))
4566 if (ynm_toBoolStrict (sRef_isReadable (sRef_getConjB (s))))
4574 if (ynm_toBoolStrict (sRef_isReadable (sRef_getConjB (s))))
4581 else if (ss == SS_HOFFA)
4583 if (context_getFlag (FLG_STRICTUSERELEASED))
4594 return (ynm_fromBool (ss == SS_DEFINED
4597 || ss == SS_PDEFINED
4600 || ss == SS_ALLOCATED
4601 || ss == SS_KILLED /* evans 2001-05-26: added this for killed globals */
4602 || ss == SS_UNKNOWN));
4606 static /*@exposed@*/ sRef whatUndefined (/*@exposed@*/ sRef fref, int depth)
4611 if (depth > MAXDEPTH)
4614 ("Warning: check definition limit exceeded, checking %q. "
4615 "This either means there is a variable with at least "
4616 "%d indirections apparent in the program text, or "
4617 "there is a bug in LCLint.",
4618 sRef_unparse (fref),
4622 return sRef_undefined;
4625 if (!sRef_isKnown (fref) || sRef_isAnyDefined (fref))
4627 return sRef_undefined;
4630 if (sRef_isUnuseable (fref) || sRef_isStateUndefined (fref))
4635 ct = ctype_realType (sRef_getType (fref));
4637 if (ctype_isUnknown (ct))
4639 return sRef_undefined;
4641 else if (ctype_isPointer (ct) || ctype_isArray (ct))
4643 if (sRef_isStateUnknown (fref))
4645 return sRef_undefined;
4649 sRef fptr = sRef_constructDeref (fref);
4651 return (whatUndefined (fptr, depth + 1));
4654 else if (ctype_isStruct (ct))
4656 bool hasOneDefined = FALSE;
4658 if (sRef_isStateUnknown (fref))
4663 if (sRef_isPdefined (fref) || sRef_isAnyDefined (fref))
4665 sRefSet_realElements (sRef_derivedFields (fref), sr)
4667 hasOneDefined = TRUE;
4669 if (sRef_isField (sr))
4671 cstring fieldname = sRef_getField (sr);
4672 sRef fldref = sRef_makeField (fref, fieldname);
4673 bool shouldCheck = !sRef_isRecursiveField (fldref);
4677 sRef wdef = whatUndefined (fldref, depth + 1);
4679 if (sRef_isValid (wdef))
4685 } end_sRefSet_realElements;
4687 else if (sRef_isAllocated (fref))
4690 ** for structures, each field must be completely defined
4693 uentryList fields = ctype_getFields (ct);
4695 uentryList_elements (fields, ue)
4697 cstring name = uentry_getRealName (ue);
4698 sRef ffield = sRef_makeField (fref, name);
4699 bool shouldCheck = !sRef_isRecursiveField (ffield);
4701 if (sRef_isRelDef (uentry_getSref (ue)))
4709 sRef wdef = whatUndefined (ffield, depth + 1);
4711 if (sRef_isInvalid (wdef))
4717 } end_uentryList_elements;
4724 else if (ctype_isUnion (ct))
4733 return sRef_undefined;
4736 static bool checkDefined (/*@temp@*/ sRef sr)
4738 /*@-temptrans@*/ /* the result from whatUndefined is lost */
4739 return (sRef_isInvalid (whatUndefined (sr, 0)));
4743 bool sRef_isReallyDefined (sRef s)
4745 if (sRef_isValid (s))
4747 if (sRef_isAnyDefined (s))
4753 if (sRef_isAllocated (s) || sRef_isPdefined (s))
4755 return checkDefined (s);
4769 void sRef_showNotReallyDefined (sRef s)
4771 if (sRef_isValid (s))
4773 if (sRef_isAnyDefined (s))
4779 if (sRef_isAllocated (s) || sRef_isPdefined (s))
4781 /*@-temptrans@*/ /* the result of whatUndefined is lost */
4782 sRef ref = whatUndefined (s, 0);
4784 llassert (sRef_isValid (ref));
4789 (message ("This sub-reference is %s: %q",
4790 sstate_unparse (sRef_getDefState (ref)),
4791 sRef_unparse (ref)));
4806 sstate sRef_getDefState (sRef s)
4808 if (sRef_isInvalid (s)) return (SS_UNKNOWN);
4809 return (s->defstate);
4812 void sRef_setDefState (sRef s, sstate defstate, fileloc loc)
4814 sRef_checkMutable (s);
4815 sRef_setStateAux (s, defstate, loc);
4818 static void sRef_clearAliasStateAux (sRef s, fileloc loc)
4820 sRef_checkMutable (s);
4821 sRef_setAliasKind (s, AK_ERROR, loc);
4824 void sRef_clearAliasState (sRef s, fileloc loc)
4826 sRef_checkMutable (s);
4827 sRef_aliasSetComplete (sRef_clearAliasStateAux, s, loc);
4830 void sRef_setAliasKindComplete (sRef s, alkind kind, fileloc loc)
4832 sRef_checkMutable (s);
4833 sRef_aliasSetCompleteParam (sRef_setAliasKind, s, kind, loc);
4836 void sRef_setAliasKind (sRef s, alkind kind, fileloc loc)
4838 sRef_checkMutable (s);
4840 if (sRef_isValid (s))
4842 sRef_clearDerived (s);
4844 if ((kind != s->aliaskind && kind != s->oaliaskind)
4845 && fileloc_isDefined (loc))
4847 s->aliasinfo = stateInfo_updateLoc (s->aliasinfo, loc);
4850 s->aliaskind = kind;
4854 void sRef_setOrigAliasKind (sRef s, alkind kind)
4856 sRef_checkMutable (s);
4858 if (sRef_isValid (s))
4860 s->oaliaskind = kind;
4864 exkind sRef_getExKind (sRef s)
4866 if (sRef_isValid (s))
4868 return (s->expkind);
4876 exkind sRef_getOrigExKind (sRef s)
4878 if (sRef_isValid (s))
4880 return (s->oexpkind);
4888 static void sRef_clearExKindAux (sRef s, fileloc loc)
4890 sRef_checkMutable (s);
4891 sRef_setExKind (s, XO_UNKNOWN, loc);
4894 void sRef_setObserver (sRef s, fileloc loc)
4896 sRef_checkMutable (s);
4897 sRef_setExKind (s, XO_OBSERVER, loc);
4900 void sRef_setExposed (sRef s, fileloc loc)
4902 sRef_checkMutable (s);
4903 sRef_setExKind (s, XO_EXPOSED, loc);
4906 void sRef_clearExKindComplete (sRef s, fileloc loc)
4908 (void) sRef_aliasSetComplete (sRef_clearExKindAux, s, loc);
4911 void sRef_setExKind (sRef s, exkind exp, fileloc loc)
4913 sRef_checkMutable (s);
4915 if (sRef_isValid (s))
4917 if (s->expkind != exp)
4919 s->expinfo = stateInfo_updateLoc (s->expinfo, loc);
4927 ** s1->derived = s2->derived
4930 static void sRef_copyRealDerived (sRef s1, sRef s2)
4932 DPRINTF (("Copy real: %s / %s", sRef_unparse (s1), sRef_unparse (s2)));
4933 sRef_checkMutable (s1);
4935 if (sRef_isValid (s1) && sRef_isValid (s2))
4937 sRef sb = sRef_getRootBase (s1);
4939 sRefSet_clear (s1->deriv);
4941 sRefSet_allElements (s2->deriv, el)
4943 if (sRef_isValid (el))
4945 sRef rb = sRef_getRootBase (el);
4947 if (!sRef_same (rb, sb))
4949 sRef fb = sRef_fixDirectBase (el, s1);
4951 if (sRef_isValid (fb))
4953 sRef_copyRealDerived (fb, el);
4954 sRef_addDeriv (s1, fb);
4959 sRef_addDeriv (s1, el);
4962 } end_sRefSet_allElements ;
4967 void sRef_copyRealDerivedComplete (sRef s1, sRef s2)
4969 sRef_innerAliasSetCompleteParam (sRef_copyRealDerived, s1, s2);
4972 void sRef_setUndefined (sRef s, fileloc loc)
4974 sRef_checkMutable (s);
4976 if (sRef_isValid (s))
4978 s->defstate = SS_UNDEFINED;
4980 if (fileloc_isDefined (loc))
4982 s->definfo = stateInfo_updateLoc (s->definfo, loc);
4985 sRef_clearDerived (s);
4989 static void sRef_setDefinedAux (sRef s, fileloc loc, bool clear)
4991 sRef_checkMutable (s);
4992 if (sRef_isInvalid (s)) return;
4994 DPRINTF (("Set defined: %s", sRef_unparseFull (s)));
4996 if (s->defstate != SS_DEFINED && fileloc_isDefined (loc))
4998 s->definfo = stateInfo_updateLoc (s->definfo, loc);
5001 s->defstate = SS_DEFINED;
5003 DPRINTF (("Set defined: %s", sRef_unparseFull (s)));
5005 /* e.g., if x is allocated, *x = 3 defines x */
5007 if (s->kind == SK_PTR)
5009 sRef p = s->info->ref;
5012 if (p->defstate == SS_ALLOCATED
5013 || p->defstate == SS_SPECIAL) /* evans 2001-07-12: shouldn't need this */
5015 sRef_setDefinedAux (p, loc, clear);
5019 ** Defines a[0] also:
5022 arr = sRef_findDerivedArrayFetch (p, FALSE, 0, FALSE);
5024 if (sRef_isValid (arr))
5026 sRef_setDefinedAux (arr, loc, clear);
5029 else if (s->kind == SK_ARRAYFETCH)
5031 if (!s->info->arrayfetch->indknown
5032 || (s->info->arrayfetch->ind == 0))
5034 sRef p = s->info->arrayfetch->arr;
5035 sRef ptr = sRef_constructPointer (p);
5037 if (sRef_isValid (ptr))
5039 if (ptr->defstate == SS_ALLOCATED
5040 || ptr->defstate == SS_UNDEFINED
5041 || ptr->defstate == SS_SPECIAL) /* evans 2001-07-12: shouldn't need this */
5043 sRef_setDefinedAux (ptr, loc, clear);
5047 if (p->defstate == SS_RELDEF)
5051 else if (p->defstate == SS_ALLOCATED || p->defstate == SS_PDEFINED
5052 || p->defstate == SS_SPECIAL) /* evans 2001-07-12: shouldn't need this */
5054 p->defstate = SS_DEFINED;
5061 else if (s->kind == SK_FIELD)
5063 sRef parent = s->info->field->rec;
5065 if (sRef_isValid (parent))
5067 if (ctype_isUnion (ctype_realType (parent->type)))
5070 ** Should not clear derived from here.
5073 sRef_setDefinedNoClear (parent, loc);
5077 ; /* Nothing to do for structures. */
5089 sRef_clearDerived (s);
5093 /* evans 2001-07-12: need to define the derived references */
5094 sRefSet_elements (s->deriv, el)
5096 el->defstate = SS_DEFINED;
5097 } end_sRefSet_elements ;
5100 DPRINTF (("Set defined: %s", sRef_unparseFull (s)));
5103 static void sRef_setPartialDefined (sRef s, fileloc loc)
5105 sRef_checkMutable (s);
5107 if (!sRef_isPartial (s))
5109 sRef_setDefined (s, loc);
5113 void sRef_setPartialDefinedComplete (sRef s, fileloc loc)
5115 sRef_innerAliasSetComplete (sRef_setPartialDefined, s, loc);
5118 void sRef_setDefinedComplete (sRef s, fileloc loc)
5120 DPRINTF (("Set defined complete: %s", sRef_unparseFull (s)));
5121 sRef_innerAliasSetComplete (sRef_setDefined, s, loc);
5124 void sRef_setDefined (sRef s, fileloc loc)
5126 sRef_checkMutable (s);
5127 sRef_setDefinedAux (s, loc, TRUE);
5130 static void sRef_setDefinedNoClear (sRef s, fileloc loc)
5132 sRef_checkMutable (s);
5133 DPRINTF (("Defining: %s", sRef_unparseFull (s)));
5134 sRef_setDefinedAux (s, loc, FALSE);
5135 DPRINTF (("==> %s", sRef_unparseFull (s)));
5138 void sRef_setDefinedNCComplete (sRef s, fileloc loc)
5140 sRef_checkMutable (s);
5141 DPRINTF (("Set Defined Complete: %s", sRef_unparseFull (s)));
5142 sRef_innerAliasSetComplete (sRef_setDefinedNoClear, s, loc);
5143 DPRINTF (("==> %s", sRef_unparseFull (s)));
5146 static bool sRef_isDeepUnionField (sRef s)
5148 return (sRef_deepPred (sRef_isUnionField, s));
5151 bool sRef_isUnionField (sRef s)
5153 if (sRef_isValid (s) && s->kind == SK_FIELD)
5156 ** defining one field of a union defines the union
5159 sRef base = s->info->field->rec;
5161 if (sRef_isValid (base))
5163 return (ctype_isUnion (ctype_realType (base->type)));
5170 void sRef_setPdefined (sRef s, fileloc loc)
5172 sRef_checkMutable (s);
5173 if (sRef_isValid (s) && !sRef_isPartial (s))
5175 sRef base = sRef_getBaseSafe (s);
5177 if (s->defstate == SS_ALLOCATED)
5182 if (s->defstate != SS_PDEFINED && fileloc_isDefined (loc))
5184 s->definfo = stateInfo_updateLoc (s->definfo, loc);
5187 DPRINTF (("set pdefined: %s", sRef_unparseFull (s)));
5188 s->defstate = SS_PDEFINED;
5190 /* e.g., if x is allocated, *x = 3 defines x */
5192 while (sRef_isValid (base) && sRef_isKnown (base))
5194 if (base->defstate == SS_DEFINED)
5198 base->defstate = SS_PDEFINED;
5199 nb = sRef_getBaseSafe (base);
5210 static void sRef_setStateAux (sRef s, sstate ss, fileloc loc)
5212 sRef_checkMutable (s);
5214 if (sRef_isValid (s))
5216 /* if (s->defstate == SS_RELDEF) return; */
5218 if (s->defstate != ss && fileloc_isDefined (loc))
5220 s->definfo = stateInfo_updateLoc (s->definfo, loc);
5224 sRef_clearDerived (s);
5226 if (ss == SS_ALLOCATED)
5228 sRef base = sRef_getBaseSafe (s);
5230 while (sRef_isValid (base) && sRef_isKnown (base))
5232 if (base->defstate == SS_DEFINED)
5236 base->defstate = SS_PDEFINED;
5238 nb = sRef_getBaseSafe (base);
5251 void sRef_setAllocatedComplete (sRef s, fileloc loc)
5253 sRef_innerAliasSetComplete (sRef_setAllocated, s, loc);
5256 static void sRef_setAllocatedShallow (sRef s, fileloc loc)
5258 sRef_checkMutable (s);
5260 if (sRef_isValid (s))
5262 if (s->defstate == SS_DEAD || s->defstate == SS_UNDEFINED)
5264 s->defstate = SS_ALLOCATED;
5266 if (fileloc_isDefined (loc))
5268 s->definfo = stateInfo_updateLoc (s->definfo, loc);
5274 void sRef_setAllocatedShallowComplete (sRef s, fileloc loc)
5276 sRef_innerAliasSetComplete (sRef_setAllocatedShallow, s, loc);
5279 void sRef_setAllocated (sRef s, fileloc loc)
5281 sRef_checkMutable (s);
5282 sRef_setStateAux (s, SS_ALLOCATED, loc);
5285 void sRef_setPartial (sRef s, fileloc loc)
5287 sRef_checkMutable (s);
5288 sRef_setStateAux (s, SS_PARTIAL, loc);
5291 void sRef_setShared (sRef s, fileloc loc)
5293 sRef_checkMutable (s);
5295 if (sRef_isValid (s))
5297 if (s->aliaskind != AK_SHARED && fileloc_isDefined (loc))
5299 s->aliasinfo = stateInfo_updateLoc (s->aliasinfo, loc);
5302 s->aliaskind = AK_SHARED;
5303 /* don't! sRef_clearDerived (s); */
5307 void sRef_setLastReference (sRef s, /*@exposed@*/ sRef ref, fileloc loc)
5309 sRef_checkMutable (s);
5311 if (sRef_isValid (s))
5313 s->aliaskind = sRef_getAliasKind (ref);
5314 s->aliasinfo = stateInfo_updateRefLoc (s->aliasinfo, ref, loc);
5319 void sRef_setNullStateAux (/*@notnull@*/ sRef s, nstate ns, fileloc loc)
5321 DPRINTF (("Set null state: %s / %s", sRef_unparse (s), nstate_unparse (ns)));
5322 sRef_checkMutable (s);
5325 if (fileloc_isDefined (loc))
5327 s->nullinfo = stateInfo_updateLoc (s->nullinfo, loc);
5331 void sRef_setNotNull (sRef s, fileloc loc)
5333 if (sRef_isValid (s))
5335 sRef_setNullStateAux (s, NS_NOTNULL, loc);
5339 void sRef_setNullStateN (sRef s, nstate n)
5341 sRef_checkMutable (s);
5345 void sRef_setNullState (sRef s, nstate n, fileloc loc)
5347 if (sRef_isValid (s))
5349 sRef_setNullStateAux (s, n, loc);
5353 void sRef_setNullTerminatedStateInnerComplete (sRef s, struct s_bbufinfo b, /*@unused@*/ fileloc loc) {
5355 switch (b.bufstate) {
5356 case BB_NULLTERMINATED:
5357 sRef_setNullTerminatedState (s);
5358 sRef_setLen (s, b.len);
5360 case BB_POSSIBLYNULLTERMINATED:
5361 sRef_setPossiblyNullTerminatedState(s);
5363 case BB_NOTNULLTERMINATED:
5364 sRef_setNotNullTerminatedState (s);
5367 sRef_setSize (s, b.size);
5369 /* PL: TO BE DONE : Aliases are not modified right now, have to be similar to
5370 * setNullStateInnerComplete.
5374 void sRef_setNullStateInnerComplete (sRef s, nstate n, fileloc loc)
5376 DPRINTF (("Set null state: %s", nstate_unparse (n)));
5378 sRef_setNullState (s, n, loc);
5383 sRef_innerAliasSetComplete (sRef_setPosNull, s, loc);
5386 sRef_innerAliasSetComplete (sRef_setDefNull, s, loc);
5389 sRef_innerAliasSetComplete (sRef_setNullUnknown, s, loc);
5392 sRef_innerAliasSetComplete (sRef_setNotNull, s, loc);
5395 sRef_innerAliasSetComplete (sRef_setNotNull, s, loc);
5398 sRef_innerAliasSetComplete (sRef_setNullUnknown, s, loc);
5401 sRef_innerAliasSetComplete (sRef_setDefNull, s, loc);
5404 sRef_innerAliasSetComplete (sRef_setNullUnknown, s, loc);
5407 sRef_innerAliasSetComplete (sRef_setNullErrorLoc, s, loc);
5412 void sRef_setPosNull (sRef s, fileloc loc)
5414 if (sRef_isValid (s))
5416 sRef_setNullStateAux (s, NS_POSNULL, loc);
5420 void sRef_setDefNull (sRef s, fileloc loc)
5422 if (sRef_isValid (s))
5424 sRef_setNullStateAux (s, NS_DEFNULL, loc);
5428 void sRef_setNullUnknown (sRef s, fileloc loc)
5430 if (sRef_isValid (s))
5432 sRef_setNullStateAux (s, NS_UNKNOWN, loc);
5436 void sRef_setNullError (sRef s)
5438 if (sRef_isValid (s))
5440 sRef_setNullStateAux (s, NS_UNKNOWN, fileloc_undefined);
5444 void sRef_setNullErrorLoc (sRef s, /*@unused@*/ fileloc loc)
5446 sRef_setNullError (s);
5449 void sRef_setOnly (sRef s, fileloc loc)
5451 sRef_checkMutable (s);
5453 if (sRef_isValid (s) && s->aliaskind != AK_ONLY)
5455 s->aliaskind = AK_ONLY;
5456 s->aliasinfo = stateInfo_updateLoc (s->aliasinfo, loc);
5460 void sRef_setDependent (sRef s, fileloc loc)
5462 sRef_checkMutable (s);
5464 if (sRef_isValid (s) && !sRef_isConst (s) && (s->aliaskind != AK_DEPENDENT))
5466 DPRINTF (("Setting dependent: %s", sRef_unparseFull (s)));
5467 s->aliaskind = AK_DEPENDENT;
5468 s->aliasinfo = stateInfo_updateLoc (s->aliasinfo, loc);
5472 void sRef_setOwned (sRef s, fileloc loc)
5474 sRef_checkMutable (s);
5476 if (sRef_isValid (s) && !sRef_isConst (s) && (s->aliaskind != AK_OWNED))
5478 s->aliaskind = AK_OWNED;
5479 s->aliasinfo = stateInfo_updateLoc (s->aliasinfo, loc);
5483 void sRef_setKept (sRef s, fileloc loc)
5485 sRef_checkMutable (s);
5487 if (sRef_isValid (s) && !sRef_isConst (s) && (s->aliaskind != AK_KEPT))
5489 sRef base = sRef_getBaseSafe (s);
5491 while (sRef_isValid (base) && sRef_isKnown (base))
5493 if (base->defstate == SS_DEFINED)
5495 base->defstate = SS_PDEFINED;
5496 base = sRef_getBaseSafe (base);
5505 s->aliaskind = AK_KEPT;
5506 s->aliasinfo = stateInfo_updateLoc (s->aliasinfo, loc);
5510 static void sRef_setKeptAux (sRef s, fileloc loc)
5512 if (!sRef_isShared (s))
5514 sRef_setKept (s, loc);
5518 static void sRef_setDependentAux (sRef s, fileloc loc)
5520 if (!sRef_isShared (s))
5522 sRef_setDependent (s, loc);
5526 void sRef_setKeptComplete (sRef s, fileloc loc)
5528 sRef_aliasSetComplete (sRef_setKeptAux, s, loc);
5531 void sRef_setDependentComplete (sRef s, fileloc loc)
5533 sRef_aliasSetComplete (sRef_setDependentAux, s, loc);
5536 void sRef_setFresh (sRef s, fileloc loc)
5538 sRef_checkMutable (s);
5540 if (sRef_isValid (s))
5542 s->aliaskind = AK_FRESH;
5543 s->aliasinfo = stateInfo_updateLoc (s->aliasinfo, loc);
5547 void sRef_kill (sRef s, fileloc loc)
5549 DPRINTF (("Kill: %s", sRef_unparseFull (s)));
5550 sRef_checkMutable (s);
5552 if (sRef_isValid (s) && !sRef_isShared (s) && !sRef_isConst (s))
5554 sRef base = sRef_getBaseSafe (s);
5556 while (sRef_isValid (base) && sRef_isKnown (base))
5558 if (base->defstate == SS_DEFINED)
5560 base->defstate = SS_PDEFINED;
5561 base = sRef_getBaseSafe (base);
5569 s->aliaskind = s->oaliaskind;
5570 s->defstate = SS_DEAD;
5571 s->definfo = stateInfo_updateLoc (s->definfo, loc);
5573 sRef_clearDerived (s);
5577 void sRef_maybeKill (sRef s, fileloc loc)
5579 sRef_checkMutable (s);
5581 if (sRef_isValid (s))
5583 sRef base = sRef_getBaseSafe (s);
5586 while (sRef_isValid (base) && sRef_isKnown (base))
5588 if (base->defstate == SS_DEFINED || base->defstate == SS_RELDEF)
5590 base->defstate = SS_PDEFINED;
5591 base = sRef_getBaseSafe (base);
5600 s->aliaskind = s->oaliaskind;
5601 s->defstate = SS_HOFFA;
5602 s->definfo = stateInfo_updateLoc (s->definfo, loc);
5603 sRef_clearDerived (s);
5609 ** just for type checking...
5612 static void sRef_killAux (sRef s, fileloc loc)
5614 if (sRef_isValid (s) && !sRef_isShared (s))
5616 if (sRef_isUnknownArrayFetch (s))
5618 sRef_maybeKill (s, loc);
5628 ** kills s and all aliases to s
5631 void sRef_killComplete (sRef s, fileloc loc)
5633 DPRINTF (("Kill complete: %s", sRef_unparseFull (s)));
5634 sRef_aliasSetComplete (sRef_killAux, s, loc);
5637 static bool sRef_equivalent (sRef s1, sRef s2)
5639 return (sRef_compare (s1, s2) == 0);
5643 ** returns an sRef that will not be free'd on function exit.
5646 /*@only@*/ sRef sRef_saveCopy (sRef s)
5650 if (sRef_isValid (s))
5652 bool old = inFunction;
5655 ** Exit the function scope, so this sRef is not
5656 ** stored in the deallocation table.
5660 DPRINTF (("Copying sref: %s", sRef_unparseFull(s)));
5661 ret = sRef_copy (s);
5662 DPRINTF (("Copying ===>: %s", sRef_unparseFull(ret)));
5667 ret = sRef_undefined;
5670 /*@-dependenttrans@*/
5672 /*@=dependenttrans@*/
5675 sRef sRef_copy (sRef s)
5677 if (sRef_isKindSpecial (s) && !sRef_isGlobalMarker (s))
5680 return s; /* don't copy specials (except for global markers) */
5684 if (sRef_isValid (s))
5686 sRef t = sRef_alloc ();
5688 DPRINTF (("Copying: [%p] %s", s, sRef_unparse (s)));
5689 DPRINTF (("Full: %s", sRef_unparseFull (s)));
5693 t->modified = s->modified;
5694 t->immut = FALSE; /* Note mutability is not copied. */
5697 t->info = sinfo_copy (s);
5698 t->defstate = s->defstate;
5699 t->nullstate = s->nullstate;
5701 /* start modifications */
5702 t->bufinfo.bufstate = s->bufinfo.bufstate;
5703 t->bufinfo.len = s->bufinfo.len;
5704 t->bufinfo.size = s->bufinfo.size;
5705 /* end modifications */
5707 t->aliaskind = s->aliaskind;
5708 t->oaliaskind = s->oaliaskind;
5710 t->expkind = s->expkind;
5711 t->oexpkind = s->oexpkind;
5713 t->nullinfo = stateInfo_copy (s->nullinfo);
5714 t->aliasinfo = stateInfo_copy (s->aliasinfo);
5715 t->definfo = stateInfo_copy (s->definfo);
5716 t->expinfo = stateInfo_copy (s->expinfo);
5718 t->deriv = sRefSet_newDeepCopy (s->deriv);
5719 t->state = valueTable_copy (s->state);
5721 DPRINTF (("Made copy: [%p] %s", t, sRef_unparse (t)));
5726 return sRef_undefined;
5731 # define PREDTEST(func,s) \
5732 do { if (sRef_isInvalid (s)) { return FALSE; } \
5733 else { if (sRef_isConj (s)) \
5734 { return (func (sRef_getConjA (s)) \
5735 || func (sRef_getConjB (s))); }}} while (FALSE);
5737 bool sRef_isAddress (sRef s)
5739 PREDTEST (sRef_isAddress, s);
5740 return (s->kind == SK_ADR);
5744 ** pretty weak... maybe a flag should control this.
5747 bool sRef_isThroughArrayFetch (sRef s)
5749 if (sRef_isValid (s))
5757 if (sRef_isArrayFetch (tref))
5762 lt = sRef_getBase (tref);
5764 } while (sRef_isValid (tref));
5770 bool sRef_isArrayFetch (sRef s)
5772 PREDTEST (sRef_isArrayFetch, s);
5773 return (s->kind == SK_ARRAYFETCH);
5776 bool sRef_isMacroParamRef (sRef s)
5778 if (context_inMacro () && sRef_isCvar (s))
5780 uentry ue = sRef_getUentry (s);
5781 cstring pname = makeParam (uentry_rawName (ue));
5782 uentry mac = usymtab_lookupSafe (pname);
5784 cstring_free (pname);
5785 return (uentry_isValid (mac));
5791 bool sRef_isCvar (sRef s)
5793 PREDTEST (sRef_isCvar, s);
5794 return (s->kind == SK_CVAR);
5797 bool sRef_isConst (sRef s)
5799 PREDTEST (sRef_isConst, s);
5800 return (s->kind == SK_CONST);
5803 bool sRef_isObject (sRef s)
5805 PREDTEST (sRef_isObject, s);
5806 return (s->kind == SK_OBJECT);
5809 bool sRef_isExternal (sRef s)
5811 PREDTEST (sRef_isExternal, s);
5812 return (s->kind == SK_EXTERNAL);
5815 static bool sRef_isDerived (sRef s)
5817 PREDTEST (sRef_isDerived, s);
5818 return (s->kind == SK_DERIVED);
5821 bool sRef_isField (sRef s)
5823 PREDTEST (sRef_isField, s);
5824 return (s->kind == SK_FIELD);
5827 static bool sRef_isIndex (sRef s)
5829 PREDTEST (sRef_isIndex, s);
5830 return (s->kind == SK_ARRAYFETCH);
5833 bool sRef_isAnyParam (sRef s)
5835 PREDTEST (sRef_isAnyParam, s);
5836 return (s->kind == SK_PARAM);
5839 bool sRef_isParam (sRef s)
5841 PREDTEST (sRef_isParam, s);
5842 return (s->kind == SK_PARAM);
5845 bool sRef_isDirectParam (sRef s)
5847 PREDTEST (sRef_isDirectParam, s);
5849 return ((s->kind == SK_CVAR) &&
5850 (s->info->cvar->lexlevel == functionScope) &&
5851 (context_inFunction () &&
5852 (s->info->cvar->index <= uentryList_size (context_getParams ()))));
5855 bool sRef_isPointer (sRef s)
5857 PREDTEST (sRef_isPointer, s);
5858 return (s->kind == SK_PTR);
5862 ** returns true if storage referenced by s is visible
5865 bool sRef_isReference (sRef s)
5867 PREDTEST (sRef_isReference, s);
5869 return (sRef_isPointer (s) || sRef_isIndex (s) || sRef_isFileOrGlobalScope (s)
5870 || (sRef_isField (s) && (sRef_isReference (s->info->field->rec))));
5873 bool sRef_isIReference (sRef s)
5875 return (sRef_isPointer (s) || sRef_isAddress (s) || sRef_isIndex (s)
5876 || sRef_isField (s) || sRef_isArrayFetch (s));
5879 bool sRef_isFileOrGlobalScope (sRef s)
5881 return (sRef_isCvar (s) && (s->info->cvar->lexlevel <= fileScope));
5884 bool sRef_isRealGlobal (sRef s)
5886 return (sRef_isCvar (s) && (s->info->cvar->lexlevel == globScope));
5889 bool sRef_isFileStatic (sRef s)
5891 return (sRef_isCvar (s) && (s->info->cvar->lexlevel == fileScope));
5894 bool sRef_isAliasCheckedGlobal (sRef s)
5896 if (sRef_isFileOrGlobalScope (s))
5898 uentry ue = sRef_getUentry (s);
5900 return context_checkAliasGlob (ue);
5908 void sRef_free (/*@only@*/ sRef s)
5910 if (s != sRef_undefined && s->kind != SK_SPECIAL)
5912 DPRINTF (("Free sref: [%p]", s));
5914 sRef_checkValid (s);
5916 stateInfo_free (s->expinfo);
5917 stateInfo_free (s->aliasinfo);
5918 stateInfo_free (s->definfo);
5919 stateInfo_free (s->nullinfo);
5921 sRefSet_free (s->deriv);
5922 s->deriv = sRefSet_undefined;
5924 /*@i43@*/ /* valueTable_free (s->state); */
5928 /* drl added to help locate use after release*/
5929 s->expinfo = stateInfo_undefined;
5930 s->aliasinfo = stateInfo_undefined;
5931 s->definfo = stateInfo_undefined;
5932 s->nullinfo = stateInfo_undefined;
5934 /*@i32@*/ sfree (s);
5938 void sRef_setType (sRef s, ctype t)
5940 sRef_checkMutable (s);
5942 if (sRef_isValid (s))
5948 void sRef_setTypeFull (sRef s, ctype t)
5950 sRef_checkMutable (s);
5952 if (sRef_isValid (s))
5956 sRefSet_allElements (s->deriv, current)
5958 sRef_setTypeFull (current, ctype_unknown);
5959 } end_sRefSet_allElements ;
5964 sRef_buildField (/*@exposed@*/ sRef rec, /*@dependent@*/ cstring f)
5966 return (sRef_buildNCField (rec, f));
5969 static /*@exposed@*/ sRef
5970 sRef_findDerivedField (/*@notnull@*/ sRef rec, cstring f)
5972 sRefSet_allElements (rec->deriv, sr)
5974 if (sRef_isValid (sr))
5976 if (sr->info != NULL)
5978 if (sr->kind == SK_FIELD && cstring_equal (sr->info->field->field, f))
5984 } end_sRefSet_allElements;
5986 return sRef_undefined;
5989 /*@dependent@*/ /*@observer@*/ sRefSet sRef_derivedFields (/*@temp@*/ sRef rec)
5991 if (sRef_isValid (rec))
5999 return (sRefSet_undefined);
6003 static /*@exposed@*/ sRef
6004 sRef_findDerivedPointer (sRef s)
6006 if (sRef_isValid (s))
6008 sRefSet_realElements (s->deriv, sr)
6010 if (sRef_isValid (sr) && sr->kind == SK_PTR)
6014 } end_sRefSet_realElements;
6017 return sRef_undefined;
6021 sRef_isUnknownArrayFetch (sRef s)
6023 return (sRef_isValid (s)
6024 && s->kind == SK_ARRAYFETCH
6025 && !s->info->arrayfetch->indknown);
6028 static /*@exposed@*/ sRef
6029 sRef_findDerivedArrayFetch (/*@notnull@*/ sRef s, bool isknown, int idx, bool dead)
6034 sRefSet_realElements (s->deriv, sr)
6036 if (sRef_isValid (sr)
6037 && sr->kind == SK_ARRAYFETCH
6038 && sr->info->arrayfetch->indknown
6039 && (sr->info->arrayfetch->ind == idx))
6043 } end_sRefSet_realElements;
6047 sRefSet_realElements (s->deriv, sr)
6049 if (sRef_isValid (sr)
6050 && sr->kind == SK_ARRAYFETCH
6051 && (!sr->info->arrayfetch->indknown
6052 || (sr->info->arrayfetch->indknown &&
6053 sr->info->arrayfetch->ind == 0)))
6055 if (sRef_isDead (sr) || sRef_isKept (sr))
6057 if (dead || context_getFlag (FLG_STRICTUSERELEASED))
6067 } end_sRefSet_realElements;
6070 return sRef_undefined;
6073 static /*@exposed@*/ sRef
6074 sRef_buildNCField (/*@exposed@*/ sRef rec, /*@exposed@*/ cstring f)
6078 DPRINTF (("Build nc field: %s / %s",
6079 sRef_unparseFull (rec), f));
6081 if (sRef_isInvalid (rec))
6083 return sRef_undefined;
6087 ** check if the field already has been referenced
6090 s = sRef_findDerivedField (rec, f);
6092 if (sRef_isValid (s))
6098 ctype ct = ctype_realType (rec->type);
6100 DPRINTF (("Field of: %s", sRef_unparse (rec)));
6104 s->info = (sinfo) dmalloc (sizeof (*s->info));
6105 s->info->field = (fldinfo) dmalloc (sizeof (*s->info->field));
6106 s->info->field->rec = rec; /* sRef_copy (rec); */ /*@i32@*/
6107 s->info->field->field = f; /* doesn't copy f */
6109 if (ctype_isKnown (ct) && ctype_isSU (ct))
6111 uentry ue = uentryList_lookupField (ctype_getFields (ct), f);
6113 if (!uentry_isUndefined (ue))
6115 DPRINTF (("lookup: %s for %s", uentry_unparseFull (ue),
6116 ctype_unparse (ct)));
6118 s->type = uentry_getType (ue);
6120 if (ctype_isMutable (s->type)
6121 && rec->aliaskind != AK_STACK
6122 && !alkind_isStatic (rec->aliaskind))
6124 s->aliaskind = rec->aliaskind;
6128 s->aliaskind = AK_UNKNOWN;
6131 if (sRef_isStateDefined (rec) || sRef_isStateUnknown (rec)
6132 || sRef_isPdefined (rec))
6134 sRef_setStateFromUentry (s, ue);
6138 sRef_setPartsFromUentry (s, ue);
6141 s->oaliaskind = s->aliaskind;
6142 s->oexpkind = s->expkind;
6144 DPRINTF (("sref: %s", sRef_unparseFull (s)));
6149 Never report this as an error. It can happen whenever there
6150 is casting involved.
6154 llcontbug (message ("buildNCField --- no field %s: %q / %s",
6155 f, sRef_unparse (s), ctype_unparse (ct)));
6159 return sRef_undefined;
6163 if (rec->defstate == SS_DEFINED
6164 && (s->defstate == SS_UNDEFINED || s->defstate == SS_UNKNOWN))
6166 s->defstate = SS_DEFINED;
6168 else if (rec->defstate == SS_PARTIAL)
6170 s->defstate = SS_PARTIAL;
6172 else if (rec->defstate == SS_ALLOCATED)
6174 if (ctype_isStackAllocated (ct) && ctype_isStackAllocated (s->type))
6176 s->defstate = SS_ALLOCATED;
6180 s->defstate = SS_UNDEFINED;
6183 else if (s->defstate == SS_UNKNOWN)
6185 s->defstate = rec->defstate;
6192 if (s->defstate == SS_UNDEFINED)
6194 ctype rt = ctype_realType (s->type);
6196 if (ctype_isArray (rt) || ctype_isSU (rt))
6198 s->defstate = SS_ALLOCATED;
6202 sRef_addDeriv (rec, s);
6203 DPRINTF (("Add deriv: %s", sRef_unparseFull (rec)));
6205 if (ctype_isInt (s->type) && cstring_equal (f, REFSNAME))
6207 s->aliaskind = AK_REFS;
6208 s->oaliaskind = AK_REFS;
6211 DPRINTF (("Build field ==> %s", sRef_unparseFull (s)));
6217 sRef_isStackAllocated (sRef s)
6219 return (sRef_isValid(s)
6220 && s->defstate == SS_ALLOCATED && ctype_isStackAllocated (s->type));
6224 void sRef_setArrayFetchState (/*@notnull@*/ /*@exposed@*/ sRef s,
6225 /*@notnull@*/ /*@exposed@*/ sRef arr)
6227 sRef_checkMutable (s);
6229 if (ctype_isRealAP (arr->type))
6231 s->type = ctype_baseArrayPtr (arr->type);
6234 /* a hack, methinks... makeArrayFetch (&a[0]) ==> a[] */
6235 if (sRef_isAddress (arr))
6237 sRef t = arr->info->ref;
6239 if (sRef_isArrayFetch (t))
6241 s->info->arrayfetch->arr = t->info->arrayfetch->arr;
6244 else if (ctype_isRealPointer (arr->type))
6246 sRef sp = sRef_findDerivedPointer (arr);
6248 if (sRef_isValid (sp))
6251 if (ctype_isMutable (s->type))
6253 sRef_setExKind (s, sRef_getExKind (sp), fileloc_undefined);
6255 s->aliaskind = sp->aliaskind;
6258 s->defstate = sp->defstate;
6260 if (s->defstate == SS_DEFINED)
6262 if (!context_getFlag (FLG_STRICTDESTROY))
6264 s->defstate = SS_PARTIAL;
6268 sRef_setNullStateN (s, sRef_getNullState (sp));
6272 if (arr->defstate == SS_UNDEFINED)
6274 s->defstate = SS_UNUSEABLE;
6276 else if ((arr->defstate == SS_ALLOCATED) && !ctype_isSU (s->type))
6278 s->defstate = SS_UNDEFINED;
6282 if (!context_getFlag (FLG_STRICTDESTROY))
6284 s->defstate = SS_PARTIAL;
6288 s->defstate = SS_DEFINED;
6292 ** Very weak checking for array elements.
6294 ** s->defstate = arr->defstate;
6298 sRef_setExKind (s, sRef_getExKind (arr), g_currentloc);
6300 if (arr->aliaskind == AK_LOCAL || arr->aliaskind == AK_FRESH)
6302 s->aliaskind = AK_LOCAL;
6306 s->aliaskind = AK_UNKNOWN;
6309 sRef_setTypeState (s);
6314 if (arr->defstate == SS_DEFINED)
6317 ** Very weak checking for array elements.
6319 ** s->defstate = arr->defstate;
6322 if (context_getFlag (FLG_STRICTDESTROY))
6324 s->defstate = SS_DEFINED;
6328 s->defstate = SS_PARTIAL;
6331 else if (arr->defstate == SS_ALLOCATED)
6333 if (ctype_isRealArray (s->type))
6335 s->defstate = SS_ALLOCATED;
6339 if (!s->info->arrayfetch->indknown)
6342 ** is index is unknown, elements is defined or
6343 ** allocated is any element is!
6346 s->defstate = SS_UNDEFINED;
6348 sRefSet_allElements (arr->deriv, sr)
6350 if (sRef_isValid (sr))
6352 if (sr->defstate == SS_ALLOCATED)
6354 s->defstate = SS_ALLOCATED;
6358 if (sr->defstate == SS_DEFINED)
6360 if (context_getFlag (FLG_STRICTDESTROY))
6362 s->defstate = SS_DEFINED;
6366 s->defstate = SS_PARTIAL;
6373 } end_sRefSet_allElements;
6378 s->defstate = SS_UNDEFINED;
6384 s->defstate = arr->defstate;
6389 ** kludgey way to guess where aliaskind applies
6392 if (ctype_isMutable (s->type)
6393 && !ctype_isPointer (arr->type)
6394 && !alkind_isStatic (arr->aliaskind)
6395 && !alkind_isStack (arr->aliaskind)) /* evs - 2000-06-20: don't pass stack allocation to members */
6397 s->aliaskind = arr->aliaskind;
6401 s->aliaskind = AK_UNKNOWN;
6404 sRef_setTypeState (s);
6407 if (sRef_isObserver (arr))
6409 s->expkind = XO_OBSERVER;
6413 /*@exposed@*/ sRef sRef_buildArrayFetch (/*@exposed@*/ sRef arr)
6417 if (!sRef_isValid (arr)) {
6418 /*@-nullret@*/ return arr /*@=nullret@*/;
6421 if (ctype_isRealPointer (arr->type))
6423 (void) sRef_buildPointer (arr); /* do this to define arr! */
6426 s = sRef_findDerivedArrayFetch (arr, FALSE, 0, FALSE);
6428 if (sRef_isValid (s))
6430 /* evans 2001-07-12: this is bogus, clean-up hack */
6431 if (s->info->arrayfetch->arr != arr)
6434 check (sRefSet_delete (arr->deriv, s));
6435 res = sRef_buildArrayFetch (arr);
6436 sRef_copyState (res, s);
6440 sRef_setExKind (s, sRef_getExKind (arr), g_currentloc);
6447 s->kind = SK_ARRAYFETCH;
6448 s->info = (sinfo) dmalloc (sizeof (*s->info));
6449 s->info->arrayfetch = (ainfo) dmalloc (sizeof (*s->info->arrayfetch));
6450 s->info->arrayfetch->indknown = FALSE;
6451 s->info->arrayfetch->ind = 0;
6452 s->info->arrayfetch->arr = arr; /* sRef_copy (arr); */ /*@i32@*/
6453 sRef_setArrayFetchState (s, arr);
6454 s->oaliaskind = s->aliaskind;
6455 s->oexpkind = s->expkind;
6457 if (!context_inProtectVars ())
6459 sRef_addDeriv (arr, s);
6462 llassert (valueTable_isUndefined (s->state));
6463 s->state = context_createValueTable (s);
6470 sRef_buildArrayFetchKnown (/*@exposed@*/ sRef arr, int i)
6474 if (!sRef_isValid (arr)) {
6475 /*@-nullret@*/ return arr /*@=nullret@*/;
6478 if (ctype_isRealPointer (arr->type))
6480 (void) sRef_buildPointer (arr); /* do this to define arr! */
6483 s = sRef_findDerivedArrayFetch (arr, TRUE, i, FALSE);
6485 if (sRef_isValid (s))
6487 /* evans 2001-07-12: this is bogus, clean-up hack */
6488 if (s->info->arrayfetch->arr != arr)
6491 check (sRefSet_delete (arr->deriv, s));
6492 res = sRef_buildArrayFetchKnown (arr, i);
6493 sRef_copyState (res, s);
6497 sRef_setExKind (s, sRef_getExKind (arr), g_currentloc);
6499 llassert (s->info->arrayfetch->arr == arr);
6506 s->kind = SK_ARRAYFETCH;
6507 s->info = (sinfo) dmalloc (sizeof (*s->info));
6508 s->info->arrayfetch = (ainfo) dmalloc (sizeof (*s->info->arrayfetch));
6509 s->info->arrayfetch->arr = arr; /* sRef_copy (arr); */ /*@i32@*/
6510 s->info->arrayfetch->indknown = TRUE;
6511 s->info->arrayfetch->ind = i;
6513 sRef_setArrayFetchState (s, arr);
6515 s->oaliaskind = s->aliaskind;
6516 s->oexpkind = s->expkind;
6517 sRef_addDeriv (arr, s);
6519 llassert (valueTable_isUndefined (s->state));
6520 s->state = context_createValueTable (s);
6527 ** sets everything except for defstate
6531 sRef_setPartsFromUentry (sRef s, uentry ue)
6533 sRef uref = uentry_getSref (ue);
6535 llassert (sRef_isValid (s));
6537 s->aliaskind = alkind_derive (s->aliaskind, uentry_getAliasKind (ue));
6538 s->oaliaskind = s->aliaskind;
6540 if (s->expkind == XO_UNKNOWN)
6542 s->expkind = uentry_getExpKind (ue);
6545 s->oexpkind = s->expkind;
6547 if (sRef_getNullState (s) == NS_UNKNOWN)
6549 DPRINTF (("Setting null state!"));
6550 sRef_setNullStateN (s, sRef_getNullState (uentry_getSref (ue)));
6554 DPRINTF (("Skipping null null state!"));
6557 if (s->aliaskind == AK_IMPONLY && (sRef_isExposed (s) || sRef_isObserver (s)))
6559 s->oaliaskind = s->aliaskind = AK_IMPDEPENDENT;
6562 if (sRef_isValid (uref))
6564 valueTable utable = uref->state;
6565 valueTable_free (s->state);
6566 s->state = valueTable_copy (utable);
6571 sRef_setStateFromAbstractUentry (sRef s, uentry ue)
6573 llassert (sRef_isValid (s));
6574 sRef_checkMutable (s);
6576 sRef_setPartsFromUentry (s, ue);
6578 s->aliaskind = alkind_derive (s->aliaskind, uentry_getAliasKind (ue));
6579 s->oaliaskind = s->aliaskind;
6581 if (s->expkind == XO_UNKNOWN)
6583 s->expkind = uentry_getExpKind (ue);
6586 s->oexpkind = s->expkind;
6590 sRef_setStateFromUentry (sRef s, uentry ue)
6594 sRef_checkMutable (s);
6595 llassert (sRef_isValid (s));
6597 sRef_setPartsFromUentry (s, ue);
6599 defstate = uentry_getDefState (ue);
6601 if (sstate_isKnown (defstate))
6603 s->defstate = defstate;
6612 sRef_buildPointer (/*@exposed@*/ sRef t)
6614 DPRINTF (("build pointer: %s", sRef_unparse (t)));
6616 if (sRef_isInvalid (t)) return sRef_undefined;
6618 if (sRef_isAddress (t))
6620 DPRINTF (("Return ref: %s", sRef_unparse (t->info->ref)));
6621 return (t->info->ref);
6625 sRef s = sRef_findDerivedPointer (t);
6627 DPRINTF (("find derived: %s", sRef_unparse (s)));
6629 if (sRef_isValid (s))
6632 sRef_setExKind (s, sRef_getExKind (t), g_currentloc);
6633 s->oaliaskind = s->aliaskind;
6634 s->oexpkind = s->expkind;
6640 s = sRef_constructPointerAux (t);
6642 DPRINTF (("construct: %s", sRef_unparse (s)));
6644 if (sRef_isValid (s))
6646 sRef_addDeriv (t, s);
6648 s->oaliaskind = s->aliaskind;
6649 s->oexpkind = s->expkind;
6658 sRef_constructPointer (/*@exposed@*/ sRef t)
6661 return sRef_buildPointer (t);
6664 static /*@exposed@*/ sRef sRef_constructDerefAux (sRef t, bool isdead)
6666 if (sRef_isValid (t))
6671 ** if there is a derived t[?], return that. Otherwise, *t.
6674 s = sRef_findDerivedArrayFetch (t, FALSE, 0, isdead);
6676 if (sRef_isValid (s))
6678 DPRINTF (("Found array fetch: %s", sRef_unparseFull (s)));
6683 sRef ret = sRef_constructPointer (t);
6685 DPRINTF (("Constructed pointer: %s", sRef_unparseFull (ret)));
6692 return sRef_undefined;
6696 sRef sRef_constructDeref (sRef t)
6698 return sRef_constructDerefAux (t, FALSE);
6701 sRef sRef_constructDeadDeref (sRef t)
6703 return sRef_constructDerefAux (t, TRUE);
6707 sRef_constructPointerAux (/*@notnull@*/ /*@exposed@*/ sRef t)
6709 sRef s = sRef_newRef ();
6714 s->info = (sinfo) dmalloc (sizeof (*s->info));
6715 s->info->ref = t; /* sRef_copy (t); */ /*@i32*/
6717 if (ctype_isRealAP (rt))
6719 s->type = ctype_baseArrayPtr (rt);
6722 st = ctype_realType (s->type);
6724 if (t->defstate == SS_UNDEFINED)
6726 s->defstate = SS_UNUSEABLE;
6728 else if ((t->defstate == SS_ALLOCATED) && !ctype_isSU (st))
6730 s->defstate = SS_UNDEFINED;
6734 s->defstate = t->defstate;
6737 if (t->aliaskind == AK_LOCAL || t->aliaskind == AK_FRESH)
6739 s->aliaskind = AK_LOCAL;
6743 s->aliaskind = AK_UNKNOWN;
6746 sRef_setExKind (s, sRef_getExKind (t), fileloc_undefined);
6747 sRef_setTypeState (s);
6749 s->oaliaskind = s->aliaskind;
6750 s->oexpkind = s->expkind;
6752 llassert (valueTable_isUndefined (s->state));
6753 s->state = context_createValueTable (s);
6757 bool sRef_hasDerived (sRef s)
6759 return (sRef_isValid (s) && !sRefSet_isEmpty (s->deriv));
6763 sRef_clearDerived (sRef s)
6765 if (sRef_isValid (s))
6767 sRefSet_clear (s->deriv);
6772 sRef_clearDerivedComplete (sRef s)
6775 if (sRef_isValid (s))
6777 sRef base = sRef_getBaseSafe (s);
6779 while (sRef_isValid (base))
6781 sRefSet_clear (base->deriv);
6782 base = sRef_getBaseSafe (base);
6785 sRefSet_clear (s->deriv);
6789 /*@exposed@*/ sRef sRef_makePointer (/*@exposed@*/ sRef s)
6792 sRef res = sRef_buildPointer (s);
6794 DPRINTF (("Res: %s", sRef_unparse (res)));
6799 ** &a[] => a (this is for out params)
6803 sRef_makeAnyArrayFetch (/*@exposed@*/ sRef arr)
6806 if (sRef_isAddress (arr))
6808 return (arr->info->ref);
6812 return (sRef_buildArrayFetch (arr));
6817 sRef_makeArrayFetch (/*@exposed@*/ sRef arr)
6819 return (sRef_buildArrayFetch (arr));
6823 sRef_makeArrayFetchKnown (/*@exposed@*/ sRef arr, int i)
6825 return (sRef_buildArrayFetchKnown (arr, i));
6829 sRef_makeField (sRef rec, /*@dependent@*/ cstring f)
6832 ret = sRef_buildField (rec, f);
6837 sRef_makeNCField (/*@exposed@*/ sRef rec, /*@dependent@*/ cstring f)
6839 return (sRef_buildNCField (rec, f));
6843 sRef_unparseKindName (sRef s)
6847 if (s == sRef_undefined) return cstring_makeLiteral ("<invalid>");
6849 s = sRef_fixConj (s);
6854 if (sRef_isLocalVar (s))
6856 result = cstring_makeLiteral ("Variable");
6860 result = cstring_makeLiteral ("Undef global");
6864 result = cstring_makeLiteral ("Out parameter");
6867 if (sRef_isAnyParam (s->info->arrayfetch->arr))
6869 result = cstring_makeLiteral ("Out parameter");
6871 else if (sRef_isIndexKnown (s))
6873 result = cstring_makeLiteral ("Array element");
6877 result = cstring_makeLiteral ("Value");
6881 if (sRef_isAnyParam (s->info->ref))
6883 result = cstring_makeLiteral ("Out parameter");
6887 result = cstring_makeLiteral ("Value");
6891 result = cstring_makeLiteral ("Value");
6894 result = cstring_makeLiteral ("Field");
6897 result = cstring_makeLiteral ("Object");
6899 case SK_UNCONSTRAINED:
6900 result = cstring_makeLiteral ("<anything>");
6909 result = cstring_makeLiteral ("<unknown>");
6912 result = cstring_makeLiteral ("<conj>");
6915 result = cstring_makeLiteral ("Storage");
6923 sRef_unparseKindNamePlain (sRef s)
6927 if (s == sRef_undefined) return cstring_makeLiteral ("<invalid>");
6929 s = sRef_fixConj (s);
6934 if (sRef_isLocalVar (s))
6936 result = cstring_makeLiteral ("Variable");
6940 result = cstring_makeLiteral ("Global");
6944 result = cstring_makeLiteral ("Parameter");
6947 if (sRef_isAnyParam (s->info->arrayfetch->arr))
6949 result = cstring_makeLiteral ("Parameter");
6951 else if (sRef_isIndexKnown (s))
6953 result = cstring_makeLiteral ("Array element");
6957 result = cstring_makeLiteral ("Value");
6961 if (sRef_isAnyParam (s->info->ref))
6963 result = cstring_makeLiteral ("Parameter");
6967 result = cstring_makeLiteral ("Value");
6971 result = cstring_makeLiteral ("Value");
6974 result = cstring_makeLiteral ("Field");
6977 result = cstring_makeLiteral ("Object");
6980 result = cstring_makeLiteral ("Storage");
6982 case SK_UNCONSTRAINED:
6983 result = cstring_makeLiteral ("<anything>");
6992 result = cstring_makeLiteral ("<unknown>");
6995 result = cstring_makeLiteral ("<conj>");
7007 sRef_copyState (sRef s1, sRef s2)
7009 if (sRef_isValid (s1) && sRef_isValid (s2))
7011 s1->defstate = s2->defstate;
7013 /* start modifications */
7014 s1->bufinfo.bufstate = s2->bufinfo.bufstate;
7015 s1->bufinfo.len = s2->bufinfo.len;
7016 s1->bufinfo.size = s2->bufinfo.size;
7017 /* end modifications */
7019 s1->aliaskind = s2->aliaskind;
7020 s1->aliasinfo = stateInfo_update (s1->aliasinfo, s2->aliasinfo);
7022 s1->expkind = s2->expkind;
7023 s1->expinfo = stateInfo_update (s1->expinfo, s2->expinfo);
7025 s1->nullstate = s2->nullstate;
7026 s1->nullinfo = stateInfo_update (s1->nullinfo, s2->nullinfo);
7029 /*@i834 don't free it: valueTable_free (s1->state); */
7030 /*@i32@*/ s1->state = valueTable_copy (s2->state);
7032 s1->safe = s2->safe;
7037 sRef_makeNew (ctype ct, sRef t, cstring name)
7039 sRef s = sRef_newRef ();
7044 llassert (sRef_isValid (t));
7045 s->defstate = t->defstate;
7047 s->aliaskind = t->aliaskind;
7048 s->oaliaskind = s->aliaskind;
7049 s->nullstate = t->nullstate;
7051 s->expkind = t->expkind;
7052 s->oexpkind = s->expkind;
7054 s->info = (sinfo) dmalloc (sizeof (*s->info));
7055 s->info->fname = name;
7057 /* start modifications */
7058 s->bufinfo.bufstate = t->bufinfo.bufstate;
7059 /* end modifications */
7061 llassert (valueTable_isUndefined (s->state));
7062 s->state = valueTable_copy (t->state);
7064 DPRINTF (("==> Copying state: %s", valueTable_unparse (s->state)));
7065 DPRINTF (("==> new: %s", sRef_unparseFull (s)));
7070 sRef_makeType (ctype ct)
7072 sRef s = sRef_newRef ();
7074 sRef_checkMutable (s);
7079 s->defstate = SS_UNKNOWN;
7080 s->aliaskind = AK_UNKNOWN;
7081 sRef_setNullStateN (s, NS_UNKNOWN);
7083 /* start modification */
7084 s->bufinfo.bufstate = BB_NOTNULLTERMINATED;
7085 /* end modification */
7088 if (ctype_isUA (ct))
7090 typeId uid = ctype_typeId (ct);
7091 uentry ue = usymtab_getTypeEntrySafe (uid);
7093 if (uentry_isValid (ue))
7095 sRef_mergeStateQuiet (s, uentry_getSref (ue));
7099 s->oaliaskind = s->aliaskind;
7100 s->oexpkind = s->expkind;
7101 llassert (valueTable_isUndefined (s->state));
7102 s->state = context_createValueTable (s);
7104 DPRINTF (("Create: %s", sRef_unparseFull (s)));
7109 sRef_makeConst (ctype ct)
7111 sRef s = sRef_newRef ();
7116 s->defstate = SS_UNKNOWN;
7117 s->aliaskind = AK_UNKNOWN;
7118 sRef_setNullStateN (s, NS_UNKNOWN);
7120 /* start modification */
7121 s->bufinfo.bufstate = BB_NULLTERMINATED;
7122 /* end modification */
7125 if (ctype_isUA (ct))
7127 typeId uid = ctype_typeId (ct);
7128 uentry te = usymtab_getTypeEntrySafe (uid);
7130 if (uentry_isValid (te))
7132 sRef_mergeStateQuiet (s, uentry_getSref (te));
7137 s->oaliaskind = s->aliaskind;
7138 s->oexpkind = s->expkind;
7140 llassert (valueTable_isUndefined (s->state));
7141 s->state = context_createValueTable (s);
7146 bool sRef_hasName (sRef s)
7148 if (sRef_isInvalid (s))
7157 uentry u = usymtab_getRefQuiet (s->info->cvar->lexlevel,
7158 s->info->cvar->index);
7159 return (uentry_hasName (u));
7163 if (s->info->paramno >= 0)
7165 uentry u = uentryList_getN (context_getParams (),
7168 return (uentry_hasName (u));
7172 llassert (s->info->paramno == PARAMUNKNOWN);
7182 sRef_sameName (sRef s1, sRef s2)
7184 if (sRef_isInvalid (s1))
7186 return sRef_isInvalid (s2);
7189 if (sRef_isInvalid (s2))
7197 if (s2->kind == SK_CVAR)
7199 return (s1->info->cvar->lexlevel == s2->info->cvar->lexlevel
7200 && s1->info->cvar->index == s2->info->cvar->index);
7202 else if (s2->kind == SK_PARAM)
7204 if (context_inFunctionLike ())
7206 if (s2->info->paramno != PARAMUNKNOWN)
7208 uentry u1 = usymtab_getRefQuiet (s1->info->cvar->lexlevel,
7209 s1->info->cvar->index);
7210 uentry u2 = uentryList_getN (context_getParams (),
7213 return (cstring_equalFree (uentry_getName (u1),
7214 uentry_getName (u2)));
7218 return s1->info->paramno == PARAMUNKNOWN;
7232 if (s2->kind == SK_PARAM)
7234 return (s1->info->paramno == s2->info->paramno);
7236 else if (s2->kind == SK_CVAR)
7238 if (context_inFunctionLike ())
7240 if (s1->info->paramno == PARAMUNKNOWN)
7246 uentry u1 = uentryList_getN (context_getParams (),
7248 uentry u2 = usymtab_getRefQuiet (s2->info->cvar->lexlevel,
7249 s2->info->cvar->index);
7252 return (cstring_equalFree (uentry_getName (u1),
7253 uentry_getName (u2)));
7267 case SK_UNCONSTRAINED:
7271 if (s2->kind == SK_ARRAYFETCH)
7273 if (bool_equal (s1->info->arrayfetch->indknown,
7274 s2->info->arrayfetch->indknown))
7276 if (!s1->info->arrayfetch->indknown
7277 || (s1->info->arrayfetch->ind == s2->info->arrayfetch->ind))
7279 return sRef_sameName (s1->info->arrayfetch->arr,
7280 s2->info->arrayfetch->arr);
7287 if (s2->kind == SK_FIELD)
7289 if (cstring_equal (s1->info->field->field,
7290 s2->info->field->field))
7292 return sRef_sameName (s1->info->field->rec,
7293 s2->info->field->rec);
7302 if (s2->kind == s1->kind)
7304 return sRef_sameName (s1->info->ref,
7312 return sRef_sameName (sRef_getConjA (s1), s2);
7316 return (s2->kind == SK_UNKNOWN);
7319 if (s2->kind == s1->kind)
7321 return (ctype_equal (s1->type, s2->type));
7326 if (s2->kind == SK_SPECIAL)
7328 return (s1->info->spec == s2->info->spec);
7332 return (s2->kind == SK_RESULT);
7340 sRef_fixOuterRef (/*@returned@*/ sRef s)
7342 sRef root = sRef_getRootBase (s);
7344 if (sRef_isCvar (root))
7346 uentry ue = usymtab_getRefQuiet (root->info->cvar->lexlevel,
7347 root->info->cvar->index);
7349 if (uentry_isValid (ue))
7351 sRef uref = uentry_getSref (ue);
7352 sRef sr = sRef_fixBase (s, uref);
7358 llcontbug (message ("sRef_fixOuterRef: undefined: %q", sRef_unparseDebug (s)));
7367 sRef_storeState (sRef s)
7369 if (sRef_isInvalid (s)) return;
7371 sRef_checkMutable (s);
7372 s->oaliaskind = s->aliaskind;
7373 s->oexpkind = s->expkind;
7376 static void sRef_resetStateAux (sRef s, /*@unused@*/ fileloc loc)
7378 sRef_resetState (s);
7382 sRef_resetState (sRef s)
7384 bool changed = FALSE;
7385 if (sRef_isInvalid (s)) return;
7388 if (s->oaliaskind == AK_KILLREF && !sRef_isParam (s))
7391 ** killref is used in a kludgey way, to save having to add
7392 ** another alias kind (see usymtab_handleParams)
7395 if (s->expkind != s->oexpkind)
7398 s->expkind = s->oexpkind;
7403 if (s->expkind != s->oexpkind)
7406 s->expkind = s->oexpkind;
7409 if (s->aliaskind != s->oaliaskind
7410 && s->aliaskind != AK_REFCOUNTED
7411 && s->aliaskind != AK_REFS)
7414 s->aliaskind = s->oaliaskind;
7420 sRef_clearDerived (s);
7426 sRef_resetStateComplete (sRef s)
7428 sRef_innerAliasSetComplete (sRef_resetStateAux, s, fileloc_undefined);
7432 sRef_fixBase (/*@returned@*/ sRef s, /*@returned@*/ sRef base)
7434 sRef tmp = sRef_undefined;
7437 if (sRef_isInvalid (s)) return s;
7438 if (sRef_isInvalid (base)) return base;
7448 tmp = sRef_fixBase (s->info->arrayfetch->arr, base);
7450 if (s->info->arrayfetch->indknown)
7452 ret = sRef_makeArrayFetchKnown (tmp, s->info->arrayfetch->ind);
7456 ret = sRef_makeArrayFetch (tmp);
7460 tmp = sRef_fixBase (s->info->field->rec, base);
7461 ret = sRef_buildNCField (tmp, s->info->field->field);
7464 tmp = sRef_fixBase (s->info->ref, base);
7465 ret = sRef_makePointer (tmp);
7468 tmp = sRef_fixBase (s->info->ref, base);
7469 ret = sRef_makeAddress (tmp);
7475 tmp = sRef_fixBase (s->info->conj->a, base);
7476 tmpb = sRef_fixBase (s->info->conj->b, base);
7478 ret = sRef_makeConj (tmp, tmpb);
7487 static /*@exposed@*/ sRef
7488 sRef_fixDirectBase (sRef s, sRef base)
7493 if (sRef_isInvalid (s))
7495 return sRef_undefined;
7501 if (s->info->arrayfetch->indknown)
7503 ret = sRef_makeArrayFetchKnown (base, s->info->arrayfetch->ind);
7507 ret = sRef_makeArrayFetch (base);
7511 ret = sRef_buildNCField (base, s->info->field->field);
7514 ret = sRef_makePointer (base);
7517 ret = sRef_makeAddress (base);
7523 tmpa = sRef_fixDirectBase (s->info->conj->a, base);
7524 tmpb = sRef_fixDirectBase (s->info->conj->b, base);
7526 ret = sRef_makeConj (tmpa, tmpb);
7532 sRef_copyState (ret, s);
7537 sRef_isAllocIndexRef (sRef s)
7539 return (sRef_isArrayFetch (s) && !(s->info->arrayfetch->indknown)
7540 && sRef_isAllocated (s->info->arrayfetch->arr));
7544 sRef_showRefLost (sRef s)
7546 if (sRef_hasAliasInfoLoc (s))
7548 llgenindentmsg (cstring_makeLiteral ("Original reference lost"),
7549 sRef_getAliasInfoLoc (s));
7554 sRef_showRefKilled (sRef s)
7556 if (sRef_hasStateInfoLoc (s))
7558 llgenindentmsg (message ("Storage %q released",
7559 sRef_unparse (s)), sRef_getStateInfoLoc (s));
7564 sRef_showStateInconsistent (sRef s)
7566 if (sRef_hasStateInfoLoc (s))
7569 (message ("Storage %qbecomes inconsistent (released on one branch)",
7570 sRef_unparseOpt (s)),
7571 sRef_getStateInfoLoc (s));
7576 sRef_showStateInfo (sRef s)
7578 if (sRef_hasStateInfoLoc (s))
7580 if (s->defstate == SS_DEAD)
7583 (message ("Storage %qis released", sRef_unparseOpt (s)),
7584 sRef_getStateInfoLoc (s));
7586 else if (s->defstate == SS_ALLOCATED || s->defstate == SS_DEFINED)
7589 (message ("Storage %qis %s", sRef_unparseOpt (s),
7590 sstate_unparse (s->defstate)),
7591 sRef_getStateInfoLoc (s));
7593 else if (s->defstate == SS_UNUSEABLE)
7596 (message ("Storage %qbecomes inconsistent (clauses merge with"
7597 "%qreleased on one branch)",
7598 sRef_unparseOpt (s),
7599 sRef_unparseOpt (s)),
7600 sRef_getStateInfoLoc (s));
7604 llgenindentmsg (message ("Storage %qbecomes %s",
7605 sRef_unparseOpt (s),
7606 sstate_unparse (s->defstate)),
7607 sRef_getStateInfoLoc (s));
7613 sRef_showExpInfo (sRef s)
7615 if (sRef_hasExpInfoLoc (s))
7617 llgenindentmsg (message ("Storage %qbecomes %s", sRef_unparseOpt (s),
7618 exkind_unparse (s->expkind)),
7619 sRef_getExpInfoLoc (s));
7624 sRef_showMetaStateInfo (sRef s, cstring key)
7627 metaStateInfo minfo = context_lookupMetaStateInfo (key);
7629 llassert (sRef_isValid (s));
7630 llassert (valueTable_isDefined (s->state));
7631 llassert (metaStateInfo_isDefined (minfo));
7633 val = valueTable_lookup (s->state, key);
7635 if (stateValue_hasLoc (val))
7638 (message ("Meta state %qbecomes %q", sRef_unparseOpt (s),
7639 stateValue_unparseValue (val, minfo)),
7640 stateValue_getLoc (val));
7645 sRef_showNullInfo (sRef s)
7647 DPRINTF (("Show null info: %s", sRef_unparseFull (s)));
7649 if (sRef_hasNullInfoLoc (s) && sRef_isKnown (s))
7651 DPRINTF (("has null info: %s",
7652 fileloc_unparse (sRef_getNullInfoLoc (s))));
7654 switch (sRef_getNullState (s))
7658 fileloc loc = sRef_getNullInfoLoc (s);
7660 if (fileloc_isDefined (loc) && !fileloc_isLib (loc))
7663 (message ("Storage %qbecomes null", sRef_unparseOpt (s)),
7670 fileloc loc = sRef_getNullInfoLoc (s);
7672 if (fileloc_isDefined (loc) && !fileloc_isLib (loc))
7674 llgenindentmsg (message ("Storage %qbecomes null", sRef_unparseOpt (s)),
7682 (message ("Storage %qmay become null", sRef_unparseOpt (s)),
7683 sRef_getNullInfoLoc (s));
7688 (message ("Storage %qbecomes not null", sRef_unparseOpt (s)),
7689 sRef_getNullInfoLoc (s));
7693 (message ("Storage %qnull state becomes unknown",
7694 sRef_unparseOpt (s)),
7695 sRef_getNullInfoLoc (s));
7704 (message ("<error case> Storage %q becomes %s",
7706 nstate_unparse (sRef_getNullState (s))),
7707 sRef_getNullInfoLoc (s));
7715 sRef_showAliasInfo (sRef s)
7717 if (sRef_hasAliasInfoLoc (s))
7719 if (sRef_isFresh (s))
7722 (message ("Fresh storage %qallocated", sRef_unparseOpt (s)),
7723 sRef_getAliasInfoLoc (s));
7727 if (!sRef_isRefCounted (s))
7730 (message ("Storage %qbecomes %s",
7731 sRef_unparseOpt (s),
7732 alkind_unparse (sRef_getAliasKind (s))),
7733 sRef_getAliasInfoLoc (s));
7740 sRef_mergeNullState (sRef s, nstate n)
7742 if (sRef_isValid (s))
7746 old = sRef_getNullState (s);
7748 if (n != old && n != NS_UNKNOWN)
7750 sRef_setNullState (s, n, g_currentloc);
7755 llbuglit ("sRef_mergeNullState: invalid");
7760 sRef_possiblyNull (sRef s)
7762 if (sRef_isValid (s))
7764 if (sRef_getNullState (s) == NS_ABSNULL)
7766 ctype rct = ctype_realType (s->type);
7768 if (ctype_isAbstract (rct))
7774 if (ctype_isUser (rct))
7776 uentry ue = usymtab_getTypeEntry (ctype_typeId (rct));
7778 return (nstate_possiblyNull
7779 (sRef_getNullState (uentry_getSref (ue))));
7789 return nstate_possiblyNull (sRef_getNullState (s));
7797 sRef_getScopeName (sRef s)
7799 sRef base = sRef_getRootBase (s);
7801 if (sRef_isRealGlobal (base))
7803 return (cstring_makeLiteralTemp ("Global"));
7805 else if (sRef_isFileStatic (base))
7807 return (cstring_makeLiteralTemp ("Static"));
7811 return (cstring_makeLiteralTemp ("Local"));
7816 sRef_unparseScope (sRef s)
7818 sRef base = sRef_getRootBase (s);
7820 if (sRef_isRealGlobal (base))
7822 return (cstring_makeLiteralTemp ("global"));
7824 else if (sRef_isFileStatic (base))
7826 return (cstring_makeLiteralTemp ("file static"));
7835 sRef_getScope (sRef s)
7837 llassert (sRef_isValid (s));
7839 if (sRef_isCvar (s))
7841 return s->info->cvar->lexlevel;
7843 else if (sRef_isParam (s))
7854 sRef_isDead (sRef s)
7856 return (sRef_isValid (s) && (s)->defstate == SS_DEAD);
7860 sRef_isDeadStorage (sRef s)
7862 if (sRef_isValid (s))
7864 if (s->defstate == SS_DEAD
7865 || s->defstate == SS_UNUSEABLE
7866 || s->defstate == SS_UNDEFINED
7867 || s->defstate == SS_UNKNOWN)
7873 return (sRef_isDefinitelyNull (s));
7883 sRef_isPossiblyDead (sRef s)
7885 return (sRef_isValid (s) && s->defstate == SS_HOFFA);
7888 bool sRef_isStateLive (sRef s)
7890 if (sRef_isValid (s))
7892 sstate ds = s->defstate;
7894 return (!(ds == SS_UNDEFINED
7896 || ds == SS_UNUSEABLE
7897 || ds == SS_HOFFA));
7906 bool sRef_isStateUndefined (sRef s)
7908 return ((sRef_isValid(s)) && ((s)->defstate == SS_UNDEFINED));
7911 bool sRef_isJustAllocated (sRef s)
7913 if (sRef_isAllocated (s))
7915 sRefSet_allElements (s->deriv, el)
7917 if (!(sRef_isStateUndefined (el) || sRef_isUnuseable (el)))
7921 } end_sRefSet_allElements ;
7930 sRef_isAllocatedStorage (sRef s)
7932 if (sRef_isValid (s) && ynm_toBoolStrict (sRef_isReadable (s)))
7934 return (ctype_isVisiblySharable (sRef_getType (s)));
7943 sRef_isUnuseable (sRef s)
7945 return ((sRef_isValid(s)) && ((s)->defstate == SS_UNUSEABLE));
7949 sRef_perhapsNull (sRef s)
7951 if (sRef_isValid (s))
7953 if (sRef_getNullState (s) == NS_ABSNULL)
7955 ctype rct = ctype_realType (s->type);
7957 if (ctype_isAbstract (rct))
7963 if (ctype_isUser (rct))
7965 uentry ue = usymtab_getTypeEntry (ctype_typeId (rct));
7967 return (nstate_perhapsNull
7968 (sRef_getNullState (uentry_getSref (ue))));
7978 return nstate_perhapsNull (sRef_getNullState (s));
7986 ** definitelyNull --- called when TRUE is good
7990 sRef_definitelyNull (sRef s)
7992 return (sRef_isValid (s)
7993 && (sRef_getNullState (s) == NS_DEFNULL || sRef_getNullState (s) == NS_CONSTNULL));
7997 ** based on sRef_similar
8001 sRef_setDerivNullState (sRef set, sRef guide, nstate ns)
8003 if (sRef_isValid (set))
8005 sRef deriv = sRef_getDeriv (set, guide);
8007 if (sRef_isValid (deriv))
8009 sRef_setNullStateN (deriv, ns);
8014 static /*@exposed@*/ sRef
8015 sRef_getDeriv (/*@returned@*/ /*@notnull@*/ sRef set, sRef guide)
8017 llassert (sRef_isValid (set));
8018 llassert (sRef_isValid (guide));
8020 switch (guide->kind)
8023 llassert (set->kind == SK_CVAR);
8028 llassert (set->kind == guide->kind);
8029 llassert (set->info->paramno == guide->info->paramno);
8035 if (set->kind == SK_ARRAYFETCH
8036 && (sRef_similar (set->info->arrayfetch->arr,
8037 guide->info->arrayfetch->arr)))
8043 return (sRef_makeAnyArrayFetch
8044 (sRef_getDeriv (set, guide->info->arrayfetch->arr)));
8049 if (set->kind == SK_PTR && sRef_similar (set->info->ref, guide->info->ref))
8055 return (sRef_makePointer (sRef_getDeriv (set, guide->info->ref)));
8060 if ((set->kind == SK_FIELD &&
8061 (sRef_similar (set->info->field->rec, guide->info->field->rec) &&
8062 cstring_equal (set->info->field->field, guide->info->field->field))))
8068 return (sRef_makeField (sRef_getDeriv (set, guide->info->field->rec),
8069 guide->info->field->field));
8073 if ((set->kind == SK_ADR) && sRef_similar (set->info->ref, guide->info->ref))
8079 return (sRef_makeAddress (sRef_getDeriv (set, guide->info->ref)));
8084 return sRef_undefined;
8088 case SK_UNCONSTRAINED:
8096 return sRef_undefined;
8103 ** sRef_aliasCheckPred
8105 ** A confusing but spiffy function:
8107 ** Calls predf (s, e, text, <alias>) on s and all of s's aliases
8108 ** (unless checkAliases (s) is FALSE).
8110 ** For alias calls, calls as
8111 ** predf (alias, e, text, s)
8115 sRef_aliasCheckPred (bool (predf) (sRef, exprNode, sRef, exprNode),
8116 /*@null@*/ bool (checkAliases) (sRef),
8117 sRef s, exprNode e, exprNode err)
8119 bool error = (*predf)(s, e, sRef_undefined, err);
8122 if (checkAliases != NULL && !(checkAliases (s)))
8124 /* don't check aliases */
8128 sRefSet aliases = usymtab_allAliases (s);
8131 sRefSet_realElements (aliases, current)
8133 if (sRef_isValid (current))
8135 if (!sRef_similar (current, s)
8136 || (error && sRef_sameName (current, s)))
8138 (void) (*predf)(current, e, s, err);
8141 } end_sRefSet_realElements;
8143 sRefSet_free (aliases);
8148 ** return TRUE iff predf (s) is true for s or any alias of s
8152 sRef_aliasCheckSimplePred (sRefTest predf, sRef s)
8163 aliases = usymtab_allAliases (s);
8165 sRefSet_realElements (aliases, current)
8167 if (sRef_isValid (current))
8169 sRef cref = sRef_updateSref (current);
8171 /* Whoa! a very kludgey way to make sure the right sref is used
8172 ** where there is a conditional symbol table. I am beginning
8173 ** to think that having a conditional symbol table wasn't such
8179 DPRINTF (("Checking alias: %s", sRef_unparseFull (cref)));
8180 sRefSet_free (aliases);
8184 } end_sRefSet_realElements;
8186 sRefSet_free (aliases);
8192 sRef_aliasCompleteSimplePred (bool (predf) (sRef), sRef s)
8195 bool result = FALSE;
8198 aliases = usymtab_allAliases (s);
8200 if ((*predf)(s)) result = TRUE;
8203 sRefSet_realElements (aliases, current)
8205 if (sRef_isValid (current))
8207 current = sRef_updateSref (current);
8208 if ((*predf)(current)) result = TRUE;
8210 } end_sRefSet_realElements;
8212 sRefSet_free (aliases);
8217 sRef_aliasSetComplete (void (predf) (sRef, fileloc), sRef s, fileloc loc)
8221 aliases = usymtab_allAliases (s);
8223 DPRINTF (("All aliases: %s", sRefSet_unparseFull (aliases)));
8227 sRefSet_realElements (aliases, current)
8229 if (sRef_isValid (current))
8231 current = sRef_updateSref (current);
8232 ((*predf)(current, loc));
8234 } end_sRefSet_realElements;
8236 sRefSet_free (aliases);
8240 sRef_aliasSetCompleteParam (void (predf) (sRef, alkind, fileloc), sRef s,
8241 alkind kind, fileloc loc)
8246 if (sRef_isDeep (s))
8248 aliases = usymtab_allAliases (s);
8252 aliases = usymtab_aliasedBy (s);
8255 (*predf)(s, kind, loc);
8257 sRefSet_realElements (aliases, current)
8259 if (sRef_isValid (current))
8261 current = sRef_updateSref (current);
8262 ((*predf)(current, kind, loc));
8264 } end_sRefSet_realElements;
8266 sRefSet_free (aliases);
8270 sRef_innerAliasSetComplete (void (predf) (sRef, fileloc), sRef s, fileloc loc)
8276 if (!sRef_isValid (s)) return;
8280 ** Type equivalence checking is necessary --- there might be casting.
8287 case SK_UNCONSTRAINED:
8292 inner = s->info->ref;
8293 aliases = usymtab_allAliases (inner);
8294 ct = sRef_getType (inner);
8296 sRefSet_realElements (aliases, current)
8298 if (sRef_isValid (current))
8300 current = sRef_updateSref (current);
8302 if (ctype_equal (ct, sRef_getType (current)))
8304 sRef ptr = sRef_makePointer (current);
8305 ((*predf)(ptr, loc));
8308 } end_sRefSet_realElements;
8310 sRefSet_free (aliases);
8313 inner = s->info->arrayfetch->arr;
8314 aliases = usymtab_allAliases (inner);
8315 ct = sRef_getType (inner);
8317 DPRINTF (("Array fetch: %s", sRefSet_unparse (aliases)));
8319 sRefSet_realElements (aliases, current)
8321 if (sRef_isValid (current))
8323 current = sRef_updateSref (current);
8324 DPRINTF (("Current: %s", sRef_unparseFull (current)));
8326 if (ctype_equal (ct, sRef_getType (current)))
8328 if (s->info->arrayfetch->indknown)
8330 sRef af = sRef_makeArrayFetchKnown (current, s->info->arrayfetch->ind);
8331 DPRINTF (("Defining: %s", sRef_unparseFull (af)));
8332 llassert (af->info->arrayfetch->arr == current);
8333 ((*predf)(af, loc));
8337 sRef af = sRef_makeArrayFetch (current);
8338 llassert (af->info->arrayfetch->arr == current);
8339 DPRINTF (("Defining: %s", sRef_unparseFull (af)));
8340 ((*predf)(af, loc));
8345 DPRINTF (("Type mismatch: %s / %s",
8347 ctype_unparse (sRef_getType (current))));
8350 } end_sRefSet_realElements;
8352 sRefSet_free (aliases);
8355 inner = s->info->field->rec;
8356 aliases = usymtab_allAliases (inner);
8357 ct = sRef_getType (inner);
8360 sRefSet_realElements (aliases, current)
8362 if (sRef_isValid (current))
8364 current = sRef_updateSref (current);
8366 if (ctype_equal (ct, sRef_getType (current)))
8368 sRef f = sRef_makeField (current, s->info->field->field);
8373 } end_sRefSet_realElements;
8375 sRefSet_free (aliases);
8378 sRef_innerAliasSetComplete (predf, s->info->conj->a, loc);
8379 sRef_innerAliasSetComplete (predf, s->info->conj->b, loc);
8396 sRef_innerAliasSetCompleteParam (void (predf) (sRef, sRef), sRef s, sRef t)
8402 if (!sRef_isValid (s)) return;
8406 ** Type equivalence checking is necessary --- there might be casting.
8413 case SK_UNCONSTRAINED:
8418 inner = s->info->ref;
8419 aliases = usymtab_allAliases (inner);
8420 ct = sRef_getType (inner);
8423 sRefSet_realElements (aliases, current)
8425 if (sRef_isValid (current))
8427 current = sRef_updateSref (current);
8429 if (ctype_equal (ct, sRef_getType (current)))
8431 sRef ptr = sRef_makePointer (current);
8436 } end_sRefSet_realElements;
8438 sRefSet_free (aliases);
8441 inner = s->info->arrayfetch->arr;
8442 aliases = usymtab_allAliases (inner);
8443 ct = sRef_getType (inner);
8445 sRefSet_realElements (aliases, current)
8447 if (sRef_isValid (current))
8449 current = sRef_updateSref (current);
8451 if (ctype_equal (ct, sRef_getType (current)))
8454 if (s->info->arrayfetch->indknown)
8456 sRef af = sRef_makeArrayFetchKnown (current, s->info->arrayfetch->ind);
8462 sRef af = sRef_makeArrayFetch (current);
8468 } end_sRefSet_realElements;
8470 sRefSet_free (aliases);
8473 inner = s->info->field->rec;
8474 aliases = usymtab_allAliases (inner);
8475 ct = sRef_getType (inner);
8478 sRefSet_realElements (aliases, current)
8480 if (sRef_isValid (current))
8482 current = sRef_updateSref (current);
8484 if (ctype_equal (ct, sRef_getType (current)))
8486 sRef f = sRef_makeField (current, s->info->field->field);
8491 } end_sRefSet_realElements;
8493 sRefSet_free (aliases);
8496 sRef_innerAliasSetCompleteParam (predf, s->info->conj->a, t);
8497 sRef_innerAliasSetCompleteParam (predf, s->info->conj->b, t);
8513 static void sRef_combineExKinds (/*@notnull@*/ sRef res, /*@notnull@*/ sRef other)
8515 exkind a1 = sRef_getExKind (res);
8516 exkind a2 = sRef_getExKind (other);
8518 if (a1 == a2 || a2 == XO_UNKNOWN)
8522 else if (a1 == XO_UNKNOWN)
8524 res->expinfo = stateInfo_update (res->expinfo, other->expinfo);
8529 res->expkind = XO_OBSERVER;
8534 ** Currently, this is a very ad hoc implementation, with lots of fixes to
8535 ** make real code work okay. I need to come up with some more general
8536 ** rules or principles here.
8540 sRef_combineAliasKindsError (/*@notnull@*/ sRef res,
8541 /*@notnull@*/ sRef other,
8542 clause cl, fileloc loc)
8544 bool hasError = FALSE;
8545 alkind ares = sRef_getAliasKind (res);
8546 alkind aother = sRef_getAliasKind (other);
8548 sRef_checkMutable (res);
8550 if (alkind_isDependent (ares))
8552 if (aother == AK_KEPT)
8554 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8555 res->aliaskind = AK_KEPT;
8559 if (aother == AK_LOCAL || aother == AK_STATIC
8560 || alkind_isTemp (aother))
8562 DPRINTF (("Setting dependent: %s", sRef_unparseFull (res)));
8563 res->aliaskind = AK_DEPENDENT;
8567 else if (alkind_isDependent (aother))
8569 if (ares == AK_KEPT)
8571 res->aliaskind = AK_KEPT;
8575 if (ares == AK_LOCAL || ares == AK_STATIC || alkind_isTemp (ares))
8577 DPRINTF (("Setting dependent: %s", sRef_unparseFull (res)));
8578 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8579 res->aliaskind = AK_DEPENDENT;
8583 else if ((ares == AK_LOCAL || ares == AK_UNIQUE
8584 || ares == AK_STATIC || alkind_isTemp (ares))
8585 && sRef_isFresh (other))
8588 ** cases like: if (s == NULL) s = malloc...;
8589 ** don't generate errors
8592 if (usymtab_isAltDefinitelyNullDeep (res))
8594 res->aliaskind = ares;
8601 else if ((aother == AK_LOCAL || aother == AK_UNIQUE
8602 || aother == AK_STATIC || alkind_isTemp (aother))
8603 && sRef_isFresh (res))
8606 ** cases like: if (s == NULL) s = malloc...;
8607 ** don't generate errors
8610 if (usymtab_isDefinitelyNullDeep (other))
8612 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8613 res->aliaskind = aother;
8620 else if (ares == AK_NEWREF && aother == AK_REFCOUNTED
8621 && sRef_isConst (other))
8623 res->aliaskind = AK_NEWREF;
8625 else if (aother == AK_NEWREF && ares == AK_REFCOUNTED
8626 && sRef_isConst (res))
8628 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8629 res->aliaskind = AK_NEWREF;
8631 else if (sRef_isLocalVar (res)
8632 && ((ares == AK_KEPT && aother == AK_LOCAL)
8633 || (aother == AK_KEPT && ares == AK_LOCAL)))
8635 res->aliaskind = AK_KEPT;
8644 if (sRef_isThroughArrayFetch (res))
8647 (FLG_BRANCHSTATE, FLG_STRICTBRANCHSTATE,
8649 ("Clauses exit with %q possibly referencing %s storage %s, "
8652 alkind_unparse (aother),
8653 clause_nameTaken (cl),
8654 alkind_unparse (ares),
8655 clause_nameAlternate (cl)),
8658 sRef_showAliasInfo (res);
8659 sRef_showAliasInfo (other);
8660 res->aliaskind = AK_ERROR;
8664 if (ares == AK_KEPT || aother == AK_KEPT)
8666 sRef_maybeKill (res, loc);
8674 message ("Clauses exit with %q referencing %s storage %s, "
8677 alkind_unparse (aother),
8678 clause_nameTaken (cl),
8679 alkind_unparse (ares),
8680 clause_nameAlternate (cl)),
8683 sRef_showAliasInfo (res);
8684 sRef_showAliasInfo (other);
8686 res->aliaskind = AK_ERROR;
8690 res->aliaskind = (sRef_isLocalVar (res) ? AK_LOCAL : AK_UNKNOWN);
8695 sRef_combineAliasKinds (/*@notnull@*/ sRef res, /*@notnull@*/ sRef other,
8696 clause cl, fileloc loc)
8698 alkind ares = sRef_getAliasKind (res);
8699 alkind aother = sRef_getAliasKind (other);
8701 sRef_checkMutable (res);
8703 if (alkind_equal (ares, aother)
8704 || aother == AK_UNKNOWN
8705 || aother == AK_ERROR)
8707 ; /* keep current state */
8709 else if (sRef_isDead (res) || sRef_isDead (other))
8711 /* dead error reported (or storage is dead) */
8712 res ->aliaskind = AK_ERROR;
8714 else if (ares == AK_UNKNOWN || ares == AK_ERROR
8715 || sRef_isStateUndefined (res))
8717 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8718 res->aliaskind = aother;
8720 else if (sRef_isStateUndefined (other))
8724 else if (((ares == AK_UNIQUE || alkind_isTemp (ares))
8725 && aother == AK_LOCAL)
8726 || ((aother == AK_UNIQUE || alkind_isTemp (aother))
8727 && ares == AK_LOCAL))
8729 if (ares != AK_LOCAL)
8731 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8734 res->aliaskind = AK_LOCAL;
8736 else if ((ares == AK_OWNED && aother == AK_FRESH)
8737 || (aother == AK_OWNED && ares == AK_FRESH))
8739 if (ares != AK_FRESH)
8741 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8744 res->aliaskind = AK_FRESH;
8746 else if ((ares == AK_KEEP && aother == AK_FRESH) ||
8747 (aother == AK_KEEP && ares == AK_FRESH))
8749 if (ares != AK_KEEP)
8751 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8754 res->aliaskind = AK_KEEP;
8756 else if ((ares == AK_LOCAL && aother == AK_STACK) ||
8757 (aother == AK_LOCAL && ares == AK_STACK))
8759 if (ares != AK_STACK)
8761 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8764 res->aliaskind = AK_STACK;
8766 else if ((ares == AK_LOCAL
8767 && (aother == AK_OWNED && sRef_isLocalVar (other)))
8768 || (aother == AK_LOCAL
8769 && (ares == AK_OWNED && sRef_isLocalVar (res))))
8771 if (ares != AK_LOCAL)
8773 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8776 res->aliaskind = AK_LOCAL;
8778 else if ((ares == AK_FRESH && alkind_isOnly (aother))
8779 || (aother == AK_FRESH && alkind_isOnly (ares)))
8781 res->aliaskind = AK_FRESH;
8783 else if ((aother == AK_FRESH && sRef_definitelyNull (res))
8784 || (ares == AK_FRESH && sRef_definitelyNull (other)))
8786 if (ares != AK_FRESH)
8788 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8789 res->aliaskind = AK_FRESH;
8792 else if ((sRef_isFresh (res) && sRef_isConst (other))
8793 || (sRef_isFresh (other) && sRef_isConst (res)))
8796 ** for NULL constantants
8800 if (!sRef_isFresh (res))
8802 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8805 res->aliaskind = AK_FRESH;
8807 else if ((alkind_isStatic (aother) && sRef_isConst (res))
8808 || (alkind_isStatic (ares) && sRef_isConst (other)))
8810 if (!alkind_isStatic (ares))
8812 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8813 res->aliaskind = AK_STATIC;
8818 sRef_combineAliasKindsError (res, other, cl, loc);
8822 static void sRef_combineDefState (/*@notnull@*/ sRef res,
8823 /*@notnull@*/ sRef other)
8825 sstate s1 = res->defstate;
8826 sstate s2 = other->defstate;
8829 sRef_checkMutable (res);
8831 if (s1 == s2 || s2 == SS_UNKNOWN)
8835 else if (s1 == SS_UNKNOWN)
8844 if (s2 == SS_DEFINED)
8850 llcontbuglit ("ssfixed: not implemented");
8859 flip = (s2 != SS_DEFINED);
8877 res->definfo = stateInfo_update (res->definfo, other->definfo);
8882 extern /*@notnull@*/ sRef sRef_getConjA (sRef s)
8885 llassert (sRef_isConj (s));
8887 ret = s->info->conj->a;
8888 llassert (ret != NULL);
8892 extern /*@notnull@*/ sRef sRef_getConjB (sRef s)
8895 llassert (sRef_isConj (s));
8897 ret = s->info->conj->b;
8898 llassert (ret != NULL);
8902 extern /*@exposed@*/ sRef sRef_makeArrow (sRef s, /*@dependent@*/ cstring f)
8907 p = sRef_makePointer (s);
8908 ret = sRef_makeField (p, f);
8912 extern /*@exposed@*/ sRef sRef_buildArrow (sRef s, cstring f)
8917 p = sRef_buildPointer (s);
8918 ret = sRef_buildField (p, f);
8923 static /*@null@*/ sinfo sinfo_copy (/*@notnull@*/ sRef s)
8930 ret = (sinfo) dmalloc (sizeof (*ret));
8931 ret->cvar = (cref) dmalloc (sizeof (*ret->cvar));
8932 ret->cvar->lexlevel = s->info->cvar->lexlevel;
8933 ret->cvar->index = s->info->cvar->index;
8937 ret = (sinfo) dmalloc (sizeof (*ret));
8938 ret->paramno = s->info->paramno;
8939 llassert (ret->paramno >= -1);
8943 ret = (sinfo) dmalloc (sizeof (*ret));
8944 ret->arrayfetch = (ainfo) dmalloc (sizeof (*ret->arrayfetch));
8945 ret->arrayfetch->indknown = s->info->arrayfetch->indknown;
8946 ret->arrayfetch->ind = s->info->arrayfetch->ind;
8947 ret->arrayfetch->arr = s->info->arrayfetch->arr; /* sRef_copy (s->info->arrayfetch->arr); */ /*@i32@*/
8951 ret = (sinfo) dmalloc (sizeof (*ret));
8952 ret->field = (fldinfo) dmalloc (sizeof (*ret->field));
8953 ret->field->rec = s->info->field->rec; /* sRef_copy (s->info->field->rec); */ /*@i32@*/
8954 ret->field->field = s->info->field->field;
8958 ret = (sinfo) dmalloc (sizeof (*ret));
8959 ret->object = s->info->object;
8966 ret = (sinfo) dmalloc (sizeof (*ret));
8967 ret->ref = s->info->ref; /* Ref_copy (s->info->ref); */
8971 ret = (sinfo) dmalloc (sizeof (*ret));
8972 ret->conj = (cjinfo) dmalloc (sizeof (*ret->conj));
8973 ret->conj->a = s->info->conj->a; /* sRef_copy (s->info->conj->a); */
8974 ret->conj->b = s->info->conj->b; /* sRef_copy (s->info->conj->b);*/
8977 ret = (sinfo) dmalloc (sizeof (*ret));
8978 ret->spec = s->info->spec;
8980 case SK_UNCONSTRAINED:
8982 ret = (sinfo) dmalloc (sizeof (*ret));
8983 ret->fname = s->info->fname;
8989 llassertprint (s->info == NULL, ("s = %s", sRef_unparse (s)));
8997 static /*@null@*/ sinfo sinfo_fullCopy (/*@notnull@*/ sRef s)
9002 ** Since its a full copy, only storage is assigned
9003 ** to dependent fields.
9010 ret = (sinfo) dmalloc (sizeof (*ret));
9011 ret->cvar = (cref) dmalloc (sizeof (*ret->cvar));
9012 ret->cvar->lexlevel = s->info->cvar->lexlevel;
9013 ret->cvar->index = s->info->cvar->index;
9017 ret = (sinfo) dmalloc (sizeof (*ret));
9018 ret->paramno = s->info->paramno;
9019 llassert (ret->paramno >= -1);
9023 ret = (sinfo) dmalloc (sizeof (*ret));
9024 ret->arrayfetch = (ainfo) dmalloc (sizeof (*ret->arrayfetch));
9025 ret->arrayfetch->indknown = s->info->arrayfetch->indknown;
9026 ret->arrayfetch->ind = s->info->arrayfetch->ind;
9027 ret->arrayfetch->arr = sRef_saveCopy (s->info->arrayfetch->arr);
9031 ret = (sinfo) dmalloc (sizeof (*ret));
9032 ret->field = (fldinfo) dmalloc (sizeof (*ret->field));
9033 ret->field->rec = sRef_saveCopy (s->info->field->rec);
9034 ret->field->field = s->info->field->field;
9038 ret = (sinfo) dmalloc (sizeof (*ret));
9039 ret->object = s->info->object;
9046 ret = (sinfo) dmalloc (sizeof (*ret));
9047 ret->ref = sRef_saveCopy (s->info->ref);
9051 ret = (sinfo) dmalloc (sizeof (*ret));
9052 ret->conj = (cjinfo) dmalloc (sizeof (*ret->conj));
9053 ret->conj->a = sRef_saveCopy (s->info->conj->a);
9054 ret->conj->b = sRef_saveCopy (s->info->conj->b);
9057 ret = (sinfo) dmalloc (sizeof (*ret));
9058 ret->spec = s->info->spec;
9061 case SK_UNCONSTRAINED:
9062 ret = (sinfo) dmalloc (sizeof (*ret));
9063 ret->fname = s->info->fname;
9069 llassert (s->info == NULL);
9079 sinfo_update (/*@notnull@*/ /*@exposed@*/ sRef res,
9080 /*@notnull@*/ /*@exposed@*/ sRef other)
9082 llassert (res->kind == other->kind);
9087 res->info->cvar->lexlevel = other->info->cvar->lexlevel;
9088 res->info->cvar->index = other->info->cvar->index;
9092 res->info->paramno = other->info->paramno;
9093 llassert (res->info->paramno >= -1);
9097 res->info->arrayfetch->indknown = other->info->arrayfetch->indknown;
9098 res->info->arrayfetch->ind = other->info->arrayfetch->ind;
9099 res->info->arrayfetch->arr = other->info->arrayfetch->arr;
9103 res->info->field->rec = other->info->field->rec;
9104 res->info->field->field = other->info->field->field;
9108 res->info->object = other->info->object;
9115 res->info->ref = other->info->ref;
9119 res->info->conj->a = other->info->conj->a;
9120 res->info->conj->b = other->info->conj->b;
9124 res->info->spec = other->info->spec;
9128 case SK_UNCONSTRAINED:
9129 res->info->fname = other->info->fname;
9136 llassert (res->info == NULL);
9141 static void sinfo_free (/*@special@*/ /*@temp@*/ /*@notnull@*/ sRef s)
9142 /*@uses s->kind, s->info@*/
9143 /*@releases s->info@*/
9148 DPRINTF (("Free sinfo: [%p]", s->info->cvar));
9149 sfree (s->info->cvar);
9156 DPRINTF (("Free sinfo: [%p]", s->info->arrayfetch));
9157 sfree (s->info->arrayfetch);
9161 DPRINTF (("Free sinfo: [%p]", s->info->field));
9162 sfree (s->info->field);
9171 case SK_EXTERNAL: /*@i32 is copy now! */
9175 DPRINTF (("Free sinfo: [%p]", s->info->conj));
9176 sfree (s->info->conj);
9179 case SK_UNCONSTRAINED:
9189 if (s->info != NULL) {
9190 DPRINTF (("Free sinfo: [%p]", s->info));
9196 bool sRef_isNSLocalVar (sRef s)
9198 if (sRef_isLocalVar (s))
9200 uentry ue = sRef_getUentry (s);
9202 return (!uentry_isStatic (ue));
9210 bool sRef_isLocalVar (sRef s)
9212 if (sRef_isValid(s))
9214 return (s->kind == SK_CVAR
9215 && (s->info->cvar->lexlevel > fileScope));
9221 bool sRef_isRealLocalVar (sRef s)
9223 if (sRef_isValid(s))
9225 if (s->kind == SK_CVAR)
9227 if (s->info->cvar->lexlevel == functionScope)
9229 uentry ue = sRef_getUentry (s);
9231 if (uentry_isAnyParam (ue)
9232 || uentry_isRefParam (ue))
9243 return (s->info->cvar->lexlevel > functionScope);
9251 bool sRef_isLocalParamVar (sRef s)
9253 if (sRef_isValid(s))
9255 return (s->kind == SK_PARAM
9256 || (s->kind == SK_CVAR
9257 && (s->info->cvar->lexlevel > fileScope)));
9263 static speckind speckind_fromInt (int i)
9266 llassert (i >= SR_NOTHING && i <= SR_SYSTEM);
9269 return ((speckind) i);
9273 static void sRef_updateNullState (sRef res, sRef other)
9276 res->nullstate = other->nullstate;
9277 res->nullinfo = stateInfo_update (res->nullinfo, other->nullinfo);
9280 void sRef_combineNullState (/*@notnull@*/ sRef res, /*@notnull@*/ sRef other)
9282 nstate n1 = sRef_getNullState (res);
9283 nstate n2 = sRef_getNullState (other);
9287 if (n1 == n2 || n2 == NS_UNKNOWN)
9293 /* note: n2 is not unknown or defnull */
9297 case NS_ERROR: nn = NS_ERROR; break;
9298 case NS_UNKNOWN: flip = TRUE; nn = n2; break;
9299 case NS_POSNULL: break;
9300 case NS_DEFNULL: nn = NS_POSNULL; break;
9301 case NS_RELNULL: break;
9303 if (n2 == NS_MNOTNULL)
9314 if (n2 == NS_NOTNULL)
9333 res->nullinfo = stateInfo_update (res->nullinfo, other->nullinfo);
9336 res->nullstate = nn;
9339 cstring sRef_nullMessage (sRef s)
9341 llassert (sRef_isValid (s));
9343 switch (sRef_getNullState (s))
9347 return (cstring_makeLiteralTemp ("null"));
9349 return (cstring_makeLiteralTemp ("possibly null"));
9354 /*@observer@*/ cstring sRef_ntMessage (sRef s)
9356 llassert (sRef_isValid (s));
9358 switch (s->nullstate)
9362 return (cstring_makeLiteralTemp ("not nullterminated"));
9364 return (cstring_makeLiteralTemp ("possibly non-nullterminated"));
9371 sRef sRef_fixResultType (/*@returned@*/ sRef s, ctype typ, uentry ue)
9373 sRef tmp = sRef_undefined;
9376 llassert (sRef_isValid (s));
9387 tmp = sRef_fixResultType (s->info->arrayfetch->arr, typ, ue);
9389 ct = ctype_realType (sRef_getType (tmp));
9392 if (ctype_isKnown (ct))
9394 if (ctype_isAP (ct))
9403 ("Special clause indexes non-array (%t): *%q",
9404 ct, sRef_unparse (s->info->arrayfetch->arr)),
9405 uentry_whereLast (ue));
9409 tmp = sRef_fixResultType (s->info->arrayfetch->arr, typ, ue);
9411 if (s->info->arrayfetch->indknown)
9413 ret = sRef_makeArrayFetchKnown (tmp, s->info->arrayfetch->ind);
9417 ret = sRef_makeArrayFetch (tmp);
9423 sRef rec = sRef_fixResultType (s->info->field->rec, typ, ue);
9424 ctype ct = ctype_realType (sRef_getType (rec));
9426 if (ctype_isKnown (ct))
9428 if (ctype_isSU (ct))
9430 if (uentry_isValid (uentryList_lookupField (ctype_getFields (ct),
9431 s->info->field->field)))
9440 ("Special clause accesses non-existent field of result: %q.%s",
9441 sRef_unparse (rec), s->info->field->field),
9442 uentry_whereLast (ue));
9450 ("Special clause accesses field of non-struct or union result (%t): %q.%s",
9451 ct, sRef_unparse (rec), s->info->field->field),
9452 uentry_whereLast (ue));
9456 ret = sRef_makeField (tmp, s->info->field->field);
9462 tmp = sRef_fixResultType (s->info->ref, typ, ue);
9464 ct = ctype_realType (sRef_getType (tmp));
9466 if (ctype_isKnown (ct))
9468 if (ctype_isAP (ct))
9477 ("Special clause dereferences non-pointer (%t): *%q",
9478 ct, sRef_unparse (s->info->ref)),
9479 uentry_whereLast (ue));
9483 ret = sRef_makePointer (tmp);
9490 ("Special clause uses & operator (not allowed): &%q", sRef_unparse (s->info->ref)),
9491 uentry_whereLast (ue));
9500 bool sRef_isOnly (sRef s)
9502 return (sRef_isValid(s) && alkind_isOnly (s->aliaskind));
9505 bool sRef_isDependent (sRef s)
9507 return (sRef_isValid(s) && alkind_isDependent (s->aliaskind));
9510 bool sRef_isOwned (sRef s)
9512 return (sRef_isValid (s) && (s->aliaskind == AK_OWNED));
9515 bool sRef_isKeep (sRef s)
9517 return (sRef_isValid (s) && (s->aliaskind == AK_KEEP));
9520 bool sRef_isTemp (sRef s)
9522 return (sRef_isValid (s) && alkind_isTemp (s->aliaskind));
9525 bool sRef_isLocalState (sRef s)
9527 return (sRef_isValid (s) && (s->aliaskind == AK_LOCAL));
9530 bool sRef_isUnique (sRef s)
9532 return (sRef_isValid (s) && (s->aliaskind == AK_UNIQUE));
9535 bool sRef_isShared (sRef s)
9537 return (sRef_isValid (s) && (s->aliaskind == AK_SHARED));
9540 bool sRef_isExposed (sRef s)
9542 return (sRef_isValid (s) && (s->expkind == XO_EXPOSED));
9545 bool sRef_isObserver (sRef s)
9547 return (sRef_isValid (s) && (s->expkind == XO_OBSERVER));
9550 bool sRef_isFresh (sRef s)
9552 return (sRef_isValid (s) && (s->aliaskind == AK_FRESH));
9555 bool sRef_isDefinitelyNull (sRef s)
9557 return (sRef_isValid (s) && (sRef_getNullState (s) == NS_DEFNULL
9558 || sRef_getNullState (s) == NS_CONSTNULL));
9561 bool sRef_isAllocated (sRef s)
9563 return (sRef_isValid (s) && (s->defstate == SS_ALLOCATED));
9566 bool sRef_isStack (sRef s)
9568 return (sRef_isValid (s) && (s->aliaskind == AK_STACK));
9571 bool sRef_isNotNull (sRef s)
9573 return (sRef_isValid(s) && (sRef_getNullState (s) == NS_MNOTNULL
9574 || sRef_getNullState (s) == NS_NOTNULL));
9577 alkind sRef_getAliasKind (sRef s)
9579 if (sRef_isValid(s)) {
9580 llassert (alkind_isValid (s->aliaskind));
9581 return s->aliaskind;
9587 nstate sRef_getNullState (sRef s)
9589 if (sRef_isValid (s)) {
9590 llassert (nstate_isValid (s->nullstate));
9591 return s->nullstate;
9597 void sRef_reflectAnnotation (sRef s, annotationInfo a, fileloc loc)
9599 if (sRef_isValid (s))
9601 if (!valueTable_isDefined (s->state))
9603 s->state = valueTable_create (1);
9604 valueTable_insert (s->state,
9605 cstring_copy (metaStateInfo_getName (annotationInfo_getState (a))),
9606 stateValue_create (annotationInfo_getValue (a), stateInfo_makeLoc (loc)));
9610 DPRINTF (("reflect loc: %s", fileloc_unparse (loc)));
9613 metaStateInfo_getName (annotationInfo_getState (a)),
9614 stateValue_create (annotationInfo_getValue (a), stateInfo_makeLoc (loc)));
9615 DPRINTF (("state info: %s", stateInfo_unparse (stateInfo_makeLoc (loc))));
9616 DPRINTF (("sref: %s", sRef_unparse (s)));
9617 DPRINTF (("sref: %s", sRef_unparseFull (s)));
9622 void sRef_setMetaStateValueComplete (sRef s, cstring key, int value, fileloc loc)
9624 sRefSet aliases = usymtab_allAliases (s);
9626 sRef_setMetaStateValue (s, key, value, loc);
9628 sRefSet_realElements (aliases, current)
9630 if (sRef_isValid (current))
9632 current = sRef_updateSref (current);
9633 sRef_setMetaStateValue (current, key, value, loc);
9635 } end_sRefSet_realElements ;
9637 sRefSet_free (aliases);
9640 void sRef_setMetaStateValue (sRef s, cstring key, int value, fileloc loc)
9642 sRef_checkMutable (s);
9644 if (sRef_isValid (s))
9646 if (!valueTable_isDefined (s->state))
9648 DPRINTF (("inserting state: %s: %s %d", sRef_unparse (s), key, value));
9649 s->state = valueTable_create (1);
9650 valueTable_insert (s->state, cstring_copy (key),
9651 stateValue_create (value, stateInfo_makeLoc (loc)));
9655 DPRINTF (("Updating state: %s: %s %d / %s", sRef_unparse (s), key, value,
9656 fileloc_unparse (loc)));
9657 if (valueTable_contains (s->state, key))
9660 (s->state, key, stateValue_create (value, stateInfo_makeLoc (loc)));
9665 (s->state, cstring_copy (key), stateValue_create (value, stateInfo_makeLoc (loc)));
9668 DPRINTF (("After: %s", sRef_unparseFull (s)));
9673 bool sRef_checkMetaStateValue (sRef s, cstring key, int value)
9675 if (sRef_isValid (s))
9677 if (valueTable_isDefined (s->state))
9681 DPRINTF (("check state: %s: %s %d", sRef_unparse (s), key, value));
9683 val = valueTable_lookup (s->state, key);
9684 llassert (stateValue_isDefined (val));
9685 return (stateValue_isError (val)
9686 || stateValue_getValue (val) == value);
9699 /*@observer@*/ stateValue sRef_getMetaStateValue (sRef s, cstring key)
9701 if (sRef_isValid (s))
9703 if (valueTable_isDefined (s->state))
9707 val = valueTable_lookup (s->state, key);
9708 /* Okay if its not defined, just returns stateValue_undefined */
9713 return stateValue_undefined;
9718 return stateValue_undefined;
9722 /*@observer@*/ valueTable sRef_getValueTable (sRef s)
9724 DPRINTF (("Get value table: %s", sRef_unparse (s)));
9726 if (sRef_isValid (s))
9728 llassert (sRef_isValid (s));
9729 DPRINTF (("Value table: %s", valueTable_unparse (s->state)));
9734 DPRINTF (("No value table!"));
9735 return valueTable_undefined;
9739 bool sRef_makeStateSpecial (sRef s)
9742 ** Default defined state can be made special.
9745 llassert (sRef_isValid (s)); /*@i523 why doesn't null-checking work!??? */
9747 if (s->defstate == SS_UNKNOWN || s->defstate == SS_DEFINED || s->defstate == SS_SPECIAL)
9749 s->aliaskind = AK_IMPTEMP;
9750 s->defstate = SS_SPECIAL;
9751 DPRINTF (("Made special: %s", sRef_unparseFull (s)));
9756 s->aliaskind = AK_IMPTEMP;
9757 s->defstate = SS_SPECIAL;
9762 void sRef_markImmutable (sRef s)
9764 if (sRef_isValid (s))
9766 DPRINTF (("Mark immutable: %s", sRef_unparseFull (s)));
9771 bool sRef_definitelyNullContext (sRef s)
9773 return (sRef_definitelyNull (s)
9774 || usymtab_isDefinitelyNullDeep (s));
9777 bool sRef_definitelyNullAltContext (sRef s)
9779 return (sRef_definitelyNull (s)
9780 || usymtab_isAltDefinitelyNullDeep (s));
9784 /* start modifications */
9785 struct s_bbufinfo sRef_getNullTerminatedState (sRef p_s) {
9786 struct s_bbufinfo BUFSTATE_UNKNOWN;
9787 BUFSTATE_UNKNOWN.bufstate = BB_NOTNULLTERMINATED;
9788 BUFSTATE_UNKNOWN.size = 0;
9789 BUFSTATE_UNKNOWN.len = 0;
9791 if (sRef_isValid(p_s))
9792 return p_s->bufinfo;
9793 return BUFSTATE_UNKNOWN;
9796 void sRef_setNullTerminatedState(sRef p_s) {
9797 if(sRef_isValid (p_s)) {
9798 p_s->bufinfo.bufstate = BB_NULLTERMINATED;
9800 llfatalbug( message("sRef_setNT passed a invalid sRef\n"));
9805 void sRef_setPossiblyNullTerminatedState(sRef p_s) {
9806 if( sRef_isValid (p_s)) {
9807 p_s->bufinfo.bufstate = BB_POSSIBLYNULLTERMINATED;
9809 llfatalbug( message("sRef_setPossNT passed a invalid sRef\n"));
9813 void sRef_setNotNullTerminatedState(sRef p_s) {
9814 if( sRef_isValid (p_s)) {
9815 p_s->bufinfo.bufstate = BB_NOTNULLTERMINATED;
9817 llfatalbug( message("sRef_unsetNT passed a invalid sRef\n"));
9821 void sRef_setLen(sRef p_s, int len) {
9822 if( sRef_isValid (p_s) && sRef_isNullTerminated(p_s)) {
9823 p_s->bufinfo.len = len;
9825 llfatalbug( message("sRef_setLen passed a invalid sRef\n"));
9830 void sRef_setSize(sRef p_s, int size) {
9831 if( sRef_isValid(p_s)) {
9832 p_s->bufinfo.size = size;
9834 llfatalbug( message("sRef_setSize passed a invalid sRef\n"));
9838 void sRef_resetLen(sRef p_s) {
9839 if (sRef_isValid (p_s)) {
9840 p_s->bufinfo.len = 0;
9842 llfatalbug (message ("sRef_setLen passed an invalid sRef\n"));
9846 /*drl7x 11/28/2000 */
9848 bool sRef_isFixedArray (sRef p_s) /*@*/ {
9850 c = sRef_getType (p_s);
9851 return ( ctype_isFixedArray (c) );
9854 long int sRef_getArraySize (sRef p_s) /*@*/ {
9856 llassert (sRef_isFixedArray(p_s) );
9857 DPRINTF (( message ("sRef_getArraySize getting array size for %s", sRef_unparse(p_s) ) ));
9859 c = sRef_getType (p_s);
9861 return (ctype_getArraySize (c) );