2 ** LCLint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2000 University of Virginia,
4 ** Massachusetts Institute of Technology
6 ** This program is free software; you can redistribute it and/or modify it
7 ** under the terms of the GNU General Public License as published by the
8 ** Free Software Foundation; either version 2 of the License, or (at your
9 ** option) any later version.
11 ** This program is distributed in the hope that it will be useful, but
12 ** WITHOUT ANY WARRANTY; without even the implied warranty of
13 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 ** General Public License for more details.
16 ** The GNU General Public License is available from http://www.gnu.org/ or
17 ** the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
18 ** MA 02111-1307, USA.
20 ** For information on lclint: lclint-request@cs.virginia.edu
21 ** To report a bug: lclint-bug@cs.virginia.edu
22 ** For more information: http://lclint.cs.virginia.edu
28 ** storeRef's are kept in allRefs for each function scope, and all are
29 ** free'd at the end of the function. This relies on the constraint that
30 ** no storeRef created while checking a function is used outside that
33 ** storeRefs in the file and global scopes are free'd by the uentry.
37 # include "lclintMacros.nf"
39 # include "exprChecks.h"
40 # include "aliasChecks.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 bool sRef_isDerived (sRef p_s) /*@*/ ;
56 static /*@exposed@*/ sRef sRef_fixDirectBase (sRef p_s, sRef p_base)
57 /*@modifies p_base@*/ ;
59 static bool sRef_isAllocatedStorage (sRef p_s) /*@*/ ;
60 static void sRef_setNullErrorLoc (sRef p_s, fileloc) /*@*/ ;
63 sRef_aliasSetComplete (void (p_predf) (sRef, fileloc), sRef p_s, fileloc p_loc)
66 static int sRef_depth (sRef p_s) /*@*/ ;
69 sRef_innerAliasSetComplete (void (p_predf) (sRef, fileloc), sRef p_s,
74 sRef_innerAliasSetCompleteParam (void (p_predf) (sRef, sRef), sRef p_s, sRef p_t)
78 sRef_aliasSetCompleteParam (void (p_predf) (sRef, alkind, fileloc), sRef p_s,
79 alkind p_kind, fileloc p_loc)
82 static speckind speckind_fromInt (int p_i);
83 static bool sRef_equivalent (sRef p_s1, sRef p_s2);
84 static bool sRef_isDeepUnionField (sRef p_s);
85 static void sRef_addDeriv (/*@notnull@*/ sRef p_s, /*@notnull@*/ sRef p_t);
86 static sRef sRef_makeResultType (ctype p_ct) /*@*/ ;
87 static bool sRef_checkModify (sRef p_s, sRefSet p_sl) /*@*/ ;
89 static bool skind_isSimple (skind sk)
93 case SK_PARAM: case SK_CVAR: case SK_CONST:
94 case SK_OBJECT: case SK_UNKNOWN: case SK_NEW:
101 static void sinfo_free (/*@special@*/ /*@temp@*/ /*@notnull@*/ sRef p_s)
102 /*@uses p_s->kind, p_s->info@*/
103 /*@releases p_s->info@*/ ;
105 static /*@null@*/ sinfo sinfo_copy (/*@notnull@*/ sRef p_s) /*@*/ ;
106 static void sRef_setPartsFromUentry (sRef p_s, uentry p_ue)
108 static bool checkDeadState (/*@notnull@*/ sRef p_el, bool p_tbranch, fileloc p_loc);
109 static sRef sRef_constructPointerAux (/*@notnull@*/ /*@exposed@*/ sRef p_t) /*@*/ ;
112 sRef_combineExKinds (/*@notnull@*/ sRef p_res, /*@notnull@*/ sRef p_other)
113 /*@modifies p_res@*/ ;
116 sRef_combineAliasKinds (/*@notnull@*/ sRef p_res, /*@notnull@*/ sRef p_other,
117 clause p_cl, fileloc p_loc)
118 /*@modifies p_res@*/ ;
121 sRef_combineNullState (/*@notnull@*/ sRef p_res, /*@notnull@*/ sRef p_other)
122 /*@modifies p_res@*/ ;
125 sRef_combineDefState (/*@notnull@*/ sRef p_res, /*@notnull@*/ sRef p_other)
126 /*@modifies p_res@*/ ;
128 static void sRef_setStateFromAbstractUentry (sRef p_s, uentry p_ue)
132 sinfo_update (/*@notnull@*/ /*@exposed@*/ sRef p_res,
133 /*@notnull@*/ /*@exposed@*/ sRef p_other);
134 static /*@only@*/ alinfo alinfo_makeRefLoc (/*@exposed@*/ sRef p_ref, fileloc p_loc);
135 static void sRef_setDefinedAux (sRef p_s, fileloc p_loc, bool p_clear)
137 static void sRef_setDefinedNoClear (sRef p_s, fileloc p_loc)
139 static void sRef_setStateAux (sRef p_s, sstate p_ss, fileloc p_loc)
142 static /*@exposed@*/ sRef
143 sRef_buildNCField (/*@exposed@*/ sRef p_rec, /*@exposed@*/ cstring p_f);
146 sRef_mergeStateAux (/*@notnull@*/ sRef p_res, /*@notnull@*/ sRef p_other,
147 clause p_cl, bool p_opt, fileloc p_loc,
149 /*@modifies p_res, p_other@*/ ;
151 static /*@null@*/ sinfo sinfo_fullCopy (/*@notnull@*/ sRef p_s);
152 static bool sRef_doModify (sRef p_s, sRefSet p_sl) /*@modifies p_s@*/ ;
153 static bool sRef_doModifyVal (sRef p_s, sRefSet p_sl) /*@modifies p_s@*/;
154 static bool sRef_checkModifyVal (sRef p_s, sRefSet p_sl) /*@*/ ;
156 static /*@only@*/ sRefSet
157 sRef_mergeDerivs (/*@only@*/ sRefSet p_res, sRefSet p_other,
158 bool p_opt, clause p_cl, fileloc p_loc);
160 static /*@only@*/ sRefSet
161 sRef_mergeUnionDerivs (/*@only@*/ sRefSet p_res,
162 /*@exposed@*/ sRefSet p_other,
163 bool p_opt, clause p_cl, fileloc p_loc);
165 static /*@only@*/ sRefSet
166 sRef_mergePdefinedDerivs (/*@only@*/ sRefSet p_res, sRefSet p_other, bool p_opt,
167 clause p_cl, fileloc p_loc);
169 static /*@only@*/ cstring sRef_unparseWithArgs (sRef p_s, uentryList p_args);
170 static /*@only@*/ cstring sRef_unparseNoArgs (sRef p_s);
172 static /*@exposed@*/ sRef sRef_findDerivedPointer (sRef p_s);
173 static /*@exposed@*/ sRef sRef_findDerivedField (/*@notnull@*/ sRef p_rec, cstring p_f);
174 static /*@exposed@*/ sRef
175 sRef_getDeriv (/*@notnull@*/ /*@returned@*/ sRef p_set, sRef p_guide);
177 static bool inFunction = FALSE;
178 static /*@only@*/ sRefTable allRefs;
180 /* # define DEBUGREFS */
184 static totnsrefs = 0;
185 static maxnsrefs = 0;
186 static ntotrefers = 0;
190 /*@constant null alinfo alinfo_undefined; @*/
191 # define alinfo_undefined ((alinfo) NULL)
193 static /*@only@*/ /*@notnull@*/ alinfo alinfo_makeLoc (fileloc p_loc);
194 static /*@only@*/ alinfo alinfo_copy (alinfo p_a);
196 static /*@checked@*/ bool protectDerivs = FALSE;
198 void sRef_protectDerivs (void) /*@modifies protectDerivs@*/
200 llassert (!protectDerivs);
201 protectDerivs = TRUE;
204 void sRef_clearProtectDerivs (void) /*@modifies protectDerivs@*/
206 llassert (protectDerivs);
207 protectDerivs = FALSE;
211 ** hmmm...here be kind of a hack. This function mysteriously appeared
212 ** in my code, but I'm sure I didn't write it.
216 sRef_isRecursiveField (sRef s)
218 if (sRef_isField (s))
220 if (sRef_depth (s) > 13)
225 fieldname = sRef_getField (s);
226 base = sRef_getBase (s);
228 while (sRef_isValid (base))
230 if (sRef_isField (base))
232 if (cstring_equal (fieldname, sRef_getField (base)))
238 base = sRef_getBaseSafe (base);
247 sRef_addDeriv (/*@notnull@*/ sRef s, /*@notnull@*/ sRef t)
249 if (!context_inProtectVars ()
253 && !sRef_isConst (s))
255 int sd = sRef_depth (s);
256 int td = sRef_depth (t);
263 if (sRef_isGlobal (s))
265 if (context_inFunctionLike ()
266 && ctype_isKnown (sRef_getType (s))
267 && !ctype_isFunction (sRef_getType (s)))
269 globSet g = context_getUsedGlobs ();
271 if (!globSet_member (g, s))
274 ** don't report as a bug
278 (message ("sRef_addDeriv: global variable not in used "
279 "globs: %q / %s / %q",
281 ctype_unparse (sRef_getType (s)),
282 sRefSet_unparse (s->deriv)));
287 s->deriv = sRefSet_insert (s->deriv, t);
293 s->deriv = sRefSet_insert (s->deriv, t);
299 sRef_deepPred (bool (predf) (sRef), sRef s)
301 if (sRef_isValid (s))
303 if ((*predf)(s)) return TRUE;
308 return (sRef_deepPred (predf, s->info->ref));
310 return (sRef_deepPred (predf, s->info->arrayfetch->arr));
312 return (sRef_deepPred (predf, s->info->field->rec));
314 return (sRef_deepPred (predf, s->info->conj->a)
315 || sRef_deepPred (predf, s->info->conj->b));
324 bool sRef_modInFunction (void)
329 void sRef_setStateFromType (sRef s, ctype ct)
331 if (sRef_isValid (s))
333 if (ctype_isUser (ct))
335 sRef_setStateFromUentry
336 (s, usymtab_getTypeEntry (ctype_typeId (ct)));
338 else if (ctype_isAbstract (ct))
340 sRef_setStateFromAbstractUentry
341 (s, usymtab_getTypeEntry (ctype_typeId (ct)));
345 ; /* not a user type */
350 static void sRef_setTypeState (sRef s)
352 if (sRef_isValid (s))
354 sRef_setStateFromType (s, s->type);
358 static void alinfo_free (/*@only@*/ alinfo a)
362 fileloc_free (a->loc);
367 static /*@only@*/ alinfo alinfo_update (/*@only@*/ alinfo old, alinfo newinfo)
369 ** returns an alinfo with the same value as new. May reuse the
370 ** storage of old. (i.e., same effect as copy, but more
376 old = alinfo_copy (newinfo);
378 else if (newinfo == NULL)
385 old->loc = fileloc_update (old->loc, newinfo->loc);
386 old->ref = newinfo->ref;
387 old->ue = newinfo->ue;
393 static /*@only@*/ alinfo alinfo_updateLoc (/*@only@*/ alinfo old, fileloc loc)
397 old = alinfo_makeLoc (loc);
401 old->loc = fileloc_update (old->loc, loc);
402 old->ue = uentry_undefined;
403 old->ref = sRef_undefined;
409 static /*@only@*/ alinfo
410 alinfo_updateRefLoc (/*@only@*/ alinfo old, /*@dependent@*/ sRef ref, fileloc loc)
414 old = alinfo_makeRefLoc (ref, loc);
418 old->loc = fileloc_update (old->loc, loc);
419 old->ue = uentry_undefined;
426 static /*@only@*/ alinfo
427 alinfo_copy (alinfo a)
435 alinfo ret = (alinfo) dmalloc (sizeof (*ret));
437 ret->loc = fileloc_copy (a->loc); /*< should report bug without copy! >*/
446 sRef_hasAliasInfoLoc (sRef s)
448 return (sRef_isValid (s) && (s->aliasinfo != NULL)
449 && (fileloc_isDefined (s->aliasinfo->loc)));
452 static /*@falsenull@*/ bool
453 sRef_hasStateInfoLoc (sRef s)
455 return (sRef_isValid (s) && (s->definfo != NULL)
456 && (fileloc_isDefined (s->definfo->loc)));
459 static /*@falsenull@*/ bool
460 sRef_hasExpInfoLoc (sRef s)
462 return (sRef_isValid (s)
463 && (s->expinfo != NULL) && (fileloc_isDefined (s->expinfo->loc)));
467 sRef_hasNullInfoLoc (sRef s)
469 return (sRef_isValid (s) && (s->nullinfo != NULL)
470 && (fileloc_isDefined (s->nullinfo->loc)));
474 sRef_hasAliasInfoRef (sRef s)
476 return (sRef_isValid (s) && (s->aliasinfo != NULL)
477 && (sRef_isValid (s->aliasinfo->ref)));
480 static /*@observer@*/ fileloc
481 sRef_getAliasInfoLoc (/*@exposed@*/ sRef s)
483 llassert (sRef_isValid (s) && s->aliasinfo != NULL
484 && (fileloc_isDefined (s->aliasinfo->loc)));
485 return (s->aliasinfo->loc);
488 static /*@observer@*/ fileloc
489 sRef_getStateInfoLoc (/*@exposed@*/ sRef s)
491 llassert (sRef_isValid (s) && s->definfo != NULL
492 && (fileloc_isDefined (s->definfo->loc)));
493 return (s->definfo->loc);
496 static /*@observer@*/ fileloc
497 sRef_getExpInfoLoc (/*@exposed@*/ sRef s)
499 llassert (sRef_isValid (s) && s->expinfo != NULL
500 && (fileloc_isDefined (s->expinfo->loc)));
501 return (s->expinfo->loc);
504 static /*@observer@*/ fileloc
505 sRef_getNullInfoLoc (/*@exposed@*/ sRef s)
507 llassert (sRef_isValid (s) && s->nullinfo != NULL
508 && (fileloc_isDefined (s->nullinfo->loc)));
509 return (s->nullinfo->loc);
513 sRef_getAliasInfoRef (/*@exposed@*/ sRef s)
515 llassert (sRef_isValid (s) && s->aliasinfo != NULL);
516 return (s->aliasinfo->ref);
519 static /*@only@*/ /*@notnull@*/ alinfo
520 alinfo_makeLoc (fileloc loc)
522 alinfo ret = (alinfo) dmalloc (sizeof (*ret));
524 ret->loc = fileloc_copy (loc); /* don't need to copy! */
525 ret->ue = uentry_undefined;
526 ret->ref = sRef_undefined;
531 static /*@only@*/ alinfo
532 alinfo_makeRefLoc (/*@exposed@*/ sRef ref, fileloc loc)
534 alinfo ret = (alinfo) dmalloc (sizeof (*ret));
536 ret->loc = fileloc_copy (loc);
538 ret->ue = uentry_undefined;
544 ** This function should be called before new sRefs are created
545 ** somewhere where they will have a lifetime greater than the
546 ** current function scope.
549 void sRef_setGlobalScope ()
551 llassert (inFunction);
555 void sRef_clearGlobalScope ()
557 llassert (!inFunction);
561 static bool oldInFunction = FALSE;
563 void sRef_setGlobalScopeSafe ()
565 oldInFunction = inFunction;
569 void sRef_clearGlobalScopeSafe ()
571 inFunction = oldInFunction;
574 void sRef_enterFunctionScope ()
576 llassert (!inFunction);
577 llassert (sRefTable_isEmpty (allRefs));
581 void sRef_exitFunctionScope ()
586 sRefTable_clear (allRefs);
591 llbuglit ("sRef_exitFunctionScope: not in function");
595 void sRef_destroyMod () /*@globals killed allRefs;@*/
598 llmsg (message ("Live: %d / %d ", nsrefs, totnsrefs));
601 sRefTable_free (allRefs);
605 ** Result of sRef_alloc is dependent since allRefs may
606 ** reference it. It is only if !inFunction.
609 static /*@dependent@*/ /*@out@*/ /*@notnull@*/ sRef
612 sRef s = (sRef) dmalloc (sizeof (*s));
616 allRefs = sRefTable_add (allRefs, s);
622 if (nsrefs >= maxnsrefs)
631 /*@-mustfree@*/ /*@-freshtrans@*/
633 /*@=mustfree@*/ /*@=freshtrans@*/
636 static /*@dependent@*/ /*@notnull@*/ /*@special@*/ sRef
639 /*@post:isnull result->aliasinfo, result->definfo, result->nullinfo,
640 result->expinfo, result->info, result->deriv@*/
642 sRef s = sRef_alloc ();
644 s->kind = SK_UNKNOWN;
647 s->type = ctype_unknown;
648 s->defstate = SS_UNKNOWN;
650 /* start modifications */
651 s->bufinfo.bufstate = BB_NOTNULLTERMINATED;
652 /* end modifications */
654 s->aliaskind = AK_UNKNOWN;
655 s->oaliaskind = AK_UNKNOWN;
657 s->nullstate = NS_UNKNOWN;
659 s->expkind = XO_UNKNOWN;
660 s->oexpkind = XO_UNKNOWN;
662 s->aliasinfo = alinfo_undefined;
663 s->definfo = alinfo_undefined;
664 s->nullinfo = alinfo_undefined;
665 s->expinfo = alinfo_undefined;
668 s->deriv = sRefSet_undefined;
673 static /*@notnull@*/ /*@exposed@*/ sRef
674 sRef_fixConj (/*@notnull@*/ sRef s)
679 s = sRef_getConjA (s);
680 } while (sRef_isConj (s));
682 llassert (sRef_isValid (s));
683 return s; /* don't need to ref */
692 sRef_isExternallyVisibleAux (sRef s)
695 sRef base = sRef_getRootBase (s);
697 if (sRef_isValid (base))
699 res = sRef_isParam (base) || sRef_isGlobal (base) || sRef_isExternal (base);
706 sRef_isExternallyVisible (sRef s)
708 return (sRef_aliasCheckSimplePred (sRef_isExternallyVisibleAux, s));
712 sRef_getBaseUentry (sRef s)
714 sRef base = sRef_getRootBase (s);
715 uentry res = uentry_undefined;
717 if (sRef_isValid (base))
722 res = usymtab_getRefQuiet (paramsScope, base->info->paramno);
726 res = usymtab_getRefQuiet (base->info->cvar->lexlevel,
727 base->info->cvar->index);
739 ** lookup the current uentry corresponding to s, and return the corresponding sRef.
740 ** yuk yuk yuk yuk yuk yuk yuk yuk
744 sRef_updateSref (sRef s)
750 if (!sRef_isValid (s)) return sRef_undefined;
761 case SK_UNCONSTRAINED:
769 uentry ue = sRef_getUentry (s);
771 /* must be raw name! (need the marker) */
772 ue = usymtab_lookupSafe (uentry_rawName (ue));
774 if (uentry_isUndefined (ue))
780 return (uentry_getSref (ue));
784 /* special case if ind known */
785 inner = s->info->arrayfetch->arr;
786 ret = sRef_updateSref (inner);
794 res = sRef_makeArrayFetch (ret);
800 inner = s->info->field->rec;
801 ret = sRef_updateSref (inner);
809 res = (sRef_makeField (ret, s->info->field->field));
814 inner = s->info->ref;
815 ret = sRef_updateSref (inner);
822 res = sRef_makePointer (ret);
828 inner = s->info->ref;
829 ret = sRef_updateSref (inner);
837 res = sRef_makeAddress (ret);
844 sRef innera = s->info->conj->a;
845 sRef innerb = s->info->conj->b;
846 sRef reta = sRef_updateSref (innera);
847 sRef retb = sRef_updateSref (innerb);
849 if (innera == reta && innerb == retb)
855 res = sRef_makeConj (reta, retb);
866 sRef_getUentry (sRef s)
868 llassert (sRef_isValid (s));
873 return (usymtab_getRefQuiet (paramsScope, s->info->paramno));
875 return (usymtab_getRefQuiet (s->info->cvar->lexlevel, s->info->cvar->index));
878 if (sRef_isCvar (s->info->conj->a) || sRef_isParam (s->info->conj->a)
879 || sRef_isConj (s->info->conj->a))
881 return sRef_getUentry (s->info->conj->a);
885 return sRef_getUentry (s->info->conj->b);
890 return uentry_undefined;
896 sRef_getParam (sRef s)
898 llassert (sRef_isValid (s));
899 llassert (s->kind == SK_PARAM);
901 return s->info->paramno;
905 sRef_isModified (sRef s)
907 return (!sRef_isValid (s) || s->modified);
910 void sRef_setModified (sRef s)
912 if (sRef_isValid (s))
917 if (sRef_isRefsField (s))
919 sRef base = sRef_getBase (s);
922 llassert (s->kind == SK_FIELD);
925 if (sRef_isPointer (base))
927 base = sRef_getBase (base);
930 if (sRef_isRefCounted (base))
932 base->aliaskind = AK_NEWREF;
940 ** note: this side-effects sRefSet to set modified to TRUE
941 ** for any sRef similar to s.
945 sRef_canModifyVal (sRef s, sRefSet sl)
947 if (context_getFlag (FLG_MUSTMOD))
949 return (sRef_doModifyVal (s, sl));
953 return (sRef_checkModifyVal (s, sl));
958 sRef_canModify (sRef s, sRefSet sl)
961 if (context_getFlag (FLG_MUSTMOD))
963 return (sRef_doModify (s, sl));
967 return (sRef_checkModify (s, sl));
976 bool sRef_checkModifyVal (sRef s, sRefSet sl)
978 if (sRef_isInvalid (s))
985 case SK_UNCONSTRAINED:
989 if (sRef_isGlobal (s))
991 if (context_checkGlobMod (s))
993 return (sRefSet_member (sl, s));
1003 return (sRefSet_member (sl, s)
1004 || alkind_isOnly (sRef_getOrigAliasKind (s)));
1006 /* special case if ind known */
1007 return (sRefSet_member (sl, s) ||
1008 sRef_checkModifyVal (s->info->arrayfetch->arr, sl));
1010 return (sRefSet_member (sl, s) || sRef_checkModifyVal (s->info->field->rec, sl));
1012 return (sRefSet_member (sl, s) || sRef_checkModifyVal (s->info->ref, sl));
1014 return (sRefSet_member (sl, s) || sRef_checkModifyVal (s->info->ref, sl));
1016 return ((sRef_checkModifyVal (s->info->conj->a, sl)) &&
1017 (sRef_checkModifyVal (s->info->conj->b, sl)));
1028 switch (s->info->spec)
1030 case SR_NOTHING: return TRUE;
1032 if (context_getFlag (FLG_INTERNALGLOBS))
1034 return (sRefSet_member (sl, s));
1040 case SR_SPECSTATE: return TRUE;
1041 case SR_SYSTEM: return (sRefSet_member (sl, s));
1044 case SK_RESULT: BADBRANCH;
1050 ** this should probably be elsewhere...
1052 ** returns TRUE iff sl indicates that s can be modified
1055 static bool sRef_checkModify (sRef s, sRefSet sl)
1057 llassert (sRef_isValid (s));
1061 case SK_UNCONSTRAINED:
1065 if (sRef_isGlobal (s))
1067 if (context_checkGlobMod (s))
1069 return (sRefSet_member (sl, s));
1081 return (sRefSet_member (sl, s) ||
1082 sRef_checkModifyVal (s->info->arrayfetch->arr, sl));
1085 sRef sr = s->info->field->rec;
1087 if (sr->kind == SK_PARAM)
1088 return TRUE; /* structs are copied on call */
1090 return (sRefSet_member (sl, s) || sRef_checkModifyVal (s->info->field->rec, sl));
1096 sm = sRefSet_member (sl, s);
1101 return (sRef_checkModifyVal (s->info->ref, sl));
1104 return (sRefSet_member (sl, s) || sRef_checkModifyVal (s->info->ref, sl));
1106 return ((sRef_checkModify (s->info->conj->a, sl)) &&
1107 (sRef_checkModify (s->info->conj->b, sl)));
1117 switch (s->info->spec)
1119 case SR_NOTHING: return TRUE;
1121 if (context_getFlag (FLG_INTERNALGLOBS))
1123 return (sRefSet_member (sl, s));
1129 case SR_SPECSTATE: return TRUE;
1130 case SR_SYSTEM: return (sRefSet_member (sl, s));
1133 case SK_RESULT: BADBRANCH;
1138 cstring sRef_stateVerb (sRef s)
1140 if (sRef_isDead (s))
1142 return cstring_makeLiteralTemp ("released");
1144 else if (sRef_isKept (s))
1146 return cstring_makeLiteralTemp ("kept");
1148 else if (sRef_isDependent (s))
1150 return cstring_makeLiteralTemp ("dependent");
1158 cstring sRef_stateAltVerb (sRef s)
1160 if (sRef_isDead (s))
1162 return cstring_makeLiteralTemp ("live");
1164 else if (sRef_isKept (s))
1166 return cstring_makeLiteralTemp ("not kept");
1168 else if (sRef_isDependent (s))
1170 return cstring_makeLiteralTemp ("independent");
1179 bool sRef_doModifyVal (sRef s, sRefSet sl)
1181 llassert (sRef_isValid (s));
1186 case SK_UNCONSTRAINED:
1190 if (sRef_isGlobal (s))
1193 if (context_checkGlobMod (s))
1195 return (sRefSet_modifyMember (sl, s));
1199 (void) sRefSet_modifyMember (sl, s);
1209 return (sRefSet_modifyMember (sl, s)
1210 || alkind_isOnly (sRef_getOrigAliasKind (s)));
1212 /* special case if ind known */
1213 /* unconditional OR, need side effect */
1214 return (OR (sRefSet_modifyMember (sl, s),
1215 sRef_doModifyVal (s->info->arrayfetch->arr, sl)));
1217 return (OR (sRefSet_modifyMember (sl, s),
1218 sRef_doModifyVal (s->info->field->rec, sl)));
1220 return (OR (sRefSet_modifyMember (sl, s),
1221 sRef_doModifyVal (s->info->ref, sl)));
1223 return (OR (sRefSet_modifyMember (sl, s),
1224 sRef_doModifyVal (s->info->ref, sl)));
1226 return (AND (sRef_doModifyVal (s->info->conj->a, sl) ,
1227 sRef_doModifyVal (s->info->conj->b, sl)));
1237 switch (s->info->spec)
1239 case SR_NOTHING: return TRUE;
1241 if (context_getFlag (FLG_INTERNALGLOBS))
1243 return (sRefSet_modifyMember (sl, s));
1247 (void) sRefSet_modifyMember (sl, s);
1256 return (sRefSet_modifyMember (sl, s));
1260 case SK_RESULT: BADBRANCH;
1266 ** this should probably be elsewhere...
1268 ** returns TRUE iff sl indicates that s can be modified
1272 bool sRef_doModify (sRef s, sRefSet sl)
1274 llassert (sRef_isValid (s));
1278 case SK_UNCONSTRAINED:
1282 if (sRef_isGlobal (s))
1284 if (context_checkGlobMod (s))
1286 return (sRefSet_modifyMember (sl, s));
1290 (void) sRefSet_modifyMember (sl, s);
1302 return (OR (sRefSet_modifyMember (sl, s),
1303 sRef_doModifyVal (s->info->arrayfetch->arr, sl)));
1306 sRef sr = s->info->field->rec;
1308 if (sr->kind == SK_PARAM)
1310 return TRUE; /* structs are shallow-copied on call */
1313 return (OR (sRefSet_modifyMember (sl, s),
1314 sRef_doModifyVal (s->info->field->rec, sl)));
1318 return (OR (sRefSet_modifyMember (sl, s),
1319 sRef_doModifyVal (s->info->ref, sl)));
1322 return (OR (sRefSet_modifyMember (sl, s),
1323 sRef_doModifyVal (s->info->ref, sl)));
1325 return (AND (sRef_doModify (s->info->conj->a, sl),
1326 (sRef_doModify (s->info->conj->b, sl))));
1337 switch (s->info->spec)
1339 case SR_NOTHING: return TRUE;
1340 case SR_INTERNAL: return TRUE;
1341 case SR_SPECSTATE: return TRUE;
1342 case SR_SYSTEM: return (sRefSet_modifyMember (sl, s));
1345 case SK_RESULT: BADBRANCH;
1350 static /*@exposed@*/ sRef
1351 sRef_leastCommon (/*@exposed@*/ sRef s1, sRef s2)
1353 llassert (sRef_similar (s1, s2));
1355 if (!sRef_isValid (s1)) return s1;
1356 if (!sRef_isValid (s2)) return s1;
1358 sRef_combineDefState (s1, s2);
1359 sRef_combineNullState (s1, s2);
1360 sRef_combineExKinds (s1, s2);
1362 if (s1->aliaskind != s2->aliaskind)
1364 if (s1->aliaskind == AK_UNKNOWN)
1366 s1->aliaskind = s2->aliaskind;
1368 else if (s2->aliaskind == AK_UNKNOWN)
1374 s1->aliaskind = AK_ERROR;
1381 int sRef_compare (sRef s1, sRef s2)
1383 if (s1 == s2) return 0;
1385 if (sRef_isInvalid (s1)) return -1;
1386 if (sRef_isInvalid (s2)) return 1;
1388 INTCOMPARERETURN (s1->kind, s2->kind);
1389 INTCOMPARERETURN (s1->defstate, s2->defstate);
1390 INTCOMPARERETURN (s1->aliaskind, s2->aliaskind);
1392 COMPARERETURN (nstate_compare (s1->nullstate, s2->nullstate));
1397 return (int_compare (s1->info->paramno, s2->info->paramno));
1400 COMPARERETURN (sRef_compare (s1->info->arrayfetch->arr,
1401 s2->info->arrayfetch->arr));
1403 if (s1->info->arrayfetch->indknown && s2->info->arrayfetch->indknown)
1405 return (int_compare (s1->info->arrayfetch->ind,
1406 s2->info->arrayfetch->ind));
1408 if (!s1->info->arrayfetch->indknown && !s2->info->arrayfetch->indknown)
1415 COMPARERETURN (sRef_compare (s1->info->field->rec, s2->info->field->rec));
1417 if (cstring_equal (s1->info->field->field, s2->info->field->field))
1424 return (sRef_compare (s1->info->ref, s2->info->ref));
1426 COMPARERETURN (sRef_compare (s1->info->conj->a, s2->info->conj->a));
1427 return (sRef_compare (s1->info->conj->b, s2->info->conj->b));
1428 case SK_UNCONSTRAINED:
1429 return (cstring_compare (s1->info->fname, s2->info->fname));
1441 return (generic_compare (s1->info->spec, s2->info->spec));
1446 static bool cref_equal (cref c1, cref c2)
1448 return ((c1->lexlevel == c2->lexlevel) &&
1449 (usymId_equal (c1->index, c2->index)));
1453 ** returns true if s1 could be the same storage as s2.
1454 ** i.e., a[?] ~ a[3]. Note its not symmetric ... s1
1455 ** should be more specific.
1459 ** like similar, but matches objects <-> non-objects
1463 sRef_uniqueReference (sRef s)
1465 return (sRef_isFresh (s) || sRef_isUnique (s)
1466 || sRef_isOnly (s) || sRef_isStack (s)
1467 || sRef_isAddress (s));
1471 sRef_similarRelaxedAux (sRef s1, sRef s2)
1475 if (sRef_isUnknownArrayFetch (s1))
1485 if (sRef_isInvalid (s1) || sRef_isInvalid (s2)) return FALSE;
1487 if (sRef_isConj (s2))
1488 return (sRef_similarRelaxedAux (s1, sRef_getConjA (s2)) ||
1489 sRef_similarRelaxedAux (s1, sRef_getConjB (s2)));
1494 return ((s2->kind == SK_CVAR)
1495 && (cref_equal (s1->info->cvar, s2->info->cvar)));
1497 return ((s2->kind == SK_PARAM)
1498 && (s1->info->paramno == s2->info->paramno));
1500 if (s2->kind == SK_ARRAYFETCH)
1502 if (sRef_similarRelaxedAux (s1->info->arrayfetch->arr,
1503 s2->info->arrayfetch->arr))
1505 if (s1->info->arrayfetch->indknown)
1507 if (s2->info->arrayfetch->indknown)
1509 return (s1->info->arrayfetch->ind == s2->info->arrayfetch->ind);
1524 return ((s2->kind == SK_FIELD
1525 && (sRef_similarRelaxedAux (s1->info->field->rec,
1526 s2->info->field->rec)
1527 && cstring_equal (s1->info->field->field,
1528 s2->info->field->field))));
1530 return ((s2->kind == SK_PTR)
1531 && sRef_similarRelaxedAux (s1->info->ref, s2->info->ref));
1533 return ((s2->kind == SK_ADR)
1534 && sRef_similarRelaxedAux (s1->info->ref, s2->info->ref));
1536 return ((sRef_similarRelaxedAux (s1->info->conj->a, s2) ||
1537 (sRef_similarRelaxedAux (s1->info->conj->b, s2))));
1539 return (s1->info->spec == s2->info->spec);
1540 case SK_UNCONSTRAINED:
1541 return (cstring_equal (s1->info->fname, s2->info->fname));
1556 sRef_similarRelaxed (sRef s1, sRef s2)
1562 if (sRef_isThroughArrayFetch (s1))
1572 if (sRef_isInvalid (s1) || sRef_isInvalid (s2)) return FALSE;
1574 us1 = sRef_uniqueReference (s1);
1575 us2 = sRef_uniqueReference (s2);
1577 if ((s1->kind == SK_EXTERNAL && (s2->kind != SK_EXTERNAL && !us2))
1578 || (s2->kind == SK_EXTERNAL && (s1->kind != SK_EXTERNAL && !us1)))
1581 ** Previously, also:
1582 ** || (sRef_isExposed (s1) && !us2) || (sRef_isExposed (s2) && !us1)) ????
1584 ** No clue why this was there?!
1588 if (sRef_isExposed (s1) && sRef_isCvar (s1))
1590 uentry ue1 = sRef_getUentry (s1);
1592 if (uentry_isRefParam (ue1))
1594 return sRef_similarRelaxedAux (s1, s2);
1598 if (sRef_isExposed (s2) && sRef_isCvar (s2))
1600 uentry ue2 = sRef_getUentry (s2);
1602 if (uentry_isRefParam (ue2))
1604 return sRef_similarRelaxedAux (s1, s2);
1608 return (ctype_match (s1->type, s2->type));
1612 return sRef_similarRelaxedAux (s1, s2);
1617 sRef_similar (sRef s1, sRef s2)
1619 if (s1 == s2) return TRUE;
1620 if (sRef_isInvalid (s1) || sRef_isInvalid (s2)) return FALSE;
1622 if (sRef_isConj (s2))
1624 return (sRef_similar (s1, sRef_getConjA (s2)) ||
1625 sRef_similar (s1, sRef_getConjB (s2)));
1628 if (sRef_isDerived (s2))
1630 return (sRef_includedBy (s1, s2->info->ref));
1636 return ((s2->kind == SK_CVAR)
1637 && (cref_equal (s1->info->cvar, s2->info->cvar)));
1639 return ((s2->kind == SK_PARAM)
1640 && (s1->info->paramno == s2->info->paramno));
1642 if (s2->kind == SK_ARRAYFETCH)
1644 if (sRef_similar (s1->info->arrayfetch->arr,
1645 s2->info->arrayfetch->arr))
1647 if (s1->info->arrayfetch->indknown)
1649 if (s2->info->arrayfetch->indknown)
1651 return (s1->info->arrayfetch->ind == s2->info->arrayfetch->ind);
1666 if (s2->kind == SK_PTR)
1668 if (sRef_similar (s1->info->arrayfetch->arr,
1678 return ((s2->kind == SK_FIELD
1679 && (sRef_similar (s1->info->field->rec,
1680 s2->info->field->rec)
1681 && cstring_equal (s1->info->field->field,
1682 s2->info->field->field))));
1684 if (s2->kind == SK_PTR)
1686 return sRef_similar (s1->info->ref, s2->info->ref);
1690 if (s2->kind == SK_ARRAYFETCH)
1692 if (sRef_similar (s2->info->arrayfetch->arr,
1702 return ((s2->kind == SK_ADR)
1703 && sRef_similar (s1->info->ref, s2->info->ref));
1705 return ((sRef_similar (s1->info->conj->a, s2) ||
1706 (sRef_similar (s1->info->conj->b, s2))));
1708 return (sRef_includedBy (s2, s1->info->ref));
1709 case SK_UNCONSTRAINED:
1710 return (s2->kind == SK_UNCONSTRAINED
1711 && cstring_equal (s1->info->fname, s2->info->fname));
1721 return (s2->kind == SK_SPECIAL
1722 && (s1->info->spec == s2->info->spec));
1725 /*@notreached@*/ DPRINTF (("Fell through for: %s / %s", sRef_unparse (s1), sRef_unparse (s2)));
1730 ** return TRUE iff small can be derived from big.
1732 ** (e.g. x, x.a is includedBy x;
1733 ** x.a is included By x.a;
1737 sRef_includedBy (sRef small, sRef big)
1739 if (small == big) return TRUE;
1740 if (sRef_isInvalid (small) || sRef_isInvalid (big)) return FALSE;
1742 if (sRef_isConj (big))
1743 return (sRef_similar (small, sRef_getConjA (big)) ||
1744 sRef_similar (small, sRef_getConjB (big)));
1746 switch (small->kind)
1750 return (sRef_same (small, big));
1752 if (big->kind == SK_ARRAYFETCH)
1754 if (sRef_same (small->info->arrayfetch->arr, big->info->arrayfetch->arr))
1756 if (small->info->arrayfetch->indknown)
1758 if (big->info->arrayfetch->indknown)
1760 return (small->info->arrayfetch->ind == big->info->arrayfetch->ind);
1773 return (sRef_includedBy (small->info->arrayfetch->arr, big));
1775 if (big->kind == SK_FIELD)
1778 (sRef_same (small->info->field->rec, big->info->field->rec) &&
1779 cstring_equal (small->info->field->field, big->info->field->field));
1783 return (sRef_includedBy (small->info->field->rec, big));
1787 if (big->kind == SK_PTR)
1789 return sRef_same (small->info->ref, big->info->ref);
1793 return (sRef_includedBy (small->info->ref, big));
1797 return ((big->kind == SK_ADR) && sRef_similar (small->info->ref, big->info->ref));
1799 return ((sRef_includedBy (small->info->conj->a, big) ||
1800 (sRef_includedBy (small->info->conj->b, big))));
1802 return (sRef_includedBy (small->info->ref, big));
1803 case SK_UNCONSTRAINED:
1813 switch (small->info->spec)
1815 case SR_NOTHING: return TRUE;
1817 case SR_INTERNAL: return (sRef_isSpecInternalState (big) ||
1818 sRef_isFileStatic (big));
1819 case SR_SYSTEM: return (sRef_isSystemState (big));
1826 ** Same is similar to similar, but not quite the same.
1827 ** same and realSame aren't the same, but they are really similar.
1828 ** similarly, same is the same as same. but realSame is
1829 ** not really the same as same, or similar to similar.
1831 ** Similarly to similar, same checks if two sRefs are the same.
1832 ** The similarities end, however, when same compares arrays
1833 ** with unknown indexes. Similar returns false; same returns true.
1835 ** Similarly to similar and same, realSame is the same as same,
1836 ** except they do not behave the same when face with unknown
1837 ** sRefs. Same thinks they are not the same, but realSame thinks
1843 sRef_realSame (sRef s1, sRef s2)
1845 if (s1 == s2) return TRUE;
1846 if (sRef_isInvalid (s1) || sRef_isInvalid (s2)) return FALSE;
1851 return ((s2->kind == SK_CVAR) && (cref_equal (s1->info->cvar, s2->info->cvar)));
1853 return ((s2->kind == SK_PARAM) && (s1->info->paramno == s2->info->paramno));
1855 if (s2->kind == SK_ARRAYFETCH)
1857 if (sRef_realSame (s1->info->arrayfetch->arr, s2->info->arrayfetch->arr))
1859 if (s1->info->arrayfetch->indknown && s2->info->arrayfetch->indknown)
1861 return (s1->info->arrayfetch->ind == s2->info->arrayfetch->ind);
1863 if (!s1->info->arrayfetch->indknown && !s2->info->arrayfetch->indknown)
1872 return ((s2->kind == SK_FIELD &&
1873 (sRef_realSame (s1->info->field->rec, s2->info->field->rec) &&
1874 cstring_equal (s1->info->field->field, s2->info->field->field))));
1876 return ((s2->kind == SK_PTR) && sRef_realSame (s1->info->ref, s2->info->ref));
1878 return ((s2->kind == SK_ADR) && sRef_realSame (s1->info->ref, s2->info->ref));
1880 return ((sRef_realSame (s1->info->conj->a, s2) ||
1881 (sRef_realSame (s1->info->conj->b, s2))));
1883 return ((s2->kind == SK_OBJECT)
1884 && ctype_match (s1->info->object, s2->info->object));
1886 return ((s2->kind == SK_EXTERNAL)
1887 && sRef_realSame (s1->info->ref, s2->info->ref));
1889 return ((s2->kind == SK_SPECIAL) && s1->info->spec == s2->info->spec);
1891 return ((s2->kind == SK_DERIVED) && sRef_realSame (s1->info->ref, s2->info->ref));
1892 case SK_UNCONSTRAINED:
1893 return ((s2->kind == SK_UNCONSTRAINED)
1894 && (cstring_equal (s1->info->fname, s2->info->fname)));
1900 return TRUE; /* changed this! was false */
1906 ** same is similar to similar, but not quite the same.
1908 ** Similarly to similar, same checks is two sRefs are the same.
1909 ** The similarities end, however, when same compares arrays
1910 ** with unknown indexes. Similar returns false; same returns true.
1914 sRef_same (sRef s1, sRef s2)
1916 if (s1 == s2) return TRUE;
1917 if (sRef_isInvalid (s1) || sRef_isInvalid (s2)) return FALSE;
1922 return ((s2->kind == SK_CVAR) && (cref_equal (s1->info->cvar, s2->info->cvar)));
1924 return ((s2->kind == SK_PARAM) && (s1->info->paramno == s2->info->paramno));
1926 if (s2->kind == SK_ARRAYFETCH)
1928 llassert (s1->info->field->rec != s1);
1929 if (sRef_same (s1->info->arrayfetch->arr, s2->info->arrayfetch->arr))
1931 if (s1->info->arrayfetch->indknown && s2->info->arrayfetch->indknown)
1933 return (s1->info->arrayfetch->ind == s2->info->arrayfetch->ind);
1941 llassert (s1->info->field->rec != s1);
1942 return ((s2->kind == SK_FIELD &&
1943 (sRef_same (s1->info->field->rec, s2->info->field->rec) &&
1944 cstring_equal (s1->info->field->field, s2->info->field->field))));
1948 llassert (s1->info->ref != s1);
1949 return ((s2->kind == SK_PTR) && sRef_same (s1->info->ref, s2->info->ref));
1953 llassert (s1->info->ref != s1);
1954 return ((s2->kind == SK_ADR) && sRef_same (s1->info->ref, s2->info->ref));
1957 llassert (s1->info->conj->a != s1);
1958 llassert (s1->info->conj->b != s1);
1959 return ((sRef_same (s1->info->conj->a, s2)) && /* or or and? */
1960 (sRef_same (s1->info->conj->b, s2)));
1962 return ((s2->kind == SK_SPECIAL) && s1->info->spec == s2->info->spec);
1964 llassert (s1->info->ref != s1);
1965 return ((s2->kind == SK_DERIVED) && sRef_same (s1->info->ref, s2->info->ref));
1967 case SK_UNCONSTRAINED:
1980 ** sort of similar, for use in def/use
1984 sRef_closeEnough (sRef s1, sRef s2)
1986 if (s1 == s2) return TRUE;
1987 if (sRef_isInvalid (s1) || sRef_isInvalid (s2)) return FALSE;
1992 return (((s2->kind == SK_CVAR) &&
1993 (cref_equal (s1->info->cvar, s2->info->cvar))) ||
1994 (s2->kind == SK_UNCONSTRAINED && s1->info->cvar->lexlevel == 0));
1995 case SK_UNCONSTRAINED:
1996 return (s2->kind == SK_UNCONSTRAINED
1997 || ((s2->kind == SK_CVAR) && (s2->info->cvar->lexlevel == 0)));
1999 return ((s2->kind == SK_PARAM)
2000 && (s1->info->paramno == s2->info->paramno));
2002 if (s2->kind == SK_ARRAYFETCH)
2004 if (sRef_closeEnough (s1->info->arrayfetch->arr, s2->info->arrayfetch->arr))
2006 if (s1->info->arrayfetch->indknown && s2->info->arrayfetch->indknown)
2008 return (s1->info->arrayfetch->ind == s2->info->arrayfetch->ind);
2015 return ((s2->kind == SK_FIELD &&
2016 (sRef_closeEnough (s1->info->field->rec, s2->info->field->rec) &&
2017 cstring_equal (s1->info->field->field, s2->info->field->field))));
2019 return ((s2->kind == SK_PTR) && sRef_closeEnough (s1->info->ref, s2->info->ref));
2021 return ((s2->kind == SK_ADR) && sRef_closeEnough (s1->info->ref, s2->info->ref));
2023 return ((s2->kind == SK_DERIVED) && sRef_closeEnough (s1->info->ref, s2->info->ref));
2025 return ((sRef_closeEnough (s1->info->conj->a, s2)) ||
2026 (sRef_closeEnough (s1->info->conj->b, s2)));
2028 return ((s2->kind == SK_SPECIAL) && s1->info->spec == s2->info->spec);
2044 s is an sRef of a formal paramenter in a function call constraint
2045 we trys to return a constraint expression derived from the actual parementer of a function call.
2047 /*@only@*/ constraintExpr sRef_fixConstraintParam (/*@observer@*/ sRef s, /*@observer@*/ /*@temp@*/ exprNodeList args)
2051 if (sRef_isInvalid (s))
2052 llfatalbug((message("Invalid sRef")));
2058 // s = sRef_saveCopy(s);
2059 ce = constraintExpr_makeTermsRef (s);
2066 temp = (sRef_makeField (sRef_fixBaseParam (s->info->field->rec, args),
2067 s->info->field->field));
2068 ce = constraintExpr_makeTermsRef (temp);
2074 temp = (sRef_makePointer (sRef_fixBaseParam (s->info->ref, args)));
2075 //temp = sRef_saveCopy(temp);
2076 ce = constraintExpr_makeTermsRef (temp);
2083 temp = sRef_saveCopy(s);
2084 temp = sRef_fixBaseParam (temp, args);
2085 ce = constraintExpr_makeTermsRef (temp);
2091 temp = sRef_saveCopy(s);
2092 ce = constraintExpr_makeTermsRef (temp);
2096 llassert(exprNodeList_size (args) > s->info->paramno);
2098 exprNode e = exprNodeList_nth (args, s->info->paramno);
2100 llassert( !(exprNode_isError (e)) );
2101 ce = constraintExpr_makeExprNode (e);
2108 llcontbug ((message("Trying to do fixConstraintParam on nonparam, nonglobal: %q for function with arguments %q", sRef_unparse (s), exprNodeList_unparse(args) ) ));
2109 temp = sRef_saveCopy(s);
2110 ce = constraintExpr_makeTermsRef (temp);
2120 sRef_fixBaseParam (/*@returned@*/ sRef s, exprNodeList args)
2122 if (sRef_isInvalid (s)) return (sRef_undefined);
2126 case SK_UNCONSTRAINED:
2131 if (exprNodeList_size (args) > s->info->paramno)
2133 exprNode e = exprNodeList_nth (args, s->info->paramno);
2135 if (exprNode_isError (e))
2137 return sRef_makeUnknown ();
2140 return (exprNode_getSref (e));
2144 return sRef_makeUnknown ();
2149 if (s->info->arrayfetch->indknown)
2151 return (sRef_makeArrayFetchKnown
2152 (sRef_fixBaseParam (s->info->arrayfetch->arr, args),
2153 s->info->arrayfetch->ind));
2157 return (sRef_makeArrayFetch
2158 (sRef_fixBaseParam (s->info->arrayfetch->arr, args)));
2161 return (sRef_makeField (sRef_fixBaseParam (s->info->field->rec, args),
2162 s->info->field->field));
2165 return (sRef_makePointer (sRef_fixBaseParam (s->info->ref, args)));
2168 return (sRef_makeAddress (sRef_fixBaseParam (s->info->ref, args)));
2171 return (sRef_makeConj (sRef_fixBaseParam (s->info->conj->a, args),
2172 sRef_fixBaseParam (s->info->conj->b, args)));
2188 sRef_undumpGlobal (char **c)
2198 usymId uid = usymId_fromInt (getInt (c));
2204 defstate = sstate_fromInt (getInt (c));
2207 nullstate = nstate_fromInt (getInt (c));
2209 ret = sRef_makeGlobal (uid, ctype_unknown);
2210 ret->nullstate = nullstate;
2211 ret->defstate = defstate;
2217 speckind sk = speckind_fromInt (i);
2221 case SR_NOTHING: return (sRef_makeNothing ());
2222 case SR_INTERNAL: return (sRef_makeInternalState ());
2223 case SR_SPECSTATE: return (sRef_makeSpecState ());
2224 case SR_SYSTEM: return (sRef_makeSystemState ());
2229 return sRef_undefined;
2231 return sRef_makeUnknown ();
2233 return sRef_makeUnknown ();
2235 llfatalerror (message ("sRef_undumpGlobal: bad line: %s",
2236 cstring_fromChars (*c)));
2242 sRef_undump (char **c)
2251 return (sRef_makeGlobal (usymId_fromInt (getInt (c)), ctype_unknown));
2253 return (sRef_makeParam (getInt (c), ctype_unknown));
2255 return (sRef_makeResultType (ctype_undump (c)));
2258 if ((**c >= '0' && **c <= '9') || **c == '-')
2261 sRef arr = sRef_undump (c);
2262 sRef ret = sRef_buildArrayFetchKnown (arr, i);
2268 sRef arr = sRef_undump (c);
2269 sRef ret = sRef_buildArrayFetch (arr);
2276 cstring fname = cstring_undefined;
2281 fname = cstring_appendChar (fname, **c);
2286 ret = sRef_buildField (sRef_undump (c), fname);
2287 cstring_markOwned (fname);
2293 speckind sk = speckind_fromInt (i);
2297 case SR_NOTHING: return (sRef_makeNothing ());
2298 case SR_INTERNAL: return (sRef_makeInternalState ());
2299 case SR_SPECSTATE: return (sRef_makeSpecState ());
2300 case SR_SYSTEM: return (sRef_makeSystemState ());
2306 sRef ptr = sRef_undump (c);
2307 sRef ret = sRef_makePointer (ptr);
2313 sRef adr = sRef_undump (c);
2314 sRef ret = sRef_makeAddress (adr);
2320 return (sRef_makeObject (ctype_undump (c)));
2324 sRef s1 = sRef_undump (c);
2325 sRef s2 = ((*c)++, sRef_undump (c));
2326 sRef ret = sRef_makeConj (s1, s2);
2331 return sRef_undefined;
2333 return sRef_makeUnknown ();
2335 return sRef_makeUnknown ();
2337 llfatalerror (message ("sRef_undump: bad line: %s", cstring_fromChars (*c)));
2345 if (sRef_isInvalid (s))
2347 return (cstring_makeLiteral ("-"));
2354 return (message ("p%d", s->info->paramno));
2356 if (s->info->arrayfetch->indknown)
2358 return (message ("a%d%q", s->info->arrayfetch->ind,
2359 sRef_dump (s->info->arrayfetch->arr)));
2363 return (message ("a%q", sRef_dump (s->info->arrayfetch->arr)));
2366 return (message ("f%s.%q", s->info->field->field,
2367 sRef_dump (s->info->field->rec)));
2369 return (message ("t%q", sRef_dump (s->info->ref)));
2371 return (message ("d%q", sRef_dump (s->info->ref)));
2373 return (message ("o%q", ctype_dump (s->info->object)));
2375 return (message ("s%d", (int) s->info->spec));
2377 return (message ("c%q.%q",
2378 sRef_dump (s->info->conj->a),
2379 sRef_dump (s->info->conj->b)));
2381 if (sRef_isGlobal (s))
2383 return (message ("g%d",
2384 usymtab_convertId (s->info->cvar->index)));
2388 llcontbug (message ("Dumping local variable: %q",
2389 sRef_unparseDebug (s)));
2390 return (cstring_makeLiteral ("u"));
2393 return (cstring_makeLiteral ("u"));
2395 return (message ("r%q", ctype_dump (s->type)));
2401 case SK_UNCONSTRAINED:
2402 llcontbug (message ("sRef_dump: bad kind: %q",
2403 sRef_unparseFull (s)));
2404 return (cstring_makeLiteral ("x"));
2411 cstring sRef_dumpGlobal (sRef s)
2413 if (sRef_isInvalid (s))
2415 return (cstring_makeLiteral ("-"));
2422 if (sRef_isGlobal (s))
2424 return (message ("g%d@%d@%d",
2425 usymtab_convertId (s->info->cvar->index),
2427 (int) s->nullstate));
2431 llcontbug (message ("Dumping local variable: %q",
2432 sRef_unparseDebug (s)));
2433 return (cstring_makeLiteral ("u"));
2436 return (cstring_makeLiteral ("u"));
2438 return (message ("s%d", (int) s->info->spec));
2440 llcontbug (message ("sRef_dumpGlobal: bad kind: %q",
2441 sRef_unparseFull (s)));
2442 return (cstring_makeLiteral ("x"));
2450 sRef_deriveType (sRef s, uentryList cl)
2452 if (sRef_isInvalid (s)) return ctype_unknown;
2457 return (uentry_getType (usymtab_getRefQuiet (s->info->cvar->lexlevel,
2458 s->info->cvar->index)));
2459 case SK_UNCONSTRAINED:
2460 return (ctype_unknown);
2462 return uentry_getType (uentryList_getN (cl, s->info->paramno));
2465 ctype ca = sRef_deriveType (s->info->arrayfetch->arr, cl);
2467 if (ctype_isArray (ca))
2469 return (ctype_baseArrayPtr (ca));
2471 else if (ctype_isUnknown (ca))
2477 llcontbuglit ("sRef_deriveType: inconsistent array type");
2483 ctype ct = sRef_deriveType (s->info->field->rec, cl);
2485 if (ctype_isStructorUnion (ct))
2487 uentry ue = uentryList_lookupField (ctype_getFields (ct),
2488 s->info->field->field);
2490 if (uentry_isValid (ue))
2492 return (uentry_getType (ue));
2496 llcontbuglit ("sRef_deriveType: bad field");
2497 return ctype_unknown;
2500 else if (ctype_isUnknown (ct))
2506 llcontbuglit ("sRef_deriveType: inconsistent field type");
2512 ctype ct = sRef_deriveType (s->info->ref, cl);
2514 if (ctype_isUnknown (ct)) return ct;
2515 if (ctype_isPointer (ct)) return (ctype_baseArrayPtr (ct));
2518 llcontbuglit ("sRef_deriveType: inconsistent pointer type");
2524 ctype ct = sRef_deriveType (s->info->ref, cl);
2526 if (ctype_isUnknown (ct)) return ct;
2527 return ctype_makePointer (ct);
2531 return sRef_deriveType (s->info->ref, cl);
2535 return (s->info->object);
2539 return (ctype_makeConj (sRef_deriveType (s->info->conj->a, cl),
2540 sRef_deriveType (s->info->conj->b, cl)));
2552 return ctype_unknown;
2558 sRef_getType (sRef s)
2560 if (sRef_isInvalid (s)) return ctype_unknown;
2566 sRef_unparseOpt (sRef s)
2568 sRef rb = sRef_getRootBase (s);
2570 if (sRef_isMeaningful (rb) && !sRef_isConst (rb))
2572 cstring ret = sRef_unparse (s);
2574 llassertprint (!cstring_equalLit (ret, "?"), ("print: %s", sRef_unparseDebug (s)));
2576 if (!cstring_isEmpty (ret))
2578 return (cstring_appendChar (ret, ' '));
2586 return cstring_undefined;
2590 sRef_unparsePreOpt (sRef s)
2592 sRef rb = sRef_getRootBase (s);
2594 if (sRef_isMeaningful (rb) && !sRef_isConst (rb))
2596 cstring ret = sRef_unparse (s);
2598 llassertprint (!cstring_equalLit (ret, "?"), ("print: %s", sRef_unparseDebug (s)));
2599 return (cstring_prependCharO (' ', ret));
2602 return cstring_undefined;
2606 sRef_unparse (sRef s)
2608 if (sRef_isInvalid (s)) return (cstring_makeLiteral ("?"));
2610 if (context_inFunctionLike ())
2612 return (sRef_unparseWithArgs (s, context_getParams ()));
2616 return (sRef_unparseNoArgs (s));
2620 static /*@only@*/ cstring
2621 sRef_unparseWithArgs (sRef s, uentryList args)
2623 if (sRef_isInvalid (s))
2625 return (cstring_makeLiteral ("?"));
2631 return (uentry_getName (usymtab_getRefQuiet (s->info->cvar->lexlevel,
2632 s->info->cvar->index)));
2633 case SK_UNCONSTRAINED:
2634 return (cstring_copy (s->info->fname));
2637 if (s->info->paramno < uentryList_size (args))
2639 uentry ue = uentryList_getN (args, s->info->paramno);
2641 if (uentry_isValid (ue))
2642 return uentry_getName (ue);
2645 return (message ("<bad param: %q / args %q",
2646 sRef_unparseDebug (s),
2647 uentryList_unparse (args)));
2650 if (s->info->arrayfetch->indknown)
2652 return (message ("%q[%d]", sRef_unparseWithArgs (s->info->arrayfetch->arr, args),
2653 s->info->arrayfetch->ind));
2657 return (message ("%q[]", sRef_unparseWithArgs (s->info->arrayfetch->arr, args)));
2660 if (s->info->field->rec->kind == SK_PTR)
2662 sRef ptr = s->info->field->rec;
2664 return (message ("%q->%s", sRef_unparseWithArgs (ptr->info->ref, args),
2665 s->info->field->field));
2667 return (message ("%q.%s", sRef_unparseWithArgs (s->info->field->rec, args),
2668 s->info->field->field));
2672 sRef ref = sRef_fixConj (s->info->ref);
2673 skind sk = ref->kind;
2678 ret = message ("storage pointed to by %q",
2679 sRef_unparseWithArgs (ref, args));
2681 else if (skind_isSimple (sk) || sk == SK_PTR)
2683 ret = message ("*%q", sRef_unparseWithArgs (ref, args));
2687 ret = message ("*(%q)", sRef_unparseWithArgs (ref, args));
2693 return (message ("&%q", sRef_unparseWithArgs (s->info->ref, args)));
2695 return (cstring_copy (ctype_unparse (s->info->object)));
2697 return (sRef_unparseWithArgs (sRef_getConjA (s), args));
2699 if (cstring_isDefined (s->info->fname))
2701 return (message ("[result of %s]", s->info->fname));
2705 return (cstring_makeLiteral ("<new>"));
2708 return (cstring_makeLiteral ("?"));
2710 return (message ("<derived %q>", sRef_unparse (s->info->ref)));
2712 return (message ("<external %q>", sRef_unparse (s->info->ref)));
2714 return (message ("<type %s>", ctype_unparse (s->type)));
2716 return (message ("<const %s>", ctype_unparse (s->type)));
2718 return (cstring_makeLiteral
2719 (s->info->spec == SR_NOTHING ? "nothing"
2720 : s->info->spec == SR_INTERNAL ? "internal state"
2721 : s->info->spec == SR_SPECSTATE ? "spec state"
2722 : s->info->spec == SR_SYSTEM ? "file system state"
2725 return cstring_makeLiteral ("result");
2728 llbug (message ("Bad sref, kind = %d", (int) s->kind));
2736 sRef_unparseDebug (sRef s)
2738 if (sRef_isInvalid (s)) return (cstring_makeLiteral ("<undef>"));
2742 case SK_UNCONSTRAINED:
2743 return (message ("<unconstrained %s>", s->info->fname));
2748 ce = usymtab_getRefQuiet (s->info->cvar->lexlevel, s->info->cvar->index);
2750 if (uentry_isInvalid (ce))
2752 return (message ("<scope: %d.%d *invalid*>",
2753 s->info->cvar->lexlevel,
2754 s->info->cvar->index));
2758 return (message ("<scope: %d.%d *%q*>",
2759 s->info->cvar->lexlevel,
2760 s->info->cvar->index,
2761 uentry_getName (ce)));
2767 return (message ("<parameter %d>", s->info->paramno + 1));
2770 if (s->info->arrayfetch->indknown)
2772 return (message ("%q[%d]", sRef_unparseDebug (s->info->arrayfetch->arr),
2773 s->info->arrayfetch->ind));
2777 return (message ("%q[]", sRef_unparseDebug (s->info->arrayfetch->arr)));
2780 return (message ("%q.%s", sRef_unparseDebug (s->info->field->rec),
2781 s->info->field->field));
2783 return (message ("*(%q)", sRef_unparseDebug (s->info->ref)));
2785 return (message ("&%q", sRef_unparseDebug (s->info->ref)));
2787 return (message ("<object type %s>", ctype_unparse (s->info->object)));
2789 return (message ("%q | %q", sRef_unparseDebug (s->info->conj->a),
2790 sRef_unparseDebug (s->info->conj->b)));
2792 return message ("<new: %s>", s->info->fname);
2794 return (message ("<derived %q>", sRef_unparseDebug (s->info->ref)));
2796 return (message ("<external %q>", sRef_unparseDebug (s->info->ref)));
2798 return (message ("<type %s>", ctype_unparse (s->type)));
2800 return (message ("<const %s>", ctype_unparse (s->type)));
2802 return (message ("<result %s>", ctype_unparse (s->type)));
2804 return (message ("<spec %s>",
2805 cstring_makeLiteralTemp
2806 (s->info->spec == SR_NOTHING ? "nothing"
2807 : s->info->spec == SR_INTERNAL ? "internalState"
2808 : s->info->spec == SR_SPECSTATE ? "spec state"
2809 : s->info->spec == SR_SYSTEM ? "fileSystem"
2812 return cstring_makeLiteral ("<unknown>");
2818 static /*@only@*/ cstring
2819 sRef_unparseNoArgs (sRef s)
2821 if (sRef_isInvalid (s)) return (cstring_makeLiteral ("?"));
2825 case SK_UNCONSTRAINED:
2826 return (cstring_copy (s->info->fname));
2829 uentry ce = usymtab_getRefQuiet (s->info->cvar->lexlevel,
2830 s->info->cvar->index);
2832 if (uentry_isInvalid (ce))
2834 llcontbug (message ("sRef_unparseNoArgs: bad cvar: %q", sRef_unparseDebug (s)));
2835 return (sRef_unparseDebug (s));
2839 return (uentry_getName (ce));
2843 if (s->info->arrayfetch->indknown)
2845 return (message ("%q[%d]", sRef_unparseNoArgs (s->info->arrayfetch->arr),
2846 s->info->arrayfetch->ind));
2850 return (message ("%q[]", sRef_unparseNoArgs (s->info->arrayfetch->arr)));
2853 return (message ("%q.%s", sRef_unparseNoArgs (s->info->field->rec),
2854 s->info->field->field));
2857 sRef ref = sRef_fixConj (s->info->ref);
2858 skind sk = ref->kind;
2861 if (skind_isSimple (sk) || sk == SK_PTR)
2863 ret = message ("*%q", sRef_unparseNoArgs (ref));
2867 ret = message ("*(%q)", sRef_unparseNoArgs (ref));
2873 return (message ("&%q", sRef_unparseNoArgs (s->info->ref)));
2875 return (cstring_copy (ctype_unparse (s->info->object)));
2877 return (sRef_unparseNoArgs (s->info->conj->a));
2879 return (message ("result of %s", s->info->fname));
2881 return (message ("<der %q>", sRef_unparseNoArgs (s->info->ref)));
2883 return message ("<ext %q>", sRef_unparseNoArgs (s->info->ref));
2885 return (cstring_makeLiteral
2886 (s->info->spec == SR_NOTHING ? "nothing"
2887 : s->info->spec == SR_INTERNAL ? "internal state"
2888 : s->info->spec == SR_SPECSTATE ? "spec state"
2889 : s->info->spec == SR_SYSTEM ? "file system state"
2892 return cstring_makeLiteral ("result");
2896 return cstring_makeLiteral ("?");
2898 /* llcontbug (message ("sRef_unparseNoArgs: bad case: %q", sRef_unparseDebug (s))); */
2899 return (sRef_unparseDebug (s));
2904 /*@dependent@*/ sRef sRef_makeUnconstrained (cstring fname)
2906 sRef s = sRef_new ();
2908 s->kind = SK_UNCONSTRAINED;
2909 s->info = (sinfo) dmalloc (sizeof (*s->info));
2910 s->info->fname = fname;
2915 cstring sRef_unconstrainedName (sRef s)
2917 llassert (sRef_isUnconstrained (s));
2919 return s->info->fname;
2922 bool sRef_isUnconstrained (sRef s)
2924 return (sRef_isValid(s) && s->kind == SK_UNCONSTRAINED);
2927 static /*@dependent@*/ /*@notnull@*/ sRef
2928 sRef_makeCvarAux (int level, usymId index, ctype ct)
2930 sRef s = sRef_new ();
2933 s->info = (sinfo) dmalloc (sizeof (*s->info));
2935 s->info->cvar = (cref) dmalloc (sizeof (*s->info->cvar));
2936 s->info->cvar->lexlevel = level;
2937 s->info->cvar->index = index;
2939 /* for now, all globals are defined; all locals, aren't */
2941 if (level <= fileScope)
2943 s->defstate = SS_UNKNOWN;
2947 ctype rct = ctype_realType (ct);
2949 if (level != paramsScope
2950 && (ctype_isStructorUnion (rct) || ctype_isRealArray (rct)))
2952 s->defstate = SS_ALLOCATED;
2953 s->oaliaskind = s->aliaskind = AK_STACK;
2957 s->defstate = SS_UNDEFINED;
2958 s->oaliaskind = s->aliaskind = AK_LOCAL;
2964 llassert (level >= globScope);
2965 llassert (usymId_isValid (index));
2970 /*@dependent@*/ sRef sRef_makeCvar (int level, usymId index, ctype ct)
2972 return (sRef_makeCvarAux (level, index, ct));
2975 int sRef_lexLevel (sRef s)
2977 if (sRef_isValid (s))
2981 conj = sRef_fixConj (s);
2982 s = sRef_getRootBase (conj);
2984 if (sRef_isValid (s) && s->kind == SK_CVAR)
2986 return (s->info->cvar->lexlevel);
2994 sRef_makeGlobal (usymId l, ctype ct)
2996 return (sRef_makeCvar (globScope, l, ct));
3000 sRef_setParamNo (sRef s, int l)
3002 llassert (sRef_isValid (s) && s->kind == SK_PARAM);
3003 s->info->paramno = l;
3006 /*@dependent@*/ sRef
3007 sRef_makeParam (int l, ctype ct)
3009 sRef s = sRef_new ();
3014 s->info = (sinfo) dmalloc (sizeof (*s->info));
3015 s->info->paramno = l;
3016 s->defstate = SS_UNKNOWN; /* (probably defined, unless its an out parameter) */
3022 sRef_isIndexKnown (sRef arr)
3026 llassert (sRef_isValid (arr));
3027 arr = sRef_fixConj (arr);
3029 llassert (arr->kind == SK_ARRAYFETCH);
3030 res = arr->info->arrayfetch->indknown;
3035 sRef_getIndex (sRef arr)
3039 llassert (sRef_isValid (arr));
3040 arr = sRef_fixConj (arr);
3042 llassert (arr->kind == SK_ARRAYFETCH);
3044 if (!arr->info->arrayfetch->indknown)
3046 llcontbug (message ("sRef_getIndex: unknown: %q", sRef_unparse (arr)));
3051 result = arr->info->arrayfetch->ind;
3057 static bool sRef_isZerothArrayFetch (/*@notnull@*/ sRef s)
3059 return (s->kind == SK_ARRAYFETCH
3060 && s->info->arrayfetch->indknown
3061 && (s->info->arrayfetch->ind == 0));
3064 /*@exposed@*/ sRef sRef_makeAddress (/*@exposed@*/ sRef t)
3067 if (sRef_isInvalid (t)) return sRef_undefined;
3069 if (sRef_isPointer (t))
3071 return (t->info->ref);
3073 else if (sRef_isZerothArrayFetch (t))
3075 return (t->info->arrayfetch->arr);
3079 sRef s = sRef_new ();
3082 s->type = ctype_makePointer (t->type);
3083 s->info = (sinfo) dmalloc (sizeof (*s->info));
3086 if (t->defstate == SS_UNDEFINED)
3087 /* no! it is allocated even still: && !ctype_isPointer (t->type)) */
3089 s->defstate = SS_ALLOCATED;
3093 s->defstate = t->defstate;
3096 if (t->aliaskind == AK_LOCAL)
3098 if (sRef_isLocalVar (t))
3100 s->aliaskind = AK_STACK;
3108 cstring sRef_getField (sRef s)
3112 llassert (sRef_isValid (s));
3113 s = sRef_fixConj (s);
3115 llassertprint (sRef_isValid (s) && (s->kind == SK_FIELD),
3116 ("s = %s", sRef_unparseDebug (s)));
3118 res = s->info->field->field;
3122 sRef sRef_getBase (sRef s)
3126 if (sRef_isInvalid (s)) return (sRef_undefined);
3128 s = sRef_fixConj (s);
3139 res = s->info->field->rec;
3143 res = s->info->arrayfetch->arr;
3147 res = sRef_undefined; /* shouldn't need it */
3154 ** same as getBase, except returns invalid
3155 ** (and doesn't use adr's)
3159 sRef_getBaseSafe (sRef s)
3163 if (sRef_isInvalid (s)) { return sRef_undefined; }
3165 s = sRef_fixConj (s);
3173 res = s->info->field->rec; break;
3175 res = s->info->arrayfetch->arr;
3178 res = sRef_undefined; break;
3184 /*@constant int MAXBASEDEPTH;@*/
3185 # define MAXBASEDEPTH 25
3187 static /*@exposed@*/ sRef
3188 sRef_getRootBaseAux (sRef s, int depth)
3190 if (sRef_isInvalid (s)) return sRef_undefined;
3192 if (depth > MAXBASEDEPTH)
3195 ("Warning: reference base limit exceeded for %q. "
3196 "This either means there is a variable with at least "
3197 "%d indirections from this reference, or "
3198 "there is a bug in LCLint.",
3203 return sRef_undefined;
3210 return (sRef_getRootBaseAux (s->info->ref, depth + 1));
3212 return (sRef_getRootBaseAux (s->info->field->rec, depth + 1));
3214 return (sRef_getRootBaseAux (s->info->arrayfetch->arr, depth + 1));
3216 return (sRef_getRootBaseAux (sRef_fixConj (s), depth + 1));
3222 sRef sRef_getRootBase (sRef s)
3224 return (sRef_getRootBaseAux (s, 0));
3227 static bool sRef_isDeep (sRef s)
3229 if (sRef_isInvalid (s)) return FALSE;
3239 return (sRef_isDeep (sRef_fixConj (s)));
3245 static int sRef_depth (sRef s)
3247 if (sRef_isInvalid (s)) return 0;
3255 return 1 + sRef_depth (s->info->ref);
3257 return 1 + sRef_depth (s->info->field->rec);
3259 return 1 + sRef_depth (s->info->arrayfetch->arr);
3261 return (sRef_depth (sRef_fixConj (s)));
3268 sRef_makeObject (ctype o)
3270 sRef s = sRef_new ();
3272 s->kind = SK_OBJECT;
3273 s->info = (sinfo) dmalloc (sizeof (*s->info));
3274 s->info->object = o;
3278 sRef sRef_makeExternal (/*@exposed@*/ sRef t)
3280 sRef s = sRef_new ();
3282 llassert (sRef_isValid (t));
3284 s->kind = SK_EXTERNAL;
3285 s->info = (sinfo) dmalloc (sizeof (*s->info));
3291 sRef sRef_makeDerived (/*@exposed@*/ sRef t)
3293 if (sRef_isValid (t))
3295 sRef s = sRef_new ();
3297 s->kind = SK_DERIVED;
3298 s->info = (sinfo) dmalloc (sizeof (*s->info));
3306 return sRef_undefined;
3311 ** definitely NOT symmetric:
3313 ** res fills in unknown state information from other
3317 sRef_mergeStateQuiet (sRef res, sRef other)
3319 llassert (sRef_isValid (res));
3320 llassert (sRef_isValid (other));
3322 res->modified = res->modified || other->modified;
3323 res->safe = res->safe && other->safe;
3325 if (res->defstate == SS_UNKNOWN)
3327 res->defstate = other->defstate;
3328 res->definfo = alinfo_update (res->definfo, other->definfo);
3331 if (res->aliaskind == AK_UNKNOWN ||
3332 (res->aliaskind == AK_LOCAL && alkind_isKnown (other->aliaskind)))
3334 res->aliaskind = other->aliaskind;
3335 res->oaliaskind = other->oaliaskind;
3336 res->aliasinfo = alinfo_update (res->aliasinfo, other->aliasinfo);
3339 if (res->expkind == XO_UNKNOWN)
3341 res->expkind = other->expkind;
3342 res->oexpkind = other->oexpkind;
3343 res->expinfo = alinfo_update (res->expinfo, other->expinfo);
3346 /* out takes precedence over implicitly defined */
3347 if (res->defstate == SS_DEFINED && other->defstate != SS_UNKNOWN)
3349 res->defstate = other->defstate;
3350 res->definfo = alinfo_update (res->definfo, other->definfo);
3353 if (other->nullstate == NS_ERROR || res->nullstate == NS_ERROR)
3355 res->nullstate = NS_ERROR;
3359 if (other->nullstate != NS_UNKNOWN
3360 && (res->nullstate == NS_UNKNOWN || res->nullstate == NS_NOTNULL
3361 || res->nullstate == NS_MNOTNULL))
3363 res->nullstate = other->nullstate;
3364 res->nullinfo = alinfo_update (res->nullinfo, other->nullinfo);
3370 ** definitely NOT symmetric:
3372 ** res fills in known state information from other
3376 sRef_mergeStateQuietReverse (sRef res, sRef other)
3378 bool changed = FALSE;
3380 llassert (sRef_isValid (res));
3381 llassert (sRef_isValid (other));
3383 if (res->kind != other->kind)
3389 res->kind = other->kind;
3390 res->type = other->type;
3391 res->info = sinfo_fullCopy (other);
3395 if (!ctype_equal (res->type, other->type))
3398 res->type = other->type;
3401 sinfo_update (res, other);
3404 res->modified = res->modified || other->modified;
3405 res->safe = res->safe && other->safe;
3407 if (res->aliaskind != other->aliaskind
3408 && (res->aliaskind == AK_UNKNOWN
3409 || ((res->aliaskind == AK_LOCAL
3410 || (res->aliaskind == AK_REFCOUNTED
3411 && other->aliaskind != AK_LOCAL))
3412 && other->aliaskind != AK_UNKNOWN)))
3415 res->aliaskind = other->aliaskind;
3416 res->oaliaskind = other->oaliaskind;
3417 res->aliasinfo = alinfo_update (res->aliasinfo, other->aliasinfo);
3420 if (other->expkind != XO_UNKNOWN && other->expkind != res->expkind)
3423 res->expkind = other->expkind;
3424 res->expinfo = alinfo_update (res->expinfo, other->expinfo);
3427 if (other->oexpkind != XO_UNKNOWN)
3429 res->oexpkind = other->oexpkind;
3432 /* out takes precedence over implicitly defined */
3434 if (res->defstate != other->defstate)
3436 if (other->defstate != SS_UNKNOWN)
3438 res->defstate = other->defstate;
3442 if (other->nullstate == NS_ERROR || res->nullstate == NS_ERROR)
3444 if (res->nullstate != NS_ERROR)
3446 res->nullstate = NS_ERROR;
3452 if (other->nullstate != NS_UNKNOWN && other->nullstate != res->nullstate)
3455 res->nullstate = other->nullstate;
3456 res->nullinfo = alinfo_update (res->nullinfo, other->nullinfo);
3462 sRef_clearDerived (res);
3467 sRef_mergeState (sRef res, sRef other, clause cl, fileloc loc)
3469 if (sRef_isValid (res) && sRef_isValid (other))
3471 sRef_mergeStateAux (res, other, cl, FALSE, loc, TRUE);
3475 if (sRef_isInvalid (res))
3477 llbug (message ("sRef_mergeState: invalid res sRef: %q",
3478 sRef_unparseDebug (other)));
3482 llbug (message ("sRef_mergeState: invalid other sRef: %q",
3483 sRef_unparseDebug (res)));
3489 sRef_mergeOptState (sRef res, sRef other, clause cl, fileloc loc)
3491 if (sRef_isValid (res) && sRef_isValid (other))
3493 sRef_mergeStateAux (res, other, cl, TRUE, loc, TRUE);
3497 if (sRef_isInvalid (res))
3499 llbug (message ("sRef_mergeOptState: invalid res sRef: %q",
3500 sRef_unparseDebug (other)));
3504 llbug (message ("sRef_mergeOptState: invalid other sRef: %q",
3505 sRef_unparseDebug (res)));
3511 sRef_mergeStateAux (/*@notnull@*/ sRef res, /*@notnull@*/ sRef other,
3512 clause cl, bool opt, fileloc loc,
3516 llassertfatal (sRef_isValid (res));
3517 llassertfatal (sRef_isValid (other));
3519 res->modified = res->modified || other->modified;
3521 if (res->kind == other->kind
3522 || (other->kind == SK_UNKNOWN || res->kind == SK_UNKNOWN))
3524 sstate odef = other->defstate;
3525 sstate rdef = res->defstate;
3526 nstate onull = other->nullstate;
3529 ** yucky stuff to handle
3534 if (other->defstate == SS_DEAD
3535 && ((sRef_isOnly (res) && sRef_definitelyNull (res))
3536 || (res->defstate == SS_UNDEFINED
3537 || res->defstate == SS_UNUSEABLE)))
3539 if (res->defstate == SS_UNDEFINED
3540 || res->defstate == SS_UNUSEABLE)
3542 res->defstate = SS_UNUSEABLE;
3546 res->defstate = SS_DEAD;
3549 res->definfo = alinfo_update (res->definfo, other->definfo);
3550 sRef_clearDerived (other);
3551 sRef_clearDerived (res);
3553 else if (res->defstate == SS_DEAD
3554 && ((sRef_isOnly (other) && sRef_definitelyNull (other))
3555 || (other->defstate == SS_UNDEFINED
3556 || other->defstate == SS_UNUSEABLE)))
3558 if (other->defstate == SS_UNDEFINED
3559 || other->defstate == SS_UNUSEABLE)
3561 res->defstate = SS_UNUSEABLE;
3565 res->defstate = SS_DEAD;
3568 sRef_clearDerived (other);
3569 sRef_clearDerived (res);
3571 else if (res->defstate == SS_DEFINED
3572 && (other->defstate == SS_ALLOCATED
3573 && sRef_definitelyNull (other)))
3575 other->defstate = SS_DEFINED; /* definitely null! */
3577 else if (other->defstate == SS_DEFINED
3578 && (res->defstate == SS_ALLOCATED && sRef_definitelyNull (res)))
3580 res->defstate = SS_DEFINED;
3581 res->definfo = alinfo_update (res->definfo, other->definfo);
3588 if (res->defstate == SS_DEAD && other->defstate == SS_DEAD)
3590 sRef_clearDerived (other);
3591 sRef_clearDerived (res);
3595 ** only & dead isn't really an only!
3598 if (alkind_isOnly (other->aliaskind) && other->defstate == SS_DEAD)
3600 other->aliaskind = AK_UNKNOWN;
3603 if (alkind_isOnly (res->aliaskind) && res->defstate == SS_DEAD)
3605 res->aliaskind = AK_UNKNOWN;
3609 ** Dead and dependent -> dead
3612 if (alkind_isDependent (other->aliaskind) && res->defstate == SS_DEAD)
3614 other->aliaskind = AK_UNKNOWN;
3615 other->defstate = SS_DEAD;
3616 sRef_clearDerived (res);
3617 sRef_clearDerived (other);
3620 if (alkind_isDependent (res->aliaskind) && other->defstate == SS_DEAD)
3622 res->aliaskind = AK_UNKNOWN;
3623 res->defstate = SS_DEAD;
3624 sRef_clearDerived (res);
3625 sRef_clearDerived (other);
3629 ** must do alias combine first, since it depends on
3630 ** original values of state and null.
3633 sRef_combineAliasKinds (res, other, cl, loc);
3634 sRef_combineDefState (res, other);
3635 sRef_combineNullState (res, other);
3637 if (rdef == SS_ALLOCATED || rdef == SS_SPECIAL)
3639 if (odef == SS_DEFINED)
3641 if (onull == NS_DEFNULL || onull == NS_CONSTNULL)
3643 res->deriv = sRefSet_copy (res->deriv, other->deriv);
3648 else if (odef == SS_ALLOCATED
3649 || odef == SS_SPECIAL)
3654 if (ctype_isUnion (ctype_realType (sRef_getType (res))))
3656 res->deriv = sRef_mergeUnionDerivs (res->deriv,
3662 res->deriv = sRef_mergeDerivs (res->deriv, other->deriv,
3671 res->deriv = sRef_mergeDerivs (res->deriv, other->deriv,
3681 if (rdef == SS_PDEFINED
3682 || (rdef == SS_DEFINED && odef == SS_PDEFINED))
3686 res->deriv = sRef_mergePdefinedDerivs (res->deriv, other->deriv,
3692 if ((rdef == SS_DEFINED || rdef == SS_UNKNOWN)
3693 && res->defstate == SS_ALLOCATED)
3695 res->deriv = sRefSet_copy (res->deriv, other->deriv);
3701 res->deriv = sRef_mergeDerivs (res->deriv, other->deriv,
3709 sRef_combineExKinds (res, other);
3713 if (res->kind == SK_ARRAYFETCH && other->kind == SK_PTR)
3715 sRef nother = sRef_buildArrayFetchKnown (sRef_getBase (other), 0);
3717 sRef_copyState (nother, other);
3718 sRef_mergeStateAux (res, nother, cl, opt, loc, doDerivs);
3720 else if (res->kind == SK_PTR && other->kind == SK_ARRAYFETCH)
3722 sRef nother = sRef_buildPointer (sRef_getBase (other));
3724 if (sRef_isValid (nother))
3726 sRef_copyState (nother, other);
3727 sRef_mergeStateAux (res, nother, cl, opt, loc, doDerivs);
3732 llcontbug (message ("merge conj: %q / %q", sRef_unparseFull (res),
3733 sRef_unparseFull (other)));
3741 sRef_mergeUnionDerivs (/*@only@*/ sRefSet res,
3742 /*@exposed@*/ sRefSet other, bool opt,
3743 clause cl, fileloc loc)
3745 if (sRefSet_isEmpty (res))
3747 return sRefSet_copy (res, other);
3751 sRefSet_allElements (other, el)
3753 if (sRef_isValid (el))
3755 sRef e2 = sRefSet_lookupMember (other, el);
3757 if (sRef_isValid (e2))
3759 sRef_mergeStateAux (el, e2, cl, opt, loc, FALSE);
3763 res = sRefSet_insert (res, el);
3766 } end_sRefSet_allElements ;
3772 static /*@only@*/ sRefSet
3773 sRef_mergeDerivs (/*@only@*/ sRefSet res, sRefSet other,
3774 bool opt, clause cl, fileloc loc)
3776 sRefSet ret = sRefSet_new ();
3779 sRefSet_allElements (res, el)
3781 if (sRef_isValid (el))
3783 sRef e2 = sRefSet_lookupMember (other, el);
3785 if (sRef_isValid (e2))
3787 if (el->defstate == SS_ALLOCATED &&
3788 e2->defstate == SS_PDEFINED)
3790 e2->defstate = SS_ALLOCATED;
3792 else if (e2->defstate == SS_ALLOCATED &&
3793 el->defstate == SS_PDEFINED)
3795 el->defstate = SS_ALLOCATED;
3796 sRef_clearDerived (el);
3798 else if ((el->defstate == SS_DEAD || sRef_isKept (el)) &&
3799 (e2->defstate == SS_DEFINED && !sRef_isKept (e2)))
3802 if (checkDeadState (el, TRUE, loc))
3804 if (sRef_isThroughArrayFetch (el))
3806 sRef_maybeKill (el, loc);
3807 sRef_maybeKill (e2, loc);
3811 else if ((e2->defstate == SS_DEAD || sRef_isKept (e2)) &&
3812 (el->defstate == SS_DEFINED && !sRef_isKept (el)))
3815 if (checkDeadState (e2, FALSE, loc))
3817 if (sRef_isThroughArrayFetch (el))
3819 sRef_maybeKill (el, loc);
3820 sRef_maybeKill (e2, loc);
3824 else if (el->defstate == SS_DEFINED &&
3825 e2->defstate == SS_PDEFINED)
3827 el->defstate = SS_PDEFINED;
3829 else if (e2->defstate == SS_DEFINED &&
3830 el->defstate == SS_PDEFINED)
3832 e2->defstate = SS_PDEFINED;
3839 if (ctype_isUnion (ctype_realType (sRef_getType (el))))
3841 el->deriv = sRef_mergeUnionDerivs (el->deriv, e2->deriv,
3846 el->deriv = sRef_mergeDerivs (el->deriv, e2->deriv, opt, cl, loc);
3849 if (sRef_equivalent (el, e2))
3851 ret = sRefSet_insert (ret, el);
3855 sRef sr = sRef_leastCommon (el, e2);
3857 if (sRef_isValid (sr))
3859 ret = sRefSet_insert (ret, sr);
3867 (void) sRefSet_delete (other, e2);
3869 else /* not defined */
3871 (void) checkDeadState (el, TRUE, loc);
3874 } end_sRefSet_allElements;
3876 sRefSet_allElements (other, el)
3878 if (sRef_isValid (el))
3880 (void) checkDeadState (el, FALSE, loc);
3882 } end_sRefSet_allElements;
3889 ** Returns TRUE is there is an error.
3892 static bool checkDeadState (/*@notnull@*/ sRef el, bool tbranch, fileloc loc)
3895 ** usymtab_isGuarded --- the utab should still be in the
3896 ** state of the alternate branch.
3898 ** tbranch TRUE means el is released in the last branch, e.g.
3899 ** if (x != NULL) { ; } else { sfree (x); }
3900 ** so, if x is null in the other branch no error is reported.
3902 ** tbranch FALSE means this is the other branch:
3903 ** if (x != NULL) { sfree (x); } else { ; }
3904 ** so, if x is null in this branch there is no error.
3908 if ((sRef_isDead (el) || sRef_isKept (el))
3909 && !sRef_isDeepUnionField (el) && !sRef_isThroughArrayFetch (el))
3914 if (usymtab_isProbableDeepNull (el))
3921 if (usymtab_isAltProbablyDeepNull (el))
3929 message ("Storage %q is %q in one path, but live in another.",
3931 cstring_makeLiteral (sRef_isKept (el)
3932 ? "kept" : "released")),
3936 if (sRef_isKept (el))
3938 sRef_showAliasInfo (el);
3942 sRef_showStateInfo (el);
3945 /* prevent further errors */
3946 el->defstate = SS_UNKNOWN;
3947 sRef_setAliasKind (el, AK_ERROR, fileloc_undefined);
3957 checkDerivDeadState (/*@notnull@*/ sRef el, bool tbranch, fileloc loc)
3960 if (checkDeadState (el, tbranch, loc))
3962 sRefSet_allElements (el->deriv, t)
3964 if (sRef_isValid (t))
3966 checkDerivDeadState (t, tbranch, loc);
3968 } end_sRefSet_allElements;
3973 sRef_mergePdefinedDerivs (sRefSet res, sRefSet other, bool opt,
3974 clause cl, fileloc loc)
3976 sRefSet ret = sRefSet_new ();
3978 sRefSet_allElements (res, el)
3980 if (sRef_isValid (el))
3982 sRef e2 = sRefSet_lookupMember (other, el);
3984 if (sRef_isValid (e2))
3986 if (sRef_isAllocated (el) && !sRef_isAllocated (e2))
3990 else if (sRef_isAllocated (e2) && !sRef_isAllocated (el))
3992 el->deriv = sRefSet_copy (el->deriv, e2->deriv);
3996 el->deriv = sRef_mergePdefinedDerivs (el->deriv, e2->deriv,
4000 sRef_mergeStateAux (el, e2, cl, opt, loc, FALSE);
4002 ret = sRefSet_insert (ret, el);
4003 (void) sRefSet_delete (other, e2);
4009 checkDerivDeadState (el, (cl == FALSECLAUSE), loc);
4012 ret = sRefSet_insert (ret, el);
4015 } end_sRefSet_allElements;
4017 sRefSet_allElements (other, el)
4019 if (sRef_isValid (el))
4021 if (!sRefSet_member (ret, el))
4023 /* was cl == FALSECLAUSE */
4024 checkDerivDeadState (el, FALSE, loc);
4025 ret = sRefSet_insert (ret, el);
4030 ** it's okay --- member is a different equality test
4034 } end_sRefSet_allElements;
4040 sRef sRef_makeConj (/*@exposed@*/ /*@returned@*/ sRef a, /*@exposed@*/ sRef b)
4042 llassert (sRef_isValid (a));
4043 llassert (sRef_isValid (b));
4045 if (!sRef_equivalent (a, b))
4047 sRef s = sRef_new ();
4050 s->info = (sinfo) dmalloc (sizeof (*s->info));
4051 s->info->conj = (cjinfo) dmalloc (sizeof (*s->info->conj));
4052 s->info->conj->a = a;
4053 s->info->conj->b = b;
4055 if (ctype_equal (a->type, b->type)) s->type = a->type;
4056 else s->type = ctype_makeConj (a->type, b->type);
4058 if (a->defstate == b->defstate)
4060 s->defstate = a->defstate;
4064 s->defstate = SS_UNKNOWN;
4067 s->nullstate = NS_UNKNOWN;
4069 s->safe = a->safe && b->safe;
4070 s->aliaskind = alkind_resolve (a->aliaskind, b->aliaskind);
4076 /*@-exposetrans@*/ return a; /*@=exposetrans@*/
4083 sRef s = sRef_new ();
4085 s->kind = SK_UNKNOWN;
4090 sRef_makeSpecial (speckind sk) /*@*/
4092 sRef s = sRef_new ();
4094 s->kind = SK_SPECIAL;
4095 s->info = (sinfo) dmalloc (sizeof (*s->info));
4100 static sRef srnothing = sRef_undefined;
4101 static sRef srinternal = sRef_undefined;
4102 static sRef srsystem = sRef_undefined;
4103 static sRef srspec = sRef_undefined;
4106 sRef_makeNothing (void)
4108 if (sRef_isInvalid (srnothing))
4110 srnothing = sRef_makeSpecial (SR_NOTHING);
4119 sRef_makeInternalState (void)
4121 if (sRef_isInvalid (srinternal))
4123 srinternal = sRef_makeSpecial (SR_INTERNAL);
4132 sRef_makeSpecState (void)
4134 if (sRef_isInvalid (srspec))
4136 srspec = sRef_makeSpecial (SR_SPECSTATE);
4145 sRef_makeSystemState (void)
4147 if (sRef_isInvalid (srsystem))
4149 srsystem = sRef_makeSpecial (SR_SYSTEM);
4158 sRef_makeResultType (ctype ct)
4160 sRef res = sRef_makeResult ();
4169 sRef s = sRef_new ();
4171 s->kind = SK_RESULT;
4172 s->type = ctype_unknown;
4173 s->defstate = SS_UNKNOWN;
4174 s->aliaskind = AK_UNKNOWN;
4175 s->nullstate = NS_UNKNOWN;
4182 sRef_isNothing (sRef s)
4184 return (sRef_isKindSpecial (s) && s->info->spec == SR_NOTHING);
4188 sRef_isInternalState (sRef s)
4190 return (sRef_isKindSpecial (s) && s->info->spec == SR_INTERNAL);
4194 sRef_isSpecInternalState (sRef s)
4196 return (sRef_isKindSpecial (s)
4197 && (s->info->spec == SR_INTERNAL || s->info->spec == SR_SPECSTATE));
4201 sRef_isSpecState (sRef s)
4203 return (sRef_isKindSpecial (s) && s->info->spec == SR_SPECSTATE);
4207 sRef_isResult (sRef s)
4209 return (sRef_isValid (s) && s->kind == SK_RESULT);
4213 sRef_isSystemState (sRef s)
4215 return (sRef_isKindSpecial (s) && s->info->spec == SR_SYSTEM);
4219 sRef_getScopeIndex (sRef s)
4221 llassert (sRef_isValid (s));
4222 llassert (sRef_isCvar (s));
4224 return (s->info->cvar->index);
4228 sRef_makeSafe (sRef s)
4230 if (sRef_isValid (s))
4237 sRef_makeUnsafe (sRef s)
4239 if (sRef_isValid (s))
4246 ** memory state operations
4249 /*@only@*/ cstring sRef_unparseFull (sRef s)
4251 if (sRef_isInvalid (s)) return (cstring_undefined);
4253 return (message ("[%d] %q - %q [%s] { %q }",
4255 sRef_unparseDebug (s),
4256 sRef_unparseState (s),
4257 exkind_unparse (s->oexpkind),
4258 sRefSet_unparseDebug (s->deriv)));
4261 /*@unused@*/ cstring sRef_unparseDeep (sRef s)
4263 cstring st = cstring_undefined;
4265 st = message ("%q:", sRef_unparseFull (s));
4267 if (sRef_isValid (s))
4269 sRefSet_allElements (s->deriv, el)
4271 st = message("%q\n%q", st, sRef_unparseDeep (el));
4272 } end_sRefSet_allElements ;
4278 /*@only@*/ cstring sRef_unparseState (sRef s)
4280 if (sRef_isConj (s))
4282 return (message ("%q | %q",
4283 sRef_unparseState (s->info->conj->a),
4284 sRef_unparseState (s->info->conj->b)));
4287 if (sRef_isInvalid (s))
4289 return (cstring_makeLiteral ("<invalid>"));
4292 return (message ("%s.%s.%s.%s",
4293 alkind_unparse (s->aliaskind),
4294 nstate_unparse (s->nullstate),
4295 exkind_unparse (s->expkind),
4296 sstate_unparse (s->defstate)));
4299 bool sRef_isNotUndefined (sRef s)
4301 return (sRef_isInvalid (s)
4302 || (s->defstate != SS_UNDEFINED
4303 && s->defstate != SS_UNUSEABLE
4304 && s->defstate != SS_DEAD));
4307 ynm sRef_isWriteable (sRef s)
4309 if (sRef_isInvalid (s)) return MAYBE;
4311 if (sRef_isConj (s) && s->defstate == SS_UNKNOWN)
4313 if (ynm_toBoolStrict (sRef_isWriteable (sRef_getConjA (s))))
4315 if (ynm_toBoolStrict (sRef_isWriteable (sRef_getConjB (s))))
4323 if (ynm_toBoolStrict (sRef_isWriteable (sRef_getConjB (s))))
4331 return (ynm_fromBool (s->defstate != SS_UNUSEABLE));
4334 bool sRef_hasNoStorage (sRef s)
4336 return (!sRef_isAllocatedStorage (s) || sRef_isDefinitelyNull (s));
4339 bool sRef_isStrictReadable (sRef s)
4341 return (ynm_toBoolStrict (sRef_isReadable (s)));
4344 ynm sRef_isReadable (sRef s)
4348 if (sRef_isInvalid (s)) return YES;
4352 if (sRef_isConj (s) && s->defstate == SS_UNKNOWN)
4354 if (ynm_toBoolStrict (sRef_isReadable (sRef_getConjA (s))))
4356 if (ynm_toBoolStrict (sRef_isReadable (sRef_getConjB (s))))
4364 if (ynm_toBoolStrict (sRef_isReadable (sRef_getConjB (s))))
4371 else if (ss == SS_HOFFA)
4373 if (context_getFlag (FLG_STRICTUSERELEASED))
4384 return (ynm_fromBool (ss == SS_DEFINED
4387 || ss == SS_PDEFINED
4390 || ss == SS_ALLOCATED
4391 || ss == SS_UNKNOWN));
4395 static /*@exposed@*/ sRef whatUndefined (/*@exposed@*/ sRef fref, int depth)
4400 if (depth > MAXDEPTH)
4403 ("Warning: check definition limit exceeded, checking %q. "
4404 "This either means there is a variable with at least "
4405 "%d indirections apparent in the program text, or "
4406 "there is a bug in LCLint.",
4407 sRef_unparse (fref),
4411 return sRef_undefined;
4414 if (!sRef_isKnown (fref) || sRef_isAnyDefined (fref))
4416 return sRef_undefined;
4419 if (sRef_isUnuseable (fref) || sRef_isStateUndefined (fref))
4424 ct = ctype_realType (sRef_getType (fref));
4426 if (ctype_isUnknown (ct))
4428 return sRef_undefined;
4430 else if (ctype_isPointer (ct) || ctype_isArray (ct))
4432 if (sRef_isStateUnknown (fref))
4434 return sRef_undefined;
4438 sRef fptr = sRef_constructDeref (fref);
4440 return (whatUndefined (fptr, depth + 1));
4443 else if (ctype_isStruct (ct))
4445 bool hasOneDefined = FALSE;
4447 if (sRef_isStateUnknown (fref))
4452 if (sRef_isPdefined (fref) || sRef_isAnyDefined (fref))
4454 sRefSet_realElements (sRef_derivedFields (fref), sr)
4456 hasOneDefined = TRUE;
4458 if (sRef_isField (sr))
4460 cstring fieldname = sRef_getField (sr);
4461 sRef fldref = sRef_makeField (fref, fieldname);
4462 bool shouldCheck = !sRef_isRecursiveField (fldref);
4466 sRef wdef = whatUndefined (fldref, depth + 1);
4468 if (sRef_isValid (wdef))
4474 } end_sRefSet_realElements;
4476 else if (sRef_isAllocated (fref))
4479 ** for structures, each field must be completely defined
4482 uentryList fields = ctype_getFields (ct);
4484 uentryList_elements (fields, ue)
4486 cstring name = uentry_getRealName (ue);
4487 sRef ffield = sRef_makeField (fref, name);
4488 bool shouldCheck = !sRef_isRecursiveField (ffield);
4490 if (sRef_isRelDef (uentry_getSref (ue)))
4498 sRef wdef = whatUndefined (ffield, depth + 1);
4500 if (sRef_isInvalid (wdef))
4506 } end_uentryList_elements;
4513 else if (ctype_isUnion (ct))
4522 return sRef_undefined;
4525 static bool checkDefined (sRef sr)
4527 return (sRef_isInvalid (whatUndefined (sr, 0)));
4530 bool sRef_isReallyDefined (sRef s)
4532 if (sRef_isValid (s))
4534 if (sRef_isAnyDefined (s))
4540 if (sRef_isAllocated (s) || sRef_isPdefined (s))
4542 return checkDefined (s);
4556 void sRef_showNotReallyDefined (sRef s)
4558 if (sRef_isValid (s))
4560 if (sRef_isAnyDefined (s))
4566 if (sRef_isAllocated (s) || sRef_isPdefined (s))
4568 sRef ref = whatUndefined (s, 0);
4570 llassert (sRef_isValid (ref));
4575 (message ("This sub-reference is %s: %q",
4576 sstate_unparse (sRef_getDefState (ref)),
4577 sRef_unparse (ref)));
4592 sstate sRef_getDefState (sRef s)
4594 if (sRef_isInvalid (s)) return (SS_UNKNOWN);
4595 return (s->defstate);
4598 void sRef_setDefState (sRef s, sstate defstate, fileloc loc)
4600 sRef_setStateAux (s, defstate, loc);
4603 static void sRef_clearAliasStateAux (sRef s, fileloc loc)
4605 sRef_setAliasKind (s, AK_ERROR, loc);
4608 void sRef_clearAliasState (sRef s, fileloc loc)
4610 sRef_aliasSetComplete (sRef_clearAliasStateAux, s, loc);
4613 void sRef_setAliasKindComplete (sRef s, alkind kind, fileloc loc)
4615 sRef_aliasSetCompleteParam (sRef_setAliasKind, s, kind, loc);
4618 void sRef_setAliasKind (sRef s, alkind kind, fileloc loc)
4620 if (sRef_isValid (s))
4622 sRef_clearDerived (s);
4624 if ((kind != s->aliaskind && kind != s->oaliaskind)
4625 && fileloc_isDefined (loc))
4627 s->aliasinfo = alinfo_updateLoc (s->aliasinfo, loc);
4630 s->aliaskind = kind;
4634 void sRef_setOrigAliasKind (sRef s, alkind kind)
4636 if (sRef_isValid (s))
4638 s->oaliaskind = kind;
4642 exkind sRef_getExKind (sRef s)
4644 if (sRef_isValid (s))
4646 return (s->expkind);
4654 exkind sRef_getOrigExKind (sRef s)
4656 if (sRef_isValid (s))
4658 return (s->oexpkind);
4666 static void sRef_clearExKindAux (sRef s, fileloc loc)
4668 sRef_setExKind (s, XO_UNKNOWN, loc);
4671 void sRef_setObserver (sRef s, fileloc loc)
4673 sRef_setExKind (s, XO_OBSERVER, loc);
4676 void sRef_setExposed (sRef s, fileloc loc)
4678 sRef_setExKind (s, XO_EXPOSED, loc);
4681 void sRef_clearExKindComplete (sRef s, fileloc loc)
4683 (void) sRef_aliasSetComplete (sRef_clearExKindAux, s, loc);
4686 void sRef_setExKind (sRef s, exkind exp, fileloc loc)
4688 if (sRef_isValid (s))
4690 if (s->expkind != exp)
4692 s->expinfo = alinfo_updateLoc (s->expinfo, loc);
4700 ** s1->derived = s2->derived
4703 static void sRef_copyRealDerived (sRef s1, sRef s2)
4705 if (sRef_isValid (s1) && sRef_isValid (s2))
4707 sRef sb = sRef_getRootBase (s1);
4709 sRefSet_clear (s1->deriv);
4711 sRefSet_allElements (s2->deriv, el)
4713 if (sRef_isValid (el))
4715 sRef rb = sRef_getRootBase (el);
4717 if (!sRef_same (rb, sb))
4719 sRef fb = sRef_fixDirectBase (el, s1);
4721 if (sRef_isValid (fb))
4723 sRef_copyRealDerived (fb, el);
4724 sRef_addDeriv (s1, fb);
4729 sRef_addDeriv (s1, el);
4732 } end_sRefSet_allElements ;
4737 void sRef_copyRealDerivedComplete (sRef s1, sRef s2)
4739 sRef_innerAliasSetCompleteParam (sRef_copyRealDerived, s1, s2);
4742 void sRef_setUndefined (sRef s, fileloc loc)
4744 if (sRef_isValid (s))
4746 s->defstate = SS_UNDEFINED;
4748 if (fileloc_isDefined (loc))
4750 s->definfo = alinfo_updateLoc (s->definfo, loc);
4753 sRef_clearDerived (s);
4757 static void sRef_setDefinedAux (sRef s, fileloc loc, bool clear)
4759 if (sRef_isInvalid (s)) return;
4761 if (s->defstate != SS_DEFINED && fileloc_isDefined (loc))
4763 s->definfo = alinfo_updateLoc (s->definfo, loc);
4766 s->defstate = SS_DEFINED;
4768 /* e.g., if x is allocated, *x = 3 defines x */
4770 if (s->kind == SK_PTR)
4772 sRef p = s->info->ref;
4774 if (p->defstate == SS_ALLOCATED)
4776 sRef_setDefinedAux (p, loc, clear);
4779 else if (s->kind == SK_ARRAYFETCH)
4781 if (!s->info->arrayfetch->indknown
4782 || (s->info->arrayfetch->ind == 0))
4784 sRef p = s->info->arrayfetch->arr;
4785 sRef ptr = sRef_constructPointer (p);
4787 if (sRef_isValid (ptr))
4789 if (ptr->defstate == SS_ALLOCATED
4790 || ptr->defstate == SS_UNDEFINED)
4792 sRef_setDefinedAux (ptr, loc, clear);
4796 if (p->defstate == SS_RELDEF)
4800 else if (p->defstate == SS_ALLOCATED || p->defstate == SS_PDEFINED)
4802 p->defstate = SS_DEFINED;
4809 else if (s->kind == SK_FIELD)
4811 sRef parent = s->info->field->rec;
4813 if (sRef_isValid (parent))
4815 if (ctype_isUnion (ctype_realType (parent->type)))
4818 ** Should not clear derived from here.
4821 sRef_setDefinedNoClear (parent, loc);
4825 ; /* Nothing to do for structures. */
4837 sRef_clearDerived (s);
4841 static void sRef_setPartialDefined (sRef s, fileloc loc)
4843 if (!sRef_isPartial (s))
4845 sRef_setDefined (s, loc);
4849 void sRef_setPartialDefinedComplete (sRef s, fileloc loc)
4851 sRef_innerAliasSetComplete (sRef_setPartialDefined, s, loc);
4854 void sRef_setDefinedComplete (sRef s, fileloc loc)
4856 sRef_innerAliasSetComplete (sRef_setDefined, s, loc);
4859 void sRef_setDefined (sRef s, fileloc loc)
4861 sRef_setDefinedAux (s, loc, TRUE);
4864 static void sRef_setDefinedNoClear (sRef s, fileloc loc)
4866 DPRINTF (("Defining: %s", sRef_unparseFull (s)));
4867 sRef_setDefinedAux (s, loc, FALSE);
4868 DPRINTF (("==> %s", sRef_unparseFull (s)));
4871 void sRef_setDefinedNCComplete (sRef s, fileloc loc)
4873 DPRINTF (("Set Defined Complete: %s", sRef_unparseFull (s)));
4874 sRef_innerAliasSetComplete (sRef_setDefinedNoClear, s, loc);
4875 DPRINTF (("==> %s", sRef_unparseFull (s)));
4878 static bool sRef_isDeepUnionField (sRef s)
4880 return (sRef_deepPred (sRef_isUnionField, s));
4883 bool sRef_isUnionField (sRef s)
4885 if (sRef_isValid (s) && s->kind == SK_FIELD)
4888 ** defining one field of a union defines the union
4891 sRef base = s->info->field->rec;
4893 if (sRef_isValid (base))
4895 return (ctype_isUnion (ctype_realType (base->type)));
4902 void sRef_setPdefined (sRef s, fileloc loc)
4904 if (sRef_isValid (s) && !sRef_isPartial (s))
4906 sRef base = sRef_getBaseSafe (s);
4908 if (s->defstate == SS_ALLOCATED)
4913 if (s->defstate != SS_PDEFINED && fileloc_isDefined (loc))
4915 s->definfo = alinfo_updateLoc (s->definfo, loc);
4918 s->defstate = SS_PDEFINED;
4920 /* e.g., if x is allocated, *x = 3 defines x */
4922 while (sRef_isValid (base) && sRef_isKnown (base))
4924 if (base->defstate == SS_DEFINED)
4928 base->defstate = SS_PDEFINED;
4929 nb = sRef_getBaseSafe (base);
4940 static void sRef_setStateAux (sRef s, sstate ss, fileloc loc)
4942 if (sRef_isValid (s))
4944 /* if (s->defstate == SS_RELDEF) return; */
4946 if (s->defstate != ss && fileloc_isDefined (loc))
4948 s->definfo = alinfo_updateLoc (s->definfo, loc);
4952 sRef_clearDerived (s);
4954 if (ss == SS_ALLOCATED)
4956 sRef base = sRef_getBaseSafe (s);
4958 while (sRef_isValid (base) && sRef_isKnown (base))
4960 if (base->defstate == SS_DEFINED)
4964 base->defstate = SS_PDEFINED;
4966 nb = sRef_getBaseSafe (base);
4979 void sRef_setAllocatedComplete (sRef s, fileloc loc)
4981 sRef_innerAliasSetComplete (sRef_setAllocated, s, loc);
4984 static void sRef_setAllocatedShallow (sRef s, fileloc loc)
4986 if (sRef_isValid (s))
4988 if (s->defstate == SS_DEAD || s->defstate == SS_UNDEFINED)
4990 s->defstate = SS_ALLOCATED;
4992 if (fileloc_isDefined (loc))
4994 s->definfo = alinfo_updateLoc (s->definfo, loc);
5000 void sRef_setAllocatedShallowComplete (sRef s, fileloc loc)
5002 sRef_innerAliasSetComplete (sRef_setAllocatedShallow, s, loc);
5005 void sRef_setAllocated (sRef s, fileloc loc)
5007 sRef_setStateAux (s, SS_ALLOCATED, loc);
5010 void sRef_setPartial (sRef s, fileloc loc)
5012 sRef_setStateAux (s, SS_PARTIAL, loc);
5015 void sRef_setShared (sRef s, fileloc loc)
5017 if (sRef_isValid (s))
5019 if (s->aliaskind != AK_SHARED && fileloc_isDefined (loc))
5021 s->aliasinfo = alinfo_updateLoc (s->aliasinfo, loc);
5024 s->aliaskind = AK_SHARED;
5025 /* don't! sRef_clearDerived (s); */
5029 void sRef_setLastReference (sRef s, sRef ref, fileloc loc)
5031 if (sRef_isValid (s))
5033 s->aliaskind = sRef_getAliasKind (ref);
5034 s->aliasinfo = alinfo_updateRefLoc (s->aliasinfo, ref, loc);
5039 void sRef_setNullStateAux (/*@notnull@*/ sRef s, nstate ns, fileloc loc)
5043 if (fileloc_isDefined (loc))
5045 s->nullinfo = alinfo_updateLoc (s->nullinfo, loc);
5049 void sRef_setNotNull (sRef s, fileloc loc)
5051 if (sRef_isValid (s))
5053 sRef_setNullStateAux (s, NS_NOTNULL, loc);
5057 void sRef_setNullState (sRef s, nstate n, fileloc loc)
5059 if (sRef_isValid (s))
5061 sRef_setNullStateAux (s, n, loc);
5065 void sRef_setNullTerminatedStateInnerComplete (sRef s, struct _bbufinfo b, /*@unused@*/ fileloc loc) {
5067 switch (b.bufstate) {
5068 case BB_NULLTERMINATED:
5069 sRef_setNullTerminatedState (s);
5070 sRef_setLen (s, b.len);
5072 case BB_POSSIBLYNULLTERMINATED:
5073 sRef_setPossiblyNullTerminatedState(s);
5075 case BB_NOTNULLTERMINATED:
5076 sRef_setNotNullTerminatedState (s);
5079 sRef_setSize (s, b.size);
5081 /* PL: TO BE DONE : Aliases are not modified right now, have to be similar to
5082 * setNullStateInnerComplete.
5086 void sRef_setNullStateInnerComplete (sRef s, nstate n, fileloc loc)
5088 sRef_setNullState (s, n, loc);
5093 sRef_innerAliasSetComplete (sRef_setPosNull, s, loc);
5096 sRef_innerAliasSetComplete (sRef_setDefNull, s, loc);
5099 sRef_innerAliasSetComplete (sRef_setNullUnknown, s, loc);
5102 sRef_innerAliasSetComplete (sRef_setNotNull, s, loc);
5105 sRef_innerAliasSetComplete (sRef_setNotNull, s, loc);
5108 sRef_innerAliasSetComplete (sRef_setNullUnknown, s, loc);
5111 sRef_innerAliasSetComplete (sRef_setDefNull, s, loc);
5114 sRef_innerAliasSetComplete (sRef_setNullUnknown, s, loc);
5117 sRef_innerAliasSetComplete (sRef_setNullErrorLoc, s, loc);
5122 void sRef_setPosNull (sRef s, fileloc loc)
5124 if (sRef_isValid (s))
5126 sRef_setNullStateAux (s, NS_POSNULL, loc);
5130 void sRef_setDefNull (sRef s, fileloc loc)
5132 if (sRef_isValid (s))
5134 sRef_setNullStateAux (s, NS_DEFNULL, loc);
5138 void sRef_setNullUnknown (sRef s, fileloc loc)
5140 if (sRef_isValid (s))
5142 sRef_setNullStateAux (s, NS_UNKNOWN, loc);
5146 void sRef_setNullError (sRef s)
5148 if (sRef_isValid (s))
5150 sRef_setNullStateAux (s, NS_UNKNOWN, fileloc_undefined);
5154 void sRef_setNullErrorLoc (sRef s, /*@unused@*/ fileloc loc)
5156 sRef_setNullError (s);
5159 void sRef_setOnly (sRef s, fileloc loc)
5161 if (sRef_isValid (s) && s->aliaskind != AK_ONLY)
5163 s->aliaskind = AK_ONLY;
5164 s->aliasinfo = alinfo_updateLoc (s->aliasinfo, loc);
5168 void sRef_setDependent (sRef s, fileloc loc)
5170 if (sRef_isValid (s) && !sRef_isConst (s) && (s->aliaskind != AK_DEPENDENT))
5172 s->aliaskind = AK_DEPENDENT;
5173 s->aliasinfo = alinfo_updateLoc (s->aliasinfo, loc);
5177 void sRef_setOwned (sRef s, fileloc loc)
5179 if (sRef_isValid (s) && !sRef_isConst (s) && (s->aliaskind != AK_OWNED))
5181 s->aliaskind = AK_OWNED;
5182 s->aliasinfo = alinfo_updateLoc (s->aliasinfo, loc);
5186 void sRef_setKept (sRef s, fileloc loc)
5188 if (sRef_isValid (s) && !sRef_isConst (s) && (s->aliaskind != AK_KEPT))
5190 sRef base = sRef_getBaseSafe (s);
5192 while (sRef_isValid (base) && sRef_isKnown (base))
5194 if (base->defstate == SS_DEFINED)
5196 base->defstate = SS_PDEFINED;
5197 base = sRef_getBaseSafe (base);
5206 s->aliaskind = AK_KEPT;
5207 s->aliasinfo = alinfo_updateLoc (s->aliasinfo, loc);
5211 static void sRef_setKeptAux (sRef s, fileloc loc)
5213 if (!sRef_isShared (s))
5215 sRef_setKept (s, loc);
5219 static void sRef_setDependentAux (sRef s, fileloc loc)
5221 if (!sRef_isShared (s))
5223 sRef_setDependent (s, loc);
5227 void sRef_setKeptComplete (sRef s, fileloc loc)
5229 sRef_aliasSetComplete (sRef_setKeptAux, s, loc);
5232 void sRef_setDependentComplete (sRef s, fileloc loc)
5234 sRef_aliasSetComplete (sRef_setDependentAux, s, loc);
5237 void sRef_setFresh (sRef s, fileloc loc)
5239 if (sRef_isValid (s))
5241 s->aliaskind = AK_FRESH;
5242 s->aliasinfo = alinfo_updateLoc (s->aliasinfo, loc);
5246 void sRef_kill (sRef s, fileloc loc)
5248 DPRINTF (("Kill: %s", sRef_unparseFull (s)));
5250 if (sRef_isValid (s) && !sRef_isShared (s) && !sRef_isConst (s))
5252 sRef base = sRef_getBaseSafe (s);
5254 while (sRef_isValid (base) && sRef_isKnown (base))
5256 if (base->defstate == SS_DEFINED)
5258 base->defstate = SS_PDEFINED;
5259 base = sRef_getBaseSafe (base);
5268 s->aliaskind = s->oaliaskind;
5269 s->defstate = SS_DEAD;
5270 s->definfo = alinfo_updateLoc (s->definfo, loc);
5272 sRef_clearDerived (s);
5276 void sRef_maybeKill (sRef s, fileloc loc)
5279 if (sRef_isValid (s))
5281 sRef base = sRef_getBaseSafe (s);
5284 while (sRef_isValid (base) && sRef_isKnown (base))
5286 if (base->defstate == SS_DEFINED || base->defstate == SS_RELDEF)
5288 base->defstate = SS_PDEFINED;
5289 base = sRef_getBaseSafe (base);
5298 s->aliaskind = s->oaliaskind;
5299 s->defstate = SS_HOFFA;
5300 s->definfo = alinfo_updateLoc (s->definfo, loc);
5301 sRef_clearDerived (s);
5307 ** just for type checking...
5310 static void sRef_killAux (sRef s, fileloc loc)
5312 if (sRef_isValid (s) && !sRef_isShared (s))
5314 if (sRef_isUnknownArrayFetch (s))
5316 sRef_maybeKill (s, loc);
5326 ** kills s and all aliases to s
5329 void sRef_killComplete (sRef s, fileloc loc)
5331 DPRINTF (("Kill complete: %s", sRef_unparseFull (s)));
5332 sRef_aliasSetComplete (sRef_killAux, s, loc);
5335 static bool sRef_equivalent (sRef s1, sRef s2)
5337 return (sRef_compare (s1, s2) == 0);
5341 ** returns an sRef that will not be free'd on function exit.
5344 /*@only@*/ sRef sRef_saveCopy (sRef s)
5348 if (sRef_isValid (s))
5350 bool old = inFunction;
5353 ** Exit the function scope, so this sRef is not
5354 ** stored in the deallocation table.
5358 DPRINTF (("Copying sref: %s", sRef_unparseFull(s)));
5359 ret = sRef_copy (s);
5360 DPRINTF (("Copying ===>: %s", sRef_unparseFull(ret)));
5365 ret = sRef_undefined;
5368 /*@-dependenttrans@*/
5370 /*@=dependenttrans@*/
5373 sRef sRef_copy (sRef s)
5375 if (sRef_isKindSpecial (s))
5378 return s; /* don't copy specials */
5382 if (sRef_isValid (s))
5384 sRef t = sRef_alloc ();
5388 t->modified = s->modified;
5391 t->info = sinfo_copy (s);
5393 t->defstate = s->defstate;
5395 t->nullstate = s->nullstate;
5397 /* start modifications */
5398 t->bufinfo.bufstate = s->bufinfo.bufstate;
5399 t->bufinfo.len = s->bufinfo.len;
5400 t->bufinfo.size = s->bufinfo.size;
5401 /* end modifications */
5403 t->aliaskind = s->aliaskind;
5404 t->oaliaskind = s->oaliaskind;
5406 t->expkind = s->expkind;
5407 t->oexpkind = s->oexpkind;
5409 t->aliasinfo = alinfo_copy (s->aliasinfo);
5410 t->definfo = alinfo_copy (s->definfo);
5411 t->nullinfo = alinfo_copy (s->nullinfo);
5412 t->expinfo = alinfo_copy (s->expinfo);
5414 t->deriv = sRefSet_newDeepCopy (s->deriv);
5420 return sRef_undefined;
5425 # define PREDTEST(func,s) \
5426 do { if (sRef_isInvalid (s)) { return FALSE; } \
5427 else { if (sRef_isConj (s)) \
5428 { return (func (sRef_getConjA (s)) \
5429 || func (sRef_getConjB (s))); }}} while (FALSE);
5431 bool sRef_isAddress (sRef s)
5433 PREDTEST (sRef_isAddress, s);
5434 return (s->kind == SK_ADR);
5438 ** pretty weak... maybe a flag should control this.
5441 bool sRef_isThroughArrayFetch (sRef s)
5443 if (sRef_isValid (s))
5451 if (sRef_isArrayFetch (tref))
5456 lt = sRef_getBase (tref);
5458 } while (sRef_isValid (tref));
5464 bool sRef_isArrayFetch (sRef s)
5466 PREDTEST (sRef_isArrayFetch, s);
5467 return (s->kind == SK_ARRAYFETCH);
5470 bool sRef_isMacroParamRef (sRef s)
5472 if (context_inMacro () && sRef_isCvar (s))
5474 uentry ue = sRef_getUentry (s);
5475 cstring pname = makeParam (uentry_rawName (ue));
5476 uentry mac = usymtab_lookupSafe (pname);
5478 cstring_free (pname);
5479 return (uentry_isValid (mac));
5485 bool sRef_isCvar (sRef s)
5487 PREDTEST (sRef_isCvar, s);
5488 return (s->kind == SK_CVAR);
5491 bool sRef_isConst (sRef s)
5493 PREDTEST (sRef_isConst, s);
5494 return (s->kind == SK_CONST);
5497 bool sRef_isObject (sRef s)
5499 PREDTEST (sRef_isObject, s);
5500 return (s->kind == SK_OBJECT);
5503 bool sRef_isExternal (sRef s)
5505 PREDTEST (sRef_isExternal, s);
5506 return (s->kind == SK_EXTERNAL);
5509 static bool sRef_isDerived (sRef s)
5511 PREDTEST (sRef_isDerived, s);
5512 return (s->kind == SK_DERIVED);
5515 bool sRef_isField (sRef s)
5517 PREDTEST (sRef_isField, s);
5518 return (s->kind == SK_FIELD);
5521 static bool sRef_isIndex (sRef s)
5523 PREDTEST (sRef_isIndex, s);
5524 return (s->kind == SK_ARRAYFETCH);
5527 bool sRef_isAnyParam (sRef s)
5529 PREDTEST (sRef_isAnyParam, s);
5530 return (s->kind == SK_PARAM);
5533 bool sRef_isParam (sRef s)
5535 PREDTEST (sRef_isParam, s);
5536 return (s->kind == SK_PARAM);
5539 bool sRef_isDirectParam (sRef s)
5541 PREDTEST (sRef_isDirectParam, s);
5543 return ((s->kind == SK_CVAR) &&
5544 (s->info->cvar->lexlevel == functionScope) &&
5545 (context_inFunction () &&
5546 (s->info->cvar->index <= uentryList_size (context_getParams ()))));
5549 bool sRef_isPointer (sRef s)
5551 PREDTEST (sRef_isPointer, s);
5552 return (s->kind == SK_PTR);
5556 ** returns true if storage referenced by s is visible
5559 bool sRef_isReference (sRef s)
5561 PREDTEST (sRef_isReference, s);
5563 return (sRef_isPointer (s) || sRef_isIndex (s) || sRef_isGlobal (s)
5564 || (sRef_isField (s) && (sRef_isReference (s->info->field->rec))));
5567 bool sRef_isIReference (sRef s)
5569 return (sRef_isPointer (s) || sRef_isAddress (s) || sRef_isIndex (s)
5570 || sRef_isField (s) || sRef_isArrayFetch (s));
5573 bool sRef_isGlobal (sRef s)
5575 return (sRef_isCvar (s) && (s->info->cvar->lexlevel <= fileScope));
5578 bool sRef_isRealGlobal (sRef s)
5580 return (sRef_isCvar (s) && (s->info->cvar->lexlevel == globScope));
5583 bool sRef_isFileStatic (sRef s)
5585 return (sRef_isCvar (s) && (s->info->cvar->lexlevel == fileScope));
5588 bool sRef_isAliasCheckedGlobal (sRef s)
5590 if (sRef_isGlobal (s))
5592 uentry ue = sRef_getUentry (s);
5594 return context_checkAliasGlob (ue);
5602 void sRef_free (/*@only@*/ sRef s)
5604 if (s != sRef_undefined && s->kind != SK_SPECIAL)
5606 alinfo_free (s->expinfo);
5607 alinfo_free (s->aliasinfo);
5608 alinfo_free (s->definfo);
5609 alinfo_free (s->nullinfo);
5611 sRefSet_free (s->deriv);
5612 s->deriv = sRefSet_undefined;
5619 void sRef_setType (sRef s, ctype t)
5621 if (sRef_isValid (s))
5627 void sRef_setTypeFull (sRef s, ctype t)
5629 if (sRef_isValid (s))
5633 sRefSet_allElements (s->deriv, current)
5635 sRef_setTypeFull (current, ctype_unknown);
5636 } end_sRefSet_allElements ;
5641 sRef_buildField (sRef rec, /*@dependent@*/ cstring f)
5643 return (sRef_buildNCField (rec, f));
5646 static /*@exposed@*/ sRef
5647 sRef_findDerivedField (/*@notnull@*/ sRef rec, cstring f)
5649 sRefSet_allElements (rec->deriv, sr)
5651 if (sRef_isValid (sr))
5653 if (sr->kind == SK_FIELD && cstring_equal (sr->info->field->field, f))
5658 } end_sRefSet_allElements;
5660 return sRef_undefined;
5663 /*@dependent@*/ /*@observer@*/ sRefSet
5664 sRef_derivedFields (sRef rec)
5666 if (sRef_isValid (rec))
5674 return (sRefSet_undefined);
5678 static /*@exposed@*/ sRef
5679 sRef_findDerivedPointer (sRef s)
5681 if (sRef_isValid (s))
5683 sRefSet_realElements (s->deriv, sr)
5685 if (sRef_isValid (sr) && sr->kind == SK_PTR)
5689 } end_sRefSet_realElements;
5692 return sRef_undefined;
5696 sRef_isUnknownArrayFetch (sRef s)
5698 return (sRef_isValid (s)
5699 && s->kind == SK_ARRAYFETCH
5700 && !s->info->arrayfetch->indknown);
5703 static /*@exposed@*/ sRef
5704 sRef_findDerivedArrayFetch (/*@notnull@*/ sRef s, bool isknown, int idx, bool dead)
5709 sRefSet_realElements (s->deriv, sr)
5711 if (sRef_isValid (sr)
5712 && sr->kind == SK_ARRAYFETCH
5713 && sr->info->arrayfetch->indknown
5714 && (sr->info->arrayfetch->ind == idx))
5718 } end_sRefSet_realElements;
5722 sRefSet_realElements (s->deriv, sr)
5724 if (sRef_isValid (sr)
5725 && sr->kind == SK_ARRAYFETCH
5726 && (!sr->info->arrayfetch->indknown
5727 || (sr->info->arrayfetch->indknown &&
5728 sr->info->arrayfetch->ind == 0)))
5730 if (sRef_isDead (sr) || sRef_isKept (sr))
5732 if (dead || context_getFlag (FLG_STRICTUSERELEASED))
5742 } end_sRefSet_realElements;
5745 return sRef_undefined;
5748 static /*@exposed@*/ sRef
5749 sRef_buildNCField (/*@exposed@*/ sRef rec, /*@exposed@*/ cstring f)
5753 if (sRef_isInvalid (rec))
5755 return sRef_undefined;
5759 ** check if the field already has been referenced
5762 s = sRef_findDerivedField (rec, f);
5764 if (sRef_isValid (s))
5770 ctype ct = ctype_realType (rec->type);
5774 s->info = (sinfo) dmalloc (sizeof (*s->info));
5775 s->info->field = (fldinfo) dmalloc (sizeof (*s->info->field));
5776 s->info->field->rec = rec;
5777 s->info->field->field = f; /* doesn't copy f */
5780 if (ctype_isKnown (ct) && ctype_isSU (ct))
5782 uentry ue = uentryList_lookupField (ctype_getFields (ct), f);
5784 if (!uentry_isUndefined (ue))
5786 s->type = uentry_getType (ue);
5788 if (ctype_isMutable (s->type)
5789 && rec->aliaskind != AK_STACK
5790 && !alkind_isStatic (rec->aliaskind))
5792 s->aliaskind = rec->aliaskind;
5796 s->aliaskind = AK_UNKNOWN;
5799 if (sRef_isStateDefined (rec) || sRef_isStateUnknown (rec)
5800 || sRef_isPdefined (rec))
5802 sRef_setStateFromUentry (s, ue);
5806 sRef_setPartsFromUentry (s, ue);
5809 s->oaliaskind = s->aliaskind;
5810 s->oexpkind = s->expkind;
5815 Never report this as an error. It can happen whenever there
5816 is casting involved.
5820 llcontbug (message ("buildNCField --- no field %s: %q / %s",
5821 f, sRef_unparse (s), ctype_unparse (ct)));
5825 return sRef_undefined;
5829 if (rec->defstate == SS_DEFINED
5830 && (s->defstate == SS_UNDEFINED || s->defstate == SS_UNKNOWN))
5832 s->defstate = SS_DEFINED;
5834 else if (rec->defstate == SS_PARTIAL)
5836 s->defstate = SS_PARTIAL;
5838 else if (rec->defstate == SS_ALLOCATED)
5840 if (ctype_isStackAllocated (ct) && ctype_isStackAllocated (s->type))
5842 s->defstate = SS_ALLOCATED;
5846 s->defstate = SS_UNDEFINED;
5849 else if (s->defstate == SS_UNKNOWN)
5851 s->defstate = rec->defstate;
5858 if (s->defstate == SS_UNDEFINED)
5860 ctype rt = ctype_realType (s->type);
5862 if (ctype_isArray (rt) || ctype_isSU (rt))
5864 s->defstate = SS_ALLOCATED;
5868 sRef_addDeriv (rec, s);
5870 if (ctype_isInt (s->type) && cstring_equal (f, REFSNAME))
5872 s->aliaskind = AK_REFS;
5873 s->oaliaskind = AK_REFS;
5881 sRef_isStackAllocated (sRef s)
5883 return (sRef_isValid(s)
5884 && s->defstate == SS_ALLOCATED && ctype_isStackAllocated (s->type));
5888 void sRef_setArrayFetchState (/*@notnull@*/ /*@exposed@*/ sRef s,
5889 /*@notnull@*/ /*@exposed@*/ sRef arr)
5891 if (ctype_isRealAP (arr->type))
5893 s->type = ctype_baseArrayPtr (arr->type);
5896 /* a hack, methinks... makeArrayFetch (&a[0]) ==> a[] */
5897 if (sRef_isAddress (arr))
5899 sRef t = arr->info->ref;
5901 if (sRef_isArrayFetch (t))
5903 s->info->arrayfetch->arr = t->info->arrayfetch->arr;
5906 else if (ctype_isRealPointer (arr->type))
5908 sRef sp = sRef_findDerivedPointer (arr);
5911 if (sRef_isValid (sp))
5914 if (ctype_isMutable (s->type))
5916 sRef_setExKind (s, sRef_getExKind (sp), fileloc_undefined);
5919 s->aliaskind = sp->aliaskind;
5922 s->defstate = sp->defstate;
5924 if (s->defstate == SS_DEFINED)
5926 if (!context_getFlag (FLG_STRICTDESTROY))
5928 s->defstate = SS_PARTIAL;
5932 s->nullstate = sp->nullstate;
5936 if (arr->defstate == SS_UNDEFINED)
5938 s->defstate = SS_UNUSEABLE;
5940 else if ((arr->defstate == SS_ALLOCATED) && !ctype_isSU (s->type))
5942 s->defstate = SS_UNDEFINED;
5946 if (!context_getFlag (FLG_STRICTDESTROY))
5948 s->defstate = SS_PARTIAL;
5952 s->defstate = SS_DEFINED;
5956 ** Very weak checking for array elements.
5958 ** s->defstate = arr->defstate;
5962 sRef_setExKind (s, sRef_getExKind (arr), g_currentloc);
5964 if (arr->aliaskind == AK_LOCAL || arr->aliaskind == AK_FRESH)
5966 s->aliaskind = AK_LOCAL;
5970 s->aliaskind = AK_UNKNOWN;
5973 sRef_setTypeState (s);
5978 if (arr->defstate == SS_DEFINED)
5981 ** Very weak checking for array elements.
5983 ** s->defstate = arr->defstate;
5986 if (context_getFlag (FLG_STRICTDESTROY))
5988 s->defstate = SS_DEFINED;
5992 s->defstate = SS_PARTIAL;
5995 else if (arr->defstate == SS_ALLOCATED)
5997 if (ctype_isRealArray (s->type))
5999 s->defstate = SS_ALLOCATED;
6003 if (!s->info->arrayfetch->indknown)
6006 ** is index is unknown, elements is defined or
6007 ** allocated is any element is!
6010 s->defstate = SS_UNDEFINED;
6012 sRefSet_allElements (arr->deriv, sr)
6014 if (sRef_isValid (sr))
6016 if (sr->defstate == SS_ALLOCATED)
6018 s->defstate = SS_ALLOCATED;
6022 if (sr->defstate == SS_DEFINED)
6024 if (context_getFlag (FLG_STRICTDESTROY))
6026 s->defstate = SS_DEFINED;
6030 s->defstate = SS_PARTIAL;
6037 } end_sRefSet_allElements;
6042 s->defstate = SS_UNDEFINED;
6048 s->defstate = arr->defstate;
6053 ** kludgey way to guess where aliaskind applies
6056 if (ctype_isMutable (s->type)
6057 && !ctype_isPointer (arr->type)
6058 && !alkind_isStatic (arr->aliaskind)
6059 && !alkind_isStack (arr->aliaskind)) /* evs - 2000-06-20: don't pass stack allocation to members */
6061 s->aliaskind = arr->aliaskind;
6065 s->aliaskind = AK_UNKNOWN;
6068 sRef_setTypeState (s);
6071 if (sRef_isObserver (arr))
6073 s->expkind = XO_OBSERVER;
6077 /*@exposed@*/ sRef sRef_buildArrayFetch (/*@exposed@*/ sRef arr)
6081 if (!sRef_isValid (arr)) {
6082 /*@-nullret@*/ return arr /*@=nullret@*/;
6085 if (ctype_isRealPointer (arr->type))
6087 (void) sRef_buildPointer (arr); /* do this to define arr! */
6090 s = sRef_findDerivedArrayFetch (arr, FALSE, 0, FALSE);
6092 if (sRef_isValid (s))
6094 sRef_setExKind (s, sRef_getExKind (arr), g_currentloc);
6101 s->kind = SK_ARRAYFETCH;
6102 s->info = (sinfo) dmalloc (sizeof (*s->info));
6103 s->info->arrayfetch = (ainfo) dmalloc (sizeof (*s->info->arrayfetch));
6104 s->info->arrayfetch->indknown = FALSE;
6105 s->info->arrayfetch->ind = 0;
6106 s->info->arrayfetch->arr = arr;
6107 sRef_setArrayFetchState (s, arr);
6108 s->oaliaskind = s->aliaskind;
6109 s->oexpkind = s->expkind;
6111 if (!context_inProtectVars ())
6113 sRef_addDeriv (arr, s);
6121 sRef_buildArrayFetchKnown (/*@exposed@*/ sRef arr, int i)
6125 if (!sRef_isValid (arr)) {
6126 /*@-nullret@*/ return arr /*@=nullret@*/;
6129 if (ctype_isRealPointer (arr->type))
6131 (void) sRef_buildPointer (arr); /* do this to define arr! */
6134 s = sRef_findDerivedArrayFetch (arr, TRUE, i, FALSE);
6136 if (sRef_isValid (s))
6138 sRef_setExKind (s, sRef_getExKind (arr), g_currentloc);
6145 s->kind = SK_ARRAYFETCH;
6146 s->info = (sinfo) dmalloc (sizeof (*s->info));
6147 s->info->arrayfetch = (ainfo) dmalloc (sizeof (*s->info->arrayfetch));
6148 s->info->arrayfetch->arr = arr;
6149 s->info->arrayfetch->indknown = TRUE;
6150 s->info->arrayfetch->ind = i;
6152 sRef_setArrayFetchState (s, arr);
6154 s->oaliaskind = s->aliaskind;
6155 s->oexpkind = s->expkind;
6156 sRef_addDeriv (arr, s);
6163 ** sets everything except for defstate
6167 sRef_setPartsFromUentry (sRef s, uentry ue)
6170 llassert (sRef_isValid (s));
6172 s->aliaskind = alkind_derive (s->aliaskind, uentry_getAliasKind (ue));
6173 s->oaliaskind = s->aliaskind;
6175 if (s->expkind == XO_UNKNOWN)
6177 s->expkind = uentry_getExpKind (ue);
6180 s->oexpkind = s->expkind;
6182 if (s->nullstate == NS_UNKNOWN)
6184 s->nullstate = sRef_getNullState (uentry_getSref (ue));
6187 if (s->aliaskind == AK_IMPONLY
6188 && (sRef_isExposed (s) || sRef_isObserver (s)))
6190 s->oaliaskind = s->aliaskind = AK_IMPDEPENDENT;
6196 sRef_setStateFromAbstractUentry (sRef s, uentry ue)
6198 llassert (sRef_isValid (s));
6200 sRef_setPartsFromUentry (s, ue);
6202 s->aliaskind = alkind_derive (s->aliaskind, uentry_getAliasKind (ue));
6203 s->oaliaskind = s->aliaskind;
6205 if (s->expkind == XO_UNKNOWN)
6207 s->expkind = uentry_getExpKind (ue);
6210 s->oexpkind = s->expkind;
6214 sRef_setStateFromUentry (sRef s, uentry ue)
6218 llassert (sRef_isValid (s));
6220 sRef_setPartsFromUentry (s, ue);
6222 defstate = uentry_getDefState (ue);
6224 if (sstate_isKnown (defstate))
6226 s->defstate = defstate;
6235 sRef_buildPointer (/*@exposed@*/ sRef t)
6237 DPRINTF (("build pointer: %s", sRef_unparse (t)));
6239 if (sRef_isInvalid (t)) return sRef_undefined;
6241 if (sRef_isAddress (t))
6243 DPRINTF (("Return ref: %s", sRef_unparse (t->info->ref)));
6244 return (t->info->ref);
6248 sRef s = sRef_findDerivedPointer (t);
6250 DPRINTF (("find derived: %s", sRef_unparse (s)));
6252 if (sRef_isValid (s))
6255 sRef_setExKind (s, sRef_getExKind (t), g_currentloc);
6256 s->oaliaskind = s->aliaskind;
6257 s->oexpkind = s->expkind;
6263 s = sRef_constructPointerAux (t);
6265 DPRINTF (("construct: %s", sRef_unparse (s)));
6267 if (sRef_isValid (s))
6269 sRef_addDeriv (t, s);
6271 s->oaliaskind = s->aliaskind;
6272 s->oexpkind = s->expkind;
6281 sRef_constructPointer (sRef t)
6284 return sRef_buildPointer (t);
6287 static /*@exposed@*/ sRef sRef_constructDerefAux (sRef t, bool isdead)
6289 if (sRef_isValid (t))
6294 ** if there is a derived t[?], return that. Otherwise, *t.
6298 s = sRef_findDerivedArrayFetch (t, FALSE, 0, isdead);
6300 if (sRef_isValid (s))
6306 sRef ret = sRef_constructPointer (t);
6309 ** This is necessary to prevent infinite depth
6310 ** in checking complete destruction.
6316 /* ret->defstate = SS_UNKNOWN; */
6327 return sRef_undefined;
6331 sRef sRef_constructDeref (sRef t)
6333 return sRef_constructDerefAux (t, FALSE);
6336 sRef sRef_constructDeadDeref (sRef t)
6338 return sRef_constructDerefAux (t, TRUE);
6342 sRef_constructPointerAux (/*@notnull@*/ /*@exposed@*/ sRef t)
6344 sRef s = sRef_new ();
6349 s->info = (sinfo) dmalloc (sizeof (*s->info));
6352 if (ctype_isRealAP (rt))
6354 s->type = ctype_baseArrayPtr (rt);
6357 st = ctype_realType (s->type);
6360 if (t->defstate == SS_UNDEFINED)
6362 s->defstate = SS_UNUSEABLE;
6364 else if ((t->defstate == SS_ALLOCATED) && !ctype_isSU (st))
6366 s->defstate = SS_UNDEFINED;
6370 s->defstate = t->defstate;
6373 if (t->aliaskind == AK_LOCAL || t->aliaskind == AK_FRESH)
6375 s->aliaskind = AK_LOCAL;
6379 s->aliaskind = AK_UNKNOWN;
6382 sRef_setExKind (s, sRef_getExKind (t), fileloc_undefined);
6383 sRef_setTypeState (s);
6385 s->oaliaskind = s->aliaskind;
6386 s->oexpkind = s->expkind;
6391 bool sRef_hasDerived (sRef s)
6393 return (sRef_isValid (s) && !sRefSet_isEmpty (s->deriv));
6397 sRef_clearDerived (sRef s)
6399 if (sRef_isValid (s))
6401 sRefSet_clear (s->deriv);
6406 sRef_clearDerivedComplete (sRef s)
6409 if (sRef_isValid (s))
6411 sRef base = sRef_getBaseSafe (s);
6413 while (sRef_isValid (base))
6415 sRefSet_clear (base->deriv);
6416 base = sRef_getBaseSafe (base);
6419 sRefSet_clear (s->deriv);
6424 sRef_makePointer (sRef s)
6427 sRef res = sRef_buildPointer (s);
6429 DPRINTF (("Res: %s", sRef_unparse (res)));
6434 ** &a[] => a (this is for out params)
6438 sRef_makeAnyArrayFetch (/*@exposed@*/ sRef arr)
6441 if (sRef_isAddress (arr))
6443 return (arr->info->ref);
6447 return (sRef_buildArrayFetch (arr));
6452 sRef_makeArrayFetch (sRef arr)
6454 return (sRef_buildArrayFetch (arr));
6458 sRef_makeArrayFetchKnown (sRef arr, int i)
6460 return (sRef_buildArrayFetchKnown (arr, i));
6464 sRef_makeField (sRef rec, /*@dependent@*/ cstring f)
6467 ret = sRef_buildField (rec, f);
6472 sRef_makeNCField (sRef rec, /*@dependent@*/ cstring f)
6474 return (sRef_buildNCField (rec, f));
6478 sRef_unparseKindName (sRef s)
6482 if (s == sRef_undefined) return cstring_makeLiteral ("<invalid>");
6484 s = sRef_fixConj (s);
6489 if (sRef_isLocalVar (s))
6491 result = cstring_makeLiteral ("Variable");
6495 result = cstring_makeLiteral ("Undef global");
6499 result = cstring_makeLiteral ("Out parameter");
6502 if (sRef_isAnyParam (s->info->arrayfetch->arr))
6504 result = cstring_makeLiteral ("Out parameter");
6506 else if (sRef_isIndexKnown (s))
6508 result = cstring_makeLiteral ("Array element");
6512 result = cstring_makeLiteral ("Value");
6516 if (sRef_isAnyParam (s->info->ref))
6518 result = cstring_makeLiteral ("Out parameter");
6522 result = cstring_makeLiteral ("Value");
6526 result = cstring_makeLiteral ("Value");
6529 result = cstring_makeLiteral ("Field");
6532 result = cstring_makeLiteral ("Object");
6534 case SK_UNCONSTRAINED:
6535 result = cstring_makeLiteral ("<anything>");
6544 result = cstring_makeLiteral ("<unknown>");
6547 result = cstring_makeLiteral ("<conj>");
6550 result = cstring_makeLiteral ("Storage");
6558 sRef_unparseKindNamePlain (sRef s)
6562 if (s == sRef_undefined) return cstring_makeLiteral ("<invalid>");
6564 s = sRef_fixConj (s);
6569 if (sRef_isLocalVar (s))
6571 result = cstring_makeLiteral ("Variable");
6575 result = cstring_makeLiteral ("Global");
6579 result = cstring_makeLiteral ("Parameter");
6582 if (sRef_isAnyParam (s->info->arrayfetch->arr))
6584 result = cstring_makeLiteral ("Parameter");
6586 else if (sRef_isIndexKnown (s))
6588 result = cstring_makeLiteral ("Array element");
6592 result = cstring_makeLiteral ("Value");
6596 if (sRef_isAnyParam (s->info->ref))
6598 result = cstring_makeLiteral ("Parameter");
6602 result = cstring_makeLiteral ("Value");
6606 result = cstring_makeLiteral ("Value");
6609 result = cstring_makeLiteral ("Field");
6612 result = cstring_makeLiteral ("Object");
6615 result = cstring_makeLiteral ("Storage");
6617 case SK_UNCONSTRAINED:
6618 result = cstring_makeLiteral ("<anything>");
6627 result = cstring_makeLiteral ("<unknown>");
6630 result = cstring_makeLiteral ("<conj>");
6642 sRef_copyState (sRef s1, sRef s2)
6644 if (sRef_isValid (s1) && sRef_isValid (s2))
6646 s1->defstate = s2->defstate;
6648 s1->nullstate = s2->nullstate;
6649 s1->nullinfo = alinfo_update (s1->nullinfo, s2->nullinfo);
6651 /* start modifications */
6652 s1->bufinfo.bufstate = s2->bufinfo.bufstate;
6653 s1->bufinfo.len = s2->bufinfo.len;
6654 s1->bufinfo.size = s2->bufinfo.size;
6655 /* end modifications */
6657 s1->aliaskind = s2->aliaskind;
6658 s1->aliasinfo = alinfo_update (s1->aliasinfo, s2->aliasinfo);
6660 s1->expkind = s2->expkind;
6661 s1->expinfo = alinfo_update (s1->expinfo, s2->expinfo);
6663 s1->safe = s2->safe;
6668 sRef_makeNew (ctype ct, sRef t, cstring name)
6670 sRef s = sRef_new ();
6675 llassert (sRef_isValid (t));
6676 s->defstate = t->defstate;
6678 s->aliaskind = t->aliaskind;
6679 s->oaliaskind = s->aliaskind;
6681 s->nullstate = t->nullstate;
6683 s->expkind = t->expkind;
6684 s->oexpkind = s->expkind;
6686 s->info = (sinfo) dmalloc (sizeof (*s->info));
6687 s->info->fname = name;
6689 /* start modifications */
6690 s->bufinfo.bufstate = t->bufinfo.bufstate;
6691 /* end modifications */
6697 sRef_makeType (ctype ct)
6699 sRef s = sRef_new ();
6704 s->defstate = SS_UNKNOWN;
6705 s->aliaskind = AK_UNKNOWN;
6706 s->nullstate = NS_UNKNOWN;
6707 /* start modification */
6708 s->bufinfo.bufstate = BB_NOTNULLTERMINATED;
6709 /* end modification */
6712 if (ctype_isUA (ct))
6714 typeId uid = ctype_typeId (ct);
6715 uentry ue = usymtab_getTypeEntrySafe (uid);
6717 if (uentry_isValid (ue))
6719 sRef_mergeStateQuiet (s, uentry_getSref (ue));
6723 s->oaliaskind = s->aliaskind;
6724 s->oexpkind = s->expkind;
6730 sRef_makeConst (ctype ct)
6732 sRef s = sRef_new ();
6737 s->defstate = SS_UNKNOWN;
6738 s->aliaskind = AK_UNKNOWN;
6739 s->nullstate = NS_UNKNOWN;
6740 /* start modification */
6741 s->bufinfo.bufstate = BB_NULLTERMINATED;
6742 /* end modification */
6745 if (ctype_isUA (ct))
6747 typeId uid = ctype_typeId (ct);
6748 uentry te = usymtab_getTypeEntrySafe (uid);
6750 if (uentry_isValid (te))
6752 sRef_mergeStateQuiet (s, uentry_getSref (te));
6757 s->oaliaskind = s->aliaskind;
6758 s->oexpkind = s->expkind;
6763 bool sRef_hasName (sRef s)
6765 if (sRef_isInvalid (s))
6774 uentry u = usymtab_getRefQuiet (s->info->cvar->lexlevel,
6775 s->info->cvar->index);
6776 return (uentry_hasName (u));
6780 uentry u = uentryList_getN (context_getParams (),
6783 return (uentry_hasName (u));
6790 bool sRef_sameObject (sRef s1, sRef s2)
6792 return sRef_sameName(s1, s2);
6795 sRef_sameName (sRef s1, sRef s2)
6797 if (sRef_isInvalid (s1))
6799 return sRef_isInvalid (s2);
6802 if (sRef_isInvalid (s2))
6810 if (s2->kind == SK_CVAR)
6812 return (s1->info->cvar->lexlevel == s2->info->cvar->lexlevel
6813 && s1->info->cvar->index == s2->info->cvar->index);
6815 else if (s2->kind == SK_PARAM)
6817 if (context_inFunctionLike ())
6819 uentry u1 = usymtab_getRefQuiet (s1->info->cvar->lexlevel,
6820 s1->info->cvar->index);
6821 uentry u2 = uentryList_getN (context_getParams (),
6824 return (cstring_equalFree (uentry_getName (u1),
6825 uentry_getName (u2)));
6838 if (s2->kind == SK_PARAM)
6840 return (s1->info->paramno == s2->info->paramno);
6842 else if (s2->kind == SK_CVAR)
6844 if (context_inFunctionLike ())
6846 uentry u1 = uentryList_getN (context_getParams (),
6848 uentry u2 = usymtab_getRefQuiet (s2->info->cvar->lexlevel,
6849 s2->info->cvar->index);
6852 return (cstring_equalFree (uentry_getName (u1),
6853 uentry_getName (u2)));
6866 case SK_UNCONSTRAINED:
6870 if (s2->kind == SK_ARRAYFETCH)
6872 if (bool_equal (s1->info->arrayfetch->indknown,
6873 s2->info->arrayfetch->indknown))
6875 if (!s1->info->arrayfetch->indknown
6876 || (s1->info->arrayfetch->ind == s2->info->arrayfetch->ind))
6878 return sRef_sameName (s1->info->arrayfetch->arr,
6879 s2->info->arrayfetch->arr);
6886 if (s2->kind == SK_FIELD)
6888 if (cstring_equal (s1->info->field->field,
6889 s2->info->field->field))
6891 return sRef_sameName (s1->info->field->rec,
6892 s2->info->field->rec);
6901 if (s2->kind == s1->kind)
6903 return sRef_sameName (s1->info->ref,
6911 return sRef_sameName (sRef_getConjA (s1), s2);
6915 return (s2->kind == SK_UNKNOWN);
6918 if (s2->kind == s1->kind)
6920 return (ctype_equal (s1->type, s2->type));
6925 if (s2->kind == SK_SPECIAL)
6927 return (s1->info->spec == s2->info->spec);
6931 return (s2->kind == SK_RESULT);
6939 sRef_fixOuterRef (/*@returned@*/ sRef s)
6941 sRef root = sRef_getRootBase (s);
6943 if (sRef_isCvar (root))
6945 uentry ue = usymtab_getRefQuiet (root->info->cvar->lexlevel,
6946 root->info->cvar->index);
6948 if (uentry_isValid (ue))
6950 sRef uref = uentry_getSref (ue);
6951 sRef sr = sRef_fixBase (s, uref);
6957 llcontbug (message ("sRef_fixOuterRef: undefined: %q", sRef_unparseDebug (s)));
6966 sRef_storeState (sRef s)
6968 if (sRef_isInvalid (s)) return;
6970 s->oaliaskind = s->aliaskind;
6971 s->oexpkind = s->expkind;
6974 static void sRef_resetStateAux (sRef s, /*@unused@*/ fileloc loc)
6976 sRef_resetState (s);
6980 sRef_resetState (sRef s)
6982 bool changed = FALSE;
6983 if (sRef_isInvalid (s)) return;
6986 if (s->oaliaskind == AK_KILLREF && !sRef_isParam (s))
6989 ** killref is used in a kludgey way, to save having to add
6990 ** another alias kind (see usymtab_handleParams)
6993 if (s->expkind != s->oexpkind)
6996 s->expkind = s->oexpkind;
7001 if (s->expkind != s->oexpkind)
7004 s->expkind = s->oexpkind;
7007 if (s->aliaskind != s->oaliaskind
7008 && s->aliaskind != AK_REFCOUNTED
7009 && s->aliaskind != AK_REFS)
7012 s->aliaskind = s->oaliaskind;
7018 sRef_clearDerived (s);
7024 sRef_resetStateComplete (sRef s)
7026 sRef_innerAliasSetComplete (sRef_resetStateAux, s, fileloc_undefined);
7030 sRef_fixBase (/*@returned@*/ sRef s, /*@returned@*/ sRef base)
7032 sRef tmp = sRef_undefined;
7035 if (sRef_isInvalid (s)) return s;
7036 if (sRef_isInvalid (base)) return base;
7046 tmp = sRef_fixBase (s->info->arrayfetch->arr, base);
7048 if (s->info->arrayfetch->indknown)
7050 ret = sRef_makeArrayFetchKnown (tmp, s->info->arrayfetch->ind);
7054 ret = sRef_makeArrayFetch (tmp);
7058 tmp = sRef_fixBase (s->info->field->rec, base);
7059 ret = sRef_buildNCField (tmp, s->info->field->field);
7062 tmp = sRef_fixBase (s->info->ref, base);
7063 ret = sRef_makePointer (tmp);
7066 tmp = sRef_fixBase (s->info->ref, base);
7067 ret = sRef_makeAddress (tmp);
7073 tmp = sRef_fixBase (s->info->conj->a, base);
7074 tmpb = sRef_fixBase (s->info->conj->b, base);
7076 ret = sRef_makeConj (tmp, tmpb);
7085 static /*@exposed@*/ sRef
7086 sRef_fixDirectBase (sRef s, sRef base)
7091 if (sRef_isInvalid (s))
7093 return sRef_undefined;
7099 if (s->info->arrayfetch->indknown)
7101 ret = sRef_makeArrayFetchKnown (base, s->info->arrayfetch->ind);
7105 ret = sRef_makeArrayFetch (base);
7109 ret = sRef_buildNCField (base, s->info->field->field);
7112 ret = sRef_makePointer (base);
7115 ret = sRef_makeAddress (base);
7121 tmpa = sRef_fixDirectBase (s->info->conj->a, base);
7122 tmpb = sRef_fixDirectBase (s->info->conj->b, base);
7124 ret = sRef_makeConj (tmpa, tmpb);
7130 sRef_copyState (ret, s);
7135 sRef_isAllocIndexRef (sRef s)
7137 return (sRef_isArrayFetch (s) && !(s->info->arrayfetch->indknown)
7138 && sRef_isAllocated (s->info->arrayfetch->arr));
7142 sRef_showRefLost (sRef s)
7144 if (sRef_hasAliasInfoLoc (s))
7146 llgenindentmsg (cstring_makeLiteral ("Original reference lost"),
7147 sRef_getAliasInfoLoc (s));
7152 sRef_showRefKilled (sRef s)
7154 if (sRef_hasStateInfoLoc (s))
7156 llgenindentmsg (message ("Storage %q released",
7157 sRef_unparse (s)), sRef_getStateInfoLoc (s));
7162 sRef_showStateInconsistent (sRef s)
7164 if (sRef_hasStateInfoLoc (s))
7167 (message ("Storage %qbecomes inconsistent (released on one branch)",
7168 sRef_unparseOpt (s)),
7169 sRef_getStateInfoLoc (s));
7174 sRef_showStateInfo (sRef s)
7176 if (sRef_hasStateInfoLoc (s))
7178 if (s->defstate == SS_DEAD)
7181 (message ("Storage %qis released", sRef_unparseOpt (s)),
7182 sRef_getStateInfoLoc (s));
7184 else if (s->defstate == SS_ALLOCATED || s->defstate == SS_DEFINED)
7187 (message ("Storage %qis %s", sRef_unparseOpt (s),
7188 sstate_unparse (s->defstate)),
7189 sRef_getStateInfoLoc (s));
7191 else if (s->defstate == SS_UNUSEABLE)
7194 (message ("Storage %qbecomes inconsistent (clauses merge with"
7195 "%qreleased on one branch)",
7196 sRef_unparseOpt (s),
7197 sRef_unparseOpt (s)),
7198 sRef_getStateInfoLoc (s));
7202 llgenindentmsg (message ("Storage %qbecomes %s",
7203 sRef_unparseOpt (s),
7204 sstate_unparse (s->defstate)),
7205 sRef_getStateInfoLoc (s));
7211 sRef_showExpInfo (sRef s)
7213 if (sRef_hasExpInfoLoc (s))
7215 llgenindentmsg (message ("Storage %qbecomes %s", sRef_unparseOpt (s),
7216 exkind_unparse (s->expkind)),
7217 sRef_getExpInfoLoc (s));
7222 sRef_showNullInfo (sRef s)
7224 if (sRef_hasNullInfoLoc (s) && sRef_isKnown (s))
7226 switch (s->nullstate)
7230 fileloc loc = sRef_getNullInfoLoc (s);
7232 if (fileloc_isDefined (loc) && !fileloc_isLib (loc))
7235 (message ("Storage %qbecomes null", sRef_unparseOpt (s)),
7242 fileloc loc = sRef_getNullInfoLoc (s);
7244 if (fileloc_isDefined (loc) && !fileloc_isLib (loc))
7246 llgenindentmsg (message ("Storage %qbecomes null", sRef_unparseOpt (s)),
7254 (message ("Storage %qmay become null", sRef_unparseOpt (s)),
7255 sRef_getNullInfoLoc (s));
7260 (message ("Storage %qbecomes not null", sRef_unparseOpt (s)),
7261 sRef_getNullInfoLoc (s));
7265 (message ("Storage %qnull state becomes unknown",
7266 sRef_unparseOpt (s)),
7267 sRef_getNullInfoLoc (s));
7276 (message ("<error case> Storage %q becomes %s",
7278 nstate_unparse (s->nullstate)),
7279 sRef_getNullInfoLoc (s));
7287 sRef_showAliasInfo (sRef s)
7289 if (sRef_hasAliasInfoLoc (s))
7291 if (sRef_isFresh (s))
7294 (message ("Fresh storage %qallocated", sRef_unparseOpt (s)),
7295 sRef_getAliasInfoLoc (s));
7299 if (!sRef_isRefCounted (s))
7302 (message ("Storage %qbecomes %s",
7303 sRef_unparseOpt (s),
7304 alkind_unparse (sRef_getAliasKind (s))),
7305 sRef_getAliasInfoLoc (s));
7312 sRef_mergeNullState (sRef s, nstate n)
7314 if (sRef_isValid (s))
7320 if (n != old && n != NS_UNKNOWN)
7324 s->nullinfo = alinfo_updateLoc (s->nullinfo, g_currentloc);
7329 llbuglit ("sRef_mergeNullState: invalid");
7334 sRef_possiblyNull (sRef s)
7336 if (sRef_isValid (s))
7338 if (s->nullstate == NS_ABSNULL)
7340 ctype rct = ctype_realType (s->type);
7342 if (ctype_isAbstract (rct))
7348 if (ctype_isUser (rct))
7350 uentry ue = usymtab_getTypeEntry (ctype_typeId (rct));
7352 return (nstate_possiblyNull
7353 (sRef_getNullState (uentry_getSref (ue))));
7363 return nstate_possiblyNull (s->nullstate);
7371 sRef_getScopeName (sRef s)
7373 sRef base = sRef_getRootBase (s);
7375 if (sRef_isRealGlobal (base))
7377 return (cstring_makeLiteralTemp ("Global"));
7379 else if (sRef_isFileStatic (base))
7381 return (cstring_makeLiteralTemp ("Static"));
7385 return (cstring_makeLiteralTemp ("Local"));
7390 sRef_unparseScope (sRef s)
7392 sRef base = sRef_getRootBase (s);
7394 if (sRef_isRealGlobal (base))
7396 return (cstring_makeLiteralTemp ("global"));
7398 else if (sRef_isFileStatic (base))
7400 return (cstring_makeLiteralTemp ("file static"));
7409 sRef_getScope (sRef s)
7411 llassert (sRef_isValid (s));
7413 if (sRef_isCvar (s))
7415 return s->info->cvar->lexlevel;
7417 else if (sRef_isParam (s))
7428 sRef_isDead (sRef s)
7430 return (sRef_isValid (s) && (s)->defstate == SS_DEAD);
7434 sRef_isDeadStorage (sRef s)
7436 if (sRef_isValid (s))
7438 if (s->defstate == SS_DEAD
7439 || s->defstate == SS_UNUSEABLE
7440 || s->defstate == SS_UNDEFINED
7441 || s->defstate == SS_UNKNOWN)
7447 return (sRef_isDefinitelyNull (s));
7457 sRef_isPossiblyDead (sRef s)
7459 return (sRef_isValid (s) && s->defstate == SS_HOFFA);
7462 bool sRef_isStateLive (sRef s)
7464 if (sRef_isValid (s))
7466 sstate ds = s->defstate;
7468 return (!(ds == SS_UNDEFINED
7470 || ds == SS_UNUSEABLE
7471 || ds == SS_HOFFA));
7480 bool sRef_isStateUndefined (sRef s)
7482 return ((sRef_isValid(s)) && ((s)->defstate == SS_UNDEFINED));
7485 bool sRef_isJustAllocated (sRef s)
7487 if (sRef_isAllocated (s))
7489 sRefSet_allElements (s->deriv, el)
7491 if (!(sRef_isStateUndefined (el) || sRef_isUnuseable (el)))
7495 } end_sRefSet_allElements ;
7504 sRef_isAllocatedStorage (sRef s)
7506 if (sRef_isValid (s) && ynm_toBoolStrict (sRef_isReadable (s)))
7508 return (ctype_isVisiblySharable (sRef_getType (s)));
7517 sRef_isUnuseable (sRef s)
7519 return ((sRef_isValid(s)) && ((s)->defstate == SS_UNUSEABLE));
7523 sRef_perhapsNull (sRef s)
7525 if (sRef_isValid (s))
7527 if (s->nullstate == NS_ABSNULL)
7529 ctype rct = ctype_realType (s->type);
7531 if (ctype_isAbstract (rct))
7537 if (ctype_isUser (rct))
7539 uentry ue = usymtab_getTypeEntry (ctype_typeId (rct));
7541 return (nstate_perhapsNull
7542 (sRef_getNullState (uentry_getSref (ue))));
7552 return nstate_perhapsNull (s->nullstate);
7560 ** definitelyNull --- called when TRUE is good
7564 sRef_definitelyNull (sRef s)
7566 return (sRef_isValid (s)
7567 && (s->nullstate == NS_DEFNULL || s->nullstate == NS_CONSTNULL));
7571 ** based on sRef_similar
7575 sRef_setDerivNullState (sRef set, sRef guide, nstate ns)
7577 if (sRef_isValid (set))
7579 sRef deriv = sRef_getDeriv (set, guide);
7581 if (sRef_isValid (deriv))
7583 deriv->nullstate = ns;
7588 static /*@exposed@*/ sRef
7589 sRef_getDeriv (/*@returned@*/ /*@notnull@*/ sRef set, sRef guide)
7591 llassert (sRef_isValid (set));
7592 llassert (sRef_isValid (guide));
7594 switch (guide->kind)
7597 llassert (set->kind == SK_CVAR);
7602 llassert (set->kind == guide->kind);
7603 llassert (set->info->paramno == guide->info->paramno);
7609 if (set->kind == SK_ARRAYFETCH
7610 && (sRef_similar (set->info->arrayfetch->arr,
7611 guide->info->arrayfetch->arr)))
7617 return (sRef_makeAnyArrayFetch
7618 (sRef_getDeriv (set, guide->info->arrayfetch->arr)));
7623 if (set->kind == SK_PTR && sRef_similar (set->info->ref, guide->info->ref))
7629 return (sRef_makePointer (sRef_getDeriv (set, guide->info->ref)));
7634 if ((set->kind == SK_FIELD &&
7635 (sRef_similar (set->info->field->rec, guide->info->field->rec) &&
7636 cstring_equal (set->info->field->field, guide->info->field->field))))
7642 return (sRef_makeField (sRef_getDeriv (set, guide->info->field->rec),
7643 guide->info->field->field));
7647 if ((set->kind == SK_ADR) && sRef_similar (set->info->ref, guide->info->ref))
7653 return (sRef_makeAddress (sRef_getDeriv (set, guide->info->ref)));
7658 return sRef_undefined;
7662 case SK_UNCONSTRAINED:
7670 return sRef_undefined;
7677 ** sRef_aliasCheckPred
7679 ** A confusing but spiffy function:
7681 ** Calls predf (s, e, text, <alias>) on s and all of s's aliases
7682 ** (unless checkAliases (s) is FALSE).
7684 ** For alias calls, calls as
7685 ** predf (alias, e, text, s)
7689 sRef_aliasCheckPred (bool (predf) (sRef, exprNode, sRef, exprNode),
7690 /*@null@*/ bool (checkAliases) (sRef),
7691 sRef s, exprNode e, exprNode err)
7693 bool error = (*predf)(s, e, sRef_undefined, err);
7696 if (checkAliases != NULL && !(checkAliases (s)))
7698 /* don't check aliases */
7702 sRefSet aliases = usymtab_allAliases (s);
7705 sRefSet_realElements (aliases, current)
7707 if (sRef_isValid (current))
7709 if (!sRef_similar (current, s)
7710 || (error && sRef_sameName (current, s)))
7712 (void) (*predf)(current, e, s, err);
7715 } end_sRefSet_realElements;
7717 sRefSet_free (aliases);
7722 ** return TRUE iff predf (s) is true for s or any alias of s
7726 sRef_aliasCheckSimplePred (sRefTest predf, sRef s)
7737 aliases = usymtab_allAliases (s);
7739 sRefSet_realElements (aliases, current)
7741 if (sRef_isValid (current))
7743 sRef cref = sRef_updateSref (current);
7745 /* Whoa! a very kludgey way to make sure the right sref is used
7746 ** where there is a conditional symbol table. I am beginning
7747 ** to think that having a conditional symbol table wasn't such
7754 sRefSet_free (aliases);
7758 } end_sRefSet_realElements;
7760 sRefSet_free (aliases);
7766 sRef_aliasCompleteSimplePred (bool (predf) (sRef), sRef s)
7769 bool result = FALSE;
7772 aliases = usymtab_allAliases (s);
7774 if ((*predf)(s)) result = TRUE;
7777 sRefSet_realElements (aliases, current)
7779 if (sRef_isValid (current))
7781 current = sRef_updateSref (current);
7782 if ((*predf)(current)) result = TRUE;
7784 } end_sRefSet_realElements;
7786 sRefSet_free (aliases);
7791 sRef_aliasSetComplete (void (predf) (sRef, fileloc), sRef s, fileloc loc)
7795 aliases = usymtab_allAliases (s);
7799 sRefSet_realElements (aliases, current)
7801 if (sRef_isValid (current))
7803 current = sRef_updateSref (current);
7804 ((*predf)(current, loc));
7806 } end_sRefSet_realElements;
7808 sRefSet_free (aliases);
7812 sRef_aliasSetCompleteParam (void (predf) (sRef, alkind, fileloc), sRef s,
7813 alkind kind, fileloc loc)
7818 if (sRef_isDeep (s))
7820 aliases = usymtab_allAliases (s);
7824 aliases = usymtab_aliasedBy (s);
7827 (*predf)(s, kind, loc);
7829 sRefSet_realElements (aliases, current)
7831 if (sRef_isValid (current))
7833 current = sRef_updateSref (current);
7834 ((*predf)(current, kind, loc));
7836 } end_sRefSet_realElements;
7838 sRefSet_free (aliases);
7842 sRef_innerAliasSetComplete (void (predf) (sRef, fileloc), sRef s, fileloc loc)
7848 if (!sRef_isValid (s)) return;
7852 ** Type equivalence checking is necessary --- there might be casting.
7859 case SK_UNCONSTRAINED:
7864 inner = s->info->ref;
7865 aliases = usymtab_allAliases (inner);
7866 ct = sRef_getType (inner);
7869 sRefSet_realElements (aliases, current)
7871 if (sRef_isValid (current))
7873 current = sRef_updateSref (current);
7875 if (ctype_equal (ct, sRef_getType (current)))
7877 sRef ptr = sRef_makePointer (current);
7879 ((*predf)(ptr, loc));
7882 } end_sRefSet_realElements;
7884 sRefSet_free (aliases);
7887 inner = s->info->arrayfetch->arr;
7888 aliases = usymtab_allAliases (inner);
7889 ct = sRef_getType (inner);
7891 sRefSet_realElements (aliases, current)
7893 if (sRef_isValid (current))
7895 current = sRef_updateSref (current);
7897 if (ctype_equal (ct, sRef_getType (current)))
7900 if (s->info->arrayfetch->indknown)
7902 sRef af = sRef_makeArrayFetchKnown (current, s->info->arrayfetch->ind);
7904 ((*predf)(af, loc));
7908 sRef af = sRef_makeArrayFetch (current);
7910 ((*predf)(af, loc));
7914 } end_sRefSet_realElements;
7916 sRefSet_free (aliases);
7919 inner = s->info->field->rec;
7920 aliases = usymtab_allAliases (inner);
7921 ct = sRef_getType (inner);
7924 sRefSet_realElements (aliases, current)
7926 if (sRef_isValid (current))
7928 current = sRef_updateSref (current);
7930 if (ctype_equal (ct, sRef_getType (current)))
7932 sRef f = sRef_makeField (current, s->info->field->field);
7937 } end_sRefSet_realElements;
7939 sRefSet_free (aliases);
7942 sRef_innerAliasSetComplete (predf, s->info->conj->a, loc);
7943 sRef_innerAliasSetComplete (predf, s->info->conj->b, loc);
7960 sRef_innerAliasSetCompleteParam (void (predf) (sRef, sRef), sRef s, sRef t)
7966 if (!sRef_isValid (s)) return;
7970 ** Type equivalence checking is necessary --- there might be casting.
7977 case SK_UNCONSTRAINED:
7982 inner = s->info->ref;
7983 aliases = usymtab_allAliases (inner);
7984 ct = sRef_getType (inner);
7987 sRefSet_realElements (aliases, current)
7989 if (sRef_isValid (current))
7991 current = sRef_updateSref (current);
7993 if (ctype_equal (ct, sRef_getType (current)))
7995 sRef ptr = sRef_makePointer (current);
8000 } end_sRefSet_realElements;
8002 sRefSet_free (aliases);
8005 inner = s->info->arrayfetch->arr;
8006 aliases = usymtab_allAliases (inner);
8007 ct = sRef_getType (inner);
8009 sRefSet_realElements (aliases, current)
8011 if (sRef_isValid (current))
8013 current = sRef_updateSref (current);
8015 if (ctype_equal (ct, sRef_getType (current)))
8018 if (s->info->arrayfetch->indknown)
8020 sRef af = sRef_makeArrayFetchKnown (current, s->info->arrayfetch->ind);
8026 sRef af = sRef_makeArrayFetch (current);
8032 } end_sRefSet_realElements;
8034 sRefSet_free (aliases);
8037 inner = s->info->field->rec;
8038 aliases = usymtab_allAliases (inner);
8039 ct = sRef_getType (inner);
8042 sRefSet_realElements (aliases, current)
8044 if (sRef_isValid (current))
8046 current = sRef_updateSref (current);
8048 if (ctype_equal (ct, sRef_getType (current)))
8050 sRef f = sRef_makeField (current, s->info->field->field);
8055 } end_sRefSet_realElements;
8057 sRefSet_free (aliases);
8060 sRef_innerAliasSetCompleteParam (predf, s->info->conj->a, t);
8061 sRef_innerAliasSetCompleteParam (predf, s->info->conj->b, t);
8077 static void sRef_combineExKinds (/*@notnull@*/ sRef res, /*@notnull@*/ sRef other)
8079 exkind a1 = sRef_getExKind (res);
8080 exkind a2 = sRef_getExKind (other);
8082 if (a1 == a2 || a2 == XO_UNKNOWN)
8086 else if (a1 == XO_UNKNOWN)
8088 res->expinfo = alinfo_update (res->expinfo, other->expinfo);
8093 res->expkind = XO_OBSERVER;
8098 ** Currently, this is a very ad hoc implementation, with lots of fixes to
8099 ** make real code work okay. I need to come up with some more general
8100 ** rules or principles here.
8104 sRef_combineAliasKindsError (/*@notnull@*/ sRef res,
8105 /*@notnull@*/ sRef other,
8106 clause cl, fileloc loc)
8108 bool hasError = FALSE;
8109 alkind ares = sRef_getAliasKind (res);
8110 alkind aother = sRef_getAliasKind (other);
8112 if (alkind_isDependent (ares))
8114 if (aother == AK_KEPT)
8116 res->aliasinfo = alinfo_update (res->aliasinfo, other->aliasinfo);
8117 res->aliaskind = AK_KEPT;
8121 if (aother == AK_LOCAL || aother == AK_STATIC
8122 || alkind_isTemp (aother))
8124 res->aliaskind = AK_DEPENDENT;
8128 else if (alkind_isDependent (aother))
8130 if (ares == AK_KEPT)
8132 res->aliaskind = AK_KEPT;
8136 if (ares == AK_LOCAL || ares == AK_STATIC || alkind_isTemp (ares))
8138 res->aliasinfo = alinfo_update (res->aliasinfo, other->aliasinfo);
8139 res->aliaskind = AK_DEPENDENT;
8143 else if ((ares == AK_LOCAL || ares == AK_UNIQUE
8144 || ares == AK_STATIC || alkind_isTemp (ares))
8145 && sRef_isFresh (other))
8148 ** cases like: if (s == NULL) s = malloc...;
8149 ** don't generate errors
8152 if (usymtab_isAltProbablyDeepNull (res))
8154 res->aliaskind = ares;
8161 else if ((aother == AK_LOCAL || aother == AK_UNIQUE
8162 || aother == AK_STATIC || alkind_isTemp (aother))
8163 && sRef_isFresh (res))
8166 ** cases like: if (s == NULL) s = malloc...;
8167 ** don't generate errors
8170 if (usymtab_isProbableDeepNull (other))
8172 res->aliasinfo = alinfo_update (res->aliasinfo, other->aliasinfo);
8173 res->aliaskind = aother;
8180 else if (ares == AK_NEWREF && aother == AK_REFCOUNTED
8181 && sRef_isConst (other))
8183 res->aliaskind = AK_NEWREF;
8185 else if (aother == AK_NEWREF && ares == AK_REFCOUNTED
8186 && sRef_isConst (res))
8188 res->aliasinfo = alinfo_update (res->aliasinfo, other->aliasinfo);
8189 res->aliaskind = AK_NEWREF;
8191 else if (sRef_isLocalVar (res)
8192 && ((ares == AK_KEPT && aother == AK_LOCAL)
8193 || (aother == AK_KEPT && ares == AK_LOCAL)))
8195 res->aliaskind = AK_KEPT;
8204 if (sRef_isThroughArrayFetch (res))
8207 (FLG_BRANCHSTATE, FLG_STRICTBRANCHSTATE,
8209 ("Clauses exit with %q possibly referencing %s storage %s, "
8212 alkind_unparse (aother),
8213 clause_nameTaken (cl),
8214 alkind_unparse (ares),
8215 clause_nameAlternate (cl)),
8218 sRef_showAliasInfo (res);
8219 sRef_showAliasInfo (other);
8220 res->aliaskind = AK_ERROR;
8224 if (ares == AK_KEPT || aother == AK_KEPT)
8226 sRef_maybeKill (res, loc);
8234 message ("Clauses exit with %q referencing %s storage %s, "
8237 alkind_unparse (aother),
8238 clause_nameTaken (cl),
8239 alkind_unparse (ares),
8240 clause_nameAlternate (cl)),
8243 sRef_showAliasInfo (res);
8244 sRef_showAliasInfo (other);
8246 res->aliaskind = AK_ERROR;
8250 res->aliaskind = (sRef_isLocalVar (res) ? AK_LOCAL : AK_UNKNOWN);
8255 sRef_combineAliasKinds (/*@notnull@*/ sRef res, /*@notnull@*/ sRef other,
8256 clause cl, fileloc loc)
8258 alkind ares = sRef_getAliasKind (res);
8259 alkind aother = sRef_getAliasKind (other);
8261 if (alkind_equal (ares, aother)
8262 || aother == AK_UNKNOWN
8263 || aother == AK_ERROR)
8265 ; /* keep current state */
8267 else if (sRef_isDead (res) || sRef_isDead (other))
8269 /* dead error reported (or storage is dead) */
8270 res ->aliaskind = AK_ERROR;
8272 else if (ares == AK_UNKNOWN || ares == AK_ERROR
8273 || sRef_isStateUndefined (res))
8275 res->aliasinfo = alinfo_update (res->aliasinfo, other->aliasinfo);
8276 res->aliaskind = aother;
8278 else if (sRef_isStateUndefined (other))
8282 else if (((ares == AK_UNIQUE || alkind_isTemp (ares))
8283 && aother == AK_LOCAL)
8284 || ((aother == AK_UNIQUE || alkind_isTemp (aother))
8285 && ares == AK_LOCAL))
8287 if (ares != AK_LOCAL)
8289 res->aliasinfo = alinfo_update (res->aliasinfo, other->aliasinfo);
8292 res->aliaskind = AK_LOCAL;
8294 else if ((ares == AK_OWNED && aother == AK_FRESH)
8295 || (aother == AK_OWNED && ares == AK_FRESH))
8297 if (ares != AK_FRESH)
8299 res->aliasinfo = alinfo_update (res->aliasinfo, other->aliasinfo);
8302 res->aliaskind = AK_FRESH;
8304 else if ((ares == AK_KEEP && aother == AK_FRESH) ||
8305 (aother == AK_KEEP && ares == AK_FRESH))
8307 if (ares != AK_KEEP)
8309 res->aliasinfo = alinfo_update (res->aliasinfo, other->aliasinfo);
8312 res->aliaskind = AK_KEEP;
8314 else if ((ares == AK_LOCAL && aother == AK_STACK) ||
8315 (aother == AK_LOCAL && ares == AK_STACK))
8317 if (ares != AK_STACK)
8319 res->aliasinfo = alinfo_update (res->aliasinfo, other->aliasinfo);
8322 res->aliaskind = AK_STACK;
8324 else if ((ares == AK_LOCAL
8325 && (aother == AK_OWNED && sRef_isLocalVar (other)))
8326 || (aother == AK_LOCAL
8327 && (ares == AK_OWNED && sRef_isLocalVar (res))))
8329 if (ares != AK_LOCAL)
8331 res->aliasinfo = alinfo_update (res->aliasinfo, other->aliasinfo);
8334 res->aliaskind = AK_LOCAL;
8336 else if ((ares == AK_FRESH && alkind_isOnly (aother))
8337 || (aother == AK_FRESH && alkind_isOnly (ares)))
8339 res->aliaskind = AK_FRESH;
8341 else if ((aother == AK_FRESH && sRef_definitelyNull (res))
8342 || (ares == AK_FRESH && sRef_definitelyNull (other)))
8344 if (ares != AK_FRESH)
8346 res->aliasinfo = alinfo_update (res->aliasinfo, other->aliasinfo);
8347 res->aliaskind = AK_FRESH;
8350 else if ((sRef_isFresh (res) && sRef_isConst (other))
8351 || (sRef_isFresh (other) && sRef_isConst (res)))
8354 ** for NULL constantants
8358 if (!sRef_isFresh (res))
8360 res->aliasinfo = alinfo_update (res->aliasinfo, other->aliasinfo);
8363 res->aliaskind = AK_FRESH;
8365 else if ((alkind_isStatic (aother) && sRef_isConst (res))
8366 || (alkind_isStatic (ares) && sRef_isConst (other)))
8368 if (!alkind_isStatic (ares))
8370 res->aliasinfo = alinfo_update (res->aliasinfo, other->aliasinfo);
8371 res->aliaskind = AK_STATIC;
8376 sRef_combineAliasKindsError (res, other, cl, loc);
8380 static void sRef_combineDefState (/*@notnull@*/ sRef res,
8381 /*@notnull@*/ sRef other)
8383 sstate s1 = res->defstate;
8384 sstate s2 = other->defstate;
8387 if (s1 == s2 || s2 == SS_UNKNOWN)
8391 else if (s1 == SS_UNKNOWN)
8400 if (s2 == SS_DEFINED)
8406 llcontbuglit ("ssfixed: not implemented");
8415 flip = (s2 != SS_DEFINED);
8433 res->definfo = alinfo_update (res->definfo, other->definfo);
8438 extern /*@notnull@*/ sRef sRef_getConjA (sRef s)
8441 llassert (sRef_isConj (s));
8443 ret = s->info->conj->a;
8444 llassert (ret != NULL);
8448 extern /*@notnull@*/ sRef sRef_getConjB (sRef s)
8451 llassert (sRef_isConj (s));
8453 ret = s->info->conj->b;
8454 llassert (ret != NULL);
8458 extern /*@exposed@*/ sRef sRef_makeArrow (sRef s, /*@dependent@*/ cstring f)
8463 p = sRef_makePointer (s);
8464 ret = sRef_makeField (p, f);
8468 extern /*@exposed@*/ sRef sRef_buildArrow (sRef s, cstring f)
8473 p = sRef_buildPointer (s);
8474 ret = sRef_buildField (p, f);
8479 static /*@null@*/ sinfo sinfo_copy (/*@notnull@*/ sRef s)
8486 ret = (sinfo) dmalloc (sizeof (*ret));
8487 ret->cvar = (cref) dmalloc (sizeof (*ret->cvar));
8488 ret->cvar->lexlevel = s->info->cvar->lexlevel;
8489 ret->cvar->index = s->info->cvar->index;
8493 ret = (sinfo) dmalloc (sizeof (*ret));
8494 ret->paramno = s->info->paramno;
8498 ret = (sinfo) dmalloc (sizeof (*ret));
8499 ret->arrayfetch = (ainfo) dmalloc (sizeof (*ret->arrayfetch));
8500 ret->arrayfetch->indknown = s->info->arrayfetch->indknown;
8501 ret->arrayfetch->ind = s->info->arrayfetch->ind;
8502 ret->arrayfetch->arr = s->info->arrayfetch->arr;
8506 ret = (sinfo) dmalloc (sizeof (*ret));
8507 ret->field = (fldinfo) dmalloc (sizeof (*ret->field));
8508 ret->field->rec = s->info->field->rec;
8509 ret->field->field = s->info->field->field;
8513 ret = (sinfo) dmalloc (sizeof (*ret));
8514 ret->object = s->info->object;
8521 ret = (sinfo) dmalloc (sizeof (*ret));
8522 ret->ref = s->info->ref;
8526 ret = (sinfo) dmalloc (sizeof (*ret));
8527 ret->conj = (cjinfo) dmalloc (sizeof (*ret->conj));
8528 ret->conj->a = s->info->conj->a;
8529 ret->conj->b = s->info->conj->b;
8532 ret = (sinfo) dmalloc (sizeof (*ret));
8533 ret->spec = s->info->spec;
8535 case SK_UNCONSTRAINED:
8537 ret = (sinfo) dmalloc (sizeof (*ret));
8538 ret->fname = s->info->fname;
8544 llassertprint (s->info == NULL, ("s = %s", sRef_unparse (s)));
8552 static /*@null@*/ sinfo sinfo_fullCopy (/*@notnull@*/ sRef s)
8557 ** Since its a full copy, only storage is assigned
8558 ** to dependent fields.
8565 ret = (sinfo) dmalloc (sizeof (*ret));
8566 ret->cvar = (cref) dmalloc (sizeof (*ret->cvar));
8567 ret->cvar->lexlevel = s->info->cvar->lexlevel;
8568 ret->cvar->index = s->info->cvar->index;
8572 ret = (sinfo) dmalloc (sizeof (*ret));
8573 ret->paramno = s->info->paramno;
8577 ret = (sinfo) dmalloc (sizeof (*ret));
8578 ret->arrayfetch = (ainfo) dmalloc (sizeof (*ret->arrayfetch));
8579 ret->arrayfetch->indknown = s->info->arrayfetch->indknown;
8580 ret->arrayfetch->ind = s->info->arrayfetch->ind;
8581 ret->arrayfetch->arr = sRef_saveCopy (s->info->arrayfetch->arr);
8585 ret = (sinfo) dmalloc (sizeof (*ret));
8586 ret->field = (fldinfo) dmalloc (sizeof (*ret->field));
8587 ret->field->rec = sRef_saveCopy (s->info->field->rec);
8588 ret->field->field = s->info->field->field;
8592 ret = (sinfo) dmalloc (sizeof (*ret));
8593 ret->object = s->info->object;
8600 ret = (sinfo) dmalloc (sizeof (*ret));
8601 ret->ref = sRef_saveCopy (s->info->ref);
8605 ret = (sinfo) dmalloc (sizeof (*ret));
8606 ret->conj = (cjinfo) dmalloc (sizeof (*ret->conj));
8607 ret->conj->a = sRef_saveCopy (s->info->conj->a);
8608 ret->conj->b = sRef_saveCopy (s->info->conj->b);
8611 ret = (sinfo) dmalloc (sizeof (*ret));
8612 ret->spec = s->info->spec;
8615 case SK_UNCONSTRAINED:
8616 ret = (sinfo) dmalloc (sizeof (*ret));
8617 ret->fname = s->info->fname;
8623 llassert (s->info == NULL);
8633 sinfo_update (/*@notnull@*/ /*@exposed@*/ sRef res,
8634 /*@notnull@*/ /*@exposed@*/ sRef other)
8636 llassert (res->kind == other->kind);
8641 res->info->cvar->lexlevel = other->info->cvar->lexlevel;
8642 res->info->cvar->index = other->info->cvar->index;
8646 res->info->paramno = other->info->paramno;
8650 res->info->arrayfetch->indknown = other->info->arrayfetch->indknown;
8651 res->info->arrayfetch->ind = other->info->arrayfetch->ind;
8652 res->info->arrayfetch->arr = other->info->arrayfetch->arr;
8656 res->info->field->rec = other->info->field->rec;
8657 res->info->field->field = other->info->field->field;
8661 res->info->object = other->info->object;
8668 res->info->ref = other->info->ref;
8672 res->info->conj->a = other->info->conj->a;
8673 res->info->conj->b = other->info->conj->b;
8677 res->info->spec = other->info->spec;
8681 case SK_UNCONSTRAINED:
8682 res->info->fname = other->info->fname;
8689 llassert (res->info == NULL);
8694 static void sinfo_free (/*@special@*/ /*@temp@*/ /*@notnull@*/ sRef s)
8695 /*@uses s->kind, s->info@*/
8696 /*@releases s->info@*/
8701 sfree (s->info->cvar);
8708 sfree (s->info->arrayfetch);
8712 sfree (s->info->field);
8725 sfree (s->info->conj);
8728 case SK_UNCONSTRAINED:
8741 bool sRef_isNSLocalVar (sRef s)
8743 if (sRef_isLocalVar (s))
8745 uentry ue = sRef_getUentry (s);
8747 return (!uentry_isStatic (ue));
8755 bool sRef_isLocalVar (sRef s)
8757 if (sRef_isValid(s))
8759 return (s->kind == SK_CVAR
8760 && (s->info->cvar->lexlevel > fileScope));
8766 bool sRef_isRealLocalVar (sRef s)
8768 if (sRef_isValid(s))
8770 if (s->kind == SK_CVAR)
8772 if (s->info->cvar->lexlevel == functionScope)
8774 uentry ue = sRef_getUentry (s);
8776 if (uentry_isAnyParam (ue)
8777 || uentry_isRefParam (ue))
8788 return (s->info->cvar->lexlevel > functionScope);
8796 bool sRef_isLocalParamVar (sRef s)
8798 if (sRef_isValid(s))
8800 return (s->kind == SK_PARAM
8801 || (s->kind == SK_CVAR
8802 && (s->info->cvar->lexlevel > fileScope)));
8808 static speckind speckind_fromInt (int i)
8811 llassert (i >= SR_NOTHING && i <= SR_SYSTEM);
8814 return ((speckind) i);
8817 void sRef_combineNullState (/*@notnull@*/ sRef res, /*@notnull@*/ sRef other)
8819 nstate n1 = res->nullstate;
8820 nstate n2 = other->nullstate;
8824 if (n1 == n2 || n2 == NS_UNKNOWN)
8830 /* note: n2 is not unknown or defnull */
8834 case NS_ERROR: nn = NS_ERROR; break;
8835 case NS_UNKNOWN: flip = TRUE; nn = n2; break;
8836 case NS_POSNULL: break;
8837 case NS_DEFNULL: nn = NS_POSNULL; break;
8838 case NS_RELNULL: break;
8840 if (n2 == NS_MNOTNULL)
8851 if (n2 == NS_NOTNULL)
8870 res->nullinfo = alinfo_update (res->nullinfo, other->nullinfo);
8873 res->nullstate = nn;
8876 cstring sRef_nullMessage (sRef s)
8878 llassert (sRef_isValid (s));
8880 switch (s->nullstate)
8884 return (cstring_makeLiteralTemp ("null"));
8886 return (cstring_makeLiteralTemp ("possibly null"));
8891 /*@observer@*/ cstring sRef_ntMessage (sRef s)
8893 llassert (sRef_isValid (s));
8895 switch (s->nullstate)
8899 return (cstring_makeLiteralTemp ("not nullterminated"));
8901 return (cstring_makeLiteralTemp ("possibly non-nullterminated"));
8908 sRef sRef_fixResultType (/*@returned@*/ sRef s, ctype typ, uentry ue)
8910 sRef tmp = sRef_undefined;
8913 llassert (sRef_isValid (s));
8924 tmp = sRef_fixResultType (s->info->arrayfetch->arr, typ, ue);
8926 ct = ctype_realType (sRef_getType (tmp));
8929 if (ctype_isKnown (ct))
8931 if (ctype_isAP (ct))
8940 ("Special clause indexes non-array (%t): *%q",
8941 ct, sRef_unparse (s->info->arrayfetch->arr)),
8942 uentry_whereLast (ue));
8946 tmp = sRef_fixResultType (s->info->arrayfetch->arr, typ, ue);
8948 if (s->info->arrayfetch->indknown)
8950 ret = sRef_makeArrayFetchKnown (tmp, s->info->arrayfetch->ind);
8954 ret = sRef_makeArrayFetch (tmp);
8960 sRef rec = sRef_fixResultType (s->info->field->rec, typ, ue);
8961 ctype ct = ctype_realType (sRef_getType (rec));
8963 if (ctype_isKnown (ct))
8965 if (ctype_isSU (ct))
8967 if (uentry_isValid (uentryList_lookupField (ctype_getFields (ct),
8968 s->info->field->field)))
8977 ("Special clause accesses non-existent field of result: %q.%s",
8978 sRef_unparse (rec), s->info->field->field),
8979 uentry_whereLast (ue));
8987 ("Special clause accesses field of non-struct or union result (%t): %q.%s",
8988 ct, sRef_unparse (rec), s->info->field->field),
8989 uentry_whereLast (ue));
8993 ret = sRef_makeField (tmp, s->info->field->field);
8999 tmp = sRef_fixResultType (s->info->ref, typ, ue);
9001 ct = ctype_realType (sRef_getType (tmp));
9003 if (ctype_isKnown (ct))
9005 if (ctype_isAP (ct))
9014 ("Special clause dereferences non-pointer (%t): *%q",
9015 ct, sRef_unparse (s->info->ref)),
9016 uentry_whereLast (ue));
9020 ret = sRef_makePointer (tmp);
9027 ("Special clause uses & operator (not allowed): &%q", sRef_unparse (s->info->ref)),
9028 uentry_whereLast (ue));
9037 bool sRef_isOnly (sRef s)
9039 return (sRef_isValid(s) && alkind_isOnly (s->aliaskind));
9042 bool sRef_isDependent (sRef s)
9044 return (sRef_isValid(s) && alkind_isDependent (s->aliaskind));
9047 bool sRef_isOwned (sRef s)
9049 return (sRef_isValid (s) && (s->aliaskind == AK_OWNED));
9052 bool sRef_isKeep (sRef s)
9054 return (sRef_isValid (s) && (s->aliaskind == AK_KEEP));
9057 bool sRef_isTemp (sRef s)
9059 return (sRef_isValid (s) && alkind_isTemp (s->aliaskind));
9062 bool sRef_isLocalState (sRef s)
9064 return (sRef_isValid (s) && (s->aliaskind == AK_LOCAL));
9067 bool sRef_isUnique (sRef s)
9069 return (sRef_isValid (s) && (s->aliaskind == AK_UNIQUE));
9072 bool sRef_isShared (sRef s)
9074 return (sRef_isValid (s) && (s->aliaskind == AK_SHARED));
9077 bool sRef_isExposed (sRef s)
9079 return (sRef_isValid (s) && (s->expkind == XO_EXPOSED));
9082 bool sRef_isObserver (sRef s)
9084 return (sRef_isValid (s) && (s->expkind == XO_OBSERVER));
9087 bool sRef_isFresh (sRef s)
9089 return (sRef_isValid (s) && (s->aliaskind == AK_FRESH));
9092 bool sRef_isDefinitelyNull (sRef s)
9094 return (sRef_isValid (s) && (s->nullstate == NS_DEFNULL
9095 || s->nullstate == NS_CONSTNULL));
9098 bool sRef_isAllocated (sRef s)
9100 return (sRef_isValid (s) && (s->defstate == SS_ALLOCATED));
9103 bool sRef_isStack (sRef s)
9105 return (sRef_isValid (s) && (s->aliaskind == AK_STACK));
9108 extern bool sRef_isNotNull (sRef s)
9110 return (sRef_isValid(s) && (s->nullstate == NS_MNOTNULL
9111 || s->nullstate == NS_NOTNULL));
9114 /* start modifications */
9115 struct _bbufinfo sRef_getNullTerminatedState (sRef p_s) {
9116 struct _bbufinfo BUFSTATE_UNKNOWN;
9117 BUFSTATE_UNKNOWN.bufstate = BB_NOTNULLTERMINATED;
9118 BUFSTATE_UNKNOWN.size = 0;
9119 BUFSTATE_UNKNOWN.len = 0;
9121 if (sRef_isValid(p_s))
9122 return p_s->bufinfo;
9123 return BUFSTATE_UNKNOWN;
9126 void sRef_setNullTerminatedState(sRef p_s) {
9127 if(sRef_isValid (p_s)) {
9128 p_s->bufinfo.bufstate = BB_NULLTERMINATED;
9130 llfatalbug( message("sRef_setNT passed a invalid sRef\n"));
9135 void sRef_setPossiblyNullTerminatedState(sRef p_s) {
9136 if( sRef_isValid (p_s)) {
9137 p_s->bufinfo.bufstate = BB_POSSIBLYNULLTERMINATED;
9139 llfatalbug( message("sRef_setPossNT passed a invalid sRef\n"));
9143 void sRef_setNotNullTerminatedState(sRef p_s) {
9144 if( sRef_isValid (p_s)) {
9145 p_s->bufinfo.bufstate = BB_NOTNULLTERMINATED;
9147 llfatalbug( message("sRef_unsetNT passed a invalid sRef\n"));
9151 void sRef_setLen(sRef p_s, int len) {
9152 if( sRef_isValid (p_s) && sRef_isNullTerminated(p_s)) {
9153 p_s->bufinfo.len = len;
9155 llfatalbug( message("sRef_setLen passed a invalid sRef\n"));
9160 void sRef_setSize(sRef p_s, int size) {
9161 if( sRef_isValid(p_s)) {
9162 p_s->bufinfo.size = size;
9164 llfatalbug( message("sRef_setSize passed a invalid sRef\n"));
9168 void sRef_resetLen(sRef p_s) {
9169 if (sRef_isValid (p_s)) {
9170 p_s->bufinfo.len = 0;
9172 llfatalbug (message ("sRef_setLen passed an invalid sRef\n"));
9176 /*drl7x 11/28/2000 */
9178 bool sRef_isFixedArray (sRef p_s) /*@*/ {
9180 c = sRef_getType (p_s);
9181 return ( ctype_isFixedArray (c) );
9184 long int sRef_getArraySize (sRef p_s) /*@*/ {
9186 llassert (sRef_isFixedArray(p_s) );
9187 DPRINTF (( message ("sRef_getArraySize getting array size for %s", sRef_unparse(p_s) ) ));
9189 c = sRef_getType (p_s);
9191 return (ctype_getArraySize (c) );