Don't try calling lsl when file is missing.
[splint-patched.git] / src / sRef.c
blob04a801a54ce1e0c20faa8186f6142aa1cd16abcf
1 /*
2 ** Splint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2003 University of Virginia,
4 ** Massachusetts Institute of Technology
5 **
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.
10 **
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.
15 **
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
25 ** storeRef.c
27 ** Memory management:
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
31 ** function.
33 ** storeRefs in the file and global scopes are free'd by the uentry.
37 # include "splintMacros.nf"
38 # include "basic.h"
39 # include "sRefTable.h"
40 # include "structNames.h"
43 ** Predicate functions that evaluate both arguments in order.
46 /*@notfunction@*/
47 # define OR(a,b) (a ? (b, TRUE) : b)
49 /*@notfunction@*/
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) /*@*/ ;
65 static void
66 sRef_innerAliasSetComplete (void (p_predf) (sRef, fileloc), sRef p_s,
67 fileloc p_loc)
68 /*@modifies p_s@*/ ;
70 static void
71 sRef_innerAliasSetCompleteParam (void (p_predf) (sRef, sRef), sRef p_s, sRef p_t)
72 /*@modifies p_s@*/ ;
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; */
92 # ifdef DEBUGSPLINT
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)
102 llassert (el != s);
103 sRef_checkCompletelyReasonable (el);
104 } end_sRefSet_elements ;
107 # endif
109 static /*@falsewhennull@*/ bool sRef_isReasonable (sRef s) /*@*/
111 if (sRef_isValid (s))
113 # ifdef DEBUGSPLINT
114 if (!bool_isReasonable (s->safe)
115 || !bool_isReasonable (s->modified)
116 || !bool_isReasonable (s->immut))
118 llcontbug (message ("Unreasonable sRef [%p]", s));
119 return FALSE;
122 if (!sstate_isValid (s->defstate))
124 llcontbug (message ("Unreasonable sRef [%p]", s));
125 return FALSE;
128 if (!nstate_isValid (s->nullstate))
130 llcontbug (message ("Unreasonable sRef [%p]", s));
131 return FALSE;
134 if (!alkind_isValid (s->aliaskind)
135 || !alkind_isValid (s->oaliaskind))
137 llcontbug (message ("Unreasonable sRef [%p]", s));
138 return FALSE;
141 if (!exkind_isValid (s->expkind)
142 || !exkind_isValid (s->oexpkind))
144 llcontbug (message ("Unreasonable sRef [%p]", s));
145 return FALSE;
147 # endif
149 return TRUE;
152 return FALSE;
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)
171 switch (sk)
173 case SK_PARAM: case SK_CVAR: case SK_CONST:
174 case SK_OBJECT: case SK_UNKNOWN: case SK_NEW:
175 return TRUE;
176 default:
177 return FALSE;
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)
187 /*@modifies p_s@*/ ;
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) /*@*/ ;
192 static void
193 sRef_combineExKinds (/*@notnull@*/ sRef p_res, /*@notnull@*/ sRef p_other)
194 /*@modifies p_res@*/ ;
196 static void
197 sRef_combineAliasKinds (/*@notnull@*/ sRef p_res, /*@notnull@*/ sRef p_other,
198 clause p_cl, fileloc p_loc)
199 /*@modifies p_res@*/ ;
201 static void
202 sRef_combineNullState (/*@notnull@*/ sRef p_res, /*@notnull@*/ sRef p_other)
203 /*@modifies p_res@*/ ;
205 static void
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)
210 /*@modifies p_s@*/ ;
212 static void
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)
216 /*@modifies p_s@*/ ;
217 static void sRef_setDefinedNoClear (sRef p_s, fileloc p_loc)
218 /*@modifies p_s@*/ ;
219 static void sRef_setStateAux (sRef p_s, sstate p_ss, fileloc p_loc)
220 /*@modifies p_s@*/;
222 static /*@exposed@*/ sRef
223 sRef_buildNCField (/*@exposed@*/ sRef p_rec, /*@exposed@*/ cstring p_f);
225 static void
226 sRef_mergeStateAux (/*@notnull@*/ sRef p_res, /*@notnull@*/ sRef p_other,
227 clause p_cl, bool p_opt, fileloc p_loc,
228 bool p_doDerivs)
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 */
263 # ifdef DEBUGREFS
264 static nsrefs = 0;
265 static totnsrefs = 0;
266 static maxnsrefs = 0;
267 static ntotrefers = 0;
268 static nrefers = 0;
269 # endif
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
279 sRef_alloc (void)
281 sRef s = (sRef) dmalloc (sizeof (*s));
283 s->immut = FALSE;
285 DPRINTF (("Alloc sref: [%p]", s));
287 if (inFunction)
289 allRefs = sRefTable_add (allRefs, s);
290 /*@-branchstate@*/
292 else
294 DPRINTF (("Not in function!"));
297 /*@=branchstate@*/
299 # ifdef DEBUGREFS
300 if (nsrefs >= maxnsrefs)
302 maxnsrefs = nsrefs;
305 totnsrefs++;
306 nsrefs++;
307 # endif
309 /*@-mustfree@*/ /*@-freshtrans@*/
310 return s;
311 /*@=mustfree@*/ /*@=freshtrans@*/
314 #ifdef DEADCODE
315 static void sRef_checkValidAux (sRef s, sRefSet checkedsofar)
317 llassert (FALSE);
319 if (!sRef_isReasonable (s)) return;
321 if (sRefSet_containsSameObject (checkedsofar, s))
323 return;
326 /*@-temptrans@*/
327 checkedsofar = sRefSet_insert (checkedsofar, s);
328 /*@=temptrans@*/ /* checksofar will be destroyed before checkValid returns */
330 switch (s->kind)
332 case SK_UNCONSTRAINED:
333 llassert (cstring_length (s->info->fname) < 100);
334 break;
336 case SK_CVAR:
337 llassert (s->info->cvar->lexlevel >= 0);
338 #if 0
339 llassert (s->info->cvar->lexlevel <= usymtab_getCurrentDepth ());
340 #endif
341 break;
343 case SK_PARAM:
344 llassert (s->info->paramno >= -1);
345 llassert (s->info->paramno <= 999); /* sanity check */
346 break;
348 case SK_ARRAYFETCH:
349 sRef_checkValidAux (s->info->arrayfetch->arr, checkedsofar);
350 break;
352 case SK_FIELD:
353 sRef_checkValidAux (s->info->field->rec, checkedsofar);
354 llassert (cstring_length (s->info->field->field) < 100);
355 break;
357 case SK_PTR:
358 sRef_checkValidAux (s->info->ref, checkedsofar);
359 break;
361 case SK_ADR:
362 sRef_checkValidAux (s->info->ref, checkedsofar);
363 break;
365 case SK_OBJECT:
366 /* check ctype s->info->object */
367 break;
369 case SK_CONJ:
370 sRef_checkValidAux (s->info->conj->a, checkedsofar);
371 sRef_checkValidAux (s->info->conj->b, checkedsofar);
372 break;
374 case SK_NEW:
375 llassert (cstring_length (s->info->fname) < 100);
376 break;
378 case SK_DERIVED:
379 sRef_checkValidAux (s->info->ref, checkedsofar);
380 break;
382 case SK_EXTERNAL:
383 sRef_checkValidAux (s->info->ref, checkedsofar);
384 break;
386 case SK_TYPE:
387 case SK_CONST:
388 case SK_RESULT:
389 /* check ctyp s->type */
390 break;
392 case SK_SPECIAL:
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);
397 break;
399 case SK_UNKNOWN:
400 break;
402 BADDEFAULT;
406 sRefSet_elements (s->deriv, el)
408 sRef_checkValidAux (el, checkedsofar);
409 } end_sRefSet_elements ;
411 #endif
413 # if 0
414 static /*@maynotreturn@*/ void sRef_checkValid (/*@temp@*/ sRef s) /*@modifies stderr@*/
416 sRefSet checkedsofar = sRefSet_new ();
417 sRef_checkValidAux (s, checkedsofar);
419 # endif
421 static /*@dependent@*/ /*@notnull@*/ /*@special@*/ sRef
422 sRef_new (void)
423 /*@defines result@*/
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;
430 s->safe = TRUE;
431 s->modified = FALSE;
432 s->immut = FALSE;
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;
441 s->bufinfo.len = -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;
457 s->info = NULL;
458 s->deriv = sRefSet_undefined;
460 s->state = valueTable_undefined;
462 return s;
465 static /*@dependent@*/ /*@notnull@*/ /*@special@*/ sRef
466 sRef_newRef (void)
467 /*@defines result@*/
468 /*@ensures isnull result->aliasinfo, result->definfo,
469 result->expinfo, result->info, result->deriv@*/
471 sRef res = sRef_new ();
472 res->immut = FALSE;
473 res->state = valueTable_undefined;
474 return res;
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.
495 bool
496 sRef_isRecursiveField (sRef s)
498 if (sRef_isField (s))
500 if (sRef_depth (s) > 13)
502 sRef base;
503 cstring fieldname;
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)))
514 return TRUE;
518 base = sRef_getBaseSafe (base);
523 return FALSE;
526 static void
527 sRef_addDeriv (/*@notnull@*/ sRef s, /*@notnull@*/ /*@exposed@*/ sRef t)
529 if (!context_inProtectVars ()
530 && !protectDerivs
531 && sRef_isReasonable (s)
532 && sRef_isReasonable (t)
533 && !sRef_isConst (s))
535 int sd = sRef_depth (s);
536 int td = sRef_depth (t);
538 if (sd >= td)
540 return;
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
567 llcontbug
568 (message ("sRef_addDeriv: global variable not in used "
569 "globs: %q / %s / %q",
570 sRef_unparse (s),
571 ctype_unparse (sRef_getType (s)),
572 sRefSet_unparse (s->deriv)));
575 else
577 DPRINTF (("Add deriv: [%p] %s / [%p] %s",
578 s, sRef_unparse (s),
579 t, sRef_unparse (t)));
581 s->deriv = sRefSet_insert (s->deriv, t);
585 else
587 DPRINTF (("Add deriv: [%p] %s / [%p] %s",
588 s, sRef_unparse (s),
589 t, sRef_unparse (t)));
591 s->deriv = sRefSet_insert (s->deriv, t);
596 bool
597 sRef_deepPred (bool (predf) (sRef), sRef s)
599 if (sRef_isReasonable (s))
601 if ((*predf)(s)) return TRUE;
603 switch (s->kind)
605 case SK_PTR:
606 return (sRef_deepPred (predf, s->info->ref));
607 case SK_ARRAYFETCH:
608 return (sRef_deepPred (predf, s->info->arrayfetch->arr));
609 case SK_FIELD:
610 return (sRef_deepPred (predf, s->info->field->rec));
611 case SK_CONJ:
612 return (sRef_deepPred (predf, s->info->conj->a)
613 || sRef_deepPred (predf, s->info->conj->b));
614 default:
615 return FALSE;
619 return FALSE;
622 bool sRef_modInFunction (void)
624 return inFunction;
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)));
643 else
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)));
670 # ifdef DEADCODE
671 /*@falsewhennull@*/ bool sRef_hasExpInfoLoc (sRef s)
673 return (sRef_isReasonable (s)
674 && (s->expinfo != NULL) && (fileloc_isDefined (s->expinfo->loc)));
676 # endif /* DEADCODE */
678 # if 0
679 static /*@observer@*/ /*@unused@*/ stateInfo sRef_getInfo (sRef s, cstring key)
681 stateValue sv;
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;
696 # endif
698 static bool
699 sRef_hasNullInfoLoc (sRef s)
701 return (sRef_isReasonable (s) && s->nullinfo != NULL
702 && (fileloc_isDefined (s->nullinfo->loc)));
705 bool
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);
728 #ifdef DEADCODE
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);
736 #endif
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);
746 /*@observer@*/ sRef
747 sRef_getAliasInfoRef (/*@temp@*/ sRef s)
749 llassert (sRef_isReasonable (s) && s->aliasinfo != NULL);
750 return (s->aliasinfo->ref);
753 bool sRef_inGlobalScope (void)
755 return !inFunction;
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"));
768 inFunction = FALSE;
771 void sRef_clearGlobalScope (void)
773 llassert (!inFunction);
774 DPRINTF (("enter function"));
775 inFunction = TRUE;
778 static bool oldInFunction = FALSE;
779 static int nestedScope = 0;
781 void sRef_setGlobalScopeSafe (void)
783 if (nestedScope == 0)
785 oldInFunction = inFunction;
788 nestedScope++;
789 DPRINTF (("leave function safe"));
790 inFunction = FALSE;
793 void sRef_clearGlobalScopeSafe (void)
795 nestedScope--;
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 ())
811 if (inFunction) {
812 sRef_exitFunctionScope ();
816 llassert (!inFunction);
817 llassert (sRefTable_isEmpty (allRefs));
818 inFunction = TRUE;
819 DPRINTF (("enter function"));
822 void sRef_exitFunctionScope (void)
824 if (inFunction)
826 DPRINTF (("Exit function scope."));
827 sRefTable_clear (allRefs);
828 DPRINTF (("Exit function scope done."));
829 inFunction = FALSE;
831 else
833 llbuglit ("sRef_exitFunctionScope: not in function");
837 void sRef_destroyMod (void) /*@globals killed allRefs;@*/
839 # ifdef DEBUGREFS
840 llmsg (message ("Live: %d / %d ", nsrefs, totnsrefs));
841 # endif
843 sRefTable_free (allRefs);
847 static /*@notnull@*/ /*@exposed@*/ sRef
848 sRef_fixConj (/*@notnull@*/ sRef s)
850 if (sRef_isConj (s))
852 do {
853 s = sRef_getConjA (s);
854 } while (sRef_isConj (s));
856 llassert (sRef_isReasonable (s));
857 return s; /* don't need to ref */
859 else
861 return s;
865 static bool
866 sRef_isExternallyVisibleAux (sRef s)
868 bool res = FALSE;
869 sRef base = sRef_getRootBase (s);
871 if (sRef_isReasonable (base))
873 res = sRef_isParam (base) || sRef_isFileOrGlobalScope (base) || sRef_isExternal (base);
876 return res;
879 bool
880 sRef_isExternallyVisible (sRef s)
882 return (sRef_aliasCheckSimplePred (sRef_isExternallyVisibleAux, s));
885 /*@exposed@*/ uentry
886 sRef_getBaseUentry (sRef s)
888 sRef base = sRef_getRootBase (s);
889 uentry res = uentry_undefined;
891 if (sRef_isReasonable (base))
893 switch (base->kind)
895 case SK_PARAM:
896 res = usymtab_getRefQuiet (paramsScope, usymId_fromInt (base->info->paramno));
897 break;
899 case SK_CVAR:
900 res = usymtab_getRefQuiet (base->info->cvar->lexlevel,
901 base->info->cvar->index);
902 break;
904 default:
905 break;
909 return res;
913 ** lookup the current uentry corresponding to s, and return the corresponding sRef.
914 ** yuk yuk yuk yuk yuk yuk yuk yuk
917 /*@exposed@*/ sRef
918 sRef_updateSref (sRef s)
920 sRef inner;
921 sRef ret;
922 sRef res;
924 if (!sRef_isReasonable (s)) return sRef_undefined;
926 switch (s->kind)
928 case SK_UNKNOWN:
929 case SK_OBJECT:
930 case SK_NEW:
931 case SK_TYPE:
932 case SK_DERIVED:
933 case SK_UNCONSTRAINED:
934 case SK_CONST:
935 case SK_SPECIAL:
936 case SK_RESULT:
937 return s;
938 case SK_EXTERNAL:
940 sRef r = sRef_updateSref (s->info->ref);
942 if (r != s->info->ref)
944 return sRef_makeExternal (r);
946 else
948 return s;
951 case SK_PARAM:
952 case SK_CVAR:
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))
963 return s;
965 else
967 DPRINTF (("Update sref: %s", uentry_unparseFull (ue)));
968 return (uentry_getSref (ue));
971 case SK_ARRAYFETCH:
972 /* special case if ind known */
973 inner = s->info->arrayfetch->arr;
974 ret = sRef_updateSref (inner);
976 if (ret == inner)
978 res = s;
980 else
982 res = sRef_makeArrayFetch (ret);
985 return res;
987 case SK_FIELD:
988 inner = s->info->field->rec;
989 ret = sRef_updateSref (inner);
991 if (ret == inner)
993 res = s;
995 else
997 res = (sRef_makeField (ret, s->info->field->field));
1000 return (res);
1001 case SK_PTR:
1002 inner = s->info->ref;
1003 ret = sRef_updateSref (inner);
1004 if (ret == inner)
1006 res = s;
1008 else
1010 res = sRef_makePointer (ret);
1013 return (res);
1015 case SK_ADR:
1016 inner = s->info->ref;
1017 ret = sRef_updateSref (inner);
1019 if (ret == inner)
1021 res = s;
1023 else
1025 res = sRef_makeAddress (ret);
1028 return (res);
1030 case SK_CONJ:
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)
1039 res = s;
1041 else
1043 res = sRef_makeConj (reta, retb);
1046 return (res);
1050 BADEXIT;
1053 uentry
1054 sRef_getUentry (sRef s)
1056 llassert (sRef_isReasonable (s));
1058 switch (s->kind)
1060 case SK_PARAM:
1061 return (usymtab_getRefQuiet (paramsScope, usymId_fromInt (s->info->paramno)));
1062 case SK_CVAR:
1063 return (usymtab_getRefQuiet (s->info->cvar->lexlevel, s->info->cvar->index));
1064 case SK_CONJ:
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);
1071 else
1073 return sRef_getUentry (s->info->conj->b);
1076 case SK_FIELD: /* evans 2002-07-17: added case for SK_FIELD */
1077 case SK_UNKNOWN:
1078 case SK_SPECIAL:
1079 return uentry_undefined;
1080 BADDEFAULT;
1085 sRef_getParam (sRef s)
1087 llassert (sRef_isReasonable (s));
1088 llassert (s->kind == SK_PARAM);
1090 return s->info->paramno;
1093 bool
1094 sRef_isModified (sRef s)
1096 return (!sRef_isReasonable (s) || s->modified);
1099 void sRef_setModified (sRef s)
1101 if (sRef_isReasonable (s))
1103 s->modified = TRUE;
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.
1129 bool
1130 sRef_canModifyVal (sRef s, sRefSet sl)
1132 if (context_getFlag (FLG_MUSTMOD))
1134 return (sRef_doModifyVal (s, sl));
1136 else
1138 return (sRef_checkModifyVal (s, sl));
1142 bool
1143 sRef_canModify (sRef s, sRefSet sl)
1145 if (context_getFlag (FLG_MUSTMOD))
1147 return (sRef_doModify (s, sl));
1149 else
1151 return (sRef_checkModify (s, sl));
1156 ** No side-effects
1159 static
1160 bool sRef_checkModifyVal (sRef s, sRefSet sl)
1162 DPRINTF (("Check modify val: %s", sRef_unparse (s)));
1164 if (sRef_isInvalid (s))
1166 return TRUE;
1169 switch (s->kind)
1171 case SK_UNCONSTRAINED:
1172 case SK_CONST:
1173 return TRUE;
1174 case SK_CVAR:
1175 DPRINTF (("Modify var: %s", sRef_unparse (s)));
1177 if (sRef_isFileOrGlobalScope (s))
1179 if (context_checkGlobMod (s))
1181 return (sRefSet_member (sl, s));
1184 return TRUE;
1186 else
1188 return TRUE;
1190 case SK_PARAM:
1191 return (sRefSet_member (sl, s)
1192 || alkind_isOnly (sRef_getOrigAliasKind (s)));
1193 case SK_ARRAYFETCH:
1194 /* special case if ind known */
1195 return (sRefSet_member (sl, s) ||
1196 sRef_checkModifyVal (s->info->arrayfetch->arr, sl));
1197 case SK_FIELD:
1198 return (sRefSet_member (sl, s) || sRef_checkModifyVal (s->info->field->rec, sl));
1199 case SK_PTR:
1200 return (sRefSet_member (sl, s) || sRef_checkModifyVal (s->info->ref, sl));
1201 case SK_ADR:
1202 return (sRefSet_member (sl, s) || sRef_checkModifyVal (s->info->ref, sl));
1203 case SK_CONJ:
1204 return ((sRef_checkModifyVal (s->info->conj->a, sl)) &&
1205 (sRef_checkModifyVal (s->info->conj->b, sl)));
1206 case SK_UNKNOWN:
1207 case SK_OBJECT:
1208 case SK_NEW:
1209 case SK_TYPE:
1210 case SK_DERIVED:
1211 return TRUE;
1212 case SK_EXTERNAL:
1213 return TRUE;
1214 case SK_SPECIAL:
1216 switch (s->info->spec)
1218 case SR_NOTHING: return TRUE;
1219 case SR_INTERNAL:
1220 if (context_getFlag (FLG_INTERNALGLOBS))
1222 return (sRefSet_member (sl, s));
1224 else
1226 return TRUE;
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;
1235 BADEXIT;
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));
1248 switch (s->kind)
1250 case SK_UNCONSTRAINED:
1251 case SK_CONST:
1252 return TRUE;
1253 case SK_CVAR:
1254 if (sRef_isFileOrGlobalScope (s))
1256 if (context_checkGlobMod (s))
1258 return (sRefSet_member (sl, s));
1261 return TRUE;
1263 else
1265 return TRUE;
1267 case SK_PARAM:
1268 return TRUE;
1269 case SK_ARRAYFETCH:
1270 return (sRefSet_member (sl, s) ||
1271 sRef_checkModifyVal (s->info->arrayfetch->arr, sl));
1272 case SK_FIELD:
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));
1281 case SK_PTR:
1283 bool sm;
1285 sm = sRefSet_member (sl, s);
1287 if (sm)
1288 return TRUE;
1289 else
1290 return (sRef_checkModifyVal (s->info->ref, sl));
1292 case SK_ADR:
1293 return (sRefSet_member (sl, s) || sRef_checkModifyVal (s->info->ref, sl));
1294 case SK_CONJ:
1295 return ((sRef_checkModify (s->info->conj->a, sl)) &&
1296 (sRef_checkModify (s->info->conj->b, sl)));
1297 case SK_NEW:
1298 case SK_OBJECT:
1299 case SK_UNKNOWN:
1300 case SK_TYPE:
1301 case SK_DERIVED:
1302 case SK_EXTERNAL:
1303 return TRUE;
1304 case SK_SPECIAL:
1306 switch (s->info->spec)
1308 case SR_NOTHING: return TRUE;
1309 case SR_INTERNAL:
1310 if (context_getFlag (FLG_INTERNALGLOBS))
1312 return (sRefSet_member (sl, s));
1314 else
1316 return TRUE;
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;
1325 BADEXIT;
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");
1342 else
1344 BADEXIT;
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");
1362 else
1364 BADEXIT;
1368 static
1369 bool sRef_doModifyVal (sRef s, sRefSet sl)
1371 llassert (sRef_isReasonable (s));
1373 switch (s->kind)
1375 case SK_UNCONSTRAINED:
1376 case SK_CONST:
1377 return TRUE;
1378 case SK_CVAR:
1379 if (sRef_isFileOrGlobalScope (s))
1382 if (context_checkGlobMod (s))
1384 return (sRefSet_modifyMember (sl, s));
1386 else
1388 (void) sRefSet_modifyMember (sl, s);
1391 return TRUE;
1393 else
1395 return TRUE;
1397 case SK_PARAM:
1398 return (sRefSet_modifyMember (sl, s)
1399 || alkind_isOnly (sRef_getOrigAliasKind (s)));
1400 case SK_ARRAYFETCH:
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)));
1405 case SK_FIELD:
1406 return (OR (sRefSet_modifyMember (sl, s),
1407 sRef_doModifyVal (s->info->field->rec, sl)));
1408 case SK_PTR:
1409 return (OR (sRefSet_modifyMember (sl, s),
1410 sRef_doModifyVal (s->info->ref, sl)));
1411 case SK_ADR:
1412 return (OR (sRefSet_modifyMember (sl, s),
1413 sRef_doModifyVal (s->info->ref, sl)));
1414 case SK_CONJ:
1415 return (AND (sRef_doModifyVal (s->info->conj->a, sl) ,
1416 sRef_doModifyVal (s->info->conj->b, sl)));
1417 case SK_OBJECT:
1418 case SK_DERIVED:
1419 case SK_EXTERNAL:
1420 case SK_UNKNOWN:
1421 case SK_NEW:
1422 case SK_TYPE:
1423 return TRUE;
1424 case SK_SPECIAL:
1426 switch (s->info->spec)
1428 case SR_NOTHING: return TRUE;
1429 case SR_INTERNAL:
1430 if (context_getFlag (FLG_INTERNALGLOBS))
1432 return (sRefSet_modifyMember (sl, s));
1434 else
1436 (void) sRefSet_modifyMember (sl, s);
1437 return TRUE;
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;
1447 BADEXIT;
1451 ** this should probably be elsewhere...
1453 ** returns TRUE iff sl indicates that s can be modified
1456 static
1457 bool sRef_doModify (sRef s, sRefSet sl)
1459 llassert (sRef_isReasonable (s));
1461 switch (s->kind)
1463 case SK_UNCONSTRAINED:
1464 case SK_CONST:
1465 return TRUE;
1466 case SK_CVAR:
1467 if (sRef_isFileOrGlobalScope (s))
1469 if (context_checkGlobMod (s))
1471 return (sRefSet_modifyMember (sl, s));
1473 else
1475 (void) sRefSet_modifyMember (sl, s);
1478 return TRUE;
1480 else
1482 return TRUE;
1484 case SK_PARAM:
1485 return TRUE;
1486 case SK_ARRAYFETCH:
1487 return (OR (sRefSet_modifyMember (sl, s),
1488 sRef_doModifyVal (s->info->arrayfetch->arr, sl)));
1489 case SK_FIELD:
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)));
1501 case SK_PTR:
1503 return (OR (sRefSet_modifyMember (sl, s),
1504 sRef_doModifyVal (s->info->ref, sl)));
1506 case SK_ADR:
1507 return (OR (sRefSet_modifyMember (sl, s),
1508 sRef_doModifyVal (s->info->ref, sl)));
1509 case SK_CONJ:
1510 return (AND (sRef_doModify (s->info->conj->a, sl),
1511 (sRef_doModify (s->info->conj->b, sl))));
1512 case SK_UNKNOWN:
1513 case SK_NEW:
1514 case SK_TYPE:
1515 return TRUE;
1516 case SK_OBJECT:
1517 case SK_DERIVED:
1518 case SK_EXTERNAL:
1519 return TRUE;
1520 case SK_SPECIAL:
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;
1533 BADEXIT;
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)
1558 else
1560 s1->aliaskind = AK_ERROR;
1564 return s1;
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)));
1585 switch (s1->kind)
1587 case SK_PARAM:
1588 return (int_compare (s1->info->paramno, s2->info->paramno));
1589 case SK_ARRAYFETCH:
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)
1600 return 0;
1602 return 1;
1604 case SK_FIELD:
1606 COMPARERETURN (sRef_compare (s1->info->field->rec, s2->info->field->rec));
1608 if (cstring_equal (s1->info->field->field, s2->info->field->field))
1609 return 0;
1611 return 1;
1613 case SK_PTR:
1614 case SK_ADR:
1615 return (sRef_compare (s1->info->ref, s2->info->ref));
1616 case SK_CONJ:
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));
1621 case SK_NEW:
1622 case SK_CVAR:
1623 case SK_UNKNOWN:
1624 case SK_OBJECT:
1625 case SK_TYPE:
1626 case SK_DERIVED:
1627 case SK_EXTERNAL:
1628 case SK_CONST:
1629 case SK_RESULT:
1630 return 0;
1631 case SK_SPECIAL:
1632 return (generic_compare (s1->info->spec, s2->info->spec));
1634 BADEXIT;
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
1653 static bool
1654 sRef_uniqueReference (sRef s)
1656 return (sRef_isFresh (s) || sRef_isUnique (s)
1657 || sRef_isOnly (s) || sRef_isStack (s)
1658 || sRef_isAddress (s));
1661 static bool
1662 sRef_similarRelaxedAux (sRef s1, sRef s2)
1664 if (s1 == s2)
1666 if (sRef_isUnknownArrayFetch (s1))
1668 return FALSE;
1670 else
1672 return TRUE;
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)));
1682 switch (s1->kind)
1684 case SK_CVAR:
1685 return ((s2->kind == SK_CVAR)
1686 && (cref_equal (s1->info->cvar, s2->info->cvar)));
1687 case SK_PARAM:
1688 return ((s2->kind == SK_PARAM)
1689 && (s1->info->paramno == s2->info->paramno));
1690 case SK_ARRAYFETCH:
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);
1702 else
1704 return FALSE;
1707 else
1709 return FALSE;
1713 return FALSE;
1714 case SK_FIELD:
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))));
1720 case SK_PTR:
1721 return ((s2->kind == SK_PTR)
1722 && sRef_similarRelaxedAux (s1->info->ref, s2->info->ref));
1723 case SK_ADR:
1724 return ((s2->kind == SK_ADR)
1725 && sRef_similarRelaxedAux (s1->info->ref, s2->info->ref));
1726 case SK_CONJ:
1727 return ((sRef_similarRelaxedAux (s1->info->conj->a, s2) ||
1728 (sRef_similarRelaxedAux (s1->info->conj->b, s2))));
1729 case SK_SPECIAL:
1730 return (s1->info->spec == s2->info->spec);
1731 case SK_UNCONSTRAINED:
1732 return (cstring_equal (s1->info->fname, s2->info->fname));
1733 case SK_DERIVED:
1734 case SK_CONST:
1735 case SK_TYPE:
1736 case SK_NEW:
1737 case SK_UNKNOWN:
1738 case SK_OBJECT:
1739 case SK_EXTERNAL:
1740 case SK_RESULT:
1741 return FALSE;
1743 BADEXIT;
1746 bool
1747 sRef_similarRelaxed (sRef s1, sRef s2)
1749 bool us1, us2;
1751 if (s1 == s2)
1753 if (sRef_isThroughArrayFetch (s1))
1755 return FALSE;
1757 else
1759 return TRUE;
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));
1801 else
1803 return sRef_similarRelaxedAux (s1, s2);
1807 bool
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));
1824 switch (s1->kind)
1826 case SK_CVAR:
1827 return ((s2->kind == SK_CVAR)
1828 && (cref_equal (s1->info->cvar, s2->info->cvar)));
1829 case SK_PARAM:
1830 return ((s2->kind == SK_PARAM)
1831 && (s1->info->paramno == s2->info->paramno));
1832 case SK_ARRAYFETCH:
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);
1844 else
1846 return TRUE;
1849 else
1851 return TRUE;
1855 else
1857 if (s2->kind == SK_PTR)
1859 if (sRef_similar (s1->info->arrayfetch->arr,
1860 s2->info->ref))
1862 return TRUE;
1867 return FALSE;
1868 case SK_FIELD:
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))));
1874 case SK_PTR:
1875 if (s2->kind == SK_PTR)
1877 return sRef_similar (s1->info->ref, s2->info->ref);
1879 else
1881 if (s2->kind == SK_ARRAYFETCH)
1883 if (sRef_similar (s2->info->arrayfetch->arr,
1884 s1->info->ref))
1886 return TRUE;
1891 return FALSE;
1892 case SK_ADR:
1893 return ((s2->kind == SK_ADR)
1894 && sRef_similar (s1->info->ref, s2->info->ref));
1895 case SK_CONJ:
1896 return ((sRef_similar (s1->info->conj->a, s2) ||
1897 (sRef_similar (s1->info->conj->b, s2))));
1898 case SK_DERIVED:
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));
1903 case SK_CONST:
1904 case SK_TYPE:
1905 case SK_NEW:
1906 case SK_UNKNOWN:
1907 case SK_OBJECT:
1908 case SK_EXTERNAL:
1909 case SK_RESULT:
1910 return FALSE;
1911 case SK_SPECIAL:
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)));
1917 BADEXIT;
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;
1927 bool
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)
1939 case SK_CVAR:
1940 case SK_PARAM:
1941 return (sRef_same (small, big));
1942 case SK_ARRAYFETCH:
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);
1953 else
1955 return TRUE;
1958 else
1960 return TRUE;
1964 return (sRef_includedBy (small->info->arrayfetch->arr, big));
1965 case SK_FIELD:
1966 if (big->kind == SK_FIELD)
1968 return
1969 (sRef_same (small->info->field->rec, big->info->field->rec) &&
1970 cstring_equal (small->info->field->field, big->info->field->field));
1972 else
1974 return (sRef_includedBy (small->info->field->rec, big));
1977 case SK_PTR:
1978 if (big->kind == SK_PTR)
1980 return sRef_same (small->info->ref, big->info->ref);
1982 else
1984 return (sRef_includedBy (small->info->ref, big));
1987 case SK_ADR:
1988 return ((big->kind == SK_ADR) && sRef_similar (small->info->ref, big->info->ref));
1989 case SK_CONJ:
1990 return ((sRef_includedBy (small->info->conj->a, big) ||
1991 (sRef_includedBy (small->info->conj->b, big))));
1992 case SK_DERIVED:
1993 return (sRef_includedBy (small->info->ref, big));
1994 case SK_UNCONSTRAINED:
1995 case SK_CONST:
1996 case SK_TYPE:
1997 case SK_NEW:
1998 case SK_UNKNOWN:
1999 case SK_OBJECT:
2000 case SK_EXTERNAL:
2001 case SK_RESULT:
2002 return FALSE;
2003 case SK_SPECIAL:
2004 switch (small->info->spec)
2006 case SR_NOTHING: return TRUE;
2007 case SR_SPECSTATE:
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;
2014 BADEXIT;
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
2030 ** the are.
2034 bool
2035 sRef_realSame (sRef s1, sRef s2)
2037 if (s1 == s2) return TRUE;
2039 if (sRef_isUnreasonable (s1)
2040 || sRef_isUnreasonable (s2))
2042 return FALSE;
2045 switch (s1->kind)
2047 case SK_CVAR:
2048 return ((s2->kind == SK_CVAR) && (cref_equal (s1->info->cvar, s2->info->cvar)));
2049 case SK_PARAM:
2050 return ((s2->kind == SK_PARAM) && (s1->info->paramno == s2->info->paramno));
2051 case SK_ARRAYFETCH:
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)
2062 return TRUE;
2064 return FALSE;
2067 return FALSE;
2068 case SK_FIELD:
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))));
2072 case SK_PTR:
2073 return ((s2->kind == SK_PTR) && sRef_realSame (s1->info->ref, s2->info->ref));
2074 case SK_ADR:
2075 return ((s2->kind == SK_ADR) && sRef_realSame (s1->info->ref, s2->info->ref));
2076 case SK_CONJ:
2077 return ((sRef_realSame (s1->info->conj->a, s2) ||
2078 (sRef_realSame (s1->info->conj->b, s2))));
2079 case SK_OBJECT:
2080 return ((s2->kind == SK_OBJECT)
2081 && ctype_match (s1->info->object, s2->info->object));
2082 case SK_EXTERNAL:
2083 return ((s2->kind == SK_EXTERNAL)
2084 && sRef_realSame (s1->info->ref, s2->info->ref));
2085 case SK_SPECIAL:
2086 return ((s2->kind == SK_SPECIAL) && s1->info->spec == s2->info->spec);
2087 case SK_DERIVED:
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)));
2092 case SK_TYPE:
2093 case SK_CONST:
2094 case SK_NEW:
2095 case SK_UNKNOWN:
2096 case SK_RESULT:
2097 return TRUE; /* changed this! was false */
2099 BADEXIT;
2102 #ifdef DEADCODE
2103 bool
2104 sRef_sameObject (sRef s1, sRef s2)
2106 return (s1 == s2);
2108 #endif
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.
2118 bool
2119 sRef_same (sRef s1, sRef s2)
2121 if (s1 == s2) return TRUE;
2122 if (sRef_isInvalid (s1) || sRef_isInvalid (s2)) return FALSE;
2124 switch (s1->kind)
2126 case SK_CVAR:
2127 return ((s2->kind == SK_CVAR) && (cref_equal (s1->info->cvar, s2->info->cvar)));
2128 case SK_PARAM:
2129 return ((s2->kind == SK_PARAM) && (s1->info->paramno == s2->info->paramno));
2130 case SK_ARRAYFETCH:
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);
2140 return TRUE;
2143 return FALSE;
2144 case SK_FIELD:
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))));
2151 case SK_PTR:
2153 llassert (s1->info->ref != s1);
2154 return ((s2->kind == SK_PTR) && sRef_same (s1->info->ref, s2->info->ref));
2156 case SK_ADR:
2158 llassert (s1->info->ref != s1);
2159 return ((s2->kind == SK_ADR) && sRef_same (s1->info->ref, s2->info->ref));
2161 case SK_CONJ:
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)));
2166 case SK_SPECIAL:
2167 return ((s2->kind == SK_SPECIAL) && s1->info->spec == s2->info->spec);
2168 case SK_DERIVED:
2169 llassert (s1->info->ref != s1);
2170 return ((s2->kind == SK_DERIVED) && sRef_same (s1->info->ref, s2->info->ref));
2171 case SK_CONST:
2172 case SK_UNCONSTRAINED:
2173 case SK_TYPE:
2174 case SK_UNKNOWN:
2175 case SK_NEW:
2176 case SK_OBJECT:
2177 case SK_EXTERNAL:
2178 case SK_RESULT:
2179 return FALSE;
2181 BADEXIT;
2184 #ifdef DEADCODE
2186 ** sort of similar, for use in def/use
2189 static bool
2190 sRef_closeEnough (sRef s1, sRef s2)
2192 if (s1 == s2) return TRUE;
2193 if (sRef_isInvalid (s1) || sRef_isInvalid (s2)) return FALSE;
2195 switch (s1->kind)
2197 case SK_CVAR:
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)));
2204 case SK_PARAM:
2205 return ((s2->kind == SK_PARAM)
2206 && (s1->info->paramno == s2->info->paramno));
2207 case SK_ARRAYFETCH:
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);
2216 return TRUE;
2219 return FALSE;
2220 case SK_FIELD:
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))));
2224 case SK_PTR:
2225 return ((s2->kind == SK_PTR) && sRef_closeEnough (s1->info->ref, s2->info->ref));
2226 case SK_ADR:
2227 return ((s2->kind == SK_ADR) && sRef_closeEnough (s1->info->ref, s2->info->ref));
2228 case SK_DERIVED:
2229 return ((s2->kind == SK_DERIVED) && sRef_closeEnough (s1->info->ref, s2->info->ref));
2230 case SK_CONJ:
2231 return ((sRef_closeEnough (s1->info->conj->a, s2)) ||
2232 (sRef_closeEnough (s1->info->conj->b, s2)));
2233 case SK_SPECIAL:
2234 return ((s2->kind == SK_SPECIAL) && s1->info->spec == s2->info->spec);
2235 case SK_TYPE:
2236 case SK_CONST:
2237 case SK_UNKNOWN:
2238 case SK_NEW:
2239 case SK_OBJECT:
2240 case SK_EXTERNAL:
2241 case SK_RESULT:
2243 return FALSE;
2245 BADEXIT;
2247 #endif
2250 drl add 12/24/2000
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)
2257 constraintExpr ce;
2259 if (sRef_isInvalid (s))
2260 llfatalbug((message("Invalid sRef")));
2262 switch (s->kind)
2264 case SK_RESULT:
2266 ce = constraintExpr_makeTermsRef (s);
2267 return ce;
2269 case SK_FIELD:
2271 sRef temp;
2273 temp = (sRef_makeField (sRef_fixBaseParam (s->info->field->rec, args),
2274 s->info->field->field));
2275 ce = constraintExpr_makeTermsRef (temp);
2276 return ce;
2278 case SK_PTR:
2280 sRef temp;
2281 temp = (sRef_makePointer (sRef_fixBaseParam (s->info->ref, args)));
2282 ce = constraintExpr_makeTermsRef (temp);
2283 return ce;
2286 case SK_ARRAYFETCH:
2288 sRef temp;
2289 temp = sRef_saveCopy(s);
2290 temp = sRef_fixBaseParam (temp, args);
2291 ce = constraintExpr_makeTermsRef (temp);
2293 sRef_free(temp);
2294 return ce;
2296 case SK_CVAR:
2298 sRef temp;
2299 temp = sRef_saveCopy(s);
2300 ce = constraintExpr_makeTermsRef (temp);
2301 sRef_free(temp);
2302 return ce;
2304 case SK_PARAM:
2306 exprNode e;
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);
2312 return ce;
2315 default:
2317 sRef temp;
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);
2323 sRef_free(temp);
2324 return ce;
2329 /*@exposed@*/ sRef
2330 sRef_fixBaseParam (/*@returned@*/ sRef s, exprNodeList args)
2332 if (sRef_isInvalid (s)) return (sRef_undefined);
2334 switch (s->kind)
2336 case SK_UNCONSTRAINED:
2337 case SK_CVAR:
2338 return s;
2339 case SK_PARAM:
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));
2352 else
2354 return sRef_makeUnknown ();
2357 case SK_ARRAYFETCH:
2359 if (s->info->arrayfetch->indknown)
2361 return (sRef_makeArrayFetchKnown
2362 (sRef_fixBaseParam (s->info->arrayfetch->arr, args),
2363 s->info->arrayfetch->ind));
2365 else
2367 return (sRef_makeArrayFetch
2368 (sRef_fixBaseParam (s->info->arrayfetch->arr, args)));
2370 case SK_FIELD:
2372 sRef res;
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)));
2377 return res;
2379 case SK_PTR:
2380 return (sRef_makePointer (sRef_fixBaseParam (s->info->ref, args)));
2382 case SK_ADR:
2383 return (sRef_makeAddress (sRef_fixBaseParam (s->info->ref, args)));
2385 case SK_CONJ:
2386 return (sRef_makeConj (sRef_fixBaseParam (s->info->conj->a, args),
2387 sRef_fixBaseParam (s->info->conj->b, args)));
2388 case SK_DERIVED:
2389 case SK_SPECIAL:
2390 case SK_TYPE:
2391 case SK_CONST:
2392 case SK_NEW:
2393 case SK_UNKNOWN:
2394 case SK_OBJECT:
2395 case SK_EXTERNAL:
2396 case SK_RESULT:
2397 return s;
2399 BADEXIT;
2402 /*@exposed@*/ sRef
2403 sRef_undumpGlobal (char **c)
2405 char p = **c;
2407 (*c)++;
2409 switch (p)
2411 case 'g':
2413 usymId uid = usymId_fromInt (reader_getInt (c));
2414 sstate defstate;
2415 nstate nullstate;
2416 sRef ret;
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;
2427 return ret;
2429 case 's':
2431 int i = reader_getInt (c);
2432 speckind sk = speckind_fromInt (i);
2434 switch (sk)
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;
2442 BADEXIT;
2444 case '-':
2445 return sRef_undefined;
2446 case 'u':
2447 return sRef_makeUnknown ();
2448 case 'x':
2449 return sRef_makeUnknown ();
2450 default:
2451 llfatalerror (message ("sRef_undumpGlobal: bad line: %s",
2452 cstring_fromChars (*c)));
2454 BADEXIT;
2457 static /*@exposed@*/ sRef sRef_undumpBody (char **c)
2459 char p = **c;
2461 (*c)++;
2463 switch (p)
2465 case 'g':
2466 return (sRef_makeGlobal (usymId_fromInt (reader_getInt (c)),
2467 ctype_unknown, stateInfo_currentLoc ()));
2468 case 'p':
2469 return (sRef_makeParam (reader_getInt (c), ctype_unknown,
2470 stateInfo_makeLoc (g_currentloc, SA_DECLARED)));
2471 case 'r':
2472 return (sRef_makeResult (ctype_undump (c)));
2473 case 'a':
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);
2481 return ret;
2483 else
2485 sRef arr = sRef_undump (c);
2486 sRef ret = sRef_buildArrayFetch (arr);
2488 return ret;
2491 case 'f':
2493 cstring fname = cstring_undefined;
2494 sRef ret;
2496 while (**c != '.')
2498 fname = cstring_appendChar (fname, **c);
2499 (*c)++;
2501 (*c)++;
2503 ret = sRef_buildField (sRef_undump (c), fname);
2504 cstring_markOwned (fname);
2505 return (ret);
2507 case 's':
2509 int i = reader_getInt (c);
2510 speckind sk = speckind_fromInt (i);
2512 switch (sk)
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;
2520 BADEXIT;
2522 case 't':
2524 sRef ptr = sRef_undump (c);
2525 sRef ret = sRef_makePointer (ptr);
2527 return (ret);
2529 case 'd':
2531 sRef adr = sRef_undump (c);
2532 sRef ret = sRef_makeAddress (adr);
2534 return (ret);
2536 case 'o':
2538 return (sRef_makeObject (ctype_undump (c)));
2540 case 'c':
2542 sRef s1;
2543 sRef s2;
2545 s1 = sRef_undump (c);
2546 (*c)++;
2547 s2 = sRef_undump (c);
2549 return (sRef_makeConj (s1, s2));
2551 case '-':
2552 return sRef_undefined;
2553 case 'u':
2554 return sRef_makeUnknown ();
2555 case 'x':
2556 return sRef_makeUnknown ();
2557 default:
2558 llfatalerror (message ("sRef_undump: bad line: %s", cstring_fromChars (*c)));
2560 BADEXIT;
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, '=');
2574 return res;
2577 static /*@only@*/ cstring sRef_dumpBody (sRef s)
2579 if (sRef_isInvalid (s))
2581 return (cstring_makeLiteral ("-"));
2583 else
2585 switch (s->kind)
2587 case SK_PARAM:
2588 return (message ("p%d", s->info->paramno));
2589 case SK_ARRAYFETCH:
2590 if (s->info->arrayfetch->indknown)
2592 return (message ("a%d%q", s->info->arrayfetch->ind,
2593 sRef_dump (s->info->arrayfetch->arr)));
2595 else
2597 return (message ("a%q", sRef_dump (s->info->arrayfetch->arr)));
2599 case SK_FIELD:
2600 return (message ("f%s.%q", s->info->field->field,
2601 sRef_dump (s->info->field->rec)));
2602 case SK_PTR:
2603 return (message ("t%q", sRef_dump (s->info->ref)));
2604 case SK_ADR:
2605 return (message ("d%q", sRef_dump (s->info->ref)));
2606 case SK_OBJECT:
2607 return (message ("o%q", ctype_dump (s->info->object)));
2608 case SK_SPECIAL:
2609 return (message ("s%d", (int) s->info->spec));
2610 case SK_CONJ:
2611 return (message ("c%q.%q",
2612 sRef_dump (s->info->conj->a),
2613 sRef_dump (s->info->conj->b)));
2614 case SK_CVAR:
2615 if (sRef_isFileOrGlobalScope (s))
2617 return (message ("g%d",
2618 usymtab_convertId (s->info->cvar->index)));
2620 else
2622 llcontbug (message ("Dumping local variable: %q",
2623 sRef_unparseDebug (s)));
2624 return (cstring_makeLiteral ("u"));
2626 case SK_UNKNOWN:
2627 return (cstring_makeLiteral ("u"));
2628 case SK_RESULT:
2629 return (message ("r%q", ctype_dump (s->type)));
2630 case SK_TYPE:
2631 case SK_CONST:
2632 case SK_EXTERNAL:
2633 case SK_DERIVED:
2634 case SK_NEW:
2635 case SK_UNCONSTRAINED:
2636 llcontbug (message ("sRef_dump: bad kind: %q",
2637 sRef_unparseFull (s)));
2638 return (cstring_makeLiteral ("x"));
2642 BADEXIT;
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)));
2654 return res;
2657 cstring sRef_dumpGlobal (sRef s)
2659 llassert (!sRef_hasValue (s));
2661 if (sRef_isInvalid (s))
2663 return (cstring_makeLiteral ("-"));
2665 else
2667 switch (s->kind)
2669 case SK_CVAR:
2670 if (sRef_isFileOrGlobalScope (s))
2672 return (message ("g%d@%d@%d",
2673 usymtab_convertId (s->info->cvar->index),
2674 (int) s->defstate,
2675 (int) sRef_getNullState (s)));
2677 else
2679 llcontbug (message ("Dumping local variable: %q",
2680 sRef_unparseDebug (s)));
2681 return (cstring_makeLiteral ("u"));
2683 case SK_UNKNOWN:
2684 return (cstring_makeLiteral ("u"));
2685 case SK_SPECIAL:
2686 return (message ("s%d", (int) s->info->spec));
2687 default:
2688 llcontbug (message ("sRef_dumpGlobal: bad kind: %q",
2689 sRef_unparseFull (s)));
2690 return (cstring_makeLiteral ("x"));
2694 BADEXIT;
2697 ctype
2698 sRef_deriveType (sRef s, uentryList cl)
2700 if (sRef_isInvalid (s)) return ctype_unknown;
2702 switch (s->kind)
2704 case SK_CVAR:
2705 return (uentry_getType (usymtab_getRefQuiet (s->info->cvar->lexlevel,
2706 s->info->cvar->index)));
2707 case SK_UNCONSTRAINED:
2708 return (ctype_unknown);
2709 case SK_PARAM:
2710 if (s->info->paramno >= 0)
2712 return uentry_getType (uentryList_getN (cl, s->info->paramno));
2714 else
2716 return ctype_unknown;
2718 case SK_ARRAYFETCH:
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))
2728 return (ca);
2730 else
2732 llcontbuglit ("sRef_deriveType: inconsistent array type");
2733 return ca;
2736 case SK_FIELD:
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));
2749 else
2751 llcontbuglit ("sRef_deriveType: bad field");
2752 return ctype_unknown;
2755 else if (ctype_isUnknown (ct))
2757 return (ct);
2759 else
2761 llcontbuglit ("sRef_deriveType: inconsistent field type");
2762 return (ct);
2765 case SK_PTR:
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));
2771 else
2773 llcontbuglit ("sRef_deriveType: inconsistent pointer type");
2774 return (ct);
2777 case SK_ADR:
2779 ctype ct = sRef_deriveType (s->info->ref, cl);
2781 if (ctype_isUnknown (ct)) return ct;
2782 return ctype_makePointer (ct);
2784 case SK_DERIVED:
2786 return sRef_deriveType (s->info->ref, cl);
2788 case SK_OBJECT:
2790 return (s->info->object);
2792 case SK_CONJ:
2794 return (ctype_makeConj (sRef_deriveType (s->info->conj->a, cl),
2795 sRef_deriveType (s->info->conj->b, cl)));
2797 case SK_RESULT:
2798 case SK_CONST:
2799 case SK_TYPE:
2801 return (s->type);
2803 case SK_SPECIAL:
2804 case SK_UNKNOWN:
2805 case SK_EXTERNAL:
2806 case SK_NEW:
2807 return ctype_unknown;
2809 BADEXIT;
2812 ctype
2813 sRef_getType (sRef s)
2815 if (sRef_isInvalid (s)) return ctype_unknown;
2816 return s->type;
2820 /*@only@*/ cstring
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, ' '));
2835 else
2837 return ret;
2841 return cstring_undefined;
2844 cstring
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;
2860 /*@only@*/ cstring
2861 sRef_unparse (sRef s)
2863 if (sRef_isInvalid (s)) return (cstring_makeLiteral ("?"));
2865 if (context_inFunctionLike ())
2867 return (sRef_unparseWithArgs (s, context_getParams ()));
2869 else
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 ("?"));
2884 switch (s->kind)
2886 case SK_CVAR:
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));
2891 case SK_PARAM:
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));
2904 case SK_ARRAYFETCH:
2905 if (s->info->arrayfetch->indknown)
2907 return (message ("%q[%d]", sRef_unparseWithArgs (s->info->arrayfetch->arr, args),
2908 s->info->arrayfetch->ind));
2910 else
2912 return (message ("%q[]", sRef_unparseWithArgs (s->info->arrayfetch->arr, args)));
2914 case SK_FIELD:
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));
2925 case SK_PTR:
2927 sRef ref = sRef_fixConj (s->info->ref);
2928 skind sk = ref->kind;
2929 cstring ret;
2931 if (sk == SK_NEW)
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));
2940 else
2942 ret = message ("*(%q)", sRef_unparseWithArgs (ref, args));
2945 return ret;
2947 case SK_ADR:
2948 return (message ("&%q", sRef_unparseWithArgs (s->info->ref, args)));
2949 case SK_OBJECT:
2950 return (cstring_copy (ctype_unparse (s->info->object)));
2951 case SK_CONJ:
2952 return (sRef_unparseWithArgs (sRef_getConjA (s), args));
2953 case SK_NEW:
2954 if (cstring_isDefined (s->info->fname))
2956 return (message ("[result of %s]", s->info->fname));
2958 else
2960 return (cstring_makeLiteral ("<new>"));
2962 case SK_UNKNOWN:
2963 return (cstring_makeLiteral ("?"));
2964 case SK_DERIVED:
2965 return (message ("<derived %q>", sRef_unparse (s->info->ref)));
2966 case SK_EXTERNAL:
2967 return (message ("<external %q>", sRef_unparse (s->info->ref)));
2968 case SK_TYPE:
2969 return (message ("<type %s>", ctype_unparse (s->type)));
2970 case SK_CONST:
2971 return (message ("<const %s>", ctype_unparse (s->type)));
2972 case SK_SPECIAL:
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>");
2980 BADDEFAULT;
2982 case SK_RESULT:
2983 return cstring_makeLiteral ("result");
2984 default:
2985 llbug (message ("Bad sref, kind = %d", (int) s->kind));
2986 BADEXIT;
2990 /*@only@*/ cstring
2991 sRef_unparseDebug (sRef s)
2993 if (sRef_isInvalid (s))
2995 return (cstring_makeLiteral ("<undef>"));
2998 switch (s->kind)
3000 case SK_UNCONSTRAINED:
3001 return (message ("<unconstrained %s>", s->info->fname));
3002 case SK_CVAR:
3004 uentry ce;
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));
3014 else
3016 return (message ("<scope: %d.%d *%q*>",
3017 s->info->cvar->lexlevel,
3018 s->info->cvar->index,
3019 uentry_getName (ce)));
3023 case SK_PARAM:
3025 return (message ("<parameter %d>", s->info->paramno + 1));
3027 case SK_ARRAYFETCH:
3028 if (s->info->arrayfetch->indknown)
3030 return (message ("%q[%d]", sRef_unparseDebug (s->info->arrayfetch->arr),
3031 s->info->arrayfetch->ind));
3033 else
3035 return (message ("%q[]", sRef_unparseDebug (s->info->arrayfetch->arr)));
3037 case SK_FIELD:
3038 return (message ("%q.%s", sRef_unparseDebug (s->info->field->rec),
3039 s->info->field->field));
3040 case SK_PTR:
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));
3048 else
3050 return (message ("*(%q)", sRef_unparseDebug (s->info->ref)));
3052 case SK_ADR:
3053 return (message ("&%q", sRef_unparseDebug (s->info->ref)));
3054 case SK_OBJECT:
3055 return (message ("<object type %s>", ctype_unparse (s->info->object)));
3056 case SK_CONJ:
3057 return (message ("%q | %q", sRef_unparseDebug (s->info->conj->a),
3058 sRef_unparseDebug (s->info->conj->b)));
3059 case SK_NEW:
3060 return message ("<new: %s>", s->info->fname);
3061 case SK_DERIVED:
3062 return (message ("<derived %q>", sRef_unparseDebug (s->info->ref)));
3063 case SK_EXTERNAL:
3064 return (message ("<external %q>", sRef_unparseDebug (s->info->ref)));
3065 case SK_TYPE:
3066 return (message ("<type %s>", ctype_unparse (s->type)));
3067 case SK_CONST:
3068 if (sRef_hasValue (s))
3070 return (message ("<const %s=%q>", ctype_unparse (s->type), multiVal_unparse (sRef_getValue (s))));
3072 else
3074 return (message ("<const %s>", ctype_unparse (s->type)));
3076 case SK_RESULT:
3077 return (message ("<result %s>", ctype_unparse (s->type)));
3078 case SK_SPECIAL:
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"
3085 : "error")));
3086 case SK_UNKNOWN:
3087 return cstring_makeLiteral ("<unknown>");
3090 BADEXIT;
3093 static /*@only@*/ cstring
3094 sRef_unparseNoArgs (sRef s)
3096 if (sRef_isInvalid (s)) return (cstring_makeLiteral ("?"));
3098 switch (s->kind)
3100 case SK_UNCONSTRAINED:
3101 return (cstring_copy (s->info->fname));
3102 case SK_CVAR:
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));
3113 else
3115 return (uentry_getName (ce));
3118 case SK_ARRAYFETCH:
3119 if (s->info->arrayfetch->indknown)
3121 return (message ("%q[%d]", sRef_unparseNoArgs (s->info->arrayfetch->arr),
3122 s->info->arrayfetch->ind));
3124 else
3126 return (message ("%q[]", sRef_unparseNoArgs (s->info->arrayfetch->arr)));
3128 case SK_FIELD:
3129 return (message ("%q.%s", sRef_unparseNoArgs (s->info->field->rec),
3130 s->info->field->field));
3131 case SK_PTR:
3133 sRef ref = sRef_fixConj (s->info->ref);
3134 skind sk = ref->kind;
3135 cstring ret;
3137 if (skind_isSimple (sk) || sk == SK_PTR)
3139 ret = message ("*%q", sRef_unparseNoArgs (ref));
3141 else
3143 ret = message ("*(%q)", sRef_unparseNoArgs (ref));
3146 return (ret);
3148 case SK_ADR:
3149 return (message ("&%q", sRef_unparseNoArgs (s->info->ref)));
3150 case SK_OBJECT:
3151 return (cstring_copy (ctype_unparse (s->info->object)));
3152 case SK_CONJ:
3153 return (sRef_unparseNoArgs (s->info->conj->a));
3154 case SK_NEW:
3155 return (message ("result of %s", s->info->fname));
3156 case SK_DERIVED:
3157 return (message ("<der %q>", sRef_unparseNoArgs (s->info->ref)));
3158 case SK_EXTERNAL:
3159 return message ("<ext %q>", sRef_unparseNoArgs (s->info->ref));
3160 case SK_SPECIAL:
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"
3166 : "<spec error>"));
3167 case SK_RESULT:
3168 return cstring_makeLiteral ("result");
3169 case SK_CONST:
3170 case SK_TYPE:
3171 case SK_UNKNOWN:
3172 return cstring_makeLiteral ("?");
3173 case SK_PARAM:
3174 /* llcontbug (message ("sRef_unparseNoArgs: bad case: %q", sRef_unparseDebug (s))); */
3175 return (sRef_unparseDebug (s));
3177 BADEXIT;
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 */
3188 return (s);
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 ();
3208 s->kind = SK_CVAR;
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;
3221 else
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;
3231 else
3233 s->defstate = SS_UNDEFINED;
3234 s->oaliaskind = s->aliaskind = AK_LOCAL;
3238 s->type = ct;
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);
3246 return s;
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))
3258 sRef conj;
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);
3269 return globScope;
3272 sRef
3273 sRef_makeGlobal (usymId l, ctype ct, /*@only@*/ stateInfo stinfo)
3275 return (sRef_makeCvar (globScope, l, ct, stinfo));
3278 void
3279 sRef_setParamNo (sRef s, int l)
3281 llassert (sRef_isReasonable (s) && s->kind == SK_PARAM);
3282 s->info->paramno = l;
3283 llassert (l >= -1);
3286 /*@dependent@*/ sRef
3287 sRef_makeParam (int l, ctype ct, stateInfo stinfo)
3289 sRef s = sRef_new ();
3291 s->kind = SK_PARAM;
3292 s->type = ct;
3294 s->info = (sinfo) dmalloc (sizeof (*s->info));
3295 s->info->paramno = l;
3296 llassert (l >= -1);
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);
3302 return s;
3305 bool
3306 sRef_isIndexKnown (sRef arr)
3308 bool res;
3310 llassert (sRef_isReasonable (arr));
3311 arr = sRef_fixConj (arr);
3313 llassert (arr->kind == SK_ARRAYFETCH);
3314 res = arr->info->arrayfetch->indknown;
3315 return (res);
3319 sRef_getIndex (sRef arr)
3321 int result;
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)));
3331 result = 0;
3333 else
3335 result = arr->info->arrayfetch->ind;
3338 return result;
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);
3361 else
3363 sRef s = sRef_newRef ();
3365 s->kind = SK_ADR;
3366 s->type = ctype_makePointer (t->type);
3367 s->info = (sinfo) dmalloc (sizeof (*s->info));
3368 s->info->ref = t;
3370 if (t->defstate == SS_UNDEFINED)
3371 /* no! it is allocated even still: && !ctype_isPointer (t->type)) */
3373 s->defstate = SS_ALLOCATED;
3375 else
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));
3391 return s;
3395 cstring sRef_getField (sRef s)
3397 cstring res;
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;
3406 return (res);
3409 sRef sRef_getBase (sRef s)
3411 sRef res;
3413 if (sRef_isInvalid (s)) return (sRef_undefined);
3415 s = sRef_fixConj (s);
3417 switch (s->kind)
3419 case SK_ADR:
3420 case SK_PTR:
3421 case SK_DERIVED:
3422 case SK_EXTERNAL:
3423 res = s->info->ref;
3424 break;
3425 case SK_FIELD:
3426 res = s->info->field->rec;
3427 break;
3429 case SK_ARRAYFETCH:
3430 res = s->info->arrayfetch->arr;
3431 break;
3433 default:
3434 res = sRef_undefined; /* shouldn't need it */
3437 return (res);
3441 ** same as getBase, except returns invalid
3442 ** (and doesn't use adr's)
3445 sRef
3446 sRef_getBaseSafe (sRef s)
3448 sRef res;
3450 if (sRef_isInvalid (s)) { return sRef_undefined; }
3452 s = sRef_fixConj (s);
3454 switch (s->kind)
3456 case SK_PTR:
3457 res = s->info->ref;
3458 break;
3459 case SK_FIELD:
3460 res = s->info->field->rec; break;
3461 case SK_ARRAYFETCH:
3462 res = s->info->arrayfetch->arr;
3463 break;
3464 default:
3465 res = sRef_undefined; break;
3468 return res;
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)
3481 llgenmsg (message
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.",
3486 sRef_unparse (s),
3487 MAXBASEDEPTH),
3488 g_currentloc);
3490 return sRef_undefined;
3493 switch (s->kind)
3495 case SK_ADR:
3496 case SK_PTR:
3497 return (sRef_getRootBaseAux (s->info->ref, depth + 1));
3498 case SK_FIELD:
3499 return (sRef_getRootBaseAux (s->info->field->rec, depth + 1));
3500 case SK_ARRAYFETCH:
3501 return (sRef_getRootBaseAux (s->info->arrayfetch->arr, depth + 1));
3502 case SK_CONJ:
3503 return (sRef_getRootBaseAux (sRef_fixConj (s), depth + 1));
3504 default:
3505 return s;
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;
3518 switch (s->kind)
3520 case SK_ADR:
3521 case SK_PTR:
3522 case SK_FIELD:
3523 case SK_ARRAYFETCH:
3524 return TRUE;
3525 case SK_CONJ:
3526 return (sRef_isDeep (sRef_fixConj (s)));
3527 default:
3528 return FALSE;
3532 static int sRef_depth (sRef s)
3534 if (sRef_isInvalid (s)) return 0;
3536 switch (s->kind)
3538 case SK_ADR:
3539 case SK_PTR:
3540 case SK_DERIVED:
3541 case SK_EXTERNAL:
3542 return 1 + sRef_depth (s->info->ref);
3543 case SK_FIELD:
3544 return 1 + sRef_depth (s->info->field->rec);
3545 case SK_ARRAYFETCH:
3546 return 1 + sRef_depth (s->info->arrayfetch->arr);
3547 case SK_CONJ:
3548 return (sRef_depth (sRef_fixConj (s)));
3549 default:
3550 return 1;
3554 sRef
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));
3564 return s;
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));
3579 s->type = t->type;
3580 s->info->ref = t;
3581 llassert (valueTable_isUndefined (s->state));
3582 s->state = context_createValueTable (s, stateInfo_makeLoc (g_currentloc, SA_DECLARED));
3583 return s;
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));
3594 s->info->ref = t;
3596 s->type = t->type;
3597 llassert (valueTable_isUndefined (s->state));
3598 s->state = context_createValueTable (s, stateInfo_makeLoc (g_currentloc, SA_CREATED));
3599 return s;
3601 else
3603 return sRef_undefined;
3608 ** definitely NOT symmetric:
3610 ** res fills in unknown state information from other
3613 void
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);
3654 else
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
3671 void
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)
3682 changed = TRUE;
3684 sinfo_free (res);
3686 res->kind = other->kind;
3687 res->type = other->type;
3688 res->info = sinfo_fullCopy (other);
3690 else
3692 if (!ctype_equal (res->type, other->type))
3694 changed = TRUE;
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)))
3711 changed = TRUE;
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)
3719 changed = TRUE;
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);
3745 changed = TRUE;
3748 else
3750 if (sRef_getNullState (other) != NS_UNKNOWN
3751 && sRef_getNullState (other) != sRef_getNullState (res))
3753 changed = TRUE;
3754 sRef_updateNullState (res, other);
3758 if (changed)
3760 sRef_clearDerived (res);
3764 void
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);
3771 else
3773 if (sRef_isInvalid (res))
3775 llbug (message ("sRef_mergeState: invalid res sRef: %q",
3776 sRef_unparseDebug (other)));
3778 else
3780 llbug (message ("sRef_mergeState: invalid other sRef: %q",
3781 sRef_unparseDebug (res)));
3786 void
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);
3793 else
3795 if (sRef_isInvalid (res))
3797 llbug (message ("sRef_mergeOptState: invalid res sRef: %q",
3798 sRef_unparseDebug (other)));
3800 else
3802 llbug (message ("sRef_mergeOptState: invalid other sRef: %q",
3803 sRef_unparseDebug (res)));
3808 static void
3809 sRef_mergeStateAux (/*@notnull@*/ sRef res, /*@notnull@*/ sRef other,
3810 clause cl, bool opt, fileloc loc,
3811 bool doDerivs)
3812 /*@modifies res@*/
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
3836 ** if (s) free (s);
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;
3849 else
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;
3868 else
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);
3889 else
3891 ; /* okay */
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)
3956 if (doDerivs)
3958 if (ctype_isUnion (ctype_realType (sRef_getType (res))))
3960 res->deriv = sRef_mergeUnionDerivs (res->deriv,
3961 other->deriv,
3962 opt, cl, loc);
3963 DPRINTF (("Copy derivs: %s", sRef_unparseFull (res)));
3965 else
3967 res->deriv = sRef_mergeDerivs (res->deriv, other->deriv,
3968 opt, cl, loc);
3969 DPRINTF (("Copy derivs: %s", sRef_unparseFull (res)));
3973 else
3975 if (doDerivs)
3977 res->deriv = sRef_mergeDerivs (res->deriv, other->deriv,
3978 opt, cl, loc);
3979 DPRINTF (("Copy derivs: %s", sRef_unparseFull (res)));
3981 else
3987 else
3989 if (rdef == SS_PDEFINED
3990 || (rdef == SS_DEFINED && odef == SS_PDEFINED))
3992 if (doDerivs)
3994 res->deriv = sRef_mergePdefinedDerivs (res->deriv, other->deriv,
3995 opt, cl, loc);
3996 DPRINTF (("Copy derivs: %s", sRef_unparseFull (res)));
3999 else
4001 if ((rdef == SS_DEFINED || rdef == SS_UNKNOWN)
4002 && res->defstate == SS_ALLOCATED)
4004 res->deriv = sRefSet_copyInto (res->deriv, other->deriv);
4006 else
4008 if (doDerivs)
4010 res->deriv = sRef_mergeDerivs (res->deriv, other->deriv,
4011 opt, cl, loc);
4012 DPRINTF (("Copy derivs: %s", sRef_unparseFull (res)));
4019 sRef_combineExKinds (res, other);
4021 else
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);
4040 else
4042 llcontbug (message ("merge conj: %q / %q", sRef_unparseFull (res),
4043 sRef_unparseFull (other)));
4049 ** Merge value table states
4052 # if 0
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),
4072 &msg);
4073 DPRINTF (("Val: %d / %s", val, msg));
4075 } end_valueTable_elements ;
4076 # endif
4078 DPRINTF (("Merge aux: %s / %s",
4079 sRef_unparseFull (res),
4080 sRef_unparseFull (other)));
4083 static sRefSet
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);
4092 else
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);
4104 else
4106 res = sRefSet_insert (res, el);
4109 } end_sRefSet_allElements ;
4111 return res;
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);
4185 else
4187 ; /* okay */
4190 if (ctype_isUnion (ctype_realType (sRef_getType (el))))
4192 el->deriv = sRef_mergeUnionDerivs (el->deriv, e2->deriv,
4193 opt, cl, loc);
4195 else
4197 el->deriv = sRef_mergeDerivs (el->deriv, e2->deriv, opt, cl, loc);
4200 if (sRef_equivalent (el, e2))
4202 ret = sRefSet_insert (ret, el);
4204 else
4206 sRef sr = sRef_leastCommon (el, e2);
4208 if (sRef_isReasonable (sr))
4210 ret = sRefSet_insert (ret, sr);
4212 else
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;
4237 sRefSet_free (res);
4238 return (ret);
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))
4266 if (!tbranch)
4268 if (usymtab_isDefinitelyNullDeep (el))
4270 return TRUE;
4273 else
4275 if (usymtab_isAltDefinitelyNullDeep (el))
4277 return TRUE;
4281 if (optgenerror
4282 (FLG_BRANCHSTATE,
4283 message ("Storage %q is %q in one path, but live in another.",
4284 sRef_unparse (el),
4285 cstring_makeLiteral (sRef_isKept (el)
4286 ? "kept" : "released")),
4287 loc))
4289 if (sRef_isKept (el))
4291 sRef_showAliasInfo (el);
4293 else
4295 sRef_showStateInfo (el);
4298 if (sRef_isValid (e2))
4300 if (sRef_isKept (e2))
4302 sRef_showAliasInfo (e2);
4304 else
4306 sRef_showStateInfo (e2);
4310 /* prevent further errors */
4311 el->defstate = SS_UNKNOWN;
4312 sRef_setAliasKind (el, AK_ERROR, fileloc_undefined);
4313 return FALSE;
4317 return TRUE;
4320 static void
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;
4335 static sRefSet
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);
4357 else
4359 el->deriv = sRef_mergePdefinedDerivs (el->deriv, e2->deriv,
4360 opt, cl, loc);
4363 sRef_mergeStateAux (el, e2, cl, opt, loc, FALSE);
4365 ret = sRefSet_insert (ret, el);
4366 (void) sRefSet_delete (other, e2);
4368 else
4370 if (!opt)
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);
4390 else
4393 ** it's okay --- member is a different equality test
4397 } end_sRefSet_allElements;
4399 sRefSet_free (res);
4400 return (ret);
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 ();
4412 s->kind = SK_CONJ;
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);
4427 else
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));
4439 return s;
4441 else
4443 /*@-exposetrans@*/ return a; /*@=exposetrans@*/
4447 /*@dependent@*/ sRef
4448 sRef_makeUnknown (void)
4450 sRef s = sRef_new ();
4452 s->kind = SK_UNKNOWN;
4453 return s;
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));
4463 s->info->spec = sk;
4464 /*@-dependenttrans@*/
4465 return s;
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);
4482 return srnothing;
4485 sRef
4486 sRef_makeInternalState (void)
4488 if (sRef_isInvalid (srinternal))
4490 srinternal = sRef_makeSpecial (SR_INTERNAL);
4493 return srinternal;
4496 sRef
4497 sRef_makeSpecState (void)
4499 if (sRef_isInvalid (srspec))
4501 srspec = sRef_makeSpecial (SR_SPECSTATE);
4504 return srspec;
4507 sRef
4508 sRef_makeSystemState (void)
4510 if (sRef_isInvalid (srsystem))
4512 srsystem = sRef_makeSpecial (SR_SYSTEM);
4515 return srsystem;
4518 sRef
4519 sRef_makeGlobalMarker (void)
4521 sRef s = sRef_makeSpecial (SR_GLOBALMARKER);
4522 llassert (valueTable_isUndefined (s->state));
4523 s->state = context_createGlobalMarkerValueTable (stateInfo_undefined);
4524 return s;
4527 sRef
4528 sRef_makeResult (ctype c)
4530 sRef s = sRef_newRef ();
4532 s->kind = SK_RESULT;
4533 s->type = c;
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)));
4541 return s;
4545 bool
4546 sRef_isNothing (sRef s)
4548 return (sRef_isKindSpecial (s) && s->info->spec == SR_NOTHING);
4551 bool
4552 sRef_isInternalState (sRef s)
4554 return (sRef_isKindSpecial (s) && s->info->spec == SR_INTERNAL);
4557 bool
4558 sRef_isSpecInternalState (sRef s)
4560 return (sRef_isKindSpecial (s)
4561 && (s->info->spec == SR_INTERNAL || s->info->spec == SR_SPECSTATE));
4564 bool
4565 sRef_isSpecState (sRef s)
4567 return (sRef_isKindSpecial (s) && s->info->spec == SR_SPECSTATE);
4570 bool
4571 sRef_isResult (sRef s)
4573 return (sRef_isReasonable (s) && s->kind == SK_RESULT);
4576 bool
4577 sRef_isSystemState (sRef s)
4579 return (sRef_isKindSpecial (s) && s->info->spec == SR_SYSTEM);
4582 bool
4583 sRef_isGlobalMarker (sRef s)
4585 return (sRef_isKindSpecial (s) && s->info->spec == SR_GLOBALMARKER);
4588 usymId
4589 sRef_getScopeIndex (sRef s)
4591 llassert (sRef_isReasonable (s));
4592 llassert (sRef_isCvar (s));
4594 return (s->info->cvar->index);
4597 void
4598 sRef_makeSafe (sRef s)
4600 if (sRef_isReasonable (s))
4602 s->safe = TRUE;
4606 void
4607 sRef_makeUnsafe (sRef s)
4609 if (sRef_isReasonable (s))
4611 s->safe = FALSE;
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)));
4633 #if 0
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 ;
4648 return st;
4650 #endif
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))))
4691 return YES;
4693 return MAYBE;
4695 else
4697 if (ynm_toBoolStrict (sRef_isWriteable (sRef_getConjB (s))))
4699 return MAYBE;
4701 return NO;
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)
4727 sstate ss;
4729 if (sRef_isInvalid (s)) return YES;
4731 ss = s->defstate;
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))))
4739 return YES;
4741 return MAYBE;
4743 else
4745 if (ynm_toBoolStrict (sRef_isValidLvalue (sRef_getConjB (s))))
4747 return MAYBE;
4749 return NO;
4752 else if (ss == SS_HOFFA)
4754 if (context_getFlag (FLG_STRICTUSERELEASED))
4756 return MAYBE;
4758 else
4760 return YES;
4763 else
4765 return (ynm_fromBool (ss == SS_DEFINED
4766 || ss == SS_FIXED
4767 || ss == SS_RELDEF
4768 || ss == SS_PDEFINED
4769 || ss == SS_PARTIAL
4770 || ss == SS_SPECIAL
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)
4779 ctype ct;
4781 if (depth > MAXDEPTH)
4783 llgenmsg (message
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),
4789 MAXDEPTH),
4790 g_currentloc);
4792 return sRef_undefined;
4795 if (!sRef_isKnown (fref) || sRef_isAnyDefined (fref))
4797 return sRef_undefined;
4800 if (sRef_isUnuseable (fref) || sRef_isStateUndefined (fref))
4802 return 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;
4817 else
4819 sRef fptr = sRef_constructDeref (fref);
4821 return (whatUndefined (fptr, depth + 1));
4824 else if (ctype_isStruct (ct))
4826 if (sRef_isStateUnknown (fref))
4828 return 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);
4841 if (shouldCheck)
4843 sRef wdef = whatUndefined (fldref, depth + 1);
4845 if (sRef_isReasonable (wdef))
4847 return 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)))
4869 ; /* no error */
4871 else
4873 if (shouldCheck)
4875 sRef wdef = whatUndefined (ffield, depth + 1);
4877 if (sRef_isInvalid (wdef))
4879 return wdef;
4883 } end_uentryList_elements;
4885 else
4890 else if (ctype_isUnion (ct))
4894 else
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)));
4906 /*@=temptrans@*/
4909 bool sRef_isReallyDefined (sRef s)
4911 if (sRef_isReasonable (s))
4913 if (sRef_isAnyDefined (s))
4915 return TRUE;
4917 else
4919 if (sRef_isAllocated (s) || sRef_isPdefined (s))
4921 return checkDefined (s);
4923 else
4925 return FALSE;
4929 else
4931 return TRUE;
4935 void sRef_showNotReallyDefined (sRef s)
4937 if (sRef_isReasonable (s))
4939 if (sRef_isAnyDefined (s))
4941 BADBRANCH;
4943 else
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));
4952 if (ref != s)
4954 llgenindentmsgnoloc
4955 (message ("This sub-reference is %s: %q",
4956 sstate_unparse (sRef_getDefState (ref)),
4957 sRef_unparse (ref)));
4960 else
4966 else
4968 BADBRANCH;
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);
5036 else
5038 return XO_UNKNOWN;
5042 exkind sRef_getOrigExKind (sRef s)
5044 if (sRef_isReasonable (s))
5046 return (s->oexpkind);
5048 else
5050 return XO_UNKNOWN;
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);
5088 s->expkind = exp;
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);
5123 else
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;
5168 sRef arr;
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;
5214 else
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);
5233 else
5235 ; /* Nothing to do for structures. */
5240 else
5245 if (clear)
5247 sRef_clearDerived (s);
5249 else
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)
5284 sRefSet aliases;
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)));
5348 return FALSE;
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)
5360 return;
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)
5372 sRef nb;
5374 DPRINTF (("set pdefined: %s", sRef_unparseFull (base)));
5375 base->defstate = SS_PDEFINED;
5376 nb = sRef_getBaseSafe (base);
5377 base = nb;
5379 else
5381 break;
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);
5403 s->defstate = ss;
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)
5414 sRef nb;
5416 DPRINTF (("set pdefined: %s", sRef_unparseFull (s)));
5417 base->defstate = SS_PDEFINED;
5418 nb = sRef_getBaseSafe (base);
5419 base = nb;
5421 else
5423 break;
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);
5493 static
5494 void sRef_setNullStateAux (/*@notnull@*/ sRef s, nstate ns, fileloc loc)
5496 sRef_checkMutable (s);
5497 s->nullstate = ns;
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);
5519 s->nullstate = n;
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);
5533 # ifdef DEADCODE
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);
5540 break;
5541 case BB_POSSIBLYNULLTERMINATED:
5542 sRef_setPossiblyNullTerminatedState(s);
5543 break;
5544 case BB_NOTNULLTERMINATED:
5545 sRef_setNotNullTerminatedState (s);
5546 break;
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);
5563 switch (n)
5565 case NS_POSNULL:
5566 sRef_innerAliasSetComplete (sRef_setPosNull, s, loc);
5567 break;
5568 case NS_DEFNULL:
5569 sRef_innerAliasSetComplete (sRef_setDefNull, s, loc);
5570 break;
5571 case NS_UNKNOWN:
5572 sRef_innerAliasSetComplete (sRef_setNullUnknown, s, loc);
5573 break;
5574 case NS_NOTNULL:
5575 sRef_innerAliasSetComplete (sRef_setNotNull, s, loc);
5576 break;
5577 case NS_MNOTNULL:
5578 sRef_innerAliasSetComplete (sRef_setNotNull, s, loc);
5579 break;
5580 case NS_RELNULL:
5581 sRef_innerAliasSetComplete (sRef_setNullUnknown, s, loc);
5582 break;
5583 case NS_CONSTNULL:
5584 sRef_innerAliasSetComplete (sRef_setDefNull, s, loc);
5585 break;
5586 case NS_ABSNULL:
5587 sRef_innerAliasSetComplete (sRef_setNullUnknown, s, loc);
5588 break;
5589 case NS_ERROR:
5590 sRef_innerAliasSetComplete (sRef_setNullErrorLoc, s, loc);
5591 break;
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);
5680 else
5682 break;
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);
5746 else
5748 break;
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);
5775 else
5777 break;
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);
5804 else
5806 sRef_kill (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)
5832 sRef ret;
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.
5843 inFunction = FALSE;
5844 DPRINTF (("Copying sref: %s", sRef_unparseFull(s)));
5845 ret = sRef_copy (s);
5846 DPRINTF (("Copying ===>: %s", sRef_unparseFull(ret)));
5847 inFunction = old;
5849 else
5851 ret = sRef_undefined;
5854 /*@-dependenttrans@*/
5855 return ret;
5856 /*@=dependenttrans@*/
5859 sRef sRef_copy (sRef s)
5861 if (sRef_isKindSpecial (s) && !sRef_isGlobalMarker (s))
5863 /*@-retalias@*/
5864 return s; /* don't copy specials (except for global markers) */
5865 /*@=retalias@*/
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)));
5875 t->kind = s->kind;
5876 t->safe = s->safe;
5877 t->modified = s->modified;
5878 t->immut = FALSE; /* Note mutability is not copied. */
5879 t->type = s->type;
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)));
5908 return t;
5910 else
5912 return sRef_undefined;
5916 /*@notfunction@*/
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))
5937 sRef tref = s;
5941 sRef lt;
5943 if (sRef_isArrayFetch (tref))
5945 return TRUE;
5948 lt = sRef_getBase (tref);
5949 tref = lt;
5950 } while (sRef_isReasonable (tref));
5953 return FALSE;
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));
5974 return FALSE;
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);
5989 # ifdef DEADCODE
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);
6090 else
6092 return FALSE;
6096 void sRef_free (/*@only@*/ sRef s)
6098 if (s != sRef_undefined && s->kind != SK_SPECIAL)
6100 DPRINTF (("Free sref: [%p]", s));
6102 # if 0
6103 sRef_checkValid (s);
6104 # endif
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);
6117 sinfo_free (s);
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;
6125 sfree (s);
6129 void sRef_setType (sRef s, ctype t)
6131 if (sRef_isReasonable (s))
6133 sRef_checkMutable (s);
6134 s->type = t;
6138 void sRef_setTypeFull (sRef s, ctype t)
6140 if (sRef_isReasonable (s))
6142 sRef_checkMutable (s);
6143 s->type = t;
6145 sRefSet_allElements (s->deriv, current)
6147 sRef_setTypeFull (current, ctype_unknown);
6148 } end_sRefSet_allElements ;
6152 /*@exposed@*/ sRef
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))
6171 return sr;
6175 else
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))
6189 sRefSet ret;
6190 ret = rec->deriv;
6191 return (ret);
6193 else
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)
6208 return sr;
6210 } end_sRefSet_realElements;
6213 return sRef_undefined;
6216 bool
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)
6228 if (isknown)
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))
6237 return sr;
6239 } end_sRefSet_realElements;
6241 else
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))
6255 return sr;
6258 else
6260 return sr;
6263 } end_sRefSet_realElements;
6266 return sRef_undefined;
6269 static /*@exposed@*/ sRef
6270 sRef_buildNCField (/*@exposed@*/ sRef rec, /*@exposed@*/ cstring f)
6272 sRef s;
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))
6290 return s;
6292 else
6294 ctype ct = ctype_realType (rec->type);
6296 DPRINTF (("Field of: %s", sRef_unparse (rec)));
6298 s = sRef_newRef ();
6299 s->kind = SK_FIELD;
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;
6322 else
6324 s->aliaskind = AK_UNKNOWN;
6327 if (sRef_isStateDefined (rec) || sRef_isStateUnknown (rec)
6328 || sRef_isPdefined (rec))
6330 sRef_setStateFromUentry (s, ue);
6332 else
6334 sRef_setPartsFromUentry (s, ue);
6337 s->oaliaskind = s->aliaskind;
6338 s->oexpkind = s->expkind;
6340 DPRINTF (("sref: %s", sRef_unparseFull (s)));
6342 else
6345 Never report this as an error. It can happen whenever there
6346 is casting involved.
6348 if (report)
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;
6374 else
6376 s->defstate = SS_UNDEFINED;
6379 else if (s->defstate == SS_UNKNOWN)
6381 s->defstate = rec->defstate;
6383 else
6385 ; /* no change */
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)));
6408 return s;
6412 bool
6413 sRef_isStackAllocated (sRef s)
6415 return (sRef_isReasonable(s)
6416 && s->defstate == SS_ALLOCATED && ctype_isStackAllocated (s->type));
6419 static
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));
6473 else
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;
6483 else
6485 if (!context_getFlag (FLG_STRICTDESTROY))
6487 s->defstate = SS_PARTIAL;
6489 else
6491 s->defstate = SS_DEFINED;
6495 ** Very weak checking for array elements.
6496 ** Was:
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;
6508 else
6510 s->aliaskind = AK_UNKNOWN;
6513 sRef_setTypeState (s);
6516 else
6518 if (arr->defstate == SS_DEFINED)
6521 ** Very weak checking for array elements.
6522 ** Was:
6523 ** s->defstate = arr->defstate;
6526 if (context_getFlag (FLG_STRICTDESTROY))
6528 s->defstate = SS_DEFINED;
6530 else
6532 s->defstate = SS_PARTIAL;
6535 else if (arr->defstate == SS_ALLOCATED)
6537 if (ctype_isRealArray (s->type))
6539 s->defstate = SS_ALLOCATED;
6541 else
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;
6562 else
6564 if (sr->defstate == SS_DEFINED)
6566 if (context_getFlag (FLG_STRICTDESTROY))
6568 s->defstate = SS_DEFINED;
6570 else
6572 s->defstate = SS_PARTIAL;
6575 break;
6579 else
6581 llcontbug (message ("Invalid sRef as derived element of %s", sRef_unparse (arr)));
6584 } end_sRefSet_allElements;
6586 else
6588 s->defstate = SS_UNDEFINED;
6592 else
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;
6608 else
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)
6625 sRef s;
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)
6643 sRef res;
6644 check (sRefSet_delete (arr->deriv, s));
6645 res = sRef_buildArrayFetch (arr);
6646 sRef_copyState (res, s);
6647 llassert (res->info->arrayfetch->arr == arr);
6648 return res;
6651 s->expkind = sRef_getExKind (arr);
6652 s->expinfo = stateInfo_copy (arr->expinfo);
6654 return s;
6656 else
6658 s = sRef_newRef ();
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));
6683 return (s);
6687 /*@exposed@*/ sRef
6688 sRef_buildArrayFetchKnown (/*@exposed@*/ sRef arr, int i)
6690 sRef s;
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)
6708 sRef res;
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);
6716 return res;
6719 s->expkind = sRef_getExKind (arr);
6720 s->expinfo = stateInfo_copy (arr->expinfo);
6722 llassert (s->info->arrayfetch->arr == arr);
6723 return s;
6725 else
6727 s = sRef_newRef ();
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));
6745 return (s);
6750 ** sets everything except for defstate
6753 static void
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)));
6775 else
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);
6793 static void
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;
6812 void
6813 sRef_setStateFromUentry (sRef s, uentry ue)
6815 sstate defstate;
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;
6828 else
6834 /*@exposed@*/ sRef
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);
6846 else
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;
6860 return s;
6862 else
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;
6876 return s;
6881 /*@exposed@*/ sRef
6882 sRef_constructPointer (/*@exposed@*/ sRef t)
6883 /*@modifies t@*/
6885 return sRef_buildPointer (t);
6888 static /*@exposed@*/ sRef sRef_constructDerefAux (sRef t, bool isdead)
6890 if (sRef_isReasonable (t))
6892 sRef s;
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)));
6903 return s;
6905 else
6907 sRef ret = sRef_constructPointer (t);
6909 DPRINTF (("Constructed pointer: %s", sRef_unparseFull (ret)));
6911 return ret;
6914 else
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);
6930 static sRef
6931 sRef_constructPointerAux (/*@notnull@*/ /*@exposed@*/ sRef t)
6933 sRef s = sRef_newRef ();
6934 ctype rt = t->type;
6935 ctype st;
6937 llassert (valueTable_isUndefined (s->state));
6939 s->kind = SK_PTR;
6940 s->info = (sinfo) dmalloc (sizeof (*s->info));
6941 s->info->ref = t;
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);
6960 else
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;
6970 else
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)));
6989 return s;
6992 bool sRef_hasDerived (sRef s)
6994 return (sRef_isReasonable (s) && !sRefSet_isEmpty (s->deriv));
6997 void
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);
7007 void
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)
7027 /*@modifies s@*/
7029 sRef res = sRef_buildPointer (s);
7031 DPRINTF (("Res: %s", sRef_unparseFull (res)));
7032 return res;
7036 ** &a[] => a (this is for out params)
7039 /*@exposed@*/ sRef
7040 sRef_makeAnyArrayFetch (/*@exposed@*/ sRef arr)
7042 if (sRef_isAddress (arr))
7044 return (arr->info->ref);
7046 else
7048 return (sRef_buildArrayFetch (arr));
7052 /*@exposed@*/ sRef
7053 sRef_makeArrayFetch (/*@exposed@*/ sRef arr)
7055 return (sRef_buildArrayFetch (arr));
7058 /*@exposed@*/ sRef
7059 sRef_makeArrayFetchKnown (/*@exposed@*/ sRef arr, int i)
7061 return (sRef_buildArrayFetchKnown (arr, i));
7064 /*@exposed@*/ sRef
7065 sRef_makeField (sRef rec, /*@dependent@*/ cstring f)
7067 sRef ret;
7068 ret = sRef_buildField (rec, f);
7069 return ret;
7072 /*@exposed@*/ sRef
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)
7081 cstring result;
7083 if (s == sRef_undefined)
7084 return cstring_makeLiteral ("<invalid>");
7086 s = sRef_fixConj (s);
7088 switch (s->kind)
7090 case SK_CVAR:
7091 if (sRef_isLocalVar (s))
7093 result = cstring_makeLiteral ("Variable");
7095 else
7097 result = cstring_makeLiteral (plain ? "Global" : "Undef global");
7099 break;
7100 case SK_PARAM:
7101 result = cstring_makeLiteral (plain ? "Parameter" : "Out parameter");
7102 break;
7103 case SK_ARRAYFETCH:
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");
7112 else
7114 result = cstring_makeLiteral ("Value");
7116 break;
7117 case SK_PTR:
7118 if (sRef_isAnyParam (s->info->ref))
7120 result = cstring_makeLiteral (plain ? "Parameter" : "Out parameter");
7122 else
7124 result = cstring_makeLiteral ("Value");
7126 break;
7127 case SK_ADR:
7128 result = cstring_makeLiteral ("Value");
7129 break;
7130 case SK_FIELD:
7131 result = cstring_makeLiteral ("Field");
7132 break;
7133 case SK_OBJECT:
7134 result = cstring_makeLiteral ("Object");
7135 break;
7136 case SK_UNCONSTRAINED:
7137 result = cstring_makeLiteral ("<anything>");
7138 break;
7139 case SK_RESULT:
7140 case SK_SPECIAL:
7141 case SK_UNKNOWN:
7142 case SK_EXTERNAL:
7143 case SK_DERIVED:
7144 case SK_CONST:
7145 case SK_TYPE:
7146 result = cstring_makeLiteral ("<unknown>");
7147 break;
7148 case SK_CONJ:
7149 result = cstring_makeLiteral ("<conj>");
7150 break;
7151 case SK_NEW:
7152 result = cstring_makeLiteral ("Storage");
7153 break;
7154 default:
7155 return cstring_makeLiteral ("<invalid>");
7158 return result;
7161 /*@only@*/ cstring
7162 sRef_unparseKindName (sRef s)
7164 return sRef_unparseKindNameAux (s, FALSE);
7167 /*@only@*/ cstring
7168 sRef_unparseKindNamePlain (sRef s)
7170 return sRef_unparseKindNameAux (s, TRUE);
7174 ** s1 <- s2
7177 void
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;
7210 sRef
7211 sRef_makeNew (ctype ct, sRef t, cstring name)
7213 sRef s = sRef_newRef ();
7215 s->kind = SK_NEW;
7216 s->type = ct;
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)));
7240 return s;
7243 sRef
7244 sRef_makeType (ctype ct)
7246 sRef s = sRef_newRef ();
7248 sRef_checkMutable (s);
7250 s->kind = SK_TYPE;
7251 s->type = ct;
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)));
7278 return s;
7281 sRef
7282 sRef_makeConst (ctype ct)
7284 sRef s = sRef_newRef ();
7286 s->kind = SK_CONST;
7287 s->type = ct;
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));
7315 return s;
7318 bool sRef_hasName (sRef s)
7320 if (sRef_isInvalid (s))
7322 return (FALSE);
7325 switch (s->kind)
7327 case SK_CVAR:
7329 uentry u = usymtab_getRefQuiet (s->info->cvar->lexlevel,
7330 s->info->cvar->index);
7331 return (uentry_hasName (u));
7333 case SK_PARAM:
7335 if (s->info->paramno >= 0)
7337 uentry u = uentryList_getN (context_getParams (),
7338 s->info->paramno);
7340 return (uentry_hasName (u));
7342 else
7344 llassert (s->info->paramno == PARAMUNKNOWN);
7345 return FALSE;
7348 default:
7349 return TRUE;
7353 bool
7354 sRef_sameName (sRef s1, sRef s2)
7356 if (sRef_isInvalid (s1))
7358 return sRef_isInvalid (s2);
7361 if (sRef_isInvalid (s2))
7363 return (FALSE);
7366 switch (s1->kind)
7368 case SK_CVAR:
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 (),
7383 s2->info->paramno);
7385 return (cstring_equalFree (uentry_getName (u1),
7386 uentry_getName (u2)));
7388 else
7390 return s1->info->paramno == PARAMUNKNOWN;
7393 else
7395 return FALSE;
7398 else
7400 return FALSE;
7402 case SK_PARAM:
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)
7414 return FALSE;
7416 else
7418 uentry u1 = uentryList_getN (context_getParams (),
7419 s1->info->paramno);
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)));
7427 else
7429 return FALSE;
7432 else
7434 return FALSE;
7438 case SK_UNCONSTRAINED:
7439 return FALSE;
7441 case SK_ARRAYFETCH:
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);
7456 return FALSE;
7457 case SK_FIELD:
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);
7468 return FALSE;
7469 case SK_PTR:
7470 case SK_ADR:
7471 case SK_DERIVED:
7472 case SK_EXTERNAL:
7473 if (s2->kind == s1->kind)
7475 return sRef_sameName (s1->info->ref,
7476 s2->info->ref);
7479 return FALSE;
7480 case SK_OBJECT:
7481 return FALSE;
7482 case SK_CONJ:
7483 return sRef_sameName (sRef_getConjA (s1), s2);
7484 case SK_NEW:
7485 return FALSE;
7486 case SK_UNKNOWN:
7487 return (s2->kind == SK_UNKNOWN);
7488 case SK_TYPE:
7489 case SK_CONST:
7490 if (s2->kind == s1->kind)
7492 return (ctype_equal (s1->type, s2->type));
7495 return FALSE;
7496 case SK_SPECIAL:
7497 if (s2->kind == SK_SPECIAL)
7499 return (s1->info->spec == s2->info->spec);
7501 return FALSE;
7502 case SK_RESULT:
7503 return (s2->kind == SK_RESULT);
7504 default:
7505 return FALSE;
7507 BADEXIT;
7510 sRef
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);
7525 return (sr);
7527 else
7529 llcontbug (message ("sRef_fixOuterRef: undefined: %q", sRef_unparseDebug (s)));
7530 return (s);
7534 return (s);
7537 void
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);
7552 void
7553 sRef_resetState (sRef s)
7555 bool changed = FALSE;
7556 if (sRef_isInvalid (s)) return;
7558 if (s->expkind != s->oexpkind)
7560 changed = TRUE;
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))
7574 changed = TRUE;
7575 s->aliaskind = s->oaliaskind;
7578 if (changed)
7580 sRef_clearDerived (s);
7584 void
7585 sRef_resetStateComplete (sRef s)
7587 sRef_innerAliasSetComplete (sRef_resetStateAux, s, fileloc_undefined);
7590 /*@exposed@*/ sRef
7591 sRef_fixBase (/*@returned@*/ sRef s, /*@returned@*/ sRef base)
7593 sRef tmp = sRef_undefined;
7594 sRef ret;
7596 if (sRef_isInvalid (s)) return s;
7597 if (sRef_isInvalid (base)) return base;
7599 switch (s->kind)
7601 case SK_RESULT:
7602 case SK_PARAM:
7603 case SK_CVAR:
7604 ret = base;
7605 break;
7606 case SK_ARRAYFETCH:
7607 tmp = sRef_fixBase (s->info->arrayfetch->arr, base);
7609 if (s->info->arrayfetch->indknown)
7611 ret = sRef_makeArrayFetchKnown (tmp, s->info->arrayfetch->ind);
7613 else
7615 ret = sRef_makeArrayFetch (tmp);
7617 break;
7618 case SK_FIELD:
7619 tmp = sRef_fixBase (s->info->field->rec, base);
7620 ret = sRef_buildNCField (tmp, s->info->field->field);
7621 break;
7622 case SK_PTR:
7623 tmp = sRef_fixBase (s->info->ref, base);
7624 ret = sRef_makePointer (tmp);
7625 break;
7626 case SK_ADR:
7627 tmp = sRef_fixBase (s->info->ref, base);
7628 ret = sRef_makeAddress (tmp);
7629 break;
7630 case SK_CONJ:
7632 sRef tmpb;
7634 tmp = sRef_fixBase (s->info->conj->a, base);
7635 tmpb = sRef_fixBase (s->info->conj->b, base);
7637 ret = sRef_makeConj (tmp, tmpb);
7638 break;
7640 BADDEFAULT;
7643 return ret;
7646 static /*@exposed@*/ sRef
7647 sRef_fixDirectBase (sRef s, sRef base)
7649 sRef ret;
7651 if (sRef_isInvalid (s))
7653 return sRef_undefined;
7656 switch (s->kind)
7658 case SK_ARRAYFETCH:
7659 if (s->info->arrayfetch->indknown)
7661 ret = sRef_makeArrayFetchKnown (base, s->info->arrayfetch->ind);
7663 else
7665 ret = sRef_makeArrayFetch (base);
7667 break;
7668 case SK_FIELD:
7669 ret = sRef_buildNCField (base, s->info->field->field);
7670 break;
7671 case SK_PTR:
7672 ret = sRef_makePointer (base);
7673 break;
7674 case SK_ADR:
7675 ret = sRef_makeAddress (base);
7676 break;
7677 case SK_CONJ:
7679 sRef tmpa, tmpb;
7681 tmpa = sRef_fixDirectBase (s->info->conj->a, base);
7682 tmpb = sRef_fixDirectBase (s->info->conj->b, base);
7684 ret = sRef_makeConj (tmpa, tmpb);
7685 break;
7687 BADDEFAULT;
7690 sRef_copyState (ret, s);
7691 return ret;
7694 bool
7695 sRef_isAllocIndexRef (sRef s)
7697 return (sRef_isArrayFetch (s) && !(s->info->arrayfetch->indknown)
7698 && sRef_isAllocated (s->info->arrayfetch->arr));
7701 void
7702 sRef_showRefLost (sRef s)
7704 if (sRef_hasAliasInfoLoc (s))
7706 llgenindentmsg (cstring_makeLiteral ("Original reference lost"),
7707 sRef_getAliasInfoLoc (s));
7711 void
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)));
7719 } else {
7720 stateInfo_display (s->definfo, message ("Storage %q", sRef_unparseOpt (s)));
7725 void
7726 sRef_showStateInconsistent (sRef s)
7728 if (sRef_hasStateInfoLoc (s))
7730 llgenindentmsg
7731 (message ("Storage %qbecomes inconsistent (released on one branch)",
7732 sRef_unparseOpt (s)),
7733 sRef_getStateInfoLoc (s));
7737 void
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)));
7743 } else {
7744 stateInfo_display (s->definfo, message ("Storage %q", sRef_unparseOpt (s)));
7749 void
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)));
7755 } else {
7756 stateInfo_display (s->expinfo, message ("Storage %q", sRef_unparseOpt (s)));
7761 void
7762 sRef_showMetaStateInfo (sRef s, cstring key)
7764 stateValue val;
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))
7775 llgenindentmsg
7776 (message ("%qbecomes %q", sRef_unparseOpt (s),
7777 stateValue_unparseValue (val, minfo)),
7778 stateValue_getLoc (val));
7782 void
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))
7794 case NS_CONSTNULL:
7796 fileloc loc = sRef_getNullInfoLoc (s);
7798 if (fileloc_isDefined (loc) && !fileloc_isLib (loc))
7800 llgenindentmsg
7801 (message ("Storage %qbecomes null", sRef_unparseOpt (s)),
7802 loc);
7804 break;
7806 case NS_DEFNULL:
7808 fileloc loc = sRef_getNullInfoLoc (s);
7810 if (fileloc_isDefined (loc) && !fileloc_isLib (loc))
7812 llgenindentmsg (message ("Storage %qbecomes null", sRef_unparseOpt (s)),
7813 loc);
7815 break;
7817 case NS_ABSNULL:
7818 case NS_POSNULL:
7819 llgenindentmsg
7820 (message ("Storage %qmay become null", sRef_unparseOpt (s)),
7821 sRef_getNullInfoLoc (s));
7822 break;
7823 case NS_NOTNULL:
7824 case NS_MNOTNULL:
7825 llgenindentmsg
7826 (message ("Storage %qbecomes not null", sRef_unparseOpt (s)),
7827 sRef_getNullInfoLoc (s));
7828 break;
7829 case NS_UNKNOWN:
7830 llgenindentmsg
7831 (message ("Storage %qnull state becomes unknown",
7832 sRef_unparseOpt (s)),
7833 sRef_getNullInfoLoc (s));
7834 break;
7836 case NS_ERROR:
7837 BADBRANCHCONT;
7838 break;
7840 default:
7841 llgenindentmsg
7842 (message ("<error case> Storage %q becomes %s",
7843 sRef_unparse (s),
7844 nstate_unparse (sRef_getNullState (s))),
7845 sRef_getNullInfoLoc (s));
7847 break;
7852 void
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)));
7861 } else {
7862 stateInfo_display (s->aliasinfo, message ("Fresh storage %q", sRef_unparseOpt (s)));
7865 else
7867 if (context_getLocIndentSpaces () == 0) {
7868 stateInfo_display (s->aliasinfo, message (" Storage %q", sRef_unparseOpt (s)));
7869 } else {
7870 stateInfo_display (s->aliasinfo, message ("Storage %q", sRef_unparseOpt (s)));
7876 void
7877 sRef_mergeNullState (sRef s, nstate n)
7879 if (sRef_isReasonable (s))
7881 nstate old;
7883 old = sRef_getNullState (s);
7885 if (n != old && n != NS_UNKNOWN)
7887 sRef_setNullState (s, n, g_currentloc);
7890 else
7892 llbuglit ("sRef_mergeNullState: invalid");
7896 bool
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))
7907 return FALSE;
7909 else
7911 if (ctype_isUser (rct))
7913 uentry ue = usymtab_getTypeEntry (ctype_typeId (rct));
7915 return (nstate_possiblyNull
7916 (sRef_getNullState (uentry_getSref (ue))));
7918 else
7920 return FALSE;
7924 else
7926 return nstate_possiblyNull (sRef_getNullState (s));
7930 return FALSE;
7933 cstring
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"));
7946 else
7948 return (cstring_makeLiteralTemp ("Local"));
7952 cstring
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"));
7965 else
7967 BADEXIT;
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))
7982 return paramsScope;
7984 else
7986 return fileScope;
7990 bool
7991 sRef_isDead (sRef s)
7993 return (sRef_isReasonable (s) && (s)->defstate == SS_DEAD);
7996 bool
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)
8006 return TRUE;
8008 else
8010 return (sRef_isDefinitelyNull (s));
8013 else
8015 return FALSE;
8019 bool
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
8032 || ds == SS_DEAD
8033 || ds == SS_UNUSEABLE
8034 || ds == SS_HOFFA));
8036 else
8038 return FALSE;
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)))
8056 return FALSE;
8058 } end_sRefSet_allElements ;
8060 return TRUE;
8063 return FALSE;
8066 static bool
8067 sRef_isAllocatedStorage (sRef s)
8069 if (sRef_isReasonable (s) && ynm_toBoolStrict (sRef_isValidLvalue (s)))
8071 return (ctype_isVisiblySharable (sRef_getType (s)));
8073 else
8075 return FALSE;
8079 bool
8080 sRef_isUnuseable (sRef s)
8082 return ((sRef_isValid(s)) && ((s)->defstate == SS_UNUSEABLE));
8085 bool
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))
8096 return FALSE;
8098 else
8100 if (ctype_isUser (rct))
8102 uentry ue = usymtab_getTypeEntry (ctype_typeId (rct));
8104 return (nstate_perhapsNull
8105 (sRef_getNullState (uentry_getSref (ue))));
8107 else
8109 return FALSE;
8113 else
8115 return nstate_perhapsNull (sRef_getNullState (s));
8119 return FALSE;
8123 ** definitelyNull --- called when TRUE is good
8126 bool
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
8137 void
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)
8159 case SK_CVAR:
8160 llassert (set->kind == SK_CVAR);
8161 return set;
8163 case SK_PARAM:
8164 llassert (set->kind == guide->kind);
8165 llassert (set->info->paramno == guide->info->paramno);
8166 return set;
8168 case SK_ARRAYFETCH:
8170 if (set->kind == SK_ARRAYFETCH
8171 && (sRef_similar (set->info->arrayfetch->arr,
8172 guide->info->arrayfetch->arr)))
8174 return set;
8176 else
8178 return (sRef_makeAnyArrayFetch
8179 (sRef_getDeriv (set, guide->info->arrayfetch->arr)));
8182 case SK_PTR:
8184 if (set->kind == SK_PTR && sRef_similar (set->info->ref, guide->info->ref))
8186 return set;
8188 else
8190 return (sRef_makePointer (sRef_getDeriv (set, guide->info->ref)));
8193 case SK_FIELD:
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))))
8199 return set;
8201 else
8203 return (sRef_makeField (sRef_getDeriv (set, guide->info->field->rec),
8204 guide->info->field->field));
8206 case SK_ADR:
8208 if ((set->kind == SK_ADR) && sRef_similar (set->info->ref, guide->info->ref))
8210 return set;
8212 else
8214 return (sRef_makeAddress (sRef_getDeriv (set, guide->info->ref)));
8217 case SK_CONJ:
8219 return sRef_undefined;
8221 case SK_RESULT:
8222 case SK_SPECIAL:
8223 case SK_UNCONSTRAINED:
8224 case SK_TYPE:
8225 case SK_CONST:
8226 case SK_NEW:
8227 case SK_UNKNOWN:
8228 case SK_OBJECT:
8229 case SK_DERIVED:
8230 case SK_EXTERNAL:
8231 return sRef_undefined;
8234 BADEXIT;
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)
8249 void
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 */
8260 else
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);
8276 else
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
8291 bool
8292 sRef_aliasCheckSimplePred (sRefTest predf, sRef s)
8295 if ((*predf)(s))
8297 return TRUE;
8299 else
8301 sRefSet aliases;
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
8314 ** a great idea. ;(
8317 if ((*predf)(cref))
8319 DPRINTF (("Checking alias: %s", sRef_unparseFull (cref)));
8320 sRefSet_free (aliases);
8321 return TRUE;
8324 } end_sRefSet_realElements;
8326 sRefSet_free (aliases);
8328 return FALSE;
8331 bool
8332 sRef_aliasCompleteSimplePred (bool (predf) (sRef), sRef s)
8334 sRefSet aliases;
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);
8351 return result;
8354 void
8355 sRef_aliasSetComplete (void (predf) (sRef, fileloc), sRef s, fileloc loc)
8357 sRefSet aliases;
8359 aliases = usymtab_allAliases (s);
8361 DPRINTF (("All aliases: %s --> %s", sRef_unparseFull (s), sRefSet_unparseFull (aliases)));
8363 (*predf)(s, loc);
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);
8380 void
8381 sRef_aliasSetCompleteParam (void (predf) (sRef, int, fileloc), sRef s,
8382 int kind, fileloc loc)
8384 sRefSet aliases;
8386 if (sRef_isDeep (s))
8388 aliases = usymtab_allAliases (s);
8390 else
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
8413 void
8414 sRef_aliasSetCompleteAlkParam (void (predf) (sRef, alkind, fileloc), sRef s,
8415 alkind kind, fileloc loc)
8417 sRefSet aliases;
8419 if (sRef_isDeep (s))
8421 aliases = usymtab_allAliases (s);
8423 else
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);
8442 static void
8443 sRef_innerAliasSetComplete (void (predf) (sRef, fileloc), sRef s, fileloc loc)
8445 sRef inner;
8446 sRefSet aliases;
8447 ctype ct;
8449 if (!sRef_isReasonable (s)) return;
8452 ** Type equivalence checking is necessary --- there might be casting.
8455 (*predf)(s, loc);
8457 switch (s->kind)
8459 case SK_UNCONSTRAINED:
8460 case SK_CVAR:
8461 case SK_PARAM:
8462 break;
8463 case SK_PTR:
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);
8483 break;
8484 case SK_ARRAYFETCH:
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));
8510 else
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));
8521 else
8523 DPRINTF (("Type mismatch: %s / %s",
8524 ctype_unparse (ct),
8525 ctype_unparse (sRef_getType (current))));
8528 } end_sRefSet_realElements;
8530 sRefSet_free (aliases);
8531 break;
8532 case SK_FIELD:
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);
8547 ((*predf)(f, loc));
8550 } end_sRefSet_realElements;
8552 sRefSet_free (aliases);
8553 break;
8554 case SK_CONJ:
8555 sRef_innerAliasSetComplete (predf, s->info->conj->a, loc);
8556 sRef_innerAliasSetComplete (predf, s->info->conj->b, loc);
8557 break;
8558 case SK_SPECIAL:
8559 case SK_ADR:
8560 case SK_TYPE:
8561 case SK_CONST:
8562 case SK_NEW:
8563 case SK_UNKNOWN:
8564 case SK_OBJECT:
8565 case SK_DERIVED:
8566 case SK_EXTERNAL:
8567 case SK_RESULT:
8568 break;
8572 static void
8573 sRef_innerAliasSetCompleteParam (void (predf) (sRef, sRef), sRef s, sRef t)
8575 sRef inner;
8576 sRefSet aliases;
8577 ctype ct;
8579 if (!sRef_isReasonable (s)) return;
8582 ** Type equivalence checking is necessary --- there might be casting.
8585 (*predf)(s, t);
8587 switch (s->kind)
8589 case SK_UNCONSTRAINED:
8590 case SK_CVAR:
8591 case SK_PARAM:
8592 break;
8593 case SK_PTR:
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);
8608 ((*predf)(ptr, t));
8611 } end_sRefSet_realElements;
8613 sRefSet_free (aliases);
8614 break;
8615 case SK_ARRAYFETCH:
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);
8633 ((*predf)(af, t));
8635 else
8637 sRef af = sRef_makeArrayFetch (current);
8639 ((*predf)(af, t));
8643 } end_sRefSet_realElements;
8645 sRefSet_free (aliases);
8646 break;
8647 case SK_FIELD:
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);
8662 ((*predf)(f, t));
8665 } end_sRefSet_realElements;
8667 sRefSet_free (aliases);
8668 break;
8669 case SK_CONJ:
8670 sRef_innerAliasSetCompleteParam (predf, s->info->conj->a, t);
8671 sRef_innerAliasSetCompleteParam (predf, s->info->conj->b, t);
8672 break;
8673 case SK_SPECIAL:
8674 case SK_ADR:
8675 case SK_TYPE:
8676 case SK_CONST:
8677 case SK_NEW:
8678 case SK_UNKNOWN:
8679 case SK_OBJECT:
8680 case SK_DERIVED:
8681 case SK_EXTERNAL:
8682 case SK_RESULT:
8683 break;
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);
8699 res->expkind = a2;
8701 else
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.
8713 static void
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;
8731 else
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;
8747 else
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;
8770 else
8772 hasError = TRUE;
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;
8789 else
8791 hasError = TRUE;
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);
8821 else
8823 hasError = TRUE;
8826 if (hasError)
8828 if (sRef_isThroughArrayFetch (res))
8830 if (optgenerror2
8831 (FLG_BRANCHSTATE, FLG_STRICTBRANCHSTATE,
8832 message
8833 ("Clauses exit with %q possibly referencing %s storage %s, "
8834 "%s storage %s",
8835 sRef_unparse (res),
8836 alkind_unparse (aother),
8837 clause_nameTaken (cl),
8838 alkind_unparse (ares),
8839 clause_nameAlternate (cl)),
8840 loc))
8842 sRef_showAliasInfo (res);
8843 sRef_showAliasInfo (other);
8844 res->aliaskind = AK_ERROR;
8846 else
8848 if (ares == AK_KEPT || aother == AK_KEPT)
8850 sRef_maybeKill (res, loc);
8854 else
8856 if (optgenerror
8857 (FLG_BRANCHSTATE,
8858 message ("Clauses exit with %q referencing %s storage %s, "
8859 "%s storage %s",
8860 sRef_unparse (res),
8861 alkind_unparse (aother),
8862 clause_nameTaken (cl),
8863 alkind_unparse (ares),
8864 clause_nameAlternate (cl)),
8865 loc))
8867 sRef_showAliasInfo (res);
8868 sRef_showAliasInfo (other);
8870 res->aliaskind = AK_ERROR;
8874 res->aliaskind = (sRef_isLocalVar (res) ? AK_LOCAL : AK_UNKNOWN);
8878 static void
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
8985 ** this is bogus!
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;
9004 else
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;
9015 bool flip = FALSE;
9017 sRef_checkMutable (res);
9019 if (s1 == s2 || s2 == SS_UNKNOWN)
9023 else if (s1 == SS_UNKNOWN)
9025 flip = TRUE;
9027 else
9029 switch (s1)
9031 case SS_FIXED:
9032 if (s2 == SS_DEFINED)
9034 break;
9036 else
9038 llcontbuglit ("ssfixed: not implemented");
9039 flip = TRUE;
9041 break;
9042 case SS_DEFINED:
9043 flip = TRUE;
9044 break;
9045 case SS_PDEFINED:
9046 case SS_ALLOCATED:
9047 flip = (s2 != SS_DEFINED);
9048 break;
9049 case SS_HOFFA:
9050 case SS_RELDEF:
9051 case SS_UNUSEABLE:
9052 case SS_UNDEFINED:
9053 case SS_PARTIAL:
9054 case SS_UNDEFGLOB:
9055 case SS_KILLED:
9056 case SS_DEAD:
9057 case SS_SPECIAL:
9058 break;
9059 BADDEFAULT;
9063 if (flip)
9065 res->definfo = stateInfo_update (res->definfo, other->definfo);
9066 res->defstate = s2;
9070 extern /*@notnull@*/ sRef sRef_getConjA (sRef s)
9072 sRef ret;
9073 llassert (sRef_isConj (s));
9075 ret = s->info->conj->a;
9076 llassert (ret != NULL);
9077 return ret;
9080 extern /*@notnull@*/ sRef sRef_getConjB (sRef s)
9082 sRef ret;
9083 llassert (sRef_isConj (s));
9085 ret = s->info->conj->b;
9086 llassert (ret != NULL);
9087 return ret;
9090 extern /*@exposed@*/ sRef sRef_makeArrow (sRef s, /*@dependent@*/ cstring f)
9092 sRef p;
9093 sRef ret;
9095 p = sRef_makePointer (s);
9096 ret = sRef_makeField (p, f);
9097 DPRINTF (("Arrow: %s => %s",
9098 sRef_unparseFull (s), sRef_unparseFull (ret)));
9099 return ret;
9102 extern /*@exposed@*/ sRef sRef_buildArrow (sRef s, cstring f)
9104 sRef p;
9105 sRef ret;
9107 p = sRef_buildPointer (s);
9108 ret = sRef_buildField (p, f);
9110 return ret;
9113 static /*@null@*/ sinfo sinfo_copy (/*@notnull@*/ sRef s)
9115 sinfo ret;
9117 switch (s->kind)
9119 case SK_CVAR:
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;
9124 break;
9126 case SK_PARAM:
9127 ret = (sinfo) dmalloc (sizeof (*ret));
9128 ret->paramno = s->info->paramno;
9129 llassert (ret->paramno >= -1);
9130 break;
9132 case SK_ARRAYFETCH:
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;
9138 break;
9140 case SK_FIELD:
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;
9145 break;
9147 case SK_OBJECT:
9148 ret = (sinfo) dmalloc (sizeof (*ret));
9149 ret->object = s->info->object;
9150 break;
9152 case SK_PTR:
9153 case SK_ADR:
9154 case SK_DERIVED:
9155 case SK_EXTERNAL:
9156 ret = (sinfo) dmalloc (sizeof (*ret));
9157 ret->ref = s->info->ref; /* Ref_copy (s->info->ref); */
9158 break;
9160 case SK_CONJ:
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);*/
9165 break;
9166 case SK_SPECIAL:
9167 ret = (sinfo) dmalloc (sizeof (*ret));
9168 ret->spec = s->info->spec;
9169 break;
9171 case SK_UNCONSTRAINED:
9172 case SK_NEW:
9173 ret = (sinfo) dmalloc (sizeof (*ret));
9174 ret->fname = s->info->fname;
9175 break;
9177 default:
9178 llassertprint (s->info == NULL, ("s = %s", sRef_unparse (s)));
9179 ret = NULL;
9180 break;
9183 return ret;
9186 static /*@null@*/ sinfo sinfo_fullCopy (/*@notnull@*/ sRef s)
9188 sinfo ret;
9191 ** Since its a full copy, only storage is assigned
9192 ** to dependent fields.
9194 /*@-onlytrans@*/
9196 switch (s->kind)
9198 case SK_CVAR:
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;
9203 break;
9205 case SK_PARAM:
9206 ret = (sinfo) dmalloc (sizeof (*ret));
9207 ret->paramno = s->info->paramno;
9208 llassert (ret->paramno >= -1);
9209 break;
9211 case SK_ARRAYFETCH:
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);
9217 break;
9219 case SK_FIELD:
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;
9224 break;
9226 case SK_OBJECT:
9227 ret = (sinfo) dmalloc (sizeof (*ret));
9228 ret->object = s->info->object;
9229 break;
9231 case SK_PTR:
9232 case SK_ADR:
9233 case SK_DERIVED:
9234 case SK_EXTERNAL:
9235 ret = (sinfo) dmalloc (sizeof (*ret));
9236 ret->ref = sRef_saveCopy (s->info->ref);
9237 break;
9239 case SK_CONJ:
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);
9244 break;
9245 case SK_SPECIAL:
9246 ret = (sinfo) dmalloc (sizeof (*ret));
9247 ret->spec = s->info->spec;
9248 break;
9249 case SK_NEW:
9250 case SK_UNCONSTRAINED:
9251 ret = (sinfo) dmalloc (sizeof (*ret));
9252 ret->fname = s->info->fname;
9253 break;
9254 default:
9255 llassert (s->info == NULL);
9256 ret = NULL;
9257 break;
9259 /*@=onlytrans@*/
9260 return ret;
9264 static void
9265 sinfo_update (/*@notnull@*/ /*@exposed@*/ sRef res,
9266 /*@notnull@*/ /*@exposed@*/ sRef other)
9268 llassert (res->kind == other->kind);
9270 switch (res->kind)
9272 case SK_CVAR:
9273 res->info->cvar->lexlevel = other->info->cvar->lexlevel;
9274 res->info->cvar->index = other->info->cvar->index;
9275 break;
9277 case SK_PARAM:
9278 res->info->paramno = other->info->paramno;
9279 llassert (res->info->paramno >= -1);
9280 break;
9282 case SK_ARRAYFETCH:
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;
9286 break;
9288 case SK_FIELD:
9289 res->info->field->rec = other->info->field->rec;
9290 res->info->field->field = other->info->field->field;
9291 break;
9293 case SK_OBJECT:
9294 res->info->object = other->info->object;
9295 break;
9297 case SK_PTR:
9298 case SK_ADR:
9299 case SK_DERIVED:
9300 case SK_EXTERNAL:
9301 res->info->ref = other->info->ref;
9302 break;
9304 case SK_CONJ:
9305 res->info->conj->a = other->info->conj->a;
9306 res->info->conj->b = other->info->conj->b;
9307 break;
9309 case SK_SPECIAL:
9310 res->info->spec = other->info->spec;
9311 break;
9313 case SK_NEW:
9314 case SK_UNCONSTRAINED:
9315 res->info->fname = other->info->fname;
9316 break;
9318 default:
9319 llassert (res->info == NULL);
9320 break;
9324 static void sinfo_free (/*@special@*/ /*@temp@*/ /*@notnull@*/ sRef s)
9325 /*@uses s->kind, s->info@*/
9326 /*@releases s->info@*/
9328 switch (s->kind)
9330 case SK_CVAR:
9331 DPRINTF (("Free sinfo: [%p]", s->info->cvar));
9332 sfree (s->info->cvar);
9333 break;
9335 case SK_PARAM:
9336 break;
9338 case SK_ARRAYFETCH:
9339 DPRINTF (("Free sinfo: [%p]", s->info->arrayfetch));
9340 sfree (s->info->arrayfetch);
9341 break;
9343 case SK_FIELD:
9344 DPRINTF (("Free sinfo: [%p]", s->info->field));
9345 sfree (s->info->field);
9346 break;
9348 case SK_OBJECT:
9349 break;
9351 case SK_PTR:
9352 case SK_ADR:
9353 case SK_DERIVED:
9354 case SK_EXTERNAL: /* is copy now! */
9355 break;
9357 case SK_CONJ:
9358 DPRINTF (("Free sinfo: [%p]", s->info->conj));
9359 sfree (s->info->conj);
9360 break;
9362 default:
9363 break;
9366 if (s->info != NULL) {
9367 DPRINTF (("Free sinfo: [%p]", s->info));
9370 sfree (s->info);
9373 bool sRef_isNSLocalVar (sRef s)
9375 if (sRef_isLocalVar (s))
9377 uentry ue = sRef_getUentry (s);
9379 return (!uentry_isStatic (ue));
9381 else
9383 return FALSE;
9387 bool sRef_isLocalVar (sRef s)
9389 if (sRef_isValid(s))
9391 return (s->kind == SK_CVAR
9392 && (s->info->cvar->lexlevel > fileScope));
9395 return FALSE;
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))
9411 return FALSE;
9413 else
9415 return TRUE;
9418 else
9420 return (s->info->cvar->lexlevel > functionScope);
9425 return FALSE;
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)));
9437 return FALSE;
9440 static speckind speckind_fromInt (int i)
9442 /*@+enumint@*/
9443 llassert (i >= SR_NOTHING && i <= SR_SYSTEM);
9444 /*@=enumint@*/
9446 return ((speckind) i);
9450 static void sRef_updateNullState (/*@notnull@*/ sRef res, /*@notnull@*/ sRef other)
9451 /*@modifies res@*/
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);
9463 bool flip = FALSE;
9464 nstate nn = n1;
9466 if (n1 == n2 || n2 == NS_UNKNOWN)
9470 else
9472 /* note: n2 is not unknown or defnull */
9474 switch (n1)
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;
9481 case NS_NOTNULL:
9482 if (n2 == NS_MNOTNULL)
9486 else
9488 flip = TRUE;
9489 nn = NS_POSNULL;
9491 break;
9492 case NS_MNOTNULL:
9493 if (n2 == NS_NOTNULL)
9495 nn = NS_NOTNULL;
9497 else
9499 flip = TRUE;
9500 nn = NS_POSNULL;
9502 break;
9503 case NS_CONSTNULL:
9504 case NS_ABSNULL:
9505 flip = TRUE;
9506 nn = n2;
9510 if (flip)
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))
9526 case NS_DEFNULL:
9527 case NS_CONSTNULL:
9528 return (cstring_makeLiteralTemp ("null"));
9529 default:
9530 return (cstring_makeLiteralTemp ("possibly null"));
9534 # ifdef DEADCODE
9535 /*@observer@*/ cstring sRef_ntMessage (sRef s)
9537 llassert (sRef_isReasonable (s));
9539 switch (s->nullstate)
9541 case NS_DEFNULL:
9542 case NS_CONSTNULL:
9543 return (cstring_makeLiteralTemp ("not nullterminated"));
9544 default:
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;
9554 sRef ret;
9556 llassert (sRef_isReasonable (s));
9558 switch (s->kind)
9560 case SK_RESULT:
9561 s->type = typ;
9562 ret = s;
9563 break;
9564 case SK_ARRAYFETCH:
9566 ctype ct;
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))
9577 else
9579 voptgenerror
9580 (FLG_TYPE,
9581 message
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);
9594 else
9596 ret = sRef_makeArrayFetch (tmp);
9599 break;
9600 case SK_FIELD:
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)))
9614 else
9616 voptgenerror
9617 (FLG_TYPE,
9618 message
9619 ("Special clause accesses non-existent field of result: %q.%s",
9620 sRef_unparse (rec), s->info->field->field),
9621 uentry_whereLast (ue));
9624 else
9626 voptgenerror
9627 (FLG_TYPE,
9628 message
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);
9636 break;
9638 case SK_PTR:
9640 ctype ct;
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))
9651 else
9653 voptgenerror
9654 (FLG_TYPE,
9655 message
9656 ("Special clause dereferences non-pointer (%t): *%q",
9657 ct, sRef_unparse (s->info->ref)),
9658 uentry_whereLast (ue));
9662 ret = sRef_makePointer (tmp);
9663 break;
9665 case SK_ADR:
9666 voptgenerror
9667 (FLG_TYPE,
9668 message
9669 ("Special clause uses & operator (not allowed): &%q", sRef_unparse (s->info->ref)),
9670 uentry_whereLast (ue));
9671 ret = s;
9672 break;
9673 BADDEFAULT;
9676 return ret;
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));
9699 # ifdef DEADCODE
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;
9765 return AK_ERROR;
9768 nstate sRef_getNullState (sRef s)
9770 if (sRef_isReasonable (s)) {
9771 llassert (nstate_isValid (s->nullstate));
9772 return s->nullstate;
9775 return NS_UNKNOWN;
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);
9785 valueTable_insert
9786 (s->state,
9787 cstring_copy (metaStateInfo_getName (annotationInfo_getState (a))),
9788 stateValue_create (annotationInfo_getValue (a),
9789 stateInfo_makeLoc (loc, SA_DECLARED)));
9791 else
9793 DPRINTF (("reflect loc: %s", fileloc_unparse (loc)));
9794 valueTable_update
9795 (s->state,
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)));
9838 else
9840 DPRINTF (("Updating state: %s: %s %d / %s", sRef_unparse (s), key, value,
9841 fileloc_unparse (loc)));
9842 if (valueTable_contains (s->state, key))
9844 valueTable_update
9845 (s->state, key, stateValue_create (value,
9846 stateInfo_makeLoc (loc, SA_CHANGED)));
9848 else
9850 valueTable_insert
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))
9866 stateValue val;
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);
9875 else
9877 return TRUE;
9880 else
9882 return TRUE;
9886 /*@observer@*/ stateValue sRef_getMetaStateValue (sRef s, cstring key)
9888 if (sRef_isReasonable (s))
9890 if (valueTable_isDefined (s->state))
9892 stateValue val;
9894 val = valueTable_lookup (s->state, key);
9895 /* Okay if its not defined, just returns stateValue_undefined */
9896 return val;
9898 else
9900 return stateValue_undefined;
9903 else
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)));
9917 return s->state;
9919 else
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)));
9939 return TRUE;
9941 else
9943 /* s->aliaskind = AK_IMPTEMP; */
9944 s->defstate = SS_SPECIAL;
9945 return FALSE;
9949 void sRef_markImmutable (sRef s)
9951 if (sRef_isReasonable (s))
9953 DPRINTF (("Mark immutable: %s", sRef_unparseFull (s)));
9954 s->immut = TRUE;
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));
9971 # ifdef DEADCODE
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;
9988 } else {
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;
9997 } else {
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;
10005 } else {
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;
10015 else
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;
10027 else
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;
10038 else
10040 llfatalbug (message ("sRef_setLen passed an invalid sRef\n"));
10044 /*drl7x 11/28/2000 */
10046 bool sRef_isFixedArray (sRef p_s) /*@*/ {
10047 ctype c;
10048 c = sRef_getType (p_s);
10049 return ( ctype_isFixedArray (c) );
10052 size_t sRef_getArraySize (sRef p_s) /*@*/
10054 ctype c;
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)));
10068 return;
10071 multiVal_free (s->val);
10072 s->val = 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))
10085 return s->val;
10088 return multiVal_undefined;