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