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 constraintExpr sRef_fixConstraintParam ( sRef s, exprNodeList args)
2051 if (sRef_isInvalid (s))
2052 llfatalbug((message("Invalid sRef")));
2058 ce = constraintExpr_makeTermsRef (s);
2065 temp = (sRef_makeField (sRef_fixBaseParam (s->info->field->rec, args),
2066 s->info->field->field));
2067 ce = constraintExpr_makeTermsRef (temp);
2073 temp = (sRef_makePointer (sRef_fixBaseParam (s->info->ref, args)));
2074 ce = constraintExpr_makeTermsRef (temp);
2081 temp = sRef_fixBaseParam (s, args);
2082 ce = constraintExpr_makeTermsRef (temp);
2086 ce = constraintExpr_makeTermsRef (s);
2089 llassert(exprNodeList_size (args) > s->info->paramno);
2091 exprNode e = exprNodeList_nth (args, s->info->paramno);
2093 llassert( !(exprNode_isError (e)) );
2094 ce = constraintExpr_makeExprNode (e);
2099 llcontbug ((message("Trying to do fixConstraintParam on nonparam, nonglobal: %s for function with arguments %s", sRef_unparse (s), exprNodeList_unparse(args) ) ));
2100 ce = constraintExpr_makeTermsRef (s);
2109 sRef_fixBaseParam (/*@returned@*/ sRef s, exprNodeList args)
2111 if (sRef_isInvalid (s)) return (sRef_undefined);
2115 case SK_UNCONSTRAINED:
2120 if (exprNodeList_size (args) > s->info->paramno)
2122 exprNode e = exprNodeList_nth (args, s->info->paramno);
2124 if (exprNode_isError (e))
2126 return sRef_makeUnknown ();
2129 return (exprNode_getSref (e));
2133 return sRef_makeUnknown ();
2138 if (s->info->arrayfetch->indknown)
2140 return (sRef_makeArrayFetchKnown
2141 (sRef_fixBaseParam (s->info->arrayfetch->arr, args),
2142 s->info->arrayfetch->ind));
2146 return (sRef_makeArrayFetch
2147 (sRef_fixBaseParam (s->info->arrayfetch->arr, args)));
2150 return (sRef_makeField (sRef_fixBaseParam (s->info->field->rec, args),
2151 s->info->field->field));
2154 return (sRef_makePointer (sRef_fixBaseParam (s->info->ref, args)));
2157 return (sRef_makeAddress (sRef_fixBaseParam (s->info->ref, args)));
2160 return (sRef_makeConj (sRef_fixBaseParam (s->info->conj->a, args),
2161 sRef_fixBaseParam (s->info->conj->b, args)));
2177 sRef_undumpGlobal (char **c)
2187 usymId uid = usymId_fromInt (getInt (c));
2193 defstate = sstate_fromInt (getInt (c));
2196 nullstate = nstate_fromInt (getInt (c));
2198 ret = sRef_makeGlobal (uid, ctype_unknown);
2199 ret->nullstate = nullstate;
2200 ret->defstate = defstate;
2206 speckind sk = speckind_fromInt (i);
2210 case SR_NOTHING: return (sRef_makeNothing ());
2211 case SR_INTERNAL: return (sRef_makeInternalState ());
2212 case SR_SPECSTATE: return (sRef_makeSpecState ());
2213 case SR_SYSTEM: return (sRef_makeSystemState ());
2218 return sRef_undefined;
2220 return sRef_makeUnknown ();
2222 return sRef_makeUnknown ();
2224 llfatalerror (message ("sRef_undumpGlobal: bad line: %s",
2225 cstring_fromChars (*c)));
2231 sRef_undump (char **c)
2240 return (sRef_makeGlobal (usymId_fromInt (getInt (c)), ctype_unknown));
2242 return (sRef_makeParam (getInt (c), ctype_unknown));
2244 return (sRef_makeResultType (ctype_undump (c)));
2247 if ((**c >= '0' && **c <= '9') || **c == '-')
2250 sRef arr = sRef_undump (c);
2251 sRef ret = sRef_buildArrayFetchKnown (arr, i);
2257 sRef arr = sRef_undump (c);
2258 sRef ret = sRef_buildArrayFetch (arr);
2265 cstring fname = cstring_undefined;
2270 fname = cstring_appendChar (fname, **c);
2275 ret = sRef_buildField (sRef_undump (c), fname);
2276 cstring_markOwned (fname);
2282 speckind sk = speckind_fromInt (i);
2286 case SR_NOTHING: return (sRef_makeNothing ());
2287 case SR_INTERNAL: return (sRef_makeInternalState ());
2288 case SR_SPECSTATE: return (sRef_makeSpecState ());
2289 case SR_SYSTEM: return (sRef_makeSystemState ());
2295 sRef ptr = sRef_undump (c);
2296 sRef ret = sRef_makePointer (ptr);
2302 sRef adr = sRef_undump (c);
2303 sRef ret = sRef_makeAddress (adr);
2309 return (sRef_makeObject (ctype_undump (c)));
2313 sRef s1 = sRef_undump (c);
2314 sRef s2 = ((*c)++, sRef_undump (c));
2315 sRef ret = sRef_makeConj (s1, s2);
2320 return sRef_undefined;
2322 return sRef_makeUnknown ();
2324 return sRef_makeUnknown ();
2326 llfatalerror (message ("sRef_undump: bad line: %s", cstring_fromChars (*c)));
2334 if (sRef_isInvalid (s))
2336 return (cstring_makeLiteral ("-"));
2343 return (message ("p%d", s->info->paramno));
2345 if (s->info->arrayfetch->indknown)
2347 return (message ("a%d%q", s->info->arrayfetch->ind,
2348 sRef_dump (s->info->arrayfetch->arr)));
2352 return (message ("a%q", sRef_dump (s->info->arrayfetch->arr)));
2355 return (message ("f%s.%q", s->info->field->field,
2356 sRef_dump (s->info->field->rec)));
2358 return (message ("t%q", sRef_dump (s->info->ref)));
2360 return (message ("d%q", sRef_dump (s->info->ref)));
2362 return (message ("o%q", ctype_dump (s->info->object)));
2364 return (message ("s%d", (int) s->info->spec));
2366 return (message ("c%q.%q",
2367 sRef_dump (s->info->conj->a),
2368 sRef_dump (s->info->conj->b)));
2370 if (sRef_isGlobal (s))
2372 return (message ("g%d",
2373 usymtab_convertId (s->info->cvar->index)));
2377 llcontbug (message ("Dumping local variable: %q",
2378 sRef_unparseDebug (s)));
2379 return (cstring_makeLiteral ("u"));
2382 return (cstring_makeLiteral ("u"));
2384 return (message ("r%q", ctype_dump (s->type)));
2390 case SK_UNCONSTRAINED:
2391 llcontbug (message ("sRef_dump: bad kind: %q",
2392 sRef_unparseFull (s)));
2393 return (cstring_makeLiteral ("x"));
2400 cstring sRef_dumpGlobal (sRef s)
2402 if (sRef_isInvalid (s))
2404 return (cstring_makeLiteral ("-"));
2411 if (sRef_isGlobal (s))
2413 return (message ("g%d@%d@%d",
2414 usymtab_convertId (s->info->cvar->index),
2416 (int) s->nullstate));
2420 llcontbug (message ("Dumping local variable: %q",
2421 sRef_unparseDebug (s)));
2422 return (cstring_makeLiteral ("u"));
2425 return (cstring_makeLiteral ("u"));
2427 return (message ("s%d", (int) s->info->spec));
2429 llcontbug (message ("sRef_dumpGlobal: bad kind: %q",
2430 sRef_unparseFull (s)));
2431 return (cstring_makeLiteral ("x"));
2439 sRef_deriveType (sRef s, uentryList cl)
2441 if (sRef_isInvalid (s)) return ctype_unknown;
2446 return (uentry_getType (usymtab_getRefQuiet (s->info->cvar->lexlevel,
2447 s->info->cvar->index)));
2448 case SK_UNCONSTRAINED:
2449 return (ctype_unknown);
2451 return uentry_getType (uentryList_getN (cl, s->info->paramno));
2454 ctype ca = sRef_deriveType (s->info->arrayfetch->arr, cl);
2456 if (ctype_isArray (ca))
2458 return (ctype_baseArrayPtr (ca));
2460 else if (ctype_isUnknown (ca))
2466 llcontbuglit ("sRef_deriveType: inconsistent array type");
2472 ctype ct = sRef_deriveType (s->info->field->rec, cl);
2474 if (ctype_isStructorUnion (ct))
2476 uentry ue = uentryList_lookupField (ctype_getFields (ct),
2477 s->info->field->field);
2479 if (uentry_isValid (ue))
2481 return (uentry_getType (ue));
2485 llcontbuglit ("sRef_deriveType: bad field");
2486 return ctype_unknown;
2489 else if (ctype_isUnknown (ct))
2495 llcontbuglit ("sRef_deriveType: inconsistent field type");
2501 ctype ct = sRef_deriveType (s->info->ref, cl);
2503 if (ctype_isUnknown (ct)) return ct;
2504 if (ctype_isPointer (ct)) return (ctype_baseArrayPtr (ct));
2507 llcontbuglit ("sRef_deriveType: inconsistent pointer type");
2513 ctype ct = sRef_deriveType (s->info->ref, cl);
2515 if (ctype_isUnknown (ct)) return ct;
2516 return ctype_makePointer (ct);
2520 return sRef_deriveType (s->info->ref, cl);
2524 return (s->info->object);
2528 return (ctype_makeConj (sRef_deriveType (s->info->conj->a, cl),
2529 sRef_deriveType (s->info->conj->b, cl)));
2541 return ctype_unknown;
2547 sRef_getType (sRef s)
2549 if (sRef_isInvalid (s)) return ctype_unknown;
2555 sRef_unparseOpt (sRef s)
2557 sRef rb = sRef_getRootBase (s);
2559 if (sRef_isMeaningful (rb) && !sRef_isConst (rb))
2561 cstring ret = sRef_unparse (s);
2563 llassertprint (!cstring_equalLit (ret, "?"), ("print: %s", sRef_unparseDebug (s)));
2565 if (!cstring_isEmpty (ret))
2567 return (cstring_appendChar (ret, ' '));
2575 return cstring_undefined;
2579 sRef_unparsePreOpt (sRef s)
2581 sRef rb = sRef_getRootBase (s);
2583 if (sRef_isMeaningful (rb) && !sRef_isConst (rb))
2585 cstring ret = sRef_unparse (s);
2587 llassertprint (!cstring_equalLit (ret, "?"), ("print: %s", sRef_unparseDebug (s)));
2588 return (cstring_prependCharO (' ', ret));
2591 return cstring_undefined;
2595 sRef_unparse (sRef s)
2597 if (sRef_isInvalid (s)) return (cstring_makeLiteral ("?"));
2599 if (context_inFunctionLike ())
2601 return (sRef_unparseWithArgs (s, context_getParams ()));
2605 return (sRef_unparseNoArgs (s));
2609 static /*@only@*/ cstring
2610 sRef_unparseWithArgs (sRef s, uentryList args)
2612 if (sRef_isInvalid (s))
2614 return (cstring_makeLiteral ("?"));
2620 return (uentry_getName (usymtab_getRefQuiet (s->info->cvar->lexlevel,
2621 s->info->cvar->index)));
2622 case SK_UNCONSTRAINED:
2623 return (cstring_copy (s->info->fname));
2626 if (s->info->paramno < uentryList_size (args))
2628 uentry ue = uentryList_getN (args, s->info->paramno);
2630 if (uentry_isValid (ue))
2631 return uentry_getName (ue);
2634 return (message ("<bad param: %q / args %q",
2635 sRef_unparseDebug (s),
2636 uentryList_unparse (args)));
2639 if (s->info->arrayfetch->indknown)
2641 return (message ("%q[%d]", sRef_unparseWithArgs (s->info->arrayfetch->arr, args),
2642 s->info->arrayfetch->ind));
2646 return (message ("%q[]", sRef_unparseWithArgs (s->info->arrayfetch->arr, args)));
2649 if (s->info->field->rec->kind == SK_PTR)
2651 sRef ptr = s->info->field->rec;
2653 return (message ("%q->%s", sRef_unparseWithArgs (ptr->info->ref, args),
2654 s->info->field->field));
2656 return (message ("%q.%s", sRef_unparseWithArgs (s->info->field->rec, args),
2657 s->info->field->field));
2661 sRef ref = sRef_fixConj (s->info->ref);
2662 skind sk = ref->kind;
2667 ret = message ("storage pointed to by %q",
2668 sRef_unparseWithArgs (ref, args));
2670 else if (skind_isSimple (sk) || sk == SK_PTR)
2672 ret = message ("*%q", sRef_unparseWithArgs (ref, args));
2676 ret = message ("*(%q)", sRef_unparseWithArgs (ref, args));
2682 return (message ("&%q", sRef_unparseWithArgs (s->info->ref, args)));
2684 return (cstring_copy (ctype_unparse (s->info->object)));
2686 return (sRef_unparseWithArgs (sRef_getConjA (s), args));
2688 if (cstring_isDefined (s->info->fname))
2690 return (message ("[result of %s]", s->info->fname));
2694 return (cstring_makeLiteral ("<new>"));
2697 return (cstring_makeLiteral ("?"));
2699 return (message ("<derived %q>", sRef_unparse (s->info->ref)));
2701 return (message ("<external %q>", sRef_unparse (s->info->ref)));
2703 return (message ("<type %s>", ctype_unparse (s->type)));
2705 return (message ("<const %s>", ctype_unparse (s->type)));
2707 return (cstring_makeLiteral
2708 (s->info->spec == SR_NOTHING ? "nothing"
2709 : s->info->spec == SR_INTERNAL ? "internal state"
2710 : s->info->spec == SR_SPECSTATE ? "spec state"
2711 : s->info->spec == SR_SYSTEM ? "file system state"
2714 return cstring_makeLiteral ("result");
2717 llbug (message ("Bad sref, kind = %d", (int) s->kind));
2725 sRef_unparseDebug (sRef s)
2727 if (sRef_isInvalid (s)) return (cstring_makeLiteral ("<undef>"));
2731 case SK_UNCONSTRAINED:
2732 return (message ("<unconstrained %s>", s->info->fname));
2737 ce = usymtab_getRefQuiet (s->info->cvar->lexlevel, s->info->cvar->index);
2739 if (uentry_isInvalid (ce))
2741 return (message ("<scope: %d.%d *invalid*>",
2742 s->info->cvar->lexlevel,
2743 s->info->cvar->index));
2747 return (message ("<scope: %d.%d *%q*>",
2748 s->info->cvar->lexlevel,
2749 s->info->cvar->index,
2750 uentry_getName (ce)));
2756 return (message ("<parameter %d>", s->info->paramno + 1));
2759 if (s->info->arrayfetch->indknown)
2761 return (message ("%q[%d]", sRef_unparseDebug (s->info->arrayfetch->arr),
2762 s->info->arrayfetch->ind));
2766 return (message ("%q[]", sRef_unparseDebug (s->info->arrayfetch->arr)));
2769 return (message ("%q.%s", sRef_unparseDebug (s->info->field->rec),
2770 s->info->field->field));
2772 return (message ("*(%q)", sRef_unparseDebug (s->info->ref)));
2774 return (message ("&%q", sRef_unparseDebug (s->info->ref)));
2776 return (message ("<object type %s>", ctype_unparse (s->info->object)));
2778 return (message ("%q | %q", sRef_unparseDebug (s->info->conj->a),
2779 sRef_unparseDebug (s->info->conj->b)));
2781 return message ("<new: %s>", s->info->fname);
2783 return (message ("<derived %q>", sRef_unparseDebug (s->info->ref)));
2785 return (message ("<external %q>", sRef_unparseDebug (s->info->ref)));
2787 return (message ("<type %s>", ctype_unparse (s->type)));
2789 return (message ("<const %s>", ctype_unparse (s->type)));
2791 return (message ("<result %s>", ctype_unparse (s->type)));
2793 return (message ("<spec %s>",
2794 cstring_makeLiteralTemp
2795 (s->info->spec == SR_NOTHING ? "nothing"
2796 : s->info->spec == SR_INTERNAL ? "internalState"
2797 : s->info->spec == SR_SPECSTATE ? "spec state"
2798 : s->info->spec == SR_SYSTEM ? "fileSystem"
2801 return cstring_makeLiteral ("<unknown>");
2807 static /*@only@*/ cstring
2808 sRef_unparseNoArgs (sRef s)
2810 if (sRef_isInvalid (s)) return (cstring_makeLiteral ("?"));
2814 case SK_UNCONSTRAINED:
2815 return (cstring_copy (s->info->fname));
2818 uentry ce = usymtab_getRefQuiet (s->info->cvar->lexlevel,
2819 s->info->cvar->index);
2821 if (uentry_isInvalid (ce))
2823 llcontbug (message ("sRef_unparseNoArgs: bad cvar: %q", sRef_unparseDebug (s)));
2824 return (sRef_unparseDebug (s));
2828 return (uentry_getName (ce));
2832 if (s->info->arrayfetch->indknown)
2834 return (message ("%q[%d]", sRef_unparseNoArgs (s->info->arrayfetch->arr),
2835 s->info->arrayfetch->ind));
2839 return (message ("%q[]", sRef_unparseNoArgs (s->info->arrayfetch->arr)));
2842 return (message ("%q.%s", sRef_unparseNoArgs (s->info->field->rec),
2843 s->info->field->field));
2846 sRef ref = sRef_fixConj (s->info->ref);
2847 skind sk = ref->kind;
2850 if (skind_isSimple (sk) || sk == SK_PTR)
2852 ret = message ("*%q", sRef_unparseNoArgs (ref));
2856 ret = message ("*(%q)", sRef_unparseNoArgs (ref));
2862 return (message ("&%q", sRef_unparseNoArgs (s->info->ref)));
2864 return (cstring_copy (ctype_unparse (s->info->object)));
2866 return (sRef_unparseNoArgs (s->info->conj->a));
2868 return (message ("result of %s", s->info->fname));
2870 return (message ("<der %q>", sRef_unparseNoArgs (s->info->ref)));
2872 return message ("<ext %q>", sRef_unparseNoArgs (s->info->ref));
2874 return (cstring_makeLiteral
2875 (s->info->spec == SR_NOTHING ? "nothing"
2876 : s->info->spec == SR_INTERNAL ? "internal state"
2877 : s->info->spec == SR_SPECSTATE ? "spec state"
2878 : s->info->spec == SR_SYSTEM ? "file system state"
2881 return cstring_makeLiteral ("result");
2885 return cstring_makeLiteral ("?");
2887 /* llcontbug (message ("sRef_unparseNoArgs: bad case: %q", sRef_unparseDebug (s))); */
2888 return (sRef_unparseDebug (s));
2893 /*@dependent@*/ sRef sRef_makeUnconstrained (cstring fname)
2895 sRef s = sRef_new ();
2897 s->kind = SK_UNCONSTRAINED;
2898 s->info = (sinfo) dmalloc (sizeof (*s->info));
2899 s->info->fname = fname;
2904 cstring sRef_unconstrainedName (sRef s)
2906 llassert (sRef_isUnconstrained (s));
2908 return s->info->fname;
2911 bool sRef_isUnconstrained (sRef s)
2913 return (sRef_isValid(s) && s->kind == SK_UNCONSTRAINED);
2916 static /*@dependent@*/ /*@notnull@*/ sRef
2917 sRef_makeCvarAux (int level, usymId index, ctype ct)
2919 sRef s = sRef_new ();
2922 s->info = (sinfo) dmalloc (sizeof (*s->info));
2924 s->info->cvar = (cref) dmalloc (sizeof (*s->info->cvar));
2925 s->info->cvar->lexlevel = level;
2926 s->info->cvar->index = index;
2928 /* for now, all globals are defined; all locals, aren't */
2930 if (level <= fileScope)
2932 s->defstate = SS_UNKNOWN;
2936 ctype rct = ctype_realType (ct);
2938 if (level != paramsScope
2939 && (ctype_isStructorUnion (rct) || ctype_isRealArray (rct)))
2941 s->defstate = SS_ALLOCATED;
2942 s->oaliaskind = s->aliaskind = AK_STACK;
2946 s->defstate = SS_UNDEFINED;
2947 s->oaliaskind = s->aliaskind = AK_LOCAL;
2953 llassert (level >= globScope);
2954 llassert (usymId_isValid (index));
2959 /*@dependent@*/ sRef sRef_makeCvar (int level, usymId index, ctype ct)
2961 return (sRef_makeCvarAux (level, index, ct));
2964 int sRef_lexLevel (sRef s)
2966 if (sRef_isValid (s))
2970 conj = sRef_fixConj (s);
2971 s = sRef_getRootBase (conj);
2973 if (sRef_isValid (s) && s->kind == SK_CVAR)
2975 return (s->info->cvar->lexlevel);
2983 sRef_makeGlobal (usymId l, ctype ct)
2985 return (sRef_makeCvar (globScope, l, ct));
2989 sRef_setParamNo (sRef s, int l)
2991 llassert (sRef_isValid (s) && s->kind == SK_PARAM);
2992 s->info->paramno = l;
2995 /*@dependent@*/ sRef
2996 sRef_makeParam (int l, ctype ct)
2998 sRef s = sRef_new ();
3003 s->info = (sinfo) dmalloc (sizeof (*s->info));
3004 s->info->paramno = l;
3005 s->defstate = SS_UNKNOWN; /* (probably defined, unless its an out parameter) */
3011 sRef_isIndexKnown (sRef arr)
3015 llassert (sRef_isValid (arr));
3016 arr = sRef_fixConj (arr);
3018 llassert (arr->kind == SK_ARRAYFETCH);
3019 res = arr->info->arrayfetch->indknown;
3024 sRef_getIndex (sRef arr)
3028 llassert (sRef_isValid (arr));
3029 arr = sRef_fixConj (arr);
3031 llassert (arr->kind == SK_ARRAYFETCH);
3033 if (!arr->info->arrayfetch->indknown)
3035 llcontbug (message ("sRef_getIndex: unknown: %q", sRef_unparse (arr)));
3040 result = arr->info->arrayfetch->ind;
3046 static bool sRef_isZerothArrayFetch (/*@notnull@*/ sRef s)
3048 return (s->kind == SK_ARRAYFETCH
3049 && s->info->arrayfetch->indknown
3050 && (s->info->arrayfetch->ind == 0));
3053 /*@exposed@*/ sRef sRef_makeAddress (/*@exposed@*/ sRef t)
3056 if (sRef_isInvalid (t)) return sRef_undefined;
3058 if (sRef_isPointer (t))
3060 return (t->info->ref);
3062 else if (sRef_isZerothArrayFetch (t))
3064 return (t->info->arrayfetch->arr);
3068 sRef s = sRef_new ();
3071 s->type = ctype_makePointer (t->type);
3072 s->info = (sinfo) dmalloc (sizeof (*s->info));
3075 if (t->defstate == SS_UNDEFINED)
3076 /* no! it is allocated even still: && !ctype_isPointer (t->type)) */
3078 s->defstate = SS_ALLOCATED;
3082 s->defstate = t->defstate;
3085 if (t->aliaskind == AK_LOCAL)
3087 if (sRef_isLocalVar (t))
3089 s->aliaskind = AK_STACK;
3097 cstring sRef_getField (sRef s)
3101 llassert (sRef_isValid (s));
3102 s = sRef_fixConj (s);
3104 llassertprint (sRef_isValid (s) && (s->kind == SK_FIELD),
3105 ("s = %s", sRef_unparseDebug (s)));
3107 res = s->info->field->field;
3111 sRef sRef_getBase (sRef s)
3115 if (sRef_isInvalid (s)) return (sRef_undefined);
3117 s = sRef_fixConj (s);
3128 res = s->info->field->rec;
3132 res = s->info->arrayfetch->arr;
3136 res = sRef_undefined; /* shouldn't need it */
3143 ** same as getBase, except returns invalid
3144 ** (and doesn't use adr's)
3148 sRef_getBaseSafe (sRef s)
3152 if (sRef_isInvalid (s)) { return sRef_undefined; }
3154 s = sRef_fixConj (s);
3162 res = s->info->field->rec; break;
3164 res = s->info->arrayfetch->arr;
3167 res = sRef_undefined; break;
3173 /*@constant int MAXBASEDEPTH;@*/
3174 # define MAXBASEDEPTH 25
3176 static /*@exposed@*/ sRef
3177 sRef_getRootBaseAux (sRef s, int depth)
3179 if (sRef_isInvalid (s)) return sRef_undefined;
3181 if (depth > MAXBASEDEPTH)
3184 ("Warning: reference base limit exceeded for %q. "
3185 "This either means there is a variable with at least "
3186 "%d indirections from this reference, or "
3187 "there is a bug in LCLint.",
3192 return sRef_undefined;
3199 return (sRef_getRootBaseAux (s->info->ref, depth + 1));
3201 return (sRef_getRootBaseAux (s->info->field->rec, depth + 1));
3203 return (sRef_getRootBaseAux (s->info->arrayfetch->arr, depth + 1));
3205 return (sRef_getRootBaseAux (sRef_fixConj (s), depth + 1));
3211 sRef sRef_getRootBase (sRef s)
3213 return (sRef_getRootBaseAux (s, 0));
3216 static bool sRef_isDeep (sRef s)
3218 if (sRef_isInvalid (s)) return FALSE;
3228 return (sRef_isDeep (sRef_fixConj (s)));
3234 static int sRef_depth (sRef s)
3236 if (sRef_isInvalid (s)) return 0;
3244 return 1 + sRef_depth (s->info->ref);
3246 return 1 + sRef_depth (s->info->field->rec);
3248 return 1 + sRef_depth (s->info->arrayfetch->arr);
3250 return (sRef_depth (sRef_fixConj (s)));
3257 sRef_makeObject (ctype o)
3259 sRef s = sRef_new ();
3261 s->kind = SK_OBJECT;
3262 s->info = (sinfo) dmalloc (sizeof (*s->info));
3263 s->info->object = o;
3267 sRef sRef_makeExternal (/*@exposed@*/ sRef t)
3269 sRef s = sRef_new ();
3271 llassert (sRef_isValid (t));
3273 s->kind = SK_EXTERNAL;
3274 s->info = (sinfo) dmalloc (sizeof (*s->info));
3280 sRef sRef_makeDerived (/*@exposed@*/ sRef t)
3282 if (sRef_isValid (t))
3284 sRef s = sRef_new ();
3286 s->kind = SK_DERIVED;
3287 s->info = (sinfo) dmalloc (sizeof (*s->info));
3295 return sRef_undefined;
3300 ** definitely NOT symmetric:
3302 ** res fills in unknown state information from other
3306 sRef_mergeStateQuiet (sRef res, sRef other)
3308 llassert (sRef_isValid (res));
3309 llassert (sRef_isValid (other));
3311 res->modified = res->modified || other->modified;
3312 res->safe = res->safe && other->safe;
3314 if (res->defstate == SS_UNKNOWN)
3316 res->defstate = other->defstate;
3317 res->definfo = alinfo_update (res->definfo, other->definfo);
3320 if (res->aliaskind == AK_UNKNOWN ||
3321 (res->aliaskind == AK_LOCAL && alkind_isKnown (other->aliaskind)))
3323 res->aliaskind = other->aliaskind;
3324 res->oaliaskind = other->oaliaskind;
3325 res->aliasinfo = alinfo_update (res->aliasinfo, other->aliasinfo);
3328 if (res->expkind == XO_UNKNOWN)
3330 res->expkind = other->expkind;
3331 res->oexpkind = other->oexpkind;
3332 res->expinfo = alinfo_update (res->expinfo, other->expinfo);
3335 /* out takes precedence over implicitly defined */
3336 if (res->defstate == SS_DEFINED && other->defstate != SS_UNKNOWN)
3338 res->defstate = other->defstate;
3339 res->definfo = alinfo_update (res->definfo, other->definfo);
3342 if (other->nullstate == NS_ERROR || res->nullstate == NS_ERROR)
3344 res->nullstate = NS_ERROR;
3348 if (other->nullstate != NS_UNKNOWN
3349 && (res->nullstate == NS_UNKNOWN || res->nullstate == NS_NOTNULL
3350 || res->nullstate == NS_MNOTNULL))
3352 res->nullstate = other->nullstate;
3353 res->nullinfo = alinfo_update (res->nullinfo, other->nullinfo);
3359 ** definitely NOT symmetric:
3361 ** res fills in known state information from other
3365 sRef_mergeStateQuietReverse (sRef res, sRef other)
3367 bool changed = FALSE;
3369 llassert (sRef_isValid (res));
3370 llassert (sRef_isValid (other));
3372 if (res->kind != other->kind)
3378 res->kind = other->kind;
3379 res->type = other->type;
3380 res->info = sinfo_fullCopy (other);
3384 if (!ctype_equal (res->type, other->type))
3387 res->type = other->type;
3390 sinfo_update (res, other);
3393 res->modified = res->modified || other->modified;
3394 res->safe = res->safe && other->safe;
3396 if (res->aliaskind != other->aliaskind
3397 && (res->aliaskind == AK_UNKNOWN
3398 || ((res->aliaskind == AK_LOCAL
3399 || (res->aliaskind == AK_REFCOUNTED
3400 && other->aliaskind != AK_LOCAL))
3401 && other->aliaskind != AK_UNKNOWN)))
3404 res->aliaskind = other->aliaskind;
3405 res->oaliaskind = other->oaliaskind;
3406 res->aliasinfo = alinfo_update (res->aliasinfo, other->aliasinfo);
3409 if (other->expkind != XO_UNKNOWN && other->expkind != res->expkind)
3412 res->expkind = other->expkind;
3413 res->expinfo = alinfo_update (res->expinfo, other->expinfo);
3416 if (other->oexpkind != XO_UNKNOWN)
3418 res->oexpkind = other->oexpkind;
3421 /* out takes precedence over implicitly defined */
3423 if (res->defstate != other->defstate)
3425 if (other->defstate != SS_UNKNOWN)
3427 res->defstate = other->defstate;
3431 if (other->nullstate == NS_ERROR || res->nullstate == NS_ERROR)
3433 if (res->nullstate != NS_ERROR)
3435 res->nullstate = NS_ERROR;
3441 if (other->nullstate != NS_UNKNOWN && other->nullstate != res->nullstate)
3444 res->nullstate = other->nullstate;
3445 res->nullinfo = alinfo_update (res->nullinfo, other->nullinfo);
3451 sRef_clearDerived (res);
3456 sRef_mergeState (sRef res, sRef other, clause cl, fileloc loc)
3458 if (sRef_isValid (res) && sRef_isValid (other))
3460 sRef_mergeStateAux (res, other, cl, FALSE, loc, TRUE);
3464 if (sRef_isInvalid (res))
3466 llbug (message ("sRef_mergeState: invalid res sRef: %q",
3467 sRef_unparseDebug (other)));
3471 llbug (message ("sRef_mergeState: invalid other sRef: %q",
3472 sRef_unparseDebug (res)));
3478 sRef_mergeOptState (sRef res, sRef other, clause cl, fileloc loc)
3480 if (sRef_isValid (res) && sRef_isValid (other))
3482 sRef_mergeStateAux (res, other, cl, TRUE, loc, TRUE);
3486 if (sRef_isInvalid (res))
3488 llbug (message ("sRef_mergeOptState: invalid res sRef: %q",
3489 sRef_unparseDebug (other)));
3493 llbug (message ("sRef_mergeOptState: invalid other sRef: %q",
3494 sRef_unparseDebug (res)));
3500 sRef_mergeStateAux (/*@notnull@*/ sRef res, /*@notnull@*/ sRef other,
3501 clause cl, bool opt, fileloc loc,
3505 llassertfatal (sRef_isValid (res));
3506 llassertfatal (sRef_isValid (other));
3508 res->modified = res->modified || other->modified;
3510 if (res->kind == other->kind
3511 || (other->kind == SK_UNKNOWN || res->kind == SK_UNKNOWN))
3513 sstate odef = other->defstate;
3514 sstate rdef = res->defstate;
3515 nstate onull = other->nullstate;
3518 ** yucky stuff to handle
3523 if (other->defstate == SS_DEAD
3524 && ((sRef_isOnly (res) && sRef_definitelyNull (res))
3525 || (res->defstate == SS_UNDEFINED
3526 || res->defstate == SS_UNUSEABLE)))
3528 if (res->defstate == SS_UNDEFINED
3529 || res->defstate == SS_UNUSEABLE)
3531 res->defstate = SS_UNUSEABLE;
3535 res->defstate = SS_DEAD;
3538 res->definfo = alinfo_update (res->definfo, other->definfo);
3539 sRef_clearDerived (other);
3540 sRef_clearDerived (res);
3542 else if (res->defstate == SS_DEAD
3543 && ((sRef_isOnly (other) && sRef_definitelyNull (other))
3544 || (other->defstate == SS_UNDEFINED
3545 || other->defstate == SS_UNUSEABLE)))
3547 if (other->defstate == SS_UNDEFINED
3548 || other->defstate == SS_UNUSEABLE)
3550 res->defstate = SS_UNUSEABLE;
3554 res->defstate = SS_DEAD;
3557 sRef_clearDerived (other);
3558 sRef_clearDerived (res);
3560 else if (res->defstate == SS_DEFINED
3561 && (other->defstate == SS_ALLOCATED
3562 && sRef_definitelyNull (other)))
3564 other->defstate = SS_DEFINED; /* definitely null! */
3566 else if (other->defstate == SS_DEFINED
3567 && (res->defstate == SS_ALLOCATED && sRef_definitelyNull (res)))
3569 res->defstate = SS_DEFINED;
3570 res->definfo = alinfo_update (res->definfo, other->definfo);
3577 if (res->defstate == SS_DEAD && other->defstate == SS_DEAD)
3579 sRef_clearDerived (other);
3580 sRef_clearDerived (res);
3584 ** only & dead isn't really an only!
3587 if (alkind_isOnly (other->aliaskind) && other->defstate == SS_DEAD)
3589 other->aliaskind = AK_UNKNOWN;
3592 if (alkind_isOnly (res->aliaskind) && res->defstate == SS_DEAD)
3594 res->aliaskind = AK_UNKNOWN;
3598 ** Dead and dependent -> dead
3601 if (alkind_isDependent (other->aliaskind) && res->defstate == SS_DEAD)
3603 other->aliaskind = AK_UNKNOWN;
3604 other->defstate = SS_DEAD;
3605 sRef_clearDerived (res);
3606 sRef_clearDerived (other);
3609 if (alkind_isDependent (res->aliaskind) && other->defstate == SS_DEAD)
3611 res->aliaskind = AK_UNKNOWN;
3612 res->defstate = SS_DEAD;
3613 sRef_clearDerived (res);
3614 sRef_clearDerived (other);
3618 ** must do alias combine first, since it depends on
3619 ** original values of state and null.
3622 sRef_combineAliasKinds (res, other, cl, loc);
3623 sRef_combineDefState (res, other);
3624 sRef_combineNullState (res, other);
3626 if (rdef == SS_ALLOCATED || rdef == SS_SPECIAL)
3628 if (odef == SS_DEFINED)
3630 if (onull == NS_DEFNULL || onull == NS_CONSTNULL)
3632 res->deriv = sRefSet_copy (res->deriv, other->deriv);
3637 else if (odef == SS_ALLOCATED
3638 || odef == SS_SPECIAL)
3643 if (ctype_isUnion (ctype_realType (sRef_getType (res))))
3645 res->deriv = sRef_mergeUnionDerivs (res->deriv,
3651 res->deriv = sRef_mergeDerivs (res->deriv, other->deriv,
3660 res->deriv = sRef_mergeDerivs (res->deriv, other->deriv,
3670 if (rdef == SS_PDEFINED
3671 || (rdef == SS_DEFINED && odef == SS_PDEFINED))
3675 res->deriv = sRef_mergePdefinedDerivs (res->deriv, other->deriv,
3681 if ((rdef == SS_DEFINED || rdef == SS_UNKNOWN)
3682 && res->defstate == SS_ALLOCATED)
3684 res->deriv = sRefSet_copy (res->deriv, other->deriv);
3690 res->deriv = sRef_mergeDerivs (res->deriv, other->deriv,
3698 sRef_combineExKinds (res, other);
3702 if (res->kind == SK_ARRAYFETCH && other->kind == SK_PTR)
3704 sRef nother = sRef_buildArrayFetchKnown (sRef_getBase (other), 0);
3706 sRef_copyState (nother, other);
3707 sRef_mergeStateAux (res, nother, cl, opt, loc, doDerivs);
3709 else if (res->kind == SK_PTR && other->kind == SK_ARRAYFETCH)
3711 sRef nother = sRef_buildPointer (sRef_getBase (other));
3713 if (sRef_isValid (nother))
3715 sRef_copyState (nother, other);
3716 sRef_mergeStateAux (res, nother, cl, opt, loc, doDerivs);
3721 llcontbug (message ("merge conj: %q / %q", sRef_unparseFull (res),
3722 sRef_unparseFull (other)));
3730 sRef_mergeUnionDerivs (/*@only@*/ sRefSet res,
3731 /*@exposed@*/ sRefSet other, bool opt,
3732 clause cl, fileloc loc)
3734 if (sRefSet_isEmpty (res))
3736 return sRefSet_copy (res, other);
3740 sRefSet_allElements (other, el)
3742 if (sRef_isValid (el))
3744 sRef e2 = sRefSet_lookupMember (other, el);
3746 if (sRef_isValid (e2))
3748 sRef_mergeStateAux (el, e2, cl, opt, loc, FALSE);
3752 res = sRefSet_insert (res, el);
3755 } end_sRefSet_allElements ;
3761 static /*@only@*/ sRefSet
3762 sRef_mergeDerivs (/*@only@*/ sRefSet res, sRefSet other,
3763 bool opt, clause cl, fileloc loc)
3765 sRefSet ret = sRefSet_new ();
3768 sRefSet_allElements (res, el)
3770 if (sRef_isValid (el))
3772 sRef e2 = sRefSet_lookupMember (other, el);
3774 if (sRef_isValid (e2))
3776 if (el->defstate == SS_ALLOCATED &&
3777 e2->defstate == SS_PDEFINED)
3779 e2->defstate = SS_ALLOCATED;
3781 else if (e2->defstate == SS_ALLOCATED &&
3782 el->defstate == SS_PDEFINED)
3784 el->defstate = SS_ALLOCATED;
3785 sRef_clearDerived (el);
3787 else if ((el->defstate == SS_DEAD || sRef_isKept (el)) &&
3788 (e2->defstate == SS_DEFINED && !sRef_isKept (e2)))
3791 if (checkDeadState (el, TRUE, loc))
3793 if (sRef_isThroughArrayFetch (el))
3795 sRef_maybeKill (el, loc);
3796 sRef_maybeKill (e2, loc);
3800 else if ((e2->defstate == SS_DEAD || sRef_isKept (e2)) &&
3801 (el->defstate == SS_DEFINED && !sRef_isKept (el)))
3804 if (checkDeadState (e2, FALSE, loc))
3806 if (sRef_isThroughArrayFetch (el))
3808 sRef_maybeKill (el, loc);
3809 sRef_maybeKill (e2, loc);
3813 else if (el->defstate == SS_DEFINED &&
3814 e2->defstate == SS_PDEFINED)
3816 el->defstate = SS_PDEFINED;
3818 else if (e2->defstate == SS_DEFINED &&
3819 el->defstate == SS_PDEFINED)
3821 e2->defstate = SS_PDEFINED;
3828 if (ctype_isUnion (ctype_realType (sRef_getType (el))))
3830 el->deriv = sRef_mergeUnionDerivs (el->deriv, e2->deriv,
3835 el->deriv = sRef_mergeDerivs (el->deriv, e2->deriv, opt, cl, loc);
3838 if (sRef_equivalent (el, e2))
3840 ret = sRefSet_insert (ret, el);
3844 sRef sr = sRef_leastCommon (el, e2);
3846 if (sRef_isValid (sr))
3848 ret = sRefSet_insert (ret, sr);
3856 (void) sRefSet_delete (other, e2);
3858 else /* not defined */
3860 (void) checkDeadState (el, TRUE, loc);
3863 } end_sRefSet_allElements;
3865 sRefSet_allElements (other, el)
3867 if (sRef_isValid (el))
3869 (void) checkDeadState (el, FALSE, loc);
3871 } end_sRefSet_allElements;
3878 ** Returns TRUE is there is an error.
3881 static bool checkDeadState (/*@notnull@*/ sRef el, bool tbranch, fileloc loc)
3884 ** usymtab_isGuarded --- the utab should still be in the
3885 ** state of the alternate branch.
3887 ** tbranch TRUE means el is released in the last branch, e.g.
3888 ** if (x != NULL) { ; } else { sfree (x); }
3889 ** so, if x is null in the other branch no error is reported.
3891 ** tbranch FALSE means this is the other branch:
3892 ** if (x != NULL) { sfree (x); } else { ; }
3893 ** so, if x is null in this branch there is no error.
3897 if ((sRef_isDead (el) || sRef_isKept (el))
3898 && !sRef_isDeepUnionField (el) && !sRef_isThroughArrayFetch (el))
3903 if (usymtab_isProbableDeepNull (el))
3910 if (usymtab_isAltProbablyDeepNull (el))
3918 message ("Storage %q is %q in one path, but live in another.",
3920 cstring_makeLiteral (sRef_isKept (el)
3921 ? "kept" : "released")),
3925 if (sRef_isKept (el))
3927 sRef_showAliasInfo (el);
3931 sRef_showStateInfo (el);
3934 /* prevent further errors */
3935 el->defstate = SS_UNKNOWN;
3936 sRef_setAliasKind (el, AK_ERROR, fileloc_undefined);
3946 checkDerivDeadState (/*@notnull@*/ sRef el, bool tbranch, fileloc loc)
3949 if (checkDeadState (el, tbranch, loc))
3951 sRefSet_allElements (el->deriv, t)
3953 if (sRef_isValid (t))
3955 checkDerivDeadState (t, tbranch, loc);
3957 } end_sRefSet_allElements;
3962 sRef_mergePdefinedDerivs (sRefSet res, sRefSet other, bool opt,
3963 clause cl, fileloc loc)
3965 sRefSet ret = sRefSet_new ();
3967 sRefSet_allElements (res, el)
3969 if (sRef_isValid (el))
3971 sRef e2 = sRefSet_lookupMember (other, el);
3973 if (sRef_isValid (e2))
3975 if (sRef_isAllocated (el) && !sRef_isAllocated (e2))
3979 else if (sRef_isAllocated (e2) && !sRef_isAllocated (el))
3981 el->deriv = sRefSet_copy (el->deriv, e2->deriv);
3985 el->deriv = sRef_mergePdefinedDerivs (el->deriv, e2->deriv,
3989 sRef_mergeStateAux (el, e2, cl, opt, loc, FALSE);
3991 ret = sRefSet_insert (ret, el);
3992 (void) sRefSet_delete (other, e2);
3998 checkDerivDeadState (el, (cl == FALSECLAUSE), loc);
4001 ret = sRefSet_insert (ret, el);
4004 } end_sRefSet_allElements;
4006 sRefSet_allElements (other, el)
4008 if (sRef_isValid (el))
4010 if (!sRefSet_member (ret, el))
4012 /* was cl == FALSECLAUSE */
4013 checkDerivDeadState (el, FALSE, loc);
4014 ret = sRefSet_insert (ret, el);
4019 ** it's okay --- member is a different equality test
4023 } end_sRefSet_allElements;
4029 sRef sRef_makeConj (/*@exposed@*/ /*@returned@*/ sRef a, /*@exposed@*/ sRef b)
4031 llassert (sRef_isValid (a));
4032 llassert (sRef_isValid (b));
4034 if (!sRef_equivalent (a, b))
4036 sRef s = sRef_new ();
4039 s->info = (sinfo) dmalloc (sizeof (*s->info));
4040 s->info->conj = (cjinfo) dmalloc (sizeof (*s->info->conj));
4041 s->info->conj->a = a;
4042 s->info->conj->b = b;
4044 if (ctype_equal (a->type, b->type)) s->type = a->type;
4045 else s->type = ctype_makeConj (a->type, b->type);
4047 if (a->defstate == b->defstate)
4049 s->defstate = a->defstate;
4053 s->defstate = SS_UNKNOWN;
4056 s->nullstate = NS_UNKNOWN;
4058 s->safe = a->safe && b->safe;
4059 s->aliaskind = alkind_resolve (a->aliaskind, b->aliaskind);
4065 /*@-exposetrans@*/ return a; /*@=exposetrans@*/
4072 sRef s = sRef_new ();
4074 s->kind = SK_UNKNOWN;
4079 sRef_makeSpecial (speckind sk) /*@*/
4081 sRef s = sRef_new ();
4083 s->kind = SK_SPECIAL;
4084 s->info = (sinfo) dmalloc (sizeof (*s->info));
4089 static sRef srnothing = sRef_undefined;
4090 static sRef srinternal = sRef_undefined;
4091 static sRef srsystem = sRef_undefined;
4092 static sRef srspec = sRef_undefined;
4095 sRef_makeNothing (void)
4097 if (sRef_isInvalid (srnothing))
4099 srnothing = sRef_makeSpecial (SR_NOTHING);
4108 sRef_makeInternalState (void)
4110 if (sRef_isInvalid (srinternal))
4112 srinternal = sRef_makeSpecial (SR_INTERNAL);
4121 sRef_makeSpecState (void)
4123 if (sRef_isInvalid (srspec))
4125 srspec = sRef_makeSpecial (SR_SPECSTATE);
4134 sRef_makeSystemState (void)
4136 if (sRef_isInvalid (srsystem))
4138 srsystem = sRef_makeSpecial (SR_SYSTEM);
4147 sRef_makeResultType (ctype ct)
4149 sRef res = sRef_makeResult ();
4158 sRef s = sRef_new ();
4160 s->kind = SK_RESULT;
4161 s->type = ctype_unknown;
4162 s->defstate = SS_UNKNOWN;
4163 s->aliaskind = AK_UNKNOWN;
4164 s->nullstate = NS_UNKNOWN;
4171 sRef_isNothing (sRef s)
4173 return (sRef_isKindSpecial (s) && s->info->spec == SR_NOTHING);
4177 sRef_isInternalState (sRef s)
4179 return (sRef_isKindSpecial (s) && s->info->spec == SR_INTERNAL);
4183 sRef_isSpecInternalState (sRef s)
4185 return (sRef_isKindSpecial (s)
4186 && (s->info->spec == SR_INTERNAL || s->info->spec == SR_SPECSTATE));
4190 sRef_isSpecState (sRef s)
4192 return (sRef_isKindSpecial (s) && s->info->spec == SR_SPECSTATE);
4196 sRef_isResult (sRef s)
4198 return (sRef_isValid (s) && s->kind == SK_RESULT);
4202 sRef_isSystemState (sRef s)
4204 return (sRef_isKindSpecial (s) && s->info->spec == SR_SYSTEM);
4208 sRef_getScopeIndex (sRef s)
4210 llassert (sRef_isValid (s));
4211 llassert (sRef_isCvar (s));
4213 return (s->info->cvar->index);
4217 sRef_makeSafe (sRef s)
4219 if (sRef_isValid (s))
4226 sRef_makeUnsafe (sRef s)
4228 if (sRef_isValid (s))
4235 ** memory state operations
4238 /*@only@*/ cstring sRef_unparseFull (sRef s)
4240 if (sRef_isInvalid (s)) return (cstring_undefined);
4242 return (message ("[%d] %q - %q [%s] { %q }",
4244 sRef_unparseDebug (s),
4245 sRef_unparseState (s),
4246 exkind_unparse (s->oexpkind),
4247 sRefSet_unparseDebug (s->deriv)));
4250 /*@unused@*/ cstring sRef_unparseDeep (sRef s)
4252 cstring st = cstring_undefined;
4254 st = message ("%q:", sRef_unparseFull (s));
4256 if (sRef_isValid (s))
4258 sRefSet_allElements (s->deriv, el)
4260 st = message("%q\n%q", st, sRef_unparseDeep (el));
4261 } end_sRefSet_allElements ;
4267 /*@only@*/ cstring sRef_unparseState (sRef s)
4269 if (sRef_isConj (s))
4271 return (message ("%q | %q",
4272 sRef_unparseState (s->info->conj->a),
4273 sRef_unparseState (s->info->conj->b)));
4276 if (sRef_isInvalid (s))
4278 return (cstring_makeLiteral ("<invalid>"));
4281 return (message ("%s.%s.%s.%s",
4282 alkind_unparse (s->aliaskind),
4283 nstate_unparse (s->nullstate),
4284 exkind_unparse (s->expkind),
4285 sstate_unparse (s->defstate)));
4288 bool sRef_isNotUndefined (sRef s)
4290 return (sRef_isInvalid (s)
4291 || (s->defstate != SS_UNDEFINED
4292 && s->defstate != SS_UNUSEABLE
4293 && s->defstate != SS_DEAD));
4296 ynm sRef_isWriteable (sRef s)
4298 if (sRef_isInvalid (s)) return MAYBE;
4300 if (sRef_isConj (s) && s->defstate == SS_UNKNOWN)
4302 if (ynm_toBoolStrict (sRef_isWriteable (sRef_getConjA (s))))
4304 if (ynm_toBoolStrict (sRef_isWriteable (sRef_getConjB (s))))
4312 if (ynm_toBoolStrict (sRef_isWriteable (sRef_getConjB (s))))
4320 return (ynm_fromBool (s->defstate != SS_UNUSEABLE));
4323 bool sRef_hasNoStorage (sRef s)
4325 return (!sRef_isAllocatedStorage (s) || sRef_isDefinitelyNull (s));
4328 bool sRef_isStrictReadable (sRef s)
4330 return (ynm_toBoolStrict (sRef_isReadable (s)));
4333 ynm sRef_isReadable (sRef s)
4337 if (sRef_isInvalid (s)) return YES;
4341 if (sRef_isConj (s) && s->defstate == SS_UNKNOWN)
4343 if (ynm_toBoolStrict (sRef_isReadable (sRef_getConjA (s))))
4345 if (ynm_toBoolStrict (sRef_isReadable (sRef_getConjB (s))))
4353 if (ynm_toBoolStrict (sRef_isReadable (sRef_getConjB (s))))
4360 else if (ss == SS_HOFFA)
4362 if (context_getFlag (FLG_STRICTUSERELEASED))
4373 return (ynm_fromBool (ss == SS_DEFINED
4376 || ss == SS_PDEFINED
4379 || ss == SS_ALLOCATED
4380 || ss == SS_UNKNOWN));
4384 static /*@exposed@*/ sRef whatUndefined (/*@exposed@*/ sRef fref, int depth)
4389 if (depth > MAXDEPTH)
4392 ("Warning: check definition limit exceeded, checking %q. "
4393 "This either means there is a variable with at least "
4394 "%d indirections apparent in the program text, or "
4395 "there is a bug in LCLint.",
4396 sRef_unparse (fref),
4400 return sRef_undefined;
4403 if (!sRef_isKnown (fref) || sRef_isAnyDefined (fref))
4405 return sRef_undefined;
4408 if (sRef_isUnuseable (fref) || sRef_isStateUndefined (fref))
4413 ct = ctype_realType (sRef_getType (fref));
4415 if (ctype_isUnknown (ct))
4417 return sRef_undefined;
4419 else if (ctype_isPointer (ct) || ctype_isArray (ct))
4421 if (sRef_isStateUnknown (fref))
4423 return sRef_undefined;
4427 sRef fptr = sRef_constructDeref (fref);
4429 return (whatUndefined (fptr, depth + 1));
4432 else if (ctype_isStruct (ct))
4434 bool hasOneDefined = FALSE;
4436 if (sRef_isStateUnknown (fref))
4441 if (sRef_isPdefined (fref) || sRef_isAnyDefined (fref))
4443 sRefSet_realElements (sRef_derivedFields (fref), sr)
4445 hasOneDefined = TRUE;
4447 if (sRef_isField (sr))
4449 cstring fieldname = sRef_getField (sr);
4450 sRef fldref = sRef_makeField (fref, fieldname);
4451 bool shouldCheck = !sRef_isRecursiveField (fldref);
4455 sRef wdef = whatUndefined (fldref, depth + 1);
4457 if (sRef_isValid (wdef))
4463 } end_sRefSet_realElements;
4465 else if (sRef_isAllocated (fref))
4468 ** for structures, each field must be completely defined
4471 uentryList fields = ctype_getFields (ct);
4473 uentryList_elements (fields, ue)
4475 cstring name = uentry_getRealName (ue);
4476 sRef ffield = sRef_makeField (fref, name);
4477 bool shouldCheck = !sRef_isRecursiveField (ffield);
4479 if (sRef_isRelDef (uentry_getSref (ue)))
4487 sRef wdef = whatUndefined (ffield, depth + 1);
4489 if (sRef_isInvalid (wdef))
4495 } end_uentryList_elements;
4502 else if (ctype_isUnion (ct))
4511 return sRef_undefined;
4514 static bool checkDefined (sRef sr)
4516 return (sRef_isInvalid (whatUndefined (sr, 0)));
4519 bool sRef_isReallyDefined (sRef s)
4521 if (sRef_isValid (s))
4523 if (sRef_isAnyDefined (s))
4529 if (sRef_isAllocated (s) || sRef_isPdefined (s))
4531 return checkDefined (s);
4545 void sRef_showNotReallyDefined (sRef s)
4547 if (sRef_isValid (s))
4549 if (sRef_isAnyDefined (s))
4555 if (sRef_isAllocated (s) || sRef_isPdefined (s))
4557 sRef ref = whatUndefined (s, 0);
4559 llassert (sRef_isValid (ref));
4564 (message ("This sub-reference is %s: %q",
4565 sstate_unparse (sRef_getDefState (ref)),
4566 sRef_unparse (ref)));
4581 sstate sRef_getDefState (sRef s)
4583 if (sRef_isInvalid (s)) return (SS_UNKNOWN);
4584 return (s->defstate);
4587 void sRef_setDefState (sRef s, sstate defstate, fileloc loc)
4589 sRef_setStateAux (s, defstate, loc);
4592 static void sRef_clearAliasStateAux (sRef s, fileloc loc)
4594 sRef_setAliasKind (s, AK_ERROR, loc);
4597 void sRef_clearAliasState (sRef s, fileloc loc)
4599 sRef_aliasSetComplete (sRef_clearAliasStateAux, s, loc);
4602 void sRef_setAliasKindComplete (sRef s, alkind kind, fileloc loc)
4604 sRef_aliasSetCompleteParam (sRef_setAliasKind, s, kind, loc);
4607 void sRef_setAliasKind (sRef s, alkind kind, fileloc loc)
4609 if (sRef_isValid (s))
4611 sRef_clearDerived (s);
4613 if ((kind != s->aliaskind && kind != s->oaliaskind)
4614 && fileloc_isDefined (loc))
4616 s->aliasinfo = alinfo_updateLoc (s->aliasinfo, loc);
4619 s->aliaskind = kind;
4623 void sRef_setOrigAliasKind (sRef s, alkind kind)
4625 if (sRef_isValid (s))
4627 s->oaliaskind = kind;
4631 exkind sRef_getExKind (sRef s)
4633 if (sRef_isValid (s))
4635 return (s->expkind);
4643 exkind sRef_getOrigExKind (sRef s)
4645 if (sRef_isValid (s))
4647 return (s->oexpkind);
4655 static void sRef_clearExKindAux (sRef s, fileloc loc)
4657 sRef_setExKind (s, XO_UNKNOWN, loc);
4660 void sRef_setObserver (sRef s, fileloc loc)
4662 sRef_setExKind (s, XO_OBSERVER, loc);
4665 void sRef_setExposed (sRef s, fileloc loc)
4667 sRef_setExKind (s, XO_EXPOSED, loc);
4670 void sRef_clearExKindComplete (sRef s, fileloc loc)
4672 (void) sRef_aliasSetComplete (sRef_clearExKindAux, s, loc);
4675 void sRef_setExKind (sRef s, exkind exp, fileloc loc)
4677 if (sRef_isValid (s))
4679 if (s->expkind != exp)
4681 s->expinfo = alinfo_updateLoc (s->expinfo, loc);
4689 ** s1->derived = s2->derived
4692 static void sRef_copyRealDerived (sRef s1, sRef s2)
4694 if (sRef_isValid (s1) && sRef_isValid (s2))
4696 sRef sb = sRef_getRootBase (s1);
4698 sRefSet_clear (s1->deriv);
4700 sRefSet_allElements (s2->deriv, el)
4702 if (sRef_isValid (el))
4704 sRef rb = sRef_getRootBase (el);
4706 if (!sRef_same (rb, sb))
4708 sRef fb = sRef_fixDirectBase (el, s1);
4710 if (sRef_isValid (fb))
4712 sRef_copyRealDerived (fb, el);
4713 sRef_addDeriv (s1, fb);
4718 sRef_addDeriv (s1, el);
4721 } end_sRefSet_allElements ;
4726 void sRef_copyRealDerivedComplete (sRef s1, sRef s2)
4728 sRef_innerAliasSetCompleteParam (sRef_copyRealDerived, s1, s2);
4731 void sRef_setUndefined (sRef s, fileloc loc)
4733 if (sRef_isValid (s))
4735 s->defstate = SS_UNDEFINED;
4737 if (fileloc_isDefined (loc))
4739 s->definfo = alinfo_updateLoc (s->definfo, loc);
4742 sRef_clearDerived (s);
4746 static void sRef_setDefinedAux (sRef s, fileloc loc, bool clear)
4748 if (sRef_isInvalid (s)) return;
4750 if (s->defstate != SS_DEFINED && fileloc_isDefined (loc))
4752 s->definfo = alinfo_updateLoc (s->definfo, loc);
4755 s->defstate = SS_DEFINED;
4757 /* e.g., if x is allocated, *x = 3 defines x */
4759 if (s->kind == SK_PTR)
4761 sRef p = s->info->ref;
4763 if (p->defstate == SS_ALLOCATED)
4765 sRef_setDefinedAux (p, loc, clear);
4768 else if (s->kind == SK_ARRAYFETCH)
4770 if (!s->info->arrayfetch->indknown
4771 || (s->info->arrayfetch->ind == 0))
4773 sRef p = s->info->arrayfetch->arr;
4774 sRef ptr = sRef_constructPointer (p);
4776 if (sRef_isValid (ptr))
4778 if (ptr->defstate == SS_ALLOCATED
4779 || ptr->defstate == SS_UNDEFINED)
4781 sRef_setDefinedAux (ptr, loc, clear);
4785 if (p->defstate == SS_RELDEF)
4789 else if (p->defstate == SS_ALLOCATED || p->defstate == SS_PDEFINED)
4791 p->defstate = SS_DEFINED;
4798 else if (s->kind == SK_FIELD)
4800 sRef parent = s->info->field->rec;
4802 if (sRef_isValid (parent))
4804 if (ctype_isUnion (ctype_realType (parent->type)))
4807 ** Should not clear derived from here.
4810 sRef_setDefinedNoClear (parent, loc);
4814 ; /* Nothing to do for structures. */
4826 sRef_clearDerived (s);
4830 static void sRef_setPartialDefined (sRef s, fileloc loc)
4832 if (!sRef_isPartial (s))
4834 sRef_setDefined (s, loc);
4838 void sRef_setPartialDefinedComplete (sRef s, fileloc loc)
4840 sRef_innerAliasSetComplete (sRef_setPartialDefined, s, loc);
4843 void sRef_setDefinedComplete (sRef s, fileloc loc)
4845 sRef_innerAliasSetComplete (sRef_setDefined, s, loc);
4848 void sRef_setDefined (sRef s, fileloc loc)
4850 sRef_setDefinedAux (s, loc, TRUE);
4853 static void sRef_setDefinedNoClear (sRef s, fileloc loc)
4855 DPRINTF (("Defining: %s", sRef_unparseFull (s)));
4856 sRef_setDefinedAux (s, loc, FALSE);
4857 DPRINTF (("==> %s", sRef_unparseFull (s)));
4860 void sRef_setDefinedNCComplete (sRef s, fileloc loc)
4862 DPRINTF (("Set Defined Complete: %s", sRef_unparseFull (s)));
4863 sRef_innerAliasSetComplete (sRef_setDefinedNoClear, s, loc);
4864 DPRINTF (("==> %s", sRef_unparseFull (s)));
4867 static bool sRef_isDeepUnionField (sRef s)
4869 return (sRef_deepPred (sRef_isUnionField, s));
4872 bool sRef_isUnionField (sRef s)
4874 if (sRef_isValid (s) && s->kind == SK_FIELD)
4877 ** defining one field of a union defines the union
4880 sRef base = s->info->field->rec;
4882 if (sRef_isValid (base))
4884 return (ctype_isUnion (ctype_realType (base->type)));
4891 void sRef_setPdefined (sRef s, fileloc loc)
4893 if (sRef_isValid (s) && !sRef_isPartial (s))
4895 sRef base = sRef_getBaseSafe (s);
4897 if (s->defstate == SS_ALLOCATED)
4902 if (s->defstate != SS_PDEFINED && fileloc_isDefined (loc))
4904 s->definfo = alinfo_updateLoc (s->definfo, loc);
4907 s->defstate = SS_PDEFINED;
4909 /* e.g., if x is allocated, *x = 3 defines x */
4911 while (sRef_isValid (base) && sRef_isKnown (base))
4913 if (base->defstate == SS_DEFINED)
4917 base->defstate = SS_PDEFINED;
4918 nb = sRef_getBaseSafe (base);
4929 static void sRef_setStateAux (sRef s, sstate ss, fileloc loc)
4931 if (sRef_isValid (s))
4933 /* if (s->defstate == SS_RELDEF) return; */
4935 if (s->defstate != ss && fileloc_isDefined (loc))
4937 s->definfo = alinfo_updateLoc (s->definfo, loc);
4941 sRef_clearDerived (s);
4943 if (ss == SS_ALLOCATED)
4945 sRef base = sRef_getBaseSafe (s);
4947 while (sRef_isValid (base) && sRef_isKnown (base))
4949 if (base->defstate == SS_DEFINED)
4953 base->defstate = SS_PDEFINED;
4955 nb = sRef_getBaseSafe (base);
4968 void sRef_setAllocatedComplete (sRef s, fileloc loc)
4970 sRef_innerAliasSetComplete (sRef_setAllocated, s, loc);
4973 static void sRef_setAllocatedShallow (sRef s, fileloc loc)
4975 if (sRef_isValid (s))
4977 if (s->defstate == SS_DEAD || s->defstate == SS_UNDEFINED)
4979 s->defstate = SS_ALLOCATED;
4981 if (fileloc_isDefined (loc))
4983 s->definfo = alinfo_updateLoc (s->definfo, loc);
4989 void sRef_setAllocatedShallowComplete (sRef s, fileloc loc)
4991 sRef_innerAliasSetComplete (sRef_setAllocatedShallow, s, loc);
4994 void sRef_setAllocated (sRef s, fileloc loc)
4996 sRef_setStateAux (s, SS_ALLOCATED, loc);
4999 void sRef_setPartial (sRef s, fileloc loc)
5001 sRef_setStateAux (s, SS_PARTIAL, loc);
5004 void sRef_setShared (sRef s, fileloc loc)
5006 if (sRef_isValid (s))
5008 if (s->aliaskind != AK_SHARED && fileloc_isDefined (loc))
5010 s->aliasinfo = alinfo_updateLoc (s->aliasinfo, loc);
5013 s->aliaskind = AK_SHARED;
5014 /* don't! sRef_clearDerived (s); */
5018 void sRef_setLastReference (sRef s, sRef ref, fileloc loc)
5020 if (sRef_isValid (s))
5022 s->aliaskind = sRef_getAliasKind (ref);
5023 s->aliasinfo = alinfo_updateRefLoc (s->aliasinfo, ref, loc);
5028 void sRef_setNullStateAux (/*@notnull@*/ sRef s, nstate ns, fileloc loc)
5032 if (fileloc_isDefined (loc))
5034 s->nullinfo = alinfo_updateLoc (s->nullinfo, loc);
5038 void sRef_setNotNull (sRef s, fileloc loc)
5040 if (sRef_isValid (s))
5042 sRef_setNullStateAux (s, NS_NOTNULL, loc);
5046 void sRef_setNullState (sRef s, nstate n, fileloc loc)
5048 if (sRef_isValid (s))
5050 sRef_setNullStateAux (s, n, loc);
5054 void sRef_setNullTerminatedStateInnerComplete (sRef s, struct _bbufinfo b, /*@unused@*/ fileloc loc) {
5056 switch (b.bufstate) {
5057 case BB_NULLTERMINATED:
5058 sRef_setNullTerminatedState (s);
5059 sRef_setLen (s, b.len);
5061 case BB_POSSIBLYNULLTERMINATED:
5062 sRef_setPossiblyNullTerminatedState(s);
5064 case BB_NOTNULLTERMINATED:
5065 sRef_setNotNullTerminatedState (s);
5068 sRef_setSize (s, b.size);
5070 /* PL: TO BE DONE : Aliases are not modified right now, have to be similar to
5071 * setNullStateInnerComplete.
5075 void sRef_setNullStateInnerComplete (sRef s, nstate n, fileloc loc)
5077 sRef_setNullState (s, n, loc);
5082 sRef_innerAliasSetComplete (sRef_setPosNull, s, loc);
5085 sRef_innerAliasSetComplete (sRef_setDefNull, s, loc);
5088 sRef_innerAliasSetComplete (sRef_setNullUnknown, s, loc);
5091 sRef_innerAliasSetComplete (sRef_setNotNull, s, loc);
5094 sRef_innerAliasSetComplete (sRef_setNotNull, s, loc);
5097 sRef_innerAliasSetComplete (sRef_setNullUnknown, s, loc);
5100 sRef_innerAliasSetComplete (sRef_setDefNull, s, loc);
5103 sRef_innerAliasSetComplete (sRef_setNullUnknown, s, loc);
5106 sRef_innerAliasSetComplete (sRef_setNullErrorLoc, s, loc);
5111 void sRef_setPosNull (sRef s, fileloc loc)
5113 if (sRef_isValid (s))
5115 sRef_setNullStateAux (s, NS_POSNULL, loc);
5119 void sRef_setDefNull (sRef s, fileloc loc)
5121 if (sRef_isValid (s))
5123 sRef_setNullStateAux (s, NS_DEFNULL, loc);
5127 void sRef_setNullUnknown (sRef s, fileloc loc)
5129 if (sRef_isValid (s))
5131 sRef_setNullStateAux (s, NS_UNKNOWN, loc);
5135 void sRef_setNullError (sRef s)
5137 if (sRef_isValid (s))
5139 sRef_setNullStateAux (s, NS_UNKNOWN, fileloc_undefined);
5143 void sRef_setNullErrorLoc (sRef s, /*@unused@*/ fileloc loc)
5145 sRef_setNullError (s);
5148 void sRef_setOnly (sRef s, fileloc loc)
5150 if (sRef_isValid (s) && s->aliaskind != AK_ONLY)
5152 s->aliaskind = AK_ONLY;
5153 s->aliasinfo = alinfo_updateLoc (s->aliasinfo, loc);
5157 void sRef_setDependent (sRef s, fileloc loc)
5159 if (sRef_isValid (s) && !sRef_isConst (s) && (s->aliaskind != AK_DEPENDENT))
5161 s->aliaskind = AK_DEPENDENT;
5162 s->aliasinfo = alinfo_updateLoc (s->aliasinfo, loc);
5166 void sRef_setOwned (sRef s, fileloc loc)
5168 if (sRef_isValid (s) && !sRef_isConst (s) && (s->aliaskind != AK_OWNED))
5170 s->aliaskind = AK_OWNED;
5171 s->aliasinfo = alinfo_updateLoc (s->aliasinfo, loc);
5175 void sRef_setKept (sRef s, fileloc loc)
5177 if (sRef_isValid (s) && !sRef_isConst (s) && (s->aliaskind != AK_KEPT))
5179 sRef base = sRef_getBaseSafe (s);
5181 while (sRef_isValid (base) && sRef_isKnown (base))
5183 if (base->defstate == SS_DEFINED)
5185 base->defstate = SS_PDEFINED;
5186 base = sRef_getBaseSafe (base);
5195 s->aliaskind = AK_KEPT;
5196 s->aliasinfo = alinfo_updateLoc (s->aliasinfo, loc);
5200 static void sRef_setKeptAux (sRef s, fileloc loc)
5202 if (!sRef_isShared (s))
5204 sRef_setKept (s, loc);
5208 static void sRef_setDependentAux (sRef s, fileloc loc)
5210 if (!sRef_isShared (s))
5212 sRef_setDependent (s, loc);
5216 void sRef_setKeptComplete (sRef s, fileloc loc)
5218 sRef_aliasSetComplete (sRef_setKeptAux, s, loc);
5221 void sRef_setDependentComplete (sRef s, fileloc loc)
5223 sRef_aliasSetComplete (sRef_setDependentAux, s, loc);
5226 void sRef_setFresh (sRef s, fileloc loc)
5228 if (sRef_isValid (s))
5230 s->aliaskind = AK_FRESH;
5231 s->aliasinfo = alinfo_updateLoc (s->aliasinfo, loc);
5235 void sRef_kill (sRef s, fileloc loc)
5237 DPRINTF (("Kill: %s", sRef_unparseFull (s)));
5239 if (sRef_isValid (s) && !sRef_isShared (s) && !sRef_isConst (s))
5241 sRef base = sRef_getBaseSafe (s);
5243 while (sRef_isValid (base) && sRef_isKnown (base))
5245 if (base->defstate == SS_DEFINED)
5247 base->defstate = SS_PDEFINED;
5248 base = sRef_getBaseSafe (base);
5257 s->aliaskind = s->oaliaskind;
5258 s->defstate = SS_DEAD;
5259 s->definfo = alinfo_updateLoc (s->definfo, loc);
5261 sRef_clearDerived (s);
5265 void sRef_maybeKill (sRef s, fileloc loc)
5268 if (sRef_isValid (s))
5270 sRef base = sRef_getBaseSafe (s);
5273 while (sRef_isValid (base) && sRef_isKnown (base))
5275 if (base->defstate == SS_DEFINED || base->defstate == SS_RELDEF)
5277 base->defstate = SS_PDEFINED;
5278 base = sRef_getBaseSafe (base);
5287 s->aliaskind = s->oaliaskind;
5288 s->defstate = SS_HOFFA;
5289 s->definfo = alinfo_updateLoc (s->definfo, loc);
5290 sRef_clearDerived (s);
5296 ** just for type checking...
5299 static void sRef_killAux (sRef s, fileloc loc)
5301 if (sRef_isValid (s) && !sRef_isShared (s))
5303 if (sRef_isUnknownArrayFetch (s))
5305 sRef_maybeKill (s, loc);
5315 ** kills s and all aliases to s
5318 void sRef_killComplete (sRef s, fileloc loc)
5320 DPRINTF (("Kill complete: %s", sRef_unparseFull (s)));
5321 sRef_aliasSetComplete (sRef_killAux, s, loc);
5324 static bool sRef_equivalent (sRef s1, sRef s2)
5326 return (sRef_compare (s1, s2) == 0);
5330 ** returns an sRef that will not be free'd on function exit.
5333 /*@only@*/ sRef sRef_saveCopy (sRef s)
5337 if (sRef_isValid (s))
5339 bool old = inFunction;
5342 ** Exit the function scope, so this sRef is not
5343 ** stored in the deallocation table.
5347 DPRINTF (("Copying sref: %s", sRef_unparseFull(s)));
5348 ret = sRef_copy (s);
5349 DPRINTF (("Copying ===>: %s", sRef_unparseFull(ret)));
5354 ret = sRef_undefined;
5357 /*@-dependenttrans@*/
5359 /*@=dependenttrans@*/
5362 sRef sRef_copy (sRef s)
5364 if (sRef_isKindSpecial (s))
5367 return s; /* don't copy specials */
5371 if (sRef_isValid (s))
5373 sRef t = sRef_alloc ();
5377 t->modified = s->modified;
5380 t->info = sinfo_copy (s);
5382 t->defstate = s->defstate;
5384 t->nullstate = s->nullstate;
5386 /* start modifications */
5387 t->bufinfo.bufstate = s->bufinfo.bufstate;
5388 t->bufinfo.len = s->bufinfo.len;
5389 t->bufinfo.size = s->bufinfo.size;
5390 /* end modifications */
5392 t->aliaskind = s->aliaskind;
5393 t->oaliaskind = s->oaliaskind;
5395 t->expkind = s->expkind;
5396 t->oexpkind = s->oexpkind;
5398 t->aliasinfo = alinfo_copy (s->aliasinfo);
5399 t->definfo = alinfo_copy (s->definfo);
5400 t->nullinfo = alinfo_copy (s->nullinfo);
5401 t->expinfo = alinfo_copy (s->expinfo);
5403 t->deriv = sRefSet_newDeepCopy (s->deriv);
5409 return sRef_undefined;
5414 # define PREDTEST(func,s) \
5415 do { if (sRef_isInvalid (s)) { return FALSE; } \
5416 else { if (sRef_isConj (s)) \
5417 { return (func (sRef_getConjA (s)) \
5418 || func (sRef_getConjB (s))); }}} while (FALSE);
5420 bool sRef_isAddress (sRef s)
5422 PREDTEST (sRef_isAddress, s);
5423 return (s->kind == SK_ADR);
5427 ** pretty weak... maybe a flag should control this.
5430 bool sRef_isThroughArrayFetch (sRef s)
5432 if (sRef_isValid (s))
5440 if (sRef_isArrayFetch (tref))
5445 lt = sRef_getBase (tref);
5447 } while (sRef_isValid (tref));
5453 bool sRef_isArrayFetch (sRef s)
5455 PREDTEST (sRef_isArrayFetch, s);
5456 return (s->kind == SK_ARRAYFETCH);
5459 bool sRef_isMacroParamRef (sRef s)
5461 if (context_inMacro () && sRef_isCvar (s))
5463 uentry ue = sRef_getUentry (s);
5464 cstring pname = makeParam (uentry_rawName (ue));
5465 uentry mac = usymtab_lookupSafe (pname);
5467 cstring_free (pname);
5468 return (uentry_isValid (mac));
5474 bool sRef_isCvar (sRef s)
5476 PREDTEST (sRef_isCvar, s);
5477 return (s->kind == SK_CVAR);
5480 bool sRef_isConst (sRef s)
5482 PREDTEST (sRef_isConst, s);
5483 return (s->kind == SK_CONST);
5486 bool sRef_isObject (sRef s)
5488 PREDTEST (sRef_isObject, s);
5489 return (s->kind == SK_OBJECT);
5492 bool sRef_isExternal (sRef s)
5494 PREDTEST (sRef_isExternal, s);
5495 return (s->kind == SK_EXTERNAL);
5498 static bool sRef_isDerived (sRef s)
5500 PREDTEST (sRef_isDerived, s);
5501 return (s->kind == SK_DERIVED);
5504 bool sRef_isField (sRef s)
5506 PREDTEST (sRef_isField, s);
5507 return (s->kind == SK_FIELD);
5510 static bool sRef_isIndex (sRef s)
5512 PREDTEST (sRef_isIndex, s);
5513 return (s->kind == SK_ARRAYFETCH);
5516 bool sRef_isAnyParam (sRef s)
5518 PREDTEST (sRef_isAnyParam, s);
5519 return (s->kind == SK_PARAM);
5522 bool sRef_isParam (sRef s)
5524 PREDTEST (sRef_isParam, s);
5525 return (s->kind == SK_PARAM);
5528 bool sRef_isDirectParam (sRef s)
5530 PREDTEST (sRef_isDirectParam, s);
5532 return ((s->kind == SK_CVAR) &&
5533 (s->info->cvar->lexlevel == functionScope) &&
5534 (context_inFunction () &&
5535 (s->info->cvar->index <= uentryList_size (context_getParams ()))));
5538 bool sRef_isPointer (sRef s)
5540 PREDTEST (sRef_isPointer, s);
5541 return (s->kind == SK_PTR);
5545 ** returns true if storage referenced by s is visible
5548 bool sRef_isReference (sRef s)
5550 PREDTEST (sRef_isReference, s);
5552 return (sRef_isPointer (s) || sRef_isIndex (s) || sRef_isGlobal (s)
5553 || (sRef_isField (s) && (sRef_isReference (s->info->field->rec))));
5556 bool sRef_isIReference (sRef s)
5558 return (sRef_isPointer (s) || sRef_isAddress (s) || sRef_isIndex (s)
5559 || sRef_isField (s) || sRef_isArrayFetch (s));
5562 bool sRef_isGlobal (sRef s)
5564 return (sRef_isCvar (s) && (s->info->cvar->lexlevel <= fileScope));
5567 bool sRef_isRealGlobal (sRef s)
5569 return (sRef_isCvar (s) && (s->info->cvar->lexlevel == globScope));
5572 bool sRef_isFileStatic (sRef s)
5574 return (sRef_isCvar (s) && (s->info->cvar->lexlevel == fileScope));
5577 bool sRef_isAliasCheckedGlobal (sRef s)
5579 if (sRef_isGlobal (s))
5581 uentry ue = sRef_getUentry (s);
5583 return context_checkAliasGlob (ue);
5591 void sRef_free (/*@only@*/ sRef s)
5593 if (s != sRef_undefined && s->kind != SK_SPECIAL)
5595 alinfo_free (s->expinfo);
5596 alinfo_free (s->aliasinfo);
5597 alinfo_free (s->definfo);
5598 alinfo_free (s->nullinfo);
5600 sRefSet_free (s->deriv);
5601 s->deriv = sRefSet_undefined;
5608 void sRef_setType (sRef s, ctype t)
5610 if (sRef_isValid (s))
5616 void sRef_setTypeFull (sRef s, ctype t)
5618 if (sRef_isValid (s))
5622 sRefSet_allElements (s->deriv, current)
5624 sRef_setTypeFull (current, ctype_unknown);
5625 } end_sRefSet_allElements ;
5630 sRef_buildField (sRef rec, /*@dependent@*/ cstring f)
5632 return (sRef_buildNCField (rec, f));
5635 static /*@exposed@*/ sRef
5636 sRef_findDerivedField (/*@notnull@*/ sRef rec, cstring f)
5638 sRefSet_allElements (rec->deriv, sr)
5640 if (sRef_isValid (sr))
5642 if (sr->kind == SK_FIELD && cstring_equal (sr->info->field->field, f))
5647 } end_sRefSet_allElements;
5649 return sRef_undefined;
5652 /*@dependent@*/ /*@observer@*/ sRefSet
5653 sRef_derivedFields (sRef rec)
5655 if (sRef_isValid (rec))
5663 return (sRefSet_undefined);
5667 static /*@exposed@*/ sRef
5668 sRef_findDerivedPointer (sRef s)
5670 if (sRef_isValid (s))
5672 sRefSet_realElements (s->deriv, sr)
5674 if (sRef_isValid (sr) && sr->kind == SK_PTR)
5678 } end_sRefSet_realElements;
5681 return sRef_undefined;
5685 sRef_isUnknownArrayFetch (sRef s)
5687 return (sRef_isValid (s)
5688 && s->kind == SK_ARRAYFETCH
5689 && !s->info->arrayfetch->indknown);
5692 static /*@exposed@*/ sRef
5693 sRef_findDerivedArrayFetch (/*@notnull@*/ sRef s, bool isknown, int idx, bool dead)
5698 sRefSet_realElements (s->deriv, sr)
5700 if (sRef_isValid (sr)
5701 && sr->kind == SK_ARRAYFETCH
5702 && sr->info->arrayfetch->indknown
5703 && (sr->info->arrayfetch->ind == idx))
5707 } end_sRefSet_realElements;
5711 sRefSet_realElements (s->deriv, sr)
5713 if (sRef_isValid (sr)
5714 && sr->kind == SK_ARRAYFETCH
5715 && (!sr->info->arrayfetch->indknown
5716 || (sr->info->arrayfetch->indknown &&
5717 sr->info->arrayfetch->ind == 0)))
5719 if (sRef_isDead (sr) || sRef_isKept (sr))
5721 if (dead || context_getFlag (FLG_STRICTUSERELEASED))
5731 } end_sRefSet_realElements;
5734 return sRef_undefined;
5737 static /*@exposed@*/ sRef
5738 sRef_buildNCField (/*@exposed@*/ sRef rec, /*@exposed@*/ cstring f)
5742 if (sRef_isInvalid (rec))
5744 return sRef_undefined;
5748 ** check if the field already has been referenced
5751 s = sRef_findDerivedField (rec, f);
5753 if (sRef_isValid (s))
5759 ctype ct = ctype_realType (rec->type);
5763 s->info = (sinfo) dmalloc (sizeof (*s->info));
5764 s->info->field = (fldinfo) dmalloc (sizeof (*s->info->field));
5765 s->info->field->rec = rec;
5766 s->info->field->field = f; /* doesn't copy f */
5769 if (ctype_isKnown (ct) && ctype_isSU (ct))
5771 uentry ue = uentryList_lookupField (ctype_getFields (ct), f);
5773 if (!uentry_isUndefined (ue))
5775 s->type = uentry_getType (ue);
5777 if (ctype_isMutable (s->type)
5778 && rec->aliaskind != AK_STACK
5779 && !alkind_isStatic (rec->aliaskind))
5781 s->aliaskind = rec->aliaskind;
5785 s->aliaskind = AK_UNKNOWN;
5788 if (sRef_isStateDefined (rec) || sRef_isStateUnknown (rec)
5789 || sRef_isPdefined (rec))
5791 sRef_setStateFromUentry (s, ue);
5795 sRef_setPartsFromUentry (s, ue);
5798 s->oaliaskind = s->aliaskind;
5799 s->oexpkind = s->expkind;
5804 Never report this as an error. It can happen whenever there
5805 is casting involved.
5809 llcontbug (message ("buildNCField --- no field %s: %q / %s",
5810 f, sRef_unparse (s), ctype_unparse (ct)));
5814 return sRef_undefined;
5818 if (rec->defstate == SS_DEFINED
5819 && (s->defstate == SS_UNDEFINED || s->defstate == SS_UNKNOWN))
5821 s->defstate = SS_DEFINED;
5823 else if (rec->defstate == SS_PARTIAL)
5825 s->defstate = SS_PARTIAL;
5827 else if (rec->defstate == SS_ALLOCATED)
5829 if (ctype_isStackAllocated (ct) && ctype_isStackAllocated (s->type))
5831 s->defstate = SS_ALLOCATED;
5835 s->defstate = SS_UNDEFINED;
5838 else if (s->defstate == SS_UNKNOWN)
5840 s->defstate = rec->defstate;
5847 if (s->defstate == SS_UNDEFINED)
5849 ctype rt = ctype_realType (s->type);
5851 if (ctype_isArray (rt) || ctype_isSU (rt))
5853 s->defstate = SS_ALLOCATED;
5857 sRef_addDeriv (rec, s);
5859 if (ctype_isInt (s->type) && cstring_equal (f, REFSNAME))
5861 s->aliaskind = AK_REFS;
5862 s->oaliaskind = AK_REFS;
5870 sRef_isStackAllocated (sRef s)
5872 return (sRef_isValid(s)
5873 && s->defstate == SS_ALLOCATED && ctype_isStackAllocated (s->type));
5877 void sRef_setArrayFetchState (/*@notnull@*/ /*@exposed@*/ sRef s,
5878 /*@notnull@*/ /*@exposed@*/ sRef arr)
5880 if (ctype_isRealAP (arr->type))
5882 s->type = ctype_baseArrayPtr (arr->type);
5885 /* a hack, methinks... makeArrayFetch (&a[0]) ==> a[] */
5886 if (sRef_isAddress (arr))
5888 sRef t = arr->info->ref;
5890 if (sRef_isArrayFetch (t))
5892 s->info->arrayfetch->arr = t->info->arrayfetch->arr;
5895 else if (ctype_isRealPointer (arr->type))
5897 sRef sp = sRef_findDerivedPointer (arr);
5900 if (sRef_isValid (sp))
5903 if (ctype_isMutable (s->type))
5905 sRef_setExKind (s, sRef_getExKind (sp), fileloc_undefined);
5908 s->aliaskind = sp->aliaskind;
5911 s->defstate = sp->defstate;
5913 if (s->defstate == SS_DEFINED)
5915 if (!context_getFlag (FLG_STRICTDESTROY))
5917 s->defstate = SS_PARTIAL;
5921 s->nullstate = sp->nullstate;
5925 if (arr->defstate == SS_UNDEFINED)
5927 s->defstate = SS_UNUSEABLE;
5929 else if ((arr->defstate == SS_ALLOCATED) && !ctype_isSU (s->type))
5931 s->defstate = SS_UNDEFINED;
5935 if (!context_getFlag (FLG_STRICTDESTROY))
5937 s->defstate = SS_PARTIAL;
5941 s->defstate = SS_DEFINED;
5945 ** Very weak checking for array elements.
5947 ** s->defstate = arr->defstate;
5951 sRef_setExKind (s, sRef_getExKind (arr), g_currentloc);
5953 if (arr->aliaskind == AK_LOCAL || arr->aliaskind == AK_FRESH)
5955 s->aliaskind = AK_LOCAL;
5959 s->aliaskind = AK_UNKNOWN;
5962 sRef_setTypeState (s);
5967 if (arr->defstate == SS_DEFINED)
5970 ** Very weak checking for array elements.
5972 ** s->defstate = arr->defstate;
5975 if (context_getFlag (FLG_STRICTDESTROY))
5977 s->defstate = SS_DEFINED;
5981 s->defstate = SS_PARTIAL;
5984 else if (arr->defstate == SS_ALLOCATED)
5986 if (ctype_isRealArray (s->type))
5988 s->defstate = SS_ALLOCATED;
5992 if (!s->info->arrayfetch->indknown)
5995 ** is index is unknown, elements is defined or
5996 ** allocated is any element is!
5999 s->defstate = SS_UNDEFINED;
6001 sRefSet_allElements (arr->deriv, sr)
6003 if (sRef_isValid (sr))
6005 if (sr->defstate == SS_ALLOCATED)
6007 s->defstate = SS_ALLOCATED;
6011 if (sr->defstate == SS_DEFINED)
6013 if (context_getFlag (FLG_STRICTDESTROY))
6015 s->defstate = SS_DEFINED;
6019 s->defstate = SS_PARTIAL;
6026 } end_sRefSet_allElements;
6031 s->defstate = SS_UNDEFINED;
6037 s->defstate = arr->defstate;
6042 ** kludgey way to guess where aliaskind applies
6045 if (ctype_isMutable (s->type)
6046 && !ctype_isPointer (arr->type)
6047 && !alkind_isStatic (arr->aliaskind)
6048 && !alkind_isStack (arr->aliaskind)) /* evs - 2000-06-20: don't pass stack allocation to members */
6050 s->aliaskind = arr->aliaskind;
6054 s->aliaskind = AK_UNKNOWN;
6057 sRef_setTypeState (s);
6060 if (sRef_isObserver (arr))
6062 s->expkind = XO_OBSERVER;
6066 /*@exposed@*/ sRef sRef_buildArrayFetch (/*@exposed@*/ sRef arr)
6070 if (!sRef_isValid (arr)) {
6071 /*@-nullret@*/ return arr /*@=nullret@*/;
6074 if (ctype_isRealPointer (arr->type))
6076 (void) sRef_buildPointer (arr); /* do this to define arr! */
6079 s = sRef_findDerivedArrayFetch (arr, FALSE, 0, FALSE);
6081 if (sRef_isValid (s))
6083 sRef_setExKind (s, sRef_getExKind (arr), g_currentloc);
6090 s->kind = SK_ARRAYFETCH;
6091 s->info = (sinfo) dmalloc (sizeof (*s->info));
6092 s->info->arrayfetch = (ainfo) dmalloc (sizeof (*s->info->arrayfetch));
6093 s->info->arrayfetch->indknown = FALSE;
6094 s->info->arrayfetch->ind = 0;
6095 s->info->arrayfetch->arr = arr;
6096 sRef_setArrayFetchState (s, arr);
6097 s->oaliaskind = s->aliaskind;
6098 s->oexpkind = s->expkind;
6100 if (!context_inProtectVars ())
6102 sRef_addDeriv (arr, s);
6110 sRef_buildArrayFetchKnown (/*@exposed@*/ sRef arr, int i)
6114 if (!sRef_isValid (arr)) {
6115 /*@-nullret@*/ return arr /*@=nullret@*/;
6118 if (ctype_isRealPointer (arr->type))
6120 (void) sRef_buildPointer (arr); /* do this to define arr! */
6123 s = sRef_findDerivedArrayFetch (arr, TRUE, i, FALSE);
6125 if (sRef_isValid (s))
6127 sRef_setExKind (s, sRef_getExKind (arr), g_currentloc);
6134 s->kind = SK_ARRAYFETCH;
6135 s->info = (sinfo) dmalloc (sizeof (*s->info));
6136 s->info->arrayfetch = (ainfo) dmalloc (sizeof (*s->info->arrayfetch));
6137 s->info->arrayfetch->arr = arr;
6138 s->info->arrayfetch->indknown = TRUE;
6139 s->info->arrayfetch->ind = i;
6141 sRef_setArrayFetchState (s, arr);
6143 s->oaliaskind = s->aliaskind;
6144 s->oexpkind = s->expkind;
6145 sRef_addDeriv (arr, s);
6152 ** sets everything except for defstate
6156 sRef_setPartsFromUentry (sRef s, uentry ue)
6159 llassert (sRef_isValid (s));
6161 s->aliaskind = alkind_derive (s->aliaskind, uentry_getAliasKind (ue));
6162 s->oaliaskind = s->aliaskind;
6164 if (s->expkind == XO_UNKNOWN)
6166 s->expkind = uentry_getExpKind (ue);
6169 s->oexpkind = s->expkind;
6171 if (s->nullstate == NS_UNKNOWN)
6173 s->nullstate = sRef_getNullState (uentry_getSref (ue));
6176 if (s->aliaskind == AK_IMPONLY
6177 && (sRef_isExposed (s) || sRef_isObserver (s)))
6179 s->oaliaskind = s->aliaskind = AK_IMPDEPENDENT;
6185 sRef_setStateFromAbstractUentry (sRef s, uentry ue)
6187 llassert (sRef_isValid (s));
6189 sRef_setPartsFromUentry (s, ue);
6191 s->aliaskind = alkind_derive (s->aliaskind, uentry_getAliasKind (ue));
6192 s->oaliaskind = s->aliaskind;
6194 if (s->expkind == XO_UNKNOWN)
6196 s->expkind = uentry_getExpKind (ue);
6199 s->oexpkind = s->expkind;
6203 sRef_setStateFromUentry (sRef s, uentry ue)
6207 llassert (sRef_isValid (s));
6209 sRef_setPartsFromUentry (s, ue);
6211 defstate = uentry_getDefState (ue);
6213 if (sstate_isKnown (defstate))
6215 s->defstate = defstate;
6224 sRef_buildPointer (/*@exposed@*/ sRef t)
6226 DPRINTF (("build pointer: %s", sRef_unparse (t)));
6228 if (sRef_isInvalid (t)) return sRef_undefined;
6230 if (sRef_isAddress (t))
6232 DPRINTF (("Return ref: %s", sRef_unparse (t->info->ref)));
6233 return (t->info->ref);
6237 sRef s = sRef_findDerivedPointer (t);
6239 DPRINTF (("find derived: %s", sRef_unparse (s)));
6241 if (sRef_isValid (s))
6244 sRef_setExKind (s, sRef_getExKind (t), g_currentloc);
6245 s->oaliaskind = s->aliaskind;
6246 s->oexpkind = s->expkind;
6252 s = sRef_constructPointerAux (t);
6254 DPRINTF (("construct: %s", sRef_unparse (s)));
6256 if (sRef_isValid (s))
6258 sRef_addDeriv (t, s);
6260 s->oaliaskind = s->aliaskind;
6261 s->oexpkind = s->expkind;
6270 sRef_constructPointer (sRef t)
6273 return sRef_buildPointer (t);
6276 static /*@exposed@*/ sRef sRef_constructDerefAux (sRef t, bool isdead)
6278 if (sRef_isValid (t))
6283 ** if there is a derived t[?], return that. Otherwise, *t.
6287 s = sRef_findDerivedArrayFetch (t, FALSE, 0, isdead);
6289 if (sRef_isValid (s))
6295 sRef ret = sRef_constructPointer (t);
6298 ** This is necessary to prevent infinite depth
6299 ** in checking complete destruction.
6305 /* ret->defstate = SS_UNKNOWN; */
6316 return sRef_undefined;
6320 sRef sRef_constructDeref (sRef t)
6322 return sRef_constructDerefAux (t, FALSE);
6325 sRef sRef_constructDeadDeref (sRef t)
6327 return sRef_constructDerefAux (t, TRUE);
6331 sRef_constructPointerAux (/*@notnull@*/ /*@exposed@*/ sRef t)
6333 sRef s = sRef_new ();
6338 s->info = (sinfo) dmalloc (sizeof (*s->info));
6341 if (ctype_isRealAP (rt))
6343 s->type = ctype_baseArrayPtr (rt);
6346 st = ctype_realType (s->type);
6349 if (t->defstate == SS_UNDEFINED)
6351 s->defstate = SS_UNUSEABLE;
6353 else if ((t->defstate == SS_ALLOCATED) && !ctype_isSU (st))
6355 s->defstate = SS_UNDEFINED;
6359 s->defstate = t->defstate;
6362 if (t->aliaskind == AK_LOCAL || t->aliaskind == AK_FRESH)
6364 s->aliaskind = AK_LOCAL;
6368 s->aliaskind = AK_UNKNOWN;
6371 sRef_setExKind (s, sRef_getExKind (t), fileloc_undefined);
6372 sRef_setTypeState (s);
6374 s->oaliaskind = s->aliaskind;
6375 s->oexpkind = s->expkind;
6380 bool sRef_hasDerived (sRef s)
6382 return (sRef_isValid (s) && !sRefSet_isEmpty (s->deriv));
6386 sRef_clearDerived (sRef s)
6388 if (sRef_isValid (s))
6390 sRefSet_clear (s->deriv);
6395 sRef_clearDerivedComplete (sRef s)
6398 if (sRef_isValid (s))
6400 sRef base = sRef_getBaseSafe (s);
6402 while (sRef_isValid (base))
6404 sRefSet_clear (base->deriv);
6405 base = sRef_getBaseSafe (base);
6408 sRefSet_clear (s->deriv);
6413 sRef_makePointer (sRef s)
6416 sRef res = sRef_buildPointer (s);
6418 DPRINTF (("Res: %s", sRef_unparse (res)));
6423 ** &a[] => a (this is for out params)
6427 sRef_makeAnyArrayFetch (/*@exposed@*/ sRef arr)
6430 if (sRef_isAddress (arr))
6432 return (arr->info->ref);
6436 return (sRef_buildArrayFetch (arr));
6441 sRef_makeArrayFetch (sRef arr)
6443 return (sRef_buildArrayFetch (arr));
6447 sRef_makeArrayFetchKnown (sRef arr, int i)
6449 return (sRef_buildArrayFetchKnown (arr, i));
6453 sRef_makeField (sRef rec, /*@dependent@*/ cstring f)
6456 ret = sRef_buildField (rec, f);
6461 sRef_makeNCField (sRef rec, /*@dependent@*/ cstring f)
6463 return (sRef_buildNCField (rec, f));
6467 sRef_unparseKindName (sRef s)
6471 if (s == sRef_undefined) return cstring_makeLiteral ("<invalid>");
6473 s = sRef_fixConj (s);
6478 if (sRef_isLocalVar (s))
6480 result = cstring_makeLiteral ("Variable");
6484 result = cstring_makeLiteral ("Undef global");
6488 result = cstring_makeLiteral ("Out parameter");
6491 if (sRef_isAnyParam (s->info->arrayfetch->arr))
6493 result = cstring_makeLiteral ("Out parameter");
6495 else if (sRef_isIndexKnown (s))
6497 result = cstring_makeLiteral ("Array element");
6501 result = cstring_makeLiteral ("Value");
6505 if (sRef_isAnyParam (s->info->ref))
6507 result = cstring_makeLiteral ("Out parameter");
6511 result = cstring_makeLiteral ("Value");
6515 result = cstring_makeLiteral ("Value");
6518 result = cstring_makeLiteral ("Field");
6521 result = cstring_makeLiteral ("Object");
6523 case SK_UNCONSTRAINED:
6524 result = cstring_makeLiteral ("<anything>");
6533 result = cstring_makeLiteral ("<unknown>");
6536 result = cstring_makeLiteral ("<conj>");
6539 result = cstring_makeLiteral ("Storage");
6547 sRef_unparseKindNamePlain (sRef s)
6551 if (s == sRef_undefined) return cstring_makeLiteral ("<invalid>");
6553 s = sRef_fixConj (s);
6558 if (sRef_isLocalVar (s))
6560 result = cstring_makeLiteral ("Variable");
6564 result = cstring_makeLiteral ("Global");
6568 result = cstring_makeLiteral ("Parameter");
6571 if (sRef_isAnyParam (s->info->arrayfetch->arr))
6573 result = cstring_makeLiteral ("Parameter");
6575 else if (sRef_isIndexKnown (s))
6577 result = cstring_makeLiteral ("Array element");
6581 result = cstring_makeLiteral ("Value");
6585 if (sRef_isAnyParam (s->info->ref))
6587 result = cstring_makeLiteral ("Parameter");
6591 result = cstring_makeLiteral ("Value");
6595 result = cstring_makeLiteral ("Value");
6598 result = cstring_makeLiteral ("Field");
6601 result = cstring_makeLiteral ("Object");
6604 result = cstring_makeLiteral ("Storage");
6606 case SK_UNCONSTRAINED:
6607 result = cstring_makeLiteral ("<anything>");
6616 result = cstring_makeLiteral ("<unknown>");
6619 result = cstring_makeLiteral ("<conj>");
6631 sRef_copyState (sRef s1, sRef s2)
6633 if (sRef_isValid (s1) && sRef_isValid (s2))
6635 s1->defstate = s2->defstate;
6637 s1->nullstate = s2->nullstate;
6638 s1->nullinfo = alinfo_update (s1->nullinfo, s2->nullinfo);
6640 /* start modifications */
6641 s1->bufinfo.bufstate = s2->bufinfo.bufstate;
6642 s1->bufinfo.len = s2->bufinfo.len;
6643 s1->bufinfo.size = s2->bufinfo.size;
6644 /* end modifications */
6646 s1->aliaskind = s2->aliaskind;
6647 s1->aliasinfo = alinfo_update (s1->aliasinfo, s2->aliasinfo);
6649 s1->expkind = s2->expkind;
6650 s1->expinfo = alinfo_update (s1->expinfo, s2->expinfo);
6652 s1->safe = s2->safe;
6657 sRef_makeNew (ctype ct, sRef t, cstring name)
6659 sRef s = sRef_new ();
6664 llassert (sRef_isValid (t));
6665 s->defstate = t->defstate;
6667 s->aliaskind = t->aliaskind;
6668 s->oaliaskind = s->aliaskind;
6670 s->nullstate = t->nullstate;
6672 s->expkind = t->expkind;
6673 s->oexpkind = s->expkind;
6675 s->info = (sinfo) dmalloc (sizeof (*s->info));
6676 s->info->fname = name;
6678 /* start modifications */
6679 s->bufinfo.bufstate = t->bufinfo.bufstate;
6680 /* end modifications */
6686 sRef_makeType (ctype ct)
6688 sRef s = sRef_new ();
6693 s->defstate = SS_UNKNOWN;
6694 s->aliaskind = AK_UNKNOWN;
6695 s->nullstate = NS_UNKNOWN;
6696 /* start modification */
6697 s->bufinfo.bufstate = BB_NOTNULLTERMINATED;
6698 /* end modification */
6701 if (ctype_isUA (ct))
6703 typeId uid = ctype_typeId (ct);
6704 uentry ue = usymtab_getTypeEntrySafe (uid);
6706 if (uentry_isValid (ue))
6708 sRef_mergeStateQuiet (s, uentry_getSref (ue));
6712 s->oaliaskind = s->aliaskind;
6713 s->oexpkind = s->expkind;
6719 sRef_makeConst (ctype ct)
6721 sRef s = sRef_new ();
6726 s->defstate = SS_UNKNOWN;
6727 s->aliaskind = AK_UNKNOWN;
6728 s->nullstate = NS_UNKNOWN;
6729 /* start modification */
6730 s->bufinfo.bufstate = BB_NULLTERMINATED;
6731 /* end modification */
6734 if (ctype_isUA (ct))
6736 typeId uid = ctype_typeId (ct);
6737 uentry te = usymtab_getTypeEntrySafe (uid);
6739 if (uentry_isValid (te))
6741 sRef_mergeStateQuiet (s, uentry_getSref (te));
6746 s->oaliaskind = s->aliaskind;
6747 s->oexpkind = s->expkind;
6752 bool sRef_hasName (sRef s)
6754 if (sRef_isInvalid (s))
6763 uentry u = usymtab_getRefQuiet (s->info->cvar->lexlevel,
6764 s->info->cvar->index);
6765 return (uentry_hasName (u));
6769 uentry u = uentryList_getN (context_getParams (),
6772 return (uentry_hasName (u));
6779 bool sRef_sameObject (sRef s1, sRef s2)
6781 return sRef_sameName(s1, s2);
6784 sRef_sameName (sRef s1, sRef s2)
6786 if (sRef_isInvalid (s1))
6788 return sRef_isInvalid (s2);
6791 if (sRef_isInvalid (s2))
6799 if (s2->kind == SK_CVAR)
6801 return (s1->info->cvar->lexlevel == s2->info->cvar->lexlevel
6802 && s1->info->cvar->index == s2->info->cvar->index);
6804 else if (s2->kind == SK_PARAM)
6806 if (context_inFunctionLike ())
6808 uentry u1 = usymtab_getRefQuiet (s1->info->cvar->lexlevel,
6809 s1->info->cvar->index);
6810 uentry u2 = uentryList_getN (context_getParams (),
6813 return (cstring_equalFree (uentry_getName (u1),
6814 uentry_getName (u2)));
6827 if (s2->kind == SK_PARAM)
6829 return (s1->info->paramno == s2->info->paramno);
6831 else if (s2->kind == SK_CVAR)
6833 if (context_inFunctionLike ())
6835 uentry u1 = uentryList_getN (context_getParams (),
6837 uentry u2 = usymtab_getRefQuiet (s2->info->cvar->lexlevel,
6838 s2->info->cvar->index);
6841 return (cstring_equalFree (uentry_getName (u1),
6842 uentry_getName (u2)));
6855 case SK_UNCONSTRAINED:
6859 if (s2->kind == SK_ARRAYFETCH)
6861 if (bool_equal (s1->info->arrayfetch->indknown,
6862 s2->info->arrayfetch->indknown))
6864 if (!s1->info->arrayfetch->indknown
6865 || (s1->info->arrayfetch->ind == s2->info->arrayfetch->ind))
6867 return sRef_sameName (s1->info->arrayfetch->arr,
6868 s2->info->arrayfetch->arr);
6875 if (s2->kind == SK_FIELD)
6877 if (cstring_equal (s1->info->field->field,
6878 s2->info->field->field))
6880 return sRef_sameName (s1->info->field->rec,
6881 s2->info->field->rec);
6890 if (s2->kind == s1->kind)
6892 return sRef_sameName (s1->info->ref,
6900 return sRef_sameName (sRef_getConjA (s1), s2);
6904 return (s2->kind == SK_UNKNOWN);
6907 if (s2->kind == s1->kind)
6909 return (ctype_equal (s1->type, s2->type));
6914 if (s2->kind == SK_SPECIAL)
6916 return (s1->info->spec == s2->info->spec);
6920 return (s2->kind == SK_RESULT);
6928 sRef_fixOuterRef (/*@returned@*/ sRef s)
6930 sRef root = sRef_getRootBase (s);
6932 if (sRef_isCvar (root))
6934 uentry ue = usymtab_getRefQuiet (root->info->cvar->lexlevel,
6935 root->info->cvar->index);
6937 if (uentry_isValid (ue))
6939 sRef uref = uentry_getSref (ue);
6940 sRef sr = sRef_fixBase (s, uref);
6946 llcontbug (message ("sRef_fixOuterRef: undefined: %q", sRef_unparseDebug (s)));
6955 sRef_storeState (sRef s)
6957 if (sRef_isInvalid (s)) return;
6959 s->oaliaskind = s->aliaskind;
6960 s->oexpkind = s->expkind;
6963 static void sRef_resetStateAux (sRef s, /*@unused@*/ fileloc loc)
6965 sRef_resetState (s);
6969 sRef_resetState (sRef s)
6971 bool changed = FALSE;
6972 if (sRef_isInvalid (s)) return;
6975 if (s->oaliaskind == AK_KILLREF && !sRef_isParam (s))
6978 ** killref is used in a kludgey way, to save having to add
6979 ** another alias kind (see usymtab_handleParams)
6982 if (s->expkind != s->oexpkind)
6985 s->expkind = s->oexpkind;
6990 if (s->expkind != s->oexpkind)
6993 s->expkind = s->oexpkind;
6996 if (s->aliaskind != s->oaliaskind
6997 && s->aliaskind != AK_REFCOUNTED
6998 && s->aliaskind != AK_REFS)
7001 s->aliaskind = s->oaliaskind;
7007 sRef_clearDerived (s);
7013 sRef_resetStateComplete (sRef s)
7015 sRef_innerAliasSetComplete (sRef_resetStateAux, s, fileloc_undefined);
7019 sRef_fixBase (/*@returned@*/ sRef s, /*@returned@*/ sRef base)
7021 sRef tmp = sRef_undefined;
7024 if (sRef_isInvalid (s)) return s;
7025 if (sRef_isInvalid (base)) return base;
7035 tmp = sRef_fixBase (s->info->arrayfetch->arr, base);
7037 if (s->info->arrayfetch->indknown)
7039 ret = sRef_makeArrayFetchKnown (tmp, s->info->arrayfetch->ind);
7043 ret = sRef_makeArrayFetch (tmp);
7047 tmp = sRef_fixBase (s->info->field->rec, base);
7048 ret = sRef_buildNCField (tmp, s->info->field->field);
7051 tmp = sRef_fixBase (s->info->ref, base);
7052 ret = sRef_makePointer (tmp);
7055 tmp = sRef_fixBase (s->info->ref, base);
7056 ret = sRef_makeAddress (tmp);
7062 tmp = sRef_fixBase (s->info->conj->a, base);
7063 tmpb = sRef_fixBase (s->info->conj->b, base);
7065 ret = sRef_makeConj (tmp, tmpb);
7074 static /*@exposed@*/ sRef
7075 sRef_fixDirectBase (sRef s, sRef base)
7080 if (sRef_isInvalid (s))
7082 return sRef_undefined;
7088 if (s->info->arrayfetch->indknown)
7090 ret = sRef_makeArrayFetchKnown (base, s->info->arrayfetch->ind);
7094 ret = sRef_makeArrayFetch (base);
7098 ret = sRef_buildNCField (base, s->info->field->field);
7101 ret = sRef_makePointer (base);
7104 ret = sRef_makeAddress (base);
7110 tmpa = sRef_fixDirectBase (s->info->conj->a, base);
7111 tmpb = sRef_fixDirectBase (s->info->conj->b, base);
7113 ret = sRef_makeConj (tmpa, tmpb);
7119 sRef_copyState (ret, s);
7124 sRef_isAllocIndexRef (sRef s)
7126 return (sRef_isArrayFetch (s) && !(s->info->arrayfetch->indknown)
7127 && sRef_isAllocated (s->info->arrayfetch->arr));
7131 sRef_showRefLost (sRef s)
7133 if (sRef_hasAliasInfoLoc (s))
7135 llgenindentmsg (cstring_makeLiteral ("Original reference lost"),
7136 sRef_getAliasInfoLoc (s));
7141 sRef_showRefKilled (sRef s)
7143 if (sRef_hasStateInfoLoc (s))
7145 llgenindentmsg (message ("Storage %q released",
7146 sRef_unparse (s)), sRef_getStateInfoLoc (s));
7151 sRef_showStateInconsistent (sRef s)
7153 if (sRef_hasStateInfoLoc (s))
7156 (message ("Storage %qbecomes inconsistent (released on one branch)",
7157 sRef_unparseOpt (s)),
7158 sRef_getStateInfoLoc (s));
7163 sRef_showStateInfo (sRef s)
7165 if (sRef_hasStateInfoLoc (s))
7167 if (s->defstate == SS_DEAD)
7170 (message ("Storage %qis released", sRef_unparseOpt (s)),
7171 sRef_getStateInfoLoc (s));
7173 else if (s->defstate == SS_ALLOCATED || s->defstate == SS_DEFINED)
7176 (message ("Storage %qis %s", sRef_unparseOpt (s),
7177 sstate_unparse (s->defstate)),
7178 sRef_getStateInfoLoc (s));
7180 else if (s->defstate == SS_UNUSEABLE)
7183 (message ("Storage %qbecomes inconsistent (clauses merge with"
7184 "%qreleased on one branch)",
7185 sRef_unparseOpt (s),
7186 sRef_unparseOpt (s)),
7187 sRef_getStateInfoLoc (s));
7191 llgenindentmsg (message ("Storage %qbecomes %s",
7192 sRef_unparseOpt (s),
7193 sstate_unparse (s->defstate)),
7194 sRef_getStateInfoLoc (s));
7200 sRef_showExpInfo (sRef s)
7202 if (sRef_hasExpInfoLoc (s))
7204 llgenindentmsg (message ("Storage %qbecomes %s", sRef_unparseOpt (s),
7205 exkind_unparse (s->expkind)),
7206 sRef_getExpInfoLoc (s));
7211 sRef_showNullInfo (sRef s)
7213 if (sRef_hasNullInfoLoc (s) && sRef_isKnown (s))
7215 switch (s->nullstate)
7219 fileloc loc = sRef_getNullInfoLoc (s);
7221 if (fileloc_isDefined (loc) && !fileloc_isLib (loc))
7224 (message ("Storage %qbecomes null", sRef_unparseOpt (s)),
7231 fileloc loc = sRef_getNullInfoLoc (s);
7233 if (fileloc_isDefined (loc) && !fileloc_isLib (loc))
7235 llgenindentmsg (message ("Storage %qbecomes null", sRef_unparseOpt (s)),
7243 (message ("Storage %qmay become null", sRef_unparseOpt (s)),
7244 sRef_getNullInfoLoc (s));
7249 (message ("Storage %qbecomes not null", sRef_unparseOpt (s)),
7250 sRef_getNullInfoLoc (s));
7254 (message ("Storage %qnull state becomes unknown",
7255 sRef_unparseOpt (s)),
7256 sRef_getNullInfoLoc (s));
7265 (message ("<error case> Storage %q becomes %s",
7267 nstate_unparse (s->nullstate)),
7268 sRef_getNullInfoLoc (s));
7276 sRef_showAliasInfo (sRef s)
7278 if (sRef_hasAliasInfoLoc (s))
7280 if (sRef_isFresh (s))
7283 (message ("Fresh storage %qallocated", sRef_unparseOpt (s)),
7284 sRef_getAliasInfoLoc (s));
7288 if (!sRef_isRefCounted (s))
7291 (message ("Storage %qbecomes %s",
7292 sRef_unparseOpt (s),
7293 alkind_unparse (sRef_getAliasKind (s))),
7294 sRef_getAliasInfoLoc (s));
7301 sRef_mergeNullState (sRef s, nstate n)
7303 if (sRef_isValid (s))
7309 if (n != old && n != NS_UNKNOWN)
7313 s->nullinfo = alinfo_updateLoc (s->nullinfo, g_currentloc);
7318 llbuglit ("sRef_mergeNullState: invalid");
7323 sRef_possiblyNull (sRef s)
7325 if (sRef_isValid (s))
7327 if (s->nullstate == NS_ABSNULL)
7329 ctype rct = ctype_realType (s->type);
7331 if (ctype_isAbstract (rct))
7337 if (ctype_isUser (rct))
7339 uentry ue = usymtab_getTypeEntry (ctype_typeId (rct));
7341 return (nstate_possiblyNull
7342 (sRef_getNullState (uentry_getSref (ue))));
7352 return nstate_possiblyNull (s->nullstate);
7360 sRef_getScopeName (sRef s)
7362 sRef base = sRef_getRootBase (s);
7364 if (sRef_isRealGlobal (base))
7366 return (cstring_makeLiteralTemp ("Global"));
7368 else if (sRef_isFileStatic (base))
7370 return (cstring_makeLiteralTemp ("Static"));
7374 return (cstring_makeLiteralTemp ("Local"));
7379 sRef_unparseScope (sRef s)
7381 sRef base = sRef_getRootBase (s);
7383 if (sRef_isRealGlobal (base))
7385 return (cstring_makeLiteralTemp ("global"));
7387 else if (sRef_isFileStatic (base))
7389 return (cstring_makeLiteralTemp ("file static"));
7398 sRef_getScope (sRef s)
7400 llassert (sRef_isValid (s));
7402 if (sRef_isCvar (s))
7404 return s->info->cvar->lexlevel;
7406 else if (sRef_isParam (s))
7417 sRef_isDead (sRef s)
7419 return (sRef_isValid (s) && (s)->defstate == SS_DEAD);
7423 sRef_isDeadStorage (sRef s)
7425 if (sRef_isValid (s))
7427 if (s->defstate == SS_DEAD
7428 || s->defstate == SS_UNUSEABLE
7429 || s->defstate == SS_UNDEFINED
7430 || s->defstate == SS_UNKNOWN)
7436 return (sRef_isDefinitelyNull (s));
7446 sRef_isPossiblyDead (sRef s)
7448 return (sRef_isValid (s) && s->defstate == SS_HOFFA);
7451 bool sRef_isStateLive (sRef s)
7453 if (sRef_isValid (s))
7455 sstate ds = s->defstate;
7457 return (!(ds == SS_UNDEFINED
7459 || ds == SS_UNUSEABLE
7460 || ds == SS_HOFFA));
7469 bool sRef_isStateUndefined (sRef s)
7471 return ((sRef_isValid(s)) && ((s)->defstate == SS_UNDEFINED));
7474 bool sRef_isJustAllocated (sRef s)
7476 if (sRef_isAllocated (s))
7478 sRefSet_allElements (s->deriv, el)
7480 if (!(sRef_isStateUndefined (el) || sRef_isUnuseable (el)))
7484 } end_sRefSet_allElements ;
7493 sRef_isAllocatedStorage (sRef s)
7495 if (sRef_isValid (s) && ynm_toBoolStrict (sRef_isReadable (s)))
7497 return (ctype_isVisiblySharable (sRef_getType (s)));
7506 sRef_isUnuseable (sRef s)
7508 return ((sRef_isValid(s)) && ((s)->defstate == SS_UNUSEABLE));
7512 sRef_perhapsNull (sRef s)
7514 if (sRef_isValid (s))
7516 if (s->nullstate == NS_ABSNULL)
7518 ctype rct = ctype_realType (s->type);
7520 if (ctype_isAbstract (rct))
7526 if (ctype_isUser (rct))
7528 uentry ue = usymtab_getTypeEntry (ctype_typeId (rct));
7530 return (nstate_perhapsNull
7531 (sRef_getNullState (uentry_getSref (ue))));
7541 return nstate_perhapsNull (s->nullstate);
7549 ** definitelyNull --- called when TRUE is good
7553 sRef_definitelyNull (sRef s)
7555 return (sRef_isValid (s)
7556 && (s->nullstate == NS_DEFNULL || s->nullstate == NS_CONSTNULL));
7560 ** based on sRef_similar
7564 sRef_setDerivNullState (sRef set, sRef guide, nstate ns)
7566 if (sRef_isValid (set))
7568 sRef deriv = sRef_getDeriv (set, guide);
7570 if (sRef_isValid (deriv))
7572 deriv->nullstate = ns;
7577 static /*@exposed@*/ sRef
7578 sRef_getDeriv (/*@returned@*/ /*@notnull@*/ sRef set, sRef guide)
7580 llassert (sRef_isValid (set));
7581 llassert (sRef_isValid (guide));
7583 switch (guide->kind)
7586 llassert (set->kind == SK_CVAR);
7591 llassert (set->kind == guide->kind);
7592 llassert (set->info->paramno == guide->info->paramno);
7598 if (set->kind == SK_ARRAYFETCH
7599 && (sRef_similar (set->info->arrayfetch->arr,
7600 guide->info->arrayfetch->arr)))
7606 return (sRef_makeAnyArrayFetch
7607 (sRef_getDeriv (set, guide->info->arrayfetch->arr)));
7612 if (set->kind == SK_PTR && sRef_similar (set->info->ref, guide->info->ref))
7618 return (sRef_makePointer (sRef_getDeriv (set, guide->info->ref)));
7623 if ((set->kind == SK_FIELD &&
7624 (sRef_similar (set->info->field->rec, guide->info->field->rec) &&
7625 cstring_equal (set->info->field->field, guide->info->field->field))))
7631 return (sRef_makeField (sRef_getDeriv (set, guide->info->field->rec),
7632 guide->info->field->field));
7636 if ((set->kind == SK_ADR) && sRef_similar (set->info->ref, guide->info->ref))
7642 return (sRef_makeAddress (sRef_getDeriv (set, guide->info->ref)));
7647 return sRef_undefined;
7651 case SK_UNCONSTRAINED:
7659 return sRef_undefined;
7666 ** sRef_aliasCheckPred
7668 ** A confusing but spiffy function:
7670 ** Calls predf (s, e, text, <alias>) on s and all of s's aliases
7671 ** (unless checkAliases (s) is FALSE).
7673 ** For alias calls, calls as
7674 ** predf (alias, e, text, s)
7678 sRef_aliasCheckPred (bool (predf) (sRef, exprNode, sRef, exprNode),
7679 /*@null@*/ bool (checkAliases) (sRef),
7680 sRef s, exprNode e, exprNode err)
7682 bool error = (*predf)(s, e, sRef_undefined, err);
7685 if (checkAliases != NULL && !(checkAliases (s)))
7687 /* don't check aliases */
7691 sRefSet aliases = usymtab_allAliases (s);
7694 sRefSet_realElements (aliases, current)
7696 if (sRef_isValid (current))
7698 if (!sRef_similar (current, s)
7699 || (error && sRef_sameName (current, s)))
7701 (void) (*predf)(current, e, s, err);
7704 } end_sRefSet_realElements;
7706 sRefSet_free (aliases);
7711 ** return TRUE iff predf (s) is true for s or any alias of s
7715 sRef_aliasCheckSimplePred (sRefTest predf, sRef s)
7726 aliases = usymtab_allAliases (s);
7728 sRefSet_realElements (aliases, current)
7730 if (sRef_isValid (current))
7732 sRef cref = sRef_updateSref (current);
7734 /* Whoa! a very kludgey way to make sure the right sref is used
7735 ** where there is a conditional symbol table. I am beginning
7736 ** to think that having a conditional symbol table wasn't such
7743 sRefSet_free (aliases);
7747 } end_sRefSet_realElements;
7749 sRefSet_free (aliases);
7755 sRef_aliasCompleteSimplePred (bool (predf) (sRef), sRef s)
7758 bool result = FALSE;
7761 aliases = usymtab_allAliases (s);
7763 if ((*predf)(s)) result = TRUE;
7766 sRefSet_realElements (aliases, current)
7768 if (sRef_isValid (current))
7770 current = sRef_updateSref (current);
7771 if ((*predf)(current)) result = TRUE;
7773 } end_sRefSet_realElements;
7775 sRefSet_free (aliases);
7780 sRef_aliasSetComplete (void (predf) (sRef, fileloc), sRef s, fileloc loc)
7784 aliases = usymtab_allAliases (s);
7788 sRefSet_realElements (aliases, current)
7790 if (sRef_isValid (current))
7792 current = sRef_updateSref (current);
7793 ((*predf)(current, loc));
7795 } end_sRefSet_realElements;
7797 sRefSet_free (aliases);
7801 sRef_aliasSetCompleteParam (void (predf) (sRef, alkind, fileloc), sRef s,
7802 alkind kind, fileloc loc)
7807 if (sRef_isDeep (s))
7809 aliases = usymtab_allAliases (s);
7813 aliases = usymtab_aliasedBy (s);
7816 (*predf)(s, kind, loc);
7818 sRefSet_realElements (aliases, current)
7820 if (sRef_isValid (current))
7822 current = sRef_updateSref (current);
7823 ((*predf)(current, kind, loc));
7825 } end_sRefSet_realElements;
7827 sRefSet_free (aliases);
7831 sRef_innerAliasSetComplete (void (predf) (sRef, fileloc), sRef s, fileloc loc)
7837 if (!sRef_isValid (s)) return;
7841 ** Type equivalence checking is necessary --- there might be casting.
7848 case SK_UNCONSTRAINED:
7853 inner = s->info->ref;
7854 aliases = usymtab_allAliases (inner);
7855 ct = sRef_getType (inner);
7858 sRefSet_realElements (aliases, current)
7860 if (sRef_isValid (current))
7862 current = sRef_updateSref (current);
7864 if (ctype_equal (ct, sRef_getType (current)))
7866 sRef ptr = sRef_makePointer (current);
7868 ((*predf)(ptr, loc));
7871 } end_sRefSet_realElements;
7873 sRefSet_free (aliases);
7876 inner = s->info->arrayfetch->arr;
7877 aliases = usymtab_allAliases (inner);
7878 ct = sRef_getType (inner);
7880 sRefSet_realElements (aliases, current)
7882 if (sRef_isValid (current))
7884 current = sRef_updateSref (current);
7886 if (ctype_equal (ct, sRef_getType (current)))
7889 if (s->info->arrayfetch->indknown)
7891 sRef af = sRef_makeArrayFetchKnown (current, s->info->arrayfetch->ind);
7893 ((*predf)(af, loc));
7897 sRef af = sRef_makeArrayFetch (current);
7899 ((*predf)(af, loc));
7903 } end_sRefSet_realElements;
7905 sRefSet_free (aliases);
7908 inner = s->info->field->rec;
7909 aliases = usymtab_allAliases (inner);
7910 ct = sRef_getType (inner);
7913 sRefSet_realElements (aliases, current)
7915 if (sRef_isValid (current))
7917 current = sRef_updateSref (current);
7919 if (ctype_equal (ct, sRef_getType (current)))
7921 sRef f = sRef_makeField (current, s->info->field->field);
7926 } end_sRefSet_realElements;
7928 sRefSet_free (aliases);
7931 sRef_innerAliasSetComplete (predf, s->info->conj->a, loc);
7932 sRef_innerAliasSetComplete (predf, s->info->conj->b, loc);
7949 sRef_innerAliasSetCompleteParam (void (predf) (sRef, sRef), sRef s, sRef t)
7955 if (!sRef_isValid (s)) return;
7959 ** Type equivalence checking is necessary --- there might be casting.
7966 case SK_UNCONSTRAINED:
7971 inner = s->info->ref;
7972 aliases = usymtab_allAliases (inner);
7973 ct = sRef_getType (inner);
7976 sRefSet_realElements (aliases, current)
7978 if (sRef_isValid (current))
7980 current = sRef_updateSref (current);
7982 if (ctype_equal (ct, sRef_getType (current)))
7984 sRef ptr = sRef_makePointer (current);
7989 } end_sRefSet_realElements;
7991 sRefSet_free (aliases);
7994 inner = s->info->arrayfetch->arr;
7995 aliases = usymtab_allAliases (inner);
7996 ct = sRef_getType (inner);
7998 sRefSet_realElements (aliases, current)
8000 if (sRef_isValid (current))
8002 current = sRef_updateSref (current);
8004 if (ctype_equal (ct, sRef_getType (current)))
8007 if (s->info->arrayfetch->indknown)
8009 sRef af = sRef_makeArrayFetchKnown (current, s->info->arrayfetch->ind);
8015 sRef af = sRef_makeArrayFetch (current);
8021 } end_sRefSet_realElements;
8023 sRefSet_free (aliases);
8026 inner = s->info->field->rec;
8027 aliases = usymtab_allAliases (inner);
8028 ct = sRef_getType (inner);
8031 sRefSet_realElements (aliases, current)
8033 if (sRef_isValid (current))
8035 current = sRef_updateSref (current);
8037 if (ctype_equal (ct, sRef_getType (current)))
8039 sRef f = sRef_makeField (current, s->info->field->field);
8044 } end_sRefSet_realElements;
8046 sRefSet_free (aliases);
8049 sRef_innerAliasSetCompleteParam (predf, s->info->conj->a, t);
8050 sRef_innerAliasSetCompleteParam (predf, s->info->conj->b, t);
8066 static void sRef_combineExKinds (/*@notnull@*/ sRef res, /*@notnull@*/ sRef other)
8068 exkind a1 = sRef_getExKind (res);
8069 exkind a2 = sRef_getExKind (other);
8071 if (a1 == a2 || a2 == XO_UNKNOWN)
8075 else if (a1 == XO_UNKNOWN)
8077 res->expinfo = alinfo_update (res->expinfo, other->expinfo);
8082 res->expkind = XO_OBSERVER;
8087 ** Currently, this is a very ad hoc implementation, with lots of fixes to
8088 ** make real code work okay. I need to come up with some more general
8089 ** rules or principles here.
8093 sRef_combineAliasKindsError (/*@notnull@*/ sRef res,
8094 /*@notnull@*/ sRef other,
8095 clause cl, fileloc loc)
8097 bool hasError = FALSE;
8098 alkind ares = sRef_getAliasKind (res);
8099 alkind aother = sRef_getAliasKind (other);
8101 if (alkind_isDependent (ares))
8103 if (aother == AK_KEPT)
8105 res->aliasinfo = alinfo_update (res->aliasinfo, other->aliasinfo);
8106 res->aliaskind = AK_KEPT;
8110 if (aother == AK_LOCAL || aother == AK_STATIC
8111 || alkind_isTemp (aother))
8113 res->aliaskind = AK_DEPENDENT;
8117 else if (alkind_isDependent (aother))
8119 if (ares == AK_KEPT)
8121 res->aliaskind = AK_KEPT;
8125 if (ares == AK_LOCAL || ares == AK_STATIC || alkind_isTemp (ares))
8127 res->aliasinfo = alinfo_update (res->aliasinfo, other->aliasinfo);
8128 res->aliaskind = AK_DEPENDENT;
8132 else if ((ares == AK_LOCAL || ares == AK_UNIQUE
8133 || ares == AK_STATIC || alkind_isTemp (ares))
8134 && sRef_isFresh (other))
8137 ** cases like: if (s == NULL) s = malloc...;
8138 ** don't generate errors
8141 if (usymtab_isAltProbablyDeepNull (res))
8143 res->aliaskind = ares;
8150 else if ((aother == AK_LOCAL || aother == AK_UNIQUE
8151 || aother == AK_STATIC || alkind_isTemp (aother))
8152 && sRef_isFresh (res))
8155 ** cases like: if (s == NULL) s = malloc...;
8156 ** don't generate errors
8159 if (usymtab_isProbableDeepNull (other))
8161 res->aliasinfo = alinfo_update (res->aliasinfo, other->aliasinfo);
8162 res->aliaskind = aother;
8169 else if (ares == AK_NEWREF && aother == AK_REFCOUNTED
8170 && sRef_isConst (other))
8172 res->aliaskind = AK_NEWREF;
8174 else if (aother == AK_NEWREF && ares == AK_REFCOUNTED
8175 && sRef_isConst (res))
8177 res->aliasinfo = alinfo_update (res->aliasinfo, other->aliasinfo);
8178 res->aliaskind = AK_NEWREF;
8180 else if (sRef_isLocalVar (res)
8181 && ((ares == AK_KEPT && aother == AK_LOCAL)
8182 || (aother == AK_KEPT && ares == AK_LOCAL)))
8184 res->aliaskind = AK_KEPT;
8193 if (sRef_isThroughArrayFetch (res))
8196 (FLG_BRANCHSTATE, FLG_STRICTBRANCHSTATE,
8198 ("Clauses exit with %q possibly referencing %s storage %s, "
8201 alkind_unparse (aother),
8202 clause_nameTaken (cl),
8203 alkind_unparse (ares),
8204 clause_nameAlternate (cl)),
8207 sRef_showAliasInfo (res);
8208 sRef_showAliasInfo (other);
8209 res->aliaskind = AK_ERROR;
8213 if (ares == AK_KEPT || aother == AK_KEPT)
8215 sRef_maybeKill (res, loc);
8223 message ("Clauses exit with %q referencing %s storage %s, "
8226 alkind_unparse (aother),
8227 clause_nameTaken (cl),
8228 alkind_unparse (ares),
8229 clause_nameAlternate (cl)),
8232 sRef_showAliasInfo (res);
8233 sRef_showAliasInfo (other);
8235 res->aliaskind = AK_ERROR;
8239 res->aliaskind = (sRef_isLocalVar (res) ? AK_LOCAL : AK_UNKNOWN);
8244 sRef_combineAliasKinds (/*@notnull@*/ sRef res, /*@notnull@*/ sRef other,
8245 clause cl, fileloc loc)
8247 alkind ares = sRef_getAliasKind (res);
8248 alkind aother = sRef_getAliasKind (other);
8250 if (alkind_equal (ares, aother)
8251 || aother == AK_UNKNOWN
8252 || aother == AK_ERROR)
8254 ; /* keep current state */
8256 else if (sRef_isDead (res) || sRef_isDead (other))
8258 /* dead error reported (or storage is dead) */
8259 res ->aliaskind = AK_ERROR;
8261 else if (ares == AK_UNKNOWN || ares == AK_ERROR
8262 || sRef_isStateUndefined (res))
8264 res->aliasinfo = alinfo_update (res->aliasinfo, other->aliasinfo);
8265 res->aliaskind = aother;
8267 else if (sRef_isStateUndefined (other))
8271 else if (((ares == AK_UNIQUE || alkind_isTemp (ares))
8272 && aother == AK_LOCAL)
8273 || ((aother == AK_UNIQUE || alkind_isTemp (aother))
8274 && ares == AK_LOCAL))
8276 if (ares != AK_LOCAL)
8278 res->aliasinfo = alinfo_update (res->aliasinfo, other->aliasinfo);
8281 res->aliaskind = AK_LOCAL;
8283 else if ((ares == AK_OWNED && aother == AK_FRESH)
8284 || (aother == AK_OWNED && ares == AK_FRESH))
8286 if (ares != AK_FRESH)
8288 res->aliasinfo = alinfo_update (res->aliasinfo, other->aliasinfo);
8291 res->aliaskind = AK_FRESH;
8293 else if ((ares == AK_KEEP && aother == AK_FRESH) ||
8294 (aother == AK_KEEP && ares == AK_FRESH))
8296 if (ares != AK_KEEP)
8298 res->aliasinfo = alinfo_update (res->aliasinfo, other->aliasinfo);
8301 res->aliaskind = AK_KEEP;
8303 else if ((ares == AK_LOCAL && aother == AK_STACK) ||
8304 (aother == AK_LOCAL && ares == AK_STACK))
8306 if (ares != AK_STACK)
8308 res->aliasinfo = alinfo_update (res->aliasinfo, other->aliasinfo);
8311 res->aliaskind = AK_STACK;
8313 else if ((ares == AK_LOCAL
8314 && (aother == AK_OWNED && sRef_isLocalVar (other)))
8315 || (aother == AK_LOCAL
8316 && (ares == AK_OWNED && sRef_isLocalVar (res))))
8318 if (ares != AK_LOCAL)
8320 res->aliasinfo = alinfo_update (res->aliasinfo, other->aliasinfo);
8323 res->aliaskind = AK_LOCAL;
8325 else if ((ares == AK_FRESH && alkind_isOnly (aother))
8326 || (aother == AK_FRESH && alkind_isOnly (ares)))
8328 res->aliaskind = AK_FRESH;
8330 else if ((aother == AK_FRESH && sRef_definitelyNull (res))
8331 || (ares == AK_FRESH && sRef_definitelyNull (other)))
8333 if (ares != AK_FRESH)
8335 res->aliasinfo = alinfo_update (res->aliasinfo, other->aliasinfo);
8336 res->aliaskind = AK_FRESH;
8339 else if ((sRef_isFresh (res) && sRef_isConst (other))
8340 || (sRef_isFresh (other) && sRef_isConst (res)))
8343 ** for NULL constantants
8347 if (!sRef_isFresh (res))
8349 res->aliasinfo = alinfo_update (res->aliasinfo, other->aliasinfo);
8352 res->aliaskind = AK_FRESH;
8354 else if ((alkind_isStatic (aother) && sRef_isConst (res))
8355 || (alkind_isStatic (ares) && sRef_isConst (other)))
8357 if (!alkind_isStatic (ares))
8359 res->aliasinfo = alinfo_update (res->aliasinfo, other->aliasinfo);
8360 res->aliaskind = AK_STATIC;
8365 sRef_combineAliasKindsError (res, other, cl, loc);
8369 static void sRef_combineDefState (/*@notnull@*/ sRef res,
8370 /*@notnull@*/ sRef other)
8372 sstate s1 = res->defstate;
8373 sstate s2 = other->defstate;
8376 if (s1 == s2 || s2 == SS_UNKNOWN)
8380 else if (s1 == SS_UNKNOWN)
8389 if (s2 == SS_DEFINED)
8395 llcontbuglit ("ssfixed: not implemented");
8404 flip = (s2 != SS_DEFINED);
8422 res->definfo = alinfo_update (res->definfo, other->definfo);
8427 extern /*@notnull@*/ sRef sRef_getConjA (sRef s)
8430 llassert (sRef_isConj (s));
8432 ret = s->info->conj->a;
8433 llassert (ret != NULL);
8437 extern /*@notnull@*/ sRef sRef_getConjB (sRef s)
8440 llassert (sRef_isConj (s));
8442 ret = s->info->conj->b;
8443 llassert (ret != NULL);
8447 extern /*@exposed@*/ sRef sRef_makeArrow (sRef s, /*@dependent@*/ cstring f)
8452 p = sRef_makePointer (s);
8453 ret = sRef_makeField (p, f);
8457 extern /*@exposed@*/ sRef sRef_buildArrow (sRef s, cstring f)
8462 p = sRef_buildPointer (s);
8463 ret = sRef_buildField (p, f);
8468 static /*@null@*/ sinfo sinfo_copy (/*@notnull@*/ sRef s)
8475 ret = (sinfo) dmalloc (sizeof (*ret));
8476 ret->cvar = (cref) dmalloc (sizeof (*ret->cvar));
8477 ret->cvar->lexlevel = s->info->cvar->lexlevel;
8478 ret->cvar->index = s->info->cvar->index;
8482 ret = (sinfo) dmalloc (sizeof (*ret));
8483 ret->paramno = s->info->paramno;
8487 ret = (sinfo) dmalloc (sizeof (*ret));
8488 ret->arrayfetch = (ainfo) dmalloc (sizeof (*ret->arrayfetch));
8489 ret->arrayfetch->indknown = s->info->arrayfetch->indknown;
8490 ret->arrayfetch->ind = s->info->arrayfetch->ind;
8491 ret->arrayfetch->arr = s->info->arrayfetch->arr;
8495 ret = (sinfo) dmalloc (sizeof (*ret));
8496 ret->field = (fldinfo) dmalloc (sizeof (*ret->field));
8497 ret->field->rec = s->info->field->rec;
8498 ret->field->field = s->info->field->field;
8502 ret = (sinfo) dmalloc (sizeof (*ret));
8503 ret->object = s->info->object;
8510 ret = (sinfo) dmalloc (sizeof (*ret));
8511 ret->ref = s->info->ref;
8515 ret = (sinfo) dmalloc (sizeof (*ret));
8516 ret->conj = (cjinfo) dmalloc (sizeof (*ret->conj));
8517 ret->conj->a = s->info->conj->a;
8518 ret->conj->b = s->info->conj->b;
8521 ret = (sinfo) dmalloc (sizeof (*ret));
8522 ret->spec = s->info->spec;
8524 case SK_UNCONSTRAINED:
8526 ret = (sinfo) dmalloc (sizeof (*ret));
8527 ret->fname = s->info->fname;
8533 llassertprint (s->info == NULL, ("s = %s", sRef_unparse (s)));
8541 static /*@null@*/ sinfo sinfo_fullCopy (/*@notnull@*/ sRef s)
8546 ** Since its a full copy, only storage is assigned
8547 ** to dependent fields.
8554 ret = (sinfo) dmalloc (sizeof (*ret));
8555 ret->cvar = (cref) dmalloc (sizeof (*ret->cvar));
8556 ret->cvar->lexlevel = s->info->cvar->lexlevel;
8557 ret->cvar->index = s->info->cvar->index;
8561 ret = (sinfo) dmalloc (sizeof (*ret));
8562 ret->paramno = s->info->paramno;
8566 ret = (sinfo) dmalloc (sizeof (*ret));
8567 ret->arrayfetch = (ainfo) dmalloc (sizeof (*ret->arrayfetch));
8568 ret->arrayfetch->indknown = s->info->arrayfetch->indknown;
8569 ret->arrayfetch->ind = s->info->arrayfetch->ind;
8570 ret->arrayfetch->arr = sRef_saveCopy (s->info->arrayfetch->arr);
8574 ret = (sinfo) dmalloc (sizeof (*ret));
8575 ret->field = (fldinfo) dmalloc (sizeof (*ret->field));
8576 ret->field->rec = sRef_saveCopy (s->info->field->rec);
8577 ret->field->field = s->info->field->field;
8581 ret = (sinfo) dmalloc (sizeof (*ret));
8582 ret->object = s->info->object;
8589 ret = (sinfo) dmalloc (sizeof (*ret));
8590 ret->ref = sRef_saveCopy (s->info->ref);
8594 ret = (sinfo) dmalloc (sizeof (*ret));
8595 ret->conj = (cjinfo) dmalloc (sizeof (*ret->conj));
8596 ret->conj->a = sRef_saveCopy (s->info->conj->a);
8597 ret->conj->b = sRef_saveCopy (s->info->conj->b);
8600 ret = (sinfo) dmalloc (sizeof (*ret));
8601 ret->spec = s->info->spec;
8604 case SK_UNCONSTRAINED:
8605 ret = (sinfo) dmalloc (sizeof (*ret));
8606 ret->fname = s->info->fname;
8612 llassert (s->info == NULL);
8622 sinfo_update (/*@notnull@*/ /*@exposed@*/ sRef res,
8623 /*@notnull@*/ /*@exposed@*/ sRef other)
8625 llassert (res->kind == other->kind);
8630 res->info->cvar->lexlevel = other->info->cvar->lexlevel;
8631 res->info->cvar->index = other->info->cvar->index;
8635 res->info->paramno = other->info->paramno;
8639 res->info->arrayfetch->indknown = other->info->arrayfetch->indknown;
8640 res->info->arrayfetch->ind = other->info->arrayfetch->ind;
8641 res->info->arrayfetch->arr = other->info->arrayfetch->arr;
8645 res->info->field->rec = other->info->field->rec;
8646 res->info->field->field = other->info->field->field;
8650 res->info->object = other->info->object;
8657 res->info->ref = other->info->ref;
8661 res->info->conj->a = other->info->conj->a;
8662 res->info->conj->b = other->info->conj->b;
8666 res->info->spec = other->info->spec;
8670 case SK_UNCONSTRAINED:
8671 res->info->fname = other->info->fname;
8678 llassert (res->info == NULL);
8683 static void sinfo_free (/*@special@*/ /*@temp@*/ /*@notnull@*/ sRef s)
8684 /*@uses s->kind, s->info@*/
8685 /*@releases s->info@*/
8690 sfree (s->info->cvar);
8697 sfree (s->info->arrayfetch);
8701 sfree (s->info->field);
8714 sfree (s->info->conj);
8717 case SK_UNCONSTRAINED:
8730 bool sRef_isNSLocalVar (sRef s)
8732 if (sRef_isLocalVar (s))
8734 uentry ue = sRef_getUentry (s);
8736 return (!uentry_isStatic (ue));
8744 bool sRef_isLocalVar (sRef s)
8746 if (sRef_isValid(s))
8748 return (s->kind == SK_CVAR
8749 && (s->info->cvar->lexlevel > fileScope));
8755 bool sRef_isRealLocalVar (sRef s)
8757 if (sRef_isValid(s))
8759 if (s->kind == SK_CVAR)
8761 if (s->info->cvar->lexlevel == functionScope)
8763 uentry ue = sRef_getUentry (s);
8765 if (uentry_isAnyParam (ue)
8766 || uentry_isRefParam (ue))
8777 return (s->info->cvar->lexlevel > functionScope);
8785 bool sRef_isLocalParamVar (sRef s)
8787 if (sRef_isValid(s))
8789 return (s->kind == SK_PARAM
8790 || (s->kind == SK_CVAR
8791 && (s->info->cvar->lexlevel > fileScope)));
8797 static speckind speckind_fromInt (int i)
8800 llassert (i >= SR_NOTHING && i <= SR_SYSTEM);
8803 return ((speckind) i);
8806 void sRef_combineNullState (/*@notnull@*/ sRef res, /*@notnull@*/ sRef other)
8808 nstate n1 = res->nullstate;
8809 nstate n2 = other->nullstate;
8813 if (n1 == n2 || n2 == NS_UNKNOWN)
8819 /* note: n2 is not unknown or defnull */
8823 case NS_ERROR: nn = NS_ERROR; break;
8824 case NS_UNKNOWN: flip = TRUE; nn = n2; break;
8825 case NS_POSNULL: break;
8826 case NS_DEFNULL: nn = NS_POSNULL; break;
8827 case NS_RELNULL: break;
8829 if (n2 == NS_MNOTNULL)
8840 if (n2 == NS_NOTNULL)
8859 res->nullinfo = alinfo_update (res->nullinfo, other->nullinfo);
8862 res->nullstate = nn;
8865 cstring sRef_nullMessage (sRef s)
8867 llassert (sRef_isValid (s));
8869 switch (s->nullstate)
8873 return (cstring_makeLiteralTemp ("null"));
8875 return (cstring_makeLiteralTemp ("possibly null"));
8880 /*@observer@*/ cstring sRef_ntMessage (sRef s)
8882 llassert (sRef_isValid (s));
8884 switch (s->nullstate)
8888 return (cstring_makeLiteralTemp ("not nullterminated"));
8890 return (cstring_makeLiteralTemp ("possibly non-nullterminated"));
8897 sRef sRef_fixResultType (/*@returned@*/ sRef s, ctype typ, uentry ue)
8899 sRef tmp = sRef_undefined;
8902 llassert (sRef_isValid (s));
8913 tmp = sRef_fixResultType (s->info->arrayfetch->arr, typ, ue);
8915 ct = ctype_realType (sRef_getType (tmp));
8918 if (ctype_isKnown (ct))
8920 if (ctype_isAP (ct))
8929 ("Special clause indexes non-array (%t): *%q",
8930 ct, sRef_unparse (s->info->arrayfetch->arr)),
8931 uentry_whereLast (ue));
8935 tmp = sRef_fixResultType (s->info->arrayfetch->arr, typ, ue);
8937 if (s->info->arrayfetch->indknown)
8939 ret = sRef_makeArrayFetchKnown (tmp, s->info->arrayfetch->ind);
8943 ret = sRef_makeArrayFetch (tmp);
8949 sRef rec = sRef_fixResultType (s->info->field->rec, typ, ue);
8950 ctype ct = ctype_realType (sRef_getType (rec));
8952 if (ctype_isKnown (ct))
8954 if (ctype_isSU (ct))
8956 if (uentry_isValid (uentryList_lookupField (ctype_getFields (ct),
8957 s->info->field->field)))
8966 ("Special clause accesses non-existent field of result: %q.%s",
8967 sRef_unparse (rec), s->info->field->field),
8968 uentry_whereLast (ue));
8976 ("Special clause accesses field of non-struct or union result (%t): %q.%s",
8977 ct, sRef_unparse (rec), s->info->field->field),
8978 uentry_whereLast (ue));
8982 ret = sRef_makeField (tmp, s->info->field->field);
8988 tmp = sRef_fixResultType (s->info->ref, typ, ue);
8990 ct = ctype_realType (sRef_getType (tmp));
8992 if (ctype_isKnown (ct))
8994 if (ctype_isAP (ct))
9003 ("Special clause dereferences non-pointer (%t): *%q",
9004 ct, sRef_unparse (s->info->ref)),
9005 uentry_whereLast (ue));
9009 ret = sRef_makePointer (tmp);
9016 ("Special clause uses & operator (not allowed): &%q", sRef_unparse (s->info->ref)),
9017 uentry_whereLast (ue));
9026 bool sRef_isOnly (sRef s)
9028 return (sRef_isValid(s) && alkind_isOnly (s->aliaskind));
9031 bool sRef_isDependent (sRef s)
9033 return (sRef_isValid(s) && alkind_isDependent (s->aliaskind));
9036 bool sRef_isOwned (sRef s)
9038 return (sRef_isValid (s) && (s->aliaskind == AK_OWNED));
9041 bool sRef_isKeep (sRef s)
9043 return (sRef_isValid (s) && (s->aliaskind == AK_KEEP));
9046 bool sRef_isTemp (sRef s)
9048 return (sRef_isValid (s) && alkind_isTemp (s->aliaskind));
9051 bool sRef_isLocalState (sRef s)
9053 return (sRef_isValid (s) && (s->aliaskind == AK_LOCAL));
9056 bool sRef_isUnique (sRef s)
9058 return (sRef_isValid (s) && (s->aliaskind == AK_UNIQUE));
9061 bool sRef_isShared (sRef s)
9063 return (sRef_isValid (s) && (s->aliaskind == AK_SHARED));
9066 bool sRef_isExposed (sRef s)
9068 return (sRef_isValid (s) && (s->expkind == XO_EXPOSED));
9071 bool sRef_isObserver (sRef s)
9073 return (sRef_isValid (s) && (s->expkind == XO_OBSERVER));
9076 bool sRef_isFresh (sRef s)
9078 return (sRef_isValid (s) && (s->aliaskind == AK_FRESH));
9081 bool sRef_isDefinitelyNull (sRef s)
9083 return (sRef_isValid (s) && (s->nullstate == NS_DEFNULL
9084 || s->nullstate == NS_CONSTNULL));
9087 bool sRef_isAllocated (sRef s)
9089 return (sRef_isValid (s) && (s->defstate == SS_ALLOCATED));
9092 bool sRef_isStack (sRef s)
9094 return (sRef_isValid (s) && (s->aliaskind == AK_STACK));
9097 extern bool sRef_isNotNull (sRef s)
9099 return (sRef_isValid(s) && (s->nullstate == NS_MNOTNULL
9100 || s->nullstate == NS_NOTNULL));
9103 /* start modifications */
9104 struct _bbufinfo sRef_getNullTerminatedState (sRef p_s) {
9105 struct _bbufinfo BUFSTATE_UNKNOWN;
9106 BUFSTATE_UNKNOWN.bufstate = BB_NOTNULLTERMINATED;
9107 BUFSTATE_UNKNOWN.size = 0;
9108 BUFSTATE_UNKNOWN.len = 0;
9110 if (sRef_isValid(p_s))
9111 return p_s->bufinfo;
9112 return BUFSTATE_UNKNOWN;
9115 void sRef_setNullTerminatedState(sRef p_s) {
9116 if(sRef_isValid (p_s)) {
9117 p_s->bufinfo.bufstate = BB_NULLTERMINATED;
9119 llfatalbug( message("sRef_setNT passed a invalid sRef\n"));
9124 void sRef_setPossiblyNullTerminatedState(sRef p_s) {
9125 if( sRef_isValid (p_s)) {
9126 p_s->bufinfo.bufstate = BB_POSSIBLYNULLTERMINATED;
9128 llfatalbug( message("sRef_setPossNT passed a invalid sRef\n"));
9132 void sRef_setNotNullTerminatedState(sRef p_s) {
9133 if( sRef_isValid (p_s)) {
9134 p_s->bufinfo.bufstate = BB_NOTNULLTERMINATED;
9136 llfatalbug( message("sRef_unsetNT passed a invalid sRef\n"));
9140 void sRef_setLen(sRef p_s, int len) {
9141 if( sRef_isValid (p_s) && sRef_isNullTerminated(p_s)) {
9142 p_s->bufinfo.len = len;
9144 llfatalbug( message("sRef_setLen passed a invalid sRef\n"));
9149 void sRef_setSize(sRef p_s, int size) {
9150 if( sRef_isValid(p_s)) {
9151 p_s->bufinfo.size = size;
9153 llfatalbug( message("sRef_setSize passed a invalid sRef\n"));
9157 void sRef_resetLen(sRef p_s) {
9158 if (sRef_isValid (p_s)) {
9159 p_s->bufinfo.len = 0;
9161 llfatalbug (message ("sRef_setLen passed an invalid sRef\n"));
9165 /*drl7x 11/28/2000 */
9167 bool sRef_isFixedArray (sRef p_s) /*@*/ {
9169 c = sRef_getType (p_s);
9170 return ( ctype_isFixedArray (c) );
9173 long int sRef_getArraySize (sRef p_s) /*@*/ {
9175 llassert (sRef_isFixedArray(p_s) );
9176 DPRINTF (( message ("sRef_getArraySize getting array size for %s", sRef_unparse(p_s) ) ));
9178 c = sRef_getType (p_s);
9180 return (ctype_getArraySize (c) );