2 ** Splint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2002 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 splint: info@splint.org
21 ** To report a bug: splint-bug@splint.org
22 ** For more information: http://www.splint.org
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 "splintMacros.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) /*@*/ ;
65 static void sRef_setNullStateN (sRef p_s, nstate p_n) /*@modifies p_s@*/ ;
67 static int sRef_depth (sRef p_s) /*@*/ ;
70 sRef_innerAliasSetComplete (void (p_predf) (sRef, fileloc), sRef p_s,
75 sRef_innerAliasSetCompleteParam (void (p_predf) (sRef, sRef), sRef p_s, sRef p_t)
78 static speckind speckind_fromInt (int p_i);
79 static bool sRef_equivalent (sRef p_s1, sRef p_s2);
80 static bool sRef_isDeepUnionField (sRef p_s);
81 static void sRef_addDeriv (/*@notnull@*/ sRef p_s, /*@notnull@*/ /*@exposed@*/ sRef p_t);
82 static bool sRef_checkModify (sRef p_s, sRefSet p_sl) /*@*/ ;
85 ** If s is definitely null, it has no memory state.
88 static void sRef_resetAliasKind (/*@notnull@*/ sRef s) /*@modifies s->aliaskind@*/
90 if (s->nullstate == NS_DEFNULL)
92 /* s->aliaskind = AK_ERROR; */
97 extern void sRef_checkCompletelyReasonable (sRef s) /*@*/
99 DPRINTF (("Check sRef: [%p] %s / %s", s, sRef_unparse (s),
100 sRefSet_unparse (sRef_derivedFields (s))));
102 if (sRef_isReasonable (s))
104 sRefSet_elements (s->deriv, el)
107 sRef_checkCompletelyReasonable (el);
108 } end_sRefSet_elements ;
113 /*@falsewhennull@*/ bool sRef_isReasonable (sRef s) /*@*/
115 if (sRef_isValid (s))
118 if (!bool_isReasonable (s->safe)
119 || !bool_isReasonable (s->modified)
120 || !bool_isReasonable (s->immut))
122 llcontbug (message ("Unreasonable sRef [%p]", s));
126 if (!sstate_isValid (s->defstate))
128 llcontbug (message ("Unreasonable sRef [%p]", s));
132 if (!nstate_isValid (s->nullstate))
134 llcontbug (message ("Unreasonable sRef [%p]", s));
138 if (!alkind_isValid (s->aliaskind)
139 || !alkind_isValid (s->oaliaskind))
141 llcontbug (message ("Unreasonable sRef [%p]", s));
145 if (!exkind_isValid (s->expkind)
146 || !exkind_isValid (s->oexpkind))
148 llcontbug (message ("Unreasonable sRef [%p]", s));
159 static /*@nullwhentrue@*/ bool sRef_isUnreasonable (sRef s) /*@*/
161 return (!sRef_isReasonable (s));
164 static void sRef_checkMutable (/*@unused@*/ sRef s)
166 if (sRef_isReasonable (s) && s->immut)
168 llcontbug (message ("Modification to sRef marked immutable: %q",
169 sRef_unparseFull (s)));
173 static bool skind_isSimple (skind sk)
177 case SK_PARAM: case SK_CVAR: case SK_CONST:
178 case SK_OBJECT: case SK_UNKNOWN: case SK_NEW:
185 static void sinfo_free (/*@special@*/ /*@temp@*/ /*@notnull@*/ sRef p_s)
186 /*@uses p_s->kind, p_s->info@*/
187 /*@releases p_s->info@*/ ;
189 static /*@null@*/ sinfo sinfo_copy (/*@notnull@*/ sRef p_s) /*@*/ ;
190 static void sRef_setPartsFromUentry (sRef p_s, uentry p_ue)
192 static bool checkDeadState (/*@notnull@*/ sRef p_el, bool p_tbranch, fileloc p_loc);
193 static /*@dependent@*/ sRef sRef_constructPointerAux (/*@notnull@*/ /*@exposed@*/ sRef p_t) /*@*/ ;
196 sRef_combineExKinds (/*@notnull@*/ sRef p_res, /*@notnull@*/ sRef p_other)
197 /*@modifies p_res@*/ ;
200 sRef_combineAliasKinds (/*@notnull@*/ sRef p_res, /*@notnull@*/ sRef p_other,
201 clause p_cl, fileloc p_loc)
202 /*@modifies p_res@*/ ;
205 sRef_combineNullState (/*@notnull@*/ sRef p_res, /*@notnull@*/ sRef p_other)
206 /*@modifies p_res@*/ ;
209 sRef_combineDefState (/*@notnull@*/ sRef p_res, /*@notnull@*/ sRef p_other)
210 /*@modifies p_res@*/ ;
212 static void sRef_setStateFromAbstractUentry (sRef p_s, uentry p_ue)
216 sinfo_update (/*@notnull@*/ /*@exposed@*/ sRef p_res,
217 /*@notnull@*/ /*@exposed@*/ sRef p_other);
218 static void sRef_setDefinedAux (sRef p_s, fileloc p_loc, bool p_clear)
220 static void sRef_setDefinedNoClear (sRef p_s, fileloc p_loc)
222 static void sRef_setStateAux (sRef p_s, sstate p_ss, fileloc p_loc)
225 static /*@exposed@*/ sRef
226 sRef_buildNCField (/*@exposed@*/ sRef p_rec, /*@exposed@*/ cstring p_f);
229 sRef_mergeStateAux (/*@notnull@*/ sRef p_res, /*@notnull@*/ sRef p_other,
230 clause p_cl, bool p_opt, fileloc p_loc,
232 /*@modifies p_res, p_other@*/ ;
234 static /*@null@*/ sinfo sinfo_fullCopy (/*@notnull@*/ sRef p_s);
235 static bool sRef_doModify (sRef p_s, sRefSet p_sl) /*@modifies p_s@*/ ;
236 static bool sRef_doModifyVal (sRef p_s, sRefSet p_sl) /*@modifies p_s@*/;
237 static bool sRef_checkModifyVal (sRef p_s, sRefSet p_sl) /*@*/ ;
239 static /*@only@*/ sRefSet
240 sRef_mergeDerivs (/*@only@*/ sRefSet p_res, sRefSet p_other,
241 bool p_opt, clause p_cl, fileloc p_loc);
243 static /*@only@*/ sRefSet
244 sRef_mergeUnionDerivs (/*@only@*/ sRefSet p_res,
245 /*@exposed@*/ sRefSet p_other,
246 bool p_opt, clause p_cl, fileloc p_loc);
248 static /*@only@*/ sRefSet
249 sRef_mergePdefinedDerivs (/*@only@*/ sRefSet p_res, sRefSet p_other, bool p_opt,
250 clause p_cl, fileloc p_loc);
252 static /*@only@*/ cstring sRef_unparseWithArgs (sRef p_s, uentryList p_args);
253 static /*@only@*/ cstring sRef_unparseNoArgs (sRef p_s);
255 static /*@exposed@*/ sRef sRef_findDerivedPointer (sRef p_s);
256 static /*@exposed@*/ sRef sRef_findDerivedArrayFetch (/*@notnull@*/ sRef, bool, int, bool) ;
257 static /*@exposed@*/ sRef sRef_findDerivedField (/*@notnull@*/ sRef p_rec, cstring p_f);
258 static /*@exposed@*/ sRef
259 sRef_getDeriv (/*@notnull@*/ /*@returned@*/ sRef p_set, sRef p_guide);
261 static bool inFunction = FALSE;
262 static /*@only@*/ sRefTable allRefs;
264 /* # define DEBUGREFS */
268 static totnsrefs = 0;
269 static maxnsrefs = 0;
270 static ntotrefers = 0;
274 static /*@checked@*/ bool protectDerivs = FALSE;
277 ** Result of sRef_alloc is dependent since allRefs may
278 ** reference it. It is only if !inFunction.
281 static /*@dependent@*/ /*@out@*/ /*@notnull@*/ sRef
284 sRef s = (sRef) dmalloc (sizeof (*s));
288 DPRINTF (("Alloc sref: [%p]", s));
292 allRefs = sRefTable_add (allRefs, s);
297 DPRINTF (("Not in function!"));
303 if (nsrefs >= maxnsrefs)
312 /*@-mustfree@*/ /*@-freshtrans@*/
314 /*@=mustfree@*/ /*@=freshtrans@*/
317 static void sRef_checkValidAux (sRef s, sRefSet checkedsofar)
321 if (!sRef_isReasonable (s)) return;
323 if (sRefSet_containsSameObject (checkedsofar, s))
329 checkedsofar = sRefSet_insert (checkedsofar, s);
330 /*@=temptrans@*/ /* checksofar will be destroyed before checkValid returns */
334 case SK_UNCONSTRAINED:
335 llassert (cstring_length (s->info->fname) < 100);
339 llassert (s->info->cvar->lexlevel >= 0);
340 /* llassert (s->info->cvar->lexlevel <= usymtab_getCurrentDepth ()); */
344 llassert (s->info->paramno >= -1);
345 llassert (s->info->paramno <= 50); /*@i32 bogus...*/
349 sRef_checkValidAux (s->info->arrayfetch->arr, checkedsofar);
353 sRef_checkValidAux (s->info->field->rec, checkedsofar);
354 llassert (cstring_length (s->info->field->field) < 100);
358 sRef_checkValidAux (s->info->ref, checkedsofar);
362 sRef_checkValidAux (s->info->ref, checkedsofar);
366 /* check ctype s->info->object */
370 sRef_checkValidAux (s->info->conj->a, checkedsofar);
371 sRef_checkValidAux (s->info->conj->b, checkedsofar);
375 llassert (cstring_length (s->info->fname) < 100);
379 sRef_checkValidAux (s->info->ref, checkedsofar);
383 sRef_checkValidAux (s->info->ref, checkedsofar);
389 /* check ctyp s->type */
393 llassert (s->info->spec == SR_NOTHING
394 || s->info->spec == SR_INTERNAL
395 || s->info->spec == SR_SPECSTATE
396 || s->info->spec == SR_SYSTEM);
406 sRefSet_elements (s->deriv, el)
408 sRef_checkValidAux (el, checkedsofar);
409 } end_sRefSet_elements ;
412 void sRef_checkValid (/*@unused@*/ sRef s)
416 sRefSet checkedsofar = sRefSet_new ();
417 sRef_checkValidAux (s, checkedsofar);
421 static /*@dependent@*/ /*@notnull@*/ /*@special@*/ sRef
424 /*@ensures isnull result->aliasinfo, result->definfo,
425 result->expinfo, result->info, result->deriv, result->state@*/
427 sRef s = sRef_alloc ();
429 s->kind = SK_UNKNOWN;
433 s->val = multiVal_undefined;
435 s->type = ctype_unknown;
436 s->defstate = SS_UNKNOWN;
438 /* start modifications */
439 s->bufinfo.bufstate = BB_NOTNULLTERMINATED;
440 s->bufinfo.size = -1; /*@i24 unknown@*/
441 s->bufinfo.len = -1; /*@i24 unknown@*/
442 /* end modifications */
444 s->aliaskind = AK_UNKNOWN;
445 s->oaliaskind = AK_UNKNOWN;
447 s->nullstate = NS_UNKNOWN;
449 s->expkind = XO_UNKNOWN;
450 s->oexpkind = XO_UNKNOWN;
452 s->aliasinfo = stateInfo_undefined;
453 s->definfo = stateInfo_undefined;
454 s->nullinfo = stateInfo_undefined;
455 s->expinfo = stateInfo_undefined;
458 s->deriv = sRefSet_undefined;
460 s->state = valueTable_undefined;
465 static /*@dependent@*/ /*@notnull@*/ /*@special@*/ sRef
468 /*@ensures isnull result->aliasinfo, result->definfo,
469 result->expinfo, result->info, result->deriv@*/
471 sRef res = sRef_new ();
473 res->state = valueTable_undefined;
478 void sRef_protectDerivs (void) /*@modifies protectDerivs@*/
480 llassert (!protectDerivs);
481 protectDerivs = TRUE;
484 void sRef_clearProtectDerivs (void) /*@modifies protectDerivs@*/
486 llassert (protectDerivs);
487 protectDerivs = FALSE;
491 ** hmmm...here be kind of a hack. This function mysteriously appeared
492 ** in my code, but I'm sure I didn't write it.
496 sRef_isRecursiveField (sRef s)
498 if (sRef_isField (s))
500 if (sRef_depth (s) > 13)
505 fieldname = sRef_getField (s);
506 base = sRef_getBase (s);
508 while (sRef_isReasonable (base))
510 if (sRef_isField (base))
512 if (cstring_equal (fieldname, sRef_getField (base)))
518 base = sRef_getBaseSafe (base);
527 sRef_addDeriv (/*@notnull@*/ sRef s, /*@notnull@*/ /*@exposed@*/ sRef t)
529 if (!context_inProtectVars ()
531 && sRef_isReasonable (s)
532 && sRef_isReasonable (t)
533 && !sRef_isConst (s))
535 int sd = sRef_depth (s);
536 int td = sRef_depth (t);
543 /* This sometimes fails: (evans 2001-07-12)
544 if (sRef_isArrayFetch (t))
546 DPRINTF (("Derived fetch: %s / %s / %s",
547 sRef_unparseFull (s), sRef_unparseFull (t),
548 sRef_unparseFull (t->info->arrayfetch->arr)));
549 llassert (t->info->arrayfetch->arr == s);
553 if (sRef_isFileOrGlobalScope (s))
555 if (context_inFunctionLike ()
556 && ctype_isKnown (sRef_getType (s))
557 && !ctype_isFunction (sRef_getType (s)))
559 globSet g = context_getUsedGlobs ();
561 if (!globSet_member (g, s))
564 ** don't report as a bug
568 (message ("sRef_addDeriv: global variable not in used "
569 "globs: %q / %s / %q",
571 ctype_unparse (sRef_getType (s)),
572 sRefSet_unparse (s->deriv)));
577 DPRINTF (("Add deriv: [%p] %s / [%p] %s",
579 t, sRef_unparse (t)));
581 s->deriv = sRefSet_insert (s->deriv, t);
587 DPRINTF (("Add deriv: [%p] %s / [%p] %s",
589 t, sRef_unparse (t)));
591 s->deriv = sRefSet_insert (s->deriv, t);
597 sRef_deepPred (bool (predf) (sRef), sRef s)
599 if (sRef_isReasonable (s))
601 if ((*predf)(s)) return TRUE;
606 return (sRef_deepPred (predf, s->info->ref));
608 return (sRef_deepPred (predf, s->info->arrayfetch->arr));
610 return (sRef_deepPred (predf, s->info->field->rec));
612 return (sRef_deepPred (predf, s->info->conj->a)
613 || sRef_deepPred (predf, s->info->conj->b));
622 bool sRef_modInFunction (void)
627 void sRef_setStateFromType (sRef s, ctype ct)
629 if (sRef_isReasonable (s))
631 if (ctype_isUser (ct))
633 DPRINTF (("Here we are: %s", sRef_unparseFull (s)));
634 sRef_setStateFromUentry
635 (s, usymtab_getTypeEntry (ctype_typeId (ct)));
637 else if (ctype_isAbstract (ct))
639 DPRINTF (("Here we are: %s", sRef_unparseFull (s)));
640 sRef_setStateFromAbstractUentry
641 (s, usymtab_getTypeEntry (ctype_typeId (ct)));
645 ; /* not a user type */
650 static void sRef_setTypeState (sRef s)
652 if (sRef_isReasonable (s))
654 sRef_setStateFromType (s, s->type);
659 sRef_hasAliasInfoLoc (sRef s)
661 return (sRef_isReasonable (s) && (s->aliasinfo != NULL)
662 && (fileloc_isDefined (s->aliasinfo->loc)));
665 static /*@falsewhennull@*/ bool
666 sRef_hasStateInfoLoc (sRef s)
668 return (sRef_isReasonable (s) && (s->definfo != NULL)
669 && (fileloc_isDefined (s->definfo->loc)));
672 static /*@falsewhennull@*/ bool
673 sRef_hasExpInfoLoc (sRef s)
675 return (sRef_isReasonable (s)
676 && (s->expinfo != NULL) && (fileloc_isDefined (s->expinfo->loc)));
680 static /*@observer@*/ /*@unused@*/ stateInfo sRef_getInfo (sRef s, cstring key)
684 if (!sRef_isReasonable (s)) {
685 return stateInfo_undefined;
688 sv = valueTable_lookup (s->state, key);
690 if (stateValue_isDefined (sv))
692 return stateValue_getInfo (sv);
695 return stateInfo_undefined;
700 sRef_hasNullInfoLoc (sRef s)
702 return (sRef_isReasonable (s) && s->nullinfo != NULL
703 && (fileloc_isDefined (s->nullinfo->loc)));
707 sRef_hasAliasInfoRef (sRef s)
709 return (sRef_isReasonable (s) && (s->aliasinfo != NULL)
710 && (sRef_isReasonable (s->aliasinfo->ref)));
713 static /*@observer@*/ fileloc
714 sRef_getAliasInfoLoc (/*@exposed@*/ sRef s)
716 llassert (sRef_isReasonable (s) && s->aliasinfo != NULL
717 && (fileloc_isDefined (s->aliasinfo->loc)));
718 return (s->aliasinfo->loc);
721 static /*@observer@*/ fileloc
722 sRef_getStateInfoLoc (/*@exposed@*/ sRef s)
724 llassert (sRef_isReasonable (s) && s->definfo != NULL
725 && (fileloc_isDefined (s->definfo->loc)));
726 return (s->definfo->loc);
729 static /*@observer@*/ fileloc
730 sRef_getExpInfoLoc (/*@exposed@*/ sRef s)
732 llassert (sRef_isReasonable (s) && s->expinfo != NULL
733 && (fileloc_isDefined (s->expinfo->loc)));
734 return (s->expinfo->loc);
737 static /*@observer@*/ fileloc
738 sRef_getNullInfoLoc (/*@exposed@*/ sRef s)
740 llassert (sRef_isReasonable (s) && s->nullinfo != NULL
741 && (fileloc_isDefined (s->nullinfo->loc)));
742 return (s->nullinfo->loc);
746 sRef_getAliasInfoRef (/*@temp@*/ sRef s)
748 llassert (sRef_isReasonable (s) && s->aliasinfo != NULL);
749 return (s->aliasinfo->ref);
752 bool sRef_inGlobalScope ()
758 ** This function should be called before new sRefs are created
759 ** somewhere where they will have a lifetime greater than the
760 ** current function scope.
763 void sRef_setGlobalScope ()
765 llassert (inFunction);
766 DPRINTF (("leave function"));
770 void sRef_clearGlobalScope ()
772 llassert (!inFunction);
773 DPRINTF (("enter function"));
777 static bool oldInFunction = FALSE;
778 static int nestedScope = 0;
780 void sRef_setGlobalScopeSafe ()
782 if (nestedScope == 0)
784 oldInFunction = inFunction;
788 DPRINTF (("leave function safe"));
792 void sRef_clearGlobalScopeSafe ()
795 llassert (nestedScope >= 0);
797 if (nestedScope == 0)
799 inFunction = oldInFunction;
802 DPRINTF (("clear function: %s", bool_unparse (inFunction)));
805 void sRef_enterFunctionScope ()
807 /* evans 2001-09-09 - cleanup if we are in a macro! */
808 if (context_inMacro ())
811 sRef_exitFunctionScope ();
815 llassert (!inFunction);
816 llassert (sRefTable_isEmpty (allRefs));
818 DPRINTF (("enter function"));
821 void sRef_exitFunctionScope ()
825 DPRINTF (("Exit function scope."));
826 sRefTable_clear (allRefs);
827 DPRINTF (("Exit function scope done."));
832 llbuglit ("sRef_exitFunctionScope: not in function");
836 void sRef_destroyMod () /*@globals killed allRefs;@*/
839 llmsg (message ("Live: %d / %d ", nsrefs, totnsrefs));
842 sRefTable_free (allRefs);
846 static /*@notnull@*/ /*@exposed@*/ sRef
847 sRef_fixConj (/*@notnull@*/ sRef s)
852 s = sRef_getConjA (s);
853 } while (sRef_isConj (s));
855 llassert (sRef_isReasonable (s));
856 return s; /* don't need to ref */
865 sRef_isExternallyVisibleAux (sRef s)
868 sRef base = sRef_getRootBase (s);
870 if (sRef_isReasonable (base))
872 res = sRef_isParam (base) || sRef_isFileOrGlobalScope (base) || sRef_isExternal (base);
879 sRef_isExternallyVisible (sRef s)
881 return (sRef_aliasCheckSimplePred (sRef_isExternallyVisibleAux, s));
885 sRef_getBaseUentry (sRef s)
887 sRef base = sRef_getRootBase (s);
888 uentry res = uentry_undefined;
890 if (sRef_isReasonable (base))
895 res = usymtab_getRefQuiet (paramsScope, base->info->paramno);
899 res = usymtab_getRefQuiet (base->info->cvar->lexlevel,
900 base->info->cvar->index);
912 ** lookup the current uentry corresponding to s, and return the corresponding sRef.
913 ** yuk yuk yuk yuk yuk yuk yuk yuk
917 sRef_updateSref (sRef s)
923 if (!sRef_isReasonable (s)) return sRef_undefined;
932 case SK_UNCONSTRAINED:
939 sRef r = sRef_updateSref (s->info->ref);
941 if (r != s->info->ref)
943 return sRef_makeExternal (r);
953 uentry ue = sRef_getUentry (s);
955 /* must be raw name! (need the marker) */
956 ue = usymtab_lookupSafe (uentry_rawName (ue));
958 if (uentry_isUndefined (ue))
964 DPRINTF (("Update sref: %s", uentry_unparseFull (ue)));
965 return (uentry_getSref (ue));
969 /* special case if ind known */
970 inner = s->info->arrayfetch->arr;
971 ret = sRef_updateSref (inner);
979 res = sRef_makeArrayFetch (ret);
985 inner = s->info->field->rec;
986 ret = sRef_updateSref (inner);
994 res = (sRef_makeField (ret, s->info->field->field));
999 inner = s->info->ref;
1000 ret = sRef_updateSref (inner);
1007 res = sRef_makePointer (ret);
1013 inner = s->info->ref;
1014 ret = sRef_updateSref (inner);
1022 res = sRef_makeAddress (ret);
1029 sRef innera = s->info->conj->a;
1030 sRef innerb = s->info->conj->b;
1031 sRef reta = sRef_updateSref (innera);
1032 sRef retb = sRef_updateSref (innerb);
1034 if (innera == reta && innerb == retb)
1040 res = sRef_makeConj (reta, retb);
1051 sRef_getUentry (sRef s)
1053 llassert (sRef_isReasonable (s));
1058 return (usymtab_getRefQuiet (paramsScope, s->info->paramno));
1060 return (usymtab_getRefQuiet (s->info->cvar->lexlevel, s->info->cvar->index));
1063 if (sRef_isCvar (s->info->conj->a) || sRef_isParam (s->info->conj->a)
1064 || sRef_isConj (s->info->conj->a))
1066 return sRef_getUentry (s->info->conj->a);
1070 return sRef_getUentry (s->info->conj->b);
1075 return uentry_undefined;
1081 sRef_getParam (sRef s)
1083 llassert (sRef_isReasonable (s));
1084 llassert (s->kind == SK_PARAM);
1086 return s->info->paramno;
1090 sRef_isModified (sRef s)
1092 return (!sRef_isReasonable (s) || s->modified);
1095 void sRef_setModified (sRef s)
1097 if (sRef_isReasonable (s))
1102 if (sRef_isRefsField (s))
1104 sRef base = sRef_getBase (s);
1106 llassert (s->kind == SK_FIELD);
1108 if (sRef_isPointer (base))
1110 base = sRef_getBase (base);
1113 if (sRef_isRefCounted (base))
1115 base->aliaskind = AK_NEWREF;
1122 ** note: this side-effects sRefSet to set modified to TRUE
1123 ** for any sRef similar to s.
1127 sRef_canModifyVal (sRef s, sRefSet sl)
1129 if (context_getFlag (FLG_MUSTMOD))
1131 return (sRef_doModifyVal (s, sl));
1135 return (sRef_checkModifyVal (s, sl));
1140 sRef_canModify (sRef s, sRefSet sl)
1142 if (context_getFlag (FLG_MUSTMOD))
1144 return (sRef_doModify (s, sl));
1148 return (sRef_checkModify (s, sl));
1157 bool sRef_checkModifyVal (sRef s, sRefSet sl)
1159 DPRINTF (("Check modify val: %s", sRef_unparse (s)));
1161 if (sRef_isInvalid (s))
1168 case SK_UNCONSTRAINED:
1172 DPRINTF (("Modify var: %s", sRef_unparse (s)));
1174 if (sRef_isFileOrGlobalScope (s))
1176 if (context_checkGlobMod (s))
1178 return (sRefSet_member (sl, s));
1188 return (sRefSet_member (sl, s)
1189 || alkind_isOnly (sRef_getOrigAliasKind (s)));
1191 /* special case if ind known */
1192 return (sRefSet_member (sl, s) ||
1193 sRef_checkModifyVal (s->info->arrayfetch->arr, sl));
1195 return (sRefSet_member (sl, s) || sRef_checkModifyVal (s->info->field->rec, sl));
1197 return (sRefSet_member (sl, s) || sRef_checkModifyVal (s->info->ref, sl));
1199 return (sRefSet_member (sl, s) || sRef_checkModifyVal (s->info->ref, sl));
1201 return ((sRef_checkModifyVal (s->info->conj->a, sl)) &&
1202 (sRef_checkModifyVal (s->info->conj->b, sl)));
1213 switch (s->info->spec)
1215 case SR_NOTHING: return TRUE;
1217 if (context_getFlag (FLG_INTERNALGLOBS))
1219 return (sRefSet_member (sl, s));
1225 case SR_SPECSTATE: return TRUE;
1226 case SR_SYSTEM: return (sRefSet_member (sl, s));
1227 case SR_GLOBALMARKER: BADBRANCH;
1230 case SK_RESULT: BADBRANCH;
1236 ** this should probably be elsewhere...
1238 ** returns TRUE iff sl indicates that s can be modified
1241 static bool sRef_checkModify (sRef s, sRefSet sl)
1243 llassert (sRef_isReasonable (s));
1247 case SK_UNCONSTRAINED:
1251 if (sRef_isFileOrGlobalScope (s))
1253 if (context_checkGlobMod (s))
1255 return (sRefSet_member (sl, s));
1267 return (sRefSet_member (sl, s) ||
1268 sRef_checkModifyVal (s->info->arrayfetch->arr, sl));
1271 sRef sr = s->info->field->rec;
1273 if (sr->kind == SK_PARAM)
1274 return TRUE; /* structs are copied on call */
1276 return (sRefSet_member (sl, s) || sRef_checkModifyVal (s->info->field->rec, sl));
1282 sm = sRefSet_member (sl, s);
1287 return (sRef_checkModifyVal (s->info->ref, sl));
1290 return (sRefSet_member (sl, s) || sRef_checkModifyVal (s->info->ref, sl));
1292 return ((sRef_checkModify (s->info->conj->a, sl)) &&
1293 (sRef_checkModify (s->info->conj->b, sl)));
1303 switch (s->info->spec)
1305 case SR_NOTHING: return TRUE;
1307 if (context_getFlag (FLG_INTERNALGLOBS))
1309 return (sRefSet_member (sl, s));
1315 case SR_SPECSTATE: return TRUE;
1316 case SR_SYSTEM: return (sRefSet_member (sl, s));
1317 case SR_GLOBALMARKER: BADBRANCH;
1320 case SK_RESULT: BADBRANCH;
1325 cstring sRef_stateVerb (sRef s)
1327 if (sRef_isDead (s))
1329 return cstring_makeLiteralTemp ("released");
1331 else if (sRef_isKept (s))
1333 return cstring_makeLiteralTemp ("kept");
1335 else if (sRef_isDependent (s))
1337 return cstring_makeLiteralTemp ("dependent");
1345 cstring sRef_stateAltVerb (sRef s)
1347 if (sRef_isDead (s))
1349 return cstring_makeLiteralTemp ("live");
1351 else if (sRef_isKept (s))
1353 return cstring_makeLiteralTemp ("not kept");
1355 else if (sRef_isDependent (s))
1357 return cstring_makeLiteralTemp ("independent");
1366 bool sRef_doModifyVal (sRef s, sRefSet sl)
1368 llassert (sRef_isReasonable (s));
1373 case SK_UNCONSTRAINED:
1377 if (sRef_isFileOrGlobalScope (s))
1380 if (context_checkGlobMod (s))
1382 return (sRefSet_modifyMember (sl, s));
1386 (void) sRefSet_modifyMember (sl, s);
1396 return (sRefSet_modifyMember (sl, s)
1397 || alkind_isOnly (sRef_getOrigAliasKind (s)));
1399 /* special case if ind known */
1400 /* unconditional OR, need side effect */
1401 return (OR (sRefSet_modifyMember (sl, s),
1402 sRef_doModifyVal (s->info->arrayfetch->arr, sl)));
1404 return (OR (sRefSet_modifyMember (sl, s),
1405 sRef_doModifyVal (s->info->field->rec, sl)));
1407 return (OR (sRefSet_modifyMember (sl, s),
1408 sRef_doModifyVal (s->info->ref, sl)));
1410 return (OR (sRefSet_modifyMember (sl, s),
1411 sRef_doModifyVal (s->info->ref, sl)));
1413 return (AND (sRef_doModifyVal (s->info->conj->a, sl) ,
1414 sRef_doModifyVal (s->info->conj->b, sl)));
1424 switch (s->info->spec)
1426 case SR_NOTHING: return TRUE;
1428 if (context_getFlag (FLG_INTERNALGLOBS))
1430 return (sRefSet_modifyMember (sl, s));
1434 (void) sRefSet_modifyMember (sl, s);
1437 case SR_SPECSTATE: return TRUE;
1438 case SR_SYSTEM: return (sRefSet_modifyMember (sl, s));
1439 case SR_GLOBALMARKER: BADBRANCH;
1443 case SK_RESULT: BADBRANCH;
1449 ** this should probably be elsewhere...
1451 ** returns TRUE iff sl indicates that s can be modified
1455 bool sRef_doModify (sRef s, sRefSet sl)
1457 llassert (sRef_isReasonable (s));
1461 case SK_UNCONSTRAINED:
1465 if (sRef_isFileOrGlobalScope (s))
1467 if (context_checkGlobMod (s))
1469 return (sRefSet_modifyMember (sl, s));
1473 (void) sRefSet_modifyMember (sl, s);
1485 return (OR (sRefSet_modifyMember (sl, s),
1486 sRef_doModifyVal (s->info->arrayfetch->arr, sl)));
1489 sRef sr = s->info->field->rec;
1491 if (sr->kind == SK_PARAM)
1493 return TRUE; /* structs are shallow-copied on call */
1496 return (OR (sRefSet_modifyMember (sl, s),
1497 sRef_doModifyVal (s->info->field->rec, sl)));
1501 return (OR (sRefSet_modifyMember (sl, s),
1502 sRef_doModifyVal (s->info->ref, sl)));
1505 return (OR (sRefSet_modifyMember (sl, s),
1506 sRef_doModifyVal (s->info->ref, sl)));
1508 return (AND (sRef_doModify (s->info->conj->a, sl),
1509 (sRef_doModify (s->info->conj->b, sl))));
1520 switch (s->info->spec)
1522 case SR_NOTHING: return TRUE;
1523 case SR_INTERNAL: return TRUE;
1524 case SR_SPECSTATE: return TRUE;
1525 case SR_SYSTEM: return (sRefSet_modifyMember (sl, s));
1526 case SR_GLOBALMARKER: BADBRANCH;
1529 case SK_RESULT: BADBRANCH;
1534 static /*@exposed@*/ sRef
1535 sRef_leastCommon (/*@exposed@*/ sRef s1, sRef s2)
1537 llassert (sRef_similar (s1, s2));
1539 if (!sRef_isReasonable (s1)) return s1;
1540 if (!sRef_isReasonable (s2)) return s1;
1542 sRef_combineDefState (s1, s2);
1543 sRef_combineNullState (s1, s2);
1544 sRef_combineExKinds (s1, s2);
1546 if (s1->aliaskind != s2->aliaskind)
1548 if (s1->aliaskind == AK_UNKNOWN)
1550 s1->aliaskind = s2->aliaskind;
1552 else if (s2->aliaskind == AK_UNKNOWN)
1558 s1->aliaskind = AK_ERROR;
1565 int sRef_compare (sRef s1, sRef s2)
1567 if (s1 == s2) return 0;
1569 if (sRef_isInvalid (s1)) return -1;
1570 if (sRef_isInvalid (s2)) return 1;
1572 INTCOMPARERETURN (s1->kind, s2->kind);
1573 INTCOMPARERETURN (s1->defstate, s2->defstate);
1574 INTCOMPARERETURN (s1->aliaskind, s2->aliaskind);
1576 DPRINTF (("Compare null state: %s / %s",
1577 sRef_unparseFull (s1),
1578 sRef_unparseFull (s2)));
1580 COMPARERETURN (nstate_compare (sRef_getNullState (s1),
1581 sRef_getNullState (s2)));
1586 return (int_compare (s1->info->paramno, s2->info->paramno));
1589 COMPARERETURN (sRef_compare (s1->info->arrayfetch->arr,
1590 s2->info->arrayfetch->arr));
1592 if (s1->info->arrayfetch->indknown && s2->info->arrayfetch->indknown)
1594 return (int_compare (s1->info->arrayfetch->ind,
1595 s2->info->arrayfetch->ind));
1597 if (!s1->info->arrayfetch->indknown && !s2->info->arrayfetch->indknown)
1604 COMPARERETURN (sRef_compare (s1->info->field->rec, s2->info->field->rec));
1606 if (cstring_equal (s1->info->field->field, s2->info->field->field))
1613 return (sRef_compare (s1->info->ref, s2->info->ref));
1615 COMPARERETURN (sRef_compare (s1->info->conj->a, s2->info->conj->a));
1616 return (sRef_compare (s1->info->conj->b, s2->info->conj->b));
1617 case SK_UNCONSTRAINED:
1618 return (cstring_compare (s1->info->fname, s2->info->fname));
1630 return (generic_compare (s1->info->spec, s2->info->spec));
1635 static bool cref_equal (cref c1, cref c2)
1637 return ((c1->lexlevel == c2->lexlevel) &&
1638 (usymId_equal (c1->index, c2->index)));
1642 ** returns true if s1 could be the same storage as s2.
1643 ** i.e., a[?] ~ a[3]. Note its not symmetric ... s1
1644 ** should be more specific.
1648 ** like similar, but matches objects <-> non-objects
1652 sRef_uniqueReference (sRef s)
1654 return (sRef_isFresh (s) || sRef_isUnique (s)
1655 || sRef_isOnly (s) || sRef_isStack (s)
1656 || sRef_isAddress (s));
1660 sRef_similarRelaxedAux (sRef s1, sRef s2)
1664 if (sRef_isUnknownArrayFetch (s1))
1674 if (sRef_isInvalid (s1) || sRef_isInvalid (s2)) return FALSE;
1676 if (sRef_isConj (s2))
1677 return (sRef_similarRelaxedAux (s1, sRef_getConjA (s2)) ||
1678 sRef_similarRelaxedAux (s1, sRef_getConjB (s2)));
1683 return ((s2->kind == SK_CVAR)
1684 && (cref_equal (s1->info->cvar, s2->info->cvar)));
1686 return ((s2->kind == SK_PARAM)
1687 && (s1->info->paramno == s2->info->paramno));
1689 if (s2->kind == SK_ARRAYFETCH)
1691 if (sRef_similarRelaxedAux (s1->info->arrayfetch->arr,
1692 s2->info->arrayfetch->arr))
1694 if (s1->info->arrayfetch->indknown)
1696 if (s2->info->arrayfetch->indknown)
1698 return (s1->info->arrayfetch->ind == s2->info->arrayfetch->ind);
1713 return ((s2->kind == SK_FIELD
1714 && (sRef_similarRelaxedAux (s1->info->field->rec,
1715 s2->info->field->rec)
1716 && cstring_equal (s1->info->field->field,
1717 s2->info->field->field))));
1719 return ((s2->kind == SK_PTR)
1720 && sRef_similarRelaxedAux (s1->info->ref, s2->info->ref));
1722 return ((s2->kind == SK_ADR)
1723 && sRef_similarRelaxedAux (s1->info->ref, s2->info->ref));
1725 return ((sRef_similarRelaxedAux (s1->info->conj->a, s2) ||
1726 (sRef_similarRelaxedAux (s1->info->conj->b, s2))));
1728 return (s1->info->spec == s2->info->spec);
1729 case SK_UNCONSTRAINED:
1730 return (cstring_equal (s1->info->fname, s2->info->fname));
1745 sRef_similarRelaxed (sRef s1, sRef s2)
1751 if (sRef_isThroughArrayFetch (s1))
1761 if (sRef_isInvalid (s1) || sRef_isInvalid (s2)) return FALSE;
1763 us1 = sRef_uniqueReference (s1);
1764 us2 = sRef_uniqueReference (s2);
1766 if ((s1->kind == SK_EXTERNAL && (s2->kind != SK_EXTERNAL && !us2))
1767 || (s2->kind == SK_EXTERNAL && (s1->kind != SK_EXTERNAL && !us1)))
1770 ** Previously, also:
1771 ** || (sRef_isExposed (s1) && !us2) || (sRef_isExposed (s2) && !us1)) ????
1773 ** No clue why this was there?!
1777 if (sRef_isExposed (s1) && sRef_isCvar (s1))
1779 uentry ue1 = sRef_getUentry (s1);
1781 if (uentry_isRefParam (ue1))
1783 return sRef_similarRelaxedAux (s1, s2);
1787 if (sRef_isExposed (s2) && sRef_isCvar (s2))
1789 uentry ue2 = sRef_getUentry (s2);
1791 if (uentry_isRefParam (ue2))
1793 return sRef_similarRelaxedAux (s1, s2);
1797 return (ctype_match (s1->type, s2->type));
1801 return sRef_similarRelaxedAux (s1, s2);
1806 sRef_similar (sRef s1, sRef s2)
1808 if (s1 == s2) return TRUE;
1809 if (sRef_isInvalid (s1) || sRef_isInvalid (s2)) return FALSE;
1811 if (sRef_isConj (s2))
1813 return (sRef_similar (s1, sRef_getConjA (s2)) ||
1814 sRef_similar (s1, sRef_getConjB (s2)));
1817 if (sRef_isDerived (s2))
1819 return (sRef_includedBy (s1, s2->info->ref));
1825 return ((s2->kind == SK_CVAR)
1826 && (cref_equal (s1->info->cvar, s2->info->cvar)));
1828 return ((s2->kind == SK_PARAM)
1829 && (s1->info->paramno == s2->info->paramno));
1831 if (s2->kind == SK_ARRAYFETCH)
1833 if (sRef_similar (s1->info->arrayfetch->arr,
1834 s2->info->arrayfetch->arr))
1836 if (s1->info->arrayfetch->indknown)
1838 if (s2->info->arrayfetch->indknown)
1840 return (s1->info->arrayfetch->ind == s2->info->arrayfetch->ind);
1855 if (s2->kind == SK_PTR)
1857 if (sRef_similar (s1->info->arrayfetch->arr,
1867 return ((s2->kind == SK_FIELD
1868 && (sRef_similar (s1->info->field->rec,
1869 s2->info->field->rec)
1870 && cstring_equal (s1->info->field->field,
1871 s2->info->field->field))));
1873 if (s2->kind == SK_PTR)
1875 return sRef_similar (s1->info->ref, s2->info->ref);
1879 if (s2->kind == SK_ARRAYFETCH)
1881 if (sRef_similar (s2->info->arrayfetch->arr,
1891 return ((s2->kind == SK_ADR)
1892 && sRef_similar (s1->info->ref, s2->info->ref));
1894 return ((sRef_similar (s1->info->conj->a, s2) ||
1895 (sRef_similar (s1->info->conj->b, s2))));
1897 return (sRef_includedBy (s2, s1->info->ref));
1898 case SK_UNCONSTRAINED:
1899 return (s2->kind == SK_UNCONSTRAINED
1900 && cstring_equal (s1->info->fname, s2->info->fname));
1910 return (s2->kind == SK_SPECIAL
1911 && (s1->info->spec == s2->info->spec));
1914 /*@notreached@*/ DPRINTF (("Fell through for: %s / %s", sRef_unparse (s1), sRef_unparse (s2)));
1919 ** return TRUE iff small can be derived from big.
1921 ** (e.g. x, x.a is includedBy x;
1922 ** x.a is included By x.a;
1926 sRef_includedBy (sRef small, sRef big)
1928 if (small == big) return TRUE;
1929 if (sRef_isInvalid (small) || sRef_isInvalid (big)) return FALSE;
1931 if (sRef_isConj (big))
1932 return (sRef_similar (small, sRef_getConjA (big)) ||
1933 sRef_similar (small, sRef_getConjB (big)));
1935 switch (small->kind)
1939 return (sRef_same (small, big));
1941 if (big->kind == SK_ARRAYFETCH)
1943 if (sRef_same (small->info->arrayfetch->arr, big->info->arrayfetch->arr))
1945 if (small->info->arrayfetch->indknown)
1947 if (big->info->arrayfetch->indknown)
1949 return (small->info->arrayfetch->ind == big->info->arrayfetch->ind);
1962 return (sRef_includedBy (small->info->arrayfetch->arr, big));
1964 if (big->kind == SK_FIELD)
1967 (sRef_same (small->info->field->rec, big->info->field->rec) &&
1968 cstring_equal (small->info->field->field, big->info->field->field));
1972 return (sRef_includedBy (small->info->field->rec, big));
1976 if (big->kind == SK_PTR)
1978 return sRef_same (small->info->ref, big->info->ref);
1982 return (sRef_includedBy (small->info->ref, big));
1986 return ((big->kind == SK_ADR) && sRef_similar (small->info->ref, big->info->ref));
1988 return ((sRef_includedBy (small->info->conj->a, big) ||
1989 (sRef_includedBy (small->info->conj->b, big))));
1991 return (sRef_includedBy (small->info->ref, big));
1992 case SK_UNCONSTRAINED:
2002 switch (small->info->spec)
2004 case SR_NOTHING: return TRUE;
2006 case SR_INTERNAL: return (sRef_isSpecInternalState (big) ||
2007 sRef_isFileStatic (big));
2008 case SR_SYSTEM: return (sRef_isSystemState (big));
2009 case SR_GLOBALMARKER: BADBRANCH;
2016 ** Same is similar to similar, but not quite the same.
2017 ** same and realSame aren't the same, but they are really similar.
2018 ** similarly, same is the same as same. but realSame is
2019 ** not really the same as same, or similar to similar.
2021 ** Similarly to similar, same checks if two sRefs are the same.
2022 ** The similarities end, however, when same compares arrays
2023 ** with unknown indexes. Similar returns false; same returns true.
2025 ** Similarly to similar and same, realSame is the same as same,
2026 ** except they do not behave the same when face with unknown
2027 ** sRefs. Same thinks they are not the same, but realSame thinks
2033 sRef_realSame (sRef s1, sRef s2)
2035 if (s1 == s2) return TRUE;
2037 if (sRef_isUnreasonable (s1)
2038 || sRef_isUnreasonable (s2))
2046 return ((s2->kind == SK_CVAR) && (cref_equal (s1->info->cvar, s2->info->cvar)));
2048 return ((s2->kind == SK_PARAM) && (s1->info->paramno == s2->info->paramno));
2050 if (s2->kind == SK_ARRAYFETCH)
2052 if (sRef_realSame (s1->info->arrayfetch->arr, s2->info->arrayfetch->arr))
2054 if (s1->info->arrayfetch->indknown && s2->info->arrayfetch->indknown)
2056 return (s1->info->arrayfetch->ind == s2->info->arrayfetch->ind);
2058 if (!s1->info->arrayfetch->indknown && !s2->info->arrayfetch->indknown)
2067 return ((s2->kind == SK_FIELD &&
2068 (sRef_realSame (s1->info->field->rec, s2->info->field->rec) &&
2069 cstring_equal (s1->info->field->field, s2->info->field->field))));
2071 return ((s2->kind == SK_PTR) && sRef_realSame (s1->info->ref, s2->info->ref));
2073 return ((s2->kind == SK_ADR) && sRef_realSame (s1->info->ref, s2->info->ref));
2075 return ((sRef_realSame (s1->info->conj->a, s2) ||
2076 (sRef_realSame (s1->info->conj->b, s2))));
2078 return ((s2->kind == SK_OBJECT)
2079 && ctype_match (s1->info->object, s2->info->object));
2081 return ((s2->kind == SK_EXTERNAL)
2082 && sRef_realSame (s1->info->ref, s2->info->ref));
2084 return ((s2->kind == SK_SPECIAL) && s1->info->spec == s2->info->spec);
2086 return ((s2->kind == SK_DERIVED) && sRef_realSame (s1->info->ref, s2->info->ref));
2087 case SK_UNCONSTRAINED:
2088 return ((s2->kind == SK_UNCONSTRAINED)
2089 && (cstring_equal (s1->info->fname, s2->info->fname)));
2095 return TRUE; /* changed this! was false */
2101 sRef_sameObject (sRef s1, sRef s2)
2107 ** same is similar to similar, but not quite the same.
2109 ** Similarly to similar, same checks is two sRefs are the same.
2110 ** The similarities end, however, when same compares arrays
2111 ** with unknown indexes. Similar returns false; same returns true.
2115 sRef_same (sRef s1, sRef s2)
2117 if (s1 == s2) return TRUE;
2118 if (sRef_isInvalid (s1) || sRef_isInvalid (s2)) return FALSE;
2123 return ((s2->kind == SK_CVAR) && (cref_equal (s1->info->cvar, s2->info->cvar)));
2125 return ((s2->kind == SK_PARAM) && (s1->info->paramno == s2->info->paramno));
2127 if (s2->kind == SK_ARRAYFETCH)
2129 llassert (s1->info->field->rec != s1);
2130 if (sRef_same (s1->info->arrayfetch->arr, s2->info->arrayfetch->arr))
2132 if (s1->info->arrayfetch->indknown && s2->info->arrayfetch->indknown)
2134 return (s1->info->arrayfetch->ind == s2->info->arrayfetch->ind);
2142 llassert (s1->info->field->rec != s1);
2143 return ((s2->kind == SK_FIELD &&
2144 (sRef_same (s1->info->field->rec, s2->info->field->rec) &&
2145 cstring_equal (s1->info->field->field, s2->info->field->field))));
2149 llassert (s1->info->ref != s1);
2150 return ((s2->kind == SK_PTR) && sRef_same (s1->info->ref, s2->info->ref));
2154 llassert (s1->info->ref != s1);
2155 return ((s2->kind == SK_ADR) && sRef_same (s1->info->ref, s2->info->ref));
2158 llassert (s1->info->conj->a != s1);
2159 llassert (s1->info->conj->b != s1);
2160 return ((sRef_same (s1->info->conj->a, s2)) && /* or or and? */
2161 (sRef_same (s1->info->conj->b, s2)));
2163 return ((s2->kind == SK_SPECIAL) && s1->info->spec == s2->info->spec);
2165 llassert (s1->info->ref != s1);
2166 return ((s2->kind == SK_DERIVED) && sRef_same (s1->info->ref, s2->info->ref));
2168 case SK_UNCONSTRAINED:
2181 ** sort of similar, for use in def/use
2185 sRef_closeEnough (sRef s1, sRef s2)
2187 if (s1 == s2) return TRUE;
2188 if (sRef_isInvalid (s1) || sRef_isInvalid (s2)) return FALSE;
2193 return (((s2->kind == SK_CVAR) &&
2194 (cref_equal (s1->info->cvar, s2->info->cvar))) ||
2195 (s2->kind == SK_UNCONSTRAINED && s1->info->cvar->lexlevel == 0));
2196 case SK_UNCONSTRAINED:
2197 return (s2->kind == SK_UNCONSTRAINED
2198 || ((s2->kind == SK_CVAR) && (s2->info->cvar->lexlevel == 0)));
2200 return ((s2->kind == SK_PARAM)
2201 && (s1->info->paramno == s2->info->paramno));
2203 if (s2->kind == SK_ARRAYFETCH)
2205 if (sRef_closeEnough (s1->info->arrayfetch->arr, s2->info->arrayfetch->arr))
2207 if (s1->info->arrayfetch->indknown && s2->info->arrayfetch->indknown)
2209 return (s1->info->arrayfetch->ind == s2->info->arrayfetch->ind);
2216 return ((s2->kind == SK_FIELD &&
2217 (sRef_closeEnough (s1->info->field->rec, s2->info->field->rec) &&
2218 cstring_equal (s1->info->field->field, s2->info->field->field))));
2220 return ((s2->kind == SK_PTR) && sRef_closeEnough (s1->info->ref, s2->info->ref));
2222 return ((s2->kind == SK_ADR) && sRef_closeEnough (s1->info->ref, s2->info->ref));
2224 return ((s2->kind == SK_DERIVED) && sRef_closeEnough (s1->info->ref, s2->info->ref));
2226 return ((sRef_closeEnough (s1->info->conj->a, s2)) ||
2227 (sRef_closeEnough (s1->info->conj->b, s2)));
2229 return ((s2->kind == SK_SPECIAL) && s1->info->spec == s2->info->spec);
2245 s is an sRef of a formal paramenter in a function call constraint
2246 we trys to return a constraint expression derived from the actual parementer of a function call.
2249 /*@only@*/ constraintExpr sRef_fixConstraintParam (/*@observer@*/ sRef s, /*@observer@*/ /*@temp@*/ exprNodeList args)
2253 if (sRef_isInvalid (s))
2254 llfatalbug((message("Invalid sRef")));
2260 /* s = sRef_saveCopy(s); */ /*@i523@*/
2261 ce = constraintExpr_makeTermsRef (s);
2268 temp = (sRef_makeField (sRef_fixBaseParam (s->info->field->rec, args),
2269 s->info->field->field));
2270 ce = constraintExpr_makeTermsRef (temp);
2276 temp = (sRef_makePointer (sRef_fixBaseParam (s->info->ref, args)));
2277 /* temp = sRef_saveCopy(temp); */ /*@i523@*/
2278 ce = constraintExpr_makeTermsRef (temp);
2285 temp = sRef_saveCopy(s);
2286 temp = sRef_fixBaseParam (temp, args);
2287 ce = constraintExpr_makeTermsRef (temp);
2295 temp = sRef_saveCopy(s);
2296 ce = constraintExpr_makeTermsRef (temp);
2301 llassert(exprNodeList_size (args) > s->info->paramno);
2303 exprNode e = exprNodeList_nth (args, s->info->paramno);
2305 llassert( !(exprNode_isError (e)) );
2306 ce = constraintExpr_makeExprNode (e);
2313 llcontbug (message ("Trying to do fixConstraintParam on nonparam, nonglobal: %q for function with arguments %q",
2314 sRef_unparse (s), exprNodeList_unparse(args)));
2315 temp = sRef_saveCopy(s);
2316 ce = constraintExpr_makeTermsRef (temp);
2325 sRef_fixBaseParam (/*@returned@*/ sRef s, exprNodeList args)
2327 if (sRef_isInvalid (s)) return (sRef_undefined);
2331 case SK_UNCONSTRAINED:
2336 if (exprNodeList_size (args) > s->info->paramno)
2338 exprNode e = exprNodeList_nth (args, s->info->paramno);
2340 if (exprNode_isError (e))
2342 return sRef_makeUnknown ();
2345 return (exprNode_getSref (e));
2349 return sRef_makeUnknown ();
2354 if (s->info->arrayfetch->indknown)
2356 return (sRef_makeArrayFetchKnown
2357 (sRef_fixBaseParam (s->info->arrayfetch->arr, args),
2358 s->info->arrayfetch->ind));
2362 return (sRef_makeArrayFetch
2363 (sRef_fixBaseParam (s->info->arrayfetch->arr, args)));
2368 DPRINTF (("Fix field: %s", sRef_unparseFull (s)));
2369 res = sRef_makeField (sRef_fixBaseParam (s->info->field->rec, args),
2370 s->info->field->field);
2371 DPRINTF (("Returns: %s", sRef_unparseFull (res)));
2375 return (sRef_makePointer (sRef_fixBaseParam (s->info->ref, args)));
2378 return (sRef_makeAddress (sRef_fixBaseParam (s->info->ref, args)));
2381 return (sRef_makeConj (sRef_fixBaseParam (s->info->conj->a, args),
2382 sRef_fixBaseParam (s->info->conj->b, args)));
2398 sRef_undumpGlobal (char **c)
2408 usymId uid = usymId_fromInt (reader_getInt (c));
2413 reader_checkChar (c, '@');
2414 defstate = sstate_fromInt (reader_getInt (c));
2416 reader_checkChar (c, '@');
2417 nullstate = nstate_fromInt (reader_getInt (c));
2419 ret = sRef_makeGlobal (uid, ctype_unknown, stateInfo_currentLoc ());
2420 sRef_setNullStateN (ret, nullstate);
2421 ret->defstate = defstate;
2426 int i = reader_getInt (c);
2427 speckind sk = speckind_fromInt (i);
2431 case SR_NOTHING: return (sRef_makeNothing ());
2432 case SR_INTERNAL: return (sRef_makeInternalState ());
2433 case SR_SPECSTATE: return (sRef_makeSpecState ());
2434 case SR_SYSTEM: return (sRef_makeSystemState ());
2435 case SR_GLOBALMARKER: BADBRANCH;
2440 return sRef_undefined;
2442 return sRef_makeUnknown ();
2444 return sRef_makeUnknown ();
2446 llfatalerror (message ("sRef_undumpGlobal: bad line: %s",
2447 cstring_fromChars (*c)));
2452 static /*@exposed@*/ sRef sRef_undumpBody (char **c)
2461 return (sRef_makeGlobal (usymId_fromInt (reader_getInt (c)), ctype_unknown, stateInfo_currentLoc ()));
2463 return (sRef_makeParam (reader_getInt (c), ctype_unknown, stateInfo_makeLoc (g_currentloc)));
2465 return (sRef_makeResult (ctype_undump (c)));
2468 if ((**c >= '0' && **c <= '9') || **c == '-')
2470 int i = reader_getInt (c);
2471 sRef arr = sRef_undump (c);
2472 sRef ret = sRef_buildArrayFetchKnown (arr, i);
2478 sRef arr = sRef_undump (c);
2479 sRef ret = sRef_buildArrayFetch (arr);
2486 cstring fname = cstring_undefined;
2491 fname = cstring_appendChar (fname, **c);
2496 ret = sRef_buildField (sRef_undump (c), fname);
2497 cstring_markOwned (fname);
2502 int i = reader_getInt (c);
2503 speckind sk = speckind_fromInt (i);
2507 case SR_NOTHING: return (sRef_makeNothing ());
2508 case SR_INTERNAL: return (sRef_makeInternalState ());
2509 case SR_SPECSTATE: return (sRef_makeSpecState ());
2510 case SR_SYSTEM: return (sRef_makeSystemState ());
2511 case SR_GLOBALMARKER: BADBRANCH;
2517 sRef ptr = sRef_undump (c);
2518 sRef ret = sRef_makePointer (ptr);
2524 sRef adr = sRef_undump (c);
2525 sRef ret = sRef_makeAddress (adr);
2531 return (sRef_makeObject (ctype_undump (c)));
2535 sRef s1 = sRef_undump (c);
2536 sRef s2 = ((*c)++, sRef_undump (c));
2537 sRef ret = sRef_makeConj (s1, s2);
2542 return sRef_undefined;
2544 return sRef_makeUnknown ();
2546 return sRef_makeUnknown ();
2548 llfatalerror (message ("sRef_undump: bad line: %s", cstring_fromChars (*c)));
2553 /*@exposed@*/ sRef sRef_undump (char **c)
2555 sRef res = sRef_undumpBody (c);
2557 if (reader_optCheckChar (c, '='))
2559 multiVal mv = multiVal_undump (c);
2560 sRef_setValue (res, mv);
2561 reader_checkChar (c, '=');
2567 static /*@only@*/ cstring sRef_dumpBody (sRef s)
2569 if (sRef_isInvalid (s))
2571 return (cstring_makeLiteral ("-"));
2578 return (message ("p%d", s->info->paramno));
2580 if (s->info->arrayfetch->indknown)
2582 return (message ("a%d%q", s->info->arrayfetch->ind,
2583 sRef_dump (s->info->arrayfetch->arr)));
2587 return (message ("a%q", sRef_dump (s->info->arrayfetch->arr)));
2590 return (message ("f%s.%q", s->info->field->field,
2591 sRef_dump (s->info->field->rec)));
2593 return (message ("t%q", sRef_dump (s->info->ref)));
2595 return (message ("d%q", sRef_dump (s->info->ref)));
2597 return (message ("o%q", ctype_dump (s->info->object)));
2599 return (message ("s%d", (int) s->info->spec));
2601 return (message ("c%q.%q",
2602 sRef_dump (s->info->conj->a),
2603 sRef_dump (s->info->conj->b)));
2605 if (sRef_isFileOrGlobalScope (s))
2607 return (message ("g%d",
2608 usymtab_convertId (s->info->cvar->index)));
2612 llcontbug (message ("Dumping local variable: %q",
2613 sRef_unparseDebug (s)));
2614 return (cstring_makeLiteral ("u"));
2617 return (cstring_makeLiteral ("u"));
2619 return (message ("r%q", ctype_dump (s->type)));
2625 case SK_UNCONSTRAINED:
2626 llcontbug (message ("sRef_dump: bad kind: %q",
2627 sRef_unparseFull (s)));
2628 return (cstring_makeLiteral ("x"));
2635 /*@only@*/ cstring sRef_dump (sRef s)
2637 cstring res = sRef_dumpBody (s);
2639 if (sRef_hasValue (s))
2641 res = message ("%q=%q=", res, multiVal_dump (sRef_getValue (s)));
2647 cstring sRef_dumpGlobal (sRef s)
2649 llassert (!sRef_hasValue (s));
2651 if (sRef_isInvalid (s))
2653 return (cstring_makeLiteral ("-"));
2660 if (sRef_isFileOrGlobalScope (s))
2662 return (message ("g%d@%d@%d",
2663 usymtab_convertId (s->info->cvar->index),
2665 (int) sRef_getNullState (s)));
2669 llcontbug (message ("Dumping local variable: %q",
2670 sRef_unparseDebug (s)));
2671 return (cstring_makeLiteral ("u"));
2674 return (cstring_makeLiteral ("u"));
2676 return (message ("s%d", (int) s->info->spec));
2678 llcontbug (message ("sRef_dumpGlobal: bad kind: %q",
2679 sRef_unparseFull (s)));
2680 return (cstring_makeLiteral ("x"));
2688 sRef_deriveType (sRef s, uentryList cl)
2690 if (sRef_isInvalid (s)) return ctype_unknown;
2695 return (uentry_getType (usymtab_getRefQuiet (s->info->cvar->lexlevel,
2696 s->info->cvar->index)));
2697 case SK_UNCONSTRAINED:
2698 return (ctype_unknown);
2700 if (s->info->paramno >= 0)
2702 return uentry_getType (uentryList_getN (cl, s->info->paramno));
2706 return ctype_unknown;
2710 ctype ca = sRef_deriveType (s->info->arrayfetch->arr, cl);
2712 if (ctype_isArray (ca))
2714 return (ctype_baseArrayPtr (ca));
2716 else if (ctype_isUnknown (ca))
2722 llcontbuglit ("sRef_deriveType: inconsistent array type");
2728 ctype ct = sRef_deriveType (s->info->field->rec, cl);
2730 if (ctype_isStructorUnion (ct))
2732 uentry ue = uentryList_lookupField (ctype_getFields (ct),
2733 s->info->field->field);
2735 if (uentry_isValid (ue))
2737 return (uentry_getType (ue));
2741 llcontbuglit ("sRef_deriveType: bad field");
2742 return ctype_unknown;
2745 else if (ctype_isUnknown (ct))
2751 llcontbuglit ("sRef_deriveType: inconsistent field type");
2757 ctype ct = sRef_deriveType (s->info->ref, cl);
2759 if (ctype_isUnknown (ct)) return ct;
2760 if (ctype_isPointer (ct)) return (ctype_baseArrayPtr (ct));
2763 llcontbuglit ("sRef_deriveType: inconsistent pointer type");
2769 ctype ct = sRef_deriveType (s->info->ref, cl);
2771 if (ctype_isUnknown (ct)) return ct;
2772 return ctype_makePointer (ct);
2776 return sRef_deriveType (s->info->ref, cl);
2780 return (s->info->object);
2784 return (ctype_makeConj (sRef_deriveType (s->info->conj->a, cl),
2785 sRef_deriveType (s->info->conj->b, cl)));
2797 return ctype_unknown;
2803 sRef_getType (sRef s)
2805 if (sRef_isInvalid (s)) return ctype_unknown;
2811 sRef_unparseOpt (sRef s)
2813 sRef rb = sRef_getRootBase (s);
2815 if (sRef_isMeaningful (rb) && !sRef_isConst (rb))
2817 cstring ret = sRef_unparse (s);
2819 llassertprint (!cstring_equalLit (ret, "?"), ("print: %s", sRef_unparseDebug (s)));
2821 if (!cstring_isEmpty (ret))
2823 return (cstring_appendChar (ret, ' '));
2831 return cstring_undefined;
2835 sRef_unparsePreOpt (sRef s)
2837 sRef rb = sRef_getRootBase (s);
2839 if (sRef_isMeaningful (rb) && !sRef_isConst (rb))
2841 cstring ret = sRef_unparse (s);
2843 llassertprint (!cstring_equalLit (ret, "?"), ("print: %s", sRef_unparseDebug (s)));
2844 return (cstring_prependCharO (' ', ret));
2847 return cstring_undefined;
2851 sRef_unparse (sRef s)
2853 if (sRef_isInvalid (s)) return (cstring_makeLiteral ("?"));
2855 if (context_inFunctionLike ())
2857 return (sRef_unparseWithArgs (s, context_getParams ()));
2861 DPRINTF (("Not in function like: %s", context_unparse ()));
2862 return (sRef_unparseNoArgs (s));
2866 static /*@only@*/ cstring
2867 sRef_unparseWithArgs (sRef s, uentryList args)
2869 if (sRef_isInvalid (s))
2871 return (cstring_makeLiteral ("?"));
2877 return (uentry_getName (usymtab_getRefQuiet (s->info->cvar->lexlevel,
2878 s->info->cvar->index)));
2879 case SK_UNCONSTRAINED:
2880 return (cstring_copy (s->info->fname));
2883 if (s->info->paramno < uentryList_size (args)
2884 && s->info->paramno >= 0)
2886 uentry ue = uentryList_getN (args, s->info->paramno);
2888 if (uentry_isValid (ue))
2889 return uentry_getName (ue);
2892 return (message ("parameter %d", s->info->paramno + 1));
2895 if (s->info->arrayfetch->indknown)
2897 return (message ("%q[%d]", sRef_unparseWithArgs (s->info->arrayfetch->arr, args),
2898 s->info->arrayfetch->ind));
2902 return (message ("%q[]", sRef_unparseWithArgs (s->info->arrayfetch->arr, args)));
2905 if (s->info->field->rec->kind == SK_PTR)
2907 sRef ptr = s->info->field->rec;
2909 return (message ("%q->%s", sRef_unparseWithArgs (ptr->info->ref, args),
2910 s->info->field->field));
2912 return (message ("%q.%s", sRef_unparseWithArgs (s->info->field->rec, args),
2913 s->info->field->field));
2917 sRef ref = sRef_fixConj (s->info->ref);
2918 skind sk = ref->kind;
2923 ret = message ("storage pointed to by %q",
2924 sRef_unparseWithArgs (ref, args));
2926 else if (skind_isSimple (sk) || sk == SK_PTR)
2928 ret = message ("*%q", sRef_unparseWithArgs (ref, args));
2932 ret = message ("*(%q)", sRef_unparseWithArgs (ref, args));
2938 return (message ("&%q", sRef_unparseWithArgs (s->info->ref, args)));
2940 return (cstring_copy (ctype_unparse (s->info->object)));
2942 return (sRef_unparseWithArgs (sRef_getConjA (s), args));
2944 if (cstring_isDefined (s->info->fname))
2946 return (message ("[result of %s]", s->info->fname));
2950 return (cstring_makeLiteral ("<new>"));
2953 return (cstring_makeLiteral ("?"));
2955 return (message ("<derived %q>", sRef_unparse (s->info->ref)));
2957 return (message ("<external %q>", sRef_unparse (s->info->ref)));
2959 return (message ("<type %s>", ctype_unparse (s->type)));
2961 return (message ("<const %s>", ctype_unparse (s->type)));
2963 switch (s->info->spec)
2965 case SR_NOTHING: return cstring_makeLiteral ("nothing");
2966 case SR_INTERNAL: return cstring_makeLiteral ("internal state");
2967 case SR_SPECSTATE: return cstring_makeLiteral ("spec state");
2968 case SR_SYSTEM: return cstring_makeLiteral ("file system state");
2969 case SR_GLOBALMARKER: return cstring_makeLiteral ("<global marker>");
2973 return cstring_makeLiteral ("result");
2976 llbug (message ("Bad sref, kind = %d", (int) s->kind));
2984 sRef_unparseDebug (sRef s)
2986 if (sRef_isInvalid (s))
2988 return (cstring_makeLiteral ("<undef>"));
2994 case SK_UNCONSTRAINED:
2995 return (message ("<unconstrained %s>", s->info->fname));
3000 ce = usymtab_getRefQuiet (s->info->cvar->lexlevel, s->info->cvar->index);
3002 if (uentry_isInvalid (ce))
3004 return (message ("<scope: %d.%d *invalid*>",
3005 s->info->cvar->lexlevel,
3006 s->info->cvar->index));
3010 return (message ("<scope: %d.%d *%q*>",
3011 s->info->cvar->lexlevel,
3012 s->info->cvar->index,
3013 uentry_getName (ce)));
3019 return (message ("<parameter %d>", s->info->paramno + 1));
3022 if (s->info->arrayfetch->indknown)
3024 return (message ("%q[%d]", sRef_unparseDebug (s->info->arrayfetch->arr),
3025 s->info->arrayfetch->ind));
3029 return (message ("%q[]", sRef_unparseDebug (s->info->arrayfetch->arr)));
3032 return (message ("%q.%s", sRef_unparseDebug (s->info->field->rec),
3033 s->info->field->field));
3035 if (sRef_isField (s->info->ref))
3037 sRef fld = s->info->ref;
3039 return (message ("%q->%s", sRef_unparseDebug (fld->info->field->rec),
3040 fld->info->field->field));
3044 return (message ("*(%q)", sRef_unparseDebug (s->info->ref)));
3047 return (message ("&%q", sRef_unparseDebug (s->info->ref)));
3049 return (message ("<object type %s>", ctype_unparse (s->info->object)));
3051 return (message ("%q | %q", sRef_unparseDebug (s->info->conj->a),
3052 sRef_unparseDebug (s->info->conj->b)));
3054 return message ("<new: %s>", s->info->fname);
3056 return (message ("<derived %q>", sRef_unparseDebug (s->info->ref)));
3058 return (message ("<external %q>", sRef_unparseDebug (s->info->ref)));
3060 return (message ("<type %s>", ctype_unparse (s->type)));
3062 if (sRef_hasValue (s))
3064 return (message ("<const %s=%q>", ctype_unparse (s->type), multiVal_unparse (sRef_getValue (s))));
3068 return (message ("<const %s>", ctype_unparse (s->type)));
3071 return (message ("<result %s>", ctype_unparse (s->type)));
3073 return (message ("<spec %s>",
3074 cstring_makeLiteralTemp
3075 (s->info->spec == SR_NOTHING ? "nothing"
3076 : s->info->spec == SR_INTERNAL ? "internalState"
3077 : s->info->spec == SR_SPECSTATE ? "spec state"
3078 : s->info->spec == SR_SYSTEM ? "fileSystem"
3081 return cstring_makeLiteral ("<unknown>");
3087 static /*@only@*/ cstring
3088 sRef_unparseNoArgs (sRef s)
3090 if (sRef_isInvalid (s)) return (cstring_makeLiteral ("?"));
3094 case SK_UNCONSTRAINED:
3095 return (cstring_copy (s->info->fname));
3098 uentry ce = usymtab_getRefQuiet (s->info->cvar->lexlevel,
3099 s->info->cvar->index);
3101 if (uentry_isInvalid (ce))
3103 llcontbug (message ("sRef_unparseNoArgs: bad cvar: %q",
3104 sRef_unparseDebug (s)));
3105 return (sRef_unparseDebug (s));
3109 return (uentry_getName (ce));
3113 if (s->info->arrayfetch->indknown)
3115 return (message ("%q[%d]", sRef_unparseNoArgs (s->info->arrayfetch->arr),
3116 s->info->arrayfetch->ind));
3120 return (message ("%q[]", sRef_unparseNoArgs (s->info->arrayfetch->arr)));
3123 return (message ("%q.%s", sRef_unparseNoArgs (s->info->field->rec),
3124 s->info->field->field));
3127 sRef ref = sRef_fixConj (s->info->ref);
3128 skind sk = ref->kind;
3131 if (skind_isSimple (sk) || sk == SK_PTR)
3133 ret = message ("*%q", sRef_unparseNoArgs (ref));
3137 ret = message ("*(%q)", sRef_unparseNoArgs (ref));
3143 return (message ("&%q", sRef_unparseNoArgs (s->info->ref)));
3145 return (cstring_copy (ctype_unparse (s->info->object)));
3147 return (sRef_unparseNoArgs (s->info->conj->a));
3149 return (message ("result of %s", s->info->fname));
3151 return (message ("<der %q>", sRef_unparseNoArgs (s->info->ref)));
3153 return message ("<ext %q>", sRef_unparseNoArgs (s->info->ref));
3155 return (cstring_makeLiteral
3156 (s->info->spec == SR_NOTHING ? "nothing"
3157 : s->info->spec == SR_INTERNAL ? "internal state"
3158 : s->info->spec == SR_SPECSTATE ? "spec state"
3159 : s->info->spec == SR_SYSTEM ? "file system state"
3162 return cstring_makeLiteral ("result");
3166 return cstring_makeLiteral ("?");
3168 /* llcontbug (message ("sRef_unparseNoArgs: bad case: %q", sRef_unparseDebug (s))); */
3169 return (sRef_unparseDebug (s));
3174 /*@dependent@*/ sRef sRef_makeUnconstrained (cstring fname)
3176 sRef s = sRef_new ();
3178 s->kind = SK_UNCONSTRAINED;
3179 s->info = (sinfo) dmalloc (sizeof (*s->info));
3180 s->info->fname = fname;
3185 cstring sRef_unconstrainedName (sRef s)
3187 llassert (sRef_isUnconstrained (s));
3189 return s->info->fname;
3192 bool sRef_isUnconstrained (sRef s)
3194 return (sRef_isReasonable(s) && s->kind == SK_UNCONSTRAINED);
3197 static /*@dependent@*/ /*@notnull@*/ sRef
3198 sRef_makeCvarAux (int level, usymId index, ctype ct, /*@only@*/ stateInfo stinfo)
3200 sRef s = sRef_newRef ();
3203 s->info = (sinfo) dmalloc (sizeof (*s->info));
3205 s->info->cvar = (cref) dmalloc (sizeof (*s->info->cvar));
3206 s->info->cvar->lexlevel = level;
3207 s->info->cvar->index = index;
3209 /* for now, all globals are defined; all locals, aren't */
3211 if (level <= fileScope)
3213 s->defstate = SS_UNKNOWN;
3217 ctype rct = ctype_realType (ct);
3219 if (level != paramsScope
3220 && (ctype_isStructorUnion (rct) || ctype_isRealArray (rct)))
3222 s->defstate = SS_ALLOCATED;
3223 s->oaliaskind = s->aliaskind = AK_STACK;
3227 s->defstate = SS_UNDEFINED;
3228 s->oaliaskind = s->aliaskind = AK_LOCAL;
3234 llassert (level >= globScope);
3235 llassert (usymId_isValid (index));
3237 DPRINTF (("Made cvar: [%p] %s", s, sRef_unparseDebug (s)));
3238 llassert (valueTable_isUndefined (s->state));
3239 s->state = context_createValueTable (s, stinfo);
3243 /*@dependent@*/ sRef sRef_makeCvar (int level, usymId index, ctype ct, /*@only@*/ stateInfo stinfo)
3245 return (sRef_makeCvarAux (level, index, ct, stinfo));
3248 int sRef_lexLevel (sRef s)
3250 if (sRef_isReasonable (s))
3254 conj = sRef_fixConj (s);
3255 s = sRef_getRootBase (conj);
3257 if (sRef_isReasonable (s) && s->kind == SK_CVAR)
3259 return (s->info->cvar->lexlevel);
3267 sRef_makeGlobal (usymId l, ctype ct, /*@only@*/ stateInfo stinfo)
3269 return (sRef_makeCvar (globScope, l, ct, stinfo));
3273 sRef_setParamNo (sRef s, int l)
3275 llassert (sRef_isReasonable (s) && s->kind == SK_PARAM);
3276 s->info->paramno = l;
3280 /*@dependent@*/ sRef
3281 sRef_makeParam (int l, ctype ct, stateInfo stinfo)
3283 sRef s = sRef_new ();
3288 s->info = (sinfo) dmalloc (sizeof (*s->info));
3289 s->info->paramno = l;
3291 s->defstate = SS_UNKNOWN;
3292 /* (probably defined, unless its an out parameter) */
3294 llassert (valueTable_isUndefined (s->state));
3295 s->state = context_createValueTable (s, stinfo);
3300 sRef_isIndexKnown (sRef arr)
3304 llassert (sRef_isReasonable (arr));
3305 arr = sRef_fixConj (arr);
3307 llassert (arr->kind == SK_ARRAYFETCH);
3308 res = arr->info->arrayfetch->indknown;
3313 sRef_getIndex (sRef arr)
3317 llassert (sRef_isReasonable (arr));
3318 arr = sRef_fixConj (arr);
3320 llassert (arr->kind == SK_ARRAYFETCH);
3322 if (!arr->info->arrayfetch->indknown)
3324 llcontbug (message ("sRef_getIndex: unknown: %q", sRef_unparse (arr)));
3329 result = arr->info->arrayfetch->ind;
3335 static bool sRef_isZerothArrayFetch (/*@notnull@*/ sRef s)
3337 return (s->kind == SK_ARRAYFETCH
3338 && s->info->arrayfetch->indknown
3339 && (s->info->arrayfetch->ind == 0));
3342 /*@exposed@*/ sRef sRef_makeAddress (/*@exposed@*/ sRef t)
3345 if (sRef_isInvalid (t)) return sRef_undefined;
3347 if (sRef_isPointer (t))
3349 return (t->info->ref);
3351 else if (sRef_isZerothArrayFetch (t))
3353 return (t->info->arrayfetch->arr);
3357 sRef s = sRef_newRef ();
3360 s->type = ctype_makePointer (t->type);
3361 s->info = (sinfo) dmalloc (sizeof (*s->info));
3362 s->info->ref = t; /* sRef_copy (t); */ /*@i32@*/
3364 if (t->defstate == SS_UNDEFINED)
3365 /* no! it is allocated even still: && !ctype_isPointer (t->type)) */
3367 s->defstate = SS_ALLOCATED;
3371 s->defstate = t->defstate;
3374 if (t->aliaskind == AK_LOCAL)
3376 if (sRef_isLocalVar (t))
3378 s->aliaskind = AK_STACK;
3382 llassert (valueTable_isUndefined (s->state));
3383 s->state = context_createValueTable (s, stateInfo_makeLoc (g_currentloc));
3388 cstring sRef_getField (sRef s)
3392 llassert (sRef_isReasonable (s));
3393 s = sRef_fixConj (s);
3395 llassertprint (sRef_isReasonable (s) && (s->kind == SK_FIELD),
3396 ("s = %s", sRef_unparseDebug (s)));
3398 res = s->info->field->field;
3402 sRef sRef_getBase (sRef s)
3406 if (sRef_isInvalid (s)) return (sRef_undefined);
3408 s = sRef_fixConj (s);
3419 res = s->info->field->rec;
3423 res = s->info->arrayfetch->arr;
3427 res = sRef_undefined; /* shouldn't need it */
3434 ** same as getBase, except returns invalid
3435 ** (and doesn't use adr's)
3439 sRef_getBaseSafe (sRef s)
3443 if (sRef_isInvalid (s)) { return sRef_undefined; }
3445 s = sRef_fixConj (s);
3453 res = s->info->field->rec; break;
3455 res = s->info->arrayfetch->arr;
3458 res = sRef_undefined; break;
3464 /*@constant int MAXBASEDEPTH;@*/
3465 # define MAXBASEDEPTH 25
3467 static /*@exposed@*/ sRef
3468 sRef_getRootBaseAux (sRef s, int depth)
3470 if (sRef_isInvalid (s)) return sRef_undefined;
3472 if (depth > MAXBASEDEPTH)
3475 ("Warning: reference base limit exceeded for %q. "
3476 "This either means there is a variable with at least "
3477 "%d indirections from this reference, or "
3478 "there is a bug in Splint.",
3483 return sRef_undefined;
3490 return (sRef_getRootBaseAux (s->info->ref, depth + 1));
3492 return (sRef_getRootBaseAux (s->info->field->rec, depth + 1));
3494 return (sRef_getRootBaseAux (s->info->arrayfetch->arr, depth + 1));
3496 return (sRef_getRootBaseAux (sRef_fixConj (s), depth + 1));
3502 sRef sRef_getRootBase (sRef s)
3504 return (sRef_getRootBaseAux (s, 0));
3507 static bool sRef_isDeep (sRef s)
3509 if (sRef_isInvalid (s)) return FALSE;
3519 return (sRef_isDeep (sRef_fixConj (s)));
3525 static int sRef_depth (sRef s)
3527 if (sRef_isInvalid (s)) return 0;
3535 return 1 + sRef_depth (s->info->ref);
3537 return 1 + sRef_depth (s->info->field->rec);
3539 return 1 + sRef_depth (s->info->arrayfetch->arr);
3541 return (sRef_depth (sRef_fixConj (s)));
3548 sRef_makeObject (ctype o)
3550 sRef s = sRef_newRef (); /*@i423 same line is bad...@*/
3552 s->kind = SK_OBJECT;
3553 s->info = (sinfo) dmalloc (sizeof (*s->info));
3554 s->info->object = o;
3555 llassert (valueTable_isUndefined (s->state));
3556 s->state = context_createValueTable (s, stateInfo_makeLoc (g_currentloc));
3561 ** This is used to represent storage referenced by a parameter.
3564 sRef sRef_makeExternal (sRef t)
3566 sRef s = sRef_newRef ();
3568 llassert (sRef_isReasonable (t));
3570 s->kind = SK_EXTERNAL;
3571 s->info = (sinfo) dmalloc (sizeof (*s->info));
3573 s->info->ref = t; /* sRef_copy (t); */ /*@i32 was exposed@*/
3574 llassert (valueTable_isUndefined (s->state));
3575 s->state = context_createValueTable (s, stateInfo_makeLoc (g_currentloc));
3579 /*@dependent@*/ sRef sRef_makeDerived (/*@exposed@*/ sRef t)
3581 if (sRef_isReasonable (t))
3583 sRef s = sRef_newRef ();
3585 s->kind = SK_DERIVED;
3586 s->info = (sinfo) dmalloc (sizeof (*s->info));
3587 s->info->ref = t; /* sRef_copy (t); */ /*@i32@*/
3590 llassert (valueTable_isUndefined (s->state));
3591 s->state = context_createValueTable (s, stateInfo_makeLoc (g_currentloc));
3596 return sRef_undefined;
3601 ** definitely NOT symmetric:
3603 ** res fills in unknown state information from other
3607 sRef_mergeStateQuiet (sRef res, sRef other)
3609 llassert (sRef_isReasonable (res));
3610 llassert (sRef_isReasonable (other));
3612 res->modified = res->modified || other->modified;
3613 res->safe = res->safe && other->safe;
3615 if (res->defstate == SS_UNKNOWN)
3617 res->defstate = other->defstate;
3618 res->definfo = stateInfo_update (res->definfo, other->definfo);
3621 if (res->aliaskind == AK_UNKNOWN ||
3622 (res->aliaskind == AK_LOCAL && alkind_isKnown (other->aliaskind)))
3624 res->aliaskind = other->aliaskind;
3625 res->oaliaskind = other->oaliaskind;
3626 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
3629 if (res->expkind == XO_UNKNOWN)
3631 res->expkind = other->expkind;
3632 res->oexpkind = other->oexpkind;
3633 res->expinfo = stateInfo_update (res->expinfo, other->expinfo);
3636 /* out takes precedence over implicitly defined */
3637 if (res->defstate == SS_DEFINED && other->defstate != SS_UNKNOWN)
3639 res->defstate = other->defstate;
3640 res->definfo = stateInfo_update (res->definfo, other->definfo);
3643 if (sRef_getNullState (other) == NS_ERROR || sRef_getNullState (res) == NS_ERROR)
3645 sRef_setNullState (res, NS_ERROR, fileloc_undefined);
3649 if (sRef_getNullState (other) != NS_UNKNOWN
3650 && (sRef_getNullState (res) == NS_UNKNOWN || sRef_getNullState (res) == NS_NOTNULL
3651 || sRef_getNullState (res) == NS_MNOTNULL))
3653 sRef_updateNullState (res, other);
3659 ** definitely NOT symmetric:
3661 ** res fills in known state information from other
3665 sRef_mergeStateQuietReverse (/*@dependent@*/ sRef res, /*@dependent@*/ sRef other)
3667 bool changed = FALSE;
3669 llassert (sRef_isReasonable (res));
3670 llassert (sRef_isReasonable (other));
3671 sRef_checkMutable (res);
3673 if (res->kind != other->kind)
3679 res->kind = other->kind;
3680 res->type = other->type;
3681 res->info = sinfo_fullCopy (other);
3685 if (!ctype_equal (res->type, other->type))
3688 res->type = other->type;
3691 sinfo_update (res, other);
3694 res->modified = res->modified || other->modified;
3695 res->safe = res->safe && other->safe;
3697 if (res->aliaskind != other->aliaskind
3698 && (res->aliaskind == AK_UNKNOWN
3699 || ((res->aliaskind == AK_LOCAL
3700 || (res->aliaskind == AK_REFCOUNTED
3701 && other->aliaskind != AK_LOCAL))
3702 && other->aliaskind != AK_UNKNOWN)))
3705 res->aliaskind = other->aliaskind;
3706 res->oaliaskind = other->oaliaskind;
3707 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
3710 if (other->expkind != XO_UNKNOWN && other->expkind != res->expkind)
3713 res->expkind = other->expkind;
3714 res->expinfo = stateInfo_update (res->expinfo, other->expinfo);
3717 if (other->oexpkind != XO_UNKNOWN)
3719 res->oexpkind = other->oexpkind;
3722 /* out takes precedence over implicitly defined */
3724 if (res->defstate != other->defstate)
3726 if (other->defstate != SS_UNKNOWN)
3728 res->defstate = other->defstate;
3732 if (sRef_getNullState (other) == NS_ERROR || sRef_getNullState (res) == NS_ERROR)
3734 if (sRef_getNullState (res) != NS_ERROR)
3736 sRef_setNullStateN (res, NS_ERROR);
3742 if (sRef_getNullState (other) != NS_UNKNOWN && sRef_getNullState (other) != sRef_getNullState (res))
3745 sRef_updateNullState (res, other);
3751 sRef_clearDerived (res);
3756 sRef_mergeState (sRef res, sRef other, clause cl, fileloc loc)
3758 if (sRef_isReasonable (res) && sRef_isReasonable (other))
3760 sRef_mergeStateAux (res, other, cl, FALSE, loc, TRUE);
3764 if (sRef_isInvalid (res))
3766 llbug (message ("sRef_mergeState: invalid res sRef: %q",
3767 sRef_unparseDebug (other)));
3771 llbug (message ("sRef_mergeState: invalid other sRef: %q",
3772 sRef_unparseDebug (res)));
3778 sRef_mergeOptState (sRef res, sRef other, clause cl, fileloc loc)
3780 if (sRef_isReasonable (res) && sRef_isReasonable (other))
3782 sRef_mergeStateAux (res, other, cl, TRUE, loc, TRUE);
3786 if (sRef_isInvalid (res))
3788 llbug (message ("sRef_mergeOptState: invalid res sRef: %q",
3789 sRef_unparseDebug (other)));
3793 llbug (message ("sRef_mergeOptState: invalid other sRef: %q",
3794 sRef_unparseDebug (res)));
3800 sRef_mergeStateAux (/*@notnull@*/ sRef res, /*@notnull@*/ sRef other,
3801 clause cl, bool opt, fileloc loc,
3805 llassertfatal (sRef_isReasonable (res));
3806 llassertfatal (sRef_isReasonable (other));
3808 DPRINTF (("Merge aux: %s / %s",
3809 sRef_unparseFull (res),
3810 sRef_unparseFull (other)));
3812 sRef_checkMutable (res);
3813 sRef_checkMutable (other);
3815 res->modified = res->modified || other->modified;
3817 if (res->kind == other->kind
3818 || (other->kind == SK_UNKNOWN || res->kind == SK_UNKNOWN))
3820 sstate odef = other->defstate;
3821 sstate rdef = res->defstate;
3822 nstate onull = sRef_getNullState (other);
3825 ** yucky stuff to handle
3830 if (other->defstate == SS_DEAD
3831 && ((sRef_isOnly (res) && sRef_definitelyNull (res))
3832 || (res->defstate == SS_UNDEFINED
3833 || res->defstate == SS_UNUSEABLE)))
3835 if (res->defstate == SS_UNDEFINED
3836 || res->defstate == SS_UNUSEABLE)
3838 res->defstate = SS_UNUSEABLE;
3842 res->defstate = SS_DEAD;
3845 res->definfo = stateInfo_update (res->definfo, other->definfo);
3846 sRef_clearDerived (other);
3847 sRef_clearDerived (res);
3849 else if (res->defstate == SS_DEAD
3850 && ((sRef_isOnly (other) && sRef_definitelyNull (other))
3851 || (other->defstate == SS_UNDEFINED
3852 || other->defstate == SS_UNUSEABLE)))
3854 if (other->defstate == SS_UNDEFINED
3855 || other->defstate == SS_UNUSEABLE)
3857 res->defstate = SS_UNUSEABLE;
3861 res->defstate = SS_DEAD;
3864 sRef_clearDerived (other);
3865 sRef_clearDerived (res);
3867 else if (res->defstate == SS_DEFINED
3868 && (other->defstate == SS_ALLOCATED
3869 && sRef_definitelyNull (other)))
3871 other->defstate = SS_DEFINED; /* definitely null! */
3873 else if (other->defstate == SS_DEFINED
3874 && (res->defstate == SS_ALLOCATED && sRef_definitelyNull (res)))
3876 res->defstate = SS_DEFINED;
3877 res->definfo = stateInfo_update (res->definfo, other->definfo);
3884 if (res->defstate == SS_DEAD && other->defstate == SS_DEAD)
3886 sRef_clearDerived (other);
3887 sRef_clearDerived (res);
3891 ** only & dead isn't really an only!
3894 if (alkind_isOnly (other->aliaskind) && other->defstate == SS_DEAD)
3896 other->aliaskind = AK_UNKNOWN;
3899 if (alkind_isOnly (res->aliaskind) && res->defstate == SS_DEAD)
3901 res->aliaskind = AK_UNKNOWN;
3905 ** Dead and dependent -> dead
3908 if (alkind_isDependent (other->aliaskind) && res->defstate == SS_DEAD)
3910 other->aliaskind = AK_UNKNOWN;
3911 other->defstate = SS_DEAD;
3912 sRef_clearDerived (res);
3913 sRef_clearDerived (other);
3916 if (alkind_isDependent (res->aliaskind) && other->defstate == SS_DEAD)
3918 res->aliaskind = AK_UNKNOWN;
3919 res->defstate = SS_DEAD;
3920 sRef_clearDerived (res);
3921 sRef_clearDerived (other);
3925 ** must do alias combine first, since it depends on
3926 ** original values of state and null.
3929 sRef_combineAliasKinds (res, other, cl, loc);
3930 sRef_combineDefState (res, other);
3931 sRef_combineNullState (res, other);
3933 if (rdef == SS_ALLOCATED || rdef == SS_SPECIAL)
3935 if (odef == SS_DEFINED)
3937 if (onull == NS_DEFNULL || onull == NS_CONSTNULL)
3939 res->deriv = sRefSet_copyInto (res->deriv, other->deriv);
3940 DPRINTF (("Copy derivs: %s", sRef_unparseFull (res)));
3943 else if (odef == SS_ALLOCATED || odef == SS_SPECIAL)
3948 if (ctype_isUnion (ctype_realType (sRef_getType (res))))
3950 res->deriv = sRef_mergeUnionDerivs (res->deriv,
3953 DPRINTF (("Copy derivs: %s", sRef_unparseFull (res)));
3957 res->deriv = sRef_mergeDerivs (res->deriv, other->deriv,
3959 DPRINTF (("Copy derivs: %s", sRef_unparseFull (res)));
3967 res->deriv = sRef_mergeDerivs (res->deriv, other->deriv,
3969 DPRINTF (("Copy derivs: %s", sRef_unparseFull (res)));
3979 if (rdef == SS_PDEFINED
3980 || (rdef == SS_DEFINED && odef == SS_PDEFINED))
3984 res->deriv = sRef_mergePdefinedDerivs (res->deriv, other->deriv,
3986 DPRINTF (("Copy derivs: %s", sRef_unparseFull (res)));
3991 if ((rdef == SS_DEFINED || rdef == SS_UNKNOWN)
3992 && res->defstate == SS_ALLOCATED)
3994 res->deriv = sRefSet_copyInto (res->deriv, other->deriv);
4000 res->deriv = sRef_mergeDerivs (res->deriv, other->deriv,
4002 DPRINTF (("Copy derivs: %s", sRef_unparseFull (res)));
4009 sRef_combineExKinds (res, other);
4013 if (res->kind == SK_ARRAYFETCH && other->kind == SK_PTR)
4015 sRef nother = sRef_buildArrayFetchKnown (sRef_getBase (other), 0);
4017 sRef_copyState (nother, other);
4018 sRef_mergeStateAux (res, nother, cl, opt, loc, doDerivs);
4020 else if (res->kind == SK_PTR && other->kind == SK_ARRAYFETCH)
4022 sRef nother = sRef_buildPointer (sRef_getBase (other));
4024 if (sRef_isReasonable (nother))
4026 sRef_copyState (nother, other);
4027 sRef_mergeStateAux (res, nother, cl, opt, loc, doDerivs);
4032 llcontbug (message ("merge conj: %q / %q", sRef_unparseFull (res),
4033 sRef_unparseFull (other)));
4039 ** Merge value table states
4046 ** This doesn't do anything. And its broken too...
4049 valueTable_elements (res->state, key, sv)
4051 stateValue os = valueTable_lookup (other->state, key);
4052 /*@unused@*/ int val;
4053 /*@unused@*/ char *msg;
4055 llassert (stateValue_isDefined (os));
4057 DPRINTF (("Merge state: %s / %s",
4058 cstring_toCharsSafe (stateValue_unparse (sv)),
4059 cstring_toCharsSafe (stateValue_unparse (os))));
4061 val = valueMatix_lookup (key,
4062 stateValue_getValue (os),
4063 stateValue_getValue (sv),
4065 DPRINTF (("Val: %d / %s", val, msg));
4067 } end_valueTable_elements ;
4070 DPRINTF (("Merge aux: %s / %s",
4071 sRef_unparseFull (res),
4072 sRef_unparseFull (other)));
4076 sRef_mergeUnionDerivs (/*@only@*/ sRefSet res,
4077 /*@exposed@*/ sRefSet other, bool opt,
4078 clause cl, fileloc loc)
4080 if (sRefSet_isEmpty (res))
4082 return sRefSet_copyInto (res, other);
4086 sRefSet_allElements (other, el)
4088 if (sRef_isReasonable (el))
4090 sRef e2 = sRefSet_lookupMember (other, el);
4092 if (sRef_isReasonable (e2))
4094 sRef_mergeStateAux (el, e2, cl, opt, loc, FALSE);
4098 res = sRefSet_insert (res, el);
4101 } end_sRefSet_allElements ;
4107 static /*@only@*/ sRefSet
4108 sRef_mergeDerivs (/*@only@*/ sRefSet res, sRefSet other,
4109 bool opt, clause cl, fileloc loc)
4111 sRefSet ret = sRefSet_new ();
4113 sRefSet_allElements (res, el)
4115 if (sRef_isReasonable (el))
4117 sRef e2 = sRefSet_lookupMember (other, el);
4119 if (sRef_isReasonable (e2))
4121 if (el->defstate == SS_ALLOCATED &&
4122 e2->defstate == SS_PDEFINED)
4124 e2->defstate = SS_ALLOCATED;
4126 else if (e2->defstate == SS_ALLOCATED &&
4127 el->defstate == SS_PDEFINED)
4129 el->defstate = SS_ALLOCATED;
4130 sRef_clearDerived (el);
4132 else if ((el->defstate == SS_DEAD || sRef_isKept (el)) &&
4133 (e2->defstate == SS_DEFINED && !sRef_isKept (e2)))
4136 if (checkDeadState (el, TRUE, loc))
4138 if (sRef_isThroughArrayFetch (el))
4140 sRef_maybeKill (el, loc);
4141 sRef_maybeKill (e2, loc);
4145 else if ((e2->defstate == SS_DEAD || sRef_isKept (e2)) &&
4146 (el->defstate == SS_DEFINED && !sRef_isKept (el)))
4149 if (checkDeadState (e2, FALSE, loc))
4151 if (sRef_isThroughArrayFetch (el))
4153 sRef_maybeKill (el, loc);
4154 sRef_maybeKill (e2, loc);
4158 else if (el->defstate == SS_DEFINED &&
4159 e2->defstate == SS_PDEFINED)
4161 DPRINTF (("set pdefined: %s", sRef_unparseFull (el)));
4162 el->defstate = SS_PDEFINED;
4164 else if (e2->defstate == SS_DEFINED &&
4165 el->defstate == SS_PDEFINED)
4167 DPRINTF (("set pdefined: %s", sRef_unparseFull (e2)));
4168 e2->defstate = SS_PDEFINED;
4175 if (ctype_isUnion (ctype_realType (sRef_getType (el))))
4177 el->deriv = sRef_mergeUnionDerivs (el->deriv, e2->deriv,
4182 el->deriv = sRef_mergeDerivs (el->deriv, e2->deriv, opt, cl, loc);
4185 if (sRef_equivalent (el, e2))
4187 ret = sRefSet_insert (ret, el);
4191 sRef sr = sRef_leastCommon (el, e2);
4193 if (sRef_isReasonable (sr))
4195 ret = sRefSet_insert (ret, sr);
4203 (void) sRefSet_delete (other, e2);
4205 else /* not defined */
4207 (void) checkDeadState (el, TRUE, loc);
4210 } end_sRefSet_allElements;
4212 sRefSet_allElements (other, el)
4214 if (sRef_isReasonable (el))
4216 (void) checkDeadState (el, FALSE, loc);
4218 } end_sRefSet_allElements;
4225 ** Returns TRUE is there is an error.
4228 static bool checkDeadState (/*@notnull@*/ sRef el, bool tbranch, fileloc loc)
4231 ** usymtab_isGuarded --- the utab should still be in the
4232 ** state of the alternate branch.
4234 ** tbranch TRUE means el is released in the last branch, e.g.
4235 ** if (x != NULL) { ; } else { sfree (x); }
4236 ** so, if x is null in the other branch no error is reported.
4238 ** tbranch FALSE means this is the other branch:
4239 ** if (x != NULL) { sfree (x); } else { ; }
4240 ** so, if x is null in this branch there is no error.
4244 if ((sRef_isDead (el) || sRef_isKept (el))
4245 && !sRef_isDeepUnionField (el) && !sRef_isThroughArrayFetch (el))
4250 if (usymtab_isDefinitelyNullDeep (el))
4257 if (usymtab_isAltDefinitelyNullDeep (el))
4265 message ("Storage %q is %q in one path, but live in another.",
4267 cstring_makeLiteral (sRef_isKept (el)
4268 ? "kept" : "released")),
4271 if (sRef_isKept (el))
4273 sRef_showAliasInfo (el);
4277 sRef_showStateInfo (el);
4280 /* prevent further errors */
4281 el->defstate = SS_UNKNOWN;
4282 sRef_setAliasKind (el, AK_ERROR, fileloc_undefined);
4292 checkDerivDeadState (/*@notnull@*/ sRef el, bool tbranch, fileloc loc)
4295 if (checkDeadState (el, tbranch, loc))
4297 sRefSet_allElements (el->deriv, t)
4299 if (sRef_isReasonable (t))
4301 checkDerivDeadState (t, tbranch, loc);
4303 } end_sRefSet_allElements;
4308 sRef_mergePdefinedDerivs (sRefSet res, sRefSet other, bool opt,
4309 clause cl, fileloc loc)
4311 sRefSet ret = sRefSet_new ();
4313 sRefSet_allElements (res, el)
4315 if (sRef_isReasonable (el))
4317 sRef e2 = sRefSet_lookupMember (other, el);
4319 if (sRef_isReasonable (e2))
4321 if (sRef_isAllocated (el) && !sRef_isAllocated (e2))
4325 else if (sRef_isAllocated (e2) && !sRef_isAllocated (el))
4327 el->deriv = sRefSet_copyInto (el->deriv, e2->deriv);
4331 el->deriv = sRef_mergePdefinedDerivs (el->deriv, e2->deriv,
4335 sRef_mergeStateAux (el, e2, cl, opt, loc, FALSE);
4337 ret = sRefSet_insert (ret, el);
4338 (void) sRefSet_delete (other, e2);
4344 checkDerivDeadState (el, (cl == FALSECLAUSE), loc);
4347 ret = sRefSet_insert (ret, el);
4350 } end_sRefSet_allElements;
4352 sRefSet_allElements (other, el)
4354 if (sRef_isReasonable (el))
4356 if (!sRefSet_member (ret, el))
4358 /* was cl == FALSECLAUSE */
4359 checkDerivDeadState (el, FALSE, loc);
4360 ret = sRefSet_insert (ret, el);
4365 ** it's okay --- member is a different equality test
4369 } end_sRefSet_allElements;
4375 sRef sRef_makeConj (/*@exposed@*/ /*@returned@*/ sRef a, /*@exposed@*/ sRef b)
4377 llassert (sRef_isReasonable (a));
4378 llassert (sRef_isReasonable (b));
4380 if (!sRef_equivalent (a, b))
4382 sRef s = sRef_newRef ();
4385 s->info = (sinfo) dmalloc (sizeof (*s->info));
4386 s->info->conj = (cjinfo) dmalloc (sizeof (*s->info->conj));
4387 s->info->conj->a = a; /* sRef_copy (a) */ /*@i32*/ ;
4388 s->info->conj->b = b; /* sRef_copy (b);*/ /*@i32@*/ ;
4390 if (ctype_equal (a->type, b->type)) s->type = a->type;
4391 else s->type = ctype_makeConj (a->type, b->type);
4393 if (a->defstate == b->defstate)
4395 s->defstate = a->defstate;
4399 s->defstate = SS_UNKNOWN;
4402 sRef_setNullStateN (s, NS_UNKNOWN);
4404 s->safe = a->safe && b->safe;
4405 s->aliaskind = alkind_resolve (a->aliaskind, b->aliaskind);
4407 llassert (valueTable_isUndefined (s->state));
4408 s->state = context_createValueTable (s, stateInfo_makeLoc (g_currentloc));
4413 /*@-exposetrans@*/ return a; /*@=exposetrans@*/
4417 /*@dependent@*/ sRef
4420 sRef s = sRef_new ();
4422 s->kind = SK_UNKNOWN;
4426 static /*@owned@*/ /*@notnull@*/ sRef
4427 sRef_makeSpecial (speckind sk) /*@*/
4429 sRef s = sRef_new ();
4431 s->kind = SK_SPECIAL;
4432 s->info = (sinfo) dmalloc (sizeof (*s->info));
4434 /*@-dependenttrans@*/
4436 /*@=dependenttrans@*/
4439 static /*@owned@*/ sRef srnothing = sRef_undefined;
4440 static /*@owned@*/ sRef srinternal = sRef_undefined;
4441 static /*@owned@*/ sRef srsystem = sRef_undefined;
4442 static /*@owned@*/ sRef srspec = sRef_undefined;
4444 /*@dependent@*/ sRef
4445 sRef_makeNothing (void)
4447 if (sRef_isInvalid (srnothing))
4449 srnothing = sRef_makeSpecial (SR_NOTHING);
4456 sRef_makeInternalState (void)
4458 if (sRef_isInvalid (srinternal))
4460 srinternal = sRef_makeSpecial (SR_INTERNAL);
4467 sRef_makeSpecState (void)
4469 if (sRef_isInvalid (srspec))
4471 srspec = sRef_makeSpecial (SR_SPECSTATE);
4478 sRef_makeSystemState (void)
4480 if (sRef_isInvalid (srsystem))
4482 srsystem = sRef_makeSpecial (SR_SYSTEM);
4489 sRef_makeGlobalMarker (void)
4491 sRef s = sRef_makeSpecial (SR_GLOBALMARKER);
4492 llassert (valueTable_isUndefined (s->state));
4493 s->state = context_createGlobalMarkerValueTable (stateInfo_undefined);
4498 sRef_makeResult (ctype c)
4500 sRef s = sRef_newRef ();
4502 s->kind = SK_RESULT;
4504 s->defstate = SS_UNKNOWN;
4505 s->aliaskind = AK_UNKNOWN;
4506 sRef_setNullStateN (s, NS_UNKNOWN);
4507 llassert (valueTable_isUndefined (s->state));
4508 s->state = context_createValueTable (s, stateInfo_makeLoc (g_currentloc));
4510 DPRINTF (("Result: [%p] %s", s, sRef_unparseFull (s)));
4516 sRef_isNothing (sRef s)
4518 return (sRef_isKindSpecial (s) && s->info->spec == SR_NOTHING);
4522 sRef_isInternalState (sRef s)
4524 return (sRef_isKindSpecial (s) && s->info->spec == SR_INTERNAL);
4528 sRef_isSpecInternalState (sRef s)
4530 return (sRef_isKindSpecial (s)
4531 && (s->info->spec == SR_INTERNAL || s->info->spec == SR_SPECSTATE));
4535 sRef_isSpecState (sRef s)
4537 return (sRef_isKindSpecial (s) && s->info->spec == SR_SPECSTATE);
4541 sRef_isResult (sRef s)
4543 return (sRef_isReasonable (s) && s->kind == SK_RESULT);
4547 sRef_isSystemState (sRef s)
4549 return (sRef_isKindSpecial (s) && s->info->spec == SR_SYSTEM);
4553 sRef_isGlobalMarker (sRef s)
4555 return (sRef_isKindSpecial (s) && s->info->spec == SR_GLOBALMARKER);
4559 sRef_getScopeIndex (sRef s)
4561 llassert (sRef_isReasonable (s));
4562 llassert (sRef_isCvar (s));
4564 return (s->info->cvar->index);
4568 sRef_makeSafe (sRef s)
4570 if (sRef_isReasonable (s))
4577 sRef_makeUnsafe (sRef s)
4579 if (sRef_isReasonable (s))
4586 ** memory state operations
4589 /*@only@*/ cstring sRef_unparseFull (sRef s)
4591 if (sRef_isInvalid (s)) return (cstring_undefined);
4593 return (message ("[%p] %q - %q [%s] { %q } < %q >",
4595 sRef_unparseDebug (s),
4596 sRef_unparseState (s),
4597 exkind_unparse (s->oexpkind),
4598 sRefSet_unparseDebug (s->deriv),
4599 valueTable_unparse (s->state)));
4602 /*@unused@*/ cstring sRef_unparseDeep (sRef s)
4604 cstring st = cstring_undefined;
4606 st = message ("%q:", sRef_unparseFull (s));
4608 if (sRef_isReasonable (s))
4610 sRefSet_allElements (s->deriv, el)
4612 st = message("%q\n%q", st, sRef_unparseDeep (el));
4613 } end_sRefSet_allElements ;
4619 /*@only@*/ cstring sRef_unparseState (sRef s)
4621 if (sRef_isConj (s))
4623 return (message ("%q | %q",
4624 sRef_unparseState (s->info->conj->a),
4625 sRef_unparseState (s->info->conj->b)));
4628 if (sRef_isInvalid (s))
4630 return (cstring_makeLiteral ("<invalid>"));
4633 return (message ("%s.%s.%s.%s",
4634 alkind_unparse (s->aliaskind),
4635 nstate_unparse (sRef_getNullState (s)),
4636 exkind_unparse (s->expkind),
4637 sstate_unparse (s->defstate)));
4640 bool sRef_isNotUndefined (sRef s)
4642 return (sRef_isInvalid (s)
4643 || (s->defstate != SS_UNDEFINED
4644 && s->defstate != SS_UNUSEABLE
4645 && s->defstate != SS_DEAD));
4648 ynm sRef_isWriteable (sRef s)
4650 if (sRef_isInvalid (s)) return MAYBE;
4652 if (sRef_isConj (s) && s->defstate == SS_UNKNOWN)
4654 if (ynm_toBoolStrict (sRef_isWriteable (sRef_getConjA (s))))
4656 if (ynm_toBoolStrict (sRef_isWriteable (sRef_getConjB (s))))
4664 if (ynm_toBoolStrict (sRef_isWriteable (sRef_getConjB (s))))
4672 return (ynm_fromBool (s->defstate != SS_UNUSEABLE));
4675 bool sRef_hasNoStorage (sRef s)
4677 return (!sRef_isAllocatedStorage (s) || sRef_isDefinitelyNull (s));
4680 bool sRef_isStrictReadable (sRef s)
4682 return (ynm_toBoolStrict (sRef_isValidLvalue (s)));
4686 ** Is this what is does?
4687 ** Returns YES if s can be used as an rvalue,
4688 ** MAYBE if its not clear
4689 ** NO if s cannot be safely used as an rvalue.
4692 ynm sRef_isValidLvalue (sRef s)
4696 if (sRef_isInvalid (s)) return YES;
4700 if (sRef_isConj (s) && s->defstate == SS_UNKNOWN)
4702 if (ynm_toBoolStrict (sRef_isValidLvalue (sRef_getConjA (s))))
4704 if (ynm_toBoolStrict (sRef_isValidLvalue (sRef_getConjB (s))))
4712 if (ynm_toBoolStrict (sRef_isValidLvalue (sRef_getConjB (s))))
4719 else if (ss == SS_HOFFA)
4721 if (context_getFlag (FLG_STRICTUSERELEASED))
4732 return (ynm_fromBool (ss == SS_DEFINED
4735 || ss == SS_PDEFINED
4738 || ss == SS_ALLOCATED
4739 || ss == SS_KILLED /* evans 2001-05-26: added this for killed globals */
4740 || ss == SS_UNKNOWN));
4744 static /*@exposed@*/ sRef whatUndefined (/*@exposed@*/ sRef fref, int depth)
4749 if (depth > MAXDEPTH)
4752 ("Warning: check definition limit exceeded, checking %q. "
4753 "This either means there is a variable with at least "
4754 "%d indirections apparent in the program text, or "
4755 "there is a bug in Splint.",
4756 sRef_unparse (fref),
4760 return sRef_undefined;
4763 if (!sRef_isKnown (fref) || sRef_isAnyDefined (fref))
4765 return sRef_undefined;
4768 if (sRef_isUnuseable (fref) || sRef_isStateUndefined (fref))
4773 ct = ctype_realType (sRef_getType (fref));
4775 if (ctype_isUnknown (ct))
4777 return sRef_undefined;
4779 else if (ctype_isPointer (ct) || ctype_isArray (ct))
4781 if (sRef_isStateUnknown (fref))
4783 return sRef_undefined;
4787 sRef fptr = sRef_constructDeref (fref);
4789 return (whatUndefined (fptr, depth + 1));
4792 else if (ctype_isStruct (ct))
4794 bool hasOneDefined = FALSE;
4796 if (sRef_isStateUnknown (fref))
4801 if (sRef_isPdefined (fref) || sRef_isAnyDefined (fref))
4803 sRefSet_realElements (sRef_derivedFields (fref), sr)
4805 hasOneDefined = TRUE;
4807 if (sRef_isField (sr))
4809 cstring fieldname = sRef_getField (sr);
4810 sRef fldref = sRef_makeField (fref, fieldname);
4811 bool shouldCheck = !sRef_isRecursiveField (fldref);
4815 sRef wdef = whatUndefined (fldref, depth + 1);
4817 if (sRef_isReasonable (wdef))
4823 } end_sRefSet_realElements;
4825 else if (sRef_isAllocated (fref))
4828 ** for structures, each field must be completely defined
4831 uentryList fields = ctype_getFields (ct);
4833 uentryList_elements (fields, ue)
4835 cstring name = uentry_getRealName (ue);
4836 sRef ffield = sRef_makeField (fref, name);
4837 bool shouldCheck = !sRef_isRecursiveField (ffield);
4839 if (sRef_isRelDef (uentry_getSref (ue)))
4847 sRef wdef = whatUndefined (ffield, depth + 1);
4849 if (sRef_isInvalid (wdef))
4855 } end_uentryList_elements;
4862 else if (ctype_isUnion (ct))
4871 return sRef_undefined;
4874 static bool checkDefined (/*@temp@*/ sRef sr)
4876 /*@-temptrans@*/ /* the result from whatUndefined is lost */
4877 return (sRef_isInvalid (whatUndefined (sr, 0)));
4881 bool sRef_isReallyDefined (sRef s)
4883 if (sRef_isReasonable (s))
4885 if (sRef_isAnyDefined (s))
4891 if (sRef_isAllocated (s) || sRef_isPdefined (s))
4893 return checkDefined (s);
4907 void sRef_showNotReallyDefined (sRef s)
4909 if (sRef_isReasonable (s))
4911 if (sRef_isAnyDefined (s))
4917 if (sRef_isAllocated (s) || sRef_isPdefined (s))
4919 /*@-temptrans@*/ /* the result of whatUndefined is lost */
4920 sRef ref = whatUndefined (s, 0);
4922 llassert (sRef_isReasonable (ref));
4927 (message ("This sub-reference is %s: %q",
4928 sstate_unparse (sRef_getDefState (ref)),
4929 sRef_unparse (ref)));
4944 sstate sRef_getDefState (sRef s)
4946 if (sRef_isInvalid (s)) return (SS_UNKNOWN);
4947 return (s->defstate);
4950 void sRef_setDefState (sRef s, sstate defstate, fileloc loc)
4952 sRef_checkMutable (s);
4953 sRef_setStateAux (s, defstate, loc);
4956 static void sRef_clearAliasStateAux (sRef s, fileloc loc)
4958 sRef_checkMutable (s);
4959 sRef_setAliasKind (s, AK_ERROR, loc);
4962 void sRef_clearAliasState (sRef s, fileloc loc)
4964 sRef_checkMutable (s);
4965 sRef_aliasSetComplete (sRef_clearAliasStateAux, s, loc);
4968 void sRef_setAliasKindComplete (sRef s, alkind kind, fileloc loc)
4970 sRef_checkMutable (s);
4971 sRef_aliasSetCompleteAlkParam (sRef_setAliasKind, s, kind, loc);
4974 void sRef_setAliasKind (sRef s, alkind kind, fileloc loc)
4976 sRef_checkMutable (s);
4978 if (sRef_isReasonable (s))
4980 sRef_clearDerived (s);
4982 if ((kind != s->aliaskind && kind != s->oaliaskind)
4983 && fileloc_isDefined (loc))
4985 s->aliasinfo = stateInfo_updateLoc (s->aliasinfo, loc);
4988 s->aliaskind = kind;
4992 void sRef_setOrigAliasKind (sRef s, alkind kind)
4994 sRef_checkMutable (s);
4996 if (sRef_isReasonable (s))
4998 s->oaliaskind = kind;
5002 exkind sRef_getExKind (sRef s)
5004 if (sRef_isReasonable (s))
5006 return (s->expkind);
5014 exkind sRef_getOrigExKind (sRef s)
5016 if (sRef_isReasonable (s))
5018 return (s->oexpkind);
5026 static void sRef_clearExKindAux (sRef s, fileloc loc)
5028 sRef_checkMutable (s);
5029 sRef_setExKind (s, XO_UNKNOWN, loc);
5032 void sRef_setObserver (sRef s, fileloc loc)
5034 sRef_checkMutable (s);
5035 sRef_setExKind (s, XO_OBSERVER, loc);
5038 void sRef_setExposed (sRef s, fileloc loc)
5040 sRef_checkMutable (s);
5041 sRef_setExKind (s, XO_EXPOSED, loc);
5044 void sRef_clearExKindComplete (sRef s, fileloc loc)
5046 (void) sRef_aliasSetComplete (sRef_clearExKindAux, s, loc);
5049 void sRef_setExKind (sRef s, exkind exp, fileloc loc)
5051 sRef_checkMutable (s);
5053 if (sRef_isReasonable (s))
5055 if (s->expkind != exp)
5057 s->expinfo = stateInfo_updateLoc (s->expinfo, loc);
5065 ** s1->derived = s2->derived
5068 static void sRef_copyRealDerived (sRef s1, sRef s2)
5070 DPRINTF (("Copy real: %s / %s", sRef_unparse (s1), sRef_unparse (s2)));
5071 sRef_checkMutable (s1);
5073 if (sRef_isReasonable (s1) && sRef_isReasonable (s2))
5075 sRef sb = sRef_getRootBase (s1);
5077 sRefSet_clear (s1->deriv);
5079 sRefSet_allElements (s2->deriv, el)
5081 if (sRef_isReasonable (el))
5083 sRef rb = sRef_getRootBase (el);
5085 if (!sRef_same (rb, sb))
5087 sRef fb = sRef_fixDirectBase (el, s1);
5089 if (sRef_isReasonable (fb))
5091 sRef_copyRealDerived (fb, el);
5092 sRef_addDeriv (s1, fb);
5097 sRef_addDeriv (s1, el);
5100 } end_sRefSet_allElements ;
5105 void sRef_copyRealDerivedComplete (sRef s1, sRef s2)
5107 sRef_innerAliasSetCompleteParam (sRef_copyRealDerived, s1, s2);
5110 void sRef_setUndefined (sRef s, fileloc loc)
5112 sRef_checkMutable (s);
5114 if (sRef_isReasonable (s))
5116 s->defstate = SS_UNDEFINED;
5118 if (fileloc_isDefined (loc))
5120 s->definfo = stateInfo_updateLoc (s->definfo, loc);
5123 sRef_clearDerived (s);
5127 static void sRef_setDefinedAux (sRef s, fileloc loc, bool clear)
5129 sRef_checkMutable (s);
5130 if (sRef_isInvalid (s)) return;
5132 DPRINTF (("Set defined: %s", sRef_unparseFull (s)));
5134 if (s->defstate != SS_DEFINED && fileloc_isDefined (loc))
5136 s->definfo = stateInfo_updateLoc (s->definfo, loc);
5139 s->defstate = SS_DEFINED;
5141 DPRINTF (("Set defined: %s", sRef_unparseFull (s)));
5143 /* e.g., if x is allocated, *x = 3 defines x */
5145 if (s->kind == SK_PTR)
5147 sRef p = s->info->ref;
5150 if (p->defstate == SS_ALLOCATED
5151 || p->defstate == SS_SPECIAL) /* evans 2001-07-12: shouldn't need this */
5153 sRef_setDefinedAux (p, loc, clear);
5157 ** Defines a[0] also:
5160 arr = sRef_findDerivedArrayFetch (p, FALSE, 0, FALSE);
5162 if (sRef_isReasonable (arr))
5164 sRef_setDefinedAux (arr, loc, clear);
5167 else if (s->kind == SK_ARRAYFETCH)
5169 if (!s->info->arrayfetch->indknown
5170 || (s->info->arrayfetch->ind == 0))
5172 sRef p = s->info->arrayfetch->arr;
5173 sRef ptr = sRef_constructPointer (p);
5175 if (sRef_isReasonable (ptr))
5177 if (ptr->defstate == SS_ALLOCATED
5178 || ptr->defstate == SS_UNDEFINED
5179 || ptr->defstate == SS_SPECIAL) /* evans 2001-07-12: shouldn't need this */
5181 sRef_setDefinedAux (ptr, loc, clear);
5185 if (p->defstate == SS_RELDEF)
5189 else if (p->defstate == SS_ALLOCATED || p->defstate == SS_PDEFINED
5190 || p->defstate == SS_SPECIAL) /* evans 2001-07-12: shouldn't need this */
5192 p->defstate = SS_DEFINED;
5199 else if (s->kind == SK_FIELD)
5201 sRef parent = s->info->field->rec;
5203 if (sRef_isReasonable (parent))
5205 if (ctype_isUnion (ctype_realType (parent->type)))
5208 ** Should not clear derived from here.
5211 sRef_setDefinedNoClear (parent, loc);
5215 ; /* Nothing to do for structures. */
5227 sRef_clearDerived (s);
5231 /* evans 2001-07-12: need to define the derived references */
5232 sRefSet_elements (s->deriv, el)
5234 llassert (sRef_isReasonable (el));
5235 el->defstate = SS_DEFINED;
5236 } end_sRefSet_elements ;
5239 DPRINTF (("Set defined: %s", sRef_unparseFull (s)));
5242 static void sRef_setPartialDefined (sRef s, fileloc loc)
5244 sRef_checkMutable (s);
5246 if (!sRef_isPartial (s))
5248 sRef_setDefined (s, loc);
5252 void sRef_setPartialDefinedComplete (sRef s, fileloc loc)
5254 sRef_innerAliasSetComplete (sRef_setPartialDefined, s, loc);
5257 void sRef_setDefinedComplete (sRef s, fileloc loc)
5259 sRef_innerAliasSetComplete (sRef_setDefined, s, loc);
5262 void sRef_setDefinedCompleteDirect (sRef s, fileloc loc)
5266 aliases = usymtab_allAliases (s);
5267 DPRINTF (("Set defined complete: %s", sRef_unparseFull (s)));
5268 DPRINTF (("All aliases: %s", sRefSet_unparseFull (aliases)));
5270 sRef_setDefined (s, loc);
5272 sRefSet_realElements (aliases, current)
5274 if (sRef_isReasonable (current))
5276 current = sRef_updateSref (current);
5277 sRef_setDefined (current, loc);
5279 } end_sRefSet_realElements;
5281 sRefSet_free (aliases);
5282 sRef_innerAliasSetComplete (sRef_setDefined, s, loc);
5285 void sRef_setDefined (sRef s, fileloc loc)
5287 sRef_checkMutable (s);
5288 sRef_setDefinedAux (s, loc, TRUE);
5291 static void sRef_setDefinedNoClear (sRef s, fileloc loc)
5293 sRef_checkMutable (s);
5294 DPRINTF (("Defining: %s", sRef_unparseFull (s)));
5295 sRef_setDefinedAux (s, loc, FALSE);
5296 DPRINTF (("==> %s", sRef_unparseFull (s)));
5299 void sRef_setDefinedNCComplete (sRef s, fileloc loc)
5301 sRef_checkMutable (s);
5302 DPRINTF (("Set Defined Complete: %s", sRef_unparseFull (s)));
5303 sRef_innerAliasSetComplete (sRef_setDefinedNoClear, s, loc);
5304 DPRINTF (("==> %s", sRef_unparseFull (s)));
5307 static bool sRef_isDeepUnionField (sRef s)
5309 return (sRef_deepPred (sRef_isUnionField, s));
5312 bool sRef_isUnionField (sRef s)
5314 if (sRef_isReasonable (s) && s->kind == SK_FIELD)
5317 ** defining one field of a union defines the union
5320 sRef base = s->info->field->rec;
5322 if (sRef_isReasonable (base))
5324 return (ctype_isUnion (ctype_realType (base->type)));
5331 void sRef_setPdefined (sRef s, fileloc loc)
5333 sRef_checkMutable (s);
5334 if (sRef_isReasonable (s) && !sRef_isPartial (s))
5336 sRef base = sRef_getBaseSafe (s);
5338 if (s->defstate == SS_ALLOCATED)
5343 if (s->defstate != SS_PDEFINED && fileloc_isDefined (loc))
5345 s->definfo = stateInfo_updateLoc (s->definfo, loc);
5348 DPRINTF (("set pdefined: %s", sRef_unparseFull (s)));
5349 s->defstate = SS_PDEFINED;
5351 /* e.g., if x is allocated, *x = 3 defines x */
5353 while (sRef_isReasonable (base) && sRef_isKnown (base))
5355 if (base->defstate == SS_DEFINED)
5359 DPRINTF (("set pdefined: %s", sRef_unparseFull (base)));
5360 base->defstate = SS_PDEFINED;
5361 nb = sRef_getBaseSafe (base);
5372 static void sRef_setStateAux (sRef s, sstate ss, fileloc loc)
5374 sRef_checkMutable (s);
5376 if (sRef_isReasonable (s))
5378 /* if (s->defstate == SS_RELDEF) return; */
5380 if (s->defstate != ss && fileloc_isDefined (loc))
5382 s->definfo = stateInfo_updateLoc (s->definfo, loc);
5386 sRef_clearDerived (s);
5388 if (ss == SS_ALLOCATED)
5390 sRef base = sRef_getBaseSafe (s);
5392 while (sRef_isReasonable (base) && sRef_isKnown (base))
5394 if (base->defstate == SS_DEFINED)
5398 DPRINTF (("set pdefined: %s", sRef_unparseFull (s)));
5399 base->defstate = SS_PDEFINED;
5400 nb = sRef_getBaseSafe (base);
5412 void sRef_setAllocatedComplete (sRef s, fileloc loc)
5414 sRef_innerAliasSetComplete (sRef_setAllocated, s, loc);
5417 static void sRef_setAllocatedShallow (sRef s, fileloc loc)
5419 sRef_checkMutable (s);
5421 if (sRef_isReasonable (s))
5423 if (s->defstate == SS_DEAD || s->defstate == SS_UNDEFINED)
5425 s->defstate = SS_ALLOCATED;
5427 if (fileloc_isDefined (loc))
5429 s->definfo = stateInfo_updateLoc (s->definfo, loc);
5435 void sRef_setAllocatedShallowComplete (sRef s, fileloc loc)
5437 sRef_innerAliasSetComplete (sRef_setAllocatedShallow, s, loc);
5440 void sRef_setAllocated (sRef s, fileloc loc)
5442 sRef_checkMutable (s);
5443 sRef_setStateAux (s, SS_ALLOCATED, loc);
5446 void sRef_setPartial (sRef s, fileloc loc)
5448 sRef_checkMutable (s);
5449 sRef_setStateAux (s, SS_PARTIAL, loc);
5452 void sRef_setShared (sRef s, fileloc loc)
5454 sRef_checkMutable (s);
5456 if (sRef_isReasonable (s))
5458 if (s->aliaskind != AK_SHARED && fileloc_isDefined (loc))
5460 s->aliasinfo = stateInfo_updateLoc (s->aliasinfo, loc);
5463 s->aliaskind = AK_SHARED;
5464 /* don't! sRef_clearDerived (s); */
5468 void sRef_setLastReference (sRef s, /*@exposed@*/ sRef ref, fileloc loc)
5470 sRef_checkMutable (s);
5472 if (sRef_isReasonable (s))
5474 s->aliaskind = sRef_getAliasKind (ref);
5475 s->aliasinfo = stateInfo_updateRefLoc (s->aliasinfo, ref, loc);
5480 void sRef_setNullStateAux (/*@notnull@*/ sRef s, nstate ns, fileloc loc)
5482 sRef_checkMutable (s);
5484 sRef_resetAliasKind (s);
5486 if (fileloc_isDefined (loc))
5488 s->nullinfo = stateInfo_updateLoc (s->nullinfo, loc);
5492 void sRef_setNotNull (sRef s, fileloc loc)
5494 if (sRef_isReasonable (s))
5496 sRef_setNullStateAux (s, NS_NOTNULL, loc);
5500 void sRef_setNullStateN (sRef s, nstate n)
5502 if (sRef_isReasonable (s))
5504 sRef_checkMutable (s);
5506 sRef_resetAliasKind (s);
5510 void sRef_setNullState (sRef s, nstate n, fileloc loc)
5512 if (sRef_isReasonable (s))
5514 sRef_setNullStateAux (s, n, loc);
5518 void sRef_setNullTerminatedStateInnerComplete (sRef s, struct s_bbufinfo b, /*@unused@*/ fileloc loc)
5520 switch (b.bufstate) {
5521 case BB_NULLTERMINATED:
5522 sRef_setNullTerminatedState (s);
5523 sRef_setLen (s, b.len);
5525 case BB_POSSIBLYNULLTERMINATED:
5526 sRef_setPossiblyNullTerminatedState(s);
5528 case BB_NOTNULLTERMINATED:
5529 sRef_setNotNullTerminatedState (s);
5533 sRef_setSize (s, b.size);
5535 /* PL: TO BE DONE : Aliases are not modified right now, have to be similar to
5536 * setNullStateInnerComplete.
5540 void sRef_setNullStateInnerComplete (sRef s, nstate n, fileloc loc)
5542 DPRINTF (("Set null state: %s", nstate_unparse (n)));
5544 sRef_setNullState (s, n, loc);
5549 sRef_innerAliasSetComplete (sRef_setPosNull, s, loc);
5552 sRef_innerAliasSetComplete (sRef_setDefNull, s, loc);
5555 sRef_innerAliasSetComplete (sRef_setNullUnknown, s, loc);
5558 sRef_innerAliasSetComplete (sRef_setNotNull, s, loc);
5561 sRef_innerAliasSetComplete (sRef_setNotNull, s, loc);
5564 sRef_innerAliasSetComplete (sRef_setNullUnknown, s, loc);
5567 sRef_innerAliasSetComplete (sRef_setDefNull, s, loc);
5570 sRef_innerAliasSetComplete (sRef_setNullUnknown, s, loc);
5573 sRef_innerAliasSetComplete (sRef_setNullErrorLoc, s, loc);
5578 void sRef_setPosNull (sRef s, fileloc loc)
5580 if (sRef_isReasonable (s))
5582 sRef_setNullStateAux (s, NS_POSNULL, loc);
5586 void sRef_setDefNull (sRef s, fileloc loc)
5588 if (sRef_isReasonable (s))
5590 sRef_setNullStateAux (s, NS_DEFNULL, loc);
5594 void sRef_setNullUnknown (sRef s, fileloc loc)
5596 if (sRef_isReasonable (s))
5598 sRef_setNullStateAux (s, NS_UNKNOWN, loc);
5602 void sRef_setNullError (sRef s)
5604 if (sRef_isReasonable (s) && !sRef_isConst (s))
5606 sRef_setNullStateAux (s, NS_UNKNOWN, fileloc_undefined);
5610 void sRef_setNullErrorLoc (sRef s, fileloc loc)
5612 if (sRef_isReasonable (s) && !sRef_isConst (s))
5614 sRef_setNullStateAux (s, NS_UNKNOWN, loc);
5618 void sRef_setOnly (sRef s, fileloc loc)
5620 if (sRef_isReasonable (s) && s->aliaskind != AK_ONLY)
5622 sRef_checkMutable (s);
5623 s->aliaskind = AK_ONLY;
5624 s->aliasinfo = stateInfo_updateLoc (s->aliasinfo, loc);
5628 void sRef_setDependent (sRef s, fileloc loc)
5630 if (sRef_isReasonable (s) && !sRef_isConst (s) && (s->aliaskind != AK_DEPENDENT))
5632 sRef_checkMutable (s);
5633 DPRINTF (("Setting dependent: %s", sRef_unparseFull (s)));
5634 s->aliaskind = AK_DEPENDENT;
5635 s->aliasinfo = stateInfo_updateLoc (s->aliasinfo, loc);
5639 void sRef_setOwned (sRef s, fileloc loc)
5641 if (sRef_isReasonable (s) && !sRef_isConst (s) && (s->aliaskind != AK_OWNED))
5643 sRef_checkMutable (s);
5644 s->aliaskind = AK_OWNED;
5645 s->aliasinfo = stateInfo_updateLoc (s->aliasinfo, loc);
5649 void sRef_setKept (sRef s, fileloc loc)
5651 if (sRef_isReasonable (s) && !sRef_isConst (s) && (s->aliaskind != AK_KEPT))
5653 sRef base = sRef_getBaseSafe (s);
5655 while (sRef_isReasonable (base) && sRef_isKnown (base))
5657 if (base->defstate == SS_DEFINED)
5659 sRef_checkMutable (base);
5660 base->defstate = SS_PDEFINED;
5661 base = sRef_getBaseSafe (base);
5669 sRef_checkMutable (s);
5670 s->aliaskind = AK_KEPT;
5671 s->aliasinfo = stateInfo_updateLoc (s->aliasinfo, loc);
5675 static void sRef_setKeptAux (sRef s, fileloc loc)
5677 if (!sRef_isShared (s))
5679 sRef_setKept (s, loc);
5683 static void sRef_setDependentAux (sRef s, fileloc loc)
5685 if (!sRef_isShared (s))
5687 sRef_setDependent (s, loc);
5691 void sRef_setKeptComplete (sRef s, fileloc loc)
5693 sRef_aliasSetComplete (sRef_setKeptAux, s, loc);
5696 void sRef_setDependentComplete (sRef s, fileloc loc)
5698 sRef_aliasSetComplete (sRef_setDependentAux, s, loc);
5701 void sRef_setFresh (sRef s, fileloc loc)
5703 if (sRef_isReasonable (s) && !sRef_isConst (s))
5705 sRef_checkMutable (s);
5706 s->aliaskind = AK_FRESH;
5707 s->aliasinfo = stateInfo_updateLoc (s->aliasinfo, loc);
5711 void sRef_kill (sRef s, fileloc loc)
5713 DPRINTF (("Kill: %s", sRef_unparseFull (s)));
5715 if (sRef_isReasonable (s) && !sRef_isShared (s) && !sRef_isConst (s))
5717 sRef base = sRef_getBaseSafe (s);
5718 sRef_checkMutable (s);
5720 while (sRef_isReasonable (base) && sRef_isKnown (base))
5722 if (base->defstate == SS_DEFINED)
5724 sRef_checkMutable (base);
5725 base->defstate = SS_PDEFINED;
5726 base = sRef_getBaseSafe (base);
5734 s->aliaskind = s->oaliaskind;
5735 s->defstate = SS_DEAD;
5736 s->definfo = stateInfo_updateLoc (s->definfo, loc);
5738 sRef_clearDerived (s);
5742 void sRef_maybeKill (sRef s, fileloc loc)
5744 if (sRef_isReasonable (s))
5746 sRef base = sRef_getBaseSafe (s);
5747 sRef_checkMutable (s);
5749 while (sRef_isReasonable (base) && sRef_isKnown (base))
5751 if (base->defstate == SS_DEFINED || base->defstate == SS_RELDEF)
5753 sRef_checkMutable (base);
5754 base->defstate = SS_PDEFINED;
5755 base = sRef_getBaseSafe (base);
5764 s->aliaskind = s->oaliaskind;
5765 s->defstate = SS_HOFFA;
5766 s->definfo = stateInfo_updateLoc (s->definfo, loc);
5767 sRef_clearDerived (s);
5773 ** just for type checking...
5776 static void sRef_killAux (sRef s, fileloc loc)
5778 if (sRef_isReasonable (s) && !sRef_isShared (s))
5780 if (sRef_isUnknownArrayFetch (s))
5782 sRef_maybeKill (s, loc);
5792 ** kills s and all aliases to s
5795 void sRef_killComplete (sRef s, fileloc loc)
5797 DPRINTF (("Kill complete: %s", sRef_unparseFull (s)));
5798 sRef_aliasSetComplete (sRef_killAux, s, loc);
5801 static bool sRef_equivalent (sRef s1, sRef s2)
5803 return (sRef_compare (s1, s2) == 0);
5807 ** returns an sRef that will not be free'd on function exit.
5810 /*@only@*/ sRef sRef_saveCopy (sRef s)
5814 if (sRef_isReasonable (s))
5816 bool old = inFunction;
5819 ** Exit the function scope, so this sRef is not
5820 ** stored in the deallocation table.
5824 DPRINTF (("Copying sref: %s", sRef_unparseFull(s)));
5825 ret = sRef_copy (s);
5826 DPRINTF (("Copying ===>: %s", sRef_unparseFull(ret)));
5831 ret = sRef_undefined;
5834 /*@-dependenttrans@*/
5836 /*@=dependenttrans@*/
5839 sRef sRef_copy (sRef s)
5841 if (sRef_isKindSpecial (s) && !sRef_isGlobalMarker (s))
5844 return s; /* don't copy specials (except for global markers) */
5848 if (sRef_isReasonable (s))
5850 sRef t = sRef_alloc ();
5852 DPRINTF (("Copying: [%p] %s", s, sRef_unparse (s)));
5853 DPRINTF (("Full: %s", sRef_unparseFull (s)));
5857 t->modified = s->modified;
5858 t->immut = FALSE; /* Note mutability is not copied. */
5860 t->val = multiVal_copy (s->val);
5862 t->info = sinfo_copy (s);
5863 t->defstate = s->defstate;
5864 t->nullstate = s->nullstate;
5866 /* start modifications */
5867 t->bufinfo.bufstate = s->bufinfo.bufstate;
5868 t->bufinfo.len = s->bufinfo.len;
5869 t->bufinfo.size = s->bufinfo.size;
5870 /* end modifications */
5872 t->aliaskind = s->aliaskind;
5873 t->oaliaskind = s->oaliaskind;
5875 t->expkind = s->expkind;
5876 t->oexpkind = s->oexpkind;
5878 t->nullinfo = stateInfo_copy (s->nullinfo);
5879 t->aliasinfo = stateInfo_copy (s->aliasinfo);
5880 t->definfo = stateInfo_copy (s->definfo);
5881 t->expinfo = stateInfo_copy (s->expinfo);
5883 t->deriv = sRefSet_newDeepCopy (s->deriv);
5884 t->state = valueTable_copy (s->state);
5886 DPRINTF (("Made copy: %s => %s", sRef_unparseFull (s), sRef_unparseFull (t)));
5891 return sRef_undefined;
5896 # define PREDTEST(func,s) \
5897 do { if (sRef_isInvalid (s)) { return FALSE; } \
5898 else { if (sRef_isConj (s)) \
5899 { return (func (sRef_getConjA (s)) \
5900 || func (sRef_getConjB (s))); }}} while (FALSE);
5902 bool sRef_isAddress (sRef s)
5904 PREDTEST (sRef_isAddress, s);
5905 return (s->kind == SK_ADR);
5909 ** pretty weak... maybe a flag should control this.
5912 bool sRef_isThroughArrayFetch (sRef s)
5914 if (sRef_isReasonable (s))
5922 if (sRef_isArrayFetch (tref))
5927 lt = sRef_getBase (tref);
5929 } while (sRef_isReasonable (tref));
5935 bool sRef_isArrayFetch (sRef s)
5937 PREDTEST (sRef_isArrayFetch, s);
5938 return (s->kind == SK_ARRAYFETCH);
5941 bool sRef_isMacroParamRef (sRef s)
5943 if (context_inMacro () && sRef_isCvar (s))
5945 uentry ue = sRef_getUentry (s);
5946 cstring pname = makeParam (uentry_rawName (ue));
5947 uentry mac = usymtab_lookupSafe (pname);
5949 cstring_free (pname);
5950 return (uentry_isValid (mac));
5956 bool sRef_isCvar (sRef s)
5958 PREDTEST (sRef_isCvar, s);
5959 return (s->kind == SK_CVAR);
5962 bool sRef_isConst (sRef s)
5964 PREDTEST (sRef_isConst, s);
5965 return (s->kind == SK_CONST);
5968 bool sRef_isObject (sRef s)
5970 PREDTEST (sRef_isObject, s);
5971 return (s->kind == SK_OBJECT);
5974 bool sRef_isExternal (sRef s)
5976 PREDTEST (sRef_isExternal, s);
5977 return (s->kind == SK_EXTERNAL);
5980 static bool sRef_isDerived (sRef s)
5982 PREDTEST (sRef_isDerived, s);
5983 return (s->kind == SK_DERIVED);
5986 bool sRef_isField (sRef s)
5988 PREDTEST (sRef_isField, s);
5989 return (s->kind == SK_FIELD);
5992 static bool sRef_isIndex (sRef s)
5994 PREDTEST (sRef_isIndex, s);
5995 return (s->kind == SK_ARRAYFETCH);
5998 bool sRef_isAnyParam (sRef s)
6000 PREDTEST (sRef_isAnyParam, s);
6001 return (s->kind == SK_PARAM);
6004 bool sRef_isParam (sRef s)
6006 PREDTEST (sRef_isParam, s);
6007 return (s->kind == SK_PARAM);
6010 bool sRef_isDirectParam (sRef s)
6012 PREDTEST (sRef_isDirectParam, s);
6014 return ((s->kind == SK_CVAR) &&
6015 (s->info->cvar->lexlevel == functionScope) &&
6016 (context_inFunction () &&
6017 (s->info->cvar->index <= uentryList_size (context_getParams ()))));
6020 bool sRef_isPointer (sRef s)
6022 PREDTEST (sRef_isPointer, s);
6023 return (s->kind == SK_PTR);
6027 ** returns true if storage referenced by s is visible
6030 bool sRef_isReference (sRef s)
6032 PREDTEST (sRef_isReference, s);
6034 return (sRef_isPointer (s) || sRef_isIndex (s) || sRef_isFileOrGlobalScope (s)
6035 || (sRef_isField (s) && (sRef_isReference (s->info->field->rec))));
6038 bool sRef_isIReference (sRef s)
6040 return (sRef_isPointer (s) || sRef_isAddress (s) || sRef_isIndex (s)
6041 || sRef_isField (s) || sRef_isArrayFetch (s));
6044 bool sRef_isFileOrGlobalScope (sRef s)
6046 return (sRef_isCvar (s) && (s->info->cvar->lexlevel <= fileScope));
6049 bool sRef_isRealGlobal (sRef s)
6051 return (sRef_isCvar (s) && (s->info->cvar->lexlevel == globScope));
6054 bool sRef_isFileStatic (sRef s)
6056 return (sRef_isCvar (s) && (s->info->cvar->lexlevel == fileScope));
6059 bool sRef_isAliasCheckedGlobal (sRef s)
6061 if (sRef_isFileOrGlobalScope (s))
6063 uentry ue = sRef_getUentry (s);
6065 return context_checkAliasGlob (ue);
6073 void sRef_free (/*@only@*/ sRef s)
6075 if (s != sRef_undefined && s->kind != SK_SPECIAL)
6077 DPRINTF (("Free sref: [%p]", s));
6079 sRef_checkValid (s);
6081 stateInfo_free (s->expinfo);
6082 stateInfo_free (s->aliasinfo);
6083 stateInfo_free (s->definfo);
6084 stateInfo_free (s->nullinfo);
6086 sRefSet_free (s->deriv);
6087 s->deriv = sRefSet_undefined;
6089 /*@i43@*/ /* valueTable_free (s->state); */
6093 /* drl added to help locate use after release*/
6094 s->expinfo = stateInfo_undefined;
6095 s->aliasinfo = stateInfo_undefined;
6096 s->definfo = stateInfo_undefined;
6097 s->nullinfo = stateInfo_undefined;
6099 /*@i32@*/ sfree (s);
6103 void sRef_setType (sRef s, ctype t)
6105 if (sRef_isReasonable (s))
6107 sRef_checkMutable (s);
6112 void sRef_setTypeFull (sRef s, ctype t)
6114 if (sRef_isReasonable (s))
6116 sRef_checkMutable (s);
6119 sRefSet_allElements (s->deriv, current)
6121 sRef_setTypeFull (current, ctype_unknown);
6122 } end_sRefSet_allElements ;
6127 sRef_buildField (/*@exposed@*/ sRef rec, /*@dependent@*/ cstring f)
6129 return (sRef_buildNCField (rec, f));
6132 static /*@exposed@*/ sRef
6133 sRef_findDerivedField (/*@notnull@*/ sRef rec, cstring f)
6135 sRefSet_allElements (sRef_derivedFields (rec), sr)
6137 if (sRef_isReasonable (sr))
6139 if (sRef_isReasonable (sr))
6141 if (sr->info != NULL)
6143 if (sr->kind == SK_FIELD && cstring_equal (sr->info->field->field, f))
6151 llcontbug (message ("Invalid sRef as derived field of %s", sRef_unparse (rec)));
6154 } end_sRefSet_allElements;
6156 return sRef_undefined;
6159 /*@dependent@*/ /*@observer@*/ sRefSet sRef_derivedFields (/*@temp@*/ sRef rec)
6161 if (sRef_isReasonable (rec))
6169 return (sRefSet_undefined);
6173 static /*@exposed@*/ sRef
6174 sRef_findDerivedPointer (sRef s)
6176 if (sRef_isReasonable (s))
6178 sRefSet_realElements (s->deriv, sr)
6180 if (sRef_isReasonable (sr) && sr->kind == SK_PTR)
6184 } end_sRefSet_realElements;
6187 return sRef_undefined;
6191 sRef_isUnknownArrayFetch (sRef s)
6193 return (sRef_isReasonable (s)
6194 && s->kind == SK_ARRAYFETCH
6195 && !s->info->arrayfetch->indknown);
6198 static /*@exposed@*/ sRef
6199 sRef_findDerivedArrayFetch (/*@notnull@*/ sRef s, bool isknown, int idx, bool dead)
6204 sRefSet_realElements (s->deriv, sr)
6206 if (sRef_isReasonable (sr)
6207 && sr->kind == SK_ARRAYFETCH
6208 && sr->info->arrayfetch->indknown
6209 && (sr->info->arrayfetch->ind == idx))
6213 } end_sRefSet_realElements;
6217 sRefSet_realElements (s->deriv, sr)
6219 if (sRef_isReasonable (sr)
6220 && sr->kind == SK_ARRAYFETCH
6221 && (!sr->info->arrayfetch->indknown
6222 || (sr->info->arrayfetch->indknown &&
6223 sr->info->arrayfetch->ind == 0)))
6225 if (sRef_isDead (sr) || sRef_isKept (sr))
6227 if (dead || context_getFlag (FLG_STRICTUSERELEASED))
6237 } end_sRefSet_realElements;
6240 return sRef_undefined;
6243 static /*@exposed@*/ sRef
6244 sRef_buildNCField (/*@exposed@*/ sRef rec, /*@exposed@*/ cstring f)
6248 DPRINTF (("Build nc field: %s / %s",
6249 sRef_unparseFull (rec), f));
6251 if (sRef_isInvalid (rec))
6253 return sRef_undefined;
6257 ** check if the field already has been referenced
6260 s = sRef_findDerivedField (rec, f);
6262 if (sRef_isReasonable (s))
6268 ctype ct = ctype_realType (rec->type);
6270 DPRINTF (("Field of: %s", sRef_unparse (rec)));
6274 s->info = (sinfo) dmalloc (sizeof (*s->info));
6275 s->info->field = (fldinfo) dmalloc (sizeof (*s->info->field));
6276 s->info->field->rec = rec; /* sRef_copy (rec); */ /*@i32@*/
6277 s->info->field->field = f; /* doesn't copy f */
6279 if (ctype_isKnown (ct) && ctype_isSU (ct))
6281 uentry ue = uentryList_lookupField (ctype_getFields (ct), f);
6283 if (!uentry_isUndefined (ue))
6285 DPRINTF (("lookup: %s for %s", uentry_unparseFull (ue),
6286 ctype_unparse (ct)));
6288 s->type = uentry_getType (ue);
6290 if (ctype_isMutable (s->type)
6291 && rec->aliaskind != AK_STACK
6292 && !alkind_isStatic (rec->aliaskind))
6294 s->aliaskind = rec->aliaskind;
6298 s->aliaskind = AK_UNKNOWN;
6301 if (sRef_isStateDefined (rec) || sRef_isStateUnknown (rec)
6302 || sRef_isPdefined (rec))
6304 sRef_setStateFromUentry (s, ue);
6308 sRef_setPartsFromUentry (s, ue);
6311 s->oaliaskind = s->aliaskind;
6312 s->oexpkind = s->expkind;
6314 DPRINTF (("sref: %s", sRef_unparseFull (s)));
6319 Never report this as an error. It can happen whenever there
6320 is casting involved.
6324 llcontbug (message ("buildNCField --- no field %s: %q / %s",
6325 f, sRef_unparse (s), ctype_unparse (ct)));
6329 return sRef_undefined;
6333 if (rec->defstate == SS_DEFINED
6334 && (s->defstate == SS_UNDEFINED || s->defstate == SS_UNKNOWN))
6336 s->defstate = SS_DEFINED;
6338 else if (rec->defstate == SS_PARTIAL)
6340 s->defstate = SS_PARTIAL;
6342 else if (rec->defstate == SS_ALLOCATED)
6344 if (ctype_isStackAllocated (ct) && ctype_isStackAllocated (s->type))
6346 s->defstate = SS_ALLOCATED;
6350 s->defstate = SS_UNDEFINED;
6353 else if (s->defstate == SS_UNKNOWN)
6355 s->defstate = rec->defstate;
6362 if (s->defstate == SS_UNDEFINED)
6364 ctype rt = ctype_realType (s->type);
6366 if (ctype_isArray (rt) || ctype_isSU (rt))
6368 s->defstate = SS_ALLOCATED;
6372 sRef_addDeriv (rec, s);
6373 DPRINTF (("Add deriv: %s", sRef_unparseFull (rec)));
6375 if (ctype_isInt (s->type) && cstring_equal (f, REFSNAME))
6377 s->aliaskind = AK_REFS;
6378 s->oaliaskind = AK_REFS;
6381 DPRINTF (("Build field ==> %s", sRef_unparseFull (s)));
6387 sRef_isStackAllocated (sRef s)
6389 return (sRef_isReasonable(s)
6390 && s->defstate == SS_ALLOCATED && ctype_isStackAllocated (s->type));
6394 void sRef_setArrayFetchState (/*@notnull@*/ /*@exposed@*/ sRef s,
6395 /*@notnull@*/ /*@exposed@*/ sRef arr)
6397 sRef_checkMutable (s);
6399 if (ctype_isRealAP (arr->type))
6401 s->type = ctype_baseArrayPtr (arr->type);
6404 /* a hack, methinks... makeArrayFetch (&a[0]) ==> a[] */
6405 /* evans - 2001-08-27: not sure where this was necessary - it
6406 ** causes an assertion in in aliasCheckPred to fail.
6409 if (sRef_isAddress (arr))
6411 sRef t = arr->info->ref;
6413 if (sRef_isArrayFetch (t))
6415 s->info->arrayfetch->arr = t->info->arrayfetch->arr;
6418 else if (ctype_isRealPointer (arr->type))
6420 sRef sp = sRef_findDerivedPointer (arr);
6422 if (sRef_isReasonable (sp))
6425 if (ctype_isMutable (s->type))
6427 sRef_setExKind (s, sRef_getExKind (sp), fileloc_undefined);
6429 s->aliaskind = sp->aliaskind;
6432 s->defstate = sp->defstate;
6434 if (s->defstate == SS_DEFINED)
6436 if (!context_getFlag (FLG_STRICTDESTROY))
6438 s->defstate = SS_PARTIAL;
6442 DPRINTF (("Set null state: %s / %s", sRef_unparseFull (s), sRef_unparseFull (sp)));
6443 sRef_setNullStateN (s, sRef_getNullState (sp));
6447 if (arr->defstate == SS_UNDEFINED)
6449 s->defstate = SS_UNUSEABLE;
6451 else if ((arr->defstate == SS_ALLOCATED) && !ctype_isSU (s->type))
6453 s->defstate = SS_UNDEFINED;
6457 if (!context_getFlag (FLG_STRICTDESTROY))
6459 s->defstate = SS_PARTIAL;
6463 s->defstate = SS_DEFINED;
6467 ** Very weak checking for array elements.
6469 ** s->defstate = arr->defstate;
6473 sRef_setExKind (s, sRef_getExKind (arr), g_currentloc);
6475 if (arr->aliaskind == AK_LOCAL || arr->aliaskind == AK_FRESH)
6477 s->aliaskind = AK_LOCAL;
6481 s->aliaskind = AK_UNKNOWN;
6484 sRef_setTypeState (s);
6489 if (arr->defstate == SS_DEFINED)
6492 ** Very weak checking for array elements.
6494 ** s->defstate = arr->defstate;
6497 if (context_getFlag (FLG_STRICTDESTROY))
6499 s->defstate = SS_DEFINED;
6503 s->defstate = SS_PARTIAL;
6506 else if (arr->defstate == SS_ALLOCATED)
6508 if (ctype_isRealArray (s->type))
6510 s->defstate = SS_ALLOCATED;
6514 if (!s->info->arrayfetch->indknown)
6517 ** is index is unknown, elements is defined or
6518 ** allocated is any element is!
6521 s->defstate = SS_UNDEFINED;
6523 sRefSet_allElements (arr->deriv, sr)
6525 if (sRef_isReasonable (sr))
6527 if (sRef_isReasonable (sr))
6529 if (sr->defstate == SS_ALLOCATED)
6531 s->defstate = SS_ALLOCATED;
6535 if (sr->defstate == SS_DEFINED)
6537 if (context_getFlag (FLG_STRICTDESTROY))
6539 s->defstate = SS_DEFINED;
6543 s->defstate = SS_PARTIAL;
6552 llcontbug (message ("Invalid sRef as derived element of %s", sRef_unparse (arr)));
6555 } end_sRefSet_allElements;
6559 s->defstate = SS_UNDEFINED;
6565 s->defstate = arr->defstate;
6570 ** kludgey way to guess where aliaskind applies
6573 if (ctype_isMutable (s->type)
6574 && !ctype_isPointer (arr->type)
6575 && !alkind_isStatic (arr->aliaskind)
6576 && !alkind_isStack (arr->aliaskind)) /* evs - 2000-06-20: don't pass stack allocation to members */
6578 s->aliaskind = arr->aliaskind;
6582 s->aliaskind = AK_UNKNOWN;
6585 sRef_setTypeState (s);
6588 if (sRef_isObserver (arr))
6590 s->expkind = XO_OBSERVER;
6594 /*@exposed@*/ sRef sRef_buildArrayFetch (/*@exposed@*/ sRef arr)
6598 if (!sRef_isReasonable (arr)) {
6599 /*@-nullret@*/ return arr /*@=nullret@*/;
6602 if (ctype_isRealPointer (arr->type))
6604 (void) sRef_buildPointer (arr); /* do this to define arr! */
6607 s = sRef_findDerivedArrayFetch (arr, FALSE, 0, FALSE);
6609 if (sRef_isReasonable (s))
6611 /* evans 2001-07-12: this is bogus, clean-up hack */
6612 if (s->info->arrayfetch->arr != arr)
6615 check (sRefSet_delete (arr->deriv, s));
6616 res = sRef_buildArrayFetch (arr);
6617 sRef_copyState (res, s);
6618 llassert (res->info->arrayfetch->arr == arr);
6622 sRef_setExKind (s, sRef_getExKind (arr), g_currentloc);
6629 s->kind = SK_ARRAYFETCH;
6630 s->info = (sinfo) dmalloc (sizeof (*s->info));
6631 s->info->arrayfetch = (ainfo) dmalloc (sizeof (*s->info->arrayfetch));
6632 s->info->arrayfetch->indknown = FALSE;
6633 s->info->arrayfetch->ind = 0;
6634 s->info->arrayfetch->arr = arr; /* sRef_copy (arr); */ /*@i32@*/
6636 sRef_setArrayFetchState (s, arr);
6638 s->oaliaskind = s->aliaskind;
6639 s->oexpkind = s->expkind;
6641 if (!context_inProtectVars ())
6643 sRef_addDeriv (arr, s);
6646 if (valueTable_isUndefined (s->state))
6648 s->state = context_createValueTable (s, stateInfo_makeLoc (g_currentloc));
6656 sRef_buildArrayFetchKnown (/*@exposed@*/ sRef arr, int i)
6660 if (!sRef_isReasonable (arr)) {
6661 /*@-nullret@*/ return arr /*@=nullret@*/;
6664 if (ctype_isRealPointer (arr->type))
6666 (void) sRef_buildPointer (arr); /* do this to define arr! */
6669 s = sRef_findDerivedArrayFetch (arr, TRUE, i, FALSE);
6671 if (sRef_isReasonable (s))
6673 /* evans 2001-07-12: this is bogus, clean-up hack */
6674 if (s->info->arrayfetch->arr != arr)
6678 check (sRefSet_delete (arr->deriv, s));
6679 res = sRef_buildArrayFetchKnown (arr, i);
6681 llassert (res->info->arrayfetch->arr == arr);
6682 sRef_copyState (res, s);
6683 llassert (res->info->arrayfetch->arr == arr);
6687 sRef_setExKind (s, sRef_getExKind (arr), g_currentloc);
6688 llassert (s->info->arrayfetch->arr == arr);
6695 s->kind = SK_ARRAYFETCH;
6696 s->info = (sinfo) dmalloc (sizeof (*s->info));
6697 s->info->arrayfetch = (ainfo) dmalloc (sizeof (*s->info->arrayfetch));
6698 s->info->arrayfetch->arr = arr; /* sRef_copy (arr); */ /*@i32@*/
6699 s->info->arrayfetch->indknown = TRUE;
6700 s->info->arrayfetch->ind = i;
6702 sRef_setArrayFetchState (s, arr);
6703 /* evans 2001-08-27 no: can change this - llassert (s->info->arrayfetch->arr == arr); */
6705 s->oaliaskind = s->aliaskind;
6706 s->oexpkind = s->expkind;
6707 sRef_addDeriv (arr, s);
6709 llassert (valueTable_isUndefined (s->state));
6710 s->state = context_createValueTable (s, stateInfo_makeLoc (g_currentloc));
6716 ** sets everything except for defstate
6720 sRef_setPartsFromUentry (sRef s, uentry ue)
6722 sRef uref = uentry_getSref (ue);
6724 llassert (sRef_isReasonable (s));
6726 s->aliaskind = alkind_derive (s->aliaskind, uentry_getAliasKind (ue));
6727 s->oaliaskind = s->aliaskind;
6729 if (s->expkind == XO_UNKNOWN)
6731 s->expkind = uentry_getExpKind (ue);
6734 s->oexpkind = s->expkind;
6736 if (sRef_getNullState (s) == NS_UNKNOWN)
6738 DPRINTF (("Set null state: %s / %s", sRef_unparseFull (s), uentry_unparseFull (ue)));
6739 sRef_setNullStateN (s, sRef_getNullState (uentry_getSref (ue)));
6743 DPRINTF (("Skipping null null state!"));
6746 if (s->aliaskind == AK_IMPONLY && (sRef_isExposed (s) || sRef_isObserver (s)))
6748 s->oaliaskind = s->aliaskind = AK_IMPDEPENDENT;
6751 if (sRef_isReasonable (uref))
6753 valueTable utable = uref->state;
6754 valueTable_free (s->state);
6755 s->state = valueTable_copy (utable);
6760 sRef_setStateFromAbstractUentry (sRef s, uentry ue)
6762 llassert (sRef_isReasonable (s));
6763 sRef_checkMutable (s);
6765 sRef_setPartsFromUentry (s, ue);
6767 s->aliaskind = alkind_derive (s->aliaskind, uentry_getAliasKind (ue));
6768 s->oaliaskind = s->aliaskind;
6770 if (s->expkind == XO_UNKNOWN)
6772 s->expkind = uentry_getExpKind (ue);
6775 s->oexpkind = s->expkind;
6779 sRef_setStateFromUentry (sRef s, uentry ue)
6783 sRef_checkMutable (s);
6784 llassert (sRef_isReasonable (s));
6786 sRef_setPartsFromUentry (s, ue);
6788 defstate = uentry_getDefState (ue);
6790 if (sstate_isKnown (defstate))
6792 s->defstate = defstate;
6801 sRef_buildPointer (/*@exposed@*/ sRef t)
6803 DPRINTF (("build pointer: %s", sRef_unparse (t)));
6805 if (sRef_isInvalid (t)) return sRef_undefined;
6807 if (sRef_isAddress (t))
6809 DPRINTF (("Return ref: %s", sRef_unparse (t->info->ref)));
6810 return (t->info->ref);
6814 sRef s = sRef_findDerivedPointer (t);
6816 DPRINTF (("find derived: %s", sRef_unparse (s)));
6818 if (sRef_isReasonable (s))
6821 sRef_setExKind (s, sRef_getExKind (t), g_currentloc);
6822 s->oaliaskind = s->aliaskind;
6823 s->oexpkind = s->expkind;
6829 s = sRef_constructPointerAux (t);
6831 DPRINTF (("construct: %s", sRef_unparse (s)));
6833 if (sRef_isReasonable (s))
6835 sRef_addDeriv (t, s);
6837 s->oaliaskind = s->aliaskind;
6838 s->oexpkind = s->expkind;
6847 sRef_constructPointer (/*@exposed@*/ sRef t)
6850 return sRef_buildPointer (t);
6853 static /*@exposed@*/ sRef sRef_constructDerefAux (sRef t, bool isdead)
6855 if (sRef_isReasonable (t))
6860 ** if there is a derived t[?], return that. Otherwise, *t.
6863 s = sRef_findDerivedArrayFetch (t, FALSE, 0, isdead);
6865 if (sRef_isReasonable (s))
6867 DPRINTF (("Found array fetch: %s", sRef_unparseFull (s)));
6872 sRef ret = sRef_constructPointer (t);
6874 DPRINTF (("Constructed pointer: %s", sRef_unparseFull (ret)));
6881 return sRef_undefined;
6885 sRef sRef_constructDeref (sRef t)
6887 return sRef_constructDerefAux (t, FALSE);
6890 sRef sRef_constructDeadDeref (sRef t)
6892 return sRef_constructDerefAux (t, TRUE);
6896 sRef_constructPointerAux (/*@notnull@*/ /*@exposed@*/ sRef t)
6898 sRef s = sRef_newRef ();
6902 llassert (valueTable_isUndefined (s->state));
6905 s->info = (sinfo) dmalloc (sizeof (*s->info));
6906 s->info->ref = t; /* sRef_copy (t); */ /*@i32*/
6908 if (ctype_isRealAP (rt))
6910 s->type = ctype_baseArrayPtr (rt);
6913 st = ctype_realType (s->type);
6915 if (t->defstate == SS_UNDEFINED)
6917 s->defstate = SS_UNUSEABLE;
6919 else if ((t->defstate == SS_ALLOCATED) && !ctype_isSU (st))
6921 s->defstate = SS_UNDEFINED;
6925 s->defstate = t->defstate;
6928 if (t->aliaskind == AK_LOCAL || t->aliaskind == AK_FRESH)
6930 s->aliaskind = AK_LOCAL;
6934 s->aliaskind = AK_UNKNOWN;
6937 sRef_setExKind (s, sRef_getExKind (t), fileloc_undefined);
6938 sRef_setTypeState (s);
6940 s->oaliaskind = s->aliaskind;
6941 s->oexpkind = s->expkind;
6943 if (valueTable_isUndefined (s->state))
6945 s->state = context_createValueTable (s, stateInfo_makeLoc (g_currentloc));
6951 bool sRef_hasDerived (sRef s)
6953 return (sRef_isReasonable (s) && !sRefSet_isEmpty (s->deriv));
6957 sRef_clearDerived (sRef s)
6959 if (sRef_isReasonable (s))
6961 DPRINTF (("Clear derived: [%p] %s", s, sRef_unparseDebug (s)));
6962 sRefSet_clear (s->deriv);
6967 sRef_clearDerivedComplete (sRef s)
6969 if (sRef_isReasonable (s))
6971 sRef base = sRef_getBaseSafe (s);
6973 while (sRef_isReasonable (base))
6975 DPRINTF (("Clear derived: [%p] %s", base, sRef_unparse (base)));
6976 sRefSet_clear (base->deriv);
6977 base = sRef_getBaseSafe (base);
6980 DPRINTF (("Clear derived: [%p] %s", s, sRef_unparse (s)));
6981 sRefSet_clear (s->deriv);
6985 /*@exposed@*/ sRef sRef_makePointer (/*@exposed@*/ sRef s)
6988 sRef res = sRef_buildPointer (s);
6990 DPRINTF (("Res: %s", sRef_unparse (res)));
6995 ** &a[] => a (this is for out params)
6999 sRef_makeAnyArrayFetch (/*@exposed@*/ sRef arr)
7001 if (sRef_isAddress (arr))
7003 return (arr->info->ref);
7007 return (sRef_buildArrayFetch (arr));
7012 sRef_makeArrayFetch (/*@exposed@*/ sRef arr)
7014 return (sRef_buildArrayFetch (arr));
7018 sRef_makeArrayFetchKnown (/*@exposed@*/ sRef arr, int i)
7020 return (sRef_buildArrayFetchKnown (arr, i));
7024 sRef_makeField (sRef rec, /*@dependent@*/ cstring f)
7027 ret = sRef_buildField (rec, f);
7032 sRef_makeNCField (/*@exposed@*/ sRef rec, /*@dependent@*/ cstring f)
7034 return (sRef_buildNCField (rec, f));
7038 sRef_unparseKindName (sRef s)
7042 if (s == sRef_undefined) return cstring_makeLiteral ("<invalid>");
7044 s = sRef_fixConj (s);
7049 if (sRef_isLocalVar (s))
7051 result = cstring_makeLiteral ("Variable");
7055 result = cstring_makeLiteral ("Undef global");
7059 result = cstring_makeLiteral ("Out parameter");
7062 if (sRef_isAnyParam (s->info->arrayfetch->arr))
7064 result = cstring_makeLiteral ("Out parameter");
7066 else if (sRef_isIndexKnown (s))
7068 result = cstring_makeLiteral ("Array element");
7072 result = cstring_makeLiteral ("Value");
7076 if (sRef_isAnyParam (s->info->ref))
7078 result = cstring_makeLiteral ("Out parameter");
7082 result = cstring_makeLiteral ("Value");
7086 result = cstring_makeLiteral ("Value");
7089 result = cstring_makeLiteral ("Field");
7092 result = cstring_makeLiteral ("Object");
7094 case SK_UNCONSTRAINED:
7095 result = cstring_makeLiteral ("<anything>");
7104 result = cstring_makeLiteral ("<unknown>");
7107 result = cstring_makeLiteral ("<conj>");
7110 result = cstring_makeLiteral ("Storage");
7118 sRef_unparseKindNamePlain (sRef s)
7122 if (s == sRef_undefined) return cstring_makeLiteral ("<invalid>");
7124 s = sRef_fixConj (s);
7129 if (sRef_isLocalVar (s))
7131 result = cstring_makeLiteral ("Variable");
7135 result = cstring_makeLiteral ("Global");
7139 result = cstring_makeLiteral ("Parameter");
7142 if (sRef_isAnyParam (s->info->arrayfetch->arr))
7144 result = cstring_makeLiteral ("Parameter");
7146 else if (sRef_isIndexKnown (s))
7148 result = cstring_makeLiteral ("Array element");
7152 result = cstring_makeLiteral ("Value");
7156 if (sRef_isAnyParam (s->info->ref))
7158 result = cstring_makeLiteral ("Parameter");
7162 result = cstring_makeLiteral ("Value");
7166 result = cstring_makeLiteral ("Value");
7169 result = cstring_makeLiteral ("Field");
7172 result = cstring_makeLiteral ("Object");
7175 result = cstring_makeLiteral ("Storage");
7177 case SK_UNCONSTRAINED:
7178 result = cstring_makeLiteral ("<anything>");
7187 result = cstring_makeLiteral ("<unknown>");
7190 result = cstring_makeLiteral ("<conj>");
7202 sRef_copyState (sRef s1, sRef s2)
7204 if (sRef_isReasonable (s1) && sRef_isReasonable (s2))
7206 s1->defstate = s2->defstate;
7208 /* start modifications */
7209 s1->bufinfo.bufstate = s2->bufinfo.bufstate;
7210 s1->bufinfo.len = s2->bufinfo.len;
7211 s1->bufinfo.size = s2->bufinfo.size;
7212 /* end modifications */
7214 s1->aliaskind = s2->aliaskind;
7215 s1->aliasinfo = stateInfo_update (s1->aliasinfo, s2->aliasinfo);
7217 s1->expkind = s2->expkind;
7218 s1->expinfo = stateInfo_update (s1->expinfo, s2->expinfo);
7220 s1->nullstate = s2->nullstate;
7221 s1->nullinfo = stateInfo_update (s1->nullinfo, s2->nullinfo);
7224 /*@i834 don't free it: valueTable_free (s1->state); */
7225 /*@i32@*/ s1->state = valueTable_copy (s2->state);
7227 s1->safe = s2->safe;
7232 sRef_makeNew (ctype ct, sRef t, cstring name)
7234 sRef s = sRef_newRef ();
7239 llassert (sRef_isReasonable (t));
7240 s->defstate = t->defstate;
7242 s->aliaskind = t->aliaskind;
7243 s->oaliaskind = s->aliaskind;
7244 s->nullstate = t->nullstate;
7246 s->expkind = t->expkind;
7247 s->oexpkind = s->expkind;
7249 s->info = (sinfo) dmalloc (sizeof (*s->info));
7250 s->info->fname = name;
7252 /* start modifications */
7253 s->bufinfo.bufstate = t->bufinfo.bufstate;
7254 /* end modifications */
7256 llassert (valueTable_isUndefined (s->state));
7257 s->state = valueTable_copy (t->state);
7259 DPRINTF (("==> Copying state: %s", valueTable_unparse (s->state)));
7260 DPRINTF (("==> new: %s", sRef_unparseFull (s)));
7265 sRef_makeType (ctype ct)
7267 sRef s = sRef_newRef ();
7269 sRef_checkMutable (s);
7274 s->defstate = SS_UNKNOWN;
7275 s->aliaskind = AK_UNKNOWN;
7276 sRef_setNullStateN (s, NS_UNKNOWN);
7278 /* start modification */
7279 s->bufinfo.bufstate = BB_NOTNULLTERMINATED;
7280 /* end modification */
7283 if (ctype_isUA (ct))
7285 typeId uid = ctype_typeId (ct);
7286 uentry ue = usymtab_getTypeEntrySafe (uid);
7288 if (uentry_isValid (ue))
7290 sRef_mergeStateQuiet (s, uentry_getSref (ue));
7294 s->oaliaskind = s->aliaskind;
7295 s->oexpkind = s->expkind;
7296 llassert (valueTable_isUndefined (s->state));
7297 s->state = context_createValueTable (s, stateInfo_makeLoc (g_currentloc));
7299 DPRINTF (("Create: %s", sRef_unparseFull (s)));
7304 sRef_makeConst (ctype ct)
7306 sRef s = sRef_newRef ();
7311 s->defstate = SS_UNKNOWN;
7312 s->aliaskind = AK_UNKNOWN;
7313 sRef_setNullStateN (s, NS_UNKNOWN);
7315 /* start modification */
7316 s->bufinfo.bufstate = BB_NULLTERMINATED;
7317 /* end modification */
7319 /* evans 2002-04-22: added isManifestBool to avoid errors for -boolfalse initializations */
7320 if (!ctype_isManifestBool (ct) && ctype_isUA (ct))
7322 typeId uid = ctype_typeId (ct);
7323 uentry te = usymtab_getTypeEntrySafe (uid);
7325 if (uentry_isValid (te))
7327 sRef_mergeStateQuiet (s, uentry_getSref (te));
7331 s->oaliaskind = s->aliaskind;
7332 s->oexpkind = s->expkind;
7334 llassert (valueTable_isUndefined (s->state));
7335 s->state = context_createValueTable (s, stateInfo_makeLoc (g_currentloc));
7340 bool sRef_hasName (sRef s)
7342 if (sRef_isInvalid (s))
7351 uentry u = usymtab_getRefQuiet (s->info->cvar->lexlevel,
7352 s->info->cvar->index);
7353 return (uentry_hasName (u));
7357 if (s->info->paramno >= 0)
7359 uentry u = uentryList_getN (context_getParams (),
7362 return (uentry_hasName (u));
7366 llassert (s->info->paramno == PARAMUNKNOWN);
7376 sRef_sameName (sRef s1, sRef s2)
7378 if (sRef_isInvalid (s1))
7380 return sRef_isInvalid (s2);
7383 if (sRef_isInvalid (s2))
7391 if (s2->kind == SK_CVAR)
7393 return (s1->info->cvar->lexlevel == s2->info->cvar->lexlevel
7394 && s1->info->cvar->index == s2->info->cvar->index);
7396 else if (s2->kind == SK_PARAM)
7398 if (context_inFunctionLike ())
7400 if (s2->info->paramno != PARAMUNKNOWN)
7402 uentry u1 = usymtab_getRefQuiet (s1->info->cvar->lexlevel,
7403 s1->info->cvar->index);
7404 uentry u2 = uentryList_getN (context_getParams (),
7407 return (cstring_equalFree (uentry_getName (u1),
7408 uentry_getName (u2)));
7412 return s1->info->paramno == PARAMUNKNOWN;
7426 if (s2->kind == SK_PARAM)
7428 return (s1->info->paramno == s2->info->paramno);
7430 else if (s2->kind == SK_CVAR)
7432 if (context_inFunctionLike ())
7434 if (s1->info->paramno == PARAMUNKNOWN)
7440 uentry u1 = uentryList_getN (context_getParams (),
7442 uentry u2 = usymtab_getRefQuiet (s2->info->cvar->lexlevel,
7443 s2->info->cvar->index);
7446 return (cstring_equalFree (uentry_getName (u1),
7447 uentry_getName (u2)));
7461 case SK_UNCONSTRAINED:
7465 if (s2->kind == SK_ARRAYFETCH)
7467 if (bool_equal (s1->info->arrayfetch->indknown,
7468 s2->info->arrayfetch->indknown))
7470 if (!s1->info->arrayfetch->indknown
7471 || (s1->info->arrayfetch->ind == s2->info->arrayfetch->ind))
7473 return sRef_sameName (s1->info->arrayfetch->arr,
7474 s2->info->arrayfetch->arr);
7481 if (s2->kind == SK_FIELD)
7483 if (cstring_equal (s1->info->field->field,
7484 s2->info->field->field))
7486 return sRef_sameName (s1->info->field->rec,
7487 s2->info->field->rec);
7496 if (s2->kind == s1->kind)
7498 return sRef_sameName (s1->info->ref,
7506 return sRef_sameName (sRef_getConjA (s1), s2);
7510 return (s2->kind == SK_UNKNOWN);
7513 if (s2->kind == s1->kind)
7515 return (ctype_equal (s1->type, s2->type));
7520 if (s2->kind == SK_SPECIAL)
7522 return (s1->info->spec == s2->info->spec);
7526 return (s2->kind == SK_RESULT);
7534 sRef_fixOuterRef (/*@returned@*/ sRef s)
7536 sRef root = sRef_getRootBase (s);
7538 if (sRef_isCvar (root))
7540 uentry ue = usymtab_getRefQuiet (root->info->cvar->lexlevel,
7541 root->info->cvar->index);
7543 if (uentry_isValid (ue))
7545 sRef uref = uentry_getSref (ue);
7546 sRef sr = sRef_fixBase (s, uref);
7552 llcontbug (message ("sRef_fixOuterRef: undefined: %q", sRef_unparseDebug (s)));
7561 sRef_storeState (sRef s)
7563 if (sRef_isInvalid (s)) return;
7565 sRef_checkMutable (s);
7566 s->oaliaskind = s->aliaskind;
7567 s->oexpkind = s->expkind;
7570 static void sRef_resetStateAux (sRef s, /*@unused@*/ fileloc loc)
7572 sRef_resetState (s);
7576 sRef_resetState (sRef s)
7578 bool changed = FALSE;
7579 if (sRef_isInvalid (s)) return;
7582 if (s->oaliaskind == AK_KILLREF && !sRef_isParam (s))
7585 ** killref is used in a kludgey way, to save having to add
7586 ** another alias kind (see usymtab_handleParams)
7589 if (s->expkind != s->oexpkind)
7592 s->expkind = s->oexpkind;
7597 if (s->expkind != s->oexpkind)
7600 s->expkind = s->oexpkind;
7603 if (s->aliaskind != s->oaliaskind
7604 && s->aliaskind != AK_REFCOUNTED
7605 && s->aliaskind != AK_REFS)
7608 s->aliaskind = s->oaliaskind;
7614 sRef_clearDerived (s);
7620 sRef_resetStateComplete (sRef s)
7622 sRef_innerAliasSetComplete (sRef_resetStateAux, s, fileloc_undefined);
7626 sRef_fixBase (/*@returned@*/ sRef s, /*@returned@*/ sRef base)
7628 sRef tmp = sRef_undefined;
7631 if (sRef_isInvalid (s)) return s;
7632 if (sRef_isInvalid (base)) return base;
7642 tmp = sRef_fixBase (s->info->arrayfetch->arr, base);
7644 if (s->info->arrayfetch->indknown)
7646 ret = sRef_makeArrayFetchKnown (tmp, s->info->arrayfetch->ind);
7650 ret = sRef_makeArrayFetch (tmp);
7654 tmp = sRef_fixBase (s->info->field->rec, base);
7655 ret = sRef_buildNCField (tmp, s->info->field->field);
7658 tmp = sRef_fixBase (s->info->ref, base);
7659 ret = sRef_makePointer (tmp);
7662 tmp = sRef_fixBase (s->info->ref, base);
7663 ret = sRef_makeAddress (tmp);
7669 tmp = sRef_fixBase (s->info->conj->a, base);
7670 tmpb = sRef_fixBase (s->info->conj->b, base);
7672 ret = sRef_makeConj (tmp, tmpb);
7681 static /*@exposed@*/ sRef
7682 sRef_fixDirectBase (sRef s, sRef base)
7687 if (sRef_isInvalid (s))
7689 return sRef_undefined;
7695 if (s->info->arrayfetch->indknown)
7697 ret = sRef_makeArrayFetchKnown (base, s->info->arrayfetch->ind);
7701 ret = sRef_makeArrayFetch (base);
7705 ret = sRef_buildNCField (base, s->info->field->field);
7708 ret = sRef_makePointer (base);
7711 ret = sRef_makeAddress (base);
7717 tmpa = sRef_fixDirectBase (s->info->conj->a, base);
7718 tmpb = sRef_fixDirectBase (s->info->conj->b, base);
7720 ret = sRef_makeConj (tmpa, tmpb);
7726 sRef_copyState (ret, s);
7731 sRef_isAllocIndexRef (sRef s)
7733 return (sRef_isArrayFetch (s) && !(s->info->arrayfetch->indknown)
7734 && sRef_isAllocated (s->info->arrayfetch->arr));
7738 sRef_showRefLost (sRef s)
7740 if (sRef_hasAliasInfoLoc (s))
7742 llgenindentmsg (cstring_makeLiteral ("Original reference lost"),
7743 sRef_getAliasInfoLoc (s));
7748 sRef_showRefKilled (sRef s)
7750 if (sRef_hasStateInfoLoc (s))
7752 llgenindentmsg (message ("Storage %q released",
7753 sRef_unparse (s)), sRef_getStateInfoLoc (s));
7758 sRef_showStateInconsistent (sRef s)
7760 if (sRef_hasStateInfoLoc (s))
7763 (message ("Storage %qbecomes inconsistent (released on one branch)",
7764 sRef_unparseOpt (s)),
7765 sRef_getStateInfoLoc (s));
7770 sRef_showStateInfo (sRef s)
7772 if (sRef_hasStateInfoLoc (s))
7774 if (s->defstate == SS_DEAD)
7777 (message ("Storage %qis released", sRef_unparseOpt (s)),
7778 sRef_getStateInfoLoc (s));
7780 else if (s->defstate == SS_ALLOCATED || s->defstate == SS_DEFINED)
7783 (message ("Storage %qis %s", sRef_unparseOpt (s),
7784 sstate_unparse (s->defstate)),
7785 sRef_getStateInfoLoc (s));
7787 else if (s->defstate == SS_UNUSEABLE)
7790 (message ("Storage %qbecomes inconsistent (clauses merge with"
7791 "%qreleased on one branch)",
7792 sRef_unparseOpt (s),
7793 sRef_unparseOpt (s)),
7794 sRef_getStateInfoLoc (s));
7798 llgenindentmsg (message ("Storage %qbecomes %s",
7799 sRef_unparseOpt (s),
7800 sstate_unparse (s->defstate)),
7801 sRef_getStateInfoLoc (s));
7807 sRef_showExpInfo (sRef s)
7809 if (sRef_hasExpInfoLoc (s))
7811 llgenindentmsg (message ("Storage %qbecomes %s", sRef_unparseOpt (s),
7812 exkind_unparse (s->expkind)),
7813 sRef_getExpInfoLoc (s));
7818 sRef_showMetaStateInfo (sRef s, cstring key)
7821 metaStateInfo minfo = context_lookupMetaStateInfo (key);
7823 llassert (sRef_isReasonable (s));
7824 llassert (valueTable_isDefined (s->state));
7825 llassert (metaStateInfo_isDefined (minfo));
7827 val = valueTable_lookup (s->state, key);
7829 if (stateValue_hasLoc (val))
7832 (message ("%qbecomes %q", sRef_unparseOpt (s),
7833 stateValue_unparseValue (val, minfo)),
7834 stateValue_getLoc (val));
7839 sRef_showNullInfo (sRef s)
7841 DPRINTF (("Show null info: %s", sRef_unparseFull (s)));
7843 if (sRef_hasNullInfoLoc (s) && sRef_isKnown (s))
7845 DPRINTF (("has null info: %s",
7846 fileloc_unparse (sRef_getNullInfoLoc (s))));
7848 switch (sRef_getNullState (s))
7852 fileloc loc = sRef_getNullInfoLoc (s);
7854 if (fileloc_isDefined (loc) && !fileloc_isLib (loc))
7857 (message ("Storage %qbecomes null", sRef_unparseOpt (s)),
7864 fileloc loc = sRef_getNullInfoLoc (s);
7866 if (fileloc_isDefined (loc) && !fileloc_isLib (loc))
7868 llgenindentmsg (message ("Storage %qbecomes null", sRef_unparseOpt (s)),
7876 (message ("Storage %qmay become null", sRef_unparseOpt (s)),
7877 sRef_getNullInfoLoc (s));
7882 (message ("Storage %qbecomes not null", sRef_unparseOpt (s)),
7883 sRef_getNullInfoLoc (s));
7887 (message ("Storage %qnull state becomes unknown",
7888 sRef_unparseOpt (s)),
7889 sRef_getNullInfoLoc (s));
7898 (message ("<error case> Storage %q becomes %s",
7900 nstate_unparse (sRef_getNullState (s))),
7901 sRef_getNullInfoLoc (s));
7909 sRef_showAliasInfo (sRef s)
7911 if (sRef_hasAliasInfoLoc (s))
7913 if (sRef_isFresh (s))
7916 (message ("Fresh storage %qallocated", sRef_unparseOpt (s)),
7917 sRef_getAliasInfoLoc (s));
7921 if (!sRef_isRefCounted (s))
7924 (message ("Storage %qbecomes %s",
7925 sRef_unparseOpt (s),
7926 alkind_unparse (sRef_getAliasKind (s))),
7927 sRef_getAliasInfoLoc (s));
7934 sRef_mergeNullState (sRef s, nstate n)
7936 if (sRef_isReasonable (s))
7940 old = sRef_getNullState (s);
7942 if (n != old && n != NS_UNKNOWN)
7944 sRef_setNullState (s, n, g_currentloc);
7949 llbuglit ("sRef_mergeNullState: invalid");
7954 sRef_possiblyNull (sRef s)
7956 if (sRef_isReasonable (s))
7958 if (sRef_getNullState (s) == NS_ABSNULL)
7960 ctype rct = ctype_realType (s->type);
7962 if (ctype_isAbstract (rct))
7968 if (ctype_isUser (rct))
7970 uentry ue = usymtab_getTypeEntry (ctype_typeId (rct));
7972 return (nstate_possiblyNull
7973 (sRef_getNullState (uentry_getSref (ue))));
7983 return nstate_possiblyNull (sRef_getNullState (s));
7991 sRef_getScopeName (sRef s)
7993 sRef base = sRef_getRootBase (s);
7995 if (sRef_isRealGlobal (base))
7997 return (cstring_makeLiteralTemp ("Global"));
7999 else if (sRef_isFileStatic (base))
8001 return (cstring_makeLiteralTemp ("Static"));
8005 return (cstring_makeLiteralTemp ("Local"));
8010 sRef_unparseScope (sRef s)
8012 sRef base = sRef_getRootBase (s);
8014 if (sRef_isRealGlobal (base))
8016 return (cstring_makeLiteralTemp ("global"));
8018 else if (sRef_isFileStatic (base))
8020 return (cstring_makeLiteralTemp ("file static"));
8029 sRef_getScope (sRef s)
8031 llassert (sRef_isReasonable (s));
8033 if (sRef_isCvar (s))
8035 return s->info->cvar->lexlevel;
8037 else if (sRef_isParam (s))
8048 sRef_isDead (sRef s)
8050 return (sRef_isReasonable (s) && (s)->defstate == SS_DEAD);
8054 sRef_isDeadStorage (sRef s)
8056 if (sRef_isReasonable (s))
8058 if (s->defstate == SS_DEAD
8059 || s->defstate == SS_UNUSEABLE
8060 || s->defstate == SS_UNDEFINED
8061 || s->defstate == SS_UNKNOWN)
8067 return (sRef_isDefinitelyNull (s));
8077 sRef_isPossiblyDead (sRef s)
8079 return (sRef_isReasonable (s) && s->defstate == SS_HOFFA);
8082 bool sRef_isStateLive (sRef s)
8084 if (sRef_isReasonable (s))
8086 sstate ds = s->defstate;
8088 return (!(ds == SS_UNDEFINED
8090 || ds == SS_UNUSEABLE
8091 || ds == SS_HOFFA));
8100 bool sRef_isStateUndefined (sRef s)
8102 return ((sRef_isReasonable(s)) && ((s)->defstate == SS_UNDEFINED));
8105 bool sRef_isJustAllocated (sRef s)
8107 if (sRef_isAllocated (s))
8109 sRefSet_allElements (s->deriv, el)
8111 if (!(sRef_isStateUndefined (el) || sRef_isUnuseable (el)))
8115 } end_sRefSet_allElements ;
8124 sRef_isAllocatedStorage (sRef s)
8126 if (sRef_isReasonable (s) && ynm_toBoolStrict (sRef_isValidLvalue (s)))
8128 return (ctype_isVisiblySharable (sRef_getType (s)));
8137 sRef_isUnuseable (sRef s)
8139 return ((sRef_isValid(s)) && ((s)->defstate == SS_UNUSEABLE));
8143 sRef_perhapsNull (sRef s)
8145 if (sRef_isReasonable (s))
8147 if (sRef_getNullState (s) == NS_ABSNULL)
8149 ctype rct = ctype_realType (s->type);
8151 if (ctype_isAbstract (rct))
8157 if (ctype_isUser (rct))
8159 uentry ue = usymtab_getTypeEntry (ctype_typeId (rct));
8161 return (nstate_perhapsNull
8162 (sRef_getNullState (uentry_getSref (ue))));
8172 return nstate_perhapsNull (sRef_getNullState (s));
8180 ** definitelyNull --- called when TRUE is good
8184 sRef_definitelyNull (sRef s)
8186 return (sRef_isReasonable (s)
8187 && (sRef_getNullState (s) == NS_DEFNULL || sRef_getNullState (s) == NS_CONSTNULL));
8191 ** based on sRef_similar
8195 sRef_setDerivNullState (sRef set, sRef guide, nstate ns)
8197 if (sRef_isReasonable (set))
8199 sRef deriv = sRef_getDeriv (set, guide);
8201 if (sRef_isReasonable (deriv))
8203 sRef_setNullStateN (deriv, ns);
8208 static /*@exposed@*/ sRef
8209 sRef_getDeriv (/*@returned@*/ /*@notnull@*/ sRef set, sRef guide)
8211 llassert (sRef_isReasonable (set));
8212 llassert (sRef_isReasonable (guide));
8214 switch (guide->kind)
8217 llassert (set->kind == SK_CVAR);
8221 llassert (set->kind == guide->kind);
8222 llassert (set->info->paramno == guide->info->paramno);
8227 if (set->kind == SK_ARRAYFETCH
8228 && (sRef_similar (set->info->arrayfetch->arr,
8229 guide->info->arrayfetch->arr)))
8235 return (sRef_makeAnyArrayFetch
8236 (sRef_getDeriv (set, guide->info->arrayfetch->arr)));
8241 if (set->kind == SK_PTR && sRef_similar (set->info->ref, guide->info->ref))
8247 return (sRef_makePointer (sRef_getDeriv (set, guide->info->ref)));
8252 if ((set->kind == SK_FIELD &&
8253 (sRef_similar (set->info->field->rec, guide->info->field->rec) &&
8254 cstring_equal (set->info->field->field, guide->info->field->field))))
8260 return (sRef_makeField (sRef_getDeriv (set, guide->info->field->rec),
8261 guide->info->field->field));
8265 if ((set->kind == SK_ADR) && sRef_similar (set->info->ref, guide->info->ref))
8271 return (sRef_makeAddress (sRef_getDeriv (set, guide->info->ref)));
8276 return sRef_undefined;
8280 case SK_UNCONSTRAINED:
8288 return sRef_undefined;
8295 ** sRef_aliasCheckPred
8297 ** A confusing but spiffy function:
8299 ** Calls predf (s, e, text, <alias>) on s and all of s's aliases
8300 ** (unless checkAliases (s) is FALSE).
8302 ** For alias calls, calls as
8303 ** predf (alias, e, text, s)
8307 sRef_aliasCheckPred (bool (predf) (sRef, exprNode, sRef, exprNode),
8308 /*@null@*/ bool (checkAliases) (sRef),
8309 sRef s, exprNode e, exprNode err)
8311 bool error = (*predf)(s, e, sRef_undefined, err);
8314 if (checkAliases != NULL && !(checkAliases (s)))
8316 /* don't check aliases */
8320 sRefSet aliases = usymtab_allAliases (s);
8322 sRefSet_realElements (aliases, current)
8324 if (sRef_isReasonable (current))
8326 if (sRef_isReasonable (current))
8328 if (!sRef_similar (current, s)
8329 || (error && sRef_sameName (current, s)))
8331 (void) (*predf)(current, e, s, err);
8336 llcontbug (message ("Invalid sRef as alias field of %s", sRef_unparse (s)));
8339 } end_sRefSet_realElements;
8341 sRefSet_free (aliases);
8346 ** return TRUE iff predf (s) is true for s or any alias of s
8350 sRef_aliasCheckSimplePred (sRefTest predf, sRef s)
8361 aliases = usymtab_allAliases (s);
8363 sRefSet_realElements (aliases, current)
8365 if (sRef_isReasonable (current))
8367 sRef cref = sRef_updateSref (current);
8369 /* Whoa! a very kludgey way to make sure the right sref is used
8370 ** where there is a conditional symbol table. I am beginning
8371 ** to think that having a conditional symbol table wasn't such
8377 DPRINTF (("Checking alias: %s", sRef_unparseFull (cref)));
8378 sRefSet_free (aliases);
8382 } end_sRefSet_realElements;
8384 sRefSet_free (aliases);
8390 sRef_aliasCompleteSimplePred (bool (predf) (sRef), sRef s)
8393 bool result = FALSE;
8396 aliases = usymtab_allAliases (s);
8398 if ((*predf)(s)) result = TRUE;
8401 sRefSet_realElements (aliases, current)
8403 if (sRef_isReasonable (current))
8405 current = sRef_updateSref (current);
8406 if ((*predf)(current)) result = TRUE;
8408 } end_sRefSet_realElements;
8410 sRefSet_free (aliases);
8415 sRef_aliasSetComplete (void (predf) (sRef, fileloc), sRef s, fileloc loc)
8419 aliases = usymtab_allAliases (s);
8421 DPRINTF (("All aliases: %s", sRefSet_unparseFull (aliases)));
8425 sRefSet_realElements (aliases, current)
8427 if (sRef_isReasonable (current))
8429 current = sRef_updateSref (current);
8430 ((*predf)(current, loc));
8431 DPRINTF (("Killed: %s", sRef_unparseFull (current)));
8433 } end_sRefSet_realElements;
8435 sRefSet_free (aliases);
8439 sRef_aliasSetCompleteParam (void (predf) (sRef, int, fileloc), sRef s,
8440 int kind, fileloc loc)
8444 if (sRef_isDeep (s))
8446 aliases = usymtab_allAliases (s);
8450 aliases = usymtab_aliasedBy (s);
8453 (*predf)(s, kind, loc);
8455 sRefSet_realElements (aliases, current)
8457 if (sRef_isReasonable (current))
8459 current = sRef_updateSref (current);
8460 ((*predf)(current, kind, loc));
8462 } end_sRefSet_realElements;
8464 sRefSet_free (aliases);
8468 ** Version of aliasSetCompleteParam for alkind parameters
8472 sRef_aliasSetCompleteAlkParam (void (predf) (sRef, alkind, fileloc), sRef s,
8473 alkind kind, fileloc loc)
8477 if (sRef_isDeep (s))
8479 aliases = usymtab_allAliases (s);
8483 aliases = usymtab_aliasedBy (s);
8486 (*predf)(s, kind, loc);
8488 sRefSet_realElements (aliases, current)
8490 if (sRef_isReasonable (current))
8492 current = sRef_updateSref (current);
8493 ((*predf)(current, kind, loc));
8495 } end_sRefSet_realElements;
8497 sRefSet_free (aliases);
8501 sRef_innerAliasSetComplete (void (predf) (sRef, fileloc), sRef s, fileloc loc)
8507 if (!sRef_isReasonable (s)) return;
8510 ** Type equivalence checking is necessary --- there might be casting.
8517 case SK_UNCONSTRAINED:
8522 inner = s->info->ref;
8523 aliases = usymtab_allAliases (inner);
8524 ct = sRef_getType (inner);
8526 sRefSet_realElements (aliases, current)
8528 if (sRef_isReasonable (current))
8530 current = sRef_updateSref (current);
8532 if (ctype_equal (ct, sRef_getType (current)))
8534 sRef ptr = sRef_makePointer (current);
8535 ((*predf)(ptr, loc));
8538 } end_sRefSet_realElements;
8540 sRefSet_free (aliases);
8543 inner = s->info->arrayfetch->arr;
8544 aliases = usymtab_allAliases (inner);
8545 ct = sRef_getType (inner);
8547 DPRINTF (("Array fetch: %s", sRefSet_unparse (aliases)));
8549 sRefSet_realElements (aliases, current)
8551 if (sRef_isReasonable (current))
8553 current = sRef_updateSref (current);
8554 DPRINTF (("Current: %s", sRef_unparseFull (current)));
8556 if (ctype_equal (ct, sRef_getType (current)))
8558 if (s->info->arrayfetch->indknown)
8560 sRef af = sRef_makeArrayFetchKnown (current, s->info->arrayfetch->ind);
8561 DPRINTF (("Defining: %s", sRef_unparseFull (af)));
8562 /* evans 2001-08-27 This isn't true:
8563 llassert (af->info->arrayfetch->arr == current);
8564 see comments in buildArrayFetchKnown
8566 ((*predf)(af, loc));
8570 sRef af = sRef_makeArrayFetch (current);
8571 /* evans 2001-08-27 This isn't true:
8572 llassert (af->info->arrayfetch->arr == current);
8573 see comments in buildArrayFetch
8575 DPRINTF (("Defining: %s", sRef_unparseFull (af)));
8576 ((*predf)(af, loc));
8581 DPRINTF (("Type mismatch: %s / %s",
8583 ctype_unparse (sRef_getType (current))));
8586 } end_sRefSet_realElements;
8588 sRefSet_free (aliases);
8591 inner = s->info->field->rec;
8592 aliases = usymtab_allAliases (inner);
8593 ct = sRef_getType (inner);
8595 sRefSet_realElements (aliases, current)
8597 if (sRef_isReasonable (current))
8599 current = sRef_updateSref (current);
8601 if (ctype_equal (ct, sRef_getType (current)))
8603 sRef f = sRef_makeField (current, s->info->field->field);
8608 } end_sRefSet_realElements;
8610 sRefSet_free (aliases);
8613 sRef_innerAliasSetComplete (predf, s->info->conj->a, loc);
8614 sRef_innerAliasSetComplete (predf, s->info->conj->b, loc);
8631 sRef_innerAliasSetCompleteParam (void (predf) (sRef, sRef), sRef s, sRef t)
8637 if (!sRef_isReasonable (s)) return;
8640 ** Type equivalence checking is necessary --- there might be casting.
8647 case SK_UNCONSTRAINED:
8652 inner = s->info->ref;
8653 aliases = usymtab_allAliases (inner);
8654 ct = sRef_getType (inner);
8656 sRefSet_realElements (aliases, current)
8658 if (sRef_isReasonable (current))
8660 current = sRef_updateSref (current);
8662 if (ctype_equal (ct, sRef_getType (current)))
8664 sRef ptr = sRef_makePointer (current);
8669 } end_sRefSet_realElements;
8671 sRefSet_free (aliases);
8674 inner = s->info->arrayfetch->arr;
8675 aliases = usymtab_allAliases (inner);
8676 ct = sRef_getType (inner);
8678 sRefSet_realElements (aliases, current)
8680 if (sRef_isReasonable (current))
8682 current = sRef_updateSref (current);
8684 if (ctype_equal (ct, sRef_getType (current)))
8687 if (s->info->arrayfetch->indknown)
8689 sRef af = sRef_makeArrayFetchKnown (current, s->info->arrayfetch->ind);
8695 sRef af = sRef_makeArrayFetch (current);
8701 } end_sRefSet_realElements;
8703 sRefSet_free (aliases);
8706 inner = s->info->field->rec;
8707 aliases = usymtab_allAliases (inner);
8708 ct = sRef_getType (inner);
8711 sRefSet_realElements (aliases, current)
8713 if (sRef_isReasonable (current))
8715 current = sRef_updateSref (current);
8717 if (ctype_equal (ct, sRef_getType (current)))
8719 sRef f = sRef_makeField (current, s->info->field->field);
8724 } end_sRefSet_realElements;
8726 sRefSet_free (aliases);
8729 sRef_innerAliasSetCompleteParam (predf, s->info->conj->a, t);
8730 sRef_innerAliasSetCompleteParam (predf, s->info->conj->b, t);
8746 static void sRef_combineExKinds (/*@notnull@*/ sRef res, /*@notnull@*/ sRef other)
8748 exkind a1 = sRef_getExKind (res);
8749 exkind a2 = sRef_getExKind (other);
8751 if (a1 == a2 || a2 == XO_UNKNOWN)
8755 else if (a1 == XO_UNKNOWN)
8757 res->expinfo = stateInfo_update (res->expinfo, other->expinfo);
8762 res->expkind = XO_OBSERVER;
8767 ** Currently, this is a very ad hoc implementation, with lots of fixes to
8768 ** make real code work okay. I need to come up with some more general
8769 ** rules or principles here.
8773 sRef_combineAliasKindsError (/*@notnull@*/ sRef res,
8774 /*@notnull@*/ sRef other,
8775 clause cl, fileloc loc)
8777 bool hasError = FALSE;
8778 alkind ares = sRef_getAliasKind (res);
8779 alkind aother = sRef_getAliasKind (other);
8781 sRef_checkMutable (res);
8783 if (alkind_isDependent (ares))
8785 if (aother == AK_KEPT)
8787 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8788 res->aliaskind = AK_KEPT;
8792 if (aother == AK_LOCAL || aother == AK_STATIC
8793 || alkind_isTemp (aother))
8795 DPRINTF (("Setting dependent: %s", sRef_unparseFull (res)));
8796 res->aliaskind = AK_DEPENDENT;
8800 else if (alkind_isDependent (aother))
8802 if (ares == AK_KEPT)
8804 res->aliaskind = AK_KEPT;
8808 if (ares == AK_LOCAL || ares == AK_STATIC || alkind_isTemp (ares))
8810 DPRINTF (("Setting dependent: %s", sRef_unparseFull (res)));
8811 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8812 res->aliaskind = AK_DEPENDENT;
8816 else if ((ares == AK_LOCAL || ares == AK_UNIQUE
8817 || ares == AK_STATIC || alkind_isTemp (ares))
8818 && sRef_isFresh (other))
8821 ** cases like: if (s == NULL) s = malloc...;
8822 ** don't generate errors
8825 if (usymtab_isAltDefinitelyNullDeep (res))
8827 res->aliaskind = ares;
8834 else if ((aother == AK_LOCAL || aother == AK_UNIQUE
8835 || aother == AK_STATIC || alkind_isTemp (aother))
8836 && sRef_isFresh (res))
8839 ** cases like: if (s == NULL) s = malloc...;
8840 ** don't generate errors
8843 if (usymtab_isDefinitelyNullDeep (other))
8845 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8846 res->aliaskind = aother;
8853 else if (ares == AK_NEWREF && aother == AK_REFCOUNTED
8854 && sRef_isConst (other))
8856 res->aliaskind = AK_NEWREF;
8858 else if (aother == AK_NEWREF && ares == AK_REFCOUNTED
8859 && sRef_isConst (res))
8861 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8862 res->aliaskind = AK_NEWREF;
8864 else if (sRef_isLocalVar (res)
8865 && ((ares == AK_KEPT && aother == AK_LOCAL)
8866 || (aother == AK_KEPT && ares == AK_LOCAL)))
8868 res->aliaskind = AK_KEPT;
8877 if (sRef_isThroughArrayFetch (res))
8880 (FLG_BRANCHSTATE, FLG_STRICTBRANCHSTATE,
8882 ("Clauses exit with %q possibly referencing %s storage %s, "
8885 alkind_unparse (aother),
8886 clause_nameTaken (cl),
8887 alkind_unparse (ares),
8888 clause_nameAlternate (cl)),
8891 sRef_showAliasInfo (res);
8892 sRef_showAliasInfo (other);
8893 res->aliaskind = AK_ERROR;
8897 if (ares == AK_KEPT || aother == AK_KEPT)
8899 sRef_maybeKill (res, loc);
8907 message ("Clauses exit with %q referencing %s storage %s, "
8910 alkind_unparse (aother),
8911 clause_nameTaken (cl),
8912 alkind_unparse (ares),
8913 clause_nameAlternate (cl)),
8916 sRef_showAliasInfo (res);
8917 sRef_showAliasInfo (other);
8919 res->aliaskind = AK_ERROR;
8923 res->aliaskind = (sRef_isLocalVar (res) ? AK_LOCAL : AK_UNKNOWN);
8928 sRef_combineAliasKinds (/*@notnull@*/ sRef res, /*@notnull@*/ sRef other,
8929 clause cl, fileloc loc)
8931 alkind ares = sRef_getAliasKind (res);
8932 alkind aother = sRef_getAliasKind (other);
8934 sRef_checkMutable (res);
8936 DPRINTF (("Combine alias kinds: \n\t%s / \n\t%s",
8937 sRef_unparseFull (res), sRef_unparseFull (other)));
8938 if (alkind_equal (ares, aother)
8939 || aother == AK_UNKNOWN
8940 || aother == AK_ERROR)
8942 ; /* keep current state */
8944 else if (sRef_isDead (res) || sRef_isDead (other))
8946 /* dead error reported (or storage is dead) */
8947 res ->aliaskind = AK_ERROR;
8949 else if (ares == AK_UNKNOWN || ares == AK_ERROR
8950 || sRef_isStateUndefined (res)
8951 || sRef_isDefinitelyNull (res))
8953 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8954 res->aliaskind = aother;
8956 else if (sRef_isStateUndefined (other)
8957 || sRef_isDefinitelyNull (other))
8961 else if (((ares == AK_UNIQUE || alkind_isTemp (ares))
8962 && aother == AK_LOCAL)
8963 || ((aother == AK_UNIQUE || alkind_isTemp (aother))
8964 && ares == AK_LOCAL))
8966 if (ares != AK_LOCAL)
8968 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8971 res->aliaskind = AK_LOCAL;
8973 else if ((ares == AK_OWNED && aother == AK_FRESH)
8974 || (aother == AK_OWNED && ares == AK_FRESH))
8976 if (ares != AK_FRESH)
8978 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8981 res->aliaskind = AK_FRESH;
8983 else if ((ares == AK_KEEP && aother == AK_FRESH) ||
8984 (aother == AK_KEEP && ares == AK_FRESH))
8986 if (ares != AK_KEEP)
8988 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8991 res->aliaskind = AK_KEEP;
8993 else if ((ares == AK_LOCAL && aother == AK_STACK) ||
8994 (aother == AK_LOCAL && ares == AK_STACK))
8996 if (ares != AK_STACK)
8998 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
9001 res->aliaskind = AK_STACK;
9003 else if ((ares == AK_LOCAL
9004 && (aother == AK_OWNED && sRef_isLocalVar (other)))
9005 || (aother == AK_LOCAL
9006 && (ares == AK_OWNED && sRef_isLocalVar (res))))
9008 if (ares != AK_LOCAL)
9010 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
9013 res->aliaskind = AK_LOCAL;
9015 else if ((ares == AK_FRESH && alkind_isOnly (aother))
9016 || (aother == AK_FRESH && alkind_isOnly (ares)))
9018 res->aliaskind = AK_FRESH;
9020 else if ((aother == AK_FRESH && sRef_definitelyNull (res))
9021 || (ares == AK_FRESH && sRef_definitelyNull (other)))
9023 if (ares != AK_FRESH)
9025 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
9026 res->aliaskind = AK_FRESH;
9029 else if ((sRef_isFresh (res) && sRef_isConst (other))
9030 || (sRef_isFresh (other) && sRef_isConst (res)))
9033 ** for NULL constantants
9037 if (!sRef_isFresh (res))
9039 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
9042 res->aliaskind = AK_FRESH;
9044 else if ((alkind_isStatic (aother) && sRef_isConst (res))
9045 || (alkind_isStatic (ares) && sRef_isConst (other)))
9047 if (!alkind_isStatic (ares))
9049 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
9050 res->aliaskind = AK_STATIC;
9055 sRef_combineAliasKindsError (res, other, cl, loc);
9059 static void sRef_combineDefState (/*@notnull@*/ sRef res,
9060 /*@notnull@*/ sRef other)
9062 sstate s1 = res->defstate;
9063 sstate s2 = other->defstate;
9066 sRef_checkMutable (res);
9068 if (s1 == s2 || s2 == SS_UNKNOWN)
9072 else if (s1 == SS_UNKNOWN)
9081 if (s2 == SS_DEFINED)
9087 llcontbuglit ("ssfixed: not implemented");
9096 flip = (s2 != SS_DEFINED);
9114 res->definfo = stateInfo_update (res->definfo, other->definfo);
9119 extern /*@notnull@*/ sRef sRef_getConjA (sRef s)
9122 llassert (sRef_isConj (s));
9124 ret = s->info->conj->a;
9125 llassert (ret != NULL);
9129 extern /*@notnull@*/ sRef sRef_getConjB (sRef s)
9132 llassert (sRef_isConj (s));
9134 ret = s->info->conj->b;
9135 llassert (ret != NULL);
9139 extern /*@exposed@*/ sRef sRef_makeArrow (sRef s, /*@dependent@*/ cstring f)
9144 p = sRef_makePointer (s);
9145 ret = sRef_makeField (p, f);
9146 DPRINTF (("Arrow: %s => %s",
9147 sRef_unparseFull (s), sRef_unparseFull (ret)));
9151 extern /*@exposed@*/ sRef sRef_buildArrow (sRef s, cstring f)
9156 p = sRef_buildPointer (s);
9157 ret = sRef_buildField (p, f);
9162 static /*@null@*/ sinfo sinfo_copy (/*@notnull@*/ sRef s)
9169 ret = (sinfo) dmalloc (sizeof (*ret));
9170 ret->cvar = (cref) dmalloc (sizeof (*ret->cvar));
9171 ret->cvar->lexlevel = s->info->cvar->lexlevel;
9172 ret->cvar->index = s->info->cvar->index;
9176 ret = (sinfo) dmalloc (sizeof (*ret));
9177 ret->paramno = s->info->paramno;
9178 llassert (ret->paramno >= -1);
9182 ret = (sinfo) dmalloc (sizeof (*ret));
9183 ret->arrayfetch = (ainfo) dmalloc (sizeof (*ret->arrayfetch));
9184 ret->arrayfetch->indknown = s->info->arrayfetch->indknown;
9185 ret->arrayfetch->ind = s->info->arrayfetch->ind;
9186 ret->arrayfetch->arr = s->info->arrayfetch->arr; /* sRef_copy (s->info->arrayfetch->arr); */ /*@i32@*/
9190 ret = (sinfo) dmalloc (sizeof (*ret));
9191 ret->field = (fldinfo) dmalloc (sizeof (*ret->field));
9192 ret->field->rec = s->info->field->rec; /* sRef_copy (s->info->field->rec); */ /*@i32@*/
9193 ret->field->field = s->info->field->field;
9197 ret = (sinfo) dmalloc (sizeof (*ret));
9198 ret->object = s->info->object;
9205 ret = (sinfo) dmalloc (sizeof (*ret));
9206 ret->ref = s->info->ref; /* Ref_copy (s->info->ref); */
9210 ret = (sinfo) dmalloc (sizeof (*ret));
9211 ret->conj = (cjinfo) dmalloc (sizeof (*ret->conj));
9212 ret->conj->a = s->info->conj->a; /* sRef_copy (s->info->conj->a); */
9213 ret->conj->b = s->info->conj->b; /* sRef_copy (s->info->conj->b);*/
9216 ret = (sinfo) dmalloc (sizeof (*ret));
9217 ret->spec = s->info->spec;
9219 case SK_UNCONSTRAINED:
9221 ret = (sinfo) dmalloc (sizeof (*ret));
9222 ret->fname = s->info->fname;
9228 llassertprint (s->info == NULL, ("s = %s", sRef_unparse (s)));
9236 static /*@null@*/ sinfo sinfo_fullCopy (/*@notnull@*/ sRef s)
9241 ** Since its a full copy, only storage is assigned
9242 ** to dependent fields.
9249 ret = (sinfo) dmalloc (sizeof (*ret));
9250 ret->cvar = (cref) dmalloc (sizeof (*ret->cvar));
9251 ret->cvar->lexlevel = s->info->cvar->lexlevel;
9252 ret->cvar->index = s->info->cvar->index;
9256 ret = (sinfo) dmalloc (sizeof (*ret));
9257 ret->paramno = s->info->paramno;
9258 llassert (ret->paramno >= -1);
9262 ret = (sinfo) dmalloc (sizeof (*ret));
9263 ret->arrayfetch = (ainfo) dmalloc (sizeof (*ret->arrayfetch));
9264 ret->arrayfetch->indknown = s->info->arrayfetch->indknown;
9265 ret->arrayfetch->ind = s->info->arrayfetch->ind;
9266 ret->arrayfetch->arr = sRef_saveCopy (s->info->arrayfetch->arr);
9270 ret = (sinfo) dmalloc (sizeof (*ret));
9271 ret->field = (fldinfo) dmalloc (sizeof (*ret->field));
9272 ret->field->rec = sRef_saveCopy (s->info->field->rec);
9273 ret->field->field = s->info->field->field;
9277 ret = (sinfo) dmalloc (sizeof (*ret));
9278 ret->object = s->info->object;
9285 ret = (sinfo) dmalloc (sizeof (*ret));
9286 ret->ref = sRef_saveCopy (s->info->ref);
9290 ret = (sinfo) dmalloc (sizeof (*ret));
9291 ret->conj = (cjinfo) dmalloc (sizeof (*ret->conj));
9292 ret->conj->a = sRef_saveCopy (s->info->conj->a);
9293 ret->conj->b = sRef_saveCopy (s->info->conj->b);
9296 ret = (sinfo) dmalloc (sizeof (*ret));
9297 ret->spec = s->info->spec;
9300 case SK_UNCONSTRAINED:
9301 ret = (sinfo) dmalloc (sizeof (*ret));
9302 ret->fname = s->info->fname;
9308 llassert (s->info == NULL);
9318 sinfo_update (/*@notnull@*/ /*@exposed@*/ sRef res,
9319 /*@notnull@*/ /*@exposed@*/ sRef other)
9321 llassert (res->kind == other->kind);
9326 res->info->cvar->lexlevel = other->info->cvar->lexlevel;
9327 res->info->cvar->index = other->info->cvar->index;
9331 res->info->paramno = other->info->paramno;
9332 llassert (res->info->paramno >= -1);
9336 res->info->arrayfetch->indknown = other->info->arrayfetch->indknown;
9337 res->info->arrayfetch->ind = other->info->arrayfetch->ind;
9338 res->info->arrayfetch->arr = other->info->arrayfetch->arr;
9342 res->info->field->rec = other->info->field->rec;
9343 res->info->field->field = other->info->field->field;
9347 res->info->object = other->info->object;
9354 res->info->ref = other->info->ref;
9358 res->info->conj->a = other->info->conj->a;
9359 res->info->conj->b = other->info->conj->b;
9363 res->info->spec = other->info->spec;
9367 case SK_UNCONSTRAINED:
9368 res->info->fname = other->info->fname;
9375 llassert (res->info == NULL);
9380 static void sinfo_free (/*@special@*/ /*@temp@*/ /*@notnull@*/ sRef s)
9381 /*@uses s->kind, s->info@*/
9382 /*@releases s->info@*/
9387 DPRINTF (("Free sinfo: [%p]", s->info->cvar));
9388 sfree (s->info->cvar);
9395 DPRINTF (("Free sinfo: [%p]", s->info->arrayfetch));
9396 sfree (s->info->arrayfetch);
9400 DPRINTF (("Free sinfo: [%p]", s->info->field));
9401 sfree (s->info->field);
9410 case SK_EXTERNAL: /*@i32 is copy now! */
9414 DPRINTF (("Free sinfo: [%p]", s->info->conj));
9415 sfree (s->info->conj);
9418 case SK_UNCONSTRAINED:
9428 if (s->info != NULL) {
9429 DPRINTF (("Free sinfo: [%p]", s->info));
9435 bool sRef_isNSLocalVar (sRef s)
9437 if (sRef_isLocalVar (s))
9439 uentry ue = sRef_getUentry (s);
9441 return (!uentry_isStatic (ue));
9449 bool sRef_isLocalVar (sRef s)
9451 if (sRef_isValid(s))
9453 return (s->kind == SK_CVAR
9454 && (s->info->cvar->lexlevel > fileScope));
9460 bool sRef_isRealLocalVar (sRef s)
9462 if (sRef_isValid(s))
9464 if (s->kind == SK_CVAR)
9466 if (s->info->cvar->lexlevel == functionScope)
9468 uentry ue = sRef_getUentry (s);
9470 if (uentry_isAnyParam (ue)
9471 || uentry_isRefParam (ue))
9482 return (s->info->cvar->lexlevel > functionScope);
9490 bool sRef_isLocalParamVar (sRef s)
9492 if (sRef_isValid(s))
9494 return (s->kind == SK_PARAM
9495 || (s->kind == SK_CVAR
9496 && (s->info->cvar->lexlevel > fileScope)));
9502 static speckind speckind_fromInt (int i)
9505 llassert (i >= SR_NOTHING && i <= SR_SYSTEM);
9508 return ((speckind) i);
9512 static void sRef_updateNullState (/*@notnull@*/ sRef res, /*@notnull@*/ sRef other)
9515 res->nullstate = other->nullstate;
9516 res->nullinfo = stateInfo_update (res->nullinfo, other->nullinfo);
9517 sRef_resetAliasKind (res);
9520 void sRef_combineNullState (/*@notnull@*/ sRef res, /*@notnull@*/ sRef other)
9522 nstate n1 = sRef_getNullState (res);
9523 nstate n2 = sRef_getNullState (other);
9527 if (n1 == n2 || n2 == NS_UNKNOWN)
9533 /* note: n2 is not unknown or defnull */
9537 case NS_ERROR: nn = NS_ERROR; break;
9538 case NS_UNKNOWN: flip = TRUE; nn = n2; break;
9539 case NS_POSNULL: break;
9540 case NS_DEFNULL: nn = NS_POSNULL; break;
9541 case NS_RELNULL: break;
9543 if (n2 == NS_MNOTNULL)
9554 if (n2 == NS_NOTNULL)
9573 res->nullinfo = stateInfo_update (res->nullinfo, other->nullinfo);
9576 res->nullstate = nn;
9577 sRef_resetAliasKind (res);
9580 cstring sRef_nullMessage (sRef s)
9582 llassert (sRef_isReasonable (s));
9584 switch (sRef_getNullState (s))
9588 return (cstring_makeLiteralTemp ("null"));
9590 return (cstring_makeLiteralTemp ("possibly null"));
9595 /*@observer@*/ cstring sRef_ntMessage (sRef s)
9597 llassert (sRef_isReasonable (s));
9599 switch (s->nullstate)
9603 return (cstring_makeLiteralTemp ("not nullterminated"));
9605 return (cstring_makeLiteralTemp ("possibly non-nullterminated"));
9612 sRef sRef_fixResultType (/*@returned@*/ sRef s, ctype typ, uentry ue)
9614 sRef tmp = sRef_undefined;
9617 llassert (sRef_isReasonable (s));
9628 tmp = sRef_fixResultType (s->info->arrayfetch->arr, typ, ue);
9630 ct = ctype_realType (sRef_getType (tmp));
9633 if (ctype_isKnown (ct))
9635 if (ctype_isAP (ct))
9644 ("Special clause indexes non-array (%t): *%q",
9645 ct, sRef_unparse (s->info->arrayfetch->arr)),
9646 uentry_whereLast (ue));
9650 tmp = sRef_fixResultType (s->info->arrayfetch->arr, typ, ue);
9652 if (s->info->arrayfetch->indknown)
9654 ret = sRef_makeArrayFetchKnown (tmp, s->info->arrayfetch->ind);
9658 ret = sRef_makeArrayFetch (tmp);
9664 sRef rec = sRef_fixResultType (s->info->field->rec, typ, ue);
9665 ctype ct = ctype_realType (sRef_getType (rec));
9667 if (ctype_isKnown (ct))
9669 if (ctype_isSU (ct))
9671 if (uentry_isValid (uentryList_lookupField (ctype_getFields (ct),
9672 s->info->field->field)))
9681 ("Special clause accesses non-existent field of result: %q.%s",
9682 sRef_unparse (rec), s->info->field->field),
9683 uentry_whereLast (ue));
9691 ("Special clause accesses field of non-struct or union result (%t): %q.%s",
9692 ct, sRef_unparse (rec), s->info->field->field),
9693 uentry_whereLast (ue));
9697 ret = sRef_makeField (tmp, s->info->field->field);
9703 tmp = sRef_fixResultType (s->info->ref, typ, ue);
9705 ct = ctype_realType (sRef_getType (tmp));
9707 if (ctype_isKnown (ct))
9709 if (ctype_isAP (ct))
9718 ("Special clause dereferences non-pointer (%t): *%q",
9719 ct, sRef_unparse (s->info->ref)),
9720 uentry_whereLast (ue));
9724 ret = sRef_makePointer (tmp);
9731 ("Special clause uses & operator (not allowed): &%q", sRef_unparse (s->info->ref)),
9732 uentry_whereLast (ue));
9741 bool sRef_isOnly (sRef s)
9743 return (sRef_isValid(s) && alkind_isOnly (s->aliaskind));
9746 bool sRef_isDependent (sRef s)
9748 return (sRef_isValid(s) && alkind_isDependent (s->aliaskind));
9751 bool sRef_isOwned (sRef s)
9753 return (sRef_isReasonable (s) && (s->aliaskind == AK_OWNED));
9756 bool sRef_isKeep (sRef s)
9758 return (sRef_isReasonable (s) && (s->aliaskind == AK_KEEP));
9761 bool sRef_isTemp (sRef s)
9763 return (sRef_isReasonable (s) && alkind_isTemp (s->aliaskind));
9766 bool sRef_isLocalState (sRef s)
9768 return (sRef_isReasonable (s) && (s->aliaskind == AK_LOCAL));
9771 bool sRef_isUnique (sRef s)
9773 return (sRef_isReasonable (s) && (s->aliaskind == AK_UNIQUE));
9776 bool sRef_isShared (sRef s)
9778 return (sRef_isReasonable (s) && (s->aliaskind == AK_SHARED));
9781 bool sRef_isExposed (sRef s)
9783 return (sRef_isReasonable (s) && (s->expkind == XO_EXPOSED));
9786 bool sRef_isObserver (sRef s)
9788 return (sRef_isReasonable (s) && (s->expkind == XO_OBSERVER));
9791 bool sRef_isFresh (sRef s)
9793 return (sRef_isReasonable (s) && (s->aliaskind == AK_FRESH));
9796 bool sRef_isDefinitelyNull (sRef s)
9798 return (sRef_isReasonable (s) && (sRef_getNullState (s) == NS_DEFNULL
9799 || sRef_getNullState (s) == NS_CONSTNULL));
9802 bool sRef_isAllocated (sRef s)
9804 return (sRef_isReasonable (s) && (s->defstate == SS_ALLOCATED));
9807 bool sRef_isStack (sRef s)
9809 return (sRef_isReasonable (s) && (s->aliaskind == AK_STACK));
9812 bool sRef_isNotNull (sRef s)
9814 return (sRef_isValid(s) && (sRef_getNullState (s) == NS_MNOTNULL
9815 || sRef_getNullState (s) == NS_NOTNULL));
9818 alkind sRef_getAliasKind (sRef s)
9820 if (sRef_isValid(s)) {
9821 llassert (alkind_isValid (s->aliaskind));
9822 return s->aliaskind;
9828 nstate sRef_getNullState (sRef s)
9830 if (sRef_isReasonable (s)) {
9831 llassert (nstate_isValid (s->nullstate));
9832 return s->nullstate;
9838 void sRef_reflectAnnotation (sRef s, annotationInfo a, fileloc loc)
9840 if (sRef_isReasonable (s))
9842 if (!valueTable_isDefined (s->state))
9844 s->state = valueTable_create (1);
9845 valueTable_insert (s->state,
9846 cstring_copy (metaStateInfo_getName (annotationInfo_getState (a))),
9847 stateValue_create (annotationInfo_getValue (a), stateInfo_makeLoc (loc)));
9851 DPRINTF (("reflect loc: %s", fileloc_unparse (loc)));
9854 metaStateInfo_getName (annotationInfo_getState (a)),
9855 stateValue_create (annotationInfo_getValue (a), stateInfo_makeLoc (loc)));
9856 DPRINTF (("state info: %s", stateInfo_unparse (stateInfo_makeLoc (loc))));
9857 DPRINTF (("sref: %s", sRef_unparse (s)));
9858 DPRINTF (("sref: %s", sRef_unparseFull (s)));
9863 void sRef_setMetaStateValueComplete (sRef s, cstring key, int value, fileloc loc)
9865 sRefSet aliases = usymtab_allAliases (s);
9867 sRef_setMetaStateValue (s, key, value, loc);
9869 sRefSet_realElements (aliases, current)
9871 if (sRef_isReasonable (current))
9873 current = sRef_updateSref (current);
9874 sRef_setMetaStateValue (current, key, value, loc);
9876 } end_sRefSet_realElements ;
9878 sRefSet_free (aliases);
9881 void sRef_setMetaStateValue (sRef s, cstring key, int value, fileloc loc)
9883 sRef_checkMutable (s);
9885 if (sRef_isReasonable (s))
9887 if (!valueTable_isDefined (s->state))
9889 DPRINTF (("inserting state: %s: %s %d", sRef_unparse (s), key, value));
9890 s->state = valueTable_create (1);
9891 valueTable_insert (s->state, cstring_copy (key),
9892 stateValue_create (value, stateInfo_makeLoc (loc)));
9896 DPRINTF (("Updating state: %s: %s %d / %s", sRef_unparse (s), key, value,
9897 fileloc_unparse (loc)));
9898 if (valueTable_contains (s->state, key))
9901 (s->state, key, stateValue_create (value, stateInfo_makeLoc (loc)));
9906 (s->state, cstring_copy (key), stateValue_create (value, stateInfo_makeLoc (loc)));
9909 DPRINTF (("After: %s", sRef_unparseFull (s)));
9914 bool sRef_checkMetaStateValue (sRef s, cstring key, int value)
9916 if (sRef_isReasonable (s))
9918 if (valueTable_isDefined (s->state))
9922 DPRINTF (("check state: %s: %s %d", sRef_unparse (s), key, value));
9924 val = valueTable_lookup (s->state, key);
9925 llassert (stateValue_isDefined (val));
9926 return (stateValue_isError (val)
9927 || stateValue_getValue (val) == value);
9940 /*@observer@*/ stateValue sRef_getMetaStateValue (sRef s, cstring key)
9942 if (sRef_isReasonable (s))
9944 if (valueTable_isDefined (s->state))
9948 val = valueTable_lookup (s->state, key);
9949 /* Okay if its not defined, just returns stateValue_undefined */
9954 return stateValue_undefined;
9959 return stateValue_undefined;
9963 /*@observer@*/ valueTable sRef_getValueTable (sRef s)
9965 DPRINTF (("Get value table: %s", sRef_unparse (s)));
9967 if (sRef_isReasonable (s))
9969 llassert (sRef_isReasonable (s));
9970 DPRINTF (("Value table: %s", valueTable_unparse (s->state)));
9975 DPRINTF (("No value table!"));
9976 return valueTable_undefined;
9980 bool sRef_makeStateSpecial (sRef s)
9983 ** Default defined state can be made special.
9986 llassert (sRef_isReasonable (s)); /*@i523 why doesn't null-checking work!??? */
9988 if (s->defstate == SS_UNKNOWN || s->defstate == SS_DEFINED || s->defstate == SS_SPECIAL)
9990 /* s->aliaskind = AK_IMPTEMP; */ /* evans 2001-07-23 shouldn't effect alias state */
9991 s->defstate = SS_SPECIAL;
9992 DPRINTF (("Made special: %s", sRef_unparseFull (s)));
9997 /* s->aliaskind = AK_IMPTEMP; */
9998 s->defstate = SS_SPECIAL;
10003 void sRef_markImmutable (sRef s)
10005 if (sRef_isReasonable (s))
10007 DPRINTF (("Mark immutable: %s", sRef_unparseFull (s)));
10012 bool sRef_definitelyNullContext (sRef s)
10014 return (sRef_definitelyNull (s)
10015 || usymtab_isDefinitelyNullDeep (s));
10018 bool sRef_definitelyNullAltContext (sRef s)
10020 return (sRef_definitelyNull (s)
10021 || usymtab_isAltDefinitelyNullDeep (s));
10025 /* start modifications */
10026 struct s_bbufinfo sRef_getNullTerminatedState (sRef p_s) {
10027 struct s_bbufinfo BUFSTATE_UNKNOWN;
10028 BUFSTATE_UNKNOWN.bufstate = BB_NOTNULLTERMINATED;
10029 BUFSTATE_UNKNOWN.size = 0;
10030 BUFSTATE_UNKNOWN.len = 0;
10032 if (sRef_isValid(p_s))
10033 return p_s->bufinfo;
10034 return BUFSTATE_UNKNOWN;
10037 void sRef_setNullTerminatedState(sRef p_s) {
10038 if(sRef_isReasonable (p_s)) {
10039 p_s->bufinfo.bufstate = BB_NULLTERMINATED;
10041 llfatalbug( message("sRef_setNT passed a invalid sRef\n"));
10046 void sRef_setPossiblyNullTerminatedState(sRef p_s) {
10047 if( sRef_isReasonable (p_s)) {
10048 p_s->bufinfo.bufstate = BB_POSSIBLYNULLTERMINATED;
10050 llfatalbug( message("sRef_setPossNT passed a invalid sRef\n"));
10054 void sRef_setNotNullTerminatedState(sRef p_s) {
10055 if( sRef_isReasonable (p_s)) {
10056 p_s->bufinfo.bufstate = BB_NOTNULLTERMINATED;
10058 llfatalbug( message("sRef_unsetNT passed a invalid sRef\n"));
10062 void sRef_setLen(sRef p_s, int len) {
10063 if (sRef_isReasonable (p_s) && sRef_isNullTerminated(p_s))
10065 p_s->bufinfo.len = len;
10069 llfatalbug( message("sRef_setLen passed an invalid sRef\n"));
10074 void sRef_setSize(sRef p_s, int size) {
10075 if( sRef_isValid(p_s))
10077 p_s->bufinfo.size = size;
10081 llfatalbug( message("sRef_setSize passed a invalid sRef\n"));
10085 void sRef_resetLen(sRef p_s) {
10086 if (sRef_isReasonable (p_s))
10088 p_s->bufinfo.len = 0;
10092 llfatalbug (message ("sRef_setLen passed an invalid sRef\n"));
10096 /*drl7x 11/28/2000 */
10098 bool sRef_isFixedArray (sRef p_s) /*@*/ {
10100 c = sRef_getType (p_s);
10101 return ( ctype_isFixedArray (c) );
10104 size_t sRef_getArraySize (sRef p_s) /*@*/
10107 llassert (sRef_isFixedArray(p_s) );
10108 DPRINTF (( message ("sRef_getArraySize getting array size for %s", sRef_unparse(p_s) ) ));
10110 c = sRef_getType (p_s);
10111 return (ctype_getArraySize (c));
10114 void sRef_setValue (sRef s, multiVal val)
10116 if (!sRef_isReasonable (s))
10118 llcontbuglit ("Unreasonable sRef");
10119 llcontbug (message ("sRef: %s", sRef_unparse (s)));
10123 multiVal_free (s->val);
10127 bool sRef_hasValue (sRef s)
10129 return (sRef_isReasonable (s)
10130 && multiVal_isDefined (s->val));
10133 multiVal sRef_getValue (sRef s)
10135 if (sRef_isReasonable (s))
10140 return multiVal_undefined;