]> andersk Git - splint.git/blob - src/sRef.c
Temporarily set flags to splintme without warnings.
[splint.git] / src / sRef.c
1 /*
2 ** Splint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2002 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.
19 **
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
23 */
24 /*
25 ** storeRef.c
26 **
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.
32 **
33 **    storeRefs in the file and global scopes are free'd by the uentry.
34 **
35 */
36
37 # include "splintMacros.nf"
38 # include "basic.h"
39 # include "exprChecks.h"
40 # include "transferChecks.h"
41 # include "sRefTable.h"
42 # include "structNames.h"
43
44 /*
45 ** Predicate functions that evaluate both arguments in order.
46 */
47
48 /*@notfunction@*/
49 # define OR(a,b)  (a ? (b, TRUE) : b)
50
51 /*@notfunction@*/
52 # define AND(a,b) (a ? b : (b, FALSE))
53
54 static void sRef_checkValidAux (sRef p_s, sRefSet p_checkedsofar) /*@modifies p_checkedsofar@*/ ;
55
56 static bool sRef_isDerived (sRef p_s) /*@*/ ;
57
58 static /*@exposed@*/ sRef sRef_fixDirectBase (sRef p_s, sRef p_base) 
59    /*@modifies p_base@*/ ;
60
61 static void sRef_updateNullState (sRef p_res, sRef p_other) /*@modifies p_res@*/ ;
62
63 static bool sRef_isAllocatedStorage (sRef p_s) /*@*/ ;
64 static void sRef_setNullErrorLoc (sRef p_s, fileloc) /*@*/ ;
65 static void sRef_setNullStateN (sRef p_s, nstate p_n) /*@modifies p_s@*/ ;
66
67 static int sRef_depth (sRef p_s) /*@*/ ;
68
69 static void
70   sRef_innerAliasSetComplete (void (p_predf) (sRef, fileloc), sRef p_s, 
71                               fileloc p_loc)
72   /*@modifies p_s@*/ ;
73
74 static void
75 sRef_innerAliasSetCompleteParam (void (p_predf) (sRef, sRef), sRef p_s, sRef p_t)
76      /*@modifies p_s@*/ ;
77      
78 static speckind speckind_fromInt (int p_i);
79 static bool sRef_equivalent (sRef p_s1, sRef p_s2);
80 static bool sRef_isDeepUnionField (sRef p_s);
81 static void sRef_addDeriv (/*@notnull@*/ sRef p_s, /*@notnull@*/ /*@exposed@*/ sRef p_t);
82 static bool sRef_checkModify (sRef p_s, sRefSet p_sl) /*@*/ ;
83
84 /*
85 ** If s is definitely null, it has no memory state.
86 */
87
88 static void sRef_resetAliasKind (/*@notnull@*/ sRef s) /*@modifies s->aliaskind@*/
89 {
90   if (s->nullstate == NS_DEFNULL)
91     {
92       /* s->aliaskind = AK_ERROR; */
93     }
94 }
95
96 static void sRef_checkMutable (/*@unused@*/ sRef s)
97 {
98   /*@i235@*/
99   if (sRef_isValid (s) && s->immut)
100     {
101       llcontbug (message ("Modification to sRef marked immutable: %q", 
102                           sRef_unparseFull (s)));
103     }
104 }
105
106 static bool skind_isSimple (skind sk)
107 {
108   switch (sk)
109     {
110     case SK_PARAM: case SK_CVAR: case SK_CONST:
111     case SK_OBJECT: case SK_UNKNOWN: case SK_NEW:
112       return TRUE;
113     default:
114       return FALSE;
115     }
116 }
117
118 static void sinfo_free (/*@special@*/ /*@temp@*/ /*@notnull@*/ sRef p_s)
119    /*@uses p_s->kind, p_s->info@*/
120    /*@releases p_s->info@*/ ;
121
122 static /*@null@*/ sinfo sinfo_copy (/*@notnull@*/ sRef p_s) /*@*/ ;
123 static void sRef_setPartsFromUentry (sRef p_s, uentry p_ue)
124    /*@modifies p_s@*/ ;
125 static bool checkDeadState (/*@notnull@*/ sRef p_el, bool p_tbranch, fileloc p_loc);
126 static /*@dependent@*/ sRef sRef_constructPointerAux (/*@notnull@*/ /*@exposed@*/ sRef p_t) /*@*/ ;
127
128 static void 
129   sRef_combineExKinds (/*@notnull@*/ sRef p_res, /*@notnull@*/ sRef p_other)
130   /*@modifies p_res@*/ ;
131
132 static void 
133   sRef_combineAliasKinds (/*@notnull@*/ sRef p_res, /*@notnull@*/ sRef p_other, 
134                           clause p_cl, fileloc p_loc)
135   /*@modifies p_res@*/ ;
136
137 static void
138   sRef_combineNullState (/*@notnull@*/ sRef p_res, /*@notnull@*/ sRef p_other)
139   /*@modifies p_res@*/ ;
140
141 static void
142   sRef_combineDefState (/*@notnull@*/ sRef p_res, /*@notnull@*/ sRef p_other)
143   /*@modifies p_res@*/ ;
144
145 static void sRef_setStateFromAbstractUentry (sRef p_s, uentry p_ue) 
146   /*@modifies p_s@*/ ;
147
148 static void 
149   sinfo_update (/*@notnull@*/ /*@exposed@*/ sRef p_res, 
150                 /*@notnull@*/ /*@exposed@*/ sRef p_other);
151 static void sRef_setDefinedAux (sRef p_s, fileloc p_loc, bool p_clear)
152    /*@modifies p_s@*/ ;
153 static void sRef_setDefinedNoClear (sRef p_s, fileloc p_loc)
154    /*@modifies p_s@*/ ;
155 static void sRef_setStateAux (sRef p_s, sstate p_ss, fileloc p_loc)
156    /*@modifies p_s@*/;
157
158 static /*@exposed@*/ sRef 
159   sRef_buildNCField (/*@exposed@*/ sRef p_rec, /*@exposed@*/ cstring p_f);
160
161 static void 
162   sRef_mergeStateAux (/*@notnull@*/ sRef p_res, /*@notnull@*/ sRef p_other, 
163                       clause p_cl, bool p_opt, fileloc p_loc,
164                       bool p_doDerivs)
165   /*@modifies p_res, p_other@*/ ;
166
167 static /*@null@*/ sinfo sinfo_fullCopy (/*@notnull@*/ sRef p_s);
168 static bool sRef_doModify (sRef p_s, sRefSet p_sl) /*@modifies p_s@*/ ;
169 static bool sRef_doModifyVal (sRef p_s, sRefSet p_sl) /*@modifies p_s@*/;
170 static bool sRef_checkModifyVal (sRef p_s, sRefSet p_sl) /*@*/ ;
171
172 static /*@only@*/ sRefSet
173   sRef_mergeDerivs (/*@only@*/ sRefSet p_res, sRefSet p_other, 
174                     bool p_opt, clause p_cl, fileloc p_loc);
175
176 static /*@only@*/ sRefSet
177   sRef_mergeUnionDerivs (/*@only@*/ sRefSet p_res, 
178                          /*@exposed@*/ sRefSet p_other,
179                          bool p_opt, clause p_cl, fileloc p_loc);
180
181 static /*@only@*/ sRefSet 
182   sRef_mergePdefinedDerivs (/*@only@*/ sRefSet p_res, sRefSet p_other, bool p_opt,
183                             clause p_cl, fileloc p_loc);
184
185 static /*@only@*/ cstring sRef_unparseWithArgs (sRef p_s, uentryList p_args);
186 static /*@only@*/ cstring sRef_unparseNoArgs (sRef p_s);
187
188 static /*@exposed@*/ sRef sRef_findDerivedPointer (sRef p_s);
189 static /*@exposed@*/ sRef sRef_findDerivedArrayFetch (/*@notnull@*/ sRef, bool, int, bool) ;
190 static /*@exposed@*/ sRef sRef_findDerivedField (/*@notnull@*/ sRef p_rec, cstring p_f);
191 static /*@exposed@*/ sRef
192   sRef_getDeriv (/*@notnull@*/ /*@returned@*/ sRef p_set, sRef p_guide);
193
194 static bool inFunction = FALSE;
195 static /*@only@*/ sRefTable allRefs;
196
197 /* # define DEBUGREFS  */
198
199 # ifdef DEBUGREFS
200 static nsrefs = 0;
201 static totnsrefs = 0;
202 static maxnsrefs = 0;
203 static ntotrefers = 0;
204 static nrefers = 0;
205 # endif
206
207 static /*@checked@*/ bool protectDerivs = FALSE;
208
209 /*
210 ** Result of sRef_alloc is dependent since allRefs may
211 ** reference it.  It is only if !inFunction.
212 */
213
214 static /*@dependent@*/ /*@out@*/ /*@notnull@*/ sRef
215 sRef_alloc (void)
216 {
217   sRef s = (sRef) dmalloc (sizeof (*s));
218
219   s->immut = FALSE;
220
221   DPRINTF (("Alloc sref: [%p]", s));
222
223   if (inFunction)
224     {
225       allRefs = sRefTable_add (allRefs, s);
226       /*@-branchstate@*/ 
227     }
228   else
229     {
230       DPRINTF (("Not in function!"));
231     }
232
233   /*@=branchstate@*/
234
235 # ifdef DEBUGREFS
236   if (nsrefs >= maxnsrefs)
237     {
238       maxnsrefs = nsrefs;
239     }
240
241   totnsrefs++;
242   nsrefs++;
243 # endif
244
245   /*@-mustfree@*/ /*@-freshtrans@*/
246   return s;
247   /*@=mustfree@*/ /*@=freshtrans@*/
248 }
249
250 static void sRef_checkValidAux (sRef s, sRefSet checkedsofar)
251 {
252   llassert (FALSE);
253
254   if (!sRef_isValid (s)) return;
255
256   if (sRefSet_containsSameObject (checkedsofar, s))
257     {
258       return;
259     }
260
261   /*@-temptrans@*/
262   checkedsofar = sRefSet_insert (checkedsofar, s);
263   /*@=temptrans@*/ /* checksofar will be destroyed before checkValid returns */
264
265   switch (s->kind)
266     {
267     case SK_UNCONSTRAINED:
268       llassert (cstring_length (s->info->fname) < 100);
269       break;
270
271     case SK_CVAR:
272       llassert (s->info->cvar->lexlevel >= 0);
273       /* llassert (s->info->cvar->lexlevel <= usymtab_getCurrentDepth ()); */
274       break;
275
276     case SK_PARAM:
277       llassert (s->info->paramno >= -1);
278       llassert (s->info->paramno <= 50); /*@i32 bogus...*/
279       break;
280
281     case SK_ARRAYFETCH:
282       sRef_checkValidAux (s->info->arrayfetch->arr, checkedsofar);
283       break;
284
285     case SK_FIELD:
286       sRef_checkValidAux (s->info->field->rec, checkedsofar);
287       llassert (cstring_length (s->info->field->field) < 100);
288       break;
289
290     case SK_PTR:
291       sRef_checkValidAux (s->info->ref, checkedsofar);
292       break;
293  
294    case SK_ADR:
295       sRef_checkValidAux (s->info->ref, checkedsofar);
296       break;
297
298     case SK_OBJECT:
299       /* check ctype s->info->object */
300       break;
301
302     case SK_CONJ:
303       sRef_checkValidAux (s->info->conj->a, checkedsofar);
304       sRef_checkValidAux (s->info->conj->b, checkedsofar);
305       break;
306
307     case SK_NEW:
308       llassert (cstring_length (s->info->fname) < 100);
309       break;
310
311     case SK_DERIVED:
312       sRef_checkValidAux (s->info->ref, checkedsofar);
313       break;
314
315     case SK_EXTERNAL:
316       sRef_checkValidAux (s->info->ref, checkedsofar);
317       break;
318
319     case SK_TYPE:
320     case SK_CONST:
321     case SK_RESULT:
322       /* check ctyp s->type */
323       break;
324
325     case SK_SPECIAL:
326       llassert (s->info->spec == SR_NOTHING 
327                 || s->info->spec == SR_INTERNAL
328                 || s->info->spec == SR_SPECSTATE 
329                 || s->info->spec == SR_SYSTEM);
330       break;
331
332     case SK_UNKNOWN:
333       break;
334
335       BADDEFAULT;
336     }
337   
338
339   sRefSet_elements (s->deriv, el)
340     {
341       sRef_checkValidAux (el, checkedsofar);
342     } end_sRefSet_elements ;
343 }
344
345 void sRef_checkValid (/*@unused@*/ sRef s)
346 {
347   return;
348   /*
349   sRefSet checkedsofar = sRefSet_new ();
350   sRef_checkValidAux (s, checkedsofar);
351   */
352 }
353
354 static /*@dependent@*/ /*@notnull@*/ /*@special@*/ sRef
355   sRef_new (void)
356   /*@defines result@*/
357   /*@ensures isnull result->aliasinfo, result->definfo,
358                     result->expinfo, result->info, result->deriv, result->state@*/
359 {
360   sRef s = sRef_alloc ();
361
362   s->kind = SK_UNKNOWN;
363   s->safe = TRUE;
364   s->modified = FALSE;
365   s->immut = FALSE;
366   s->val = multiVal_undefined;
367
368   s->type = ctype_unknown;
369   s->defstate = SS_UNKNOWN;
370
371   /* start modifications */
372   s->bufinfo.bufstate = BB_NOTNULLTERMINATED;
373   s->bufinfo.size = -1; /*@i24 unknown@*/
374   s->bufinfo.len = -1; /*@i24 unknown@*/
375   /* end modifications */
376
377   s->aliaskind = AK_UNKNOWN;
378   s->oaliaskind = AK_UNKNOWN;
379
380   s->nullstate = NS_UNKNOWN;
381
382   s->expkind = XO_UNKNOWN;
383   s->oexpkind = XO_UNKNOWN;
384
385   s->aliasinfo = stateInfo_undefined;
386   s->definfo = stateInfo_undefined;
387   s->nullinfo = stateInfo_undefined;
388   s->expinfo = stateInfo_undefined;
389
390   s->info = NULL;
391   s->deriv = sRefSet_undefined;
392
393   s->state = valueTable_undefined;
394
395   return s;
396 }
397
398 static /*@dependent@*/ /*@notnull@*/ /*@special@*/ sRef
399   sRef_newRef (void)
400   /*@defines result@*/
401   /*@ensures isnull result->aliasinfo, result->definfo,
402                     result->expinfo, result->info, result->deriv@*/
403 {
404   sRef res = sRef_new ();
405   res->immut = FALSE;
406   res->state = valueTable_undefined;
407   return res;
408 }
409
410
411 void sRef_protectDerivs (void) /*@modifies protectDerivs@*/
412 {
413   llassert (!protectDerivs);
414   protectDerivs = TRUE;
415 }
416
417 void sRef_clearProtectDerivs (void) /*@modifies protectDerivs@*/
418 {
419   llassert (protectDerivs);
420   protectDerivs = FALSE;
421 }
422
423 /*
424 ** hmmm...here be kind of a hack.  This function mysteriously appeared
425 ** in my code, but I'm sure I didn't write it.
426 */
427
428 bool
429 sRef_isRecursiveField (sRef s)
430 {
431   if (sRef_isField (s))
432     {
433       if (sRef_depth (s) > 13)
434         {
435           sRef base;
436           cstring fieldname;
437           
438           fieldname = sRef_getField (s);
439           base = sRef_getBase (s);
440           
441           while (sRef_isValid (base))
442             {
443               if (sRef_isField (base))
444                 {
445                   if (cstring_equal (fieldname, sRef_getField (base)))
446                     {
447                       return TRUE;
448                     }
449                 }
450               
451               base = sRef_getBaseSafe (base);
452             }
453         }
454     }
455
456   return FALSE;
457 }
458
459 static void
460 sRef_addDeriv (/*@notnull@*/ sRef s, /*@notnull@*/ /*@exposed@*/ sRef t)
461 {
462   if (!context_inProtectVars () 
463       && !protectDerivs
464       && sRef_isValid (s)
465       && sRef_isValid (t)
466       && !sRef_isConst (s))
467     {
468       int sd = sRef_depth (s);
469       int td = sRef_depth (t);
470       
471       if (sd >= td)
472         {
473           return;
474         }
475
476       /* This sometimes fails: (evans 2001-07-12)
477       if (sRef_isArrayFetch (t))
478         {
479           DPRINTF (("Derived fetch: %s / %s / %s",
480                     sRef_unparseFull (s), sRef_unparseFull (t),
481                     sRef_unparseFull (t->info->arrayfetch->arr)));
482           llassert (t->info->arrayfetch->arr == s);
483         }
484       */
485
486       if (sRef_isFileOrGlobalScope (s))
487         {
488           if (context_inFunctionLike () 
489               && ctype_isKnown (sRef_getType (s))
490               && !ctype_isFunction (sRef_getType (s)))
491             {
492               globSet g = context_getUsedGlobs ();
493
494               if (!globSet_member (g, s))
495                 {
496                   /* 
497                   ** don't report as a bug 
498                   ** 
499
500                   llcontbug 
501                         (message ("sRef_addDeriv: global variable not in used "
502                                   "globs: %q / %s / %q",
503                                   sRef_unparse (s), 
504                                   ctype_unparse (sRef_getType (s)),
505                                   sRefSet_unparse (s->deriv)));
506                   */
507                 }
508               else
509                 {
510                   s->deriv = sRefSet_insert (s->deriv, t);
511                 }
512             }
513         }
514       else
515         {
516           DPRINTF (("Add deriv: [%p] %s / [%p] %s",
517                     s, sRef_unparse (s),
518                     t, sRef_unparse (t)));
519
520           s->deriv = sRefSet_insert (s->deriv, t);
521         }
522     }
523 }
524
525 bool
526 sRef_deepPred (bool (predf) (sRef), sRef s)
527 {
528   if (sRef_isValid (s))
529     {
530       if ((*predf)(s)) return TRUE;
531
532       switch (s->kind)
533         {
534         case SK_PTR:
535           return (sRef_deepPred (predf, s->info->ref));
536         case SK_ARRAYFETCH:
537           return (sRef_deepPred (predf, s->info->arrayfetch->arr));
538         case SK_FIELD:
539           return (sRef_deepPred (predf, s->info->field->rec));
540         case SK_CONJ:
541           return (sRef_deepPred (predf, s->info->conj->a)
542                   || sRef_deepPred (predf, s->info->conj->b));
543         default:
544           return FALSE;
545         }
546     }
547
548   return FALSE;
549 }
550
551 bool sRef_modInFunction (void)
552 {
553   return inFunction;
554 }
555
556 void sRef_setStateFromType (sRef s, ctype ct)
557 {
558   if (sRef_isValid (s))
559     {
560       if (ctype_isUser (ct))
561         {
562           DPRINTF (("Here we are: %s", sRef_unparseFull (s)));
563           sRef_setStateFromUentry 
564             (s, usymtab_getTypeEntry (ctype_typeId (ct)));
565         }
566       else if (ctype_isAbstract (ct))
567         {
568           DPRINTF (("Here we are: %s", sRef_unparseFull (s)));
569           sRef_setStateFromAbstractUentry 
570             (s, usymtab_getTypeEntry (ctype_typeId (ct)));
571         }
572       else
573         {
574           ; /* not a user type */
575         }
576     }
577 }
578
579 static void sRef_setTypeState (sRef s)
580 {
581   if (sRef_isValid (s))
582     {
583       sRef_setStateFromType (s, s->type);
584     }
585 }
586
587 static bool
588   sRef_hasAliasInfoLoc (sRef s)
589 {
590   return (sRef_isValid (s) && (s->aliasinfo != NULL)
591           && (fileloc_isDefined (s->aliasinfo->loc)));
592 }
593
594 static /*@falsewhennull@*/ bool
595 sRef_hasStateInfoLoc (sRef s)
596 {
597   return (sRef_isValid (s) && (s->definfo != NULL) 
598           && (fileloc_isDefined (s->definfo->loc)));
599 }
600
601 static /*@falsewhennull@*/ bool
602 sRef_hasExpInfoLoc (sRef s)
603 {
604   return (sRef_isValid (s) 
605           && (s->expinfo != NULL) && (fileloc_isDefined (s->expinfo->loc)));
606 }
607
608 # if 0
609 static /*@observer@*/ /*@unused@*/ stateInfo sRef_getInfo (sRef s, cstring key)
610 {
611   stateValue sv;
612   
613   if (!sRef_isValid (s)) {
614     return stateInfo_undefined;
615   }
616   
617   sv = valueTable_lookup (s->state, key);
618   
619   if (stateValue_isDefined (sv)) 
620     {
621       return stateValue_getInfo (sv);
622     }
623   
624   return stateInfo_undefined;
625 }
626 # endif
627
628 static bool
629 sRef_hasNullInfoLoc (sRef s)
630 {
631   return (sRef_isValid (s) && s->nullinfo != NULL
632           && (fileloc_isDefined (s->nullinfo->loc)));
633 }
634
635 bool
636 sRef_hasAliasInfoRef (sRef s)
637 {
638   return (sRef_isValid (s) && (s->aliasinfo != NULL) 
639           && (sRef_isValid (s->aliasinfo->ref)));
640 }
641
642 static /*@observer@*/ fileloc
643 sRef_getAliasInfoLoc (/*@exposed@*/ sRef s)
644 {
645   llassert (sRef_isValid (s) && s->aliasinfo != NULL
646             && (fileloc_isDefined (s->aliasinfo->loc)));
647   return (s->aliasinfo->loc);
648 }
649
650 static /*@observer@*/ fileloc
651 sRef_getStateInfoLoc (/*@exposed@*/ sRef s)
652 {
653   llassert (sRef_isValid (s) && s->definfo != NULL 
654             && (fileloc_isDefined (s->definfo->loc)));
655   return (s->definfo->loc);
656 }
657
658 static /*@observer@*/ fileloc
659 sRef_getExpInfoLoc (/*@exposed@*/ sRef s)
660 {
661   llassert (sRef_isValid (s) && s->expinfo != NULL 
662             && (fileloc_isDefined (s->expinfo->loc)));
663   return (s->expinfo->loc);
664 }
665
666 static /*@observer@*/ fileloc
667 sRef_getNullInfoLoc (/*@exposed@*/ sRef s)
668 {
669   llassert (sRef_isValid (s) && s->nullinfo != NULL 
670             && (fileloc_isDefined (s->nullinfo->loc)));
671   return (s->nullinfo->loc);
672 }
673
674 /*@observer@*/ sRef
675   sRef_getAliasInfoRef (/*@temp@*/ sRef s)
676 {
677   llassert (sRef_isValid (s) && s->aliasinfo != NULL);
678   return (s->aliasinfo->ref);
679 }
680
681 bool sRef_inGlobalScope ()
682 {
683   return !inFunction;
684 }
685
686 /*
687 ** This function should be called before new sRefs are created
688 ** somewhere where they will have a lifetime greater than the
689 ** current function scope.
690 */
691
692 void sRef_setGlobalScope ()
693 {
694   llassert (inFunction);
695   DPRINTF (("leave function"));
696   inFunction = FALSE;
697 }
698
699 void sRef_clearGlobalScope ()
700 {
701   llassert (!inFunction);
702   DPRINTF (("enter function"));
703   inFunction = TRUE;
704 }
705
706 static bool oldInFunction = FALSE;
707 static int nestedScope = 0;
708
709 void sRef_setGlobalScopeSafe ()
710 {
711   if (nestedScope == 0)
712     {
713       oldInFunction = inFunction;
714     }
715   
716   nestedScope++;
717   DPRINTF (("leave function safe"));
718   inFunction = FALSE;
719 }
720
721 void sRef_clearGlobalScopeSafe ()
722 {
723   nestedScope--;
724   llassert (nestedScope >= 0);
725   
726   if (nestedScope == 0)
727     {
728       inFunction = oldInFunction;
729     }
730
731   DPRINTF (("clear function: %s", bool_unparse (inFunction)));
732 }
733
734 void sRef_enterFunctionScope ()
735 {
736   /* evans 2001-09-09 - cleanup if we are in a macro! */
737   if (context_inMacro ())
738     {
739       if (inFunction) {
740         sRef_exitFunctionScope ();
741       }
742     }
743
744   llassert (!inFunction);
745   llassert (sRefTable_isEmpty (allRefs));
746   inFunction = TRUE;
747   DPRINTF (("enter function"));
748 }
749
750 void sRef_exitFunctionScope ()
751 {  
752   if (inFunction)
753     {
754       DPRINTF (("Exit function scope."));
755       sRefTable_clear (allRefs);
756       inFunction = FALSE;
757     }
758   else
759     {
760       llbuglit ("sRef_exitFunctionScope: not in function");
761     }
762 }
763   
764 void sRef_destroyMod () /*@globals killed allRefs;@*/
765 {
766 # ifdef DEBUGREFS  
767   llmsg (message ("Live: %d / %d ", nsrefs, totnsrefs));  
768 # endif
769
770   sRefTable_free (allRefs);
771 }
772
773
774 static /*@notnull@*/ /*@exposed@*/ sRef
775 sRef_fixConj (/*@notnull@*/ sRef s)
776 {
777   if (sRef_isConj (s))
778     {
779       do {
780         s = sRef_getConjA (s);
781       } while (sRef_isConj (s));
782       
783       llassert (sRef_isValid (s));
784       return s; /* don't need to ref */
785     }
786   else
787     {
788       return s;
789     }
790 }
791
792 static bool 
793 sRef_isExternallyVisibleAux (sRef s)
794 {
795   bool res = FALSE;
796   sRef base = sRef_getRootBase (s);
797
798   if (sRef_isValid (base))
799     {
800       res = sRef_isParam (base) || sRef_isFileOrGlobalScope (base) || sRef_isExternal (base);
801     }
802
803   return res;
804 }
805
806 bool 
807   sRef_isExternallyVisible (sRef s)
808 {
809   return (sRef_aliasCheckSimplePred (sRef_isExternallyVisibleAux, s));
810 }
811
812 /*@exposed@*/ uentry
813 sRef_getBaseUentry (sRef s)
814 {
815   sRef base = sRef_getRootBase (s);
816   uentry res = uentry_undefined;
817   
818   if (sRef_isValid (base))
819     {
820       switch (base->kind)
821         {
822         case SK_PARAM:
823           res = usymtab_getRefQuiet (paramsScope, base->info->paramno);
824           break;
825
826         case SK_CVAR:
827           res = usymtab_getRefQuiet (base->info->cvar->lexlevel, 
828                                      base->info->cvar->index);
829           break;
830
831         default:
832           break;
833         }  
834     }
835
836   return res;
837 }
838
839 /*
840 ** lookup the current uentry corresponding to s, and return the corresponding sRef.
841 ** yuk yuk yuk yuk yuk yuk yuk yuk
842 */
843
844 /*@exposed@*/ sRef
845 sRef_updateSref (sRef s)
846 {
847   sRef inner;
848   sRef ret;
849   sRef res;
850
851   if (!sRef_isValid (s)) return sRef_undefined;
852   
853   switch (s->kind)
854     {
855     case SK_UNKNOWN:
856     case SK_OBJECT:
857     case SK_NEW:
858     case SK_TYPE:
859     case SK_DERIVED:
860     case SK_UNCONSTRAINED:
861     case SK_CONST:
862     case SK_SPECIAL:
863     case SK_RESULT:
864       return s; 
865     case SK_EXTERNAL:
866       {
867         sRef r = sRef_updateSref (s->info->ref);
868
869         if (r != s->info->ref)
870           {
871             return sRef_makeExternal (r);
872           }
873         else
874           {
875             return s;
876           }
877       }
878     case SK_PARAM:
879     case SK_CVAR:
880       {
881         uentry ue = sRef_getUentry (s);
882
883         /* must be raw name!  (need the marker) */
884         ue = usymtab_lookupSafe (uentry_rawName (ue));
885         
886         if (uentry_isUndefined (ue))
887           {
888             return s;
889           }
890         else
891           {
892             DPRINTF (("Update sref: %s", uentry_unparseFull (ue)));
893             return (uentry_getSref (ue));
894           }
895       }
896     case SK_ARRAYFETCH:
897       /* special case if ind known */
898       inner = s->info->arrayfetch->arr;
899       ret = sRef_updateSref (inner);
900
901       if (ret == inner) 
902         {
903           res = s; 
904         }
905       else 
906         {
907           res = sRef_makeArrayFetch (ret);
908         }
909
910       return res;
911
912     case SK_FIELD:
913       inner = s->info->field->rec;
914       ret = sRef_updateSref (inner);
915
916       if (ret == inner) 
917         {
918           res = s; 
919         }
920       else 
921         {
922           res = (sRef_makeField (ret, s->info->field->field));
923         }
924
925       return (res);
926     case SK_PTR:
927       inner = s->info->ref;
928       ret = sRef_updateSref (inner);
929       if (ret == inner) 
930         {
931           res = s; 
932         }
933       else
934         {
935           res = sRef_makePointer (ret);
936         }
937
938       return (res);
939
940     case SK_ADR:
941       inner = s->info->ref;
942       ret = sRef_updateSref (inner);
943
944       if (ret == inner)
945         {
946           res = s; 
947         }
948       else 
949         {
950           res = sRef_makeAddress (ret);
951         }
952
953       return (res);
954
955     case SK_CONJ:
956       {
957         sRef innera = s->info->conj->a;
958         sRef innerb = s->info->conj->b;
959         sRef reta = sRef_updateSref (innera);
960         sRef retb = sRef_updateSref (innerb);
961
962         if (innera == reta && innerb == retb)
963           {
964             res = s;
965           }
966         else 
967           {
968             res = sRef_makeConj (reta, retb);
969           }
970
971         return (res);
972       }
973     }
974   
975   BADEXIT;
976 }
977
978 uentry
979 sRef_getUentry (sRef s)
980 {
981   llassert (sRef_isValid (s));
982
983   switch (s->kind)
984     {
985     case SK_PARAM:
986       return (usymtab_getRefQuiet (paramsScope, s->info->paramno));
987     case SK_CVAR:
988       return (usymtab_getRefQuiet (s->info->cvar->lexlevel, s->info->cvar->index));
989     case SK_CONJ:
990       {
991         if (sRef_isCvar (s->info->conj->a) || sRef_isParam (s->info->conj->a)
992             || sRef_isConj (s->info->conj->a))
993           {
994             return sRef_getUentry (s->info->conj->a);
995           }
996         else 
997           {
998             return sRef_getUentry (s->info->conj->b);
999           }
1000       }
1001     case SK_UNKNOWN:
1002     case SK_SPECIAL:
1003       return uentry_undefined;
1004     BADDEFAULT;
1005     }
1006 }
1007
1008 int
1009 sRef_getParam (sRef s)
1010 {
1011   llassert (sRef_isValid (s));
1012   llassert (s->kind == SK_PARAM);
1013
1014   return s->info->paramno;
1015 }
1016
1017 bool
1018 sRef_isModified (sRef s)
1019 {
1020     return (!sRef_isValid (s) || s->modified);
1021 }
1022
1023 void sRef_setModified (sRef s)
1024 {
1025   if (sRef_isValid (s))
1026     {
1027       s->modified = TRUE;
1028
1029       
1030       if (sRef_isRefsField (s))
1031         {
1032           sRef base = sRef_getBase (s);
1033           
1034           llassert (s->kind == SK_FIELD);
1035           
1036           if (sRef_isPointer (base))
1037             {
1038               base = sRef_getBase (base);
1039             }
1040           
1041           if (sRef_isRefCounted (base))
1042             {
1043               base->aliaskind = AK_NEWREF;
1044             }
1045         }
1046     }
1047 }
1048
1049 /*
1050 ** note: this side-effects sRefSet to set modified to TRUE
1051 ** for any sRef similar to s.
1052 */
1053
1054 bool
1055 sRef_canModifyVal (sRef s, sRefSet sl)
1056 {
1057   if (context_getFlag (FLG_MUSTMOD))
1058     {
1059       return (sRef_doModifyVal (s, sl));
1060     }
1061   else
1062     {
1063       return (sRef_checkModifyVal (s, sl));
1064     }
1065 }
1066
1067 bool
1068 sRef_canModify (sRef s, sRefSet sl)
1069 {
1070   if (context_getFlag (FLG_MUSTMOD))
1071     {
1072       return (sRef_doModify (s, sl));
1073     }
1074   else
1075     {
1076       return (sRef_checkModify (s, sl));
1077     }
1078 }
1079
1080 /*
1081 ** No side-effects
1082 */
1083
1084 static
1085 bool sRef_checkModifyVal (sRef s, sRefSet sl)
1086 {
1087   DPRINTF (("Check modify val: %s", sRef_unparse (s)));
1088
1089   if (sRef_isInvalid (s))
1090     {
1091       return TRUE;
1092     }
1093   
1094   switch (s->kind)
1095     {
1096     case SK_UNCONSTRAINED:
1097     case SK_CONST:
1098       return TRUE;
1099     case SK_CVAR:
1100       DPRINTF (("Modify var: %s", sRef_unparse (s)));
1101
1102       if (sRef_isFileOrGlobalScope (s))
1103         {
1104           if (context_checkGlobMod (s))
1105             {
1106               return (sRefSet_member (sl, s));
1107             }
1108
1109           return TRUE;
1110         }
1111       else
1112         {
1113           return TRUE;
1114         }
1115     case SK_PARAM:
1116             return (sRefSet_member (sl, s) 
1117               || alkind_isOnly (sRef_getOrigAliasKind (s)));
1118     case SK_ARRAYFETCH: 
1119       /* special case if ind known */
1120       return (sRefSet_member (sl, s) ||
1121               sRef_checkModifyVal (s->info->arrayfetch->arr, sl));
1122     case SK_FIELD:
1123       return (sRefSet_member (sl, s) || sRef_checkModifyVal (s->info->field->rec, sl));
1124     case SK_PTR:
1125       return (sRefSet_member (sl, s) || sRef_checkModifyVal (s->info->ref, sl));
1126     case SK_ADR:
1127       return (sRefSet_member (sl, s) || sRef_checkModifyVal (s->info->ref, sl));
1128     case SK_CONJ:
1129       return ((sRef_checkModifyVal (s->info->conj->a, sl)) &&
1130               (sRef_checkModifyVal (s->info->conj->b, sl)));
1131     case SK_UNKNOWN:
1132     case SK_OBJECT:
1133     case SK_NEW:
1134     case SK_TYPE:
1135     case SK_DERIVED:
1136       return TRUE;
1137     case SK_EXTERNAL:
1138       return TRUE;
1139     case SK_SPECIAL:
1140       {
1141         switch (s->info->spec)
1142           {
1143           case SR_NOTHING:   return TRUE;
1144           case SR_INTERNAL:  
1145             if (context_getFlag (FLG_INTERNALGLOBS))
1146               {
1147                 return (sRefSet_member (sl, s));
1148               }
1149             else
1150               {
1151                 return TRUE;
1152               }
1153           case SR_SPECSTATE: return TRUE;
1154           case SR_SYSTEM:    return (sRefSet_member (sl, s));
1155           case SR_GLOBALMARKER: BADBRANCH;
1156           }
1157       }
1158     case SK_RESULT: BADBRANCH;
1159     }
1160   BADEXIT;
1161 }
1162
1163 /*
1164 ** this should probably be elsewhere...
1165 **
1166 ** returns TRUE iff sl indicates that s can be modified
1167 */
1168
1169 static bool sRef_checkModify (sRef s, sRefSet sl)
1170 {
1171   llassert (sRef_isValid (s));
1172
1173   switch (s->kind)
1174     {
1175     case SK_UNCONSTRAINED:
1176     case SK_CONST:
1177       return TRUE;
1178     case SK_CVAR:
1179       if (sRef_isFileOrGlobalScope (s))
1180         {
1181           if (context_checkGlobMod (s))
1182             {
1183               return (sRefSet_member (sl, s));
1184             }
1185
1186           return TRUE;
1187         }
1188       else
1189         {
1190           return TRUE;
1191         }
1192     case SK_PARAM:
1193       return TRUE;
1194     case SK_ARRAYFETCH:
1195       return (sRefSet_member (sl, s) ||
1196               sRef_checkModifyVal (s->info->arrayfetch->arr, sl));
1197     case SK_FIELD:
1198       {
1199         sRef sr = s->info->field->rec;
1200
1201         if (sr->kind == SK_PARAM)
1202           return TRUE; /* structs are copied on call */
1203
1204         return (sRefSet_member (sl, s) || sRef_checkModifyVal (s->info->field->rec, sl));
1205       }
1206     case SK_PTR:
1207       {
1208         bool sm;
1209
1210         sm = sRefSet_member (sl, s);
1211
1212         if (sm)
1213           return TRUE;
1214         else
1215           return (sRef_checkModifyVal (s->info->ref, sl));
1216       }
1217     case SK_ADR:
1218       return (sRefSet_member (sl, s) || sRef_checkModifyVal (s->info->ref, sl));
1219     case SK_CONJ:
1220       return ((sRef_checkModify (s->info->conj->a, sl)) &&
1221               (sRef_checkModify (s->info->conj->b, sl)));
1222     case SK_NEW:
1223     case SK_OBJECT:
1224     case SK_UNKNOWN:
1225     case SK_TYPE:
1226     case SK_DERIVED:
1227     case SK_EXTERNAL:
1228       return TRUE;
1229     case SK_SPECIAL:
1230       {
1231         switch (s->info->spec)
1232           {
1233           case SR_NOTHING:   return TRUE;
1234           case SR_INTERNAL:  
1235             if (context_getFlag (FLG_INTERNALGLOBS))
1236               {
1237                 return (sRefSet_member (sl, s));
1238               }
1239             else
1240               {
1241                 return TRUE;
1242               }
1243           case SR_SPECSTATE: return TRUE;
1244           case SR_SYSTEM:    return (sRefSet_member (sl, s));
1245           case SR_GLOBALMARKER: BADBRANCH;
1246           }
1247       }
1248     case SK_RESULT: BADBRANCH;
1249     }
1250   BADEXIT;
1251 }
1252
1253 cstring sRef_stateVerb (sRef s)
1254 {
1255   if (sRef_isDead (s))
1256     {
1257       return cstring_makeLiteralTemp ("released");
1258     }
1259   else if (sRef_isKept (s))
1260     {
1261       return cstring_makeLiteralTemp ("kept");
1262     }
1263   else if (sRef_isDependent (s))
1264     {
1265       return cstring_makeLiteralTemp ("dependent");
1266     }
1267   else
1268     {
1269       BADEXIT;
1270     }
1271 }
1272
1273 cstring sRef_stateAltVerb (sRef s)
1274 {
1275   if (sRef_isDead (s))
1276     {
1277       return cstring_makeLiteralTemp ("live");
1278     }
1279   else if (sRef_isKept (s))
1280     {
1281       return cstring_makeLiteralTemp ("not kept");
1282     }
1283   else if (sRef_isDependent (s))
1284     {
1285       return cstring_makeLiteralTemp ("independent");
1286     }
1287   else
1288     {
1289       BADEXIT;
1290     }
1291 }
1292
1293 static 
1294 bool sRef_doModifyVal (sRef s, sRefSet sl)
1295 {
1296   llassert (sRef_isValid (s));
1297
1298   
1299   switch (s->kind)
1300     {
1301     case SK_UNCONSTRAINED:
1302     case SK_CONST:
1303       return TRUE;
1304     case SK_CVAR:
1305       if (sRef_isFileOrGlobalScope (s))
1306         {
1307           
1308           if (context_checkGlobMod (s))
1309             {
1310               return (sRefSet_modifyMember (sl, s));
1311             }
1312           else
1313             {
1314               (void) sRefSet_modifyMember (sl, s);
1315             }
1316
1317                   return TRUE;
1318         }
1319       else
1320         {
1321           return TRUE;
1322         }      
1323     case SK_PARAM:
1324       return (sRefSet_modifyMember (sl, s) 
1325               || alkind_isOnly (sRef_getOrigAliasKind (s)));
1326     case SK_ARRAYFETCH:
1327       /* special case if ind known */
1328       /* unconditional OR, need side effect */
1329       return (OR (sRefSet_modifyMember (sl, s),
1330                   sRef_doModifyVal (s->info->arrayfetch->arr, sl)));
1331     case SK_FIELD:
1332       return (OR (sRefSet_modifyMember (sl, s),
1333                   sRef_doModifyVal (s->info->field->rec, sl)));
1334     case SK_PTR:
1335       return (OR (sRefSet_modifyMember (sl, s),
1336                   sRef_doModifyVal (s->info->ref, sl)));
1337     case SK_ADR:
1338       return (OR (sRefSet_modifyMember (sl, s),
1339                   sRef_doModifyVal (s->info->ref, sl)));
1340     case SK_CONJ:
1341       return (AND (sRef_doModifyVal (s->info->conj->a, sl) ,
1342                    sRef_doModifyVal (s->info->conj->b, sl)));
1343     case SK_OBJECT:
1344     case SK_DERIVED:
1345     case SK_EXTERNAL:
1346     case SK_UNKNOWN:
1347     case SK_NEW:
1348     case SK_TYPE:
1349       return TRUE;
1350     case SK_SPECIAL:
1351       {
1352         switch (s->info->spec)
1353           {
1354           case SR_NOTHING:   return TRUE;
1355           case SR_INTERNAL:  
1356             if (context_getFlag (FLG_INTERNALGLOBS))
1357               {
1358                 return (sRefSet_modifyMember (sl, s));
1359               }
1360             else
1361               {
1362                 (void) sRefSet_modifyMember (sl, s);
1363                 return TRUE;
1364               }
1365           case SR_SPECSTATE: return TRUE;
1366           case SR_SYSTEM:    return (sRefSet_modifyMember (sl, s));
1367           case SR_GLOBALMARKER: BADBRANCH;
1368
1369           }
1370       }
1371     case SK_RESULT: BADBRANCH;
1372     }
1373   BADEXIT;
1374 }
1375
1376 /*
1377 ** this should probably be elsewhere...
1378 **
1379 ** returns TRUE iff sl indicates that s can be modified
1380 */
1381
1382 static 
1383 bool sRef_doModify (sRef s, sRefSet sl)
1384 {
1385   llassert (sRef_isValid (s));
1386   
1387   switch (s->kind)
1388     {
1389     case SK_UNCONSTRAINED:
1390     case SK_CONST:
1391       return TRUE;
1392     case SK_CVAR:
1393       if (sRef_isFileOrGlobalScope (s))
1394         {
1395           if (context_checkGlobMod (s))
1396             {
1397               return (sRefSet_modifyMember (sl, s));
1398             }
1399           else
1400             {
1401               (void) sRefSet_modifyMember (sl, s);
1402             }
1403
1404           return TRUE;
1405         }
1406       else
1407         {
1408           return TRUE;
1409         }
1410     case SK_PARAM:
1411       return TRUE;
1412     case SK_ARRAYFETCH:
1413             return (OR (sRefSet_modifyMember (sl, s),
1414                   sRef_doModifyVal (s->info->arrayfetch->arr, sl)));
1415     case SK_FIELD:
1416       {
1417         sRef sr = s->info->field->rec;
1418
1419         if (sr->kind == SK_PARAM)
1420           {
1421             return TRUE; /* structs are shallow-copied on call */
1422           }
1423         
1424         return (OR (sRefSet_modifyMember (sl, s),
1425                     sRef_doModifyVal (s->info->field->rec, sl)));
1426       }
1427     case SK_PTR:
1428       {
1429         return (OR (sRefSet_modifyMember (sl, s),
1430                     sRef_doModifyVal (s->info->ref, sl)));
1431       }
1432     case SK_ADR:
1433       return (OR (sRefSet_modifyMember (sl, s),
1434                   sRef_doModifyVal (s->info->ref, sl)));
1435     case SK_CONJ:
1436       return (AND (sRef_doModify (s->info->conj->a, sl),
1437                   (sRef_doModify (s->info->conj->b, sl))));
1438     case SK_UNKNOWN:
1439     case SK_NEW:
1440     case SK_TYPE:
1441       return TRUE;
1442     case SK_OBJECT:
1443     case SK_DERIVED:
1444     case SK_EXTERNAL:
1445       return TRUE;
1446     case SK_SPECIAL:
1447       {
1448         switch (s->info->spec)
1449           {
1450           case SR_NOTHING:   return TRUE;
1451           case SR_INTERNAL:  return TRUE;
1452           case SR_SPECSTATE: return TRUE;
1453           case SR_SYSTEM:    return (sRefSet_modifyMember (sl, s));
1454           case SR_GLOBALMARKER: BADBRANCH;
1455           }
1456       }
1457     case SK_RESULT: BADBRANCH;
1458     }
1459   BADEXIT;
1460 }
1461
1462 static /*@exposed@*/ sRef
1463   sRef_leastCommon (/*@exposed@*/ sRef s1, sRef s2)
1464 {
1465   llassert (sRef_similar (s1, s2));
1466   
1467   if (!sRef_isValid (s1)) return s1;
1468   if (!sRef_isValid (s2)) return s1;
1469
1470   sRef_combineDefState (s1, s2);
1471   sRef_combineNullState (s1, s2);
1472   sRef_combineExKinds (s1, s2);
1473   
1474   if (s1->aliaskind != s2->aliaskind)
1475     {
1476       if (s1->aliaskind == AK_UNKNOWN)
1477         {
1478           s1->aliaskind = s2->aliaskind;
1479         }
1480       else if (s2->aliaskind == AK_UNKNOWN)
1481         {
1482           ;
1483         }
1484       else
1485         {
1486           s1->aliaskind = AK_ERROR;
1487         }
1488     }
1489
1490   return s1;
1491 }
1492
1493 int sRef_compare (sRef s1, sRef s2)
1494 {
1495   if (s1 == s2) return 0;
1496
1497   if (sRef_isInvalid (s1)) return -1;
1498   if (sRef_isInvalid (s2)) return 1;
1499       
1500   INTCOMPARERETURN (s1->kind, s2->kind);
1501   INTCOMPARERETURN (s1->defstate, s2->defstate);
1502   INTCOMPARERETURN (s1->aliaskind, s2->aliaskind);
1503
1504   DPRINTF (("Compare null state: %s / %s",
1505             sRef_unparseFull (s1),
1506             sRef_unparseFull (s2)));
1507
1508   COMPARERETURN (nstate_compare (sRef_getNullState (s1),
1509                                  sRef_getNullState (s2)));
1510
1511   switch (s1->kind)
1512     {
1513     case SK_PARAM:
1514       return (int_compare (s1->info->paramno, s2->info->paramno));
1515     case SK_ARRAYFETCH:
1516       {
1517         COMPARERETURN (sRef_compare (s1->info->arrayfetch->arr, 
1518                                      s2->info->arrayfetch->arr));
1519         
1520         if (s1->info->arrayfetch->indknown && s2->info->arrayfetch->indknown)
1521           {
1522             return (int_compare (s1->info->arrayfetch->ind, 
1523                                  s2->info->arrayfetch->ind));
1524           }
1525         if (!s1->info->arrayfetch->indknown && !s2->info->arrayfetch->indknown)
1526           return 0;
1527         
1528         return 1;
1529       }
1530     case SK_FIELD:
1531       {
1532         COMPARERETURN (sRef_compare (s1->info->field->rec, s2->info->field->rec));
1533         
1534         if (cstring_equal (s1->info->field->field, s2->info->field->field))
1535           return 0;
1536
1537         return 1;
1538       }
1539     case SK_PTR:
1540     case SK_ADR:
1541       return (sRef_compare (s1->info->ref, s2->info->ref));
1542     case SK_CONJ:
1543       COMPARERETURN (sRef_compare (s1->info->conj->a, s2->info->conj->a));
1544       return (sRef_compare (s1->info->conj->b, s2->info->conj->b));
1545     case SK_UNCONSTRAINED:
1546       return (cstring_compare (s1->info->fname, s2->info->fname));
1547     case SK_NEW:
1548     case SK_CVAR:
1549     case SK_UNKNOWN:
1550     case SK_OBJECT:
1551     case SK_TYPE:
1552     case SK_DERIVED:
1553     case SK_EXTERNAL:
1554     case SK_CONST:
1555     case SK_RESULT:
1556       return 0;
1557     case SK_SPECIAL:
1558       return (generic_compare (s1->info->spec, s2->info->spec));
1559     }
1560   BADEXIT;
1561 }
1562
1563 static bool cref_equal (cref c1, cref c2)
1564 {
1565   return ((c1->lexlevel == c2->lexlevel) &&
1566           (usymId_equal (c1->index, c2->index)));
1567 }
1568
1569 /*
1570 ** returns true if s1 could be the same storage as s2.
1571 ** i.e., a[?] ~ a[3].  Note its not symmetric ... s1
1572 ** should be more specific.
1573 */
1574
1575 /*
1576 ** like similar, but matches objects <-> non-objects
1577 */
1578
1579 static bool 
1580 sRef_uniqueReference (sRef s)
1581 {
1582   return (sRef_isFresh (s) || sRef_isUnique (s) 
1583           || sRef_isOnly (s) || sRef_isStack (s)
1584           || sRef_isAddress (s)); 
1585 }
1586
1587 static bool
1588 sRef_similarRelaxedAux (sRef s1, sRef s2)
1589 {
1590   if (s1 == s2)
1591     {
1592       if (sRef_isUnknownArrayFetch (s1))
1593         {
1594           return FALSE;
1595         }
1596       else
1597         {
1598           return TRUE;
1599         }
1600     }
1601
1602   if (sRef_isInvalid (s1) || sRef_isInvalid (s2)) return FALSE;
1603
1604   if (sRef_isConj (s2)) 
1605     return (sRef_similarRelaxedAux (s1, sRef_getConjA (s2)) ||
1606             sRef_similarRelaxedAux (s1, sRef_getConjB (s2)));
1607
1608   switch (s1->kind)
1609     {
1610     case SK_CVAR:
1611       return ((s2->kind == SK_CVAR)
1612               && (cref_equal (s1->info->cvar, s2->info->cvar)));
1613     case SK_PARAM:
1614       return ((s2->kind == SK_PARAM)
1615               && (s1->info->paramno == s2->info->paramno));
1616     case SK_ARRAYFETCH:
1617       if (s2->kind == SK_ARRAYFETCH)
1618         {
1619           if (sRef_similarRelaxedAux (s1->info->arrayfetch->arr,
1620                                       s2->info->arrayfetch->arr))
1621             {
1622               if (s1->info->arrayfetch->indknown)
1623                 {
1624                   if (s2->info->arrayfetch->indknown)
1625                     {
1626                       return (s1->info->arrayfetch->ind == s2->info->arrayfetch->ind);
1627                     }
1628                   else 
1629                     {
1630                       return FALSE;
1631                     }
1632                 }
1633               else
1634                 {
1635                   return FALSE;
1636                 }
1637             }
1638         }
1639       return FALSE;
1640     case SK_FIELD:
1641       return ((s2->kind == SK_FIELD
1642                && (sRef_similarRelaxedAux (s1->info->field->rec,
1643                                            s2->info->field->rec)
1644                    && cstring_equal (s1->info->field->field,
1645                                      s2->info->field->field))));
1646     case SK_PTR:
1647       return ((s2->kind == SK_PTR)
1648               && sRef_similarRelaxedAux (s1->info->ref, s2->info->ref));
1649     case SK_ADR:
1650       return ((s2->kind == SK_ADR)
1651               && sRef_similarRelaxedAux (s1->info->ref, s2->info->ref));
1652     case SK_CONJ:
1653       return ((sRef_similarRelaxedAux (s1->info->conj->a, s2) ||
1654               (sRef_similarRelaxedAux (s1->info->conj->b, s2))));
1655     case SK_SPECIAL:
1656       return (s1->info->spec == s2->info->spec);
1657     case SK_UNCONSTRAINED:
1658       return (cstring_equal (s1->info->fname, s2->info->fname));
1659     case SK_DERIVED:
1660     case SK_CONST:
1661     case SK_TYPE:
1662     case SK_NEW:
1663     case SK_UNKNOWN:
1664     case SK_OBJECT:
1665     case SK_EXTERNAL:
1666     case SK_RESULT:
1667       return FALSE;
1668     }
1669   BADEXIT;
1670 }
1671
1672 bool
1673 sRef_similarRelaxed (sRef s1, sRef s2)
1674 {
1675   bool us1, us2;
1676
1677   if (s1 == s2) 
1678     {
1679       if (sRef_isThroughArrayFetch (s1))
1680         {
1681           return FALSE;
1682         }
1683       else
1684         {
1685           return TRUE;
1686         }
1687     }
1688
1689   if (sRef_isInvalid (s1) || sRef_isInvalid (s2)) return FALSE;
1690
1691   us1 = sRef_uniqueReference (s1);
1692   us2 = sRef_uniqueReference (s2);
1693
1694   if ((s1->kind == SK_EXTERNAL && (s2->kind != SK_EXTERNAL && !us2))
1695       || (s2->kind == SK_EXTERNAL && (s1->kind != SK_EXTERNAL && !us1)))
1696     {
1697       /*
1698       ** Previously, also:
1699       **   || (sRef_isExposed (s1) && !us2) || (sRef_isExposed (s2) && !us1)) ???? 
1700       **
1701       ** No clue why this was there?!
1702       */
1703
1704
1705       if (sRef_isExposed (s1) && sRef_isCvar (s1))
1706         {
1707           uentry ue1 = sRef_getUentry (s1);
1708
1709           if (uentry_isRefParam (ue1))
1710             {
1711               return sRef_similarRelaxedAux (s1, s2);
1712             }
1713         }
1714       
1715       if (sRef_isExposed (s2) && sRef_isCvar (s2))
1716         {
1717           uentry ue2 = sRef_getUentry (s2);
1718
1719           if (uentry_isRefParam (ue2))
1720             {
1721               return sRef_similarRelaxedAux (s1, s2);
1722             }
1723         }
1724       
1725             return (ctype_match (s1->type, s2->type));
1726     }
1727   else
1728     {
1729             return sRef_similarRelaxedAux (s1, s2);
1730     }
1731 }
1732
1733 bool
1734 sRef_similar (sRef s1, sRef s2)
1735 {
1736   if (s1 == s2) return TRUE;
1737   if (sRef_isInvalid (s1) || sRef_isInvalid (s2)) return FALSE;
1738
1739   if (sRef_isConj (s2)) 
1740     {
1741       return (sRef_similar (s1, sRef_getConjA (s2)) ||
1742               sRef_similar (s1, sRef_getConjB (s2)));
1743     }
1744
1745   if (sRef_isDerived (s2))
1746    {
1747      return (sRef_includedBy (s1, s2->info->ref));
1748    }
1749
1750   switch (s1->kind)
1751     {
1752     case SK_CVAR:
1753       return ((s2->kind == SK_CVAR)
1754               && (cref_equal (s1->info->cvar, s2->info->cvar)));
1755     case SK_PARAM:
1756       return ((s2->kind == SK_PARAM)
1757               && (s1->info->paramno == s2->info->paramno));
1758     case SK_ARRAYFETCH:
1759       if (s2->kind == SK_ARRAYFETCH)
1760         {
1761           if (sRef_similar (s1->info->arrayfetch->arr,
1762                             s2->info->arrayfetch->arr))
1763             {
1764               if (s1->info->arrayfetch->indknown)
1765                 {
1766                   if (s2->info->arrayfetch->indknown)
1767                     {
1768                       return (s1->info->arrayfetch->ind == s2->info->arrayfetch->ind);
1769                     }
1770                   else 
1771                     {
1772                       return TRUE;
1773                     }
1774                 }
1775               else
1776                 {
1777                   return TRUE;
1778                 }
1779             }
1780         }
1781       else 
1782         {
1783           if (s2->kind == SK_PTR)
1784             {
1785               if (sRef_similar (s1->info->arrayfetch->arr,
1786                                 s2->info->ref))
1787                 {
1788                   return TRUE; 
1789                 }
1790             }
1791         }
1792
1793       return FALSE;
1794     case SK_FIELD:
1795       return ((s2->kind == SK_FIELD
1796                && (sRef_similar (s1->info->field->rec,
1797                                  s2->info->field->rec)
1798                    && cstring_equal (s1->info->field->field,
1799                                      s2->info->field->field))));
1800     case SK_PTR:
1801       if (s2->kind == SK_PTR)
1802         {
1803           return sRef_similar (s1->info->ref, s2->info->ref);
1804         }
1805       else 
1806         {
1807           if (s2->kind == SK_ARRAYFETCH)
1808             {
1809               if (sRef_similar (s2->info->arrayfetch->arr,
1810                                 s1->info->ref))
1811                 {
1812                   return TRUE; 
1813                 }
1814             }
1815         }
1816
1817       return FALSE;
1818     case SK_ADR:
1819       return ((s2->kind == SK_ADR)
1820               && sRef_similar (s1->info->ref, s2->info->ref));
1821     case SK_CONJ:
1822       return ((sRef_similar (s1->info->conj->a, s2) ||
1823               (sRef_similar (s1->info->conj->b, s2))));
1824     case SK_DERIVED:
1825       return (sRef_includedBy (s2, s1->info->ref));
1826     case SK_UNCONSTRAINED:
1827       return (s2->kind == SK_UNCONSTRAINED
1828               && cstring_equal (s1->info->fname, s2->info->fname));
1829     case SK_CONST:
1830     case SK_TYPE:
1831     case SK_NEW:
1832     case SK_UNKNOWN:
1833     case SK_OBJECT:
1834     case SK_EXTERNAL:
1835     case SK_RESULT:
1836       return FALSE;
1837     case SK_SPECIAL:
1838       return (s2->kind == SK_SPECIAL 
1839               && (s1->info->spec == s2->info->spec));
1840     }
1841
1842   /*@notreached@*/ DPRINTF (("Fell through for: %s / %s", sRef_unparse (s1), sRef_unparse (s2)));
1843   BADEXIT;
1844 }
1845
1846 /*
1847 ** return TRUE iff small can be derived from big.
1848 **
1849 ** (e.g. x, x.a is includedBy x;
1850 **       x.a is included By x.a;
1851 */
1852
1853 bool
1854 sRef_includedBy (sRef small, sRef big)
1855 {
1856   if (small == big) return TRUE;
1857   if (sRef_isInvalid (small) || sRef_isInvalid (big)) return FALSE;
1858
1859   if (sRef_isConj (big)) 
1860     return (sRef_similar (small, sRef_getConjA (big)) ||
1861             sRef_similar (small, sRef_getConjB (big)));
1862
1863   switch (small->kind)
1864     {
1865     case SK_CVAR:
1866     case SK_PARAM:
1867       return (sRef_same (small, big));
1868     case SK_ARRAYFETCH:
1869       if (big->kind == SK_ARRAYFETCH)
1870         {
1871           if (sRef_same (small->info->arrayfetch->arr, big->info->arrayfetch->arr))
1872             {
1873               if (small->info->arrayfetch->indknown)
1874                 {
1875                   if (big->info->arrayfetch->indknown)
1876                     {
1877                       return (small->info->arrayfetch->ind == big->info->arrayfetch->ind);
1878                     }
1879                   else 
1880                     {
1881                       return TRUE;
1882                     }
1883                 }
1884               else
1885                 {
1886                   return TRUE;
1887                 }
1888             }
1889         }
1890       return (sRef_includedBy (small->info->arrayfetch->arr, big));
1891     case SK_FIELD:
1892       if (big->kind == SK_FIELD)
1893         {
1894           return 
1895             (sRef_same (small->info->field->rec, big->info->field->rec) &&
1896              cstring_equal (small->info->field->field, big->info->field->field));
1897         }
1898       else
1899         {
1900           return (sRef_includedBy (small->info->field->rec, big));
1901         }
1902
1903     case SK_PTR:
1904       if (big->kind == SK_PTR)
1905         {
1906           return sRef_same (small->info->ref, big->info->ref);
1907         }
1908       else
1909         {
1910           return (sRef_includedBy (small->info->ref, big));
1911         }
1912
1913     case SK_ADR:
1914       return ((big->kind == SK_ADR) && sRef_similar (small->info->ref, big->info->ref));
1915     case SK_CONJ:
1916       return ((sRef_includedBy (small->info->conj->a, big) ||
1917               (sRef_includedBy (small->info->conj->b, big))));
1918     case SK_DERIVED:
1919       return (sRef_includedBy (small->info->ref, big));
1920     case SK_UNCONSTRAINED:
1921     case SK_CONST:
1922     case SK_TYPE:
1923     case SK_NEW:
1924     case SK_UNKNOWN:
1925     case SK_OBJECT:
1926     case SK_EXTERNAL:
1927     case SK_RESULT:
1928       return FALSE;
1929     case SK_SPECIAL:
1930       switch (small->info->spec)
1931         {
1932         case SR_NOTHING: return TRUE;
1933         case SR_SPECSTATE:
1934         case SR_INTERNAL: return (sRef_isSpecInternalState (big) ||
1935                                   sRef_isFileStatic (big));
1936         case SR_SYSTEM: return (sRef_isSystemState (big));
1937         case SR_GLOBALMARKER: BADBRANCH;
1938         }
1939     }
1940   BADEXIT;
1941 }
1942
1943 /*
1944 ** Same is similar to similar, but not quite the same. 
1945 ** same and realSame aren't the same, but they are really similar.
1946 ** similarly, same is the same as same. but realSame is
1947 ** not really the same as same, or similar to similar.
1948 **
1949 ** Similarly to similar, same checks if two sRefs are the same.
1950 ** The similarities end, however, when same compares arrays
1951 ** with unknown indexes.  Similar returns false; same returns true.
1952 **
1953 ** Similarly to similar and same, realSame is the same as same,
1954 ** except they do not behave the same when face with unknown
1955 ** sRefs.  Same thinks they are not the same, but realSame thinks
1956 ** the are.
1957 **
1958 */
1959
1960 bool
1961 sRef_realSame (sRef s1, sRef s2)
1962 {
1963   if (s1 == s2) return TRUE;  
1964   if (sRef_isInvalid (s1) || sRef_isInvalid (s2)) return FALSE;
1965
1966   switch (s1->kind)
1967     {
1968     case SK_CVAR:
1969       return ((s2->kind == SK_CVAR) && (cref_equal (s1->info->cvar, s2->info->cvar)));
1970     case SK_PARAM:
1971       return ((s2->kind == SK_PARAM) && (s1->info->paramno == s2->info->paramno));
1972     case SK_ARRAYFETCH:
1973       if (s2->kind == SK_ARRAYFETCH)
1974         {
1975           if (sRef_realSame (s1->info->arrayfetch->arr, s2->info->arrayfetch->arr))
1976             {
1977               if (s1->info->arrayfetch->indknown && s2->info->arrayfetch->indknown)
1978                 {
1979                   return (s1->info->arrayfetch->ind == s2->info->arrayfetch->ind);
1980                 }
1981               if (!s1->info->arrayfetch->indknown && !s2->info->arrayfetch->indknown)
1982                 {
1983                   return TRUE;
1984                 }
1985               return FALSE;
1986             }
1987         }
1988       return FALSE;
1989     case SK_FIELD:
1990       return ((s2->kind == SK_FIELD &&
1991                (sRef_realSame (s1->info->field->rec, s2->info->field->rec) &&
1992                 cstring_equal (s1->info->field->field, s2->info->field->field))));
1993     case SK_PTR:
1994       return ((s2->kind == SK_PTR) && sRef_realSame (s1->info->ref, s2->info->ref));
1995     case SK_ADR:
1996       return ((s2->kind == SK_ADR) && sRef_realSame (s1->info->ref, s2->info->ref));
1997     case SK_CONJ:
1998       return ((sRef_realSame (s1->info->conj->a, s2) ||
1999               (sRef_realSame (s1->info->conj->b, s2))));
2000     case SK_OBJECT:
2001       return ((s2->kind == SK_OBJECT) 
2002               && ctype_match (s1->info->object, s2->info->object));
2003     case SK_EXTERNAL:
2004       return ((s2->kind == SK_EXTERNAL) 
2005               && sRef_realSame (s1->info->ref, s2->info->ref));
2006     case SK_SPECIAL:
2007       return ((s2->kind == SK_SPECIAL) && s1->info->spec == s2->info->spec);
2008     case SK_DERIVED:
2009       return ((s2->kind == SK_DERIVED) && sRef_realSame (s1->info->ref, s2->info->ref));
2010     case SK_UNCONSTRAINED:
2011       return ((s2->kind == SK_UNCONSTRAINED) 
2012               && (cstring_equal (s1->info->fname, s2->info->fname)));
2013     case SK_TYPE:
2014     case SK_CONST:
2015     case SK_NEW:
2016     case SK_UNKNOWN:
2017     case SK_RESULT:
2018       return TRUE; /* changed this! was false */
2019     }
2020   BADEXIT;
2021 }
2022
2023 bool
2024 sRef_sameObject (sRef s1, sRef s2)
2025 {
2026   return (s1 == s2);
2027 }
2028
2029 /*
2030 ** same is similar to similar, but not quite the same. 
2031 **
2032 ** Similarly to similar, same checks is two sRefs are the same.
2033 ** The similarities end, however, when same compares arrays
2034 ** with unknown indexes.  Similar returns false; same returns true.
2035 */
2036
2037 bool
2038 sRef_same (sRef s1, sRef s2)
2039 {
2040   if (s1 == s2) return TRUE;
2041   if (sRef_isInvalid (s1) || sRef_isInvalid (s2)) return FALSE;
2042
2043   switch (s1->kind)
2044     {
2045     case SK_CVAR:
2046       return ((s2->kind == SK_CVAR) && (cref_equal (s1->info->cvar, s2->info->cvar)));
2047     case SK_PARAM:
2048       return ((s2->kind == SK_PARAM) && (s1->info->paramno == s2->info->paramno));
2049     case SK_ARRAYFETCH:
2050       if (s2->kind == SK_ARRAYFETCH)
2051         {
2052           llassert (s1->info->field->rec != s1);
2053           if (sRef_same (s1->info->arrayfetch->arr, s2->info->arrayfetch->arr))
2054             {
2055               if (s1->info->arrayfetch->indknown && s2->info->arrayfetch->indknown)
2056                 {
2057                   return (s1->info->arrayfetch->ind == s2->info->arrayfetch->ind);
2058                 }
2059               return TRUE;
2060             }
2061         }
2062       return FALSE;
2063     case SK_FIELD:
2064       {
2065         llassert (s1->info->field->rec != s1);
2066         return ((s2->kind == SK_FIELD &&
2067                  (sRef_same (s1->info->field->rec, s2->info->field->rec) &&
2068                   cstring_equal (s1->info->field->field, s2->info->field->field))));
2069       }
2070     case SK_PTR:
2071       {
2072         llassert (s1->info->ref != s1);
2073         return ((s2->kind == SK_PTR) && sRef_same (s1->info->ref, s2->info->ref));
2074       }
2075     case SK_ADR:
2076       {
2077         llassert (s1->info->ref != s1);
2078         return ((s2->kind == SK_ADR) && sRef_same (s1->info->ref, s2->info->ref));
2079       }
2080     case SK_CONJ:
2081       llassert (s1->info->conj->a != s1);
2082       llassert (s1->info->conj->b != s1);
2083       return ((sRef_same (s1->info->conj->a, s2)) && /* or or and? */
2084               (sRef_same (s1->info->conj->b, s2)));
2085     case SK_SPECIAL:
2086       return ((s2->kind == SK_SPECIAL) && s1->info->spec == s2->info->spec);
2087     case SK_DERIVED:
2088       llassert (s1->info->ref != s1);
2089       return ((s2->kind == SK_DERIVED) && sRef_same (s1->info->ref, s2->info->ref));
2090     case SK_CONST:
2091     case SK_UNCONSTRAINED:
2092     case SK_TYPE:
2093     case SK_UNKNOWN:
2094     case SK_NEW:
2095     case SK_OBJECT:
2096     case SK_EXTERNAL:
2097     case SK_RESULT:
2098       return FALSE; 
2099     }
2100   BADEXIT;
2101 }
2102
2103 /*
2104 ** sort of similar, for use in def/use
2105 */
2106
2107 static bool
2108 sRef_closeEnough (sRef s1, sRef s2)
2109 {
2110   if (s1 == s2) return TRUE;
2111   if (sRef_isInvalid (s1) || sRef_isInvalid (s2)) return FALSE;
2112
2113   switch (s1->kind)
2114     {
2115     case SK_CVAR:
2116       return (((s2->kind == SK_CVAR) &&
2117                (cref_equal (s1->info->cvar, s2->info->cvar))) ||
2118               (s2->kind == SK_UNCONSTRAINED && s1->info->cvar->lexlevel == 0));
2119     case SK_UNCONSTRAINED:
2120       return (s2->kind == SK_UNCONSTRAINED
2121               || ((s2->kind == SK_CVAR) && (s2->info->cvar->lexlevel == 0)));
2122     case SK_PARAM:
2123       return ((s2->kind == SK_PARAM) 
2124               && (s1->info->paramno == s2->info->paramno));
2125     case SK_ARRAYFETCH:
2126       if (s2->kind == SK_ARRAYFETCH)
2127         {
2128           if (sRef_closeEnough (s1->info->arrayfetch->arr, s2->info->arrayfetch->arr))
2129             {
2130               if (s1->info->arrayfetch->indknown && s2->info->arrayfetch->indknown)
2131                 {
2132                   return (s1->info->arrayfetch->ind == s2->info->arrayfetch->ind);
2133                 }
2134               return TRUE;
2135             }
2136         }
2137       return FALSE;
2138     case SK_FIELD:
2139       return ((s2->kind == SK_FIELD &&
2140                (sRef_closeEnough (s1->info->field->rec, s2->info->field->rec) &&
2141                 cstring_equal (s1->info->field->field, s2->info->field->field))));
2142     case SK_PTR:
2143       return ((s2->kind == SK_PTR) && sRef_closeEnough (s1->info->ref, s2->info->ref));
2144     case SK_ADR:
2145       return ((s2->kind == SK_ADR) && sRef_closeEnough (s1->info->ref, s2->info->ref));
2146     case SK_DERIVED:
2147       return ((s2->kind == SK_DERIVED) && sRef_closeEnough (s1->info->ref, s2->info->ref));
2148     case SK_CONJ:
2149       return ((sRef_closeEnough (s1->info->conj->a, s2)) ||
2150               (sRef_closeEnough (s1->info->conj->b, s2)));
2151     case SK_SPECIAL:
2152       return ((s2->kind == SK_SPECIAL) && s1->info->spec == s2->info->spec);
2153     case SK_TYPE:
2154     case SK_CONST:
2155     case SK_UNKNOWN:
2156     case SK_NEW:
2157     case SK_OBJECT:
2158     case SK_EXTERNAL:
2159     case SK_RESULT:
2160
2161       return FALSE;
2162     }
2163   BADEXIT;
2164 }
2165
2166 /*
2167   drl add 12/24/2000
2168   s is an sRef of a formal paramenter in a function call constraint
2169   we trys to return a constraint expression derived from the actual parementer of a function call.
2170 */
2171
2172 /*@only@*/ constraintExpr sRef_fixConstraintParam (/*@observer@*/  sRef s, /*@observer@*/ /*@temp@*/ exprNodeList args)
2173 {
2174   constraintExpr ce;
2175
2176   if (sRef_isInvalid (s))
2177     llfatalbug((message("Invalid sRef")));
2178
2179   switch (s->kind)
2180     {
2181     case SK_RESULT:
2182       {
2183         /* s = sRef_saveCopy(s); */ /*@i523@*/
2184         ce = constraintExpr_makeTermsRef (s);
2185         return ce;
2186       }
2187     case SK_FIELD:
2188       {
2189         sRef temp;
2190         
2191         temp = (sRef_makeField (sRef_fixBaseParam (s->info->field->rec, args),
2192                               s->info->field->field));
2193         ce = constraintExpr_makeTermsRef (temp);
2194         return ce;
2195       }
2196     case SK_PTR:
2197       {
2198         sRef temp;
2199         temp = (sRef_makePointer (sRef_fixBaseParam (s->info->ref, args)));
2200         /* temp = sRef_saveCopy(temp); */ /*@i523@*/
2201         ce = constraintExpr_makeTermsRef (temp);
2202         return ce;
2203       }
2204
2205     case SK_ARRAYFETCH:
2206        {
2207         sRef temp;
2208         temp = sRef_saveCopy(s);
2209         temp = sRef_fixBaseParam (temp, args);
2210         ce = constraintExpr_makeTermsRef (temp);
2211
2212         sRef_free(temp);
2213         return ce;
2214       }
2215     case SK_CVAR:
2216       {
2217         sRef temp;
2218         temp = sRef_saveCopy(s);
2219         ce = constraintExpr_makeTermsRef (temp);
2220         sRef_free(temp);
2221         return ce;
2222       }
2223     case SK_PARAM:
2224       llassert(exprNodeList_size (args) > s->info->paramno);
2225         {
2226           exprNode e = exprNodeList_nth (args, s->info->paramno);
2227
2228           llassert( !(exprNode_isError (e)) );
2229           ce = constraintExpr_makeExprNode (e);
2230           return ce;
2231         }
2232
2233     default:
2234       {
2235         sRef temp;
2236         llcontbug (message ("Trying to do fixConstraintParam on nonparam, nonglobal: %q for function with arguments %q",
2237                             sRef_unparse (s), exprNodeList_unparse(args)));
2238       temp = sRef_saveCopy(s);
2239       ce = constraintExpr_makeTermsRef (temp);
2240
2241       sRef_free(temp);
2242       return ce;
2243       }
2244     }
2245 }
2246
2247 /*@exposed@*/ sRef
2248 sRef_fixBaseParam (/*@returned@*/ sRef s, exprNodeList args)
2249 {
2250   if (sRef_isInvalid (s)) return (sRef_undefined);
2251
2252   switch (s->kind)
2253     {
2254     case SK_UNCONSTRAINED:
2255     case SK_CVAR:
2256       return s;
2257     case SK_PARAM:
2258       {
2259         if (exprNodeList_size (args) > s->info->paramno)
2260           {
2261             exprNode e = exprNodeList_nth (args, s->info->paramno);
2262
2263             if (exprNode_isError (e))
2264               {
2265                 return sRef_makeUnknown ();
2266               }
2267             
2268             return (exprNode_getSref (e));
2269           }
2270         else
2271           {
2272             return sRef_makeUnknown ();
2273           }
2274       }
2275     case SK_ARRAYFETCH:
2276
2277       if (s->info->arrayfetch->indknown)
2278         {
2279           return (sRef_makeArrayFetchKnown 
2280                   (sRef_fixBaseParam (s->info->arrayfetch->arr, args),
2281                    s->info->arrayfetch->ind));
2282         }
2283       else
2284         {
2285           return (sRef_makeArrayFetch 
2286                   (sRef_fixBaseParam (s->info->arrayfetch->arr, args)));
2287         }
2288     case SK_FIELD:
2289       {
2290         sRef res;
2291         DPRINTF (("Fix field: %s", sRef_unparseFull (s)));
2292         res = sRef_makeField (sRef_fixBaseParam (s->info->field->rec, args),
2293                               s->info->field->field);
2294         DPRINTF (("Returns: %s", sRef_unparseFull (res)));
2295         return res;
2296       }
2297     case SK_PTR:
2298       return (sRef_makePointer (sRef_fixBaseParam (s->info->ref, args)));
2299
2300     case SK_ADR:
2301       return (sRef_makeAddress (sRef_fixBaseParam (s->info->ref, args)));
2302
2303     case SK_CONJ:
2304       return (sRef_makeConj (sRef_fixBaseParam (s->info->conj->a, args),
2305                              sRef_fixBaseParam (s->info->conj->b, args)));
2306     case SK_DERIVED:
2307     case SK_SPECIAL:
2308     case SK_TYPE:
2309     case SK_CONST:
2310     case SK_NEW:
2311     case SK_UNKNOWN:
2312     case SK_OBJECT:
2313     case SK_EXTERNAL:
2314     case SK_RESULT:
2315       return s;
2316     }
2317   BADEXIT;
2318 }
2319
2320 /*@exposed@*/ sRef
2321 sRef_undumpGlobal (char **c)
2322 {
2323   char p = **c;
2324
2325   (*c)++;
2326
2327   switch (p)
2328     {
2329     case 'g':
2330       {
2331         usymId uid = usymId_fromInt (reader_getInt (c));
2332         sstate defstate;
2333         nstate nullstate;
2334         sRef ret;
2335
2336         reader_checkChar (c, '@');
2337         defstate = sstate_fromInt (reader_getInt (c));
2338
2339         reader_checkChar (c, '@');
2340         nullstate = nstate_fromInt (reader_getInt (c));
2341
2342         ret = sRef_makeGlobal (uid, ctype_unknown, stateInfo_currentLoc ());
2343         sRef_setNullStateN (ret, nullstate);
2344         ret->defstate = defstate;
2345         return ret;
2346       }
2347     case 's':
2348       {
2349         int i = reader_getInt (c);
2350         speckind sk = speckind_fromInt (i);
2351
2352         switch (sk)
2353           {
2354           case SR_NOTHING:   return (sRef_makeNothing ());
2355           case SR_INTERNAL:  return (sRef_makeInternalState ());
2356           case SR_SPECSTATE: return (sRef_makeSpecState ());
2357           case SR_SYSTEM:    return (sRef_makeSystemState ());
2358           case SR_GLOBALMARKER: BADBRANCH;
2359           }
2360         BADEXIT;
2361       }
2362     case '-':
2363       return sRef_undefined;
2364     case 'u':
2365       return sRef_makeUnknown ();
2366     case 'x':
2367       return sRef_makeUnknown ();
2368     default:
2369       llfatalerror (message ("sRef_undumpGlobal: bad line: %s",
2370                              cstring_fromChars (*c)));
2371     }
2372   BADEXIT;
2373 }
2374
2375 static /*@exposed@*/ sRef sRef_undumpBody (char **c)
2376 {
2377   char p = **c;
2378
2379   (*c)++;
2380
2381   switch (p)
2382     {
2383     case 'g':
2384       return (sRef_makeGlobal (usymId_fromInt (reader_getInt (c)), ctype_unknown, stateInfo_currentLoc ()));
2385     case 'p':
2386       return (sRef_makeParam (reader_getInt (c), ctype_unknown, stateInfo_makeLoc (g_currentloc)));
2387     case 'r':
2388       return (sRef_makeResult (ctype_undump (c)));
2389     case 'a':
2390       {
2391         if ((**c >= '0' && **c <= '9') || **c == '-')
2392           {
2393             int i = reader_getInt (c);
2394             sRef arr = sRef_undump (c);
2395             sRef ret = sRef_buildArrayFetchKnown (arr, i);
2396
2397             return ret;
2398           }
2399         else
2400           {
2401             sRef arr = sRef_undump (c);
2402             sRef ret = sRef_buildArrayFetch (arr);
2403
2404             return ret;
2405           }
2406       }
2407     case 'f':
2408       {
2409         cstring fname = cstring_undefined;
2410         sRef ret;
2411
2412         while (**c != '.')
2413           {
2414             fname = cstring_appendChar (fname, **c);
2415             (*c)++;
2416           }
2417         (*c)++;
2418
2419         ret = sRef_buildField (sRef_undump (c), fname);
2420         cstring_markOwned (fname);
2421         return (ret);
2422       }
2423     case 's':
2424       {
2425         int i = reader_getInt (c);
2426         speckind sk = speckind_fromInt (i);
2427
2428         switch (sk)
2429           {
2430           case SR_NOTHING:   return (sRef_makeNothing ());
2431           case SR_INTERNAL:  return (sRef_makeInternalState ());
2432           case SR_SPECSTATE: return (sRef_makeSpecState ());
2433           case SR_SYSTEM:    return (sRef_makeSystemState ());
2434           case SR_GLOBALMARKER: BADBRANCH;
2435           }
2436         BADEXIT;
2437       }
2438     case 't':
2439       {
2440         sRef ptr = sRef_undump (c);
2441         sRef ret = sRef_makePointer (ptr);
2442
2443         return (ret);
2444       }
2445     case 'd':
2446       {
2447         sRef adr = sRef_undump (c);
2448         sRef ret = sRef_makeAddress (adr);
2449
2450         return (ret);
2451       }
2452     case 'o':
2453       {
2454         return (sRef_makeObject (ctype_undump (c)));
2455       }
2456     case 'c':
2457       {
2458         sRef s1 = sRef_undump (c);
2459         sRef s2 = ((*c)++, sRef_undump (c));
2460         sRef ret = sRef_makeConj (s1, s2);
2461
2462         return (ret);
2463       }
2464     case '-':
2465       return sRef_undefined;
2466     case 'u':
2467       return sRef_makeUnknown ();
2468     case 'x':
2469       return sRef_makeUnknown ();
2470     default:
2471       llfatalerror (message ("sRef_undump: bad line: %s", cstring_fromChars (*c)));
2472     }
2473   BADEXIT;
2474 }
2475
2476 /*@exposed@*/ sRef sRef_undump (char **c)
2477 {
2478   sRef res = sRef_undumpBody (c);
2479
2480   if (reader_optCheckChar (c, '='))
2481     {
2482       multiVal mv = multiVal_undump (c);
2483       sRef_setValue (res, mv);
2484       reader_checkChar (c, '=');
2485     }
2486
2487   return res;
2488 }
2489
2490 static /*@only@*/ cstring sRef_dumpBody (sRef s)
2491 {
2492   if (sRef_isInvalid (s))
2493     {
2494       return (cstring_makeLiteral ("-"));
2495     }
2496   else
2497     {
2498       switch (s->kind)
2499         {
2500         case SK_PARAM:
2501           return (message ("p%d", s->info->paramno));
2502         case SK_ARRAYFETCH:
2503           if (s->info->arrayfetch->indknown)
2504             {
2505               return (message ("a%d%q", s->info->arrayfetch->ind,
2506                                sRef_dump (s->info->arrayfetch->arr)));
2507             }
2508           else
2509             {
2510               return (message ("a%q", sRef_dump (s->info->arrayfetch->arr)));
2511             }
2512         case SK_FIELD:
2513           return (message ("f%s.%q", s->info->field->field, 
2514                            sRef_dump (s->info->field->rec)));
2515         case SK_PTR:
2516           return (message ("t%q", sRef_dump (s->info->ref)));
2517         case SK_ADR:
2518           return (message ("d%q", sRef_dump (s->info->ref)));
2519         case SK_OBJECT:
2520           return (message ("o%q", ctype_dump (s->info->object)));
2521         case SK_SPECIAL:
2522           return (message ("s%d", (int) s->info->spec));
2523         case SK_CONJ:
2524           return (message ("c%q.%q",
2525                            sRef_dump (s->info->conj->a),
2526                            sRef_dump (s->info->conj->b)));
2527         case SK_CVAR:
2528           if (sRef_isFileOrGlobalScope (s))
2529             {
2530               return (message ("g%d", 
2531                                usymtab_convertId (s->info->cvar->index)));
2532             }
2533           else
2534             {
2535               llcontbug (message ("Dumping local variable: %q",
2536                                   sRef_unparseDebug (s)));
2537               return (cstring_makeLiteral ("u"));
2538             }
2539         case SK_UNKNOWN:
2540           return (cstring_makeLiteral ("u"));
2541         case SK_RESULT:
2542           return (message ("r%q", ctype_dump (s->type)));
2543         case SK_TYPE:
2544         case SK_CONST:
2545         case SK_EXTERNAL:
2546         case SK_DERIVED:
2547         case SK_NEW:
2548         case SK_UNCONSTRAINED:
2549           llcontbug (message ("sRef_dump: bad kind: %q",
2550                               sRef_unparseFull (s)));
2551           return (cstring_makeLiteral ("x"));
2552         }
2553     }
2554      
2555   BADEXIT;
2556 }
2557
2558 /*@only@*/ cstring sRef_dump (sRef s)
2559 {
2560   cstring res = sRef_dumpBody (s);
2561
2562   if (sRef_hasValue (s))
2563     {
2564       res = message ("%q=%q=", res, multiVal_dump (sRef_getValue (s)));
2565     }
2566
2567   return res;
2568 }
2569
2570 cstring sRef_dumpGlobal (sRef s)
2571 {
2572   llassert (!sRef_hasValue (s));
2573
2574   if (sRef_isInvalid (s))
2575     {
2576       return (cstring_makeLiteral ("-"));
2577     }
2578   else
2579     {
2580       switch (s->kind)
2581         {
2582         case SK_CVAR:
2583           if (sRef_isFileOrGlobalScope (s))
2584             {
2585               return (message ("g%d@%d@%d", 
2586                                usymtab_convertId (s->info->cvar->index),
2587                                (int) s->defstate,
2588                                (int) sRef_getNullState (s)));
2589             }
2590           else
2591             {
2592               llcontbug (message ("Dumping local variable: %q",
2593                                   sRef_unparseDebug (s)));
2594               return (cstring_makeLiteral ("u"));
2595             }
2596         case SK_UNKNOWN:
2597           return (cstring_makeLiteral ("u"));
2598         case SK_SPECIAL:
2599           return (message ("s%d", (int) s->info->spec));
2600         default:
2601           llcontbug (message ("sRef_dumpGlobal: bad kind: %q",
2602                               sRef_unparseFull (s)));
2603           return (cstring_makeLiteral ("x"));
2604         }
2605     }
2606      
2607   BADEXIT;
2608 }
2609
2610 ctype
2611 sRef_deriveType (sRef s, uentryList cl)
2612 {
2613   if (sRef_isInvalid (s)) return ctype_unknown;
2614
2615   switch (s->kind)
2616     {
2617     case SK_CVAR:
2618       return (uentry_getType (usymtab_getRefQuiet (s->info->cvar->lexlevel, 
2619                                               s->info->cvar->index)));
2620     case SK_UNCONSTRAINED:
2621       return (ctype_unknown);
2622     case SK_PARAM:
2623       if (s->info->paramno >= 0) 
2624         {
2625           return uentry_getType (uentryList_getN (cl, s->info->paramno));
2626         }
2627       else
2628         {
2629           return ctype_unknown;
2630         }
2631     case SK_ARRAYFETCH:
2632       {
2633         ctype ca = sRef_deriveType (s->info->arrayfetch->arr, cl);
2634         
2635         if (ctype_isArray (ca))
2636           {
2637             return (ctype_baseArrayPtr (ca));
2638           }
2639         else if (ctype_isUnknown (ca))
2640           {
2641             return (ca);
2642           }
2643         else
2644           {
2645             llcontbuglit ("sRef_deriveType: inconsistent array type");
2646             return ca;
2647           }
2648       }
2649     case SK_FIELD:
2650       {
2651         ctype ct = sRef_deriveType (s->info->field->rec, cl);
2652         
2653         if (ctype_isStructorUnion (ct))
2654           {
2655             uentry ue = uentryList_lookupField (ctype_getFields (ct), 
2656                                                s->info->field->field);
2657             
2658             if (uentry_isValid (ue))
2659               {
2660                 return (uentry_getType (ue));
2661               }
2662             else
2663               {
2664                 llcontbuglit ("sRef_deriveType: bad field");
2665                 return ctype_unknown;
2666               }
2667           }
2668         else if (ctype_isUnknown (ct))
2669           {
2670             return (ct);
2671           }
2672         else
2673           {
2674             llcontbuglit ("sRef_deriveType: inconsistent field type");
2675             return (ct);
2676           }
2677       }
2678     case SK_PTR:
2679       {
2680         ctype ct = sRef_deriveType (s->info->ref, cl);
2681         
2682         if (ctype_isUnknown (ct)) return ct;
2683         if (ctype_isPointer (ct)) return (ctype_baseArrayPtr (ct));
2684         else
2685           {
2686             llcontbuglit ("sRef_deriveType: inconsistent pointer type");
2687             return (ct);
2688           }
2689       }
2690     case SK_ADR:
2691       {
2692         ctype ct = sRef_deriveType (s->info->ref, cl);
2693         
2694         if (ctype_isUnknown (ct)) return ct;
2695         return ctype_makePointer (ct);
2696       }
2697     case SK_DERIVED:
2698       {
2699         return sRef_deriveType (s->info->ref, cl);
2700       }
2701     case SK_OBJECT:
2702       {
2703         return (s->info->object);
2704       }
2705     case SK_CONJ:
2706       {
2707         return (ctype_makeConj (sRef_deriveType (s->info->conj->a, cl),
2708                                sRef_deriveType (s->info->conj->b, cl)));
2709       }
2710     case SK_RESULT:
2711     case SK_CONST:
2712     case SK_TYPE:
2713       {
2714         return (s->type);
2715       }
2716     case SK_SPECIAL:
2717     case SK_UNKNOWN:
2718     case SK_EXTERNAL:
2719     case SK_NEW:
2720       return ctype_unknown;
2721     }
2722   BADEXIT;
2723 }
2724
2725 ctype
2726 sRef_getType (sRef s)
2727 {
2728   if (sRef_isInvalid (s)) return ctype_unknown;
2729   return s->type;
2730 }
2731
2732
2733 /*@only@*/ cstring
2734 sRef_unparseOpt (sRef s)
2735 {
2736   sRef rb = sRef_getRootBase (s);
2737
2738   if (sRef_isMeaningful (rb) && !sRef_isConst (rb))
2739     {
2740       cstring ret = sRef_unparse (s);
2741       
2742       llassertprint (!cstring_equalLit (ret, "?"), ("print: %s", sRef_unparseDebug (s)));
2743
2744       if (!cstring_isEmpty (ret))
2745         {
2746           return (cstring_appendChar (ret, ' '));
2747         }
2748       else
2749         {
2750           return ret;
2751         }
2752     }
2753
2754   return cstring_undefined;
2755 }
2756
2757 cstring
2758 sRef_unparsePreOpt (sRef s)
2759 {
2760   sRef rb = sRef_getRootBase (s);
2761
2762   if (sRef_isMeaningful (rb) && !sRef_isConst (rb))
2763     {
2764       cstring ret = sRef_unparse (s);
2765       
2766       llassertprint (!cstring_equalLit (ret, "?"), ("print: %s", sRef_unparseDebug (s)));
2767       return (cstring_prependCharO (' ', ret));
2768     }
2769
2770   return cstring_undefined;
2771 }
2772
2773 /*@only@*/ cstring
2774 sRef_unparse (sRef s)
2775 {
2776   if (sRef_isInvalid (s)) return (cstring_makeLiteral ("?"));
2777
2778   if (context_inFunctionLike ())
2779     {
2780       return (sRef_unparseWithArgs (s, context_getParams ()));
2781     }
2782   else
2783     {
2784       DPRINTF (("Not in function like: %s", context_unparse ()));
2785       return (sRef_unparseNoArgs (s));
2786     }
2787 }
2788
2789 static /*@only@*/ cstring
2790 sRef_unparseWithArgs (sRef s, uentryList args)
2791 {
2792   if (sRef_isInvalid (s))
2793     {
2794       return (cstring_makeLiteral ("?"));
2795     }
2796
2797   switch (s->kind)
2798     {
2799     case SK_CVAR:
2800       return (uentry_getName (usymtab_getRefQuiet (s->info->cvar->lexlevel,
2801                                                    s->info->cvar->index)));
2802     case SK_UNCONSTRAINED:
2803       return (cstring_copy (s->info->fname));
2804     case SK_PARAM:
2805       {
2806         if (s->info->paramno < uentryList_size (args)
2807             && s->info->paramno >= 0)
2808           {
2809             uentry ue = uentryList_getN (args, s->info->paramno);
2810             
2811             if (uentry_isValid (ue))
2812               return uentry_getName (ue);
2813           }
2814
2815         return (message ("parameter %d", s->info->paramno + 1));
2816       }
2817     case SK_ARRAYFETCH:
2818       if (s->info->arrayfetch->indknown)
2819         {
2820           return (message ("%q[%d]", sRef_unparseWithArgs (s->info->arrayfetch->arr, args),
2821                                 s->info->arrayfetch->ind));
2822         }
2823       else
2824         {
2825           return (message ("%q[]", sRef_unparseWithArgs (s->info->arrayfetch->arr, args)));
2826         }
2827     case SK_FIELD:
2828       if (s->info->field->rec->kind == SK_PTR)
2829         {
2830           sRef ptr = s->info->field->rec;
2831
2832           return (message ("%q->%s", sRef_unparseWithArgs (ptr->info->ref, args),
2833                            s->info->field->field));       
2834         }
2835       return (message ("%q.%s", sRef_unparseWithArgs (s->info->field->rec, args),
2836                        s->info->field->field));
2837
2838     case SK_PTR:
2839       {
2840         sRef ref = sRef_fixConj (s->info->ref);
2841         skind sk = ref->kind;
2842         cstring ret;
2843
2844         if (sk == SK_NEW)
2845           {
2846             ret = message ("storage pointed to by %q",
2847                            sRef_unparseWithArgs (ref, args));
2848           }
2849         else if (skind_isSimple (sk) || sk == SK_PTR)
2850           {
2851             ret = message ("*%q", sRef_unparseWithArgs (ref, args));
2852           }
2853         else
2854           {
2855             ret = message ("*(%q)", sRef_unparseWithArgs (ref, args));
2856           }
2857
2858         return ret;
2859       }
2860     case SK_ADR:
2861       return (message ("&%q", sRef_unparseWithArgs (s->info->ref, args)));
2862     case SK_OBJECT:
2863       return (cstring_copy (ctype_unparse (s->info->object)));
2864     case SK_CONJ:
2865       return (sRef_unparseWithArgs (sRef_getConjA (s), args));
2866     case SK_NEW:
2867       if (cstring_isDefined (s->info->fname))
2868         {
2869           return (message ("[result of %s]", s->info->fname));
2870         }
2871       else
2872         {
2873           return (cstring_makeLiteral ("<new>"));
2874         }
2875     case SK_UNKNOWN:
2876       return (cstring_makeLiteral ("?"));
2877     case SK_DERIVED:
2878       return (message ("<derived %q>", sRef_unparse (s->info->ref)));
2879     case SK_EXTERNAL:
2880       return (message ("<external %q>", sRef_unparse (s->info->ref)));
2881     case SK_TYPE:
2882       return (message ("<type %s>", ctype_unparse (s->type)));
2883     case SK_CONST:
2884       return (message ("<const %s>", ctype_unparse (s->type)));
2885     case SK_SPECIAL:
2886       switch (s->info->spec)
2887         {
2888         case SR_NOTHING: return cstring_makeLiteral ("nothing");
2889         case SR_INTERNAL: return cstring_makeLiteral ("internal state");
2890         case SR_SPECSTATE: return cstring_makeLiteral ("spec state");
2891         case SR_SYSTEM: return cstring_makeLiteral ("file system state");
2892         case SR_GLOBALMARKER: return cstring_makeLiteral ("<global marker>");
2893         }
2894       BADBRANCH;
2895     case SK_RESULT:
2896       return cstring_makeLiteral ("result");
2897     default:
2898       {
2899         llbug (message ("Bad sref, kind = %d", (int) s->kind));
2900       }
2901     }
2902
2903   BADEXIT;
2904 }
2905
2906 /*@only@*/ cstring
2907 sRef_unparseDebug (sRef s)
2908 {
2909   if (sRef_isInvalid (s)) 
2910     {
2911       return (cstring_makeLiteral ("<undef>"));
2912     }
2913
2914
2915   switch (s->kind)
2916     {
2917     case SK_UNCONSTRAINED:
2918       return (message ("<unconstrained %s>", s->info->fname));
2919     case SK_CVAR:
2920       {
2921         uentry ce;
2922
2923         ce = usymtab_getRefQuiet (s->info->cvar->lexlevel, s->info->cvar->index);
2924
2925         if (uentry_isInvalid (ce))
2926           {
2927             return (message ("<scope: %d.%d *invalid*>", 
2928                              s->info->cvar->lexlevel,
2929                              s->info->cvar->index));
2930           }
2931         else
2932           {
2933             return (message ("<scope: %d.%d *%q*>", 
2934                              s->info->cvar->lexlevel,
2935                              s->info->cvar->index,
2936                              uentry_getName (ce)));
2937           }
2938
2939       }
2940     case SK_PARAM:
2941       {
2942         return (message ("<parameter %d>", s->info->paramno + 1));
2943       }
2944     case SK_ARRAYFETCH:
2945       if (s->info->arrayfetch->indknown)
2946         {
2947           return (message ("%q[%d]", sRef_unparseDebug (s->info->arrayfetch->arr),
2948                            s->info->arrayfetch->ind));
2949         }
2950       else
2951         {
2952           return (message ("%q[]", sRef_unparseDebug (s->info->arrayfetch->arr)));
2953         }
2954     case SK_FIELD:
2955       return (message ("%q.%s", sRef_unparseDebug (s->info->field->rec),
2956                        s->info->field->field));
2957     case SK_PTR:
2958       if (sRef_isField (s->info->ref)) 
2959         {
2960           sRef fld = s->info->ref;
2961
2962           return (message ("%q->%s", sRef_unparseDebug (fld->info->field->rec),
2963                            fld->info->field->field));
2964         }
2965       else
2966         {
2967           return (message ("*(%q)", sRef_unparseDebug (s->info->ref)));
2968         }
2969     case SK_ADR:
2970       return (message ("&%q", sRef_unparseDebug (s->info->ref)));
2971     case SK_OBJECT:
2972       return (message ("<object type %s>", ctype_unparse (s->info->object)));
2973     case SK_CONJ:
2974       return (message ("%q | %q", sRef_unparseDebug (s->info->conj->a),
2975                        sRef_unparseDebug (s->info->conj->b)));
2976     case SK_NEW:
2977       return message ("<new: %s>", s->info->fname);
2978     case SK_DERIVED:
2979       return (message ("<derived %q>", sRef_unparseDebug (s->info->ref)));
2980     case SK_EXTERNAL:
2981       return (message ("<external %q>", sRef_unparseDebug (s->info->ref)));
2982     case SK_TYPE:
2983       return (message ("<type %s>", ctype_unparse (s->type)));
2984     case SK_CONST:
2985       if (sRef_hasValue (s))
2986         {
2987           return (message ("<const %s=%q>", ctype_unparse (s->type), multiVal_unparse (sRef_getValue (s))));
2988         }
2989       else
2990         {
2991           return (message ("<const %s>", ctype_unparse (s->type)));
2992         }
2993     case SK_RESULT:
2994       return (message ("<result %s>", ctype_unparse (s->type)));
2995     case SK_SPECIAL:
2996       return (message ("<spec %s>",
2997                        cstring_makeLiteralTemp
2998                        (s->info->spec == SR_NOTHING ? "nothing"
2999                         : s->info->spec == SR_INTERNAL ? "internalState"
3000                         : s->info->spec == SR_SPECSTATE ? "spec state"
3001                         : s->info->spec == SR_SYSTEM ? "fileSystem"
3002                         : "error")));
3003     case SK_UNKNOWN:
3004       return cstring_makeLiteral ("<unknown>");
3005     }
3006
3007   BADEXIT;
3008 }
3009
3010 static /*@only@*/ cstring
3011 sRef_unparseNoArgs (sRef s)
3012 {
3013   if (sRef_isInvalid (s)) return (cstring_makeLiteral ("?"));
3014
3015   switch (s->kind)
3016     {
3017     case SK_UNCONSTRAINED:
3018       return (cstring_copy (s->info->fname));
3019     case SK_CVAR:
3020       {
3021         uentry ce = usymtab_getRefQuiet (s->info->cvar->lexlevel, 
3022                                          s->info->cvar->index);
3023
3024         if (uentry_isInvalid (ce))
3025           {
3026             llcontbug (message ("sRef_unparseNoArgs: bad cvar: %q", 
3027                                 sRef_unparseDebug (s)));
3028             return (sRef_unparseDebug (s)); 
3029           }
3030         else
3031           {
3032             return (uentry_getName (ce));
3033           }
3034       }
3035     case SK_ARRAYFETCH:
3036       if (s->info->arrayfetch->indknown)
3037         {
3038           return (message ("%q[%d]", sRef_unparseNoArgs (s->info->arrayfetch->arr),
3039                            s->info->arrayfetch->ind));
3040         }
3041       else
3042         {
3043           return (message ("%q[]", sRef_unparseNoArgs (s->info->arrayfetch->arr)));
3044         }
3045     case SK_FIELD:
3046       return (message ("%q.%s", sRef_unparseNoArgs (s->info->field->rec),
3047                        s->info->field->field));
3048     case SK_PTR:
3049       {
3050         sRef ref = sRef_fixConj (s->info->ref);
3051         skind sk = ref->kind;
3052         cstring ret;
3053
3054         if (skind_isSimple (sk) || sk == SK_PTR)
3055           {
3056             ret = message ("*%q", sRef_unparseNoArgs (ref));
3057           }
3058         else
3059           {
3060             ret = message ("*(%q)", sRef_unparseNoArgs (ref));
3061           }
3062
3063         return (ret);
3064       }
3065     case SK_ADR:
3066       return (message ("&%q", sRef_unparseNoArgs (s->info->ref)));
3067     case SK_OBJECT:
3068       return (cstring_copy (ctype_unparse (s->info->object)));
3069     case SK_CONJ:
3070       return (sRef_unparseNoArgs (s->info->conj->a));
3071     case SK_NEW:
3072       return (message ("result of %s", s->info->fname));
3073     case SK_DERIVED:
3074       return (message ("<der %q>", sRef_unparseNoArgs (s->info->ref)));
3075     case SK_EXTERNAL:
3076       return message ("<ext %q>", sRef_unparseNoArgs (s->info->ref));
3077     case SK_SPECIAL:
3078       return (cstring_makeLiteral
3079               (s->info->spec == SR_NOTHING ? "nothing"
3080                : s->info->spec == SR_INTERNAL ? "internal state"
3081                : s->info->spec == SR_SPECSTATE ? "spec state"
3082                : s->info->spec == SR_SYSTEM ? "file system state"
3083                : "<spec error>"));
3084     case SK_RESULT:
3085       return cstring_makeLiteral ("result");
3086     case SK_CONST:
3087     case SK_TYPE:
3088     case SK_UNKNOWN:
3089       return cstring_makeLiteral ("?");
3090     case SK_PARAM:
3091       /* llcontbug (message ("sRef_unparseNoArgs: bad case: %q", sRef_unparseDebug (s))); */
3092       return (sRef_unparseDebug (s));
3093     }
3094   BADEXIT;
3095 }
3096
3097 /*@dependent@*/ sRef sRef_makeUnconstrained (cstring fname)
3098 {
3099   sRef s = sRef_new ();
3100
3101   s->kind = SK_UNCONSTRAINED;
3102   s->info = (sinfo) dmalloc (sizeof (*s->info));
3103   s->info->fname = fname;
3104
3105   return (s);
3106 }
3107
3108 cstring sRef_unconstrainedName (sRef s)
3109 {
3110   llassert (sRef_isUnconstrained (s));
3111
3112   return s->info->fname;
3113 }
3114
3115 bool sRef_isUnconstrained (sRef s) 
3116 {
3117   return (sRef_isValid(s) && s->kind == SK_UNCONSTRAINED);
3118 }
3119
3120 static /*@dependent@*/ /*@notnull@*/ sRef 
3121   sRef_makeCvarAux (int level, usymId index, ctype ct, /*@only@*/ stateInfo stinfo)
3122 {
3123   sRef s = sRef_newRef ();
3124   
3125   s->kind = SK_CVAR;
3126   s->info = (sinfo) dmalloc (sizeof (*s->info));
3127
3128   s->info->cvar = (cref) dmalloc (sizeof (*s->info->cvar));
3129   s->info->cvar->lexlevel = level;
3130   s->info->cvar->index = index;
3131
3132   /* for now, all globals are defined; all locals, aren't */
3133
3134   if (level <= fileScope)
3135     {
3136       s->defstate = SS_UNKNOWN;
3137     }
3138   else 
3139     {
3140       ctype rct = ctype_realType (ct);
3141
3142       if (level != paramsScope
3143           && (ctype_isStructorUnion (rct) || ctype_isRealArray (rct)))
3144         {
3145           s->defstate = SS_ALLOCATED; 
3146           s->oaliaskind = s->aliaskind = AK_STACK;
3147         }
3148       else
3149         {
3150           s->defstate = SS_UNDEFINED;
3151           s->oaliaskind = s->aliaskind = AK_LOCAL;
3152         }
3153     }
3154
3155   s->type = ct;
3156
3157   llassert (level >= globScope);
3158   llassert (usymId_isValid (index));
3159
3160   DPRINTF (("Made cvar: [%p] %s", s, sRef_unparseDebug (s)));
3161   llassert (valueTable_isUndefined (s->state));
3162   s->state = context_createValueTable (s, stinfo); 
3163   return s;
3164 }
3165
3166 /*@dependent@*/ sRef sRef_makeCvar (int level, usymId index, ctype ct, /*@only@*/ stateInfo stinfo)
3167 {
3168   return (sRef_makeCvarAux (level, index, ct, stinfo));
3169 }
3170
3171 int sRef_lexLevel (sRef s)
3172 {
3173   if (sRef_isValid (s))
3174     {
3175       sRef conj;
3176
3177       conj = sRef_fixConj (s);
3178       s = sRef_getRootBase (conj);
3179       
3180       if (sRef_isValid (s) && s->kind == SK_CVAR)
3181         {
3182           return (s->info->cvar->lexlevel);
3183         }
3184     }
3185
3186   return globScope;
3187 }
3188
3189 sRef
3190 sRef_makeGlobal (usymId l, ctype ct, /*@only@*/ stateInfo stinfo)
3191 {
3192   return (sRef_makeCvar (globScope, l, ct, stinfo));
3193 }
3194
3195 void
3196 sRef_setParamNo (sRef s, int l)
3197 {
3198   llassert (sRef_isValid (s) && s->kind == SK_PARAM);
3199   s->info->paramno = l;
3200   llassert (l >= -1);
3201 }
3202
3203 /*@dependent@*/ sRef
3204 sRef_makeParam (int l, ctype ct, stateInfo stinfo)
3205 {
3206   sRef s = sRef_new ();
3207
3208   s->kind = SK_PARAM;
3209   s->type = ct;
3210
3211   s->info = (sinfo) dmalloc (sizeof (*s->info));
3212   s->info->paramno = l; 
3213   llassert (l >= -1);
3214   s->defstate = SS_UNKNOWN; 
3215   /* (probably defined, unless its an out parameter) */
3216
3217   llassert (valueTable_isUndefined (s->state));
3218   s->state = context_createValueTable (s, stinfo);
3219   return s;
3220 }
3221
3222 bool
3223 sRef_isIndexKnown (sRef arr)
3224 {
3225   bool res;
3226
3227   llassert (sRef_isValid (arr));
3228   arr = sRef_fixConj (arr);
3229   
3230   llassert (arr->kind == SK_ARRAYFETCH);  
3231   res = arr->info->arrayfetch->indknown;
3232   return (res);
3233 }
3234
3235 int
3236 sRef_getIndex (sRef arr)
3237 {
3238   int result;
3239
3240   llassert (sRef_isValid (arr));
3241   arr = sRef_fixConj (arr);
3242
3243   llassert (arr->kind == SK_ARRAYFETCH);  
3244
3245   if (!arr->info->arrayfetch->indknown)
3246     {
3247       llcontbug (message ("sRef_getIndex: unknown: %q", sRef_unparse (arr)));
3248       result = 0; 
3249     }
3250   else
3251     {
3252       result = arr->info->arrayfetch->ind;
3253     }
3254
3255   return result;
3256 }
3257
3258 static bool sRef_isZerothArrayFetch (/*@notnull@*/ sRef s)
3259 {
3260   return (s->kind == SK_ARRAYFETCH
3261           && s->info->arrayfetch->indknown
3262           && (s->info->arrayfetch->ind == 0));
3263 }
3264
3265 /*@exposed@*/ sRef sRef_makeAddress (/*@exposed@*/ sRef t)
3266 {
3267   
3268   if (sRef_isInvalid (t)) return sRef_undefined;
3269
3270   if (sRef_isPointer (t))
3271     {
3272       return (t->info->ref);
3273     }
3274   else if (sRef_isZerothArrayFetch (t))
3275     {
3276       return (t->info->arrayfetch->arr);
3277     }
3278   else
3279     {
3280       sRef s = sRef_newRef ();
3281       
3282       s->kind = SK_ADR;
3283       s->type = ctype_makePointer (t->type);
3284       s->info = (sinfo) dmalloc (sizeof (*s->info));
3285       s->info->ref = t; /* sRef_copy (t);  */ /*@i32@*/
3286       
3287       if (t->defstate == SS_UNDEFINED) 
3288         /* no! it is allocated even still: && !ctype_isPointer (t->type)) */
3289         {
3290           s->defstate = SS_ALLOCATED;
3291         }
3292       else
3293         {
3294           s->defstate = t->defstate;
3295         }
3296
3297       if (t->aliaskind == AK_LOCAL)
3298         {
3299           if (sRef_isLocalVar (t))
3300             {
3301               s->aliaskind = AK_STACK;
3302             }
3303         }
3304
3305       llassert (valueTable_isUndefined (s->state));
3306       s->state = context_createValueTable (s, stateInfo_makeLoc (g_currentloc));
3307       return s;
3308     }
3309 }
3310
3311 cstring sRef_getField (sRef s)
3312 {
3313   cstring res;
3314
3315   llassert (sRef_isValid (s));
3316   s = sRef_fixConj (s);
3317
3318   llassertprint (sRef_isValid (s) && (s->kind == SK_FIELD),
3319                  ("s = %s", sRef_unparseDebug (s)));
3320
3321   res = s->info->field->field;
3322   return (res);
3323 }
3324
3325 sRef sRef_getBase (sRef s)
3326 {
3327   sRef res;
3328
3329   if (sRef_isInvalid (s)) return (sRef_undefined);
3330
3331   s = sRef_fixConj (s);
3332
3333   switch (s->kind)
3334     {
3335     case SK_ADR:
3336     case SK_PTR:
3337     case SK_DERIVED:
3338     case SK_EXTERNAL:
3339       res = s->info->ref;
3340       break;
3341     case SK_FIELD:
3342       res = s->info->field->rec;
3343       break;
3344
3345     case SK_ARRAYFETCH:
3346       res = s->info->arrayfetch->arr;
3347       break;
3348
3349     default:
3350       res = sRef_undefined; /* shouldn't need it */
3351     }
3352
3353   return (res);
3354 }
3355
3356 /*
3357 ** same as getBase, except returns invalid
3358 ** (and doesn't use adr's)                   
3359 */
3360
3361 sRef
3362 sRef_getBaseSafe (sRef s)
3363 {
3364   sRef res;
3365
3366   if (sRef_isInvalid (s)) { return sRef_undefined; }
3367
3368   s = sRef_fixConj (s);
3369
3370   switch (s->kind)
3371     {
3372     case SK_PTR:
3373             res = s->info->ref; 
3374       break;
3375     case SK_FIELD:
3376             res = s->info->field->rec; break;
3377     case SK_ARRAYFETCH:
3378             res = s->info->arrayfetch->arr; 
3379       break;
3380     default:
3381       res = sRef_undefined; break;
3382     }
3383
3384   return res;
3385 }
3386
3387 /*@constant int MAXBASEDEPTH;@*/
3388 # define MAXBASEDEPTH 25
3389
3390 static /*@exposed@*/ sRef 
3391 sRef_getRootBaseAux (sRef s, int depth)
3392 {
3393   if (sRef_isInvalid (s)) return sRef_undefined;
3394
3395   if (depth > MAXBASEDEPTH)
3396     {
3397       llgenmsg (message 
3398                 ("Warning: reference base limit exceeded for %q. "
3399                  "This either means there is a variable with at least "
3400                  "%d indirections from this reference, or "
3401                  "there is a bug in Splint.",
3402                  sRef_unparse (s),
3403                  MAXBASEDEPTH),
3404                 g_currentloc);
3405
3406       return sRef_undefined;
3407     }
3408
3409   switch (s->kind)
3410     {
3411     case SK_ADR:
3412     case SK_PTR:
3413       return (sRef_getRootBaseAux (s->info->ref, depth + 1));
3414     case SK_FIELD:
3415       return (sRef_getRootBaseAux (s->info->field->rec, depth + 1));
3416     case SK_ARRAYFETCH:
3417       return (sRef_getRootBaseAux (s->info->arrayfetch->arr, depth + 1));
3418     case SK_CONJ:
3419       return (sRef_getRootBaseAux (sRef_fixConj (s), depth + 1));
3420     default:
3421       return s;
3422     }
3423 }
3424
3425 sRef sRef_getRootBase (sRef s)
3426 {
3427   return (sRef_getRootBaseAux (s, 0));
3428 }
3429
3430 static bool sRef_isDeep (sRef s)
3431 {
3432   if (sRef_isInvalid (s)) return FALSE;
3433   
3434   switch (s->kind)
3435     {
3436     case SK_ADR:
3437     case SK_PTR:
3438     case SK_FIELD:
3439     case SK_ARRAYFETCH:
3440       return TRUE;
3441     case SK_CONJ:
3442       return (sRef_isDeep (sRef_fixConj (s)));
3443     default:
3444       return FALSE;
3445     }
3446 }
3447
3448 static int sRef_depth (sRef s)
3449 {
3450   if (sRef_isInvalid (s)) return 0;
3451   
3452   switch (s->kind)
3453     {
3454     case SK_ADR:
3455     case SK_PTR:
3456     case SK_DERIVED:
3457     case SK_EXTERNAL:
3458       return 1 + sRef_depth (s->info->ref);
3459     case SK_FIELD:
3460       return 1 + sRef_depth (s->info->field->rec);
3461     case SK_ARRAYFETCH:
3462       return 1 + sRef_depth (s->info->arrayfetch->arr);
3463     case SK_CONJ:
3464       return (sRef_depth (sRef_fixConj (s)));
3465     default:
3466       return 1;
3467     }
3468 }
3469
3470 sRef
3471 sRef_makeObject (ctype o)
3472 {
3473   sRef s = sRef_newRef (); /*@i423 same line is bad...@*/
3474
3475   s->kind = SK_OBJECT;
3476   s->info = (sinfo) dmalloc (sizeof (*s->info));
3477   s->info->object = o;
3478   llassert (valueTable_isUndefined (s->state));
3479   s->state = context_createValueTable (s, stateInfo_makeLoc (g_currentloc));
3480   return s;
3481 }
3482
3483 /*
3484 ** This is used to represent storage referenced by a parameter.
3485 */
3486
3487 sRef sRef_makeExternal (sRef t)
3488 {
3489   sRef s = sRef_newRef ();
3490
3491   llassert (sRef_isValid (t));
3492
3493   s->kind = SK_EXTERNAL;
3494   s->info = (sinfo) dmalloc (sizeof (*s->info));
3495   s->type = t->type;
3496   s->info->ref = t; /* sRef_copy (t); */ /*@i32 was exposed@*/
3497   llassert (valueTable_isUndefined (s->state));
3498   s->state = context_createValueTable (s, stateInfo_makeLoc (g_currentloc));
3499   return s;
3500 }
3501
3502 /*@dependent@*/ sRef sRef_makeDerived (/*@exposed@*/ sRef t)
3503 {
3504   if (sRef_isValid (t))
3505     {
3506       sRef s = sRef_newRef ();
3507       
3508       s->kind = SK_DERIVED;
3509       s->info = (sinfo) dmalloc (sizeof (*s->info));
3510       s->info->ref = t; /* sRef_copy (t); */ /*@i32@*/ 
3511       
3512       s->type = t->type;
3513       llassert (valueTable_isUndefined (s->state));
3514       s->state = context_createValueTable (s, stateInfo_makeLoc (g_currentloc));
3515       return s;
3516     }
3517   else
3518     {
3519       return sRef_undefined;
3520     }
3521 }
3522
3523 /*
3524 ** definitely NOT symmetric:
3525 **
3526 **   res fills in unknown state information from other
3527 */
3528
3529 void
3530 sRef_mergeStateQuiet (sRef res, sRef other)
3531 {
3532   llassert (sRef_isValid (res));
3533   llassert (sRef_isValid (other));
3534
3535   res->modified = res->modified || other->modified;
3536   res->safe = res->safe && other->safe;
3537
3538   if (res->defstate == SS_UNKNOWN) 
3539     {
3540       res->defstate = other->defstate;
3541       res->definfo = stateInfo_update (res->definfo, other->definfo);
3542     }
3543
3544   if (res->aliaskind == AK_UNKNOWN || 
3545       (res->aliaskind == AK_LOCAL && alkind_isKnown (other->aliaskind)))
3546     {
3547       res->aliaskind = other->aliaskind;
3548       res->oaliaskind = other->oaliaskind;
3549       res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
3550     }
3551
3552   if (res->expkind == XO_UNKNOWN)
3553     {
3554       res->expkind = other->expkind;
3555       res->oexpkind = other->oexpkind;
3556       res->expinfo = stateInfo_update (res->expinfo, other->expinfo);
3557     }
3558   
3559   /* out takes precedence over implicitly defined */
3560   if (res->defstate == SS_DEFINED && other->defstate != SS_UNKNOWN) 
3561     {
3562       res->defstate = other->defstate;
3563       res->definfo = stateInfo_update (res->definfo, other->definfo);
3564     }
3565
3566   if (sRef_getNullState (other) == NS_ERROR || sRef_getNullState (res) == NS_ERROR) 
3567     {
3568       sRef_setNullState (res, NS_ERROR, fileloc_undefined);
3569     }
3570   else
3571     {
3572       if (sRef_getNullState (other) != NS_UNKNOWN 
3573           && (sRef_getNullState (res) == NS_UNKNOWN || sRef_getNullState (res) == NS_NOTNULL 
3574               || sRef_getNullState (res) == NS_MNOTNULL))
3575         {
3576           sRef_updateNullState (res, other);
3577         }
3578     }
3579 }
3580
3581 /*
3582 ** definitely NOT symmetric:
3583 **
3584 **   res fills in known state information from other
3585 */
3586
3587 void
3588 sRef_mergeStateQuietReverse (/*@dependent@*/ sRef res, /*@dependent@*/ sRef other)
3589 {
3590   bool changed = FALSE;
3591
3592   llassert (sRef_isValid (res));
3593   llassert (sRef_isValid (other));
3594   sRef_checkMutable (res);
3595
3596   if (res->kind != other->kind)
3597     {
3598       changed = TRUE;
3599
3600       sinfo_free (res);
3601
3602       res->kind = other->kind;
3603       res->type = other->type;
3604       res->info = sinfo_fullCopy (other);
3605     }
3606   else
3607     {
3608       if (!ctype_equal (res->type, other->type))
3609         {
3610           changed = TRUE;
3611           res->type = other->type;
3612         }
3613       
3614       sinfo_update (res, other);
3615     }
3616
3617   res->modified = res->modified || other->modified;
3618   res->safe = res->safe && other->safe;
3619
3620   if (res->aliaskind != other->aliaskind
3621       && (res->aliaskind == AK_UNKNOWN
3622           || ((res->aliaskind == AK_LOCAL 
3623                || (res->aliaskind == AK_REFCOUNTED
3624                    && other->aliaskind != AK_LOCAL))
3625               && other->aliaskind != AK_UNKNOWN)))
3626     {
3627       changed = TRUE;
3628       res->aliaskind = other->aliaskind;
3629       res->oaliaskind = other->oaliaskind;
3630       res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
3631     }
3632
3633   if (other->expkind != XO_UNKNOWN && other->expkind != res->expkind)
3634     {
3635       changed = TRUE;
3636       res->expkind = other->expkind;
3637       res->expinfo = stateInfo_update (res->expinfo, other->expinfo);
3638     }
3639
3640   if (other->oexpkind != XO_UNKNOWN)
3641     {
3642       res->oexpkind = other->oexpkind;
3643     }
3644
3645   /* out takes precedence over implicitly defined */
3646
3647   if (res->defstate != other->defstate)
3648     {
3649       if (other->defstate != SS_UNKNOWN)
3650         {
3651           res->defstate = other->defstate;
3652         }
3653     }
3654
3655   if (sRef_getNullState (other) == NS_ERROR || sRef_getNullState (res) == NS_ERROR)
3656     {
3657       if (sRef_getNullState (res) != NS_ERROR)
3658         {
3659           sRef_setNullStateN (res, NS_ERROR);
3660           changed = TRUE;
3661         }
3662     }
3663   else
3664     {
3665       if (sRef_getNullState (other) != NS_UNKNOWN && sRef_getNullState (other) != sRef_getNullState (res))
3666         {
3667           changed = TRUE;
3668           sRef_updateNullState (res, other);
3669         }
3670     }
3671
3672   if (changed)
3673     {
3674       sRef_clearDerived (res); 
3675     }
3676 }
3677
3678 void 
3679 sRef_mergeState (sRef res, sRef other, clause cl, fileloc loc)
3680 {
3681   if (sRef_isValid (res) && sRef_isValid (other))
3682     {
3683       sRef_mergeStateAux (res, other, cl, FALSE, loc, TRUE);
3684     }
3685   else
3686     {
3687       if (sRef_isInvalid (res))
3688         {
3689           llbug (message ("sRef_mergeState: invalid res sRef: %q", 
3690                           sRef_unparseDebug (other)));
3691         }
3692       else 
3693         {
3694           llbug (message ("sRef_mergeState: invalid other sRef: %q", 
3695                           sRef_unparseDebug (res)));
3696         }
3697     }
3698 }
3699
3700 void 
3701 sRef_mergeOptState (sRef res, sRef other, clause cl, fileloc loc)
3702 {
3703   if (sRef_isValid (res) && sRef_isValid (other))
3704     {
3705       sRef_mergeStateAux (res, other, cl, TRUE, loc, TRUE);
3706     }
3707   else
3708     {
3709       if (sRef_isInvalid (res))
3710         {
3711           llbug (message ("sRef_mergeOptState: invalid res sRef: %q", 
3712                           sRef_unparseDebug (other)));
3713         }
3714       else 
3715         {
3716           llbug (message ("sRef_mergeOptState: invalid other sRef: %q", 
3717                           sRef_unparseDebug (res)));
3718         }
3719     }
3720 }
3721
3722 static void
3723 sRef_mergeStateAux (/*@notnull@*/ sRef res, /*@notnull@*/ sRef other, 
3724                     clause cl, bool opt, fileloc loc,
3725                     bool doDerivs)
3726    /*@modifies res@*/ 
3727 {
3728   llassertfatal (sRef_isValid (res));
3729   llassertfatal (sRef_isValid (other));
3730   
3731   DPRINTF (("Merge aux: %s / %s",
3732             sRef_unparseFull (res),
3733             sRef_unparseFull (other)));
3734
3735   sRef_checkMutable (res);
3736   sRef_checkMutable (other);
3737
3738   res->modified = res->modified || other->modified;
3739
3740   if (res->kind == other->kind 
3741       || (other->kind == SK_UNKNOWN || res->kind == SK_UNKNOWN))
3742     {
3743       sstate odef = other->defstate;
3744       sstate rdef = res->defstate;
3745       nstate onull = sRef_getNullState (other);
3746       
3747       /*
3748       ** yucky stuff to handle 
3749       **
3750       **   if (s) free (s);
3751       */
3752
3753       if (other->defstate == SS_DEAD 
3754           && ((sRef_isOnly (res) && sRef_definitelyNull (res))
3755               || (res->defstate == SS_UNDEFINED
3756                   || res->defstate == SS_UNUSEABLE)))
3757         {
3758           if (res->defstate == SS_UNDEFINED
3759               || res->defstate == SS_UNUSEABLE)
3760             {
3761               res->defstate = SS_UNUSEABLE;
3762             }
3763           else
3764             {
3765               res->defstate = SS_DEAD;
3766             }
3767
3768           res->definfo = stateInfo_update (res->definfo, other->definfo);
3769           sRef_clearDerived (other);
3770           sRef_clearDerived (res);
3771         }
3772       else if (res->defstate == SS_DEAD 
3773                && ((sRef_isOnly (other) && sRef_definitelyNull (other))
3774                    || (other->defstate == SS_UNDEFINED
3775                        || other->defstate == SS_UNUSEABLE)))
3776         {
3777           if (other->defstate == SS_UNDEFINED
3778               || other->defstate == SS_UNUSEABLE)
3779             {
3780               res->defstate = SS_UNUSEABLE;
3781             }
3782           else
3783             {
3784               res->defstate = SS_DEAD;
3785             }
3786           
3787           sRef_clearDerived (other);
3788           sRef_clearDerived (res);
3789         }
3790       else if (res->defstate == SS_DEFINED 
3791                && (other->defstate == SS_ALLOCATED 
3792                    && sRef_definitelyNull (other)))
3793         {
3794           other->defstate = SS_DEFINED; /* definitely null! */
3795         }
3796       else if (other->defstate == SS_DEFINED
3797                && (res->defstate == SS_ALLOCATED && sRef_definitelyNull (res)))
3798         {
3799           res->defstate = SS_DEFINED;
3800           res->definfo = stateInfo_update (res->definfo, other->definfo);
3801         }
3802       else
3803         {
3804           ; /* okay */
3805         }
3806
3807       if (res->defstate == SS_DEAD && other->defstate == SS_DEAD)
3808         {
3809           sRef_clearDerived (other);
3810           sRef_clearDerived (res);
3811         }
3812
3813       /*
3814       ** only & dead isn't really an only!
3815       */
3816
3817       if (alkind_isOnly (other->aliaskind) && other->defstate == SS_DEAD)
3818         {
3819           other->aliaskind = AK_UNKNOWN;
3820         }
3821
3822       if (alkind_isOnly (res->aliaskind) && res->defstate == SS_DEAD)
3823         {
3824           res->aliaskind = AK_UNKNOWN;
3825         }
3826
3827       /*
3828       ** Dead and dependent -> dead
3829       */
3830       
3831       if (alkind_isDependent (other->aliaskind) && res->defstate == SS_DEAD)
3832         {
3833           other->aliaskind = AK_UNKNOWN;
3834           other->defstate = SS_DEAD;
3835           sRef_clearDerived (res);
3836           sRef_clearDerived (other);
3837         }
3838       
3839       if (alkind_isDependent (res->aliaskind) && other->defstate == SS_DEAD)
3840         {
3841           res->aliaskind = AK_UNKNOWN;
3842           res->defstate = SS_DEAD;
3843           sRef_clearDerived (res);
3844           sRef_clearDerived (other);
3845         }
3846
3847       /*
3848       ** must do alias combine first, since it depends on 
3849       ** original values of state and null.
3850       */
3851
3852       sRef_combineAliasKinds (res, other, cl, loc);
3853       sRef_combineDefState (res, other);
3854       sRef_combineNullState (res, other);
3855
3856       if (rdef == SS_ALLOCATED || rdef == SS_SPECIAL)
3857         {
3858           if (odef == SS_DEFINED)
3859             {
3860               if (onull == NS_DEFNULL || onull == NS_CONSTNULL)
3861                 {
3862                   res->deriv = sRefSet_copyInto (res->deriv, other->deriv);
3863                   DPRINTF (("Copy derivs: %s", sRef_unparseFull (res)));
3864                 }                             
3865             }
3866           else if (odef == SS_ALLOCATED || odef == SS_SPECIAL)
3867             {
3868               
3869               if (doDerivs)
3870                 {
3871                   if (ctype_isUnion (ctype_realType (sRef_getType (res))))
3872                     {
3873                       res->deriv = sRef_mergeUnionDerivs (res->deriv, 
3874                                                           other->deriv, 
3875                                                           opt, cl, loc);
3876                       DPRINTF (("Copy derivs: %s", sRef_unparseFull (res)));
3877                     }
3878                   else
3879                     {
3880                       res->deriv = sRef_mergeDerivs (res->deriv, other->deriv, 
3881                                                      opt, cl, loc);
3882                       DPRINTF (("Copy derivs: %s", sRef_unparseFull (res)));
3883                     }
3884                 }
3885             }
3886           else
3887             {
3888               if (doDerivs)
3889                 {
3890                   res->deriv = sRef_mergeDerivs (res->deriv, other->deriv, 
3891                                                  opt, cl, loc);
3892                   DPRINTF (("Copy derivs: %s", sRef_unparseFull (res)));
3893                 }
3894               else
3895                 {
3896                   ;
3897                 }
3898             }
3899         }
3900       else
3901         {
3902           if (rdef == SS_PDEFINED
3903               || (rdef == SS_DEFINED && odef == SS_PDEFINED))
3904             {
3905                 if (doDerivs)
3906                     {
3907                       res->deriv = sRef_mergePdefinedDerivs (res->deriv, other->deriv, 
3908                                                              opt, cl, loc);
3909                       DPRINTF (("Copy derivs: %s", sRef_unparseFull (res)));
3910                     }
3911             }
3912           else
3913             {
3914               if ((rdef == SS_DEFINED  || rdef == SS_UNKNOWN)
3915                   && res->defstate == SS_ALLOCATED)
3916                 {
3917                   res->deriv = sRefSet_copyInto (res->deriv, other->deriv);
3918                 }
3919               else
3920                 {
3921                   if (doDerivs)
3922                     {
3923                       res->deriv = sRef_mergeDerivs (res->deriv, other->deriv, 
3924                                                      opt, cl, loc);
3925                       DPRINTF (("Copy derivs: %s", sRef_unparseFull (res)));
3926                     }
3927                 }
3928             }
3929         }
3930       
3931       
3932       sRef_combineExKinds (res, other);
3933     }
3934   else
3935     {
3936       if (res->kind == SK_ARRAYFETCH && other->kind == SK_PTR)
3937         {
3938           sRef nother = sRef_buildArrayFetchKnown (sRef_getBase (other), 0);
3939
3940           sRef_copyState (nother, other);
3941           sRef_mergeStateAux (res, nother, cl, opt, loc, doDerivs);
3942         }
3943       else if (res->kind == SK_PTR && other->kind == SK_ARRAYFETCH)
3944         {
3945           sRef nother = sRef_buildPointer (sRef_getBase (other));
3946
3947           if (sRef_isValid (nother))
3948             {
3949               sRef_copyState (nother, other);
3950               sRef_mergeStateAux (res, nother, cl, opt, loc, doDerivs);
3951             }
3952         }
3953       else
3954         {
3955           llcontbug (message ("merge conj: %q / %q", sRef_unparseFull (res), 
3956                               sRef_unparseFull (other)));
3957           
3958         }
3959     }
3960
3961   /* 
3962   ** Merge value table states
3963   */
3964
3965
3966   /*@i3245@*/
3967 # if 0
3968   /*
3969   ** This doesn't do anything.  And its broken too...
3970   */
3971
3972   valueTable_elements (res->state, key, sv) 
3973     {
3974       stateValue os = valueTable_lookup (other->state, key);
3975       /*@unused@*/ int val;
3976       /*@unused@*/ char *msg;
3977
3978       llassert (stateValue_isDefined (os));
3979       
3980       DPRINTF (("Merge state: %s / %s", 
3981                 cstring_toCharsSafe (stateValue_unparse (sv)), 
3982                 cstring_toCharsSafe (stateValue_unparse (os))));
3983       /*
3984         val = valueMatix_lookup (key, 
3985         stateValue_getValue (os),
3986         stateValue_getValue (sv), 
3987         &msg);
3988         DPRINTF (("Val: %d / %s", val, msg));
3989       */
3990   } end_valueTable_elements ; 
3991 # endif
3992
3993   DPRINTF (("Merge aux: %s / %s",
3994             sRef_unparseFull (res),
3995             sRef_unparseFull (other)));
3996 }
3997
3998 static sRefSet
3999 sRef_mergeUnionDerivs (/*@only@*/ sRefSet res, 
4000                        /*@exposed@*/ sRefSet other, bool opt,
4001                        clause cl, fileloc loc)
4002 {
4003   if (sRefSet_isEmpty (res))
4004     {
4005       return sRefSet_copyInto (res, other);
4006     }
4007   else
4008     {
4009       sRefSet_allElements (other, el)
4010         {
4011           if (sRef_isValid (el))
4012             {
4013               sRef e2 = sRefSet_lookupMember (other, el);
4014               
4015               if (sRef_isValid (e2))
4016                 {
4017                   sRef_mergeStateAux (el, e2, cl, opt, loc, FALSE);
4018                 }
4019               else
4020                 {
4021                   res = sRefSet_insert (res, el);
4022                 }
4023             }
4024         } end_sRefSet_allElements ;
4025
4026       return res;
4027     }
4028 }
4029
4030 static /*@only@*/ sRefSet
4031 sRef_mergeDerivs (/*@only@*/ sRefSet res, sRefSet other, 
4032                   bool opt, clause cl, fileloc loc)
4033 {
4034   sRefSet ret = sRefSet_new ();
4035
4036   sRefSet_allElements (res, el)
4037     {
4038       if (sRef_isValid (el))
4039         {
4040           sRef e2 = sRefSet_lookupMember (other, el);
4041
4042           if (sRef_isValid (e2))
4043             {
4044               if (el->defstate == SS_ALLOCATED &&
4045                   e2->defstate == SS_PDEFINED)
4046                 {
4047                   e2->defstate = SS_ALLOCATED;
4048                 }
4049               else if (e2->defstate == SS_ALLOCATED &&
4050                        el->defstate == SS_PDEFINED)
4051                 {
4052                   el->defstate = SS_ALLOCATED;
4053                   sRef_clearDerived (el);
4054                 }
4055               else if ((el->defstate == SS_DEAD || sRef_isKept (el)) &&
4056                        (e2->defstate == SS_DEFINED && !sRef_isKept (e2)))
4057                 {
4058                   
4059                   if (checkDeadState (el, TRUE, loc))
4060                     {
4061                       if (sRef_isThroughArrayFetch (el))
4062                         {
4063                           sRef_maybeKill (el, loc);
4064                           sRef_maybeKill (e2, loc);
4065                         }
4066                     }
4067                 }
4068               else if ((e2->defstate == SS_DEAD || sRef_isKept (e2)) &&
4069                        (el->defstate == SS_DEFINED && !sRef_isKept (el)))
4070                 {
4071                   
4072                   if (checkDeadState (e2, FALSE, loc))
4073                     {
4074                       if (sRef_isThroughArrayFetch (el))
4075                         {
4076                           sRef_maybeKill (el, loc);
4077                           sRef_maybeKill (e2, loc);
4078                         }
4079                     }
4080                 }
4081               else if (el->defstate == SS_DEFINED &&
4082                        e2->defstate == SS_PDEFINED)
4083                 {
4084                   DPRINTF (("set pdefined: %s", sRef_unparseFull (el)));
4085                   el->defstate = SS_PDEFINED;
4086                 }
4087               else if (e2->defstate == SS_DEFINED &&
4088                        el->defstate == SS_PDEFINED)
4089                 {
4090                   DPRINTF (("set pdefined: %s", sRef_unparseFull (e2)));
4091                   e2->defstate = SS_PDEFINED;
4092                 }
4093               else
4094                 {
4095                   ; /* okay */
4096                 }
4097
4098               if (ctype_isUnion (ctype_realType (sRef_getType (el))))
4099                 {
4100                   el->deriv = sRef_mergeUnionDerivs (el->deriv, e2->deriv, 
4101                                                      opt, cl, loc); 
4102                 }
4103               else
4104                 {
4105                   el->deriv = sRef_mergeDerivs (el->deriv, e2->deriv, opt, cl, loc); 
4106                 }
4107               
4108               if (sRef_equivalent (el, e2))
4109                 {
4110                   ret = sRefSet_insert (ret, el);
4111                 }
4112               else
4113                 {
4114                   sRef sr = sRef_leastCommon (el, e2);
4115
4116                   if (sRef_isValid (sr))
4117                     {
4118                       ret = sRefSet_insert (ret, sr);
4119                     }
4120                   else
4121                     {
4122                       ;
4123                     }
4124                 }
4125               
4126               (void) sRefSet_delete (other, e2);
4127             }
4128           else /* not defined */
4129             {
4130               (void) checkDeadState (el, TRUE, loc);
4131             }
4132         }
4133     } end_sRefSet_allElements;
4134
4135   sRefSet_allElements (other, el)
4136     {
4137       if (sRef_isValid (el))
4138         {
4139           (void) checkDeadState (el, FALSE, loc);
4140         }
4141     } end_sRefSet_allElements;
4142     
4143   sRefSet_free (res); 
4144   return (ret);
4145 }
4146
4147 /*
4148 ** Returns TRUE is there is an error.
4149 */
4150
4151 static bool checkDeadState (/*@notnull@*/ sRef el, bool tbranch, fileloc loc)
4152 {
4153   /*
4154   ** usymtab_isGuarded --- the utab should still be in the
4155   ** state of the alternate branch.
4156   **
4157   ** tbranch TRUE means el is released in the last branch, e.g.
4158   **     if (x != NULL) { ; } else { sfree (x); }
4159   ** so, if x is null in the other branch no error is reported.
4160   **
4161   ** tbranch FALSE means this is the other branch:
4162   **     if (x != NULL) { sfree (x); } else { ; }
4163   ** so, if x is null in this branch there is no error.
4164   */
4165
4166   
4167   if ((sRef_isDead (el) || sRef_isKept (el))
4168       && !sRef_isDeepUnionField (el) && !sRef_isThroughArrayFetch (el))
4169     {
4170        
4171       if (!tbranch)
4172         {
4173           if (usymtab_isDefinitelyNullDeep (el))
4174             {
4175               return TRUE;
4176             }
4177         }
4178       else
4179         {
4180           if (usymtab_isAltDefinitelyNullDeep (el))
4181             {
4182               return TRUE;
4183             }
4184         }
4185       
4186       if (optgenerror
4187           (FLG_BRANCHSTATE,
4188            message ("Storage %q is %q in one path, but live in another.",
4189                     sRef_unparse (el),
4190                     cstring_makeLiteral (sRef_isKept (el) 
4191                                          ? "kept" : "released")),
4192            loc))
4193         {
4194           if (sRef_isKept (el))
4195             {
4196               sRef_showAliasInfo (el);      
4197             }
4198           else
4199             {
4200               sRef_showStateInfo (el);
4201             }
4202
4203           /* prevent further errors */
4204           el->defstate = SS_UNKNOWN; 
4205           sRef_setAliasKind (el, AK_ERROR, fileloc_undefined);
4206           
4207           return FALSE;
4208         }
4209     }
4210
4211   return TRUE;
4212 }
4213
4214 static void 
4215 checkDerivDeadState (/*@notnull@*/ sRef el, bool tbranch, fileloc loc)
4216 {
4217   
4218   if (checkDeadState (el, tbranch, loc))
4219     {
4220       sRefSet_allElements (el->deriv, t)
4221         {
4222           if (sRef_isValid (t))
4223             {
4224                       checkDerivDeadState (t, tbranch, loc);
4225             }
4226         } end_sRefSet_allElements;
4227     }
4228 }
4229
4230 static sRefSet
4231   sRef_mergePdefinedDerivs (sRefSet res, sRefSet other, bool opt, 
4232                             clause cl, fileloc loc)
4233 {
4234   sRefSet ret = sRefSet_new ();
4235
4236   sRefSet_allElements (res, el)
4237     {
4238       if (sRef_isValid (el))
4239         {
4240           sRef e2 = sRefSet_lookupMember (other, el);
4241           
4242           if (sRef_isValid (e2))
4243             {
4244               if (sRef_isAllocated (el) && !sRef_isAllocated (e2))
4245                 {
4246                   ;
4247                 }
4248               else if (sRef_isAllocated (e2) && !sRef_isAllocated (el))
4249                 {
4250                   el->deriv = sRefSet_copyInto (el->deriv, e2->deriv); 
4251                 }
4252               else
4253                 {
4254                   el->deriv = sRef_mergePdefinedDerivs (el->deriv, e2->deriv, 
4255                                                         opt, cl, loc);
4256                 }
4257
4258               sRef_mergeStateAux (el, e2, cl, opt, loc, FALSE);
4259               
4260               ret = sRefSet_insert (ret, el);
4261               (void) sRefSet_delete (other, e2);
4262             }
4263           else
4264             {
4265               if (!opt)
4266                 {
4267                                   checkDerivDeadState (el, (cl == FALSECLAUSE), loc);
4268                 }
4269
4270               ret = sRefSet_insert (ret, el);
4271             }
4272         }
4273     } end_sRefSet_allElements;
4274   
4275   sRefSet_allElements (other, el)
4276     {
4277       if (sRef_isValid (el))
4278         {
4279           if (!sRefSet_member (ret, el))
4280             {
4281                               /* was cl == FALSECLAUSE */
4282               checkDerivDeadState (el, FALSE, loc);
4283               ret = sRefSet_insert (ret, el);
4284             }
4285           else
4286             {
4287               /*
4288               ** it's okay --- member is a different equality test 
4289               */
4290             }
4291         }
4292     } end_sRefSet_allElements;
4293
4294   sRefSet_free (res);
4295   return (ret);
4296 }
4297
4298 sRef sRef_makeConj (/*@exposed@*/ /*@returned@*/ sRef a, /*@exposed@*/ sRef b)
4299 {
4300   llassert (sRef_isValid (a));
4301   llassert (sRef_isValid (b));
4302       
4303   if (!sRef_equivalent (a, b))
4304     {
4305       sRef s = sRef_newRef ();
4306       
4307       s->kind = SK_CONJ;
4308       s->info = (sinfo) dmalloc (sizeof (*s->info));
4309       s->info->conj = (cjinfo) dmalloc (sizeof (*s->info->conj));
4310       s->info->conj->a = a; /* sRef_copy (a) */ /*@i32*/ ;
4311       s->info->conj->b = b; /* sRef_copy (b);*/ /*@i32@*/ ;
4312       
4313       if (ctype_equal (a->type, b->type)) s->type = a->type;
4314       else s->type = ctype_makeConj (a->type, b->type);
4315       
4316       if (a->defstate == b->defstate)
4317         {
4318           s->defstate = a->defstate;
4319         }
4320       else
4321         {
4322           s->defstate = SS_UNKNOWN; 
4323         }
4324       
4325       sRef_setNullStateN (s, NS_UNKNOWN);
4326       
4327       s->safe = a->safe && b->safe;
4328       s->aliaskind = alkind_resolve (a->aliaskind, b->aliaskind);
4329
4330       llassert (valueTable_isUndefined (s->state));
4331       s->state = context_createValueTable (s, stateInfo_makeLoc (g_currentloc));
4332       return s;
4333     }
4334   else
4335     {
4336       /*@-exposetrans@*/ return a; /*@=exposetrans@*/
4337     }
4338 }
4339
4340 /*@dependent@*/ sRef
4341 sRef_makeUnknown ()
4342 {
4343   sRef s = sRef_new ();
4344
4345   s->kind = SK_UNKNOWN;
4346   return s;
4347 }
4348
4349 static /*@owned@*/ /*@notnull@*/ sRef
4350 sRef_makeSpecial (speckind sk) /*@*/
4351 {
4352   sRef s = sRef_new ();
4353
4354   s->kind = SK_SPECIAL;
4355   s->info = (sinfo) dmalloc (sizeof (*s->info));
4356   s->info->spec = sk;
4357   /*@-dependenttrans@*/
4358   return s;
4359   /*@=dependenttrans@*/
4360 }
4361
4362 static /*@owned@*/ sRef srnothing = sRef_undefined;
4363 static /*@owned@*/ sRef srinternal = sRef_undefined;
4364 static /*@owned@*/ sRef srsystem = sRef_undefined;
4365 static /*@owned@*/ sRef srspec = sRef_undefined;
4366
4367 /*@dependent@*/ sRef
4368 sRef_makeNothing (void)
4369 {
4370   if (sRef_isInvalid (srnothing))
4371     {
4372       srnothing = sRef_makeSpecial (SR_NOTHING);
4373     }
4374
4375   return srnothing;
4376 }
4377
4378 sRef
4379 sRef_makeInternalState (void)
4380 {
4381   if (sRef_isInvalid (srinternal))
4382     {
4383       srinternal = sRef_makeSpecial (SR_INTERNAL);
4384     }
4385
4386   return srinternal;
4387 }
4388
4389 sRef
4390 sRef_makeSpecState (void)
4391 {
4392   if (sRef_isInvalid (srspec))
4393     {
4394       srspec = sRef_makeSpecial (SR_SPECSTATE);
4395     }
4396
4397   return srspec;
4398 }
4399
4400 sRef
4401 sRef_makeSystemState (void)
4402 {
4403   if (sRef_isInvalid (srsystem))
4404     {
4405       srsystem = sRef_makeSpecial (SR_SYSTEM);
4406     }
4407
4408   return srsystem;
4409 }
4410
4411 sRef
4412 sRef_makeGlobalMarker (void)
4413 {
4414   sRef s = sRef_makeSpecial (SR_GLOBALMARKER);
4415   llassert (valueTable_isUndefined (s->state));
4416   s->state = context_createGlobalMarkerValueTable (stateInfo_undefined);
4417   return s;
4418 }
4419
4420 sRef
4421 sRef_makeResult (ctype c)
4422 {
4423   sRef s = sRef_newRef ();
4424   
4425   s->kind = SK_RESULT;
4426   s->type = c;
4427   s->defstate = SS_UNKNOWN; 
4428   s->aliaskind = AK_UNKNOWN;
4429   sRef_setNullStateN (s, NS_UNKNOWN);
4430   llassert (valueTable_isUndefined (s->state));
4431   s->state = context_createValueTable (s, stateInfo_makeLoc (g_currentloc));
4432
4433   DPRINTF (("Result: [%p] %s", s, sRef_unparseFull (s)));
4434   return s;
4435 }
4436
4437
4438 bool
4439 sRef_isNothing (sRef s)
4440 {
4441   return (sRef_isKindSpecial (s) && s->info->spec == SR_NOTHING);
4442 }
4443
4444 bool
4445 sRef_isInternalState (sRef s)
4446 {
4447   return (sRef_isKindSpecial (s) && s->info->spec == SR_INTERNAL);
4448 }
4449
4450 bool
4451 sRef_isSpecInternalState (sRef s)
4452 {
4453   return (sRef_isKindSpecial (s) 
4454           && (s->info->spec == SR_INTERNAL || s->info->spec == SR_SPECSTATE));
4455 }
4456
4457 bool
4458 sRef_isSpecState (sRef s)
4459 {
4460   return (sRef_isKindSpecial (s) && s->info->spec == SR_SPECSTATE);
4461 }
4462
4463 bool
4464 sRef_isResult (sRef s)
4465 {
4466   return (sRef_isValid (s) && s->kind == SK_RESULT);
4467 }
4468
4469 bool
4470 sRef_isSystemState (sRef s)
4471 {
4472   return (sRef_isKindSpecial (s) && s->info->spec == SR_SYSTEM);
4473 }
4474
4475 bool
4476 sRef_isGlobalMarker (sRef s)
4477 {
4478   return (sRef_isKindSpecial (s) && s->info->spec == SR_GLOBALMARKER);
4479 }
4480
4481 usymId
4482 sRef_getScopeIndex (sRef s)
4483 {
4484   llassert (sRef_isValid (s));
4485   llassert (sRef_isCvar (s));
4486
4487   return (s->info->cvar->index);
4488 }
4489
4490 void
4491 sRef_makeSafe (sRef s)
4492 {
4493   if (sRef_isValid (s)) 
4494     {
4495       s->safe = TRUE;
4496     }
4497 }
4498
4499 void
4500 sRef_makeUnsafe (sRef s)
4501 {
4502   if (sRef_isValid (s)) 
4503     {
4504       s->safe = FALSE;
4505     }
4506 }
4507
4508 /*
4509 ** memory state operations
4510 */
4511
4512 /*@only@*/ cstring sRef_unparseFull (sRef s)
4513 {
4514   if (sRef_isInvalid (s)) return (cstring_undefined);
4515
4516   return (message ("[%p] %q - %q [%s] { %q } < %q >", 
4517                    s,
4518                    sRef_unparseDebug (s), 
4519                    sRef_unparseState (s),
4520                    exkind_unparse (s->oexpkind),
4521                    sRefSet_unparseDebug (s->deriv),
4522                    valueTable_unparse (s->state)));
4523 }
4524
4525 /*@unused@*/ cstring sRef_unparseDeep (sRef s)
4526 {
4527   cstring st = cstring_undefined;
4528
4529   st = message ("%q:", sRef_unparseFull (s));
4530
4531   if (sRef_isValid (s))
4532     {
4533       sRefSet_allElements (s->deriv, el)
4534         {
4535           st = message("%q\n%q", st, sRef_unparseDeep (el));
4536         } end_sRefSet_allElements ;
4537     }
4538
4539   return st;
4540 }
4541
4542 /*@only@*/ cstring sRef_unparseState (sRef s)
4543 {
4544   if (sRef_isConj (s))
4545     {
4546       return (message ("%q | %q", 
4547                        sRef_unparseState (s->info->conj->a),
4548                        sRef_unparseState (s->info->conj->b)));
4549     }
4550
4551   if (sRef_isInvalid (s))
4552     {
4553       return (cstring_makeLiteral ("<invalid>"));
4554     }
4555
4556   return (message ("%s.%s.%s.%s", 
4557                    alkind_unparse (s->aliaskind), 
4558                    nstate_unparse (sRef_getNullState (s)),
4559                    exkind_unparse (s->expkind),
4560                    sstate_unparse (s->defstate)));
4561 }
4562
4563 bool sRef_isNotUndefined (sRef s)
4564 {
4565   return (sRef_isInvalid (s)
4566           || (s->defstate != SS_UNDEFINED
4567               && s->defstate != SS_UNUSEABLE
4568               && s->defstate != SS_DEAD));
4569 }
4570
4571 ynm sRef_isWriteable (sRef s)
4572 {
4573   if (sRef_isInvalid (s)) return MAYBE;
4574
4575   if (sRef_isConj (s) && s->defstate == SS_UNKNOWN)
4576     {
4577       if (ynm_toBoolStrict (sRef_isWriteable (sRef_getConjA (s))))
4578         {
4579           if (ynm_toBoolStrict (sRef_isWriteable (sRef_getConjB (s))))
4580             {
4581               return YES;
4582             }
4583           return MAYBE;
4584         }
4585       else
4586         {
4587           if (ynm_toBoolStrict (sRef_isWriteable (sRef_getConjB (s))))
4588             {
4589               return MAYBE;
4590             }
4591           return NO;
4592         }
4593     }
4594
4595   return (ynm_fromBool (s->defstate != SS_UNUSEABLE));
4596 }
4597
4598 bool sRef_hasNoStorage (sRef s)
4599 {
4600   return (!sRef_isAllocatedStorage (s) || sRef_isDefinitelyNull (s));
4601 }
4602
4603 bool sRef_isStrictReadable (sRef s)
4604 {
4605   return (ynm_toBoolStrict (sRef_isValidLvalue (s)));
4606 }
4607
4608 /*
4609 ** Is this what is does?
4610 ** Returns YES if s can be used as an rvalue,
4611 **         MAYBE if its not clear
4612 **         NO if s cannot be safely used as an rvalue.
4613 */
4614
4615 ynm sRef_isValidLvalue (sRef s)
4616 {
4617   sstate ss;
4618
4619   if (sRef_isInvalid (s)) return YES;
4620
4621   ss = s->defstate;
4622   
4623   if (sRef_isConj (s) && s->defstate == SS_UNKNOWN)
4624     {
4625       if (ynm_toBoolStrict (sRef_isValidLvalue (sRef_getConjA (s))))
4626         {
4627           if (ynm_toBoolStrict (sRef_isValidLvalue (sRef_getConjB (s))))
4628             {
4629               return YES;
4630             }
4631           return MAYBE;
4632         }
4633       else
4634         {
4635           if (ynm_toBoolStrict (sRef_isValidLvalue (sRef_getConjB (s))))
4636             {
4637               return MAYBE;
4638             }
4639           return NO;
4640         }
4641     }
4642   else if (ss == SS_HOFFA)
4643     {
4644       if (context_getFlag (FLG_STRICTUSERELEASED))
4645         {
4646           return MAYBE;
4647         }
4648       else
4649         {
4650           return YES;
4651         }
4652     }
4653   else
4654     {
4655       return (ynm_fromBool (ss == SS_DEFINED 
4656                             || ss == SS_FIXED 
4657                             || ss == SS_RELDEF 
4658                             || ss == SS_PDEFINED 
4659                             || ss == SS_PARTIAL 
4660                             || ss == SS_SPECIAL
4661                             || ss == SS_ALLOCATED 
4662                             || ss == SS_KILLED /* evans 2001-05-26: added this for killed globals */
4663                             || ss == SS_UNKNOWN));
4664     }
4665 }
4666
4667 static /*@exposed@*/ sRef whatUndefined (/*@exposed@*/ sRef fref, int depth)
4668 {
4669   ctype ct;
4670
4671   
4672   if (depth > MAXDEPTH)
4673     {
4674       llgenmsg (message 
4675                 ("Warning: check definition limit exceeded, checking %q. "
4676                  "This either means there is a variable with at least "
4677                  "%d indirections apparent in the program text, or "
4678                  "there is a bug in Splint.",
4679                  sRef_unparse (fref),
4680                  MAXDEPTH),
4681                 g_currentloc);
4682
4683       return sRef_undefined;
4684     }
4685
4686   if (!sRef_isKnown (fref) || sRef_isAnyDefined (fref))
4687     {
4688       return sRef_undefined;
4689     }
4690
4691   if (sRef_isUnuseable (fref) || sRef_isStateUndefined (fref))
4692     {
4693       return fref;
4694     }
4695
4696   ct = ctype_realType (sRef_getType (fref));
4697   
4698   if (ctype_isUnknown (ct))
4699     {
4700       return sRef_undefined;
4701     }
4702   else if (ctype_isPointer (ct) || ctype_isArray (ct))
4703     {
4704       if (sRef_isStateUnknown (fref))
4705         {
4706           return sRef_undefined;
4707         }
4708       else
4709         {
4710           sRef fptr = sRef_constructDeref (fref);
4711
4712           return (whatUndefined (fptr, depth + 1));
4713         }
4714     }
4715   else if (ctype_isStruct (ct))
4716     {
4717       bool hasOneDefined = FALSE;
4718       
4719       if (sRef_isStateUnknown (fref))
4720         {
4721           return fref;
4722         }
4723           
4724       if (sRef_isPdefined (fref) || sRef_isAnyDefined (fref))
4725         {
4726           sRefSet_realElements (sRef_derivedFields (fref), sr)
4727             {
4728               hasOneDefined = TRUE;
4729               
4730               if (sRef_isField (sr))
4731                 {
4732                   cstring fieldname = sRef_getField (sr);
4733                   sRef fldref = sRef_makeField (fref, fieldname);
4734                   bool shouldCheck = !sRef_isRecursiveField (fldref);
4735                   
4736                   if (shouldCheck)
4737                     {
4738                       sRef wdef = whatUndefined (fldref, depth + 1);
4739
4740                       if (sRef_isValid (wdef))
4741                         {
4742                           return wdef;
4743                         }
4744                     }
4745                 }
4746             } end_sRefSet_realElements;
4747         }
4748       else if (sRef_isAllocated (fref))
4749         {
4750           /*
4751           ** for structures, each field must be completely defined
4752           */
4753           
4754           uentryList fields = ctype_getFields (ct);
4755               
4756           uentryList_elements (fields, ue)
4757             {
4758               cstring name = uentry_getRealName (ue);
4759               sRef ffield = sRef_makeField (fref, name);
4760               bool shouldCheck = !sRef_isRecursiveField (ffield);
4761
4762               if (sRef_isRelDef (uentry_getSref (ue)))
4763                 {
4764                   ; /* no error */
4765                 }
4766               else
4767                 {
4768                   if (shouldCheck)
4769                     {
4770                       sRef wdef = whatUndefined (ffield, depth + 1);
4771
4772                       if (sRef_isInvalid (wdef))
4773                         {
4774                           return wdef;
4775                         }
4776                     }
4777                 }
4778             } end_uentryList_elements;
4779         }
4780       else
4781         {
4782           ;
4783         }
4784     }
4785   else if (ctype_isUnion (ct))
4786     {
4787       ; 
4788     }
4789   else
4790     {
4791       ;
4792     }
4793
4794   return sRef_undefined;
4795 }
4796
4797 static bool checkDefined (/*@temp@*/ sRef sr)
4798 {
4799   /*@-temptrans@*/ /* the result from whatUndefined is lost */
4800   return (sRef_isInvalid (whatUndefined (sr, 0)));
4801   /*@=temptrans@*/ 
4802 }
4803
4804 bool sRef_isReallyDefined (sRef s)
4805 {
4806   if (sRef_isValid (s))
4807     {
4808       if (sRef_isAnyDefined (s))
4809         {
4810           return TRUE;
4811         }
4812       else
4813         {
4814           if (sRef_isAllocated (s) || sRef_isPdefined (s))
4815             {
4816               return checkDefined (s);
4817             }
4818           else
4819             {
4820               return FALSE;
4821             }
4822         }
4823     }
4824   else
4825     {
4826       return TRUE;
4827     }
4828 }
4829
4830 void sRef_showNotReallyDefined (sRef s)
4831 {
4832   if (sRef_isValid (s))
4833     {
4834       if (sRef_isAnyDefined (s))
4835         {
4836           BADBRANCH;
4837         }
4838       else
4839         {
4840           if (sRef_isAllocated (s) || sRef_isPdefined (s))
4841             {
4842               /*@-temptrans@*/ /* the result of whatUndefined is lost */
4843               sRef ref = whatUndefined (s, 0);
4844
4845               llassert (sRef_isValid (ref));
4846
4847               if (ref != s)
4848                 {
4849                   llgenindentmsgnoloc
4850                     (message ("This sub-reference is %s: %q",
4851                               sstate_unparse (sRef_getDefState (ref)),
4852                               sRef_unparse (ref)));
4853                 }
4854             }
4855           else
4856             {
4857               ;
4858             }
4859         }
4860     }
4861   else
4862     {
4863       BADBRANCH;
4864     }
4865 }
4866
4867 sstate sRef_getDefState (sRef s)
4868 {
4869   if (sRef_isInvalid (s)) return (SS_UNKNOWN);
4870   return (s->defstate);
4871 }
4872
4873 void sRef_setDefState (sRef s, sstate defstate, fileloc loc)
4874 {
4875   sRef_checkMutable (s);  
4876   sRef_setStateAux (s, defstate, loc);
4877 }
4878
4879 static void sRef_clearAliasStateAux (sRef s, fileloc loc)
4880 {
4881   sRef_checkMutable (s);  
4882   sRef_setAliasKind (s, AK_ERROR, loc);
4883 }
4884
4885 void sRef_clearAliasState (sRef s, fileloc loc)
4886 {
4887   sRef_checkMutable (s);  
4888   sRef_aliasSetComplete (sRef_clearAliasStateAux, s, loc);
4889 }
4890
4891 void sRef_setAliasKindComplete (sRef s, alkind kind, fileloc loc)
4892 {
4893   sRef_checkMutable (s);  
4894   sRef_aliasSetCompleteAlkParam (sRef_setAliasKind, s, kind, loc); 
4895 }
4896
4897 void sRef_setAliasKind (sRef s, alkind kind, fileloc loc)
4898 {
4899   sRef_checkMutable (s);  
4900
4901   if (sRef_isValid (s))
4902     {
4903       sRef_clearDerived (s);
4904
4905       if ((kind != s->aliaskind && kind != s->oaliaskind)
4906           && fileloc_isDefined (loc))
4907         {
4908           s->aliasinfo = stateInfo_updateLoc (s->aliasinfo, loc);
4909         }
4910       
4911       s->aliaskind = kind;
4912     }
4913 }
4914
4915 void sRef_setOrigAliasKind (sRef s, alkind kind)
4916 {
4917   sRef_checkMutable (s);  
4918
4919   if (sRef_isValid (s))
4920     {
4921       s->oaliaskind = kind;
4922     }
4923 }
4924
4925 exkind sRef_getExKind (sRef s)
4926 {
4927   if (sRef_isValid (s))
4928     {
4929       return (s->expkind);
4930     }
4931   else
4932     {
4933       return XO_UNKNOWN;
4934     }
4935 }
4936
4937 exkind sRef_getOrigExKind (sRef s)
4938 {
4939   if (sRef_isValid (s))
4940     {
4941       return (s->oexpkind);
4942     }
4943   else
4944     {
4945       return XO_UNKNOWN;
4946     }
4947 }
4948
4949 static void sRef_clearExKindAux (sRef s, fileloc loc)
4950 {
4951   sRef_checkMutable (s);  
4952   sRef_setExKind (s, XO_UNKNOWN, loc);
4953 }
4954
4955 void sRef_setObserver (sRef s, fileloc loc) 
4956 {
4957   sRef_checkMutable (s);  
4958   sRef_setExKind (s, XO_OBSERVER, loc);
4959 }
4960
4961 void sRef_setExposed (sRef s, fileloc loc) 
4962 {
4963   sRef_checkMutable (s);  
4964   sRef_setExKind (s, XO_EXPOSED, loc);
4965 }
4966
4967 void sRef_clearExKindComplete (sRef s, fileloc loc)
4968 {
4969   (void) sRef_aliasSetComplete (sRef_clearExKindAux, s, loc);
4970 }
4971
4972 void sRef_setExKind (sRef s, exkind exp, fileloc loc)
4973 {
4974   sRef_checkMutable (s);
4975
4976   if (sRef_isValid (s))
4977     {
4978       if (s->expkind != exp)
4979         {
4980           s->expinfo = stateInfo_updateLoc (s->expinfo, loc);
4981         }
4982       
4983       s->expkind = exp;
4984     }
4985 }
4986
4987 /*
4988 ** s1->derived = s2->derived
4989 */
4990
4991 static void sRef_copyRealDerived (sRef s1, sRef s2)
4992 {
4993   DPRINTF (("Copy real: %s / %s", sRef_unparse (s1), sRef_unparse (s2)));
4994   sRef_checkMutable (s1);
4995
4996   if (sRef_isValid (s1) && sRef_isValid (s2))
4997     {
4998       sRef sb = sRef_getRootBase (s1);
4999
5000       sRefSet_clear (s1->deriv);
5001
5002       sRefSet_allElements (s2->deriv, el)
5003         {
5004           if (sRef_isValid (el))
5005             {
5006               sRef rb = sRef_getRootBase (el);
5007               
5008               if (!sRef_same (rb, sb))
5009                 {
5010                   sRef fb = sRef_fixDirectBase (el, s1);
5011                   
5012                   if (sRef_isValid (fb))
5013                     {
5014                       sRef_copyRealDerived (fb, el);
5015                       sRef_addDeriv (s1, fb);
5016                     }
5017                 }
5018               else
5019                 {
5020                   sRef_addDeriv (s1, el);
5021                 }
5022             }
5023         } end_sRefSet_allElements ;
5024     }
5025   
5026   }
5027
5028 void sRef_copyRealDerivedComplete (sRef s1, sRef s2)
5029 {
5030   sRef_innerAliasSetCompleteParam (sRef_copyRealDerived, s1, s2);
5031 }
5032
5033 void sRef_setUndefined (sRef s, fileloc loc)
5034 {
5035   sRef_checkMutable (s);
5036
5037   if (sRef_isValid (s))
5038     {
5039       s->defstate = SS_UNDEFINED;
5040
5041       if (fileloc_isDefined (loc))
5042         {
5043           s->definfo = stateInfo_updateLoc (s->definfo, loc);
5044         }
5045
5046       sRef_clearDerived (s);
5047     }
5048 }
5049
5050 static void sRef_setDefinedAux (sRef s, fileloc loc, bool clear)
5051 {
5052   sRef_checkMutable (s);
5053   if (sRef_isInvalid (s)) return;
5054
5055   DPRINTF (("Set defined: %s", sRef_unparseFull (s)));
5056
5057   if (s->defstate != SS_DEFINED && fileloc_isDefined (loc))
5058     {
5059       s->definfo = stateInfo_updateLoc (s->definfo, loc);
5060     }
5061   
5062   s->defstate = SS_DEFINED;
5063   
5064   DPRINTF (("Set defined: %s", sRef_unparseFull (s)));
5065
5066   /* e.g., if x is allocated, *x = 3 defines x */
5067   
5068   if (s->kind == SK_PTR)
5069     {
5070       sRef p = s->info->ref;
5071       sRef arr;
5072
5073       if (p->defstate == SS_ALLOCATED
5074           || p->defstate == SS_SPECIAL) /* evans 2001-07-12: shouldn't need this */
5075         {
5076           sRef_setDefinedAux (p, loc, clear);
5077         }
5078
5079       /* 
5080       ** Defines a[0] also:
5081       */
5082
5083       arr = sRef_findDerivedArrayFetch (p, FALSE, 0, FALSE);
5084
5085       if (sRef_isValid (arr))
5086         {
5087           sRef_setDefinedAux (arr, loc, clear);
5088         }
5089     }
5090   else if (s->kind == SK_ARRAYFETCH) 
5091     {
5092       if (!s->info->arrayfetch->indknown
5093           || (s->info->arrayfetch->ind == 0))
5094         {
5095           sRef p = s->info->arrayfetch->arr;
5096           sRef ptr = sRef_constructPointer (p);
5097
5098           if (sRef_isValid (ptr))
5099             {
5100               if (ptr->defstate == SS_ALLOCATED 
5101                   || ptr->defstate == SS_UNDEFINED
5102                   || ptr->defstate == SS_SPECIAL) /* evans 2001-07-12: shouldn't need this */
5103                 {
5104                   sRef_setDefinedAux (ptr, loc, clear);
5105                 }
5106             }
5107           
5108           if (p->defstate == SS_RELDEF) 
5109             {
5110               ;
5111             }
5112           else if (p->defstate == SS_ALLOCATED || p->defstate == SS_PDEFINED
5113                    || p->defstate == SS_SPECIAL) /* evans 2001-07-12: shouldn't need this */
5114             {
5115               p->defstate = SS_DEFINED;
5116             }
5117           else
5118             {
5119             }
5120         }
5121     }
5122   else if (s->kind == SK_FIELD)
5123     {
5124       sRef parent = s->info->field->rec;
5125       
5126       if (sRef_isValid (parent))
5127         {
5128           if (ctype_isUnion (ctype_realType (parent->type)))
5129             {
5130               /*
5131               ** Should not clear derived from here.
5132               */
5133               
5134               sRef_setDefinedNoClear (parent, loc);
5135             }
5136           else
5137             {
5138               ; /* Nothing to do for structures. */
5139             }
5140         }
5141
5142           }
5143   else
5144     {
5145       ;
5146     }
5147
5148   if (clear)
5149     {
5150       sRef_clearDerived (s);
5151     } 
5152   else
5153     {
5154       /* evans 2001-07-12: need to define the derived references */
5155       sRefSet_elements (s->deriv, el)
5156         {
5157           llassert (sRef_isValid (el));
5158           el->defstate = SS_DEFINED;
5159         } end_sRefSet_elements ;
5160     }
5161
5162   DPRINTF (("Set defined: %s", sRef_unparseFull (s)));
5163 }
5164
5165 static void sRef_setPartialDefined (sRef s, fileloc loc)
5166 {
5167   sRef_checkMutable (s);
5168
5169   if (!sRef_isPartial (s))
5170     {
5171       sRef_setDefined (s, loc);
5172     }
5173 }
5174
5175 void sRef_setPartialDefinedComplete (sRef s, fileloc loc)
5176 {
5177   sRef_innerAliasSetComplete (sRef_setPartialDefined, s, loc);
5178 }
5179
5180 void sRef_setDefinedComplete (sRef s, fileloc loc)
5181 {
5182   sRef_innerAliasSetComplete (sRef_setDefined, s, loc);
5183 }
5184
5185 void sRef_setDefinedCompleteDirect (sRef s, fileloc loc)
5186 {
5187   sRefSet aliases;
5188   
5189   aliases = usymtab_allAliases (s);
5190   DPRINTF (("Set defined complete: %s", sRef_unparseFull (s)));
5191   DPRINTF (("All aliases: %s", sRefSet_unparseFull (aliases)));
5192   
5193   sRef_setDefined (s, loc);
5194
5195   sRefSet_realElements (aliases, current)
5196     {
5197       if (sRef_isValid (current))
5198         {
5199           current = sRef_updateSref (current);
5200           sRef_setDefined (current, loc);
5201         }
5202     } end_sRefSet_realElements;
5203   
5204   sRefSet_free (aliases);
5205   sRef_innerAliasSetComplete (sRef_setDefined, s, loc);
5206 }
5207
5208 void sRef_setDefined (sRef s, fileloc loc)
5209 {
5210   sRef_checkMutable (s);
5211   sRef_setDefinedAux (s, loc, TRUE);
5212 }
5213
5214 static void sRef_setDefinedNoClear (sRef s, fileloc loc)
5215 {
5216   sRef_checkMutable (s);
5217   DPRINTF (("Defining: %s", sRef_unparseFull (s)));
5218   sRef_setDefinedAux (s, loc, FALSE);
5219   DPRINTF (("==> %s", sRef_unparseFull (s)));
5220 }
5221
5222 void sRef_setDefinedNCComplete (sRef s, fileloc loc)
5223 {
5224   sRef_checkMutable (s);
5225   DPRINTF (("Set Defined Complete: %s", sRef_unparseFull (s)));
5226   sRef_innerAliasSetComplete (sRef_setDefinedNoClear, s, loc);
5227   DPRINTF (("==> %s", sRef_unparseFull (s)));
5228 }
5229
5230 static bool sRef_isDeepUnionField (sRef s)
5231 {
5232   return (sRef_deepPred (sRef_isUnionField, s));
5233 }
5234
5235 bool sRef_isUnionField (sRef s)
5236 {
5237   if (sRef_isValid (s) && s->kind == SK_FIELD)
5238     {
5239       /*
5240        ** defining one field of a union defines the union
5241        */
5242       
5243       sRef base = s->info->field->rec;
5244
5245       if (sRef_isValid (base))
5246         {
5247           return (ctype_isUnion (ctype_realType (base->type)));
5248         }
5249     }
5250
5251   return FALSE;
5252 }
5253
5254 void sRef_setPdefined (sRef s, fileloc loc)
5255 {
5256   sRef_checkMutable (s);
5257   if (sRef_isValid (s) && !sRef_isPartial (s))
5258     {
5259       sRef base = sRef_getBaseSafe (s);
5260
5261       if (s->defstate == SS_ALLOCATED)
5262         {
5263           return;
5264         }
5265       
5266       if (s->defstate != SS_PDEFINED && fileloc_isDefined (loc))
5267         {
5268           s->definfo = stateInfo_updateLoc (s->definfo, loc);
5269         }
5270
5271       DPRINTF (("set pdefined: %s", sRef_unparseFull (s)));
5272       s->defstate = SS_PDEFINED;
5273       
5274       /* e.g., if x is allocated, *x = 3 defines x */
5275       
5276       while (sRef_isValid (base) && sRef_isKnown (base))
5277         {
5278           if (base->defstate == SS_DEFINED)
5279             { 
5280               sRef nb;
5281               
5282               DPRINTF (("set pdefined: %s", sRef_unparseFull (base)));
5283               base->defstate = SS_PDEFINED; 
5284               nb = sRef_getBaseSafe (base); 
5285               base = nb;
5286             }
5287           else 
5288             { 
5289               break; 
5290             }
5291         }      
5292     }
5293 }
5294
5295 static void sRef_setStateAux (sRef s, sstate ss, fileloc loc)
5296 {
5297   sRef_checkMutable (s);
5298
5299   if (sRef_isValid (s))
5300     {
5301       /* if (s->defstate == SS_RELDEF) return; */
5302
5303       if (s->defstate != ss && fileloc_isDefined (loc))
5304         {
5305           s->definfo = stateInfo_updateLoc (s->definfo, loc);
5306         }
5307
5308       s->defstate = ss;
5309       sRef_clearDerived (s); 
5310
5311       if (ss == SS_ALLOCATED)
5312         {
5313           sRef base = sRef_getBaseSafe (s);
5314           
5315           while (sRef_isValid (base) && sRef_isKnown (base))
5316             {
5317               if (base->defstate == SS_DEFINED) 
5318                 { 
5319                   sRef nb;
5320
5321                   DPRINTF (("set pdefined: %s", sRef_unparseFull (s)));           
5322                   base->defstate = SS_PDEFINED; 
5323                   nb = sRef_getBaseSafe (base); 
5324                   base = nb;
5325                 }
5326               else 
5327                 { 
5328                   break; 
5329                 }
5330             }
5331         }
5332     }
5333 }
5334
5335 void sRef_setAllocatedComplete (sRef s, fileloc loc)
5336 {
5337   sRef_innerAliasSetComplete (sRef_setAllocated, s, loc);
5338 }
5339
5340 static void sRef_setAllocatedShallow (sRef s, fileloc loc)
5341 {
5342   sRef_checkMutable (s);
5343
5344   if (sRef_isValid (s))
5345     {
5346       if (s->defstate == SS_DEAD || s->defstate == SS_UNDEFINED)
5347         {
5348           s->defstate = SS_ALLOCATED;
5349           
5350           if (fileloc_isDefined (loc))
5351             {
5352               s->definfo = stateInfo_updateLoc (s->definfo, loc);
5353             }
5354         }
5355     }
5356 }
5357
5358 void sRef_setAllocatedShallowComplete (sRef s, fileloc loc)
5359 {
5360   sRef_innerAliasSetComplete (sRef_setAllocatedShallow, s, loc);
5361 }
5362
5363 void sRef_setAllocated (sRef s, fileloc loc)
5364 {
5365   sRef_checkMutable (s);
5366   sRef_setStateAux (s, SS_ALLOCATED, loc);
5367 }
5368
5369 void sRef_setPartial (sRef s, fileloc loc)
5370 {
5371   sRef_checkMutable (s);
5372   sRef_setStateAux (s, SS_PARTIAL, loc);
5373 }
5374
5375 void sRef_setShared (sRef s, fileloc loc)
5376 {
5377   sRef_checkMutable (s);
5378
5379   if (sRef_isValid (s))
5380     {
5381       if (s->aliaskind != AK_SHARED && fileloc_isDefined (loc))
5382         {
5383           s->aliasinfo = stateInfo_updateLoc (s->aliasinfo, loc);
5384         }
5385
5386       s->aliaskind = AK_SHARED;
5387       /* don't! sRef_clearDerived (s); */
5388     }
5389 }
5390
5391 void sRef_setLastReference (sRef s, /*@exposed@*/ sRef ref, fileloc loc)
5392 {
5393   sRef_checkMutable (s);
5394
5395   if (sRef_isValid (s))
5396     {
5397       s->aliaskind = sRef_getAliasKind (ref);
5398       s->aliasinfo = stateInfo_updateRefLoc (s->aliasinfo, ref, loc);
5399     }
5400 }
5401
5402 static
5403 void sRef_setNullStateAux (/*@notnull@*/ sRef s, nstate ns, fileloc loc)
5404 {
5405   sRef_checkMutable (s);
5406   s->nullstate = ns;
5407   sRef_resetAliasKind (s);
5408
5409   if (fileloc_isDefined (loc))
5410     {
5411       s->nullinfo = stateInfo_updateLoc (s->nullinfo, loc);
5412     }
5413 }
5414
5415 void sRef_setNotNull (sRef s, fileloc loc)
5416 {
5417   if (sRef_isValid (s))
5418     {
5419       sRef_setNullStateAux (s, NS_NOTNULL, loc);
5420     }
5421 }
5422
5423 void sRef_setNullStateN (sRef s, nstate n)
5424 {
5425   if (sRef_isValid (s))
5426     {
5427       sRef_checkMutable (s);
5428       s->nullstate = n;
5429       sRef_resetAliasKind (s);
5430     }
5431 }
5432
5433 void sRef_setNullState (sRef s, nstate n, fileloc loc)
5434 {
5435   if (sRef_isValid (s))
5436     {
5437       sRef_setNullStateAux (s, n, loc);
5438     }
5439 }
5440
5441 void sRef_setNullTerminatedStateInnerComplete (sRef s, struct s_bbufinfo b, /*@unused@*/ fileloc loc) 
5442 {
5443   switch (b.bufstate) {
5444   case BB_NULLTERMINATED:
5445     sRef_setNullTerminatedState (s);
5446     sRef_setLen (s, b.len);
5447     break;
5448   case BB_POSSIBLYNULLTERMINATED:
5449     sRef_setPossiblyNullTerminatedState(s);
5450     break;
5451   case BB_NOTNULLTERMINATED:
5452     sRef_setNotNullTerminatedState (s);
5453     break;
5454   }
5455
5456   sRef_setSize (s, b.size);
5457   
5458   /* PL: TO BE DONE : Aliases are not modified right now, have to be similar to
5459    * setNullStateInnerComplete.
5460    */
5461 }
5462
5463 void sRef_setNullStateInnerComplete (sRef s, nstate n, fileloc loc)
5464 {
5465   DPRINTF (("Set null state: %s", nstate_unparse (n)));
5466   
5467   sRef_setNullState (s, n, loc);
5468   
5469   switch (n)
5470     {
5471     case NS_POSNULL:
5472       sRef_innerAliasSetComplete (sRef_setPosNull, s, loc);
5473       break;
5474     case NS_DEFNULL:
5475       sRef_innerAliasSetComplete (sRef_setDefNull, s, loc);
5476       break;
5477     case NS_UNKNOWN:
5478       sRef_innerAliasSetComplete (sRef_setNullUnknown, s, loc);
5479       break;
5480     case NS_NOTNULL:
5481       sRef_innerAliasSetComplete (sRef_setNotNull, s, loc);
5482       break;
5483     case NS_MNOTNULL:
5484       sRef_innerAliasSetComplete (sRef_setNotNull, s, loc);
5485       break;
5486     case NS_RELNULL:
5487       sRef_innerAliasSetComplete (sRef_setNullUnknown, s, loc);
5488       break;
5489     case NS_CONSTNULL:
5490       sRef_innerAliasSetComplete (sRef_setDefNull, s, loc);
5491       break;
5492     case NS_ABSNULL:
5493       sRef_innerAliasSetComplete (sRef_setNullUnknown, s, loc);
5494       break;
5495     case NS_ERROR:
5496       sRef_innerAliasSetComplete (sRef_setNullErrorLoc, s, loc);
5497       break;
5498     }
5499 }
5500
5501 void sRef_setPosNull (sRef s, fileloc loc)
5502 {
5503   if (sRef_isValid (s))
5504     {
5505       sRef_setNullStateAux (s, NS_POSNULL, loc);
5506     }
5507 }
5508   
5509 void sRef_setDefNull (sRef s, fileloc loc)
5510 {
5511   if (sRef_isValid (s))
5512     {
5513       sRef_setNullStateAux (s, NS_DEFNULL, loc);
5514     }
5515 }
5516
5517 void sRef_setNullUnknown (sRef s, fileloc loc)
5518 {
5519   if (sRef_isValid (s))
5520     {
5521       sRef_setNullStateAux (s, NS_UNKNOWN, loc);
5522     }
5523 }
5524
5525 void sRef_setNullError (sRef s)
5526 {
5527   if (sRef_isValid (s))
5528     {
5529       sRef_setNullStateAux (s, NS_UNKNOWN, fileloc_undefined);
5530     }
5531 }
5532
5533 void sRef_setNullErrorLoc (sRef s, /*@unused@*/ fileloc loc)
5534 {
5535   sRef_setNullError (s);
5536 }
5537
5538 void sRef_setOnly (sRef s, fileloc loc)
5539 {
5540   sRef_checkMutable (s);
5541
5542   if (sRef_isValid (s) && s->aliaskind != AK_ONLY)
5543     {
5544       s->aliaskind = AK_ONLY;
5545       s->aliasinfo = stateInfo_updateLoc (s->aliasinfo, loc);
5546           }
5547 }
5548
5549 void sRef_setDependent (sRef s, fileloc loc)
5550 {
5551   sRef_checkMutable (s);
5552
5553   if (sRef_isValid (s) && !sRef_isConst (s) && (s->aliaskind != AK_DEPENDENT))
5554     {
5555       DPRINTF (("Setting dependent: %s", sRef_unparseFull (s)));
5556       s->aliaskind = AK_DEPENDENT;
5557       s->aliasinfo = stateInfo_updateLoc (s->aliasinfo, loc);
5558     }
5559 }
5560
5561 void sRef_setOwned (sRef s, fileloc loc)
5562 {
5563   sRef_checkMutable (s);
5564
5565   if (sRef_isValid (s) && !sRef_isConst (s) && (s->aliaskind != AK_OWNED))
5566     {
5567       s->aliaskind = AK_OWNED;
5568       s->aliasinfo = stateInfo_updateLoc (s->aliasinfo, loc);
5569     }
5570 }
5571
5572 void sRef_setKept (sRef s, fileloc loc)
5573 {
5574   sRef_checkMutable (s);
5575
5576   if (sRef_isValid (s) && !sRef_isConst (s) && (s->aliaskind != AK_KEPT))
5577     {
5578       sRef base = sRef_getBaseSafe (s);  
5579       
5580       while (sRef_isValid (base) && sRef_isKnown (base))
5581         {
5582           if (base->defstate == SS_DEFINED) 
5583             {
5584               base->defstate = SS_PDEFINED; 
5585               base = sRef_getBaseSafe (base); 
5586             }
5587           else 
5588             {
5589               break; 
5590             }
5591         }
5592
5593       s->aliaskind = AK_KEPT;
5594       s->aliasinfo = stateInfo_updateLoc (s->aliasinfo, loc);
5595     }
5596 }
5597
5598 static void sRef_setKeptAux (sRef s, fileloc loc)
5599 {
5600   if (!sRef_isShared (s))
5601     {
5602       sRef_setKept (s, loc);
5603     }
5604 }
5605
5606 static void sRef_setDependentAux (sRef s, fileloc loc)
5607 {
5608   if (!sRef_isShared (s))
5609     {
5610       sRef_setDependent (s, loc);
5611     }
5612 }
5613
5614 void sRef_setKeptComplete (sRef s, fileloc loc)
5615 {
5616   sRef_aliasSetComplete (sRef_setKeptAux, s, loc);
5617 }
5618
5619 void sRef_setDependentComplete (sRef s, fileloc loc)
5620 {
5621   sRef_aliasSetComplete (sRef_setDependentAux, s, loc);
5622 }
5623
5624 void sRef_setFresh (sRef s, fileloc loc)
5625 {
5626   sRef_checkMutable (s);
5627
5628   if (sRef_isValid (s))
5629     {
5630       s->aliaskind = AK_FRESH;
5631       s->aliasinfo = stateInfo_updateLoc (s->aliasinfo, loc);
5632     }
5633 }
5634
5635 void sRef_kill (sRef s, fileloc loc)
5636 {
5637   DPRINTF (("Kill: %s", sRef_unparseFull (s)));
5638   sRef_checkMutable (s);
5639
5640   if (sRef_isValid (s) && !sRef_isShared (s) && !sRef_isConst (s))
5641     {
5642       sRef base = sRef_getBaseSafe (s);  
5643       
5644       while (sRef_isValid (base) && sRef_isKnown (base))
5645         {
5646           if (base->defstate == SS_DEFINED) 
5647             {
5648               base->defstate = SS_PDEFINED; 
5649               base = sRef_getBaseSafe (base); 
5650             }
5651           else 
5652             {
5653               break; 
5654             }
5655         }
5656       
5657       s->aliaskind = s->oaliaskind;
5658       s->defstate = SS_DEAD;
5659       s->definfo = stateInfo_updateLoc (s->definfo, loc);
5660
5661       sRef_clearDerived (s);
5662     }
5663 }
5664
5665 void sRef_maybeKill (sRef s, fileloc loc)
5666 {
5667   sRef_checkMutable (s);
5668
5669   if (sRef_isValid (s))
5670     {
5671       sRef base = sRef_getBaseSafe (s);  
5672
5673             
5674       while (sRef_isValid (base) && sRef_isKnown (base))
5675         {
5676           if (base->defstate == SS_DEFINED || base->defstate == SS_RELDEF)
5677             {
5678               base->defstate = SS_PDEFINED; 
5679               base = sRef_getBaseSafe (base); 
5680             }
5681           else 
5682             {
5683               break; 
5684             }
5685           
5686         }
5687       
5688       s->aliaskind = s->oaliaskind;
5689       s->defstate = SS_HOFFA; 
5690       s->definfo = stateInfo_updateLoc (s->definfo, loc);
5691       sRef_clearDerived (s); 
5692     }
5693
5694   }
5695
5696 /*
5697 ** just for type checking...
5698 */
5699
5700 static void sRef_killAux (sRef s, fileloc loc)
5701 {
5702   if (sRef_isValid (s) && !sRef_isShared (s))
5703     {
5704       if (sRef_isUnknownArrayFetch (s))
5705         {
5706           sRef_maybeKill (s, loc);
5707         }
5708       else
5709         {
5710           sRef_kill (s, loc);
5711         }
5712     }
5713 }
5714
5715 /*
5716 ** kills s and all aliases to s
5717 */
5718
5719 void sRef_killComplete (sRef s, fileloc loc)
5720 {
5721   DPRINTF (("Kill complete: %s", sRef_unparseFull (s)));
5722   sRef_aliasSetComplete (sRef_killAux, s, loc);
5723 }
5724
5725 static bool sRef_equivalent (sRef s1, sRef s2)
5726 {
5727   return (sRef_compare (s1, s2) == 0);
5728 }
5729
5730 /*
5731 ** returns an sRef that will not be free'd on function exit.
5732 */
5733
5734 /*@only@*/ sRef sRef_saveCopy (sRef s)
5735 {
5736   sRef ret;
5737
5738   if (sRef_isValid (s))
5739     {
5740       bool old = inFunction;
5741
5742       /*
5743       ** Exit the function scope, so this sRef is not
5744       ** stored in the deallocation table.
5745       */
5746       
5747       inFunction = FALSE;
5748       DPRINTF (("Copying sref: %s", sRef_unparseFull(s)));
5749       ret = sRef_copy (s);
5750       DPRINTF (("Copying ===>: %s", sRef_unparseFull(ret)));
5751       inFunction = old;
5752     }
5753   else
5754     {
5755       ret = sRef_undefined;
5756     }
5757
5758   /*@-dependenttrans@*/ 
5759   return ret;
5760   /*@=dependenttrans@*/ 
5761 }
5762
5763 sRef sRef_copy (sRef s)
5764 {
5765   if (sRef_isKindSpecial (s) && !sRef_isGlobalMarker (s))
5766     {
5767       /*@-retalias@*/
5768       return s; /* don't copy specials (except for global markers) */
5769       /*@=retalias@*/
5770     }
5771
5772   if (sRef_isValid (s))
5773     {
5774       sRef t = sRef_alloc ();
5775
5776       DPRINTF (("Copying: [%p] %s", s, sRef_unparse (s)));
5777       DPRINTF (("Full: %s", sRef_unparseFull (s)));
5778
5779       t->kind = s->kind;
5780       t->safe = s->safe;
5781       t->modified = s->modified;
5782       t->immut = FALSE; /* Note mutability is not copied. */
5783       t->type = s->type;
5784       t->val = multiVal_copy (s->val);
5785
5786       t->info = sinfo_copy (s);
5787       t->defstate = s->defstate;
5788       t->nullstate = s->nullstate;
5789  
5790       /* start modifications */
5791       t->bufinfo.bufstate = s->bufinfo.bufstate;
5792       t->bufinfo.len = s->bufinfo.len;
5793       t->bufinfo.size = s->bufinfo.size;
5794       /* end modifications */
5795
5796       t->aliaskind = s->aliaskind;
5797       t->oaliaskind = s->oaliaskind;
5798
5799       t->expkind = s->expkind;
5800       t->oexpkind = s->oexpkind;
5801
5802       t->nullinfo = stateInfo_copy (s->nullinfo);
5803       t->aliasinfo = stateInfo_copy (s->aliasinfo);
5804       t->definfo = stateInfo_copy (s->definfo);
5805       t->expinfo = stateInfo_copy (s->expinfo);
5806
5807       t->deriv = sRefSet_newDeepCopy (s->deriv);
5808       t->state = valueTable_copy (s->state);
5809
5810       DPRINTF (("Made copy: %s => %s", sRef_unparseFull (s), sRef_unparseFull (t)));
5811       return t;
5812     }
5813   else
5814     {
5815       return sRef_undefined;
5816     }
5817 }
5818
5819 /*@notfunction@*/
5820 # define PREDTEST(func,s) \
5821    do { if (sRef_isInvalid (s)) { return FALSE; } \
5822         else { if (sRef_isConj (s)) \
5823                   { return (func (sRef_getConjA (s)) \
5824                             || func (sRef_getConjB (s))); }}} while (FALSE);
5825
5826 bool sRef_isAddress (sRef s)
5827 {
5828   PREDTEST (sRef_isAddress, s);
5829   return (s->kind == SK_ADR);
5830 }
5831           
5832 /*
5833 ** pretty weak... maybe a flag should control this.
5834 */
5835
5836 bool sRef_isThroughArrayFetch (sRef s)
5837 {
5838   if (sRef_isValid (s))
5839     {
5840       sRef tref = s;
5841
5842       do 
5843         {
5844           sRef lt;
5845
5846           if (sRef_isArrayFetch (tref)) 
5847             {
5848               return TRUE;
5849             }
5850           
5851           lt = sRef_getBase (tref);
5852           tref = lt;
5853         } while (sRef_isValid (tref));
5854     } 
5855
5856   return FALSE;
5857 }
5858
5859 bool sRef_isArrayFetch (sRef s)
5860 {
5861   PREDTEST (sRef_isArrayFetch, s);
5862   return (s->kind == SK_ARRAYFETCH);
5863 }
5864
5865 bool sRef_isMacroParamRef (sRef s)
5866 {
5867   if (context_inMacro () && sRef_isCvar (s))
5868     {
5869       uentry ue = sRef_getUentry (s);
5870       cstring pname = makeParam (uentry_rawName (ue));
5871       uentry mac = usymtab_lookupSafe (pname);
5872
5873       cstring_free (pname);
5874       return (uentry_isValid (mac));
5875     }
5876
5877   return FALSE;
5878 }
5879       
5880 bool sRef_isCvar (sRef s) 
5881 {
5882   PREDTEST (sRef_isCvar, s);
5883   return (s->kind == SK_CVAR);
5884 }
5885
5886 bool sRef_isConst (sRef s) 
5887 {
5888   PREDTEST (sRef_isConst, s);
5889   return (s->kind == SK_CONST);
5890 }
5891
5892 bool sRef_isObject (sRef s) 
5893 {
5894   PREDTEST (sRef_isObject, s);
5895   return (s->kind == SK_OBJECT);
5896 }
5897
5898 bool sRef_isExternal (sRef s) 
5899 {
5900   PREDTEST (sRef_isExternal, s);
5901   return (s->kind == SK_EXTERNAL);
5902 }
5903
5904 static bool sRef_isDerived (sRef s) 
5905 {
5906   PREDTEST (sRef_isDerived, s);
5907   return (s->kind == SK_DERIVED);
5908 }
5909
5910 bool sRef_isField (sRef s)
5911 {
5912   PREDTEST (sRef_isField, s);
5913   return (s->kind == SK_FIELD);
5914 }
5915
5916 static bool sRef_isIndex (sRef s)
5917 {
5918   PREDTEST (sRef_isIndex, s);
5919   return (s->kind == SK_ARRAYFETCH);
5920 }
5921
5922 bool sRef_isAnyParam (sRef s)
5923 {
5924   PREDTEST (sRef_isAnyParam, s);
5925   return (s->kind == SK_PARAM);  
5926 }
5927
5928 bool sRef_isParam (sRef s)
5929 {
5930   PREDTEST (sRef_isParam, s);
5931   return (s->kind == SK_PARAM);
5932 }
5933
5934 bool sRef_isDirectParam (sRef s)
5935 {
5936   PREDTEST (sRef_isDirectParam, s);
5937
5938   return ((s->kind == SK_CVAR) &&
5939           (s->info->cvar->lexlevel == functionScope) &&
5940           (context_inFunction () && 
5941            (s->info->cvar->index <= uentryList_size (context_getParams ()))));
5942 }
5943
5944 bool sRef_isPointer (sRef s)
5945 {
5946   PREDTEST (sRef_isPointer, s);
5947   return (s->kind == SK_PTR);
5948 }
5949
5950 /*
5951 ** returns true if storage referenced by s is visible
5952 */
5953
5954 bool sRef_isReference (sRef s)
5955 {
5956   PREDTEST (sRef_isReference, s);
5957
5958   return (sRef_isPointer (s) || sRef_isIndex (s) || sRef_isFileOrGlobalScope (s)
5959           || (sRef_isField (s) && (sRef_isReference (s->info->field->rec))));
5960 }
5961
5962 bool sRef_isIReference (sRef s)
5963 {
5964   return (sRef_isPointer (s) || sRef_isAddress (s) || sRef_isIndex (s)
5965           || sRef_isField (s) || sRef_isArrayFetch (s));
5966 }
5967
5968 bool sRef_isFileOrGlobalScope (sRef s)
5969 {
5970   return (sRef_isCvar (s) && (s->info->cvar->lexlevel <= fileScope));
5971 }
5972
5973 bool sRef_isRealGlobal (sRef s)
5974 {
5975   return (sRef_isCvar (s) && (s->info->cvar->lexlevel == globScope));
5976 }
5977
5978 bool sRef_isFileStatic (sRef s)
5979 {
5980   return (sRef_isCvar (s) && (s->info->cvar->lexlevel == fileScope));
5981 }
5982
5983 bool sRef_isAliasCheckedGlobal (sRef s)
5984 {
5985   if (sRef_isFileOrGlobalScope (s))
5986     {
5987       uentry ue = sRef_getUentry (s);
5988
5989       return context_checkAliasGlob (ue);
5990     }
5991   else
5992     {
5993       return FALSE;
5994     }
5995 }
5996
5997 void sRef_free (/*@only@*/ sRef s)
5998 {
5999   if (s != sRef_undefined && s->kind != SK_SPECIAL)
6000     {
6001       DPRINTF (("Free sref: [%p]", s));
6002
6003       sRef_checkValid (s);
6004
6005       stateInfo_free (s->expinfo);
6006       stateInfo_free (s->aliasinfo);
6007       stateInfo_free (s->definfo);
6008       stateInfo_free (s->nullinfo);
6009
6010       sRefSet_free (s->deriv);
6011       s->deriv = sRefSet_undefined;
6012
6013       /*@i43@*/ /* valueTable_free (s->state); */
6014       sinfo_free (s);
6015       
6016       
6017       /* drl added to help locate use after release*/
6018       s->expinfo = stateInfo_undefined;
6019       s->aliasinfo = stateInfo_undefined;
6020       s->definfo = stateInfo_undefined;
6021       s->nullinfo = stateInfo_undefined;
6022
6023       /*@i32@*/ sfree (s);
6024     }
6025 }
6026
6027 void sRef_setType (sRef s, ctype t)
6028 {
6029   sRef_checkMutable (s);
6030
6031   if (sRef_isValid (s))
6032     {
6033       s->type = t;
6034     }
6035 }
6036
6037 void sRef_setTypeFull (sRef s, ctype t)
6038 {
6039   sRef_checkMutable (s);
6040
6041   if (sRef_isValid (s))
6042     {
6043       s->type = t;
6044
6045       sRefSet_allElements (s->deriv, current)
6046         {
6047           sRef_setTypeFull (current, ctype_unknown);
6048         } end_sRefSet_allElements ;
6049     }
6050 }
6051
6052 /*@exposed@*/ sRef
6053   sRef_buildField (/*@exposed@*/ sRef rec, /*@dependent@*/ cstring f)
6054 {
6055   return (sRef_buildNCField (rec, f)); 
6056 }
6057
6058 static /*@exposed@*/ sRef
6059 sRef_findDerivedField (/*@notnull@*/ sRef rec, cstring f)
6060 {
6061   sRefSet_allElements (rec->deriv, sr)
6062     {
6063       if (sRef_isValid (sr))
6064         {
6065           if (sr->info != NULL) 
6066             {
6067               if (sr->kind == SK_FIELD && cstring_equal (sr->info->field->field, f))
6068                 {
6069                   return sr;
6070                 }
6071             }
6072         }
6073     } end_sRefSet_allElements;
6074
6075   return sRef_undefined;
6076 }
6077
6078 /*@dependent@*/ /*@observer@*/ sRefSet sRef_derivedFields (/*@temp@*/ sRef rec)
6079 {
6080   if (sRef_isValid (rec))
6081     {
6082       sRefSet ret;
6083       ret = rec->deriv;
6084       return (ret);
6085     }
6086   else
6087     {
6088       return (sRefSet_undefined);
6089     }
6090 }
6091
6092 static /*@exposed@*/ sRef
6093   sRef_findDerivedPointer (sRef s)
6094 {
6095   if (sRef_isValid (s))
6096     {
6097       sRefSet_realElements (s->deriv, sr)
6098         {
6099           if (sRef_isValid (sr) && sr->kind == SK_PTR)
6100             {
6101               return sr;
6102             }
6103         } end_sRefSet_realElements;
6104     }
6105
6106   return sRef_undefined;
6107 }
6108
6109 bool
6110 sRef_isUnknownArrayFetch (sRef s)
6111 {
6112   return (sRef_isValid (s) 
6113           && s->kind == SK_ARRAYFETCH
6114           && !s->info->arrayfetch->indknown);
6115 }
6116
6117 static /*@exposed@*/ sRef
6118 sRef_findDerivedArrayFetch (/*@notnull@*/ sRef s, bool isknown, int idx, bool dead)
6119 {
6120   
6121   if (isknown) 
6122     {
6123       sRefSet_realElements (s->deriv, sr)
6124         {
6125           if (sRef_isValid (sr)
6126               && sr->kind == SK_ARRAYFETCH
6127               && sr->info->arrayfetch->indknown
6128               && (sr->info->arrayfetch->ind == idx))
6129             {
6130               return sr;
6131             }
6132         } end_sRefSet_realElements;
6133     }
6134   else
6135     {
6136       sRefSet_realElements (s->deriv, sr)
6137         {
6138           if (sRef_isValid (sr)
6139               && sr->kind == SK_ARRAYFETCH
6140               && (!sr->info->arrayfetch->indknown
6141                   || (sr->info->arrayfetch->indknown && 
6142                       sr->info->arrayfetch->ind == 0)))
6143             {
6144               if (sRef_isDead (sr) || sRef_isKept (sr))
6145                 {
6146                   if (dead || context_getFlag (FLG_STRICTUSERELEASED))
6147                     {
6148                       return sr;
6149                     }
6150                 }
6151               else
6152                 {
6153                   return sr;
6154                 }
6155             }
6156         } end_sRefSet_realElements;
6157     }
6158
6159   return sRef_undefined;
6160 }
6161
6162 static /*@exposed@*/ sRef 
6163 sRef_buildNCField (/*@exposed@*/ sRef rec, /*@exposed@*/ cstring f)
6164 {
6165   sRef s;
6166
6167   DPRINTF (("Build nc field: %s / %s",
6168             sRef_unparseFull (rec), f));
6169
6170   if (sRef_isInvalid (rec))
6171     {
6172       return sRef_undefined;
6173     }
6174       
6175   /*
6176   ** check if the field already has been referenced 
6177   */
6178
6179   s = sRef_findDerivedField (rec, f);
6180   
6181   if (sRef_isValid (s))
6182     {
6183       return s;
6184     }
6185   else
6186     {
6187       ctype ct = ctype_realType (rec->type);
6188       
6189       DPRINTF (("Field of: %s", sRef_unparse (rec)));
6190       
6191       s = sRef_newRef ();      
6192       s->kind = SK_FIELD;
6193       s->info = (sinfo) dmalloc (sizeof (*s->info));
6194       s->info->field = (fldinfo) dmalloc (sizeof (*s->info->field));
6195       s->info->field->rec = rec; /* sRef_copy (rec); */ /*@i32@*/
6196       s->info->field->field = f; /* doesn't copy f */
6197       
6198       if (ctype_isKnown (ct) && ctype_isSU (ct))
6199         {
6200           uentry ue = uentryList_lookupField (ctype_getFields (ct), f);
6201         
6202           if (!uentry_isUndefined (ue))
6203             {
6204               DPRINTF (("lookup: %s for %s", uentry_unparseFull (ue),
6205                         ctype_unparse (ct)));
6206               
6207               s->type = uentry_getType (ue);
6208
6209               if (ctype_isMutable (s->type)
6210                   && rec->aliaskind != AK_STACK 
6211                   && !alkind_isStatic (rec->aliaskind))
6212                 {
6213                   s->aliaskind = rec->aliaskind;
6214                 }
6215               else
6216                 {
6217                   s->aliaskind = AK_UNKNOWN;
6218                 }
6219
6220               if (sRef_isStateDefined (rec) || sRef_isStateUnknown (rec) 
6221                   || sRef_isPdefined (rec))
6222                 {
6223                   sRef_setStateFromUentry (s, ue);
6224                 }
6225               else
6226                 {
6227                   sRef_setPartsFromUentry (s, ue);
6228                 }
6229               
6230               s->oaliaskind = s->aliaskind;
6231               s->oexpkind = s->expkind;
6232               
6233               DPRINTF (("sref: %s", sRef_unparseFull (s)));
6234             }
6235           else
6236             {
6237               /*
6238                 Never report this as an error.  It can happen whenever there
6239                 is casting involved.
6240
6241               if (report)
6242                 {
6243                   llcontbug (message ("buildNCField --- no field %s: %q / %s",
6244                                       f, sRef_unparse (s), ctype_unparse (ct)));
6245                 }
6246                 */
6247
6248               return sRef_undefined;
6249             }
6250         }
6251       
6252       if (rec->defstate == SS_DEFINED 
6253           && (s->defstate == SS_UNDEFINED || s->defstate == SS_UNKNOWN))
6254         {
6255           s->defstate = SS_DEFINED;
6256         }
6257       else if (rec->defstate == SS_PARTIAL)
6258         {
6259           s->defstate = SS_PARTIAL;
6260         }
6261       else if (rec->defstate == SS_ALLOCATED) 
6262         {
6263           if (ctype_isStackAllocated (ct) && ctype_isStackAllocated (s->type))
6264             {
6265               s->defstate = SS_ALLOCATED;
6266             }
6267           else
6268             {
6269               s->defstate = SS_UNDEFINED;
6270             }
6271         }
6272       else if (s->defstate == SS_UNKNOWN)
6273         {
6274           s->defstate = rec->defstate;
6275         }
6276       else
6277         {
6278           ; /* no change */
6279         }
6280
6281       if (s->defstate == SS_UNDEFINED)
6282         {
6283           ctype rt = ctype_realType (s->type);
6284           
6285           if (ctype_isArray (rt) || ctype_isSU (rt))
6286             {
6287               s->defstate = SS_ALLOCATED;
6288             }
6289         }
6290
6291       sRef_addDeriv (rec, s);
6292       DPRINTF (("Add deriv: %s", sRef_unparseFull (rec)));
6293
6294       if (ctype_isInt (s->type) && cstring_equal (f, REFSNAME))
6295         {
6296           s->aliaskind = AK_REFS;
6297           s->oaliaskind = AK_REFS;
6298         }
6299
6300       DPRINTF (("Build field ==> %s", sRef_unparseFull (s)));
6301       return s;
6302     }
6303 }
6304
6305 bool
6306 sRef_isStackAllocated (sRef s)
6307 {
6308   return (sRef_isValid(s) 
6309           && s->defstate == SS_ALLOCATED && ctype_isStackAllocated (s->type));
6310 }
6311           
6312 static
6313 void sRef_setArrayFetchState (/*@notnull@*/ /*@exposed@*/ sRef s, 
6314                               /*@notnull@*/ /*@exposed@*/ sRef arr)
6315 {
6316   sRef_checkMutable (s);
6317
6318   if (ctype_isRealAP (arr->type))
6319     {
6320       s->type = ctype_baseArrayPtr (arr->type);
6321     }
6322
6323   /* a hack, methinks... makeArrayFetch (&a[0]) ==> a[] */
6324   /* evans - 2001-08-27: not sure where this was necessary - it
6325   ** causes an assertion in in aliasCheckPred to fail.
6326   */
6327
6328   if (sRef_isAddress (arr)) 
6329     {
6330       sRef t = arr->info->ref;
6331       
6332       if (sRef_isArrayFetch (t))
6333         {
6334           s->info->arrayfetch->arr = t->info->arrayfetch->arr;
6335         }
6336     }
6337   else if (ctype_isRealPointer (arr->type))
6338     {
6339       sRef sp = sRef_findDerivedPointer (arr);
6340       
6341       if (sRef_isValid (sp))
6342         {
6343           
6344           if (ctype_isMutable (s->type))
6345             {
6346               sRef_setExKind (s, sRef_getExKind (sp), fileloc_undefined);
6347                       
6348               s->aliaskind = sp->aliaskind;
6349             }
6350
6351           s->defstate = sp->defstate;
6352
6353           if (s->defstate == SS_DEFINED) 
6354             {
6355               if (!context_getFlag (FLG_STRICTDESTROY))
6356                 {
6357                   s->defstate = SS_PARTIAL;
6358                 }
6359             }
6360
6361           DPRINTF (("Set null state: %s / %s", sRef_unparseFull (s), sRef_unparseFull (sp)));
6362           sRef_setNullStateN (s, sRef_getNullState (sp));
6363         }
6364       else
6365         {
6366           if (arr->defstate == SS_UNDEFINED)
6367             {
6368               s->defstate = SS_UNUSEABLE;
6369             }
6370           else if ((arr->defstate == SS_ALLOCATED) && !ctype_isSU (s->type))
6371             {
6372               s->defstate = SS_UNDEFINED;
6373             }
6374           else
6375             {
6376               if (!context_getFlag (FLG_STRICTDESTROY))
6377                 {
6378                   s->defstate = SS_PARTIAL;
6379                 }
6380               else
6381                 {
6382                   s->defstate = SS_DEFINED;
6383                 }
6384
6385               /*
6386               ** Very weak checking for array elements.
6387               ** Was:
6388               **     s->defstate = arr->defstate;
6389               */
6390             }
6391
6392           sRef_setExKind (s, sRef_getExKind (arr), g_currentloc);
6393
6394           if (arr->aliaskind == AK_LOCAL || arr->aliaskind == AK_FRESH)
6395             {
6396               s->aliaskind = AK_LOCAL;
6397             }
6398           else
6399             {
6400               s->aliaskind = AK_UNKNOWN;
6401             }
6402           
6403           sRef_setTypeState (s);
6404         }
6405     }
6406   else
6407     {
6408       if (arr->defstate == SS_DEFINED)
6409         {
6410           /*
6411           ** Very weak checking for array elements.
6412           ** Was:
6413           **     s->defstate = arr->defstate;
6414           */
6415
6416           if (context_getFlag (FLG_STRICTDESTROY))
6417             {
6418               s->defstate = SS_DEFINED;
6419             }
6420           else
6421             {
6422               s->defstate = SS_PARTIAL;
6423             }
6424         }
6425       else if (arr->defstate == SS_ALLOCATED)
6426         {
6427           if (ctype_isRealArray (s->type))
6428             {
6429               s->defstate = SS_ALLOCATED;
6430             }
6431           else 
6432             {
6433               if (!s->info->arrayfetch->indknown)
6434                 {
6435                   /*
6436                   ** is index is unknown, elements is defined or 
6437                   ** allocated is any element is!
6438                   */
6439                   
6440                   s->defstate = SS_UNDEFINED;
6441                   
6442                   sRefSet_allElements (arr->deriv, sr)
6443                     {
6444                       if (sRef_isValid (sr))
6445                         {
6446                           if (sr->defstate == SS_ALLOCATED)
6447                             {
6448                               s->defstate = SS_ALLOCATED;
6449                             }
6450                           else 
6451                             {
6452                               if (sr->defstate == SS_DEFINED)
6453                                 {
6454                                   if (context_getFlag (FLG_STRICTDESTROY))
6455                                     {
6456                                       s->defstate = SS_DEFINED;
6457                                     }
6458                                   else
6459                                     {
6460                                       s->defstate = SS_PARTIAL;
6461                                     }
6462
6463                                   break;
6464                                 }
6465                             }
6466                         }
6467                     } end_sRefSet_allElements;
6468                   
6469                                 }
6470               else
6471                 {
6472                   s->defstate = SS_UNDEFINED;
6473                 }
6474             }
6475         }
6476       else
6477         {
6478           s->defstate = arr->defstate;
6479         }
6480       
6481       
6482       /*
6483       ** kludgey way to guess where aliaskind applies
6484       */
6485       
6486       if (ctype_isMutable (s->type) 
6487           && !ctype_isPointer (arr->type) 
6488           && !alkind_isStatic (arr->aliaskind)
6489           && !alkind_isStack (arr->aliaskind)) /* evs - 2000-06-20: don't pass stack allocation to members */
6490         {
6491           s->aliaskind = arr->aliaskind;
6492         }
6493       else
6494         {
6495           s->aliaskind = AK_UNKNOWN;
6496         }
6497     
6498       sRef_setTypeState (s);
6499     }
6500
6501   if (sRef_isObserver (arr)) 
6502     {
6503       s->expkind = XO_OBSERVER;
6504     }
6505 }  
6506
6507 /*@exposed@*/ sRef sRef_buildArrayFetch (/*@exposed@*/ sRef arr)
6508 {
6509   sRef s;
6510
6511   if (!sRef_isValid (arr)) {
6512     /*@-nullret@*/ return arr /*@=nullret@*/;
6513   }
6514
6515   if (ctype_isRealPointer (arr->type))
6516     {
6517       (void) sRef_buildPointer (arr); /* do this to define arr! */
6518     }
6519   
6520   s = sRef_findDerivedArrayFetch (arr, FALSE, 0, FALSE);
6521   
6522   if (sRef_isValid (s))
6523     {
6524       /* evans 2001-07-12: this is bogus, clean-up hack */
6525       if (s->info->arrayfetch->arr != arr)
6526         {
6527           sRef res;
6528           check (sRefSet_delete (arr->deriv, s));
6529           res = sRef_buildArrayFetch (arr);
6530           sRef_copyState (res, s);
6531           llassert (res->info->arrayfetch->arr == arr); 
6532           return res;
6533         }
6534
6535       sRef_setExKind (s, sRef_getExKind (arr), g_currentloc);
6536       return s;
6537     }
6538   else
6539     {
6540       s = sRef_newRef ();
6541
6542       s->kind = SK_ARRAYFETCH;
6543       s->info = (sinfo) dmalloc (sizeof (*s->info));
6544       s->info->arrayfetch = (ainfo) dmalloc (sizeof (*s->info->arrayfetch));
6545       s->info->arrayfetch->indknown = FALSE;
6546       s->info->arrayfetch->ind = 0;
6547       s->info->arrayfetch->arr = arr; /* sRef_copy (arr); */ /*@i32@*/
6548
6549       sRef_setArrayFetchState (s, arr);
6550
6551       s->oaliaskind = s->aliaskind;
6552       s->oexpkind = s->expkind;
6553
6554       if (!context_inProtectVars ())
6555         {
6556           sRef_addDeriv (arr, s);
6557         }
6558       
6559       if (valueTable_isUndefined (s->state))
6560         {
6561           s->state = context_createValueTable (s, stateInfo_makeLoc (g_currentloc));
6562         }
6563       
6564       return (s);
6565     }
6566 }
6567
6568 /*@exposed@*/ sRef
6569   sRef_buildArrayFetchKnown (/*@exposed@*/ sRef arr, int i)
6570 {
6571   sRef s;
6572
6573   if (!sRef_isValid (arr)) {
6574     /*@-nullret@*/ return arr /*@=nullret@*/;
6575   }
6576
6577   if (ctype_isRealPointer (arr->type))
6578     {
6579       (void) sRef_buildPointer (arr); /* do this to define arr! */
6580     }
6581
6582   s = sRef_findDerivedArrayFetch (arr, TRUE, i, FALSE);
6583
6584   if (sRef_isValid (s))
6585     {
6586       /* evans 2001-07-12: this is bogus, clean-up hack */
6587       if (s->info->arrayfetch->arr != arr)
6588         {
6589           sRef res;
6590
6591           check (sRefSet_delete (arr->deriv, s));
6592           res = sRef_buildArrayFetchKnown (arr, i);
6593
6594           llassert (res->info->arrayfetch->arr == arr);
6595           sRef_copyState (res, s);
6596           llassert (res->info->arrayfetch->arr == arr);
6597           return res;
6598         }
6599
6600       sRef_setExKind (s, sRef_getExKind (arr), g_currentloc);      
6601       llassert (s->info->arrayfetch->arr == arr);
6602       return s;
6603     }
6604   else
6605     {
6606       s = sRef_newRef ();
6607       
6608       s->kind = SK_ARRAYFETCH;
6609       s->info = (sinfo) dmalloc (sizeof (*s->info));
6610       s->info->arrayfetch = (ainfo) dmalloc (sizeof (*s->info->arrayfetch));
6611       s->info->arrayfetch->arr = arr; /* sRef_copy (arr); */ /*@i32@*/
6612       s->info->arrayfetch->indknown = TRUE;
6613       s->info->arrayfetch->ind = i;
6614
6615       sRef_setArrayFetchState (s, arr);
6616       /* evans 2001-08-27 no: can change this - llassert (s->info->arrayfetch->arr == arr); */
6617
6618       s->oaliaskind = s->aliaskind;
6619       s->oexpkind = s->expkind;
6620       sRef_addDeriv (arr, s);
6621
6622       llassert (valueTable_isUndefined (s->state));
6623       s->state = context_createValueTable (s, stateInfo_makeLoc (g_currentloc));
6624       return (s);
6625     }
6626 }
6627
6628 /*
6629 ** sets everything except for defstate
6630 */
6631
6632 static void
6633 sRef_setPartsFromUentry (sRef s, uentry ue)
6634 {    
6635   sRef uref = uentry_getSref (ue);
6636
6637   llassert (sRef_isValid (s));
6638
6639   s->aliaskind = alkind_derive (s->aliaskind, uentry_getAliasKind (ue));
6640   s->oaliaskind = s->aliaskind;
6641
6642   if (s->expkind == XO_UNKNOWN)
6643     {
6644       s->expkind = uentry_getExpKind (ue);
6645     }
6646   
6647   s->oexpkind = s->expkind;
6648   
6649   if (sRef_getNullState (s) == NS_UNKNOWN)
6650     {
6651       DPRINTF (("Set null state: %s / %s", sRef_unparseFull (s), uentry_unparseFull (ue)));
6652       sRef_setNullStateN (s, sRef_getNullState (uentry_getSref (ue)));
6653     }
6654   else
6655     {
6656       DPRINTF (("Skipping null null state!"));
6657     }
6658
6659   if (s->aliaskind == AK_IMPONLY && (sRef_isExposed (s) || sRef_isObserver (s)))
6660     {
6661       s->oaliaskind = s->aliaskind = AK_IMPDEPENDENT;
6662     } 
6663
6664   if (sRef_isValid (uref))
6665     {
6666       valueTable utable = uref->state;
6667       valueTable_free (s->state);
6668       s->state = valueTable_copy (utable);
6669     }
6670 }
6671
6672 static void
6673 sRef_setStateFromAbstractUentry (sRef s, uentry ue)
6674 {
6675   llassert (sRef_isValid (s));
6676   sRef_checkMutable (s);
6677
6678   sRef_setPartsFromUentry (s, ue);
6679
6680   s->aliaskind = alkind_derive (s->aliaskind, uentry_getAliasKind (ue));
6681   s->oaliaskind = s->aliaskind;
6682
6683   if (s->expkind == XO_UNKNOWN)
6684     {
6685       s->expkind = uentry_getExpKind (ue);
6686     }
6687
6688   s->oexpkind = s->expkind;
6689 }
6690
6691 void
6692 sRef_setStateFromUentry (sRef s, uentry ue)
6693 {
6694   sstate defstate;
6695
6696   sRef_checkMutable (s);
6697   llassert (sRef_isValid (s));
6698   
6699   sRef_setPartsFromUentry (s, ue);
6700
6701   defstate = uentry_getDefState (ue);
6702
6703   if (sstate_isKnown (defstate))
6704     {
6705       s->defstate = defstate;
6706     }
6707   else
6708     {
6709       ;
6710     }
6711 }
6712
6713 /*@exposed@*/ sRef
6714   sRef_buildPointer (/*@exposed@*/ sRef t)
6715 {
6716   DPRINTF (("build pointer: %s", sRef_unparse (t)));
6717
6718   if (sRef_isInvalid (t)) return sRef_undefined;
6719
6720   if (sRef_isAddress (t))
6721     {
6722       DPRINTF (("Return ref: %s", sRef_unparse (t->info->ref)));
6723       return (t->info->ref);
6724     }
6725   else
6726     {
6727       sRef s = sRef_findDerivedPointer (t);
6728
6729       DPRINTF (("find derived: %s", sRef_unparse (s)));
6730
6731       if (sRef_isValid (s))
6732         {
6733           
6734           sRef_setExKind (s, sRef_getExKind (t), g_currentloc);
6735           s->oaliaskind = s->aliaskind;
6736           s->oexpkind = s->expkind;
6737
6738           return s;
6739         }
6740       else
6741         {
6742           s = sRef_constructPointerAux (t);
6743           
6744           DPRINTF (("construct: %s", sRef_unparse (s)));
6745
6746           if (sRef_isValid (s))
6747             {
6748               sRef_addDeriv (t, s);
6749
6750               s->oaliaskind = s->aliaskind;
6751               s->oexpkind = s->expkind;
6752             }
6753           
6754           return s;
6755         }
6756     }
6757 }
6758
6759 /*@exposed@*/ sRef
6760 sRef_constructPointer (/*@exposed@*/ sRef t)
6761    /*@modifies t@*/
6762 {
6763   return sRef_buildPointer (t);
6764 }
6765
6766 static /*@exposed@*/ sRef sRef_constructDerefAux (sRef t, bool isdead)
6767 {
6768   if (sRef_isValid (t))
6769     {
6770       sRef s;
6771       
6772       /*
6773       ** if there is a derived t[?], return that.  Otherwise, *t.
6774       */
6775       
6776       s = sRef_findDerivedArrayFetch (t, FALSE, 0, isdead);
6777       
6778       if (sRef_isValid (s))
6779         {
6780           DPRINTF (("Found array fetch: %s", sRef_unparseFull (s)));
6781           return s;
6782         }
6783       else
6784         {
6785           sRef ret = sRef_constructPointer (t);
6786
6787           DPRINTF (("Constructed pointer: %s", sRef_unparseFull (ret)));
6788
6789           return ret;
6790         }
6791     }
6792   else
6793     {
6794       return sRef_undefined;
6795     }
6796 }
6797
6798 sRef sRef_constructDeref (sRef t)
6799 {
6800   return sRef_constructDerefAux (t, FALSE);
6801 }
6802
6803 sRef sRef_constructDeadDeref (sRef t)
6804 {
6805   return sRef_constructDerefAux (t, TRUE);
6806 }
6807
6808 static sRef
6809 sRef_constructPointerAux (/*@notnull@*/ /*@exposed@*/ sRef t)
6810 {
6811   sRef s = sRef_newRef ();
6812   ctype rt = t->type;
6813   ctype st;
6814   
6815   llassert (valueTable_isUndefined (s->state));
6816
6817   s->kind = SK_PTR;
6818   s->info = (sinfo) dmalloc (sizeof (*s->info));
6819   s->info->ref = t; /* sRef_copy (t); */ /*@i32*/
6820   
6821   if (ctype_isRealAP (rt))
6822     {
6823       s->type = ctype_baseArrayPtr (rt);
6824     }
6825   
6826   st = ctype_realType (s->type);  
6827
6828   if (t->defstate == SS_UNDEFINED)
6829     {
6830       s->defstate = SS_UNUSEABLE;
6831     }
6832   else if ((t->defstate == SS_ALLOCATED) && !ctype_isSU (st))
6833     {
6834       s->defstate = SS_UNDEFINED;
6835     }
6836   else
6837     {
6838       s->defstate = t->defstate;
6839     }
6840   
6841   if (t->aliaskind == AK_LOCAL || t->aliaskind == AK_FRESH)
6842     {
6843       s->aliaskind = AK_LOCAL;
6844     }
6845   else
6846     {
6847       s->aliaskind = AK_UNKNOWN;
6848     }
6849
6850   sRef_setExKind (s, sRef_getExKind (t), fileloc_undefined);
6851   sRef_setTypeState (s);
6852
6853   s->oaliaskind = s->aliaskind;
6854   s->oexpkind = s->expkind;
6855
6856   if (valueTable_isUndefined (s->state))
6857     {
6858       s->state = context_createValueTable (s, stateInfo_makeLoc (g_currentloc));
6859     }
6860
6861   return s;
6862 }
6863
6864 bool sRef_hasDerived (sRef s)
6865 {
6866   return (sRef_isValid (s) && !sRefSet_isEmpty (s->deriv));
6867 }
6868
6869 void
6870 sRef_clearDerived (sRef s)
6871 {
6872   if (sRef_isValid (s))
6873     {
6874       sRefSet_clear (s->deriv); 
6875     }
6876 }
6877
6878 void
6879 sRef_clearDerivedComplete (sRef s)
6880 {
6881   
6882   if (sRef_isValid (s))
6883     {
6884       sRef base = sRef_getBaseSafe (s);
6885
6886       while (sRef_isValid (base))
6887         {
6888           sRefSet_clear (base->deriv); 
6889           base = sRef_getBaseSafe (base);
6890         }
6891
6892       sRefSet_clear (s->deriv); 
6893     }
6894 }
6895
6896 /*@exposed@*/ sRef sRef_makePointer (/*@exposed@*/ sRef s)
6897      /*@modifies s@*/
6898 {
6899   sRef res = sRef_buildPointer (s); 
6900
6901   DPRINTF (("Res: %s", sRef_unparse (res)));
6902   return res;
6903 }
6904
6905 /*
6906 ** &a[] => a (this is for out params)
6907 */
6908
6909 /*@exposed@*/ sRef
6910 sRef_makeAnyArrayFetch (/*@exposed@*/ sRef arr)
6911 {  
6912   if (sRef_isAddress (arr))
6913     {
6914       return (arr->info->ref);
6915     }
6916   else
6917     {
6918       return (sRef_buildArrayFetch (arr));
6919     }
6920 }
6921
6922 /*@exposed@*/ sRef
6923 sRef_makeArrayFetch (/*@exposed@*/ sRef arr)
6924 {
6925   return (sRef_buildArrayFetch (arr));
6926 }
6927
6928 /*@exposed@*/ sRef
6929 sRef_makeArrayFetchKnown (/*@exposed@*/ sRef arr, int i)
6930 {
6931   return (sRef_buildArrayFetchKnown (arr, i));
6932 }
6933
6934 /*@exposed@*/ sRef
6935 sRef_makeField (sRef rec, /*@dependent@*/ cstring f)
6936 {
6937   sRef ret;
6938   ret = sRef_buildField (rec, f);
6939   return ret;
6940 }
6941
6942 /*@exposed@*/ sRef
6943 sRef_makeNCField (/*@exposed@*/ sRef rec, /*@dependent@*/ cstring f)
6944 {
6945   return (sRef_buildNCField (rec, f));
6946 }
6947
6948 /*@only@*/ cstring
6949 sRef_unparseKindName (sRef s)
6950 {
6951   cstring result;
6952
6953   if (s == sRef_undefined) return cstring_makeLiteral ("<invalid>");
6954
6955   s = sRef_fixConj (s);
6956
6957   switch (s->kind)
6958     {
6959     case SK_CVAR: 
6960       if (sRef_isLocalVar (s)) 
6961         {
6962           result = cstring_makeLiteral ("Variable");
6963         }
6964       else
6965         {
6966           result = cstring_makeLiteral ("Undef global");
6967         }
6968       break;
6969     case SK_PARAM:
6970       result = cstring_makeLiteral ("Out parameter");
6971       break;
6972     case SK_ARRAYFETCH:
6973       if (sRef_isAnyParam (s->info->arrayfetch->arr)) 
6974         {
6975           result = cstring_makeLiteral ("Out parameter");
6976         }
6977       else if (sRef_isIndexKnown (s))
6978         {
6979           result = cstring_makeLiteral ("Array element");
6980         }
6981       else
6982         {
6983           result = cstring_makeLiteral ("Value");
6984         }
6985       break;
6986     case SK_PTR:
6987       if (sRef_isAnyParam (s->info->ref)) 
6988         {
6989           result = cstring_makeLiteral ("Out parameter");
6990         }
6991       else
6992         {
6993           result = cstring_makeLiteral ("Value");
6994         }
6995       break;
6996     case SK_ADR:
6997       result = cstring_makeLiteral ("Value");
6998       break;
6999     case SK_FIELD:
7000       result = cstring_makeLiteral ("Field");
7001       break;
7002     case SK_OBJECT:
7003       result = cstring_makeLiteral ("Object");
7004       break;
7005     case SK_UNCONSTRAINED:
7006       result = cstring_makeLiteral ("<anything>");
7007       break;
7008     case SK_RESULT:
7009     case SK_SPECIAL:
7010     case SK_UNKNOWN:
7011     case SK_EXTERNAL:
7012     case SK_DERIVED:
7013     case SK_CONST:
7014     case SK_TYPE:
7015       result = cstring_makeLiteral ("<unknown>");
7016       break;
7017     case SK_CONJ:
7018       result = cstring_makeLiteral ("<conj>");
7019       break;
7020     case SK_NEW:
7021       result = cstring_makeLiteral ("Storage");
7022       break;
7023     }
7024   
7025   return result;
7026 }
7027
7028 /*@only@*/ cstring
7029 sRef_unparseKindNamePlain (sRef s)
7030 {
7031   cstring result;
7032
7033   if (s == sRef_undefined) return cstring_makeLiteral ("<invalid>");
7034
7035   s = sRef_fixConj (s);
7036
7037   switch (s->kind)
7038     {
7039     case SK_CVAR: 
7040       if (sRef_isLocalVar (s)) 
7041         {
7042           result = cstring_makeLiteral ("Variable");
7043         }
7044       else 
7045         {
7046           result = cstring_makeLiteral ("Global");
7047         }
7048       break;
7049     case SK_PARAM:
7050       result = cstring_makeLiteral ("Parameter");
7051       break;
7052     case SK_ARRAYFETCH:
7053       if (sRef_isAnyParam (s->info->arrayfetch->arr)) 
7054         {
7055           result = cstring_makeLiteral ("Parameter");
7056         }
7057       else if (sRef_isIndexKnown (s))
7058         {
7059           result = cstring_makeLiteral ("Array element");
7060         }
7061       else 
7062         {
7063           result = cstring_makeLiteral ("Value");
7064         }
7065       break;
7066     case SK_PTR:
7067       if (sRef_isAnyParam (s->info->ref))
7068         {
7069           result = cstring_makeLiteral ("Parameter");
7070         }
7071       else
7072         {
7073           result = cstring_makeLiteral ("Value");
7074         }
7075       break;
7076     case SK_ADR:
7077       result = cstring_makeLiteral ("Value");
7078       break;
7079     case SK_FIELD:
7080       result = cstring_makeLiteral ("Field");
7081       break;
7082     case SK_OBJECT:
7083       result = cstring_makeLiteral ("Object");
7084       break;
7085     case SK_NEW:
7086       result = cstring_makeLiteral ("Storage");
7087       break;
7088     case SK_UNCONSTRAINED:
7089       result = cstring_makeLiteral ("<anything>");
7090       break;
7091     case SK_RESULT:
7092     case SK_TYPE:
7093     case SK_CONST:
7094     case SK_EXTERNAL:
7095     case SK_DERIVED:
7096     case SK_UNKNOWN:
7097     case SK_SPECIAL:
7098       result = cstring_makeLiteral ("<unknown>");
7099       break;
7100     case SK_CONJ:
7101       result = cstring_makeLiteral ("<conj>");
7102       break;
7103     }
7104   
7105   return result;
7106 }
7107
7108 /*
7109 ** s1 <- s2
7110 */
7111
7112 void
7113 sRef_copyState (sRef s1, sRef s2)
7114 {
7115   if (sRef_isValid (s1) && sRef_isValid (s2))
7116     {
7117       s1->defstate = s2->defstate;
7118       
7119       /* start modifications */
7120       s1->bufinfo.bufstate = s2->bufinfo.bufstate;
7121       s1->bufinfo.len = s2->bufinfo.len;
7122       s1->bufinfo.size = s2->bufinfo.size;
7123       /* end modifications */
7124
7125       s1->aliaskind = s2->aliaskind;
7126       s1->aliasinfo = stateInfo_update (s1->aliasinfo, s2->aliasinfo);
7127
7128       s1->expkind = s2->expkind;
7129       s1->expinfo = stateInfo_update (s1->expinfo, s2->expinfo);
7130
7131       s1->nullstate = s2->nullstate;
7132       s1->nullinfo = stateInfo_update (s1->nullinfo, s2->nullinfo);
7133
7134       /*@-mustfree@*/
7135       /*@i834 don't free it: valueTable_free (s1->state); */
7136       /*@i32@*/ s1->state = valueTable_copy (s2->state);
7137       /*@=mustfree@*/
7138       s1->safe = s2->safe;
7139     }
7140 }
7141
7142 sRef
7143 sRef_makeNew (ctype ct, sRef t, cstring name)
7144 {
7145   sRef s = sRef_newRef ();
7146
7147   s->kind = SK_NEW;
7148   s->type = ct;
7149
7150   llassert (sRef_isValid (t));
7151   s->defstate = t->defstate;
7152
7153   s->aliaskind = t->aliaskind;
7154   s->oaliaskind = s->aliaskind;
7155   s->nullstate = t->nullstate;
7156   
7157   s->expkind = t->expkind;
7158   s->oexpkind = s->expkind;
7159   
7160   s->info = (sinfo) dmalloc (sizeof (*s->info));
7161   s->info->fname = name;
7162
7163   /* start modifications */
7164   s->bufinfo.bufstate = t->bufinfo.bufstate;
7165   /* end modifications */
7166   
7167   llassert (valueTable_isUndefined (s->state));
7168   s->state = valueTable_copy (t->state);
7169
7170   DPRINTF (("==> Copying state: %s", valueTable_unparse (s->state)));
7171   DPRINTF (("==> new: %s", sRef_unparseFull (s)));
7172   return s;
7173 }
7174
7175 sRef
7176 sRef_makeType (ctype ct)
7177 {
7178   sRef s = sRef_newRef ();
7179
7180   sRef_checkMutable (s);
7181
7182   s->kind = SK_TYPE;
7183   s->type = ct;
7184
7185   s->defstate = SS_UNKNOWN; 
7186   s->aliaskind = AK_UNKNOWN;
7187   sRef_setNullStateN (s, NS_UNKNOWN);
7188
7189   /* start modification */
7190   s->bufinfo.bufstate = BB_NOTNULLTERMINATED;
7191   /* end modification */
7192
7193     
7194   if (ctype_isUA (ct))
7195     {
7196       typeId uid = ctype_typeId (ct);
7197       uentry ue = usymtab_getTypeEntrySafe (uid);
7198
7199       if (uentry_isValid (ue))
7200         {
7201           sRef_mergeStateQuiet (s, uentry_getSref (ue));
7202         }
7203     }
7204   
7205   s->oaliaskind = s->aliaskind;
7206   s->oexpkind = s->expkind;
7207   llassert (valueTable_isUndefined (s->state));
7208   s->state = context_createValueTable (s, stateInfo_makeLoc (g_currentloc));
7209
7210   DPRINTF (("Create: %s", sRef_unparseFull (s)));
7211   return s;
7212 }
7213
7214 sRef
7215 sRef_makeConst (ctype ct)
7216 {
7217   sRef s = sRef_newRef ();
7218   
7219   s->kind = SK_CONST;
7220   s->type = ct;
7221
7222   s->defstate = SS_UNKNOWN;
7223   s->aliaskind = AK_UNKNOWN;
7224   sRef_setNullStateN (s, NS_UNKNOWN);
7225
7226   /* start modification */
7227   s->bufinfo.bufstate = BB_NULLTERMINATED;
7228   /* end modification */
7229   if (ctype_isUA (ct))
7230     {
7231       typeId uid = ctype_typeId (ct);
7232       uentry te = usymtab_getTypeEntrySafe (uid);
7233       
7234       if (uentry_isValid (te))
7235         {
7236           sRef_mergeStateQuiet (s, uentry_getSref (te));
7237         }
7238     }
7239   
7240   
7241   s->oaliaskind = s->aliaskind;
7242   s->oexpkind = s->expkind;
7243
7244   llassert (valueTable_isUndefined (s->state));
7245   s->state = context_createValueTable (s, stateInfo_makeLoc (g_currentloc));
7246
7247   return s;
7248 }
7249
7250 bool sRef_hasName (sRef s)
7251 {
7252   if (sRef_isInvalid (s))
7253     {
7254       return (FALSE);
7255     }
7256
7257   switch (s->kind)
7258     {
7259     case SK_CVAR:
7260       {
7261         uentry u = usymtab_getRefQuiet (s->info->cvar->lexlevel,
7262                                          s->info->cvar->index);
7263         return (uentry_hasName (u));
7264       }
7265     case SK_PARAM:
7266       {
7267         if (s->info->paramno >= 0)
7268           {
7269             uentry u = uentryList_getN (context_getParams (), 
7270                                         s->info->paramno);
7271             
7272             return (uentry_hasName (u));
7273           }
7274         else
7275           {
7276             llassert (s->info->paramno == PARAMUNKNOWN);
7277             return FALSE;
7278           }
7279       }
7280     default:
7281       return TRUE;
7282     }
7283 }
7284
7285 bool
7286 sRef_sameName (sRef s1, sRef s2)
7287 {
7288   if (sRef_isInvalid (s1))
7289     {
7290       return sRef_isInvalid (s2);
7291     }
7292
7293   if (sRef_isInvalid (s2))
7294     {
7295       return (FALSE);
7296     }
7297
7298   switch (s1->kind)
7299     {
7300     case SK_CVAR:
7301       if (s2->kind == SK_CVAR)
7302         {
7303           return (s1->info->cvar->lexlevel == s2->info->cvar->lexlevel
7304                   && s1->info->cvar->index == s2->info->cvar->index);
7305         }
7306       else if (s2->kind == SK_PARAM)
7307         {
7308           if (context_inFunctionLike ())
7309             {
7310               if (s2->info->paramno != PARAMUNKNOWN)
7311                 {
7312                   uentry u1 = usymtab_getRefQuiet (s1->info->cvar->lexlevel,
7313                                                    s1->info->cvar->index);
7314                   uentry u2 = uentryList_getN (context_getParams (), 
7315                                                s2->info->paramno);
7316                   
7317                   return (cstring_equalFree (uentry_getName (u1),
7318                                              uentry_getName (u2)));
7319                 }
7320               else
7321                 {
7322                   return s1->info->paramno == PARAMUNKNOWN;
7323                 }
7324             }
7325           else 
7326             {
7327               return FALSE;
7328             }
7329         }
7330       else
7331         {
7332           return FALSE;
7333         }
7334     case SK_PARAM:
7335       {
7336         if (s2->kind == SK_PARAM)
7337           {
7338             return (s1->info->paramno == s2->info->paramno);
7339           }
7340         else if (s2->kind == SK_CVAR)
7341           {
7342             if (context_inFunctionLike ())
7343               {
7344                 if (s1->info->paramno == PARAMUNKNOWN)
7345                   {
7346                     return FALSE;
7347                   }
7348                 else
7349                   {
7350                     uentry u1 = uentryList_getN (context_getParams (), 
7351                                                  s1->info->paramno);
7352                     uentry u2 = usymtab_getRefQuiet (s2->info->cvar->lexlevel,
7353                                                      s2->info->cvar->index);
7354                     
7355                     
7356                     return (cstring_equalFree (uentry_getName (u1),
7357                                                uentry_getName (u2)));
7358                   }
7359               }
7360             else 
7361               {
7362                 return FALSE;
7363               }
7364           }
7365         else
7366           {
7367             return FALSE;
7368           }
7369       }
7370
7371     case SK_UNCONSTRAINED:
7372       return FALSE;
7373
7374     case SK_ARRAYFETCH:
7375       if (s2->kind == SK_ARRAYFETCH)
7376         {
7377           if (bool_equal (s1->info->arrayfetch->indknown,
7378                           s2->info->arrayfetch->indknown))
7379             {
7380               if (!s1->info->arrayfetch->indknown 
7381                   || (s1->info->arrayfetch->ind == s2->info->arrayfetch->ind))
7382                 {
7383                   return sRef_sameName (s1->info->arrayfetch->arr,
7384                                         s2->info->arrayfetch->arr);
7385                 }
7386             }
7387         }
7388
7389       return FALSE;
7390     case SK_FIELD:
7391       if (s2->kind == SK_FIELD)
7392         {
7393           if (cstring_equal (s1->info->field->field,
7394                              s2->info->field->field))
7395             {
7396               return sRef_sameName (s1->info->field->rec,
7397                                     s2->info->field->rec);
7398             }
7399
7400         }
7401       return FALSE;
7402     case SK_PTR:
7403     case SK_ADR:
7404     case SK_DERIVED:
7405     case SK_EXTERNAL:
7406       if (s2->kind == s1->kind)
7407         {
7408           return sRef_sameName (s1->info->ref,
7409                                 s2->info->ref);
7410         }
7411
7412       return FALSE;
7413     case SK_OBJECT:
7414       return FALSE;
7415     case SK_CONJ:
7416       return sRef_sameName (sRef_getConjA (s1), s2);
7417     case SK_NEW:
7418       return FALSE;
7419     case SK_UNKNOWN:
7420       return (s2->kind == SK_UNKNOWN);
7421     case SK_TYPE:
7422     case SK_CONST:
7423       if (s2->kind == s1->kind)
7424         {
7425           return (ctype_equal (s1->type, s2->type));
7426         }
7427       
7428       return FALSE;
7429     case SK_SPECIAL:
7430       if (s2->kind == SK_SPECIAL)
7431         {
7432           return (s1->info->spec == s2->info->spec);
7433         }
7434       return FALSE;
7435     case SK_RESULT:
7436       return (s2->kind == SK_RESULT);
7437     default:
7438       return FALSE;
7439     }
7440   BADEXIT;
7441 }
7442                 
7443 sRef
7444 sRef_fixOuterRef (/*@returned@*/ sRef s)
7445 {
7446   sRef root = sRef_getRootBase (s);
7447
7448   if (sRef_isCvar (root))
7449     {
7450       uentry ue = usymtab_getRefQuiet (root->info->cvar->lexlevel, 
7451                                        root->info->cvar->index);
7452
7453       if (uentry_isValid (ue))
7454         {
7455           sRef uref = uentry_getSref (ue);
7456           sRef sr = sRef_fixBase (s, uref);
7457
7458           return (sr);
7459         }
7460       else
7461         {
7462           llcontbug (message ("sRef_fixOuterRef: undefined: %q", sRef_unparseDebug (s)));
7463           return (s);
7464         }
7465     }
7466
7467   return (s);
7468 }
7469
7470 void
7471 sRef_storeState (sRef s)
7472 {
7473   if (sRef_isInvalid (s)) return;
7474
7475   sRef_checkMutable (s);
7476   s->oaliaskind = s->aliaskind;
7477   s->oexpkind = s->expkind;
7478 }
7479   
7480 static void sRef_resetStateAux (sRef s, /*@unused@*/ fileloc loc)
7481 {
7482   sRef_resetState (s);
7483 }
7484
7485 void
7486 sRef_resetState (sRef s)
7487 {
7488   bool changed = FALSE;
7489   if (sRef_isInvalid (s)) return;
7490
7491   
7492   if (s->oaliaskind == AK_KILLREF && !sRef_isParam (s))
7493     {
7494       /*
7495       ** killref is used in a kludgey way, to save having to add
7496       ** another alias kind (see usymtab_handleParams)
7497       */
7498  
7499       if (s->expkind != s->oexpkind)
7500         {
7501           changed = TRUE;
7502           s->expkind = s->oexpkind;
7503         }
7504     }
7505   else
7506     {
7507       if (s->expkind != s->oexpkind)
7508         {
7509           changed = TRUE;
7510           s->expkind = s->oexpkind;       
7511         }
7512
7513       if (s->aliaskind != s->oaliaskind
7514           && s->aliaskind != AK_REFCOUNTED
7515           && s->aliaskind != AK_REFS)
7516         {
7517           changed = TRUE;
7518           s->aliaskind = s->oaliaskind;
7519         }
7520     }
7521
7522   if (changed)
7523     {
7524       sRef_clearDerived (s);
7525     }
7526   
7527   }
7528
7529 void
7530 sRef_resetStateComplete (sRef s)
7531 {
7532   sRef_innerAliasSetComplete (sRef_resetStateAux, s, fileloc_undefined);
7533 }
7534
7535 /*@exposed@*/ sRef
7536 sRef_fixBase (/*@returned@*/ sRef s, /*@returned@*/ sRef base)
7537 {
7538   sRef tmp = sRef_undefined;
7539   sRef ret;
7540
7541   if (sRef_isInvalid (s)) return s;
7542   if (sRef_isInvalid (base)) return base;
7543
7544   switch (s->kind)
7545     {
7546     case SK_RESULT:
7547     case SK_PARAM:
7548     case SK_CVAR:
7549       ret = base;
7550       break;
7551     case SK_ARRAYFETCH:
7552       tmp = sRef_fixBase (s->info->arrayfetch->arr, base);
7553
7554       if (s->info->arrayfetch->indknown)
7555         {
7556           ret = sRef_makeArrayFetchKnown (tmp, s->info->arrayfetch->ind);
7557         }
7558       else
7559         {
7560           ret = sRef_makeArrayFetch (tmp);
7561         }
7562       break;
7563     case SK_FIELD:
7564       tmp = sRef_fixBase (s->info->field->rec, base);
7565       ret = sRef_buildNCField (tmp, s->info->field->field);
7566       break;
7567     case SK_PTR:
7568       tmp = sRef_fixBase (s->info->ref, base);
7569       ret = sRef_makePointer (tmp);
7570       break;
7571     case SK_ADR:
7572       tmp = sRef_fixBase (s->info->ref, base);
7573       ret = sRef_makeAddress (tmp);
7574       break;
7575     case SK_CONJ:
7576       {
7577         sRef tmpb;
7578
7579         tmp = sRef_fixBase (s->info->conj->a, base);
7580         tmpb = sRef_fixBase (s->info->conj->b, base);
7581
7582         ret = sRef_makeConj (tmp, tmpb);
7583         break;
7584       }
7585       BADDEFAULT;
7586     }
7587
7588   return ret;
7589 }
7590
7591 static /*@exposed@*/ sRef 
7592 sRef_fixDirectBase (sRef s, sRef base)
7593 {
7594   sRef ret;
7595
7596   
7597   if (sRef_isInvalid (s))
7598     {
7599       return sRef_undefined;
7600     }
7601   
7602   switch (s->kind)
7603     {
7604     case SK_ARRAYFETCH:
7605       if (s->info->arrayfetch->indknown)
7606         {
7607           ret = sRef_makeArrayFetchKnown (base, s->info->arrayfetch->ind);
7608         }
7609       else
7610         {
7611           ret = sRef_makeArrayFetch (base);
7612         }
7613       break;
7614     case SK_FIELD:
7615       ret = sRef_buildNCField (base, s->info->field->field);
7616       break;
7617     case SK_PTR:
7618             ret = sRef_makePointer (base);
7619             break;
7620     case SK_ADR:
7621       ret = sRef_makeAddress (base);
7622       break;
7623     case SK_CONJ:
7624       {
7625         sRef tmpa, tmpb;
7626
7627         tmpa = sRef_fixDirectBase (s->info->conj->a, base);
7628         tmpb = sRef_fixDirectBase (s->info->conj->b, base);
7629
7630         ret = sRef_makeConj (tmpa, tmpb);
7631         break;
7632       }
7633       BADDEFAULT;
7634     }
7635
7636     sRef_copyState (ret, s);
7637     return ret;
7638 }
7639
7640 bool
7641 sRef_isAllocIndexRef (sRef s)
7642 {
7643   return (sRef_isArrayFetch (s) && !(s->info->arrayfetch->indknown) 
7644           && sRef_isAllocated (s->info->arrayfetch->arr));
7645 }
7646
7647 void
7648 sRef_showRefLost (sRef s)
7649 {
7650   if (sRef_hasAliasInfoLoc (s))
7651     {
7652       llgenindentmsg (cstring_makeLiteral ("Original reference lost"),
7653                       sRef_getAliasInfoLoc (s));
7654     }
7655 }
7656
7657 void
7658 sRef_showRefKilled (sRef s)
7659 {
7660   if (sRef_hasStateInfoLoc (s))
7661     {
7662       llgenindentmsg (message ("Storage %q released", 
7663                                sRef_unparse (s)), sRef_getStateInfoLoc (s));
7664     }
7665 }
7666
7667 void
7668 sRef_showStateInconsistent (sRef s)
7669 {
7670   if (sRef_hasStateInfoLoc (s))
7671     {
7672       llgenindentmsg
7673         (message ("Storage %qbecomes inconsistent (released on one branch)",
7674                   sRef_unparseOpt (s)), 
7675          sRef_getStateInfoLoc (s));
7676     }
7677 }
7678
7679 void
7680 sRef_showStateInfo (sRef s)
7681 {
7682   if (sRef_hasStateInfoLoc (s))
7683     {
7684       if (s->defstate == SS_DEAD)
7685         {
7686           llgenindentmsg 
7687             (message ("Storage %qis released", sRef_unparseOpt (s)),
7688              sRef_getStateInfoLoc (s));
7689         }
7690       else if (s->defstate == SS_ALLOCATED || s->defstate == SS_DEFINED)
7691         {
7692           llgenindentmsg 
7693             (message ("Storage %qis %s", sRef_unparseOpt (s), 
7694                       sstate_unparse (s->defstate)),
7695              sRef_getStateInfoLoc (s));
7696         }
7697       else if (s->defstate == SS_UNUSEABLE)
7698         {
7699           llgenindentmsg 
7700             (message ("Storage %qbecomes inconsistent (clauses merge with"
7701                       "%qreleased on one branch)",
7702                       sRef_unparseOpt (s), 
7703                       sRef_unparseOpt (s)),
7704              sRef_getStateInfoLoc (s));
7705         }
7706       else 
7707         {
7708           llgenindentmsg (message ("Storage %qbecomes %s", 
7709                                    sRef_unparseOpt (s), 
7710                                    sstate_unparse (s->defstate)),
7711                           sRef_getStateInfoLoc (s));
7712         }
7713     }
7714 }
7715
7716 void
7717 sRef_showExpInfo (sRef s)
7718 {
7719   if (sRef_hasExpInfoLoc (s))
7720     {
7721       llgenindentmsg (message ("Storage %qbecomes %s", sRef_unparseOpt (s), 
7722                                exkind_unparse (s->expkind)),
7723                       sRef_getExpInfoLoc (s));
7724     }
7725 }
7726
7727 void
7728 sRef_showMetaStateInfo (sRef s, cstring key)
7729 {
7730   stateValue val;
7731   metaStateInfo minfo = context_lookupMetaStateInfo (key);
7732
7733   llassert (sRef_isValid (s));
7734   llassert (valueTable_isDefined (s->state));
7735   llassert (metaStateInfo_isDefined (minfo));
7736
7737   val = valueTable_lookup (s->state, key);
7738   
7739   if (stateValue_hasLoc (val))
7740     {
7741       llgenindentmsg 
7742         (message ("%qbecomes %q", sRef_unparseOpt (s), 
7743                   stateValue_unparseValue (val, minfo)),
7744          stateValue_getLoc (val));
7745     }
7746 }
7747
7748 void
7749 sRef_showNullInfo (sRef s)
7750 {
7751   DPRINTF (("Show null info: %s", sRef_unparseFull (s)));
7752
7753   if (sRef_hasNullInfoLoc (s) && sRef_isKnown (s))
7754     {
7755       DPRINTF (("has null info: %s",
7756                 fileloc_unparse (sRef_getNullInfoLoc (s))));
7757
7758       switch (sRef_getNullState (s))
7759         {
7760         case NS_CONSTNULL:
7761           {
7762             fileloc loc = sRef_getNullInfoLoc (s);
7763             
7764             if (fileloc_isDefined (loc) && !fileloc_isLib (loc))
7765               {
7766                 llgenindentmsg 
7767                   (message ("Storage %qbecomes null", sRef_unparseOpt (s)),
7768                    loc);
7769               }
7770             break;
7771           }
7772         case NS_DEFNULL:
7773           {
7774             fileloc loc = sRef_getNullInfoLoc (s);
7775             
7776             if (fileloc_isDefined (loc) && !fileloc_isLib (loc))
7777               {
7778                 llgenindentmsg (message ("Storage %qbecomes null", sRef_unparseOpt (s)),
7779                                 loc);
7780               }
7781             break;
7782           }
7783         case NS_ABSNULL:
7784         case NS_POSNULL:
7785           llgenindentmsg
7786             (message ("Storage %qmay become null", sRef_unparseOpt (s)),
7787              sRef_getNullInfoLoc (s));
7788           break;
7789         case NS_NOTNULL:
7790         case NS_MNOTNULL:
7791           llgenindentmsg
7792             (message ("Storage %qbecomes not null", sRef_unparseOpt (s)),
7793              sRef_getNullInfoLoc (s));
7794           break;
7795         case NS_UNKNOWN:
7796           llgenindentmsg
7797             (message ("Storage %qnull state becomes unknown",
7798                       sRef_unparseOpt (s)),
7799              sRef_getNullInfoLoc (s));
7800           break;
7801
7802         case NS_ERROR:
7803           BADBRANCHCONT;
7804           break;
7805
7806         default:
7807           llgenindentmsg
7808             (message ("<error case> Storage %q becomes %s",
7809                       sRef_unparse (s), 
7810                       nstate_unparse (sRef_getNullState (s))),
7811              sRef_getNullInfoLoc (s));
7812           
7813           break;
7814         }
7815     }
7816 }
7817
7818 void
7819 sRef_showAliasInfo (sRef s)
7820 {
7821   if (sRef_hasAliasInfoLoc (s))
7822     {
7823       if (sRef_isFresh (s))
7824         {
7825           llgenindentmsg 
7826             (message ("Fresh storage %qallocated", sRef_unparseOpt (s)),
7827              sRef_getAliasInfoLoc (s));
7828         }
7829       else 
7830         {
7831           if (!sRef_isRefCounted (s))
7832             {
7833               llgenindentmsg 
7834                 (message ("Storage %qbecomes %s", 
7835                           sRef_unparseOpt (s),
7836                           alkind_unparse (sRef_getAliasKind (s))),
7837                  sRef_getAliasInfoLoc (s));
7838             }
7839         }
7840     }
7841 }
7842
7843 void
7844 sRef_mergeNullState (sRef s, nstate n)
7845 {
7846   if (sRef_isValid (s))
7847     {
7848       nstate old;
7849       
7850       old = sRef_getNullState (s);
7851       
7852       if (n != old && n != NS_UNKNOWN)
7853         {                 
7854             sRef_setNullState (s, n, g_currentloc);
7855         }
7856     }
7857   else
7858     {
7859       llbuglit ("sRef_mergeNullState: invalid");
7860     }
7861 }
7862
7863 bool
7864 sRef_possiblyNull (sRef s)
7865 {
7866   if (sRef_isValid (s))
7867       {
7868         if (sRef_getNullState (s) == NS_ABSNULL)
7869         {
7870           ctype rct = ctype_realType (s->type);
7871
7872           if (ctype_isAbstract (rct))
7873             {
7874               return FALSE;
7875             }
7876           else
7877             {
7878               if (ctype_isUser (rct))
7879                 {
7880                   uentry ue = usymtab_getTypeEntry (ctype_typeId (rct));
7881                   
7882                   return (nstate_possiblyNull
7883                           (sRef_getNullState (uentry_getSref (ue))));
7884                 }
7885               else
7886                 {
7887                   return FALSE;
7888                 }
7889             }
7890         }
7891       else
7892         {
7893           return nstate_possiblyNull (sRef_getNullState (s));
7894         }
7895     }
7896
7897   return FALSE;
7898 }
7899
7900 cstring
7901 sRef_getScopeName (sRef s)
7902 {
7903   sRef base = sRef_getRootBase (s);
7904
7905   if (sRef_isRealGlobal (base))
7906     {
7907       return (cstring_makeLiteralTemp ("Global"));
7908     }
7909   else if (sRef_isFileStatic (base))
7910     {
7911       return (cstring_makeLiteralTemp ("Static"));
7912     }
7913   else
7914     {
7915       return (cstring_makeLiteralTemp ("Local"));
7916     }
7917 }
7918
7919 cstring
7920 sRef_unparseScope (sRef s)
7921 {
7922   sRef base = sRef_getRootBase (s);
7923
7924   if (sRef_isRealGlobal (base))
7925     {
7926       return (cstring_makeLiteralTemp ("global"));
7927     }
7928   else if (sRef_isFileStatic (base))
7929     {
7930       return (cstring_makeLiteralTemp ("file static"));
7931     }
7932   else
7933     {
7934       BADEXIT;
7935     }
7936 }
7937
7938 int
7939 sRef_getScope (sRef s)
7940 {
7941   llassert (sRef_isValid (s));
7942
7943   if (sRef_isCvar (s))
7944     {
7945       return s->info->cvar->lexlevel;
7946     }
7947   else if (sRef_isParam (s))
7948     {
7949       return paramsScope;
7950     }
7951   else
7952     {
7953       return fileScope;
7954     }
7955 }
7956
7957 bool
7958 sRef_isDead (sRef s)
7959 {
7960   return (sRef_isValid (s) && (s)->defstate == SS_DEAD);
7961 }
7962
7963 bool
7964 sRef_isDeadStorage (sRef s)
7965 {
7966   if (sRef_isValid (s))
7967     {
7968       if (s->defstate == SS_DEAD
7969           || s->defstate == SS_UNUSEABLE
7970           || s->defstate == SS_UNDEFINED
7971           || s->defstate == SS_UNKNOWN)
7972         {
7973           return TRUE;
7974         }
7975       else 
7976         {
7977           return (sRef_isDefinitelyNull (s));
7978         }
7979     }
7980   else
7981     {
7982       return FALSE;
7983     }
7984 }
7985
7986 bool
7987 sRef_isPossiblyDead (sRef s)
7988 {
7989   return (sRef_isValid (s) && s->defstate == SS_HOFFA);
7990 }
7991
7992 bool sRef_isStateLive (sRef s)
7993 {
7994   if (sRef_isValid (s))
7995     {
7996       sstate ds = s->defstate;
7997
7998       return (!(ds == SS_UNDEFINED 
7999                 || ds == SS_DEAD
8000                 || ds == SS_UNUSEABLE
8001                 || ds == SS_HOFFA));
8002     }
8003   else
8004     {
8005       return FALSE;
8006     }
8007 }
8008
8009
8010 bool sRef_isStateUndefined (sRef s)
8011 {
8012   return ((sRef_isValid(s)) && ((s)->defstate == SS_UNDEFINED));
8013 }
8014
8015 bool sRef_isJustAllocated (sRef s)
8016 {
8017   if (sRef_isAllocated (s))
8018     {
8019       sRefSet_allElements (s->deriv, el)
8020         {
8021           if (!(sRef_isStateUndefined (el) || sRef_isUnuseable (el)))
8022             {
8023               return FALSE;
8024             }
8025         } end_sRefSet_allElements ;
8026
8027       return TRUE;
8028     }
8029
8030   return FALSE;
8031 }
8032
8033 static bool
8034 sRef_isAllocatedStorage (sRef s)
8035 {
8036   if (sRef_isValid (s) && ynm_toBoolStrict (sRef_isValidLvalue (s)))
8037     {
8038       return (ctype_isVisiblySharable (sRef_getType (s)));
8039     }
8040   else
8041     {
8042       return FALSE;
8043     }
8044 }
8045
8046 bool
8047 sRef_isUnuseable (sRef s)
8048 {
8049   return ((sRef_isValid(s)) && ((s)->defstate == SS_UNUSEABLE));
8050 }
8051
8052 bool
8053 sRef_perhapsNull (sRef s)
8054 {
8055   if (sRef_isValid (s))
8056     {
8057       if (sRef_getNullState (s) == NS_ABSNULL)
8058         {
8059           ctype rct = ctype_realType (s->type);
8060
8061           if (ctype_isAbstract (rct))
8062             {
8063               return FALSE;
8064             }
8065           else
8066             {
8067               if (ctype_isUser (rct))
8068                 {
8069                   uentry ue = usymtab_getTypeEntry (ctype_typeId (rct));
8070
8071                   return (nstate_perhapsNull 
8072                           (sRef_getNullState (uentry_getSref (ue))));
8073                 }
8074               else
8075                 {
8076                   return FALSE;
8077                 }
8078             }
8079         }
8080       else
8081         {
8082           return nstate_perhapsNull (sRef_getNullState (s));
8083         }
8084     }
8085
8086   return FALSE;
8087 }
8088
8089 /*
8090 ** definitelyNull --- called when TRUE is good
8091 */
8092
8093 bool 
8094 sRef_definitelyNull (sRef s)
8095 {
8096   return (sRef_isValid (s)
8097           && (sRef_getNullState (s) == NS_DEFNULL || sRef_getNullState (s) == NS_CONSTNULL));
8098 }
8099
8100 /*
8101 ** based on sRef_similar
8102 */
8103
8104 void
8105 sRef_setDerivNullState (sRef set, sRef guide, nstate ns)
8106 {
8107   if (sRef_isValid (set))
8108     {
8109       sRef deriv = sRef_getDeriv (set, guide);
8110       
8111       if (sRef_isValid (deriv))
8112         {
8113           sRef_setNullStateN (deriv, ns);
8114         }
8115     }
8116 }
8117
8118 static /*@exposed@*/ sRef
8119 sRef_getDeriv (/*@returned@*/ /*@notnull@*/ sRef set, sRef guide)
8120 {
8121   llassert (sRef_isValid (set));
8122   llassert (sRef_isValid (guide));
8123
8124   switch (guide->kind)
8125     {
8126     case SK_CVAR:
8127       llassert (set->kind == SK_CVAR);
8128       
8129       return set;
8130
8131     case SK_PARAM:
8132       llassert (set->kind == guide->kind);
8133       llassert (set->info->paramno == guide->info->paramno);
8134
8135       return set;
8136
8137     case SK_ARRAYFETCH:
8138
8139       if (set->kind == SK_ARRAYFETCH
8140           && (sRef_similar (set->info->arrayfetch->arr,
8141                             guide->info->arrayfetch->arr)))
8142         {
8143           return set;
8144         }
8145       else
8146         {
8147           return (sRef_makeAnyArrayFetch 
8148                   (sRef_getDeriv (set, guide->info->arrayfetch->arr)));
8149         }
8150
8151     case SK_PTR:
8152       
8153       if (set->kind == SK_PTR && sRef_similar (set->info->ref, guide->info->ref))
8154         {
8155           return set;
8156         }
8157       else
8158         {
8159           return (sRef_makePointer (sRef_getDeriv (set, guide->info->ref)));
8160         }
8161       
8162     case SK_FIELD:
8163       
8164       if ((set->kind == SK_FIELD &&
8165            (sRef_similar (set->info->field->rec, guide->info->field->rec) &&
8166             cstring_equal (set->info->field->field, guide->info->field->field))))
8167         {
8168           return set;
8169         }
8170       else
8171         {
8172           return (sRef_makeField (sRef_getDeriv (set, guide->info->field->rec),
8173                                   guide->info->field->field));
8174         }
8175     case SK_ADR:
8176       
8177       if ((set->kind == SK_ADR) && sRef_similar (set->info->ref, guide->info->ref))
8178         {
8179           return set;
8180         }
8181       else
8182         {
8183           return (sRef_makeAddress (sRef_getDeriv (set, guide->info->ref)));
8184         }
8185
8186     case SK_CONJ:
8187       
8188             return sRef_undefined;
8189
8190     case SK_RESULT:
8191     case SK_SPECIAL:
8192     case SK_UNCONSTRAINED:
8193     case SK_TYPE:
8194     case SK_CONST:
8195     case SK_NEW:
8196     case SK_UNKNOWN:
8197     case SK_OBJECT:
8198     case SK_DERIVED:
8199     case SK_EXTERNAL:
8200       return sRef_undefined;
8201     }
8202
8203   BADEXIT;
8204 }
8205       
8206 /*
8207 ** sRef_aliasCheckPred
8208 **
8209 ** A confusing but spiffy function:
8210 **
8211 **    Calls predf (s, e, text, <alias>) on s and all of s's aliases
8212 **    (unless checkAliases (s) is FALSE).
8213 **
8214 **    For alias calls, calls as
8215 **          predf (alias, e, text, s)
8216 */
8217
8218 void
8219 sRef_aliasCheckPred (bool (predf) (sRef, exprNode, sRef, exprNode),
8220                      /*@null@*/ bool (checkAliases) (sRef),
8221                      sRef s, exprNode e, exprNode err)
8222 {
8223   bool error = (*predf)(s, e, sRef_undefined, err);
8224   
8225   
8226   if (checkAliases != NULL && !(checkAliases (s)))
8227     {
8228       /* don't check aliases */
8229     }
8230   else
8231     {
8232       sRefSet aliases = usymtab_allAliases (s);
8233       
8234       sRefSet_realElements (aliases, current)
8235         {
8236           if (sRef_isValid (current))
8237             {
8238               if (!sRef_similar (current, s)
8239                   || (error && sRef_sameName (current, s)))
8240                 {
8241                   (void) (*predf)(current, e, s, err);
8242                 }
8243               }
8244         } end_sRefSet_realElements;
8245
8246       sRefSet_free (aliases);
8247     }
8248 }
8249
8250 /*
8251 ** return TRUE iff predf (s) is true for s or any alias of s
8252 */
8253
8254 bool
8255 sRef_aliasCheckSimplePred (sRefTest predf, sRef s)
8256 {
8257     
8258   if ((*predf)(s))
8259     {
8260       return TRUE;
8261     }
8262   else
8263     {
8264       sRefSet aliases;
8265
8266       aliases = usymtab_allAliases (s);
8267       
8268       sRefSet_realElements (aliases, current)
8269         {
8270           if (sRef_isValid (current))
8271             {
8272               sRef cref = sRef_updateSref (current);
8273               
8274               /* Whoa! a very kludgey way to make sure the right sref is used
8275               ** where there is a conditional symbol table.  I am beginning
8276               ** to think that having a conditional symbol table wasn't such
8277               ** a great idea.  ;(
8278               */
8279               
8280               if ((*predf)(cref))
8281                 {
8282                   DPRINTF (("Checking alias: %s", sRef_unparseFull (cref)));
8283                   sRefSet_free (aliases);
8284                   return TRUE;
8285                 }
8286             }
8287         } end_sRefSet_realElements;
8288
8289       sRefSet_free (aliases);
8290     }
8291   return FALSE;
8292 }
8293
8294 bool
8295 sRef_aliasCompleteSimplePred (bool (predf) (sRef), sRef s)
8296 {
8297   sRefSet aliases;
8298   bool result = FALSE;
8299   
8300   
8301   aliases = usymtab_allAliases (s);
8302   
8303   if ((*predf)(s)) result = TRUE;
8304
8305   
8306   sRefSet_realElements (aliases, current)
8307     {
8308       if (sRef_isValid (current))
8309         {
8310           current = sRef_updateSref (current);
8311           if ((*predf)(current)) result = TRUE;
8312         }
8313     } end_sRefSet_realElements;
8314   
8315   sRefSet_free (aliases);
8316   return result;
8317 }
8318
8319 void
8320 sRef_aliasSetComplete (void (predf) (sRef, fileloc), sRef s, fileloc loc)
8321 {
8322   sRefSet aliases;
8323   
8324   aliases = usymtab_allAliases (s);
8325
8326   DPRINTF (("All aliases: %s", sRefSet_unparseFull (aliases)));
8327
8328   (*predf)(s, loc);
8329
8330   sRefSet_realElements (aliases, current)
8331     {
8332       if (sRef_isValid (current))
8333         {
8334           current = sRef_updateSref (current);
8335           ((*predf)(current, loc));
8336           DPRINTF (("Killed: %s", sRef_unparseFull (current)));
8337         }
8338     } end_sRefSet_realElements;
8339
8340   sRefSet_free (aliases);
8341 }
8342
8343 void
8344 sRef_aliasSetCompleteParam (void (predf) (sRef, int, fileloc), sRef s, 
8345                             int kind, fileloc loc)
8346 {
8347   sRefSet aliases;
8348   
8349   if (sRef_isDeep (s))
8350     {
8351       aliases = usymtab_allAliases (s);
8352     }
8353   else
8354     {
8355       aliases = usymtab_aliasedBy (s);
8356     }
8357
8358   (*predf)(s, kind, loc);
8359
8360   sRefSet_realElements (aliases, current)
8361     {
8362       if (sRef_isValid (current))
8363         {
8364           current = sRef_updateSref (current);
8365           ((*predf)(current, kind, loc));
8366         }
8367     } end_sRefSet_realElements;
8368
8369   sRefSet_free (aliases);
8370 }
8371
8372 /*
8373 ** Version of aliasSetCompleteParam for alkind parameters
8374 */
8375
8376 void
8377 sRef_aliasSetCompleteAlkParam (void (predf) (sRef, alkind, fileloc), sRef s, 
8378                                alkind kind, fileloc loc)
8379 {
8380   sRefSet aliases;
8381   
8382   if (sRef_isDeep (s))
8383     {
8384       aliases = usymtab_allAliases (s);
8385     }
8386   else
8387     {
8388       aliases = usymtab_aliasedBy (s);
8389     }
8390
8391   (*predf)(s, kind, loc);
8392
8393   sRefSet_realElements (aliases, current)
8394     {
8395       if (sRef_isValid (current))
8396         {
8397           current = sRef_updateSref (current);
8398           ((*predf)(current, kind, loc));
8399         }
8400     } end_sRefSet_realElements;
8401
8402   sRefSet_free (aliases);
8403 }
8404
8405 static void
8406 sRef_innerAliasSetComplete (void (predf) (sRef, fileloc), sRef s, fileloc loc)
8407 {
8408   sRef inner;
8409   sRefSet aliases;
8410   ctype ct;
8411
8412   if (!sRef_isValid (s)) return;
8413
8414   /*
8415   ** Type equivalence checking is necessary --- there might be casting.
8416   */
8417
8418   (*predf)(s, loc);
8419
8420   switch (s->kind)
8421     {
8422     case SK_UNCONSTRAINED:
8423     case SK_CVAR:
8424     case SK_PARAM:
8425       break;
8426     case SK_PTR:
8427       inner = s->info->ref;
8428       aliases = usymtab_allAliases (inner);
8429       ct = sRef_getType (inner);
8430       
8431       sRefSet_realElements (aliases, current)
8432         {
8433           if (sRef_isValid (current))
8434             {
8435               current = sRef_updateSref (current);
8436               
8437               if (ctype_equal (ct, sRef_getType (current)))
8438                 {
8439                   sRef ptr = sRef_makePointer (current);
8440                   ((*predf)(ptr, loc));
8441                 }
8442             }
8443         } end_sRefSet_realElements;
8444
8445       sRefSet_free (aliases);
8446       break;
8447     case SK_ARRAYFETCH:
8448       inner = s->info->arrayfetch->arr;
8449       aliases = usymtab_allAliases (inner);
8450       ct = sRef_getType (inner);
8451
8452       DPRINTF (("Array fetch: %s", sRefSet_unparse (aliases)));
8453
8454       sRefSet_realElements (aliases, current)
8455         {
8456           if (sRef_isValid (current))
8457             {
8458               current = sRef_updateSref (current);
8459               DPRINTF (("Current: %s", sRef_unparseFull (current)));
8460
8461               if (ctype_equal (ct, sRef_getType (current)))
8462                 {
8463                   if (s->info->arrayfetch->indknown)
8464                     {
8465                       sRef af = sRef_makeArrayFetchKnown (current, s->info->arrayfetch->ind);
8466                       DPRINTF (("Defining: %s", sRef_unparseFull (af)));
8467                       /* evans 2001-08-27 This isn't true:
8468                            llassert (af->info->arrayfetch->arr == current);
8469                          see comments in buildArrayFetchKnown
8470                       */
8471                       ((*predf)(af, loc));
8472                     }
8473                   else
8474                     {
8475                       sRef af = sRef_makeArrayFetch (current);
8476                       /* evans 2001-08-27 This isn't true:
8477                          llassert (af->info->arrayfetch->arr == current);
8478                          see comments in buildArrayFetch
8479                       */ 
8480                       DPRINTF (("Defining: %s", sRef_unparseFull (af)));
8481                       ((*predf)(af, loc));
8482                     }
8483                 }
8484               else
8485                 {
8486                   DPRINTF (("Type mismatch: %s / %s",
8487                             ctype_unparse (ct),
8488                             ctype_unparse (sRef_getType (current))));
8489                 }
8490             }
8491         } end_sRefSet_realElements;
8492
8493       sRefSet_free (aliases);
8494       break;
8495     case SK_FIELD:
8496       inner = s->info->field->rec;
8497       aliases = usymtab_allAliases (inner);
8498       ct = sRef_getType (inner);
8499       
8500       sRefSet_realElements (aliases, current)
8501         {
8502           if (sRef_isValid (current))
8503             {
8504               current = sRef_updateSref (current);
8505               
8506               if (ctype_equal (ct, sRef_getType (current)))
8507                 {
8508                   sRef f = sRef_makeField (current, s->info->field->field);
8509                   
8510                   ((*predf)(f, loc));
8511                 }
8512             }
8513         } end_sRefSet_realElements;
8514       
8515       sRefSet_free (aliases);
8516       break;
8517     case SK_CONJ:
8518       sRef_innerAliasSetComplete (predf, s->info->conj->a, loc);
8519       sRef_innerAliasSetComplete (predf, s->info->conj->b, loc);
8520       break;
8521     case SK_SPECIAL:
8522     case SK_ADR:
8523     case SK_TYPE:
8524     case SK_CONST:
8525     case SK_NEW:
8526     case SK_UNKNOWN:
8527     case SK_OBJECT:
8528     case SK_DERIVED:
8529     case SK_EXTERNAL:
8530     case SK_RESULT:
8531       break;
8532     }
8533 }
8534
8535 static void
8536 sRef_innerAliasSetCompleteParam (void (predf) (sRef, sRef), sRef s, sRef t)
8537 {
8538   sRef inner;
8539   sRefSet aliases;
8540   ctype ct;
8541
8542   if (!sRef_isValid (s)) return;
8543
8544   /*
8545   ** Type equivalence checking is necessary --- there might be casting.
8546   */
8547
8548   (*predf)(s, t);
8549
8550   switch (s->kind)
8551     {
8552     case SK_UNCONSTRAINED:
8553     case SK_CVAR:
8554     case SK_PARAM:
8555       break;
8556     case SK_PTR:
8557       inner = s->info->ref;
8558       aliases = usymtab_allAliases (inner);
8559       ct = sRef_getType (inner);
8560             
8561       sRefSet_realElements (aliases, current)
8562         {
8563           if (sRef_isValid (current))
8564             {
8565               current = sRef_updateSref (current);
8566               
8567               if (ctype_equal (ct, sRef_getType (current)))
8568                 {
8569                   sRef ptr = sRef_makePointer (current);
8570                   
8571                   ((*predf)(ptr, t));
8572                 }
8573             }
8574         } end_sRefSet_realElements;
8575
8576       sRefSet_free (aliases);
8577       break;
8578     case SK_ARRAYFETCH:
8579       inner = s->info->arrayfetch->arr;
8580       aliases = usymtab_allAliases (inner);
8581       ct = sRef_getType (inner);
8582
8583       sRefSet_realElements (aliases, current)
8584         {
8585           if (sRef_isValid (current))
8586             {
8587               current = sRef_updateSref (current);
8588               
8589               if (ctype_equal (ct, sRef_getType (current)))
8590                 {
8591                                   
8592                   if (s->info->arrayfetch->indknown)
8593                     {
8594                       sRef af = sRef_makeArrayFetchKnown (current, s->info->arrayfetch->ind);
8595                       
8596                       ((*predf)(af, t));
8597                     }
8598                   else
8599                     {
8600                       sRef af = sRef_makeArrayFetch (current);
8601                       
8602                       ((*predf)(af, t));
8603                     }
8604                 }
8605             }
8606         } end_sRefSet_realElements;
8607
8608       sRefSet_free (aliases);
8609       break;
8610     case SK_FIELD:
8611       inner = s->info->field->rec;
8612       aliases = usymtab_allAliases (inner);
8613       ct = sRef_getType (inner);
8614
8615       
8616       sRefSet_realElements (aliases, current)
8617         {
8618           if (sRef_isValid (current))
8619             {
8620               current = sRef_updateSref (current);
8621               
8622               if (ctype_equal (ct, sRef_getType (current)))
8623                 {
8624                   sRef f = sRef_makeField (current, s->info->field->field);
8625                   
8626                   ((*predf)(f, t));
8627                 }
8628             }
8629         } end_sRefSet_realElements;
8630       
8631       sRefSet_free (aliases);
8632       break;
8633     case SK_CONJ:
8634       sRef_innerAliasSetCompleteParam (predf, s->info->conj->a, t);
8635       sRef_innerAliasSetCompleteParam (predf, s->info->conj->b, t);
8636       break;
8637     case SK_SPECIAL:
8638     case SK_ADR:
8639     case SK_TYPE:
8640     case SK_CONST:
8641     case SK_NEW:
8642     case SK_UNKNOWN:
8643     case SK_OBJECT:
8644     case SK_DERIVED:
8645     case SK_EXTERNAL:
8646     case SK_RESULT:
8647       break;
8648     }
8649 }
8650
8651 static void sRef_combineExKinds (/*@notnull@*/ sRef res, /*@notnull@*/ sRef other)
8652 {
8653   exkind a1 = sRef_getExKind (res);
8654   exkind a2 = sRef_getExKind (other);
8655
8656   if (a1 == a2 || a2 == XO_UNKNOWN) 
8657     {
8658       ;
8659     }
8660   else if (a1 == XO_UNKNOWN) 
8661     { 
8662       res->expinfo = stateInfo_update (res->expinfo, other->expinfo);
8663       res->expkind = a2;
8664     }
8665   else
8666     {
8667       res->expkind = XO_OBSERVER;
8668     }
8669 }
8670
8671 /*
8672 ** Currently, this is a very ad hoc implementation, with lots of fixes to
8673 ** make real code work okay.  I need to come up with some more general
8674 ** rules or principles here.
8675 */
8676
8677 static void 
8678   sRef_combineAliasKindsError (/*@notnull@*/ sRef res, 
8679                                /*@notnull@*/ sRef other, 
8680                                clause cl, fileloc loc)
8681 {
8682   bool hasError = FALSE;
8683   alkind ares = sRef_getAliasKind (res);
8684   alkind aother = sRef_getAliasKind (other);
8685
8686   sRef_checkMutable (res);
8687
8688   if (alkind_isDependent (ares))
8689     {
8690       if (aother == AK_KEPT)
8691         {
8692           res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8693           res->aliaskind = AK_KEPT;      
8694         }
8695       else 
8696         {
8697           if (aother == AK_LOCAL || aother == AK_STATIC 
8698               || alkind_isTemp (aother))
8699             {
8700               DPRINTF (("Setting dependent: %s", sRef_unparseFull (res)));
8701               res->aliaskind = AK_DEPENDENT;
8702             }
8703         }
8704     }
8705   else if (alkind_isDependent (aother))
8706     {
8707       if (ares == AK_KEPT)
8708         {
8709           res->aliaskind = AK_KEPT;      
8710         }
8711       else 
8712         {
8713           if (ares == AK_LOCAL || ares == AK_STATIC || alkind_isTemp (ares))
8714             {
8715               DPRINTF (("Setting dependent: %s", sRef_unparseFull (res)));
8716               res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8717               res->aliaskind = AK_DEPENDENT;
8718             }
8719         }
8720     }
8721   else if ((ares == AK_LOCAL || ares == AK_UNIQUE
8722             || ares == AK_STATIC || alkind_isTemp (ares))
8723            && sRef_isFresh (other))
8724     {
8725       /*
8726       ** cases like: if (s == NULL) s = malloc...;
8727       **    don't generate errors
8728       */
8729       
8730       if (usymtab_isAltDefinitelyNullDeep (res))
8731         {
8732           res->aliaskind = ares;
8733         }
8734       else
8735         {
8736           hasError = TRUE; 
8737         }
8738     }
8739   else if ((aother == AK_LOCAL || aother == AK_UNIQUE
8740             || aother == AK_STATIC || alkind_isTemp (aother))
8741            && sRef_isFresh (res))
8742     {
8743       /*
8744       ** cases like: if (s == NULL) s = malloc...;
8745       **    don't generate errors
8746       */
8747       
8748       if (usymtab_isDefinitelyNullDeep (other))
8749         {
8750           res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8751           res->aliaskind = aother;
8752         }
8753       else
8754         {
8755           hasError = TRUE;
8756         }
8757     }
8758   else if (ares == AK_NEWREF && aother == AK_REFCOUNTED 
8759            && sRef_isConst (other))
8760     {
8761       res->aliaskind = AK_NEWREF;
8762     }
8763   else if (aother == AK_NEWREF && ares == AK_REFCOUNTED
8764            && sRef_isConst (res))
8765     {
8766       res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8767       res->aliaskind = AK_NEWREF;
8768     }
8769   else if (sRef_isLocalVar (res)
8770            && ((ares == AK_KEPT && aother == AK_LOCAL)
8771                || (aother == AK_KEPT && ares == AK_LOCAL)))
8772     {
8773       res->aliaskind = AK_KEPT;
8774     }
8775   else
8776     {
8777       hasError = TRUE;
8778     }
8779
8780   if (hasError)
8781     {
8782       if (sRef_isThroughArrayFetch (res))
8783         {
8784           if (optgenerror2 
8785               (FLG_BRANCHSTATE, FLG_STRICTBRANCHSTATE,
8786                message
8787                ("Clauses exit with %q possibly referencing %s storage %s, "
8788                 "%s storage %s", 
8789                 sRef_unparse (res),
8790                 alkind_unparse (aother),
8791                 clause_nameTaken (cl),
8792                 alkind_unparse (ares),
8793                 clause_nameAlternate (cl)),
8794                loc))
8795             {
8796               sRef_showAliasInfo (res);
8797               sRef_showAliasInfo (other);
8798               res->aliaskind = AK_ERROR;
8799             }
8800           else
8801             {
8802               if (ares == AK_KEPT || aother == AK_KEPT)
8803                 {
8804                   sRef_maybeKill (res, loc);
8805                 }
8806             }
8807         }
8808       else 
8809         {
8810           if (optgenerror 
8811               (FLG_BRANCHSTATE,
8812                message ("Clauses exit with %q referencing %s storage %s, "
8813                         "%s storage %s", 
8814                         sRef_unparse (res),
8815                         alkind_unparse (aother),
8816                         clause_nameTaken (cl),
8817                         alkind_unparse (ares),
8818                         clause_nameAlternate (cl)),
8819                loc))
8820             {
8821               sRef_showAliasInfo (res);
8822               sRef_showAliasInfo (other);
8823               
8824               res->aliaskind = AK_ERROR;
8825             }
8826         }
8827       
8828       res->aliaskind = (sRef_isLocalVar (res) ? AK_LOCAL : AK_UNKNOWN);
8829     }
8830 }
8831
8832 static void 
8833   sRef_combineAliasKinds (/*@notnull@*/ sRef res, /*@notnull@*/ sRef other, 
8834                           clause cl, fileloc loc)
8835 {
8836   alkind ares = sRef_getAliasKind (res);
8837   alkind aother = sRef_getAliasKind (other);
8838
8839   sRef_checkMutable (res);
8840
8841   DPRINTF (("Combine alias kinds: \n\t%s / \n\t%s",
8842             sRef_unparseFull (res), sRef_unparseFull (other)));
8843   if (alkind_equal (ares, aother)
8844       || aother == AK_UNKNOWN
8845       || aother == AK_ERROR)
8846     {
8847       ; /* keep current state */
8848     }
8849   else if (sRef_isDead (res) || sRef_isDead (other))
8850     {
8851       /* dead error reported (or storage is dead) */
8852       res ->aliaskind = AK_ERROR; 
8853     }
8854   else if (ares == AK_UNKNOWN || ares == AK_ERROR
8855            || sRef_isStateUndefined (res)
8856            || sRef_isDefinitelyNull (res))
8857     { 
8858       res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8859       res->aliaskind = aother;  
8860     }
8861   else if (sRef_isStateUndefined (other)
8862            || sRef_isDefinitelyNull (other))
8863     {
8864       ;
8865     }
8866   else if (((ares == AK_UNIQUE || alkind_isTemp (ares))
8867             && aother == AK_LOCAL) 
8868            || ((aother == AK_UNIQUE || alkind_isTemp (aother))
8869                && ares == AK_LOCAL))
8870     {
8871       if (ares != AK_LOCAL)
8872         {
8873           res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8874         }
8875
8876       res->aliaskind = AK_LOCAL;
8877     }
8878   else if ((ares == AK_OWNED && aother == AK_FRESH) 
8879            || (aother == AK_OWNED && ares == AK_FRESH))
8880     {
8881       if (ares != AK_FRESH)
8882         {
8883           res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8884         }
8885       
8886       res->aliaskind = AK_FRESH;
8887     }
8888   else if ((ares == AK_KEEP && aother == AK_FRESH) ||
8889            (aother == AK_KEEP && ares == AK_FRESH))
8890     {
8891       if (ares != AK_KEEP)
8892         {
8893           res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8894         }
8895       
8896       res->aliaskind = AK_KEEP;
8897     }
8898   else if ((ares == AK_LOCAL && aother == AK_STACK) ||
8899            (aother == AK_LOCAL && ares == AK_STACK))
8900     {
8901       if (ares != AK_STACK)
8902         {
8903           res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8904         }
8905
8906       res->aliaskind = AK_STACK;
8907     }
8908   else if ((ares == AK_LOCAL
8909             && (aother == AK_OWNED && sRef_isLocalVar (other)))
8910            || (aother == AK_LOCAL 
8911                && (ares == AK_OWNED && sRef_isLocalVar (res))))
8912     {
8913       if (ares != AK_LOCAL)
8914         {
8915           res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8916         }
8917
8918       res->aliaskind = AK_LOCAL;
8919     }
8920   else if ((ares == AK_FRESH && alkind_isOnly (aother))
8921            || (aother == AK_FRESH && alkind_isOnly (ares)))
8922     {
8923       res->aliaskind = AK_FRESH;
8924     }
8925   else if ((aother == AK_FRESH && sRef_definitelyNull (res))
8926            || (ares == AK_FRESH && sRef_definitelyNull (other)))
8927     {
8928       if (ares != AK_FRESH)
8929         {
8930           res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8931           res->aliaskind = AK_FRESH;
8932         }
8933     }
8934   else if ((sRef_isFresh (res) && sRef_isConst (other))
8935            || (sRef_isFresh (other) && sRef_isConst (res)))
8936     {
8937       /*
8938       ** for NULL constantants
8939       ** this is bogus!
8940       */
8941
8942       if (!sRef_isFresh (res))
8943         {
8944           res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8945         }
8946
8947       res->aliaskind = AK_FRESH;
8948     }
8949   else if ((alkind_isStatic (aother) && sRef_isConst (res))
8950            || (alkind_isStatic (ares) && sRef_isConst (other)))
8951     {
8952       if (!alkind_isStatic (ares))
8953         {
8954           res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8955           res->aliaskind = AK_STATIC;
8956         }
8957     }
8958   else
8959     {
8960       sRef_combineAliasKindsError (res, other, cl, loc);
8961     }
8962 }
8963
8964 static void sRef_combineDefState (/*@notnull@*/ sRef res, 
8965                                   /*@notnull@*/ sRef other)
8966 {
8967   sstate s1 = res->defstate;
8968   sstate s2 = other->defstate;
8969   bool flip = FALSE;
8970
8971   sRef_checkMutable (res);
8972
8973   if (s1 == s2 || s2 == SS_UNKNOWN)
8974     {
8975       ;
8976     }
8977   else if (s1 == SS_UNKNOWN)
8978     {
8979       flip = TRUE;
8980     }
8981   else
8982     {
8983       switch (s1)
8984         {
8985         case SS_FIXED:   
8986           if (s2 == SS_DEFINED) 
8987             {
8988               break;
8989             }
8990           else
8991             {
8992               llcontbuglit ("ssfixed: not implemented");
8993               flip = TRUE;
8994             }
8995           break;
8996         case SS_DEFINED: 
8997           flip = TRUE;
8998           break;
8999         case SS_PDEFINED:
9000         case SS_ALLOCATED: 
9001           flip = (s2 != SS_DEFINED);
9002           break;
9003         case SS_HOFFA:
9004         case SS_RELDEF:
9005         case SS_UNUSEABLE: 
9006         case SS_UNDEFINED: 
9007         case SS_PARTIAL:
9008         case SS_UNDEFGLOB:
9009         case SS_KILLED:
9010         case SS_DEAD:      
9011         case SS_SPECIAL: 
9012           break;
9013         BADDEFAULT;
9014         }
9015     }
9016
9017   if (flip)
9018     {
9019       res->definfo = stateInfo_update (res->definfo, other->definfo);
9020       res->defstate = s2;
9021     }
9022 }
9023
9024 extern /*@notnull@*/ sRef sRef_getConjA (sRef s)
9025 {
9026   sRef ret;
9027   llassert (sRef_isConj (s));
9028
9029   ret = s->info->conj->a;
9030   llassert (ret != NULL);
9031   return ret;
9032 }
9033
9034 extern /*@notnull@*/ sRef sRef_getConjB (sRef s)
9035 {
9036   sRef ret;
9037   llassert (sRef_isConj (s));
9038
9039   ret = s->info->conj->b;
9040   llassert (ret != NULL);
9041   return ret;
9042 }
9043   
9044 extern /*@exposed@*/ sRef sRef_makeArrow (sRef s, /*@dependent@*/ cstring f)
9045 {
9046   sRef p;
9047   sRef ret;
9048   
9049   p = sRef_makePointer (s);
9050   ret = sRef_makeField (p, f);
9051   DPRINTF (("Arrow: %s => %s",
9052             sRef_unparseFull (s), sRef_unparseFull (ret)));
9053   return ret;
9054 }
9055
9056 extern /*@exposed@*/ sRef sRef_buildArrow (sRef s, cstring f)
9057 {
9058   sRef p;
9059   sRef ret;
9060
9061   p = sRef_buildPointer (s);
9062   ret = sRef_buildField (p, f);
9063   
9064   return ret;
9065 }
9066
9067 static /*@null@*/ sinfo sinfo_copy (/*@notnull@*/ sRef s)
9068 {
9069   sinfo ret;
9070
9071   switch (s->kind)
9072     {
9073     case SK_CVAR:
9074       ret = (sinfo) dmalloc (sizeof (*ret));
9075       ret->cvar = (cref) dmalloc (sizeof (*ret->cvar));
9076       ret->cvar->lexlevel = s->info->cvar->lexlevel; 
9077       ret->cvar->index = s->info->cvar->index; 
9078       break;
9079
9080     case SK_PARAM:
9081       ret = (sinfo) dmalloc (sizeof (*ret));
9082       ret->paramno = s->info->paramno; 
9083       llassert (ret->paramno >= -1);
9084       break;
9085
9086     case SK_ARRAYFETCH:
9087       ret = (sinfo) dmalloc (sizeof (*ret));
9088       ret->arrayfetch = (ainfo) dmalloc (sizeof (*ret->arrayfetch));
9089       ret->arrayfetch->indknown = s->info->arrayfetch->indknown;
9090       ret->arrayfetch->ind = s->info->arrayfetch->ind;
9091       ret->arrayfetch->arr = s->info->arrayfetch->arr; /* sRef_copy (s->info->arrayfetch->arr); */ /*@i32@*/
9092       break;
9093
9094     case SK_FIELD:
9095       ret = (sinfo) dmalloc (sizeof (*ret));
9096       ret->field = (fldinfo) dmalloc (sizeof (*ret->field));
9097       ret->field->rec = s->info->field->rec; /* sRef_copy (s->info->field->rec); */ /*@i32@*/
9098       ret->field->field = s->info->field->field; 
9099       break;
9100
9101     case SK_OBJECT:
9102       ret = (sinfo) dmalloc (sizeof (*ret));
9103       ret->object = s->info->object;
9104       break;
9105
9106     case SK_PTR:
9107     case SK_ADR:
9108     case SK_DERIVED:
9109     case SK_EXTERNAL:
9110       ret = (sinfo) dmalloc (sizeof (*ret));
9111       ret->ref = s->info->ref; /* Ref_copy (s->info->ref); */
9112       break;
9113
9114     case SK_CONJ:
9115       ret = (sinfo) dmalloc (sizeof (*ret));
9116       ret->conj = (cjinfo) dmalloc (sizeof (*ret->conj));
9117       ret->conj->a = s->info->conj->a; /* sRef_copy (s->info->conj->a); */
9118       ret->conj->b = s->info->conj->b; /* sRef_copy (s->info->conj->b);*/
9119       break;
9120     case SK_SPECIAL:
9121       ret = (sinfo) dmalloc (sizeof (*ret));
9122       ret->spec = s->info->spec;
9123       break;
9124     case SK_UNCONSTRAINED:
9125     case SK_NEW:
9126       ret = (sinfo) dmalloc (sizeof (*ret));
9127       ret->fname = s->info->fname;
9128       break;
9129     case SK_RESULT:
9130     case SK_CONST:
9131     case SK_TYPE:
9132     case SK_UNKNOWN:
9133       llassertprint (s->info == NULL, ("s = %s", sRef_unparse (s)));
9134       ret = NULL;
9135       break;
9136     }
9137
9138   return ret;
9139 }
9140
9141 static /*@null@*/ sinfo sinfo_fullCopy (/*@notnull@*/ sRef s)
9142 {
9143   sinfo ret;
9144
9145   /*
9146   ** Since its a full copy, only storage is assigned
9147   ** to dependent fields.
9148   */
9149   /*@-onlytrans@*/
9150
9151   switch (s->kind)
9152     {
9153     case SK_CVAR:
9154       ret = (sinfo) dmalloc (sizeof (*ret));
9155       ret->cvar = (cref) dmalloc (sizeof (*ret->cvar));
9156       ret->cvar->lexlevel = s->info->cvar->lexlevel; 
9157       ret->cvar->index = s->info->cvar->index; 
9158       break;
9159
9160     case SK_PARAM:
9161       ret = (sinfo) dmalloc (sizeof (*ret));
9162       ret->paramno = s->info->paramno; 
9163       llassert (ret->paramno >= -1);
9164       break;
9165
9166     case SK_ARRAYFETCH:
9167       ret = (sinfo) dmalloc (sizeof (*ret));
9168       ret->arrayfetch = (ainfo) dmalloc (sizeof (*ret->arrayfetch));
9169       ret->arrayfetch->indknown = s->info->arrayfetch->indknown;
9170       ret->arrayfetch->ind = s->info->arrayfetch->ind;
9171       ret->arrayfetch->arr = sRef_saveCopy (s->info->arrayfetch->arr);
9172       break;
9173
9174     case SK_FIELD:
9175       ret = (sinfo) dmalloc (sizeof (*ret));
9176       ret->field = (fldinfo) dmalloc (sizeof (*ret->field));
9177       ret->field->rec = sRef_saveCopy (s->info->field->rec);
9178       ret->field->field = s->info->field->field; 
9179       break;
9180
9181     case SK_OBJECT:
9182       ret = (sinfo) dmalloc (sizeof (*ret));
9183       ret->object = s->info->object;
9184       break;
9185
9186     case SK_PTR:
9187     case SK_ADR:
9188     case SK_DERIVED:
9189     case SK_EXTERNAL:
9190       ret = (sinfo) dmalloc (sizeof (*ret));
9191       ret->ref = sRef_saveCopy (s->info->ref);   
9192       break;
9193
9194     case SK_CONJ:
9195       ret = (sinfo) dmalloc (sizeof (*ret));
9196       ret->conj = (cjinfo) dmalloc (sizeof (*ret->conj));
9197       ret->conj->a = sRef_saveCopy (s->info->conj->a);
9198       ret->conj->b = sRef_saveCopy (s->info->conj->b);
9199       break;
9200     case SK_SPECIAL:
9201       ret = (sinfo) dmalloc (sizeof (*ret));
9202       ret->spec = s->info->spec;
9203       break;
9204     case SK_NEW:
9205     case SK_UNCONSTRAINED:
9206       ret = (sinfo) dmalloc (sizeof (*ret));
9207       ret->fname = s->info->fname;
9208       break;
9209     case SK_CONST:
9210     case SK_TYPE:
9211     case SK_RESULT:
9212     case SK_UNKNOWN:
9213       llassert (s->info == NULL);
9214       ret = NULL;
9215       break;
9216     }
9217   /*@=onlytrans@*/ 
9218   return ret;
9219 }
9220
9221
9222 static void 
9223   sinfo_update (/*@notnull@*/ /*@exposed@*/ sRef res, 
9224                 /*@notnull@*/ /*@exposed@*/ sRef other)
9225 {
9226   llassert (res->kind == other->kind);
9227
9228   switch (res->kind)
9229     {
9230     case SK_CVAR:
9231       res->info->cvar->lexlevel = other->info->cvar->lexlevel; 
9232       res->info->cvar->index = other->info->cvar->index; 
9233       break;
9234
9235     case SK_PARAM:
9236       res->info->paramno = other->info->paramno; 
9237       llassert (res->info->paramno >= -1);
9238       break;
9239
9240     case SK_ARRAYFETCH:
9241       res->info->arrayfetch->indknown = other->info->arrayfetch->indknown;
9242       res->info->arrayfetch->ind = other->info->arrayfetch->ind;
9243       res->info->arrayfetch->arr = other->info->arrayfetch->arr;
9244       break;
9245
9246     case SK_FIELD:
9247       res->info->field->rec = other->info->field->rec;
9248       res->info->field->field = other->info->field->field; 
9249       break;
9250
9251     case SK_OBJECT:
9252       res->info->object = other->info->object;
9253       break;
9254
9255     case SK_PTR:
9256     case SK_ADR:
9257     case SK_DERIVED:
9258     case SK_EXTERNAL:
9259       res->info->ref = other->info->ref;         
9260       break;
9261
9262     case SK_CONJ:
9263       res->info->conj->a = other->info->conj->a;
9264       res->info->conj->b = other->info->conj->b;
9265       break;
9266
9267     case SK_SPECIAL:
9268       res->info->spec = other->info->spec;
9269       break;
9270
9271     case SK_NEW:
9272     case SK_UNCONSTRAINED:
9273       res->info->fname = other->info->fname;
9274       break;
9275
9276     case SK_CONST:
9277     case SK_TYPE:
9278     case SK_UNKNOWN:
9279     case SK_RESULT:
9280       llassert (res->info == NULL);
9281       break;
9282     }
9283 }
9284
9285 static void sinfo_free (/*@special@*/ /*@temp@*/ /*@notnull@*/ sRef s)
9286    /*@uses s->kind, s->info@*/
9287    /*@releases s->info@*/ 
9288 {
9289   switch (s->kind)
9290     {
9291     case SK_CVAR:
9292       DPRINTF (("Free sinfo: [%p]", s->info->cvar));
9293       sfree (s->info->cvar);
9294       break;
9295
9296     case SK_PARAM:
9297       break;
9298
9299     case SK_ARRAYFETCH:
9300       DPRINTF (("Free sinfo: [%p]", s->info->arrayfetch));
9301       sfree (s->info->arrayfetch);
9302       break;
9303
9304     case SK_FIELD:
9305       DPRINTF (("Free sinfo: [%p]", s->info->field));
9306       sfree (s->info->field); 
9307       break;
9308
9309     case SK_OBJECT:
9310       break;
9311
9312     case SK_PTR:
9313     case SK_ADR:
9314     case SK_DERIVED:
9315     case SK_EXTERNAL: /*@i32 is copy now! */
9316       break;
9317
9318     case SK_CONJ:
9319       DPRINTF (("Free sinfo: [%p]", s->info->conj));
9320       sfree (s->info->conj);
9321       break;
9322
9323     case SK_UNCONSTRAINED:
9324     case SK_SPECIAL:
9325     case SK_CONST:
9326     case SK_NEW:
9327     case SK_TYPE:
9328     case SK_UNKNOWN:
9329     case SK_RESULT:
9330       break;
9331     }
9332
9333   if (s->info != NULL) {
9334       DPRINTF (("Free sinfo: [%p]", s->info));
9335   }
9336
9337   sfree (s->info);
9338 }
9339
9340 bool sRef_isNSLocalVar (sRef s)  
9341 {
9342   if (sRef_isLocalVar (s))
9343     {
9344       uentry ue = sRef_getUentry (s);
9345
9346       return (!uentry_isStatic (ue));
9347     }
9348   else
9349     {
9350       return FALSE;
9351     }
9352 }
9353
9354 bool sRef_isLocalVar (sRef s)  
9355 {
9356   if (sRef_isValid(s))
9357     {
9358       return (s->kind == SK_CVAR 
9359               && (s->info->cvar->lexlevel > fileScope));
9360     }
9361   
9362   return FALSE;
9363 }
9364
9365 bool sRef_isRealLocalVar (sRef s)  
9366 {
9367   if (sRef_isValid(s))
9368     {
9369       if (s->kind == SK_CVAR)
9370         {
9371           if (s->info->cvar->lexlevel == functionScope)
9372             {
9373               uentry ue = sRef_getUentry (s);
9374
9375               if (uentry_isAnyParam (ue)
9376                   || uentry_isRefParam (ue))
9377                 {
9378                   return FALSE;
9379                 }
9380               else
9381                 {
9382                   return TRUE;
9383                 }
9384             }
9385           else
9386             {
9387               return (s->info->cvar->lexlevel > functionScope);
9388             }
9389         }
9390     }
9391   
9392   return FALSE;
9393 }
9394
9395 bool sRef_isLocalParamVar (sRef s)  
9396 {
9397   if (sRef_isValid(s))
9398     {
9399       return (s->kind == SK_PARAM
9400               || (s->kind == SK_CVAR 
9401                   && (s->info->cvar->lexlevel > fileScope)));
9402     }
9403   
9404   return FALSE;
9405 }
9406
9407 static speckind speckind_fromInt (int i)
9408 {
9409   /*@+enumint@*/ 
9410   llassert (i >= SR_NOTHING && i <= SR_SYSTEM); 
9411   /*@=enumint@*/
9412
9413   return ((speckind) i);
9414 }
9415
9416
9417 static void sRef_updateNullState (/*@notnull@*/ sRef res, /*@notnull@*/ sRef other)
9418      /*@modifies res@*/
9419 {
9420   res->nullstate = other->nullstate;
9421   res->nullinfo = stateInfo_update (res->nullinfo, other->nullinfo);
9422   sRef_resetAliasKind (res);
9423 }
9424
9425 void sRef_combineNullState (/*@notnull@*/ sRef res, /*@notnull@*/ sRef other)
9426 {
9427   nstate n1 = sRef_getNullState (res);
9428   nstate n2 = sRef_getNullState (other);
9429   bool flip = FALSE;
9430   nstate nn = n1;
9431
9432   if (n1 == n2 || n2 == NS_UNKNOWN)
9433     {
9434       ;
9435     }
9436   else
9437     {
9438       /* note: n2 is not unknown or defnull */
9439
9440       switch (n1)
9441         {
9442         case NS_ERROR:   nn = NS_ERROR; break;
9443         case NS_UNKNOWN: flip = TRUE; nn = n2; break; 
9444         case NS_POSNULL: break;
9445         case NS_DEFNULL: nn = NS_POSNULL; break;
9446         case NS_RELNULL: break;
9447         case NS_NOTNULL:  
9448           if (n2 == NS_MNOTNULL)
9449             {
9450               ;
9451             }
9452           else 
9453             { 
9454               flip = TRUE;
9455               nn = NS_POSNULL; 
9456             }
9457           break;
9458         case NS_MNOTNULL: 
9459           if (n2 == NS_NOTNULL) 
9460             {
9461               nn = NS_NOTNULL; 
9462             }
9463           else 
9464             {
9465               flip = TRUE;
9466               nn = NS_POSNULL; 
9467             }
9468           break;
9469         case NS_CONSTNULL:
9470         case NS_ABSNULL:
9471           flip = TRUE;
9472           nn = n2;
9473         }
9474     }
9475   
9476   if (flip)
9477     {
9478       res->nullinfo = stateInfo_update (res->nullinfo, other->nullinfo);      
9479     }
9480
9481   res->nullstate = nn;
9482   sRef_resetAliasKind (res);
9483 }
9484
9485 cstring sRef_nullMessage (sRef s)
9486 {
9487   llassert (sRef_isValid (s));
9488
9489   switch (sRef_getNullState (s))
9490     {
9491     case NS_DEFNULL:
9492     case NS_CONSTNULL:
9493       return (cstring_makeLiteralTemp ("null"));
9494     default:
9495       return (cstring_makeLiteralTemp ("possibly null"));
9496     }
9497   BADEXIT;
9498 }
9499
9500 /*@observer@*/ cstring sRef_ntMessage (sRef s)
9501 {
9502   llassert (sRef_isValid (s));
9503
9504   switch (s->nullstate)
9505     {
9506     case NS_DEFNULL:
9507     case NS_CONSTNULL:
9508       return (cstring_makeLiteralTemp ("not nullterminated"));
9509     default:
9510       return (cstring_makeLiteralTemp ("possibly non-nullterminated"));
9511     }
9512   BADEXIT;
9513 }
9514
9515
9516
9517 sRef sRef_fixResultType (/*@returned@*/ sRef s, ctype typ, uentry ue)
9518 {
9519   sRef tmp = sRef_undefined;
9520   sRef ret;
9521
9522   llassert (sRef_isValid (s));
9523
9524   switch (s->kind)
9525     {
9526     case SK_RESULT:
9527       s->type = typ;
9528       ret = s;
9529       break;
9530     case SK_ARRAYFETCH:
9531       {
9532         ctype ct;
9533         tmp = sRef_fixResultType (s->info->arrayfetch->arr, typ, ue);
9534
9535         ct = ctype_realType (sRef_getType (tmp));
9536
9537         
9538         if (ctype_isKnown (ct))
9539           {
9540             if (ctype_isAP (ct))
9541               {
9542                 ;
9543               }
9544             else
9545               {
9546                 voptgenerror 
9547                   (FLG_TYPE,
9548                    message
9549                    ("Special clause indexes non-array (%t): *%q",
9550                     ct, sRef_unparse (s->info->arrayfetch->arr)),
9551                    uentry_whereLast (ue));
9552               }
9553           }
9554
9555         tmp = sRef_fixResultType (s->info->arrayfetch->arr, typ, ue);
9556
9557         if (s->info->arrayfetch->indknown)
9558           {
9559             ret = sRef_makeArrayFetchKnown (tmp, s->info->arrayfetch->ind);
9560           }
9561         else
9562           {
9563             ret = sRef_makeArrayFetch (tmp);
9564           }
9565       }
9566       break;
9567     case SK_FIELD:
9568       {
9569         sRef rec = sRef_fixResultType (s->info->field->rec, typ, ue);
9570         ctype ct = ctype_realType (sRef_getType (rec));
9571
9572         if (ctype_isKnown (ct))
9573           {
9574             if (ctype_isSU (ct))
9575               {
9576                 if (uentry_isValid (uentryList_lookupField (ctype_getFields (ct), 
9577                                                             s->info->field->field)))
9578                   {
9579                     ;
9580                   }
9581                 else
9582                   {
9583                     voptgenerror 
9584                       (FLG_TYPE,
9585                        message
9586                        ("Special clause accesses non-existent field of result: %q.%s",
9587                         sRef_unparse (rec), s->info->field->field),
9588                        uentry_whereLast (ue));
9589                   }
9590               }
9591             else
9592               {
9593                 voptgenerror 
9594                   (FLG_TYPE,
9595                    message
9596                    ("Special clause accesses field of non-struct or union result (%t): %q.%s",
9597                     ct, sRef_unparse (rec), s->info->field->field),
9598                    uentry_whereLast (ue));
9599               }
9600           }
9601         
9602         ret = sRef_makeField (tmp, s->info->field->field);
9603         break;
9604       }
9605     case SK_PTR:
9606       {
9607         ctype ct;
9608         tmp = sRef_fixResultType (s->info->ref, typ, ue);
9609
9610         ct = ctype_realType (sRef_getType (tmp));
9611
9612         if (ctype_isKnown (ct))
9613           {
9614             if (ctype_isAP (ct))
9615               {
9616                 ;
9617               }
9618             else
9619               {
9620                 voptgenerror 
9621                   (FLG_TYPE,
9622                    message
9623                    ("Special clause dereferences non-pointer (%t): *%q",
9624                     ct, sRef_unparse (s->info->ref)),
9625                    uentry_whereLast (ue));
9626               }
9627           }
9628         
9629         ret = sRef_makePointer (tmp);
9630         break;
9631       }
9632     case SK_ADR:
9633       voptgenerror 
9634         (FLG_TYPE,
9635          message
9636          ("Special clause uses & operator (not allowed): &%q", sRef_unparse (s->info->ref)),
9637          uentry_whereLast (ue));
9638       ret = s;
9639       break;
9640     BADDEFAULT;
9641     }
9642
9643   return ret;
9644 }
9645
9646 bool sRef_isOnly (sRef s)
9647 {
9648   return (sRef_isValid(s) && alkind_isOnly (s->aliaskind));
9649 }
9650
9651 bool sRef_isDependent (sRef s) 
9652 {
9653   return (sRef_isValid(s) && alkind_isDependent (s->aliaskind));
9654 }
9655
9656 bool sRef_isOwned (sRef s)
9657 {
9658   return (sRef_isValid (s) && (s->aliaskind == AK_OWNED));
9659 }
9660
9661 bool sRef_isKeep (sRef s) 
9662 {
9663   return (sRef_isValid (s) && (s->aliaskind == AK_KEEP));
9664 }
9665
9666 bool sRef_isTemp (sRef s)
9667 {
9668   return (sRef_isValid (s) && alkind_isTemp (s->aliaskind));
9669 }
9670
9671 bool sRef_isLocalState (sRef s) 
9672 {
9673   return (sRef_isValid (s) && (s->aliaskind == AK_LOCAL));
9674 }
9675
9676 bool sRef_isUnique (sRef s)
9677 {
9678   return (sRef_isValid (s) && (s->aliaskind == AK_UNIQUE));
9679 }
9680
9681 bool sRef_isShared (sRef s) 
9682 {
9683   return (sRef_isValid (s) && (s->aliaskind == AK_SHARED));
9684 }
9685
9686 bool sRef_isExposed (sRef s) 
9687 {
9688   return (sRef_isValid (s) && (s->expkind == XO_EXPOSED));
9689 }
9690
9691 bool sRef_isObserver (sRef s) 
9692 {
9693   return (sRef_isValid (s) && (s->expkind == XO_OBSERVER));
9694 }
9695
9696 bool sRef_isFresh (sRef s) 
9697 {
9698   return (sRef_isValid (s) && (s->aliaskind == AK_FRESH));
9699 }
9700
9701 bool sRef_isDefinitelyNull (sRef s) 
9702 {
9703   return (sRef_isValid (s) && (sRef_getNullState (s) == NS_DEFNULL 
9704                                || sRef_getNullState (s) == NS_CONSTNULL));
9705 }
9706
9707 bool sRef_isAllocated (sRef s)
9708 {
9709   return (sRef_isValid (s) && (s->defstate == SS_ALLOCATED));
9710 }
9711
9712 bool sRef_isStack (sRef s)
9713 {
9714   return (sRef_isValid (s) && (s->aliaskind == AK_STACK));
9715 }
9716
9717 bool sRef_isNotNull (sRef s)
9718 {
9719   return (sRef_isValid(s) && (sRef_getNullState (s) == NS_MNOTNULL 
9720                               || sRef_getNullState (s) == NS_NOTNULL));
9721 }
9722
9723 alkind sRef_getAliasKind (sRef s)
9724 {
9725   if (sRef_isValid(s)) {
9726     llassert (alkind_isValid (s->aliaskind));
9727     return s->aliaskind;
9728   }
9729
9730   return AK_ERROR;
9731 }
9732
9733 nstate sRef_getNullState (sRef s)
9734 {
9735   if (sRef_isValid (s)) {
9736     llassert (nstate_isValid (s->nullstate));
9737     return s->nullstate;
9738   }
9739   
9740   return NS_UNKNOWN;
9741 }
9742
9743 void sRef_reflectAnnotation (sRef s, annotationInfo a, fileloc loc)
9744 {
9745   if (sRef_isValid (s))
9746     {
9747       if (!valueTable_isDefined (s->state))
9748         {
9749           s->state = valueTable_create (1);
9750           valueTable_insert (s->state, 
9751                              cstring_copy (metaStateInfo_getName (annotationInfo_getState (a))),
9752                              stateValue_create (annotationInfo_getValue (a), stateInfo_makeLoc (loc)));
9753         }
9754       else
9755         {
9756           DPRINTF (("reflect loc: %s", fileloc_unparse (loc)));
9757           valueTable_update 
9758             (s->state,
9759              metaStateInfo_getName (annotationInfo_getState (a)),
9760              stateValue_create (annotationInfo_getValue (a), stateInfo_makeLoc (loc)));
9761           DPRINTF (("state info: %s", stateInfo_unparse (stateInfo_makeLoc (loc))));
9762           DPRINTF (("sref: %s", sRef_unparse (s)));
9763           DPRINTF (("sref: %s", sRef_unparseFull (s)));
9764         }
9765     }
9766 }
9767
9768 void sRef_setMetaStateValueComplete (sRef s, cstring key, int value, fileloc loc)
9769 {
9770   sRefSet aliases = usymtab_allAliases (s);
9771
9772   sRef_setMetaStateValue (s, key, value, loc);
9773
9774   sRefSet_realElements (aliases, current)
9775     {
9776       if (sRef_isValid (current))
9777         {
9778           current = sRef_updateSref (current);
9779           sRef_setMetaStateValue (current, key, value, loc);
9780         }
9781     } end_sRefSet_realElements ;
9782
9783   sRefSet_free (aliases);
9784 }
9785
9786 void sRef_setMetaStateValue (sRef s, cstring key, int value, fileloc loc)
9787 {
9788   sRef_checkMutable (s);
9789
9790   if (sRef_isValid (s))
9791     {
9792       if (!valueTable_isDefined (s->state))
9793         {
9794           DPRINTF (("inserting state: %s: %s %d", sRef_unparse (s), key, value));
9795           s->state = valueTable_create (1);
9796           valueTable_insert (s->state, cstring_copy (key),
9797                              stateValue_create (value, stateInfo_makeLoc (loc)));
9798         }
9799       else
9800         {
9801           DPRINTF (("Updating state: %s: %s %d / %s", sRef_unparse (s), key, value,
9802                     fileloc_unparse (loc)));
9803           if (valueTable_contains (s->state, key))
9804             {
9805               valueTable_update 
9806                 (s->state, key, stateValue_create (value, stateInfo_makeLoc (loc)));
9807             }
9808           else
9809             {
9810               valueTable_insert 
9811                 (s->state, cstring_copy (key), stateValue_create (value, stateInfo_makeLoc (loc)));
9812             }
9813
9814           DPRINTF (("After: %s", sRef_unparseFull (s)));
9815         }
9816     }
9817 }
9818
9819 bool sRef_checkMetaStateValue (sRef s, cstring key, int value)
9820 {
9821   if (sRef_isValid (s))
9822     {
9823       if (valueTable_isDefined (s->state))
9824         {
9825           stateValue val;
9826           
9827           DPRINTF (("check state: %s: %s %d", sRef_unparse (s), key, value));
9828           
9829           val = valueTable_lookup (s->state, key);
9830           llassert (stateValue_isDefined (val));
9831           return (stateValue_isError (val)
9832                   || stateValue_getValue (val) == value);
9833         }
9834       else
9835         {
9836           return TRUE;
9837         }
9838     }
9839   else
9840     {
9841       return TRUE;
9842     }
9843 }
9844
9845 /*@observer@*/ stateValue sRef_getMetaStateValue (sRef s, cstring key)
9846 {
9847   if (sRef_isValid (s))
9848     {
9849       if (valueTable_isDefined (s->state))
9850         {
9851           stateValue val;
9852           
9853           val = valueTable_lookup (s->state, key);
9854           /* Okay if its not defined, just returns stateValue_undefined */
9855           return val;
9856         }
9857       else
9858         {
9859           return stateValue_undefined;
9860         }
9861     }
9862   else
9863     {
9864       return stateValue_undefined;
9865     }
9866 }
9867
9868 /*@observer@*/ valueTable sRef_getValueTable (sRef s) 
9869 {
9870   DPRINTF (("Get value table: %s", sRef_unparse (s)));
9871
9872   if (sRef_isValid (s)) 
9873     {
9874       llassert (sRef_isValid (s));
9875       DPRINTF (("Value table: %s", valueTable_unparse (s->state)));
9876       return s->state;
9877     }  
9878   else 
9879     {
9880       DPRINTF (("No value table!"));
9881       return valueTable_undefined;
9882     }
9883 }
9884
9885 bool sRef_makeStateSpecial (sRef s)
9886 {
9887   /*
9888   ** Default defined state can be made special.
9889   */
9890
9891   llassert (sRef_isValid (s)); /*@i523 why doesn't null-checking work!??? */
9892
9893   if (s->defstate == SS_UNKNOWN || s->defstate == SS_DEFINED || s->defstate == SS_SPECIAL)
9894     {
9895       /* s->aliaskind = AK_IMPTEMP; */ /* evans 2001-07-23 shouldn't effect alias state */
9896       s->defstate = SS_SPECIAL;
9897       DPRINTF (("Made special: %s", sRef_unparseFull (s)));
9898       return TRUE;
9899     }
9900   else
9901     {
9902       /* s->aliaskind = AK_IMPTEMP; */
9903       s->defstate = SS_SPECIAL;
9904       return FALSE;
9905     }
9906 }
9907
9908 void sRef_markImmutable (sRef s)
9909 {
9910   if (sRef_isValid (s))
9911     {
9912       DPRINTF (("Mark immutable: %s", sRef_unparseFull (s)));
9913       s->immut = TRUE;
9914     }
9915 }
9916
9917 bool sRef_definitelyNullContext (sRef s)
9918 {
9919   return (sRef_definitelyNull (s)
9920           || usymtab_isDefinitelyNullDeep (s));
9921 }
9922
9923 bool sRef_definitelyNullAltContext (sRef s)
9924 {
9925   return (sRef_definitelyNull (s)
9926           || usymtab_isAltDefinitelyNullDeep (s));
9927 }
9928
9929
9930 /* start modifications */
9931 struct s_bbufinfo sRef_getNullTerminatedState (sRef p_s) {
9932    struct s_bbufinfo BUFSTATE_UNKNOWN;
9933    BUFSTATE_UNKNOWN.bufstate = BB_NOTNULLTERMINATED;
9934    BUFSTATE_UNKNOWN.size = 0;
9935    BUFSTATE_UNKNOWN.len = 0;
9936    
9937    if (sRef_isValid(p_s))
9938       return p_s->bufinfo;
9939    return BUFSTATE_UNKNOWN; 
9940 }
9941
9942 void sRef_setNullTerminatedState(sRef p_s) {
9943    if(sRef_isValid (p_s)) {
9944       p_s->bufinfo.bufstate = BB_NULLTERMINATED;
9945    } else {
9946       llfatalbug( message("sRef_setNT passed a invalid sRef\n"));
9947    }
9948 }
9949
9950
9951 void sRef_setPossiblyNullTerminatedState(sRef p_s) {
9952    if( sRef_isValid (p_s)) {
9953       p_s->bufinfo.bufstate = BB_POSSIBLYNULLTERMINATED;
9954    } else {
9955       llfatalbug( message("sRef_setPossNT passed a invalid sRef\n"));
9956    }
9957 }
9958
9959 void sRef_setNotNullTerminatedState(sRef p_s) {
9960    if( sRef_isValid (p_s)) {
9961       p_s->bufinfo.bufstate = BB_NOTNULLTERMINATED;
9962    } else {
9963       llfatalbug( message("sRef_unsetNT passed a invalid sRef\n"));
9964    }
9965 }
9966
9967 void sRef_setLen(sRef p_s, int len) {
9968    if( sRef_isValid (p_s) && sRef_isNullTerminated(p_s)) {
9969       p_s->bufinfo.len = len;
9970    } else {
9971       llfatalbug( message("sRef_setLen passed a invalid sRef\n"));
9972    }
9973 }
9974     
9975
9976 void sRef_setSize(sRef p_s, int size) {
9977    if( sRef_isValid(p_s)) {
9978        p_s->bufinfo.size = size;
9979    } else {
9980       llfatalbug( message("sRef_setSize passed a invalid sRef\n"));
9981    }
9982 }
9983
9984 void sRef_resetLen(sRef p_s) {
9985         if (sRef_isValid (p_s)) {
9986                 p_s->bufinfo.len = 0;
9987         } else {
9988                 llfatalbug (message ("sRef_setLen passed an invalid sRef\n"));
9989         }
9990 }
9991
9992 /*drl7x 11/28/2000 */
9993
9994 bool sRef_isFixedArray (sRef p_s) /*@*/ {
9995   ctype c;
9996   c = sRef_getType (p_s);
9997   return ( ctype_isFixedArray (c) );
9998 }
9999
10000 long int sRef_getArraySize (sRef p_s) /*@*/ {
10001   ctype c;
10002   llassert (sRef_isFixedArray(p_s) );
10003   DPRINTF (( message ("sRef_getArraySize getting array size for %s", sRef_unparse(p_s) )  ));
10004   
10005   c = sRef_getType (p_s);
10006
10007   return (ctype_getArraySize (c) );
10008 }
10009
10010 void sRef_setValue (sRef s, multiVal val)
10011 {
10012   llassert (sRef_isValid (s));
10013   multiVal_free (s->val);
10014   s->val = val;
10015 }
10016
10017 bool sRef_hasValue (sRef s)
10018 {
10019   return (sRef_isValid (s)
10020           && multiVal_isDefined (s->val));
10021 }
10022
10023 multiVal sRef_getValue (sRef s)
10024 {
10025   if (sRef_isValid (s))
10026     {
10027       return s->val;
10028     }
10029
10030   return multiVal_undefined;
10031 }
This page took 0.813698 seconds and 5 git commands to generate.