2 ** Splint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2003 University of Virginia,
4 ** Massachusetts Institute of Technology
6 ** This program is free software; you can redistribute it and/or modify it
7 ** under the terms of the GNU General Public License as published by the
8 ** Free Software Foundation; either version 2 of the License, or (at your
9 ** option) any later version.
11 ** This program is distributed in the hope that it will be useful, but
12 ** WITHOUT ANY WARRANTY; without even the implied warranty of
13 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 ** General Public License for more details.
16 ** The GNU General Public License is available from http://www.gnu.org/ or
17 ** the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
18 ** MA 02111-1307, USA.
20 ** For information on splint: info@splint.org
21 ** To report a bug: splint-bug@splint.org
22 ** For more information: http://www.splint.org
28 ** storeRef's are kept in allRefs for each function scope, and all are
29 ** free'd at the end of the function. This relies on the constraint that
30 ** no storeRef created while checking a function is used outside that
33 ** storeRefs in the file and global scopes are free'd by the uentry.
37 # include "splintMacros.nf"
39 # include "sRefTable.h"
40 # include "structNames.h"
43 ** Predicate functions that evaluate both arguments in order.
47 # define OR(a,b) (a ? (b, TRUE) : b)
50 # define AND(a,b) (a ? b : (b, FALSE))
52 static bool sRef_isDerived (sRef p_s
) /*@*/ ;
54 static /*@exposed@*/ sRef
sRef_fixDirectBase (sRef p_s
, sRef p_base
)
55 /*@modifies p_base@*/ ;
57 static void sRef_updateNullState (sRef p_res
, sRef p_other
) /*@modifies p_res@*/ ;
59 static bool sRef_isAllocatedStorage (sRef p_s
) /*@*/ ;
60 static void sRef_setNullErrorLoc (sRef p_s
, fileloc
) /*@*/ ;
61 static void sRef_setNullStateN (sRef p_s
, nstate p_n
) /*@modifies p_s@*/ ;
63 static int sRef_depth (sRef p_s
) /*@*/ ;
66 sRef_innerAliasSetComplete (void (p_predf
) (sRef
, fileloc
), sRef p_s
,
71 sRef_innerAliasSetCompleteParam (void (p_predf
) (sRef
, sRef
), sRef p_s
, sRef p_t
)
74 static speckind
speckind_fromInt (int p_i
);
75 static bool sRef_equivalent (sRef p_s1
, sRef p_s2
);
76 static bool sRef_isDeepUnionField (sRef p_s
);
77 static void sRef_addDeriv (/*@notnull@*/ sRef p_s
, /*@notnull@*/ /*@exposed@*/ sRef p_t
);
78 static bool sRef_checkModify (sRef p_s
, sRefSet p_sl
) /*@*/ ;
81 ** If s is definitely null, it has no memory state.
84 static void sRef_resetAliasKind (/*@notnull@*/ sRef s
) /*@modifies s->aliaskind@*/
86 if (s
->nullstate
== NS_DEFNULL
)
88 /* s->aliaskind = AK_ERROR; */
93 extern void sRef_checkCompletelyReasonable (sRef s
) /*@*/
95 DPRINTF (("Check sRef: [%p] %s / %s", s
, sRef_unparse (s
),
96 sRefSet_unparse (sRef_derivedFields (s
))));
98 if (sRef_isReasonable (s
))
100 sRefSet_elements (s
->deriv
, el
)
103 sRef_checkCompletelyReasonable (el
);
104 } end_sRefSet_elements
;
109 static /*@falsewhennull@*/ bool sRef_isReasonable (sRef s
) /*@*/
111 if (sRef_isValid (s
))
114 if (!bool_isReasonable (s
->safe
)
115 || !bool_isReasonable (s
->modified
)
116 || !bool_isReasonable (s
->immut
))
118 llcontbug (message ("Unreasonable sRef [%p]", s
));
122 if (!sstate_isValid (s
->defstate
))
124 llcontbug (message ("Unreasonable sRef [%p]", s
));
128 if (!nstate_isValid (s
->nullstate
))
130 llcontbug (message ("Unreasonable sRef [%p]", s
));
134 if (!alkind_isValid (s
->aliaskind
)
135 || !alkind_isValid (s
->oaliaskind
))
137 llcontbug (message ("Unreasonable sRef [%p]", s
));
141 if (!exkind_isValid (s
->expkind
)
142 || !exkind_isValid (s
->oexpkind
))
144 llcontbug (message ("Unreasonable sRef [%p]", s
));
155 static /*@nullwhentrue@*/ bool sRef_isUnreasonable (sRef s
) /*@*/
157 return (!sRef_isReasonable (s
));
160 static void sRef_checkMutable (/*@unused@*/ sRef s
)
162 if (sRef_isReasonable (s
) && s
->immut
)
164 llcontbug (message ("Modification to sRef marked immutable: %q",
165 sRef_unparseFull (s
)));
169 static bool skind_isSimple (skind sk
)
173 case SK_PARAM
: case SK_CVAR
: case SK_CONST
:
174 case SK_OBJECT
: case SK_UNKNOWN
: case SK_NEW
:
181 static void sinfo_free (/*@special@*/ /*@temp@*/ /*@notnull@*/ sRef p_s
)
182 /*@uses p_s->kind, p_s->info@*/
183 /*@releases p_s->info@*/ ;
185 static /*@null@*/ sinfo
sinfo_copy (/*@notnull@*/ sRef p_s
) /*@*/ ;
186 static void sRef_setPartsFromUentry (sRef p_s
, uentry p_ue
)
188 static bool checkDeadState (/*@notnull@*/ sRef p_el
, /*@null@*/ sRef p_e2
,
189 bool p_tbranch
, fileloc p_loc
);
190 static /*@dependent@*/ sRef
sRef_constructPointerAux (/*@notnull@*/ /*@exposed@*/ sRef p_t
) /*@*/ ;
193 sRef_combineExKinds (/*@notnull@*/ sRef p_res
, /*@notnull@*/ sRef p_other
)
194 /*@modifies p_res@*/ ;
197 sRef_combineAliasKinds (/*@notnull@*/ sRef p_res
, /*@notnull@*/ sRef p_other
,
198 clause p_cl
, fileloc p_loc
)
199 /*@modifies p_res@*/ ;
202 sRef_combineNullState (/*@notnull@*/ sRef p_res
, /*@notnull@*/ sRef p_other
)
203 /*@modifies p_res@*/ ;
206 sRef_combineDefState (/*@notnull@*/ sRef p_res
, /*@notnull@*/ sRef p_other
)
207 /*@modifies p_res@*/ ;
209 static void sRef_setStateFromAbstractUentry (sRef p_s
, uentry p_ue
)
213 sinfo_update (/*@notnull@*/ /*@exposed@*/ sRef p_res
,
214 /*@notnull@*/ /*@exposed@*/ sRef p_other
);
215 static void sRef_setDefinedAux (sRef p_s
, fileloc p_loc
, bool p_clear
)
217 static void sRef_setDefinedNoClear (sRef p_s
, fileloc p_loc
)
219 static void sRef_setStateAux (sRef p_s
, sstate p_ss
, fileloc p_loc
)
222 static /*@exposed@*/ sRef
223 sRef_buildNCField (/*@exposed@*/ sRef p_rec
, /*@exposed@*/ cstring p_f
);
226 sRef_mergeStateAux (/*@notnull@*/ sRef p_res
, /*@notnull@*/ sRef p_other
,
227 clause p_cl
, bool p_opt
, fileloc p_loc
,
229 /*@modifies p_res, p_other@*/ ;
231 static /*@null@*/ sinfo
sinfo_fullCopy (/*@notnull@*/ sRef p_s
);
232 static bool sRef_doModify (sRef p_s
, sRefSet p_sl
) /*@modifies p_s@*/ ;
233 static bool sRef_doModifyVal (sRef p_s
, sRefSet p_sl
) /*@modifies p_s@*/;
234 static bool sRef_checkModifyVal (sRef p_s
, sRefSet p_sl
) /*@*/ ;
236 static /*@only@*/ sRefSet
237 sRef_mergeDerivs (/*@only@*/ sRefSet p_res
, sRefSet p_other
,
238 bool p_opt
, clause p_cl
, fileloc p_loc
);
240 static /*@only@*/ sRefSet
241 sRef_mergeUnionDerivs (/*@only@*/ sRefSet p_res
,
242 /*@exposed@*/ sRefSet p_other
,
243 bool p_opt
, clause p_cl
, fileloc p_loc
);
245 static /*@only@*/ sRefSet
246 sRef_mergePdefinedDerivs (/*@only@*/ sRefSet p_res
, sRefSet p_other
, bool p_opt
,
247 clause p_cl
, fileloc p_loc
);
249 static /*@only@*/ cstring
sRef_unparseWithArgs (sRef p_s
, uentryList p_args
);
250 static /*@only@*/ cstring
sRef_unparseNoArgs (sRef p_s
);
252 static /*@exposed@*/ sRef
sRef_findDerivedPointer (sRef p_s
);
253 static /*@exposed@*/ sRef
sRef_findDerivedArrayFetch (/*@notnull@*/ sRef
, bool, int, bool) ;
254 static /*@exposed@*/ sRef
sRef_findDerivedField (/*@notnull@*/ sRef p_rec
, cstring p_f
);
255 static /*@exposed@*/ sRef
256 sRef_getDeriv (/*@notnull@*/ /*@returned@*/ sRef p_set
, sRef p_guide
);
258 static bool inFunction
= FALSE
;
259 static /*@only@*/ sRefTable allRefs
;
261 /* # define DEBUGREFS */
265 static totnsrefs
= 0;
266 static maxnsrefs
= 0;
267 static ntotrefers
= 0;
271 static /*@checked@*/ bool protectDerivs
= FALSE
;
274 ** Result of sRef_alloc is dependent since allRefs may
275 ** reference it. It is only if !inFunction.
278 static /*@dependent@*/ /*@out@*/ /*@notnull@*/ sRef
281 sRef s
= (sRef
) dmalloc (sizeof (*s
));
285 DPRINTF (("Alloc sref: [%p]", s
));
289 allRefs
= sRefTable_add (allRefs
, s
);
294 DPRINTF (("Not in function!"));
300 if (nsrefs
>= maxnsrefs
)
309 /*@-mustfree@*/ /*@-freshtrans@*/
311 /*@=mustfree@*/ /*@=freshtrans@*/
315 static void sRef_checkValidAux (sRef s
, sRefSet checkedsofar
)
319 if (!sRef_isReasonable (s
)) return;
321 if (sRefSet_containsSameObject (checkedsofar
, s
))
327 checkedsofar
= sRefSet_insert (checkedsofar
, s
);
328 /*@=temptrans@*/ /* checksofar will be destroyed before checkValid returns */
332 case SK_UNCONSTRAINED
:
333 llassert (cstring_length (s
->info
->fname
) < 100);
337 llassert (s
->info
->cvar
->lexlevel
>= 0);
339 llassert (s
->info
->cvar
->lexlevel
<= usymtab_getCurrentDepth ());
344 llassert (s
->info
->paramno
>= -1);
345 llassert (s
->info
->paramno
<= 999); /* sanity check */
349 sRef_checkValidAux (s
->info
->arrayfetch
->arr
, checkedsofar
);
353 sRef_checkValidAux (s
->info
->field
->rec
, checkedsofar
);
354 llassert (cstring_length (s
->info
->field
->field
) < 100);
358 sRef_checkValidAux (s
->info
->ref
, checkedsofar
);
362 sRef_checkValidAux (s
->info
->ref
, checkedsofar
);
366 /* check ctype s->info->object */
370 sRef_checkValidAux (s
->info
->conj
->a
, checkedsofar
);
371 sRef_checkValidAux (s
->info
->conj
->b
, checkedsofar
);
375 llassert (cstring_length (s
->info
->fname
) < 100);
379 sRef_checkValidAux (s
->info
->ref
, checkedsofar
);
383 sRef_checkValidAux (s
->info
->ref
, checkedsofar
);
389 /* check ctyp s->type */
393 llassert (s
->info
->spec
== SR_NOTHING
394 || s
->info
->spec
== SR_INTERNAL
395 || s
->info
->spec
== SR_SPECSTATE
396 || s
->info
->spec
== SR_SYSTEM
);
406 sRefSet_elements (s
->deriv
, el
)
408 sRef_checkValidAux (el
, checkedsofar
);
409 } end_sRefSet_elements
;
414 static /*@maynotreturn@*/ void sRef_checkValid (/*@temp@*/ sRef s
) /*@modifies stderr@*/
416 sRefSet checkedsofar
= sRefSet_new ();
417 sRef_checkValidAux (s
, checkedsofar
);
421 static /*@dependent@*/ /*@notnull@*/ /*@special@*/ sRef
424 /*@ensures isnull result->aliasinfo, result->definfo,
425 result->expinfo, result->info, result->deriv, result->state@*/
427 sRef s
= sRef_alloc ();
429 s
->kind
= SK_UNKNOWN
;
433 s
->val
= multiVal_undefined
;
435 s
->type
= ctype_unknown
;
436 s
->defstate
= SS_UNKNOWN
;
438 /* start modifications */
439 s
->bufinfo
.bufstate
= BB_NOTNULLTERMINATED
;
440 s
->bufinfo
.size
= -1;
442 /* end modifications */
444 s
->aliaskind
= AK_UNKNOWN
;
445 s
->oaliaskind
= AK_UNKNOWN
;
447 s
->nullstate
= NS_UNKNOWN
;
449 s
->expkind
= XO_UNKNOWN
;
450 s
->oexpkind
= XO_UNKNOWN
;
452 s
->aliasinfo
= stateInfo_undefined
;
453 s
->definfo
= stateInfo_undefined
;
454 s
->nullinfo
= stateInfo_undefined
;
455 s
->expinfo
= stateInfo_undefined
;
458 s
->deriv
= sRefSet_undefined
;
460 s
->state
= valueTable_undefined
;
465 static /*@dependent@*/ /*@notnull@*/ /*@special@*/ sRef
468 /*@ensures isnull result->aliasinfo, result->definfo,
469 result->expinfo, result->info, result->deriv@*/
471 sRef res
= sRef_new ();
473 res
->state
= valueTable_undefined
;
478 void sRef_protectDerivs (void) /*@modifies protectDerivs@*/
480 llassert (!protectDerivs
);
481 protectDerivs
= TRUE
;
484 void sRef_clearProtectDerivs (void) /*@modifies protectDerivs@*/
486 llassert (protectDerivs
);
487 protectDerivs
= FALSE
;
491 ** hmmm...here be kind of a hack. This function mysteriously appeared
492 ** in my code, but I'm sure I didn't write it.
496 sRef_isRecursiveField (sRef s
)
498 if (sRef_isField (s
))
500 if (sRef_depth (s
) > 13)
505 fieldname
= sRef_getField (s
);
506 base
= sRef_getBase (s
);
508 while (sRef_isReasonable (base
))
510 if (sRef_isField (base
))
512 if (cstring_equal (fieldname
, sRef_getField (base
)))
518 base
= sRef_getBaseSafe (base
);
527 sRef_addDeriv (/*@notnull@*/ sRef s
, /*@notnull@*/ /*@exposed@*/ sRef t
)
529 if (!context_inProtectVars ()
531 && sRef_isReasonable (s
)
532 && sRef_isReasonable (t
)
533 && !sRef_isConst (s
))
535 int sd
= sRef_depth (s
);
536 int td
= sRef_depth (t
);
543 /* This sometimes fails: (evans 2001-07-12)
544 if (sRef_isArrayFetch (t))
546 DPRINTF (("Derived fetch: %s / %s / %s",
547 sRef_unparseFull (s), sRef_unparseFull (t),
548 sRef_unparseFull (t->info->arrayfetch->arr)));
549 llassert (t->info->arrayfetch->arr == s);
553 if (sRef_isFileOrGlobalScope (s
))
555 if (context_inFunctionLike ()
556 && ctype_isKnown (sRef_getType (s
))
557 && !ctype_isFunction (sRef_getType (s
)))
559 globSet g
= context_getUsedGlobs ();
561 if (!globSet_member (g
, s
))
564 ** don't report as a bug
568 (message ("sRef_addDeriv: global variable not in used "
569 "globs: %q / %s / %q",
571 ctype_unparse (sRef_getType (s)),
572 sRefSet_unparse (s->deriv)));
577 DPRINTF (("Add deriv: [%p] %s / [%p] %s",
579 t
, sRef_unparse (t
)));
581 s
->deriv
= sRefSet_insert (s
->deriv
, t
);
587 DPRINTF (("Add deriv: [%p] %s / [%p] %s",
589 t
, sRef_unparse (t
)));
591 s
->deriv
= sRefSet_insert (s
->deriv
, t
);
597 sRef_deepPred (bool (predf
) (sRef
), sRef s
)
599 if (sRef_isReasonable (s
))
601 if ((*predf
)(s
)) return TRUE
;
606 return (sRef_deepPred (predf
, s
->info
->ref
));
608 return (sRef_deepPred (predf
, s
->info
->arrayfetch
->arr
));
610 return (sRef_deepPred (predf
, s
->info
->field
->rec
));
612 return (sRef_deepPred (predf
, s
->info
->conj
->a
)
613 || sRef_deepPred (predf
, s
->info
->conj
->b
));
622 bool sRef_modInFunction (void)
627 void sRef_setStateFromType (sRef s
, ctype ct
)
629 if (sRef_isReasonable (s
))
631 if (ctype_isUser (ct
))
633 DPRINTF (("Here we are: %s", sRef_unparseFull (s
)));
634 sRef_setStateFromUentry
635 (s
, usymtab_getTypeEntry (ctype_typeId (ct
)));
637 else if (ctype_isAbstract (ct
))
639 DPRINTF (("Here we are: %s", sRef_unparseFull (s
)));
640 sRef_setStateFromAbstractUentry
641 (s
, usymtab_getTypeEntry (ctype_typeId (ct
)));
645 ; /* not a user type */
650 static void sRef_setTypeState (sRef s
)
652 if (sRef_isReasonable (s
))
654 sRef_setStateFromType (s
, s
->type
);
658 bool sRef_hasAliasInfoLoc (sRef s
)
660 return (sRef_isReasonable (s
) && (s
->aliasinfo
!= NULL
)
661 && (fileloc_isDefined (s
->aliasinfo
->loc
)));
664 /*@falsewhennull@*/ bool sRef_hasStateInfoLoc (sRef s
)
666 return (sRef_isReasonable (s
) && (s
->definfo
!= NULL
)
667 && (fileloc_isDefined (s
->definfo
->loc
)));
671 /*@falsewhennull@*/ bool sRef_hasExpInfoLoc (sRef s
)
673 return (sRef_isReasonable (s
)
674 && (s
->expinfo
!= NULL
) && (fileloc_isDefined (s
->expinfo
->loc
)));
676 # endif /* DEADCODE */
679 static /*@observer@*/ /*@unused@*/ stateInfo
sRef_getInfo (sRef s
, cstring key
)
683 if (!sRef_isReasonable (s
)) {
684 return stateInfo_undefined
;
687 sv
= valueTable_lookup (s
->state
, key
);
689 if (stateValue_isDefined (sv
))
691 return stateValue_getInfo (sv
);
694 return stateInfo_undefined
;
699 sRef_hasNullInfoLoc (sRef s
)
701 return (sRef_isReasonable (s
) && s
->nullinfo
!= NULL
702 && (fileloc_isDefined (s
->nullinfo
->loc
)));
706 sRef_hasAliasInfoRef (sRef s
)
708 return (sRef_isReasonable (s
) && (s
->aliasinfo
!= NULL
)
709 && (sRef_isReasonable (s
->aliasinfo
->ref
)));
712 static /*@observer@*/ fileloc
713 sRef_getAliasInfoLoc (/*@exposed@*/ sRef s
)
715 llassert (sRef_isReasonable (s
) && s
->aliasinfo
!= NULL
716 && (fileloc_isDefined (s
->aliasinfo
->loc
)));
717 return (s
->aliasinfo
->loc
);
720 static /*@observer@*/ fileloc
721 sRef_getStateInfoLoc (/*@exposed@*/ sRef s
)
723 llassert (sRef_isReasonable (s
) && s
->definfo
!= NULL
724 && (fileloc_isDefined (s
->definfo
->loc
)));
725 return (s
->definfo
->loc
);
729 static /*@observer@*/ fileloc
730 sRef_getExpInfoLoc (/*@exposed@*/ sRef s
)
732 llassert (sRef_isReasonable (s
) && s
->expinfo
!= NULL
733 && (fileloc_isDefined (s
->expinfo
->loc
)));
734 return (s
->expinfo
->loc
);
738 static /*@observer@*/ fileloc
739 sRef_getNullInfoLoc (/*@exposed@*/ sRef s
)
741 llassert (sRef_isReasonable (s
) && s
->nullinfo
!= NULL
742 && (fileloc_isDefined (s
->nullinfo
->loc
)));
743 return (s
->nullinfo
->loc
);
747 sRef_getAliasInfoRef (/*@temp@*/ sRef s
)
749 llassert (sRef_isReasonable (s
) && s
->aliasinfo
!= NULL
);
750 return (s
->aliasinfo
->ref
);
753 bool sRef_inGlobalScope (void)
759 ** This function should be called before new sRefs are created
760 ** somewhere where they will have a lifetime greater than the
761 ** current function scope.
764 void sRef_setGlobalScope (void)
766 llassert (inFunction
);
767 DPRINTF (("leave function"));
771 void sRef_clearGlobalScope (void)
773 llassert (!inFunction
);
774 DPRINTF (("enter function"));
778 static bool oldInFunction
= FALSE
;
779 static int nestedScope
= 0;
781 void sRef_setGlobalScopeSafe (void)
783 if (nestedScope
== 0)
785 oldInFunction
= inFunction
;
789 DPRINTF (("leave function safe"));
793 void sRef_clearGlobalScopeSafe (void)
796 llassert (nestedScope
>= 0);
798 if (nestedScope
== 0)
800 inFunction
= oldInFunction
;
803 DPRINTF (("clear function: %s", bool_unparse (inFunction
)));
806 void sRef_enterFunctionScope (void)
808 /* evans 2001-09-09 - cleanup if we are in a macro! */
809 if (context_inMacro ())
812 sRef_exitFunctionScope ();
816 llassert (!inFunction
);
817 llassert (sRefTable_isEmpty (allRefs
));
819 DPRINTF (("enter function"));
822 void sRef_exitFunctionScope (void)
826 DPRINTF (("Exit function scope."));
827 sRefTable_clear (allRefs
);
828 DPRINTF (("Exit function scope done."));
833 llbuglit ("sRef_exitFunctionScope: not in function");
837 void sRef_destroyMod (void) /*@globals killed allRefs;@*/
840 llmsg (message ("Live: %d / %d ", nsrefs
, totnsrefs
));
843 sRefTable_free (allRefs
);
847 static /*@notnull@*/ /*@exposed@*/ sRef
848 sRef_fixConj (/*@notnull@*/ sRef s
)
853 s
= sRef_getConjA (s
);
854 } while (sRef_isConj (s
));
856 llassert (sRef_isReasonable (s
));
857 return s
; /* don't need to ref */
866 sRef_isExternallyVisibleAux (sRef s
)
869 sRef base
= sRef_getRootBase (s
);
871 if (sRef_isReasonable (base
))
873 res
= sRef_isParam (base
) || sRef_isFileOrGlobalScope (base
) || sRef_isExternal (base
);
880 sRef_isExternallyVisible (sRef s
)
882 return (sRef_aliasCheckSimplePred (sRef_isExternallyVisibleAux
, s
));
886 sRef_getBaseUentry (sRef s
)
888 sRef base
= sRef_getRootBase (s
);
889 uentry res
= uentry_undefined
;
891 if (sRef_isReasonable (base
))
896 res
= usymtab_getRefQuiet (paramsScope
, usymId_fromInt (base
->info
->paramno
));
900 res
= usymtab_getRefQuiet (base
->info
->cvar
->lexlevel
,
901 base
->info
->cvar
->index
);
913 ** lookup the current uentry corresponding to s, and return the corresponding sRef.
914 ** yuk yuk yuk yuk yuk yuk yuk yuk
918 sRef_updateSref (sRef s
)
924 if (!sRef_isReasonable (s
)) return sRef_undefined
;
933 case SK_UNCONSTRAINED
:
940 sRef r
= sRef_updateSref (s
->info
->ref
);
942 if (r
!= s
->info
->ref
)
944 return sRef_makeExternal (r
);
954 uentry ue
= sRef_getUentry (s
);
956 /* must be raw name! (need the marker) */
957 /* Must be in the correct scope! */
959 ue
= usymtab_lookupSafeScope (uentry_rawName (ue
), sRef_lexLevel (s
));
961 if (uentry_isUndefined (ue
))
967 DPRINTF (("Update sref: %s", uentry_unparseFull (ue
)));
968 return (uentry_getSref (ue
));
972 /* special case if ind known */
973 inner
= s
->info
->arrayfetch
->arr
;
974 ret
= sRef_updateSref (inner
);
982 res
= sRef_makeArrayFetch (ret
);
988 inner
= s
->info
->field
->rec
;
989 ret
= sRef_updateSref (inner
);
997 res
= (sRef_makeField (ret
, s
->info
->field
->field
));
1002 inner
= s
->info
->ref
;
1003 ret
= sRef_updateSref (inner
);
1010 res
= sRef_makePointer (ret
);
1016 inner
= s
->info
->ref
;
1017 ret
= sRef_updateSref (inner
);
1025 res
= sRef_makeAddress (ret
);
1032 sRef innera
= s
->info
->conj
->a
;
1033 sRef innerb
= s
->info
->conj
->b
;
1034 sRef reta
= sRef_updateSref (innera
);
1035 sRef retb
= sRef_updateSref (innerb
);
1037 if (innera
== reta
&& innerb
== retb
)
1043 res
= sRef_makeConj (reta
, retb
);
1054 sRef_getUentry (sRef s
)
1056 llassert (sRef_isReasonable (s
));
1061 return (usymtab_getRefQuiet (paramsScope
, usymId_fromInt (s
->info
->paramno
)));
1063 return (usymtab_getRefQuiet (s
->info
->cvar
->lexlevel
, s
->info
->cvar
->index
));
1066 if (sRef_isCvar (s
->info
->conj
->a
) || sRef_isParam (s
->info
->conj
->a
)
1067 || sRef_isConj (s
->info
->conj
->a
))
1069 return sRef_getUentry (s
->info
->conj
->a
);
1073 return sRef_getUentry (s
->info
->conj
->b
);
1076 case SK_FIELD
: /* evans 2002-07-17: added case for SK_FIELD */
1079 return uentry_undefined
;
1085 sRef_getParam (sRef s
)
1087 llassert (sRef_isReasonable (s
));
1088 llassert (s
->kind
== SK_PARAM
);
1090 return s
->info
->paramno
;
1094 sRef_isModified (sRef s
)
1096 return (!sRef_isReasonable (s
) || s
->modified
);
1099 void sRef_setModified (sRef s
)
1101 if (sRef_isReasonable (s
))
1105 if (sRef_isRefsField (s
))
1107 sRef base
= sRef_getBase (s
);
1109 llassert (s
->kind
== SK_FIELD
);
1111 if (sRef_isPointer (base
))
1113 base
= sRef_getBase (base
);
1116 if (sRef_isRefCounted (base
))
1118 base
->aliaskind
= AK_NEWREF
;
1125 ** note: this side-effects sRefSet to set modified to TRUE
1126 ** for any sRef similar to s.
1130 sRef_canModifyVal (sRef s
, sRefSet sl
)
1132 if (context_getFlag (FLG_MUSTMOD
))
1134 return (sRef_doModifyVal (s
, sl
));
1138 return (sRef_checkModifyVal (s
, sl
));
1143 sRef_canModify (sRef s
, sRefSet sl
)
1145 if (context_getFlag (FLG_MUSTMOD
))
1147 return (sRef_doModify (s
, sl
));
1151 return (sRef_checkModify (s
, sl
));
1160 bool sRef_checkModifyVal (sRef s
, sRefSet sl
)
1162 DPRINTF (("Check modify val: %s", sRef_unparse (s
)));
1164 if (sRef_isInvalid (s
))
1171 case SK_UNCONSTRAINED
:
1175 DPRINTF (("Modify var: %s", sRef_unparse (s
)));
1177 if (sRef_isFileOrGlobalScope (s
))
1179 if (context_checkGlobMod (s
))
1181 return (sRefSet_member (sl
, s
));
1191 return (sRefSet_member (sl
, s
)
1192 || alkind_isOnly (sRef_getOrigAliasKind (s
)));
1194 /* special case if ind known */
1195 return (sRefSet_member (sl
, s
) ||
1196 sRef_checkModifyVal (s
->info
->arrayfetch
->arr
, sl
));
1198 return (sRefSet_member (sl
, s
) || sRef_checkModifyVal (s
->info
->field
->rec
, sl
));
1200 return (sRefSet_member (sl
, s
) || sRef_checkModifyVal (s
->info
->ref
, sl
));
1202 return (sRefSet_member (sl
, s
) || sRef_checkModifyVal (s
->info
->ref
, sl
));
1204 return ((sRef_checkModifyVal (s
->info
->conj
->a
, sl
)) &&
1205 (sRef_checkModifyVal (s
->info
->conj
->b
, sl
)));
1216 switch (s
->info
->spec
)
1218 case SR_NOTHING
: return TRUE
;
1220 if (context_getFlag (FLG_INTERNALGLOBS
))
1222 return (sRefSet_member (sl
, s
));
1228 case SR_SPECSTATE
: return TRUE
;
1229 case SR_SYSTEM
: return (sRefSet_member (sl
, s
));
1230 case SR_GLOBALMARKER
: BADBRANCH
;
1233 case SK_RESULT
: BADBRANCH
;
1239 ** this should probably be elsewhere...
1241 ** returns TRUE iff sl indicates that s can be modified
1244 static bool sRef_checkModify (sRef s
, sRefSet sl
)
1246 llassert (sRef_isReasonable (s
));
1250 case SK_UNCONSTRAINED
:
1254 if (sRef_isFileOrGlobalScope (s
))
1256 if (context_checkGlobMod (s
))
1258 return (sRefSet_member (sl
, s
));
1270 return (sRefSet_member (sl
, s
) ||
1271 sRef_checkModifyVal (s
->info
->arrayfetch
->arr
, sl
));
1274 sRef sr
= s
->info
->field
->rec
;
1276 if (sr
->kind
== SK_PARAM
)
1277 return TRUE
; /* structs are copied on call */
1279 return (sRefSet_member (sl
, s
) || sRef_checkModifyVal (s
->info
->field
->rec
, sl
));
1285 sm
= sRefSet_member (sl
, s
);
1290 return (sRef_checkModifyVal (s
->info
->ref
, sl
));
1293 return (sRefSet_member (sl
, s
) || sRef_checkModifyVal (s
->info
->ref
, sl
));
1295 return ((sRef_checkModify (s
->info
->conj
->a
, sl
)) &&
1296 (sRef_checkModify (s
->info
->conj
->b
, sl
)));
1306 switch (s
->info
->spec
)
1308 case SR_NOTHING
: return TRUE
;
1310 if (context_getFlag (FLG_INTERNALGLOBS
))
1312 return (sRefSet_member (sl
, s
));
1318 case SR_SPECSTATE
: return TRUE
;
1319 case SR_SYSTEM
: return (sRefSet_member (sl
, s
));
1320 case SR_GLOBALMARKER
: BADBRANCH
;
1323 case SK_RESULT
: BADBRANCH
;
1328 cstring
sRef_stateVerb (sRef s
)
1330 if (sRef_isDead (s
))
1332 return cstring_makeLiteralTemp ("released");
1334 else if (sRef_isKept (s
))
1336 return cstring_makeLiteralTemp ("kept");
1338 else if (sRef_isDependent (s
))
1340 return cstring_makeLiteralTemp ("dependent");
1348 cstring
sRef_stateAltVerb (sRef s
)
1350 if (sRef_isDead (s
))
1352 return cstring_makeLiteralTemp ("live");
1354 else if (sRef_isKept (s
))
1356 return cstring_makeLiteralTemp ("not kept");
1358 else if (sRef_isDependent (s
))
1360 return cstring_makeLiteralTemp ("independent");
1369 bool sRef_doModifyVal (sRef s
, sRefSet sl
)
1371 llassert (sRef_isReasonable (s
));
1375 case SK_UNCONSTRAINED
:
1379 if (sRef_isFileOrGlobalScope (s
))
1382 if (context_checkGlobMod (s
))
1384 return (sRefSet_modifyMember (sl
, s
));
1388 (void) sRefSet_modifyMember (sl
, s
);
1398 return (sRefSet_modifyMember (sl
, s
)
1399 || alkind_isOnly (sRef_getOrigAliasKind (s
)));
1401 /* special case if ind known */
1402 /* unconditional OR, need side effect */
1403 return (OR (sRefSet_modifyMember (sl
, s
),
1404 sRef_doModifyVal (s
->info
->arrayfetch
->arr
, sl
)));
1406 return (OR (sRefSet_modifyMember (sl
, s
),
1407 sRef_doModifyVal (s
->info
->field
->rec
, sl
)));
1409 return (OR (sRefSet_modifyMember (sl
, s
),
1410 sRef_doModifyVal (s
->info
->ref
, sl
)));
1412 return (OR (sRefSet_modifyMember (sl
, s
),
1413 sRef_doModifyVal (s
->info
->ref
, sl
)));
1415 return (AND (sRef_doModifyVal (s
->info
->conj
->a
, sl
) ,
1416 sRef_doModifyVal (s
->info
->conj
->b
, sl
)));
1426 switch (s
->info
->spec
)
1428 case SR_NOTHING
: return TRUE
;
1430 if (context_getFlag (FLG_INTERNALGLOBS
))
1432 return (sRefSet_modifyMember (sl
, s
));
1436 (void) sRefSet_modifyMember (sl
, s
);
1439 case SR_SPECSTATE
: return TRUE
;
1440 case SR_SYSTEM
: return (sRefSet_modifyMember (sl
, s
));
1441 case SR_GLOBALMARKER
: BADBRANCH
;
1445 case SK_RESULT
: BADBRANCH
;
1451 ** this should probably be elsewhere...
1453 ** returns TRUE iff sl indicates that s can be modified
1457 bool sRef_doModify (sRef s
, sRefSet sl
)
1459 llassert (sRef_isReasonable (s
));
1463 case SK_UNCONSTRAINED
:
1467 if (sRef_isFileOrGlobalScope (s
))
1469 if (context_checkGlobMod (s
))
1471 return (sRefSet_modifyMember (sl
, s
));
1475 (void) sRefSet_modifyMember (sl
, s
);
1487 return (OR (sRefSet_modifyMember (sl
, s
),
1488 sRef_doModifyVal (s
->info
->arrayfetch
->arr
, sl
)));
1491 sRef sr
= s
->info
->field
->rec
;
1493 if (sr
->kind
== SK_PARAM
)
1495 return TRUE
; /* structs are shallow-copied on call */
1498 return (OR (sRefSet_modifyMember (sl
, s
),
1499 sRef_doModifyVal (s
->info
->field
->rec
, sl
)));
1503 return (OR (sRefSet_modifyMember (sl
, s
),
1504 sRef_doModifyVal (s
->info
->ref
, sl
)));
1507 return (OR (sRefSet_modifyMember (sl
, s
),
1508 sRef_doModifyVal (s
->info
->ref
, sl
)));
1510 return (AND (sRef_doModify (s
->info
->conj
->a
, sl
),
1511 (sRef_doModify (s
->info
->conj
->b
, sl
))));
1522 switch (s
->info
->spec
)
1524 case SR_NOTHING
: return TRUE
;
1525 case SR_INTERNAL
: return TRUE
;
1526 case SR_SPECSTATE
: return TRUE
;
1527 case SR_SYSTEM
: return (sRefSet_modifyMember (sl
, s
));
1528 case SR_GLOBALMARKER
: BADBRANCH
;
1531 case SK_RESULT
: BADBRANCH
;
1536 static /*@exposed@*/ sRef
1537 sRef_leastCommon (/*@exposed@*/ sRef s1
, sRef s2
)
1539 llassert (sRef_similar (s1
, s2
));
1541 if (!sRef_isReasonable (s1
)) return s1
;
1542 if (!sRef_isReasonable (s2
)) return s1
;
1544 sRef_combineDefState (s1
, s2
);
1545 sRef_combineNullState (s1
, s2
);
1546 sRef_combineExKinds (s1
, s2
);
1548 if (s1
->aliaskind
!= s2
->aliaskind
)
1550 if (s1
->aliaskind
== AK_UNKNOWN
)
1552 s1
->aliaskind
= s2
->aliaskind
;
1554 else if (s2
->aliaskind
== AK_UNKNOWN
)
1560 s1
->aliaskind
= AK_ERROR
;
1567 int sRef_compare (sRef s1
, sRef s2
)
1569 if (s1
== s2
) return 0;
1571 if (sRef_isInvalid (s1
)) return -1;
1572 if (sRef_isInvalid (s2
)) return 1;
1574 INTCOMPARERETURN (s1
->kind
, s2
->kind
);
1575 INTCOMPARERETURN (s1
->defstate
, s2
->defstate
);
1576 INTCOMPARERETURN (s1
->aliaskind
, s2
->aliaskind
);
1578 DPRINTF (("Compare null state: %s / %s",
1579 sRef_unparseFull (s1
),
1580 sRef_unparseFull (s2
)));
1582 COMPARERETURN (nstate_compare (sRef_getNullState (s1
),
1583 sRef_getNullState (s2
)));
1588 return (int_compare (s1
->info
->paramno
, s2
->info
->paramno
));
1591 COMPARERETURN (sRef_compare (s1
->info
->arrayfetch
->arr
,
1592 s2
->info
->arrayfetch
->arr
));
1594 if (s1
->info
->arrayfetch
->indknown
&& s2
->info
->arrayfetch
->indknown
)
1596 return (int_compare (s1
->info
->arrayfetch
->ind
,
1597 s2
->info
->arrayfetch
->ind
));
1599 if (!s1
->info
->arrayfetch
->indknown
&& !s2
->info
->arrayfetch
->indknown
)
1606 COMPARERETURN (sRef_compare (s1
->info
->field
->rec
, s2
->info
->field
->rec
));
1608 if (cstring_equal (s1
->info
->field
->field
, s2
->info
->field
->field
))
1615 return (sRef_compare (s1
->info
->ref
, s2
->info
->ref
));
1617 COMPARERETURN (sRef_compare (s1
->info
->conj
->a
, s2
->info
->conj
->a
));
1618 return (sRef_compare (s1
->info
->conj
->b
, s2
->info
->conj
->b
));
1619 case SK_UNCONSTRAINED
:
1620 return (cstring_compare (s1
->info
->fname
, s2
->info
->fname
));
1632 return (generic_compare (s1
->info
->spec
, s2
->info
->spec
));
1637 static bool cref_equal (cref c1
, cref c2
)
1639 return ((c1
->lexlevel
== c2
->lexlevel
) &&
1640 (usymId_equal (c1
->index
, c2
->index
)));
1644 ** returns true if s1 could be the same storage as s2.
1645 ** i.e., a[?] ~ a[3]. Note its not symmetric ... s1
1646 ** should be more specific.
1650 ** like similar, but matches objects <-> non-objects
1654 sRef_uniqueReference (sRef s
)
1656 return (sRef_isFresh (s
) || sRef_isUnique (s
)
1657 || sRef_isOnly (s
) || sRef_isStack (s
)
1658 || sRef_isAddress (s
));
1662 sRef_similarRelaxedAux (sRef s1
, sRef s2
)
1666 if (sRef_isUnknownArrayFetch (s1
))
1676 if (sRef_isInvalid (s1
) || sRef_isInvalid (s2
)) return FALSE
;
1678 if (sRef_isConj (s2
))
1679 return (sRef_similarRelaxedAux (s1
, sRef_getConjA (s2
)) ||
1680 sRef_similarRelaxedAux (s1
, sRef_getConjB (s2
)));
1685 return ((s2
->kind
== SK_CVAR
)
1686 && (cref_equal (s1
->info
->cvar
, s2
->info
->cvar
)));
1688 return ((s2
->kind
== SK_PARAM
)
1689 && (s1
->info
->paramno
== s2
->info
->paramno
));
1691 if (s2
->kind
== SK_ARRAYFETCH
)
1693 if (sRef_similarRelaxedAux (s1
->info
->arrayfetch
->arr
,
1694 s2
->info
->arrayfetch
->arr
))
1696 if (s1
->info
->arrayfetch
->indknown
)
1698 if (s2
->info
->arrayfetch
->indknown
)
1700 return (s1
->info
->arrayfetch
->ind
== s2
->info
->arrayfetch
->ind
);
1715 return ((s2
->kind
== SK_FIELD
1716 && (sRef_similarRelaxedAux (s1
->info
->field
->rec
,
1717 s2
->info
->field
->rec
)
1718 && cstring_equal (s1
->info
->field
->field
,
1719 s2
->info
->field
->field
))));
1721 return ((s2
->kind
== SK_PTR
)
1722 && sRef_similarRelaxedAux (s1
->info
->ref
, s2
->info
->ref
));
1724 return ((s2
->kind
== SK_ADR
)
1725 && sRef_similarRelaxedAux (s1
->info
->ref
, s2
->info
->ref
));
1727 return ((sRef_similarRelaxedAux (s1
->info
->conj
->a
, s2
) ||
1728 (sRef_similarRelaxedAux (s1
->info
->conj
->b
, s2
))));
1730 return (s1
->info
->spec
== s2
->info
->spec
);
1731 case SK_UNCONSTRAINED
:
1732 return (cstring_equal (s1
->info
->fname
, s2
->info
->fname
));
1747 sRef_similarRelaxed (sRef s1
, sRef s2
)
1753 if (sRef_isThroughArrayFetch (s1
))
1763 if (sRef_isInvalid (s1
) || sRef_isInvalid (s2
)) return FALSE
;
1765 us1
= sRef_uniqueReference (s1
);
1766 us2
= sRef_uniqueReference (s2
);
1768 if ((s1
->kind
== SK_EXTERNAL
&& (s2
->kind
!= SK_EXTERNAL
&& !us2
))
1769 || (s2
->kind
== SK_EXTERNAL
&& (s1
->kind
!= SK_EXTERNAL
&& !us1
)))
1772 ** Previously, also:
1773 ** || (sRef_isExposed (s1) && !us2) || (sRef_isExposed (s2) && !us1)) ????
1775 ** No clue why this was there?!
1779 if (sRef_isExposed (s1
) && sRef_isCvar (s1
))
1781 uentry ue1
= sRef_getUentry (s1
);
1783 if (uentry_isRefParam (ue1
))
1785 return sRef_similarRelaxedAux (s1
, s2
);
1789 if (sRef_isExposed (s2
) && sRef_isCvar (s2
))
1791 uentry ue2
= sRef_getUentry (s2
);
1793 if (uentry_isRefParam (ue2
))
1795 return sRef_similarRelaxedAux (s1
, s2
);
1799 return (ctype_match (s1
->type
, s2
->type
));
1803 return sRef_similarRelaxedAux (s1
, s2
);
1808 sRef_similar (sRef s1
, sRef s2
)
1810 if (s1
== s2
) return TRUE
;
1811 if (sRef_isInvalid (s1
) || sRef_isInvalid (s2
)) return FALSE
;
1813 if (sRef_isConj (s2
))
1815 return (sRef_similar (s1
, sRef_getConjA (s2
)) ||
1816 sRef_similar (s1
, sRef_getConjB (s2
)));
1819 if (sRef_isDerived (s2
))
1821 return (sRef_includedBy (s1
, s2
->info
->ref
));
1827 return ((s2
->kind
== SK_CVAR
)
1828 && (cref_equal (s1
->info
->cvar
, s2
->info
->cvar
)));
1830 return ((s2
->kind
== SK_PARAM
)
1831 && (s1
->info
->paramno
== s2
->info
->paramno
));
1833 if (s2
->kind
== SK_ARRAYFETCH
)
1835 if (sRef_similar (s1
->info
->arrayfetch
->arr
,
1836 s2
->info
->arrayfetch
->arr
))
1838 if (s1
->info
->arrayfetch
->indknown
)
1840 if (s2
->info
->arrayfetch
->indknown
)
1842 return (s1
->info
->arrayfetch
->ind
== s2
->info
->arrayfetch
->ind
);
1857 if (s2
->kind
== SK_PTR
)
1859 if (sRef_similar (s1
->info
->arrayfetch
->arr
,
1869 return ((s2
->kind
== SK_FIELD
1870 && (sRef_similar (s1
->info
->field
->rec
,
1871 s2
->info
->field
->rec
)
1872 && cstring_equal (s1
->info
->field
->field
,
1873 s2
->info
->field
->field
))));
1875 if (s2
->kind
== SK_PTR
)
1877 return sRef_similar (s1
->info
->ref
, s2
->info
->ref
);
1881 if (s2
->kind
== SK_ARRAYFETCH
)
1883 if (sRef_similar (s2
->info
->arrayfetch
->arr
,
1893 return ((s2
->kind
== SK_ADR
)
1894 && sRef_similar (s1
->info
->ref
, s2
->info
->ref
));
1896 return ((sRef_similar (s1
->info
->conj
->a
, s2
) ||
1897 (sRef_similar (s1
->info
->conj
->b
, s2
))));
1899 return (sRef_includedBy (s2
, s1
->info
->ref
));
1900 case SK_UNCONSTRAINED
:
1901 return (s2
->kind
== SK_UNCONSTRAINED
1902 && cstring_equal (s1
->info
->fname
, s2
->info
->fname
));
1912 return (s2
->kind
== SK_SPECIAL
1913 && (s1
->info
->spec
== s2
->info
->spec
));
1916 /*@notreached@*/ DPRINTF (("Fell through for: %s / %s", sRef_unparse (s1
), sRef_unparse (s2
)));
1921 ** return TRUE iff small can be derived from big.
1923 ** (e.g. x, x.a is includedBy x;
1924 ** x.a is included By x.a;
1928 sRef_includedBy (sRef small
, sRef big
)
1930 if (small
== big
) return TRUE
;
1931 if (sRef_isInvalid (small
) || sRef_isInvalid (big
)) return FALSE
;
1933 if (sRef_isConj (big
))
1934 return (sRef_similar (small
, sRef_getConjA (big
)) ||
1935 sRef_similar (small
, sRef_getConjB (big
)));
1937 switch (small
->kind
)
1941 return (sRef_same (small
, big
));
1943 if (big
->kind
== SK_ARRAYFETCH
)
1945 if (sRef_same (small
->info
->arrayfetch
->arr
, big
->info
->arrayfetch
->arr
))
1947 if (small
->info
->arrayfetch
->indknown
)
1949 if (big
->info
->arrayfetch
->indknown
)
1951 return (small
->info
->arrayfetch
->ind
== big
->info
->arrayfetch
->ind
);
1964 return (sRef_includedBy (small
->info
->arrayfetch
->arr
, big
));
1966 if (big
->kind
== SK_FIELD
)
1969 (sRef_same (small
->info
->field
->rec
, big
->info
->field
->rec
) &&
1970 cstring_equal (small
->info
->field
->field
, big
->info
->field
->field
));
1974 return (sRef_includedBy (small
->info
->field
->rec
, big
));
1978 if (big
->kind
== SK_PTR
)
1980 return sRef_same (small
->info
->ref
, big
->info
->ref
);
1984 return (sRef_includedBy (small
->info
->ref
, big
));
1988 return ((big
->kind
== SK_ADR
) && sRef_similar (small
->info
->ref
, big
->info
->ref
));
1990 return ((sRef_includedBy (small
->info
->conj
->a
, big
) ||
1991 (sRef_includedBy (small
->info
->conj
->b
, big
))));
1993 return (sRef_includedBy (small
->info
->ref
, big
));
1994 case SK_UNCONSTRAINED
:
2004 switch (small
->info
->spec
)
2006 case SR_NOTHING
: return TRUE
;
2008 case SR_INTERNAL
: return (sRef_isSpecInternalState (big
) ||
2009 sRef_isFileStatic (big
));
2010 case SR_SYSTEM
: return (sRef_isSystemState (big
));
2011 case SR_GLOBALMARKER
: BADBRANCH
;
2018 ** Same is similar to similar, but not quite the same.
2019 ** same and realSame aren't the same, but they are really similar.
2020 ** similarly, same is the same as same. but realSame is
2021 ** not really the same as same, or similar to similar.
2023 ** Similarly to similar, same checks if two sRefs are the same.
2024 ** The similarities end, however, when same compares arrays
2025 ** with unknown indexes. Similar returns false; same returns true.
2027 ** Similarly to similar and same, realSame is the same as same,
2028 ** except they do not behave the same when face with unknown
2029 ** sRefs. Same thinks they are not the same, but realSame thinks
2035 sRef_realSame (sRef s1
, sRef s2
)
2037 if (s1
== s2
) return TRUE
;
2039 if (sRef_isUnreasonable (s1
)
2040 || sRef_isUnreasonable (s2
))
2048 return ((s2
->kind
== SK_CVAR
) && (cref_equal (s1
->info
->cvar
, s2
->info
->cvar
)));
2050 return ((s2
->kind
== SK_PARAM
) && (s1
->info
->paramno
== s2
->info
->paramno
));
2052 if (s2
->kind
== SK_ARRAYFETCH
)
2054 if (sRef_realSame (s1
->info
->arrayfetch
->arr
, s2
->info
->arrayfetch
->arr
))
2056 if (s1
->info
->arrayfetch
->indknown
&& s2
->info
->arrayfetch
->indknown
)
2058 return (s1
->info
->arrayfetch
->ind
== s2
->info
->arrayfetch
->ind
);
2060 if (!s1
->info
->arrayfetch
->indknown
&& !s2
->info
->arrayfetch
->indknown
)
2069 return ((s2
->kind
== SK_FIELD
&&
2070 (sRef_realSame (s1
->info
->field
->rec
, s2
->info
->field
->rec
) &&
2071 cstring_equal (s1
->info
->field
->field
, s2
->info
->field
->field
))));
2073 return ((s2
->kind
== SK_PTR
) && sRef_realSame (s1
->info
->ref
, s2
->info
->ref
));
2075 return ((s2
->kind
== SK_ADR
) && sRef_realSame (s1
->info
->ref
, s2
->info
->ref
));
2077 return ((sRef_realSame (s1
->info
->conj
->a
, s2
) ||
2078 (sRef_realSame (s1
->info
->conj
->b
, s2
))));
2080 return ((s2
->kind
== SK_OBJECT
)
2081 && ctype_match (s1
->info
->object
, s2
->info
->object
));
2083 return ((s2
->kind
== SK_EXTERNAL
)
2084 && sRef_realSame (s1
->info
->ref
, s2
->info
->ref
));
2086 return ((s2
->kind
== SK_SPECIAL
) && s1
->info
->spec
== s2
->info
->spec
);
2088 return ((s2
->kind
== SK_DERIVED
) && sRef_realSame (s1
->info
->ref
, s2
->info
->ref
));
2089 case SK_UNCONSTRAINED
:
2090 return ((s2
->kind
== SK_UNCONSTRAINED
)
2091 && (cstring_equal (s1
->info
->fname
, s2
->info
->fname
)));
2097 return TRUE
; /* changed this! was false */
2104 sRef_sameObject (sRef s1
, sRef s2
)
2111 ** same is similar to similar, but not quite the same.
2113 ** Similarly to similar, same checks is two sRefs are the same.
2114 ** The similarities end, however, when same compares arrays
2115 ** with unknown indexes. Similar returns false; same returns true.
2119 sRef_same (sRef s1
, sRef s2
)
2121 if (s1
== s2
) return TRUE
;
2122 if (sRef_isInvalid (s1
) || sRef_isInvalid (s2
)) return FALSE
;
2127 return ((s2
->kind
== SK_CVAR
) && (cref_equal (s1
->info
->cvar
, s2
->info
->cvar
)));
2129 return ((s2
->kind
== SK_PARAM
) && (s1
->info
->paramno
== s2
->info
->paramno
));
2131 if (s2
->kind
== SK_ARRAYFETCH
)
2133 llassert (s1
->info
->field
->rec
!= s1
);
2134 if (sRef_same (s1
->info
->arrayfetch
->arr
, s2
->info
->arrayfetch
->arr
))
2136 if (s1
->info
->arrayfetch
->indknown
&& s2
->info
->arrayfetch
->indknown
)
2138 return (s1
->info
->arrayfetch
->ind
== s2
->info
->arrayfetch
->ind
);
2146 llassert (s1
->info
->field
->rec
!= s1
);
2147 return ((s2
->kind
== SK_FIELD
&&
2148 (sRef_same (s1
->info
->field
->rec
, s2
->info
->field
->rec
) &&
2149 cstring_equal (s1
->info
->field
->field
, s2
->info
->field
->field
))));
2153 llassert (s1
->info
->ref
!= s1
);
2154 return ((s2
->kind
== SK_PTR
) && sRef_same (s1
->info
->ref
, s2
->info
->ref
));
2158 llassert (s1
->info
->ref
!= s1
);
2159 return ((s2
->kind
== SK_ADR
) && sRef_same (s1
->info
->ref
, s2
->info
->ref
));
2162 llassert (s1
->info
->conj
->a
!= s1
);
2163 llassert (s1
->info
->conj
->b
!= s1
);
2164 return ((sRef_same (s1
->info
->conj
->a
, s2
)) && /* or or and? */
2165 (sRef_same (s1
->info
->conj
->b
, s2
)));
2167 return ((s2
->kind
== SK_SPECIAL
) && s1
->info
->spec
== s2
->info
->spec
);
2169 llassert (s1
->info
->ref
!= s1
);
2170 return ((s2
->kind
== SK_DERIVED
) && sRef_same (s1
->info
->ref
, s2
->info
->ref
));
2172 case SK_UNCONSTRAINED
:
2186 ** sort of similar, for use in def/use
2190 sRef_closeEnough (sRef s1
, sRef s2
)
2192 if (s1
== s2
) return TRUE
;
2193 if (sRef_isInvalid (s1
) || sRef_isInvalid (s2
)) return FALSE
;
2198 return (((s2
->kind
== SK_CVAR
) &&
2199 (cref_equal (s1
->info
->cvar
, s2
->info
->cvar
))) ||
2200 (s2
->kind
== SK_UNCONSTRAINED
&& s1
->info
->cvar
->lexlevel
== 0));
2201 case SK_UNCONSTRAINED
:
2202 return (s2
->kind
== SK_UNCONSTRAINED
2203 || ((s2
->kind
== SK_CVAR
) && (s2
->info
->cvar
->lexlevel
== 0)));
2205 return ((s2
->kind
== SK_PARAM
)
2206 && (s1
->info
->paramno
== s2
->info
->paramno
));
2208 if (s2
->kind
== SK_ARRAYFETCH
)
2210 if (sRef_closeEnough (s1
->info
->arrayfetch
->arr
, s2
->info
->arrayfetch
->arr
))
2212 if (s1
->info
->arrayfetch
->indknown
&& s2
->info
->arrayfetch
->indknown
)
2214 return (s1
->info
->arrayfetch
->ind
== s2
->info
->arrayfetch
->ind
);
2221 return ((s2
->kind
== SK_FIELD
&&
2222 (sRef_closeEnough (s1
->info
->field
->rec
, s2
->info
->field
->rec
) &&
2223 cstring_equal (s1
->info
->field
->field
, s2
->info
->field
->field
))));
2225 return ((s2
->kind
== SK_PTR
) && sRef_closeEnough (s1
->info
->ref
, s2
->info
->ref
));
2227 return ((s2
->kind
== SK_ADR
) && sRef_closeEnough (s1
->info
->ref
, s2
->info
->ref
));
2229 return ((s2
->kind
== SK_DERIVED
) && sRef_closeEnough (s1
->info
->ref
, s2
->info
->ref
));
2231 return ((sRef_closeEnough (s1
->info
->conj
->a
, s2
)) ||
2232 (sRef_closeEnough (s1
->info
->conj
->b
, s2
)));
2234 return ((s2
->kind
== SK_SPECIAL
) && s1
->info
->spec
== s2
->info
->spec
);
2251 s is an sRef of a formal paramenter in a function call constraint
2252 we trys to return a constraint expression derived from the actual parementer of a function call.
2255 /*@only@*/ constraintExpr
sRef_fixConstraintParam (/*@observer@*/ sRef s
, /*@observer@*/ /*@temp@*/ exprNodeList args
)
2259 if (sRef_isInvalid (s
))
2260 llfatalbug((message("Invalid sRef")));
2266 ce
= constraintExpr_makeTermsRef (s
);
2273 temp
= (sRef_makeField (sRef_fixBaseParam (s
->info
->field
->rec
, args
),
2274 s
->info
->field
->field
));
2275 ce
= constraintExpr_makeTermsRef (temp
);
2281 temp
= (sRef_makePointer (sRef_fixBaseParam (s
->info
->ref
, args
)));
2282 ce
= constraintExpr_makeTermsRef (temp
);
2289 temp
= sRef_saveCopy(s
);
2290 temp
= sRef_fixBaseParam (temp
, args
);
2291 ce
= constraintExpr_makeTermsRef (temp
);
2299 temp
= sRef_saveCopy(s
);
2300 ce
= constraintExpr_makeTermsRef (temp
);
2307 llassert (exprNodeList_size (args
) > s
->info
->paramno
);
2308 e
= exprNodeList_nth (args
, s
->info
->paramno
);
2310 llassert (!(exprNode_isError (e
)));
2311 ce
= constraintExpr_makeExprNode (e
);
2318 llcontbug (message ("Trying to do fixConstraintParam on nonparam, nonglobal: %q for function with arguments %q",
2319 sRef_unparse (s
), exprNodeList_unparse(args
)));
2320 temp
= sRef_saveCopy(s
);
2321 ce
= constraintExpr_makeTermsRef (temp
);
2330 sRef_fixBaseParam (/*@returned@*/ sRef s
, exprNodeList args
)
2332 if (sRef_isInvalid (s
)) return (sRef_undefined
);
2336 case SK_UNCONSTRAINED
:
2341 if (exprNodeList_size (args
) > s
->info
->paramno
)
2343 exprNode e
= exprNodeList_nth (args
, s
->info
->paramno
);
2345 if (exprNode_isError (e
))
2347 return sRef_makeUnknown ();
2350 return (exprNode_getSref (e
));
2354 return sRef_makeUnknown ();
2359 if (s
->info
->arrayfetch
->indknown
)
2361 return (sRef_makeArrayFetchKnown
2362 (sRef_fixBaseParam (s
->info
->arrayfetch
->arr
, args
),
2363 s
->info
->arrayfetch
->ind
));
2367 return (sRef_makeArrayFetch
2368 (sRef_fixBaseParam (s
->info
->arrayfetch
->arr
, args
)));
2373 DPRINTF (("Fix field: %s", sRef_unparseFull (s
)));
2374 res
= sRef_makeField (sRef_fixBaseParam (s
->info
->field
->rec
, args
),
2375 s
->info
->field
->field
);
2376 DPRINTF (("Returns: %s", sRef_unparseFull (res
)));
2380 return (sRef_makePointer (sRef_fixBaseParam (s
->info
->ref
, args
)));
2383 return (sRef_makeAddress (sRef_fixBaseParam (s
->info
->ref
, args
)));
2386 return (sRef_makeConj (sRef_fixBaseParam (s
->info
->conj
->a
, args
),
2387 sRef_fixBaseParam (s
->info
->conj
->b
, args
)));
2403 sRef_undumpGlobal (char **c
)
2413 usymId uid
= usymId_fromInt (reader_getInt (c
));
2418 reader_checkChar (c
, '@');
2419 defstate
= sstate_fromInt (reader_getInt (c
));
2421 reader_checkChar (c
, '@');
2422 nullstate
= nstate_fromInt (reader_getInt (c
));
2424 ret
= sRef_makeGlobal (uid
, ctype_unknown
, stateInfo_currentLoc ());
2425 sRef_setNullStateN (ret
, nullstate
);
2426 ret
->defstate
= defstate
;
2431 int i
= reader_getInt (c
);
2432 speckind sk
= speckind_fromInt (i
);
2436 case SR_NOTHING
: return (sRef_makeNothing ());
2437 case SR_INTERNAL
: return (sRef_makeInternalState ());
2438 case SR_SPECSTATE
: return (sRef_makeSpecState ());
2439 case SR_SYSTEM
: return (sRef_makeSystemState ());
2440 case SR_GLOBALMARKER
: BADBRANCH
;
2445 return sRef_undefined
;
2447 return sRef_makeUnknown ();
2449 return sRef_makeUnknown ();
2451 llfatalerror (message ("sRef_undumpGlobal: bad line: %s",
2452 cstring_fromChars (*c
)));
2457 static /*@exposed@*/ sRef
sRef_undumpBody (char **c
)
2466 return (sRef_makeGlobal (usymId_fromInt (reader_getInt (c
)),
2467 ctype_unknown
, stateInfo_currentLoc ()));
2469 return (sRef_makeParam (reader_getInt (c
), ctype_unknown
,
2470 stateInfo_makeLoc (g_currentloc
, SA_DECLARED
)));
2472 return (sRef_makeResult (ctype_undump (c
)));
2475 if ((**c
>= '0' && **c
<= '9') || **c
== '-')
2477 int i
= reader_getInt (c
);
2478 sRef arr
= sRef_undump (c
);
2479 sRef ret
= sRef_buildArrayFetchKnown (arr
, i
);
2485 sRef arr
= sRef_undump (c
);
2486 sRef ret
= sRef_buildArrayFetch (arr
);
2493 cstring fname
= cstring_undefined
;
2498 fname
= cstring_appendChar (fname
, **c
);
2503 ret
= sRef_buildField (sRef_undump (c
), fname
);
2504 cstring_markOwned (fname
);
2509 int i
= reader_getInt (c
);
2510 speckind sk
= speckind_fromInt (i
);
2514 case SR_NOTHING
: return (sRef_makeNothing ());
2515 case SR_INTERNAL
: return (sRef_makeInternalState ());
2516 case SR_SPECSTATE
: return (sRef_makeSpecState ());
2517 case SR_SYSTEM
: return (sRef_makeSystemState ());
2518 case SR_GLOBALMARKER
: BADBRANCH
;
2524 sRef ptr
= sRef_undump (c
);
2525 sRef ret
= sRef_makePointer (ptr
);
2531 sRef adr
= sRef_undump (c
);
2532 sRef ret
= sRef_makeAddress (adr
);
2538 return (sRef_makeObject (ctype_undump (c
)));
2545 s1
= sRef_undump (c
);
2547 s2
= sRef_undump (c
);
2549 return (sRef_makeConj (s1
, s2
));
2552 return sRef_undefined
;
2554 return sRef_makeUnknown ();
2556 return sRef_makeUnknown ();
2558 llfatalerror (message ("sRef_undump: bad line: %s", cstring_fromChars (*c
)));
2563 /*@exposed@*/ sRef
sRef_undump (char **c
)
2565 sRef res
= sRef_undumpBody (c
);
2567 if (reader_optCheckChar (c
, '='))
2569 multiVal mv
= multiVal_undump (c
);
2570 sRef_setValue (res
, mv
);
2571 reader_checkChar (c
, '=');
2577 static /*@only@*/ cstring
sRef_dumpBody (sRef s
)
2579 if (sRef_isInvalid (s
))
2581 return (cstring_makeLiteral ("-"));
2588 return (message ("p%d", s
->info
->paramno
));
2590 if (s
->info
->arrayfetch
->indknown
)
2592 return (message ("a%d%q", s
->info
->arrayfetch
->ind
,
2593 sRef_dump (s
->info
->arrayfetch
->arr
)));
2597 return (message ("a%q", sRef_dump (s
->info
->arrayfetch
->arr
)));
2600 return (message ("f%s.%q", s
->info
->field
->field
,
2601 sRef_dump (s
->info
->field
->rec
)));
2603 return (message ("t%q", sRef_dump (s
->info
->ref
)));
2605 return (message ("d%q", sRef_dump (s
->info
->ref
)));
2607 return (message ("o%q", ctype_dump (s
->info
->object
)));
2609 return (message ("s%d", (int) s
->info
->spec
));
2611 return (message ("c%q.%q",
2612 sRef_dump (s
->info
->conj
->a
),
2613 sRef_dump (s
->info
->conj
->b
)));
2615 if (sRef_isFileOrGlobalScope (s
))
2617 return (message ("g%d",
2618 usymtab_convertId (s
->info
->cvar
->index
)));
2622 llcontbug (message ("Dumping local variable: %q",
2623 sRef_unparseDebug (s
)));
2624 return (cstring_makeLiteral ("u"));
2627 return (cstring_makeLiteral ("u"));
2629 return (message ("r%q", ctype_dump (s
->type
)));
2635 case SK_UNCONSTRAINED
:
2636 llcontbug (message ("sRef_dump: bad kind: %q",
2637 sRef_unparseFull (s
)));
2638 return (cstring_makeLiteral ("x"));
2645 /*@only@*/ cstring
sRef_dump (sRef s
)
2647 cstring res
= sRef_dumpBody (s
);
2649 if (sRef_hasValue (s
))
2651 res
= message ("%q=%q=", res
, multiVal_dump (sRef_getValue (s
)));
2657 cstring
sRef_dumpGlobal (sRef s
)
2659 llassert (!sRef_hasValue (s
));
2661 if (sRef_isInvalid (s
))
2663 return (cstring_makeLiteral ("-"));
2670 if (sRef_isFileOrGlobalScope (s
))
2672 return (message ("g%d@%d@%d",
2673 usymtab_convertId (s
->info
->cvar
->index
),
2675 (int) sRef_getNullState (s
)));
2679 llcontbug (message ("Dumping local variable: %q",
2680 sRef_unparseDebug (s
)));
2681 return (cstring_makeLiteral ("u"));
2684 return (cstring_makeLiteral ("u"));
2686 return (message ("s%d", (int) s
->info
->spec
));
2688 llcontbug (message ("sRef_dumpGlobal: bad kind: %q",
2689 sRef_unparseFull (s
)));
2690 return (cstring_makeLiteral ("x"));
2698 sRef_deriveType (sRef s
, uentryList cl
)
2700 if (sRef_isInvalid (s
)) return ctype_unknown
;
2705 return (uentry_getType (usymtab_getRefQuiet (s
->info
->cvar
->lexlevel
,
2706 s
->info
->cvar
->index
)));
2707 case SK_UNCONSTRAINED
:
2708 return (ctype_unknown
);
2710 if (s
->info
->paramno
>= 0)
2712 return uentry_getType (uentryList_getN (cl
, s
->info
->paramno
));
2716 return ctype_unknown
;
2720 ctype ca
= sRef_deriveType (s
->info
->arrayfetch
->arr
, cl
);
2722 if (ctype_isArray (ca
))
2724 return (ctype_baseArrayPtr (ca
));
2726 else if (ctype_isUnknown (ca
))
2732 llcontbuglit ("sRef_deriveType: inconsistent array type");
2738 ctype ct
= sRef_deriveType (s
->info
->field
->rec
, cl
);
2740 if (ctype_isStructorUnion (ct
))
2742 uentry ue
= uentryList_lookupField (ctype_getFields (ct
),
2743 s
->info
->field
->field
);
2745 if (uentry_isValid (ue
))
2747 return (uentry_getType (ue
));
2751 llcontbuglit ("sRef_deriveType: bad field");
2752 return ctype_unknown
;
2755 else if (ctype_isUnknown (ct
))
2761 llcontbuglit ("sRef_deriveType: inconsistent field type");
2767 ctype ct
= sRef_deriveType (s
->info
->ref
, cl
);
2769 if (ctype_isUnknown (ct
)) return ct
;
2770 if (ctype_isPointer (ct
)) return (ctype_baseArrayPtr (ct
));
2773 llcontbuglit ("sRef_deriveType: inconsistent pointer type");
2779 ctype ct
= sRef_deriveType (s
->info
->ref
, cl
);
2781 if (ctype_isUnknown (ct
)) return ct
;
2782 return ctype_makePointer (ct
);
2786 return sRef_deriveType (s
->info
->ref
, cl
);
2790 return (s
->info
->object
);
2794 return (ctype_makeConj (sRef_deriveType (s
->info
->conj
->a
, cl
),
2795 sRef_deriveType (s
->info
->conj
->b
, cl
)));
2807 return ctype_unknown
;
2813 sRef_getType (sRef s
)
2815 if (sRef_isInvalid (s
)) return ctype_unknown
;
2821 sRef_unparseOpt (sRef s
)
2823 sRef rb
= sRef_getRootBase (s
);
2825 if (sRef_isMeaningful (rb
) && !sRef_isConst (rb
))
2827 cstring ret
= sRef_unparse (s
);
2829 llassertprint (!cstring_equalLit (ret
, "?"), ("print: %s", sRef_unparseDebug (s
)));
2831 if (!cstring_isEmpty (ret
))
2833 return (cstring_appendChar (ret
, ' '));
2841 return cstring_undefined
;
2845 sRef_unparsePreOpt (sRef s
)
2847 sRef rb
= sRef_getRootBase (s
);
2849 if (sRef_isMeaningful (rb
) && !sRef_isConst (rb
))
2851 cstring ret
= sRef_unparse (s
);
2853 llassertprint (!cstring_equalLit (ret
, "?"), ("print: %s", sRef_unparseDebug (s
)));
2854 return (cstring_prependCharO (' ', ret
));
2857 return cstring_undefined
;
2861 sRef_unparse (sRef s
)
2863 if (sRef_isInvalid (s
)) return (cstring_makeLiteral ("?"));
2865 if (context_inFunctionLike ())
2867 return (sRef_unparseWithArgs (s
, context_getParams ()));
2871 DPRINTF (("Not in function like: %s", context_unparse ()));
2872 return (sRef_unparseNoArgs (s
));
2876 static /*@only@*/ cstring
2877 sRef_unparseWithArgs (sRef s
, uentryList args
)
2879 if (sRef_isInvalid (s
))
2881 return (cstring_makeLiteral ("?"));
2887 return (uentry_getName (usymtab_getRefQuiet (s
->info
->cvar
->lexlevel
,
2888 s
->info
->cvar
->index
)));
2889 case SK_UNCONSTRAINED
:
2890 return (cstring_copy (s
->info
->fname
));
2893 if (s
->info
->paramno
< uentryList_size (args
)
2894 && s
->info
->paramno
>= 0)
2896 uentry ue
= uentryList_getN (args
, s
->info
->paramno
);
2898 if (uentry_isValid (ue
))
2899 return uentry_getName (ue
);
2902 return (message ("parameter %d", s
->info
->paramno
+ 1));
2905 if (s
->info
->arrayfetch
->indknown
)
2907 return (message ("%q[%d]", sRef_unparseWithArgs (s
->info
->arrayfetch
->arr
, args
),
2908 s
->info
->arrayfetch
->ind
));
2912 return (message ("%q[]", sRef_unparseWithArgs (s
->info
->arrayfetch
->arr
, args
)));
2915 if (s
->info
->field
->rec
->kind
== SK_PTR
)
2917 sRef ptr
= s
->info
->field
->rec
;
2919 return (message ("%q->%s", sRef_unparseWithArgs (ptr
->info
->ref
, args
),
2920 s
->info
->field
->field
));
2922 return (message ("%q.%s", sRef_unparseWithArgs (s
->info
->field
->rec
, args
),
2923 s
->info
->field
->field
));
2927 sRef ref
= sRef_fixConj (s
->info
->ref
);
2928 skind sk
= ref
->kind
;
2933 ret
= message ("storage pointed to by %q",
2934 sRef_unparseWithArgs (ref
, args
));
2936 else if (skind_isSimple (sk
) || sk
== SK_PTR
)
2938 ret
= message ("*%q", sRef_unparseWithArgs (ref
, args
));
2942 ret
= message ("*(%q)", sRef_unparseWithArgs (ref
, args
));
2948 return (message ("&%q", sRef_unparseWithArgs (s
->info
->ref
, args
)));
2950 return (cstring_copy (ctype_unparse (s
->info
->object
)));
2952 return (sRef_unparseWithArgs (sRef_getConjA (s
), args
));
2954 if (cstring_isDefined (s
->info
->fname
))
2956 return (message ("[result of %s]", s
->info
->fname
));
2960 return (cstring_makeLiteral ("<new>"));
2963 return (cstring_makeLiteral ("?"));
2965 return (message ("<derived %q>", sRef_unparse (s
->info
->ref
)));
2967 return (message ("<external %q>", sRef_unparse (s
->info
->ref
)));
2969 return (message ("<type %s>", ctype_unparse (s
->type
)));
2971 return (message ("<const %s>", ctype_unparse (s
->type
)));
2973 switch (s
->info
->spec
)
2975 case SR_NOTHING
: return cstring_makeLiteral ("nothing");
2976 case SR_INTERNAL
: return cstring_makeLiteral ("internal state");
2977 case SR_SPECSTATE
: return cstring_makeLiteral ("spec state");
2978 case SR_SYSTEM
: return cstring_makeLiteral ("file system state");
2979 case SR_GLOBALMARKER
: return cstring_makeLiteral ("<global marker>");
2983 return cstring_makeLiteral ("result");
2985 llbug (message ("Bad sref, kind = %d", (int) s
->kind
));
2991 sRef_unparseDebug (sRef s
)
2993 if (sRef_isInvalid (s
))
2995 return (cstring_makeLiteral ("<undef>"));
3000 case SK_UNCONSTRAINED
:
3001 return (message ("<unconstrained %s>", s
->info
->fname
));
3006 ce
= usymtab_getRefQuiet (s
->info
->cvar
->lexlevel
, s
->info
->cvar
->index
);
3008 if (uentry_isInvalid (ce
))
3010 return (message ("<scope: %d.%d *invalid*>",
3011 s
->info
->cvar
->lexlevel
,
3012 s
->info
->cvar
->index
));
3016 return (message ("<scope: %d.%d *%q*>",
3017 s
->info
->cvar
->lexlevel
,
3018 s
->info
->cvar
->index
,
3019 uentry_getName (ce
)));
3025 return (message ("<parameter %d>", s
->info
->paramno
+ 1));
3028 if (s
->info
->arrayfetch
->indknown
)
3030 return (message ("%q[%d]", sRef_unparseDebug (s
->info
->arrayfetch
->arr
),
3031 s
->info
->arrayfetch
->ind
));
3035 return (message ("%q[]", sRef_unparseDebug (s
->info
->arrayfetch
->arr
)));
3038 return (message ("%q.%s", sRef_unparseDebug (s
->info
->field
->rec
),
3039 s
->info
->field
->field
));
3041 if (sRef_isField (s
->info
->ref
))
3043 sRef fld
= s
->info
->ref
;
3045 return (message ("%q->%s", sRef_unparseDebug (fld
->info
->field
->rec
),
3046 fld
->info
->field
->field
));
3050 return (message ("*(%q)", sRef_unparseDebug (s
->info
->ref
)));
3053 return (message ("&%q", sRef_unparseDebug (s
->info
->ref
)));
3055 return (message ("<object type %s>", ctype_unparse (s
->info
->object
)));
3057 return (message ("%q | %q", sRef_unparseDebug (s
->info
->conj
->a
),
3058 sRef_unparseDebug (s
->info
->conj
->b
)));
3060 return message ("<new: %s>", s
->info
->fname
);
3062 return (message ("<derived %q>", sRef_unparseDebug (s
->info
->ref
)));
3064 return (message ("<external %q>", sRef_unparseDebug (s
->info
->ref
)));
3066 return (message ("<type %s>", ctype_unparse (s
->type
)));
3068 if (sRef_hasValue (s
))
3070 return (message ("<const %s=%q>", ctype_unparse (s
->type
), multiVal_unparse (sRef_getValue (s
))));
3074 return (message ("<const %s>", ctype_unparse (s
->type
)));
3077 return (message ("<result %s>", ctype_unparse (s
->type
)));
3079 return (message ("<spec %s>",
3080 cstring_makeLiteralTemp
3081 (s
->info
->spec
== SR_NOTHING
? "nothing"
3082 : s
->info
->spec
== SR_INTERNAL
? "internalState"
3083 : s
->info
->spec
== SR_SPECSTATE
? "spec state"
3084 : s
->info
->spec
== SR_SYSTEM
? "fileSystem"
3087 return cstring_makeLiteral ("<unknown>");
3093 static /*@only@*/ cstring
3094 sRef_unparseNoArgs (sRef s
)
3096 if (sRef_isInvalid (s
)) return (cstring_makeLiteral ("?"));
3100 case SK_UNCONSTRAINED
:
3101 return (cstring_copy (s
->info
->fname
));
3104 uentry ce
= usymtab_getRefQuiet (s
->info
->cvar
->lexlevel
,
3105 s
->info
->cvar
->index
);
3107 if (uentry_isInvalid (ce
))
3109 llcontbug (message ("sRef_unparseNoArgs: bad cvar: %q",
3110 sRef_unparseDebug (s
)));
3111 return (sRef_unparseDebug (s
));
3115 return (uentry_getName (ce
));
3119 if (s
->info
->arrayfetch
->indknown
)
3121 return (message ("%q[%d]", sRef_unparseNoArgs (s
->info
->arrayfetch
->arr
),
3122 s
->info
->arrayfetch
->ind
));
3126 return (message ("%q[]", sRef_unparseNoArgs (s
->info
->arrayfetch
->arr
)));
3129 return (message ("%q.%s", sRef_unparseNoArgs (s
->info
->field
->rec
),
3130 s
->info
->field
->field
));
3133 sRef ref
= sRef_fixConj (s
->info
->ref
);
3134 skind sk
= ref
->kind
;
3137 if (skind_isSimple (sk
) || sk
== SK_PTR
)
3139 ret
= message ("*%q", sRef_unparseNoArgs (ref
));
3143 ret
= message ("*(%q)", sRef_unparseNoArgs (ref
));
3149 return (message ("&%q", sRef_unparseNoArgs (s
->info
->ref
)));
3151 return (cstring_copy (ctype_unparse (s
->info
->object
)));
3153 return (sRef_unparseNoArgs (s
->info
->conj
->a
));
3155 return (message ("result of %s", s
->info
->fname
));
3157 return (message ("<der %q>", sRef_unparseNoArgs (s
->info
->ref
)));
3159 return message ("<ext %q>", sRef_unparseNoArgs (s
->info
->ref
));
3161 return (cstring_makeLiteral
3162 (s
->info
->spec
== SR_NOTHING
? "nothing"
3163 : s
->info
->spec
== SR_INTERNAL
? "internal state"
3164 : s
->info
->spec
== SR_SPECSTATE
? "spec state"
3165 : s
->info
->spec
== SR_SYSTEM
? "file system state"
3168 return cstring_makeLiteral ("result");
3172 return cstring_makeLiteral ("?");
3174 /* llcontbug (message ("sRef_unparseNoArgs: bad case: %q", sRef_unparseDebug (s))); */
3175 return (sRef_unparseDebug (s
));
3180 /*@dependent@*/ sRef
sRef_makeUnconstrained (cstring fname
)
3182 sRef s
= sRef_new ();
3184 s
->kind
= SK_UNCONSTRAINED
;
3185 s
->info
= (sinfo
) dmalloc (sizeof (*s
->info
));
3186 s
->info
->fname
= cstring_copy (fname
); /* evans 2002-07-12: this was exposed, causing memory errors */
3191 cstring
sRef_unconstrainedName (sRef s
)
3193 llassert (sRef_isUnconstrained (s
));
3195 return s
->info
->fname
;
3198 bool sRef_isUnconstrained (sRef s
)
3200 return (sRef_isReasonable(s
) && s
->kind
== SK_UNCONSTRAINED
);
3203 static /*@dependent@*/ /*@notnull@*/ sRef
3204 sRef_makeCvarAux (int level
, usymId index
, ctype ct
, /*@only@*/ stateInfo stinfo
)
3206 sRef s
= sRef_newRef ();
3209 s
->info
= (sinfo
) dmalloc (sizeof (*s
->info
));
3211 s
->info
->cvar
= (cref
) dmalloc (sizeof (*s
->info
->cvar
));
3212 s
->info
->cvar
->lexlevel
= level
;
3213 s
->info
->cvar
->index
= index
;
3215 /* for now, all globals are defined; all locals, aren't */
3217 if (level
<= fileScope
)
3219 s
->defstate
= SS_UNKNOWN
;
3223 ctype rct
= ctype_realType (ct
);
3225 if (level
!= paramsScope
3226 && (ctype_isStructorUnion (rct
) || ctype_isRealArray (rct
)))
3228 s
->defstate
= SS_ALLOCATED
;
3229 s
->oaliaskind
= s
->aliaskind
= AK_STACK
;
3233 s
->defstate
= SS_UNDEFINED
;
3234 s
->oaliaskind
= s
->aliaskind
= AK_LOCAL
;
3240 llassert (level
>= globScope
);
3241 llassert (usymId_isValid (index
));
3243 DPRINTF (("Made cvar: [%p] %s", s
, sRef_unparseDebug (s
)));
3244 llassert (valueTable_isUndefined (s
->state
));
3245 s
->state
= context_createValueTable (s
, stinfo
);
3249 /*@dependent@*/ sRef
sRef_makeCvar (int level
, usymId index
, ctype ct
, /*@only@*/ stateInfo stinfo
)
3251 return (sRef_makeCvarAux (level
, index
, ct
, stinfo
));
3254 int sRef_lexLevel (sRef s
)
3256 if (sRef_isReasonable (s
))
3260 conj
= sRef_fixConj (s
);
3261 s
= sRef_getRootBase (conj
);
3263 if (sRef_isReasonable (s
) && s
->kind
== SK_CVAR
)
3265 return (s
->info
->cvar
->lexlevel
);
3273 sRef_makeGlobal (usymId l
, ctype ct
, /*@only@*/ stateInfo stinfo
)
3275 return (sRef_makeCvar (globScope
, l
, ct
, stinfo
));
3279 sRef_setParamNo (sRef s
, int l
)
3281 llassert (sRef_isReasonable (s
) && s
->kind
== SK_PARAM
);
3282 s
->info
->paramno
= l
;
3286 /*@dependent@*/ sRef
3287 sRef_makeParam (int l
, ctype ct
, stateInfo stinfo
)
3289 sRef s
= sRef_new ();
3294 s
->info
= (sinfo
) dmalloc (sizeof (*s
->info
));
3295 s
->info
->paramno
= l
;
3297 s
->defstate
= SS_UNKNOWN
;
3298 /* (probably defined, unless its an out parameter) */
3300 llassert (valueTable_isUndefined (s
->state
));
3301 s
->state
= context_createValueTable (s
, stinfo
);
3306 sRef_isIndexKnown (sRef arr
)
3310 llassert (sRef_isReasonable (arr
));
3311 arr
= sRef_fixConj (arr
);
3313 llassert (arr
->kind
== SK_ARRAYFETCH
);
3314 res
= arr
->info
->arrayfetch
->indknown
;
3319 sRef_getIndex (sRef arr
)
3323 llassert (sRef_isReasonable (arr
));
3324 arr
= sRef_fixConj (arr
);
3326 llassert (arr
->kind
== SK_ARRAYFETCH
);
3328 if (!arr
->info
->arrayfetch
->indknown
)
3330 llcontbug (message ("sRef_getIndex: unknown: %q", sRef_unparse (arr
)));
3335 result
= arr
->info
->arrayfetch
->ind
;
3341 static bool sRef_isZerothArrayFetch (/*@notnull@*/ sRef s
)
3343 return (s
->kind
== SK_ARRAYFETCH
3344 && s
->info
->arrayfetch
->indknown
3345 && (s
->info
->arrayfetch
->ind
== 0));
3348 /*@exposed@*/ sRef
sRef_makeAddress (/*@exposed@*/ sRef t
)
3351 if (sRef_isInvalid (t
)) return sRef_undefined
;
3353 if (sRef_isPointer (t
))
3355 return (t
->info
->ref
);
3357 else if (sRef_isZerothArrayFetch (t
))
3359 return (t
->info
->arrayfetch
->arr
);
3363 sRef s
= sRef_newRef ();
3366 s
->type
= ctype_makePointer (t
->type
);
3367 s
->info
= (sinfo
) dmalloc (sizeof (*s
->info
));
3370 if (t
->defstate
== SS_UNDEFINED
)
3371 /* no! it is allocated even still: && !ctype_isPointer (t->type)) */
3373 s
->defstate
= SS_ALLOCATED
;
3377 s
->defstate
= t
->defstate
;
3380 if (t
->aliaskind
== AK_LOCAL
)
3382 if (sRef_isLocalVar (t
))
3384 s
->aliaskind
= AK_STACK
;
3388 llassert (valueTable_isUndefined (s
->state
));
3389 s
->state
= context_createValueTable (s
,
3390 stateInfo_makeLoc (g_currentloc
, SA_CREATED
));
3395 cstring
sRef_getField (sRef s
)
3399 llassert (sRef_isReasonable (s
));
3400 s
= sRef_fixConj (s
);
3402 llassertprint (sRef_isReasonable (s
) && (s
->kind
== SK_FIELD
),
3403 ("s = %s", sRef_unparseDebug (s
)));
3405 res
= s
->info
->field
->field
;
3409 sRef
sRef_getBase (sRef s
)
3413 if (sRef_isInvalid (s
)) return (sRef_undefined
);
3415 s
= sRef_fixConj (s
);
3426 res
= s
->info
->field
->rec
;
3430 res
= s
->info
->arrayfetch
->arr
;
3434 res
= sRef_undefined
; /* shouldn't need it */
3441 ** same as getBase, except returns invalid
3442 ** (and doesn't use adr's)
3446 sRef_getBaseSafe (sRef s
)
3450 if (sRef_isInvalid (s
)) { return sRef_undefined
; }
3452 s
= sRef_fixConj (s
);
3460 res
= s
->info
->field
->rec
; break;
3462 res
= s
->info
->arrayfetch
->arr
;
3465 res
= sRef_undefined
; break;
3471 /*@constant int MAXBASEDEPTH;@*/
3472 # define MAXBASEDEPTH 25
3474 static /*@exposed@*/ sRef
3475 sRef_getRootBaseAux (sRef s
, int depth
)
3477 if (sRef_isInvalid (s
)) return sRef_undefined
;
3479 if (depth
> MAXBASEDEPTH
)
3482 ("Warning: reference base limit exceeded for %q. "
3483 "This either means there is a variable with at least "
3484 "%d indirections from this reference, or "
3485 "there is a bug in Splint.",
3490 return sRef_undefined
;
3497 return (sRef_getRootBaseAux (s
->info
->ref
, depth
+ 1));
3499 return (sRef_getRootBaseAux (s
->info
->field
->rec
, depth
+ 1));
3501 return (sRef_getRootBaseAux (s
->info
->arrayfetch
->arr
, depth
+ 1));
3503 return (sRef_getRootBaseAux (sRef_fixConj (s
), depth
+ 1));
3509 sRef
sRef_getRootBase (sRef s
)
3511 return (sRef_getRootBaseAux (s
, 0));
3514 static bool sRef_isDeep (sRef s
)
3516 if (sRef_isInvalid (s
)) return FALSE
;
3526 return (sRef_isDeep (sRef_fixConj (s
)));
3532 static int sRef_depth (sRef s
)
3534 if (sRef_isInvalid (s
)) return 0;
3542 return 1 + sRef_depth (s
->info
->ref
);
3544 return 1 + sRef_depth (s
->info
->field
->rec
);
3546 return 1 + sRef_depth (s
->info
->arrayfetch
->arr
);
3548 return (sRef_depth (sRef_fixConj (s
)));
3555 sRef_makeObject (ctype o
)
3557 sRef s
= sRef_newRef ();
3559 s
->kind
= SK_OBJECT
;
3560 s
->info
= (sinfo
) dmalloc (sizeof (*s
->info
));
3561 s
->info
->object
= o
;
3562 llassert (valueTable_isUndefined (s
->state
));
3563 s
->state
= context_createValueTable (s
, stateInfo_makeLoc (g_currentloc
, SA_CREATED
));
3568 ** This is used to represent storage referenced by a parameter.
3571 sRef
sRef_makeExternal (sRef t
)
3573 sRef s
= sRef_newRef ();
3575 llassert (sRef_isReasonable (t
));
3577 s
->kind
= SK_EXTERNAL
;
3578 s
->info
= (sinfo
) dmalloc (sizeof (*s
->info
));
3581 llassert (valueTable_isUndefined (s
->state
));
3582 s
->state
= context_createValueTable (s
, stateInfo_makeLoc (g_currentloc
, SA_DECLARED
));
3586 /*@dependent@*/ sRef
sRef_makeDerived (/*@exposed@*/ sRef t
)
3588 if (sRef_isReasonable (t
))
3590 sRef s
= sRef_newRef ();
3592 s
->kind
= SK_DERIVED
;
3593 s
->info
= (sinfo
) dmalloc (sizeof (*s
->info
));
3597 llassert (valueTable_isUndefined (s
->state
));
3598 s
->state
= context_createValueTable (s
, stateInfo_makeLoc (g_currentloc
, SA_CREATED
));
3603 return sRef_undefined
;
3608 ** definitely NOT symmetric:
3610 ** res fills in unknown state information from other
3614 sRef_mergeStateQuiet (sRef res
, sRef other
)
3616 llassert (sRef_isReasonable (res
));
3617 llassert (sRef_isReasonable (other
));
3619 res
->modified
= res
->modified
|| other
->modified
;
3620 res
->safe
= res
->safe
&& other
->safe
;
3622 if (res
->defstate
== SS_UNKNOWN
)
3624 res
->defstate
= other
->defstate
;
3625 res
->definfo
= stateInfo_update (res
->definfo
, other
->definfo
);
3628 if (res
->aliaskind
== AK_UNKNOWN
||
3629 (res
->aliaskind
== AK_LOCAL
&& alkind_isKnown (other
->aliaskind
)))
3631 res
->aliaskind
= other
->aliaskind
;
3632 res
->oaliaskind
= other
->oaliaskind
;
3633 res
->aliasinfo
= stateInfo_update (res
->aliasinfo
, other
->aliasinfo
);
3636 if (res
->expkind
== XO_UNKNOWN
)
3638 res
->expkind
= other
->expkind
;
3639 res
->oexpkind
= other
->oexpkind
;
3640 res
->expinfo
= stateInfo_update (res
->expinfo
, other
->expinfo
);
3643 /* out takes precedence over implicitly defined */
3644 if (res
->defstate
== SS_DEFINED
&& other
->defstate
!= SS_UNKNOWN
)
3646 res
->defstate
= other
->defstate
;
3647 res
->definfo
= stateInfo_update (res
->definfo
, other
->definfo
);
3650 if (sRef_getNullState (other
) == NS_ERROR
|| sRef_getNullState (res
) == NS_ERROR
)
3652 sRef_setNullState (res
, NS_ERROR
, fileloc_undefined
);
3656 if (sRef_getNullState (other
) != NS_UNKNOWN
3657 && (sRef_getNullState (res
) == NS_UNKNOWN
|| sRef_getNullState (res
) == NS_NOTNULL
3658 || sRef_getNullState (res
) == NS_MNOTNULL
))
3660 sRef_updateNullState (res
, other
);
3666 ** definitely NOT symmetric:
3668 ** res fills in known state information from other
3672 sRef_mergeStateQuietReverse (/*@dependent@*/ sRef res
, /*@dependent@*/ sRef other
)
3674 bool changed
= FALSE
;
3676 llassert (sRef_isReasonable (res
));
3677 llassert (sRef_isReasonable (other
));
3678 sRef_checkMutable (res
);
3680 if (res
->kind
!= other
->kind
)
3686 res
->kind
= other
->kind
;
3687 res
->type
= other
->type
;
3688 res
->info
= sinfo_fullCopy (other
);
3692 if (!ctype_equal (res
->type
, other
->type
))
3695 res
->type
= other
->type
;
3698 sinfo_update (res
, other
);
3701 res
->modified
= res
->modified
|| other
->modified
;
3702 res
->safe
= res
->safe
&& other
->safe
;
3704 if (res
->aliaskind
!= other
->aliaskind
3705 && (res
->aliaskind
== AK_UNKNOWN
3706 || ((res
->aliaskind
== AK_LOCAL
3707 || (res
->aliaskind
== AK_REFCOUNTED
3708 && other
->aliaskind
!= AK_LOCAL
))
3709 && other
->aliaskind
!= AK_UNKNOWN
)))
3712 res
->aliaskind
= other
->aliaskind
;
3713 res
->oaliaskind
= other
->oaliaskind
;
3714 res
->aliasinfo
= stateInfo_update (res
->aliasinfo
, other
->aliasinfo
);
3717 if (other
->expkind
!= XO_UNKNOWN
&& other
->expkind
!= res
->expkind
)
3720 res
->expkind
= other
->expkind
;
3721 res
->expinfo
= stateInfo_update (res
->expinfo
, other
->expinfo
);
3724 if (other
->oexpkind
!= XO_UNKNOWN
)
3726 res
->oexpkind
= other
->oexpkind
;
3729 /* out takes precedence over implicitly defined */
3731 if (res
->defstate
!= other
->defstate
)
3733 if (other
->defstate
!= SS_UNKNOWN
)
3735 res
->defstate
= other
->defstate
;
3736 res
->definfo
= stateInfo_update (res
->definfo
, other
->definfo
);
3740 if (sRef_getNullState (other
) == NS_ERROR
|| sRef_getNullState (res
) == NS_ERROR
)
3742 if (sRef_getNullState (res
) != NS_ERROR
)
3744 sRef_setNullStateN (res
, NS_ERROR
);
3750 if (sRef_getNullState (other
) != NS_UNKNOWN
3751 && sRef_getNullState (other
) != sRef_getNullState (res
))
3754 sRef_updateNullState (res
, other
);
3760 sRef_clearDerived (res
);
3765 sRef_mergeState (sRef res
, sRef other
, clause cl
, fileloc loc
)
3767 if (sRef_isReasonable (res
) && sRef_isReasonable (other
))
3769 sRef_mergeStateAux (res
, other
, cl
, FALSE
, loc
, TRUE
);
3773 if (sRef_isInvalid (res
))
3775 llbug (message ("sRef_mergeState: invalid res sRef: %q",
3776 sRef_unparseDebug (other
)));
3780 llbug (message ("sRef_mergeState: invalid other sRef: %q",
3781 sRef_unparseDebug (res
)));
3787 sRef_mergeOptState (sRef res
, sRef other
, clause cl
, fileloc loc
)
3789 if (sRef_isReasonable (res
) && sRef_isReasonable (other
))
3791 sRef_mergeStateAux (res
, other
, cl
, TRUE
, loc
, TRUE
);
3795 if (sRef_isInvalid (res
))
3797 llbug (message ("sRef_mergeOptState: invalid res sRef: %q",
3798 sRef_unparseDebug (other
)));
3802 llbug (message ("sRef_mergeOptState: invalid other sRef: %q",
3803 sRef_unparseDebug (res
)));
3809 sRef_mergeStateAux (/*@notnull@*/ sRef res
, /*@notnull@*/ sRef other
,
3810 clause cl
, bool opt
, fileloc loc
,
3814 llassertfatal (sRef_isReasonable (res
));
3815 llassertfatal (sRef_isReasonable (other
));
3817 DPRINTF (("Merge aux: %s / %s",
3818 sRef_unparseFull (res
),
3819 sRef_unparseFull (other
)));
3821 sRef_checkMutable (res
);
3822 sRef_checkMutable (other
);
3824 res
->modified
= res
->modified
|| other
->modified
;
3826 if (res
->kind
== other
->kind
3827 || (other
->kind
== SK_UNKNOWN
|| res
->kind
== SK_UNKNOWN
))
3829 sstate odef
= other
->defstate
;
3830 sstate rdef
= res
->defstate
;
3831 nstate onull
= sRef_getNullState (other
);
3834 ** yucky stuff to handle
3839 if (other
->defstate
== SS_DEAD
3840 && ((sRef_isOnly (res
) && sRef_definitelyNull (res
))
3841 || (res
->defstate
== SS_UNDEFINED
3842 || res
->defstate
== SS_UNUSEABLE
)))
3844 if (res
->defstate
== SS_UNDEFINED
3845 || res
->defstate
== SS_UNUSEABLE
)
3847 res
->defstate
= SS_UNUSEABLE
;
3851 res
->defstate
= SS_DEAD
;
3854 res
->definfo
= stateInfo_update (res
->definfo
, other
->definfo
);
3855 sRef_clearDerived (other
);
3856 sRef_clearDerived (res
);
3858 else if (res
->defstate
== SS_DEAD
3859 && ((sRef_isOnly (other
) && sRef_definitelyNull (other
))
3860 || (other
->defstate
== SS_UNDEFINED
3861 || other
->defstate
== SS_UNUSEABLE
)))
3863 if (other
->defstate
== SS_UNDEFINED
3864 || other
->defstate
== SS_UNUSEABLE
)
3866 res
->defstate
= SS_UNUSEABLE
;
3870 res
->defstate
= SS_DEAD
;
3873 res
->definfo
= stateInfo_update (res
->definfo
, other
->definfo
);
3874 sRef_clearDerived (other
);
3875 sRef_clearDerived (res
);
3877 else if (res
->defstate
== SS_DEFINED
3878 && (other
->defstate
== SS_ALLOCATED
3879 && sRef_definitelyNull (other
)))
3881 other
->defstate
= SS_DEFINED
; /* definitely null! */
3883 else if (other
->defstate
== SS_DEFINED
3884 && (res
->defstate
== SS_ALLOCATED
&& sRef_definitelyNull (res
)))
3886 res
->defstate
= SS_DEFINED
;
3887 res
->definfo
= stateInfo_update (res
->definfo
, other
->definfo
);
3894 if (res
->defstate
== SS_DEAD
&& other
->defstate
== SS_DEAD
)
3896 sRef_clearDerived (other
);
3897 sRef_clearDerived (res
);
3901 ** only & dead isn't really an only!
3904 if (alkind_isOnly (other
->aliaskind
) && other
->defstate
== SS_DEAD
)
3906 other
->aliaskind
= AK_UNKNOWN
;
3909 if (alkind_isOnly (res
->aliaskind
) && res
->defstate
== SS_DEAD
)
3911 res
->aliaskind
= AK_UNKNOWN
;
3915 ** Dead and dependent -> dead
3918 if (alkind_isDependent (other
->aliaskind
) && res
->defstate
== SS_DEAD
)
3920 other
->aliaskind
= AK_UNKNOWN
;
3921 other
->defstate
= SS_DEAD
;
3922 sRef_clearDerived (res
);
3923 sRef_clearDerived (other
);
3926 if (alkind_isDependent (res
->aliaskind
) && other
->defstate
== SS_DEAD
)
3928 res
->aliaskind
= AK_UNKNOWN
;
3929 res
->defstate
= SS_DEAD
;
3930 sRef_clearDerived (res
);
3931 sRef_clearDerived (other
);
3935 ** must do alias combine first, since it depends on
3936 ** original values of state and null.
3939 sRef_combineAliasKinds (res
, other
, cl
, loc
);
3940 sRef_combineDefState (res
, other
);
3941 sRef_combineNullState (res
, other
);
3943 if (rdef
== SS_ALLOCATED
|| rdef
== SS_SPECIAL
)
3945 if (odef
== SS_DEFINED
)
3947 if (onull
== NS_DEFNULL
|| onull
== NS_CONSTNULL
)
3949 res
->deriv
= sRefSet_copyInto (res
->deriv
, other
->deriv
);
3950 DPRINTF (("Copy derivs: %s", sRef_unparseFull (res
)));
3953 else if (odef
== SS_ALLOCATED
|| odef
== SS_SPECIAL
)
3958 if (ctype_isUnion (ctype_realType (sRef_getType (res
))))
3960 res
->deriv
= sRef_mergeUnionDerivs (res
->deriv
,
3963 DPRINTF (("Copy derivs: %s", sRef_unparseFull (res
)));
3967 res
->deriv
= sRef_mergeDerivs (res
->deriv
, other
->deriv
,
3969 DPRINTF (("Copy derivs: %s", sRef_unparseFull (res
)));
3977 res
->deriv
= sRef_mergeDerivs (res
->deriv
, other
->deriv
,
3979 DPRINTF (("Copy derivs: %s", sRef_unparseFull (res
)));
3989 if (rdef
== SS_PDEFINED
3990 || (rdef
== SS_DEFINED
&& odef
== SS_PDEFINED
))
3994 res
->deriv
= sRef_mergePdefinedDerivs (res
->deriv
, other
->deriv
,
3996 DPRINTF (("Copy derivs: %s", sRef_unparseFull (res
)));
4001 if ((rdef
== SS_DEFINED
|| rdef
== SS_UNKNOWN
)
4002 && res
->defstate
== SS_ALLOCATED
)
4004 res
->deriv
= sRefSet_copyInto (res
->deriv
, other
->deriv
);
4010 res
->deriv
= sRef_mergeDerivs (res
->deriv
, other
->deriv
,
4012 DPRINTF (("Copy derivs: %s", sRef_unparseFull (res
)));
4019 sRef_combineExKinds (res
, other
);
4023 if (res
->kind
== SK_ARRAYFETCH
&& other
->kind
== SK_PTR
)
4025 sRef nother
= sRef_buildArrayFetchKnown (sRef_getBase (other
), 0);
4027 sRef_copyState (nother
, other
);
4028 sRef_mergeStateAux (res
, nother
, cl
, opt
, loc
, doDerivs
);
4030 else if (res
->kind
== SK_PTR
&& other
->kind
== SK_ARRAYFETCH
)
4032 sRef nother
= sRef_buildPointer (sRef_getBase (other
));
4034 if (sRef_isReasonable (nother
))
4036 sRef_copyState (nother
, other
);
4037 sRef_mergeStateAux (res
, nother
, cl
, opt
, loc
, doDerivs
);
4042 llcontbug (message ("merge conj: %q / %q", sRef_unparseFull (res
),
4043 sRef_unparseFull (other
)));
4049 ** Merge value table states
4054 ** This doesn't do anything. And its broken too...
4057 valueTable_elements (res
->state
, key
, sv
)
4059 stateValue os
= valueTable_lookup (other
->state
, key
);
4060 /*@unused@*/ int val
;
4061 /*@unused@*/ char *msg
;
4063 llassert (stateValue_isDefined (os
));
4065 DPRINTF (("Merge state: %s / %s",
4066 cstring_toCharsSafe (stateValue_unparse (sv
)),
4067 cstring_toCharsSafe (stateValue_unparse (os
))));
4069 val = valueMatix_lookup (key,
4070 stateValue_getValue (os),
4071 stateValue_getValue (sv),
4073 DPRINTF (("Val: %d / %s", val, msg));
4075 } end_valueTable_elements
;
4078 DPRINTF (("Merge aux: %s / %s",
4079 sRef_unparseFull (res
),
4080 sRef_unparseFull (other
)));
4084 sRef_mergeUnionDerivs (/*@only@*/ sRefSet res
,
4085 /*@exposed@*/ sRefSet other
, bool opt
,
4086 clause cl
, fileloc loc
)
4088 if (sRefSet_isEmpty (res
))
4090 return sRefSet_copyInto (res
, other
);
4094 sRefSet_allElements (other
, el
)
4096 if (sRef_isReasonable (el
))
4098 sRef e2
= sRefSet_lookupMember (other
, el
);
4100 if (sRef_isReasonable (e2
))
4102 sRef_mergeStateAux (el
, e2
, cl
, opt
, loc
, FALSE
);
4106 res
= sRefSet_insert (res
, el
);
4109 } end_sRefSet_allElements
;
4115 static /*@only@*/ sRefSet
4116 sRef_mergeDerivs (/*@only@*/ sRefSet res
, sRefSet other
,
4117 bool opt
, clause cl
, fileloc loc
)
4119 sRefSet ret
= sRefSet_new ();
4121 sRefSet_allElements (res
, el
)
4123 if (sRef_isReasonable (el
))
4125 sRef e2
= sRefSet_lookupMember (other
, el
);
4127 if (sRef_isReasonable (e2
))
4129 if (el
->defstate
== SS_ALLOCATED
&&
4130 e2
->defstate
== SS_PDEFINED
)
4132 e2
->defstate
= SS_ALLOCATED
;
4134 else if (e2
->defstate
== SS_ALLOCATED
&&
4135 el
->defstate
== SS_PDEFINED
)
4137 el
->defstate
= SS_ALLOCATED
;
4138 el
->definfo
= stateInfo_update (el
->definfo
, e2
->definfo
);
4139 sRef_clearDerived (el
);
4141 else if ((el
->defstate
== SS_DEAD
|| sRef_isKept (el
)) &&
4142 (e2
->defstate
== SS_DEFINED
&& !sRef_isKept (e2
)))
4144 DPRINTF (("Checking dead: %s / %s", sRef_unparseFull (el
),
4145 sRef_unparseFull (e2
)));
4147 if (checkDeadState (el
, e2
, TRUE
, loc
))
4149 if (sRef_isThroughArrayFetch (el
))
4151 sRef_maybeKill (el
, loc
);
4152 sRef_maybeKill (e2
, loc
);
4156 else if ((e2
->defstate
== SS_DEAD
|| sRef_isKept (e2
)) &&
4157 (el
->defstate
== SS_DEFINED
&& !sRef_isKept (el
)))
4159 DPRINTF (("Checking dead: %s / %s", sRef_unparseFull (el
),
4160 sRef_unparseFull (e2
)));
4162 if (checkDeadState (e2
, el
, FALSE
, loc
))
4164 if (sRef_isThroughArrayFetch (el
))
4166 sRef_maybeKill (el
, loc
);
4167 sRef_maybeKill (e2
, loc
);
4171 else if (el
->defstate
== SS_DEFINED
&&
4172 e2
->defstate
== SS_PDEFINED
)
4174 DPRINTF (("set pdefined: %s", sRef_unparseFull (el
)));
4175 el
->defstate
= SS_PDEFINED
;
4176 el
->definfo
= stateInfo_update (el
->definfo
, e2
->definfo
);
4178 else if (e2
->defstate
== SS_DEFINED
&&
4179 el
->defstate
== SS_PDEFINED
)
4181 DPRINTF (("set pdefined: %s", sRef_unparseFull (e2
)));
4182 e2
->defstate
= SS_PDEFINED
;
4183 e2
->definfo
= stateInfo_update (e2
->definfo
, el
->definfo
);
4190 if (ctype_isUnion (ctype_realType (sRef_getType (el
))))
4192 el
->deriv
= sRef_mergeUnionDerivs (el
->deriv
, e2
->deriv
,
4197 el
->deriv
= sRef_mergeDerivs (el
->deriv
, e2
->deriv
, opt
, cl
, loc
);
4200 if (sRef_equivalent (el
, e2
))
4202 ret
= sRefSet_insert (ret
, el
);
4206 sRef sr
= sRef_leastCommon (el
, e2
);
4208 if (sRef_isReasonable (sr
))
4210 ret
= sRefSet_insert (ret
, sr
);
4218 (void) sRefSet_delete (other
, e2
);
4220 else /* not defined */
4222 DPRINTF (("Checking dead: %s", sRef_unparseFull (el
)));
4223 (void) checkDeadState (el
, e2
, TRUE
, loc
);
4226 } end_sRefSet_allElements
;
4228 sRefSet_allElements (other
, el
)
4230 if (sRef_isReasonable (el
))
4232 DPRINTF (("Checking dead: %s", sRef_unparseFull (el
)));
4233 (void) checkDeadState (el
, sRef_undefined
, FALSE
, loc
);
4235 } end_sRefSet_allElements
;
4242 ** Returns TRUE is there is an error.
4245 static bool checkDeadState (/*@notnull@*/ sRef el
, sRef e2
, bool tbranch
, fileloc loc
)
4248 ** usymtab_isGuarded --- the utab should still be in the
4249 ** state of the alternate branch.
4251 ** tbranch TRUE means el is released in the last branch, e.g.
4252 ** if (x != NULL) { ; } else { sfree (x); }
4253 ** so, if x is null in the other branch no error is reported.
4255 ** tbranch FALSE means this is the other branch:
4256 ** if (x != NULL) { sfree (x); } else { ; }
4257 ** so, if x is null in this branch there is no error.
4261 if ((sRef_isDead (el
) || sRef_isKept (el
))
4262 && !sRef_isDeepUnionField (el
)
4263 && !sRef_isThroughArrayFetch (el
))
4268 if (usymtab_isDefinitelyNullDeep (el
))
4275 if (usymtab_isAltDefinitelyNullDeep (el
))
4283 message ("Storage %q is %q in one path, but live in another.",
4285 cstring_makeLiteral (sRef_isKept (el
)
4286 ? "kept" : "released")),
4289 if (sRef_isKept (el
))
4291 sRef_showAliasInfo (el
);
4295 sRef_showStateInfo (el
);
4298 if (sRef_isValid (e2
))
4300 if (sRef_isKept (e2
))
4302 sRef_showAliasInfo (e2
);
4306 sRef_showStateInfo (e2
);
4310 /* prevent further errors */
4311 el
->defstate
= SS_UNKNOWN
;
4312 sRef_setAliasKind (el
, AK_ERROR
, fileloc_undefined
);
4321 checkDerivDeadState (/*@notnull@*/ sRef el
, bool tbranch
, fileloc loc
)
4323 if (checkDeadState (el
, sRef_undefined
, tbranch
, loc
))
4325 sRefSet_allElements (el
->deriv
, t
)
4327 if (sRef_isReasonable (t
))
4329 checkDerivDeadState (t
, tbranch
, loc
);
4331 } end_sRefSet_allElements
;
4336 sRef_mergePdefinedDerivs (sRefSet res
, sRefSet other
, bool opt
,
4337 clause cl
, fileloc loc
)
4339 sRefSet ret
= sRefSet_new ();
4341 sRefSet_allElements (res
, el
)
4343 if (sRef_isReasonable (el
))
4345 sRef e2
= sRefSet_lookupMember (other
, el
);
4347 if (sRef_isReasonable (e2
))
4349 if (sRef_isAllocated (el
) && !sRef_isAllocated (e2
))
4353 else if (sRef_isAllocated (e2
) && !sRef_isAllocated (el
))
4355 el
->deriv
= sRefSet_copyInto (el
->deriv
, e2
->deriv
);
4359 el
->deriv
= sRef_mergePdefinedDerivs (el
->deriv
, e2
->deriv
,
4363 sRef_mergeStateAux (el
, e2
, cl
, opt
, loc
, FALSE
);
4365 ret
= sRefSet_insert (ret
, el
);
4366 (void) sRefSet_delete (other
, e2
);
4372 checkDerivDeadState (el
, (cl
== FALSECLAUSE
), loc
);
4375 ret
= sRefSet_insert (ret
, el
);
4378 } end_sRefSet_allElements
;
4380 sRefSet_allElements (other
, el
)
4382 if (sRef_isReasonable (el
))
4384 if (!sRefSet_member (ret
, el
))
4386 /* was cl == FALSECLAUSE */
4387 checkDerivDeadState (el
, FALSE
, loc
);
4388 ret
= sRefSet_insert (ret
, el
);
4393 ** it's okay --- member is a different equality test
4397 } end_sRefSet_allElements
;
4403 sRef
sRef_makeConj (/*@exposed@*/ /*@returned@*/ sRef a
, /*@exposed@*/ sRef b
)
4405 llassert (sRef_isReasonable (a
));
4406 llassert (sRef_isReasonable (b
));
4408 if (!sRef_equivalent (a
, b
))
4410 sRef s
= sRef_newRef ();
4413 s
->info
= (sinfo
) dmalloc (sizeof (*s
->info
));
4414 s
->info
->conj
= (cjinfo
) dmalloc (sizeof (*s
->info
->conj
));
4415 s
->info
->conj
->a
= a
;
4416 s
->info
->conj
->b
= b
;
4418 if (ctype_equal (a
->type
, b
->type
)) s
->type
= a
->type
;
4419 else s
->type
= ctype_makeConj (a
->type
, b
->type
);
4421 if (a
->defstate
== b
->defstate
)
4423 s
->defstate
= a
->defstate
;
4424 s
->definfo
= stateInfo_update (s
->definfo
, a
->definfo
);
4425 s
->definfo
= stateInfo_update (s
->definfo
, b
->definfo
);
4429 s
->defstate
= SS_UNKNOWN
;
4432 sRef_setNullStateN (s
, NS_UNKNOWN
);
4434 s
->safe
= a
->safe
&& b
->safe
;
4435 s
->aliaskind
= alkind_resolve (a
->aliaskind
, b
->aliaskind
);
4437 llassert (valueTable_isUndefined (s
->state
));
4438 s
->state
= context_createValueTable (s
, stateInfo_makeLoc (g_currentloc
, SA_MERGED
));
4443 /*@-exposetrans@*/ return a
; /*@=exposetrans@*/
4447 /*@dependent@*/ sRef
4448 sRef_makeUnknown (void)
4450 sRef s
= sRef_new ();
4452 s
->kind
= SK_UNKNOWN
;
4456 static /*@owned@*/ /*@notnull@*/ sRef
4457 sRef_makeSpecial (speckind sk
) /*@*/
4459 sRef s
= sRef_new ();
4461 s
->kind
= SK_SPECIAL
;
4462 s
->info
= (sinfo
) dmalloc (sizeof (*s
->info
));
4464 /*@-dependenttrans@*/
4466 /*@=dependenttrans@*/
4469 static /*@owned@*/ sRef srnothing
= sRef_undefined
;
4470 static /*@owned@*/ sRef srinternal
= sRef_undefined
;
4471 static /*@owned@*/ sRef srsystem
= sRef_undefined
;
4472 static /*@owned@*/ sRef srspec
= sRef_undefined
;
4474 /*@dependent@*/ sRef
4475 sRef_makeNothing (void)
4477 if (sRef_isInvalid (srnothing
))
4479 srnothing
= sRef_makeSpecial (SR_NOTHING
);
4486 sRef_makeInternalState (void)
4488 if (sRef_isInvalid (srinternal
))
4490 srinternal
= sRef_makeSpecial (SR_INTERNAL
);
4497 sRef_makeSpecState (void)
4499 if (sRef_isInvalid (srspec
))
4501 srspec
= sRef_makeSpecial (SR_SPECSTATE
);
4508 sRef_makeSystemState (void)
4510 if (sRef_isInvalid (srsystem
))
4512 srsystem
= sRef_makeSpecial (SR_SYSTEM
);
4519 sRef_makeGlobalMarker (void)
4521 sRef s
= sRef_makeSpecial (SR_GLOBALMARKER
);
4522 llassert (valueTable_isUndefined (s
->state
));
4523 s
->state
= context_createGlobalMarkerValueTable (stateInfo_undefined
);
4528 sRef_makeResult (ctype c
)
4530 sRef s
= sRef_newRef ();
4532 s
->kind
= SK_RESULT
;
4534 s
->defstate
= SS_UNKNOWN
;
4535 s
->aliaskind
= AK_UNKNOWN
;
4536 sRef_setNullStateN (s
, NS_UNKNOWN
);
4537 llassert (valueTable_isUndefined (s
->state
));
4538 s
->state
= context_createValueTable (s
, stateInfo_makeLoc (g_currentloc
, SA_DECLARED
));
4540 DPRINTF (("Result: [%p] %s", s
, sRef_unparseFull (s
)));
4546 sRef_isNothing (sRef s
)
4548 return (sRef_isKindSpecial (s
) && s
->info
->spec
== SR_NOTHING
);
4552 sRef_isInternalState (sRef s
)
4554 return (sRef_isKindSpecial (s
) && s
->info
->spec
== SR_INTERNAL
);
4558 sRef_isSpecInternalState (sRef s
)
4560 return (sRef_isKindSpecial (s
)
4561 && (s
->info
->spec
== SR_INTERNAL
|| s
->info
->spec
== SR_SPECSTATE
));
4565 sRef_isSpecState (sRef s
)
4567 return (sRef_isKindSpecial (s
) && s
->info
->spec
== SR_SPECSTATE
);
4571 sRef_isResult (sRef s
)
4573 return (sRef_isReasonable (s
) && s
->kind
== SK_RESULT
);
4577 sRef_isSystemState (sRef s
)
4579 return (sRef_isKindSpecial (s
) && s
->info
->spec
== SR_SYSTEM
);
4583 sRef_isGlobalMarker (sRef s
)
4585 return (sRef_isKindSpecial (s
) && s
->info
->spec
== SR_GLOBALMARKER
);
4589 sRef_getScopeIndex (sRef s
)
4591 llassert (sRef_isReasonable (s
));
4592 llassert (sRef_isCvar (s
));
4594 return (s
->info
->cvar
->index
);
4598 sRef_makeSafe (sRef s
)
4600 if (sRef_isReasonable (s
))
4607 sRef_makeUnsafe (sRef s
)
4609 if (sRef_isReasonable (s
))
4616 ** memory state operations
4619 /*@only@*/ cstring
sRef_unparseFull (sRef s
)
4621 if (sRef_isInvalid (s
)) return (cstring_undefined
);
4623 return (message ("[%p] %q - %q { %q } [%s] { %q } < %q >",
4625 sRef_unparseDebug (s
),
4626 sRef_unparseState (s
),
4627 stateInfo_unparse (s
->definfo
),
4628 exkind_unparse (s
->oexpkind
),
4629 sRefSet_unparseDebug (s
->deriv
),
4630 valueTable_unparse (s
->state
)));
4634 cstring
sRef_unparseDeep (sRef s
)
4636 cstring st
= cstring_undefined
;
4638 st
= message ("%q:", sRef_unparseFull (s
));
4640 if (sRef_isReasonable (s
))
4642 sRefSet_allElements (s
->deriv
, el
)
4644 st
= message("%q\n%q", st
, sRef_unparseDeep (el
));
4645 } end_sRefSet_allElements
;
4652 /*@only@*/ cstring
sRef_unparseState (sRef s
)
4654 if (sRef_isConj (s
))
4656 return (message ("%q | %q",
4657 sRef_unparseState (s
->info
->conj
->a
),
4658 sRef_unparseState (s
->info
->conj
->b
)));
4661 if (sRef_isInvalid (s
))
4663 return (cstring_makeLiteral ("<invalid>"));
4666 return (message ("%s.%s.%s.%s",
4667 alkind_unparse (s
->aliaskind
),
4668 nstate_unparse (sRef_getNullState (s
)),
4669 exkind_unparse (s
->expkind
),
4670 sstate_unparse (s
->defstate
)));
4673 bool sRef_isNotUndefined (sRef s
)
4675 return (sRef_isInvalid (s
)
4676 || (s
->defstate
!= SS_UNDEFINED
4677 && s
->defstate
!= SS_UNUSEABLE
4678 && s
->defstate
!= SS_DEAD
));
4681 ynm
sRef_isWriteable (sRef s
)
4683 if (sRef_isInvalid (s
)) return MAYBE
;
4685 if (sRef_isConj (s
) && s
->defstate
== SS_UNKNOWN
)
4687 if (ynm_toBoolStrict (sRef_isWriteable (sRef_getConjA (s
))))
4689 if (ynm_toBoolStrict (sRef_isWriteable (sRef_getConjB (s
))))
4697 if (ynm_toBoolStrict (sRef_isWriteable (sRef_getConjB (s
))))
4705 return (ynm_fromBool (s
->defstate
!= SS_UNUSEABLE
));
4708 bool sRef_hasNoStorage (sRef s
)
4710 return (!sRef_isAllocatedStorage (s
) || sRef_isDefinitelyNull (s
));
4713 bool sRef_isStrictReadable (sRef s
)
4715 return (ynm_toBoolStrict (sRef_isValidLvalue (s
)));
4719 ** Is this what is does?
4720 ** Returns YES if s can be used as an rvalue,
4721 ** MAYBE if its not clear
4722 ** NO if s cannot be safely used as an rvalue.
4725 ynm
sRef_isValidLvalue (sRef s
)
4729 if (sRef_isInvalid (s
)) return YES
;
4733 if (sRef_isConj (s
) && s
->defstate
== SS_UNKNOWN
)
4735 if (ynm_toBoolStrict (sRef_isValidLvalue (sRef_getConjA (s
))))
4737 if (ynm_toBoolStrict (sRef_isValidLvalue (sRef_getConjB (s
))))
4745 if (ynm_toBoolStrict (sRef_isValidLvalue (sRef_getConjB (s
))))
4752 else if (ss
== SS_HOFFA
)
4754 if (context_getFlag (FLG_STRICTUSERELEASED
))
4765 return (ynm_fromBool (ss
== SS_DEFINED
4768 || ss
== SS_PDEFINED
4771 || ss
== SS_ALLOCATED
4772 || ss
== SS_KILLED
/* evans 2001-05-26: added this for killed globals */
4773 || ss
== SS_UNKNOWN
));
4777 static /*@exposed@*/ sRef
whatUndefined (/*@exposed@*/ sRef fref
, int depth
)
4781 if (depth
> MAXDEPTH
)
4784 ("Warning: check definition limit exceeded, checking %q. "
4785 "This either means there is a variable with at least "
4786 "%d indirections apparent in the program text, or "
4787 "there is a bug in Splint.",
4788 sRef_unparse (fref
),
4792 return sRef_undefined
;
4795 if (!sRef_isKnown (fref
) || sRef_isAnyDefined (fref
))
4797 return sRef_undefined
;
4800 if (sRef_isUnuseable (fref
) || sRef_isStateUndefined (fref
))
4805 ct
= ctype_realType (sRef_getType (fref
));
4807 if (ctype_isUnknown (ct
))
4809 return sRef_undefined
;
4811 else if (ctype_isPointer (ct
) || ctype_isArray (ct
))
4813 if (sRef_isStateUnknown (fref
))
4815 return sRef_undefined
;
4819 sRef fptr
= sRef_constructDeref (fref
);
4821 return (whatUndefined (fptr
, depth
+ 1));
4824 else if (ctype_isStruct (ct
))
4826 if (sRef_isStateUnknown (fref
))
4831 if (sRef_isPdefined (fref
) || sRef_isAnyDefined (fref
))
4833 sRefSet_realElements (sRef_derivedFields (fref
), sr
)
4835 if (sRef_isField (sr
))
4837 cstring fieldname
= sRef_getField (sr
);
4838 sRef fldref
= sRef_makeField (fref
, fieldname
);
4839 bool shouldCheck
= !sRef_isRecursiveField (fldref
);
4843 sRef wdef
= whatUndefined (fldref
, depth
+ 1);
4845 if (sRef_isReasonable (wdef
))
4851 } end_sRefSet_realElements
;
4853 else if (sRef_isAllocated (fref
))
4856 ** for structures, each field must be completely defined
4859 uentryList fields
= ctype_getFields (ct
);
4861 uentryList_elements (fields
, ue
)
4863 cstring name
= uentry_getRealName (ue
);
4864 sRef ffield
= sRef_makeField (fref
, name
);
4865 bool shouldCheck
= !sRef_isRecursiveField (ffield
);
4867 if (sRef_isRelDef (uentry_getSref (ue
)))
4875 sRef wdef
= whatUndefined (ffield
, depth
+ 1);
4877 if (sRef_isInvalid (wdef
))
4883 } end_uentryList_elements
;
4890 else if (ctype_isUnion (ct
))
4899 return sRef_undefined
;
4902 static bool checkDefined (/*@temp@*/ sRef sr
)
4904 /*@-temptrans@*/ /* the result from whatUndefined is lost */
4905 return (sRef_isInvalid (whatUndefined (sr
, 0)));
4909 bool sRef_isReallyDefined (sRef s
)
4911 if (sRef_isReasonable (s
))
4913 if (sRef_isAnyDefined (s
))
4919 if (sRef_isAllocated (s
) || sRef_isPdefined (s
))
4921 return checkDefined (s
);
4935 void sRef_showNotReallyDefined (sRef s
)
4937 if (sRef_isReasonable (s
))
4939 if (sRef_isAnyDefined (s
))
4945 if (sRef_isAllocated (s
) || sRef_isPdefined (s
))
4947 /*@-temptrans@*/ /* the result of whatUndefined is lost */
4948 sRef ref
= whatUndefined (s
, 0);
4950 llassert (sRef_isReasonable (ref
));
4955 (message ("This sub-reference is %s: %q",
4956 sstate_unparse (sRef_getDefState (ref
)),
4957 sRef_unparse (ref
)));
4972 sstate
sRef_getDefState (sRef s
)
4974 if (sRef_isInvalid (s
)) return (SS_UNKNOWN
);
4975 return (s
->defstate
);
4978 void sRef_setDefState (sRef s
, sstate defstate
, fileloc loc
)
4980 sRef_checkMutable (s
);
4981 sRef_setStateAux (s
, defstate
, loc
);
4984 static void sRef_clearAliasStateAux (sRef s
, fileloc loc
)
4986 sRef_checkMutable (s
);
4987 sRef_setAliasKind (s
, AK_ERROR
, loc
);
4990 void sRef_clearAliasState (sRef s
, fileloc loc
)
4992 sRef_checkMutable (s
);
4993 sRef_aliasSetComplete (sRef_clearAliasStateAux
, s
, loc
);
4996 void sRef_setAliasKindComplete (sRef s
, alkind kind
, fileloc loc
)
4998 sRef_checkMutable (s
);
4999 sRef_aliasSetCompleteAlkParam (sRef_setAliasKind
, s
, kind
, loc
);
5002 void sRef_setAliasKind (sRef s
, alkind kind
, fileloc loc
)
5004 sRef_checkMutable (s
);
5006 if (sRef_isReasonable (s
))
5008 sRef_clearDerived (s
);
5010 if ((kind
!= s
->aliaskind
&& kind
!= s
->oaliaskind
)
5011 && fileloc_isDefined (loc
))
5013 s
->aliasinfo
= stateInfo_updateLoc (s
->aliasinfo
, stateAction_fromAlkind (kind
), loc
);
5016 s
->aliaskind
= kind
;
5020 void sRef_setOrigAliasKind (sRef s
, alkind kind
)
5022 sRef_checkMutable (s
);
5024 if (sRef_isReasonable (s
))
5026 s
->oaliaskind
= kind
;
5030 exkind
sRef_getExKind (sRef s
)
5032 if (sRef_isReasonable (s
))
5034 return (s
->expkind
);
5042 exkind
sRef_getOrigExKind (sRef s
)
5044 if (sRef_isReasonable (s
))
5046 return (s
->oexpkind
);
5054 static void sRef_clearExKindAux (sRef s
, fileloc loc
)
5056 sRef_checkMutable (s
);
5057 sRef_setExKind (s
, XO_UNKNOWN
, loc
);
5060 void sRef_setObserver (sRef s
, fileloc loc
)
5062 sRef_checkMutable (s
);
5063 sRef_setExKind (s
, XO_OBSERVER
, loc
);
5066 void sRef_setExposed (sRef s
, fileloc loc
)
5068 sRef_checkMutable (s
);
5069 sRef_setExKind (s
, XO_EXPOSED
, loc
);
5072 void sRef_clearExKindComplete (sRef s
, fileloc loc
)
5074 (void) sRef_aliasSetComplete (sRef_clearExKindAux
, s
, loc
);
5077 void sRef_setExKind (sRef s
, exkind exp
, fileloc loc
)
5079 sRef_checkMutable (s
);
5081 if (sRef_isReasonable (s
))
5083 if (s
->expkind
!= exp
)
5085 s
->expinfo
= stateInfo_updateLoc (s
->expinfo
, stateAction_fromExkind (exp
), loc
);
5093 ** s1->derived = s2->derived
5096 static void sRef_copyRealDerived (sRef s1
, sRef s2
)
5098 DPRINTF (("Copy real: %s / %s", sRef_unparse (s1
), sRef_unparse (s2
)));
5099 sRef_checkMutable (s1
);
5101 if (sRef_isReasonable (s1
) && sRef_isReasonable (s2
))
5103 sRef sb
= sRef_getRootBase (s1
);
5105 sRefSet_clear (s1
->deriv
);
5107 sRefSet_allElements (s2
->deriv
, el
)
5109 if (sRef_isReasonable (el
))
5111 sRef rb
= sRef_getRootBase (el
);
5113 if (!sRef_same (rb
, sb
))
5115 sRef fb
= sRef_fixDirectBase (el
, s1
);
5117 if (sRef_isReasonable (fb
))
5119 sRef_copyRealDerived (fb
, el
);
5120 sRef_addDeriv (s1
, fb
);
5125 sRef_addDeriv (s1
, el
);
5128 } end_sRefSet_allElements
;
5133 void sRef_copyRealDerivedComplete (sRef s1
, sRef s2
)
5135 sRef_innerAliasSetCompleteParam (sRef_copyRealDerived
, s1
, s2
);
5138 void sRef_setUndefined (sRef s
, fileloc loc
)
5140 sRef_checkMutable (s
);
5142 if (sRef_isReasonable (s
))
5144 s
->defstate
= SS_UNDEFINED
;
5145 s
->definfo
= stateInfo_updateLoc (s
->definfo
, SA_UNDEFINED
, loc
);
5147 sRef_clearDerived (s
);
5151 static void sRef_setDefinedAux (sRef s
, fileloc loc
, bool clear
)
5153 sRef_checkMutable (s
);
5154 if (sRef_isInvalid (s
)) return;
5156 DPRINTF (("Set defined: %s", sRef_unparseFull (s
)));
5158 s
->definfo
= stateInfo_updateLoc (s
->definfo
, SA_DEFINED
, loc
);
5159 s
->defstate
= SS_DEFINED
;
5161 DPRINTF (("Set defined: %s", sRef_unparseFull (s
)));
5163 /* e.g., if x is allocated, *x = 3 defines x */
5165 if (s
->kind
== SK_PTR
)
5167 sRef p
= s
->info
->ref
;
5170 if (p
->defstate
== SS_ALLOCATED
5171 || p
->defstate
== SS_SPECIAL
) /* evans 2001-07-12: shouldn't need this */
5173 sRef_setDefinedAux (p
, loc
, clear
);
5177 ** Defines a[0] also:
5180 arr
= sRef_findDerivedArrayFetch (p
, FALSE
, 0, FALSE
);
5182 if (sRef_isReasonable (arr
))
5184 sRef_setDefinedAux (arr
, loc
, clear
);
5187 else if (s
->kind
== SK_ARRAYFETCH
)
5189 if (!s
->info
->arrayfetch
->indknown
5190 || (s
->info
->arrayfetch
->ind
== 0))
5192 sRef p
= s
->info
->arrayfetch
->arr
;
5193 sRef ptr
= sRef_constructPointer (p
);
5195 if (sRef_isReasonable (ptr
))
5197 if (ptr
->defstate
== SS_ALLOCATED
5198 || ptr
->defstate
== SS_UNDEFINED
5199 || ptr
->defstate
== SS_SPECIAL
) /* evans 2001-07-12: shouldn't need this */
5201 sRef_setDefinedAux (ptr
, loc
, clear
);
5205 if (p
->defstate
== SS_RELDEF
)
5209 else if (p
->defstate
== SS_ALLOCATED
|| p
->defstate
== SS_PDEFINED
5210 || p
->defstate
== SS_SPECIAL
) /* evans 2001-07-12: shouldn't need this */
5212 p
->defstate
= SS_DEFINED
;
5219 else if (s
->kind
== SK_FIELD
)
5221 sRef parent
= s
->info
->field
->rec
;
5223 if (sRef_isReasonable (parent
))
5225 if (ctype_isUnion (ctype_realType (parent
->type
)))
5228 ** Should not clear derived from here.
5231 sRef_setDefinedNoClear (parent
, loc
);
5235 ; /* Nothing to do for structures. */
5247 sRef_clearDerived (s
);
5251 /* evans 2001-07-12: need to define the derived references */
5252 sRefSet_elements (s
->deriv
, el
)
5254 llassert (sRef_isReasonable (el
));
5255 el
->defstate
= SS_DEFINED
;
5256 } end_sRefSet_elements
;
5259 DPRINTF (("Set defined: %s", sRef_unparseFull (s
)));
5262 static void sRef_setPartialDefined (sRef s
, fileloc loc
)
5264 sRef_checkMutable (s
);
5266 if (!sRef_isPartial (s
))
5268 sRef_setDefined (s
, loc
);
5272 void sRef_setPartialDefinedComplete (sRef s
, fileloc loc
)
5274 sRef_innerAliasSetComplete (sRef_setPartialDefined
, s
, loc
);
5277 void sRef_setDefinedComplete (sRef s
, fileloc loc
)
5279 sRef_innerAliasSetComplete (sRef_setDefined
, s
, loc
);
5282 void sRef_setDefinedCompleteDirect (sRef s
, fileloc loc
)
5286 aliases
= usymtab_allAliases (s
);
5287 DPRINTF (("Set defined complete: %s", sRef_unparseFull (s
)));
5288 DPRINTF (("All aliases: %s", sRefSet_unparseFull (aliases
)));
5290 sRef_setDefined (s
, loc
);
5292 sRefSet_realElements (aliases
, current
)
5294 if (sRef_isReasonable (current
))
5296 current
= sRef_updateSref (current
);
5297 sRef_setDefined (current
, loc
);
5299 } end_sRefSet_realElements
;
5301 sRefSet_free (aliases
);
5302 sRef_innerAliasSetComplete (sRef_setDefined
, s
, loc
);
5305 void sRef_setDefined (sRef s
, fileloc loc
)
5307 sRef_checkMutable (s
);
5308 sRef_setDefinedAux (s
, loc
, TRUE
);
5311 static void sRef_setDefinedNoClear (sRef s
, fileloc loc
)
5313 sRef_checkMutable (s
);
5314 DPRINTF (("Defining: %s", sRef_unparseFull (s
)));
5315 sRef_setDefinedAux (s
, loc
, FALSE
);
5316 DPRINTF (("==> %s", sRef_unparseFull (s
)));
5319 void sRef_setDefinedNCComplete (sRef s
, fileloc loc
)
5321 sRef_checkMutable (s
);
5322 DPRINTF (("Set Defined Complete: %s", sRef_unparseFull (s
)));
5323 sRef_innerAliasSetComplete (sRef_setDefinedNoClear
, s
, loc
);
5324 DPRINTF (("==> %s", sRef_unparseFull (s
)));
5327 static bool sRef_isDeepUnionField (sRef s
)
5329 return (sRef_deepPred (sRef_isUnionField
, s
));
5332 bool sRef_isUnionField (sRef s
)
5334 if (sRef_isReasonable (s
) && s
->kind
== SK_FIELD
)
5337 ** defining one field of a union defines the union
5340 sRef base
= s
->info
->field
->rec
;
5342 if (sRef_isReasonable (base
))
5344 return (ctype_isUnion (ctype_realType (base
->type
)));
5351 void sRef_setPdefined (sRef s
, fileloc loc
)
5353 sRef_checkMutable (s
);
5354 if (sRef_isReasonable (s
) && !sRef_isPartial (s
))
5356 sRef base
= sRef_getBaseSafe (s
);
5358 if (s
->defstate
== SS_ALLOCATED
)
5363 s
->definfo
= stateInfo_updateLoc (s
->definfo
, SA_PDEFINED
, loc
);
5364 s
->defstate
= SS_PDEFINED
;
5366 /* e.g., if x is allocated, *x = 3 defines x */
5368 while (sRef_isReasonable (base
) && sRef_isKnown (base
))
5370 if (base
->defstate
== SS_DEFINED
)
5374 DPRINTF (("set pdefined: %s", sRef_unparseFull (base
)));
5375 base
->defstate
= SS_PDEFINED
;
5376 nb
= sRef_getBaseSafe (base
);
5387 static void sRef_setStateAux (sRef s
, sstate ss
, fileloc loc
)
5389 sRef_checkMutable (s
);
5391 DPRINTF (("Set state: %s => %s", sRef_unparseFull (s
), sstate_unparse (ss
)));
5393 if (sRef_isReasonable (s
))
5395 /* if (s->defstate == SS_RELDEF) return; */
5397 if (s
->defstate
!= ss
&& fileloc_isDefined (loc
))
5399 s
->definfo
= stateInfo_updateLoc (s
->definfo
,
5400 stateAction_fromSState (ss
), loc
);
5404 sRef_clearDerived (s
);
5406 if (ss
== SS_ALLOCATED
)
5408 sRef base
= sRef_getBaseSafe (s
);
5410 while (sRef_isReasonable (base
) && sRef_isKnown (base
))
5412 if (base
->defstate
== SS_DEFINED
)
5416 DPRINTF (("set pdefined: %s", sRef_unparseFull (s
)));
5417 base
->defstate
= SS_PDEFINED
;
5418 nb
= sRef_getBaseSafe (base
);
5430 void sRef_setAllocatedComplete (sRef s
, fileloc loc
)
5432 sRef_innerAliasSetComplete (sRef_setAllocated
, s
, loc
);
5435 static void sRef_setAllocatedShallow (sRef s
, fileloc loc
)
5437 sRef_checkMutable (s
);
5439 if (sRef_isReasonable (s
))
5441 if (s
->defstate
== SS_DEAD
|| s
->defstate
== SS_UNDEFINED
)
5443 s
->defstate
= SS_ALLOCATED
;
5444 s
->definfo
= stateInfo_updateLoc (s
->definfo
, SA_ALLOCATED
, loc
);
5449 void sRef_setAllocatedShallowComplete (sRef s
, fileloc loc
)
5451 sRef_innerAliasSetComplete (sRef_setAllocatedShallow
, s
, loc
);
5454 void sRef_setAllocated (sRef s
, fileloc loc
)
5456 sRef_checkMutable (s
);
5457 sRef_setStateAux (s
, SS_ALLOCATED
, loc
);
5460 void sRef_setPartial (sRef s
, fileloc loc
)
5462 sRef_checkMutable (s
);
5463 sRef_setStateAux (s
, SS_PARTIAL
, loc
);
5466 void sRef_setShared (sRef s
, fileloc loc
)
5468 sRef_checkMutable (s
);
5470 if (sRef_isReasonable (s
))
5472 if (s
->aliaskind
!= AK_SHARED
&& fileloc_isDefined (loc
))
5474 s
->aliasinfo
= stateInfo_updateLoc (s
->aliasinfo
, SA_SHARED
, loc
);
5477 s
->aliaskind
= AK_SHARED
;
5478 /* don't! sRef_clearDerived (s); */
5482 void sRef_setLastReference (sRef s
, /*@exposed@*/ sRef ref
, fileloc loc
)
5484 sRef_checkMutable (s
);
5486 if (sRef_isReasonable (s
))
5488 s
->aliaskind
= sRef_getAliasKind (ref
);
5489 s
->aliasinfo
= stateInfo_updateRefLoc (s
->aliasinfo
, ref
, stateAction_fromAlkind (s
->aliaskind
), loc
);
5494 void sRef_setNullStateAux (/*@notnull@*/ sRef s
, nstate ns
, fileloc loc
)
5496 sRef_checkMutable (s
);
5498 sRef_resetAliasKind (s
);
5500 if (fileloc_isDefined (loc
))
5502 s
->nullinfo
= stateInfo_updateLoc (s
->nullinfo
, stateAction_fromNState (ns
), loc
);
5506 void sRef_setNotNull (sRef s
, fileloc loc
)
5508 if (sRef_isReasonable (s
))
5510 sRef_setNullStateAux (s
, NS_NOTNULL
, loc
);
5514 void sRef_setNullStateN (sRef s
, nstate n
)
5516 if (sRef_isReasonable (s
))
5518 sRef_checkMutable (s
);
5520 DPRINTF (("Set null state ==> %s", sRef_unparseFull (s
)));
5521 sRef_resetAliasKind (s
);
5525 void sRef_setNullState (sRef s
, nstate n
, fileloc loc
)
5527 if (sRef_isReasonable (s
))
5529 sRef_setNullStateAux (s
, n
, loc
);
5534 void sRef_setNullTerminatedStateInnerComplete (sRef s
, struct s_bbufinfo b
, /*@unused@*/ fileloc loc
)
5536 switch (b
.bufstate
) {
5537 case BB_NULLTERMINATED
:
5538 sRef_setNullTerminatedState (s
);
5539 sRef_setLen (s
, b
.len
);
5541 case BB_POSSIBLYNULLTERMINATED
:
5542 sRef_setPossiblyNullTerminatedState(s
);
5544 case BB_NOTNULLTERMINATED
:
5545 sRef_setNotNullTerminatedState (s
);
5549 sRef_setSize (s
, b
.size
);
5551 /* PL: TO BE DONE : Aliases are not modified right now, have to be similar to
5552 * setNullStateInnerComplete.
5555 # endif /* DEADCODE */
5557 void sRef_setNullStateInnerComplete (sRef s
, nstate n
, fileloc loc
)
5559 DPRINTF (("Set null state: %s", nstate_unparse (n
)));
5561 sRef_setNullState (s
, n
, loc
);
5566 sRef_innerAliasSetComplete (sRef_setPosNull
, s
, loc
);
5569 sRef_innerAliasSetComplete (sRef_setDefNull
, s
, loc
);
5572 sRef_innerAliasSetComplete (sRef_setNullUnknown
, s
, loc
);
5575 sRef_innerAliasSetComplete (sRef_setNotNull
, s
, loc
);
5578 sRef_innerAliasSetComplete (sRef_setNotNull
, s
, loc
);
5581 sRef_innerAliasSetComplete (sRef_setNullUnknown
, s
, loc
);
5584 sRef_innerAliasSetComplete (sRef_setDefNull
, s
, loc
);
5587 sRef_innerAliasSetComplete (sRef_setNullUnknown
, s
, loc
);
5590 sRef_innerAliasSetComplete (sRef_setNullErrorLoc
, s
, loc
);
5595 void sRef_setPosNull (sRef s
, fileloc loc
)
5597 if (sRef_isReasonable (s
))
5599 sRef_setNullStateAux (s
, NS_POSNULL
, loc
);
5603 void sRef_setDefNull (sRef s
, fileloc loc
)
5605 if (sRef_isReasonable (s
))
5607 sRef_setNullStateAux (s
, NS_DEFNULL
, loc
);
5611 void sRef_setNullUnknown (sRef s
, fileloc loc
)
5613 if (sRef_isReasonable (s
))
5615 sRef_setNullStateAux (s
, NS_UNKNOWN
, loc
);
5619 void sRef_setNullError (sRef s
)
5621 if (sRef_isReasonable (s
) && !sRef_isConst (s
))
5623 sRef_setNullStateAux (s
, NS_UNKNOWN
, fileloc_undefined
);
5627 void sRef_setNullErrorLoc (sRef s
, fileloc loc
)
5629 if (sRef_isReasonable (s
) && !sRef_isConst (s
))
5631 sRef_setNullStateAux (s
, NS_UNKNOWN
, loc
);
5635 void sRef_setOnly (sRef s
, fileloc loc
)
5637 if (sRef_isReasonable (s
) && s
->aliaskind
!= AK_ONLY
)
5639 sRef_checkMutable (s
);
5640 s
->aliaskind
= AK_ONLY
;
5641 s
->aliasinfo
= stateInfo_updateLoc (s
->aliasinfo
, SA_ONLY
, loc
);
5645 void sRef_setDependent (sRef s
, fileloc loc
)
5647 if (sRef_isReasonable (s
) && !sRef_isConst (s
) && (s
->aliaskind
!= AK_DEPENDENT
))
5649 sRef_checkMutable (s
);
5650 DPRINTF (("Setting dependent: %s", sRef_unparseFull (s
)));
5651 s
->aliaskind
= AK_DEPENDENT
;
5652 s
->aliasinfo
= stateInfo_updateLoc (s
->aliasinfo
, SA_DEPENDENT
, loc
);
5656 void sRef_setOwned (sRef s
, fileloc loc
)
5658 if (sRef_isReasonable (s
) && !sRef_isConst (s
) && (s
->aliaskind
!= AK_OWNED
))
5660 sRef_checkMutable (s
);
5661 s
->aliaskind
= AK_OWNED
;
5662 s
->aliasinfo
= stateInfo_updateLoc (s
->aliasinfo
, SA_OWNED
, loc
);
5666 void sRef_setKept (sRef s
, fileloc loc
)
5668 if (sRef_isReasonable (s
) && !sRef_isConst (s
) && (s
->aliaskind
!= AK_KEPT
))
5670 sRef base
= sRef_getBaseSafe (s
);
5672 while (sRef_isReasonable (base
) && sRef_isKnown (base
))
5674 if (base
->defstate
== SS_DEFINED
)
5676 sRef_checkMutable (base
);
5677 base
->defstate
= SS_PDEFINED
;
5678 base
= sRef_getBaseSafe (base
);
5686 sRef_checkMutable (s
);
5687 s
->aliaskind
= AK_KEPT
;
5688 s
->aliasinfo
= stateInfo_updateLoc (s
->aliasinfo
, SA_KEPT
, loc
);
5692 static void sRef_setKeptAux (sRef s
, fileloc loc
)
5694 if (!sRef_isShared (s
))
5696 sRef_setKept (s
, loc
);
5700 static void sRef_setDependentAux (sRef s
, fileloc loc
)
5702 if (!sRef_isShared (s
))
5704 sRef_setDependent (s
, loc
);
5708 void sRef_setKeptComplete (sRef s
, fileloc loc
)
5710 sRef_aliasSetComplete (sRef_setKeptAux
, s
, loc
);
5713 void sRef_setDependentComplete (sRef s
, fileloc loc
)
5715 sRef_aliasSetComplete (sRef_setDependentAux
, s
, loc
);
5718 void sRef_setFresh (sRef s
, fileloc loc
)
5720 if (sRef_isReasonable (s
) && !sRef_isConst (s
))
5722 sRef_checkMutable (s
);
5723 s
->aliaskind
= AK_FRESH
;
5724 s
->aliasinfo
= stateInfo_updateLoc (s
->aliasinfo
, SA_CREATED
, loc
);
5725 DPRINTF (("SetFresh: %s", sRef_unparseFull (s
)));
5729 void sRef_kill (sRef s
, fileloc loc
)
5731 DPRINTF (("Kill: %s", sRef_unparseFull (s
)));
5733 if (sRef_isReasonable (s
) && !sRef_isShared (s
) && !sRef_isConst (s
))
5735 sRef base
= sRef_getBaseSafe (s
);
5736 sRef_checkMutable (s
);
5738 while (sRef_isReasonable (base
) && sRef_isKnown (base
))
5740 if (base
->defstate
== SS_DEFINED
)
5742 sRef_checkMutable (base
);
5743 base
->defstate
= SS_PDEFINED
;
5744 base
= sRef_getBaseSafe (base
);
5752 s
->aliaskind
= s
->oaliaskind
;
5753 s
->defstate
= SS_DEAD
;
5754 s
->definfo
= stateInfo_updateLoc (s
->definfo
, SA_KILLED
, loc
);
5755 DPRINTF (("State info: %s", stateInfo_unparse (s
->definfo
)));
5756 sRef_clearDerived (s
);
5760 void sRef_maybeKill (sRef s
, fileloc loc
)
5762 if (sRef_isReasonable (s
))
5764 sRef base
= sRef_getBaseSafe (s
);
5765 sRef_checkMutable (s
);
5767 while (sRef_isReasonable (base
) && sRef_isKnown (base
))
5769 if (base
->defstate
== SS_DEFINED
|| base
->defstate
== SS_RELDEF
)
5771 sRef_checkMutable (base
);
5772 base
->defstate
= SS_PDEFINED
;
5773 base
= sRef_getBaseSafe (base
);
5782 s
->aliaskind
= s
->oaliaskind
;
5783 s
->defstate
= SS_HOFFA
;
5784 s
->definfo
= stateInfo_updateLoc (s
->definfo
, SA_PKILLED
, loc
);
5785 DPRINTF (("State info: %s / %s", sRef_unparse (s
),
5786 stateInfo_unparse (s
->definfo
)));
5787 sRef_clearDerived (s
);
5793 ** just for type checking...
5796 static void sRef_killAux (sRef s
, fileloc loc
)
5798 if (sRef_isReasonable (s
) && !sRef_isShared (s
))
5800 if (sRef_isUnknownArrayFetch (s
))
5802 sRef_maybeKill (s
, loc
);
5812 ** kills s and all aliases to s
5815 void sRef_killComplete (sRef s
, fileloc loc
)
5817 DPRINTF (("Kill complete: %s", sRef_unparseFull (s
)));
5818 sRef_aliasSetComplete (sRef_killAux
, s
, loc
);
5821 static bool sRef_equivalent (sRef s1
, sRef s2
)
5823 return (sRef_compare (s1
, s2
) == 0);
5827 ** returns an sRef that will not be free'd on function exit.
5830 /*@only@*/ sRef
sRef_saveCopy (sRef s
)
5834 if (sRef_isReasonable (s
))
5836 bool old
= inFunction
;
5839 ** Exit the function scope, so this sRef is not
5840 ** stored in the deallocation table.
5844 DPRINTF (("Copying sref: %s", sRef_unparseFull(s
)));
5845 ret
= sRef_copy (s
);
5846 DPRINTF (("Copying ===>: %s", sRef_unparseFull(ret
)));
5851 ret
= sRef_undefined
;
5854 /*@-dependenttrans@*/
5856 /*@=dependenttrans@*/
5859 sRef
sRef_copy (sRef s
)
5861 if (sRef_isKindSpecial (s
) && !sRef_isGlobalMarker (s
))
5864 return s
; /* don't copy specials (except for global markers) */
5868 if (sRef_isReasonable (s
))
5870 sRef t
= sRef_alloc ();
5872 DPRINTF (("Copying: [%p] %s", s
, sRef_unparse (s
)));
5873 DPRINTF (("Full: %s", sRef_unparseFull (s
)));
5877 t
->modified
= s
->modified
;
5878 t
->immut
= FALSE
; /* Note mutability is not copied. */
5880 t
->val
= multiVal_copy (s
->val
);
5882 t
->info
= sinfo_copy (s
);
5883 t
->defstate
= s
->defstate
;
5884 t
->nullstate
= s
->nullstate
;
5885 DPRINTF (("Set null state==> %s", sRef_unparseFull (t
)));
5887 /* start modifications */
5888 t
->bufinfo
.bufstate
= s
->bufinfo
.bufstate
;
5889 t
->bufinfo
.len
= s
->bufinfo
.len
;
5890 t
->bufinfo
.size
= s
->bufinfo
.size
;
5891 /* end modifications */
5893 t
->aliaskind
= s
->aliaskind
;
5894 t
->oaliaskind
= s
->oaliaskind
;
5896 t
->expkind
= s
->expkind
;
5897 t
->oexpkind
= s
->oexpkind
;
5899 t
->nullinfo
= stateInfo_copy (s
->nullinfo
);
5900 t
->aliasinfo
= stateInfo_copy (s
->aliasinfo
);
5901 t
->definfo
= stateInfo_copy (s
->definfo
);
5902 t
->expinfo
= stateInfo_copy (s
->expinfo
);
5904 t
->deriv
= sRefSet_newDeepCopy (s
->deriv
);
5905 t
->state
= valueTable_copy (s
->state
);
5907 DPRINTF (("Made copy: %s => %s", sRef_unparseFull (s
), sRef_unparseFull (t
)));
5912 return sRef_undefined
;
5917 # define PREDTEST(func,s) \
5918 do { if (sRef_isInvalid (s)) { return FALSE; } \
5919 else { if (sRef_isConj (s)) \
5920 { return (func (sRef_getConjA (s)) \
5921 || func (sRef_getConjB (s))); }}} while (FALSE);
5923 bool sRef_isAddress (sRef s
)
5925 PREDTEST (sRef_isAddress
, s
);
5926 return (s
->kind
== SK_ADR
);
5930 ** pretty weak... maybe a flag should control this.
5933 bool sRef_isThroughArrayFetch (sRef s
)
5935 if (sRef_isReasonable (s
))
5943 if (sRef_isArrayFetch (tref
))
5948 lt
= sRef_getBase (tref
);
5950 } while (sRef_isReasonable (tref
));
5956 bool sRef_isArrayFetch (sRef s
)
5958 PREDTEST (sRef_isArrayFetch
, s
);
5959 return (s
->kind
== SK_ARRAYFETCH
);
5962 bool sRef_isMacroParamRef (sRef s
)
5964 if (context_inMacro () && sRef_isCvar (s
))
5966 uentry ue
= sRef_getUentry (s
);
5967 cstring pname
= makeParam (uentry_rawName (ue
));
5968 uentry mac
= usymtab_lookupSafe (pname
);
5970 cstring_free (pname
);
5971 return (uentry_isValid (mac
));
5977 bool sRef_isCvar (sRef s
)
5979 PREDTEST (sRef_isCvar
, s
);
5980 return (s
->kind
== SK_CVAR
);
5983 bool sRef_isConst (sRef s
)
5985 PREDTEST (sRef_isConst
, s
);
5986 return (s
->kind
== SK_CONST
);
5990 bool sRef_isObject (sRef s
)
5992 PREDTEST (sRef_isObject
, s
);
5993 return (s
->kind
== SK_OBJECT
);
5995 # endif /* DEADCODE */
5997 bool sRef_isExternal (sRef s
)
5999 PREDTEST (sRef_isExternal
, s
);
6000 return (s
->kind
== SK_EXTERNAL
);
6003 static bool sRef_isDerived (sRef s
)
6005 PREDTEST (sRef_isDerived
, s
);
6006 return (s
->kind
== SK_DERIVED
);
6009 bool sRef_isField (sRef s
)
6011 PREDTEST (sRef_isField
, s
);
6012 return (s
->kind
== SK_FIELD
);
6015 static bool sRef_isIndex (sRef s
)
6017 PREDTEST (sRef_isIndex
, s
);
6018 return (s
->kind
== SK_ARRAYFETCH
);
6021 bool sRef_isAnyParam (sRef s
)
6023 PREDTEST (sRef_isAnyParam
, s
);
6024 return (s
->kind
== SK_PARAM
);
6027 bool sRef_isParam (sRef s
)
6029 PREDTEST (sRef_isParam
, s
);
6030 return (s
->kind
== SK_PARAM
);
6033 bool sRef_isDirectParam (sRef s
)
6035 PREDTEST (sRef_isDirectParam
, s
);
6037 return ((s
->kind
== SK_CVAR
) &&
6038 (s
->info
->cvar
->lexlevel
== functionScope
) &&
6039 (context_inFunction () &&
6040 (s
->info
->cvar
->index
<= usymId_fromInt (uentryList_size (context_getParams ())))));
6043 bool sRef_isPointer (sRef s
)
6045 PREDTEST (sRef_isPointer
, s
);
6046 return (s
->kind
== SK_PTR
);
6050 ** returns true if storage referenced by s is visible
6053 bool sRef_isReference (sRef s
)
6055 PREDTEST (sRef_isReference
, s
);
6057 return (sRef_isPointer (s
) || sRef_isIndex (s
) || sRef_isFileOrGlobalScope (s
)
6058 || (sRef_isField (s
) && (sRef_isReference (s
->info
->field
->rec
))));
6061 bool sRef_isIReference (sRef s
)
6063 return (sRef_isPointer (s
) || sRef_isAddress (s
) || sRef_isIndex (s
)
6064 || sRef_isField (s
) || sRef_isArrayFetch (s
));
6067 bool sRef_isFileOrGlobalScope (sRef s
)
6069 return (sRef_isCvar (s
) && (s
->info
->cvar
->lexlevel
<= fileScope
));
6072 bool sRef_isRealGlobal (sRef s
)
6074 return (sRef_isCvar (s
) && (s
->info
->cvar
->lexlevel
== globScope
));
6077 bool sRef_isFileStatic (sRef s
)
6079 return (sRef_isCvar (s
) && (s
->info
->cvar
->lexlevel
== fileScope
));
6082 bool sRef_isAliasCheckedGlobal (sRef s
)
6084 if (sRef_isFileOrGlobalScope (s
))
6086 uentry ue
= sRef_getUentry (s
);
6088 return context_checkAliasGlob (ue
);
6096 void sRef_free (/*@only@*/ sRef s
)
6098 if (s
!= sRef_undefined
&& s
->kind
!= SK_SPECIAL
)
6100 DPRINTF (("Free sref: [%p]", s
));
6103 sRef_checkValid (s
);
6106 multiVal_free (s
->val
); /* evans 2002-07-12 */
6108 stateInfo_free (s
->expinfo
);
6109 stateInfo_free (s
->aliasinfo
);
6110 stateInfo_free (s
->definfo
);
6111 stateInfo_free (s
->nullinfo
);
6113 sRefSet_free (s
->deriv
);
6114 s
->deriv
= sRefSet_undefined
;
6116 valueTable_free (s
->state
);
6119 /* drl added to help locate use after release*/
6120 s
->expinfo
= stateInfo_undefined
;
6121 s
->aliasinfo
= stateInfo_undefined
;
6122 s
->definfo
= stateInfo_undefined
;
6123 s
->nullinfo
= stateInfo_undefined
;
6129 void sRef_setType (sRef s
, ctype t
)
6131 if (sRef_isReasonable (s
))
6133 sRef_checkMutable (s
);
6138 void sRef_setTypeFull (sRef s
, ctype t
)
6140 if (sRef_isReasonable (s
))
6142 sRef_checkMutable (s
);
6145 sRefSet_allElements (s
->deriv
, current
)
6147 sRef_setTypeFull (current
, ctype_unknown
);
6148 } end_sRefSet_allElements
;
6153 sRef_buildField (/*@exposed@*/ sRef rec
, /*@dependent@*/ cstring f
)
6155 return (sRef_buildNCField (rec
, f
));
6158 static /*@exposed@*/ sRef
6159 sRef_findDerivedField (/*@notnull@*/ sRef rec
, cstring f
)
6161 sRefSet_allElements (sRef_derivedFields (rec
), sr
)
6163 if (sRef_isReasonable (sr
))
6165 if (sRef_isReasonable (sr
))
6167 if (sr
->info
!= NULL
)
6169 if (sr
->kind
== SK_FIELD
&& cstring_equal (sr
->info
->field
->field
, f
))
6177 llcontbug (message ("Invalid sRef as derived field of %s", sRef_unparse (rec
)));
6180 } end_sRefSet_allElements
;
6182 return sRef_undefined
;
6185 /*@dependent@*/ /*@observer@*/ sRefSet
sRef_derivedFields (/*@temp@*/ sRef rec
)
6187 if (sRef_isReasonable (rec
))
6195 return (sRefSet_undefined
);
6199 static /*@exposed@*/ sRef
6200 sRef_findDerivedPointer (sRef s
)
6202 if (sRef_isReasonable (s
))
6204 sRefSet_realElements (s
->deriv
, sr
)
6206 if (sRef_isReasonable (sr
) && sr
->kind
== SK_PTR
)
6210 } end_sRefSet_realElements
;
6213 return sRef_undefined
;
6217 sRef_isUnknownArrayFetch (sRef s
)
6219 return (sRef_isReasonable (s
)
6220 && s
->kind
== SK_ARRAYFETCH
6221 && !s
->info
->arrayfetch
->indknown
);
6224 static /*@exposed@*/ sRef
6225 sRef_findDerivedArrayFetch (/*@notnull@*/ sRef s
, bool isknown
, int idx
, bool dead
)
6230 sRefSet_realElements (s
->deriv
, sr
)
6232 if (sRef_isReasonable (sr
)
6233 && sr
->kind
== SK_ARRAYFETCH
6234 && sr
->info
->arrayfetch
->indknown
6235 && (sr
->info
->arrayfetch
->ind
== idx
))
6239 } end_sRefSet_realElements
;
6243 sRefSet_realElements (s
->deriv
, sr
)
6245 if (sRef_isReasonable (sr
)
6246 && sr
->kind
== SK_ARRAYFETCH
6247 && (!sr
->info
->arrayfetch
->indknown
6248 || (sr
->info
->arrayfetch
->indknown
&&
6249 sr
->info
->arrayfetch
->ind
== 0)))
6251 if (sRef_isDead (sr
) || sRef_isKept (sr
))
6253 if (dead
|| context_getFlag (FLG_STRICTUSERELEASED
))
6263 } end_sRefSet_realElements
;
6266 return sRef_undefined
;
6269 static /*@exposed@*/ sRef
6270 sRef_buildNCField (/*@exposed@*/ sRef rec
, /*@exposed@*/ cstring f
)
6274 DPRINTF (("Build nc field: %s / %s",
6275 sRef_unparseFull (rec
), f
));
6277 if (sRef_isInvalid (rec
))
6279 return sRef_undefined
;
6283 ** check if the field already has been referenced
6286 s
= sRef_findDerivedField (rec
, f
);
6288 if (sRef_isReasonable (s
))
6294 ctype ct
= ctype_realType (rec
->type
);
6296 DPRINTF (("Field of: %s", sRef_unparse (rec
)));
6300 s
->info
= (sinfo
) dmalloc (sizeof (*s
->info
));
6301 s
->info
->field
= (fldinfo
) dmalloc (sizeof (*s
->info
->field
));
6302 s
->info
->field
->rec
= rec
;
6303 s
->info
->field
->field
= f
; /* doesn't copy f */
6305 if (ctype_isKnown (ct
) && ctype_isSU (ct
))
6307 uentry ue
= uentryList_lookupField (ctype_getFields (ct
), f
);
6309 if (!uentry_isUndefined (ue
))
6311 DPRINTF (("lookup: %s for %s", uentry_unparseFull (ue
),
6312 ctype_unparse (ct
)));
6314 s
->type
= uentry_getType (ue
);
6316 if (ctype_isMutable (s
->type
)
6317 && rec
->aliaskind
!= AK_STACK
6318 && !alkind_isStatic (rec
->aliaskind
))
6320 s
->aliaskind
= rec
->aliaskind
;
6324 s
->aliaskind
= AK_UNKNOWN
;
6327 if (sRef_isStateDefined (rec
) || sRef_isStateUnknown (rec
)
6328 || sRef_isPdefined (rec
))
6330 sRef_setStateFromUentry (s
, ue
);
6334 sRef_setPartsFromUentry (s
, ue
);
6337 s
->oaliaskind
= s
->aliaskind
;
6338 s
->oexpkind
= s
->expkind
;
6340 DPRINTF (("sref: %s", sRef_unparseFull (s
)));
6345 Never report this as an error. It can happen whenever there
6346 is casting involved.
6350 llcontbug (message ("buildNCField --- no field %s: %q / %s",
6351 f, sRef_unparse (s), ctype_unparse (ct)));
6355 return sRef_undefined
;
6359 if (rec
->defstate
== SS_DEFINED
6360 && (s
->defstate
== SS_UNDEFINED
|| s
->defstate
== SS_UNKNOWN
))
6362 s
->defstate
= SS_DEFINED
;
6364 else if (rec
->defstate
== SS_PARTIAL
)
6366 s
->defstate
= SS_PARTIAL
;
6368 else if (rec
->defstate
== SS_ALLOCATED
)
6370 if (ctype_isStackAllocated (ct
) && ctype_isStackAllocated (s
->type
))
6372 s
->defstate
= SS_ALLOCATED
;
6376 s
->defstate
= SS_UNDEFINED
;
6379 else if (s
->defstate
== SS_UNKNOWN
)
6381 s
->defstate
= rec
->defstate
;
6388 if (s
->defstate
== SS_UNDEFINED
)
6390 ctype rt
= ctype_realType (s
->type
);
6392 if (ctype_isArray (rt
) || ctype_isSU (rt
))
6394 s
->defstate
= SS_ALLOCATED
;
6398 sRef_addDeriv (rec
, s
);
6399 DPRINTF (("Add deriv: %s", sRef_unparseFull (rec
)));
6401 if (ctype_isInt (s
->type
) && cstring_equal (f
, REFSNAME
))
6403 s
->aliaskind
= AK_REFS
;
6404 s
->oaliaskind
= AK_REFS
;
6407 DPRINTF (("Build field ==> %s", sRef_unparseFull (s
)));
6413 sRef_isStackAllocated (sRef s
)
6415 return (sRef_isReasonable(s
)
6416 && s
->defstate
== SS_ALLOCATED
&& ctype_isStackAllocated (s
->type
));
6420 void sRef_setArrayFetchState (/*@notnull@*/ /*@exposed@*/ sRef s
,
6421 /*@notnull@*/ /*@exposed@*/ sRef arr
)
6423 sRef_checkMutable (s
);
6425 if (ctype_isRealAP (arr
->type
))
6427 s
->type
= ctype_baseArrayPtr (arr
->type
);
6430 /* a hack, methinks... makeArrayFetch (&a[0]) ==> a[] */
6431 /* evans - 2001-08-27: not sure where this was necessary - it
6432 ** causes an assertion in in aliasCheckPred to fail.
6435 if (sRef_isAddress (arr
))
6437 sRef t
= arr
->info
->ref
;
6439 if (sRef_isArrayFetch (t
))
6441 s
->info
->arrayfetch
->arr
= t
->info
->arrayfetch
->arr
;
6444 else if (ctype_isRealPointer (arr
->type
))
6446 sRef sp
= sRef_findDerivedPointer (arr
);
6448 if (sRef_isReasonable (sp
))
6451 if (ctype_isMutable (s
->type
))
6453 s
->expkind
= sRef_getExKind (sp
);
6454 s
->expinfo
= stateInfo_copy (sp
->expinfo
);
6456 s
->aliaskind
= sp
->aliaskind
;
6457 s
->aliasinfo
= stateInfo_copy (sp
->aliasinfo
);
6460 s
->defstate
= sp
->defstate
;
6462 if (s
->defstate
== SS_DEFINED
)
6464 if (!context_getFlag (FLG_STRICTDESTROY
))
6466 s
->defstate
= SS_PARTIAL
;
6470 DPRINTF (("Set null state: %s / %s", sRef_unparseFull (s
), sRef_unparseFull (sp
)));
6471 sRef_setNullStateN (s
, sRef_getNullState (sp
));
6475 if (arr
->defstate
== SS_UNDEFINED
)
6477 s
->defstate
= SS_UNUSEABLE
;
6479 else if ((arr
->defstate
== SS_ALLOCATED
) && !ctype_isSU (s
->type
))
6481 s
->defstate
= SS_UNDEFINED
;
6485 if (!context_getFlag (FLG_STRICTDESTROY
))
6487 s
->defstate
= SS_PARTIAL
;
6491 s
->defstate
= SS_DEFINED
;
6495 ** Very weak checking for array elements.
6497 ** s->defstate = arr->defstate;
6501 s
->expkind
= sRef_getExKind (arr
);
6502 s
->expinfo
= stateInfo_copy (arr
->expinfo
);
6504 if (arr
->aliaskind
== AK_LOCAL
|| arr
->aliaskind
== AK_FRESH
)
6506 s
->aliaskind
= AK_LOCAL
;
6510 s
->aliaskind
= AK_UNKNOWN
;
6513 sRef_setTypeState (s
);
6518 if (arr
->defstate
== SS_DEFINED
)
6521 ** Very weak checking for array elements.
6523 ** s->defstate = arr->defstate;
6526 if (context_getFlag (FLG_STRICTDESTROY
))
6528 s
->defstate
= SS_DEFINED
;
6532 s
->defstate
= SS_PARTIAL
;
6535 else if (arr
->defstate
== SS_ALLOCATED
)
6537 if (ctype_isRealArray (s
->type
))
6539 s
->defstate
= SS_ALLOCATED
;
6543 if (!s
->info
->arrayfetch
->indknown
)
6546 ** is index is unknown, elements is defined or
6547 ** allocated is any element is!
6550 s
->defstate
= SS_UNDEFINED
;
6552 sRefSet_allElements (arr
->deriv
, sr
)
6554 if (sRef_isReasonable (sr
))
6556 if (sRef_isReasonable (sr
))
6558 if (sr
->defstate
== SS_ALLOCATED
)
6560 s
->defstate
= SS_ALLOCATED
;
6564 if (sr
->defstate
== SS_DEFINED
)
6566 if (context_getFlag (FLG_STRICTDESTROY
))
6568 s
->defstate
= SS_DEFINED
;
6572 s
->defstate
= SS_PARTIAL
;
6581 llcontbug (message ("Invalid sRef as derived element of %s", sRef_unparse (arr
)));
6584 } end_sRefSet_allElements
;
6588 s
->defstate
= SS_UNDEFINED
;
6594 s
->defstate
= arr
->defstate
;
6598 ** kludgey way to guess where aliaskind applies
6601 if (ctype_isMutable (s
->type
)
6602 && !ctype_isPointer (arr
->type
)
6603 && !alkind_isStatic (arr
->aliaskind
)
6604 && !alkind_isStack (arr
->aliaskind
)) /* evs - 2000-06-20: don't pass stack allocation to members */
6606 s
->aliaskind
= arr
->aliaskind
;
6610 s
->aliaskind
= AK_UNKNOWN
;
6613 sRef_setTypeState (s
);
6616 if (sRef_isObserver (arr
))
6618 s
->expkind
= XO_OBSERVER
;
6619 s
->expinfo
= stateInfo_copy (arr
->expinfo
);
6623 /*@exposed@*/ sRef
sRef_buildArrayFetch (/*@exposed@*/ sRef arr
)
6627 if (!sRef_isReasonable (arr
)) {
6628 /*@-nullret@*/ return arr
/*@=nullret@*/;
6631 if (ctype_isRealPointer (arr
->type
))
6633 (void) sRef_buildPointer (arr
); /* do this to define arr! */
6636 s
= sRef_findDerivedArrayFetch (arr
, FALSE
, 0, FALSE
);
6638 if (sRef_isReasonable (s
))
6640 /* evans 2001-07-12: this is bogus, clean-up hack */
6641 if (s
->info
->arrayfetch
->arr
!= arr
)
6644 check (sRefSet_delete (arr
->deriv
, s
));
6645 res
= sRef_buildArrayFetch (arr
);
6646 sRef_copyState (res
, s
);
6647 llassert (res
->info
->arrayfetch
->arr
== arr
);
6651 s
->expkind
= sRef_getExKind (arr
);
6652 s
->expinfo
= stateInfo_copy (arr
->expinfo
);
6660 s
->kind
= SK_ARRAYFETCH
;
6661 s
->info
= (sinfo
) dmalloc (sizeof (*s
->info
));
6662 s
->info
->arrayfetch
= (ainfo
) dmalloc (sizeof (*s
->info
->arrayfetch
));
6663 s
->info
->arrayfetch
->indknown
= FALSE
;
6664 s
->info
->arrayfetch
->ind
= 0;
6665 s
->info
->arrayfetch
->arr
= arr
;
6667 sRef_setArrayFetchState (s
, arr
);
6669 s
->oaliaskind
= s
->aliaskind
;
6670 s
->oexpkind
= s
->expkind
;
6672 if (!context_inProtectVars ())
6674 sRef_addDeriv (arr
, s
);
6677 if (valueTable_isUndefined (s
->state
))
6679 s
->state
= context_createValueTable
6680 (s
, stateInfo_makeLoc (g_currentloc
, SA_CREATED
));
6688 sRef_buildArrayFetchKnown (/*@exposed@*/ sRef arr
, int i
)
6692 if (!sRef_isReasonable (arr
)) {
6693 /*@-nullret@*/ return arr
/*@=nullret@*/;
6696 if (ctype_isRealPointer (arr
->type
))
6698 (void) sRef_buildPointer (arr
); /* do this to define arr! */
6701 s
= sRef_findDerivedArrayFetch (arr
, TRUE
, i
, FALSE
);
6703 if (sRef_isReasonable (s
))
6705 /* evans 2001-07-12: this is bogus, clean-up hack */
6706 if (s
->info
->arrayfetch
->arr
!= arr
)
6710 check (sRefSet_delete (arr
->deriv
, s
));
6711 res
= sRef_buildArrayFetchKnown (arr
, i
);
6713 llassert (res
->info
->arrayfetch
->arr
== arr
);
6714 sRef_copyState (res
, s
);
6715 llassert (res
->info
->arrayfetch
->arr
== arr
);
6719 s
->expkind
= sRef_getExKind (arr
);
6720 s
->expinfo
= stateInfo_copy (arr
->expinfo
);
6722 llassert (s
->info
->arrayfetch
->arr
== arr
);
6729 s
->kind
= SK_ARRAYFETCH
;
6730 s
->info
= (sinfo
) dmalloc (sizeof (*s
->info
));
6731 s
->info
->arrayfetch
= (ainfo
) dmalloc (sizeof (*s
->info
->arrayfetch
));
6732 s
->info
->arrayfetch
->arr
= arr
;
6733 s
->info
->arrayfetch
->indknown
= TRUE
;
6734 s
->info
->arrayfetch
->ind
= i
;
6736 sRef_setArrayFetchState (s
, arr
);
6737 /* evans 2001-08-27 no: can change this - llassert (s->info->arrayfetch->arr == arr); */
6739 s
->oaliaskind
= s
->aliaskind
;
6740 s
->oexpkind
= s
->expkind
;
6741 sRef_addDeriv (arr
, s
);
6743 llassert (valueTable_isUndefined (s
->state
));
6744 s
->state
= context_createValueTable (s
, stateInfo_makeLoc (g_currentloc
, SA_CREATED
));
6750 ** sets everything except for defstate
6754 sRef_setPartsFromUentry (sRef s
, uentry ue
)
6756 sRef uref
= uentry_getSref (ue
);
6758 llassert (sRef_isReasonable (s
));
6760 s
->aliaskind
= alkind_derive (s
->aliaskind
, uentry_getAliasKind (ue
));
6761 s
->oaliaskind
= s
->aliaskind
;
6763 if (s
->expkind
== XO_UNKNOWN
)
6765 s
->expkind
= uentry_getExpKind (ue
);
6768 s
->oexpkind
= s
->expkind
;
6770 if (sRef_getNullState (s
) == NS_UNKNOWN
)
6772 DPRINTF (("Set null state: %s / %s", sRef_unparseFull (s
), uentry_unparseFull (ue
)));
6773 sRef_setNullStateN (s
, sRef_getNullState (uentry_getSref (ue
)));
6777 DPRINTF (("Skipping null null state!"));
6780 if (s
->aliaskind
== AK_IMPONLY
&& (sRef_isExposed (s
) || sRef_isObserver (s
)))
6782 s
->oaliaskind
= s
->aliaskind
= AK_IMPDEPENDENT
;
6785 if (sRef_isReasonable (uref
))
6787 valueTable utable
= uref
->state
;
6788 valueTable_free (s
->state
);
6789 s
->state
= valueTable_copy (utable
);
6794 sRef_setStateFromAbstractUentry (sRef s
, uentry ue
)
6796 llassert (sRef_isReasonable (s
));
6797 sRef_checkMutable (s
);
6799 sRef_setPartsFromUentry (s
, ue
);
6801 s
->aliaskind
= alkind_derive (s
->aliaskind
, uentry_getAliasKind (ue
));
6802 s
->oaliaskind
= s
->aliaskind
;
6804 if (s
->expkind
== XO_UNKNOWN
)
6806 s
->expkind
= uentry_getExpKind (ue
);
6809 s
->oexpkind
= s
->expkind
;
6813 sRef_setStateFromUentry (sRef s
, uentry ue
)
6817 sRef_checkMutable (s
);
6818 llassert (sRef_isReasonable (s
));
6820 sRef_setPartsFromUentry (s
, ue
);
6822 defstate
= uentry_getDefState (ue
);
6824 if (sstate_isKnown (defstate
))
6826 s
->defstate
= defstate
;
6835 sRef_buildPointer (/*@exposed@*/ sRef t
)
6837 DPRINTF (("build pointer: %s", sRef_unparse (t
)));
6839 if (sRef_isInvalid (t
)) return sRef_undefined
;
6841 if (sRef_isAddress (t
))
6843 DPRINTF (("Return ref: %s", sRef_unparse (t
->info
->ref
)));
6844 return (t
->info
->ref
);
6848 sRef s
= sRef_findDerivedPointer (t
);
6850 DPRINTF (("find derived: %s", sRef_unparse (s
)));
6852 if (sRef_isReasonable (s
))
6854 s
->expkind
= sRef_getExKind (t
);
6855 s
->expinfo
= stateInfo_copy (t
->expinfo
);
6857 s
->oaliaskind
= s
->aliaskind
;
6858 s
->oexpkind
= s
->expkind
;
6864 s
= sRef_constructPointerAux (t
);
6866 DPRINTF (("construct: %s", sRef_unparse (s
)));
6868 if (sRef_isReasonable (s
))
6870 sRef_addDeriv (t
, s
);
6872 s
->oaliaskind
= s
->aliaskind
;
6873 s
->oexpkind
= s
->expkind
;
6882 sRef_constructPointer (/*@exposed@*/ sRef t
)
6885 return sRef_buildPointer (t
);
6888 static /*@exposed@*/ sRef
sRef_constructDerefAux (sRef t
, bool isdead
)
6890 if (sRef_isReasonable (t
))
6895 ** if there is a derived t[?], return that. Otherwise, *t.
6898 s
= sRef_findDerivedArrayFetch (t
, FALSE
, 0, isdead
);
6900 if (sRef_isReasonable (s
))
6902 DPRINTF (("Found array fetch: %s", sRef_unparseFull (s
)));
6907 sRef ret
= sRef_constructPointer (t
);
6909 DPRINTF (("Constructed pointer: %s", sRef_unparseFull (ret
)));
6916 return sRef_undefined
;
6920 sRef
sRef_constructDeref (sRef t
)
6922 return sRef_constructDerefAux (t
, FALSE
);
6925 sRef
sRef_constructDeadDeref (sRef t
)
6927 return sRef_constructDerefAux (t
, TRUE
);
6931 sRef_constructPointerAux (/*@notnull@*/ /*@exposed@*/ sRef t
)
6933 sRef s
= sRef_newRef ();
6937 llassert (valueTable_isUndefined (s
->state
));
6940 s
->info
= (sinfo
) dmalloc (sizeof (*s
->info
));
6943 if (ctype_isRealAP (rt
))
6945 s
->type
= ctype_baseArrayPtr (rt
);
6948 st
= ctype_realType (s
->type
);
6950 if (t
->defstate
== SS_UNDEFINED
)
6952 s
->defstate
= SS_UNUSEABLE
;
6953 s
->definfo
= stateInfo_copy (t
->definfo
);
6955 else if ((t
->defstate
== SS_ALLOCATED
) && !ctype_isSU (st
))
6957 s
->defstate
= SS_UNDEFINED
;
6958 s
->definfo
= stateInfo_copy (t
->definfo
);
6962 s
->defstate
= t
->defstate
;
6963 s
->definfo
= stateInfo_copy (t
->definfo
);
6966 if (t
->aliaskind
== AK_LOCAL
|| t
->aliaskind
== AK_FRESH
)
6968 s
->aliaskind
= AK_LOCAL
;
6972 s
->aliaskind
= AK_UNKNOWN
;
6975 s
->expkind
= sRef_getExKind (t
);
6976 s
->expinfo
= stateInfo_copy (t
->expinfo
);
6978 sRef_setTypeState (s
);
6980 s
->oaliaskind
= s
->aliaskind
;
6981 s
->oexpkind
= s
->expkind
;
6983 if (valueTable_isUndefined (s
->state
))
6985 s
->state
= context_createValueTable (s
, stateInfo_makeLoc (g_currentloc
, SA_CREATED
));
6988 DPRINTF (("pointer: %s", sRef_unparseFull (s
)));
6992 bool sRef_hasDerived (sRef s
)
6994 return (sRef_isReasonable (s
) && !sRefSet_isEmpty (s
->deriv
));
6998 sRef_clearDerived (sRef s
)
7000 if (sRef_isReasonable (s
))
7002 DPRINTF (("Clear derived: [%p] %s", s
, sRef_unparseDebug (s
)));
7003 sRefSet_clear (s
->deriv
);
7008 sRef_clearDerivedComplete (sRef s
)
7010 if (sRef_isReasonable (s
))
7012 sRef base
= sRef_getBaseSafe (s
);
7014 while (sRef_isReasonable (base
))
7016 DPRINTF (("Clear derived: [%p] %s", base
, sRef_unparse (base
)));
7017 sRefSet_clear (base
->deriv
);
7018 base
= sRef_getBaseSafe (base
);
7021 DPRINTF (("Clear derived: [%p] %s", s
, sRef_unparse (s
)));
7022 sRefSet_clear (s
->deriv
);
7026 /*@exposed@*/ sRef
sRef_makePointer (/*@exposed@*/ sRef s
)
7029 sRef res
= sRef_buildPointer (s
);
7031 DPRINTF (("Res: %s", sRef_unparseFull (res
)));
7036 ** &a[] => a (this is for out params)
7040 sRef_makeAnyArrayFetch (/*@exposed@*/ sRef arr
)
7042 if (sRef_isAddress (arr
))
7044 return (arr
->info
->ref
);
7048 return (sRef_buildArrayFetch (arr
));
7053 sRef_makeArrayFetch (/*@exposed@*/ sRef arr
)
7055 return (sRef_buildArrayFetch (arr
));
7059 sRef_makeArrayFetchKnown (/*@exposed@*/ sRef arr
, int i
)
7061 return (sRef_buildArrayFetchKnown (arr
, i
));
7065 sRef_makeField (sRef rec
, /*@dependent@*/ cstring f
)
7068 ret
= sRef_buildField (rec
, f
);
7073 sRef_makeNCField (/*@exposed@*/ sRef rec
, /*@dependent@*/ cstring f
)
7075 return (sRef_buildNCField (rec
, f
));
7078 static /*@only@*/ cstring
7079 sRef_unparseKindNameAux (sRef s
, bool plain
)
7083 if (s
== sRef_undefined
)
7084 return cstring_makeLiteral ("<invalid>");
7086 s
= sRef_fixConj (s
);
7091 if (sRef_isLocalVar (s
))
7093 result
= cstring_makeLiteral ("Variable");
7097 result
= cstring_makeLiteral (plain
? "Global" : "Undef global");
7101 result
= cstring_makeLiteral (plain
? "Parameter" : "Out parameter");
7104 if (sRef_isAnyParam (s
->info
->arrayfetch
->arr
))
7106 result
= cstring_makeLiteral (plain
? "Parameter" : "Out parameter");
7108 else if (sRef_isIndexKnown (s
))
7110 result
= cstring_makeLiteral ("Array element");
7114 result
= cstring_makeLiteral ("Value");
7118 if (sRef_isAnyParam (s
->info
->ref
))
7120 result
= cstring_makeLiteral (plain
? "Parameter" : "Out parameter");
7124 result
= cstring_makeLiteral ("Value");
7128 result
= cstring_makeLiteral ("Value");
7131 result
= cstring_makeLiteral ("Field");
7134 result
= cstring_makeLiteral ("Object");
7136 case SK_UNCONSTRAINED
:
7137 result
= cstring_makeLiteral ("<anything>");
7146 result
= cstring_makeLiteral ("<unknown>");
7149 result
= cstring_makeLiteral ("<conj>");
7152 result
= cstring_makeLiteral ("Storage");
7155 return cstring_makeLiteral ("<invalid>");
7162 sRef_unparseKindName (sRef s
)
7164 return sRef_unparseKindNameAux (s
, FALSE
);
7168 sRef_unparseKindNamePlain (sRef s
)
7170 return sRef_unparseKindNameAux (s
, TRUE
);
7178 sRef_copyState (sRef s1
, sRef s2
)
7180 if (s1
!= s2
&& sRef_isReasonable (s1
) && sRef_isReasonable (s2
))
7182 s1
->defstate
= s2
->defstate
;
7184 /* start modifications */
7185 s1
->bufinfo
.bufstate
= s2
->bufinfo
.bufstate
;
7186 s1
->bufinfo
.len
= s2
->bufinfo
.len
;
7187 s1
->bufinfo
.size
= s2
->bufinfo
.size
;
7188 /* end modifications */
7190 s1
->aliaskind
= s2
->aliaskind
;
7191 s1
->aliasinfo
= stateInfo_update (s1
->aliasinfo
, s2
->aliasinfo
);
7193 s1
->expkind
= s2
->expkind
;
7194 s1
->expinfo
= stateInfo_update (s1
->expinfo
, s2
->expinfo
);
7196 s1
->nullstate
= s2
->nullstate
;
7197 DPRINTF (("Set null state==> %s", sRef_unparseFull (s1
)));
7198 s1
->nullinfo
= stateInfo_update (s1
->nullinfo
, s2
->nullinfo
);
7200 if (s1
->state
!= s2
->state
)
7202 valueTable_free (s1
->state
);
7203 s1
->state
= valueTable_copy (s2
->state
);
7206 s1
->safe
= s2
->safe
;
7211 sRef_makeNew (ctype ct
, sRef t
, cstring name
)
7213 sRef s
= sRef_newRef ();
7218 llassert (sRef_isReasonable (t
));
7219 s
->defstate
= t
->defstate
;
7221 s
->aliaskind
= t
->aliaskind
;
7222 s
->oaliaskind
= s
->aliaskind
;
7223 s
->nullstate
= t
->nullstate
;
7225 s
->expkind
= t
->expkind
;
7226 s
->oexpkind
= s
->expkind
;
7228 s
->info
= (sinfo
) dmalloc (sizeof (*s
->info
));
7229 s
->info
->fname
= name
;
7231 /* start modifications */
7232 s
->bufinfo
.bufstate
= t
->bufinfo
.bufstate
;
7233 /* end modifications */
7235 llassert (valueTable_isUndefined (s
->state
));
7236 s
->state
= valueTable_copy (t
->state
);
7238 DPRINTF (("==> Copying state: %s", valueTable_unparse (s
->state
)));
7239 DPRINTF (("==> new: %s", sRef_unparseFull (s
)));
7244 sRef_makeType (ctype ct
)
7246 sRef s
= sRef_newRef ();
7248 sRef_checkMutable (s
);
7253 s
->defstate
= SS_UNKNOWN
;
7254 s
->aliaskind
= AK_UNKNOWN
;
7255 sRef_setNullStateN (s
, NS_UNKNOWN
);
7257 /* start modification */
7258 s
->bufinfo
.bufstate
= BB_NOTNULLTERMINATED
;
7259 /* end modification */
7261 if (ctype_isUA (ct
))
7263 typeId uid
= ctype_typeId (ct
);
7264 uentry ue
= usymtab_getTypeEntrySafe (uid
);
7266 if (uentry_isValid (ue
))
7268 sRef_mergeStateQuiet (s
, uentry_getSref (ue
));
7272 s
->oaliaskind
= s
->aliaskind
;
7273 s
->oexpkind
= s
->expkind
;
7274 llassert (valueTable_isUndefined (s
->state
));
7275 s
->state
= context_createValueTable (s
, stateInfo_makeLoc (g_currentloc
, SA_CREATED
));
7277 DPRINTF (("Create: %s", sRef_unparseFull (s
)));
7282 sRef_makeConst (ctype ct
)
7284 sRef s
= sRef_newRef ();
7289 s
->defstate
= SS_UNKNOWN
;
7290 s
->aliaskind
= AK_UNKNOWN
;
7291 sRef_setNullStateN (s
, NS_UNKNOWN
);
7293 /* start modification */
7294 s
->bufinfo
.bufstate
= BB_NULLTERMINATED
;
7295 /* end modification */
7297 /* evans 2002-04-22: added isManifestBool to avoid errors for -boolfalse initializations */
7298 if (!ctype_isManifestBool (ct
) && ctype_isUA (ct
))
7300 typeId uid
= ctype_typeId (ct
);
7301 uentry te
= usymtab_getTypeEntrySafe (uid
);
7303 if (uentry_isValid (te
))
7305 sRef_mergeStateQuiet (s
, uentry_getSref (te
));
7309 s
->oaliaskind
= s
->aliaskind
;
7310 s
->oexpkind
= s
->expkind
;
7312 llassert (valueTable_isUndefined (s
->state
));
7313 s
->state
= context_createValueTable (s
, stateInfo_makeLoc (g_currentloc
, SA_CREATED
));
7318 bool sRef_hasName (sRef s
)
7320 if (sRef_isInvalid (s
))
7329 uentry u
= usymtab_getRefQuiet (s
->info
->cvar
->lexlevel
,
7330 s
->info
->cvar
->index
);
7331 return (uentry_hasName (u
));
7335 if (s
->info
->paramno
>= 0)
7337 uentry u
= uentryList_getN (context_getParams (),
7340 return (uentry_hasName (u
));
7344 llassert (s
->info
->paramno
== PARAMUNKNOWN
);
7354 sRef_sameName (sRef s1
, sRef s2
)
7356 if (sRef_isInvalid (s1
))
7358 return sRef_isInvalid (s2
);
7361 if (sRef_isInvalid (s2
))
7369 if (s2
->kind
== SK_CVAR
)
7371 return (s1
->info
->cvar
->lexlevel
== s2
->info
->cvar
->lexlevel
7372 && s1
->info
->cvar
->index
== s2
->info
->cvar
->index
);
7374 else if (s2
->kind
== SK_PARAM
)
7376 if (context_inFunctionLike ())
7378 if (s2
->info
->paramno
!= PARAMUNKNOWN
)
7380 uentry u1
= usymtab_getRefQuiet (s1
->info
->cvar
->lexlevel
,
7381 s1
->info
->cvar
->index
);
7382 uentry u2
= uentryList_getN (context_getParams (),
7385 return (cstring_equalFree (uentry_getName (u1
),
7386 uentry_getName (u2
)));
7390 return s1
->info
->paramno
== PARAMUNKNOWN
;
7404 if (s2
->kind
== SK_PARAM
)
7406 return (s1
->info
->paramno
== s2
->info
->paramno
);
7408 else if (s2
->kind
== SK_CVAR
)
7410 if (context_inFunctionLike ())
7412 if (s1
->info
->paramno
== PARAMUNKNOWN
)
7418 uentry u1
= uentryList_getN (context_getParams (),
7420 uentry u2
= usymtab_getRefQuiet (s2
->info
->cvar
->lexlevel
,
7421 s2
->info
->cvar
->index
);
7423 return (cstring_equalFree (uentry_getName (u1
),
7424 uentry_getName (u2
)));
7438 case SK_UNCONSTRAINED
:
7442 if (s2
->kind
== SK_ARRAYFETCH
)
7444 if (bool_equal (s1
->info
->arrayfetch
->indknown
,
7445 s2
->info
->arrayfetch
->indknown
))
7447 if (!s1
->info
->arrayfetch
->indknown
7448 || (s1
->info
->arrayfetch
->ind
== s2
->info
->arrayfetch
->ind
))
7450 return sRef_sameName (s1
->info
->arrayfetch
->arr
,
7451 s2
->info
->arrayfetch
->arr
);
7458 if (s2
->kind
== SK_FIELD
)
7460 if (cstring_equal (s1
->info
->field
->field
,
7461 s2
->info
->field
->field
))
7463 return sRef_sameName (s1
->info
->field
->rec
,
7464 s2
->info
->field
->rec
);
7473 if (s2
->kind
== s1
->kind
)
7475 return sRef_sameName (s1
->info
->ref
,
7483 return sRef_sameName (sRef_getConjA (s1
), s2
);
7487 return (s2
->kind
== SK_UNKNOWN
);
7490 if (s2
->kind
== s1
->kind
)
7492 return (ctype_equal (s1
->type
, s2
->type
));
7497 if (s2
->kind
== SK_SPECIAL
)
7499 return (s1
->info
->spec
== s2
->info
->spec
);
7503 return (s2
->kind
== SK_RESULT
);
7511 sRef_fixOuterRef (/*@returned@*/ sRef s
)
7513 sRef root
= sRef_getRootBase (s
);
7515 if (sRef_isCvar (root
))
7517 uentry ue
= usymtab_getRefQuiet (root
->info
->cvar
->lexlevel
,
7518 root
->info
->cvar
->index
);
7520 if (uentry_isValid (ue
))
7522 sRef uref
= uentry_getSref (ue
);
7523 sRef sr
= sRef_fixBase (s
, uref
);
7529 llcontbug (message ("sRef_fixOuterRef: undefined: %q", sRef_unparseDebug (s
)));
7538 sRef_storeState (sRef s
)
7540 if (sRef_isInvalid (s
)) return;
7542 sRef_checkMutable (s
);
7543 s
->oaliaskind
= s
->aliaskind
;
7544 s
->oexpkind
= s
->expkind
;
7547 static void sRef_resetStateAux (sRef s
, /*@unused@*/ fileloc loc
)
7549 sRef_resetState (s
);
7553 sRef_resetState (sRef s
)
7555 bool changed
= FALSE
;
7556 if (sRef_isInvalid (s
)) return;
7558 if (s
->expkind
!= s
->oexpkind
)
7561 s
->expkind
= s
->oexpkind
;
7564 if (s
->oaliaskind
== AK_KILLREF
&& !sRef_isParam (s
))
7567 ** killref is used in a kludgey way, to save having to add
7568 ** another alias kind (see usymtab_handleParams)
7571 else if (s
->oaliaskind
!= s
->aliaskind
7572 && !(s
->aliaskind
== AK_REFCOUNTED
|| s
->aliaskind
== AK_REFS
))
7575 s
->aliaskind
= s
->oaliaskind
;
7580 sRef_clearDerived (s
);
7585 sRef_resetStateComplete (sRef s
)
7587 sRef_innerAliasSetComplete (sRef_resetStateAux
, s
, fileloc_undefined
);
7591 sRef_fixBase (/*@returned@*/ sRef s
, /*@returned@*/ sRef base
)
7593 sRef tmp
= sRef_undefined
;
7596 if (sRef_isInvalid (s
)) return s
;
7597 if (sRef_isInvalid (base
)) return base
;
7607 tmp
= sRef_fixBase (s
->info
->arrayfetch
->arr
, base
);
7609 if (s
->info
->arrayfetch
->indknown
)
7611 ret
= sRef_makeArrayFetchKnown (tmp
, s
->info
->arrayfetch
->ind
);
7615 ret
= sRef_makeArrayFetch (tmp
);
7619 tmp
= sRef_fixBase (s
->info
->field
->rec
, base
);
7620 ret
= sRef_buildNCField (tmp
, s
->info
->field
->field
);
7623 tmp
= sRef_fixBase (s
->info
->ref
, base
);
7624 ret
= sRef_makePointer (tmp
);
7627 tmp
= sRef_fixBase (s
->info
->ref
, base
);
7628 ret
= sRef_makeAddress (tmp
);
7634 tmp
= sRef_fixBase (s
->info
->conj
->a
, base
);
7635 tmpb
= sRef_fixBase (s
->info
->conj
->b
, base
);
7637 ret
= sRef_makeConj (tmp
, tmpb
);
7646 static /*@exposed@*/ sRef
7647 sRef_fixDirectBase (sRef s
, sRef base
)
7651 if (sRef_isInvalid (s
))
7653 return sRef_undefined
;
7659 if (s
->info
->arrayfetch
->indknown
)
7661 ret
= sRef_makeArrayFetchKnown (base
, s
->info
->arrayfetch
->ind
);
7665 ret
= sRef_makeArrayFetch (base
);
7669 ret
= sRef_buildNCField (base
, s
->info
->field
->field
);
7672 ret
= sRef_makePointer (base
);
7675 ret
= sRef_makeAddress (base
);
7681 tmpa
= sRef_fixDirectBase (s
->info
->conj
->a
, base
);
7682 tmpb
= sRef_fixDirectBase (s
->info
->conj
->b
, base
);
7684 ret
= sRef_makeConj (tmpa
, tmpb
);
7690 sRef_copyState (ret
, s
);
7695 sRef_isAllocIndexRef (sRef s
)
7697 return (sRef_isArrayFetch (s
) && !(s
->info
->arrayfetch
->indknown
)
7698 && sRef_isAllocated (s
->info
->arrayfetch
->arr
));
7702 sRef_showRefLost (sRef s
)
7704 if (sRef_hasAliasInfoLoc (s
))
7706 llgenindentmsg (cstring_makeLiteral ("Original reference lost"),
7707 sRef_getAliasInfoLoc (s
));
7712 sRef_showRefKilled (sRef s
)
7714 if (sRef_isValid (s
))
7716 DPRINTF (("Killed: %s", sRef_unparseFull (s
)));
7717 if (context_getLocIndentSpaces () == 0) {
7718 stateInfo_display (s
->definfo
, message (" Storage %q", sRef_unparseOpt (s
)));
7720 stateInfo_display (s
->definfo
, message ("Storage %q", sRef_unparseOpt (s
)));
7726 sRef_showStateInconsistent (sRef s
)
7728 if (sRef_hasStateInfoLoc (s
))
7731 (message ("Storage %qbecomes inconsistent (released on one branch)",
7732 sRef_unparseOpt (s
)),
7733 sRef_getStateInfoLoc (s
));
7738 sRef_showStateInfo (sRef s
)
7740 if (sRef_isValid (s
)) {
7741 if (context_getLocIndentSpaces () == 0) {
7742 stateInfo_display (s
->definfo
, message (" Storage %q", sRef_unparseOpt (s
)));
7744 stateInfo_display (s
->definfo
, message ("Storage %q", sRef_unparseOpt (s
)));
7750 sRef_showExpInfo (sRef s
)
7752 if (sRef_isValid (s
)) {
7753 if (context_getLocIndentSpaces () == 0) {
7754 stateInfo_display (s
->expinfo
, message (" Storage %q", sRef_unparseOpt (s
)));
7756 stateInfo_display (s
->expinfo
, message ("Storage %q", sRef_unparseOpt (s
)));
7762 sRef_showMetaStateInfo (sRef s
, cstring key
)
7765 metaStateInfo minfo
= context_lookupMetaStateInfo (key
);
7767 llassert (sRef_isReasonable (s
));
7768 llassert (valueTable_isDefined (s
->state
));
7769 llassert (metaStateInfo_isDefined (minfo
));
7771 val
= valueTable_lookup (s
->state
, key
);
7773 if (stateValue_hasLoc (val
))
7776 (message ("%qbecomes %q", sRef_unparseOpt (s
),
7777 stateValue_unparseValue (val
, minfo
)),
7778 stateValue_getLoc (val
));
7783 sRef_showNullInfo (sRef s
)
7785 DPRINTF (("Show null info: %s", sRef_unparseFull (s
)));
7787 if (sRef_hasNullInfoLoc (s
) && sRef_isKnown (s
))
7789 DPRINTF (("has null info: %s",
7790 fileloc_unparse (sRef_getNullInfoLoc (s
))));
7792 switch (sRef_getNullState (s
))
7796 fileloc loc
= sRef_getNullInfoLoc (s
);
7798 if (fileloc_isDefined (loc
) && !fileloc_isLib (loc
))
7801 (message ("Storage %qbecomes null", sRef_unparseOpt (s
)),
7808 fileloc loc
= sRef_getNullInfoLoc (s
);
7810 if (fileloc_isDefined (loc
) && !fileloc_isLib (loc
))
7812 llgenindentmsg (message ("Storage %qbecomes null", sRef_unparseOpt (s
)),
7820 (message ("Storage %qmay become null", sRef_unparseOpt (s
)),
7821 sRef_getNullInfoLoc (s
));
7826 (message ("Storage %qbecomes not null", sRef_unparseOpt (s
)),
7827 sRef_getNullInfoLoc (s
));
7831 (message ("Storage %qnull state becomes unknown",
7832 sRef_unparseOpt (s
)),
7833 sRef_getNullInfoLoc (s
));
7842 (message ("<error case> Storage %q becomes %s",
7844 nstate_unparse (sRef_getNullState (s
))),
7845 sRef_getNullInfoLoc (s
));
7853 sRef_showAliasInfo (sRef s
)
7855 if (sRef_isValid (s
))
7857 if (sRef_isFresh (s
))
7859 if (context_getLocIndentSpaces () == 0) {
7860 stateInfo_display (s
->aliasinfo
, message (" Fresh storage %q", sRef_unparseOpt (s
)));
7862 stateInfo_display (s
->aliasinfo
, message ("Fresh storage %q", sRef_unparseOpt (s
)));
7867 if (context_getLocIndentSpaces () == 0) {
7868 stateInfo_display (s
->aliasinfo
, message (" Storage %q", sRef_unparseOpt (s
)));
7870 stateInfo_display (s
->aliasinfo
, message ("Storage %q", sRef_unparseOpt (s
)));
7877 sRef_mergeNullState (sRef s
, nstate n
)
7879 if (sRef_isReasonable (s
))
7883 old
= sRef_getNullState (s
);
7885 if (n
!= old
&& n
!= NS_UNKNOWN
)
7887 sRef_setNullState (s
, n
, g_currentloc
);
7892 llbuglit ("sRef_mergeNullState: invalid");
7897 sRef_possiblyNull (sRef s
)
7899 if (sRef_isReasonable (s
))
7901 if (sRef_getNullState (s
) == NS_ABSNULL
)
7903 ctype rct
= ctype_realType (s
->type
);
7905 if (ctype_isAbstract (rct
))
7911 if (ctype_isUser (rct
))
7913 uentry ue
= usymtab_getTypeEntry (ctype_typeId (rct
));
7915 return (nstate_possiblyNull
7916 (sRef_getNullState (uentry_getSref (ue
))));
7926 return nstate_possiblyNull (sRef_getNullState (s
));
7934 sRef_getScopeName (sRef s
)
7936 sRef base
= sRef_getRootBase (s
);
7938 if (sRef_isRealGlobal (base
))
7940 return (cstring_makeLiteralTemp ("Global"));
7942 else if (sRef_isFileStatic (base
))
7944 return (cstring_makeLiteralTemp ("Static"));
7948 return (cstring_makeLiteralTemp ("Local"));
7953 sRef_unparseScope (sRef s
)
7955 sRef base
= sRef_getRootBase (s
);
7957 if (sRef_isRealGlobal (base
))
7959 return (cstring_makeLiteralTemp ("global"));
7961 else if (sRef_isFileStatic (base
))
7963 return (cstring_makeLiteralTemp ("file static"));
7972 sRef_getScope (sRef s
)
7974 llassert (sRef_isReasonable (s
));
7976 if (sRef_isCvar (s
))
7978 return s
->info
->cvar
->lexlevel
;
7980 else if (sRef_isParam (s
))
7991 sRef_isDead (sRef s
)
7993 return (sRef_isReasonable (s
) && (s
)->defstate
== SS_DEAD
);
7997 sRef_isDeadStorage (sRef s
)
7999 if (sRef_isReasonable (s
))
8001 if (s
->defstate
== SS_DEAD
8002 || s
->defstate
== SS_UNUSEABLE
8003 || s
->defstate
== SS_UNDEFINED
8004 || s
->defstate
== SS_UNKNOWN
)
8010 return (sRef_isDefinitelyNull (s
));
8020 sRef_isPossiblyDead (sRef s
)
8022 return (sRef_isReasonable (s
) && s
->defstate
== SS_HOFFA
);
8025 bool sRef_isStateLive (sRef s
)
8027 if (sRef_isReasonable (s
))
8029 sstate ds
= s
->defstate
;
8031 return (!(ds
== SS_UNDEFINED
8033 || ds
== SS_UNUSEABLE
8034 || ds
== SS_HOFFA
));
8043 bool sRef_isStateUndefined (sRef s
)
8045 return ((sRef_isReasonable(s
)) && ((s
)->defstate
== SS_UNDEFINED
));
8048 bool sRef_isJustAllocated (sRef s
)
8050 if (sRef_isAllocated (s
))
8052 sRefSet_allElements (s
->deriv
, el
)
8054 if (!(sRef_isStateUndefined (el
) || sRef_isUnuseable (el
)))
8058 } end_sRefSet_allElements
;
8067 sRef_isAllocatedStorage (sRef s
)
8069 if (sRef_isReasonable (s
) && ynm_toBoolStrict (sRef_isValidLvalue (s
)))
8071 return (ctype_isVisiblySharable (sRef_getType (s
)));
8080 sRef_isUnuseable (sRef s
)
8082 return ((sRef_isValid(s
)) && ((s
)->defstate
== SS_UNUSEABLE
));
8086 sRef_perhapsNull (sRef s
)
8088 if (sRef_isReasonable (s
))
8090 if (sRef_getNullState (s
) == NS_ABSNULL
)
8092 ctype rct
= ctype_realType (s
->type
);
8094 if (ctype_isAbstract (rct
))
8100 if (ctype_isUser (rct
))
8102 uentry ue
= usymtab_getTypeEntry (ctype_typeId (rct
));
8104 return (nstate_perhapsNull
8105 (sRef_getNullState (uentry_getSref (ue
))));
8115 return nstate_perhapsNull (sRef_getNullState (s
));
8123 ** definitelyNull --- called when TRUE is good
8127 sRef_definitelyNull (sRef s
)
8129 return (sRef_isReasonable (s
)
8130 && (sRef_getNullState (s
) == NS_DEFNULL
|| sRef_getNullState (s
) == NS_CONSTNULL
));
8134 ** based on sRef_similar
8138 sRef_setDerivNullState (sRef set
, sRef guide
, nstate ns
)
8140 if (sRef_isReasonable (set
))
8142 sRef deriv
= sRef_getDeriv (set
, guide
);
8144 if (sRef_isReasonable (deriv
))
8146 sRef_setNullStateN (deriv
, ns
);
8151 static /*@exposed@*/ sRef
8152 sRef_getDeriv (/*@returned@*/ /*@notnull@*/ sRef set
, sRef guide
)
8154 llassert (sRef_isReasonable (set
));
8155 llassert (sRef_isReasonable (guide
));
8157 switch (guide
->kind
)
8160 llassert (set
->kind
== SK_CVAR
);
8164 llassert (set
->kind
== guide
->kind
);
8165 llassert (set
->info
->paramno
== guide
->info
->paramno
);
8170 if (set
->kind
== SK_ARRAYFETCH
8171 && (sRef_similar (set
->info
->arrayfetch
->arr
,
8172 guide
->info
->arrayfetch
->arr
)))
8178 return (sRef_makeAnyArrayFetch
8179 (sRef_getDeriv (set
, guide
->info
->arrayfetch
->arr
)));
8184 if (set
->kind
== SK_PTR
&& sRef_similar (set
->info
->ref
, guide
->info
->ref
))
8190 return (sRef_makePointer (sRef_getDeriv (set
, guide
->info
->ref
)));
8195 if ((set
->kind
== SK_FIELD
&&
8196 (sRef_similar (set
->info
->field
->rec
, guide
->info
->field
->rec
) &&
8197 cstring_equal (set
->info
->field
->field
, guide
->info
->field
->field
))))
8203 return (sRef_makeField (sRef_getDeriv (set
, guide
->info
->field
->rec
),
8204 guide
->info
->field
->field
));
8208 if ((set
->kind
== SK_ADR
) && sRef_similar (set
->info
->ref
, guide
->info
->ref
))
8214 return (sRef_makeAddress (sRef_getDeriv (set
, guide
->info
->ref
)));
8219 return sRef_undefined
;
8223 case SK_UNCONSTRAINED
:
8231 return sRef_undefined
;
8238 ** sRef_aliasCheckPred
8240 ** A confusing but spiffy function:
8242 ** Calls predf (s, e, text, <alias>) on s and all of s's aliases
8243 ** (unless checkAliases (s) is FALSE).
8245 ** For alias calls, calls as
8246 ** predf (alias, e, text, s)
8250 sRef_aliasCheckPred (bool (predf
) (sRef
, exprNode
, sRef
, exprNode
),
8251 /*@null@*/ bool (checkAliases
) (sRef
),
8252 sRef s
, exprNode e
, exprNode err
)
8254 bool error
= (*predf
)(s
, e
, sRef_undefined
, err
);
8256 if (checkAliases
!= NULL
&& !(checkAliases (s
)))
8258 /* don't check aliases */
8262 sRefSet aliases
= usymtab_allAliases (s
);
8264 sRefSet_realElements (aliases
, current
)
8266 if (sRef_isReasonable (current
))
8268 if (sRef_isReasonable (current
))
8270 if (!sRef_similar (current
, s
)
8271 || (error
&& sRef_sameName (current
, s
)))
8273 (void) (*predf
)(current
, e
, s
, err
);
8278 llcontbug (message ("Invalid sRef as alias field of %s", sRef_unparse (s
)));
8281 } end_sRefSet_realElements
;
8283 sRefSet_free (aliases
);
8288 ** return TRUE iff predf (s) is true for s or any alias of s
8292 sRef_aliasCheckSimplePred (sRefTest predf
, sRef s
)
8303 aliases
= usymtab_allAliases (s
);
8305 sRefSet_realElements (aliases
, current
)
8307 if (sRef_isReasonable (current
))
8309 sRef cref
= sRef_updateSref (current
);
8311 /* Whoa! a very kludgey way to make sure the right sref is used
8312 ** where there is a conditional symbol table. I am beginning
8313 ** to think that having a conditional symbol table wasn't such
8319 DPRINTF (("Checking alias: %s", sRef_unparseFull (cref
)));
8320 sRefSet_free (aliases
);
8324 } end_sRefSet_realElements
;
8326 sRefSet_free (aliases
);
8332 sRef_aliasCompleteSimplePred (bool (predf
) (sRef
), sRef s
)
8335 bool result
= FALSE
;
8337 aliases
= usymtab_allAliases (s
);
8339 if ((*predf
)(s
)) result
= TRUE
;
8341 sRefSet_realElements (aliases
, current
)
8343 if (sRef_isReasonable (current
))
8345 current
= sRef_updateSref (current
);
8346 if ((*predf
)(current
)) result
= TRUE
;
8348 } end_sRefSet_realElements
;
8350 sRefSet_free (aliases
);
8355 sRef_aliasSetComplete (void (predf
) (sRef
, fileloc
), sRef s
, fileloc loc
)
8359 aliases
= usymtab_allAliases (s
);
8361 DPRINTF (("All aliases: %s --> %s", sRef_unparseFull (s
), sRefSet_unparseFull (aliases
)));
8365 sRefSet_realElements (aliases
, current
)
8367 if (sRef_isReasonable (current
))
8369 DPRINTF (("Update: %s", sRef_unparseFull (current
)));
8370 current
= sRef_updateSref (current
);
8371 DPRINTF (("Updated ==> %s", sRef_unparseFull (current
)));
8372 ((*predf
)(current
, loc
));
8373 DPRINTF (("Killed: %s", sRef_unparseFull (current
)));
8375 } end_sRefSet_realElements
;
8377 sRefSet_free (aliases
);
8381 sRef_aliasSetCompleteParam (void (predf
) (sRef
, int, fileloc
), sRef s
,
8382 int kind
, fileloc loc
)
8386 if (sRef_isDeep (s
))
8388 aliases
= usymtab_allAliases (s
);
8392 aliases
= usymtab_aliasedBy (s
);
8395 (*predf
)(s
, kind
, loc
);
8397 sRefSet_realElements (aliases
, current
)
8399 if (sRef_isReasonable (current
))
8401 current
= sRef_updateSref (current
);
8402 ((*predf
)(current
, kind
, loc
));
8404 } end_sRefSet_realElements
;
8406 sRefSet_free (aliases
);
8410 ** Version of aliasSetCompleteParam for alkind parameters
8414 sRef_aliasSetCompleteAlkParam (void (predf
) (sRef
, alkind
, fileloc
), sRef s
,
8415 alkind kind
, fileloc loc
)
8419 if (sRef_isDeep (s
))
8421 aliases
= usymtab_allAliases (s
);
8425 aliases
= usymtab_aliasedBy (s
);
8428 (*predf
)(s
, kind
, loc
);
8430 sRefSet_realElements (aliases
, current
)
8432 if (sRef_isReasonable (current
))
8434 current
= sRef_updateSref (current
);
8435 ((*predf
)(current
, kind
, loc
));
8437 } end_sRefSet_realElements
;
8439 sRefSet_free (aliases
);
8443 sRef_innerAliasSetComplete (void (predf
) (sRef
, fileloc
), sRef s
, fileloc loc
)
8449 if (!sRef_isReasonable (s
)) return;
8452 ** Type equivalence checking is necessary --- there might be casting.
8459 case SK_UNCONSTRAINED
:
8464 inner
= s
->info
->ref
;
8465 aliases
= usymtab_allAliases (inner
);
8466 ct
= sRef_getType (inner
);
8468 sRefSet_realElements (aliases
, current
)
8470 if (sRef_isReasonable (current
))
8472 current
= sRef_updateSref (current
);
8474 if (ctype_equal (ct
, sRef_getType (current
)))
8476 sRef ptr
= sRef_makePointer (current
);
8477 ((*predf
)(ptr
, loc
));
8480 } end_sRefSet_realElements
;
8482 sRefSet_free (aliases
);
8485 inner
= s
->info
->arrayfetch
->arr
;
8486 aliases
= usymtab_allAliases (inner
);
8487 ct
= sRef_getType (inner
);
8489 DPRINTF (("Array fetch: %s", sRefSet_unparse (aliases
)));
8491 sRefSet_realElements (aliases
, current
)
8493 if (sRef_isReasonable (current
))
8495 current
= sRef_updateSref (current
);
8496 DPRINTF (("Current: %s", sRef_unparseFull (current
)));
8498 if (ctype_equal (ct
, sRef_getType (current
)))
8500 if (s
->info
->arrayfetch
->indknown
)
8502 sRef af
= sRef_makeArrayFetchKnown (current
, s
->info
->arrayfetch
->ind
);
8503 DPRINTF (("Defining: %s", sRef_unparseFull (af
)));
8504 /* evans 2001-08-27 This isn't true:
8505 llassert (af->info->arrayfetch->arr == current);
8506 see comments in buildArrayFetchKnown
8508 ((*predf
)(af
, loc
));
8512 sRef af
= sRef_makeArrayFetch (current
);
8513 /* evans 2001-08-27 This isn't true:
8514 llassert (af->info->arrayfetch->arr == current);
8515 see comments in buildArrayFetch
8517 DPRINTF (("Defining: %s", sRef_unparseFull (af
)));
8518 ((*predf
)(af
, loc
));
8523 DPRINTF (("Type mismatch: %s / %s",
8525 ctype_unparse (sRef_getType (current
))));
8528 } end_sRefSet_realElements
;
8530 sRefSet_free (aliases
);
8533 inner
= s
->info
->field
->rec
;
8534 aliases
= usymtab_allAliases (inner
);
8535 ct
= sRef_getType (inner
);
8537 sRefSet_realElements (aliases
, current
)
8539 if (sRef_isReasonable (current
))
8541 current
= sRef_updateSref (current
);
8543 if (ctype_equal (ct
, sRef_getType (current
)))
8545 sRef f
= sRef_makeField (current
, s
->info
->field
->field
);
8550 } end_sRefSet_realElements
;
8552 sRefSet_free (aliases
);
8555 sRef_innerAliasSetComplete (predf
, s
->info
->conj
->a
, loc
);
8556 sRef_innerAliasSetComplete (predf
, s
->info
->conj
->b
, loc
);
8573 sRef_innerAliasSetCompleteParam (void (predf
) (sRef
, sRef
), sRef s
, sRef t
)
8579 if (!sRef_isReasonable (s
)) return;
8582 ** Type equivalence checking is necessary --- there might be casting.
8589 case SK_UNCONSTRAINED
:
8594 inner
= s
->info
->ref
;
8595 aliases
= usymtab_allAliases (inner
);
8596 ct
= sRef_getType (inner
);
8598 sRefSet_realElements (aliases
, current
)
8600 if (sRef_isReasonable (current
))
8602 current
= sRef_updateSref (current
);
8604 if (ctype_equal (ct
, sRef_getType (current
)))
8606 sRef ptr
= sRef_makePointer (current
);
8611 } end_sRefSet_realElements
;
8613 sRefSet_free (aliases
);
8616 inner
= s
->info
->arrayfetch
->arr
;
8617 aliases
= usymtab_allAliases (inner
);
8618 ct
= sRef_getType (inner
);
8620 sRefSet_realElements (aliases
, current
)
8622 if (sRef_isReasonable (current
))
8624 current
= sRef_updateSref (current
);
8626 if (ctype_equal (ct
, sRef_getType (current
)))
8629 if (s
->info
->arrayfetch
->indknown
)
8631 sRef af
= sRef_makeArrayFetchKnown (current
, s
->info
->arrayfetch
->ind
);
8637 sRef af
= sRef_makeArrayFetch (current
);
8643 } end_sRefSet_realElements
;
8645 sRefSet_free (aliases
);
8648 inner
= s
->info
->field
->rec
;
8649 aliases
= usymtab_allAliases (inner
);
8650 ct
= sRef_getType (inner
);
8652 sRefSet_realElements (aliases
, current
)
8654 if (sRef_isReasonable (current
))
8656 current
= sRef_updateSref (current
);
8658 if (ctype_equal (ct
, sRef_getType (current
)))
8660 sRef f
= sRef_makeField (current
, s
->info
->field
->field
);
8665 } end_sRefSet_realElements
;
8667 sRefSet_free (aliases
);
8670 sRef_innerAliasSetCompleteParam (predf
, s
->info
->conj
->a
, t
);
8671 sRef_innerAliasSetCompleteParam (predf
, s
->info
->conj
->b
, t
);
8687 static void sRef_combineExKinds (/*@notnull@*/ sRef res
, /*@notnull@*/ sRef other
)
8689 exkind a1
= sRef_getExKind (res
);
8690 exkind a2
= sRef_getExKind (other
);
8692 if (a1
== a2
|| a2
== XO_UNKNOWN
)
8696 else if (a1
== XO_UNKNOWN
)
8698 res
->expinfo
= stateInfo_update (res
->expinfo
, other
->expinfo
);
8703 res
->expkind
= XO_OBSERVER
;
8708 ** Currently, this is a very ad hoc implementation, with lots of fixes to
8709 ** make real code work okay. I need to come up with some more general
8710 ** rules or principles here.
8714 sRef_combineAliasKindsError (/*@notnull@*/ sRef res
,
8715 /*@notnull@*/ sRef other
,
8716 clause cl
, fileloc loc
)
8718 bool hasError
= FALSE
;
8719 alkind ares
= sRef_getAliasKind (res
);
8720 alkind aother
= sRef_getAliasKind (other
);
8722 sRef_checkMutable (res
);
8724 if (alkind_isDependent (ares
))
8726 if (aother
== AK_KEPT
)
8728 res
->aliasinfo
= stateInfo_update (res
->aliasinfo
, other
->aliasinfo
);
8729 res
->aliaskind
= AK_KEPT
;
8733 if (aother
== AK_LOCAL
|| aother
== AK_STATIC
8734 || alkind_isTemp (aother
))
8736 DPRINTF (("Setting dependent: %s", sRef_unparseFull (res
)));
8737 res
->aliaskind
= AK_DEPENDENT
;
8741 else if (alkind_isDependent (aother
))
8743 if (ares
== AK_KEPT
)
8745 res
->aliaskind
= AK_KEPT
;
8749 if (ares
== AK_LOCAL
|| ares
== AK_STATIC
|| alkind_isTemp (ares
))
8751 DPRINTF (("Setting dependent: %s", sRef_unparseFull (res
)));
8752 res
->aliasinfo
= stateInfo_update (res
->aliasinfo
, other
->aliasinfo
);
8753 res
->aliaskind
= AK_DEPENDENT
;
8757 else if ((ares
== AK_LOCAL
|| ares
== AK_UNIQUE
8758 || ares
== AK_STATIC
|| alkind_isTemp (ares
))
8759 && sRef_isFresh (other
))
8762 ** cases like: if (s == NULL) s = malloc...;
8763 ** don't generate errors
8766 if (usymtab_isAltDefinitelyNullDeep (res
))
8768 res
->aliaskind
= ares
;
8775 else if ((aother
== AK_LOCAL
|| aother
== AK_UNIQUE
8776 || aother
== AK_STATIC
|| alkind_isTemp (aother
))
8777 && sRef_isFresh (res
))
8780 ** cases like: if (s == NULL) s = malloc...;
8781 ** don't generate errors
8784 if (usymtab_isDefinitelyNullDeep (other
))
8786 res
->aliasinfo
= stateInfo_update (res
->aliasinfo
, other
->aliasinfo
);
8787 res
->aliaskind
= aother
;
8794 else if (ares
== AK_NEWREF
&& aother
== AK_REFCOUNTED
8795 && sRef_isConst (other
))
8797 res
->aliaskind
= AK_NEWREF
;
8799 else if (aother
== AK_NEWREF
&& ares
== AK_REFCOUNTED
8800 && sRef_isConst (res
))
8802 res
->aliasinfo
= stateInfo_update (res
->aliasinfo
, other
->aliasinfo
);
8803 res
->aliaskind
= AK_NEWREF
;
8805 else if (sRef_isLocalVar (res
)
8806 && ((ares
== AK_KEPT
&& aother
== AK_LOCAL
)
8807 || (aother
== AK_KEPT
&& ares
== AK_LOCAL
)))
8809 res
->aliaskind
= AK_KEPT
;
8811 else if ((ares
== AK_OWNED
&& aother
== AK_ONLY
)
8812 || (aother
== AK_OWNED
&& ares
== AK_ONLY
))
8814 res
->aliaskind
= AK_OWNED
;
8816 if (aother
== AK_OWNED
)
8818 res
->aliasinfo
= stateInfo_update (res
->aliasinfo
, other
->aliasinfo
);
8828 if (sRef_isThroughArrayFetch (res
))
8831 (FLG_BRANCHSTATE
, FLG_STRICTBRANCHSTATE
,
8833 ("Clauses exit with %q possibly referencing %s storage %s, "
8836 alkind_unparse (aother
),
8837 clause_nameTaken (cl
),
8838 alkind_unparse (ares
),
8839 clause_nameAlternate (cl
)),
8842 sRef_showAliasInfo (res
);
8843 sRef_showAliasInfo (other
);
8844 res
->aliaskind
= AK_ERROR
;
8848 if (ares
== AK_KEPT
|| aother
== AK_KEPT
)
8850 sRef_maybeKill (res
, loc
);
8858 message ("Clauses exit with %q referencing %s storage %s, "
8861 alkind_unparse (aother
),
8862 clause_nameTaken (cl
),
8863 alkind_unparse (ares
),
8864 clause_nameAlternate (cl
)),
8867 sRef_showAliasInfo (res
);
8868 sRef_showAliasInfo (other
);
8870 res
->aliaskind
= AK_ERROR
;
8874 res
->aliaskind
= (sRef_isLocalVar (res
) ? AK_LOCAL
: AK_UNKNOWN
);
8879 sRef_combineAliasKinds (/*@notnull@*/ sRef res
, /*@notnull@*/ sRef other
,
8880 clause cl
, fileloc loc
)
8882 alkind ares
= sRef_getAliasKind (res
);
8883 alkind aother
= sRef_getAliasKind (other
);
8885 sRef_checkMutable (res
);
8887 DPRINTF (("Combine alias kinds: \n\t%s / \n\t%s",
8888 sRef_unparseFull (res
), sRef_unparseFull (other
)));
8889 if (alkind_equal (ares
, aother
)
8890 || aother
== AK_UNKNOWN
8891 || aother
== AK_ERROR
)
8893 ; /* keep current state */
8895 else if (sRef_isDead (res
) || sRef_isDead (other
))
8897 /* dead error reported (or storage is dead) */
8898 res
->aliaskind
= AK_ERROR
;
8900 else if (ares
== AK_UNKNOWN
|| ares
== AK_ERROR
8901 || sRef_isStateUndefined (res
)
8902 || sRef_isDefinitelyNull (res
))
8904 res
->aliasinfo
= stateInfo_update (res
->aliasinfo
, other
->aliasinfo
);
8905 res
->aliaskind
= aother
;
8907 else if (sRef_isStateUndefined (other
)
8908 || sRef_isDefinitelyNull (other
))
8912 else if (((ares
== AK_UNIQUE
|| alkind_isTemp (ares
))
8913 && aother
== AK_LOCAL
)
8914 || ((aother
== AK_UNIQUE
|| alkind_isTemp (aother
))
8915 && ares
== AK_LOCAL
))
8917 if (ares
!= AK_LOCAL
)
8919 res
->aliasinfo
= stateInfo_update (res
->aliasinfo
, other
->aliasinfo
);
8922 res
->aliaskind
= AK_LOCAL
;
8924 else if ((ares
== AK_OWNED
&& aother
== AK_FRESH
)
8925 || (aother
== AK_OWNED
&& ares
== AK_FRESH
))
8927 if (ares
!= AK_FRESH
)
8929 res
->aliasinfo
= stateInfo_update (res
->aliasinfo
, other
->aliasinfo
);
8932 res
->aliaskind
= AK_FRESH
;
8934 else if ((ares
== AK_KEEP
&& aother
== AK_FRESH
) ||
8935 (aother
== AK_KEEP
&& ares
== AK_FRESH
))
8937 if (ares
!= AK_KEEP
)
8939 res
->aliasinfo
= stateInfo_update (res
->aliasinfo
, other
->aliasinfo
);
8942 res
->aliaskind
= AK_KEEP
;
8944 else if ((ares
== AK_LOCAL
&& aother
== AK_STACK
) ||
8945 (aother
== AK_LOCAL
&& ares
== AK_STACK
))
8947 if (ares
!= AK_STACK
)
8949 res
->aliasinfo
= stateInfo_update (res
->aliasinfo
, other
->aliasinfo
);
8952 res
->aliaskind
= AK_STACK
;
8954 else if ((ares
== AK_LOCAL
8955 && (aother
== AK_OWNED
&& sRef_isLocalVar (other
)))
8956 || (aother
== AK_LOCAL
8957 && (ares
== AK_OWNED
&& sRef_isLocalVar (res
))))
8959 if (ares
!= AK_LOCAL
)
8961 res
->aliasinfo
= stateInfo_update (res
->aliasinfo
, other
->aliasinfo
);
8964 res
->aliaskind
= AK_LOCAL
;
8966 else if ((ares
== AK_FRESH
&& alkind_isOnly (aother
))
8967 || (aother
== AK_FRESH
&& alkind_isOnly (ares
)))
8969 res
->aliaskind
= AK_FRESH
;
8971 else if ((aother
== AK_FRESH
&& sRef_definitelyNull (res
))
8972 || (ares
== AK_FRESH
&& sRef_definitelyNull (other
)))
8974 if (ares
!= AK_FRESH
)
8976 res
->aliasinfo
= stateInfo_update (res
->aliasinfo
, other
->aliasinfo
);
8977 res
->aliaskind
= AK_FRESH
;
8980 else if ((sRef_isFresh (res
) && sRef_isConst (other
))
8981 || (sRef_isFresh (other
) && sRef_isConst (res
)))
8984 ** for NULL constantants
8988 if (!sRef_isFresh (res
))
8990 res
->aliasinfo
= stateInfo_update (res
->aliasinfo
, other
->aliasinfo
);
8993 res
->aliaskind
= AK_FRESH
;
8995 else if ((alkind_isStatic (aother
) && sRef_isConst (res
))
8996 || (alkind_isStatic (ares
) && sRef_isConst (other
)))
8998 if (!alkind_isStatic (ares
))
9000 res
->aliasinfo
= stateInfo_update (res
->aliasinfo
, other
->aliasinfo
);
9001 res
->aliaskind
= AK_STATIC
;
9006 sRef_combineAliasKindsError (res
, other
, cl
, loc
);
9010 static void sRef_combineDefState (/*@notnull@*/ sRef res
,
9011 /*@notnull@*/ sRef other
)
9013 sstate s1
= res
->defstate
;
9014 sstate s2
= other
->defstate
;
9017 sRef_checkMutable (res
);
9019 if (s1
== s2
|| s2
== SS_UNKNOWN
)
9023 else if (s1
== SS_UNKNOWN
)
9032 if (s2
== SS_DEFINED
)
9038 llcontbuglit ("ssfixed: not implemented");
9047 flip
= (s2
!= SS_DEFINED
);
9065 res
->definfo
= stateInfo_update (res
->definfo
, other
->definfo
);
9070 extern /*@notnull@*/ sRef
sRef_getConjA (sRef s
)
9073 llassert (sRef_isConj (s
));
9075 ret
= s
->info
->conj
->a
;
9076 llassert (ret
!= NULL
);
9080 extern /*@notnull@*/ sRef
sRef_getConjB (sRef s
)
9083 llassert (sRef_isConj (s
));
9085 ret
= s
->info
->conj
->b
;
9086 llassert (ret
!= NULL
);
9090 extern /*@exposed@*/ sRef
sRef_makeArrow (sRef s
, /*@dependent@*/ cstring f
)
9095 p
= sRef_makePointer (s
);
9096 ret
= sRef_makeField (p
, f
);
9097 DPRINTF (("Arrow: %s => %s",
9098 sRef_unparseFull (s
), sRef_unparseFull (ret
)));
9102 extern /*@exposed@*/ sRef
sRef_buildArrow (sRef s
, cstring f
)
9107 p
= sRef_buildPointer (s
);
9108 ret
= sRef_buildField (p
, f
);
9113 static /*@null@*/ sinfo
sinfo_copy (/*@notnull@*/ sRef s
)
9120 ret
= (sinfo
) dmalloc (sizeof (*ret
));
9121 ret
->cvar
= (cref
) dmalloc (sizeof (*ret
->cvar
));
9122 ret
->cvar
->lexlevel
= s
->info
->cvar
->lexlevel
;
9123 ret
->cvar
->index
= s
->info
->cvar
->index
;
9127 ret
= (sinfo
) dmalloc (sizeof (*ret
));
9128 ret
->paramno
= s
->info
->paramno
;
9129 llassert (ret
->paramno
>= -1);
9133 ret
= (sinfo
) dmalloc (sizeof (*ret
));
9134 ret
->arrayfetch
= (ainfo
) dmalloc (sizeof (*ret
->arrayfetch
));
9135 ret
->arrayfetch
->indknown
= s
->info
->arrayfetch
->indknown
;
9136 ret
->arrayfetch
->ind
= s
->info
->arrayfetch
->ind
;
9137 ret
->arrayfetch
->arr
= s
->info
->arrayfetch
->arr
;
9141 ret
= (sinfo
) dmalloc (sizeof (*ret
));
9142 ret
->field
= (fldinfo
) dmalloc (sizeof (*ret
->field
));
9143 ret
->field
->rec
= s
->info
->field
->rec
;
9144 ret
->field
->field
= s
->info
->field
->field
;
9148 ret
= (sinfo
) dmalloc (sizeof (*ret
));
9149 ret
->object
= s
->info
->object
;
9156 ret
= (sinfo
) dmalloc (sizeof (*ret
));
9157 ret
->ref
= s
->info
->ref
; /* Ref_copy (s->info->ref); */
9161 ret
= (sinfo
) dmalloc (sizeof (*ret
));
9162 ret
->conj
= (cjinfo
) dmalloc (sizeof (*ret
->conj
));
9163 ret
->conj
->a
= s
->info
->conj
->a
; /* sRef_copy (s->info->conj->a); */
9164 ret
->conj
->b
= s
->info
->conj
->b
; /* sRef_copy (s->info->conj->b);*/
9167 ret
= (sinfo
) dmalloc (sizeof (*ret
));
9168 ret
->spec
= s
->info
->spec
;
9171 case SK_UNCONSTRAINED
:
9173 ret
= (sinfo
) dmalloc (sizeof (*ret
));
9174 ret
->fname
= s
->info
->fname
;
9178 llassertprint (s
->info
== NULL
, ("s = %s", sRef_unparse (s
)));
9186 static /*@null@*/ sinfo
sinfo_fullCopy (/*@notnull@*/ sRef s
)
9191 ** Since its a full copy, only storage is assigned
9192 ** to dependent fields.
9199 ret
= (sinfo
) dmalloc (sizeof (*ret
));
9200 ret
->cvar
= (cref
) dmalloc (sizeof (*ret
->cvar
));
9201 ret
->cvar
->lexlevel
= s
->info
->cvar
->lexlevel
;
9202 ret
->cvar
->index
= s
->info
->cvar
->index
;
9206 ret
= (sinfo
) dmalloc (sizeof (*ret
));
9207 ret
->paramno
= s
->info
->paramno
;
9208 llassert (ret
->paramno
>= -1);
9212 ret
= (sinfo
) dmalloc (sizeof (*ret
));
9213 ret
->arrayfetch
= (ainfo
) dmalloc (sizeof (*ret
->arrayfetch
));
9214 ret
->arrayfetch
->indknown
= s
->info
->arrayfetch
->indknown
;
9215 ret
->arrayfetch
->ind
= s
->info
->arrayfetch
->ind
;
9216 ret
->arrayfetch
->arr
= sRef_saveCopy (s
->info
->arrayfetch
->arr
);
9220 ret
= (sinfo
) dmalloc (sizeof (*ret
));
9221 ret
->field
= (fldinfo
) dmalloc (sizeof (*ret
->field
));
9222 ret
->field
->rec
= sRef_saveCopy (s
->info
->field
->rec
);
9223 ret
->field
->field
= s
->info
->field
->field
;
9227 ret
= (sinfo
) dmalloc (sizeof (*ret
));
9228 ret
->object
= s
->info
->object
;
9235 ret
= (sinfo
) dmalloc (sizeof (*ret
));
9236 ret
->ref
= sRef_saveCopy (s
->info
->ref
);
9240 ret
= (sinfo
) dmalloc (sizeof (*ret
));
9241 ret
->conj
= (cjinfo
) dmalloc (sizeof (*ret
->conj
));
9242 ret
->conj
->a
= sRef_saveCopy (s
->info
->conj
->a
);
9243 ret
->conj
->b
= sRef_saveCopy (s
->info
->conj
->b
);
9246 ret
= (sinfo
) dmalloc (sizeof (*ret
));
9247 ret
->spec
= s
->info
->spec
;
9250 case SK_UNCONSTRAINED
:
9251 ret
= (sinfo
) dmalloc (sizeof (*ret
));
9252 ret
->fname
= s
->info
->fname
;
9255 llassert (s
->info
== NULL
);
9265 sinfo_update (/*@notnull@*/ /*@exposed@*/ sRef res
,
9266 /*@notnull@*/ /*@exposed@*/ sRef other
)
9268 llassert (res
->kind
== other
->kind
);
9273 res
->info
->cvar
->lexlevel
= other
->info
->cvar
->lexlevel
;
9274 res
->info
->cvar
->index
= other
->info
->cvar
->index
;
9278 res
->info
->paramno
= other
->info
->paramno
;
9279 llassert (res
->info
->paramno
>= -1);
9283 res
->info
->arrayfetch
->indknown
= other
->info
->arrayfetch
->indknown
;
9284 res
->info
->arrayfetch
->ind
= other
->info
->arrayfetch
->ind
;
9285 res
->info
->arrayfetch
->arr
= other
->info
->arrayfetch
->arr
;
9289 res
->info
->field
->rec
= other
->info
->field
->rec
;
9290 res
->info
->field
->field
= other
->info
->field
->field
;
9294 res
->info
->object
= other
->info
->object
;
9301 res
->info
->ref
= other
->info
->ref
;
9305 res
->info
->conj
->a
= other
->info
->conj
->a
;
9306 res
->info
->conj
->b
= other
->info
->conj
->b
;
9310 res
->info
->spec
= other
->info
->spec
;
9314 case SK_UNCONSTRAINED
:
9315 res
->info
->fname
= other
->info
->fname
;
9319 llassert (res
->info
== NULL
);
9324 static void sinfo_free (/*@special@*/ /*@temp@*/ /*@notnull@*/ sRef s
)
9325 /*@uses s->kind, s->info@*/
9326 /*@releases s->info@*/
9331 DPRINTF (("Free sinfo: [%p]", s
->info
->cvar
));
9332 sfree (s
->info
->cvar
);
9339 DPRINTF (("Free sinfo: [%p]", s
->info
->arrayfetch
));
9340 sfree (s
->info
->arrayfetch
);
9344 DPRINTF (("Free sinfo: [%p]", s
->info
->field
));
9345 sfree (s
->info
->field
);
9354 case SK_EXTERNAL
: /* is copy now! */
9358 DPRINTF (("Free sinfo: [%p]", s
->info
->conj
));
9359 sfree (s
->info
->conj
);
9366 if (s
->info
!= NULL
) {
9367 DPRINTF (("Free sinfo: [%p]", s
->info
));
9373 bool sRef_isNSLocalVar (sRef s
)
9375 if (sRef_isLocalVar (s
))
9377 uentry ue
= sRef_getUentry (s
);
9379 return (!uentry_isStatic (ue
));
9387 bool sRef_isLocalVar (sRef s
)
9389 if (sRef_isValid(s
))
9391 return (s
->kind
== SK_CVAR
9392 && (s
->info
->cvar
->lexlevel
> fileScope
));
9398 bool sRef_isRealLocalVar (sRef s
)
9400 if (sRef_isValid(s
))
9402 if (s
->kind
== SK_CVAR
)
9404 if (s
->info
->cvar
->lexlevel
== functionScope
)
9406 uentry ue
= sRef_getUentry (s
);
9408 if (uentry_isAnyParam (ue
)
9409 || uentry_isRefParam (ue
))
9420 return (s
->info
->cvar
->lexlevel
> functionScope
);
9428 bool sRef_isLocalParamVar (sRef s
)
9430 if (sRef_isValid(s
))
9432 return (s
->kind
== SK_PARAM
9433 || (s
->kind
== SK_CVAR
9434 && (s
->info
->cvar
->lexlevel
> fileScope
)));
9440 static speckind
speckind_fromInt (int i
)
9443 llassert (i
>= SR_NOTHING
&& i
<= SR_SYSTEM
);
9446 return ((speckind
) i
);
9450 static void sRef_updateNullState (/*@notnull@*/ sRef res
, /*@notnull@*/ sRef other
)
9453 res
->nullstate
= other
->nullstate
;
9454 DPRINTF (("update null state==> %s", sRef_unparseFull (res
)));
9455 res
->nullinfo
= stateInfo_update (res
->nullinfo
, other
->nullinfo
);
9456 sRef_resetAliasKind (res
);
9459 void sRef_combineNullState (/*@notnull@*/ sRef res
, /*@notnull@*/ sRef other
)
9461 nstate n1
= sRef_getNullState (res
);
9462 nstate n2
= sRef_getNullState (other
);
9466 if (n1
== n2
|| n2
== NS_UNKNOWN
)
9472 /* note: n2 is not unknown or defnull */
9476 case NS_ERROR
: nn
= NS_ERROR
; break;
9477 case NS_UNKNOWN
: flip
= TRUE
; nn
= n2
; break;
9478 case NS_POSNULL
: break;
9479 case NS_DEFNULL
: nn
= NS_POSNULL
; break;
9480 case NS_RELNULL
: break;
9482 if (n2
== NS_MNOTNULL
)
9493 if (n2
== NS_NOTNULL
)
9512 res
->nullinfo
= stateInfo_update (res
->nullinfo
, other
->nullinfo
);
9515 res
->nullstate
= nn
;
9516 DPRINTF (("update null state==> %s", sRef_unparseFull (res
)));
9517 sRef_resetAliasKind (res
);
9520 cstring
sRef_nullMessage (sRef s
)
9522 llassert (sRef_isReasonable (s
));
9524 switch (sRef_getNullState (s
))
9528 return (cstring_makeLiteralTemp ("null"));
9530 return (cstring_makeLiteralTemp ("possibly null"));
9535 /*@observer@*/ cstring
sRef_ntMessage (sRef s
)
9537 llassert (sRef_isReasonable (s
));
9539 switch (s
->nullstate
)
9543 return (cstring_makeLiteralTemp ("not nullterminated"));
9545 return (cstring_makeLiteralTemp ("possibly non-nullterminated"));
9548 # endif /* DEADCODE */
9551 sRef
sRef_fixResultType (/*@returned@*/ sRef s
, ctype typ
, uentry ue
)
9553 sRef tmp
= sRef_undefined
;
9556 llassert (sRef_isReasonable (s
));
9567 tmp
= sRef_fixResultType (s
->info
->arrayfetch
->arr
, typ
, ue
);
9569 ct
= ctype_realType (sRef_getType (tmp
));
9571 if (ctype_isKnown (ct
))
9573 if (ctype_isAP (ct
))
9582 ("Special clause indexes non-array (%t): *%q",
9583 ct
, sRef_unparse (s
->info
->arrayfetch
->arr
)),
9584 uentry_whereLast (ue
));
9588 tmp
= sRef_fixResultType (s
->info
->arrayfetch
->arr
, typ
, ue
);
9590 if (s
->info
->arrayfetch
->indknown
)
9592 ret
= sRef_makeArrayFetchKnown (tmp
, s
->info
->arrayfetch
->ind
);
9596 ret
= sRef_makeArrayFetch (tmp
);
9602 sRef rec
= sRef_fixResultType (s
->info
->field
->rec
, typ
, ue
);
9603 ctype ct
= ctype_realType (sRef_getType (rec
));
9605 if (ctype_isKnown (ct
))
9607 if (ctype_isSU (ct
))
9609 if (uentry_isValid (uentryList_lookupField (ctype_getFields (ct
),
9610 s
->info
->field
->field
)))
9619 ("Special clause accesses non-existent field of result: %q.%s",
9620 sRef_unparse (rec
), s
->info
->field
->field
),
9621 uentry_whereLast (ue
));
9629 ("Special clause accesses field of non-struct or union result (%t): %q.%s",
9630 ct
, sRef_unparse (rec
), s
->info
->field
->field
),
9631 uentry_whereLast (ue
));
9635 ret
= sRef_makeField (tmp
, s
->info
->field
->field
);
9641 tmp
= sRef_fixResultType (s
->info
->ref
, typ
, ue
);
9643 ct
= ctype_realType (sRef_getType (tmp
));
9645 if (ctype_isKnown (ct
))
9647 if (ctype_isAP (ct
))
9656 ("Special clause dereferences non-pointer (%t): *%q",
9657 ct
, sRef_unparse (s
->info
->ref
)),
9658 uentry_whereLast (ue
));
9662 ret
= sRef_makePointer (tmp
);
9669 ("Special clause uses & operator (not allowed): &%q", sRef_unparse (s
->info
->ref
)),
9670 uentry_whereLast (ue
));
9679 bool sRef_isOnly (sRef s
)
9681 return (sRef_isValid(s
) && alkind_isOnly (s
->aliaskind
));
9684 bool sRef_isDependent (sRef s
)
9686 return (sRef_isValid(s
) && alkind_isDependent (s
->aliaskind
));
9689 bool sRef_isOwned (sRef s
)
9691 return (sRef_isReasonable (s
) && (s
->aliaskind
== AK_OWNED
));
9694 bool sRef_isKeep (sRef s
)
9696 return (sRef_isReasonable (s
) && (s
->aliaskind
== AK_KEEP
));
9700 bool sRef_isTemp (sRef s
)
9702 return (sRef_isReasonable (s
) && alkind_isTemp (s
->aliaskind
));
9704 # endif /* DEADCODE */
9706 bool sRef_isLocalState (sRef s
)
9708 return (sRef_isReasonable (s
) && (s
->aliaskind
== AK_LOCAL
));
9711 bool sRef_isUnique (sRef s
)
9713 return (sRef_isReasonable (s
) && (s
->aliaskind
== AK_UNIQUE
));
9716 bool sRef_isShared (sRef s
)
9718 return (sRef_isReasonable (s
) && (s
->aliaskind
== AK_SHARED
));
9721 bool sRef_isExposed (sRef s
)
9723 return (sRef_isReasonable (s
) && (s
->expkind
== XO_EXPOSED
));
9726 bool sRef_isObserver (sRef s
)
9728 return (sRef_isReasonable (s
) && (s
->expkind
== XO_OBSERVER
));
9731 bool sRef_isFresh (sRef s
)
9733 return (sRef_isReasonable (s
) && (s
->aliaskind
== AK_FRESH
));
9736 bool sRef_isDefinitelyNull (sRef s
)
9738 return (sRef_isReasonable (s
) && (sRef_getNullState (s
) == NS_DEFNULL
9739 || sRef_getNullState (s
) == NS_CONSTNULL
));
9742 bool sRef_isAllocated (sRef s
)
9744 return (sRef_isReasonable (s
) && (s
->defstate
== SS_ALLOCATED
));
9747 bool sRef_isStack (sRef s
)
9749 return (sRef_isReasonable (s
) && (s
->aliaskind
== AK_STACK
));
9752 bool sRef_isNotNull (sRef s
)
9754 return (sRef_isValid(s
) && (sRef_getNullState (s
) == NS_MNOTNULL
9755 || sRef_getNullState (s
) == NS_NOTNULL
));
9758 alkind
sRef_getAliasKind (sRef s
)
9760 if (sRef_isValid(s
)) {
9761 llassert (alkind_isValid (s
->aliaskind
));
9762 return s
->aliaskind
;
9768 nstate
sRef_getNullState (sRef s
)
9770 if (sRef_isReasonable (s
)) {
9771 llassert (nstate_isValid (s
->nullstate
));
9772 return s
->nullstate
;
9778 void sRef_reflectAnnotation (sRef s
, annotationInfo a
, fileloc loc
)
9780 if (sRef_isReasonable (s
))
9782 if (!valueTable_isDefined (s
->state
))
9784 s
->state
= valueTable_create (1);
9787 cstring_copy (metaStateInfo_getName (annotationInfo_getState (a
))),
9788 stateValue_create (annotationInfo_getValue (a
),
9789 stateInfo_makeLoc (loc
, SA_DECLARED
)));
9793 DPRINTF (("reflect loc: %s", fileloc_unparse (loc
)));
9796 metaStateInfo_getName (annotationInfo_getState (a
)),
9797 stateValue_create (annotationInfo_getValue (a
),
9798 stateInfo_makeLoc (loc
, SA_DECLARED
)));
9800 DPRINTF (("sref: %s", sRef_unparse (s
)));
9801 DPRINTF (("sref: %s", sRef_unparseFull (s
)));
9806 void sRef_setMetaStateValueComplete (sRef s
, cstring key
, int value
, fileloc loc
)
9808 sRefSet aliases
= usymtab_allAliases (s
);
9810 sRef_setMetaStateValue (s
, key
, value
, loc
);
9812 sRefSet_realElements (aliases
, current
)
9814 if (sRef_isReasonable (current
))
9816 current
= sRef_updateSref (current
);
9817 sRef_setMetaStateValue (current
, key
, value
, loc
);
9819 } end_sRefSet_realElements
;
9821 sRefSet_free (aliases
);
9824 void sRef_setMetaStateValue (sRef s
, cstring key
, int value
, fileloc loc
)
9826 sRef_checkMutable (s
);
9828 if (sRef_isReasonable (s
))
9830 if (!valueTable_isDefined (s
->state
))
9832 DPRINTF (("inserting state: %s: %s %d", sRef_unparse (s
), key
, value
));
9833 s
->state
= valueTable_create (1);
9834 valueTable_insert (s
->state
, cstring_copy (key
),
9835 stateValue_create (value
,
9836 stateInfo_makeLoc (loc
, SA_CHANGED
)));
9840 DPRINTF (("Updating state: %s: %s %d / %s", sRef_unparse (s
), key
, value
,
9841 fileloc_unparse (loc
)));
9842 if (valueTable_contains (s
->state
, key
))
9845 (s
->state
, key
, stateValue_create (value
,
9846 stateInfo_makeLoc (loc
, SA_CHANGED
)));
9851 (s
->state
, cstring_copy (key
),
9852 stateValue_create (value
, stateInfo_makeLoc (loc
, SA_CHANGED
)));
9855 DPRINTF (("After: %s", sRef_unparseFull (s
)));
9860 bool sRef_checkMetaStateValue (sRef s
, cstring key
, int value
)
9862 if (sRef_isReasonable (s
))
9864 if (valueTable_isDefined (s
->state
))
9868 DPRINTF (("check state: %s: %s %d", sRef_unparse (s
), key
, value
));
9870 val
= valueTable_lookup (s
->state
, key
);
9871 llassert (stateValue_isDefined (val
));
9872 return (stateValue_isError (val
)
9873 || stateValue_getValue (val
) == value
);
9886 /*@observer@*/ stateValue
sRef_getMetaStateValue (sRef s
, cstring key
)
9888 if (sRef_isReasonable (s
))
9890 if (valueTable_isDefined (s
->state
))
9894 val
= valueTable_lookup (s
->state
, key
);
9895 /* Okay if its not defined, just returns stateValue_undefined */
9900 return stateValue_undefined
;
9905 return stateValue_undefined
;
9909 /*@observer@*/ valueTable
sRef_getValueTable (sRef s
)
9911 DPRINTF (("Get value table: %s", sRef_unparse (s
)));
9913 if (sRef_isReasonable (s
))
9915 llassert (sRef_isReasonable (s
));
9916 DPRINTF (("Value table: %s", valueTable_unparse (s
->state
)));
9921 DPRINTF (("No value table!"));
9922 return valueTable_undefined
;
9926 bool sRef_makeStateSpecial (sRef s
)
9929 ** Default defined state can be made special.
9932 llassert (sRef_isReasonable (s
));
9934 if (s
->defstate
== SS_UNKNOWN
|| s
->defstate
== SS_DEFINED
|| s
->defstate
== SS_SPECIAL
)
9936 /* s->aliaskind = AK_IMPTEMP; */ /* evans 2001-07-23 shouldn't effect alias state */
9937 s
->defstate
= SS_SPECIAL
;
9938 DPRINTF (("Made special: %s", sRef_unparseFull (s
)));
9943 /* s->aliaskind = AK_IMPTEMP; */
9944 s
->defstate
= SS_SPECIAL
;
9949 void sRef_markImmutable (sRef s
)
9951 if (sRef_isReasonable (s
))
9953 DPRINTF (("Mark immutable: %s", sRef_unparseFull (s
)));
9958 bool sRef_definitelyNullContext (sRef s
)
9960 return (sRef_definitelyNull (s
)
9961 || usymtab_isDefinitelyNullDeep (s
));
9964 bool sRef_definitelyNullAltContext (sRef s
)
9966 return (sRef_definitelyNull (s
)
9967 || usymtab_isAltDefinitelyNullDeep (s
));
9972 /* start modifications */
9973 struct s_bbufinfo
sRef_getNullTerminatedState (sRef p_s
) {
9974 struct s_bbufinfo BUFSTATE_UNKNOWN
;
9975 BUFSTATE_UNKNOWN
.bufstate
= BB_NOTNULLTERMINATED
;
9976 BUFSTATE_UNKNOWN
.size
= 0;
9977 BUFSTATE_UNKNOWN
.len
= 0;
9979 if (sRef_isValid(p_s
))
9980 return p_s
->bufinfo
;
9981 return BUFSTATE_UNKNOWN
;
9983 # endif /* DEADCODE */
9985 void sRef_setNullTerminatedState(sRef p_s
) {
9986 if(sRef_isReasonable (p_s
)) {
9987 p_s
->bufinfo
.bufstate
= BB_NULLTERMINATED
;
9989 llfatalbug( message("sRef_setNT passed a invalid sRef\n"));
9994 void sRef_setPossiblyNullTerminatedState(sRef p_s
) {
9995 if( sRef_isReasonable (p_s
)) {
9996 p_s
->bufinfo
.bufstate
= BB_POSSIBLYNULLTERMINATED
;
9998 llfatalbug( message("sRef_setPossNT passed a invalid sRef\n"));
10002 void sRef_setNotNullTerminatedState(sRef p_s
) {
10003 if( sRef_isReasonable (p_s
)) {
10004 p_s
->bufinfo
.bufstate
= BB_NOTNULLTERMINATED
;
10006 llfatalbug( message("sRef_unsetNT passed a invalid sRef\n"));
10010 void sRef_setLen(sRef p_s
, int len
) {
10011 if (sRef_isReasonable (p_s
) && sRef_isNullTerminated(p_s
))
10013 p_s
->bufinfo
.len
= len
;
10017 llfatalbug( message("sRef_setLen passed an invalid sRef\n"));
10022 void sRef_setSize(sRef p_s
, int size
) {
10023 if( sRef_isValid(p_s
))
10025 p_s
->bufinfo
.size
= size
;
10029 llfatalbug( message("sRef_setSize passed a invalid sRef\n"));
10033 void sRef_resetLen(sRef p_s
) {
10034 if (sRef_isReasonable (p_s
))
10036 p_s
->bufinfo
.len
= 0;
10040 llfatalbug (message ("sRef_setLen passed an invalid sRef\n"));
10044 /*drl7x 11/28/2000 */
10046 bool sRef_isFixedArray (sRef p_s
) /*@*/ {
10048 c
= sRef_getType (p_s
);
10049 return ( ctype_isFixedArray (c
) );
10052 size_t sRef_getArraySize (sRef p_s
) /*@*/
10055 llassert (sRef_isFixedArray(p_s
) );
10056 DPRINTF (( message ("sRef_getArraySize getting array size for %s", sRef_unparse(p_s
) ) ));
10058 c
= sRef_getType (p_s
);
10059 return (ctype_getArraySize (c
));
10062 void sRef_setValue (sRef s
, multiVal val
)
10064 if (!sRef_isReasonable (s
))
10066 llcontbuglit ("Unreasonable sRef");
10067 llcontbug (message ("sRef: %s", sRef_unparse (s
)));
10071 multiVal_free (s
->val
);
10075 bool sRef_hasValue (sRef s
)
10077 return (sRef_isReasonable (s
)
10078 && multiVal_isDefined (s
->val
));
10081 multiVal
sRef_getValue (sRef s
)
10083 if (sRef_isReasonable (s
))
10088 return multiVal_undefined
;