2 ** Splint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2003 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, /*@null@*/ sRef p_e2,
193 bool p_tbranch, fileloc p_loc);
194 static /*@dependent@*/ sRef sRef_constructPointerAux (/*@notnull@*/ /*@exposed@*/ sRef p_t) /*@*/ ;
197 sRef_combineExKinds (/*@notnull@*/ sRef p_res, /*@notnull@*/ sRef p_other)
198 /*@modifies p_res@*/ ;
201 sRef_combineAliasKinds (/*@notnull@*/ sRef p_res, /*@notnull@*/ sRef p_other,
202 clause p_cl, fileloc p_loc)
203 /*@modifies p_res@*/ ;
206 sRef_combineNullState (/*@notnull@*/ sRef p_res, /*@notnull@*/ sRef p_other)
207 /*@modifies p_res@*/ ;
210 sRef_combineDefState (/*@notnull@*/ sRef p_res, /*@notnull@*/ sRef p_other)
211 /*@modifies p_res@*/ ;
213 static void sRef_setStateFromAbstractUentry (sRef p_s, uentry p_ue)
217 sinfo_update (/*@notnull@*/ /*@exposed@*/ sRef p_res,
218 /*@notnull@*/ /*@exposed@*/ sRef p_other);
219 static void sRef_setDefinedAux (sRef p_s, fileloc p_loc, bool p_clear)
221 static void sRef_setDefinedNoClear (sRef p_s, fileloc p_loc)
223 static void sRef_setStateAux (sRef p_s, sstate p_ss, fileloc p_loc)
226 static /*@exposed@*/ sRef
227 sRef_buildNCField (/*@exposed@*/ sRef p_rec, /*@exposed@*/ cstring p_f);
230 sRef_mergeStateAux (/*@notnull@*/ sRef p_res, /*@notnull@*/ sRef p_other,
231 clause p_cl, bool p_opt, fileloc p_loc,
233 /*@modifies p_res, p_other@*/ ;
235 static /*@null@*/ sinfo sinfo_fullCopy (/*@notnull@*/ sRef p_s);
236 static bool sRef_doModify (sRef p_s, sRefSet p_sl) /*@modifies p_s@*/ ;
237 static bool sRef_doModifyVal (sRef p_s, sRefSet p_sl) /*@modifies p_s@*/;
238 static bool sRef_checkModifyVal (sRef p_s, sRefSet p_sl) /*@*/ ;
240 static /*@only@*/ sRefSet
241 sRef_mergeDerivs (/*@only@*/ sRefSet p_res, sRefSet p_other,
242 bool p_opt, clause p_cl, fileloc p_loc);
244 static /*@only@*/ sRefSet
245 sRef_mergeUnionDerivs (/*@only@*/ sRefSet p_res,
246 /*@exposed@*/ sRefSet p_other,
247 bool p_opt, clause p_cl, fileloc p_loc);
249 static /*@only@*/ sRefSet
250 sRef_mergePdefinedDerivs (/*@only@*/ sRefSet p_res, sRefSet p_other, bool p_opt,
251 clause p_cl, fileloc p_loc);
253 static /*@only@*/ cstring sRef_unparseWithArgs (sRef p_s, uentryList p_args);
254 static /*@only@*/ cstring sRef_unparseNoArgs (sRef p_s);
256 static /*@exposed@*/ sRef sRef_findDerivedPointer (sRef p_s);
257 static /*@exposed@*/ sRef sRef_findDerivedArrayFetch (/*@notnull@*/ sRef, bool, int, bool) ;
258 static /*@exposed@*/ sRef sRef_findDerivedField (/*@notnull@*/ sRef p_rec, cstring p_f);
259 static /*@exposed@*/ sRef
260 sRef_getDeriv (/*@notnull@*/ /*@returned@*/ sRef p_set, sRef p_guide);
262 static bool inFunction = FALSE;
263 static /*@only@*/ sRefTable allRefs;
265 /* # define DEBUGREFS */
269 static totnsrefs = 0;
270 static maxnsrefs = 0;
271 static ntotrefers = 0;
275 static /*@checked@*/ bool protectDerivs = FALSE;
278 ** Result of sRef_alloc is dependent since allRefs may
279 ** reference it. It is only if !inFunction.
282 static /*@dependent@*/ /*@out@*/ /*@notnull@*/ sRef
285 sRef s = (sRef) dmalloc (sizeof (*s));
289 DPRINTF (("Alloc sref: [%p]", s));
293 allRefs = sRefTable_add (allRefs, s);
298 DPRINTF (("Not in function!"));
304 if (nsrefs >= maxnsrefs)
313 /*@-mustfree@*/ /*@-freshtrans@*/
315 /*@=mustfree@*/ /*@=freshtrans@*/
318 static void sRef_checkValidAux (sRef s, sRefSet checkedsofar)
322 if (!sRef_isReasonable (s)) return;
324 if (sRefSet_containsSameObject (checkedsofar, s))
330 checkedsofar = sRefSet_insert (checkedsofar, s);
331 /*@=temptrans@*/ /* checksofar will be destroyed before checkValid returns */
335 case SK_UNCONSTRAINED:
336 llassert (cstring_length (s->info->fname) < 100);
340 llassert (s->info->cvar->lexlevel >= 0);
341 /* llassert (s->info->cvar->lexlevel <= usymtab_getCurrentDepth ()); */
345 llassert (s->info->paramno >= -1);
346 llassert (s->info->paramno <= 50); /*@i32 bogus...*/
350 sRef_checkValidAux (s->info->arrayfetch->arr, checkedsofar);
354 sRef_checkValidAux (s->info->field->rec, checkedsofar);
355 llassert (cstring_length (s->info->field->field) < 100);
359 sRef_checkValidAux (s->info->ref, checkedsofar);
363 sRef_checkValidAux (s->info->ref, checkedsofar);
367 /* check ctype s->info->object */
371 sRef_checkValidAux (s->info->conj->a, checkedsofar);
372 sRef_checkValidAux (s->info->conj->b, checkedsofar);
376 llassert (cstring_length (s->info->fname) < 100);
380 sRef_checkValidAux (s->info->ref, checkedsofar);
384 sRef_checkValidAux (s->info->ref, checkedsofar);
390 /* check ctyp s->type */
394 llassert (s->info->spec == SR_NOTHING
395 || s->info->spec == SR_INTERNAL
396 || s->info->spec == SR_SPECSTATE
397 || s->info->spec == SR_SYSTEM);
407 sRefSet_elements (s->deriv, el)
409 sRef_checkValidAux (el, checkedsofar);
410 } end_sRefSet_elements ;
413 void sRef_checkValid (/*@unused@*/ sRef s)
417 sRefSet checkedsofar = sRefSet_new ();
418 sRef_checkValidAux (s, checkedsofar);
422 static /*@dependent@*/ /*@notnull@*/ /*@special@*/ sRef
425 /*@ensures isnull result->aliasinfo, result->definfo,
426 result->expinfo, result->info, result->deriv, result->state@*/
428 sRef s = sRef_alloc ();
430 s->kind = SK_UNKNOWN;
434 s->val = multiVal_undefined;
436 s->type = ctype_unknown;
437 s->defstate = SS_UNKNOWN;
439 /* start modifications */
440 s->bufinfo.bufstate = BB_NOTNULLTERMINATED;
441 s->bufinfo.size = -1; /*@i24 unknown@*/
442 s->bufinfo.len = -1; /*@i24 unknown@*/
443 /* end modifications */
445 s->aliaskind = AK_UNKNOWN;
446 s->oaliaskind = AK_UNKNOWN;
448 s->nullstate = NS_UNKNOWN;
450 s->expkind = XO_UNKNOWN;
451 s->oexpkind = XO_UNKNOWN;
453 s->aliasinfo = stateInfo_undefined;
454 s->definfo = stateInfo_undefined;
455 s->nullinfo = stateInfo_undefined;
456 s->expinfo = stateInfo_undefined;
459 s->deriv = sRefSet_undefined;
461 s->state = valueTable_undefined;
466 static /*@dependent@*/ /*@notnull@*/ /*@special@*/ sRef
469 /*@ensures isnull result->aliasinfo, result->definfo,
470 result->expinfo, result->info, result->deriv@*/
472 sRef res = sRef_new ();
474 res->state = valueTable_undefined;
479 void sRef_protectDerivs (void) /*@modifies protectDerivs@*/
481 llassert (!protectDerivs);
482 protectDerivs = TRUE;
485 void sRef_clearProtectDerivs (void) /*@modifies protectDerivs@*/
487 llassert (protectDerivs);
488 protectDerivs = FALSE;
492 ** hmmm...here be kind of a hack. This function mysteriously appeared
493 ** in my code, but I'm sure I didn't write it.
497 sRef_isRecursiveField (sRef s)
499 if (sRef_isField (s))
501 if (sRef_depth (s) > 13)
506 fieldname = sRef_getField (s);
507 base = sRef_getBase (s);
509 while (sRef_isReasonable (base))
511 if (sRef_isField (base))
513 if (cstring_equal (fieldname, sRef_getField (base)))
519 base = sRef_getBaseSafe (base);
528 sRef_addDeriv (/*@notnull@*/ sRef s, /*@notnull@*/ /*@exposed@*/ sRef t)
530 if (!context_inProtectVars ()
532 && sRef_isReasonable (s)
533 && sRef_isReasonable (t)
534 && !sRef_isConst (s))
536 int sd = sRef_depth (s);
537 int td = sRef_depth (t);
544 /* This sometimes fails: (evans 2001-07-12)
545 if (sRef_isArrayFetch (t))
547 DPRINTF (("Derived fetch: %s / %s / %s",
548 sRef_unparseFull (s), sRef_unparseFull (t),
549 sRef_unparseFull (t->info->arrayfetch->arr)));
550 llassert (t->info->arrayfetch->arr == s);
554 if (sRef_isFileOrGlobalScope (s))
556 if (context_inFunctionLike ()
557 && ctype_isKnown (sRef_getType (s))
558 && !ctype_isFunction (sRef_getType (s)))
560 globSet g = context_getUsedGlobs ();
562 if (!globSet_member (g, s))
565 ** don't report as a bug
569 (message ("sRef_addDeriv: global variable not in used "
570 "globs: %q / %s / %q",
572 ctype_unparse (sRef_getType (s)),
573 sRefSet_unparse (s->deriv)));
578 DPRINTF (("Add deriv: [%p] %s / [%p] %s",
580 t, sRef_unparse (t)));
582 s->deriv = sRefSet_insert (s->deriv, t);
588 DPRINTF (("Add deriv: [%p] %s / [%p] %s",
590 t, sRef_unparse (t)));
592 s->deriv = sRefSet_insert (s->deriv, t);
598 sRef_deepPred (bool (predf) (sRef), sRef s)
600 if (sRef_isReasonable (s))
602 if ((*predf)(s)) return TRUE;
607 return (sRef_deepPred (predf, s->info->ref));
609 return (sRef_deepPred (predf, s->info->arrayfetch->arr));
611 return (sRef_deepPred (predf, s->info->field->rec));
613 return (sRef_deepPred (predf, s->info->conj->a)
614 || sRef_deepPred (predf, s->info->conj->b));
623 bool sRef_modInFunction (void)
628 void sRef_setStateFromType (sRef s, ctype ct)
630 if (sRef_isReasonable (s))
632 if (ctype_isUser (ct))
634 DPRINTF (("Here we are: %s", sRef_unparseFull (s)));
635 sRef_setStateFromUentry
636 (s, usymtab_getTypeEntry (ctype_typeId (ct)));
638 else if (ctype_isAbstract (ct))
640 DPRINTF (("Here we are: %s", sRef_unparseFull (s)));
641 sRef_setStateFromAbstractUentry
642 (s, usymtab_getTypeEntry (ctype_typeId (ct)));
646 ; /* not a user type */
651 static void sRef_setTypeState (sRef s)
653 if (sRef_isReasonable (s))
655 sRef_setStateFromType (s, s->type);
659 bool sRef_hasAliasInfoLoc (sRef s)
661 return (sRef_isReasonable (s) && (s->aliasinfo != NULL)
662 && (fileloc_isDefined (s->aliasinfo->loc)));
665 /*@falsewhennull@*/ bool sRef_hasStateInfoLoc (sRef s)
667 return (sRef_isReasonable (s) && (s->definfo != NULL)
668 && (fileloc_isDefined (s->definfo->loc)));
671 /*@falsewhennull@*/ bool sRef_hasExpInfoLoc (sRef s)
673 return (sRef_isReasonable (s)
674 && (s->expinfo != NULL) && (fileloc_isDefined (s->expinfo->loc)));
678 static /*@observer@*/ /*@unused@*/ stateInfo sRef_getInfo (sRef s, cstring key)
682 if (!sRef_isReasonable (s)) {
683 return stateInfo_undefined;
686 sv = valueTable_lookup (s->state, key);
688 if (stateValue_isDefined (sv))
690 return stateValue_getInfo (sv);
693 return stateInfo_undefined;
698 sRef_hasNullInfoLoc (sRef s)
700 return (sRef_isReasonable (s) && s->nullinfo != NULL
701 && (fileloc_isDefined (s->nullinfo->loc)));
705 sRef_hasAliasInfoRef (sRef s)
707 return (sRef_isReasonable (s) && (s->aliasinfo != NULL)
708 && (sRef_isReasonable (s->aliasinfo->ref)));
711 static /*@observer@*/ fileloc
712 sRef_getAliasInfoLoc (/*@exposed@*/ sRef s)
714 llassert (sRef_isReasonable (s) && s->aliasinfo != NULL
715 && (fileloc_isDefined (s->aliasinfo->loc)));
716 return (s->aliasinfo->loc);
719 static /*@observer@*/ fileloc
720 sRef_getStateInfoLoc (/*@exposed@*/ sRef s)
722 llassert (sRef_isReasonable (s) && s->definfo != NULL
723 && (fileloc_isDefined (s->definfo->loc)));
724 return (s->definfo->loc);
727 static /*@observer@*/ fileloc
728 sRef_getExpInfoLoc (/*@exposed@*/ sRef s)
730 llassert (sRef_isReasonable (s) && s->expinfo != NULL
731 && (fileloc_isDefined (s->expinfo->loc)));
732 return (s->expinfo->loc);
735 static /*@observer@*/ fileloc
736 sRef_getNullInfoLoc (/*@exposed@*/ sRef s)
738 llassert (sRef_isReasonable (s) && s->nullinfo != NULL
739 && (fileloc_isDefined (s->nullinfo->loc)));
740 return (s->nullinfo->loc);
744 sRef_getAliasInfoRef (/*@temp@*/ sRef s)
746 llassert (sRef_isReasonable (s) && s->aliasinfo != NULL);
747 return (s->aliasinfo->ref);
750 bool sRef_inGlobalScope ()
756 ** This function should be called before new sRefs are created
757 ** somewhere where they will have a lifetime greater than the
758 ** current function scope.
761 void sRef_setGlobalScope ()
763 llassert (inFunction);
764 DPRINTF (("leave function"));
768 void sRef_clearGlobalScope ()
770 llassert (!inFunction);
771 DPRINTF (("enter function"));
775 static bool oldInFunction = FALSE;
776 static int nestedScope = 0;
778 void sRef_setGlobalScopeSafe ()
780 if (nestedScope == 0)
782 oldInFunction = inFunction;
786 DPRINTF (("leave function safe"));
790 void sRef_clearGlobalScopeSafe ()
793 llassert (nestedScope >= 0);
795 if (nestedScope == 0)
797 inFunction = oldInFunction;
800 DPRINTF (("clear function: %s", bool_unparse (inFunction)));
803 void sRef_enterFunctionScope ()
805 /* evans 2001-09-09 - cleanup if we are in a macro! */
806 if (context_inMacro ())
809 sRef_exitFunctionScope ();
813 llassert (!inFunction);
814 llassert (sRefTable_isEmpty (allRefs));
816 DPRINTF (("enter function"));
819 void sRef_exitFunctionScope ()
823 DPRINTF (("Exit function scope."));
824 sRefTable_clear (allRefs);
825 DPRINTF (("Exit function scope done."));
830 llbuglit ("sRef_exitFunctionScope: not in function");
834 void sRef_destroyMod () /*@globals killed allRefs;@*/
837 llmsg (message ("Live: %d / %d ", nsrefs, totnsrefs));
840 sRefTable_free (allRefs);
844 static /*@notnull@*/ /*@exposed@*/ sRef
845 sRef_fixConj (/*@notnull@*/ sRef s)
850 s = sRef_getConjA (s);
851 } while (sRef_isConj (s));
853 llassert (sRef_isReasonable (s));
854 return s; /* don't need to ref */
863 sRef_isExternallyVisibleAux (sRef s)
866 sRef base = sRef_getRootBase (s);
868 if (sRef_isReasonable (base))
870 res = sRef_isParam (base) || sRef_isFileOrGlobalScope (base) || sRef_isExternal (base);
877 sRef_isExternallyVisible (sRef s)
879 return (sRef_aliasCheckSimplePred (sRef_isExternallyVisibleAux, s));
883 sRef_getBaseUentry (sRef s)
885 sRef base = sRef_getRootBase (s);
886 uentry res = uentry_undefined;
888 if (sRef_isReasonable (base))
893 res = usymtab_getRefQuiet (paramsScope, base->info->paramno);
897 res = usymtab_getRefQuiet (base->info->cvar->lexlevel,
898 base->info->cvar->index);
910 ** lookup the current uentry corresponding to s, and return the corresponding sRef.
911 ** yuk yuk yuk yuk yuk yuk yuk yuk
915 sRef_updateSref (sRef s)
921 if (!sRef_isReasonable (s)) return sRef_undefined;
930 case SK_UNCONSTRAINED:
937 sRef r = sRef_updateSref (s->info->ref);
939 if (r != s->info->ref)
941 return sRef_makeExternal (r);
951 uentry ue = sRef_getUentry (s);
953 /* must be raw name! (need the marker) */
954 ue = usymtab_lookupSafe (uentry_rawName (ue));
956 if (uentry_isUndefined (ue))
962 DPRINTF (("Update sref: %s", uentry_unparseFull (ue)));
963 return (uentry_getSref (ue));
967 /* special case if ind known */
968 inner = s->info->arrayfetch->arr;
969 ret = sRef_updateSref (inner);
977 res = sRef_makeArrayFetch (ret);
983 inner = s->info->field->rec;
984 ret = sRef_updateSref (inner);
992 res = (sRef_makeField (ret, s->info->field->field));
997 inner = s->info->ref;
998 ret = sRef_updateSref (inner);
1005 res = sRef_makePointer (ret);
1011 inner = s->info->ref;
1012 ret = sRef_updateSref (inner);
1020 res = sRef_makeAddress (ret);
1027 sRef innera = s->info->conj->a;
1028 sRef innerb = s->info->conj->b;
1029 sRef reta = sRef_updateSref (innera);
1030 sRef retb = sRef_updateSref (innerb);
1032 if (innera == reta && innerb == retb)
1038 res = sRef_makeConj (reta, retb);
1049 sRef_getUentry (sRef s)
1051 llassert (sRef_isReasonable (s));
1056 return (usymtab_getRefQuiet (paramsScope, s->info->paramno));
1058 return (usymtab_getRefQuiet (s->info->cvar->lexlevel, s->info->cvar->index));
1061 if (sRef_isCvar (s->info->conj->a) || sRef_isParam (s->info->conj->a)
1062 || sRef_isConj (s->info->conj->a))
1064 return sRef_getUentry (s->info->conj->a);
1068 return sRef_getUentry (s->info->conj->b);
1071 case SK_FIELD: /* evans 2002-07-17: added case for SK_FIELD */
1074 return uentry_undefined;
1080 sRef_getParam (sRef s)
1082 llassert (sRef_isReasonable (s));
1083 llassert (s->kind == SK_PARAM);
1085 return s->info->paramno;
1089 sRef_isModified (sRef s)
1091 return (!sRef_isReasonable (s) || s->modified);
1094 void sRef_setModified (sRef s)
1096 if (sRef_isReasonable (s))
1101 if (sRef_isRefsField (s))
1103 sRef base = sRef_getBase (s);
1105 llassert (s->kind == SK_FIELD);
1107 if (sRef_isPointer (base))
1109 base = sRef_getBase (base);
1112 if (sRef_isRefCounted (base))
1114 base->aliaskind = AK_NEWREF;
1121 ** note: this side-effects sRefSet to set modified to TRUE
1122 ** for any sRef similar to s.
1126 sRef_canModifyVal (sRef s, sRefSet sl)
1128 if (context_getFlag (FLG_MUSTMOD))
1130 return (sRef_doModifyVal (s, sl));
1134 return (sRef_checkModifyVal (s, sl));
1139 sRef_canModify (sRef s, sRefSet sl)
1141 if (context_getFlag (FLG_MUSTMOD))
1143 return (sRef_doModify (s, sl));
1147 return (sRef_checkModify (s, sl));
1156 bool sRef_checkModifyVal (sRef s, sRefSet sl)
1158 DPRINTF (("Check modify val: %s", sRef_unparse (s)));
1160 if (sRef_isInvalid (s))
1167 case SK_UNCONSTRAINED:
1171 DPRINTF (("Modify var: %s", sRef_unparse (s)));
1173 if (sRef_isFileOrGlobalScope (s))
1175 if (context_checkGlobMod (s))
1177 return (sRefSet_member (sl, s));
1187 return (sRefSet_member (sl, s)
1188 || alkind_isOnly (sRef_getOrigAliasKind (s)));
1190 /* special case if ind known */
1191 return (sRefSet_member (sl, s) ||
1192 sRef_checkModifyVal (s->info->arrayfetch->arr, sl));
1194 return (sRefSet_member (sl, s) || sRef_checkModifyVal (s->info->field->rec, sl));
1196 return (sRefSet_member (sl, s) || sRef_checkModifyVal (s->info->ref, sl));
1198 return (sRefSet_member (sl, s) || sRef_checkModifyVal (s->info->ref, sl));
1200 return ((sRef_checkModifyVal (s->info->conj->a, sl)) &&
1201 (sRef_checkModifyVal (s->info->conj->b, sl)));
1212 switch (s->info->spec)
1214 case SR_NOTHING: return TRUE;
1216 if (context_getFlag (FLG_INTERNALGLOBS))
1218 return (sRefSet_member (sl, s));
1224 case SR_SPECSTATE: return TRUE;
1225 case SR_SYSTEM: return (sRefSet_member (sl, s));
1226 case SR_GLOBALMARKER: BADBRANCH;
1229 case SK_RESULT: BADBRANCH;
1235 ** this should probably be elsewhere...
1237 ** returns TRUE iff sl indicates that s can be modified
1240 static bool sRef_checkModify (sRef s, sRefSet sl)
1242 llassert (sRef_isReasonable (s));
1246 case SK_UNCONSTRAINED:
1250 if (sRef_isFileOrGlobalScope (s))
1252 if (context_checkGlobMod (s))
1254 return (sRefSet_member (sl, s));
1266 return (sRefSet_member (sl, s) ||
1267 sRef_checkModifyVal (s->info->arrayfetch->arr, sl));
1270 sRef sr = s->info->field->rec;
1272 if (sr->kind == SK_PARAM)
1273 return TRUE; /* structs are copied on call */
1275 return (sRefSet_member (sl, s) || sRef_checkModifyVal (s->info->field->rec, sl));
1281 sm = sRefSet_member (sl, s);
1286 return (sRef_checkModifyVal (s->info->ref, sl));
1289 return (sRefSet_member (sl, s) || sRef_checkModifyVal (s->info->ref, sl));
1291 return ((sRef_checkModify (s->info->conj->a, sl)) &&
1292 (sRef_checkModify (s->info->conj->b, sl)));
1302 switch (s->info->spec)
1304 case SR_NOTHING: return TRUE;
1306 if (context_getFlag (FLG_INTERNALGLOBS))
1308 return (sRefSet_member (sl, s));
1314 case SR_SPECSTATE: return TRUE;
1315 case SR_SYSTEM: return (sRefSet_member (sl, s));
1316 case SR_GLOBALMARKER: BADBRANCH;
1319 case SK_RESULT: BADBRANCH;
1324 cstring sRef_stateVerb (sRef s)
1326 if (sRef_isDead (s))
1328 return cstring_makeLiteralTemp ("released");
1330 else if (sRef_isKept (s))
1332 return cstring_makeLiteralTemp ("kept");
1334 else if (sRef_isDependent (s))
1336 return cstring_makeLiteralTemp ("dependent");
1344 cstring sRef_stateAltVerb (sRef s)
1346 if (sRef_isDead (s))
1348 return cstring_makeLiteralTemp ("live");
1350 else if (sRef_isKept (s))
1352 return cstring_makeLiteralTemp ("not kept");
1354 else if (sRef_isDependent (s))
1356 return cstring_makeLiteralTemp ("independent");
1365 bool sRef_doModifyVal (sRef s, sRefSet sl)
1367 llassert (sRef_isReasonable (s));
1372 case SK_UNCONSTRAINED:
1376 if (sRef_isFileOrGlobalScope (s))
1379 if (context_checkGlobMod (s))
1381 return (sRefSet_modifyMember (sl, s));
1385 (void) sRefSet_modifyMember (sl, s);
1395 return (sRefSet_modifyMember (sl, s)
1396 || alkind_isOnly (sRef_getOrigAliasKind (s)));
1398 /* special case if ind known */
1399 /* unconditional OR, need side effect */
1400 return (OR (sRefSet_modifyMember (sl, s),
1401 sRef_doModifyVal (s->info->arrayfetch->arr, sl)));
1403 return (OR (sRefSet_modifyMember (sl, s),
1404 sRef_doModifyVal (s->info->field->rec, sl)));
1406 return (OR (sRefSet_modifyMember (sl, s),
1407 sRef_doModifyVal (s->info->ref, sl)));
1409 return (OR (sRefSet_modifyMember (sl, s),
1410 sRef_doModifyVal (s->info->ref, sl)));
1412 return (AND (sRef_doModifyVal (s->info->conj->a, sl) ,
1413 sRef_doModifyVal (s->info->conj->b, sl)));
1423 switch (s->info->spec)
1425 case SR_NOTHING: return TRUE;
1427 if (context_getFlag (FLG_INTERNALGLOBS))
1429 return (sRefSet_modifyMember (sl, s));
1433 (void) sRefSet_modifyMember (sl, s);
1436 case SR_SPECSTATE: return TRUE;
1437 case SR_SYSTEM: return (sRefSet_modifyMember (sl, s));
1438 case SR_GLOBALMARKER: BADBRANCH;
1442 case SK_RESULT: BADBRANCH;
1448 ** this should probably be elsewhere...
1450 ** returns TRUE iff sl indicates that s can be modified
1454 bool sRef_doModify (sRef s, sRefSet sl)
1456 llassert (sRef_isReasonable (s));
1460 case SK_UNCONSTRAINED:
1464 if (sRef_isFileOrGlobalScope (s))
1466 if (context_checkGlobMod (s))
1468 return (sRefSet_modifyMember (sl, s));
1472 (void) sRefSet_modifyMember (sl, s);
1484 return (OR (sRefSet_modifyMember (sl, s),
1485 sRef_doModifyVal (s->info->arrayfetch->arr, sl)));
1488 sRef sr = s->info->field->rec;
1490 if (sr->kind == SK_PARAM)
1492 return TRUE; /* structs are shallow-copied on call */
1495 return (OR (sRefSet_modifyMember (sl, s),
1496 sRef_doModifyVal (s->info->field->rec, sl)));
1500 return (OR (sRefSet_modifyMember (sl, s),
1501 sRef_doModifyVal (s->info->ref, sl)));
1504 return (OR (sRefSet_modifyMember (sl, s),
1505 sRef_doModifyVal (s->info->ref, sl)));
1507 return (AND (sRef_doModify (s->info->conj->a, sl),
1508 (sRef_doModify (s->info->conj->b, sl))));
1519 switch (s->info->spec)
1521 case SR_NOTHING: return TRUE;
1522 case SR_INTERNAL: return TRUE;
1523 case SR_SPECSTATE: return TRUE;
1524 case SR_SYSTEM: return (sRefSet_modifyMember (sl, s));
1525 case SR_GLOBALMARKER: BADBRANCH;
1528 case SK_RESULT: BADBRANCH;
1533 static /*@exposed@*/ sRef
1534 sRef_leastCommon (/*@exposed@*/ sRef s1, sRef s2)
1536 llassert (sRef_similar (s1, s2));
1538 if (!sRef_isReasonable (s1)) return s1;
1539 if (!sRef_isReasonable (s2)) return s1;
1541 sRef_combineDefState (s1, s2);
1542 sRef_combineNullState (s1, s2);
1543 sRef_combineExKinds (s1, s2);
1545 if (s1->aliaskind != s2->aliaskind)
1547 if (s1->aliaskind == AK_UNKNOWN)
1549 s1->aliaskind = s2->aliaskind;
1551 else if (s2->aliaskind == AK_UNKNOWN)
1557 s1->aliaskind = AK_ERROR;
1564 int sRef_compare (sRef s1, sRef s2)
1566 if (s1 == s2) return 0;
1568 if (sRef_isInvalid (s1)) return -1;
1569 if (sRef_isInvalid (s2)) return 1;
1571 INTCOMPARERETURN (s1->kind, s2->kind);
1572 INTCOMPARERETURN (s1->defstate, s2->defstate);
1573 INTCOMPARERETURN (s1->aliaskind, s2->aliaskind);
1575 DPRINTF (("Compare null state: %s / %s",
1576 sRef_unparseFull (s1),
1577 sRef_unparseFull (s2)));
1579 COMPARERETURN (nstate_compare (sRef_getNullState (s1),
1580 sRef_getNullState (s2)));
1585 return (int_compare (s1->info->paramno, s2->info->paramno));
1588 COMPARERETURN (sRef_compare (s1->info->arrayfetch->arr,
1589 s2->info->arrayfetch->arr));
1591 if (s1->info->arrayfetch->indknown && s2->info->arrayfetch->indknown)
1593 return (int_compare (s1->info->arrayfetch->ind,
1594 s2->info->arrayfetch->ind));
1596 if (!s1->info->arrayfetch->indknown && !s2->info->arrayfetch->indknown)
1603 COMPARERETURN (sRef_compare (s1->info->field->rec, s2->info->field->rec));
1605 if (cstring_equal (s1->info->field->field, s2->info->field->field))
1612 return (sRef_compare (s1->info->ref, s2->info->ref));
1614 COMPARERETURN (sRef_compare (s1->info->conj->a, s2->info->conj->a));
1615 return (sRef_compare (s1->info->conj->b, s2->info->conj->b));
1616 case SK_UNCONSTRAINED:
1617 return (cstring_compare (s1->info->fname, s2->info->fname));
1629 return (generic_compare (s1->info->spec, s2->info->spec));
1634 static bool cref_equal (cref c1, cref c2)
1636 return ((c1->lexlevel == c2->lexlevel) &&
1637 (usymId_equal (c1->index, c2->index)));
1641 ** returns true if s1 could be the same storage as s2.
1642 ** i.e., a[?] ~ a[3]. Note its not symmetric ... s1
1643 ** should be more specific.
1647 ** like similar, but matches objects <-> non-objects
1651 sRef_uniqueReference (sRef s)
1653 return (sRef_isFresh (s) || sRef_isUnique (s)
1654 || sRef_isOnly (s) || sRef_isStack (s)
1655 || sRef_isAddress (s));
1659 sRef_similarRelaxedAux (sRef s1, sRef s2)
1663 if (sRef_isUnknownArrayFetch (s1))
1673 if (sRef_isInvalid (s1) || sRef_isInvalid (s2)) return FALSE;
1675 if (sRef_isConj (s2))
1676 return (sRef_similarRelaxedAux (s1, sRef_getConjA (s2)) ||
1677 sRef_similarRelaxedAux (s1, sRef_getConjB (s2)));
1682 return ((s2->kind == SK_CVAR)
1683 && (cref_equal (s1->info->cvar, s2->info->cvar)));
1685 return ((s2->kind == SK_PARAM)
1686 && (s1->info->paramno == s2->info->paramno));
1688 if (s2->kind == SK_ARRAYFETCH)
1690 if (sRef_similarRelaxedAux (s1->info->arrayfetch->arr,
1691 s2->info->arrayfetch->arr))
1693 if (s1->info->arrayfetch->indknown)
1695 if (s2->info->arrayfetch->indknown)
1697 return (s1->info->arrayfetch->ind == s2->info->arrayfetch->ind);
1712 return ((s2->kind == SK_FIELD
1713 && (sRef_similarRelaxedAux (s1->info->field->rec,
1714 s2->info->field->rec)
1715 && cstring_equal (s1->info->field->field,
1716 s2->info->field->field))));
1718 return ((s2->kind == SK_PTR)
1719 && sRef_similarRelaxedAux (s1->info->ref, s2->info->ref));
1721 return ((s2->kind == SK_ADR)
1722 && sRef_similarRelaxedAux (s1->info->ref, s2->info->ref));
1724 return ((sRef_similarRelaxedAux (s1->info->conj->a, s2) ||
1725 (sRef_similarRelaxedAux (s1->info->conj->b, s2))));
1727 return (s1->info->spec == s2->info->spec);
1728 case SK_UNCONSTRAINED:
1729 return (cstring_equal (s1->info->fname, s2->info->fname));
1744 sRef_similarRelaxed (sRef s1, sRef s2)
1750 if (sRef_isThroughArrayFetch (s1))
1760 if (sRef_isInvalid (s1) || sRef_isInvalid (s2)) return FALSE;
1762 us1 = sRef_uniqueReference (s1);
1763 us2 = sRef_uniqueReference (s2);
1765 if ((s1->kind == SK_EXTERNAL && (s2->kind != SK_EXTERNAL && !us2))
1766 || (s2->kind == SK_EXTERNAL && (s1->kind != SK_EXTERNAL && !us1)))
1769 ** Previously, also:
1770 ** || (sRef_isExposed (s1) && !us2) || (sRef_isExposed (s2) && !us1)) ????
1772 ** No clue why this was there?!
1776 if (sRef_isExposed (s1) && sRef_isCvar (s1))
1778 uentry ue1 = sRef_getUentry (s1);
1780 if (uentry_isRefParam (ue1))
1782 return sRef_similarRelaxedAux (s1, s2);
1786 if (sRef_isExposed (s2) && sRef_isCvar (s2))
1788 uentry ue2 = sRef_getUentry (s2);
1790 if (uentry_isRefParam (ue2))
1792 return sRef_similarRelaxedAux (s1, s2);
1796 return (ctype_match (s1->type, s2->type));
1800 return sRef_similarRelaxedAux (s1, s2);
1805 sRef_similar (sRef s1, sRef s2)
1807 if (s1 == s2) return TRUE;
1808 if (sRef_isInvalid (s1) || sRef_isInvalid (s2)) return FALSE;
1810 if (sRef_isConj (s2))
1812 return (sRef_similar (s1, sRef_getConjA (s2)) ||
1813 sRef_similar (s1, sRef_getConjB (s2)));
1816 if (sRef_isDerived (s2))
1818 return (sRef_includedBy (s1, s2->info->ref));
1824 return ((s2->kind == SK_CVAR)
1825 && (cref_equal (s1->info->cvar, s2->info->cvar)));
1827 return ((s2->kind == SK_PARAM)
1828 && (s1->info->paramno == s2->info->paramno));
1830 if (s2->kind == SK_ARRAYFETCH)
1832 if (sRef_similar (s1->info->arrayfetch->arr,
1833 s2->info->arrayfetch->arr))
1835 if (s1->info->arrayfetch->indknown)
1837 if (s2->info->arrayfetch->indknown)
1839 return (s1->info->arrayfetch->ind == s2->info->arrayfetch->ind);
1854 if (s2->kind == SK_PTR)
1856 if (sRef_similar (s1->info->arrayfetch->arr,
1866 return ((s2->kind == SK_FIELD
1867 && (sRef_similar (s1->info->field->rec,
1868 s2->info->field->rec)
1869 && cstring_equal (s1->info->field->field,
1870 s2->info->field->field))));
1872 if (s2->kind == SK_PTR)
1874 return sRef_similar (s1->info->ref, s2->info->ref);
1878 if (s2->kind == SK_ARRAYFETCH)
1880 if (sRef_similar (s2->info->arrayfetch->arr,
1890 return ((s2->kind == SK_ADR)
1891 && sRef_similar (s1->info->ref, s2->info->ref));
1893 return ((sRef_similar (s1->info->conj->a, s2) ||
1894 (sRef_similar (s1->info->conj->b, s2))));
1896 return (sRef_includedBy (s2, s1->info->ref));
1897 case SK_UNCONSTRAINED:
1898 return (s2->kind == SK_UNCONSTRAINED
1899 && cstring_equal (s1->info->fname, s2->info->fname));
1909 return (s2->kind == SK_SPECIAL
1910 && (s1->info->spec == s2->info->spec));
1913 /*@notreached@*/ DPRINTF (("Fell through for: %s / %s", sRef_unparse (s1), sRef_unparse (s2)));
1918 ** return TRUE iff small can be derived from big.
1920 ** (e.g. x, x.a is includedBy x;
1921 ** x.a is included By x.a;
1925 sRef_includedBy (sRef small, sRef big)
1927 if (small == big) return TRUE;
1928 if (sRef_isInvalid (small) || sRef_isInvalid (big)) return FALSE;
1930 if (sRef_isConj (big))
1931 return (sRef_similar (small, sRef_getConjA (big)) ||
1932 sRef_similar (small, sRef_getConjB (big)));
1934 switch (small->kind)
1938 return (sRef_same (small, big));
1940 if (big->kind == SK_ARRAYFETCH)
1942 if (sRef_same (small->info->arrayfetch->arr, big->info->arrayfetch->arr))
1944 if (small->info->arrayfetch->indknown)
1946 if (big->info->arrayfetch->indknown)
1948 return (small->info->arrayfetch->ind == big->info->arrayfetch->ind);
1961 return (sRef_includedBy (small->info->arrayfetch->arr, big));
1963 if (big->kind == SK_FIELD)
1966 (sRef_same (small->info->field->rec, big->info->field->rec) &&
1967 cstring_equal (small->info->field->field, big->info->field->field));
1971 return (sRef_includedBy (small->info->field->rec, big));
1975 if (big->kind == SK_PTR)
1977 return sRef_same (small->info->ref, big->info->ref);
1981 return (sRef_includedBy (small->info->ref, big));
1985 return ((big->kind == SK_ADR) && sRef_similar (small->info->ref, big->info->ref));
1987 return ((sRef_includedBy (small->info->conj->a, big) ||
1988 (sRef_includedBy (small->info->conj->b, big))));
1990 return (sRef_includedBy (small->info->ref, big));
1991 case SK_UNCONSTRAINED:
2001 switch (small->info->spec)
2003 case SR_NOTHING: return TRUE;
2005 case SR_INTERNAL: return (sRef_isSpecInternalState (big) ||
2006 sRef_isFileStatic (big));
2007 case SR_SYSTEM: return (sRef_isSystemState (big));
2008 case SR_GLOBALMARKER: BADBRANCH;
2015 ** Same is similar to similar, but not quite the same.
2016 ** same and realSame aren't the same, but they are really similar.
2017 ** similarly, same is the same as same. but realSame is
2018 ** not really the same as same, or similar to similar.
2020 ** Similarly to similar, same checks if two sRefs are the same.
2021 ** The similarities end, however, when same compares arrays
2022 ** with unknown indexes. Similar returns false; same returns true.
2024 ** Similarly to similar and same, realSame is the same as same,
2025 ** except they do not behave the same when face with unknown
2026 ** sRefs. Same thinks they are not the same, but realSame thinks
2032 sRef_realSame (sRef s1, sRef s2)
2034 if (s1 == s2) return TRUE;
2036 if (sRef_isUnreasonable (s1)
2037 || sRef_isUnreasonable (s2))
2045 return ((s2->kind == SK_CVAR) && (cref_equal (s1->info->cvar, s2->info->cvar)));
2047 return ((s2->kind == SK_PARAM) && (s1->info->paramno == s2->info->paramno));
2049 if (s2->kind == SK_ARRAYFETCH)
2051 if (sRef_realSame (s1->info->arrayfetch->arr, s2->info->arrayfetch->arr))
2053 if (s1->info->arrayfetch->indknown && s2->info->arrayfetch->indknown)
2055 return (s1->info->arrayfetch->ind == s2->info->arrayfetch->ind);
2057 if (!s1->info->arrayfetch->indknown && !s2->info->arrayfetch->indknown)
2066 return ((s2->kind == SK_FIELD &&
2067 (sRef_realSame (s1->info->field->rec, s2->info->field->rec) &&
2068 cstring_equal (s1->info->field->field, s2->info->field->field))));
2070 return ((s2->kind == SK_PTR) && sRef_realSame (s1->info->ref, s2->info->ref));
2072 return ((s2->kind == SK_ADR) && sRef_realSame (s1->info->ref, s2->info->ref));
2074 return ((sRef_realSame (s1->info->conj->a, s2) ||
2075 (sRef_realSame (s1->info->conj->b, s2))));
2077 return ((s2->kind == SK_OBJECT)
2078 && ctype_match (s1->info->object, s2->info->object));
2080 return ((s2->kind == SK_EXTERNAL)
2081 && sRef_realSame (s1->info->ref, s2->info->ref));
2083 return ((s2->kind == SK_SPECIAL) && s1->info->spec == s2->info->spec);
2085 return ((s2->kind == SK_DERIVED) && sRef_realSame (s1->info->ref, s2->info->ref));
2086 case SK_UNCONSTRAINED:
2087 return ((s2->kind == SK_UNCONSTRAINED)
2088 && (cstring_equal (s1->info->fname, s2->info->fname)));
2094 return TRUE; /* changed this! was false */
2100 sRef_sameObject (sRef s1, sRef s2)
2106 ** same is similar to similar, but not quite the same.
2108 ** Similarly to similar, same checks is two sRefs are the same.
2109 ** The similarities end, however, when same compares arrays
2110 ** with unknown indexes. Similar returns false; same returns true.
2114 sRef_same (sRef s1, sRef s2)
2116 if (s1 == s2) return TRUE;
2117 if (sRef_isInvalid (s1) || sRef_isInvalid (s2)) return FALSE;
2122 return ((s2->kind == SK_CVAR) && (cref_equal (s1->info->cvar, s2->info->cvar)));
2124 return ((s2->kind == SK_PARAM) && (s1->info->paramno == s2->info->paramno));
2126 if (s2->kind == SK_ARRAYFETCH)
2128 llassert (s1->info->field->rec != s1);
2129 if (sRef_same (s1->info->arrayfetch->arr, s2->info->arrayfetch->arr))
2131 if (s1->info->arrayfetch->indknown && s2->info->arrayfetch->indknown)
2133 return (s1->info->arrayfetch->ind == s2->info->arrayfetch->ind);
2141 llassert (s1->info->field->rec != s1);
2142 return ((s2->kind == SK_FIELD &&
2143 (sRef_same (s1->info->field->rec, s2->info->field->rec) &&
2144 cstring_equal (s1->info->field->field, s2->info->field->field))));
2148 llassert (s1->info->ref != s1);
2149 return ((s2->kind == SK_PTR) && sRef_same (s1->info->ref, s2->info->ref));
2153 llassert (s1->info->ref != s1);
2154 return ((s2->kind == SK_ADR) && sRef_same (s1->info->ref, s2->info->ref));
2157 llassert (s1->info->conj->a != s1);
2158 llassert (s1->info->conj->b != s1);
2159 return ((sRef_same (s1->info->conj->a, s2)) && /* or or and? */
2160 (sRef_same (s1->info->conj->b, s2)));
2162 return ((s2->kind == SK_SPECIAL) && s1->info->spec == s2->info->spec);
2164 llassert (s1->info->ref != s1);
2165 return ((s2->kind == SK_DERIVED) && sRef_same (s1->info->ref, s2->info->ref));
2167 case SK_UNCONSTRAINED:
2180 ** sort of similar, for use in def/use
2184 sRef_closeEnough (sRef s1, sRef s2)
2186 if (s1 == s2) return TRUE;
2187 if (sRef_isInvalid (s1) || sRef_isInvalid (s2)) return FALSE;
2192 return (((s2->kind == SK_CVAR) &&
2193 (cref_equal (s1->info->cvar, s2->info->cvar))) ||
2194 (s2->kind == SK_UNCONSTRAINED && s1->info->cvar->lexlevel == 0));
2195 case SK_UNCONSTRAINED:
2196 return (s2->kind == SK_UNCONSTRAINED
2197 || ((s2->kind == SK_CVAR) && (s2->info->cvar->lexlevel == 0)));
2199 return ((s2->kind == SK_PARAM)
2200 && (s1->info->paramno == s2->info->paramno));
2202 if (s2->kind == SK_ARRAYFETCH)
2204 if (sRef_closeEnough (s1->info->arrayfetch->arr, s2->info->arrayfetch->arr))
2206 if (s1->info->arrayfetch->indknown && s2->info->arrayfetch->indknown)
2208 return (s1->info->arrayfetch->ind == s2->info->arrayfetch->ind);
2215 return ((s2->kind == SK_FIELD &&
2216 (sRef_closeEnough (s1->info->field->rec, s2->info->field->rec) &&
2217 cstring_equal (s1->info->field->field, s2->info->field->field))));
2219 return ((s2->kind == SK_PTR) && sRef_closeEnough (s1->info->ref, s2->info->ref));
2221 return ((s2->kind == SK_ADR) && sRef_closeEnough (s1->info->ref, s2->info->ref));
2223 return ((s2->kind == SK_DERIVED) && sRef_closeEnough (s1->info->ref, s2->info->ref));
2225 return ((sRef_closeEnough (s1->info->conj->a, s2)) ||
2226 (sRef_closeEnough (s1->info->conj->b, s2)));
2228 return ((s2->kind == SK_SPECIAL) && s1->info->spec == s2->info->spec);
2244 s is an sRef of a formal paramenter in a function call constraint
2245 we trys to return a constraint expression derived from the actual parementer of a function call.
2248 /*@only@*/ constraintExpr sRef_fixConstraintParam (/*@observer@*/ sRef s, /*@observer@*/ /*@temp@*/ exprNodeList args)
2252 if (sRef_isInvalid (s))
2253 llfatalbug((message("Invalid sRef")));
2259 /* s = sRef_saveCopy(s); */ /*@i523@*/
2260 ce = constraintExpr_makeTermsRef (s);
2267 temp = (sRef_makeField (sRef_fixBaseParam (s->info->field->rec, args),
2268 s->info->field->field));
2269 ce = constraintExpr_makeTermsRef (temp);
2275 temp = (sRef_makePointer (sRef_fixBaseParam (s->info->ref, args)));
2276 /* temp = sRef_saveCopy(temp); */ /*@i523@*/
2277 ce = constraintExpr_makeTermsRef (temp);
2284 temp = sRef_saveCopy(s);
2285 temp = sRef_fixBaseParam (temp, args);
2286 ce = constraintExpr_makeTermsRef (temp);
2294 temp = sRef_saveCopy(s);
2295 ce = constraintExpr_makeTermsRef (temp);
2300 llassert(exprNodeList_size (args) > s->info->paramno);
2302 exprNode e = exprNodeList_nth (args, s->info->paramno);
2304 llassert( !(exprNode_isError (e)) );
2305 ce = constraintExpr_makeExprNode (e);
2312 llcontbug (message ("Trying to do fixConstraintParam on nonparam, nonglobal: %q for function with arguments %q",
2313 sRef_unparse (s), exprNodeList_unparse(args)));
2314 temp = sRef_saveCopy(s);
2315 ce = constraintExpr_makeTermsRef (temp);
2324 sRef_fixBaseParam (/*@returned@*/ sRef s, exprNodeList args)
2326 if (sRef_isInvalid (s)) return (sRef_undefined);
2330 case SK_UNCONSTRAINED:
2335 if (exprNodeList_size (args) > s->info->paramno)
2337 exprNode e = exprNodeList_nth (args, s->info->paramno);
2339 if (exprNode_isError (e))
2341 return sRef_makeUnknown ();
2344 return (exprNode_getSref (e));
2348 return sRef_makeUnknown ();
2353 if (s->info->arrayfetch->indknown)
2355 return (sRef_makeArrayFetchKnown
2356 (sRef_fixBaseParam (s->info->arrayfetch->arr, args),
2357 s->info->arrayfetch->ind));
2361 return (sRef_makeArrayFetch
2362 (sRef_fixBaseParam (s->info->arrayfetch->arr, args)));
2367 DPRINTF (("Fix field: %s", sRef_unparseFull (s)));
2368 res = sRef_makeField (sRef_fixBaseParam (s->info->field->rec, args),
2369 s->info->field->field);
2370 DPRINTF (("Returns: %s", sRef_unparseFull (res)));
2374 return (sRef_makePointer (sRef_fixBaseParam (s->info->ref, args)));
2377 return (sRef_makeAddress (sRef_fixBaseParam (s->info->ref, args)));
2380 return (sRef_makeConj (sRef_fixBaseParam (s->info->conj->a, args),
2381 sRef_fixBaseParam (s->info->conj->b, args)));
2397 sRef_undumpGlobal (char **c)
2407 usymId uid = usymId_fromInt (reader_getInt (c));
2412 reader_checkChar (c, '@');
2413 defstate = sstate_fromInt (reader_getInt (c));
2415 reader_checkChar (c, '@');
2416 nullstate = nstate_fromInt (reader_getInt (c));
2418 ret = sRef_makeGlobal (uid, ctype_unknown, stateInfo_currentLoc ());
2419 sRef_setNullStateN (ret, nullstate);
2420 ret->defstate = defstate;
2425 int i = reader_getInt (c);
2426 speckind sk = speckind_fromInt (i);
2430 case SR_NOTHING: return (sRef_makeNothing ());
2431 case SR_INTERNAL: return (sRef_makeInternalState ());
2432 case SR_SPECSTATE: return (sRef_makeSpecState ());
2433 case SR_SYSTEM: return (sRef_makeSystemState ());
2434 case SR_GLOBALMARKER: BADBRANCH;
2439 return sRef_undefined;
2441 return sRef_makeUnknown ();
2443 return sRef_makeUnknown ();
2445 llfatalerror (message ("sRef_undumpGlobal: bad line: %s",
2446 cstring_fromChars (*c)));
2451 static /*@exposed@*/ sRef sRef_undumpBody (char **c)
2460 return (sRef_makeGlobal (usymId_fromInt (reader_getInt (c)),
2461 ctype_unknown, stateInfo_currentLoc ()));
2463 return (sRef_makeParam (reader_getInt (c), ctype_unknown,
2464 stateInfo_makeLoc (g_currentloc, SA_DECLARED)));
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,
3385 stateInfo_makeLoc (g_currentloc, SA_CREATED));
3390 cstring sRef_getField (sRef s)
3394 llassert (sRef_isReasonable (s));
3395 s = sRef_fixConj (s);
3397 llassertprint (sRef_isReasonable (s) && (s->kind == SK_FIELD),
3398 ("s = %s", sRef_unparseDebug (s)));
3400 res = s->info->field->field;
3404 sRef sRef_getBase (sRef s)
3408 if (sRef_isInvalid (s)) return (sRef_undefined);
3410 s = sRef_fixConj (s);
3421 res = s->info->field->rec;
3425 res = s->info->arrayfetch->arr;
3429 res = sRef_undefined; /* shouldn't need it */
3436 ** same as getBase, except returns invalid
3437 ** (and doesn't use adr's)
3441 sRef_getBaseSafe (sRef s)
3445 if (sRef_isInvalid (s)) { return sRef_undefined; }
3447 s = sRef_fixConj (s);
3455 res = s->info->field->rec; break;
3457 res = s->info->arrayfetch->arr;
3460 res = sRef_undefined; break;
3466 /*@constant int MAXBASEDEPTH;@*/
3467 # define MAXBASEDEPTH 25
3469 static /*@exposed@*/ sRef
3470 sRef_getRootBaseAux (sRef s, int depth)
3472 if (sRef_isInvalid (s)) return sRef_undefined;
3474 if (depth > MAXBASEDEPTH)
3477 ("Warning: reference base limit exceeded for %q. "
3478 "This either means there is a variable with at least "
3479 "%d indirections from this reference, or "
3480 "there is a bug in Splint.",
3485 return sRef_undefined;
3492 return (sRef_getRootBaseAux (s->info->ref, depth + 1));
3494 return (sRef_getRootBaseAux (s->info->field->rec, depth + 1));
3496 return (sRef_getRootBaseAux (s->info->arrayfetch->arr, depth + 1));
3498 return (sRef_getRootBaseAux (sRef_fixConj (s), depth + 1));
3504 sRef sRef_getRootBase (sRef s)
3506 return (sRef_getRootBaseAux (s, 0));
3509 static bool sRef_isDeep (sRef s)
3511 if (sRef_isInvalid (s)) return FALSE;
3521 return (sRef_isDeep (sRef_fixConj (s)));
3527 static int sRef_depth (sRef s)
3529 if (sRef_isInvalid (s)) return 0;
3537 return 1 + sRef_depth (s->info->ref);
3539 return 1 + sRef_depth (s->info->field->rec);
3541 return 1 + sRef_depth (s->info->arrayfetch->arr);
3543 return (sRef_depth (sRef_fixConj (s)));
3550 sRef_makeObject (ctype o)
3552 sRef s = sRef_newRef (); /*@i423 same line is bad...@*/
3554 s->kind = SK_OBJECT;
3555 s->info = (sinfo) dmalloc (sizeof (*s->info));
3556 s->info->object = o;
3557 llassert (valueTable_isUndefined (s->state));
3558 s->state = context_createValueTable (s, stateInfo_makeLoc (g_currentloc, SA_CREATED));
3563 ** This is used to represent storage referenced by a parameter.
3566 sRef sRef_makeExternal (sRef t)
3568 sRef s = sRef_newRef ();
3570 llassert (sRef_isReasonable (t));
3572 s->kind = SK_EXTERNAL;
3573 s->info = (sinfo) dmalloc (sizeof (*s->info));
3575 s->info->ref = t; /* sRef_copy (t); */ /*@i32 was exposed@*/
3576 llassert (valueTable_isUndefined (s->state));
3577 s->state = context_createValueTable (s, stateInfo_makeLoc (g_currentloc, SA_DECLARED));
3581 /*@dependent@*/ sRef sRef_makeDerived (/*@exposed@*/ sRef t)
3583 if (sRef_isReasonable (t))
3585 sRef s = sRef_newRef ();
3587 s->kind = SK_DERIVED;
3588 s->info = (sinfo) dmalloc (sizeof (*s->info));
3589 s->info->ref = t; /* sRef_copy (t); */ /*@i32@*/
3592 llassert (valueTable_isUndefined (s->state));
3593 s->state = context_createValueTable (s, stateInfo_makeLoc (g_currentloc, SA_CREATED));
3598 return sRef_undefined;
3603 ** definitely NOT symmetric:
3605 ** res fills in unknown state information from other
3609 sRef_mergeStateQuiet (sRef res, sRef other)
3611 llassert (sRef_isReasonable (res));
3612 llassert (sRef_isReasonable (other));
3614 res->modified = res->modified || other->modified;
3615 res->safe = res->safe && other->safe;
3617 if (res->defstate == SS_UNKNOWN)
3619 res->defstate = other->defstate;
3620 res->definfo = stateInfo_update (res->definfo, other->definfo);
3623 if (res->aliaskind == AK_UNKNOWN ||
3624 (res->aliaskind == AK_LOCAL && alkind_isKnown (other->aliaskind)))
3626 res->aliaskind = other->aliaskind;
3627 res->oaliaskind = other->oaliaskind;
3628 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
3631 if (res->expkind == XO_UNKNOWN)
3633 res->expkind = other->expkind;
3634 res->oexpkind = other->oexpkind;
3635 res->expinfo = stateInfo_update (res->expinfo, other->expinfo);
3638 /* out takes precedence over implicitly defined */
3639 if (res->defstate == SS_DEFINED && other->defstate != SS_UNKNOWN)
3641 res->defstate = other->defstate;
3642 res->definfo = stateInfo_update (res->definfo, other->definfo);
3645 if (sRef_getNullState (other) == NS_ERROR || sRef_getNullState (res) == NS_ERROR)
3647 sRef_setNullState (res, NS_ERROR, fileloc_undefined);
3651 if (sRef_getNullState (other) != NS_UNKNOWN
3652 && (sRef_getNullState (res) == NS_UNKNOWN || sRef_getNullState (res) == NS_NOTNULL
3653 || sRef_getNullState (res) == NS_MNOTNULL))
3655 sRef_updateNullState (res, other);
3661 ** definitely NOT symmetric:
3663 ** res fills in known state information from other
3667 sRef_mergeStateQuietReverse (/*@dependent@*/ sRef res, /*@dependent@*/ sRef other)
3669 bool changed = FALSE;
3671 llassert (sRef_isReasonable (res));
3672 llassert (sRef_isReasonable (other));
3673 sRef_checkMutable (res);
3675 if (res->kind != other->kind)
3681 res->kind = other->kind;
3682 res->type = other->type;
3683 res->info = sinfo_fullCopy (other);
3687 if (!ctype_equal (res->type, other->type))
3690 res->type = other->type;
3693 sinfo_update (res, other);
3696 res->modified = res->modified || other->modified;
3697 res->safe = res->safe && other->safe;
3699 if (res->aliaskind != other->aliaskind
3700 && (res->aliaskind == AK_UNKNOWN
3701 || ((res->aliaskind == AK_LOCAL
3702 || (res->aliaskind == AK_REFCOUNTED
3703 && other->aliaskind != AK_LOCAL))
3704 && other->aliaskind != AK_UNKNOWN)))
3707 res->aliaskind = other->aliaskind;
3708 res->oaliaskind = other->oaliaskind;
3709 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
3712 if (other->expkind != XO_UNKNOWN && other->expkind != res->expkind)
3715 res->expkind = other->expkind;
3716 res->expinfo = stateInfo_update (res->expinfo, other->expinfo);
3719 if (other->oexpkind != XO_UNKNOWN)
3721 res->oexpkind = other->oexpkind;
3724 /* out takes precedence over implicitly defined */
3726 if (res->defstate != other->defstate)
3728 if (other->defstate != SS_UNKNOWN)
3730 res->defstate = other->defstate;
3731 res->definfo = stateInfo_update (res->definfo, other->definfo);
3735 if (sRef_getNullState (other) == NS_ERROR || sRef_getNullState (res) == NS_ERROR)
3737 if (sRef_getNullState (res) != NS_ERROR)
3739 sRef_setNullStateN (res, NS_ERROR);
3745 if (sRef_getNullState (other) != NS_UNKNOWN
3746 && sRef_getNullState (other) != sRef_getNullState (res))
3749 sRef_updateNullState (res, other);
3755 sRef_clearDerived (res);
3760 sRef_mergeState (sRef res, sRef other, clause cl, fileloc loc)
3762 if (sRef_isReasonable (res) && sRef_isReasonable (other))
3764 sRef_mergeStateAux (res, other, cl, FALSE, loc, TRUE);
3768 if (sRef_isInvalid (res))
3770 llbug (message ("sRef_mergeState: invalid res sRef: %q",
3771 sRef_unparseDebug (other)));
3775 llbug (message ("sRef_mergeState: invalid other sRef: %q",
3776 sRef_unparseDebug (res)));
3782 sRef_mergeOptState (sRef res, sRef other, clause cl, fileloc loc)
3784 if (sRef_isReasonable (res) && sRef_isReasonable (other))
3786 sRef_mergeStateAux (res, other, cl, TRUE, loc, TRUE);
3790 if (sRef_isInvalid (res))
3792 llbug (message ("sRef_mergeOptState: invalid res sRef: %q",
3793 sRef_unparseDebug (other)));
3797 llbug (message ("sRef_mergeOptState: invalid other sRef: %q",
3798 sRef_unparseDebug (res)));
3804 sRef_mergeStateAux (/*@notnull@*/ sRef res, /*@notnull@*/ sRef other,
3805 clause cl, bool opt, fileloc loc,
3809 llassertfatal (sRef_isReasonable (res));
3810 llassertfatal (sRef_isReasonable (other));
3812 DPRINTF (("Merge aux: %s / %s",
3813 sRef_unparseFull (res),
3814 sRef_unparseFull (other)));
3816 sRef_checkMutable (res);
3817 sRef_checkMutable (other);
3819 res->modified = res->modified || other->modified;
3821 if (res->kind == other->kind
3822 || (other->kind == SK_UNKNOWN || res->kind == SK_UNKNOWN))
3824 sstate odef = other->defstate;
3825 sstate rdef = res->defstate;
3826 nstate onull = sRef_getNullState (other);
3829 ** yucky stuff to handle
3834 if (other->defstate == SS_DEAD
3835 && ((sRef_isOnly (res) && sRef_definitelyNull (res))
3836 || (res->defstate == SS_UNDEFINED
3837 || res->defstate == SS_UNUSEABLE)))
3839 if (res->defstate == SS_UNDEFINED
3840 || res->defstate == SS_UNUSEABLE)
3842 res->defstate = SS_UNUSEABLE;
3846 res->defstate = SS_DEAD;
3849 res->definfo = stateInfo_update (res->definfo, other->definfo);
3850 sRef_clearDerived (other);
3851 sRef_clearDerived (res);
3853 else if (res->defstate == SS_DEAD
3854 && ((sRef_isOnly (other) && sRef_definitelyNull (other))
3855 || (other->defstate == SS_UNDEFINED
3856 || other->defstate == SS_UNUSEABLE)))
3858 if (other->defstate == SS_UNDEFINED
3859 || other->defstate == SS_UNUSEABLE)
3861 res->defstate = SS_UNUSEABLE;
3865 res->defstate = SS_DEAD;
3868 res->definfo = stateInfo_update (res->definfo, other->definfo);
3869 sRef_clearDerived (other);
3870 sRef_clearDerived (res);
3872 else if (res->defstate == SS_DEFINED
3873 && (other->defstate == SS_ALLOCATED
3874 && sRef_definitelyNull (other)))
3876 other->defstate = SS_DEFINED; /* definitely null! */
3878 else if (other->defstate == SS_DEFINED
3879 && (res->defstate == SS_ALLOCATED && sRef_definitelyNull (res)))
3881 res->defstate = SS_DEFINED;
3882 res->definfo = stateInfo_update (res->definfo, other->definfo);
3889 if (res->defstate == SS_DEAD && other->defstate == SS_DEAD)
3891 sRef_clearDerived (other);
3892 sRef_clearDerived (res);
3896 ** only & dead isn't really an only!
3899 if (alkind_isOnly (other->aliaskind) && other->defstate == SS_DEAD)
3901 other->aliaskind = AK_UNKNOWN;
3904 if (alkind_isOnly (res->aliaskind) && res->defstate == SS_DEAD)
3906 res->aliaskind = AK_UNKNOWN;
3910 ** Dead and dependent -> dead
3913 if (alkind_isDependent (other->aliaskind) && res->defstate == SS_DEAD)
3915 other->aliaskind = AK_UNKNOWN;
3916 other->defstate = SS_DEAD;
3917 sRef_clearDerived (res);
3918 sRef_clearDerived (other);
3921 if (alkind_isDependent (res->aliaskind) && other->defstate == SS_DEAD)
3923 res->aliaskind = AK_UNKNOWN;
3924 res->defstate = SS_DEAD;
3925 sRef_clearDerived (res);
3926 sRef_clearDerived (other);
3930 ** must do alias combine first, since it depends on
3931 ** original values of state and null.
3934 sRef_combineAliasKinds (res, other, cl, loc);
3935 sRef_combineDefState (res, other);
3936 sRef_combineNullState (res, other);
3938 if (rdef == SS_ALLOCATED || rdef == SS_SPECIAL)
3940 if (odef == SS_DEFINED)
3942 if (onull == NS_DEFNULL || onull == NS_CONSTNULL)
3944 res->deriv = sRefSet_copyInto (res->deriv, other->deriv);
3945 DPRINTF (("Copy derivs: %s", sRef_unparseFull (res)));
3948 else if (odef == SS_ALLOCATED || odef == SS_SPECIAL)
3953 if (ctype_isUnion (ctype_realType (sRef_getType (res))))
3955 res->deriv = sRef_mergeUnionDerivs (res->deriv,
3958 DPRINTF (("Copy derivs: %s", sRef_unparseFull (res)));
3962 res->deriv = sRef_mergeDerivs (res->deriv, other->deriv,
3964 DPRINTF (("Copy derivs: %s", sRef_unparseFull (res)));
3972 res->deriv = sRef_mergeDerivs (res->deriv, other->deriv,
3974 DPRINTF (("Copy derivs: %s", sRef_unparseFull (res)));
3984 if (rdef == SS_PDEFINED
3985 || (rdef == SS_DEFINED && odef == SS_PDEFINED))
3989 res->deriv = sRef_mergePdefinedDerivs (res->deriv, other->deriv,
3991 DPRINTF (("Copy derivs: %s", sRef_unparseFull (res)));
3996 if ((rdef == SS_DEFINED || rdef == SS_UNKNOWN)
3997 && res->defstate == SS_ALLOCATED)
3999 res->deriv = sRefSet_copyInto (res->deriv, other->deriv);
4005 res->deriv = sRef_mergeDerivs (res->deriv, other->deriv,
4007 DPRINTF (("Copy derivs: %s", sRef_unparseFull (res)));
4014 sRef_combineExKinds (res, other);
4018 if (res->kind == SK_ARRAYFETCH && other->kind == SK_PTR)
4020 sRef nother = sRef_buildArrayFetchKnown (sRef_getBase (other), 0);
4022 sRef_copyState (nother, other);
4023 sRef_mergeStateAux (res, nother, cl, opt, loc, doDerivs);
4025 else if (res->kind == SK_PTR && other->kind == SK_ARRAYFETCH)
4027 sRef nother = sRef_buildPointer (sRef_getBase (other));
4029 if (sRef_isReasonable (nother))
4031 sRef_copyState (nother, other);
4032 sRef_mergeStateAux (res, nother, cl, opt, loc, doDerivs);
4037 llcontbug (message ("merge conj: %q / %q", sRef_unparseFull (res),
4038 sRef_unparseFull (other)));
4044 ** Merge value table states
4051 ** This doesn't do anything. And its broken too...
4054 valueTable_elements (res->state, key, sv)
4056 stateValue os = valueTable_lookup (other->state, key);
4057 /*@unused@*/ int val;
4058 /*@unused@*/ char *msg;
4060 llassert (stateValue_isDefined (os));
4062 DPRINTF (("Merge state: %s / %s",
4063 cstring_toCharsSafe (stateValue_unparse (sv)),
4064 cstring_toCharsSafe (stateValue_unparse (os))));
4066 val = valueMatix_lookup (key,
4067 stateValue_getValue (os),
4068 stateValue_getValue (sv),
4070 DPRINTF (("Val: %d / %s", val, msg));
4072 } end_valueTable_elements ;
4075 DPRINTF (("Merge aux: %s / %s",
4076 sRef_unparseFull (res),
4077 sRef_unparseFull (other)));
4081 sRef_mergeUnionDerivs (/*@only@*/ sRefSet res,
4082 /*@exposed@*/ sRefSet other, bool opt,
4083 clause cl, fileloc loc)
4085 if (sRefSet_isEmpty (res))
4087 return sRefSet_copyInto (res, other);
4091 sRefSet_allElements (other, el)
4093 if (sRef_isReasonable (el))
4095 sRef e2 = sRefSet_lookupMember (other, el);
4097 if (sRef_isReasonable (e2))
4099 sRef_mergeStateAux (el, e2, cl, opt, loc, FALSE);
4103 res = sRefSet_insert (res, el);
4106 } end_sRefSet_allElements ;
4112 static /*@only@*/ sRefSet
4113 sRef_mergeDerivs (/*@only@*/ sRefSet res, sRefSet other,
4114 bool opt, clause cl, fileloc loc)
4116 sRefSet ret = sRefSet_new ();
4118 sRefSet_allElements (res, el)
4120 if (sRef_isReasonable (el))
4122 sRef e2 = sRefSet_lookupMember (other, el);
4124 if (sRef_isReasonable (e2))
4126 if (el->defstate == SS_ALLOCATED &&
4127 e2->defstate == SS_PDEFINED)
4129 e2->defstate = SS_ALLOCATED;
4131 else if (e2->defstate == SS_ALLOCATED &&
4132 el->defstate == SS_PDEFINED)
4134 el->defstate = SS_ALLOCATED;
4135 el->definfo = stateInfo_update (el->definfo, e2->definfo);
4136 sRef_clearDerived (el);
4138 else if ((el->defstate == SS_DEAD || sRef_isKept (el)) &&
4139 (e2->defstate == SS_DEFINED && !sRef_isKept (e2)))
4141 DPRINTF (("Checking dead: %s / %s", sRef_unparseFull (el),
4142 sRef_unparseFull (e2)));
4144 if (checkDeadState (el, e2, TRUE, loc))
4146 if (sRef_isThroughArrayFetch (el))
4148 sRef_maybeKill (el, loc);
4149 sRef_maybeKill (e2, loc);
4153 else if ((e2->defstate == SS_DEAD || sRef_isKept (e2)) &&
4154 (el->defstate == SS_DEFINED && !sRef_isKept (el)))
4156 DPRINTF (("Checking dead: %s / %s", sRef_unparseFull (el),
4157 sRef_unparseFull (e2)));
4159 if (checkDeadState (e2, el, FALSE, loc))
4161 if (sRef_isThroughArrayFetch (el))
4163 sRef_maybeKill (el, loc);
4164 sRef_maybeKill (e2, loc);
4168 else if (el->defstate == SS_DEFINED &&
4169 e2->defstate == SS_PDEFINED)
4171 DPRINTF (("set pdefined: %s", sRef_unparseFull (el)));
4172 el->defstate = SS_PDEFINED;
4173 el->definfo = stateInfo_update (el->definfo, e2->definfo);
4175 else if (e2->defstate == SS_DEFINED &&
4176 el->defstate == SS_PDEFINED)
4178 DPRINTF (("set pdefined: %s", sRef_unparseFull (e2)));
4179 e2->defstate = SS_PDEFINED;
4180 e2->definfo = stateInfo_update (e2->definfo, el->definfo);
4187 if (ctype_isUnion (ctype_realType (sRef_getType (el))))
4189 el->deriv = sRef_mergeUnionDerivs (el->deriv, e2->deriv,
4194 el->deriv = sRef_mergeDerivs (el->deriv, e2->deriv, opt, cl, loc);
4197 if (sRef_equivalent (el, e2))
4199 ret = sRefSet_insert (ret, el);
4203 sRef sr = sRef_leastCommon (el, e2);
4205 if (sRef_isReasonable (sr))
4207 ret = sRefSet_insert (ret, sr);
4215 (void) sRefSet_delete (other, e2);
4217 else /* not defined */
4219 DPRINTF (("Checking dead: %s", sRef_unparseFull (el)));
4220 (void) checkDeadState (el, e2, TRUE, loc);
4223 } end_sRefSet_allElements;
4225 sRefSet_allElements (other, el)
4227 if (sRef_isReasonable (el))
4229 DPRINTF (("Checking dead: %s", sRef_unparseFull (el)));
4230 (void) checkDeadState (el, sRef_undefined, FALSE, loc);
4232 } end_sRefSet_allElements;
4239 ** Returns TRUE is there is an error.
4242 static bool checkDeadState (/*@notnull@*/ sRef el, sRef e2, bool tbranch, fileloc loc)
4245 ** usymtab_isGuarded --- the utab should still be in the
4246 ** state of the alternate branch.
4248 ** tbranch TRUE means el is released in the last branch, e.g.
4249 ** if (x != NULL) { ; } else { sfree (x); }
4250 ** so, if x is null in the other branch no error is reported.
4252 ** tbranch FALSE means this is the other branch:
4253 ** if (x != NULL) { sfree (x); } else { ; }
4254 ** so, if x is null in this branch there is no error.
4258 if ((sRef_isDead (el) || sRef_isKept (el))
4259 && !sRef_isDeepUnionField (el)
4260 && !sRef_isThroughArrayFetch (el))
4265 if (usymtab_isDefinitelyNullDeep (el))
4272 if (usymtab_isAltDefinitelyNullDeep (el))
4280 message ("Storage %q is %q in one path, but live in another.",
4282 cstring_makeLiteral (sRef_isKept (el)
4283 ? "kept" : "released")),
4286 if (sRef_isKept (el))
4288 sRef_showAliasInfo (el);
4292 sRef_showStateInfo (el);
4295 if (sRef_isValid (e2))
4297 if (sRef_isKept (e2))
4299 sRef_showAliasInfo (e2);
4303 sRef_showStateInfo (e2);
4307 /* prevent further errors */
4308 el->defstate = SS_UNKNOWN;
4309 sRef_setAliasKind (el, AK_ERROR, fileloc_undefined);
4318 checkDerivDeadState (/*@notnull@*/ sRef el, bool tbranch, fileloc loc)
4320 if (checkDeadState (el, sRef_undefined, tbranch, loc))
4322 sRefSet_allElements (el->deriv, t)
4324 if (sRef_isReasonable (t))
4326 checkDerivDeadState (t, tbranch, loc);
4328 } end_sRefSet_allElements;
4333 sRef_mergePdefinedDerivs (sRefSet res, sRefSet other, bool opt,
4334 clause cl, fileloc loc)
4336 sRefSet ret = sRefSet_new ();
4338 sRefSet_allElements (res, el)
4340 if (sRef_isReasonable (el))
4342 sRef e2 = sRefSet_lookupMember (other, el);
4344 if (sRef_isReasonable (e2))
4346 if (sRef_isAllocated (el) && !sRef_isAllocated (e2))
4350 else if (sRef_isAllocated (e2) && !sRef_isAllocated (el))
4352 el->deriv = sRefSet_copyInto (el->deriv, e2->deriv);
4356 el->deriv = sRef_mergePdefinedDerivs (el->deriv, e2->deriv,
4360 sRef_mergeStateAux (el, e2, cl, opt, loc, FALSE);
4362 ret = sRefSet_insert (ret, el);
4363 (void) sRefSet_delete (other, e2);
4369 checkDerivDeadState (el, (cl == FALSECLAUSE), loc);
4372 ret = sRefSet_insert (ret, el);
4375 } end_sRefSet_allElements;
4377 sRefSet_allElements (other, el)
4379 if (sRef_isReasonable (el))
4381 if (!sRefSet_member (ret, el))
4383 /* was cl == FALSECLAUSE */
4384 checkDerivDeadState (el, FALSE, loc);
4385 ret = sRefSet_insert (ret, el);
4390 ** it's okay --- member is a different equality test
4394 } end_sRefSet_allElements;
4400 sRef sRef_makeConj (/*@exposed@*/ /*@returned@*/ sRef a, /*@exposed@*/ sRef b)
4402 llassert (sRef_isReasonable (a));
4403 llassert (sRef_isReasonable (b));
4405 if (!sRef_equivalent (a, b))
4407 sRef s = sRef_newRef ();
4410 s->info = (sinfo) dmalloc (sizeof (*s->info));
4411 s->info->conj = (cjinfo) dmalloc (sizeof (*s->info->conj));
4412 s->info->conj->a = a; /* sRef_copy (a) */ /*@i32*/ ;
4413 s->info->conj->b = b; /* sRef_copy (b);*/ /*@i32@*/ ;
4415 if (ctype_equal (a->type, b->type)) s->type = a->type;
4416 else s->type = ctype_makeConj (a->type, b->type);
4418 if (a->defstate == b->defstate)
4420 s->defstate = a->defstate;
4421 s->definfo = stateInfo_update (s->definfo, a->definfo);
4422 s->definfo = stateInfo_update (s->definfo, b->definfo);
4426 s->defstate = SS_UNKNOWN;
4429 sRef_setNullStateN (s, NS_UNKNOWN);
4431 s->safe = a->safe && b->safe;
4432 s->aliaskind = alkind_resolve (a->aliaskind, b->aliaskind);
4434 llassert (valueTable_isUndefined (s->state));
4435 s->state = context_createValueTable (s, stateInfo_makeLoc (g_currentloc, SA_MERGED));
4440 /*@-exposetrans@*/ return a; /*@=exposetrans@*/
4444 /*@dependent@*/ sRef
4447 sRef s = sRef_new ();
4449 s->kind = SK_UNKNOWN;
4453 static /*@owned@*/ /*@notnull@*/ sRef
4454 sRef_makeSpecial (speckind sk) /*@*/
4456 sRef s = sRef_new ();
4458 s->kind = SK_SPECIAL;
4459 s->info = (sinfo) dmalloc (sizeof (*s->info));
4461 /*@-dependenttrans@*/
4463 /*@=dependenttrans@*/
4466 static /*@owned@*/ sRef srnothing = sRef_undefined;
4467 static /*@owned@*/ sRef srinternal = sRef_undefined;
4468 static /*@owned@*/ sRef srsystem = sRef_undefined;
4469 static /*@owned@*/ sRef srspec = sRef_undefined;
4471 /*@dependent@*/ sRef
4472 sRef_makeNothing (void)
4474 if (sRef_isInvalid (srnothing))
4476 srnothing = sRef_makeSpecial (SR_NOTHING);
4483 sRef_makeInternalState (void)
4485 if (sRef_isInvalid (srinternal))
4487 srinternal = sRef_makeSpecial (SR_INTERNAL);
4494 sRef_makeSpecState (void)
4496 if (sRef_isInvalid (srspec))
4498 srspec = sRef_makeSpecial (SR_SPECSTATE);
4505 sRef_makeSystemState (void)
4507 if (sRef_isInvalid (srsystem))
4509 srsystem = sRef_makeSpecial (SR_SYSTEM);
4516 sRef_makeGlobalMarker (void)
4518 sRef s = sRef_makeSpecial (SR_GLOBALMARKER);
4519 llassert (valueTable_isUndefined (s->state));
4520 s->state = context_createGlobalMarkerValueTable (stateInfo_undefined);
4525 sRef_makeResult (ctype c)
4527 sRef s = sRef_newRef ();
4529 s->kind = SK_RESULT;
4531 s->defstate = SS_UNKNOWN;
4532 s->aliaskind = AK_UNKNOWN;
4533 sRef_setNullStateN (s, NS_UNKNOWN);
4534 llassert (valueTable_isUndefined (s->state));
4535 s->state = context_createValueTable (s, stateInfo_makeLoc (g_currentloc, SA_DECLARED));
4537 DPRINTF (("Result: [%p] %s", s, sRef_unparseFull (s)));
4543 sRef_isNothing (sRef s)
4545 return (sRef_isKindSpecial (s) && s->info->spec == SR_NOTHING);
4549 sRef_isInternalState (sRef s)
4551 return (sRef_isKindSpecial (s) && s->info->spec == SR_INTERNAL);
4555 sRef_isSpecInternalState (sRef s)
4557 return (sRef_isKindSpecial (s)
4558 && (s->info->spec == SR_INTERNAL || s->info->spec == SR_SPECSTATE));
4562 sRef_isSpecState (sRef s)
4564 return (sRef_isKindSpecial (s) && s->info->spec == SR_SPECSTATE);
4568 sRef_isResult (sRef s)
4570 return (sRef_isReasonable (s) && s->kind == SK_RESULT);
4574 sRef_isSystemState (sRef s)
4576 return (sRef_isKindSpecial (s) && s->info->spec == SR_SYSTEM);
4580 sRef_isGlobalMarker (sRef s)
4582 return (sRef_isKindSpecial (s) && s->info->spec == SR_GLOBALMARKER);
4586 sRef_getScopeIndex (sRef s)
4588 llassert (sRef_isReasonable (s));
4589 llassert (sRef_isCvar (s));
4591 return (s->info->cvar->index);
4595 sRef_makeSafe (sRef s)
4597 if (sRef_isReasonable (s))
4604 sRef_makeUnsafe (sRef s)
4606 if (sRef_isReasonable (s))
4613 ** memory state operations
4616 /*@only@*/ cstring sRef_unparseFull (sRef s)
4618 if (sRef_isInvalid (s)) return (cstring_undefined);
4620 return (message ("[%p] %q - %q { %q } [%s] { %q } < %q >",
4622 sRef_unparseDebug (s),
4623 sRef_unparseState (s),
4624 stateInfo_unparse (s->definfo),
4625 exkind_unparse (s->oexpkind),
4626 sRefSet_unparseDebug (s->deriv),
4627 valueTable_unparse (s->state)));
4630 /*@unused@*/ cstring sRef_unparseDeep (sRef s)
4632 cstring st = cstring_undefined;
4634 st = message ("%q:", sRef_unparseFull (s));
4636 if (sRef_isReasonable (s))
4638 sRefSet_allElements (s->deriv, el)
4640 st = message("%q\n%q", st, sRef_unparseDeep (el));
4641 } end_sRefSet_allElements ;
4647 /*@only@*/ cstring sRef_unparseState (sRef s)
4649 if (sRef_isConj (s))
4651 return (message ("%q | %q",
4652 sRef_unparseState (s->info->conj->a),
4653 sRef_unparseState (s->info->conj->b)));
4656 if (sRef_isInvalid (s))
4658 return (cstring_makeLiteral ("<invalid>"));
4661 return (message ("%s.%s.%s.%s",
4662 alkind_unparse (s->aliaskind),
4663 nstate_unparse (sRef_getNullState (s)),
4664 exkind_unparse (s->expkind),
4665 sstate_unparse (s->defstate)));
4668 bool sRef_isNotUndefined (sRef s)
4670 return (sRef_isInvalid (s)
4671 || (s->defstate != SS_UNDEFINED
4672 && s->defstate != SS_UNUSEABLE
4673 && s->defstate != SS_DEAD));
4676 ynm sRef_isWriteable (sRef s)
4678 if (sRef_isInvalid (s)) return MAYBE;
4680 if (sRef_isConj (s) && s->defstate == SS_UNKNOWN)
4682 if (ynm_toBoolStrict (sRef_isWriteable (sRef_getConjA (s))))
4684 if (ynm_toBoolStrict (sRef_isWriteable (sRef_getConjB (s))))
4692 if (ynm_toBoolStrict (sRef_isWriteable (sRef_getConjB (s))))
4700 return (ynm_fromBool (s->defstate != SS_UNUSEABLE));
4703 bool sRef_hasNoStorage (sRef s)
4705 return (!sRef_isAllocatedStorage (s) || sRef_isDefinitelyNull (s));
4708 bool sRef_isStrictReadable (sRef s)
4710 return (ynm_toBoolStrict (sRef_isValidLvalue (s)));
4714 ** Is this what is does?
4715 ** Returns YES if s can be used as an rvalue,
4716 ** MAYBE if its not clear
4717 ** NO if s cannot be safely used as an rvalue.
4720 ynm sRef_isValidLvalue (sRef s)
4724 if (sRef_isInvalid (s)) return YES;
4728 if (sRef_isConj (s) && s->defstate == SS_UNKNOWN)
4730 if (ynm_toBoolStrict (sRef_isValidLvalue (sRef_getConjA (s))))
4732 if (ynm_toBoolStrict (sRef_isValidLvalue (sRef_getConjB (s))))
4740 if (ynm_toBoolStrict (sRef_isValidLvalue (sRef_getConjB (s))))
4747 else if (ss == SS_HOFFA)
4749 if (context_getFlag (FLG_STRICTUSERELEASED))
4760 return (ynm_fromBool (ss == SS_DEFINED
4763 || ss == SS_PDEFINED
4766 || ss == SS_ALLOCATED
4767 || ss == SS_KILLED /* evans 2001-05-26: added this for killed globals */
4768 || ss == SS_UNKNOWN));
4772 static /*@exposed@*/ sRef whatUndefined (/*@exposed@*/ sRef fref, int depth)
4777 if (depth > MAXDEPTH)
4780 ("Warning: check definition limit exceeded, checking %q. "
4781 "This either means there is a variable with at least "
4782 "%d indirections apparent in the program text, or "
4783 "there is a bug in Splint.",
4784 sRef_unparse (fref),
4788 return sRef_undefined;
4791 if (!sRef_isKnown (fref) || sRef_isAnyDefined (fref))
4793 return sRef_undefined;
4796 if (sRef_isUnuseable (fref) || sRef_isStateUndefined (fref))
4801 ct = ctype_realType (sRef_getType (fref));
4803 if (ctype_isUnknown (ct))
4805 return sRef_undefined;
4807 else if (ctype_isPointer (ct) || ctype_isArray (ct))
4809 if (sRef_isStateUnknown (fref))
4811 return sRef_undefined;
4815 sRef fptr = sRef_constructDeref (fref);
4817 return (whatUndefined (fptr, depth + 1));
4820 else if (ctype_isStruct (ct))
4822 bool hasOneDefined = FALSE;
4824 if (sRef_isStateUnknown (fref))
4829 if (sRef_isPdefined (fref) || sRef_isAnyDefined (fref))
4831 sRefSet_realElements (sRef_derivedFields (fref), sr)
4833 hasOneDefined = TRUE;
4835 if (sRef_isField (sr))
4837 cstring fieldname = sRef_getField (sr);
4838 sRef fldref = sRef_makeField (fref, fieldname);
4839 bool shouldCheck = !sRef_isRecursiveField (fldref);
4843 sRef wdef = whatUndefined (fldref, depth + 1);
4845 if (sRef_isReasonable (wdef))
4851 } end_sRefSet_realElements;
4853 else if (sRef_isAllocated (fref))
4856 ** for structures, each field must be completely defined
4859 uentryList fields = ctype_getFields (ct);
4861 uentryList_elements (fields, ue)
4863 cstring name = uentry_getRealName (ue);
4864 sRef ffield = sRef_makeField (fref, name);
4865 bool shouldCheck = !sRef_isRecursiveField (ffield);
4867 if (sRef_isRelDef (uentry_getSref (ue)))
4875 sRef wdef = whatUndefined (ffield, depth + 1);
4877 if (sRef_isInvalid (wdef))
4883 } end_uentryList_elements;
4890 else if (ctype_isUnion (ct))
4899 return sRef_undefined;
4902 static bool checkDefined (/*@temp@*/ sRef sr)
4904 /*@-temptrans@*/ /* the result from whatUndefined is lost */
4905 return (sRef_isInvalid (whatUndefined (sr, 0)));
4909 bool sRef_isReallyDefined (sRef s)
4911 if (sRef_isReasonable (s))
4913 if (sRef_isAnyDefined (s))
4919 if (sRef_isAllocated (s) || sRef_isPdefined (s))
4921 return checkDefined (s);
4935 void sRef_showNotReallyDefined (sRef s)
4937 if (sRef_isReasonable (s))
4939 if (sRef_isAnyDefined (s))
4945 if (sRef_isAllocated (s) || sRef_isPdefined (s))
4947 /*@-temptrans@*/ /* the result of whatUndefined is lost */
4948 sRef ref = whatUndefined (s, 0);
4950 llassert (sRef_isReasonable (ref));
4955 (message ("This sub-reference is %s: %q",
4956 sstate_unparse (sRef_getDefState (ref)),
4957 sRef_unparse (ref)));
4972 sstate sRef_getDefState (sRef s)
4974 if (sRef_isInvalid (s)) return (SS_UNKNOWN);
4975 return (s->defstate);
4978 void sRef_setDefState (sRef s, sstate defstate, fileloc loc)
4980 sRef_checkMutable (s);
4981 sRef_setStateAux (s, defstate, loc);
4984 static void sRef_clearAliasStateAux (sRef s, fileloc loc)
4986 sRef_checkMutable (s);
4987 sRef_setAliasKind (s, AK_ERROR, loc);
4990 void sRef_clearAliasState (sRef s, fileloc loc)
4992 sRef_checkMutable (s);
4993 sRef_aliasSetComplete (sRef_clearAliasStateAux, s, loc);
4996 void sRef_setAliasKindComplete (sRef s, alkind kind, fileloc loc)
4998 sRef_checkMutable (s);
4999 sRef_aliasSetCompleteAlkParam (sRef_setAliasKind, s, kind, loc);
5002 void sRef_setAliasKind (sRef s, alkind kind, fileloc loc)
5004 sRef_checkMutable (s);
5006 if (sRef_isReasonable (s))
5008 sRef_clearDerived (s);
5010 if ((kind != s->aliaskind && kind != s->oaliaskind)
5011 && fileloc_isDefined (loc))
5013 s->aliasinfo = stateInfo_updateLoc (s->aliasinfo, stateAction_fromAlkind (kind), loc);
5016 s->aliaskind = kind;
5020 void sRef_setOrigAliasKind (sRef s, alkind kind)
5022 sRef_checkMutable (s);
5024 if (sRef_isReasonable (s))
5026 s->oaliaskind = kind;
5030 exkind sRef_getExKind (sRef s)
5032 if (sRef_isReasonable (s))
5034 return (s->expkind);
5042 exkind sRef_getOrigExKind (sRef s)
5044 if (sRef_isReasonable (s))
5046 return (s->oexpkind);
5054 static void sRef_clearExKindAux (sRef s, fileloc loc)
5056 sRef_checkMutable (s);
5057 sRef_setExKind (s, XO_UNKNOWN, loc);
5060 void sRef_setObserver (sRef s, fileloc loc)
5062 sRef_checkMutable (s);
5063 sRef_setExKind (s, XO_OBSERVER, loc);
5066 void sRef_setExposed (sRef s, fileloc loc)
5068 sRef_checkMutable (s);
5069 sRef_setExKind (s, XO_EXPOSED, loc);
5072 void sRef_clearExKindComplete (sRef s, fileloc loc)
5074 (void) sRef_aliasSetComplete (sRef_clearExKindAux, s, loc);
5077 void sRef_setExKind (sRef s, exkind exp, fileloc loc)
5079 sRef_checkMutable (s);
5081 if (sRef_isReasonable (s))
5083 if (s->expkind != exp)
5085 s->expinfo = stateInfo_updateLoc (s->expinfo, stateAction_fromExkind (exp), loc);
5093 ** s1->derived = s2->derived
5096 static void sRef_copyRealDerived (sRef s1, sRef s2)
5098 DPRINTF (("Copy real: %s / %s", sRef_unparse (s1), sRef_unparse (s2)));
5099 sRef_checkMutable (s1);
5101 if (sRef_isReasonable (s1) && sRef_isReasonable (s2))
5103 sRef sb = sRef_getRootBase (s1);
5105 sRefSet_clear (s1->deriv);
5107 sRefSet_allElements (s2->deriv, el)
5109 if (sRef_isReasonable (el))
5111 sRef rb = sRef_getRootBase (el);
5113 if (!sRef_same (rb, sb))
5115 sRef fb = sRef_fixDirectBase (el, s1);
5117 if (sRef_isReasonable (fb))
5119 sRef_copyRealDerived (fb, el);
5120 sRef_addDeriv (s1, fb);
5125 sRef_addDeriv (s1, el);
5128 } end_sRefSet_allElements ;
5133 void sRef_copyRealDerivedComplete (sRef s1, sRef s2)
5135 sRef_innerAliasSetCompleteParam (sRef_copyRealDerived, s1, s2);
5138 void sRef_setUndefined (sRef s, fileloc loc)
5140 sRef_checkMutable (s);
5142 if (sRef_isReasonable (s))
5144 s->defstate = SS_UNDEFINED;
5145 s->definfo = stateInfo_updateLoc (s->definfo, SA_UNDEFINED, loc);
5147 sRef_clearDerived (s);
5151 static void sRef_setDefinedAux (sRef s, fileloc loc, bool clear)
5153 sRef_checkMutable (s);
5154 if (sRef_isInvalid (s)) return;
5156 DPRINTF (("Set defined: %s", sRef_unparseFull (s)));
5158 s->definfo = stateInfo_updateLoc (s->definfo, SA_DEFINED, loc);
5159 s->defstate = SS_DEFINED;
5161 DPRINTF (("Set defined: %s", sRef_unparseFull (s)));
5163 /* e.g., if x is allocated, *x = 3 defines x */
5165 if (s->kind == SK_PTR)
5167 sRef p = s->info->ref;
5170 if (p->defstate == SS_ALLOCATED
5171 || p->defstate == SS_SPECIAL) /* evans 2001-07-12: shouldn't need this */
5173 sRef_setDefinedAux (p, loc, clear);
5177 ** Defines a[0] also:
5180 arr = sRef_findDerivedArrayFetch (p, FALSE, 0, FALSE);
5182 if (sRef_isReasonable (arr))
5184 sRef_setDefinedAux (arr, loc, clear);
5187 else if (s->kind == SK_ARRAYFETCH)
5189 if (!s->info->arrayfetch->indknown
5190 || (s->info->arrayfetch->ind == 0))
5192 sRef p = s->info->arrayfetch->arr;
5193 sRef ptr = sRef_constructPointer (p);
5195 if (sRef_isReasonable (ptr))
5197 if (ptr->defstate == SS_ALLOCATED
5198 || ptr->defstate == SS_UNDEFINED
5199 || ptr->defstate == SS_SPECIAL) /* evans 2001-07-12: shouldn't need this */
5201 sRef_setDefinedAux (ptr, loc, clear);
5205 if (p->defstate == SS_RELDEF)
5209 else if (p->defstate == SS_ALLOCATED || p->defstate == SS_PDEFINED
5210 || p->defstate == SS_SPECIAL) /* evans 2001-07-12: shouldn't need this */
5212 p->defstate = SS_DEFINED;
5219 else if (s->kind == SK_FIELD)
5221 sRef parent = s->info->field->rec;
5223 if (sRef_isReasonable (parent))
5225 if (ctype_isUnion (ctype_realType (parent->type)))
5228 ** Should not clear derived from here.
5231 sRef_setDefinedNoClear (parent, loc);
5235 ; /* Nothing to do for structures. */
5247 sRef_clearDerived (s);
5251 /* evans 2001-07-12: need to define the derived references */
5252 sRefSet_elements (s->deriv, el)
5254 llassert (sRef_isReasonable (el));
5255 el->defstate = SS_DEFINED;
5256 } end_sRefSet_elements ;
5259 DPRINTF (("Set defined: %s", sRef_unparseFull (s)));
5262 static void sRef_setPartialDefined (sRef s, fileloc loc)
5264 sRef_checkMutable (s);
5266 if (!sRef_isPartial (s))
5268 sRef_setDefined (s, loc);
5272 void sRef_setPartialDefinedComplete (sRef s, fileloc loc)
5274 sRef_innerAliasSetComplete (sRef_setPartialDefined, s, loc);
5277 void sRef_setDefinedComplete (sRef s, fileloc loc)
5279 sRef_innerAliasSetComplete (sRef_setDefined, s, loc);
5282 void sRef_setDefinedCompleteDirect (sRef s, fileloc loc)
5286 aliases = usymtab_allAliases (s);
5287 DPRINTF (("Set defined complete: %s", sRef_unparseFull (s)));
5288 DPRINTF (("All aliases: %s", sRefSet_unparseFull (aliases)));
5290 sRef_setDefined (s, loc);
5292 sRefSet_realElements (aliases, current)
5294 if (sRef_isReasonable (current))
5296 current = sRef_updateSref (current);
5297 sRef_setDefined (current, loc);
5299 } end_sRefSet_realElements;
5301 sRefSet_free (aliases);
5302 sRef_innerAliasSetComplete (sRef_setDefined, s, loc);
5305 void sRef_setDefined (sRef s, fileloc loc)
5307 sRef_checkMutable (s);
5308 sRef_setDefinedAux (s, loc, TRUE);
5311 static void sRef_setDefinedNoClear (sRef s, fileloc loc)
5313 sRef_checkMutable (s);
5314 DPRINTF (("Defining: %s", sRef_unparseFull (s)));
5315 sRef_setDefinedAux (s, loc, FALSE);
5316 DPRINTF (("==> %s", sRef_unparseFull (s)));
5319 void sRef_setDefinedNCComplete (sRef s, fileloc loc)
5321 sRef_checkMutable (s);
5322 DPRINTF (("Set Defined Complete: %s", sRef_unparseFull (s)));
5323 sRef_innerAliasSetComplete (sRef_setDefinedNoClear, s, loc);
5324 DPRINTF (("==> %s", sRef_unparseFull (s)));
5327 static bool sRef_isDeepUnionField (sRef s)
5329 return (sRef_deepPred (sRef_isUnionField, s));
5332 bool sRef_isUnionField (sRef s)
5334 if (sRef_isReasonable (s) && s->kind == SK_FIELD)
5337 ** defining one field of a union defines the union
5340 sRef base = s->info->field->rec;
5342 if (sRef_isReasonable (base))
5344 return (ctype_isUnion (ctype_realType (base->type)));
5351 void sRef_setPdefined (sRef s, fileloc loc)
5353 sRef_checkMutable (s);
5354 if (sRef_isReasonable (s) && !sRef_isPartial (s))
5356 sRef base = sRef_getBaseSafe (s);
5358 if (s->defstate == SS_ALLOCATED)
5363 s->definfo = stateInfo_updateLoc (s->definfo, SA_PDEFINED, loc);
5364 s->defstate = SS_PDEFINED;
5366 /* e.g., if x is allocated, *x = 3 defines x */
5368 while (sRef_isReasonable (base) && sRef_isKnown (base))
5370 if (base->defstate == SS_DEFINED)
5374 DPRINTF (("set pdefined: %s", sRef_unparseFull (base)));
5375 base->defstate = SS_PDEFINED;
5376 nb = sRef_getBaseSafe (base);
5387 static void sRef_setStateAux (sRef s, sstate ss, fileloc loc)
5389 sRef_checkMutable (s);
5391 DPRINTF (("Set state: %s => %s", sRef_unparseFull (s), sstate_unparse (ss)));
5393 if (sRef_isReasonable (s))
5395 /* if (s->defstate == SS_RELDEF) return; */
5397 if (s->defstate != ss && fileloc_isDefined (loc))
5399 s->definfo = stateInfo_updateLoc (s->definfo,
5400 stateAction_fromSState (ss), loc);
5404 sRef_clearDerived (s);
5406 if (ss == SS_ALLOCATED)
5408 sRef base = sRef_getBaseSafe (s);
5410 while (sRef_isReasonable (base) && sRef_isKnown (base))
5412 if (base->defstate == SS_DEFINED)
5416 DPRINTF (("set pdefined: %s", sRef_unparseFull (s)));
5417 base->defstate = SS_PDEFINED;
5418 nb = sRef_getBaseSafe (base);
5430 void sRef_setAllocatedComplete (sRef s, fileloc loc)
5432 sRef_innerAliasSetComplete (sRef_setAllocated, s, loc);
5435 static void sRef_setAllocatedShallow (sRef s, fileloc loc)
5437 sRef_checkMutable (s);
5439 if (sRef_isReasonable (s))
5441 if (s->defstate == SS_DEAD || s->defstate == SS_UNDEFINED)
5443 s->defstate = SS_ALLOCATED;
5444 s->definfo = stateInfo_updateLoc (s->definfo, SA_ALLOCATED, loc);
5449 void sRef_setAllocatedShallowComplete (sRef s, fileloc loc)
5451 sRef_innerAliasSetComplete (sRef_setAllocatedShallow, s, loc);
5454 void sRef_setAllocated (sRef s, fileloc loc)
5456 sRef_checkMutable (s);
5457 sRef_setStateAux (s, SS_ALLOCATED, loc);
5460 void sRef_setPartial (sRef s, fileloc loc)
5462 sRef_checkMutable (s);
5463 sRef_setStateAux (s, SS_PARTIAL, loc);
5466 void sRef_setShared (sRef s, fileloc loc)
5468 sRef_checkMutable (s);
5470 if (sRef_isReasonable (s))
5472 if (s->aliaskind != AK_SHARED && fileloc_isDefined (loc))
5474 s->aliasinfo = stateInfo_updateLoc (s->aliasinfo, SA_SHARED, loc);
5477 s->aliaskind = AK_SHARED;
5478 /* don't! sRef_clearDerived (s); */
5482 void sRef_setLastReference (sRef s, /*@exposed@*/ sRef ref, fileloc loc)
5484 sRef_checkMutable (s);
5486 if (sRef_isReasonable (s))
5488 s->aliaskind = sRef_getAliasKind (ref);
5489 s->aliasinfo = stateInfo_updateRefLoc (s->aliasinfo, ref, stateAction_fromAlkind (s->aliaskind), loc);
5494 void sRef_setNullStateAux (/*@notnull@*/ sRef s, nstate ns, fileloc loc)
5496 sRef_checkMutable (s);
5498 sRef_resetAliasKind (s);
5500 if (fileloc_isDefined (loc))
5502 s->nullinfo = stateInfo_updateLoc (s->nullinfo, stateAction_fromNState (ns), loc);
5506 void sRef_setNotNull (sRef s, fileloc loc)
5508 if (sRef_isReasonable (s))
5510 sRef_setNullStateAux (s, NS_NOTNULL, loc);
5514 void sRef_setNullStateN (sRef s, nstate n)
5516 if (sRef_isReasonable (s))
5518 sRef_checkMutable (s);
5520 sRef_resetAliasKind (s);
5524 void sRef_setNullState (sRef s, nstate n, fileloc loc)
5526 if (sRef_isReasonable (s))
5528 sRef_setNullStateAux (s, n, loc);
5532 void sRef_setNullTerminatedStateInnerComplete (sRef s, struct s_bbufinfo b, /*@unused@*/ fileloc loc)
5534 switch (b.bufstate) {
5535 case BB_NULLTERMINATED:
5536 sRef_setNullTerminatedState (s);
5537 sRef_setLen (s, b.len);
5539 case BB_POSSIBLYNULLTERMINATED:
5540 sRef_setPossiblyNullTerminatedState(s);
5542 case BB_NOTNULLTERMINATED:
5543 sRef_setNotNullTerminatedState (s);
5547 sRef_setSize (s, b.size);
5549 /* PL: TO BE DONE : Aliases are not modified right now, have to be similar to
5550 * setNullStateInnerComplete.
5554 void sRef_setNullStateInnerComplete (sRef s, nstate n, fileloc loc)
5556 DPRINTF (("Set null state: %s", nstate_unparse (n)));
5558 sRef_setNullState (s, n, loc);
5563 sRef_innerAliasSetComplete (sRef_setPosNull, s, loc);
5566 sRef_innerAliasSetComplete (sRef_setDefNull, s, loc);
5569 sRef_innerAliasSetComplete (sRef_setNullUnknown, s, loc);
5572 sRef_innerAliasSetComplete (sRef_setNotNull, s, loc);
5575 sRef_innerAliasSetComplete (sRef_setNotNull, s, loc);
5578 sRef_innerAliasSetComplete (sRef_setNullUnknown, s, loc);
5581 sRef_innerAliasSetComplete (sRef_setDefNull, s, loc);
5584 sRef_innerAliasSetComplete (sRef_setNullUnknown, s, loc);
5587 sRef_innerAliasSetComplete (sRef_setNullErrorLoc, s, loc);
5592 void sRef_setPosNull (sRef s, fileloc loc)
5594 if (sRef_isReasonable (s))
5596 sRef_setNullStateAux (s, NS_POSNULL, loc);
5600 void sRef_setDefNull (sRef s, fileloc loc)
5602 if (sRef_isReasonable (s))
5604 sRef_setNullStateAux (s, NS_DEFNULL, loc);
5608 void sRef_setNullUnknown (sRef s, fileloc loc)
5610 if (sRef_isReasonable (s))
5612 sRef_setNullStateAux (s, NS_UNKNOWN, loc);
5616 void sRef_setNullError (sRef s)
5618 if (sRef_isReasonable (s) && !sRef_isConst (s))
5620 sRef_setNullStateAux (s, NS_UNKNOWN, fileloc_undefined);
5624 void sRef_setNullErrorLoc (sRef s, fileloc loc)
5626 if (sRef_isReasonable (s) && !sRef_isConst (s))
5628 sRef_setNullStateAux (s, NS_UNKNOWN, loc);
5632 void sRef_setOnly (sRef s, fileloc loc)
5634 if (sRef_isReasonable (s) && s->aliaskind != AK_ONLY)
5636 sRef_checkMutable (s);
5637 s->aliaskind = AK_ONLY;
5638 s->aliasinfo = stateInfo_updateLoc (s->aliasinfo, SA_ONLY, loc);
5642 void sRef_setDependent (sRef s, fileloc loc)
5644 if (sRef_isReasonable (s) && !sRef_isConst (s) && (s->aliaskind != AK_DEPENDENT))
5646 sRef_checkMutable (s);
5647 DPRINTF (("Setting dependent: %s", sRef_unparseFull (s)));
5648 s->aliaskind = AK_DEPENDENT;
5649 s->aliasinfo = stateInfo_updateLoc (s->aliasinfo, SA_DEPENDENT, loc);
5653 void sRef_setOwned (sRef s, fileloc loc)
5655 if (sRef_isReasonable (s) && !sRef_isConst (s) && (s->aliaskind != AK_OWNED))
5657 sRef_checkMutable (s);
5658 s->aliaskind = AK_OWNED;
5659 s->aliasinfo = stateInfo_updateLoc (s->aliasinfo, SA_OWNED, loc);
5663 void sRef_setKept (sRef s, fileloc loc)
5665 if (sRef_isReasonable (s) && !sRef_isConst (s) && (s->aliaskind != AK_KEPT))
5667 sRef base = sRef_getBaseSafe (s);
5669 while (sRef_isReasonable (base) && sRef_isKnown (base))
5671 if (base->defstate == SS_DEFINED)
5673 sRef_checkMutable (base);
5674 base->defstate = SS_PDEFINED;
5675 base = sRef_getBaseSafe (base);
5683 sRef_checkMutable (s);
5684 s->aliaskind = AK_KEPT;
5685 s->aliasinfo = stateInfo_updateLoc (s->aliasinfo, SA_KEPT, loc);
5689 static void sRef_setKeptAux (sRef s, fileloc loc)
5691 if (!sRef_isShared (s))
5693 sRef_setKept (s, loc);
5697 static void sRef_setDependentAux (sRef s, fileloc loc)
5699 if (!sRef_isShared (s))
5701 sRef_setDependent (s, loc);
5705 void sRef_setKeptComplete (sRef s, fileloc loc)
5707 sRef_aliasSetComplete (sRef_setKeptAux, s, loc);
5710 void sRef_setDependentComplete (sRef s, fileloc loc)
5712 sRef_aliasSetComplete (sRef_setDependentAux, s, loc);
5715 void sRef_setFresh (sRef s, fileloc loc)
5717 if (sRef_isReasonable (s) && !sRef_isConst (s))
5719 sRef_checkMutable (s);
5720 s->aliaskind = AK_FRESH;
5721 s->aliasinfo = stateInfo_updateLoc (s->aliasinfo, SA_CREATED, loc);
5722 DPRINTF (("SetFresh: %s", sRef_unparseFull (s)));
5726 void sRef_kill (sRef s, fileloc loc)
5728 DPRINTF (("Kill: %s", sRef_unparseFull (s)));
5730 if (sRef_isReasonable (s) && !sRef_isShared (s) && !sRef_isConst (s))
5732 sRef base = sRef_getBaseSafe (s);
5733 sRef_checkMutable (s);
5735 while (sRef_isReasonable (base) && sRef_isKnown (base))
5737 if (base->defstate == SS_DEFINED)
5739 sRef_checkMutable (base);
5740 base->defstate = SS_PDEFINED;
5741 base = sRef_getBaseSafe (base);
5749 s->aliaskind = s->oaliaskind;
5750 s->defstate = SS_DEAD;
5751 s->definfo = stateInfo_updateLoc (s->definfo, SA_KILLED, loc);
5752 DPRINTF (("State info: %s", stateInfo_unparse (s->definfo)));
5753 sRef_clearDerived (s);
5757 void sRef_maybeKill (sRef s, fileloc loc)
5759 if (sRef_isReasonable (s))
5761 sRef base = sRef_getBaseSafe (s);
5762 sRef_checkMutable (s);
5764 while (sRef_isReasonable (base) && sRef_isKnown (base))
5766 if (base->defstate == SS_DEFINED || base->defstate == SS_RELDEF)
5768 sRef_checkMutable (base);
5769 base->defstate = SS_PDEFINED;
5770 base = sRef_getBaseSafe (base);
5779 s->aliaskind = s->oaliaskind;
5780 s->defstate = SS_HOFFA;
5781 s->definfo = stateInfo_updateLoc (s->definfo, SA_PKILLED, loc);
5782 DPRINTF (("State info: %s / %s", sRef_unparse (s),
5783 stateInfo_unparse (s->definfo)));
5784 sRef_clearDerived (s);
5790 ** just for type checking...
5793 static void sRef_killAux (sRef s, fileloc loc)
5795 if (sRef_isReasonable (s) && !sRef_isShared (s))
5797 if (sRef_isUnknownArrayFetch (s))
5799 sRef_maybeKill (s, loc);
5809 ** kills s and all aliases to s
5812 void sRef_killComplete (sRef s, fileloc loc)
5814 DPRINTF (("Kill complete: %s", sRef_unparseFull (s)));
5815 sRef_aliasSetComplete (sRef_killAux, s, loc);
5818 static bool sRef_equivalent (sRef s1, sRef s2)
5820 return (sRef_compare (s1, s2) == 0);
5824 ** returns an sRef that will not be free'd on function exit.
5827 /*@only@*/ sRef sRef_saveCopy (sRef s)
5831 if (sRef_isReasonable (s))
5833 bool old = inFunction;
5836 ** Exit the function scope, so this sRef is not
5837 ** stored in the deallocation table.
5841 DPRINTF (("Copying sref: %s", sRef_unparseFull(s)));
5842 ret = sRef_copy (s);
5843 DPRINTF (("Copying ===>: %s", sRef_unparseFull(ret)));
5848 ret = sRef_undefined;
5851 /*@-dependenttrans@*/
5853 /*@=dependenttrans@*/
5856 sRef sRef_copy (sRef s)
5858 if (sRef_isKindSpecial (s) && !sRef_isGlobalMarker (s))
5861 return s; /* don't copy specials (except for global markers) */
5865 if (sRef_isReasonable (s))
5867 sRef t = sRef_alloc ();
5869 DPRINTF (("Copying: [%p] %s", s, sRef_unparse (s)));
5870 DPRINTF (("Full: %s", sRef_unparseFull (s)));
5874 t->modified = s->modified;
5875 t->immut = FALSE; /* Note mutability is not copied. */
5877 t->val = multiVal_copy (s->val);
5879 t->info = sinfo_copy (s);
5880 t->defstate = s->defstate;
5881 t->nullstate = s->nullstate;
5883 /* start modifications */
5884 t->bufinfo.bufstate = s->bufinfo.bufstate;
5885 t->bufinfo.len = s->bufinfo.len;
5886 t->bufinfo.size = s->bufinfo.size;
5887 /* end modifications */
5889 t->aliaskind = s->aliaskind;
5890 t->oaliaskind = s->oaliaskind;
5892 t->expkind = s->expkind;
5893 t->oexpkind = s->oexpkind;
5895 t->nullinfo = stateInfo_copy (s->nullinfo);
5896 t->aliasinfo = stateInfo_copy (s->aliasinfo);
5897 t->definfo = stateInfo_copy (s->definfo);
5898 t->expinfo = stateInfo_copy (s->expinfo);
5900 t->deriv = sRefSet_newDeepCopy (s->deriv);
5901 t->state = valueTable_copy (s->state);
5903 DPRINTF (("Made copy: %s => %s", sRef_unparseFull (s), sRef_unparseFull (t)));
5908 return sRef_undefined;
5913 # define PREDTEST(func,s) \
5914 do { if (sRef_isInvalid (s)) { return FALSE; } \
5915 else { if (sRef_isConj (s)) \
5916 { return (func (sRef_getConjA (s)) \
5917 || func (sRef_getConjB (s))); }}} while (FALSE);
5919 bool sRef_isAddress (sRef s)
5921 PREDTEST (sRef_isAddress, s);
5922 return (s->kind == SK_ADR);
5926 ** pretty weak... maybe a flag should control this.
5929 bool sRef_isThroughArrayFetch (sRef s)
5931 if (sRef_isReasonable (s))
5939 if (sRef_isArrayFetch (tref))
5944 lt = sRef_getBase (tref);
5946 } while (sRef_isReasonable (tref));
5952 bool sRef_isArrayFetch (sRef s)
5954 PREDTEST (sRef_isArrayFetch, s);
5955 return (s->kind == SK_ARRAYFETCH);
5958 bool sRef_isMacroParamRef (sRef s)
5960 if (context_inMacro () && sRef_isCvar (s))
5962 uentry ue = sRef_getUentry (s);
5963 cstring pname = makeParam (uentry_rawName (ue));
5964 uentry mac = usymtab_lookupSafe (pname);
5966 cstring_free (pname);
5967 return (uentry_isValid (mac));
5973 bool sRef_isCvar (sRef s)
5975 PREDTEST (sRef_isCvar, s);
5976 return (s->kind == SK_CVAR);
5979 bool sRef_isConst (sRef s)
5981 PREDTEST (sRef_isConst, s);
5982 return (s->kind == SK_CONST);
5985 bool sRef_isObject (sRef s)
5987 PREDTEST (sRef_isObject, s);
5988 return (s->kind == SK_OBJECT);
5991 bool sRef_isExternal (sRef s)
5993 PREDTEST (sRef_isExternal, s);
5994 return (s->kind == SK_EXTERNAL);
5997 static bool sRef_isDerived (sRef s)
5999 PREDTEST (sRef_isDerived, s);
6000 return (s->kind == SK_DERIVED);
6003 bool sRef_isField (sRef s)
6005 PREDTEST (sRef_isField, s);
6006 return (s->kind == SK_FIELD);
6009 static bool sRef_isIndex (sRef s)
6011 PREDTEST (sRef_isIndex, s);
6012 return (s->kind == SK_ARRAYFETCH);
6015 bool sRef_isAnyParam (sRef s)
6017 PREDTEST (sRef_isAnyParam, s);
6018 return (s->kind == SK_PARAM);
6021 bool sRef_isParam (sRef s)
6023 PREDTEST (sRef_isParam, s);
6024 return (s->kind == SK_PARAM);
6027 bool sRef_isDirectParam (sRef s)
6029 PREDTEST (sRef_isDirectParam, s);
6031 return ((s->kind == SK_CVAR) &&
6032 (s->info->cvar->lexlevel == functionScope) &&
6033 (context_inFunction () &&
6034 (s->info->cvar->index <= uentryList_size (context_getParams ()))));
6037 bool sRef_isPointer (sRef s)
6039 PREDTEST (sRef_isPointer, s);
6040 return (s->kind == SK_PTR);
6044 ** returns true if storage referenced by s is visible
6047 bool sRef_isReference (sRef s)
6049 PREDTEST (sRef_isReference, s);
6051 return (sRef_isPointer (s) || sRef_isIndex (s) || sRef_isFileOrGlobalScope (s)
6052 || (sRef_isField (s) && (sRef_isReference (s->info->field->rec))));
6055 bool sRef_isIReference (sRef s)
6057 return (sRef_isPointer (s) || sRef_isAddress (s) || sRef_isIndex (s)
6058 || sRef_isField (s) || sRef_isArrayFetch (s));
6061 bool sRef_isFileOrGlobalScope (sRef s)
6063 return (sRef_isCvar (s) && (s->info->cvar->lexlevel <= fileScope));
6066 bool sRef_isRealGlobal (sRef s)
6068 return (sRef_isCvar (s) && (s->info->cvar->lexlevel == globScope));
6071 bool sRef_isFileStatic (sRef s)
6073 return (sRef_isCvar (s) && (s->info->cvar->lexlevel == fileScope));
6076 bool sRef_isAliasCheckedGlobal (sRef s)
6078 if (sRef_isFileOrGlobalScope (s))
6080 uentry ue = sRef_getUentry (s);
6082 return context_checkAliasGlob (ue);
6090 void sRef_free (/*@only@*/ sRef s)
6092 if (s != sRef_undefined && s->kind != SK_SPECIAL)
6094 DPRINTF (("Free sref: [%p]", s));
6096 sRef_checkValid (s);
6098 multiVal_free (s->val); /* evans 2002-07-12 */
6100 stateInfo_free (s->expinfo);
6101 stateInfo_free (s->aliasinfo);
6102 stateInfo_free (s->definfo);
6103 stateInfo_free (s->nullinfo);
6105 sRefSet_free (s->deriv);
6106 s->deriv = sRefSet_undefined;
6108 valueTable_free (s->state);
6112 /* drl added to help locate use after release*/
6113 s->expinfo = stateInfo_undefined;
6114 s->aliasinfo = stateInfo_undefined;
6115 s->definfo = stateInfo_undefined;
6116 s->nullinfo = stateInfo_undefined;
6118 /*@i32@*/ sfree (s);
6122 void sRef_setType (sRef s, ctype t)
6124 if (sRef_isReasonable (s))
6126 sRef_checkMutable (s);
6131 void sRef_setTypeFull (sRef s, ctype t)
6133 if (sRef_isReasonable (s))
6135 sRef_checkMutable (s);
6138 sRefSet_allElements (s->deriv, current)
6140 sRef_setTypeFull (current, ctype_unknown);
6141 } end_sRefSet_allElements ;
6146 sRef_buildField (/*@exposed@*/ sRef rec, /*@dependent@*/ cstring f)
6148 return (sRef_buildNCField (rec, f));
6151 static /*@exposed@*/ sRef
6152 sRef_findDerivedField (/*@notnull@*/ sRef rec, cstring f)
6154 sRefSet_allElements (sRef_derivedFields (rec), sr)
6156 if (sRef_isReasonable (sr))
6158 if (sRef_isReasonable (sr))
6160 if (sr->info != NULL)
6162 if (sr->kind == SK_FIELD && cstring_equal (sr->info->field->field, f))
6170 llcontbug (message ("Invalid sRef as derived field of %s", sRef_unparse (rec)));
6173 } end_sRefSet_allElements;
6175 return sRef_undefined;
6178 /*@dependent@*/ /*@observer@*/ sRefSet sRef_derivedFields (/*@temp@*/ sRef rec)
6180 if (sRef_isReasonable (rec))
6188 return (sRefSet_undefined);
6192 static /*@exposed@*/ sRef
6193 sRef_findDerivedPointer (sRef s)
6195 if (sRef_isReasonable (s))
6197 sRefSet_realElements (s->deriv, sr)
6199 if (sRef_isReasonable (sr) && sr->kind == SK_PTR)
6203 } end_sRefSet_realElements;
6206 return sRef_undefined;
6210 sRef_isUnknownArrayFetch (sRef s)
6212 return (sRef_isReasonable (s)
6213 && s->kind == SK_ARRAYFETCH
6214 && !s->info->arrayfetch->indknown);
6217 static /*@exposed@*/ sRef
6218 sRef_findDerivedArrayFetch (/*@notnull@*/ sRef s, bool isknown, int idx, bool dead)
6223 sRefSet_realElements (s->deriv, sr)
6225 if (sRef_isReasonable (sr)
6226 && sr->kind == SK_ARRAYFETCH
6227 && sr->info->arrayfetch->indknown
6228 && (sr->info->arrayfetch->ind == idx))
6232 } end_sRefSet_realElements;
6236 sRefSet_realElements (s->deriv, sr)
6238 if (sRef_isReasonable (sr)
6239 && sr->kind == SK_ARRAYFETCH
6240 && (!sr->info->arrayfetch->indknown
6241 || (sr->info->arrayfetch->indknown &&
6242 sr->info->arrayfetch->ind == 0)))
6244 if (sRef_isDead (sr) || sRef_isKept (sr))
6246 if (dead || context_getFlag (FLG_STRICTUSERELEASED))
6256 } end_sRefSet_realElements;
6259 return sRef_undefined;
6262 static /*@exposed@*/ sRef
6263 sRef_buildNCField (/*@exposed@*/ sRef rec, /*@exposed@*/ cstring f)
6267 DPRINTF (("Build nc field: %s / %s",
6268 sRef_unparseFull (rec), f));
6270 if (sRef_isInvalid (rec))
6272 return sRef_undefined;
6276 ** check if the field already has been referenced
6279 s = sRef_findDerivedField (rec, f);
6281 if (sRef_isReasonable (s))
6287 ctype ct = ctype_realType (rec->type);
6289 DPRINTF (("Field of: %s", sRef_unparse (rec)));
6293 s->info = (sinfo) dmalloc (sizeof (*s->info));
6294 s->info->field = (fldinfo) dmalloc (sizeof (*s->info->field));
6295 s->info->field->rec = rec; /* sRef_copy (rec); */ /*@i32@*/
6296 s->info->field->field = f; /* doesn't copy f */
6298 if (ctype_isKnown (ct) && ctype_isSU (ct))
6300 uentry ue = uentryList_lookupField (ctype_getFields (ct), f);
6302 if (!uentry_isUndefined (ue))
6304 DPRINTF (("lookup: %s for %s", uentry_unparseFull (ue),
6305 ctype_unparse (ct)));
6307 s->type = uentry_getType (ue);
6309 if (ctype_isMutable (s->type)
6310 && rec->aliaskind != AK_STACK
6311 && !alkind_isStatic (rec->aliaskind))
6313 s->aliaskind = rec->aliaskind;
6317 s->aliaskind = AK_UNKNOWN;
6320 if (sRef_isStateDefined (rec) || sRef_isStateUnknown (rec)
6321 || sRef_isPdefined (rec))
6323 sRef_setStateFromUentry (s, ue);
6327 sRef_setPartsFromUentry (s, ue);
6330 s->oaliaskind = s->aliaskind;
6331 s->oexpkind = s->expkind;
6333 DPRINTF (("sref: %s", sRef_unparseFull (s)));
6338 Never report this as an error. It can happen whenever there
6339 is casting involved.
6343 llcontbug (message ("buildNCField --- no field %s: %q / %s",
6344 f, sRef_unparse (s), ctype_unparse (ct)));
6348 return sRef_undefined;
6352 if (rec->defstate == SS_DEFINED
6353 && (s->defstate == SS_UNDEFINED || s->defstate == SS_UNKNOWN))
6355 s->defstate = SS_DEFINED;
6357 else if (rec->defstate == SS_PARTIAL)
6359 s->defstate = SS_PARTIAL;
6361 else if (rec->defstate == SS_ALLOCATED)
6363 if (ctype_isStackAllocated (ct) && ctype_isStackAllocated (s->type))
6365 s->defstate = SS_ALLOCATED;
6369 s->defstate = SS_UNDEFINED;
6372 else if (s->defstate == SS_UNKNOWN)
6374 s->defstate = rec->defstate;
6381 if (s->defstate == SS_UNDEFINED)
6383 ctype rt = ctype_realType (s->type);
6385 if (ctype_isArray (rt) || ctype_isSU (rt))
6387 s->defstate = SS_ALLOCATED;
6391 sRef_addDeriv (rec, s);
6392 DPRINTF (("Add deriv: %s", sRef_unparseFull (rec)));
6394 if (ctype_isInt (s->type) && cstring_equal (f, REFSNAME))
6396 s->aliaskind = AK_REFS;
6397 s->oaliaskind = AK_REFS;
6400 DPRINTF (("Build field ==> %s", sRef_unparseFull (s)));
6406 sRef_isStackAllocated (sRef s)
6408 return (sRef_isReasonable(s)
6409 && s->defstate == SS_ALLOCATED && ctype_isStackAllocated (s->type));
6413 void sRef_setArrayFetchState (/*@notnull@*/ /*@exposed@*/ sRef s,
6414 /*@notnull@*/ /*@exposed@*/ sRef arr)
6416 sRef_checkMutable (s);
6418 if (ctype_isRealAP (arr->type))
6420 s->type = ctype_baseArrayPtr (arr->type);
6423 /* a hack, methinks... makeArrayFetch (&a[0]) ==> a[] */
6424 /* evans - 2001-08-27: not sure where this was necessary - it
6425 ** causes an assertion in in aliasCheckPred to fail.
6428 if (sRef_isAddress (arr))
6430 sRef t = arr->info->ref;
6432 if (sRef_isArrayFetch (t))
6434 s->info->arrayfetch->arr = t->info->arrayfetch->arr;
6437 else if (ctype_isRealPointer (arr->type))
6439 sRef sp = sRef_findDerivedPointer (arr);
6441 if (sRef_isReasonable (sp))
6444 if (ctype_isMutable (s->type))
6446 s->expkind = sRef_getExKind (sp);
6447 s->expinfo = stateInfo_copy (sp->expinfo);
6449 s->aliaskind = sp->aliaskind;
6450 s->aliasinfo = stateInfo_copy (sp->aliasinfo);
6453 s->defstate = sp->defstate;
6455 if (s->defstate == SS_DEFINED)
6457 if (!context_getFlag (FLG_STRICTDESTROY))
6459 s->defstate = SS_PARTIAL;
6463 DPRINTF (("Set null state: %s / %s", sRef_unparseFull (s), sRef_unparseFull (sp)));
6464 sRef_setNullStateN (s, sRef_getNullState (sp));
6468 if (arr->defstate == SS_UNDEFINED)
6470 s->defstate = SS_UNUSEABLE;
6472 else if ((arr->defstate == SS_ALLOCATED) && !ctype_isSU (s->type))
6474 s->defstate = SS_UNDEFINED;
6478 if (!context_getFlag (FLG_STRICTDESTROY))
6480 s->defstate = SS_PARTIAL;
6484 s->defstate = SS_DEFINED;
6488 ** Very weak checking for array elements.
6490 ** s->defstate = arr->defstate;
6494 s->expkind = sRef_getExKind (arr);
6495 s->expinfo = stateInfo_copy (arr->expinfo);
6497 if (arr->aliaskind == AK_LOCAL || arr->aliaskind == AK_FRESH)
6499 s->aliaskind = AK_LOCAL;
6503 s->aliaskind = AK_UNKNOWN;
6506 sRef_setTypeState (s);
6511 if (arr->defstate == SS_DEFINED)
6514 ** Very weak checking for array elements.
6516 ** s->defstate = arr->defstate;
6519 if (context_getFlag (FLG_STRICTDESTROY))
6521 s->defstate = SS_DEFINED;
6525 s->defstate = SS_PARTIAL;
6528 else if (arr->defstate == SS_ALLOCATED)
6530 if (ctype_isRealArray (s->type))
6532 s->defstate = SS_ALLOCATED;
6536 if (!s->info->arrayfetch->indknown)
6539 ** is index is unknown, elements is defined or
6540 ** allocated is any element is!
6543 s->defstate = SS_UNDEFINED;
6545 sRefSet_allElements (arr->deriv, sr)
6547 if (sRef_isReasonable (sr))
6549 if (sRef_isReasonable (sr))
6551 if (sr->defstate == SS_ALLOCATED)
6553 s->defstate = SS_ALLOCATED;
6557 if (sr->defstate == SS_DEFINED)
6559 if (context_getFlag (FLG_STRICTDESTROY))
6561 s->defstate = SS_DEFINED;
6565 s->defstate = SS_PARTIAL;
6574 llcontbug (message ("Invalid sRef as derived element of %s", sRef_unparse (arr)));
6577 } end_sRefSet_allElements;
6581 s->defstate = SS_UNDEFINED;
6587 s->defstate = arr->defstate;
6592 ** kludgey way to guess where aliaskind applies
6595 if (ctype_isMutable (s->type)
6596 && !ctype_isPointer (arr->type)
6597 && !alkind_isStatic (arr->aliaskind)
6598 && !alkind_isStack (arr->aliaskind)) /* evs - 2000-06-20: don't pass stack allocation to members */
6600 s->aliaskind = arr->aliaskind;
6604 s->aliaskind = AK_UNKNOWN;
6607 sRef_setTypeState (s);
6610 if (sRef_isObserver (arr))
6612 s->expkind = XO_OBSERVER;
6613 s->expinfo = stateInfo_copy (arr->expinfo);
6617 /*@exposed@*/ sRef sRef_buildArrayFetch (/*@exposed@*/ sRef arr)
6621 if (!sRef_isReasonable (arr)) {
6622 /*@-nullret@*/ return arr /*@=nullret@*/;
6625 if (ctype_isRealPointer (arr->type))
6627 (void) sRef_buildPointer (arr); /* do this to define arr! */
6630 s = sRef_findDerivedArrayFetch (arr, FALSE, 0, FALSE);
6632 if (sRef_isReasonable (s))
6634 /* evans 2001-07-12: this is bogus, clean-up hack */
6635 if (s->info->arrayfetch->arr != arr)
6638 check (sRefSet_delete (arr->deriv, s));
6639 res = sRef_buildArrayFetch (arr);
6640 sRef_copyState (res, s);
6641 llassert (res->info->arrayfetch->arr == arr);
6645 s->expkind = sRef_getExKind (arr);
6646 s->expinfo = stateInfo_copy (arr->expinfo);
6654 s->kind = SK_ARRAYFETCH;
6655 s->info = (sinfo) dmalloc (sizeof (*s->info));
6656 s->info->arrayfetch = (ainfo) dmalloc (sizeof (*s->info->arrayfetch));
6657 s->info->arrayfetch->indknown = FALSE;
6658 s->info->arrayfetch->ind = 0;
6659 s->info->arrayfetch->arr = arr; /* sRef_copy (arr); */ /*@i32@*/
6661 sRef_setArrayFetchState (s, arr);
6663 s->oaliaskind = s->aliaskind;
6664 s->oexpkind = s->expkind;
6666 if (!context_inProtectVars ())
6668 sRef_addDeriv (arr, s);
6671 if (valueTable_isUndefined (s->state))
6673 s->state = context_createValueTable
6674 (s, stateInfo_makeLoc (g_currentloc, SA_CREATED));
6682 sRef_buildArrayFetchKnown (/*@exposed@*/ sRef arr, int i)
6686 if (!sRef_isReasonable (arr)) {
6687 /*@-nullret@*/ return arr /*@=nullret@*/;
6690 if (ctype_isRealPointer (arr->type))
6692 (void) sRef_buildPointer (arr); /* do this to define arr! */
6695 s = sRef_findDerivedArrayFetch (arr, TRUE, i, FALSE);
6697 if (sRef_isReasonable (s))
6699 /* evans 2001-07-12: this is bogus, clean-up hack */
6700 if (s->info->arrayfetch->arr != arr)
6704 check (sRefSet_delete (arr->deriv, s));
6705 res = sRef_buildArrayFetchKnown (arr, i);
6707 llassert (res->info->arrayfetch->arr == arr);
6708 sRef_copyState (res, s);
6709 llassert (res->info->arrayfetch->arr == arr);
6713 s->expkind = sRef_getExKind (arr);
6714 s->expinfo = stateInfo_copy (arr->expinfo);
6716 llassert (s->info->arrayfetch->arr == arr);
6723 s->kind = SK_ARRAYFETCH;
6724 s->info = (sinfo) dmalloc (sizeof (*s->info));
6725 s->info->arrayfetch = (ainfo) dmalloc (sizeof (*s->info->arrayfetch));
6726 s->info->arrayfetch->arr = arr; /* sRef_copy (arr); */ /*@i32@*/
6727 s->info->arrayfetch->indknown = TRUE;
6728 s->info->arrayfetch->ind = i;
6730 sRef_setArrayFetchState (s, arr);
6731 /* evans 2001-08-27 no: can change this - llassert (s->info->arrayfetch->arr == arr); */
6733 s->oaliaskind = s->aliaskind;
6734 s->oexpkind = s->expkind;
6735 sRef_addDeriv (arr, s);
6737 llassert (valueTable_isUndefined (s->state));
6738 s->state = context_createValueTable (s, stateInfo_makeLoc (g_currentloc, SA_CREATED));
6744 ** sets everything except for defstate
6748 sRef_setPartsFromUentry (sRef s, uentry ue)
6750 sRef uref = uentry_getSref (ue);
6752 llassert (sRef_isReasonable (s));
6754 s->aliaskind = alkind_derive (s->aliaskind, uentry_getAliasKind (ue));
6755 s->oaliaskind = s->aliaskind;
6757 if (s->expkind == XO_UNKNOWN)
6759 s->expkind = uentry_getExpKind (ue);
6762 s->oexpkind = s->expkind;
6764 if (sRef_getNullState (s) == NS_UNKNOWN)
6766 DPRINTF (("Set null state: %s / %s", sRef_unparseFull (s), uentry_unparseFull (ue)));
6767 sRef_setNullStateN (s, sRef_getNullState (uentry_getSref (ue)));
6771 DPRINTF (("Skipping null null state!"));
6774 if (s->aliaskind == AK_IMPONLY && (sRef_isExposed (s) || sRef_isObserver (s)))
6776 s->oaliaskind = s->aliaskind = AK_IMPDEPENDENT;
6779 if (sRef_isReasonable (uref))
6781 valueTable utable = uref->state;
6782 valueTable_free (s->state);
6783 s->state = valueTable_copy (utable);
6788 sRef_setStateFromAbstractUentry (sRef s, uentry ue)
6790 llassert (sRef_isReasonable (s));
6791 sRef_checkMutable (s);
6793 sRef_setPartsFromUentry (s, ue);
6795 s->aliaskind = alkind_derive (s->aliaskind, uentry_getAliasKind (ue));
6796 s->oaliaskind = s->aliaskind;
6798 if (s->expkind == XO_UNKNOWN)
6800 s->expkind = uentry_getExpKind (ue);
6803 s->oexpkind = s->expkind;
6807 sRef_setStateFromUentry (sRef s, uentry ue)
6811 sRef_checkMutable (s);
6812 llassert (sRef_isReasonable (s));
6814 sRef_setPartsFromUentry (s, ue);
6816 defstate = uentry_getDefState (ue);
6818 if (sstate_isKnown (defstate))
6820 s->defstate = defstate;
6829 sRef_buildPointer (/*@exposed@*/ sRef t)
6831 DPRINTF (("build pointer: %s", sRef_unparse (t)));
6833 if (sRef_isInvalid (t)) return sRef_undefined;
6835 if (sRef_isAddress (t))
6837 DPRINTF (("Return ref: %s", sRef_unparse (t->info->ref)));
6838 return (t->info->ref);
6842 sRef s = sRef_findDerivedPointer (t);
6844 DPRINTF (("find derived: %s", sRef_unparse (s)));
6846 if (sRef_isReasonable (s))
6848 s->expkind = sRef_getExKind (t);
6849 s->expinfo = stateInfo_copy (t->expinfo);
6851 s->oaliaskind = s->aliaskind;
6852 s->oexpkind = s->expkind;
6858 s = sRef_constructPointerAux (t);
6860 DPRINTF (("construct: %s", sRef_unparse (s)));
6862 if (sRef_isReasonable (s))
6864 sRef_addDeriv (t, s);
6866 s->oaliaskind = s->aliaskind;
6867 s->oexpkind = s->expkind;
6876 sRef_constructPointer (/*@exposed@*/ sRef t)
6879 return sRef_buildPointer (t);
6882 static /*@exposed@*/ sRef sRef_constructDerefAux (sRef t, bool isdead)
6884 if (sRef_isReasonable (t))
6889 ** if there is a derived t[?], return that. Otherwise, *t.
6892 s = sRef_findDerivedArrayFetch (t, FALSE, 0, isdead);
6894 if (sRef_isReasonable (s))
6896 DPRINTF (("Found array fetch: %s", sRef_unparseFull (s)));
6901 sRef ret = sRef_constructPointer (t);
6903 DPRINTF (("Constructed pointer: %s", sRef_unparseFull (ret)));
6910 return sRef_undefined;
6914 sRef sRef_constructDeref (sRef t)
6916 return sRef_constructDerefAux (t, FALSE);
6919 sRef sRef_constructDeadDeref (sRef t)
6921 return sRef_constructDerefAux (t, TRUE);
6925 sRef_constructPointerAux (/*@notnull@*/ /*@exposed@*/ sRef t)
6927 sRef s = sRef_newRef ();
6931 llassert (valueTable_isUndefined (s->state));
6934 s->info = (sinfo) dmalloc (sizeof (*s->info));
6935 s->info->ref = t; /* sRef_copy (t); */ /*@i32*/
6937 if (ctype_isRealAP (rt))
6939 s->type = ctype_baseArrayPtr (rt);
6942 st = ctype_realType (s->type);
6944 if (t->defstate == SS_UNDEFINED)
6946 s->defstate = SS_UNUSEABLE;
6947 s->definfo = stateInfo_copy (t->definfo);
6949 else if ((t->defstate == SS_ALLOCATED) && !ctype_isSU (st))
6951 s->defstate = SS_UNDEFINED;
6952 s->definfo = stateInfo_copy (t->definfo);
6956 s->defstate = t->defstate;
6957 s->definfo = stateInfo_copy (t->definfo);
6960 if (t->aliaskind == AK_LOCAL || t->aliaskind == AK_FRESH)
6962 s->aliaskind = AK_LOCAL;
6966 s->aliaskind = AK_UNKNOWN;
6969 s->expkind = sRef_getExKind (t);
6970 s->expinfo = stateInfo_copy (t->expinfo);
6972 sRef_setTypeState (s);
6974 s->oaliaskind = s->aliaskind;
6975 s->oexpkind = s->expkind;
6977 if (valueTable_isUndefined (s->state))
6979 s->state = context_createValueTable (s, stateInfo_makeLoc (g_currentloc, SA_CREATED));
6982 DPRINTF (("pointer: %s", sRef_unparseFull (s)));
6986 bool sRef_hasDerived (sRef s)
6988 return (sRef_isReasonable (s) && !sRefSet_isEmpty (s->deriv));
6992 sRef_clearDerived (sRef s)
6994 if (sRef_isReasonable (s))
6996 DPRINTF (("Clear derived: [%p] %s", s, sRef_unparseDebug (s)));
6997 sRefSet_clear (s->deriv);
7002 sRef_clearDerivedComplete (sRef s)
7004 if (sRef_isReasonable (s))
7006 sRef base = sRef_getBaseSafe (s);
7008 while (sRef_isReasonable (base))
7010 DPRINTF (("Clear derived: [%p] %s", base, sRef_unparse (base)));
7011 sRefSet_clear (base->deriv);
7012 base = sRef_getBaseSafe (base);
7015 DPRINTF (("Clear derived: [%p] %s", s, sRef_unparse (s)));
7016 sRefSet_clear (s->deriv);
7020 /*@exposed@*/ sRef sRef_makePointer (/*@exposed@*/ sRef s)
7023 sRef res = sRef_buildPointer (s);
7025 DPRINTF (("Res: %s", sRef_unparseFull (res)));
7030 ** &a[] => a (this is for out params)
7034 sRef_makeAnyArrayFetch (/*@exposed@*/ sRef arr)
7036 if (sRef_isAddress (arr))
7038 return (arr->info->ref);
7042 return (sRef_buildArrayFetch (arr));
7047 sRef_makeArrayFetch (/*@exposed@*/ sRef arr)
7049 return (sRef_buildArrayFetch (arr));
7053 sRef_makeArrayFetchKnown (/*@exposed@*/ sRef arr, int i)
7055 return (sRef_buildArrayFetchKnown (arr, i));
7059 sRef_makeField (sRef rec, /*@dependent@*/ cstring f)
7062 ret = sRef_buildField (rec, f);
7067 sRef_makeNCField (/*@exposed@*/ sRef rec, /*@dependent@*/ cstring f)
7069 return (sRef_buildNCField (rec, f));
7073 sRef_unparseKindName (sRef s)
7077 if (s == sRef_undefined) return cstring_makeLiteral ("<invalid>");
7079 s = sRef_fixConj (s);
7084 if (sRef_isLocalVar (s))
7086 result = cstring_makeLiteral ("Variable");
7090 result = cstring_makeLiteral ("Undef global");
7094 result = cstring_makeLiteral ("Out parameter");
7097 if (sRef_isAnyParam (s->info->arrayfetch->arr))
7099 result = cstring_makeLiteral ("Out parameter");
7101 else if (sRef_isIndexKnown (s))
7103 result = cstring_makeLiteral ("Array element");
7107 result = cstring_makeLiteral ("Value");
7111 if (sRef_isAnyParam (s->info->ref))
7113 result = cstring_makeLiteral ("Out parameter");
7117 result = cstring_makeLiteral ("Value");
7121 result = cstring_makeLiteral ("Value");
7124 result = cstring_makeLiteral ("Field");
7127 result = cstring_makeLiteral ("Object");
7129 case SK_UNCONSTRAINED:
7130 result = cstring_makeLiteral ("<anything>");
7139 result = cstring_makeLiteral ("<unknown>");
7142 result = cstring_makeLiteral ("<conj>");
7145 result = cstring_makeLiteral ("Storage");
7153 sRef_unparseKindNamePlain (sRef s)
7157 if (s == sRef_undefined) return cstring_makeLiteral ("<invalid>");
7159 s = sRef_fixConj (s);
7164 if (sRef_isLocalVar (s))
7166 result = cstring_makeLiteral ("Variable");
7170 result = cstring_makeLiteral ("Global");
7174 result = cstring_makeLiteral ("Parameter");
7177 if (sRef_isAnyParam (s->info->arrayfetch->arr))
7179 result = cstring_makeLiteral ("Parameter");
7181 else if (sRef_isIndexKnown (s))
7183 result = cstring_makeLiteral ("Array element");
7187 result = cstring_makeLiteral ("Value");
7191 if (sRef_isAnyParam (s->info->ref))
7193 result = cstring_makeLiteral ("Parameter");
7197 result = cstring_makeLiteral ("Value");
7201 result = cstring_makeLiteral ("Value");
7204 result = cstring_makeLiteral ("Field");
7207 result = cstring_makeLiteral ("Object");
7210 result = cstring_makeLiteral ("Storage");
7212 case SK_UNCONSTRAINED:
7213 result = cstring_makeLiteral ("<anything>");
7222 result = cstring_makeLiteral ("<unknown>");
7225 result = cstring_makeLiteral ("<conj>");
7237 sRef_copyState (sRef s1, sRef s2)
7239 if (sRef_isReasonable (s1) && sRef_isReasonable (s2))
7241 s1->defstate = s2->defstate;
7243 /* start modifications */
7244 s1->bufinfo.bufstate = s2->bufinfo.bufstate;
7245 s1->bufinfo.len = s2->bufinfo.len;
7246 s1->bufinfo.size = s2->bufinfo.size;
7247 /* end modifications */
7249 s1->aliaskind = s2->aliaskind;
7250 s1->aliasinfo = stateInfo_update (s1->aliasinfo, s2->aliasinfo);
7252 s1->expkind = s2->expkind;
7253 s1->expinfo = stateInfo_update (s1->expinfo, s2->expinfo);
7255 s1->nullstate = s2->nullstate;
7256 s1->nullinfo = stateInfo_update (s1->nullinfo, s2->nullinfo);
7259 /*@i834 don't free it: valueTable_free (s1->state); */
7260 /*@i32@*/ s1->state = valueTable_copy (s2->state);
7262 s1->safe = s2->safe;
7267 sRef_makeNew (ctype ct, sRef t, cstring name)
7269 sRef s = sRef_newRef ();
7274 llassert (sRef_isReasonable (t));
7275 s->defstate = t->defstate;
7277 s->aliaskind = t->aliaskind;
7278 s->oaliaskind = s->aliaskind;
7279 s->nullstate = t->nullstate;
7281 s->expkind = t->expkind;
7282 s->oexpkind = s->expkind;
7284 s->info = (sinfo) dmalloc (sizeof (*s->info));
7285 s->info->fname = name;
7287 /* start modifications */
7288 s->bufinfo.bufstate = t->bufinfo.bufstate;
7289 /* end modifications */
7291 llassert (valueTable_isUndefined (s->state));
7292 s->state = valueTable_copy (t->state);
7294 DPRINTF (("==> Copying state: %s", valueTable_unparse (s->state)));
7295 DPRINTF (("==> new: %s", sRef_unparseFull (s)));
7300 sRef_makeType (ctype ct)
7302 sRef s = sRef_newRef ();
7304 sRef_checkMutable (s);
7309 s->defstate = SS_UNKNOWN;
7310 s->aliaskind = AK_UNKNOWN;
7311 sRef_setNullStateN (s, NS_UNKNOWN);
7313 /* start modification */
7314 s->bufinfo.bufstate = BB_NOTNULLTERMINATED;
7315 /* end modification */
7318 if (ctype_isUA (ct))
7320 typeId uid = ctype_typeId (ct);
7321 uentry ue = usymtab_getTypeEntrySafe (uid);
7323 if (uentry_isValid (ue))
7325 sRef_mergeStateQuiet (s, uentry_getSref (ue));
7329 s->oaliaskind = s->aliaskind;
7330 s->oexpkind = s->expkind;
7331 llassert (valueTable_isUndefined (s->state));
7332 s->state = context_createValueTable (s, stateInfo_makeLoc (g_currentloc, SA_CREATED));
7334 DPRINTF (("Create: %s", sRef_unparseFull (s)));
7339 sRef_makeConst (ctype ct)
7341 sRef s = sRef_newRef ();
7346 s->defstate = SS_UNKNOWN;
7347 s->aliaskind = AK_UNKNOWN;
7348 sRef_setNullStateN (s, NS_UNKNOWN);
7350 /* start modification */
7351 s->bufinfo.bufstate = BB_NULLTERMINATED;
7352 /* end modification */
7354 /* evans 2002-04-22: added isManifestBool to avoid errors for -boolfalse initializations */
7355 if (!ctype_isManifestBool (ct) && ctype_isUA (ct))
7357 typeId uid = ctype_typeId (ct);
7358 uentry te = usymtab_getTypeEntrySafe (uid);
7360 if (uentry_isValid (te))
7362 sRef_mergeStateQuiet (s, uentry_getSref (te));
7366 s->oaliaskind = s->aliaskind;
7367 s->oexpkind = s->expkind;
7369 llassert (valueTable_isUndefined (s->state));
7370 s->state = context_createValueTable (s, stateInfo_makeLoc (g_currentloc, SA_CREATED));
7375 bool sRef_hasName (sRef s)
7377 if (sRef_isInvalid (s))
7386 uentry u = usymtab_getRefQuiet (s->info->cvar->lexlevel,
7387 s->info->cvar->index);
7388 return (uentry_hasName (u));
7392 if (s->info->paramno >= 0)
7394 uentry u = uentryList_getN (context_getParams (),
7397 return (uentry_hasName (u));
7401 llassert (s->info->paramno == PARAMUNKNOWN);
7411 sRef_sameName (sRef s1, sRef s2)
7413 if (sRef_isInvalid (s1))
7415 return sRef_isInvalid (s2);
7418 if (sRef_isInvalid (s2))
7426 if (s2->kind == SK_CVAR)
7428 return (s1->info->cvar->lexlevel == s2->info->cvar->lexlevel
7429 && s1->info->cvar->index == s2->info->cvar->index);
7431 else if (s2->kind == SK_PARAM)
7433 if (context_inFunctionLike ())
7435 if (s2->info->paramno != PARAMUNKNOWN)
7437 uentry u1 = usymtab_getRefQuiet (s1->info->cvar->lexlevel,
7438 s1->info->cvar->index);
7439 uentry u2 = uentryList_getN (context_getParams (),
7442 return (cstring_equalFree (uentry_getName (u1),
7443 uentry_getName (u2)));
7447 return s1->info->paramno == PARAMUNKNOWN;
7461 if (s2->kind == SK_PARAM)
7463 return (s1->info->paramno == s2->info->paramno);
7465 else if (s2->kind == SK_CVAR)
7467 if (context_inFunctionLike ())
7469 if (s1->info->paramno == PARAMUNKNOWN)
7475 uentry u1 = uentryList_getN (context_getParams (),
7477 uentry u2 = usymtab_getRefQuiet (s2->info->cvar->lexlevel,
7478 s2->info->cvar->index);
7481 return (cstring_equalFree (uentry_getName (u1),
7482 uentry_getName (u2)));
7496 case SK_UNCONSTRAINED:
7500 if (s2->kind == SK_ARRAYFETCH)
7502 if (bool_equal (s1->info->arrayfetch->indknown,
7503 s2->info->arrayfetch->indknown))
7505 if (!s1->info->arrayfetch->indknown
7506 || (s1->info->arrayfetch->ind == s2->info->arrayfetch->ind))
7508 return sRef_sameName (s1->info->arrayfetch->arr,
7509 s2->info->arrayfetch->arr);
7516 if (s2->kind == SK_FIELD)
7518 if (cstring_equal (s1->info->field->field,
7519 s2->info->field->field))
7521 return sRef_sameName (s1->info->field->rec,
7522 s2->info->field->rec);
7531 if (s2->kind == s1->kind)
7533 return sRef_sameName (s1->info->ref,
7541 return sRef_sameName (sRef_getConjA (s1), s2);
7545 return (s2->kind == SK_UNKNOWN);
7548 if (s2->kind == s1->kind)
7550 return (ctype_equal (s1->type, s2->type));
7555 if (s2->kind == SK_SPECIAL)
7557 return (s1->info->spec == s2->info->spec);
7561 return (s2->kind == SK_RESULT);
7569 sRef_fixOuterRef (/*@returned@*/ sRef s)
7571 sRef root = sRef_getRootBase (s);
7573 if (sRef_isCvar (root))
7575 uentry ue = usymtab_getRefQuiet (root->info->cvar->lexlevel,
7576 root->info->cvar->index);
7578 if (uentry_isValid (ue))
7580 sRef uref = uentry_getSref (ue);
7581 sRef sr = sRef_fixBase (s, uref);
7587 llcontbug (message ("sRef_fixOuterRef: undefined: %q", sRef_unparseDebug (s)));
7596 sRef_storeState (sRef s)
7598 if (sRef_isInvalid (s)) return;
7600 sRef_checkMutable (s);
7601 s->oaliaskind = s->aliaskind;
7602 s->oexpkind = s->expkind;
7605 static void sRef_resetStateAux (sRef s, /*@unused@*/ fileloc loc)
7607 sRef_resetState (s);
7611 sRef_resetState (sRef s)
7613 bool changed = FALSE;
7614 if (sRef_isInvalid (s)) return;
7617 if (s->oaliaskind == AK_KILLREF && !sRef_isParam (s))
7620 ** killref is used in a kludgey way, to save having to add
7621 ** another alias kind (see usymtab_handleParams)
7624 if (s->expkind != s->oexpkind)
7627 s->expkind = s->oexpkind;
7632 if (s->expkind != s->oexpkind)
7635 s->expkind = s->oexpkind;
7638 if (s->aliaskind != s->oaliaskind
7639 && s->aliaskind != AK_REFCOUNTED
7640 && s->aliaskind != AK_REFS)
7643 s->aliaskind = s->oaliaskind;
7649 sRef_clearDerived (s);
7655 sRef_resetStateComplete (sRef s)
7657 sRef_innerAliasSetComplete (sRef_resetStateAux, s, fileloc_undefined);
7661 sRef_fixBase (/*@returned@*/ sRef s, /*@returned@*/ sRef base)
7663 sRef tmp = sRef_undefined;
7666 if (sRef_isInvalid (s)) return s;
7667 if (sRef_isInvalid (base)) return base;
7677 tmp = sRef_fixBase (s->info->arrayfetch->arr, base);
7679 if (s->info->arrayfetch->indknown)
7681 ret = sRef_makeArrayFetchKnown (tmp, s->info->arrayfetch->ind);
7685 ret = sRef_makeArrayFetch (tmp);
7689 tmp = sRef_fixBase (s->info->field->rec, base);
7690 ret = sRef_buildNCField (tmp, s->info->field->field);
7693 tmp = sRef_fixBase (s->info->ref, base);
7694 ret = sRef_makePointer (tmp);
7697 tmp = sRef_fixBase (s->info->ref, base);
7698 ret = sRef_makeAddress (tmp);
7704 tmp = sRef_fixBase (s->info->conj->a, base);
7705 tmpb = sRef_fixBase (s->info->conj->b, base);
7707 ret = sRef_makeConj (tmp, tmpb);
7716 static /*@exposed@*/ sRef
7717 sRef_fixDirectBase (sRef s, sRef base)
7722 if (sRef_isInvalid (s))
7724 return sRef_undefined;
7730 if (s->info->arrayfetch->indknown)
7732 ret = sRef_makeArrayFetchKnown (base, s->info->arrayfetch->ind);
7736 ret = sRef_makeArrayFetch (base);
7740 ret = sRef_buildNCField (base, s->info->field->field);
7743 ret = sRef_makePointer (base);
7746 ret = sRef_makeAddress (base);
7752 tmpa = sRef_fixDirectBase (s->info->conj->a, base);
7753 tmpb = sRef_fixDirectBase (s->info->conj->b, base);
7755 ret = sRef_makeConj (tmpa, tmpb);
7761 sRef_copyState (ret, s);
7766 sRef_isAllocIndexRef (sRef s)
7768 return (sRef_isArrayFetch (s) && !(s->info->arrayfetch->indknown)
7769 && sRef_isAllocated (s->info->arrayfetch->arr));
7773 sRef_showRefLost (sRef s)
7775 if (sRef_hasAliasInfoLoc (s))
7777 llgenindentmsg (cstring_makeLiteral ("Original reference lost"),
7778 sRef_getAliasInfoLoc (s));
7783 sRef_showRefKilled (sRef s)
7785 if (sRef_isValid (s))
7787 DPRINTF (("Killed: %s", sRef_unparseFull (s)));
7788 if (context_getLocIndentSpaces () == 0) {
7789 stateInfo_display (s->definfo, message (" Storage %q", sRef_unparseOpt (s)));
7791 stateInfo_display (s->definfo, message ("Storage %q", sRef_unparseOpt (s)));
7797 sRef_showStateInconsistent (sRef s)
7799 if (sRef_hasStateInfoLoc (s))
7802 (message ("Storage %qbecomes inconsistent (released on one branch)",
7803 sRef_unparseOpt (s)),
7804 sRef_getStateInfoLoc (s));
7809 sRef_showStateInfo (sRef s)
7811 if (sRef_isValid (s)) {
7812 if (context_getLocIndentSpaces () == 0) {
7813 stateInfo_display (s->definfo, message (" Storage %q", sRef_unparseOpt (s)));
7815 stateInfo_display (s->definfo, message ("Storage %q", sRef_unparseOpt (s)));
7821 sRef_showExpInfo (sRef s)
7823 if (sRef_isValid (s)) {
7824 if (context_getLocIndentSpaces () == 0) {
7825 stateInfo_display (s->expinfo, message (" Storage %q", sRef_unparseOpt (s)));
7827 stateInfo_display (s->expinfo, message ("Storage %q", sRef_unparseOpt (s)));
7833 sRef_showMetaStateInfo (sRef s, cstring key)
7836 metaStateInfo minfo = context_lookupMetaStateInfo (key);
7838 llassert (sRef_isReasonable (s));
7839 llassert (valueTable_isDefined (s->state));
7840 llassert (metaStateInfo_isDefined (minfo));
7842 val = valueTable_lookup (s->state, key);
7844 if (stateValue_hasLoc (val))
7847 (message ("%qbecomes %q", sRef_unparseOpt (s),
7848 stateValue_unparseValue (val, minfo)),
7849 stateValue_getLoc (val));
7854 sRef_showNullInfo (sRef s)
7856 DPRINTF (("Show null info: %s", sRef_unparseFull (s)));
7858 if (sRef_hasNullInfoLoc (s) && sRef_isKnown (s))
7860 DPRINTF (("has null info: %s",
7861 fileloc_unparse (sRef_getNullInfoLoc (s))));
7863 switch (sRef_getNullState (s))
7867 fileloc loc = sRef_getNullInfoLoc (s);
7869 if (fileloc_isDefined (loc) && !fileloc_isLib (loc))
7872 (message ("Storage %qbecomes null", sRef_unparseOpt (s)),
7879 fileloc loc = sRef_getNullInfoLoc (s);
7881 if (fileloc_isDefined (loc) && !fileloc_isLib (loc))
7883 llgenindentmsg (message ("Storage %qbecomes null", sRef_unparseOpt (s)),
7891 (message ("Storage %qmay become null", sRef_unparseOpt (s)),
7892 sRef_getNullInfoLoc (s));
7897 (message ("Storage %qbecomes not null", sRef_unparseOpt (s)),
7898 sRef_getNullInfoLoc (s));
7902 (message ("Storage %qnull state becomes unknown",
7903 sRef_unparseOpt (s)),
7904 sRef_getNullInfoLoc (s));
7913 (message ("<error case> Storage %q becomes %s",
7915 nstate_unparse (sRef_getNullState (s))),
7916 sRef_getNullInfoLoc (s));
7924 sRef_showAliasInfo (sRef s)
7926 if (sRef_isValid (s))
7928 if (sRef_isFresh (s))
7930 if (context_getLocIndentSpaces () == 0) {
7931 stateInfo_display (s->aliasinfo, message (" Fresh storage %q", sRef_unparseOpt (s)));
7933 stateInfo_display (s->aliasinfo, message ("Fresh storage %q", sRef_unparseOpt (s)));
7938 if (context_getLocIndentSpaces () == 0) {
7939 stateInfo_display (s->aliasinfo, message (" Storage %q", sRef_unparseOpt (s)));
7941 stateInfo_display (s->aliasinfo, message ("Storage %q", sRef_unparseOpt (s)));
7948 sRef_mergeNullState (sRef s, nstate n)
7950 if (sRef_isReasonable (s))
7954 old = sRef_getNullState (s);
7956 if (n != old && n != NS_UNKNOWN)
7958 sRef_setNullState (s, n, g_currentloc);
7963 llbuglit ("sRef_mergeNullState: invalid");
7968 sRef_possiblyNull (sRef s)
7970 if (sRef_isReasonable (s))
7972 if (sRef_getNullState (s) == NS_ABSNULL)
7974 ctype rct = ctype_realType (s->type);
7976 if (ctype_isAbstract (rct))
7982 if (ctype_isUser (rct))
7984 uentry ue = usymtab_getTypeEntry (ctype_typeId (rct));
7986 return (nstate_possiblyNull
7987 (sRef_getNullState (uentry_getSref (ue))));
7997 return nstate_possiblyNull (sRef_getNullState (s));
8005 sRef_getScopeName (sRef s)
8007 sRef base = sRef_getRootBase (s);
8009 if (sRef_isRealGlobal (base))
8011 return (cstring_makeLiteralTemp ("Global"));
8013 else if (sRef_isFileStatic (base))
8015 return (cstring_makeLiteralTemp ("Static"));
8019 return (cstring_makeLiteralTemp ("Local"));
8024 sRef_unparseScope (sRef s)
8026 sRef base = sRef_getRootBase (s);
8028 if (sRef_isRealGlobal (base))
8030 return (cstring_makeLiteralTemp ("global"));
8032 else if (sRef_isFileStatic (base))
8034 return (cstring_makeLiteralTemp ("file static"));
8043 sRef_getScope (sRef s)
8045 llassert (sRef_isReasonable (s));
8047 if (sRef_isCvar (s))
8049 return s->info->cvar->lexlevel;
8051 else if (sRef_isParam (s))
8062 sRef_isDead (sRef s)
8064 return (sRef_isReasonable (s) && (s)->defstate == SS_DEAD);
8068 sRef_isDeadStorage (sRef s)
8070 if (sRef_isReasonable (s))
8072 if (s->defstate == SS_DEAD
8073 || s->defstate == SS_UNUSEABLE
8074 || s->defstate == SS_UNDEFINED
8075 || s->defstate == SS_UNKNOWN)
8081 return (sRef_isDefinitelyNull (s));
8091 sRef_isPossiblyDead (sRef s)
8093 return (sRef_isReasonable (s) && s->defstate == SS_HOFFA);
8096 bool sRef_isStateLive (sRef s)
8098 if (sRef_isReasonable (s))
8100 sstate ds = s->defstate;
8102 return (!(ds == SS_UNDEFINED
8104 || ds == SS_UNUSEABLE
8105 || ds == SS_HOFFA));
8114 bool sRef_isStateUndefined (sRef s)
8116 return ((sRef_isReasonable(s)) && ((s)->defstate == SS_UNDEFINED));
8119 bool sRef_isJustAllocated (sRef s)
8121 if (sRef_isAllocated (s))
8123 sRefSet_allElements (s->deriv, el)
8125 if (!(sRef_isStateUndefined (el) || sRef_isUnuseable (el)))
8129 } end_sRefSet_allElements ;
8138 sRef_isAllocatedStorage (sRef s)
8140 if (sRef_isReasonable (s) && ynm_toBoolStrict (sRef_isValidLvalue (s)))
8142 return (ctype_isVisiblySharable (sRef_getType (s)));
8151 sRef_isUnuseable (sRef s)
8153 return ((sRef_isValid(s)) && ((s)->defstate == SS_UNUSEABLE));
8157 sRef_perhapsNull (sRef s)
8159 if (sRef_isReasonable (s))
8161 if (sRef_getNullState (s) == NS_ABSNULL)
8163 ctype rct = ctype_realType (s->type);
8165 if (ctype_isAbstract (rct))
8171 if (ctype_isUser (rct))
8173 uentry ue = usymtab_getTypeEntry (ctype_typeId (rct));
8175 return (nstate_perhapsNull
8176 (sRef_getNullState (uentry_getSref (ue))));
8186 return nstate_perhapsNull (sRef_getNullState (s));
8194 ** definitelyNull --- called when TRUE is good
8198 sRef_definitelyNull (sRef s)
8200 return (sRef_isReasonable (s)
8201 && (sRef_getNullState (s) == NS_DEFNULL || sRef_getNullState (s) == NS_CONSTNULL));
8205 ** based on sRef_similar
8209 sRef_setDerivNullState (sRef set, sRef guide, nstate ns)
8211 if (sRef_isReasonable (set))
8213 sRef deriv = sRef_getDeriv (set, guide);
8215 if (sRef_isReasonable (deriv))
8217 sRef_setNullStateN (deriv, ns);
8222 static /*@exposed@*/ sRef
8223 sRef_getDeriv (/*@returned@*/ /*@notnull@*/ sRef set, sRef guide)
8225 llassert (sRef_isReasonable (set));
8226 llassert (sRef_isReasonable (guide));
8228 switch (guide->kind)
8231 llassert (set->kind == SK_CVAR);
8235 llassert (set->kind == guide->kind);
8236 llassert (set->info->paramno == guide->info->paramno);
8241 if (set->kind == SK_ARRAYFETCH
8242 && (sRef_similar (set->info->arrayfetch->arr,
8243 guide->info->arrayfetch->arr)))
8249 return (sRef_makeAnyArrayFetch
8250 (sRef_getDeriv (set, guide->info->arrayfetch->arr)));
8255 if (set->kind == SK_PTR && sRef_similar (set->info->ref, guide->info->ref))
8261 return (sRef_makePointer (sRef_getDeriv (set, guide->info->ref)));
8266 if ((set->kind == SK_FIELD &&
8267 (sRef_similar (set->info->field->rec, guide->info->field->rec) &&
8268 cstring_equal (set->info->field->field, guide->info->field->field))))
8274 return (sRef_makeField (sRef_getDeriv (set, guide->info->field->rec),
8275 guide->info->field->field));
8279 if ((set->kind == SK_ADR) && sRef_similar (set->info->ref, guide->info->ref))
8285 return (sRef_makeAddress (sRef_getDeriv (set, guide->info->ref)));
8290 return sRef_undefined;
8294 case SK_UNCONSTRAINED:
8302 return sRef_undefined;
8309 ** sRef_aliasCheckPred
8311 ** A confusing but spiffy function:
8313 ** Calls predf (s, e, text, <alias>) on s and all of s's aliases
8314 ** (unless checkAliases (s) is FALSE).
8316 ** For alias calls, calls as
8317 ** predf (alias, e, text, s)
8321 sRef_aliasCheckPred (bool (predf) (sRef, exprNode, sRef, exprNode),
8322 /*@null@*/ bool (checkAliases) (sRef),
8323 sRef s, exprNode e, exprNode err)
8325 bool error = (*predf)(s, e, sRef_undefined, err);
8328 if (checkAliases != NULL && !(checkAliases (s)))
8330 /* don't check aliases */
8334 sRefSet aliases = usymtab_allAliases (s);
8336 sRefSet_realElements (aliases, current)
8338 if (sRef_isReasonable (current))
8340 if (sRef_isReasonable (current))
8342 if (!sRef_similar (current, s)
8343 || (error && sRef_sameName (current, s)))
8345 (void) (*predf)(current, e, s, err);
8350 llcontbug (message ("Invalid sRef as alias field of %s", sRef_unparse (s)));
8353 } end_sRefSet_realElements;
8355 sRefSet_free (aliases);
8360 ** return TRUE iff predf (s) is true for s or any alias of s
8364 sRef_aliasCheckSimplePred (sRefTest predf, sRef s)
8375 aliases = usymtab_allAliases (s);
8377 sRefSet_realElements (aliases, current)
8379 if (sRef_isReasonable (current))
8381 sRef cref = sRef_updateSref (current);
8383 /* Whoa! a very kludgey way to make sure the right sref is used
8384 ** where there is a conditional symbol table. I am beginning
8385 ** to think that having a conditional symbol table wasn't such
8391 DPRINTF (("Checking alias: %s", sRef_unparseFull (cref)));
8392 sRefSet_free (aliases);
8396 } end_sRefSet_realElements;
8398 sRefSet_free (aliases);
8404 sRef_aliasCompleteSimplePred (bool (predf) (sRef), sRef s)
8407 bool result = FALSE;
8410 aliases = usymtab_allAliases (s);
8412 if ((*predf)(s)) result = TRUE;
8415 sRefSet_realElements (aliases, current)
8417 if (sRef_isReasonable (current))
8419 current = sRef_updateSref (current);
8420 if ((*predf)(current)) result = TRUE;
8422 } end_sRefSet_realElements;
8424 sRefSet_free (aliases);
8429 sRef_aliasSetComplete (void (predf) (sRef, fileloc), sRef s, fileloc loc)
8433 aliases = usymtab_allAliases (s);
8435 DPRINTF (("All aliases: %s", sRefSet_unparseFull (aliases)));
8439 sRefSet_realElements (aliases, current)
8441 if (sRef_isReasonable (current))
8443 current = sRef_updateSref (current);
8444 ((*predf)(current, loc));
8445 DPRINTF (("Killed: %s", sRef_unparseFull (current)));
8447 } end_sRefSet_realElements;
8449 sRefSet_free (aliases);
8453 sRef_aliasSetCompleteParam (void (predf) (sRef, int, fileloc), sRef s,
8454 int kind, fileloc loc)
8458 if (sRef_isDeep (s))
8460 aliases = usymtab_allAliases (s);
8464 aliases = usymtab_aliasedBy (s);
8467 (*predf)(s, kind, loc);
8469 sRefSet_realElements (aliases, current)
8471 if (sRef_isReasonable (current))
8473 current = sRef_updateSref (current);
8474 ((*predf)(current, kind, loc));
8476 } end_sRefSet_realElements;
8478 sRefSet_free (aliases);
8482 ** Version of aliasSetCompleteParam for alkind parameters
8486 sRef_aliasSetCompleteAlkParam (void (predf) (sRef, alkind, fileloc), sRef s,
8487 alkind kind, fileloc loc)
8491 if (sRef_isDeep (s))
8493 aliases = usymtab_allAliases (s);
8497 aliases = usymtab_aliasedBy (s);
8500 (*predf)(s, kind, loc);
8502 sRefSet_realElements (aliases, current)
8504 if (sRef_isReasonable (current))
8506 current = sRef_updateSref (current);
8507 ((*predf)(current, kind, loc));
8509 } end_sRefSet_realElements;
8511 sRefSet_free (aliases);
8515 sRef_innerAliasSetComplete (void (predf) (sRef, fileloc), sRef s, fileloc loc)
8521 if (!sRef_isReasonable (s)) return;
8524 ** Type equivalence checking is necessary --- there might be casting.
8531 case SK_UNCONSTRAINED:
8536 inner = s->info->ref;
8537 aliases = usymtab_allAliases (inner);
8538 ct = sRef_getType (inner);
8540 sRefSet_realElements (aliases, current)
8542 if (sRef_isReasonable (current))
8544 current = sRef_updateSref (current);
8546 if (ctype_equal (ct, sRef_getType (current)))
8548 sRef ptr = sRef_makePointer (current);
8549 ((*predf)(ptr, loc));
8552 } end_sRefSet_realElements;
8554 sRefSet_free (aliases);
8557 inner = s->info->arrayfetch->arr;
8558 aliases = usymtab_allAliases (inner);
8559 ct = sRef_getType (inner);
8561 DPRINTF (("Array fetch: %s", sRefSet_unparse (aliases)));
8563 sRefSet_realElements (aliases, current)
8565 if (sRef_isReasonable (current))
8567 current = sRef_updateSref (current);
8568 DPRINTF (("Current: %s", sRef_unparseFull (current)));
8570 if (ctype_equal (ct, sRef_getType (current)))
8572 if (s->info->arrayfetch->indknown)
8574 sRef af = sRef_makeArrayFetchKnown (current, s->info->arrayfetch->ind);
8575 DPRINTF (("Defining: %s", sRef_unparseFull (af)));
8576 /* evans 2001-08-27 This isn't true:
8577 llassert (af->info->arrayfetch->arr == current);
8578 see comments in buildArrayFetchKnown
8580 ((*predf)(af, loc));
8584 sRef af = sRef_makeArrayFetch (current);
8585 /* evans 2001-08-27 This isn't true:
8586 llassert (af->info->arrayfetch->arr == current);
8587 see comments in buildArrayFetch
8589 DPRINTF (("Defining: %s", sRef_unparseFull (af)));
8590 ((*predf)(af, loc));
8595 DPRINTF (("Type mismatch: %s / %s",
8597 ctype_unparse (sRef_getType (current))));
8600 } end_sRefSet_realElements;
8602 sRefSet_free (aliases);
8605 inner = s->info->field->rec;
8606 aliases = usymtab_allAliases (inner);
8607 ct = sRef_getType (inner);
8609 sRefSet_realElements (aliases, current)
8611 if (sRef_isReasonable (current))
8613 current = sRef_updateSref (current);
8615 if (ctype_equal (ct, sRef_getType (current)))
8617 sRef f = sRef_makeField (current, s->info->field->field);
8622 } end_sRefSet_realElements;
8624 sRefSet_free (aliases);
8627 sRef_innerAliasSetComplete (predf, s->info->conj->a, loc);
8628 sRef_innerAliasSetComplete (predf, s->info->conj->b, loc);
8645 sRef_innerAliasSetCompleteParam (void (predf) (sRef, sRef), sRef s, sRef t)
8651 if (!sRef_isReasonable (s)) return;
8654 ** Type equivalence checking is necessary --- there might be casting.
8661 case SK_UNCONSTRAINED:
8666 inner = s->info->ref;
8667 aliases = usymtab_allAliases (inner);
8668 ct = sRef_getType (inner);
8670 sRefSet_realElements (aliases, current)
8672 if (sRef_isReasonable (current))
8674 current = sRef_updateSref (current);
8676 if (ctype_equal (ct, sRef_getType (current)))
8678 sRef ptr = sRef_makePointer (current);
8683 } end_sRefSet_realElements;
8685 sRefSet_free (aliases);
8688 inner = s->info->arrayfetch->arr;
8689 aliases = usymtab_allAliases (inner);
8690 ct = sRef_getType (inner);
8692 sRefSet_realElements (aliases, current)
8694 if (sRef_isReasonable (current))
8696 current = sRef_updateSref (current);
8698 if (ctype_equal (ct, sRef_getType (current)))
8701 if (s->info->arrayfetch->indknown)
8703 sRef af = sRef_makeArrayFetchKnown (current, s->info->arrayfetch->ind);
8709 sRef af = sRef_makeArrayFetch (current);
8715 } end_sRefSet_realElements;
8717 sRefSet_free (aliases);
8720 inner = s->info->field->rec;
8721 aliases = usymtab_allAliases (inner);
8722 ct = sRef_getType (inner);
8725 sRefSet_realElements (aliases, current)
8727 if (sRef_isReasonable (current))
8729 current = sRef_updateSref (current);
8731 if (ctype_equal (ct, sRef_getType (current)))
8733 sRef f = sRef_makeField (current, s->info->field->field);
8738 } end_sRefSet_realElements;
8740 sRefSet_free (aliases);
8743 sRef_innerAliasSetCompleteParam (predf, s->info->conj->a, t);
8744 sRef_innerAliasSetCompleteParam (predf, s->info->conj->b, t);
8760 static void sRef_combineExKinds (/*@notnull@*/ sRef res, /*@notnull@*/ sRef other)
8762 exkind a1 = sRef_getExKind (res);
8763 exkind a2 = sRef_getExKind (other);
8765 if (a1 == a2 || a2 == XO_UNKNOWN)
8769 else if (a1 == XO_UNKNOWN)
8771 res->expinfo = stateInfo_update (res->expinfo, other->expinfo);
8776 res->expkind = XO_OBSERVER;
8781 ** Currently, this is a very ad hoc implementation, with lots of fixes to
8782 ** make real code work okay. I need to come up with some more general
8783 ** rules or principles here.
8787 sRef_combineAliasKindsError (/*@notnull@*/ sRef res,
8788 /*@notnull@*/ sRef other,
8789 clause cl, fileloc loc)
8791 bool hasError = FALSE;
8792 alkind ares = sRef_getAliasKind (res);
8793 alkind aother = sRef_getAliasKind (other);
8795 sRef_checkMutable (res);
8797 if (alkind_isDependent (ares))
8799 if (aother == AK_KEPT)
8801 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8802 res->aliaskind = AK_KEPT;
8806 if (aother == AK_LOCAL || aother == AK_STATIC
8807 || alkind_isTemp (aother))
8809 DPRINTF (("Setting dependent: %s", sRef_unparseFull (res)));
8810 res->aliaskind = AK_DEPENDENT;
8814 else if (alkind_isDependent (aother))
8816 if (ares == AK_KEPT)
8818 res->aliaskind = AK_KEPT;
8822 if (ares == AK_LOCAL || ares == AK_STATIC || alkind_isTemp (ares))
8824 DPRINTF (("Setting dependent: %s", sRef_unparseFull (res)));
8825 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8826 res->aliaskind = AK_DEPENDENT;
8830 else if ((ares == AK_LOCAL || ares == AK_UNIQUE
8831 || ares == AK_STATIC || alkind_isTemp (ares))
8832 && sRef_isFresh (other))
8835 ** cases like: if (s == NULL) s = malloc...;
8836 ** don't generate errors
8839 if (usymtab_isAltDefinitelyNullDeep (res))
8841 res->aliaskind = ares;
8848 else if ((aother == AK_LOCAL || aother == AK_UNIQUE
8849 || aother == AK_STATIC || alkind_isTemp (aother))
8850 && sRef_isFresh (res))
8853 ** cases like: if (s == NULL) s = malloc...;
8854 ** don't generate errors
8857 if (usymtab_isDefinitelyNullDeep (other))
8859 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8860 res->aliaskind = aother;
8867 else if (ares == AK_NEWREF && aother == AK_REFCOUNTED
8868 && sRef_isConst (other))
8870 res->aliaskind = AK_NEWREF;
8872 else if (aother == AK_NEWREF && ares == AK_REFCOUNTED
8873 && sRef_isConst (res))
8875 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8876 res->aliaskind = AK_NEWREF;
8878 else if (sRef_isLocalVar (res)
8879 && ((ares == AK_KEPT && aother == AK_LOCAL)
8880 || (aother == AK_KEPT && ares == AK_LOCAL)))
8882 res->aliaskind = AK_KEPT;
8884 else if ((ares == AK_OWNED && aother == AK_ONLY)
8885 || (aother == AK_OWNED && ares == AK_ONLY))
8887 res->aliaskind = AK_OWNED;
8889 if (aother == AK_OWNED)
8891 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8901 if (sRef_isThroughArrayFetch (res))
8904 (FLG_BRANCHSTATE, FLG_STRICTBRANCHSTATE,
8906 ("Clauses exit with %q possibly referencing %s storage %s, "
8909 alkind_unparse (aother),
8910 clause_nameTaken (cl),
8911 alkind_unparse (ares),
8912 clause_nameAlternate (cl)),
8915 sRef_showAliasInfo (res);
8916 sRef_showAliasInfo (other);
8917 res->aliaskind = AK_ERROR;
8921 if (ares == AK_KEPT || aother == AK_KEPT)
8923 sRef_maybeKill (res, loc);
8931 message ("Clauses exit with %q referencing %s storage %s, "
8934 alkind_unparse (aother),
8935 clause_nameTaken (cl),
8936 alkind_unparse (ares),
8937 clause_nameAlternate (cl)),
8940 sRef_showAliasInfo (res);
8941 sRef_showAliasInfo (other);
8943 res->aliaskind = AK_ERROR;
8947 res->aliaskind = (sRef_isLocalVar (res) ? AK_LOCAL : AK_UNKNOWN);
8952 sRef_combineAliasKinds (/*@notnull@*/ sRef res, /*@notnull@*/ sRef other,
8953 clause cl, fileloc loc)
8955 alkind ares = sRef_getAliasKind (res);
8956 alkind aother = sRef_getAliasKind (other);
8958 sRef_checkMutable (res);
8960 DPRINTF (("Combine alias kinds: \n\t%s / \n\t%s",
8961 sRef_unparseFull (res), sRef_unparseFull (other)));
8962 if (alkind_equal (ares, aother)
8963 || aother == AK_UNKNOWN
8964 || aother == AK_ERROR)
8966 ; /* keep current state */
8968 else if (sRef_isDead (res) || sRef_isDead (other))
8970 /* dead error reported (or storage is dead) */
8971 res ->aliaskind = AK_ERROR;
8973 else if (ares == AK_UNKNOWN || ares == AK_ERROR
8974 || sRef_isStateUndefined (res)
8975 || sRef_isDefinitelyNull (res))
8977 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8978 res->aliaskind = aother;
8980 else if (sRef_isStateUndefined (other)
8981 || sRef_isDefinitelyNull (other))
8985 else if (((ares == AK_UNIQUE || alkind_isTemp (ares))
8986 && aother == AK_LOCAL)
8987 || ((aother == AK_UNIQUE || alkind_isTemp (aother))
8988 && ares == AK_LOCAL))
8990 if (ares != AK_LOCAL)
8992 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8995 res->aliaskind = AK_LOCAL;
8997 else if ((ares == AK_OWNED && aother == AK_FRESH)
8998 || (aother == AK_OWNED && ares == AK_FRESH))
9000 if (ares != AK_FRESH)
9002 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
9005 res->aliaskind = AK_FRESH;
9007 else if ((ares == AK_KEEP && aother == AK_FRESH) ||
9008 (aother == AK_KEEP && ares == AK_FRESH))
9010 if (ares != AK_KEEP)
9012 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
9015 res->aliaskind = AK_KEEP;
9017 else if ((ares == AK_LOCAL && aother == AK_STACK) ||
9018 (aother == AK_LOCAL && ares == AK_STACK))
9020 if (ares != AK_STACK)
9022 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
9025 res->aliaskind = AK_STACK;
9027 else if ((ares == AK_LOCAL
9028 && (aother == AK_OWNED && sRef_isLocalVar (other)))
9029 || (aother == AK_LOCAL
9030 && (ares == AK_OWNED && sRef_isLocalVar (res))))
9032 if (ares != AK_LOCAL)
9034 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
9037 res->aliaskind = AK_LOCAL;
9039 else if ((ares == AK_FRESH && alkind_isOnly (aother))
9040 || (aother == AK_FRESH && alkind_isOnly (ares)))
9042 res->aliaskind = AK_FRESH;
9044 else if ((aother == AK_FRESH && sRef_definitelyNull (res))
9045 || (ares == AK_FRESH && sRef_definitelyNull (other)))
9047 if (ares != AK_FRESH)
9049 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
9050 res->aliaskind = AK_FRESH;
9053 else if ((sRef_isFresh (res) && sRef_isConst (other))
9054 || (sRef_isFresh (other) && sRef_isConst (res)))
9057 ** for NULL constantants
9061 if (!sRef_isFresh (res))
9063 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
9066 res->aliaskind = AK_FRESH;
9068 else if ((alkind_isStatic (aother) && sRef_isConst (res))
9069 || (alkind_isStatic (ares) && sRef_isConst (other)))
9071 if (!alkind_isStatic (ares))
9073 res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
9074 res->aliaskind = AK_STATIC;
9079 sRef_combineAliasKindsError (res, other, cl, loc);
9083 static void sRef_combineDefState (/*@notnull@*/ sRef res,
9084 /*@notnull@*/ sRef other)
9086 sstate s1 = res->defstate;
9087 sstate s2 = other->defstate;
9090 sRef_checkMutable (res);
9092 if (s1 == s2 || s2 == SS_UNKNOWN)
9096 else if (s1 == SS_UNKNOWN)
9105 if (s2 == SS_DEFINED)
9111 llcontbuglit ("ssfixed: not implemented");
9120 flip = (s2 != SS_DEFINED);
9138 res->definfo = stateInfo_update (res->definfo, other->definfo);
9143 extern /*@notnull@*/ sRef sRef_getConjA (sRef s)
9146 llassert (sRef_isConj (s));
9148 ret = s->info->conj->a;
9149 llassert (ret != NULL);
9153 extern /*@notnull@*/ sRef sRef_getConjB (sRef s)
9156 llassert (sRef_isConj (s));
9158 ret = s->info->conj->b;
9159 llassert (ret != NULL);
9163 extern /*@exposed@*/ sRef sRef_makeArrow (sRef s, /*@dependent@*/ cstring f)
9168 p = sRef_makePointer (s);
9169 ret = sRef_makeField (p, f);
9170 DPRINTF (("Arrow: %s => %s",
9171 sRef_unparseFull (s), sRef_unparseFull (ret)));
9175 extern /*@exposed@*/ sRef sRef_buildArrow (sRef s, cstring f)
9180 p = sRef_buildPointer (s);
9181 ret = sRef_buildField (p, f);
9186 static /*@null@*/ sinfo sinfo_copy (/*@notnull@*/ sRef s)
9193 ret = (sinfo) dmalloc (sizeof (*ret));
9194 ret->cvar = (cref) dmalloc (sizeof (*ret->cvar));
9195 ret->cvar->lexlevel = s->info->cvar->lexlevel;
9196 ret->cvar->index = s->info->cvar->index;
9200 ret = (sinfo) dmalloc (sizeof (*ret));
9201 ret->paramno = s->info->paramno;
9202 llassert (ret->paramno >= -1);
9206 ret = (sinfo) dmalloc (sizeof (*ret));
9207 ret->arrayfetch = (ainfo) dmalloc (sizeof (*ret->arrayfetch));
9208 ret->arrayfetch->indknown = s->info->arrayfetch->indknown;
9209 ret->arrayfetch->ind = s->info->arrayfetch->ind;
9210 ret->arrayfetch->arr = s->info->arrayfetch->arr; /* sRef_copy (s->info->arrayfetch->arr); */ /*@i32@*/
9214 ret = (sinfo) dmalloc (sizeof (*ret));
9215 ret->field = (fldinfo) dmalloc (sizeof (*ret->field));
9216 ret->field->rec = s->info->field->rec; /* sRef_copy (s->info->field->rec); */ /*@i32@*/
9217 ret->field->field = s->info->field->field;
9221 ret = (sinfo) dmalloc (sizeof (*ret));
9222 ret->object = s->info->object;
9229 ret = (sinfo) dmalloc (sizeof (*ret));
9230 ret->ref = s->info->ref; /* Ref_copy (s->info->ref); */
9234 ret = (sinfo) dmalloc (sizeof (*ret));
9235 ret->conj = (cjinfo) dmalloc (sizeof (*ret->conj));
9236 ret->conj->a = s->info->conj->a; /* sRef_copy (s->info->conj->a); */
9237 ret->conj->b = s->info->conj->b; /* sRef_copy (s->info->conj->b);*/
9240 ret = (sinfo) dmalloc (sizeof (*ret));
9241 ret->spec = s->info->spec;
9244 case SK_UNCONSTRAINED:
9246 ret = (sinfo) dmalloc (sizeof (*ret));
9247 ret->fname = s->info->fname;
9254 llassertprint (s->info == NULL, ("s = %s", sRef_unparse (s)));
9262 static /*@null@*/ sinfo sinfo_fullCopy (/*@notnull@*/ sRef s)
9267 ** Since its a full copy, only storage is assigned
9268 ** to dependent fields.
9275 ret = (sinfo) dmalloc (sizeof (*ret));
9276 ret->cvar = (cref) dmalloc (sizeof (*ret->cvar));
9277 ret->cvar->lexlevel = s->info->cvar->lexlevel;
9278 ret->cvar->index = s->info->cvar->index;
9282 ret = (sinfo) dmalloc (sizeof (*ret));
9283 ret->paramno = s->info->paramno;
9284 llassert (ret->paramno >= -1);
9288 ret = (sinfo) dmalloc (sizeof (*ret));
9289 ret->arrayfetch = (ainfo) dmalloc (sizeof (*ret->arrayfetch));
9290 ret->arrayfetch->indknown = s->info->arrayfetch->indknown;
9291 ret->arrayfetch->ind = s->info->arrayfetch->ind;
9292 ret->arrayfetch->arr = sRef_saveCopy (s->info->arrayfetch->arr);
9296 ret = (sinfo) dmalloc (sizeof (*ret));
9297 ret->field = (fldinfo) dmalloc (sizeof (*ret->field));
9298 ret->field->rec = sRef_saveCopy (s->info->field->rec);
9299 ret->field->field = s->info->field->field;
9303 ret = (sinfo) dmalloc (sizeof (*ret));
9304 ret->object = s->info->object;
9311 ret = (sinfo) dmalloc (sizeof (*ret));
9312 ret->ref = sRef_saveCopy (s->info->ref);
9316 ret = (sinfo) dmalloc (sizeof (*ret));
9317 ret->conj = (cjinfo) dmalloc (sizeof (*ret->conj));
9318 ret->conj->a = sRef_saveCopy (s->info->conj->a);
9319 ret->conj->b = sRef_saveCopy (s->info->conj->b);
9322 ret = (sinfo) dmalloc (sizeof (*ret));
9323 ret->spec = s->info->spec;
9326 case SK_UNCONSTRAINED:
9327 ret = (sinfo) dmalloc (sizeof (*ret));
9328 ret->fname = s->info->fname;
9334 llassert (s->info == NULL);
9344 sinfo_update (/*@notnull@*/ /*@exposed@*/ sRef res,
9345 /*@notnull@*/ /*@exposed@*/ sRef other)
9347 llassert (res->kind == other->kind);
9352 res->info->cvar->lexlevel = other->info->cvar->lexlevel;
9353 res->info->cvar->index = other->info->cvar->index;
9357 res->info->paramno = other->info->paramno;
9358 llassert (res->info->paramno >= -1);
9362 res->info->arrayfetch->indknown = other->info->arrayfetch->indknown;
9363 res->info->arrayfetch->ind = other->info->arrayfetch->ind;
9364 res->info->arrayfetch->arr = other->info->arrayfetch->arr;
9368 res->info->field->rec = other->info->field->rec;
9369 res->info->field->field = other->info->field->field;
9373 res->info->object = other->info->object;
9380 res->info->ref = other->info->ref;
9384 res->info->conj->a = other->info->conj->a;
9385 res->info->conj->b = other->info->conj->b;
9389 res->info->spec = other->info->spec;
9393 case SK_UNCONSTRAINED:
9394 res->info->fname = other->info->fname;
9401 llassert (res->info == NULL);
9406 static void sinfo_free (/*@special@*/ /*@temp@*/ /*@notnull@*/ sRef s)
9407 /*@uses s->kind, s->info@*/
9408 /*@releases s->info@*/
9413 DPRINTF (("Free sinfo: [%p]", s->info->cvar));
9414 sfree (s->info->cvar);
9421 DPRINTF (("Free sinfo: [%p]", s->info->arrayfetch));
9422 sfree (s->info->arrayfetch);
9426 DPRINTF (("Free sinfo: [%p]", s->info->field));
9427 sfree (s->info->field);
9436 case SK_EXTERNAL: /*@i32 is copy now! */
9440 DPRINTF (("Free sinfo: [%p]", s->info->conj));
9441 sfree (s->info->conj);
9444 case SK_UNCONSTRAINED:
9454 if (s->info != NULL) {
9455 DPRINTF (("Free sinfo: [%p]", s->info));
9461 bool sRef_isNSLocalVar (sRef s)
9463 if (sRef_isLocalVar (s))
9465 uentry ue = sRef_getUentry (s);
9467 return (!uentry_isStatic (ue));
9475 bool sRef_isLocalVar (sRef s)
9477 if (sRef_isValid(s))
9479 return (s->kind == SK_CVAR
9480 && (s->info->cvar->lexlevel > fileScope));
9486 bool sRef_isRealLocalVar (sRef s)
9488 if (sRef_isValid(s))
9490 if (s->kind == SK_CVAR)
9492 if (s->info->cvar->lexlevel == functionScope)
9494 uentry ue = sRef_getUentry (s);
9496 if (uentry_isAnyParam (ue)
9497 || uentry_isRefParam (ue))
9508 return (s->info->cvar->lexlevel > functionScope);
9516 bool sRef_isLocalParamVar (sRef s)
9518 if (sRef_isValid(s))
9520 return (s->kind == SK_PARAM
9521 || (s->kind == SK_CVAR
9522 && (s->info->cvar->lexlevel > fileScope)));
9528 static speckind speckind_fromInt (int i)
9531 llassert (i >= SR_NOTHING && i <= SR_SYSTEM);
9534 return ((speckind) i);
9538 static void sRef_updateNullState (/*@notnull@*/ sRef res, /*@notnull@*/ sRef other)
9541 res->nullstate = other->nullstate;
9542 res->nullinfo = stateInfo_update (res->nullinfo, other->nullinfo);
9543 sRef_resetAliasKind (res);
9546 void sRef_combineNullState (/*@notnull@*/ sRef res, /*@notnull@*/ sRef other)
9548 nstate n1 = sRef_getNullState (res);
9549 nstate n2 = sRef_getNullState (other);
9553 if (n1 == n2 || n2 == NS_UNKNOWN)
9559 /* note: n2 is not unknown or defnull */
9563 case NS_ERROR: nn = NS_ERROR; break;
9564 case NS_UNKNOWN: flip = TRUE; nn = n2; break;
9565 case NS_POSNULL: break;
9566 case NS_DEFNULL: nn = NS_POSNULL; break;
9567 case NS_RELNULL: break;
9569 if (n2 == NS_MNOTNULL)
9580 if (n2 == NS_NOTNULL)
9599 res->nullinfo = stateInfo_update (res->nullinfo, other->nullinfo);
9602 res->nullstate = nn;
9603 sRef_resetAliasKind (res);
9606 cstring sRef_nullMessage (sRef s)
9608 llassert (sRef_isReasonable (s));
9610 switch (sRef_getNullState (s))
9614 return (cstring_makeLiteralTemp ("null"));
9616 return (cstring_makeLiteralTemp ("possibly null"));
9621 /*@observer@*/ cstring sRef_ntMessage (sRef s)
9623 llassert (sRef_isReasonable (s));
9625 switch (s->nullstate)
9629 return (cstring_makeLiteralTemp ("not nullterminated"));
9631 return (cstring_makeLiteralTemp ("possibly non-nullterminated"));
9638 sRef sRef_fixResultType (/*@returned@*/ sRef s, ctype typ, uentry ue)
9640 sRef tmp = sRef_undefined;
9643 llassert (sRef_isReasonable (s));
9654 tmp = sRef_fixResultType (s->info->arrayfetch->arr, typ, ue);
9656 ct = ctype_realType (sRef_getType (tmp));
9659 if (ctype_isKnown (ct))
9661 if (ctype_isAP (ct))
9670 ("Special clause indexes non-array (%t): *%q",
9671 ct, sRef_unparse (s->info->arrayfetch->arr)),
9672 uentry_whereLast (ue));
9676 tmp = sRef_fixResultType (s->info->arrayfetch->arr, typ, ue);
9678 if (s->info->arrayfetch->indknown)
9680 ret = sRef_makeArrayFetchKnown (tmp, s->info->arrayfetch->ind);
9684 ret = sRef_makeArrayFetch (tmp);
9690 sRef rec = sRef_fixResultType (s->info->field->rec, typ, ue);
9691 ctype ct = ctype_realType (sRef_getType (rec));
9693 if (ctype_isKnown (ct))
9695 if (ctype_isSU (ct))
9697 if (uentry_isValid (uentryList_lookupField (ctype_getFields (ct),
9698 s->info->field->field)))
9707 ("Special clause accesses non-existent field of result: %q.%s",
9708 sRef_unparse (rec), s->info->field->field),
9709 uentry_whereLast (ue));
9717 ("Special clause accesses field of non-struct or union result (%t): %q.%s",
9718 ct, sRef_unparse (rec), s->info->field->field),
9719 uentry_whereLast (ue));
9723 ret = sRef_makeField (tmp, s->info->field->field);
9729 tmp = sRef_fixResultType (s->info->ref, typ, ue);
9731 ct = ctype_realType (sRef_getType (tmp));
9733 if (ctype_isKnown (ct))
9735 if (ctype_isAP (ct))
9744 ("Special clause dereferences non-pointer (%t): *%q",
9745 ct, sRef_unparse (s->info->ref)),
9746 uentry_whereLast (ue));
9750 ret = sRef_makePointer (tmp);
9757 ("Special clause uses & operator (not allowed): &%q", sRef_unparse (s->info->ref)),
9758 uentry_whereLast (ue));
9767 bool sRef_isOnly (sRef s)
9769 return (sRef_isValid(s) && alkind_isOnly (s->aliaskind));
9772 bool sRef_isDependent (sRef s)
9774 return (sRef_isValid(s) && alkind_isDependent (s->aliaskind));
9777 bool sRef_isOwned (sRef s)
9779 return (sRef_isReasonable (s) && (s->aliaskind == AK_OWNED));
9782 bool sRef_isKeep (sRef s)
9784 return (sRef_isReasonable (s) && (s->aliaskind == AK_KEEP));
9787 bool sRef_isTemp (sRef s)
9789 return (sRef_isReasonable (s) && alkind_isTemp (s->aliaskind));
9792 bool sRef_isLocalState (sRef s)
9794 return (sRef_isReasonable (s) && (s->aliaskind == AK_LOCAL));
9797 bool sRef_isUnique (sRef s)
9799 return (sRef_isReasonable (s) && (s->aliaskind == AK_UNIQUE));
9802 bool sRef_isShared (sRef s)
9804 return (sRef_isReasonable (s) && (s->aliaskind == AK_SHARED));
9807 bool sRef_isExposed (sRef s)
9809 return (sRef_isReasonable (s) && (s->expkind == XO_EXPOSED));
9812 bool sRef_isObserver (sRef s)
9814 return (sRef_isReasonable (s) && (s->expkind == XO_OBSERVER));
9817 bool sRef_isFresh (sRef s)
9819 return (sRef_isReasonable (s) && (s->aliaskind == AK_FRESH));
9822 bool sRef_isDefinitelyNull (sRef s)
9824 return (sRef_isReasonable (s) && (sRef_getNullState (s) == NS_DEFNULL
9825 || sRef_getNullState (s) == NS_CONSTNULL));
9828 bool sRef_isAllocated (sRef s)
9830 return (sRef_isReasonable (s) && (s->defstate == SS_ALLOCATED));
9833 bool sRef_isStack (sRef s)
9835 return (sRef_isReasonable (s) && (s->aliaskind == AK_STACK));
9838 bool sRef_isNotNull (sRef s)
9840 return (sRef_isValid(s) && (sRef_getNullState (s) == NS_MNOTNULL
9841 || sRef_getNullState (s) == NS_NOTNULL));
9844 alkind sRef_getAliasKind (sRef s)
9846 if (sRef_isValid(s)) {
9847 llassert (alkind_isValid (s->aliaskind));
9848 return s->aliaskind;
9854 nstate sRef_getNullState (sRef s)
9856 if (sRef_isReasonable (s)) {
9857 llassert (nstate_isValid (s->nullstate));
9858 return s->nullstate;
9864 void sRef_reflectAnnotation (sRef s, annotationInfo a, fileloc loc)
9866 if (sRef_isReasonable (s))
9868 if (!valueTable_isDefined (s->state))
9870 s->state = valueTable_create (1);
9873 cstring_copy (metaStateInfo_getName (annotationInfo_getState (a))),
9874 stateValue_create (annotationInfo_getValue (a),
9875 stateInfo_makeLoc (loc, SA_DECLARED)));
9879 DPRINTF (("reflect loc: %s", fileloc_unparse (loc)));
9882 metaStateInfo_getName (annotationInfo_getState (a)),
9883 stateValue_create (annotationInfo_getValue (a),
9884 stateInfo_makeLoc (loc, SA_DECLARED)));
9886 DPRINTF (("sref: %s", sRef_unparse (s)));
9887 DPRINTF (("sref: %s", sRef_unparseFull (s)));
9892 void sRef_setMetaStateValueComplete (sRef s, cstring key, int value, fileloc loc)
9894 sRefSet aliases = usymtab_allAliases (s);
9896 sRef_setMetaStateValue (s, key, value, loc);
9898 sRefSet_realElements (aliases, current)
9900 if (sRef_isReasonable (current))
9902 current = sRef_updateSref (current);
9903 sRef_setMetaStateValue (current, key, value, loc);
9905 } end_sRefSet_realElements ;
9907 sRefSet_free (aliases);
9910 void sRef_setMetaStateValue (sRef s, cstring key, int value, fileloc loc)
9912 sRef_checkMutable (s);
9914 if (sRef_isReasonable (s))
9916 if (!valueTable_isDefined (s->state))
9918 DPRINTF (("inserting state: %s: %s %d", sRef_unparse (s), key, value));
9919 s->state = valueTable_create (1);
9920 valueTable_insert (s->state, cstring_copy (key),
9921 stateValue_create (value,
9922 stateInfo_makeLoc (loc, SA_CHANGED)));
9926 DPRINTF (("Updating state: %s: %s %d / %s", sRef_unparse (s), key, value,
9927 fileloc_unparse (loc)));
9928 if (valueTable_contains (s->state, key))
9931 (s->state, key, stateValue_create (value,
9932 stateInfo_makeLoc (loc, SA_CHANGED)));
9937 (s->state, cstring_copy (key),
9938 stateValue_create (value, stateInfo_makeLoc (loc, SA_CHANGED)));
9941 DPRINTF (("After: %s", sRef_unparseFull (s)));
9946 bool sRef_checkMetaStateValue (sRef s, cstring key, int value)
9948 if (sRef_isReasonable (s))
9950 if (valueTable_isDefined (s->state))
9954 DPRINTF (("check state: %s: %s %d", sRef_unparse (s), key, value));
9956 val = valueTable_lookup (s->state, key);
9957 llassert (stateValue_isDefined (val));
9958 return (stateValue_isError (val)
9959 || stateValue_getValue (val) == value);
9972 /*@observer@*/ stateValue sRef_getMetaStateValue (sRef s, cstring key)
9974 if (sRef_isReasonable (s))
9976 if (valueTable_isDefined (s->state))
9980 val = valueTable_lookup (s->state, key);
9981 /* Okay if its not defined, just returns stateValue_undefined */
9986 return stateValue_undefined;
9991 return stateValue_undefined;
9995 /*@observer@*/ valueTable sRef_getValueTable (sRef s)
9997 DPRINTF (("Get value table: %s", sRef_unparse (s)));
9999 if (sRef_isReasonable (s))
10001 llassert (sRef_isReasonable (s));
10002 DPRINTF (("Value table: %s", valueTable_unparse (s->state)));
10007 DPRINTF (("No value table!"));
10008 return valueTable_undefined;
10012 bool sRef_makeStateSpecial (sRef s)
10015 ** Default defined state can be made special.
10018 llassert (sRef_isReasonable (s)); /*@i523 why doesn't null-checking work!??? */
10020 if (s->defstate == SS_UNKNOWN || s->defstate == SS_DEFINED || s->defstate == SS_SPECIAL)
10022 /* s->aliaskind = AK_IMPTEMP; */ /* evans 2001-07-23 shouldn't effect alias state */
10023 s->defstate = SS_SPECIAL;
10024 DPRINTF (("Made special: %s", sRef_unparseFull (s)));
10029 /* s->aliaskind = AK_IMPTEMP; */
10030 s->defstate = SS_SPECIAL;
10035 void sRef_markImmutable (sRef s)
10037 if (sRef_isReasonable (s))
10039 DPRINTF (("Mark immutable: %s", sRef_unparseFull (s)));
10044 bool sRef_definitelyNullContext (sRef s)
10046 return (sRef_definitelyNull (s)
10047 || usymtab_isDefinitelyNullDeep (s));
10050 bool sRef_definitelyNullAltContext (sRef s)
10052 return (sRef_definitelyNull (s)
10053 || usymtab_isAltDefinitelyNullDeep (s));
10057 /* start modifications */
10058 struct s_bbufinfo sRef_getNullTerminatedState (sRef p_s) {
10059 struct s_bbufinfo BUFSTATE_UNKNOWN;
10060 BUFSTATE_UNKNOWN.bufstate = BB_NOTNULLTERMINATED;
10061 BUFSTATE_UNKNOWN.size = 0;
10062 BUFSTATE_UNKNOWN.len = 0;
10064 if (sRef_isValid(p_s))
10065 return p_s->bufinfo;
10066 return BUFSTATE_UNKNOWN;
10069 void sRef_setNullTerminatedState(sRef p_s) {
10070 if(sRef_isReasonable (p_s)) {
10071 p_s->bufinfo.bufstate = BB_NULLTERMINATED;
10073 llfatalbug( message("sRef_setNT passed a invalid sRef\n"));
10078 void sRef_setPossiblyNullTerminatedState(sRef p_s) {
10079 if( sRef_isReasonable (p_s)) {
10080 p_s->bufinfo.bufstate = BB_POSSIBLYNULLTERMINATED;
10082 llfatalbug( message("sRef_setPossNT passed a invalid sRef\n"));
10086 void sRef_setNotNullTerminatedState(sRef p_s) {
10087 if( sRef_isReasonable (p_s)) {
10088 p_s->bufinfo.bufstate = BB_NOTNULLTERMINATED;
10090 llfatalbug( message("sRef_unsetNT passed a invalid sRef\n"));
10094 void sRef_setLen(sRef p_s, int len) {
10095 if (sRef_isReasonable (p_s) && sRef_isNullTerminated(p_s))
10097 p_s->bufinfo.len = len;
10101 llfatalbug( message("sRef_setLen passed an invalid sRef\n"));
10106 void sRef_setSize(sRef p_s, int size) {
10107 if( sRef_isValid(p_s))
10109 p_s->bufinfo.size = size;
10113 llfatalbug( message("sRef_setSize passed a invalid sRef\n"));
10117 void sRef_resetLen(sRef p_s) {
10118 if (sRef_isReasonable (p_s))
10120 p_s->bufinfo.len = 0;
10124 llfatalbug (message ("sRef_setLen passed an invalid sRef\n"));
10128 /*drl7x 11/28/2000 */
10130 bool sRef_isFixedArray (sRef p_s) /*@*/ {
10132 c = sRef_getType (p_s);
10133 return ( ctype_isFixedArray (c) );
10136 size_t sRef_getArraySize (sRef p_s) /*@*/
10139 llassert (sRef_isFixedArray(p_s) );
10140 DPRINTF (( message ("sRef_getArraySize getting array size for %s", sRef_unparse(p_s) ) ));
10142 c = sRef_getType (p_s);
10143 return (ctype_getArraySize (c));
10146 void sRef_setValue (sRef s, multiVal val)
10148 if (!sRef_isReasonable (s))
10150 llcontbuglit ("Unreasonable sRef");
10151 llcontbug (message ("sRef: %s", sRef_unparse (s)));
10155 multiVal_free (s->val);
10159 bool sRef_hasValue (sRef s)
10161 return (sRef_isReasonable (s)
10162 && multiVal_isDefined (s->val));
10165 multiVal sRef_getValue (sRef s)
10167 if (sRef_isReasonable (s))
10172 return multiVal_undefined;