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);
1073 case SK_FIELD: /* evans 2002-07-17: added case for SK_FIELD */
1076 return uentry_undefined;
1082 sRef_getParam (sRef s)
1084 llassert (sRef_isReasonable (s));
1085 llassert (s->kind == SK_PARAM);
1087 return s->info->paramno;
1091 sRef_isModified (sRef s)
1093 return (!sRef_isReasonable (s) || s->modified);
1096 void sRef_setModified (sRef s)
1098 if (sRef_isReasonable (s))
1103 if (sRef_isRefsField (s))
1105 sRef base = sRef_getBase (s);
1107 llassert (s->kind == SK_FIELD);
1109 if (sRef_isPointer (base))
1111 base = sRef_getBase (base);
1114 if (sRef_isRefCounted (base))
1116 base->aliaskind = AK_NEWREF;
1123 ** note: this side-effects sRefSet to set modified to TRUE
1124 ** for any sRef similar to s.
1128 sRef_canModifyVal (sRef s, sRefSet sl)
1130 if (context_getFlag (FLG_MUSTMOD))
1132 return (sRef_doModifyVal (s, sl));
1136 return (sRef_checkModifyVal (s, sl));
1141 sRef_canModify (sRef s, sRefSet sl)
1143 if (context_getFlag (FLG_MUSTMOD))
1145 return (sRef_doModify (s, sl));
1149 return (sRef_checkModify (s, sl));
1158 bool sRef_checkModifyVal (sRef s, sRefSet sl)
1160 DPRINTF (("Check modify val: %s", sRef_unparse (s)));
1162 if (sRef_isInvalid (s))
1169 case SK_UNCONSTRAINED:
1173 DPRINTF (("Modify var: %s", sRef_unparse (s)));
1175 if (sRef_isFileOrGlobalScope (s))
1177 if (context_checkGlobMod (s))
1179 return (sRefSet_member (sl, s));
1189 return (sRefSet_member (sl, s)
1190 || alkind_isOnly (sRef_getOrigAliasKind (s)));
1192 /* special case if ind known */
1193 return (sRefSet_member (sl, s) ||
1194 sRef_checkModifyVal (s->info->arrayfetch->arr, sl));
1196 return (sRefSet_member (sl, s) || sRef_checkModifyVal (s->info->field->rec, sl));
1198 return (sRefSet_member (sl, s) || sRef_checkModifyVal (s->info->ref, sl));
1200 return (sRefSet_member (sl, s) || sRef_checkModifyVal (s->info->ref, sl));
1202 return ((sRef_checkModifyVal (s->info->conj->a, sl)) &&
1203 (sRef_checkModifyVal (s->info->conj->b, sl)));
1214 switch (s->info->spec)
1216 case SR_NOTHING: return TRUE;
1218 if (context_getFlag (FLG_INTERNALGLOBS))
1220 return (sRefSet_member (sl, s));
1226 case SR_SPECSTATE: return TRUE;
1227 case SR_SYSTEM: return (sRefSet_member (sl, s));
1228 case SR_GLOBALMARKER: BADBRANCH;
1231 case SK_RESULT: BADBRANCH;
1237 ** this should probably be elsewhere...
1239 ** returns TRUE iff sl indicates that s can be modified
1242 static bool sRef_checkModify (sRef s, sRefSet sl)
1244 llassert (sRef_isReasonable (s));
1248 case SK_UNCONSTRAINED:
1252 if (sRef_isFileOrGlobalScope (s))
1254 if (context_checkGlobMod (s))
1256 return (sRefSet_member (sl, s));
1268 return (sRefSet_member (sl, s) ||
1269 sRef_checkModifyVal (s->info->arrayfetch->arr, sl));
1272 sRef sr = s->info->field->rec;
1274 if (sr->kind == SK_PARAM)
1275 return TRUE; /* structs are copied on call */
1277 return (sRefSet_member (sl, s) || sRef_checkModifyVal (s->info->field->rec, sl));
1283 sm = sRefSet_member (sl, s);
1288 return (sRef_checkModifyVal (s->info->ref, sl));
1291 return (sRefSet_member (sl, s) || sRef_checkModifyVal (s->info->ref, sl));
1293 return ((sRef_checkModify (s->info->conj->a, sl)) &&
1294 (sRef_checkModify (s->info->conj->b, sl)));
1304 switch (s->info->spec)
1306 case SR_NOTHING: return TRUE;
1308 if (context_getFlag (FLG_INTERNALGLOBS))
1310 return (sRefSet_member (sl, s));
1316 case SR_SPECSTATE: return TRUE;
1317 case SR_SYSTEM: return (sRefSet_member (sl, s));
1318 case SR_GLOBALMARKER: BADBRANCH;
1321 case SK_RESULT: BADBRANCH;
1326 cstring sRef_stateVerb (sRef s)
1328 if (sRef_isDead (s))
1330 return cstring_makeLiteralTemp ("released");
1332 else if (sRef_isKept (s))
1334 return cstring_makeLiteralTemp ("kept");
1336 else if (sRef_isDependent (s))
1338 return cstring_makeLiteralTemp ("dependent");
1346 cstring sRef_stateAltVerb (sRef s)
1348 if (sRef_isDead (s))
1350 return cstring_makeLiteralTemp ("live");
1352 else if (sRef_isKept (s))
1354 return cstring_makeLiteralTemp ("not kept");
1356 else if (sRef_isDependent (s))
1358 return cstring_makeLiteralTemp ("independent");
1367 bool sRef_doModifyVal (sRef s, sRefSet sl)
1369 llassert (sRef_isReasonable (s));
1374 case SK_UNCONSTRAINED:
1378 if (sRef_isFileOrGlobalScope (s))
1381 if (context_checkGlobMod (s))
1383 return (sRefSet_modifyMember (sl, s));
1387 (void) sRefSet_modifyMember (sl, s);
1397 return (sRefSet_modifyMember (sl, s)
1398 || alkind_isOnly (sRef_getOrigAliasKind (s)));
1400 /* special case if ind known */
1401 /* unconditional OR, need side effect */
1402 return (OR (sRefSet_modifyMember (sl, s),
1403 sRef_doModifyVal (s->info->arrayfetch->arr, sl)));
1405 return (OR (sRefSet_modifyMember (sl, s),
1406 sRef_doModifyVal (s->info->field->rec, sl)));
1408 return (OR (sRefSet_modifyMember (sl, s),
1409 sRef_doModifyVal (s->info->ref, sl)));
1411 return (OR (sRefSet_modifyMember (sl, s),
1412 sRef_doModifyVal (s->info->ref, sl)));
1414 return (AND (sRef_doModifyVal (s->info->conj->a, sl) ,
1415 sRef_doModifyVal (s->info->conj->b, sl)));
1425 switch (s->info->spec)
1427 case SR_NOTHING: return TRUE;
1429 if (context_getFlag (FLG_INTERNALGLOBS))
1431 return (sRefSet_modifyMember (sl, s));
1435 (void) sRefSet_modifyMember (sl, s);
1438 case SR_SPECSTATE: return TRUE;
1439 case SR_SYSTEM: return (sRefSet_modifyMember (sl, s));
1440 case SR_GLOBALMARKER: BADBRANCH;
1444 case SK_RESULT: BADBRANCH;
1450 ** this should probably be elsewhere...
1452 ** returns TRUE iff sl indicates that s can be modified
1456 bool sRef_doModify (sRef s, sRefSet sl)
1458 llassert (sRef_isReasonable (s));
1462 case SK_UNCONSTRAINED:
1466 if (sRef_isFileOrGlobalScope (s))
1468 if (context_checkGlobMod (s))
1470 return (sRefSet_modifyMember (sl, s));
1474 (void) sRefSet_modifyMember (sl, s);
1486 return (OR (sRefSet_modifyMember (sl, s),
1487 sRef_doModifyVal (s->info->arrayfetch->arr, sl)));
1490 sRef sr = s->info->field->rec;
1492 if (sr->kind == SK_PARAM)
1494 return TRUE; /* structs are shallow-copied on call */
1497 return (OR (sRefSet_modifyMember (sl, s),
1498 sRef_doModifyVal (s->info->field->rec, sl)));
1502 return (OR (sRefSet_modifyMember (sl, s),
1503 sRef_doModifyVal (s->info->ref, sl)));
1506 return (OR (sRefSet_modifyMember (sl, s),
1507 sRef_doModifyVal (s->info->ref, sl)));
1509 return (AND (sRef_doModify (s->info->conj->a, sl),
1510 (sRef_doModify (s->info->conj->b, sl))));
1521 switch (s->info->spec)
1523 case SR_NOTHING: return TRUE;
1524 case SR_INTERNAL: return TRUE;
1525 case SR_SPECSTATE: return TRUE;
1526 case SR_SYSTEM: return (sRefSet_modifyMember (sl, s));
1527 case SR_GLOBALMARKER: BADBRANCH;
1530 case SK_RESULT: BADBRANCH;
1535 static /*@exposed@*/ sRef
1536 sRef_leastCommon (/*@exposed@*/ sRef s1, sRef s2)
1538 llassert (sRef_similar (s1, s2));
1540 if (!sRef_isReasonable (s1)) return s1;
1541 if (!sRef_isReasonable (s2)) return s1;
1543 sRef_combineDefState (s1, s2);
1544 sRef_combineNullState (s1, s2);
1545 sRef_combineExKinds (s1, s2);
1547 if (s1->aliaskind != s2->aliaskind)
1549 if (s1->aliaskind == AK_UNKNOWN)
1551 s1->aliaskind = s2->aliaskind;
1553 else if (s2->aliaskind == AK_UNKNOWN)
1559 s1->aliaskind = AK_ERROR;
1566 int sRef_compare (sRef s1, sRef s2)
1568 if (s1 == s2) return 0;
1570 if (sRef_isInvalid (s1)) return -1;
1571 if (sRef_isInvalid (s2)) return 1;
1573 INTCOMPARERETURN (s1->kind, s2->kind);
1574 INTCOMPARERETURN (s1->defstate, s2->defstate);
1575 INTCOMPARERETURN (s1->aliaskind, s2->aliaskind);
1577 DPRINTF (("Compare null state: %s / %s",
1578 sRef_unparseFull (s1),
1579 sRef_unparseFull (s2)));
1581 COMPARERETURN (nstate_compare (sRef_getNullState (s1),
1582 sRef_getNullState (s2)));
1587 return (int_compare (s1->info->paramno, s2->info->paramno));
1590 COMPARERETURN (sRef_compare (s1->info->arrayfetch->arr,
1591 s2->info->arrayfetch->arr));
1593 if (s1->info->arrayfetch->indknown && s2->info->arrayfetch->indknown)
1595 return (int_compare (s1->info->arrayfetch->ind,
1596 s2->info->arrayfetch->ind));
1598 if (!s1->info->arrayfetch->indknown && !s2->info->arrayfetch->indknown)
1605 COMPARERETURN (sRef_compare (s1->info->field->rec, s2->info->field->rec));
1607 if (cstring_equal (s1->info->field->field, s2->info->field->field))
1614 return (sRef_compare (s1->info->ref, s2->info->ref));
1616 COMPARERETURN (sRef_compare (s1->info->conj->a, s2->info->conj->a));
1617 return (sRef_compare (s1->info->conj->b, s2->info->conj->b));
1618 case SK_UNCONSTRAINED:
1619 return (cstring_compare (s1->info->fname, s2->info->fname));
1631 return (generic_compare (s1->info->spec, s2->info->spec));
1636 static bool cref_equal (cref c1, cref c2)
1638 return ((c1->lexlevel == c2->lexlevel) &&
1639 (usymId_equal (c1->index, c2->index)));
1643 ** returns true if s1 could be the same storage as s2.
1644 ** i.e., a[?] ~ a[3]. Note its not symmetric ... s1
1645 ** should be more specific.
1649 ** like similar, but matches objects <-> non-objects
1653 sRef_uniqueReference (sRef s)
1655 return (sRef_isFresh (s) || sRef_isUnique (s)
1656 || sRef_isOnly (s) || sRef_isStack (s)
1657 || sRef_isAddress (s));
1661 sRef_similarRelaxedAux (sRef s1, sRef s2)
1665 if (sRef_isUnknownArrayFetch (s1))
1675 if (sRef_isInvalid (s1) || sRef_isInvalid (s2)) return FALSE;
1677 if (sRef_isConj (s2))
1678 return (sRef_similarRelaxedAux (s1, sRef_getConjA (s2)) ||
1679 sRef_similarRelaxedAux (s1, sRef_getConjB (s2)));
1684 return ((s2->kind == SK_CVAR)
1685 && (cref_equal (s1->info->cvar, s2->info->cvar)));
1687 return ((s2->kind == SK_PARAM)
1688 && (s1->info->paramno == s2->info->paramno));
1690 if (s2->kind == SK_ARRAYFETCH)
1692 if (sRef_similarRelaxedAux (s1->info->arrayfetch->arr,
1693 s2->info->arrayfetch->arr))
1695 if (s1->info->arrayfetch->indknown)
1697 if (s2->info->arrayfetch->indknown)
1699 return (s1->info->arrayfetch->ind == s2->info->arrayfetch->ind);
1714 return ((s2->kind == SK_FIELD
1715 && (sRef_similarRelaxedAux (s1->info->field->rec,
1716 s2->info->field->rec)
1717 && cstring_equal (s1->info->field->field,
1718 s2->info->field->field))));
1720 return ((s2->kind == SK_PTR)
1721 && sRef_similarRelaxedAux (s1->info->ref, s2->info->ref));
1723 return ((s2->kind == SK_ADR)
1724 && sRef_similarRelaxedAux (s1->info->ref, s2->info->ref));
1726 return ((sRef_similarRelaxedAux (s1->info->conj->a, s2) ||
1727 (sRef_similarRelaxedAux (s1->info->conj->b, s2))));
1729 return (s1->info->spec == s2->info->spec);
1730 case SK_UNCONSTRAINED:
1731 return (cstring_equal (s1->info->fname, s2->info->fname));
1746 sRef_similarRelaxed (sRef s1, sRef s2)
1752 if (sRef_isThroughArrayFetch (s1))
1762 if (sRef_isInvalid (s1) || sRef_isInvalid (s2)) return FALSE;
1764 us1 = sRef_uniqueReference (s1);
1765 us2 = sRef_uniqueReference (s2);
1767 if ((s1->kind == SK_EXTERNAL && (s2->kind != SK_EXTERNAL && !us2))
1768 || (s2->kind == SK_EXTERNAL && (s1->kind != SK_EXTERNAL && !us1)))
1771 ** Previously, also:
1772 ** || (sRef_isExposed (s1) && !us2) || (sRef_isExposed (s2) && !us1)) ????
1774 ** No clue why this was there?!
1778 if (sRef_isExposed (s1) && sRef_isCvar (s1))
1780 uentry ue1 = sRef_getUentry (s1);
1782 if (uentry_isRefParam (ue1))
1784 return sRef_similarRelaxedAux (s1, s2);
1788 if (sRef_isExposed (s2) && sRef_isCvar (s2))
1790 uentry ue2 = sRef_getUentry (s2);
1792 if (uentry_isRefParam (ue2))
1794 return sRef_similarRelaxedAux (s1, s2);
1798 return (ctype_match (s1->type, s2->type));
1802 return sRef_similarRelaxedAux (s1, s2);
1807 sRef_similar (sRef s1, sRef s2)
1809 if (s1 == s2) return TRUE;
1810 if (sRef_isInvalid (s1) || sRef_isInvalid (s2)) return FALSE;
1812 if (sRef_isConj (s2))
1814 return (sRef_similar (s1, sRef_getConjA (s2)) ||
1815 sRef_similar (s1, sRef_getConjB (s2)));
1818 if (sRef_isDerived (s2))
1820 return (sRef_includedBy (s1, s2->info->ref));
1826 return ((s2->kind == SK_CVAR)
1827 && (cref_equal (s1->info->cvar, s2->info->cvar)));
1829 return ((s2->kind == SK_PARAM)
1830 && (s1->info->paramno == s2->info->paramno));
1832 if (s2->kind == SK_ARRAYFETCH)
1834 if (sRef_similar (s1->info->arrayfetch->arr,
1835 s2->info->arrayfetch->arr))
1837 if (s1->info->arrayfetch->indknown)
1839 if (s2->info->arrayfetch->indknown)
1841 return (s1->info->arrayfetch->ind == s2->info->arrayfetch->ind);
1856 if (s2->kind == SK_PTR)
1858 if (sRef_similar (s1->info->arrayfetch->arr,
1868 return ((s2->kind == SK_FIELD
1869 && (sRef_similar (s1->info->field->rec,
1870 s2->info->field->rec)
1871 && cstring_equal (s1->info->field->field,
1872 s2->info->field->field))));
1874 if (s2->kind == SK_PTR)
1876 return sRef_similar (s1->info->ref, s2->info->ref);
1880 if (s2->kind == SK_ARRAYFETCH)
1882 if (sRef_similar (s2->info->arrayfetch->arr,
1892 return ((s2->kind == SK_ADR)
1893 && sRef_similar (s1->info->ref, s2->info->ref));
1895 return ((sRef_similar (s1->info->conj->a, s2) ||
1896 (sRef_similar (s1->info->conj->b, s2))));
1898 return (sRef_includedBy (s2, s1->info->ref));
1899 case SK_UNCONSTRAINED:
1900 return (s2->kind == SK_UNCONSTRAINED
1901 && cstring_equal (s1->info->fname, s2->info->fname));
1911 return (s2->kind == SK_SPECIAL
1912 && (s1->info->spec == s2->info->spec));
1915 /*@notreached@*/ DPRINTF (("Fell through for: %s / %s", sRef_unparse (s1), sRef_unparse (s2)));
1920 ** return TRUE iff small can be derived from big.
1922 ** (e.g. x, x.a is includedBy x;
1923 ** x.a is included By x.a;
1927 sRef_includedBy (sRef small, sRef big)
1929 if (small == big) return TRUE;
1930 if (sRef_isInvalid (small) || sRef_isInvalid (big)) return FALSE;
1932 if (sRef_isConj (big))
1933 return (sRef_similar (small, sRef_getConjA (big)) ||
1934 sRef_similar (small, sRef_getConjB (big)));
1936 switch (small->kind)
1940 return (sRef_same (small, big));
1942 if (big->kind == SK_ARRAYFETCH)
1944 if (sRef_same (small->info->arrayfetch->arr, big->info->arrayfetch->arr))
1946 if (small->info->arrayfetch->indknown)
1948 if (big->info->arrayfetch->indknown)
1950 return (small->info->arrayfetch->ind == big->info->arrayfetch->ind);
1963 return (sRef_includedBy (small->info->arrayfetch->arr, big));
1965 if (big->kind == SK_FIELD)
1968 (sRef_same (small->info->field->rec, big->info->field->rec) &&
1969 cstring_equal (small->info->field->field, big->info->field->field));
1973 return (sRef_includedBy (small->info->field->rec, big));
1977 if (big->kind == SK_PTR)
1979 return sRef_same (small->info->ref, big->info->ref);
1983 return (sRef_includedBy (small->info->ref, big));
1987 return ((big->kind == SK_ADR) && sRef_similar (small->info->ref, big->info->ref));
1989 return ((sRef_includedBy (small->info->conj->a, big) ||
1990 (sRef_includedBy (small->info->conj->b, big))));
1992 return (sRef_includedBy (small->info->ref, big));
1993 case SK_UNCONSTRAINED:
2003 switch (small->info->spec)
2005 case SR_NOTHING: return TRUE;
2007 case SR_INTERNAL: return (sRef_isSpecInternalState (big) ||
2008 sRef_isFileStatic (big));
2009 case SR_SYSTEM: return (sRef_isSystemState (big));
2010 case SR_GLOBALMARKER: BADBRANCH;
2017 ** Same is similar to similar, but not quite the same.
2018 ** same and realSame aren't the same, but they are really similar.
2019 ** similarly, same is the same as same. but realSame is
2020 ** not really the same as same, or similar to similar.
2022 ** Similarly to similar, same checks if two sRefs are the same.
2023 ** The similarities end, however, when same compares arrays
2024 ** with unknown indexes. Similar returns false; same returns true.
2026 ** Similarly to similar and same, realSame is the same as same,
2027 ** except they do not behave the same when face with unknown
2028 ** sRefs. Same thinks they are not the same, but realSame thinks
2034 sRef_realSame (sRef s1, sRef s2)
2036 if (s1 == s2) return TRUE;
2038 if (sRef_isUnreasonable (s1)
2039 || sRef_isUnreasonable (s2))
2047 return ((s2->kind == SK_CVAR) && (cref_equal (s1->info->cvar, s2->info->cvar)));
2049 return ((s2->kind == SK_PARAM) && (s1->info->paramno == s2->info->paramno));
2051 if (s2->kind == SK_ARRAYFETCH)
2053 if (sRef_realSame (s1->info->arrayfetch->arr, s2->info->arrayfetch->arr))
2055 if (s1->info->arrayfetch->indknown && s2->info->arrayfetch->indknown)
2057 return (s1->info->arrayfetch->ind == s2->info->arrayfetch->ind);
2059 if (!s1->info->arrayfetch->indknown && !s2->info->arrayfetch->indknown)
2068 return ((s2->kind == SK_FIELD &&
2069 (sRef_realSame (s1->info->field->rec, s2->info->field->rec) &&
2070 cstring_equal (s1->info->field->field, s2->info->field->field))));
2072 return ((s2->kind == SK_PTR) && sRef_realSame (s1->info->ref, s2->info->ref));
2074 return ((s2->kind == SK_ADR) && sRef_realSame (s1->info->ref, s2->info->ref));
2076 return ((sRef_realSame (s1->info->conj->a, s2) ||
2077 (sRef_realSame (s1->info->conj->b, s2))));
2079 return ((s2->kind == SK_OBJECT)
2080 && ctype_match (s1->info->object, s2->info->object));
2082 return ((s2->kind == SK_EXTERNAL)
2083 && sRef_realSame (s1->info->ref, s2->info->ref));
2085 return ((s2->kind == SK_SPECIAL) && s1->info->spec == s2->info->spec);
2087 return ((s2->kind == SK_DERIVED) && sRef_realSame (s1->info->ref, s2->info->ref));
2088 case SK_UNCONSTRAINED:
2089 return ((s2->kind == SK_UNCONSTRAINED)
2090 && (cstring_equal (s1->info->fname, s2->info->fname)));
2096 return TRUE; /* changed this! was false */
2102 sRef_sameObject (sRef s1, sRef s2)
2108 ** same is similar to similar, but not quite the same.
2110 ** Similarly to similar, same checks is two sRefs are the same.
2111 ** The similarities end, however, when same compares arrays
2112 ** with unknown indexes. Similar returns false; same returns true.
2116 sRef_same (sRef s1, sRef s2)
2118 if (s1 == s2) return TRUE;
2119 if (sRef_isInvalid (s1) || sRef_isInvalid (s2)) return FALSE;
2124 return ((s2->kind == SK_CVAR) && (cref_equal (s1->info->cvar, s2->info->cvar)));
2126 return ((s2->kind == SK_PARAM) && (s1->info->paramno == s2->info->paramno));
2128 if (s2->kind == SK_ARRAYFETCH)
2130 llassert (s1->info->field->rec != s1);
2131 if (sRef_same (s1->info->arrayfetch->arr, s2->info->arrayfetch->arr))
2133 if (s1->info->arrayfetch->indknown && s2->info->arrayfetch->indknown)
2135 return (s1->info->arrayfetch->ind == s2->info->arrayfetch->ind);
2143 llassert (s1->info->field->rec != s1);
2144 return ((s2->kind == SK_FIELD &&
2145 (sRef_same (s1->info->field->rec, s2->info->field->rec) &&
2146 cstring_equal (s1->info->field->field, s2->info->field->field))));
2150 llassert (s1->info->ref != s1);
2151 return ((s2->kind == SK_PTR) && sRef_same (s1->info->ref, s2->info->ref));
2155 llassert (s1->info->ref != s1);
2156 return ((s2->kind == SK_ADR) && sRef_same (s1->info->ref, s2->info->ref));
2159 llassert (s1->info->conj->a != s1);
2160 llassert (s1->info->conj->b != s1);
2161 return ((sRef_same (s1->info->conj->a, s2)) && /* or or and? */
2162 (sRef_same (s1->info->conj->b, s2)));
2164 return ((s2->kind == SK_SPECIAL) && s1->info->spec == s2->info->spec);
2166 llassert (s1->info->ref != s1);
2167 return ((s2->kind == SK_DERIVED) && sRef_same (s1->info->ref, s2->info->ref));
2169 case SK_UNCONSTRAINED:
2182 ** sort of similar, for use in def/use
2186 sRef_closeEnough (sRef s1, sRef s2)
2188 if (s1 == s2) return TRUE;
2189 if (sRef_isInvalid (s1) || sRef_isInvalid (s2)) return FALSE;
2194 return (((s2->kind == SK_CVAR) &&
2195 (cref_equal (s1->info->cvar, s2->info->cvar))) ||
2196 (s2->kind == SK_UNCONSTRAINED && s1->info->cvar->lexlevel == 0));
2197 case SK_UNCONSTRAINED:
2198 return (s2->kind == SK_UNCONSTRAINED
2199 || ((s2->kind == SK_CVAR) && (s2->info->cvar->lexlevel == 0)));
2201 return ((s2->kind == SK_PARAM)
2202 && (s1->info->paramno == s2->info->paramno));
2204 if (s2->kind == SK_ARRAYFETCH)
2206 if (sRef_closeEnough (s1->info->arrayfetch->arr, s2->info->arrayfetch->arr))
2208 if (s1->info->arrayfetch->indknown && s2->info->arrayfetch->indknown)
2210 return (s1->info->arrayfetch->ind == s2->info->arrayfetch->ind);
2217 return ((s2->kind == SK_FIELD &&
2218 (sRef_closeEnough (s1->info->field->rec, s2->info->field->rec) &&
2219 cstring_equal (s1->info->field->field, s2->info->field->field))));
2221 return ((s2->kind == SK_PTR) && sRef_closeEnough (s1->info->ref, s2->info->ref));
2223 return ((s2->kind == SK_ADR) && sRef_closeEnough (s1->info->ref, s2->info->ref));
2225 return ((s2->kind == SK_DERIVED) && sRef_closeEnough (s1->info->ref, s2->info->ref));
2227 return ((sRef_closeEnough (s1->info->conj->a, s2)) ||
2228 (sRef_closeEnough (s1->info->conj->b, s2)));
2230 return ((s2->kind == SK_SPECIAL) && s1->info->spec == s2->info->spec);
2246 s is an sRef of a formal paramenter in a function call constraint
2247 we trys to return a constraint expression derived from the actual parementer of a function call.
2250 /*@only@*/ constraintExpr sRef_fixConstraintParam (/*@observer@*/ sRef s, /*@observer@*/ /*@temp@*/ exprNodeList args)
2254 if (sRef_isInvalid (s))
2255 llfatalbug((message("Invalid sRef")));
2261 /* s = sRef_saveCopy(s); */ /*@i523@*/
2262 ce = constraintExpr_makeTermsRef (s);
2269 temp = (sRef_makeField (sRef_fixBaseParam (s->info->field->rec, args),
2270 s->info->field->field));
2271 ce = constraintExpr_makeTermsRef (temp);
2277 temp = (sRef_makePointer (sRef_fixBaseParam (s->info->ref, args)));
2278 /* temp = sRef_saveCopy(temp); */ /*@i523@*/
2279 ce = constraintExpr_makeTermsRef (temp);
2286 temp = sRef_saveCopy(s);
2287 temp = sRef_fixBaseParam (temp, args);
2288 ce = constraintExpr_makeTermsRef (temp);
2296 temp = sRef_saveCopy(s);
2297 ce = constraintExpr_makeTermsRef (temp);
2302 llassert(exprNodeList_size (args) > s->info->paramno);
2304 exprNode e = exprNodeList_nth (args, s->info->paramno);
2306 llassert( !(exprNode_isError (e)) );
2307 ce = constraintExpr_makeExprNode (e);
2314 llcontbug (message ("Trying to do fixConstraintParam on nonparam, nonglobal: %q for function with arguments %q",
2315 sRef_unparse (s), exprNodeList_unparse(args)));
2316 temp = sRef_saveCopy(s);
2317 ce = constraintExpr_makeTermsRef (temp);
2326 sRef_fixBaseParam (/*@returned@*/ sRef s, exprNodeList args)
2328 if (sRef_isInvalid (s)) return (sRef_undefined);
2332 case SK_UNCONSTRAINED:
2337 if (exprNodeList_size (args) > s->info->paramno)
2339 exprNode e = exprNodeList_nth (args, s->info->paramno);
2341 if (exprNode_isError (e))
2343 return sRef_makeUnknown ();
2346 return (exprNode_getSref (e));
2350 return sRef_makeUnknown ();
2355 if (s->info->arrayfetch->indknown)
2357 return (sRef_makeArrayFetchKnown
2358 (sRef_fixBaseParam (s->info->arrayfetch->arr, args),
2359 s->info->arrayfetch->ind));
2363 return (sRef_makeArrayFetch
2364 (sRef_fixBaseParam (s->info->arrayfetch->arr, args)));
2369 DPRINTF (("Fix field: %s", sRef_unparseFull (s)));
2370 res = sRef_makeField (sRef_fixBaseParam (s->info->field->rec, args),
2371 s->info->field->field);
2372 DPRINTF (("Returns: %s", sRef_unparseFull (res)));
2376 return (sRef_makePointer (sRef_fixBaseParam (s->info->ref, args)));
2379 return (sRef_makeAddress (sRef_fixBaseParam (s->info->ref, args)));
2382 return (sRef_makeConj (sRef_fixBaseParam (s->info->conj->a, args),
2383 sRef_fixBaseParam (s->info->conj->b, args)));
2399 sRef_undumpGlobal (char **c)
2409 usymId uid = usymId_fromInt (reader_getInt (c));
2414 reader_checkChar (c, '@');
2415 defstate = sstate_fromInt (reader_getInt (c));
2417 reader_checkChar (c, '@');
2418 nullstate = nstate_fromInt (reader_getInt (c));
2420 ret = sRef_makeGlobal (uid, ctype_unknown, stateInfo_currentLoc ());
2421 sRef_setNullStateN (ret, nullstate);
2422 ret->defstate = defstate;
2427 int i = reader_getInt (c);
2428 speckind sk = speckind_fromInt (i);
2432 case SR_NOTHING: return (sRef_makeNothing ());
2433 case SR_INTERNAL: return (sRef_makeInternalState ());
2434 case SR_SPECSTATE: return (sRef_makeSpecState ());
2435 case SR_SYSTEM: return (sRef_makeSystemState ());
2436 case SR_GLOBALMARKER: BADBRANCH;
2441 return sRef_undefined;
2443 return sRef_makeUnknown ();
2445 return sRef_makeUnknown ();
2447 llfatalerror (message ("sRef_undumpGlobal: bad line: %s",
2448 cstring_fromChars (*c)));
2453 static /*@exposed@*/ sRef sRef_undumpBody (char **c)
2462 return (sRef_makeGlobal (usymId_fromInt (reader_getInt (c)), ctype_unknown, stateInfo_currentLoc ()));
2464 return (sRef_makeParam (reader_getInt (c), ctype_unknown, stateInfo_makeLoc (g_currentloc)));
2466 return (sRef_makeResult (ctype_undump (c)));
2469 if ((**c >= '0' && **c <= '9') || **c == '-')
2471 int i = reader_getInt (c);
2472 sRef arr = sRef_undump (c);
2473 sRef ret = sRef_buildArrayFetchKnown (arr, i);
2479 sRef arr = sRef_undump (c);
2480 sRef ret = sRef_buildArrayFetch (arr);
2487 cstring fname = cstring_undefined;
2492 fname = cstring_appendChar (fname, **c);
2497 ret = sRef_buildField (sRef_undump (c), fname);
2498 cstring_markOwned (fname);
2503 int i = reader_getInt (c);
2504 speckind sk = speckind_fromInt (i);
2508 case SR_NOTHING: return (sRef_makeNothing ());
2509 case SR_INTERNAL: return (sRef_makeInternalState ());
2510 case SR_SPECSTATE: return (sRef_makeSpecState ());
2511 case SR_SYSTEM: return (sRef_makeSystemState ());
2512 case SR_GLOBALMARKER: BADBRANCH;
2518 sRef ptr = sRef_undump (c);
2519 sRef ret = sRef_makePointer (ptr);
2525 sRef adr = sRef_undump (c);
2526 sRef ret = sRef_makeAddress (adr);
2532 return (sRef_makeObject (ctype_undump (c)));
2536 sRef s1 = sRef_undump (c);
2537 sRef s2 = ((*c)++, sRef_undump (c));
2538 sRef ret = sRef_makeConj (s1, s2);
2543 return sRef_undefined;
2545 return sRef_makeUnknown ();
2547 return sRef_makeUnknown ();
2549 llfatalerror (message ("sRef_undump: bad line: %s", cstring_fromChars (*c)));
2554 /*@exposed@*/ sRef sRef_undump (char **c)
2556 sRef res = sRef_undumpBody (c);
2558 if (reader_optCheckChar (c, '='))
2560 multiVal mv = multiVal_undump (c);
2561 sRef_setValue (res, mv);
2562 reader_checkChar (c, '=');
2568 static /*@only@*/ cstring sRef_dumpBody (sRef s)
2570 if (sRef_isInvalid (s))
2572 return (cstring_makeLiteral ("-"));
2579 return (message ("p%d", s->info->paramno));
2581 if (s->info->arrayfetch->indknown)
2583 return (message ("a%d%q", s->info->arrayfetch->ind,
2584 sRef_dump (s->info->arrayfetch->arr)));
2588 return (message ("a%q", sRef_dump (s->info->arrayfetch->arr)));
2591 return (message ("f%s.%q", s->info->field->field,
2592 sRef_dump (s->info->field->rec)));
2594 return (message ("t%q", sRef_dump (s->info->ref)));
2596 return (message ("d%q", sRef_dump (s->info->ref)));
2598 return (message ("o%q", ctype_dump (s->info->object)));
2600 return (message ("s%d", (int) s->info->spec));
2602 return (message ("c%q.%q",
2603 sRef_dump (s->info->conj->a),
2604 sRef_dump (s->info->conj->b)));
2606 if (sRef_isFileOrGlobalScope (s))
2608 return (message ("g%d",
2609 usymtab_convertId (s->info->cvar->index)));
2613 llcontbug (message ("Dumping local variable: %q",
2614 sRef_unparseDebug (s)));
2615 return (cstring_makeLiteral ("u"));
2618 return (cstring_makeLiteral ("u"));
2620 return (message ("r%q", ctype_dump (s->type)));
2626 case SK_UNCONSTRAINED:
2627 llcontbug (message ("sRef_dump: bad kind: %q",
2628 sRef_unparseFull (s)));
2629 return (cstring_makeLiteral ("x"));
2636 /*@only@*/ cstring sRef_dump (sRef s)
2638 cstring res = sRef_dumpBody (s);
2640 if (sRef_hasValue (s))
2642 res = message ("%q=%q=", res, multiVal_dump (sRef_getValue (s)));
2648 cstring sRef_dumpGlobal (sRef s)
2650 llassert (!sRef_hasValue (s));
2652 if (sRef_isInvalid (s))
2654 return (cstring_makeLiteral ("-"));
2661 if (sRef_isFileOrGlobalScope (s))
2663 return (message ("g%d@%d@%d",
2664 usymtab_convertId (s->info->cvar->index),
2666 (int) sRef_getNullState (s)));
2670 llcontbug (message ("Dumping local variable: %q",
2671 sRef_unparseDebug (s)));
2672 return (cstring_makeLiteral ("u"));
2675 return (cstring_makeLiteral ("u"));
2677 return (message ("s%d", (int) s->info->spec));
2679 llcontbug (message ("sRef_dumpGlobal: bad kind: %q",
2680 sRef_unparseFull (s)));
2681 return (cstring_makeLiteral ("x"));
2689 sRef_deriveType (sRef s, uentryList cl)
2691 if (sRef_isInvalid (s)) return ctype_unknown;
2696 return (uentry_getType (usymtab_getRefQuiet (s->info->cvar->lexlevel,
2697 s->info->cvar->index)));
2698 case SK_UNCONSTRAINED:
2699 return (ctype_unknown);
2701 if (s->info->paramno >= 0)
2703 return uentry_getType (uentryList_getN (cl, s->info->paramno));
2707 return ctype_unknown;
2711 ctype ca = sRef_deriveType (s->info->arrayfetch->arr, cl);
2713 if (ctype_isArray (ca))
2715 return (ctype_baseArrayPtr (ca));
2717 else if (ctype_isUnknown (ca))
2723 llcontbuglit ("sRef_deriveType: inconsistent array type");
2729 ctype ct = sRef_deriveType (s->info->field->rec, cl);
2731 if (ctype_isStructorUnion (ct))
2733 uentry ue = uentryList_lookupField (ctype_getFields (ct),
2734 s->info->field->field);
2736 if (uentry_isValid (ue))
2738 return (uentry_getType (ue));
2742 llcontbuglit ("sRef_deriveType: bad field");
2743 return ctype_unknown;
2746 else if (ctype_isUnknown (ct))
2752 llcontbuglit ("sRef_deriveType: inconsistent field type");
2758 ctype ct = sRef_deriveType (s->info->ref, cl);
2760 if (ctype_isUnknown (ct)) return ct;
2761 if (ctype_isPointer (ct)) return (ctype_baseArrayPtr (ct));
2764 llcontbuglit ("sRef_deriveType: inconsistent pointer type");
2770 ctype ct = sRef_deriveType (s->info->ref, cl);
2772 if (ctype_isUnknown (ct)) return ct;
2773 return ctype_makePointer (ct);
2777 return sRef_deriveType (s->info->ref, cl);
2781 return (s->info->object);
2785 return (ctype_makeConj (sRef_deriveType (s->info->conj->a, cl),
2786 sRef_deriveType (s->info->conj->b, cl)));
2798 return ctype_unknown;
2804 sRef_getType (sRef s)
2806 if (sRef_isInvalid (s)) return ctype_unknown;
2812 sRef_unparseOpt (sRef s)
2814 sRef rb = sRef_getRootBase (s);
2816 if (sRef_isMeaningful (rb) && !sRef_isConst (rb))
2818 cstring ret = sRef_unparse (s);
2820 llassertprint (!cstring_equalLit (ret, "?"), ("print: %s", sRef_unparseDebug (s)));
2822 if (!cstring_isEmpty (ret))
2824 return (cstring_appendChar (ret, ' '));
2832 return cstring_undefined;
2836 sRef_unparsePreOpt (sRef s)
2838 sRef rb = sRef_getRootBase (s);
2840 if (sRef_isMeaningful (rb) && !sRef_isConst (rb))
2842 cstring ret = sRef_unparse (s);
2844 llassertprint (!cstring_equalLit (ret, "?"), ("print: %s", sRef_unparseDebug (s)));
2845 return (cstring_prependCharO (' ', ret));
2848 return cstring_undefined;
2852 sRef_unparse (sRef s)
2854 if (sRef_isInvalid (s)) return (cstring_makeLiteral ("?"));
2856 if (context_inFunctionLike ())
2858 return (sRef_unparseWithArgs (s, context_getParams ()));
2862 DPRINTF (("Not in function like: %s", context_unparse ()));
2863 return (sRef_unparseNoArgs (s));
2867 static /*@only@*/ cstring
2868 sRef_unparseWithArgs (sRef s, uentryList args)
2870 if (sRef_isInvalid (s))
2872 return (cstring_makeLiteral ("?"));
2878 return (uentry_getName (usymtab_getRefQuiet (s->info->cvar->lexlevel,
2879 s->info->cvar->index)));
2880 case SK_UNCONSTRAINED:
2881 return (cstring_copy (s->info->fname));
2884 if (s->info->paramno < uentryList_size (args)
2885 && s->info->paramno >= 0)
2887 uentry ue = uentryList_getN (args, s->info->paramno);
2889 if (uentry_isValid (ue))
2890 return uentry_getName (ue);
2893 return (message ("parameter %d", s->info->paramno + 1));
2896 if (s->info->arrayfetch->indknown)
2898 return (message ("%q[%d]", sRef_unparseWithArgs (s->info->arrayfetch->arr, args),
2899 s->info->arrayfetch->ind));
2903 return (message ("%q[]", sRef_unparseWithArgs (s->info->arrayfetch->arr, args)));
2906 if (s->info->field->rec->kind == SK_PTR)
2908 sRef ptr = s->info->field->rec;
2910 return (message ("%q->%s", sRef_unparseWithArgs (ptr->info->ref, args),
2911 s->info->field->field));
2913 return (message ("%q.%s", sRef_unparseWithArgs (s->info->field->rec, args),
2914 s->info->field->field));
2918 sRef ref = sRef_fixConj (s->info->ref);
2919 skind sk = ref->kind;
2924 ret = message ("storage pointed to by %q",
2925 sRef_unparseWithArgs (ref, args));
2927 else if (skind_isSimple (sk) || sk == SK_PTR)
2929 ret = message ("*%q", sRef_unparseWithArgs (ref, args));
2933 ret = message ("*(%q)", sRef_unparseWithArgs (ref, args));
2939 return (message ("&%q", sRef_unparseWithArgs (s->info->ref, args)));
2941 return (cstring_copy (ctype_unparse (s->info->object)));
2943 return (sRef_unparseWithArgs (sRef_getConjA (s), args));
2945 if (cstring_isDefined (s->info->fname))
2947 return (message ("[result of %s]", s->info->fname));
2951 return (cstring_makeLiteral ("<new>"));
2954 return (cstring_makeLiteral ("?"));
2956 return (message ("<derived %q>", sRef_unparse (s->info->ref)));
2958 return (message ("<external %q>", sRef_unparse (s->info->ref)));
2960 return (message ("<type %s>", ctype_unparse (s->type)));
2962 return (message ("<const %s>", ctype_unparse (s->type)));
2964 switch (s->info->spec)
2966 case SR_NOTHING: return cstring_makeLiteral ("nothing");
2967 case SR_INTERNAL: return cstring_makeLiteral ("internal state");
2968 case SR_SPECSTATE: return cstring_makeLiteral ("spec state");
2969 case SR_SYSTEM: return cstring_makeLiteral ("file system state");
2970 case SR_GLOBALMARKER: return cstring_makeLiteral ("<global marker>");
2974 return cstring_makeLiteral ("result");
2977 llbug (message ("Bad sref, kind = %d", (int) s->kind));
2985 sRef_unparseDebug (sRef s)
2987 if (sRef_isInvalid (s))
2989 return (cstring_makeLiteral ("<undef>"));
2995 case SK_UNCONSTRAINED:
2996 return (message ("<unconstrained %s>", s->info->fname));
3001 ce = usymtab_getRefQuiet (s->info->cvar->lexlevel, s->info->cvar->index);
3003 if (uentry_isInvalid (ce))
3005 return (message ("<scope: %d.%d *invalid*>",
3006 s->info->cvar->lexlevel,
3007 s->info->cvar->index));
3011 return (message ("<scope: %d.%d *%q*>",
3012 s->info->cvar->lexlevel,
3013 s->info->cvar->index,
3014 uentry_getName (ce)));
3020 return (message ("<parameter %d>", s->info->paramno + 1));
3023 if (s->info->arrayfetch->indknown)
3025 return (message ("%q[%d]", sRef_unparseDebug (s->info->arrayfetch->arr),
3026 s->info->arrayfetch->ind));
3030 return (message ("%q[]", sRef_unparseDebug (s->info->arrayfetch->arr)));
3033 return (message ("%q.%s", sRef_unparseDebug (s->info->field->rec),
3034 s->info->field->field));
3036 if (sRef_isField (s->info->ref))
3038 sRef fld = s->info->ref;
3040 return (message ("%q->%s", sRef_unparseDebug (fld->info->field->rec),
3041 fld->info->field->field));
3045 return (message ("*(%q)", sRef_unparseDebug (s->info->ref)));
3048 return (message ("&%q", sRef_unparseDebug (s->info->ref)));
3050 return (message ("<object type %s>", ctype_unparse (s->info->object)));
3052 return (message ("%q | %q", sRef_unparseDebug (s->info->conj->a),
3053 sRef_unparseDebug (s->info->conj->b)));
3055 return message ("<new: %s>", s->info->fname);
3057 return (message ("<derived %q>", sRef_unparseDebug (s->info->ref)));
3059 return (message ("<external %q>", sRef_unparseDebug (s->info->ref)));
3061 return (message ("<type %s>", ctype_unparse (s->type)));
3063 if (sRef_hasValue (s))
3065 return (message ("<const %s=%q>", ctype_unparse (s->type), multiVal_unparse (sRef_getValue (s))));
3069 return (message ("<const %s>", ctype_unparse (s->type)));
3072 return (message ("<result %s>", ctype_unparse (s->type)));
3074 return (message ("<spec %s>",
3075 cstring_makeLiteralTemp
3076 (s->info->spec == SR_NOTHING ? "nothing"
3077 : s->info->spec == SR_INTERNAL ? "internalState"
3078 : s->info->spec == SR_SPECSTATE ? "spec state"
3079 : s->info->spec == SR_SYSTEM ? "fileSystem"
3082 return cstring_makeLiteral ("<unknown>");
3088 static /*@only@*/ cstring
3089 sRef_unparseNoArgs (sRef s)
3091 if (sRef_isInvalid (s)) return (cstring_makeLiteral ("?"));
3095 case SK_UNCONSTRAINED:
3096 return (cstring_copy (s->info->fname));
3099 uentry ce = usymtab_getRefQuiet (s->info->cvar->lexlevel,
3100 s->info->cvar->index);
3102 if (uentry_isInvalid (ce))
3104 llcontbug (message ("sRef_unparseNoArgs: bad cvar: %q",
3105 sRef_unparseDebug (s)));
3106 return (sRef_unparseDebug (s));
3110 return (uentry_getName (ce));
3114 if (s->info->arrayfetch->indknown)
3116 return (message ("%q[%d]", sRef_unparseNoArgs (s->info->arrayfetch->arr),
3117 s->info->arrayfetch->ind));
3121 return (message ("%q[]", sRef_unparseNoArgs (s->info->arrayfetch->arr)));
3124 return (message ("%q.%s", sRef_unparseNoArgs (s->info->field->rec),
3125 s->info->field->field));
3128 sRef ref = sRef_fixConj (s->info->ref);
3129 skind sk = ref->kind;
3132 if (skind_isSimple (sk) || sk == SK_PTR)
3134 ret = message ("*%q", sRef_unparseNoArgs (ref));
3138 ret = message ("*(%q)", sRef_unparseNoArgs (ref));
3144 return (message ("&%q", sRef_unparseNoArgs (s->info->ref)));
3146 return (cstring_copy (ctype_unparse (s->info->object)));
3148 return (sRef_unparseNoArgs (s->info->conj->a));
3150 return (message ("result of %s", s->info->fname));
3152 return (message ("<der %q>", sRef_unparseNoArgs (s->info->ref)));
3154 return message ("<ext %q>", sRef_unparseNoArgs (s->info->ref));
3156 return (cstring_makeLiteral
3157 (s->info->spec == SR_NOTHING ? "nothing"
3158 : s->info->spec == SR_INTERNAL ? "internal state"
3159 : s->info->spec == SR_SPECSTATE ? "spec state"
3160 : s->info->spec == SR_SYSTEM ? "file system state"
3163 return cstring_makeLiteral ("result");
3167 return cstring_makeLiteral ("?");
3169 /* llcontbug (message ("sRef_unparseNoArgs: bad case: %q", sRef_unparseDebug (s))); */
3170 return (sRef_unparseDebug (s));
3175 /*@dependent@*/ sRef sRef_makeUnconstrained (cstring fname)
3177 sRef s = sRef_new ();
3179 s->kind = SK_UNCONSTRAINED;
3180 s->info = (sinfo) dmalloc (sizeof (*s->info));
3181 s->info->fname = cstring_copy (fname); /* evans 2002-07-12: this was exposed, causing memory errors */
3186 cstring sRef_unconstrainedName (sRef s)
3188 llassert (sRef_isUnconstrained (s));
3190 return s->info->fname;
3193 bool sRef_isUnconstrained (sRef s)
3195 return (sRef_isReasonable(s) && s->kind == SK_UNCONSTRAINED);
3198 static /*@dependent@*/ /*@notnull@*/ sRef
3199 sRef_makeCvarAux (int level, usymId index, ctype ct, /*@only@*/ stateInfo stinfo)
3201 sRef s = sRef_newRef ();
3204 s->info = (sinfo) dmalloc (sizeof (*s->info));
3206 s->info->cvar = (cref) dmalloc (sizeof (*s->info->cvar));
3207 s->info->cvar->lexlevel = level;
3208 s->info->cvar->index = index;
3210 /* for now, all globals are defined; all locals, aren't */
3212 if (level <= fileScope)
3214 s->defstate = SS_UNKNOWN;
3218 ctype rct = ctype_realType (ct);
3220 if (level != paramsScope
3221 && (ctype_isStructorUnion (rct) || ctype_isRealArray (rct)))
3223 s->defstate = SS_ALLOCATED;
3224 s->oaliaskind = s->aliaskind = AK_STACK;
3228 s->defstate = SS_UNDEFINED;
3229 s->oaliaskind = s->aliaskind = AK_LOCAL;
3235 llassert (level >= globScope);
3236 llassert (usymId_isValid (index));
3238 DPRINTF (("Made cvar: [%p] %s", s, sRef_unparseDebug (s)));
3239 llassert (valueTable_isUndefined (s->state));
3240 s->state = context_createValueTable (s, stinfo);
3244 /*@dependent@*/ sRef sRef_makeCvar (int level, usymId index, ctype ct, /*@only@*/ stateInfo stinfo)
3246 return (sRef_makeCvarAux (level, index, ct, stinfo));
3249 int sRef_lexLevel (sRef s)
3251 if (sRef_isReasonable (s))
3255 conj = sRef_fixConj (s);
3256 s = sRef_getRootBase (conj);
3258 if (sRef_isReasonable (s) && s->kind == SK_CVAR)
3260 return (s->info->cvar->lexlevel);
3268 sRef_makeGlobal (usymId l, ctype ct, /*@only@*/ stateInfo stinfo)
3270 return (sRef_makeCvar (globScope, l, ct, stinfo));
3274 sRef_setParamNo (sRef s, int l)
3276 llassert (sRef_isReasonable (s) && s->kind == SK_PARAM);
3277 s->info->paramno = l;
3281 /*@dependent@*/ sRef
3282 sRef_makeParam (int l, ctype ct, stateInfo stinfo)
3284 sRef s = sRef_new ();
3289 s->info = (sinfo) dmalloc (sizeof (*s->info));
3290 s->info->paramno = l;
3292 s->defstate = SS_UNKNOWN;
3293 /* (probably defined, unless its an out parameter) */
3295 llassert (valueTable_isUndefined (s->state));
3296 s->state = context_createValueTable (s, stinfo);
3301 sRef_isIndexKnown (sRef arr)
3305 llassert (sRef_isReasonable (arr));
3306 arr = sRef_fixConj (arr);
3308 llassert (arr->kind == SK_ARRAYFETCH);
3309 res = arr->info->arrayfetch->indknown;
3314 sRef_getIndex (sRef arr)
3318 llassert (sRef_isReasonable (arr));
3319 arr = sRef_fixConj (arr);
3321 llassert (arr->kind == SK_ARRAYFETCH);
3323 if (!arr->info->arrayfetch->indknown)
3325 llcontbug (message ("sRef_getIndex: unknown: %q", sRef_unparse (arr)));
3330 result = arr->info->arrayfetch->ind;
3336 static bool sRef_isZerothArrayFetch (/*@notnull@*/ sRef s)
3338 return (s->kind == SK_ARRAYFETCH
3339 && s->info->arrayfetch->indknown
3340 && (s->info->arrayfetch->ind == 0));
3343 /*@exposed@*/ sRef sRef_makeAddress (/*@exposed@*/ sRef t)
3346 if (sRef_isInvalid (t)) return sRef_undefined;
3348 if (sRef_isPointer (t))
3350 return (t->info->ref);
3352 else if (sRef_isZerothArrayFetch (t))
3354 return (t->info->arrayfetch->arr);
3358 sRef s = sRef_newRef ();
3361 s->type = ctype_makePointer (t->type);
3362 s->info = (sinfo) dmalloc (sizeof (*s->info));
3363 s->info->ref = t; /* sRef_copy (t); */ /*@i32@*/
3365 if (t->defstate == SS_UNDEFINED)
3366 /* no! it is allocated even still: && !ctype_isPointer (t->type)) */
3368 s->defstate = SS_ALLOCATED;
3372 s->defstate = t->defstate;
3375 if (t->aliaskind == AK_LOCAL)
3377 if (sRef_isLocalVar (t))
3379 s->aliaskind = AK_STACK;
3383 llassert (valueTable_isUndefined (s->state));
3384 s->state = context_createValueTable (s, stateInfo_makeLoc (g_currentloc));
3389 cstring sRef_getField (sRef s)
3393 llassert (sRef_isReasonable (s));
3394 s = sRef_fixConj (s);
3396 llassertprint (sRef_isReasonable (s) && (s->kind == SK_FIELD),
3397 ("s = %s", sRef_unparseDebug (s)));
3399 res = s->info->field->field;
3403 sRef sRef_getBase (sRef s)
3407 if (sRef_isInvalid (s)) return (sRef_undefined);
3409 s = sRef_fixConj (s);
3420 res = s->info->field->rec;
3424 res = s->info->arrayfetch->arr;
3428 res = sRef_undefined; /* shouldn't need it */
3435 ** same as getBase, except returns invalid
3436 ** (and doesn't use adr's)
3440 sRef_getBaseSafe (sRef s)
3444 if (sRef_isInvalid (s)) { return sRef_undefined; }
3446 s = sRef_fixConj (s);
3454 res = s->info->field->rec; break;
3456 res = s->info->arrayfetch->arr;
3459 res = sRef_undefined; break;
3465 /*@constant int MAXBASEDEPTH;@*/
3466 # define MAXBASEDEPTH 25
3468 static /*@exposed@*/ sRef
3469 sRef_getRootBaseAux (sRef s, int depth)
3471 if (sRef_isInvalid (s)) return sRef_undefined;
3473 if (depth > MAXBASEDEPTH)
3476 ("Warning: reference base limit exceeded for %q. "
3477 "This either means there is a variable with at least "
3478 "%d indirections from this reference, or "
3479 "there is a bug in Splint.",
3484 return sRef_undefined;
3491 return (sRef_getRootBaseAux (s->info->ref, depth + 1));
3493 return (sRef_getRootBaseAux (s->info->field->rec, depth + 1));
3495 return (sRef_getRootBaseAux (s->info->arrayfetch->arr, depth + 1));
3497 return (sRef_getRootBaseAux (sRef_fixConj (s), depth + 1));
3503 sRef sRef_getRootBase (sRef s)
3505 return (sRef_getRootBaseAux (s, 0));
3508 static bool sRef_isDeep (sRef s)
3510 if (sRef_isInvalid (s)) return FALSE;
3520 return (sRef_isDeep (sRef_fixConj (s)));
3526 static int sRef_depth (sRef s)
3528 if (sRef_isInvalid (s)) return 0;
3536 return 1 + sRef_depth (s->info->ref);
3538 return 1 + sRef_depth (s->info->field->rec);
3540 return 1 + sRef_depth (s->info->arrayfetch->arr);
3542 return (sRef_depth (sRef_fixConj (s)));
3549 sRef_makeObject (ctype o)
3551 sRef s = sRef_newRef (); /*@i423 same line is bad...@*/
3553 s->kind = SK_OBJECT;
3554 s->info = (sinfo) dmalloc (sizeof (*s->info));
3555 s->info->object = o;
3556 llassert (valueTable_isUndefined (s->state));
3557 s->state = context_createValueTable (s, stateInfo_makeLoc (g_currentloc));
3562 ** This is used to represent storage referenced by a parameter.
3565 sRef sRef_makeExternal (sRef t)
3567 sRef s = sRef_newRef ();
3569 llassert (sRef_isReasonable (t));
3571 s->kind = SK_EXTERNAL;
3572 s->info = (sinfo) dmalloc (sizeof (*s->info));
3574 s->info->ref = t; /* sRef_copy (t); */ /*@i32 was exposed@*/
3575 llassert (valueTable_isUndefined (s->state));
3576 s->state = context_createValueTable (s, stateInfo_makeLoc (g_currentloc));
3580 /*@dependent@*/ sRef sRef_makeDerived (/*@exposed@*/ sRef t)
3582 if (sRef_isReasonable (t))
3584 sRef s = sRef_newRef ();
3586 s->kind = SK_DERIVED;
3587 s->info = (sinfo) dmalloc (sizeof (*s->info));
3588 s->info->ref = t; /* sRef_copy (t); */ /*@i32@*/
3591 llassert (valueTable_isUndefined (s->state));
3592 s->state = context_createValueTable (s, stateInfo_makeLoc (g_currentloc));
3597 return sRef_undefined;
3602 ** definitely NOT symmetric:
3604 ** res fills in unknown state information from other
3608 sRef_mergeStateQuiet (sRef res, sRef other)
3610 llassert (sRef_isReasonable (res));
3611 llassert (sRef_isReasonable (other));
3613 res->modified = res->modified || other->modified;
3614 res->safe = res->safe && other->safe;
3616 if (res->defstate == SS_UNKNOWN)
3618 res->defstate = other->defstate;
3619 res->definfo = stateInfo_update (res->definfo, other->definfo);
3622 if (res->aliaskind == AK_UNKNOWN ||
3623 (res->aliaskind == AK_LOCAL && alkind_isKnown (other->aliaskind)))
3625 res->aliaskind = other->aliaskind;
3626 res->oaliaskind = other->oaliaskind;
3627 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
3630 if (res->expkind == XO_UNKNOWN)
3632 res->expkind = other->expkind;
3633 res->oexpkind = other->oexpkind;
3634 res->expinfo = stateInfo_update (res->expinfo, other->expinfo);
3637 /* out takes precedence over implicitly defined */
3638 if (res->defstate == SS_DEFINED && other->defstate != SS_UNKNOWN)
3640 res->defstate = other->defstate;
3641 res->definfo = stateInfo_update (res->definfo, other->definfo);
3644 if (sRef_getNullState (other) == NS_ERROR || sRef_getNullState (res) == NS_ERROR)
3646 sRef_setNullState (res, NS_ERROR, fileloc_undefined);
3650 if (sRef_getNullState (other) != NS_UNKNOWN
3651 && (sRef_getNullState (res) == NS_UNKNOWN || sRef_getNullState (res) == NS_NOTNULL
3652 || sRef_getNullState (res) == NS_MNOTNULL))
3654 sRef_updateNullState (res, other);
3660 ** definitely NOT symmetric:
3662 ** res fills in known state information from other
3666 sRef_mergeStateQuietReverse (/*@dependent@*/ sRef res, /*@dependent@*/ sRef other)
3668 bool changed = FALSE;
3670 llassert (sRef_isReasonable (res));
3671 llassert (sRef_isReasonable (other));
3672 sRef_checkMutable (res);
3674 if (res->kind != other->kind)
3680 res->kind = other->kind;
3681 res->type = other->type;
3682 res->info = sinfo_fullCopy (other);
3686 if (!ctype_equal (res->type, other->type))
3689 res->type = other->type;
3692 sinfo_update (res, other);
3695 res->modified = res->modified || other->modified;
3696 res->safe = res->safe && other->safe;
3698 if (res->aliaskind != other->aliaskind
3699 && (res->aliaskind == AK_UNKNOWN
3700 || ((res->aliaskind == AK_LOCAL
3701 || (res->aliaskind == AK_REFCOUNTED
3702 && other->aliaskind != AK_LOCAL))
3703 && other->aliaskind != AK_UNKNOWN)))
3706 res->aliaskind = other->aliaskind;
3707 res->oaliaskind = other->oaliaskind;
3708 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
3711 if (other->expkind != XO_UNKNOWN && other->expkind != res->expkind)
3714 res->expkind = other->expkind;
3715 res->expinfo = stateInfo_update (res->expinfo, other->expinfo);
3718 if (other->oexpkind != XO_UNKNOWN)
3720 res->oexpkind = other->oexpkind;
3723 /* out takes precedence over implicitly defined */
3725 if (res->defstate != other->defstate)
3727 if (other->defstate != SS_UNKNOWN)
3729 res->defstate = other->defstate;
3733 if (sRef_getNullState (other) == NS_ERROR || sRef_getNullState (res) == NS_ERROR)
3735 if (sRef_getNullState (res) != NS_ERROR)
3737 sRef_setNullStateN (res, NS_ERROR);
3743 if (sRef_getNullState (other) != NS_UNKNOWN && sRef_getNullState (other) != sRef_getNullState (res))
3746 sRef_updateNullState (res, other);
3752 sRef_clearDerived (res);
3757 sRef_mergeState (sRef res, sRef other, clause cl, fileloc loc)
3759 if (sRef_isReasonable (res) && sRef_isReasonable (other))
3761 sRef_mergeStateAux (res, other, cl, FALSE, loc, TRUE);
3765 if (sRef_isInvalid (res))
3767 llbug (message ("sRef_mergeState: invalid res sRef: %q",
3768 sRef_unparseDebug (other)));
3772 llbug (message ("sRef_mergeState: invalid other sRef: %q",
3773 sRef_unparseDebug (res)));
3779 sRef_mergeOptState (sRef res, sRef other, clause cl, fileloc loc)
3781 if (sRef_isReasonable (res) && sRef_isReasonable (other))
3783 sRef_mergeStateAux (res, other, cl, TRUE, loc, TRUE);
3787 if (sRef_isInvalid (res))
3789 llbug (message ("sRef_mergeOptState: invalid res sRef: %q",
3790 sRef_unparseDebug (other)));
3794 llbug (message ("sRef_mergeOptState: invalid other sRef: %q",
3795 sRef_unparseDebug (res)));
3801 sRef_mergeStateAux (/*@notnull@*/ sRef res, /*@notnull@*/ sRef other,
3802 clause cl, bool opt, fileloc loc,
3806 llassertfatal (sRef_isReasonable (res));
3807 llassertfatal (sRef_isReasonable (other));
3809 DPRINTF (("Merge aux: %s / %s",
3810 sRef_unparseFull (res),
3811 sRef_unparseFull (other)));
3813 sRef_checkMutable (res);
3814 sRef_checkMutable (other);
3816 res->modified = res->modified || other->modified;
3818 if (res->kind == other->kind
3819 || (other->kind == SK_UNKNOWN || res->kind == SK_UNKNOWN))
3821 sstate odef = other->defstate;
3822 sstate rdef = res->defstate;
3823 nstate onull = sRef_getNullState (other);
3826 ** yucky stuff to handle
3831 if (other->defstate == SS_DEAD
3832 && ((sRef_isOnly (res) && sRef_definitelyNull (res))
3833 || (res->defstate == SS_UNDEFINED
3834 || res->defstate == SS_UNUSEABLE)))
3836 if (res->defstate == SS_UNDEFINED
3837 || res->defstate == SS_UNUSEABLE)
3839 res->defstate = SS_UNUSEABLE;
3843 res->defstate = SS_DEAD;
3846 res->definfo = stateInfo_update (res->definfo, other->definfo);
3847 sRef_clearDerived (other);
3848 sRef_clearDerived (res);
3850 else if (res->defstate == SS_DEAD
3851 && ((sRef_isOnly (other) && sRef_definitelyNull (other))
3852 || (other->defstate == SS_UNDEFINED
3853 || other->defstate == SS_UNUSEABLE)))
3855 if (other->defstate == SS_UNDEFINED
3856 || other->defstate == SS_UNUSEABLE)
3858 res->defstate = SS_UNUSEABLE;
3862 res->defstate = SS_DEAD;
3865 sRef_clearDerived (other);
3866 sRef_clearDerived (res);
3868 else if (res->defstate == SS_DEFINED
3869 && (other->defstate == SS_ALLOCATED
3870 && sRef_definitelyNull (other)))
3872 other->defstate = SS_DEFINED; /* definitely null! */
3874 else if (other->defstate == SS_DEFINED
3875 && (res->defstate == SS_ALLOCATED && sRef_definitelyNull (res)))
3877 res->defstate = SS_DEFINED;
3878 res->definfo = stateInfo_update (res->definfo, other->definfo);
3885 if (res->defstate == SS_DEAD && other->defstate == SS_DEAD)
3887 sRef_clearDerived (other);
3888 sRef_clearDerived (res);
3892 ** only & dead isn't really an only!
3895 if (alkind_isOnly (other->aliaskind) && other->defstate == SS_DEAD)
3897 other->aliaskind = AK_UNKNOWN;
3900 if (alkind_isOnly (res->aliaskind) && res->defstate == SS_DEAD)
3902 res->aliaskind = AK_UNKNOWN;
3906 ** Dead and dependent -> dead
3909 if (alkind_isDependent (other->aliaskind) && res->defstate == SS_DEAD)
3911 other->aliaskind = AK_UNKNOWN;
3912 other->defstate = SS_DEAD;
3913 sRef_clearDerived (res);
3914 sRef_clearDerived (other);
3917 if (alkind_isDependent (res->aliaskind) && other->defstate == SS_DEAD)
3919 res->aliaskind = AK_UNKNOWN;
3920 res->defstate = SS_DEAD;
3921 sRef_clearDerived (res);
3922 sRef_clearDerived (other);
3926 ** must do alias combine first, since it depends on
3927 ** original values of state and null.
3930 sRef_combineAliasKinds (res, other, cl, loc);
3931 sRef_combineDefState (res, other);
3932 sRef_combineNullState (res, other);
3934 if (rdef == SS_ALLOCATED || rdef == SS_SPECIAL)
3936 if (odef == SS_DEFINED)
3938 if (onull == NS_DEFNULL || onull == NS_CONSTNULL)
3940 res->deriv = sRefSet_copyInto (res->deriv, other->deriv);
3941 DPRINTF (("Copy derivs: %s", sRef_unparseFull (res)));
3944 else if (odef == SS_ALLOCATED || odef == SS_SPECIAL)
3949 if (ctype_isUnion (ctype_realType (sRef_getType (res))))
3951 res->deriv = sRef_mergeUnionDerivs (res->deriv,
3954 DPRINTF (("Copy derivs: %s", sRef_unparseFull (res)));
3958 res->deriv = sRef_mergeDerivs (res->deriv, other->deriv,
3960 DPRINTF (("Copy derivs: %s", sRef_unparseFull (res)));
3968 res->deriv = sRef_mergeDerivs (res->deriv, other->deriv,
3970 DPRINTF (("Copy derivs: %s", sRef_unparseFull (res)));
3980 if (rdef == SS_PDEFINED
3981 || (rdef == SS_DEFINED && odef == SS_PDEFINED))
3985 res->deriv = sRef_mergePdefinedDerivs (res->deriv, other->deriv,
3987 DPRINTF (("Copy derivs: %s", sRef_unparseFull (res)));
3992 if ((rdef == SS_DEFINED || rdef == SS_UNKNOWN)
3993 && res->defstate == SS_ALLOCATED)
3995 res->deriv = sRefSet_copyInto (res->deriv, other->deriv);
4001 res->deriv = sRef_mergeDerivs (res->deriv, other->deriv,
4003 DPRINTF (("Copy derivs: %s", sRef_unparseFull (res)));
4010 sRef_combineExKinds (res, other);
4014 if (res->kind == SK_ARRAYFETCH && other->kind == SK_PTR)
4016 sRef nother = sRef_buildArrayFetchKnown (sRef_getBase (other), 0);
4018 sRef_copyState (nother, other);
4019 sRef_mergeStateAux (res, nother, cl, opt, loc, doDerivs);
4021 else if (res->kind == SK_PTR && other->kind == SK_ARRAYFETCH)
4023 sRef nother = sRef_buildPointer (sRef_getBase (other));
4025 if (sRef_isReasonable (nother))
4027 sRef_copyState (nother, other);
4028 sRef_mergeStateAux (res, nother, cl, opt, loc, doDerivs);
4033 llcontbug (message ("merge conj: %q / %q", sRef_unparseFull (res),
4034 sRef_unparseFull (other)));
4040 ** Merge value table states
4047 ** This doesn't do anything. And its broken too...
4050 valueTable_elements (res->state, key, sv)
4052 stateValue os = valueTable_lookup (other->state, key);
4053 /*@unused@*/ int val;
4054 /*@unused@*/ char *msg;
4056 llassert (stateValue_isDefined (os));
4058 DPRINTF (("Merge state: %s / %s",
4059 cstring_toCharsSafe (stateValue_unparse (sv)),
4060 cstring_toCharsSafe (stateValue_unparse (os))));
4062 val = valueMatix_lookup (key,
4063 stateValue_getValue (os),
4064 stateValue_getValue (sv),
4066 DPRINTF (("Val: %d / %s", val, msg));
4068 } end_valueTable_elements ;
4071 DPRINTF (("Merge aux: %s / %s",
4072 sRef_unparseFull (res),
4073 sRef_unparseFull (other)));
4077 sRef_mergeUnionDerivs (/*@only@*/ sRefSet res,
4078 /*@exposed@*/ sRefSet other, bool opt,
4079 clause cl, fileloc loc)
4081 if (sRefSet_isEmpty (res))
4083 return sRefSet_copyInto (res, other);
4087 sRefSet_allElements (other, el)
4089 if (sRef_isReasonable (el))
4091 sRef e2 = sRefSet_lookupMember (other, el);
4093 if (sRef_isReasonable (e2))
4095 sRef_mergeStateAux (el, e2, cl, opt, loc, FALSE);
4099 res = sRefSet_insert (res, el);
4102 } end_sRefSet_allElements ;
4108 static /*@only@*/ sRefSet
4109 sRef_mergeDerivs (/*@only@*/ sRefSet res, sRefSet other,
4110 bool opt, clause cl, fileloc loc)
4112 sRefSet ret = sRefSet_new ();
4114 sRefSet_allElements (res, el)
4116 if (sRef_isReasonable (el))
4118 sRef e2 = sRefSet_lookupMember (other, el);
4120 if (sRef_isReasonable (e2))
4122 if (el->defstate == SS_ALLOCATED &&
4123 e2->defstate == SS_PDEFINED)
4125 e2->defstate = SS_ALLOCATED;
4127 else if (e2->defstate == SS_ALLOCATED &&
4128 el->defstate == SS_PDEFINED)
4130 el->defstate = SS_ALLOCATED;
4131 sRef_clearDerived (el);
4133 else if ((el->defstate == SS_DEAD || sRef_isKept (el)) &&
4134 (e2->defstate == SS_DEFINED && !sRef_isKept (e2)))
4137 if (checkDeadState (el, TRUE, loc))
4139 if (sRef_isThroughArrayFetch (el))
4141 sRef_maybeKill (el, loc);
4142 sRef_maybeKill (e2, loc);
4146 else if ((e2->defstate == SS_DEAD || sRef_isKept (e2)) &&
4147 (el->defstate == SS_DEFINED && !sRef_isKept (el)))
4150 if (checkDeadState (e2, FALSE, loc))
4152 if (sRef_isThroughArrayFetch (el))
4154 sRef_maybeKill (el, loc);
4155 sRef_maybeKill (e2, loc);
4159 else if (el->defstate == SS_DEFINED &&
4160 e2->defstate == SS_PDEFINED)
4162 DPRINTF (("set pdefined: %s", sRef_unparseFull (el)));
4163 el->defstate = SS_PDEFINED;
4165 else if (e2->defstate == SS_DEFINED &&
4166 el->defstate == SS_PDEFINED)
4168 DPRINTF (("set pdefined: %s", sRef_unparseFull (e2)));
4169 e2->defstate = SS_PDEFINED;
4176 if (ctype_isUnion (ctype_realType (sRef_getType (el))))
4178 el->deriv = sRef_mergeUnionDerivs (el->deriv, e2->deriv,
4183 el->deriv = sRef_mergeDerivs (el->deriv, e2->deriv, opt, cl, loc);
4186 if (sRef_equivalent (el, e2))
4188 ret = sRefSet_insert (ret, el);
4192 sRef sr = sRef_leastCommon (el, e2);
4194 if (sRef_isReasonable (sr))
4196 ret = sRefSet_insert (ret, sr);
4204 (void) sRefSet_delete (other, e2);
4206 else /* not defined */
4208 (void) checkDeadState (el, TRUE, loc);
4211 } end_sRefSet_allElements;
4213 sRefSet_allElements (other, el)
4215 if (sRef_isReasonable (el))
4217 (void) checkDeadState (el, FALSE, loc);
4219 } end_sRefSet_allElements;
4226 ** Returns TRUE is there is an error.
4229 static bool checkDeadState (/*@notnull@*/ sRef el, bool tbranch, fileloc loc)
4232 ** usymtab_isGuarded --- the utab should still be in the
4233 ** state of the alternate branch.
4235 ** tbranch TRUE means el is released in the last branch, e.g.
4236 ** if (x != NULL) { ; } else { sfree (x); }
4237 ** so, if x is null in the other branch no error is reported.
4239 ** tbranch FALSE means this is the other branch:
4240 ** if (x != NULL) { sfree (x); } else { ; }
4241 ** so, if x is null in this branch there is no error.
4245 if ((sRef_isDead (el) || sRef_isKept (el))
4246 && !sRef_isDeepUnionField (el) && !sRef_isThroughArrayFetch (el))
4251 if (usymtab_isDefinitelyNullDeep (el))
4258 if (usymtab_isAltDefinitelyNullDeep (el))
4266 message ("Storage %q is %q in one path, but live in another.",
4268 cstring_makeLiteral (sRef_isKept (el)
4269 ? "kept" : "released")),
4272 if (sRef_isKept (el))
4274 sRef_showAliasInfo (el);
4278 sRef_showStateInfo (el);
4281 /* prevent further errors */
4282 el->defstate = SS_UNKNOWN;
4283 sRef_setAliasKind (el, AK_ERROR, fileloc_undefined);
4293 checkDerivDeadState (/*@notnull@*/ sRef el, bool tbranch, fileloc loc)
4296 if (checkDeadState (el, tbranch, loc))
4298 sRefSet_allElements (el->deriv, t)
4300 if (sRef_isReasonable (t))
4302 checkDerivDeadState (t, tbranch, loc);
4304 } end_sRefSet_allElements;
4309 sRef_mergePdefinedDerivs (sRefSet res, sRefSet other, bool opt,
4310 clause cl, fileloc loc)
4312 sRefSet ret = sRefSet_new ();
4314 sRefSet_allElements (res, el)
4316 if (sRef_isReasonable (el))
4318 sRef e2 = sRefSet_lookupMember (other, el);
4320 if (sRef_isReasonable (e2))
4322 if (sRef_isAllocated (el) && !sRef_isAllocated (e2))
4326 else if (sRef_isAllocated (e2) && !sRef_isAllocated (el))
4328 el->deriv = sRefSet_copyInto (el->deriv, e2->deriv);
4332 el->deriv = sRef_mergePdefinedDerivs (el->deriv, e2->deriv,
4336 sRef_mergeStateAux (el, e2, cl, opt, loc, FALSE);
4338 ret = sRefSet_insert (ret, el);
4339 (void) sRefSet_delete (other, e2);
4345 checkDerivDeadState (el, (cl == FALSECLAUSE), loc);
4348 ret = sRefSet_insert (ret, el);
4351 } end_sRefSet_allElements;
4353 sRefSet_allElements (other, el)
4355 if (sRef_isReasonable (el))
4357 if (!sRefSet_member (ret, el))
4359 /* was cl == FALSECLAUSE */
4360 checkDerivDeadState (el, FALSE, loc);
4361 ret = sRefSet_insert (ret, el);
4366 ** it's okay --- member is a different equality test
4370 } end_sRefSet_allElements;
4376 sRef sRef_makeConj (/*@exposed@*/ /*@returned@*/ sRef a, /*@exposed@*/ sRef b)
4378 llassert (sRef_isReasonable (a));
4379 llassert (sRef_isReasonable (b));
4381 if (!sRef_equivalent (a, b))
4383 sRef s = sRef_newRef ();
4386 s->info = (sinfo) dmalloc (sizeof (*s->info));
4387 s->info->conj = (cjinfo) dmalloc (sizeof (*s->info->conj));
4388 s->info->conj->a = a; /* sRef_copy (a) */ /*@i32*/ ;
4389 s->info->conj->b = b; /* sRef_copy (b);*/ /*@i32@*/ ;
4391 if (ctype_equal (a->type, b->type)) s->type = a->type;
4392 else s->type = ctype_makeConj (a->type, b->type);
4394 if (a->defstate == b->defstate)
4396 s->defstate = a->defstate;
4400 s->defstate = SS_UNKNOWN;
4403 sRef_setNullStateN (s, NS_UNKNOWN);
4405 s->safe = a->safe && b->safe;
4406 s->aliaskind = alkind_resolve (a->aliaskind, b->aliaskind);
4408 llassert (valueTable_isUndefined (s->state));
4409 s->state = context_createValueTable (s, stateInfo_makeLoc (g_currentloc));
4414 /*@-exposetrans@*/ return a; /*@=exposetrans@*/
4418 /*@dependent@*/ sRef
4421 sRef s = sRef_new ();
4423 s->kind = SK_UNKNOWN;
4427 static /*@owned@*/ /*@notnull@*/ sRef
4428 sRef_makeSpecial (speckind sk) /*@*/
4430 sRef s = sRef_new ();
4432 s->kind = SK_SPECIAL;
4433 s->info = (sinfo) dmalloc (sizeof (*s->info));
4435 /*@-dependenttrans@*/
4437 /*@=dependenttrans@*/
4440 static /*@owned@*/ sRef srnothing = sRef_undefined;
4441 static /*@owned@*/ sRef srinternal = sRef_undefined;
4442 static /*@owned@*/ sRef srsystem = sRef_undefined;
4443 static /*@owned@*/ sRef srspec = sRef_undefined;
4445 /*@dependent@*/ sRef
4446 sRef_makeNothing (void)
4448 if (sRef_isInvalid (srnothing))
4450 srnothing = sRef_makeSpecial (SR_NOTHING);
4457 sRef_makeInternalState (void)
4459 if (sRef_isInvalid (srinternal))
4461 srinternal = sRef_makeSpecial (SR_INTERNAL);
4468 sRef_makeSpecState (void)
4470 if (sRef_isInvalid (srspec))
4472 srspec = sRef_makeSpecial (SR_SPECSTATE);
4479 sRef_makeSystemState (void)
4481 if (sRef_isInvalid (srsystem))
4483 srsystem = sRef_makeSpecial (SR_SYSTEM);
4490 sRef_makeGlobalMarker (void)
4492 sRef s = sRef_makeSpecial (SR_GLOBALMARKER);
4493 llassert (valueTable_isUndefined (s->state));
4494 s->state = context_createGlobalMarkerValueTable (stateInfo_undefined);
4499 sRef_makeResult (ctype c)
4501 sRef s = sRef_newRef ();
4503 s->kind = SK_RESULT;
4505 s->defstate = SS_UNKNOWN;
4506 s->aliaskind = AK_UNKNOWN;
4507 sRef_setNullStateN (s, NS_UNKNOWN);
4508 llassert (valueTable_isUndefined (s->state));
4509 s->state = context_createValueTable (s, stateInfo_makeLoc (g_currentloc));
4511 DPRINTF (("Result: [%p] %s", s, sRef_unparseFull (s)));
4517 sRef_isNothing (sRef s)
4519 return (sRef_isKindSpecial (s) && s->info->spec == SR_NOTHING);
4523 sRef_isInternalState (sRef s)
4525 return (sRef_isKindSpecial (s) && s->info->spec == SR_INTERNAL);
4529 sRef_isSpecInternalState (sRef s)
4531 return (sRef_isKindSpecial (s)
4532 && (s->info->spec == SR_INTERNAL || s->info->spec == SR_SPECSTATE));
4536 sRef_isSpecState (sRef s)
4538 return (sRef_isKindSpecial (s) && s->info->spec == SR_SPECSTATE);
4542 sRef_isResult (sRef s)
4544 return (sRef_isReasonable (s) && s->kind == SK_RESULT);
4548 sRef_isSystemState (sRef s)
4550 return (sRef_isKindSpecial (s) && s->info->spec == SR_SYSTEM);
4554 sRef_isGlobalMarker (sRef s)
4556 return (sRef_isKindSpecial (s) && s->info->spec == SR_GLOBALMARKER);
4560 sRef_getScopeIndex (sRef s)
4562 llassert (sRef_isReasonable (s));
4563 llassert (sRef_isCvar (s));
4565 return (s->info->cvar->index);
4569 sRef_makeSafe (sRef s)
4571 if (sRef_isReasonable (s))
4578 sRef_makeUnsafe (sRef s)
4580 if (sRef_isReasonable (s))
4587 ** memory state operations
4590 /*@only@*/ cstring sRef_unparseFull (sRef s)
4592 if (sRef_isInvalid (s)) return (cstring_undefined);
4594 return (message ("[%p] %q - %q [%s] { %q } < %q >",
4596 sRef_unparseDebug (s),
4597 sRef_unparseState (s),
4598 exkind_unparse (s->oexpkind),
4599 sRefSet_unparseDebug (s->deriv),
4600 valueTable_unparse (s->state)));
4603 /*@unused@*/ cstring sRef_unparseDeep (sRef s)
4605 cstring st = cstring_undefined;
4607 st = message ("%q:", sRef_unparseFull (s));
4609 if (sRef_isReasonable (s))
4611 sRefSet_allElements (s->deriv, el)
4613 st = message("%q\n%q", st, sRef_unparseDeep (el));
4614 } end_sRefSet_allElements ;
4620 /*@only@*/ cstring sRef_unparseState (sRef s)
4622 if (sRef_isConj (s))
4624 return (message ("%q | %q",
4625 sRef_unparseState (s->info->conj->a),
4626 sRef_unparseState (s->info->conj->b)));
4629 if (sRef_isInvalid (s))
4631 return (cstring_makeLiteral ("<invalid>"));
4634 return (message ("%s.%s.%s.%s",
4635 alkind_unparse (s->aliaskind),
4636 nstate_unparse (sRef_getNullState (s)),
4637 exkind_unparse (s->expkind),
4638 sstate_unparse (s->defstate)));
4641 bool sRef_isNotUndefined (sRef s)
4643 return (sRef_isInvalid (s)
4644 || (s->defstate != SS_UNDEFINED
4645 && s->defstate != SS_UNUSEABLE
4646 && s->defstate != SS_DEAD));
4649 ynm sRef_isWriteable (sRef s)
4651 if (sRef_isInvalid (s)) return MAYBE;
4653 if (sRef_isConj (s) && s->defstate == SS_UNKNOWN)
4655 if (ynm_toBoolStrict (sRef_isWriteable (sRef_getConjA (s))))
4657 if (ynm_toBoolStrict (sRef_isWriteable (sRef_getConjB (s))))
4665 if (ynm_toBoolStrict (sRef_isWriteable (sRef_getConjB (s))))
4673 return (ynm_fromBool (s->defstate != SS_UNUSEABLE));
4676 bool sRef_hasNoStorage (sRef s)
4678 return (!sRef_isAllocatedStorage (s) || sRef_isDefinitelyNull (s));
4681 bool sRef_isStrictReadable (sRef s)
4683 return (ynm_toBoolStrict (sRef_isValidLvalue (s)));
4687 ** Is this what is does?
4688 ** Returns YES if s can be used as an rvalue,
4689 ** MAYBE if its not clear
4690 ** NO if s cannot be safely used as an rvalue.
4693 ynm sRef_isValidLvalue (sRef s)
4697 if (sRef_isInvalid (s)) return YES;
4701 if (sRef_isConj (s) && s->defstate == SS_UNKNOWN)
4703 if (ynm_toBoolStrict (sRef_isValidLvalue (sRef_getConjA (s))))
4705 if (ynm_toBoolStrict (sRef_isValidLvalue (sRef_getConjB (s))))
4713 if (ynm_toBoolStrict (sRef_isValidLvalue (sRef_getConjB (s))))
4720 else if (ss == SS_HOFFA)
4722 if (context_getFlag (FLG_STRICTUSERELEASED))
4733 return (ynm_fromBool (ss == SS_DEFINED
4736 || ss == SS_PDEFINED
4739 || ss == SS_ALLOCATED
4740 || ss == SS_KILLED /* evans 2001-05-26: added this for killed globals */
4741 || ss == SS_UNKNOWN));
4745 static /*@exposed@*/ sRef whatUndefined (/*@exposed@*/ sRef fref, int depth)
4750 if (depth > MAXDEPTH)
4753 ("Warning: check definition limit exceeded, checking %q. "
4754 "This either means there is a variable with at least "
4755 "%d indirections apparent in the program text, or "
4756 "there is a bug in Splint.",
4757 sRef_unparse (fref),
4761 return sRef_undefined;
4764 if (!sRef_isKnown (fref) || sRef_isAnyDefined (fref))
4766 return sRef_undefined;
4769 if (sRef_isUnuseable (fref) || sRef_isStateUndefined (fref))
4774 ct = ctype_realType (sRef_getType (fref));
4776 if (ctype_isUnknown (ct))
4778 return sRef_undefined;
4780 else if (ctype_isPointer (ct) || ctype_isArray (ct))
4782 if (sRef_isStateUnknown (fref))
4784 return sRef_undefined;
4788 sRef fptr = sRef_constructDeref (fref);
4790 return (whatUndefined (fptr, depth + 1));
4793 else if (ctype_isStruct (ct))
4795 bool hasOneDefined = FALSE;
4797 if (sRef_isStateUnknown (fref))
4802 if (sRef_isPdefined (fref) || sRef_isAnyDefined (fref))
4804 sRefSet_realElements (sRef_derivedFields (fref), sr)
4806 hasOneDefined = TRUE;
4808 if (sRef_isField (sr))
4810 cstring fieldname = sRef_getField (sr);
4811 sRef fldref = sRef_makeField (fref, fieldname);
4812 bool shouldCheck = !sRef_isRecursiveField (fldref);
4816 sRef wdef = whatUndefined (fldref, depth + 1);
4818 if (sRef_isReasonable (wdef))
4824 } end_sRefSet_realElements;
4826 else if (sRef_isAllocated (fref))
4829 ** for structures, each field must be completely defined
4832 uentryList fields = ctype_getFields (ct);
4834 uentryList_elements (fields, ue)
4836 cstring name = uentry_getRealName (ue);
4837 sRef ffield = sRef_makeField (fref, name);
4838 bool shouldCheck = !sRef_isRecursiveField (ffield);
4840 if (sRef_isRelDef (uentry_getSref (ue)))
4848 sRef wdef = whatUndefined (ffield, depth + 1);
4850 if (sRef_isInvalid (wdef))
4856 } end_uentryList_elements;
4863 else if (ctype_isUnion (ct))
4872 return sRef_undefined;
4875 static bool checkDefined (/*@temp@*/ sRef sr)
4877 /*@-temptrans@*/ /* the result from whatUndefined is lost */
4878 return (sRef_isInvalid (whatUndefined (sr, 0)));
4882 bool sRef_isReallyDefined (sRef s)
4884 if (sRef_isReasonable (s))
4886 if (sRef_isAnyDefined (s))
4892 if (sRef_isAllocated (s) || sRef_isPdefined (s))
4894 return checkDefined (s);
4908 void sRef_showNotReallyDefined (sRef s)
4910 if (sRef_isReasonable (s))
4912 if (sRef_isAnyDefined (s))
4918 if (sRef_isAllocated (s) || sRef_isPdefined (s))
4920 /*@-temptrans@*/ /* the result of whatUndefined is lost */
4921 sRef ref = whatUndefined (s, 0);
4923 llassert (sRef_isReasonable (ref));
4928 (message ("This sub-reference is %s: %q",
4929 sstate_unparse (sRef_getDefState (ref)),
4930 sRef_unparse (ref)));
4945 sstate sRef_getDefState (sRef s)
4947 if (sRef_isInvalid (s)) return (SS_UNKNOWN);
4948 return (s->defstate);
4951 void sRef_setDefState (sRef s, sstate defstate, fileloc loc)
4953 sRef_checkMutable (s);
4954 sRef_setStateAux (s, defstate, loc);
4957 static void sRef_clearAliasStateAux (sRef s, fileloc loc)
4959 sRef_checkMutable (s);
4960 sRef_setAliasKind (s, AK_ERROR, loc);
4963 void sRef_clearAliasState (sRef s, fileloc loc)
4965 sRef_checkMutable (s);
4966 sRef_aliasSetComplete (sRef_clearAliasStateAux, s, loc);
4969 void sRef_setAliasKindComplete (sRef s, alkind kind, fileloc loc)
4971 sRef_checkMutable (s);
4972 sRef_aliasSetCompleteAlkParam (sRef_setAliasKind, s, kind, loc);
4975 void sRef_setAliasKind (sRef s, alkind kind, fileloc loc)
4977 sRef_checkMutable (s);
4979 if (sRef_isReasonable (s))
4981 sRef_clearDerived (s);
4983 if ((kind != s->aliaskind && kind != s->oaliaskind)
4984 && fileloc_isDefined (loc))
4986 s->aliasinfo = stateInfo_updateLoc (s->aliasinfo, loc);
4989 s->aliaskind = kind;
4993 void sRef_setOrigAliasKind (sRef s, alkind kind)
4995 sRef_checkMutable (s);
4997 if (sRef_isReasonable (s))
4999 s->oaliaskind = kind;
5003 exkind sRef_getExKind (sRef s)
5005 if (sRef_isReasonable (s))
5007 return (s->expkind);
5015 exkind sRef_getOrigExKind (sRef s)
5017 if (sRef_isReasonable (s))
5019 return (s->oexpkind);
5027 static void sRef_clearExKindAux (sRef s, fileloc loc)
5029 sRef_checkMutable (s);
5030 sRef_setExKind (s, XO_UNKNOWN, loc);
5033 void sRef_setObserver (sRef s, fileloc loc)
5035 sRef_checkMutable (s);
5036 sRef_setExKind (s, XO_OBSERVER, loc);
5039 void sRef_setExposed (sRef s, fileloc loc)
5041 sRef_checkMutable (s);
5042 sRef_setExKind (s, XO_EXPOSED, loc);
5045 void sRef_clearExKindComplete (sRef s, fileloc loc)
5047 (void) sRef_aliasSetComplete (sRef_clearExKindAux, s, loc);
5050 void sRef_setExKind (sRef s, exkind exp, fileloc loc)
5052 sRef_checkMutable (s);
5054 if (sRef_isReasonable (s))
5056 if (s->expkind != exp)
5058 s->expinfo = stateInfo_updateLoc (s->expinfo, loc);
5066 ** s1->derived = s2->derived
5069 static void sRef_copyRealDerived (sRef s1, sRef s2)
5071 DPRINTF (("Copy real: %s / %s", sRef_unparse (s1), sRef_unparse (s2)));
5072 sRef_checkMutable (s1);
5074 if (sRef_isReasonable (s1) && sRef_isReasonable (s2))
5076 sRef sb = sRef_getRootBase (s1);
5078 sRefSet_clear (s1->deriv);
5080 sRefSet_allElements (s2->deriv, el)
5082 if (sRef_isReasonable (el))
5084 sRef rb = sRef_getRootBase (el);
5086 if (!sRef_same (rb, sb))
5088 sRef fb = sRef_fixDirectBase (el, s1);
5090 if (sRef_isReasonable (fb))
5092 sRef_copyRealDerived (fb, el);
5093 sRef_addDeriv (s1, fb);
5098 sRef_addDeriv (s1, el);
5101 } end_sRefSet_allElements ;
5106 void sRef_copyRealDerivedComplete (sRef s1, sRef s2)
5108 sRef_innerAliasSetCompleteParam (sRef_copyRealDerived, s1, s2);
5111 void sRef_setUndefined (sRef s, fileloc loc)
5113 sRef_checkMutable (s);
5115 if (sRef_isReasonable (s))
5117 s->defstate = SS_UNDEFINED;
5119 if (fileloc_isDefined (loc))
5121 s->definfo = stateInfo_updateLoc (s->definfo, loc);
5124 sRef_clearDerived (s);
5128 static void sRef_setDefinedAux (sRef s, fileloc loc, bool clear)
5130 sRef_checkMutable (s);
5131 if (sRef_isInvalid (s)) return;
5133 DPRINTF (("Set defined: %s", sRef_unparseFull (s)));
5135 if (s->defstate != SS_DEFINED && fileloc_isDefined (loc))
5137 s->definfo = stateInfo_updateLoc (s->definfo, loc);
5140 s->defstate = SS_DEFINED;
5142 DPRINTF (("Set defined: %s", sRef_unparseFull (s)));
5144 /* e.g., if x is allocated, *x = 3 defines x */
5146 if (s->kind == SK_PTR)
5148 sRef p = s->info->ref;
5151 if (p->defstate == SS_ALLOCATED
5152 || p->defstate == SS_SPECIAL) /* evans 2001-07-12: shouldn't need this */
5154 sRef_setDefinedAux (p, loc, clear);
5158 ** Defines a[0] also:
5161 arr = sRef_findDerivedArrayFetch (p, FALSE, 0, FALSE);
5163 if (sRef_isReasonable (arr))
5165 sRef_setDefinedAux (arr, loc, clear);
5168 else if (s->kind == SK_ARRAYFETCH)
5170 if (!s->info->arrayfetch->indknown
5171 || (s->info->arrayfetch->ind == 0))
5173 sRef p = s->info->arrayfetch->arr;
5174 sRef ptr = sRef_constructPointer (p);
5176 if (sRef_isReasonable (ptr))
5178 if (ptr->defstate == SS_ALLOCATED
5179 || ptr->defstate == SS_UNDEFINED
5180 || ptr->defstate == SS_SPECIAL) /* evans 2001-07-12: shouldn't need this */
5182 sRef_setDefinedAux (ptr, loc, clear);
5186 if (p->defstate == SS_RELDEF)
5190 else if (p->defstate == SS_ALLOCATED || p->defstate == SS_PDEFINED
5191 || p->defstate == SS_SPECIAL) /* evans 2001-07-12: shouldn't need this */
5193 p->defstate = SS_DEFINED;
5200 else if (s->kind == SK_FIELD)
5202 sRef parent = s->info->field->rec;
5204 if (sRef_isReasonable (parent))
5206 if (ctype_isUnion (ctype_realType (parent->type)))
5209 ** Should not clear derived from here.
5212 sRef_setDefinedNoClear (parent, loc);
5216 ; /* Nothing to do for structures. */
5228 sRef_clearDerived (s);
5232 /* evans 2001-07-12: need to define the derived references */
5233 sRefSet_elements (s->deriv, el)
5235 llassert (sRef_isReasonable (el));
5236 el->defstate = SS_DEFINED;
5237 } end_sRefSet_elements ;
5240 DPRINTF (("Set defined: %s", sRef_unparseFull (s)));
5243 static void sRef_setPartialDefined (sRef s, fileloc loc)
5245 sRef_checkMutable (s);
5247 if (!sRef_isPartial (s))
5249 sRef_setDefined (s, loc);
5253 void sRef_setPartialDefinedComplete (sRef s, fileloc loc)
5255 sRef_innerAliasSetComplete (sRef_setPartialDefined, s, loc);
5258 void sRef_setDefinedComplete (sRef s, fileloc loc)
5260 sRef_innerAliasSetComplete (sRef_setDefined, s, loc);
5263 void sRef_setDefinedCompleteDirect (sRef s, fileloc loc)
5267 aliases = usymtab_allAliases (s);
5268 DPRINTF (("Set defined complete: %s", sRef_unparseFull (s)));
5269 DPRINTF (("All aliases: %s", sRefSet_unparseFull (aliases)));
5271 sRef_setDefined (s, loc);
5273 sRefSet_realElements (aliases, current)
5275 if (sRef_isReasonable (current))
5277 current = sRef_updateSref (current);
5278 sRef_setDefined (current, loc);
5280 } end_sRefSet_realElements;
5282 sRefSet_free (aliases);
5283 sRef_innerAliasSetComplete (sRef_setDefined, s, loc);
5286 void sRef_setDefined (sRef s, fileloc loc)
5288 sRef_checkMutable (s);
5289 sRef_setDefinedAux (s, loc, TRUE);
5292 static void sRef_setDefinedNoClear (sRef s, fileloc loc)
5294 sRef_checkMutable (s);
5295 DPRINTF (("Defining: %s", sRef_unparseFull (s)));
5296 sRef_setDefinedAux (s, loc, FALSE);
5297 DPRINTF (("==> %s", sRef_unparseFull (s)));
5300 void sRef_setDefinedNCComplete (sRef s, fileloc loc)
5302 sRef_checkMutable (s);
5303 DPRINTF (("Set Defined Complete: %s", sRef_unparseFull (s)));
5304 sRef_innerAliasSetComplete (sRef_setDefinedNoClear, s, loc);
5305 DPRINTF (("==> %s", sRef_unparseFull (s)));
5308 static bool sRef_isDeepUnionField (sRef s)
5310 return (sRef_deepPred (sRef_isUnionField, s));
5313 bool sRef_isUnionField (sRef s)
5315 if (sRef_isReasonable (s) && s->kind == SK_FIELD)
5318 ** defining one field of a union defines the union
5321 sRef base = s->info->field->rec;
5323 if (sRef_isReasonable (base))
5325 return (ctype_isUnion (ctype_realType (base->type)));
5332 void sRef_setPdefined (sRef s, fileloc loc)
5334 sRef_checkMutable (s);
5335 if (sRef_isReasonable (s) && !sRef_isPartial (s))
5337 sRef base = sRef_getBaseSafe (s);
5339 if (s->defstate == SS_ALLOCATED)
5344 if (s->defstate != SS_PDEFINED && fileloc_isDefined (loc))
5346 s->definfo = stateInfo_updateLoc (s->definfo, loc);
5349 DPRINTF (("set pdefined: %s", sRef_unparseFull (s)));
5350 s->defstate = SS_PDEFINED;
5352 /* e.g., if x is allocated, *x = 3 defines x */
5354 while (sRef_isReasonable (base) && sRef_isKnown (base))
5356 if (base->defstate == SS_DEFINED)
5360 DPRINTF (("set pdefined: %s", sRef_unparseFull (base)));
5361 base->defstate = SS_PDEFINED;
5362 nb = sRef_getBaseSafe (base);
5373 static void sRef_setStateAux (sRef s, sstate ss, fileloc loc)
5375 sRef_checkMutable (s);
5377 if (sRef_isReasonable (s))
5379 /* if (s->defstate == SS_RELDEF) return; */
5381 if (s->defstate != ss && fileloc_isDefined (loc))
5383 s->definfo = stateInfo_updateLoc (s->definfo, loc);
5387 sRef_clearDerived (s);
5389 if (ss == SS_ALLOCATED)
5391 sRef base = sRef_getBaseSafe (s);
5393 while (sRef_isReasonable (base) && sRef_isKnown (base))
5395 if (base->defstate == SS_DEFINED)
5399 DPRINTF (("set pdefined: %s", sRef_unparseFull (s)));
5400 base->defstate = SS_PDEFINED;
5401 nb = sRef_getBaseSafe (base);
5413 void sRef_setAllocatedComplete (sRef s, fileloc loc)
5415 sRef_innerAliasSetComplete (sRef_setAllocated, s, loc);
5418 static void sRef_setAllocatedShallow (sRef s, fileloc loc)
5420 sRef_checkMutable (s);
5422 if (sRef_isReasonable (s))
5424 if (s->defstate == SS_DEAD || s->defstate == SS_UNDEFINED)
5426 s->defstate = SS_ALLOCATED;
5428 if (fileloc_isDefined (loc))
5430 s->definfo = stateInfo_updateLoc (s->definfo, loc);
5436 void sRef_setAllocatedShallowComplete (sRef s, fileloc loc)
5438 sRef_innerAliasSetComplete (sRef_setAllocatedShallow, s, loc);
5441 void sRef_setAllocated (sRef s, fileloc loc)
5443 sRef_checkMutable (s);
5444 sRef_setStateAux (s, SS_ALLOCATED, loc);
5447 void sRef_setPartial (sRef s, fileloc loc)
5449 sRef_checkMutable (s);
5450 sRef_setStateAux (s, SS_PARTIAL, loc);
5453 void sRef_setShared (sRef s, fileloc loc)
5455 sRef_checkMutable (s);
5457 if (sRef_isReasonable (s))
5459 if (s->aliaskind != AK_SHARED && fileloc_isDefined (loc))
5461 s->aliasinfo = stateInfo_updateLoc (s->aliasinfo, loc);
5464 s->aliaskind = AK_SHARED;
5465 /* don't! sRef_clearDerived (s); */
5469 void sRef_setLastReference (sRef s, /*@exposed@*/ sRef ref, fileloc loc)
5471 sRef_checkMutable (s);
5473 if (sRef_isReasonable (s))
5475 s->aliaskind = sRef_getAliasKind (ref);
5476 s->aliasinfo = stateInfo_updateRefLoc (s->aliasinfo, ref, loc);
5481 void sRef_setNullStateAux (/*@notnull@*/ sRef s, nstate ns, fileloc loc)
5483 sRef_checkMutable (s);
5485 sRef_resetAliasKind (s);
5487 if (fileloc_isDefined (loc))
5489 s->nullinfo = stateInfo_updateLoc (s->nullinfo, loc);
5493 void sRef_setNotNull (sRef s, fileloc loc)
5495 if (sRef_isReasonable (s))
5497 sRef_setNullStateAux (s, NS_NOTNULL, loc);
5501 void sRef_setNullStateN (sRef s, nstate n)
5503 if (sRef_isReasonable (s))
5505 sRef_checkMutable (s);
5507 sRef_resetAliasKind (s);
5511 void sRef_setNullState (sRef s, nstate n, fileloc loc)
5513 if (sRef_isReasonable (s))
5515 sRef_setNullStateAux (s, n, loc);
5519 void sRef_setNullTerminatedStateInnerComplete (sRef s, struct s_bbufinfo b, /*@unused@*/ fileloc loc)
5521 switch (b.bufstate) {
5522 case BB_NULLTERMINATED:
5523 sRef_setNullTerminatedState (s);
5524 sRef_setLen (s, b.len);
5526 case BB_POSSIBLYNULLTERMINATED:
5527 sRef_setPossiblyNullTerminatedState(s);
5529 case BB_NOTNULLTERMINATED:
5530 sRef_setNotNullTerminatedState (s);
5534 sRef_setSize (s, b.size);
5536 /* PL: TO BE DONE : Aliases are not modified right now, have to be similar to
5537 * setNullStateInnerComplete.
5541 void sRef_setNullStateInnerComplete (sRef s, nstate n, fileloc loc)
5543 DPRINTF (("Set null state: %s", nstate_unparse (n)));
5545 sRef_setNullState (s, n, loc);
5550 sRef_innerAliasSetComplete (sRef_setPosNull, s, loc);
5553 sRef_innerAliasSetComplete (sRef_setDefNull, s, loc);
5556 sRef_innerAliasSetComplete (sRef_setNullUnknown, s, loc);
5559 sRef_innerAliasSetComplete (sRef_setNotNull, s, loc);
5562 sRef_innerAliasSetComplete (sRef_setNotNull, s, loc);
5565 sRef_innerAliasSetComplete (sRef_setNullUnknown, s, loc);
5568 sRef_innerAliasSetComplete (sRef_setDefNull, s, loc);
5571 sRef_innerAliasSetComplete (sRef_setNullUnknown, s, loc);
5574 sRef_innerAliasSetComplete (sRef_setNullErrorLoc, s, loc);
5579 void sRef_setPosNull (sRef s, fileloc loc)
5581 if (sRef_isReasonable (s))
5583 sRef_setNullStateAux (s, NS_POSNULL, loc);
5587 void sRef_setDefNull (sRef s, fileloc loc)
5589 if (sRef_isReasonable (s))
5591 sRef_setNullStateAux (s, NS_DEFNULL, loc);
5595 void sRef_setNullUnknown (sRef s, fileloc loc)
5597 if (sRef_isReasonable (s))
5599 sRef_setNullStateAux (s, NS_UNKNOWN, loc);
5603 void sRef_setNullError (sRef s)
5605 if (sRef_isReasonable (s) && !sRef_isConst (s))
5607 sRef_setNullStateAux (s, NS_UNKNOWN, fileloc_undefined);
5611 void sRef_setNullErrorLoc (sRef s, fileloc loc)
5613 if (sRef_isReasonable (s) && !sRef_isConst (s))
5615 sRef_setNullStateAux (s, NS_UNKNOWN, loc);
5619 void sRef_setOnly (sRef s, fileloc loc)
5621 if (sRef_isReasonable (s) && s->aliaskind != AK_ONLY)
5623 sRef_checkMutable (s);
5624 s->aliaskind = AK_ONLY;
5625 s->aliasinfo = stateInfo_updateLoc (s->aliasinfo, loc);
5629 void sRef_setDependent (sRef s, fileloc loc)
5631 if (sRef_isReasonable (s) && !sRef_isConst (s) && (s->aliaskind != AK_DEPENDENT))
5633 sRef_checkMutable (s);
5634 DPRINTF (("Setting dependent: %s", sRef_unparseFull (s)));
5635 s->aliaskind = AK_DEPENDENT;
5636 s->aliasinfo = stateInfo_updateLoc (s->aliasinfo, loc);
5640 void sRef_setOwned (sRef s, fileloc loc)
5642 if (sRef_isReasonable (s) && !sRef_isConst (s) && (s->aliaskind != AK_OWNED))
5644 sRef_checkMutable (s);
5645 s->aliaskind = AK_OWNED;
5646 s->aliasinfo = stateInfo_updateLoc (s->aliasinfo, loc);
5650 void sRef_setKept (sRef s, fileloc loc)
5652 if (sRef_isReasonable (s) && !sRef_isConst (s) && (s->aliaskind != AK_KEPT))
5654 sRef base = sRef_getBaseSafe (s);
5656 while (sRef_isReasonable (base) && sRef_isKnown (base))
5658 if (base->defstate == SS_DEFINED)
5660 sRef_checkMutable (base);
5661 base->defstate = SS_PDEFINED;
5662 base = sRef_getBaseSafe (base);
5670 sRef_checkMutable (s);
5671 s->aliaskind = AK_KEPT;
5672 s->aliasinfo = stateInfo_updateLoc (s->aliasinfo, loc);
5676 static void sRef_setKeptAux (sRef s, fileloc loc)
5678 if (!sRef_isShared (s))
5680 sRef_setKept (s, loc);
5684 static void sRef_setDependentAux (sRef s, fileloc loc)
5686 if (!sRef_isShared (s))
5688 sRef_setDependent (s, loc);
5692 void sRef_setKeptComplete (sRef s, fileloc loc)
5694 sRef_aliasSetComplete (sRef_setKeptAux, s, loc);
5697 void sRef_setDependentComplete (sRef s, fileloc loc)
5699 sRef_aliasSetComplete (sRef_setDependentAux, s, loc);
5702 void sRef_setFresh (sRef s, fileloc loc)
5704 if (sRef_isReasonable (s) && !sRef_isConst (s))
5706 sRef_checkMutable (s);
5707 s->aliaskind = AK_FRESH;
5708 s->aliasinfo = stateInfo_updateLoc (s->aliasinfo, loc);
5709 DPRINTF (("SetFresh: %s", sRef_unparseFull (s)));
5713 void sRef_kill (sRef s, fileloc loc)
5715 DPRINTF (("Kill: %s", sRef_unparseFull (s)));
5717 if (sRef_isReasonable (s) && !sRef_isShared (s) && !sRef_isConst (s))
5719 sRef base = sRef_getBaseSafe (s);
5720 sRef_checkMutable (s);
5722 while (sRef_isReasonable (base) && sRef_isKnown (base))
5724 if (base->defstate == SS_DEFINED)
5726 sRef_checkMutable (base);
5727 base->defstate = SS_PDEFINED;
5728 base = sRef_getBaseSafe (base);
5736 s->aliaskind = s->oaliaskind;
5737 s->defstate = SS_DEAD;
5738 s->definfo = stateInfo_updateLoc (s->definfo, loc);
5740 sRef_clearDerived (s);
5744 void sRef_maybeKill (sRef s, fileloc loc)
5746 if (sRef_isReasonable (s))
5748 sRef base = sRef_getBaseSafe (s);
5749 sRef_checkMutable (s);
5751 while (sRef_isReasonable (base) && sRef_isKnown (base))
5753 if (base->defstate == SS_DEFINED || base->defstate == SS_RELDEF)
5755 sRef_checkMutable (base);
5756 base->defstate = SS_PDEFINED;
5757 base = sRef_getBaseSafe (base);
5766 s->aliaskind = s->oaliaskind;
5767 s->defstate = SS_HOFFA;
5768 s->definfo = stateInfo_updateLoc (s->definfo, loc);
5769 sRef_clearDerived (s);
5775 ** just for type checking...
5778 static void sRef_killAux (sRef s, fileloc loc)
5780 if (sRef_isReasonable (s) && !sRef_isShared (s))
5782 if (sRef_isUnknownArrayFetch (s))
5784 sRef_maybeKill (s, loc);
5794 ** kills s and all aliases to s
5797 void sRef_killComplete (sRef s, fileloc loc)
5799 DPRINTF (("Kill complete: %s", sRef_unparseFull (s)));
5800 sRef_aliasSetComplete (sRef_killAux, s, loc);
5803 static bool sRef_equivalent (sRef s1, sRef s2)
5805 return (sRef_compare (s1, s2) == 0);
5809 ** returns an sRef that will not be free'd on function exit.
5812 /*@only@*/ sRef sRef_saveCopy (sRef s)
5816 if (sRef_isReasonable (s))
5818 bool old = inFunction;
5821 ** Exit the function scope, so this sRef is not
5822 ** stored in the deallocation table.
5826 DPRINTF (("Copying sref: %s", sRef_unparseFull(s)));
5827 ret = sRef_copy (s);
5828 DPRINTF (("Copying ===>: %s", sRef_unparseFull(ret)));
5833 ret = sRef_undefined;
5836 /*@-dependenttrans@*/
5838 /*@=dependenttrans@*/
5841 sRef sRef_copy (sRef s)
5843 if (sRef_isKindSpecial (s) && !sRef_isGlobalMarker (s))
5846 return s; /* don't copy specials (except for global markers) */
5850 if (sRef_isReasonable (s))
5852 sRef t = sRef_alloc ();
5854 DPRINTF (("Copying: [%p] %s", s, sRef_unparse (s)));
5855 DPRINTF (("Full: %s", sRef_unparseFull (s)));
5859 t->modified = s->modified;
5860 t->immut = FALSE; /* Note mutability is not copied. */
5862 t->val = multiVal_copy (s->val);
5864 t->info = sinfo_copy (s);
5865 t->defstate = s->defstate;
5866 t->nullstate = s->nullstate;
5868 /* start modifications */
5869 t->bufinfo.bufstate = s->bufinfo.bufstate;
5870 t->bufinfo.len = s->bufinfo.len;
5871 t->bufinfo.size = s->bufinfo.size;
5872 /* end modifications */
5874 t->aliaskind = s->aliaskind;
5875 t->oaliaskind = s->oaliaskind;
5877 t->expkind = s->expkind;
5878 t->oexpkind = s->oexpkind;
5880 t->nullinfo = stateInfo_copy (s->nullinfo);
5881 t->aliasinfo = stateInfo_copy (s->aliasinfo);
5882 t->definfo = stateInfo_copy (s->definfo);
5883 t->expinfo = stateInfo_copy (s->expinfo);
5885 t->deriv = sRefSet_newDeepCopy (s->deriv);
5886 t->state = valueTable_copy (s->state);
5888 DPRINTF (("Made copy: %s => %s", sRef_unparseFull (s), sRef_unparseFull (t)));
5893 return sRef_undefined;
5898 # define PREDTEST(func,s) \
5899 do { if (sRef_isInvalid (s)) { return FALSE; } \
5900 else { if (sRef_isConj (s)) \
5901 { return (func (sRef_getConjA (s)) \
5902 || func (sRef_getConjB (s))); }}} while (FALSE);
5904 bool sRef_isAddress (sRef s)
5906 PREDTEST (sRef_isAddress, s);
5907 return (s->kind == SK_ADR);
5911 ** pretty weak... maybe a flag should control this.
5914 bool sRef_isThroughArrayFetch (sRef s)
5916 if (sRef_isReasonable (s))
5924 if (sRef_isArrayFetch (tref))
5929 lt = sRef_getBase (tref);
5931 } while (sRef_isReasonable (tref));
5937 bool sRef_isArrayFetch (sRef s)
5939 PREDTEST (sRef_isArrayFetch, s);
5940 return (s->kind == SK_ARRAYFETCH);
5943 bool sRef_isMacroParamRef (sRef s)
5945 if (context_inMacro () && sRef_isCvar (s))
5947 uentry ue = sRef_getUentry (s);
5948 cstring pname = makeParam (uentry_rawName (ue));
5949 uentry mac = usymtab_lookupSafe (pname);
5951 cstring_free (pname);
5952 return (uentry_isValid (mac));
5958 bool sRef_isCvar (sRef s)
5960 PREDTEST (sRef_isCvar, s);
5961 return (s->kind == SK_CVAR);
5964 bool sRef_isConst (sRef s)
5966 PREDTEST (sRef_isConst, s);
5967 return (s->kind == SK_CONST);
5970 bool sRef_isObject (sRef s)
5972 PREDTEST (sRef_isObject, s);
5973 return (s->kind == SK_OBJECT);
5976 bool sRef_isExternal (sRef s)
5978 PREDTEST (sRef_isExternal, s);
5979 return (s->kind == SK_EXTERNAL);
5982 static bool sRef_isDerived (sRef s)
5984 PREDTEST (sRef_isDerived, s);
5985 return (s->kind == SK_DERIVED);
5988 bool sRef_isField (sRef s)
5990 PREDTEST (sRef_isField, s);
5991 return (s->kind == SK_FIELD);
5994 static bool sRef_isIndex (sRef s)
5996 PREDTEST (sRef_isIndex, s);
5997 return (s->kind == SK_ARRAYFETCH);
6000 bool sRef_isAnyParam (sRef s)
6002 PREDTEST (sRef_isAnyParam, s);
6003 return (s->kind == SK_PARAM);
6006 bool sRef_isParam (sRef s)
6008 PREDTEST (sRef_isParam, s);
6009 return (s->kind == SK_PARAM);
6012 bool sRef_isDirectParam (sRef s)
6014 PREDTEST (sRef_isDirectParam, s);
6016 return ((s->kind == SK_CVAR) &&
6017 (s->info->cvar->lexlevel == functionScope) &&
6018 (context_inFunction () &&
6019 (s->info->cvar->index <= uentryList_size (context_getParams ()))));
6022 bool sRef_isPointer (sRef s)
6024 PREDTEST (sRef_isPointer, s);
6025 return (s->kind == SK_PTR);
6029 ** returns true if storage referenced by s is visible
6032 bool sRef_isReference (sRef s)
6034 PREDTEST (sRef_isReference, s);
6036 return (sRef_isPointer (s) || sRef_isIndex (s) || sRef_isFileOrGlobalScope (s)
6037 || (sRef_isField (s) && (sRef_isReference (s->info->field->rec))));
6040 bool sRef_isIReference (sRef s)
6042 return (sRef_isPointer (s) || sRef_isAddress (s) || sRef_isIndex (s)
6043 || sRef_isField (s) || sRef_isArrayFetch (s));
6046 bool sRef_isFileOrGlobalScope (sRef s)
6048 return (sRef_isCvar (s) && (s->info->cvar->lexlevel <= fileScope));
6051 bool sRef_isRealGlobal (sRef s)
6053 return (sRef_isCvar (s) && (s->info->cvar->lexlevel == globScope));
6056 bool sRef_isFileStatic (sRef s)
6058 return (sRef_isCvar (s) && (s->info->cvar->lexlevel == fileScope));
6061 bool sRef_isAliasCheckedGlobal (sRef s)
6063 if (sRef_isFileOrGlobalScope (s))
6065 uentry ue = sRef_getUentry (s);
6067 return context_checkAliasGlob (ue);
6075 void sRef_free (/*@only@*/ sRef s)
6077 if (s != sRef_undefined && s->kind != SK_SPECIAL)
6079 DPRINTF (("Free sref: [%p]", s));
6081 sRef_checkValid (s);
6083 multiVal_free (s->val); /* evans 2002-07-12 */
6085 stateInfo_free (s->expinfo);
6086 stateInfo_free (s->aliasinfo);
6087 stateInfo_free (s->definfo);
6088 stateInfo_free (s->nullinfo);
6090 sRefSet_free (s->deriv);
6091 s->deriv = sRefSet_undefined;
6093 valueTable_free (s->state);
6097 /* drl added to help locate use after release*/
6098 s->expinfo = stateInfo_undefined;
6099 s->aliasinfo = stateInfo_undefined;
6100 s->definfo = stateInfo_undefined;
6101 s->nullinfo = stateInfo_undefined;
6103 /*@i32@*/ sfree (s);
6107 void sRef_setType (sRef s, ctype t)
6109 if (sRef_isReasonable (s))
6111 sRef_checkMutable (s);
6116 void sRef_setTypeFull (sRef s, ctype t)
6118 if (sRef_isReasonable (s))
6120 sRef_checkMutable (s);
6123 sRefSet_allElements (s->deriv, current)
6125 sRef_setTypeFull (current, ctype_unknown);
6126 } end_sRefSet_allElements ;
6131 sRef_buildField (/*@exposed@*/ sRef rec, /*@dependent@*/ cstring f)
6133 return (sRef_buildNCField (rec, f));
6136 static /*@exposed@*/ sRef
6137 sRef_findDerivedField (/*@notnull@*/ sRef rec, cstring f)
6139 sRefSet_allElements (sRef_derivedFields (rec), sr)
6141 if (sRef_isReasonable (sr))
6143 if (sRef_isReasonable (sr))
6145 if (sr->info != NULL)
6147 if (sr->kind == SK_FIELD && cstring_equal (sr->info->field->field, f))
6155 llcontbug (message ("Invalid sRef as derived field of %s", sRef_unparse (rec)));
6158 } end_sRefSet_allElements;
6160 return sRef_undefined;
6163 /*@dependent@*/ /*@observer@*/ sRefSet sRef_derivedFields (/*@temp@*/ sRef rec)
6165 if (sRef_isReasonable (rec))
6173 return (sRefSet_undefined);
6177 static /*@exposed@*/ sRef
6178 sRef_findDerivedPointer (sRef s)
6180 if (sRef_isReasonable (s))
6182 sRefSet_realElements (s->deriv, sr)
6184 if (sRef_isReasonable (sr) && sr->kind == SK_PTR)
6188 } end_sRefSet_realElements;
6191 return sRef_undefined;
6195 sRef_isUnknownArrayFetch (sRef s)
6197 return (sRef_isReasonable (s)
6198 && s->kind == SK_ARRAYFETCH
6199 && !s->info->arrayfetch->indknown);
6202 static /*@exposed@*/ sRef
6203 sRef_findDerivedArrayFetch (/*@notnull@*/ sRef s, bool isknown, int idx, bool dead)
6208 sRefSet_realElements (s->deriv, sr)
6210 if (sRef_isReasonable (sr)
6211 && sr->kind == SK_ARRAYFETCH
6212 && sr->info->arrayfetch->indknown
6213 && (sr->info->arrayfetch->ind == idx))
6217 } end_sRefSet_realElements;
6221 sRefSet_realElements (s->deriv, sr)
6223 if (sRef_isReasonable (sr)
6224 && sr->kind == SK_ARRAYFETCH
6225 && (!sr->info->arrayfetch->indknown
6226 || (sr->info->arrayfetch->indknown &&
6227 sr->info->arrayfetch->ind == 0)))
6229 if (sRef_isDead (sr) || sRef_isKept (sr))
6231 if (dead || context_getFlag (FLG_STRICTUSERELEASED))
6241 } end_sRefSet_realElements;
6244 return sRef_undefined;
6247 static /*@exposed@*/ sRef
6248 sRef_buildNCField (/*@exposed@*/ sRef rec, /*@exposed@*/ cstring f)
6252 DPRINTF (("Build nc field: %s / %s",
6253 sRef_unparseFull (rec), f));
6255 if (sRef_isInvalid (rec))
6257 return sRef_undefined;
6261 ** check if the field already has been referenced
6264 s = sRef_findDerivedField (rec, f);
6266 if (sRef_isReasonable (s))
6272 ctype ct = ctype_realType (rec->type);
6274 DPRINTF (("Field of: %s", sRef_unparse (rec)));
6278 s->info = (sinfo) dmalloc (sizeof (*s->info));
6279 s->info->field = (fldinfo) dmalloc (sizeof (*s->info->field));
6280 s->info->field->rec = rec; /* sRef_copy (rec); */ /*@i32@*/
6281 s->info->field->field = f; /* doesn't copy f */
6283 if (ctype_isKnown (ct) && ctype_isSU (ct))
6285 uentry ue = uentryList_lookupField (ctype_getFields (ct), f);
6287 if (!uentry_isUndefined (ue))
6289 DPRINTF (("lookup: %s for %s", uentry_unparseFull (ue),
6290 ctype_unparse (ct)));
6292 s->type = uentry_getType (ue);
6294 if (ctype_isMutable (s->type)
6295 && rec->aliaskind != AK_STACK
6296 && !alkind_isStatic (rec->aliaskind))
6298 s->aliaskind = rec->aliaskind;
6302 s->aliaskind = AK_UNKNOWN;
6305 if (sRef_isStateDefined (rec) || sRef_isStateUnknown (rec)
6306 || sRef_isPdefined (rec))
6308 sRef_setStateFromUentry (s, ue);
6312 sRef_setPartsFromUentry (s, ue);
6315 s->oaliaskind = s->aliaskind;
6316 s->oexpkind = s->expkind;
6318 DPRINTF (("sref: %s", sRef_unparseFull (s)));
6323 Never report this as an error. It can happen whenever there
6324 is casting involved.
6328 llcontbug (message ("buildNCField --- no field %s: %q / %s",
6329 f, sRef_unparse (s), ctype_unparse (ct)));
6333 return sRef_undefined;
6337 if (rec->defstate == SS_DEFINED
6338 && (s->defstate == SS_UNDEFINED || s->defstate == SS_UNKNOWN))
6340 s->defstate = SS_DEFINED;
6342 else if (rec->defstate == SS_PARTIAL)
6344 s->defstate = SS_PARTIAL;
6346 else if (rec->defstate == SS_ALLOCATED)
6348 if (ctype_isStackAllocated (ct) && ctype_isStackAllocated (s->type))
6350 s->defstate = SS_ALLOCATED;
6354 s->defstate = SS_UNDEFINED;
6357 else if (s->defstate == SS_UNKNOWN)
6359 s->defstate = rec->defstate;
6366 if (s->defstate == SS_UNDEFINED)
6368 ctype rt = ctype_realType (s->type);
6370 if (ctype_isArray (rt) || ctype_isSU (rt))
6372 s->defstate = SS_ALLOCATED;
6376 sRef_addDeriv (rec, s);
6377 DPRINTF (("Add deriv: %s", sRef_unparseFull (rec)));
6379 if (ctype_isInt (s->type) && cstring_equal (f, REFSNAME))
6381 s->aliaskind = AK_REFS;
6382 s->oaliaskind = AK_REFS;
6385 DPRINTF (("Build field ==> %s", sRef_unparseFull (s)));
6391 sRef_isStackAllocated (sRef s)
6393 return (sRef_isReasonable(s)
6394 && s->defstate == SS_ALLOCATED && ctype_isStackAllocated (s->type));
6398 void sRef_setArrayFetchState (/*@notnull@*/ /*@exposed@*/ sRef s,
6399 /*@notnull@*/ /*@exposed@*/ sRef arr)
6401 sRef_checkMutable (s);
6403 if (ctype_isRealAP (arr->type))
6405 s->type = ctype_baseArrayPtr (arr->type);
6408 /* a hack, methinks... makeArrayFetch (&a[0]) ==> a[] */
6409 /* evans - 2001-08-27: not sure where this was necessary - it
6410 ** causes an assertion in in aliasCheckPred to fail.
6413 if (sRef_isAddress (arr))
6415 sRef t = arr->info->ref;
6417 if (sRef_isArrayFetch (t))
6419 s->info->arrayfetch->arr = t->info->arrayfetch->arr;
6422 else if (ctype_isRealPointer (arr->type))
6424 sRef sp = sRef_findDerivedPointer (arr);
6426 if (sRef_isReasonable (sp))
6429 if (ctype_isMutable (s->type))
6431 sRef_setExKind (s, sRef_getExKind (sp), fileloc_undefined);
6433 s->aliaskind = sp->aliaskind;
6436 s->defstate = sp->defstate;
6438 if (s->defstate == SS_DEFINED)
6440 if (!context_getFlag (FLG_STRICTDESTROY))
6442 s->defstate = SS_PARTIAL;
6446 DPRINTF (("Set null state: %s / %s", sRef_unparseFull (s), sRef_unparseFull (sp)));
6447 sRef_setNullStateN (s, sRef_getNullState (sp));
6451 if (arr->defstate == SS_UNDEFINED)
6453 s->defstate = SS_UNUSEABLE;
6455 else if ((arr->defstate == SS_ALLOCATED) && !ctype_isSU (s->type))
6457 s->defstate = SS_UNDEFINED;
6461 if (!context_getFlag (FLG_STRICTDESTROY))
6463 s->defstate = SS_PARTIAL;
6467 s->defstate = SS_DEFINED;
6471 ** Very weak checking for array elements.
6473 ** s->defstate = arr->defstate;
6477 sRef_setExKind (s, sRef_getExKind (arr), g_currentloc);
6479 if (arr->aliaskind == AK_LOCAL || arr->aliaskind == AK_FRESH)
6481 s->aliaskind = AK_LOCAL;
6485 s->aliaskind = AK_UNKNOWN;
6488 sRef_setTypeState (s);
6493 if (arr->defstate == SS_DEFINED)
6496 ** Very weak checking for array elements.
6498 ** s->defstate = arr->defstate;
6501 if (context_getFlag (FLG_STRICTDESTROY))
6503 s->defstate = SS_DEFINED;
6507 s->defstate = SS_PARTIAL;
6510 else if (arr->defstate == SS_ALLOCATED)
6512 if (ctype_isRealArray (s->type))
6514 s->defstate = SS_ALLOCATED;
6518 if (!s->info->arrayfetch->indknown)
6521 ** is index is unknown, elements is defined or
6522 ** allocated is any element is!
6525 s->defstate = SS_UNDEFINED;
6527 sRefSet_allElements (arr->deriv, sr)
6529 if (sRef_isReasonable (sr))
6531 if (sRef_isReasonable (sr))
6533 if (sr->defstate == SS_ALLOCATED)
6535 s->defstate = SS_ALLOCATED;
6539 if (sr->defstate == SS_DEFINED)
6541 if (context_getFlag (FLG_STRICTDESTROY))
6543 s->defstate = SS_DEFINED;
6547 s->defstate = SS_PARTIAL;
6556 llcontbug (message ("Invalid sRef as derived element of %s", sRef_unparse (arr)));
6559 } end_sRefSet_allElements;
6563 s->defstate = SS_UNDEFINED;
6569 s->defstate = arr->defstate;
6574 ** kludgey way to guess where aliaskind applies
6577 if (ctype_isMutable (s->type)
6578 && !ctype_isPointer (arr->type)
6579 && !alkind_isStatic (arr->aliaskind)
6580 && !alkind_isStack (arr->aliaskind)) /* evs - 2000-06-20: don't pass stack allocation to members */
6582 s->aliaskind = arr->aliaskind;
6586 s->aliaskind = AK_UNKNOWN;
6589 sRef_setTypeState (s);
6592 if (sRef_isObserver (arr))
6594 s->expkind = XO_OBSERVER;
6598 /*@exposed@*/ sRef sRef_buildArrayFetch (/*@exposed@*/ sRef arr)
6602 if (!sRef_isReasonable (arr)) {
6603 /*@-nullret@*/ return arr /*@=nullret@*/;
6606 if (ctype_isRealPointer (arr->type))
6608 (void) sRef_buildPointer (arr); /* do this to define arr! */
6611 s = sRef_findDerivedArrayFetch (arr, FALSE, 0, FALSE);
6613 if (sRef_isReasonable (s))
6615 /* evans 2001-07-12: this is bogus, clean-up hack */
6616 if (s->info->arrayfetch->arr != arr)
6619 check (sRefSet_delete (arr->deriv, s));
6620 res = sRef_buildArrayFetch (arr);
6621 sRef_copyState (res, s);
6622 llassert (res->info->arrayfetch->arr == arr);
6626 sRef_setExKind (s, sRef_getExKind (arr), g_currentloc);
6633 s->kind = SK_ARRAYFETCH;
6634 s->info = (sinfo) dmalloc (sizeof (*s->info));
6635 s->info->arrayfetch = (ainfo) dmalloc (sizeof (*s->info->arrayfetch));
6636 s->info->arrayfetch->indknown = FALSE;
6637 s->info->arrayfetch->ind = 0;
6638 s->info->arrayfetch->arr = arr; /* sRef_copy (arr); */ /*@i32@*/
6640 sRef_setArrayFetchState (s, arr);
6642 s->oaliaskind = s->aliaskind;
6643 s->oexpkind = s->expkind;
6645 if (!context_inProtectVars ())
6647 sRef_addDeriv (arr, s);
6650 if (valueTable_isUndefined (s->state))
6652 s->state = context_createValueTable (s, stateInfo_makeLoc (g_currentloc));
6660 sRef_buildArrayFetchKnown (/*@exposed@*/ sRef arr, int i)
6664 if (!sRef_isReasonable (arr)) {
6665 /*@-nullret@*/ return arr /*@=nullret@*/;
6668 if (ctype_isRealPointer (arr->type))
6670 (void) sRef_buildPointer (arr); /* do this to define arr! */
6673 s = sRef_findDerivedArrayFetch (arr, TRUE, i, FALSE);
6675 if (sRef_isReasonable (s))
6677 /* evans 2001-07-12: this is bogus, clean-up hack */
6678 if (s->info->arrayfetch->arr != arr)
6682 check (sRefSet_delete (arr->deriv, s));
6683 res = sRef_buildArrayFetchKnown (arr, i);
6685 llassert (res->info->arrayfetch->arr == arr);
6686 sRef_copyState (res, s);
6687 llassert (res->info->arrayfetch->arr == arr);
6691 sRef_setExKind (s, sRef_getExKind (arr), g_currentloc);
6692 llassert (s->info->arrayfetch->arr == arr);
6699 s->kind = SK_ARRAYFETCH;
6700 s->info = (sinfo) dmalloc (sizeof (*s->info));
6701 s->info->arrayfetch = (ainfo) dmalloc (sizeof (*s->info->arrayfetch));
6702 s->info->arrayfetch->arr = arr; /* sRef_copy (arr); */ /*@i32@*/
6703 s->info->arrayfetch->indknown = TRUE;
6704 s->info->arrayfetch->ind = i;
6706 sRef_setArrayFetchState (s, arr);
6707 /* evans 2001-08-27 no: can change this - llassert (s->info->arrayfetch->arr == arr); */
6709 s->oaliaskind = s->aliaskind;
6710 s->oexpkind = s->expkind;
6711 sRef_addDeriv (arr, s);
6713 llassert (valueTable_isUndefined (s->state));
6714 s->state = context_createValueTable (s, stateInfo_makeLoc (g_currentloc));
6720 ** sets everything except for defstate
6724 sRef_setPartsFromUentry (sRef s, uentry ue)
6726 sRef uref = uentry_getSref (ue);
6728 llassert (sRef_isReasonable (s));
6730 s->aliaskind = alkind_derive (s->aliaskind, uentry_getAliasKind (ue));
6731 s->oaliaskind = s->aliaskind;
6733 if (s->expkind == XO_UNKNOWN)
6735 s->expkind = uentry_getExpKind (ue);
6738 s->oexpkind = s->expkind;
6740 if (sRef_getNullState (s) == NS_UNKNOWN)
6742 DPRINTF (("Set null state: %s / %s", sRef_unparseFull (s), uentry_unparseFull (ue)));
6743 sRef_setNullStateN (s, sRef_getNullState (uentry_getSref (ue)));
6747 DPRINTF (("Skipping null null state!"));
6750 if (s->aliaskind == AK_IMPONLY && (sRef_isExposed (s) || sRef_isObserver (s)))
6752 s->oaliaskind = s->aliaskind = AK_IMPDEPENDENT;
6755 if (sRef_isReasonable (uref))
6757 valueTable utable = uref->state;
6758 valueTable_free (s->state);
6759 s->state = valueTable_copy (utable);
6764 sRef_setStateFromAbstractUentry (sRef s, uentry ue)
6766 llassert (sRef_isReasonable (s));
6767 sRef_checkMutable (s);
6769 sRef_setPartsFromUentry (s, ue);
6771 s->aliaskind = alkind_derive (s->aliaskind, uentry_getAliasKind (ue));
6772 s->oaliaskind = s->aliaskind;
6774 if (s->expkind == XO_UNKNOWN)
6776 s->expkind = uentry_getExpKind (ue);
6779 s->oexpkind = s->expkind;
6783 sRef_setStateFromUentry (sRef s, uentry ue)
6787 sRef_checkMutable (s);
6788 llassert (sRef_isReasonable (s));
6790 sRef_setPartsFromUentry (s, ue);
6792 defstate = uentry_getDefState (ue);
6794 if (sstate_isKnown (defstate))
6796 s->defstate = defstate;
6805 sRef_buildPointer (/*@exposed@*/ sRef t)
6807 DPRINTF (("build pointer: %s", sRef_unparse (t)));
6809 if (sRef_isInvalid (t)) return sRef_undefined;
6811 if (sRef_isAddress (t))
6813 DPRINTF (("Return ref: %s", sRef_unparse (t->info->ref)));
6814 return (t->info->ref);
6818 sRef s = sRef_findDerivedPointer (t);
6820 DPRINTF (("find derived: %s", sRef_unparse (s)));
6822 if (sRef_isReasonable (s))
6825 sRef_setExKind (s, sRef_getExKind (t), g_currentloc);
6826 s->oaliaskind = s->aliaskind;
6827 s->oexpkind = s->expkind;
6833 s = sRef_constructPointerAux (t);
6835 DPRINTF (("construct: %s", sRef_unparse (s)));
6837 if (sRef_isReasonable (s))
6839 sRef_addDeriv (t, s);
6841 s->oaliaskind = s->aliaskind;
6842 s->oexpkind = s->expkind;
6851 sRef_constructPointer (/*@exposed@*/ sRef t)
6854 return sRef_buildPointer (t);
6857 static /*@exposed@*/ sRef sRef_constructDerefAux (sRef t, bool isdead)
6859 if (sRef_isReasonable (t))
6864 ** if there is a derived t[?], return that. Otherwise, *t.
6867 s = sRef_findDerivedArrayFetch (t, FALSE, 0, isdead);
6869 if (sRef_isReasonable (s))
6871 DPRINTF (("Found array fetch: %s", sRef_unparseFull (s)));
6876 sRef ret = sRef_constructPointer (t);
6878 DPRINTF (("Constructed pointer: %s", sRef_unparseFull (ret)));
6885 return sRef_undefined;
6889 sRef sRef_constructDeref (sRef t)
6891 return sRef_constructDerefAux (t, FALSE);
6894 sRef sRef_constructDeadDeref (sRef t)
6896 return sRef_constructDerefAux (t, TRUE);
6900 sRef_constructPointerAux (/*@notnull@*/ /*@exposed@*/ sRef t)
6902 sRef s = sRef_newRef ();
6906 llassert (valueTable_isUndefined (s->state));
6909 s->info = (sinfo) dmalloc (sizeof (*s->info));
6910 s->info->ref = t; /* sRef_copy (t); */ /*@i32*/
6912 if (ctype_isRealAP (rt))
6914 s->type = ctype_baseArrayPtr (rt);
6917 st = ctype_realType (s->type);
6919 if (t->defstate == SS_UNDEFINED)
6921 s->defstate = SS_UNUSEABLE;
6923 else if ((t->defstate == SS_ALLOCATED) && !ctype_isSU (st))
6925 s->defstate = SS_UNDEFINED;
6929 s->defstate = t->defstate;
6932 if (t->aliaskind == AK_LOCAL || t->aliaskind == AK_FRESH)
6934 s->aliaskind = AK_LOCAL;
6938 s->aliaskind = AK_UNKNOWN;
6941 sRef_setExKind (s, sRef_getExKind (t), fileloc_undefined);
6942 sRef_setTypeState (s);
6944 s->oaliaskind = s->aliaskind;
6945 s->oexpkind = s->expkind;
6947 if (valueTable_isUndefined (s->state))
6949 s->state = context_createValueTable (s, stateInfo_makeLoc (g_currentloc));
6955 bool sRef_hasDerived (sRef s)
6957 return (sRef_isReasonable (s) && !sRefSet_isEmpty (s->deriv));
6961 sRef_clearDerived (sRef s)
6963 if (sRef_isReasonable (s))
6965 DPRINTF (("Clear derived: [%p] %s", s, sRef_unparseDebug (s)));
6966 sRefSet_clear (s->deriv);
6971 sRef_clearDerivedComplete (sRef s)
6973 if (sRef_isReasonable (s))
6975 sRef base = sRef_getBaseSafe (s);
6977 while (sRef_isReasonable (base))
6979 DPRINTF (("Clear derived: [%p] %s", base, sRef_unparse (base)));
6980 sRefSet_clear (base->deriv);
6981 base = sRef_getBaseSafe (base);
6984 DPRINTF (("Clear derived: [%p] %s", s, sRef_unparse (s)));
6985 sRefSet_clear (s->deriv);
6989 /*@exposed@*/ sRef sRef_makePointer (/*@exposed@*/ sRef s)
6992 sRef res = sRef_buildPointer (s);
6994 DPRINTF (("Res: %s", sRef_unparse (res)));
6999 ** &a[] => a (this is for out params)
7003 sRef_makeAnyArrayFetch (/*@exposed@*/ sRef arr)
7005 if (sRef_isAddress (arr))
7007 return (arr->info->ref);
7011 return (sRef_buildArrayFetch (arr));
7016 sRef_makeArrayFetch (/*@exposed@*/ sRef arr)
7018 return (sRef_buildArrayFetch (arr));
7022 sRef_makeArrayFetchKnown (/*@exposed@*/ sRef arr, int i)
7024 return (sRef_buildArrayFetchKnown (arr, i));
7028 sRef_makeField (sRef rec, /*@dependent@*/ cstring f)
7031 ret = sRef_buildField (rec, f);
7036 sRef_makeNCField (/*@exposed@*/ sRef rec, /*@dependent@*/ cstring f)
7038 return (sRef_buildNCField (rec, f));
7042 sRef_unparseKindName (sRef s)
7046 if (s == sRef_undefined) return cstring_makeLiteral ("<invalid>");
7048 s = sRef_fixConj (s);
7053 if (sRef_isLocalVar (s))
7055 result = cstring_makeLiteral ("Variable");
7059 result = cstring_makeLiteral ("Undef global");
7063 result = cstring_makeLiteral ("Out parameter");
7066 if (sRef_isAnyParam (s->info->arrayfetch->arr))
7068 result = cstring_makeLiteral ("Out parameter");
7070 else if (sRef_isIndexKnown (s))
7072 result = cstring_makeLiteral ("Array element");
7076 result = cstring_makeLiteral ("Value");
7080 if (sRef_isAnyParam (s->info->ref))
7082 result = cstring_makeLiteral ("Out parameter");
7086 result = cstring_makeLiteral ("Value");
7090 result = cstring_makeLiteral ("Value");
7093 result = cstring_makeLiteral ("Field");
7096 result = cstring_makeLiteral ("Object");
7098 case SK_UNCONSTRAINED:
7099 result = cstring_makeLiteral ("<anything>");
7108 result = cstring_makeLiteral ("<unknown>");
7111 result = cstring_makeLiteral ("<conj>");
7114 result = cstring_makeLiteral ("Storage");
7122 sRef_unparseKindNamePlain (sRef s)
7126 if (s == sRef_undefined) return cstring_makeLiteral ("<invalid>");
7128 s = sRef_fixConj (s);
7133 if (sRef_isLocalVar (s))
7135 result = cstring_makeLiteral ("Variable");
7139 result = cstring_makeLiteral ("Global");
7143 result = cstring_makeLiteral ("Parameter");
7146 if (sRef_isAnyParam (s->info->arrayfetch->arr))
7148 result = cstring_makeLiteral ("Parameter");
7150 else if (sRef_isIndexKnown (s))
7152 result = cstring_makeLiteral ("Array element");
7156 result = cstring_makeLiteral ("Value");
7160 if (sRef_isAnyParam (s->info->ref))
7162 result = cstring_makeLiteral ("Parameter");
7166 result = cstring_makeLiteral ("Value");
7170 result = cstring_makeLiteral ("Value");
7173 result = cstring_makeLiteral ("Field");
7176 result = cstring_makeLiteral ("Object");
7179 result = cstring_makeLiteral ("Storage");
7181 case SK_UNCONSTRAINED:
7182 result = cstring_makeLiteral ("<anything>");
7191 result = cstring_makeLiteral ("<unknown>");
7194 result = cstring_makeLiteral ("<conj>");
7206 sRef_copyState (sRef s1, sRef s2)
7208 if (sRef_isReasonable (s1) && sRef_isReasonable (s2))
7210 s1->defstate = s2->defstate;
7212 /* start modifications */
7213 s1->bufinfo.bufstate = s2->bufinfo.bufstate;
7214 s1->bufinfo.len = s2->bufinfo.len;
7215 s1->bufinfo.size = s2->bufinfo.size;
7216 /* end modifications */
7218 s1->aliaskind = s2->aliaskind;
7219 s1->aliasinfo = stateInfo_update (s1->aliasinfo, s2->aliasinfo);
7221 s1->expkind = s2->expkind;
7222 s1->expinfo = stateInfo_update (s1->expinfo, s2->expinfo);
7224 s1->nullstate = s2->nullstate;
7225 s1->nullinfo = stateInfo_update (s1->nullinfo, s2->nullinfo);
7228 /*@i834 don't free it: valueTable_free (s1->state); */
7229 /*@i32@*/ s1->state = valueTable_copy (s2->state);
7231 s1->safe = s2->safe;
7236 sRef_makeNew (ctype ct, sRef t, cstring name)
7238 sRef s = sRef_newRef ();
7243 llassert (sRef_isReasonable (t));
7244 s->defstate = t->defstate;
7246 s->aliaskind = t->aliaskind;
7247 s->oaliaskind = s->aliaskind;
7248 s->nullstate = t->nullstate;
7250 s->expkind = t->expkind;
7251 s->oexpkind = s->expkind;
7253 s->info = (sinfo) dmalloc (sizeof (*s->info));
7254 s->info->fname = name;
7256 /* start modifications */
7257 s->bufinfo.bufstate = t->bufinfo.bufstate;
7258 /* end modifications */
7260 llassert (valueTable_isUndefined (s->state));
7261 s->state = valueTable_copy (t->state);
7263 DPRINTF (("==> Copying state: %s", valueTable_unparse (s->state)));
7264 DPRINTF (("==> new: %s", sRef_unparseFull (s)));
7269 sRef_makeType (ctype ct)
7271 sRef s = sRef_newRef ();
7273 sRef_checkMutable (s);
7278 s->defstate = SS_UNKNOWN;
7279 s->aliaskind = AK_UNKNOWN;
7280 sRef_setNullStateN (s, NS_UNKNOWN);
7282 /* start modification */
7283 s->bufinfo.bufstate = BB_NOTNULLTERMINATED;
7284 /* end modification */
7287 if (ctype_isUA (ct))
7289 typeId uid = ctype_typeId (ct);
7290 uentry ue = usymtab_getTypeEntrySafe (uid);
7292 if (uentry_isValid (ue))
7294 sRef_mergeStateQuiet (s, uentry_getSref (ue));
7298 s->oaliaskind = s->aliaskind;
7299 s->oexpkind = s->expkind;
7300 llassert (valueTable_isUndefined (s->state));
7301 s->state = context_createValueTable (s, stateInfo_makeLoc (g_currentloc));
7303 DPRINTF (("Create: %s", sRef_unparseFull (s)));
7308 sRef_makeConst (ctype ct)
7310 sRef s = sRef_newRef ();
7315 s->defstate = SS_UNKNOWN;
7316 s->aliaskind = AK_UNKNOWN;
7317 sRef_setNullStateN (s, NS_UNKNOWN);
7319 /* start modification */
7320 s->bufinfo.bufstate = BB_NULLTERMINATED;
7321 /* end modification */
7323 /* evans 2002-04-22: added isManifestBool to avoid errors for -boolfalse initializations */
7324 if (!ctype_isManifestBool (ct) && ctype_isUA (ct))
7326 typeId uid = ctype_typeId (ct);
7327 uentry te = usymtab_getTypeEntrySafe (uid);
7329 if (uentry_isValid (te))
7331 sRef_mergeStateQuiet (s, uentry_getSref (te));
7335 s->oaliaskind = s->aliaskind;
7336 s->oexpkind = s->expkind;
7338 llassert (valueTable_isUndefined (s->state));
7339 s->state = context_createValueTable (s, stateInfo_makeLoc (g_currentloc));
7344 bool sRef_hasName (sRef s)
7346 if (sRef_isInvalid (s))
7355 uentry u = usymtab_getRefQuiet (s->info->cvar->lexlevel,
7356 s->info->cvar->index);
7357 return (uentry_hasName (u));
7361 if (s->info->paramno >= 0)
7363 uentry u = uentryList_getN (context_getParams (),
7366 return (uentry_hasName (u));
7370 llassert (s->info->paramno == PARAMUNKNOWN);
7380 sRef_sameName (sRef s1, sRef s2)
7382 if (sRef_isInvalid (s1))
7384 return sRef_isInvalid (s2);
7387 if (sRef_isInvalid (s2))
7395 if (s2->kind == SK_CVAR)
7397 return (s1->info->cvar->lexlevel == s2->info->cvar->lexlevel
7398 && s1->info->cvar->index == s2->info->cvar->index);
7400 else if (s2->kind == SK_PARAM)
7402 if (context_inFunctionLike ())
7404 if (s2->info->paramno != PARAMUNKNOWN)
7406 uentry u1 = usymtab_getRefQuiet (s1->info->cvar->lexlevel,
7407 s1->info->cvar->index);
7408 uentry u2 = uentryList_getN (context_getParams (),
7411 return (cstring_equalFree (uentry_getName (u1),
7412 uentry_getName (u2)));
7416 return s1->info->paramno == PARAMUNKNOWN;
7430 if (s2->kind == SK_PARAM)
7432 return (s1->info->paramno == s2->info->paramno);
7434 else if (s2->kind == SK_CVAR)
7436 if (context_inFunctionLike ())
7438 if (s1->info->paramno == PARAMUNKNOWN)
7444 uentry u1 = uentryList_getN (context_getParams (),
7446 uentry u2 = usymtab_getRefQuiet (s2->info->cvar->lexlevel,
7447 s2->info->cvar->index);
7450 return (cstring_equalFree (uentry_getName (u1),
7451 uentry_getName (u2)));
7465 case SK_UNCONSTRAINED:
7469 if (s2->kind == SK_ARRAYFETCH)
7471 if (bool_equal (s1->info->arrayfetch->indknown,
7472 s2->info->arrayfetch->indknown))
7474 if (!s1->info->arrayfetch->indknown
7475 || (s1->info->arrayfetch->ind == s2->info->arrayfetch->ind))
7477 return sRef_sameName (s1->info->arrayfetch->arr,
7478 s2->info->arrayfetch->arr);
7485 if (s2->kind == SK_FIELD)
7487 if (cstring_equal (s1->info->field->field,
7488 s2->info->field->field))
7490 return sRef_sameName (s1->info->field->rec,
7491 s2->info->field->rec);
7500 if (s2->kind == s1->kind)
7502 return sRef_sameName (s1->info->ref,
7510 return sRef_sameName (sRef_getConjA (s1), s2);
7514 return (s2->kind == SK_UNKNOWN);
7517 if (s2->kind == s1->kind)
7519 return (ctype_equal (s1->type, s2->type));
7524 if (s2->kind == SK_SPECIAL)
7526 return (s1->info->spec == s2->info->spec);
7530 return (s2->kind == SK_RESULT);
7538 sRef_fixOuterRef (/*@returned@*/ sRef s)
7540 sRef root = sRef_getRootBase (s);
7542 if (sRef_isCvar (root))
7544 uentry ue = usymtab_getRefQuiet (root->info->cvar->lexlevel,
7545 root->info->cvar->index);
7547 if (uentry_isValid (ue))
7549 sRef uref = uentry_getSref (ue);
7550 sRef sr = sRef_fixBase (s, uref);
7556 llcontbug (message ("sRef_fixOuterRef: undefined: %q", sRef_unparseDebug (s)));
7565 sRef_storeState (sRef s)
7567 if (sRef_isInvalid (s)) return;
7569 sRef_checkMutable (s);
7570 s->oaliaskind = s->aliaskind;
7571 s->oexpkind = s->expkind;
7574 static void sRef_resetStateAux (sRef s, /*@unused@*/ fileloc loc)
7576 sRef_resetState (s);
7580 sRef_resetState (sRef s)
7582 bool changed = FALSE;
7583 if (sRef_isInvalid (s)) return;
7586 if (s->oaliaskind == AK_KILLREF && !sRef_isParam (s))
7589 ** killref is used in a kludgey way, to save having to add
7590 ** another alias kind (see usymtab_handleParams)
7593 if (s->expkind != s->oexpkind)
7596 s->expkind = s->oexpkind;
7601 if (s->expkind != s->oexpkind)
7604 s->expkind = s->oexpkind;
7607 if (s->aliaskind != s->oaliaskind
7608 && s->aliaskind != AK_REFCOUNTED
7609 && s->aliaskind != AK_REFS)
7612 s->aliaskind = s->oaliaskind;
7618 sRef_clearDerived (s);
7624 sRef_resetStateComplete (sRef s)
7626 sRef_innerAliasSetComplete (sRef_resetStateAux, s, fileloc_undefined);
7630 sRef_fixBase (/*@returned@*/ sRef s, /*@returned@*/ sRef base)
7632 sRef tmp = sRef_undefined;
7635 if (sRef_isInvalid (s)) return s;
7636 if (sRef_isInvalid (base)) return base;
7646 tmp = sRef_fixBase (s->info->arrayfetch->arr, base);
7648 if (s->info->arrayfetch->indknown)
7650 ret = sRef_makeArrayFetchKnown (tmp, s->info->arrayfetch->ind);
7654 ret = sRef_makeArrayFetch (tmp);
7658 tmp = sRef_fixBase (s->info->field->rec, base);
7659 ret = sRef_buildNCField (tmp, s->info->field->field);
7662 tmp = sRef_fixBase (s->info->ref, base);
7663 ret = sRef_makePointer (tmp);
7666 tmp = sRef_fixBase (s->info->ref, base);
7667 ret = sRef_makeAddress (tmp);
7673 tmp = sRef_fixBase (s->info->conj->a, base);
7674 tmpb = sRef_fixBase (s->info->conj->b, base);
7676 ret = sRef_makeConj (tmp, tmpb);
7685 static /*@exposed@*/ sRef
7686 sRef_fixDirectBase (sRef s, sRef base)
7691 if (sRef_isInvalid (s))
7693 return sRef_undefined;
7699 if (s->info->arrayfetch->indknown)
7701 ret = sRef_makeArrayFetchKnown (base, s->info->arrayfetch->ind);
7705 ret = sRef_makeArrayFetch (base);
7709 ret = sRef_buildNCField (base, s->info->field->field);
7712 ret = sRef_makePointer (base);
7715 ret = sRef_makeAddress (base);
7721 tmpa = sRef_fixDirectBase (s->info->conj->a, base);
7722 tmpb = sRef_fixDirectBase (s->info->conj->b, base);
7724 ret = sRef_makeConj (tmpa, tmpb);
7730 sRef_copyState (ret, s);
7735 sRef_isAllocIndexRef (sRef s)
7737 return (sRef_isArrayFetch (s) && !(s->info->arrayfetch->indknown)
7738 && sRef_isAllocated (s->info->arrayfetch->arr));
7742 sRef_showRefLost (sRef s)
7744 if (sRef_hasAliasInfoLoc (s))
7746 llgenindentmsg (cstring_makeLiteral ("Original reference lost"),
7747 sRef_getAliasInfoLoc (s));
7752 sRef_showRefKilled (sRef s)
7754 if (sRef_hasStateInfoLoc (s))
7756 stateInfo_display (s->definfo, sRef_unparse (s));
7761 sRef_showStateInconsistent (sRef s)
7763 if (sRef_hasStateInfoLoc (s))
7766 (message ("Storage %qbecomes inconsistent (released on one branch)",
7767 sRef_unparseOpt (s)),
7768 sRef_getStateInfoLoc (s));
7773 sRef_showStateInfo (sRef s)
7775 if (sRef_hasStateInfoLoc (s))
7777 if (s->defstate == SS_DEAD)
7780 (message ("Storage %qis released", sRef_unparseOpt (s)),
7781 sRef_getStateInfoLoc (s));
7783 else if (s->defstate == SS_ALLOCATED || s->defstate == SS_DEFINED)
7786 (message ("Storage %qis %s", sRef_unparseOpt (s),
7787 sstate_unparse (s->defstate)),
7788 sRef_getStateInfoLoc (s));
7790 else if (s->defstate == SS_UNUSEABLE)
7793 (message ("Storage %qbecomes inconsistent (clauses merge with"
7794 "%qreleased on one branch)",
7795 sRef_unparseOpt (s),
7796 sRef_unparseOpt (s)),
7797 sRef_getStateInfoLoc (s));
7801 llgenindentmsg (message ("Storage %qbecomes %s",
7802 sRef_unparseOpt (s),
7803 sstate_unparse (s->defstate)),
7804 sRef_getStateInfoLoc (s));
7810 sRef_showExpInfo (sRef s)
7812 if (sRef_hasExpInfoLoc (s))
7814 llgenindentmsg (message ("Storage %qbecomes %s", sRef_unparseOpt (s),
7815 exkind_unparse (s->expkind)),
7816 sRef_getExpInfoLoc (s));
7821 sRef_showMetaStateInfo (sRef s, cstring key)
7824 metaStateInfo minfo = context_lookupMetaStateInfo (key);
7826 llassert (sRef_isReasonable (s));
7827 llassert (valueTable_isDefined (s->state));
7828 llassert (metaStateInfo_isDefined (minfo));
7830 val = valueTable_lookup (s->state, key);
7832 if (stateValue_hasLoc (val))
7835 (message ("%qbecomes %q", sRef_unparseOpt (s),
7836 stateValue_unparseValue (val, minfo)),
7837 stateValue_getLoc (val));
7842 sRef_showNullInfo (sRef s)
7844 DPRINTF (("Show null info: %s", sRef_unparseFull (s)));
7846 if (sRef_hasNullInfoLoc (s) && sRef_isKnown (s))
7848 DPRINTF (("has null info: %s",
7849 fileloc_unparse (sRef_getNullInfoLoc (s))));
7851 switch (sRef_getNullState (s))
7855 fileloc loc = sRef_getNullInfoLoc (s);
7857 if (fileloc_isDefined (loc) && !fileloc_isLib (loc))
7860 (message ("Storage %qbecomes null", sRef_unparseOpt (s)),
7867 fileloc loc = sRef_getNullInfoLoc (s);
7869 if (fileloc_isDefined (loc) && !fileloc_isLib (loc))
7871 llgenindentmsg (message ("Storage %qbecomes null", sRef_unparseOpt (s)),
7879 (message ("Storage %qmay become null", sRef_unparseOpt (s)),
7880 sRef_getNullInfoLoc (s));
7885 (message ("Storage %qbecomes not null", sRef_unparseOpt (s)),
7886 sRef_getNullInfoLoc (s));
7890 (message ("Storage %qnull state becomes unknown",
7891 sRef_unparseOpt (s)),
7892 sRef_getNullInfoLoc (s));
7901 (message ("<error case> Storage %q becomes %s",
7903 nstate_unparse (sRef_getNullState (s))),
7904 sRef_getNullInfoLoc (s));
7912 sRef_showAliasInfo (sRef s)
7914 if (sRef_hasAliasInfoLoc (s))
7916 if (sRef_isFresh (s))
7919 (message ("Fresh storage %qallocated", sRef_unparseOpt (s)),
7920 sRef_getAliasInfoLoc (s));
7924 if (!sRef_isRefCounted (s))
7927 (message ("Storage %qbecomes %s",
7928 sRef_unparseOpt (s),
7929 alkind_unparse (sRef_getAliasKind (s))),
7930 sRef_getAliasInfoLoc (s));
7937 sRef_mergeNullState (sRef s, nstate n)
7939 if (sRef_isReasonable (s))
7943 old = sRef_getNullState (s);
7945 if (n != old && n != NS_UNKNOWN)
7947 sRef_setNullState (s, n, g_currentloc);
7952 llbuglit ("sRef_mergeNullState: invalid");
7957 sRef_possiblyNull (sRef s)
7959 if (sRef_isReasonable (s))
7961 if (sRef_getNullState (s) == NS_ABSNULL)
7963 ctype rct = ctype_realType (s->type);
7965 if (ctype_isAbstract (rct))
7971 if (ctype_isUser (rct))
7973 uentry ue = usymtab_getTypeEntry (ctype_typeId (rct));
7975 return (nstate_possiblyNull
7976 (sRef_getNullState (uentry_getSref (ue))));
7986 return nstate_possiblyNull (sRef_getNullState (s));
7994 sRef_getScopeName (sRef s)
7996 sRef base = sRef_getRootBase (s);
7998 if (sRef_isRealGlobal (base))
8000 return (cstring_makeLiteralTemp ("Global"));
8002 else if (sRef_isFileStatic (base))
8004 return (cstring_makeLiteralTemp ("Static"));
8008 return (cstring_makeLiteralTemp ("Local"));
8013 sRef_unparseScope (sRef s)
8015 sRef base = sRef_getRootBase (s);
8017 if (sRef_isRealGlobal (base))
8019 return (cstring_makeLiteralTemp ("global"));
8021 else if (sRef_isFileStatic (base))
8023 return (cstring_makeLiteralTemp ("file static"));
8032 sRef_getScope (sRef s)
8034 llassert (sRef_isReasonable (s));
8036 if (sRef_isCvar (s))
8038 return s->info->cvar->lexlevel;
8040 else if (sRef_isParam (s))
8051 sRef_isDead (sRef s)
8053 return (sRef_isReasonable (s) && (s)->defstate == SS_DEAD);
8057 sRef_isDeadStorage (sRef s)
8059 if (sRef_isReasonable (s))
8061 if (s->defstate == SS_DEAD
8062 || s->defstate == SS_UNUSEABLE
8063 || s->defstate == SS_UNDEFINED
8064 || s->defstate == SS_UNKNOWN)
8070 return (sRef_isDefinitelyNull (s));
8080 sRef_isPossiblyDead (sRef s)
8082 return (sRef_isReasonable (s) && s->defstate == SS_HOFFA);
8085 bool sRef_isStateLive (sRef s)
8087 if (sRef_isReasonable (s))
8089 sstate ds = s->defstate;
8091 return (!(ds == SS_UNDEFINED
8093 || ds == SS_UNUSEABLE
8094 || ds == SS_HOFFA));
8103 bool sRef_isStateUndefined (sRef s)
8105 return ((sRef_isReasonable(s)) && ((s)->defstate == SS_UNDEFINED));
8108 bool sRef_isJustAllocated (sRef s)
8110 if (sRef_isAllocated (s))
8112 sRefSet_allElements (s->deriv, el)
8114 if (!(sRef_isStateUndefined (el) || sRef_isUnuseable (el)))
8118 } end_sRefSet_allElements ;
8127 sRef_isAllocatedStorage (sRef s)
8129 if (sRef_isReasonable (s) && ynm_toBoolStrict (sRef_isValidLvalue (s)))
8131 return (ctype_isVisiblySharable (sRef_getType (s)));
8140 sRef_isUnuseable (sRef s)
8142 return ((sRef_isValid(s)) && ((s)->defstate == SS_UNUSEABLE));
8146 sRef_perhapsNull (sRef s)
8148 if (sRef_isReasonable (s))
8150 if (sRef_getNullState (s) == NS_ABSNULL)
8152 ctype rct = ctype_realType (s->type);
8154 if (ctype_isAbstract (rct))
8160 if (ctype_isUser (rct))
8162 uentry ue = usymtab_getTypeEntry (ctype_typeId (rct));
8164 return (nstate_perhapsNull
8165 (sRef_getNullState (uentry_getSref (ue))));
8175 return nstate_perhapsNull (sRef_getNullState (s));
8183 ** definitelyNull --- called when TRUE is good
8187 sRef_definitelyNull (sRef s)
8189 return (sRef_isReasonable (s)
8190 && (sRef_getNullState (s) == NS_DEFNULL || sRef_getNullState (s) == NS_CONSTNULL));
8194 ** based on sRef_similar
8198 sRef_setDerivNullState (sRef set, sRef guide, nstate ns)
8200 if (sRef_isReasonable (set))
8202 sRef deriv = sRef_getDeriv (set, guide);
8204 if (sRef_isReasonable (deriv))
8206 sRef_setNullStateN (deriv, ns);
8211 static /*@exposed@*/ sRef
8212 sRef_getDeriv (/*@returned@*/ /*@notnull@*/ sRef set, sRef guide)
8214 llassert (sRef_isReasonable (set));
8215 llassert (sRef_isReasonable (guide));
8217 switch (guide->kind)
8220 llassert (set->kind == SK_CVAR);
8224 llassert (set->kind == guide->kind);
8225 llassert (set->info->paramno == guide->info->paramno);
8230 if (set->kind == SK_ARRAYFETCH
8231 && (sRef_similar (set->info->arrayfetch->arr,
8232 guide->info->arrayfetch->arr)))
8238 return (sRef_makeAnyArrayFetch
8239 (sRef_getDeriv (set, guide->info->arrayfetch->arr)));
8244 if (set->kind == SK_PTR && sRef_similar (set->info->ref, guide->info->ref))
8250 return (sRef_makePointer (sRef_getDeriv (set, guide->info->ref)));
8255 if ((set->kind == SK_FIELD &&
8256 (sRef_similar (set->info->field->rec, guide->info->field->rec) &&
8257 cstring_equal (set->info->field->field, guide->info->field->field))))
8263 return (sRef_makeField (sRef_getDeriv (set, guide->info->field->rec),
8264 guide->info->field->field));
8268 if ((set->kind == SK_ADR) && sRef_similar (set->info->ref, guide->info->ref))
8274 return (sRef_makeAddress (sRef_getDeriv (set, guide->info->ref)));
8279 return sRef_undefined;
8283 case SK_UNCONSTRAINED:
8291 return sRef_undefined;
8298 ** sRef_aliasCheckPred
8300 ** A confusing but spiffy function:
8302 ** Calls predf (s, e, text, <alias>) on s and all of s's aliases
8303 ** (unless checkAliases (s) is FALSE).
8305 ** For alias calls, calls as
8306 ** predf (alias, e, text, s)
8310 sRef_aliasCheckPred (bool (predf) (sRef, exprNode, sRef, exprNode),
8311 /*@null@*/ bool (checkAliases) (sRef),
8312 sRef s, exprNode e, exprNode err)
8314 bool error = (*predf)(s, e, sRef_undefined, err);
8317 if (checkAliases != NULL && !(checkAliases (s)))
8319 /* don't check aliases */
8323 sRefSet aliases = usymtab_allAliases (s);
8325 sRefSet_realElements (aliases, current)
8327 if (sRef_isReasonable (current))
8329 if (sRef_isReasonable (current))
8331 if (!sRef_similar (current, s)
8332 || (error && sRef_sameName (current, s)))
8334 (void) (*predf)(current, e, s, err);
8339 llcontbug (message ("Invalid sRef as alias field of %s", sRef_unparse (s)));
8342 } end_sRefSet_realElements;
8344 sRefSet_free (aliases);
8349 ** return TRUE iff predf (s) is true for s or any alias of s
8353 sRef_aliasCheckSimplePred (sRefTest predf, sRef s)
8364 aliases = usymtab_allAliases (s);
8366 sRefSet_realElements (aliases, current)
8368 if (sRef_isReasonable (current))
8370 sRef cref = sRef_updateSref (current);
8372 /* Whoa! a very kludgey way to make sure the right sref is used
8373 ** where there is a conditional symbol table. I am beginning
8374 ** to think that having a conditional symbol table wasn't such
8380 DPRINTF (("Checking alias: %s", sRef_unparseFull (cref)));
8381 sRefSet_free (aliases);
8385 } end_sRefSet_realElements;
8387 sRefSet_free (aliases);
8393 sRef_aliasCompleteSimplePred (bool (predf) (sRef), sRef s)
8396 bool result = FALSE;
8399 aliases = usymtab_allAliases (s);
8401 if ((*predf)(s)) result = TRUE;
8404 sRefSet_realElements (aliases, current)
8406 if (sRef_isReasonable (current))
8408 current = sRef_updateSref (current);
8409 if ((*predf)(current)) result = TRUE;
8411 } end_sRefSet_realElements;
8413 sRefSet_free (aliases);
8418 sRef_aliasSetComplete (void (predf) (sRef, fileloc), sRef s, fileloc loc)
8422 aliases = usymtab_allAliases (s);
8424 DPRINTF (("All aliases: %s", sRefSet_unparseFull (aliases)));
8428 sRefSet_realElements (aliases, current)
8430 if (sRef_isReasonable (current))
8432 current = sRef_updateSref (current);
8433 ((*predf)(current, loc));
8434 DPRINTF (("Killed: %s", sRef_unparseFull (current)));
8436 } end_sRefSet_realElements;
8438 sRefSet_free (aliases);
8442 sRef_aliasSetCompleteParam (void (predf) (sRef, int, fileloc), sRef s,
8443 int kind, fileloc loc)
8447 if (sRef_isDeep (s))
8449 aliases = usymtab_allAliases (s);
8453 aliases = usymtab_aliasedBy (s);
8456 (*predf)(s, kind, loc);
8458 sRefSet_realElements (aliases, current)
8460 if (sRef_isReasonable (current))
8462 current = sRef_updateSref (current);
8463 ((*predf)(current, kind, loc));
8465 } end_sRefSet_realElements;
8467 sRefSet_free (aliases);
8471 ** Version of aliasSetCompleteParam for alkind parameters
8475 sRef_aliasSetCompleteAlkParam (void (predf) (sRef, alkind, fileloc), sRef s,
8476 alkind kind, fileloc loc)
8480 if (sRef_isDeep (s))
8482 aliases = usymtab_allAliases (s);
8486 aliases = usymtab_aliasedBy (s);
8489 (*predf)(s, kind, loc);
8491 sRefSet_realElements (aliases, current)
8493 if (sRef_isReasonable (current))
8495 current = sRef_updateSref (current);
8496 ((*predf)(current, kind, loc));
8498 } end_sRefSet_realElements;
8500 sRefSet_free (aliases);
8504 sRef_innerAliasSetComplete (void (predf) (sRef, fileloc), sRef s, fileloc loc)
8510 if (!sRef_isReasonable (s)) return;
8513 ** Type equivalence checking is necessary --- there might be casting.
8520 case SK_UNCONSTRAINED:
8525 inner = s->info->ref;
8526 aliases = usymtab_allAliases (inner);
8527 ct = sRef_getType (inner);
8529 sRefSet_realElements (aliases, current)
8531 if (sRef_isReasonable (current))
8533 current = sRef_updateSref (current);
8535 if (ctype_equal (ct, sRef_getType (current)))
8537 sRef ptr = sRef_makePointer (current);
8538 ((*predf)(ptr, loc));
8541 } end_sRefSet_realElements;
8543 sRefSet_free (aliases);
8546 inner = s->info->arrayfetch->arr;
8547 aliases = usymtab_allAliases (inner);
8548 ct = sRef_getType (inner);
8550 DPRINTF (("Array fetch: %s", sRefSet_unparse (aliases)));
8552 sRefSet_realElements (aliases, current)
8554 if (sRef_isReasonable (current))
8556 current = sRef_updateSref (current);
8557 DPRINTF (("Current: %s", sRef_unparseFull (current)));
8559 if (ctype_equal (ct, sRef_getType (current)))
8561 if (s->info->arrayfetch->indknown)
8563 sRef af = sRef_makeArrayFetchKnown (current, s->info->arrayfetch->ind);
8564 DPRINTF (("Defining: %s", sRef_unparseFull (af)));
8565 /* evans 2001-08-27 This isn't true:
8566 llassert (af->info->arrayfetch->arr == current);
8567 see comments in buildArrayFetchKnown
8569 ((*predf)(af, loc));
8573 sRef af = sRef_makeArrayFetch (current);
8574 /* evans 2001-08-27 This isn't true:
8575 llassert (af->info->arrayfetch->arr == current);
8576 see comments in buildArrayFetch
8578 DPRINTF (("Defining: %s", sRef_unparseFull (af)));
8579 ((*predf)(af, loc));
8584 DPRINTF (("Type mismatch: %s / %s",
8586 ctype_unparse (sRef_getType (current))));
8589 } end_sRefSet_realElements;
8591 sRefSet_free (aliases);
8594 inner = s->info->field->rec;
8595 aliases = usymtab_allAliases (inner);
8596 ct = sRef_getType (inner);
8598 sRefSet_realElements (aliases, current)
8600 if (sRef_isReasonable (current))
8602 current = sRef_updateSref (current);
8604 if (ctype_equal (ct, sRef_getType (current)))
8606 sRef f = sRef_makeField (current, s->info->field->field);
8611 } end_sRefSet_realElements;
8613 sRefSet_free (aliases);
8616 sRef_innerAliasSetComplete (predf, s->info->conj->a, loc);
8617 sRef_innerAliasSetComplete (predf, s->info->conj->b, loc);
8634 sRef_innerAliasSetCompleteParam (void (predf) (sRef, sRef), sRef s, sRef t)
8640 if (!sRef_isReasonable (s)) return;
8643 ** Type equivalence checking is necessary --- there might be casting.
8650 case SK_UNCONSTRAINED:
8655 inner = s->info->ref;
8656 aliases = usymtab_allAliases (inner);
8657 ct = sRef_getType (inner);
8659 sRefSet_realElements (aliases, current)
8661 if (sRef_isReasonable (current))
8663 current = sRef_updateSref (current);
8665 if (ctype_equal (ct, sRef_getType (current)))
8667 sRef ptr = sRef_makePointer (current);
8672 } end_sRefSet_realElements;
8674 sRefSet_free (aliases);
8677 inner = s->info->arrayfetch->arr;
8678 aliases = usymtab_allAliases (inner);
8679 ct = sRef_getType (inner);
8681 sRefSet_realElements (aliases, current)
8683 if (sRef_isReasonable (current))
8685 current = sRef_updateSref (current);
8687 if (ctype_equal (ct, sRef_getType (current)))
8690 if (s->info->arrayfetch->indknown)
8692 sRef af = sRef_makeArrayFetchKnown (current, s->info->arrayfetch->ind);
8698 sRef af = sRef_makeArrayFetch (current);
8704 } end_sRefSet_realElements;
8706 sRefSet_free (aliases);
8709 inner = s->info->field->rec;
8710 aliases = usymtab_allAliases (inner);
8711 ct = sRef_getType (inner);
8714 sRefSet_realElements (aliases, current)
8716 if (sRef_isReasonable (current))
8718 current = sRef_updateSref (current);
8720 if (ctype_equal (ct, sRef_getType (current)))
8722 sRef f = sRef_makeField (current, s->info->field->field);
8727 } end_sRefSet_realElements;
8729 sRefSet_free (aliases);
8732 sRef_innerAliasSetCompleteParam (predf, s->info->conj->a, t);
8733 sRef_innerAliasSetCompleteParam (predf, s->info->conj->b, t);
8749 static void sRef_combineExKinds (/*@notnull@*/ sRef res, /*@notnull@*/ sRef other)
8751 exkind a1 = sRef_getExKind (res);
8752 exkind a2 = sRef_getExKind (other);
8754 if (a1 == a2 || a2 == XO_UNKNOWN)
8758 else if (a1 == XO_UNKNOWN)
8760 res->expinfo = stateInfo_update (res->expinfo, other->expinfo);
8765 res->expkind = XO_OBSERVER;
8770 ** Currently, this is a very ad hoc implementation, with lots of fixes to
8771 ** make real code work okay. I need to come up with some more general
8772 ** rules or principles here.
8776 sRef_combineAliasKindsError (/*@notnull@*/ sRef res,
8777 /*@notnull@*/ sRef other,
8778 clause cl, fileloc loc)
8780 bool hasError = FALSE;
8781 alkind ares = sRef_getAliasKind (res);
8782 alkind aother = sRef_getAliasKind (other);
8784 sRef_checkMutable (res);
8786 if (alkind_isDependent (ares))
8788 if (aother == AK_KEPT)
8790 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8791 res->aliaskind = AK_KEPT;
8795 if (aother == AK_LOCAL || aother == AK_STATIC
8796 || alkind_isTemp (aother))
8798 DPRINTF (("Setting dependent: %s", sRef_unparseFull (res)));
8799 res->aliaskind = AK_DEPENDENT;
8803 else if (alkind_isDependent (aother))
8805 if (ares == AK_KEPT)
8807 res->aliaskind = AK_KEPT;
8811 if (ares == AK_LOCAL || ares == AK_STATIC || alkind_isTemp (ares))
8813 DPRINTF (("Setting dependent: %s", sRef_unparseFull (res)));
8814 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8815 res->aliaskind = AK_DEPENDENT;
8819 else if ((ares == AK_LOCAL || ares == AK_UNIQUE
8820 || ares == AK_STATIC || alkind_isTemp (ares))
8821 && sRef_isFresh (other))
8824 ** cases like: if (s == NULL) s = malloc...;
8825 ** don't generate errors
8828 if (usymtab_isAltDefinitelyNullDeep (res))
8830 res->aliaskind = ares;
8837 else if ((aother == AK_LOCAL || aother == AK_UNIQUE
8838 || aother == AK_STATIC || alkind_isTemp (aother))
8839 && sRef_isFresh (res))
8842 ** cases like: if (s == NULL) s = malloc...;
8843 ** don't generate errors
8846 if (usymtab_isDefinitelyNullDeep (other))
8848 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8849 res->aliaskind = aother;
8856 else if (ares == AK_NEWREF && aother == AK_REFCOUNTED
8857 && sRef_isConst (other))
8859 res->aliaskind = AK_NEWREF;
8861 else if (aother == AK_NEWREF && ares == AK_REFCOUNTED
8862 && sRef_isConst (res))
8864 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8865 res->aliaskind = AK_NEWREF;
8867 else if (sRef_isLocalVar (res)
8868 && ((ares == AK_KEPT && aother == AK_LOCAL)
8869 || (aother == AK_KEPT && ares == AK_LOCAL)))
8871 res->aliaskind = AK_KEPT;
8873 else if ((ares == AK_OWNED && aother == AK_ONLY)
8874 || (aother == AK_OWNED && ares == AK_ONLY))
8876 res->aliaskind = AK_OWNED;
8878 if (aother == AK_OWNED)
8880 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8890 if (sRef_isThroughArrayFetch (res))
8893 (FLG_BRANCHSTATE, FLG_STRICTBRANCHSTATE,
8895 ("Clauses exit with %q possibly referencing %s storage %s, "
8898 alkind_unparse (aother),
8899 clause_nameTaken (cl),
8900 alkind_unparse (ares),
8901 clause_nameAlternate (cl)),
8904 sRef_showAliasInfo (res);
8905 sRef_showAliasInfo (other);
8906 res->aliaskind = AK_ERROR;
8910 if (ares == AK_KEPT || aother == AK_KEPT)
8912 sRef_maybeKill (res, loc);
8920 message ("Clauses exit with %q referencing %s storage %s, "
8923 alkind_unparse (aother),
8924 clause_nameTaken (cl),
8925 alkind_unparse (ares),
8926 clause_nameAlternate (cl)),
8929 sRef_showAliasInfo (res);
8930 sRef_showAliasInfo (other);
8932 res->aliaskind = AK_ERROR;
8936 res->aliaskind = (sRef_isLocalVar (res) ? AK_LOCAL : AK_UNKNOWN);
8941 sRef_combineAliasKinds (/*@notnull@*/ sRef res, /*@notnull@*/ sRef other,
8942 clause cl, fileloc loc)
8944 alkind ares = sRef_getAliasKind (res);
8945 alkind aother = sRef_getAliasKind (other);
8947 sRef_checkMutable (res);
8949 DPRINTF (("Combine alias kinds: \n\t%s / \n\t%s",
8950 sRef_unparseFull (res), sRef_unparseFull (other)));
8951 if (alkind_equal (ares, aother)
8952 || aother == AK_UNKNOWN
8953 || aother == AK_ERROR)
8955 ; /* keep current state */
8957 else if (sRef_isDead (res) || sRef_isDead (other))
8959 /* dead error reported (or storage is dead) */
8960 res ->aliaskind = AK_ERROR;
8962 else if (ares == AK_UNKNOWN || ares == AK_ERROR
8963 || sRef_isStateUndefined (res)
8964 || sRef_isDefinitelyNull (res))
8966 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8967 res->aliaskind = aother;
8969 else if (sRef_isStateUndefined (other)
8970 || sRef_isDefinitelyNull (other))
8974 else if (((ares == AK_UNIQUE || alkind_isTemp (ares))
8975 && aother == AK_LOCAL)
8976 || ((aother == AK_UNIQUE || alkind_isTemp (aother))
8977 && ares == AK_LOCAL))
8979 if (ares != AK_LOCAL)
8981 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8984 res->aliaskind = AK_LOCAL;
8986 else if ((ares == AK_OWNED && aother == AK_FRESH)
8987 || (aother == AK_OWNED && ares == AK_FRESH))
8989 if (ares != AK_FRESH)
8991 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8994 res->aliaskind = AK_FRESH;
8996 else if ((ares == AK_KEEP && aother == AK_FRESH) ||
8997 (aother == AK_KEEP && ares == AK_FRESH))
8999 if (ares != AK_KEEP)
9001 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
9004 res->aliaskind = AK_KEEP;
9006 else if ((ares == AK_LOCAL && aother == AK_STACK) ||
9007 (aother == AK_LOCAL && ares == AK_STACK))
9009 if (ares != AK_STACK)
9011 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
9014 res->aliaskind = AK_STACK;
9016 else if ((ares == AK_LOCAL
9017 && (aother == AK_OWNED && sRef_isLocalVar (other)))
9018 || (aother == AK_LOCAL
9019 && (ares == AK_OWNED && sRef_isLocalVar (res))))
9021 if (ares != AK_LOCAL)
9023 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
9026 res->aliaskind = AK_LOCAL;
9028 else if ((ares == AK_FRESH && alkind_isOnly (aother))
9029 || (aother == AK_FRESH && alkind_isOnly (ares)))
9031 res->aliaskind = AK_FRESH;
9033 else if ((aother == AK_FRESH && sRef_definitelyNull (res))
9034 || (ares == AK_FRESH && sRef_definitelyNull (other)))
9036 if (ares != AK_FRESH)
9038 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
9039 res->aliaskind = AK_FRESH;
9042 else if ((sRef_isFresh (res) && sRef_isConst (other))
9043 || (sRef_isFresh (other) && sRef_isConst (res)))
9046 ** for NULL constantants
9050 if (!sRef_isFresh (res))
9052 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
9055 res->aliaskind = AK_FRESH;
9057 else if ((alkind_isStatic (aother) && sRef_isConst (res))
9058 || (alkind_isStatic (ares) && sRef_isConst (other)))
9060 if (!alkind_isStatic (ares))
9062 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
9063 res->aliaskind = AK_STATIC;
9068 sRef_combineAliasKindsError (res, other, cl, loc);
9072 static void sRef_combineDefState (/*@notnull@*/ sRef res,
9073 /*@notnull@*/ sRef other)
9075 sstate s1 = res->defstate;
9076 sstate s2 = other->defstate;
9079 sRef_checkMutable (res);
9081 if (s1 == s2 || s2 == SS_UNKNOWN)
9085 else if (s1 == SS_UNKNOWN)
9094 if (s2 == SS_DEFINED)
9100 llcontbuglit ("ssfixed: not implemented");
9109 flip = (s2 != SS_DEFINED);
9127 res->definfo = stateInfo_update (res->definfo, other->definfo);
9132 extern /*@notnull@*/ sRef sRef_getConjA (sRef s)
9135 llassert (sRef_isConj (s));
9137 ret = s->info->conj->a;
9138 llassert (ret != NULL);
9142 extern /*@notnull@*/ sRef sRef_getConjB (sRef s)
9145 llassert (sRef_isConj (s));
9147 ret = s->info->conj->b;
9148 llassert (ret != NULL);
9152 extern /*@exposed@*/ sRef sRef_makeArrow (sRef s, /*@dependent@*/ cstring f)
9157 p = sRef_makePointer (s);
9158 ret = sRef_makeField (p, f);
9159 DPRINTF (("Arrow: %s => %s",
9160 sRef_unparseFull (s), sRef_unparseFull (ret)));
9164 extern /*@exposed@*/ sRef sRef_buildArrow (sRef s, cstring f)
9169 p = sRef_buildPointer (s);
9170 ret = sRef_buildField (p, f);
9175 static /*@null@*/ sinfo sinfo_copy (/*@notnull@*/ sRef s)
9182 ret = (sinfo) dmalloc (sizeof (*ret));
9183 ret->cvar = (cref) dmalloc (sizeof (*ret->cvar));
9184 ret->cvar->lexlevel = s->info->cvar->lexlevel;
9185 ret->cvar->index = s->info->cvar->index;
9189 ret = (sinfo) dmalloc (sizeof (*ret));
9190 ret->paramno = s->info->paramno;
9191 llassert (ret->paramno >= -1);
9195 ret = (sinfo) dmalloc (sizeof (*ret));
9196 ret->arrayfetch = (ainfo) dmalloc (sizeof (*ret->arrayfetch));
9197 ret->arrayfetch->indknown = s->info->arrayfetch->indknown;
9198 ret->arrayfetch->ind = s->info->arrayfetch->ind;
9199 ret->arrayfetch->arr = s->info->arrayfetch->arr; /* sRef_copy (s->info->arrayfetch->arr); */ /*@i32@*/
9203 ret = (sinfo) dmalloc (sizeof (*ret));
9204 ret->field = (fldinfo) dmalloc (sizeof (*ret->field));
9205 ret->field->rec = s->info->field->rec; /* sRef_copy (s->info->field->rec); */ /*@i32@*/
9206 ret->field->field = s->info->field->field;
9210 ret = (sinfo) dmalloc (sizeof (*ret));
9211 ret->object = s->info->object;
9218 ret = (sinfo) dmalloc (sizeof (*ret));
9219 ret->ref = s->info->ref; /* Ref_copy (s->info->ref); */
9223 ret = (sinfo) dmalloc (sizeof (*ret));
9224 ret->conj = (cjinfo) dmalloc (sizeof (*ret->conj));
9225 ret->conj->a = s->info->conj->a; /* sRef_copy (s->info->conj->a); */
9226 ret->conj->b = s->info->conj->b; /* sRef_copy (s->info->conj->b);*/
9229 ret = (sinfo) dmalloc (sizeof (*ret));
9230 ret->spec = s->info->spec;
9233 case SK_UNCONSTRAINED:
9235 ret = (sinfo) dmalloc (sizeof (*ret));
9236 ret->fname = s->info->fname;
9243 llassertprint (s->info == NULL, ("s = %s", sRef_unparse (s)));
9251 static /*@null@*/ sinfo sinfo_fullCopy (/*@notnull@*/ sRef s)
9256 ** Since its a full copy, only storage is assigned
9257 ** to dependent fields.
9264 ret = (sinfo) dmalloc (sizeof (*ret));
9265 ret->cvar = (cref) dmalloc (sizeof (*ret->cvar));
9266 ret->cvar->lexlevel = s->info->cvar->lexlevel;
9267 ret->cvar->index = s->info->cvar->index;
9271 ret = (sinfo) dmalloc (sizeof (*ret));
9272 ret->paramno = s->info->paramno;
9273 llassert (ret->paramno >= -1);
9277 ret = (sinfo) dmalloc (sizeof (*ret));
9278 ret->arrayfetch = (ainfo) dmalloc (sizeof (*ret->arrayfetch));
9279 ret->arrayfetch->indknown = s->info->arrayfetch->indknown;
9280 ret->arrayfetch->ind = s->info->arrayfetch->ind;
9281 ret->arrayfetch->arr = sRef_saveCopy (s->info->arrayfetch->arr);
9285 ret = (sinfo) dmalloc (sizeof (*ret));
9286 ret->field = (fldinfo) dmalloc (sizeof (*ret->field));
9287 ret->field->rec = sRef_saveCopy (s->info->field->rec);
9288 ret->field->field = s->info->field->field;
9292 ret = (sinfo) dmalloc (sizeof (*ret));
9293 ret->object = s->info->object;
9300 ret = (sinfo) dmalloc (sizeof (*ret));
9301 ret->ref = sRef_saveCopy (s->info->ref);
9305 ret = (sinfo) dmalloc (sizeof (*ret));
9306 ret->conj = (cjinfo) dmalloc (sizeof (*ret->conj));
9307 ret->conj->a = sRef_saveCopy (s->info->conj->a);
9308 ret->conj->b = sRef_saveCopy (s->info->conj->b);
9311 ret = (sinfo) dmalloc (sizeof (*ret));
9312 ret->spec = s->info->spec;
9315 case SK_UNCONSTRAINED:
9316 ret = (sinfo) dmalloc (sizeof (*ret));
9317 ret->fname = s->info->fname;
9323 llassert (s->info == NULL);
9333 sinfo_update (/*@notnull@*/ /*@exposed@*/ sRef res,
9334 /*@notnull@*/ /*@exposed@*/ sRef other)
9336 llassert (res->kind == other->kind);
9341 res->info->cvar->lexlevel = other->info->cvar->lexlevel;
9342 res->info->cvar->index = other->info->cvar->index;
9346 res->info->paramno = other->info->paramno;
9347 llassert (res->info->paramno >= -1);
9351 res->info->arrayfetch->indknown = other->info->arrayfetch->indknown;
9352 res->info->arrayfetch->ind = other->info->arrayfetch->ind;
9353 res->info->arrayfetch->arr = other->info->arrayfetch->arr;
9357 res->info->field->rec = other->info->field->rec;
9358 res->info->field->field = other->info->field->field;
9362 res->info->object = other->info->object;
9369 res->info->ref = other->info->ref;
9373 res->info->conj->a = other->info->conj->a;
9374 res->info->conj->b = other->info->conj->b;
9378 res->info->spec = other->info->spec;
9382 case SK_UNCONSTRAINED:
9383 res->info->fname = other->info->fname;
9390 llassert (res->info == NULL);
9395 static void sinfo_free (/*@special@*/ /*@temp@*/ /*@notnull@*/ sRef s)
9396 /*@uses s->kind, s->info@*/
9397 /*@releases s->info@*/
9402 DPRINTF (("Free sinfo: [%p]", s->info->cvar));
9403 sfree (s->info->cvar);
9410 DPRINTF (("Free sinfo: [%p]", s->info->arrayfetch));
9411 sfree (s->info->arrayfetch);
9415 DPRINTF (("Free sinfo: [%p]", s->info->field));
9416 sfree (s->info->field);
9425 case SK_EXTERNAL: /*@i32 is copy now! */
9429 DPRINTF (("Free sinfo: [%p]", s->info->conj));
9430 sfree (s->info->conj);
9433 case SK_UNCONSTRAINED:
9443 if (s->info != NULL) {
9444 DPRINTF (("Free sinfo: [%p]", s->info));
9450 bool sRef_isNSLocalVar (sRef s)
9452 if (sRef_isLocalVar (s))
9454 uentry ue = sRef_getUentry (s);
9456 return (!uentry_isStatic (ue));
9464 bool sRef_isLocalVar (sRef s)
9466 if (sRef_isValid(s))
9468 return (s->kind == SK_CVAR
9469 && (s->info->cvar->lexlevel > fileScope));
9475 bool sRef_isRealLocalVar (sRef s)
9477 if (sRef_isValid(s))
9479 if (s->kind == SK_CVAR)
9481 if (s->info->cvar->lexlevel == functionScope)
9483 uentry ue = sRef_getUentry (s);
9485 if (uentry_isAnyParam (ue)
9486 || uentry_isRefParam (ue))
9497 return (s->info->cvar->lexlevel > functionScope);
9505 bool sRef_isLocalParamVar (sRef s)
9507 if (sRef_isValid(s))
9509 return (s->kind == SK_PARAM
9510 || (s->kind == SK_CVAR
9511 && (s->info->cvar->lexlevel > fileScope)));
9517 static speckind speckind_fromInt (int i)
9520 llassert (i >= SR_NOTHING && i <= SR_SYSTEM);
9523 return ((speckind) i);
9527 static void sRef_updateNullState (/*@notnull@*/ sRef res, /*@notnull@*/ sRef other)
9530 res->nullstate = other->nullstate;
9531 res->nullinfo = stateInfo_update (res->nullinfo, other->nullinfo);
9532 sRef_resetAliasKind (res);
9535 void sRef_combineNullState (/*@notnull@*/ sRef res, /*@notnull@*/ sRef other)
9537 nstate n1 = sRef_getNullState (res);
9538 nstate n2 = sRef_getNullState (other);
9542 if (n1 == n2 || n2 == NS_UNKNOWN)
9548 /* note: n2 is not unknown or defnull */
9552 case NS_ERROR: nn = NS_ERROR; break;
9553 case NS_UNKNOWN: flip = TRUE; nn = n2; break;
9554 case NS_POSNULL: break;
9555 case NS_DEFNULL: nn = NS_POSNULL; break;
9556 case NS_RELNULL: break;
9558 if (n2 == NS_MNOTNULL)
9569 if (n2 == NS_NOTNULL)
9588 res->nullinfo = stateInfo_update (res->nullinfo, other->nullinfo);
9591 res->nullstate = nn;
9592 sRef_resetAliasKind (res);
9595 cstring sRef_nullMessage (sRef s)
9597 llassert (sRef_isReasonable (s));
9599 switch (sRef_getNullState (s))
9603 return (cstring_makeLiteralTemp ("null"));
9605 return (cstring_makeLiteralTemp ("possibly null"));
9610 /*@observer@*/ cstring sRef_ntMessage (sRef s)
9612 llassert (sRef_isReasonable (s));
9614 switch (s->nullstate)
9618 return (cstring_makeLiteralTemp ("not nullterminated"));
9620 return (cstring_makeLiteralTemp ("possibly non-nullterminated"));
9627 sRef sRef_fixResultType (/*@returned@*/ sRef s, ctype typ, uentry ue)
9629 sRef tmp = sRef_undefined;
9632 llassert (sRef_isReasonable (s));
9643 tmp = sRef_fixResultType (s->info->arrayfetch->arr, typ, ue);
9645 ct = ctype_realType (sRef_getType (tmp));
9648 if (ctype_isKnown (ct))
9650 if (ctype_isAP (ct))
9659 ("Special clause indexes non-array (%t): *%q",
9660 ct, sRef_unparse (s->info->arrayfetch->arr)),
9661 uentry_whereLast (ue));
9665 tmp = sRef_fixResultType (s->info->arrayfetch->arr, typ, ue);
9667 if (s->info->arrayfetch->indknown)
9669 ret = sRef_makeArrayFetchKnown (tmp, s->info->arrayfetch->ind);
9673 ret = sRef_makeArrayFetch (tmp);
9679 sRef rec = sRef_fixResultType (s->info->field->rec, typ, ue);
9680 ctype ct = ctype_realType (sRef_getType (rec));
9682 if (ctype_isKnown (ct))
9684 if (ctype_isSU (ct))
9686 if (uentry_isValid (uentryList_lookupField (ctype_getFields (ct),
9687 s->info->field->field)))
9696 ("Special clause accesses non-existent field of result: %q.%s",
9697 sRef_unparse (rec), s->info->field->field),
9698 uentry_whereLast (ue));
9706 ("Special clause accesses field of non-struct or union result (%t): %q.%s",
9707 ct, sRef_unparse (rec), s->info->field->field),
9708 uentry_whereLast (ue));
9712 ret = sRef_makeField (tmp, s->info->field->field);
9718 tmp = sRef_fixResultType (s->info->ref, typ, ue);
9720 ct = ctype_realType (sRef_getType (tmp));
9722 if (ctype_isKnown (ct))
9724 if (ctype_isAP (ct))
9733 ("Special clause dereferences non-pointer (%t): *%q",
9734 ct, sRef_unparse (s->info->ref)),
9735 uentry_whereLast (ue));
9739 ret = sRef_makePointer (tmp);
9746 ("Special clause uses & operator (not allowed): &%q", sRef_unparse (s->info->ref)),
9747 uentry_whereLast (ue));
9756 bool sRef_isOnly (sRef s)
9758 return (sRef_isValid(s) && alkind_isOnly (s->aliaskind));
9761 bool sRef_isDependent (sRef s)
9763 return (sRef_isValid(s) && alkind_isDependent (s->aliaskind));
9766 bool sRef_isOwned (sRef s)
9768 return (sRef_isReasonable (s) && (s->aliaskind == AK_OWNED));
9771 bool sRef_isKeep (sRef s)
9773 return (sRef_isReasonable (s) && (s->aliaskind == AK_KEEP));
9776 bool sRef_isTemp (sRef s)
9778 return (sRef_isReasonable (s) && alkind_isTemp (s->aliaskind));
9781 bool sRef_isLocalState (sRef s)
9783 return (sRef_isReasonable (s) && (s->aliaskind == AK_LOCAL));
9786 bool sRef_isUnique (sRef s)
9788 return (sRef_isReasonable (s) && (s->aliaskind == AK_UNIQUE));
9791 bool sRef_isShared (sRef s)
9793 return (sRef_isReasonable (s) && (s->aliaskind == AK_SHARED));
9796 bool sRef_isExposed (sRef s)
9798 return (sRef_isReasonable (s) && (s->expkind == XO_EXPOSED));
9801 bool sRef_isObserver (sRef s)
9803 return (sRef_isReasonable (s) && (s->expkind == XO_OBSERVER));
9806 bool sRef_isFresh (sRef s)
9808 return (sRef_isReasonable (s) && (s->aliaskind == AK_FRESH));
9811 bool sRef_isDefinitelyNull (sRef s)
9813 return (sRef_isReasonable (s) && (sRef_getNullState (s) == NS_DEFNULL
9814 || sRef_getNullState (s) == NS_CONSTNULL));
9817 bool sRef_isAllocated (sRef s)
9819 return (sRef_isReasonable (s) && (s->defstate == SS_ALLOCATED));
9822 bool sRef_isStack (sRef s)
9824 return (sRef_isReasonable (s) && (s->aliaskind == AK_STACK));
9827 bool sRef_isNotNull (sRef s)
9829 return (sRef_isValid(s) && (sRef_getNullState (s) == NS_MNOTNULL
9830 || sRef_getNullState (s) == NS_NOTNULL));
9833 alkind sRef_getAliasKind (sRef s)
9835 if (sRef_isValid(s)) {
9836 llassert (alkind_isValid (s->aliaskind));
9837 return s->aliaskind;
9843 nstate sRef_getNullState (sRef s)
9845 if (sRef_isReasonable (s)) {
9846 llassert (nstate_isValid (s->nullstate));
9847 return s->nullstate;
9853 void sRef_reflectAnnotation (sRef s, annotationInfo a, fileloc loc)
9855 if (sRef_isReasonable (s))
9857 if (!valueTable_isDefined (s->state))
9859 s->state = valueTable_create (1);
9860 valueTable_insert (s->state,
9861 cstring_copy (metaStateInfo_getName (annotationInfo_getState (a))),
9862 stateValue_create (annotationInfo_getValue (a), stateInfo_makeLoc (loc)));
9866 DPRINTF (("reflect loc: %s", fileloc_unparse (loc)));
9869 metaStateInfo_getName (annotationInfo_getState (a)),
9870 stateValue_create (annotationInfo_getValue (a), stateInfo_makeLoc (loc)));
9871 DPRINTF (("state info: %s", stateInfo_unparse (stateInfo_makeLoc (loc))));
9872 DPRINTF (("sref: %s", sRef_unparse (s)));
9873 DPRINTF (("sref: %s", sRef_unparseFull (s)));
9878 void sRef_setMetaStateValueComplete (sRef s, cstring key, int value, fileloc loc)
9880 sRefSet aliases = usymtab_allAliases (s);
9882 sRef_setMetaStateValue (s, key, value, loc);
9884 sRefSet_realElements (aliases, current)
9886 if (sRef_isReasonable (current))
9888 current = sRef_updateSref (current);
9889 sRef_setMetaStateValue (current, key, value, loc);
9891 } end_sRefSet_realElements ;
9893 sRefSet_free (aliases);
9896 void sRef_setMetaStateValue (sRef s, cstring key, int value, fileloc loc)
9898 sRef_checkMutable (s);
9900 if (sRef_isReasonable (s))
9902 if (!valueTable_isDefined (s->state))
9904 DPRINTF (("inserting state: %s: %s %d", sRef_unparse (s), key, value));
9905 s->state = valueTable_create (1);
9906 valueTable_insert (s->state, cstring_copy (key),
9907 stateValue_create (value, stateInfo_makeLoc (loc)));
9911 DPRINTF (("Updating state: %s: %s %d / %s", sRef_unparse (s), key, value,
9912 fileloc_unparse (loc)));
9913 if (valueTable_contains (s->state, key))
9916 (s->state, key, stateValue_create (value, stateInfo_makeLoc (loc)));
9921 (s->state, cstring_copy (key), stateValue_create (value, stateInfo_makeLoc (loc)));
9924 DPRINTF (("After: %s", sRef_unparseFull (s)));
9929 bool sRef_checkMetaStateValue (sRef s, cstring key, int value)
9931 if (sRef_isReasonable (s))
9933 if (valueTable_isDefined (s->state))
9937 DPRINTF (("check state: %s: %s %d", sRef_unparse (s), key, value));
9939 val = valueTable_lookup (s->state, key);
9940 llassert (stateValue_isDefined (val));
9941 return (stateValue_isError (val)
9942 || stateValue_getValue (val) == value);
9955 /*@observer@*/ stateValue sRef_getMetaStateValue (sRef s, cstring key)
9957 if (sRef_isReasonable (s))
9959 if (valueTable_isDefined (s->state))
9963 val = valueTable_lookup (s->state, key);
9964 /* Okay if its not defined, just returns stateValue_undefined */
9969 return stateValue_undefined;
9974 return stateValue_undefined;
9978 /*@observer@*/ valueTable sRef_getValueTable (sRef s)
9980 DPRINTF (("Get value table: %s", sRef_unparse (s)));
9982 if (sRef_isReasonable (s))
9984 llassert (sRef_isReasonable (s));
9985 DPRINTF (("Value table: %s", valueTable_unparse (s->state)));
9990 DPRINTF (("No value table!"));
9991 return valueTable_undefined;
9995 bool sRef_makeStateSpecial (sRef s)
9998 ** Default defined state can be made special.
10001 llassert (sRef_isReasonable (s)); /*@i523 why doesn't null-checking work!??? */
10003 if (s->defstate == SS_UNKNOWN || s->defstate == SS_DEFINED || s->defstate == SS_SPECIAL)
10005 /* s->aliaskind = AK_IMPTEMP; */ /* evans 2001-07-23 shouldn't effect alias state */
10006 s->defstate = SS_SPECIAL;
10007 DPRINTF (("Made special: %s", sRef_unparseFull (s)));
10012 /* s->aliaskind = AK_IMPTEMP; */
10013 s->defstate = SS_SPECIAL;
10018 void sRef_markImmutable (sRef s)
10020 if (sRef_isReasonable (s))
10022 DPRINTF (("Mark immutable: %s", sRef_unparseFull (s)));
10027 bool sRef_definitelyNullContext (sRef s)
10029 return (sRef_definitelyNull (s)
10030 || usymtab_isDefinitelyNullDeep (s));
10033 bool sRef_definitelyNullAltContext (sRef s)
10035 return (sRef_definitelyNull (s)
10036 || usymtab_isAltDefinitelyNullDeep (s));
10040 /* start modifications */
10041 struct s_bbufinfo sRef_getNullTerminatedState (sRef p_s) {
10042 struct s_bbufinfo BUFSTATE_UNKNOWN;
10043 BUFSTATE_UNKNOWN.bufstate = BB_NOTNULLTERMINATED;
10044 BUFSTATE_UNKNOWN.size = 0;
10045 BUFSTATE_UNKNOWN.len = 0;
10047 if (sRef_isValid(p_s))
10048 return p_s->bufinfo;
10049 return BUFSTATE_UNKNOWN;
10052 void sRef_setNullTerminatedState(sRef p_s) {
10053 if(sRef_isReasonable (p_s)) {
10054 p_s->bufinfo.bufstate = BB_NULLTERMINATED;
10056 llfatalbug( message("sRef_setNT passed a invalid sRef\n"));
10061 void sRef_setPossiblyNullTerminatedState(sRef p_s) {
10062 if( sRef_isReasonable (p_s)) {
10063 p_s->bufinfo.bufstate = BB_POSSIBLYNULLTERMINATED;
10065 llfatalbug( message("sRef_setPossNT passed a invalid sRef\n"));
10069 void sRef_setNotNullTerminatedState(sRef p_s) {
10070 if( sRef_isReasonable (p_s)) {
10071 p_s->bufinfo.bufstate = BB_NOTNULLTERMINATED;
10073 llfatalbug( message("sRef_unsetNT passed a invalid sRef\n"));
10077 void sRef_setLen(sRef p_s, int len) {
10078 if (sRef_isReasonable (p_s) && sRef_isNullTerminated(p_s))
10080 p_s->bufinfo.len = len;
10084 llfatalbug( message("sRef_setLen passed an invalid sRef\n"));
10089 void sRef_setSize(sRef p_s, int size) {
10090 if( sRef_isValid(p_s))
10092 p_s->bufinfo.size = size;
10096 llfatalbug( message("sRef_setSize passed a invalid sRef\n"));
10100 void sRef_resetLen(sRef p_s) {
10101 if (sRef_isReasonable (p_s))
10103 p_s->bufinfo.len = 0;
10107 llfatalbug (message ("sRef_setLen passed an invalid sRef\n"));
10111 /*drl7x 11/28/2000 */
10113 bool sRef_isFixedArray (sRef p_s) /*@*/ {
10115 c = sRef_getType (p_s);
10116 return ( ctype_isFixedArray (c) );
10119 size_t sRef_getArraySize (sRef p_s) /*@*/
10122 llassert (sRef_isFixedArray(p_s) );
10123 DPRINTF (( message ("sRef_getArraySize getting array size for %s", sRef_unparse(p_s) ) ));
10125 c = sRef_getType (p_s);
10126 return (ctype_getArraySize (c));
10129 void sRef_setValue (sRef s, multiVal val)
10131 if (!sRef_isReasonable (s))
10133 llcontbuglit ("Unreasonable sRef");
10134 llcontbug (message ("sRef: %s", sRef_unparse (s)));
10138 multiVal_free (s->val);
10142 bool sRef_hasValue (sRef s)
10144 return (sRef_isReasonable (s)
10145 && multiVal_isDefined (s->val));
10148 multiVal sRef_getValue (sRef s)
10150 if (sRef_isReasonable (s))
10155 return multiVal_undefined;