]> andersk Git - splint.git/blob - src/sRef.c
Fixes for win32
[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 <= 999); /* sanity check */
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; 
442   s->bufinfo.len = -1; 
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, usymId_fromInt (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, usymId_fromInt (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         ce = constraintExpr_makeTermsRef (s);
2260         return ce;
2261       }
2262     case SK_FIELD:
2263       {
2264         sRef temp;
2265         
2266         temp = (sRef_makeField (sRef_fixBaseParam (s->info->field->rec, args),
2267                               s->info->field->field));
2268         ce = constraintExpr_makeTermsRef (temp);
2269         return ce;
2270       }
2271     case SK_PTR:
2272       {
2273         sRef temp;
2274         temp = (sRef_makePointer (sRef_fixBaseParam (s->info->ref, args)));
2275         ce = constraintExpr_makeTermsRef (temp);
2276         return ce;
2277       }
2278
2279     case SK_ARRAYFETCH:
2280        {
2281         sRef temp;
2282         temp = sRef_saveCopy(s);
2283         temp = sRef_fixBaseParam (temp, args);
2284         ce = constraintExpr_makeTermsRef (temp);
2285
2286         sRef_free(temp);
2287         return ce;
2288       }
2289     case SK_CVAR:
2290       {
2291         sRef temp;
2292         temp = sRef_saveCopy(s);
2293         ce = constraintExpr_makeTermsRef (temp);
2294         sRef_free(temp);
2295         return ce;
2296       }
2297     case SK_PARAM:
2298       {
2299         exprNode e;
2300         llassert (exprNodeList_size (args) > s->info->paramno);
2301         e = exprNodeList_nth (args, s->info->paramno);
2302         
2303         llassert (!(exprNode_isError (e)));
2304         ce = constraintExpr_makeExprNode (e);
2305         return ce;
2306       }
2307
2308     default:
2309       {
2310         sRef temp;
2311         llcontbug (message ("Trying to do fixConstraintParam on nonparam, nonglobal: %q for function with arguments %q",
2312                             sRef_unparse (s), exprNodeList_unparse(args)));
2313       temp = sRef_saveCopy(s);
2314       ce = constraintExpr_makeTermsRef (temp);
2315
2316       sRef_free(temp);
2317       return ce;
2318       }
2319     }
2320 }
2321
2322 /*@exposed@*/ sRef
2323 sRef_fixBaseParam (/*@returned@*/ sRef s, exprNodeList args)
2324 {
2325   if (sRef_isInvalid (s)) return (sRef_undefined);
2326
2327   switch (s->kind)
2328     {
2329     case SK_UNCONSTRAINED:
2330     case SK_CVAR:
2331       return s;
2332     case SK_PARAM:
2333       {
2334         if (exprNodeList_size (args) > s->info->paramno)
2335           {
2336             exprNode e = exprNodeList_nth (args, s->info->paramno);
2337
2338             if (exprNode_isError (e))
2339               {
2340                 return sRef_makeUnknown ();
2341               }
2342             
2343             return (exprNode_getSref (e));
2344           }
2345         else
2346           {
2347             return sRef_makeUnknown ();
2348           }
2349       }
2350     case SK_ARRAYFETCH:
2351
2352       if (s->info->arrayfetch->indknown)
2353         {
2354           return (sRef_makeArrayFetchKnown 
2355                   (sRef_fixBaseParam (s->info->arrayfetch->arr, args),
2356                    s->info->arrayfetch->ind));
2357         }
2358       else
2359         {
2360           return (sRef_makeArrayFetch 
2361                   (sRef_fixBaseParam (s->info->arrayfetch->arr, args)));
2362         }
2363     case SK_FIELD:
2364       {
2365         sRef res;
2366         DPRINTF (("Fix field: %s", sRef_unparseFull (s)));
2367         res = sRef_makeField (sRef_fixBaseParam (s->info->field->rec, args),
2368                               s->info->field->field);
2369         DPRINTF (("Returns: %s", sRef_unparseFull (res)));
2370         return res;
2371       }
2372     case SK_PTR:
2373       return (sRef_makePointer (sRef_fixBaseParam (s->info->ref, args)));
2374
2375     case SK_ADR:
2376       return (sRef_makeAddress (sRef_fixBaseParam (s->info->ref, args)));
2377
2378     case SK_CONJ:
2379       return (sRef_makeConj (sRef_fixBaseParam (s->info->conj->a, args),
2380                              sRef_fixBaseParam (s->info->conj->b, args)));
2381     case SK_DERIVED:
2382     case SK_SPECIAL:
2383     case SK_TYPE:
2384     case SK_CONST:
2385     case SK_NEW:
2386     case SK_UNKNOWN:
2387     case SK_OBJECT:
2388     case SK_EXTERNAL:
2389     case SK_RESULT:
2390       return s;
2391     }
2392   BADEXIT;
2393 }
2394
2395 /*@exposed@*/ sRef
2396 sRef_undumpGlobal (char **c)
2397 {
2398   char p = **c;
2399
2400   (*c)++;
2401
2402   switch (p)
2403     {
2404     case 'g':
2405       {
2406         usymId uid = usymId_fromInt (reader_getInt (c));
2407         sstate defstate;
2408         nstate nullstate;
2409         sRef ret;
2410
2411         reader_checkChar (c, '@');
2412         defstate = sstate_fromInt (reader_getInt (c));
2413
2414         reader_checkChar (c, '@');
2415         nullstate = nstate_fromInt (reader_getInt (c));
2416
2417         ret = sRef_makeGlobal (uid, ctype_unknown, stateInfo_currentLoc ());
2418         sRef_setNullStateN (ret, nullstate);
2419         ret->defstate = defstate;
2420         return ret;
2421       }
2422     case 's':
2423       {
2424         int i = reader_getInt (c);
2425         speckind sk = speckind_fromInt (i);
2426
2427         switch (sk)
2428           {
2429           case SR_NOTHING:   return (sRef_makeNothing ());
2430           case SR_INTERNAL:  return (sRef_makeInternalState ());
2431           case SR_SPECSTATE: return (sRef_makeSpecState ());
2432           case SR_SYSTEM:    return (sRef_makeSystemState ());
2433           case SR_GLOBALMARKER: BADBRANCH;
2434           }
2435         BADEXIT;
2436       }
2437     case '-':
2438       return sRef_undefined;
2439     case 'u':
2440       return sRef_makeUnknown ();
2441     case 'x':
2442       return sRef_makeUnknown ();
2443     default:
2444       llfatalerror (message ("sRef_undumpGlobal: bad line: %s",
2445                              cstring_fromChars (*c)));
2446     }
2447   BADEXIT;
2448 }
2449
2450 static /*@exposed@*/ sRef sRef_undumpBody (char **c)
2451 {
2452   char p = **c;
2453
2454   (*c)++;
2455
2456   switch (p)
2457     {
2458     case 'g':
2459       return (sRef_makeGlobal (usymId_fromInt (reader_getInt (c)), 
2460                                ctype_unknown, stateInfo_currentLoc ()));
2461     case 'p':
2462       return (sRef_makeParam (reader_getInt (c), ctype_unknown, 
2463                               stateInfo_makeLoc (g_currentloc, SA_DECLARED)));
2464     case 'r':
2465       return (sRef_makeResult (ctype_undump (c)));
2466     case 'a':
2467       {
2468         if ((**c >= '0' && **c <= '9') || **c == '-')
2469           {
2470             int i = reader_getInt (c);
2471             sRef arr = sRef_undump (c);
2472             sRef ret = sRef_buildArrayFetchKnown (arr, i);
2473
2474             return ret;
2475           }
2476         else
2477           {
2478             sRef arr = sRef_undump (c);
2479             sRef ret = sRef_buildArrayFetch (arr);
2480
2481             return ret;
2482           }
2483       }
2484     case 'f':
2485       {
2486         cstring fname = cstring_undefined;
2487         sRef ret;
2488
2489         while (**c != '.')
2490           {
2491             fname = cstring_appendChar (fname, **c);
2492             (*c)++;
2493           }
2494         (*c)++;
2495
2496         ret = sRef_buildField (sRef_undump (c), fname);
2497         cstring_markOwned (fname);
2498         return (ret);
2499       }
2500     case 's':
2501       {
2502         int i = reader_getInt (c);
2503         speckind sk = speckind_fromInt (i);
2504
2505         switch (sk)
2506           {
2507           case SR_NOTHING:   return (sRef_makeNothing ());
2508           case SR_INTERNAL:  return (sRef_makeInternalState ());
2509           case SR_SPECSTATE: return (sRef_makeSpecState ());
2510           case SR_SYSTEM:    return (sRef_makeSystemState ());
2511           case SR_GLOBALMARKER: BADBRANCH;
2512           }
2513         BADEXIT;
2514       }
2515     case 't':
2516       {
2517         sRef ptr = sRef_undump (c);
2518         sRef ret = sRef_makePointer (ptr);
2519
2520         return (ret);
2521       }
2522     case 'd':
2523       {
2524         sRef adr = sRef_undump (c);
2525         sRef ret = sRef_makeAddress (adr);
2526
2527         return (ret);
2528       }
2529     case 'o':
2530       {
2531         return (sRef_makeObject (ctype_undump (c)));
2532       }
2533     case 'c':
2534       {
2535         sRef s1 = sRef_undump (c);
2536         sRef s2 = ((*c)++, sRef_undump (c));
2537         sRef ret = sRef_makeConj (s1, s2);
2538
2539         return (ret);
2540       }
2541     case '-':
2542       return sRef_undefined;
2543     case 'u':
2544       return sRef_makeUnknown ();
2545     case 'x':
2546       return sRef_makeUnknown ();
2547     default:
2548       llfatalerror (message ("sRef_undump: bad line: %s", cstring_fromChars (*c)));
2549     }
2550   BADEXIT;
2551 }
2552
2553 /*@exposed@*/ sRef sRef_undump (char **c)
2554 {
2555   sRef res = sRef_undumpBody (c);
2556
2557   if (reader_optCheckChar (c, '='))
2558     {
2559       multiVal mv = multiVal_undump (c);
2560       sRef_setValue (res, mv);
2561       reader_checkChar (c, '=');
2562     }
2563
2564   return res;
2565 }
2566
2567 static /*@only@*/ cstring sRef_dumpBody (sRef s)
2568 {
2569   if (sRef_isInvalid (s))
2570     {
2571       return (cstring_makeLiteral ("-"));
2572     }
2573   else
2574     {
2575       switch (s->kind)
2576         {
2577         case SK_PARAM:
2578           return (message ("p%d", s->info->paramno));
2579         case SK_ARRAYFETCH:
2580           if (s->info->arrayfetch->indknown)
2581             {
2582               return (message ("a%d%q", s->info->arrayfetch->ind,
2583                                sRef_dump (s->info->arrayfetch->arr)));
2584             }
2585           else
2586             {
2587               return (message ("a%q", sRef_dump (s->info->arrayfetch->arr)));
2588             }
2589         case SK_FIELD:
2590           return (message ("f%s.%q", s->info->field->field, 
2591                            sRef_dump (s->info->field->rec)));
2592         case SK_PTR:
2593           return (message ("t%q", sRef_dump (s->info->ref)));
2594         case SK_ADR:
2595           return (message ("d%q", sRef_dump (s->info->ref)));
2596         case SK_OBJECT:
2597           return (message ("o%q", ctype_dump (s->info->object)));
2598         case SK_SPECIAL:
2599           return (message ("s%d", (int) s->info->spec));
2600         case SK_CONJ:
2601           return (message ("c%q.%q",
2602                            sRef_dump (s->info->conj->a),
2603                            sRef_dump (s->info->conj->b)));
2604         case SK_CVAR:
2605           if (sRef_isFileOrGlobalScope (s))
2606             {
2607               return (message ("g%d", 
2608                                usymtab_convertId (s->info->cvar->index)));
2609             }
2610           else
2611             {
2612               llcontbug (message ("Dumping local variable: %q",
2613                                   sRef_unparseDebug (s)));
2614               return (cstring_makeLiteral ("u"));
2615             }
2616         case SK_UNKNOWN:
2617           return (cstring_makeLiteral ("u"));
2618         case SK_RESULT:
2619           return (message ("r%q", ctype_dump (s->type)));
2620         case SK_TYPE:
2621         case SK_CONST:
2622         case SK_EXTERNAL:
2623         case SK_DERIVED:
2624         case SK_NEW:
2625         case SK_UNCONSTRAINED:
2626           llcontbug (message ("sRef_dump: bad kind: %q",
2627                               sRef_unparseFull (s)));
2628           return (cstring_makeLiteral ("x"));
2629         }
2630     }
2631      
2632   BADEXIT;
2633 }
2634
2635 /*@only@*/ cstring sRef_dump (sRef s)
2636 {
2637   cstring res = sRef_dumpBody (s);
2638
2639   if (sRef_hasValue (s))
2640     {
2641       res = message ("%q=%q=", res, multiVal_dump (sRef_getValue (s)));
2642     }
2643
2644   return res;
2645 }
2646
2647 cstring sRef_dumpGlobal (sRef s)
2648 {
2649   llassert (!sRef_hasValue (s));
2650
2651   if (sRef_isInvalid (s))
2652     {
2653       return (cstring_makeLiteral ("-"));
2654     }
2655   else
2656     {
2657       switch (s->kind)
2658         {
2659         case SK_CVAR:
2660           if (sRef_isFileOrGlobalScope (s))
2661             {
2662               return (message ("g%d@%d@%d", 
2663                                usymtab_convertId (s->info->cvar->index),
2664                                (int) s->defstate,
2665                                (int) sRef_getNullState (s)));
2666             }
2667           else
2668             {
2669               llcontbug (message ("Dumping local variable: %q",
2670                                   sRef_unparseDebug (s)));
2671               return (cstring_makeLiteral ("u"));
2672             }
2673         case SK_UNKNOWN:
2674           return (cstring_makeLiteral ("u"));
2675         case SK_SPECIAL:
2676           return (message ("s%d", (int) s->info->spec));
2677         default:
2678           llcontbug (message ("sRef_dumpGlobal: bad kind: %q",
2679                               sRef_unparseFull (s)));
2680           return (cstring_makeLiteral ("x"));
2681         }
2682     }
2683      
2684   BADEXIT;
2685 }
2686
2687 ctype
2688 sRef_deriveType (sRef s, uentryList cl)
2689 {
2690   if (sRef_isInvalid (s)) return ctype_unknown;
2691
2692   switch (s->kind)
2693     {
2694     case SK_CVAR:
2695       return (uentry_getType (usymtab_getRefQuiet (s->info->cvar->lexlevel, 
2696                                               s->info->cvar->index)));
2697     case SK_UNCONSTRAINED:
2698       return (ctype_unknown);
2699     case SK_PARAM:
2700       if (s->info->paramno >= 0) 
2701         {
2702           return uentry_getType (uentryList_getN (cl, s->info->paramno));
2703         }
2704       else
2705         {
2706           return ctype_unknown;
2707         }
2708     case SK_ARRAYFETCH:
2709       {
2710         ctype ca = sRef_deriveType (s->info->arrayfetch->arr, cl);
2711         
2712         if (ctype_isArray (ca))
2713           {
2714             return (ctype_baseArrayPtr (ca));
2715           }
2716         else if (ctype_isUnknown (ca))
2717           {
2718             return (ca);
2719           }
2720         else
2721           {
2722             llcontbuglit ("sRef_deriveType: inconsistent array type");
2723             return ca;
2724           }
2725       }
2726     case SK_FIELD:
2727       {
2728         ctype ct = sRef_deriveType (s->info->field->rec, cl);
2729         
2730         if (ctype_isStructorUnion (ct))
2731           {
2732             uentry ue = uentryList_lookupField (ctype_getFields (ct), 
2733                                                s->info->field->field);
2734             
2735             if (uentry_isValid (ue))
2736               {
2737                 return (uentry_getType (ue));
2738               }
2739             else
2740               {
2741                 llcontbuglit ("sRef_deriveType: bad field");
2742                 return ctype_unknown;
2743               }
2744           }
2745         else if (ctype_isUnknown (ct))
2746           {
2747             return (ct);
2748           }
2749         else
2750           {
2751             llcontbuglit ("sRef_deriveType: inconsistent field type");
2752             return (ct);
2753           }
2754       }
2755     case SK_PTR:
2756       {
2757         ctype ct = sRef_deriveType (s->info->ref, cl);
2758         
2759         if (ctype_isUnknown (ct)) return ct;
2760         if (ctype_isPointer (ct)) return (ctype_baseArrayPtr (ct));
2761         else
2762           {
2763             llcontbuglit ("sRef_deriveType: inconsistent pointer type");
2764             return (ct);
2765           }
2766       }
2767     case SK_ADR:
2768       {
2769         ctype ct = sRef_deriveType (s->info->ref, cl);
2770         
2771         if (ctype_isUnknown (ct)) return ct;
2772         return ctype_makePointer (ct);
2773       }
2774     case SK_DERIVED:
2775       {
2776         return sRef_deriveType (s->info->ref, cl);
2777       }
2778     case SK_OBJECT:
2779       {
2780         return (s->info->object);
2781       }
2782     case SK_CONJ:
2783       {
2784         return (ctype_makeConj (sRef_deriveType (s->info->conj->a, cl),
2785                                sRef_deriveType (s->info->conj->b, cl)));
2786       }
2787     case SK_RESULT:
2788     case SK_CONST:
2789     case SK_TYPE:
2790       {
2791         return (s->type);
2792       }
2793     case SK_SPECIAL:
2794     case SK_UNKNOWN:
2795     case SK_EXTERNAL:
2796     case SK_NEW:
2797       return ctype_unknown;
2798     }
2799   BADEXIT;
2800 }
2801
2802 ctype
2803 sRef_getType (sRef s)
2804 {
2805   if (sRef_isInvalid (s)) return ctype_unknown;
2806   return s->type;
2807 }
2808
2809
2810 /*@only@*/ cstring
2811 sRef_unparseOpt (sRef s)
2812 {
2813   sRef rb = sRef_getRootBase (s);
2814
2815   if (sRef_isMeaningful (rb) && !sRef_isConst (rb))
2816     {
2817       cstring ret = sRef_unparse (s);
2818       
2819       llassertprint (!cstring_equalLit (ret, "?"), ("print: %s", sRef_unparseDebug (s)));
2820
2821       if (!cstring_isEmpty (ret))
2822         {
2823           return (cstring_appendChar (ret, ' '));
2824         }
2825       else
2826         {
2827           return ret;
2828         }
2829     }
2830
2831   return cstring_undefined;
2832 }
2833
2834 cstring
2835 sRef_unparsePreOpt (sRef s)
2836 {
2837   sRef rb = sRef_getRootBase (s);
2838
2839   if (sRef_isMeaningful (rb) && !sRef_isConst (rb))
2840     {
2841       cstring ret = sRef_unparse (s);
2842       
2843       llassertprint (!cstring_equalLit (ret, "?"), ("print: %s", sRef_unparseDebug (s)));
2844       return (cstring_prependCharO (' ', ret));
2845     }
2846
2847   return cstring_undefined;
2848 }
2849
2850 /*@only@*/ cstring
2851 sRef_unparse (sRef s)
2852 {
2853   if (sRef_isInvalid (s)) return (cstring_makeLiteral ("?"));
2854
2855   if (context_inFunctionLike ())
2856     {
2857       return (sRef_unparseWithArgs (s, context_getParams ()));
2858     }
2859   else
2860     {
2861       DPRINTF (("Not in function like: %s", context_unparse ()));
2862       return (sRef_unparseNoArgs (s));
2863     }
2864 }
2865
2866 static /*@only@*/ cstring
2867 sRef_unparseWithArgs (sRef s, uentryList args)
2868 {
2869   if (sRef_isInvalid (s))
2870     {
2871       return (cstring_makeLiteral ("?"));
2872     }
2873
2874   switch (s->kind)
2875     {
2876     case SK_CVAR:
2877       return (uentry_getName (usymtab_getRefQuiet (s->info->cvar->lexlevel,
2878                                                    s->info->cvar->index)));
2879     case SK_UNCONSTRAINED:
2880       return (cstring_copy (s->info->fname));
2881     case SK_PARAM:
2882       {
2883         if (s->info->paramno < uentryList_size (args)
2884             && s->info->paramno >= 0)
2885           {
2886             uentry ue = uentryList_getN (args, s->info->paramno);
2887             
2888             if (uentry_isValid (ue))
2889               return uentry_getName (ue);
2890           }
2891
2892         return (message ("parameter %d", s->info->paramno + 1));
2893       }
2894     case SK_ARRAYFETCH:
2895       if (s->info->arrayfetch->indknown)
2896         {
2897           return (message ("%q[%d]", sRef_unparseWithArgs (s->info->arrayfetch->arr, args),
2898                                 s->info->arrayfetch->ind));
2899         }
2900       else
2901         {
2902           return (message ("%q[]", sRef_unparseWithArgs (s->info->arrayfetch->arr, args)));
2903         }
2904     case SK_FIELD:
2905       if (s->info->field->rec->kind == SK_PTR)
2906         {
2907           sRef ptr = s->info->field->rec;
2908
2909           return (message ("%q->%s", sRef_unparseWithArgs (ptr->info->ref, args),
2910                            s->info->field->field));       
2911         }
2912       return (message ("%q.%s", sRef_unparseWithArgs (s->info->field->rec, args),
2913                        s->info->field->field));
2914
2915     case SK_PTR:
2916       {
2917         sRef ref = sRef_fixConj (s->info->ref);
2918         skind sk = ref->kind;
2919         cstring ret;
2920
2921         if (sk == SK_NEW)
2922           {
2923             ret = message ("storage pointed to by %q",
2924                            sRef_unparseWithArgs (ref, args));
2925           }
2926         else if (skind_isSimple (sk) || sk == SK_PTR)
2927           {
2928             ret = message ("*%q", sRef_unparseWithArgs (ref, args));
2929           }
2930         else
2931           {
2932             ret = message ("*(%q)", sRef_unparseWithArgs (ref, args));
2933           }
2934
2935         return ret;
2936       }
2937     case SK_ADR:
2938       return (message ("&%q", sRef_unparseWithArgs (s->info->ref, args)));
2939     case SK_OBJECT:
2940       return (cstring_copy (ctype_unparse (s->info->object)));
2941     case SK_CONJ:
2942       return (sRef_unparseWithArgs (sRef_getConjA (s), args));
2943     case SK_NEW:
2944       if (cstring_isDefined (s->info->fname))
2945         {
2946           return (message ("[result of %s]", s->info->fname));
2947         }
2948       else
2949         {
2950           return (cstring_makeLiteral ("<new>"));
2951         }
2952     case SK_UNKNOWN:
2953       return (cstring_makeLiteral ("?"));
2954     case SK_DERIVED:
2955       return (message ("<derived %q>", sRef_unparse (s->info->ref)));
2956     case SK_EXTERNAL:
2957       return (message ("<external %q>", sRef_unparse (s->info->ref)));
2958     case SK_TYPE:
2959       return (message ("<type %s>", ctype_unparse (s->type)));
2960     case SK_CONST:
2961       return (message ("<const %s>", ctype_unparse (s->type)));
2962     case SK_SPECIAL:
2963       switch (s->info->spec)
2964         {
2965         case SR_NOTHING: return cstring_makeLiteral ("nothing");
2966         case SR_INTERNAL: return cstring_makeLiteral ("internal state");
2967         case SR_SPECSTATE: return cstring_makeLiteral ("spec state");
2968         case SR_SYSTEM: return cstring_makeLiteral ("file system state");
2969         case SR_GLOBALMARKER: return cstring_makeLiteral ("<global marker>");
2970         }
2971       BADBRANCH;
2972     case SK_RESULT:
2973       return cstring_makeLiteral ("result");
2974     default:
2975       {
2976         llbug (message ("Bad sref, kind = %d", (int) s->kind));
2977       }
2978     }
2979
2980   BADEXIT;
2981 }
2982
2983 /*@only@*/ cstring
2984 sRef_unparseDebug (sRef s)
2985 {
2986   if (sRef_isInvalid (s)) 
2987     {
2988       return (cstring_makeLiteral ("<undef>"));
2989     }
2990
2991
2992   switch (s->kind)
2993     {
2994     case SK_UNCONSTRAINED:
2995       return (message ("<unconstrained %s>", s->info->fname));
2996     case SK_CVAR:
2997       {
2998         uentry ce;
2999
3000         ce = usymtab_getRefQuiet (s->info->cvar->lexlevel, s->info->cvar->index);
3001
3002         if (uentry_isInvalid (ce))
3003           {
3004             return (message ("<scope: %d.%d *invalid*>", 
3005                              s->info->cvar->lexlevel,
3006                              s->info->cvar->index));
3007           }
3008         else
3009           {
3010             return (message ("<scope: %d.%d *%q*>", 
3011                              s->info->cvar->lexlevel,
3012                              s->info->cvar->index,
3013                              uentry_getName (ce)));
3014           }
3015
3016       }
3017     case SK_PARAM:
3018       {
3019         return (message ("<parameter %d>", s->info->paramno + 1));
3020       }
3021     case SK_ARRAYFETCH:
3022       if (s->info->arrayfetch->indknown)
3023         {
3024           return (message ("%q[%d]", sRef_unparseDebug (s->info->arrayfetch->arr),
3025                            s->info->arrayfetch->ind));
3026         }
3027       else
3028         {
3029           return (message ("%q[]", sRef_unparseDebug (s->info->arrayfetch->arr)));
3030         }
3031     case SK_FIELD:
3032       return (message ("%q.%s", sRef_unparseDebug (s->info->field->rec),
3033                        s->info->field->field));
3034     case SK_PTR:
3035       if (sRef_isField (s->info->ref)) 
3036         {
3037           sRef fld = s->info->ref;
3038
3039           return (message ("%q->%s", sRef_unparseDebug (fld->info->field->rec),
3040                            fld->info->field->field));
3041         }
3042       else
3043         {
3044           return (message ("*(%q)", sRef_unparseDebug (s->info->ref)));
3045         }
3046     case SK_ADR:
3047       return (message ("&%q", sRef_unparseDebug (s->info->ref)));
3048     case SK_OBJECT:
3049       return (message ("<object type %s>", ctype_unparse (s->info->object)));
3050     case SK_CONJ:
3051       return (message ("%q | %q", sRef_unparseDebug (s->info->conj->a),
3052                        sRef_unparseDebug (s->info->conj->b)));
3053     case SK_NEW:
3054       return message ("<new: %s>", s->info->fname);
3055     case SK_DERIVED:
3056       return (message ("<derived %q>", sRef_unparseDebug (s->info->ref)));
3057     case SK_EXTERNAL:
3058       return (message ("<external %q>", sRef_unparseDebug (s->info->ref)));
3059     case SK_TYPE:
3060       return (message ("<type %s>", ctype_unparse (s->type)));
3061     case SK_CONST:
3062       if (sRef_hasValue (s))
3063         {
3064           return (message ("<const %s=%q>", ctype_unparse (s->type), multiVal_unparse (sRef_getValue (s))));
3065         }
3066       else
3067         {
3068           return (message ("<const %s>", ctype_unparse (s->type)));
3069         }
3070     case SK_RESULT:
3071       return (message ("<result %s>", ctype_unparse (s->type)));
3072     case SK_SPECIAL:
3073       return (message ("<spec %s>",
3074                        cstring_makeLiteralTemp
3075                        (s->info->spec == SR_NOTHING ? "nothing"
3076                         : s->info->spec == SR_INTERNAL ? "internalState"
3077                         : s->info->spec == SR_SPECSTATE ? "spec state"
3078                         : s->info->spec == SR_SYSTEM ? "fileSystem"
3079                         : "error")));
3080     case SK_UNKNOWN:
3081       return cstring_makeLiteral ("<unknown>");
3082     }
3083
3084   BADEXIT;
3085 }
3086
3087 static /*@only@*/ cstring
3088 sRef_unparseNoArgs (sRef s)
3089 {
3090   if (sRef_isInvalid (s)) return (cstring_makeLiteral ("?"));
3091
3092   switch (s->kind)
3093     {
3094     case SK_UNCONSTRAINED:
3095       return (cstring_copy (s->info->fname));
3096     case SK_CVAR:
3097       {
3098         uentry ce = usymtab_getRefQuiet (s->info->cvar->lexlevel, 
3099                                          s->info->cvar->index);
3100
3101         if (uentry_isInvalid (ce))
3102           {
3103             llcontbug (message ("sRef_unparseNoArgs: bad cvar: %q", 
3104                                 sRef_unparseDebug (s)));
3105             return (sRef_unparseDebug (s)); 
3106           }
3107         else
3108           {
3109             return (uentry_getName (ce));
3110           }
3111       }
3112     case SK_ARRAYFETCH:
3113       if (s->info->arrayfetch->indknown)
3114         {
3115           return (message ("%q[%d]", sRef_unparseNoArgs (s->info->arrayfetch->arr),
3116                            s->info->arrayfetch->ind));
3117         }
3118       else
3119         {
3120           return (message ("%q[]", sRef_unparseNoArgs (s->info->arrayfetch->arr)));
3121         }
3122     case SK_FIELD:
3123       return (message ("%q.%s", sRef_unparseNoArgs (s->info->field->rec),
3124                        s->info->field->field));
3125     case SK_PTR:
3126       {
3127         sRef ref = sRef_fixConj (s->info->ref);
3128         skind sk = ref->kind;
3129         cstring ret;
3130
3131         if (skind_isSimple (sk) || sk == SK_PTR)
3132           {
3133             ret = message ("*%q", sRef_unparseNoArgs (ref));
3134           }
3135         else
3136           {
3137             ret = message ("*(%q)", sRef_unparseNoArgs (ref));
3138           }
3139
3140         return (ret);
3141       }
3142     case SK_ADR:
3143       return (message ("&%q", sRef_unparseNoArgs (s->info->ref)));
3144     case SK_OBJECT:
3145       return (cstring_copy (ctype_unparse (s->info->object)));
3146     case SK_CONJ:
3147       return (sRef_unparseNoArgs (s->info->conj->a));
3148     case SK_NEW:
3149       return (message ("result of %s", s->info->fname));
3150     case SK_DERIVED:
3151       return (message ("<der %q>", sRef_unparseNoArgs (s->info->ref)));
3152     case SK_EXTERNAL:
3153       return message ("<ext %q>", sRef_unparseNoArgs (s->info->ref));
3154     case SK_SPECIAL:
3155       return (cstring_makeLiteral
3156               (s->info->spec == SR_NOTHING ? "nothing"
3157                : s->info->spec == SR_INTERNAL ? "internal state"
3158                : s->info->spec == SR_SPECSTATE ? "spec state"
3159                : s->info->spec == SR_SYSTEM ? "file system state"
3160                : "<spec error>"));
3161     case SK_RESULT:
3162       return cstring_makeLiteral ("result");
3163     case SK_CONST:
3164     case SK_TYPE:
3165     case SK_UNKNOWN:
3166       return cstring_makeLiteral ("?");
3167     case SK_PARAM:
3168       /* llcontbug (message ("sRef_unparseNoArgs: bad case: %q", sRef_unparseDebug (s))); */
3169       return (sRef_unparseDebug (s));
3170     }
3171   BADEXIT;
3172 }
3173
3174 /*@dependent@*/ sRef sRef_makeUnconstrained (cstring fname)
3175 {
3176   sRef s = sRef_new ();
3177
3178   s->kind = SK_UNCONSTRAINED;
3179   s->info = (sinfo) dmalloc (sizeof (*s->info));
3180   s->info->fname = cstring_copy (fname); /* evans 2002-07-12: this was exposed, causing memory errors */
3181
3182   return (s);
3183 }
3184
3185 cstring sRef_unconstrainedName (sRef s)
3186 {
3187   llassert (sRef_isUnconstrained (s));
3188
3189   return s->info->fname;
3190 }
3191
3192 bool sRef_isUnconstrained (sRef s) 
3193 {
3194   return (sRef_isReasonable(s) && s->kind == SK_UNCONSTRAINED);
3195 }
3196
3197 static /*@dependent@*/ /*@notnull@*/ sRef 
3198   sRef_makeCvarAux (int level, usymId index, ctype ct, /*@only@*/ stateInfo stinfo)
3199 {
3200   sRef s = sRef_newRef ();
3201   
3202   s->kind = SK_CVAR;
3203   s->info = (sinfo) dmalloc (sizeof (*s->info));
3204
3205   s->info->cvar = (cref) dmalloc (sizeof (*s->info->cvar));
3206   s->info->cvar->lexlevel = level;
3207   s->info->cvar->index = index;
3208
3209   /* for now, all globals are defined; all locals, aren't */
3210
3211   if (level <= fileScope)
3212     {
3213       s->defstate = SS_UNKNOWN;
3214     }
3215   else 
3216     {
3217       ctype rct = ctype_realType (ct);
3218
3219       if (level != paramsScope
3220           && (ctype_isStructorUnion (rct) || ctype_isRealArray (rct)))
3221         {
3222           s->defstate = SS_ALLOCATED; 
3223           s->oaliaskind = s->aliaskind = AK_STACK;
3224         }
3225       else
3226         {
3227           s->defstate = SS_UNDEFINED;
3228           s->oaliaskind = s->aliaskind = AK_LOCAL;
3229         }
3230     }
3231
3232   s->type = ct;
3233
3234   llassert (level >= globScope);
3235   llassert (usymId_isValid (index));
3236
3237   DPRINTF (("Made cvar: [%p] %s", s, sRef_unparseDebug (s)));
3238   llassert (valueTable_isUndefined (s->state));
3239   s->state = context_createValueTable (s, stinfo); 
3240   return s;
3241 }
3242
3243 /*@dependent@*/ sRef sRef_makeCvar (int level, usymId index, ctype ct, /*@only@*/ stateInfo stinfo)
3244 {
3245   return (sRef_makeCvarAux (level, index, ct, stinfo));
3246 }
3247
3248 int sRef_lexLevel (sRef s)
3249 {
3250   if (sRef_isReasonable (s))
3251     {
3252       sRef conj;
3253
3254       conj = sRef_fixConj (s);
3255       s = sRef_getRootBase (conj);
3256       
3257       if (sRef_isReasonable (s) && s->kind == SK_CVAR)
3258         {
3259           return (s->info->cvar->lexlevel);
3260         }
3261     }
3262
3263   return globScope;
3264 }
3265
3266 sRef
3267 sRef_makeGlobal (usymId l, ctype ct, /*@only@*/ stateInfo stinfo)
3268 {
3269   return (sRef_makeCvar (globScope, l, ct, stinfo));
3270 }
3271
3272 void
3273 sRef_setParamNo (sRef s, int l)
3274 {
3275   llassert (sRef_isReasonable (s) && s->kind == SK_PARAM);
3276   s->info->paramno = l;
3277   llassert (l >= -1);
3278 }
3279
3280 /*@dependent@*/ sRef
3281 sRef_makeParam (int l, ctype ct, stateInfo stinfo)
3282 {
3283   sRef s = sRef_new ();
3284
3285   s->kind = SK_PARAM;
3286   s->type = ct;
3287
3288   s->info = (sinfo) dmalloc (sizeof (*s->info));
3289   s->info->paramno = l; 
3290   llassert (l >= -1);
3291   s->defstate = SS_UNKNOWN; 
3292   /* (probably defined, unless its an out parameter) */
3293
3294   llassert (valueTable_isUndefined (s->state));
3295   s->state = context_createValueTable (s, stinfo);
3296   return s;
3297 }
3298
3299 bool
3300 sRef_isIndexKnown (sRef arr)
3301 {
3302   bool res;
3303
3304   llassert (sRef_isReasonable (arr));
3305   arr = sRef_fixConj (arr);
3306   
3307   llassert (arr->kind == SK_ARRAYFETCH);  
3308   res = arr->info->arrayfetch->indknown;
3309   return (res);
3310 }
3311
3312 int
3313 sRef_getIndex (sRef arr)
3314 {
3315   int result;
3316
3317   llassert (sRef_isReasonable (arr));
3318   arr = sRef_fixConj (arr);
3319
3320   llassert (arr->kind == SK_ARRAYFETCH);  
3321
3322   if (!arr->info->arrayfetch->indknown)
3323     {
3324       llcontbug (message ("sRef_getIndex: unknown: %q", sRef_unparse (arr)));
3325       result = 0; 
3326     }
3327   else
3328     {
3329       result = arr->info->arrayfetch->ind;
3330     }
3331
3332   return result;
3333 }
3334
3335 static bool sRef_isZerothArrayFetch (/*@notnull@*/ sRef s)
3336 {
3337   return (s->kind == SK_ARRAYFETCH
3338           && s->info->arrayfetch->indknown
3339           && (s->info->arrayfetch->ind == 0));
3340 }
3341
3342 /*@exposed@*/ sRef sRef_makeAddress (/*@exposed@*/ sRef t)
3343 {
3344   
3345   if (sRef_isInvalid (t)) return sRef_undefined;
3346
3347   if (sRef_isPointer (t))
3348     {
3349       return (t->info->ref);
3350     }
3351   else if (sRef_isZerothArrayFetch (t))
3352     {
3353       return (t->info->arrayfetch->arr);
3354     }
3355   else
3356     {
3357       sRef s = sRef_newRef ();
3358       
3359       s->kind = SK_ADR;
3360       s->type = ctype_makePointer (t->type);
3361       s->info = (sinfo) dmalloc (sizeof (*s->info));
3362       s->info->ref = t; 
3363       
3364       if (t->defstate == SS_UNDEFINED) 
3365         /* no! it is allocated even still: && !ctype_isPointer (t->type)) */
3366         {
3367           s->defstate = SS_ALLOCATED;
3368         }
3369       else
3370         {
3371           s->defstate = t->defstate;
3372         }
3373
3374       if (t->aliaskind == AK_LOCAL)
3375         {
3376           if (sRef_isLocalVar (t))
3377             {
3378               s->aliaskind = AK_STACK;
3379             }
3380         }
3381
3382       llassert (valueTable_isUndefined (s->state));
3383       s->state = context_createValueTable (s, 
3384                                            stateInfo_makeLoc (g_currentloc, SA_CREATED));
3385       return s;
3386     }
3387 }
3388
3389 cstring sRef_getField (sRef s)
3390 {
3391   cstring res;
3392
3393   llassert (sRef_isReasonable (s));
3394   s = sRef_fixConj (s);
3395
3396   llassertprint (sRef_isReasonable (s) && (s->kind == SK_FIELD),
3397                  ("s = %s", sRef_unparseDebug (s)));
3398
3399   res = s->info->field->field;
3400   return (res);
3401 }
3402
3403 sRef sRef_getBase (sRef s)
3404 {
3405   sRef res;
3406
3407   if (sRef_isInvalid (s)) return (sRef_undefined);
3408
3409   s = sRef_fixConj (s);
3410
3411   switch (s->kind)
3412     {
3413     case SK_ADR:
3414     case SK_PTR:
3415     case SK_DERIVED:
3416     case SK_EXTERNAL:
3417       res = s->info->ref;
3418       break;
3419     case SK_FIELD:
3420       res = s->info->field->rec;
3421       break;
3422
3423     case SK_ARRAYFETCH:
3424       res = s->info->arrayfetch->arr;
3425       break;
3426
3427     default:
3428       res = sRef_undefined; /* shouldn't need it */
3429     }
3430
3431   return (res);
3432 }
3433
3434 /*
3435 ** same as getBase, except returns invalid
3436 ** (and doesn't use adr's)                   
3437 */
3438
3439 sRef
3440 sRef_getBaseSafe (sRef s)
3441 {
3442   sRef res;
3443
3444   if (sRef_isInvalid (s)) { return sRef_undefined; }
3445
3446   s = sRef_fixConj (s);
3447
3448   switch (s->kind)
3449     {
3450     case SK_PTR:
3451             res = s->info->ref; 
3452       break;
3453     case SK_FIELD:
3454             res = s->info->field->rec; break;
3455     case SK_ARRAYFETCH:
3456             res = s->info->arrayfetch->arr; 
3457       break;
3458     default:
3459       res = sRef_undefined; break;
3460     }
3461
3462   return res;
3463 }
3464
3465 /*@constant int MAXBASEDEPTH;@*/
3466 # define MAXBASEDEPTH 25
3467
3468 static /*@exposed@*/ sRef 
3469 sRef_getRootBaseAux (sRef s, int depth)
3470 {
3471   if (sRef_isInvalid (s)) return sRef_undefined;
3472
3473   if (depth > MAXBASEDEPTH)
3474     {
3475       llgenmsg (message 
3476                 ("Warning: reference base limit exceeded for %q. "
3477                  "This either means there is a variable with at least "
3478                  "%d indirections from this reference, or "
3479                  "there is a bug in Splint.",
3480                  sRef_unparse (s),
3481                  MAXBASEDEPTH),
3482                 g_currentloc);
3483
3484       return sRef_undefined;
3485     }
3486
3487   switch (s->kind)
3488     {
3489     case SK_ADR:
3490     case SK_PTR:
3491       return (sRef_getRootBaseAux (s->info->ref, depth + 1));
3492     case SK_FIELD:
3493       return (sRef_getRootBaseAux (s->info->field->rec, depth + 1));
3494     case SK_ARRAYFETCH:
3495       return (sRef_getRootBaseAux (s->info->arrayfetch->arr, depth + 1));
3496     case SK_CONJ:
3497       return (sRef_getRootBaseAux (sRef_fixConj (s), depth + 1));
3498     default:
3499       return s;
3500     }
3501 }
3502
3503 sRef sRef_getRootBase (sRef s)
3504 {
3505   return (sRef_getRootBaseAux (s, 0));
3506 }
3507
3508 static bool sRef_isDeep (sRef s)
3509 {
3510   if (sRef_isInvalid (s)) return FALSE;
3511   
3512   switch (s->kind)
3513     {
3514     case SK_ADR:
3515     case SK_PTR:
3516     case SK_FIELD:
3517     case SK_ARRAYFETCH:
3518       return TRUE;
3519     case SK_CONJ:
3520       return (sRef_isDeep (sRef_fixConj (s)));
3521     default:
3522       return FALSE;
3523     }
3524 }
3525
3526 static int sRef_depth (sRef s)
3527 {
3528   if (sRef_isInvalid (s)) return 0;
3529   
3530   switch (s->kind)
3531     {
3532     case SK_ADR:
3533     case SK_PTR:
3534     case SK_DERIVED:
3535     case SK_EXTERNAL:
3536       return 1 + sRef_depth (s->info->ref);
3537     case SK_FIELD:
3538       return 1 + sRef_depth (s->info->field->rec);
3539     case SK_ARRAYFETCH:
3540       return 1 + sRef_depth (s->info->arrayfetch->arr);
3541     case SK_CONJ:
3542       return (sRef_depth (sRef_fixConj (s)));
3543     default:
3544       return 1;
3545     }
3546 }
3547
3548 sRef
3549 sRef_makeObject (ctype o)
3550 {
3551   sRef s = sRef_newRef (); 
3552
3553   s->kind = SK_OBJECT;
3554   s->info = (sinfo) dmalloc (sizeof (*s->info));
3555   s->info->object = o;
3556   llassert (valueTable_isUndefined (s->state));
3557   s->state = context_createValueTable (s, stateInfo_makeLoc (g_currentloc, SA_CREATED));
3558   return s;
3559 }
3560
3561 /*
3562 ** This is used to represent storage referenced by a parameter.
3563 */
3564
3565 sRef sRef_makeExternal (sRef t)
3566 {
3567   sRef s = sRef_newRef ();
3568
3569   llassert (sRef_isReasonable (t));
3570
3571   s->kind = SK_EXTERNAL;
3572   s->info = (sinfo) dmalloc (sizeof (*s->info));
3573   s->type = t->type;
3574   s->info->ref = t;
3575   llassert (valueTable_isUndefined (s->state));
3576   s->state = context_createValueTable (s, stateInfo_makeLoc (g_currentloc, SA_DECLARED));
3577   return s;
3578 }
3579
3580 /*@dependent@*/ sRef sRef_makeDerived (/*@exposed@*/ sRef t)
3581 {
3582   if (sRef_isReasonable (t))
3583     {
3584       sRef s = sRef_newRef ();
3585       
3586       s->kind = SK_DERIVED;
3587       s->info = (sinfo) dmalloc (sizeof (*s->info));
3588       s->info->ref = t;
3589       
3590       s->type = t->type;
3591       llassert (valueTable_isUndefined (s->state));
3592       s->state = context_createValueTable (s, stateInfo_makeLoc (g_currentloc, SA_CREATED));
3593       return s;
3594     }
3595   else
3596     {
3597       return sRef_undefined;
3598     }
3599 }
3600
3601 /*
3602 ** definitely NOT symmetric:
3603 **
3604 **   res fills in unknown state information from other
3605 */
3606
3607 void
3608 sRef_mergeStateQuiet (sRef res, sRef other)
3609 {
3610   llassert (sRef_isReasonable (res));
3611   llassert (sRef_isReasonable (other));
3612
3613   res->modified = res->modified || other->modified;
3614   res->safe = res->safe && other->safe;
3615
3616   if (res->defstate == SS_UNKNOWN) 
3617     {
3618       res->defstate = other->defstate;
3619       res->definfo = stateInfo_update (res->definfo, other->definfo);
3620     }
3621
3622   if (res->aliaskind == AK_UNKNOWN || 
3623       (res->aliaskind == AK_LOCAL && alkind_isKnown (other->aliaskind)))
3624     {
3625       res->aliaskind = other->aliaskind;
3626       res->oaliaskind = other->oaliaskind;
3627       res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
3628     }
3629
3630   if (res->expkind == XO_UNKNOWN)
3631     {
3632       res->expkind = other->expkind;
3633       res->oexpkind = other->oexpkind;
3634       res->expinfo = stateInfo_update (res->expinfo, other->expinfo);
3635     }
3636   
3637   /* out takes precedence over implicitly defined */
3638   if (res->defstate == SS_DEFINED && other->defstate != SS_UNKNOWN) 
3639     {
3640       res->defstate = other->defstate;
3641       res->definfo = stateInfo_update (res->definfo, other->definfo);
3642     }
3643
3644   if (sRef_getNullState (other) == NS_ERROR || sRef_getNullState (res) == NS_ERROR) 
3645     {
3646       sRef_setNullState (res, NS_ERROR, fileloc_undefined);
3647     }
3648   else
3649     {
3650       if (sRef_getNullState (other) != NS_UNKNOWN 
3651           && (sRef_getNullState (res) == NS_UNKNOWN || sRef_getNullState (res) == NS_NOTNULL 
3652               || sRef_getNullState (res) == NS_MNOTNULL))
3653         {
3654           sRef_updateNullState (res, other);
3655         }
3656     }
3657 }
3658
3659 /*
3660 ** definitely NOT symmetric:
3661 **
3662 **   res fills in known state information from other
3663 */
3664
3665 void
3666 sRef_mergeStateQuietReverse (/*@dependent@*/ sRef res, /*@dependent@*/ sRef other)
3667 {
3668   bool changed = FALSE;
3669
3670   llassert (sRef_isReasonable (res));
3671   llassert (sRef_isReasonable (other));
3672   sRef_checkMutable (res);
3673
3674   if (res->kind != other->kind)
3675     {
3676       changed = TRUE;
3677
3678       sinfo_free (res);
3679
3680       res->kind = other->kind;
3681       res->type = other->type;
3682       res->info = sinfo_fullCopy (other);
3683     }
3684   else
3685     {
3686       if (!ctype_equal (res->type, other->type))
3687         {
3688           changed = TRUE;
3689           res->type = other->type;
3690         }
3691       
3692       sinfo_update (res, other);
3693     }
3694
3695   res->modified = res->modified || other->modified;
3696   res->safe = res->safe && other->safe;
3697
3698   if (res->aliaskind != other->aliaskind
3699       && (res->aliaskind == AK_UNKNOWN
3700           || ((res->aliaskind == AK_LOCAL 
3701                || (res->aliaskind == AK_REFCOUNTED
3702                    && other->aliaskind != AK_LOCAL))
3703               && other->aliaskind != AK_UNKNOWN)))
3704     {
3705       changed = TRUE;
3706       res->aliaskind = other->aliaskind;
3707       res->oaliaskind = other->oaliaskind;
3708       res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
3709     }
3710
3711   if (other->expkind != XO_UNKNOWN && other->expkind != res->expkind)
3712     {
3713       changed = TRUE;
3714       res->expkind = other->expkind;
3715       res->expinfo = stateInfo_update (res->expinfo, other->expinfo);
3716     }
3717
3718   if (other->oexpkind != XO_UNKNOWN)
3719     {
3720       res->oexpkind = other->oexpkind;
3721     }
3722
3723   /* out takes precedence over implicitly defined */
3724
3725   if (res->defstate != other->defstate)
3726     {
3727       if (other->defstate != SS_UNKNOWN)
3728         {
3729           res->defstate = other->defstate;
3730           res->definfo = stateInfo_update (res->definfo, other->definfo);
3731         }
3732     }
3733
3734   if (sRef_getNullState (other) == NS_ERROR || sRef_getNullState (res) == NS_ERROR)
3735     {
3736       if (sRef_getNullState (res) != NS_ERROR)
3737         {
3738           sRef_setNullStateN (res, NS_ERROR);
3739           changed = TRUE;
3740         }
3741     }
3742   else
3743     {
3744       if (sRef_getNullState (other) != NS_UNKNOWN 
3745           && sRef_getNullState (other) != sRef_getNullState (res))
3746         {
3747           changed = TRUE;
3748           sRef_updateNullState (res, other);
3749         }
3750     }
3751
3752   if (changed)
3753     {
3754       sRef_clearDerived (res); 
3755     }
3756 }
3757
3758 void 
3759 sRef_mergeState (sRef res, sRef other, clause cl, fileloc loc)
3760 {
3761   if (sRef_isReasonable (res) && sRef_isReasonable (other))
3762     {
3763       sRef_mergeStateAux (res, other, cl, FALSE, loc, TRUE);
3764     }
3765   else
3766     {
3767       if (sRef_isInvalid (res))
3768         {
3769           llbug (message ("sRef_mergeState: invalid res sRef: %q", 
3770                           sRef_unparseDebug (other)));
3771         }
3772       else 
3773         {
3774           llbug (message ("sRef_mergeState: invalid other sRef: %q", 
3775                           sRef_unparseDebug (res)));
3776         }
3777     }
3778 }
3779
3780 void 
3781 sRef_mergeOptState (sRef res, sRef other, clause cl, fileloc loc)
3782 {
3783   if (sRef_isReasonable (res) && sRef_isReasonable (other))
3784     {
3785       sRef_mergeStateAux (res, other, cl, TRUE, loc, TRUE);
3786     }
3787   else
3788     {
3789       if (sRef_isInvalid (res))
3790         {
3791           llbug (message ("sRef_mergeOptState: invalid res sRef: %q", 
3792                           sRef_unparseDebug (other)));
3793         }
3794       else 
3795         {
3796           llbug (message ("sRef_mergeOptState: invalid other sRef: %q", 
3797                           sRef_unparseDebug (res)));
3798         }
3799     }
3800 }
3801
3802 static void
3803 sRef_mergeStateAux (/*@notnull@*/ sRef res, /*@notnull@*/ sRef other, 
3804                     clause cl, bool opt, fileloc loc,
3805                     bool doDerivs)
3806    /*@modifies res@*/ 
3807 {
3808   llassertfatal (sRef_isReasonable (res));
3809   llassertfatal (sRef_isReasonable (other));
3810   
3811   DPRINTF (("Merge aux: %s / %s",
3812             sRef_unparseFull (res),
3813             sRef_unparseFull (other)));
3814
3815   sRef_checkMutable (res);
3816   sRef_checkMutable (other);
3817
3818   res->modified = res->modified || other->modified;
3819
3820   if (res->kind == other->kind 
3821       || (other->kind == SK_UNKNOWN || res->kind == SK_UNKNOWN))
3822     {
3823       sstate odef = other->defstate;
3824       sstate rdef = res->defstate;
3825       nstate onull = sRef_getNullState (other);
3826       
3827       /*
3828       ** yucky stuff to handle 
3829       **
3830       **   if (s) free (s);
3831       */
3832
3833       if (other->defstate == SS_DEAD 
3834           && ((sRef_isOnly (res) && sRef_definitelyNull (res))
3835               || (res->defstate == SS_UNDEFINED
3836                   || res->defstate == SS_UNUSEABLE)))
3837         {
3838           if (res->defstate == SS_UNDEFINED
3839               || res->defstate == SS_UNUSEABLE)
3840             {
3841               res->defstate = SS_UNUSEABLE;
3842             }
3843           else
3844             {
3845               res->defstate = SS_DEAD;
3846             }
3847
3848           res->definfo = stateInfo_update (res->definfo, other->definfo);
3849           sRef_clearDerived (other);
3850           sRef_clearDerived (res);
3851         }
3852       else if (res->defstate == SS_DEAD 
3853                && ((sRef_isOnly (other) && sRef_definitelyNull (other))
3854                    || (other->defstate == SS_UNDEFINED
3855                        || other->defstate == SS_UNUSEABLE)))
3856         {
3857           if (other->defstate == SS_UNDEFINED
3858               || other->defstate == SS_UNUSEABLE)
3859             {
3860               res->defstate = SS_UNUSEABLE;
3861             }
3862           else
3863             {
3864               res->defstate = SS_DEAD;
3865             }
3866           
3867           res->definfo = stateInfo_update (res->definfo, other->definfo);
3868           sRef_clearDerived (other);
3869           sRef_clearDerived (res);
3870         }
3871       else if (res->defstate == SS_DEFINED 
3872                && (other->defstate == SS_ALLOCATED 
3873                    && sRef_definitelyNull (other)))
3874         {
3875           other->defstate = SS_DEFINED; /* definitely null! */
3876         }
3877       else if (other->defstate == SS_DEFINED
3878                && (res->defstate == SS_ALLOCATED && sRef_definitelyNull (res)))
3879         {
3880           res->defstate = SS_DEFINED;
3881           res->definfo = stateInfo_update (res->definfo, other->definfo);
3882         }
3883       else
3884         {
3885           ; /* okay */
3886         }
3887
3888       if (res->defstate == SS_DEAD && other->defstate == SS_DEAD)
3889         {
3890           sRef_clearDerived (other);
3891           sRef_clearDerived (res);
3892         }
3893
3894       /*
3895       ** only & dead isn't really an only!
3896       */
3897
3898       if (alkind_isOnly (other->aliaskind) && other->defstate == SS_DEAD)
3899         {
3900           other->aliaskind = AK_UNKNOWN;
3901         }
3902
3903       if (alkind_isOnly (res->aliaskind) && res->defstate == SS_DEAD)
3904         {
3905           res->aliaskind = AK_UNKNOWN;
3906         }
3907
3908       /*
3909       ** Dead and dependent -> dead
3910       */
3911       
3912       if (alkind_isDependent (other->aliaskind) && res->defstate == SS_DEAD)
3913         {
3914           other->aliaskind = AK_UNKNOWN;
3915           other->defstate = SS_DEAD;
3916           sRef_clearDerived (res);
3917           sRef_clearDerived (other);
3918         }
3919       
3920       if (alkind_isDependent (res->aliaskind) && other->defstate == SS_DEAD)
3921         {
3922           res->aliaskind = AK_UNKNOWN;
3923           res->defstate = SS_DEAD;
3924           sRef_clearDerived (res);
3925           sRef_clearDerived (other);
3926         }
3927
3928       /*
3929       ** must do alias combine first, since it depends on 
3930       ** original values of state and null.
3931       */
3932
3933       sRef_combineAliasKinds (res, other, cl, loc);
3934       sRef_combineDefState (res, other);
3935       sRef_combineNullState (res, other);
3936
3937       if (rdef == SS_ALLOCATED || rdef == SS_SPECIAL)
3938         {
3939           if (odef == SS_DEFINED)
3940             {
3941               if (onull == NS_DEFNULL || onull == NS_CONSTNULL)
3942                 {
3943                   res->deriv = sRefSet_copyInto (res->deriv, other->deriv);
3944                   DPRINTF (("Copy derivs: %s", sRef_unparseFull (res)));
3945                 }                             
3946             }
3947           else if (odef == SS_ALLOCATED || odef == SS_SPECIAL)
3948             {
3949               
3950               if (doDerivs)
3951                 {
3952                   if (ctype_isUnion (ctype_realType (sRef_getType (res))))
3953                     {
3954                       res->deriv = sRef_mergeUnionDerivs (res->deriv, 
3955                                                           other->deriv, 
3956                                                           opt, cl, loc);
3957                       DPRINTF (("Copy derivs: %s", sRef_unparseFull (res)));
3958                     }
3959                   else
3960                     {
3961                       res->deriv = sRef_mergeDerivs (res->deriv, other->deriv, 
3962                                                      opt, cl, loc);
3963                       DPRINTF (("Copy derivs: %s", sRef_unparseFull (res)));
3964                     }
3965                 }
3966             }
3967           else
3968             {
3969               if (doDerivs)
3970                 {
3971                   res->deriv = sRef_mergeDerivs (res->deriv, other->deriv, 
3972                                                  opt, cl, loc);
3973                   DPRINTF (("Copy derivs: %s", sRef_unparseFull (res)));
3974                 }
3975               else
3976                 {
3977                   ;
3978                 }
3979             }
3980         }
3981       else
3982         {
3983           if (rdef == SS_PDEFINED
3984               || (rdef == SS_DEFINED && odef == SS_PDEFINED))
3985             {
3986                 if (doDerivs)
3987                     {
3988                       res->deriv = sRef_mergePdefinedDerivs (res->deriv, other->deriv, 
3989                                                              opt, cl, loc);
3990                       DPRINTF (("Copy derivs: %s", sRef_unparseFull (res)));
3991                     }
3992             }
3993           else
3994             {
3995               if ((rdef == SS_DEFINED  || rdef == SS_UNKNOWN)
3996                   && res->defstate == SS_ALLOCATED)
3997                 {
3998                   res->deriv = sRefSet_copyInto (res->deriv, other->deriv);
3999                 }
4000               else
4001                 {
4002                   if (doDerivs)
4003                     {
4004                       res->deriv = sRef_mergeDerivs (res->deriv, other->deriv, 
4005                                                      opt, cl, loc);
4006                       DPRINTF (("Copy derivs: %s", sRef_unparseFull (res)));
4007                     }
4008                 }
4009             }
4010         }
4011       
4012       
4013       sRef_combineExKinds (res, other);
4014     }
4015   else
4016     {
4017       if (res->kind == SK_ARRAYFETCH && other->kind == SK_PTR)
4018         {
4019           sRef nother = sRef_buildArrayFetchKnown (sRef_getBase (other), 0);
4020
4021           sRef_copyState (nother, other);
4022           sRef_mergeStateAux (res, nother, cl, opt, loc, doDerivs);
4023         }
4024       else if (res->kind == SK_PTR && other->kind == SK_ARRAYFETCH)
4025         {
4026           sRef nother = sRef_buildPointer (sRef_getBase (other));
4027
4028           if (sRef_isReasonable (nother))
4029             {
4030               sRef_copyState (nother, other);
4031               sRef_mergeStateAux (res, nother, cl, opt, loc, doDerivs);
4032             }
4033         }
4034       else
4035         {
4036           llcontbug (message ("merge conj: %q / %q", sRef_unparseFull (res), 
4037                               sRef_unparseFull (other)));
4038           
4039         }
4040     }
4041
4042   /* 
4043   ** Merge value table states
4044   */
4045
4046 # if 0
4047   /*
4048   ** This doesn't do anything.  And its broken too...
4049   */
4050
4051   valueTable_elements (res->state, key, sv) 
4052     {
4053       stateValue os = valueTable_lookup (other->state, key);
4054       /*@unused@*/ int val;
4055       /*@unused@*/ char *msg;
4056
4057       llassert (stateValue_isDefined (os));
4058       
4059       DPRINTF (("Merge state: %s / %s", 
4060                 cstring_toCharsSafe (stateValue_unparse (sv)), 
4061                 cstring_toCharsSafe (stateValue_unparse (os))));
4062       /*
4063         val = valueMatix_lookup (key, 
4064         stateValue_getValue (os),
4065         stateValue_getValue (sv), 
4066         &msg);
4067         DPRINTF (("Val: %d / %s", val, msg));
4068       */
4069   } end_valueTable_elements ; 
4070 # endif
4071
4072   DPRINTF (("Merge aux: %s / %s",
4073             sRef_unparseFull (res),
4074             sRef_unparseFull (other)));
4075 }
4076
4077 static sRefSet
4078 sRef_mergeUnionDerivs (/*@only@*/ sRefSet res, 
4079                        /*@exposed@*/ sRefSet other, bool opt,
4080                        clause cl, fileloc loc)
4081 {
4082   if (sRefSet_isEmpty (res))
4083     {
4084       return sRefSet_copyInto (res, other);
4085     }
4086   else
4087     {
4088       sRefSet_allElements (other, el)
4089         {
4090           if (sRef_isReasonable (el))
4091             {
4092               sRef e2 = sRefSet_lookupMember (other, el);
4093               
4094               if (sRef_isReasonable (e2))
4095                 {
4096                   sRef_mergeStateAux (el, e2, cl, opt, loc, FALSE);
4097                 }
4098               else
4099                 {
4100                   res = sRefSet_insert (res, el);
4101                 }
4102             }
4103         } end_sRefSet_allElements ;
4104
4105       return res;
4106     }
4107 }
4108
4109 static /*@only@*/ sRefSet
4110 sRef_mergeDerivs (/*@only@*/ sRefSet res, sRefSet other, 
4111                   bool opt, clause cl, fileloc loc)
4112 {
4113   sRefSet ret = sRefSet_new ();
4114
4115   sRefSet_allElements (res, el)
4116     {
4117       if (sRef_isReasonable (el))
4118         {
4119           sRef e2 = sRefSet_lookupMember (other, el);
4120
4121           if (sRef_isReasonable (e2))
4122             {
4123               if (el->defstate == SS_ALLOCATED &&
4124                   e2->defstate == SS_PDEFINED)
4125                 {
4126                   e2->defstate = SS_ALLOCATED;
4127                 }
4128               else if (e2->defstate == SS_ALLOCATED &&
4129                        el->defstate == SS_PDEFINED)
4130                 {
4131                   el->defstate = SS_ALLOCATED;
4132                   el->definfo = stateInfo_update (el->definfo, e2->definfo);
4133                   sRef_clearDerived (el);
4134                 }
4135               else if ((el->defstate == SS_DEAD || sRef_isKept (el)) &&
4136                        (e2->defstate == SS_DEFINED && !sRef_isKept (e2)))
4137                 {
4138                   DPRINTF (("Checking dead: %s / %s", sRef_unparseFull (el),
4139                             sRef_unparseFull (e2)));
4140
4141                   if (checkDeadState (el, e2, TRUE, loc))
4142                     {
4143                       if (sRef_isThroughArrayFetch (el))
4144                         {
4145                           sRef_maybeKill (el, loc);
4146                           sRef_maybeKill (e2, loc);
4147                         }
4148                     }
4149                 }
4150               else if ((e2->defstate == SS_DEAD || sRef_isKept (e2)) &&
4151                        (el->defstate == SS_DEFINED && !sRef_isKept (el)))
4152                 {
4153                   DPRINTF (("Checking dead: %s / %s", sRef_unparseFull (el),
4154                             sRef_unparseFull (e2)));
4155
4156                   if (checkDeadState (e2, el, FALSE, loc))
4157                     {
4158                       if (sRef_isThroughArrayFetch (el))
4159                         {
4160                           sRef_maybeKill (el, loc);
4161                           sRef_maybeKill (e2, loc);
4162                         }
4163                     }
4164                 }
4165               else if (el->defstate == SS_DEFINED &&
4166                        e2->defstate == SS_PDEFINED)
4167                 {
4168                   DPRINTF (("set pdefined: %s", sRef_unparseFull (el)));
4169                   el->defstate = SS_PDEFINED;
4170                   el->definfo = stateInfo_update (el->definfo, e2->definfo);
4171                 }
4172               else if (e2->defstate == SS_DEFINED &&
4173                        el->defstate == SS_PDEFINED)
4174                 {
4175                   DPRINTF (("set pdefined: %s", sRef_unparseFull (e2)));
4176                   e2->defstate = SS_PDEFINED;
4177                   e2->definfo = stateInfo_update (e2->definfo, el->definfo);
4178                 }
4179               else
4180                 {
4181                   ; /* okay */
4182                 }
4183
4184               if (ctype_isUnion (ctype_realType (sRef_getType (el))))
4185                 {
4186                   el->deriv = sRef_mergeUnionDerivs (el->deriv, e2->deriv, 
4187                                                      opt, cl, loc); 
4188                 }
4189               else
4190                 {
4191                   el->deriv = sRef_mergeDerivs (el->deriv, e2->deriv, opt, cl, loc); 
4192                 }
4193               
4194               if (sRef_equivalent (el, e2))
4195                 {
4196                   ret = sRefSet_insert (ret, el);
4197                 }
4198               else
4199                 {
4200                   sRef sr = sRef_leastCommon (el, e2);
4201
4202                   if (sRef_isReasonable (sr))
4203                     {
4204                       ret = sRefSet_insert (ret, sr);
4205                     }
4206                   else
4207                     {
4208                       ;
4209                     }
4210                 }
4211               
4212               (void) sRefSet_delete (other, e2);
4213             }
4214           else /* not defined */
4215             {
4216               DPRINTF (("Checking dead: %s", sRef_unparseFull (el)));
4217               (void) checkDeadState (el, e2, TRUE, loc);
4218             }
4219         }
4220     } end_sRefSet_allElements;
4221
4222   sRefSet_allElements (other, el)
4223     {
4224       if (sRef_isReasonable (el))
4225         {
4226           DPRINTF (("Checking dead: %s", sRef_unparseFull (el)));
4227           (void) checkDeadState (el, sRef_undefined, FALSE, loc);
4228         }
4229     } end_sRefSet_allElements;
4230     
4231   sRefSet_free (res); 
4232   return (ret);
4233 }
4234
4235 /*
4236 ** Returns TRUE is there is an error.
4237 */
4238
4239 static bool checkDeadState (/*@notnull@*/ sRef el, sRef e2, bool tbranch, fileloc loc)
4240 {
4241   /*
4242   ** usymtab_isGuarded --- the utab should still be in the
4243   ** state of the alternate branch.
4244   **
4245   ** tbranch TRUE means el is released in the last branch, e.g.
4246   **     if (x != NULL) { ; } else { sfree (x); }
4247   ** so, if x is null in the other branch no error is reported.
4248   **
4249   ** tbranch FALSE means this is the other branch:
4250   **     if (x != NULL) { sfree (x); } else { ; }
4251   ** so, if x is null in this branch there is no error.
4252   */
4253
4254   
4255   if ((sRef_isDead (el) || sRef_isKept (el))
4256       && !sRef_isDeepUnionField (el) 
4257       && !sRef_isThroughArrayFetch (el))
4258     {
4259        
4260       if (!tbranch)
4261         {
4262           if (usymtab_isDefinitelyNullDeep (el))
4263             {
4264               return TRUE;
4265             }
4266         }
4267       else
4268         {
4269           if (usymtab_isAltDefinitelyNullDeep (el))
4270             {
4271               return TRUE;
4272             }
4273         }
4274       
4275       if (optgenerror
4276           (FLG_BRANCHSTATE,
4277            message ("Storage %q is %q in one path, but live in another.",
4278                     sRef_unparse (el),
4279                     cstring_makeLiteral (sRef_isKept (el) 
4280                                          ? "kept" : "released")),
4281            loc))
4282         {
4283           if (sRef_isKept (el))
4284             {
4285               sRef_showAliasInfo (el);      
4286             }
4287           else
4288             {
4289               sRef_showStateInfo (el);
4290             }
4291
4292           if (sRef_isValid (e2))
4293             {
4294               if (sRef_isKept (e2))
4295                 {
4296                   sRef_showAliasInfo (e2);      
4297                 }
4298               else
4299                 {
4300                   sRef_showStateInfo (e2);
4301                 }
4302             }
4303
4304           /* prevent further errors */
4305           el->defstate = SS_UNKNOWN; 
4306           sRef_setAliasKind (el, AK_ERROR, fileloc_undefined);    
4307           return FALSE;
4308         }
4309     }
4310
4311   return TRUE;
4312 }
4313
4314 static void 
4315 checkDerivDeadState (/*@notnull@*/ sRef el, bool tbranch, fileloc loc)
4316 {
4317   if (checkDeadState (el, sRef_undefined, tbranch, loc))
4318     {
4319       sRefSet_allElements (el->deriv, t)
4320         {
4321           if (sRef_isReasonable (t))
4322             {
4323               checkDerivDeadState (t, tbranch, loc);
4324             }
4325         } end_sRefSet_allElements;
4326     }
4327 }
4328
4329 static sRefSet
4330   sRef_mergePdefinedDerivs (sRefSet res, sRefSet other, bool opt, 
4331                             clause cl, fileloc loc)
4332 {
4333   sRefSet ret = sRefSet_new ();
4334
4335   sRefSet_allElements (res, el)
4336     {
4337       if (sRef_isReasonable (el))
4338         {
4339           sRef e2 = sRefSet_lookupMember (other, el);
4340           
4341           if (sRef_isReasonable (e2))
4342             {
4343               if (sRef_isAllocated (el) && !sRef_isAllocated (e2))
4344                 {
4345                   ;
4346                 }
4347               else if (sRef_isAllocated (e2) && !sRef_isAllocated (el))
4348                 {
4349                   el->deriv = sRefSet_copyInto (el->deriv, e2->deriv); 
4350                 }
4351               else
4352                 {
4353                   el->deriv = sRef_mergePdefinedDerivs (el->deriv, e2->deriv, 
4354                                                         opt, cl, loc);
4355                 }
4356
4357               sRef_mergeStateAux (el, e2, cl, opt, loc, FALSE);
4358               
4359               ret = sRefSet_insert (ret, el);
4360               (void) sRefSet_delete (other, e2);
4361             }
4362           else
4363             {
4364               if (!opt)
4365                 {
4366                   checkDerivDeadState (el, (cl == FALSECLAUSE), loc);
4367                 }
4368
4369               ret = sRefSet_insert (ret, el);
4370             }
4371         }
4372     } end_sRefSet_allElements;
4373   
4374   sRefSet_allElements (other, el)
4375     {
4376       if (sRef_isReasonable (el))
4377         {
4378           if (!sRefSet_member (ret, el))
4379             {
4380                               /* was cl == FALSECLAUSE */
4381               checkDerivDeadState (el, FALSE, loc);
4382               ret = sRefSet_insert (ret, el);
4383             }
4384           else
4385             {
4386               /*
4387               ** it's okay --- member is a different equality test 
4388               */
4389             }
4390         }
4391     } end_sRefSet_allElements;
4392
4393   sRefSet_free (res);
4394   return (ret);
4395 }
4396
4397 sRef sRef_makeConj (/*@exposed@*/ /*@returned@*/ sRef a, /*@exposed@*/ sRef b)
4398 {
4399   llassert (sRef_isReasonable (a));
4400   llassert (sRef_isReasonable (b));
4401       
4402   if (!sRef_equivalent (a, b))
4403     {
4404       sRef s = sRef_newRef ();
4405       
4406       s->kind = SK_CONJ;
4407       s->info = (sinfo) dmalloc (sizeof (*s->info));
4408       s->info->conj = (cjinfo) dmalloc (sizeof (*s->info->conj));
4409       s->info->conj->a = a;
4410       s->info->conj->b = b;
4411       
4412       if (ctype_equal (a->type, b->type)) s->type = a->type;
4413       else s->type = ctype_makeConj (a->type, b->type);
4414       
4415       if (a->defstate == b->defstate)
4416         {
4417           s->defstate = a->defstate;
4418           s->definfo = stateInfo_update (s->definfo, a->definfo);
4419           s->definfo = stateInfo_update (s->definfo, b->definfo);
4420         }
4421       else
4422         {
4423           s->defstate = SS_UNKNOWN; 
4424         }
4425       
4426       sRef_setNullStateN (s, NS_UNKNOWN);
4427       
4428       s->safe = a->safe && b->safe;
4429       s->aliaskind = alkind_resolve (a->aliaskind, b->aliaskind);
4430
4431       llassert (valueTable_isUndefined (s->state));
4432       s->state = context_createValueTable (s, stateInfo_makeLoc (g_currentloc, SA_MERGED));
4433       return s;
4434     }
4435   else
4436     {
4437       /*@-exposetrans@*/ return a; /*@=exposetrans@*/
4438     }
4439 }
4440
4441 /*@dependent@*/ sRef
4442 sRef_makeUnknown ()
4443 {
4444   sRef s = sRef_new ();
4445
4446   s->kind = SK_UNKNOWN;
4447   return s;
4448 }
4449
4450 static /*@owned@*/ /*@notnull@*/ sRef
4451 sRef_makeSpecial (speckind sk) /*@*/
4452 {
4453   sRef s = sRef_new ();
4454
4455   s->kind = SK_SPECIAL;
4456   s->info = (sinfo) dmalloc (sizeof (*s->info));
4457   s->info->spec = sk;
4458   /*@-dependenttrans@*/
4459   return s;
4460   /*@=dependenttrans@*/
4461 }
4462
4463 static /*@owned@*/ sRef srnothing = sRef_undefined;
4464 static /*@owned@*/ sRef srinternal = sRef_undefined;
4465 static /*@owned@*/ sRef srsystem = sRef_undefined;
4466 static /*@owned@*/ sRef srspec = sRef_undefined;
4467
4468 /*@dependent@*/ sRef
4469 sRef_makeNothing (void)
4470 {
4471   if (sRef_isInvalid (srnothing))
4472     {
4473       srnothing = sRef_makeSpecial (SR_NOTHING);
4474     }
4475
4476   return srnothing;
4477 }
4478
4479 sRef
4480 sRef_makeInternalState (void)
4481 {
4482   if (sRef_isInvalid (srinternal))
4483     {
4484       srinternal = sRef_makeSpecial (SR_INTERNAL);
4485     }
4486
4487   return srinternal;
4488 }
4489
4490 sRef
4491 sRef_makeSpecState (void)
4492 {
4493   if (sRef_isInvalid (srspec))
4494     {
4495       srspec = sRef_makeSpecial (SR_SPECSTATE);
4496     }
4497
4498   return srspec;
4499 }
4500
4501 sRef
4502 sRef_makeSystemState (void)
4503 {
4504   if (sRef_isInvalid (srsystem))
4505     {
4506       srsystem = sRef_makeSpecial (SR_SYSTEM);
4507     }
4508
4509   return srsystem;
4510 }
4511
4512 sRef
4513 sRef_makeGlobalMarker (void)
4514 {
4515   sRef s = sRef_makeSpecial (SR_GLOBALMARKER);
4516   llassert (valueTable_isUndefined (s->state));
4517   s->state = context_createGlobalMarkerValueTable (stateInfo_undefined);
4518   return s;
4519 }
4520
4521 sRef
4522 sRef_makeResult (ctype c)
4523 {
4524   sRef s = sRef_newRef ();
4525   
4526   s->kind = SK_RESULT;
4527   s->type = c;
4528   s->defstate = SS_UNKNOWN; 
4529   s->aliaskind = AK_UNKNOWN;
4530   sRef_setNullStateN (s, NS_UNKNOWN);
4531   llassert (valueTable_isUndefined (s->state));
4532   s->state = context_createValueTable (s, stateInfo_makeLoc (g_currentloc, SA_DECLARED));
4533
4534   DPRINTF (("Result: [%p] %s", s, sRef_unparseFull (s)));
4535   return s;
4536 }
4537
4538
4539 bool
4540 sRef_isNothing (sRef s)
4541 {
4542   return (sRef_isKindSpecial (s) && s->info->spec == SR_NOTHING);
4543 }
4544
4545 bool
4546 sRef_isInternalState (sRef s)
4547 {
4548   return (sRef_isKindSpecial (s) && s->info->spec == SR_INTERNAL);
4549 }
4550
4551 bool
4552 sRef_isSpecInternalState (sRef s)
4553 {
4554   return (sRef_isKindSpecial (s) 
4555           && (s->info->spec == SR_INTERNAL || s->info->spec == SR_SPECSTATE));
4556 }
4557
4558 bool
4559 sRef_isSpecState (sRef s)
4560 {
4561   return (sRef_isKindSpecial (s) && s->info->spec == SR_SPECSTATE);
4562 }
4563
4564 bool
4565 sRef_isResult (sRef s)
4566 {
4567   return (sRef_isReasonable (s) && s->kind == SK_RESULT);
4568 }
4569
4570 bool
4571 sRef_isSystemState (sRef s)
4572 {
4573   return (sRef_isKindSpecial (s) && s->info->spec == SR_SYSTEM);
4574 }
4575
4576 bool
4577 sRef_isGlobalMarker (sRef s)
4578 {
4579   return (sRef_isKindSpecial (s) && s->info->spec == SR_GLOBALMARKER);
4580 }
4581
4582 usymId
4583 sRef_getScopeIndex (sRef s)
4584 {
4585   llassert (sRef_isReasonable (s));
4586   llassert (sRef_isCvar (s));
4587
4588   return (s->info->cvar->index);
4589 }
4590
4591 void
4592 sRef_makeSafe (sRef s)
4593 {
4594   if (sRef_isReasonable (s)) 
4595     {
4596       s->safe = TRUE;
4597     }
4598 }
4599
4600 void
4601 sRef_makeUnsafe (sRef s)
4602 {
4603   if (sRef_isReasonable (s)) 
4604     {
4605       s->safe = FALSE;
4606     }
4607 }
4608
4609 /*
4610 ** memory state operations
4611 */
4612
4613 /*@only@*/ cstring sRef_unparseFull (sRef s)
4614 {
4615   if (sRef_isInvalid (s)) return (cstring_undefined);
4616
4617   return (message ("[%p] %q - %q { %q } [%s] { %q } < %q >", 
4618                    s,
4619                    sRef_unparseDebug (s), 
4620                    sRef_unparseState (s),
4621                    stateInfo_unparse (s->definfo),
4622                    exkind_unparse (s->oexpkind),
4623                    sRefSet_unparseDebug (s->deriv),
4624                    valueTable_unparse (s->state)));
4625 }
4626
4627 /*@unused@*/ cstring sRef_unparseDeep (sRef s)
4628 {
4629   cstring st = cstring_undefined;
4630
4631   st = message ("%q:", sRef_unparseFull (s));
4632
4633   if (sRef_isReasonable (s))
4634     {
4635       sRefSet_allElements (s->deriv, el)
4636         {
4637           st = message("%q\n%q", st, sRef_unparseDeep (el));
4638         } end_sRefSet_allElements ;
4639     }
4640
4641   return st;
4642 }
4643
4644 /*@only@*/ cstring sRef_unparseState (sRef s)
4645 {
4646   if (sRef_isConj (s))
4647     {
4648       return (message ("%q | %q", 
4649                        sRef_unparseState (s->info->conj->a),
4650                        sRef_unparseState (s->info->conj->b)));
4651     }
4652
4653   if (sRef_isInvalid (s))
4654     {
4655       return (cstring_makeLiteral ("<invalid>"));
4656     }
4657
4658   return (message ("%s.%s.%s.%s", 
4659                    alkind_unparse (s->aliaskind), 
4660                    nstate_unparse (sRef_getNullState (s)),
4661                    exkind_unparse (s->expkind),
4662                    sstate_unparse (s->defstate)));
4663 }
4664
4665 bool sRef_isNotUndefined (sRef s)
4666 {
4667   return (sRef_isInvalid (s)
4668           || (s->defstate != SS_UNDEFINED
4669               && s->defstate != SS_UNUSEABLE
4670               && s->defstate != SS_DEAD));
4671 }
4672
4673 ynm sRef_isWriteable (sRef s)
4674 {
4675   if (sRef_isInvalid (s)) return MAYBE;
4676
4677   if (sRef_isConj (s) && s->defstate == SS_UNKNOWN)
4678     {
4679       if (ynm_toBoolStrict (sRef_isWriteable (sRef_getConjA (s))))
4680         {
4681           if (ynm_toBoolStrict (sRef_isWriteable (sRef_getConjB (s))))
4682             {
4683               return YES;
4684             }
4685           return MAYBE;
4686         }
4687       else
4688         {
4689           if (ynm_toBoolStrict (sRef_isWriteable (sRef_getConjB (s))))
4690             {
4691               return MAYBE;
4692             }
4693           return NO;
4694         }
4695     }
4696
4697   return (ynm_fromBool (s->defstate != SS_UNUSEABLE));
4698 }
4699
4700 bool sRef_hasNoStorage (sRef s)
4701 {
4702   return (!sRef_isAllocatedStorage (s) || sRef_isDefinitelyNull (s));
4703 }
4704
4705 bool sRef_isStrictReadable (sRef s)
4706 {
4707   return (ynm_toBoolStrict (sRef_isValidLvalue (s)));
4708 }
4709
4710 /*
4711 ** Is this what is does?
4712 ** Returns YES if s can be used as an rvalue,
4713 **         MAYBE if its not clear
4714 **         NO if s cannot be safely used as an rvalue.
4715 */
4716
4717 ynm sRef_isValidLvalue (sRef s)
4718 {
4719   sstate ss;
4720
4721   if (sRef_isInvalid (s)) return YES;
4722
4723   ss = s->defstate;
4724   
4725   if (sRef_isConj (s) && s->defstate == SS_UNKNOWN)
4726     {
4727       if (ynm_toBoolStrict (sRef_isValidLvalue (sRef_getConjA (s))))
4728         {
4729           if (ynm_toBoolStrict (sRef_isValidLvalue (sRef_getConjB (s))))
4730             {
4731               return YES;
4732             }
4733           return MAYBE;
4734         }
4735       else
4736         {
4737           if (ynm_toBoolStrict (sRef_isValidLvalue (sRef_getConjB (s))))
4738             {
4739               return MAYBE;
4740             }
4741           return NO;
4742         }
4743     }
4744   else if (ss == SS_HOFFA)
4745     {
4746       if (context_getFlag (FLG_STRICTUSERELEASED))
4747         {
4748           return MAYBE;
4749         }
4750       else
4751         {
4752           return YES;
4753         }
4754     }
4755   else
4756     {
4757       return (ynm_fromBool (ss == SS_DEFINED 
4758                             || ss == SS_FIXED 
4759                             || ss == SS_RELDEF 
4760                             || ss == SS_PDEFINED 
4761                             || ss == SS_PARTIAL 
4762                             || ss == SS_SPECIAL
4763                             || ss == SS_ALLOCATED 
4764                             || ss == SS_KILLED /* evans 2001-05-26: added this for killed globals */
4765                             || ss == SS_UNKNOWN));
4766     }
4767 }
4768
4769 static /*@exposed@*/ sRef whatUndefined (/*@exposed@*/ sRef fref, int depth)
4770 {
4771   ctype ct;
4772
4773   
4774   if (depth > MAXDEPTH)
4775     {
4776       llgenmsg (message 
4777                 ("Warning: check definition limit exceeded, checking %q. "
4778                  "This either means there is a variable with at least "
4779                  "%d indirections apparent in the program text, or "
4780                  "there is a bug in Splint.",
4781                  sRef_unparse (fref),
4782                  MAXDEPTH),
4783                 g_currentloc);
4784
4785       return sRef_undefined;
4786     }
4787
4788   if (!sRef_isKnown (fref) || sRef_isAnyDefined (fref))
4789     {
4790       return sRef_undefined;
4791     }
4792
4793   if (sRef_isUnuseable (fref) || sRef_isStateUndefined (fref))
4794     {
4795       return fref;
4796     }
4797
4798   ct = ctype_realType (sRef_getType (fref));
4799   
4800   if (ctype_isUnknown (ct))
4801     {
4802       return sRef_undefined;
4803     }
4804   else if (ctype_isPointer (ct) || ctype_isArray (ct))
4805     {
4806       if (sRef_isStateUnknown (fref))
4807         {
4808           return sRef_undefined;
4809         }
4810       else
4811         {
4812           sRef fptr = sRef_constructDeref (fref);
4813
4814           return (whatUndefined (fptr, depth + 1));
4815         }
4816     }
4817   else if (ctype_isStruct (ct))
4818     {
4819       bool hasOneDefined = FALSE;
4820       
4821       if (sRef_isStateUnknown (fref))
4822         {
4823           return fref;
4824         }
4825           
4826       if (sRef_isPdefined (fref) || sRef_isAnyDefined (fref))
4827         {
4828           sRefSet_realElements (sRef_derivedFields (fref), sr)
4829             {
4830               hasOneDefined = TRUE;
4831               
4832               if (sRef_isField (sr))
4833                 {
4834                   cstring fieldname = sRef_getField (sr);
4835                   sRef fldref = sRef_makeField (fref, fieldname);
4836                   bool shouldCheck = !sRef_isRecursiveField (fldref);
4837                   
4838                   if (shouldCheck)
4839                     {
4840                       sRef wdef = whatUndefined (fldref, depth + 1);
4841
4842                       if (sRef_isReasonable (wdef))
4843                         {
4844                           return wdef;
4845                         }
4846                     }
4847                 }
4848             } end_sRefSet_realElements;
4849         }
4850       else if (sRef_isAllocated (fref))
4851         {
4852           /*
4853           ** for structures, each field must be completely defined
4854           */
4855           
4856           uentryList fields = ctype_getFields (ct);
4857               
4858           uentryList_elements (fields, ue)
4859             {
4860               cstring name = uentry_getRealName (ue);
4861               sRef ffield = sRef_makeField (fref, name);
4862               bool shouldCheck = !sRef_isRecursiveField (ffield);
4863
4864               if (sRef_isRelDef (uentry_getSref (ue)))
4865                 {
4866                   ; /* no error */
4867                 }
4868               else
4869                 {
4870                   if (shouldCheck)
4871                     {
4872                       sRef wdef = whatUndefined (ffield, depth + 1);
4873
4874                       if (sRef_isInvalid (wdef))
4875                         {
4876                           return wdef;
4877                         }
4878                     }
4879                 }
4880             } end_uentryList_elements;
4881         }
4882       else
4883         {
4884           ;
4885         }
4886     }
4887   else if (ctype_isUnion (ct))
4888     {
4889       ; 
4890     }
4891   else
4892     {
4893       ;
4894     }
4895
4896   return sRef_undefined;
4897 }
4898
4899 static bool checkDefined (/*@temp@*/ sRef sr)
4900 {
4901   /*@-temptrans@*/ /* the result from whatUndefined is lost */
4902   return (sRef_isInvalid (whatUndefined (sr, 0)));
4903   /*@=temptrans@*/ 
4904 }
4905
4906 bool sRef_isReallyDefined (sRef s)
4907 {
4908   if (sRef_isReasonable (s))
4909     {
4910       if (sRef_isAnyDefined (s))
4911         {
4912           return TRUE;
4913         }
4914       else
4915         {
4916           if (sRef_isAllocated (s) || sRef_isPdefined (s))
4917             {
4918               return checkDefined (s);
4919             }
4920           else
4921             {
4922               return FALSE;
4923             }
4924         }
4925     }
4926   else
4927     {
4928       return TRUE;
4929     }
4930 }
4931
4932 void sRef_showNotReallyDefined (sRef s)
4933 {
4934   if (sRef_isReasonable (s))
4935     {
4936       if (sRef_isAnyDefined (s))
4937         {
4938           BADBRANCH;
4939         }
4940       else
4941         {
4942           if (sRef_isAllocated (s) || sRef_isPdefined (s))
4943             {
4944               /*@-temptrans@*/ /* the result of whatUndefined is lost */
4945               sRef ref = whatUndefined (s, 0);
4946
4947               llassert (sRef_isReasonable (ref));
4948
4949               if (ref != s)
4950                 {
4951                   llgenindentmsgnoloc
4952                     (message ("This sub-reference is %s: %q",
4953                               sstate_unparse (sRef_getDefState (ref)),
4954                               sRef_unparse (ref)));
4955                 }
4956             }
4957           else
4958             {
4959               ;
4960             }
4961         }
4962     }
4963   else
4964     {
4965       BADBRANCH;
4966     }
4967 }
4968
4969 sstate sRef_getDefState (sRef s)
4970 {
4971   if (sRef_isInvalid (s)) return (SS_UNKNOWN);
4972   return (s->defstate);
4973 }
4974
4975 void sRef_setDefState (sRef s, sstate defstate, fileloc loc)
4976 {
4977   sRef_checkMutable (s);  
4978   sRef_setStateAux (s, defstate, loc);
4979 }
4980
4981 static void sRef_clearAliasStateAux (sRef s, fileloc loc)
4982 {
4983   sRef_checkMutable (s);  
4984   sRef_setAliasKind (s, AK_ERROR, loc);
4985 }
4986
4987 void sRef_clearAliasState (sRef s, fileloc loc)
4988 {
4989   sRef_checkMutable (s);  
4990   sRef_aliasSetComplete (sRef_clearAliasStateAux, s, loc);
4991 }
4992
4993 void sRef_setAliasKindComplete (sRef s, alkind kind, fileloc loc)
4994 {
4995   sRef_checkMutable (s);  
4996   sRef_aliasSetCompleteAlkParam (sRef_setAliasKind, s, kind, loc); 
4997 }
4998
4999 void sRef_setAliasKind (sRef s, alkind kind, fileloc loc)
5000 {
5001   sRef_checkMutable (s);  
5002
5003   if (sRef_isReasonable (s))
5004     {
5005       sRef_clearDerived (s);
5006
5007       if ((kind != s->aliaskind && kind != s->oaliaskind)
5008           && fileloc_isDefined (loc))
5009         {
5010           s->aliasinfo = stateInfo_updateLoc (s->aliasinfo, stateAction_fromAlkind (kind), loc);
5011         }
5012       
5013       s->aliaskind = kind;
5014     }
5015 }
5016
5017 void sRef_setOrigAliasKind (sRef s, alkind kind)
5018 {
5019   sRef_checkMutable (s);  
5020
5021   if (sRef_isReasonable (s))
5022     {
5023       s->oaliaskind = kind;
5024     }
5025 }
5026
5027 exkind sRef_getExKind (sRef s)
5028 {
5029   if (sRef_isReasonable (s))
5030     {
5031       return (s->expkind);
5032     }
5033   else
5034     {
5035       return XO_UNKNOWN;
5036     }
5037 }
5038
5039 exkind sRef_getOrigExKind (sRef s)
5040 {
5041   if (sRef_isReasonable (s))
5042     {
5043       return (s->oexpkind);
5044     }
5045   else
5046     {
5047       return XO_UNKNOWN;
5048     }
5049 }
5050
5051 static void sRef_clearExKindAux (sRef s, fileloc loc)
5052 {
5053   sRef_checkMutable (s);  
5054   sRef_setExKind (s, XO_UNKNOWN, loc);
5055 }
5056
5057 void sRef_setObserver (sRef s, fileloc loc) 
5058 {
5059   sRef_checkMutable (s);  
5060   sRef_setExKind (s, XO_OBSERVER, loc);
5061 }
5062
5063 void sRef_setExposed (sRef s, fileloc loc) 
5064 {
5065   sRef_checkMutable (s);  
5066   sRef_setExKind (s, XO_EXPOSED, loc);
5067 }
5068
5069 void sRef_clearExKindComplete (sRef s, fileloc loc)
5070 {
5071   (void) sRef_aliasSetComplete (sRef_clearExKindAux, s, loc);
5072 }
5073
5074 void sRef_setExKind (sRef s, exkind exp, fileloc loc)
5075 {
5076   sRef_checkMutable (s);
5077
5078   if (sRef_isReasonable (s))
5079     {
5080       if (s->expkind != exp)
5081         {
5082           s->expinfo = stateInfo_updateLoc (s->expinfo, stateAction_fromExkind (exp), loc);
5083         }
5084       
5085       s->expkind = exp;
5086     }
5087 }
5088
5089 /*
5090 ** s1->derived = s2->derived
5091 */
5092
5093 static void sRef_copyRealDerived (sRef s1, sRef s2)
5094 {
5095   DPRINTF (("Copy real: %s / %s", sRef_unparse (s1), sRef_unparse (s2)));
5096   sRef_checkMutable (s1);
5097
5098   if (sRef_isReasonable (s1) && sRef_isReasonable (s2))
5099     {
5100       sRef sb = sRef_getRootBase (s1);
5101
5102       sRefSet_clear (s1->deriv);
5103
5104       sRefSet_allElements (s2->deriv, el)
5105         {
5106           if (sRef_isReasonable (el))
5107             {
5108               sRef rb = sRef_getRootBase (el);
5109               
5110               if (!sRef_same (rb, sb))
5111                 {
5112                   sRef fb = sRef_fixDirectBase (el, s1);
5113                   
5114                   if (sRef_isReasonable (fb))
5115                     {
5116                       sRef_copyRealDerived (fb, el);
5117                       sRef_addDeriv (s1, fb);
5118                     }
5119                 }
5120               else
5121                 {
5122                   sRef_addDeriv (s1, el);
5123                 }
5124             }
5125         } end_sRefSet_allElements ;
5126     }
5127   
5128   }
5129
5130 void sRef_copyRealDerivedComplete (sRef s1, sRef s2)
5131 {
5132   sRef_innerAliasSetCompleteParam (sRef_copyRealDerived, s1, s2);
5133 }
5134
5135 void sRef_setUndefined (sRef s, fileloc loc)
5136 {
5137   sRef_checkMutable (s);
5138
5139   if (sRef_isReasonable (s))
5140     {
5141       s->defstate = SS_UNDEFINED;
5142       s->definfo = stateInfo_updateLoc (s->definfo, SA_UNDEFINED, loc);
5143
5144       sRef_clearDerived (s);
5145     }
5146 }
5147
5148 static void sRef_setDefinedAux (sRef s, fileloc loc, bool clear)
5149 {
5150   sRef_checkMutable (s);
5151   if (sRef_isInvalid (s)) return;
5152
5153   DPRINTF (("Set defined: %s", sRef_unparseFull (s)));
5154
5155   s->definfo = stateInfo_updateLoc (s->definfo, SA_DEFINED, loc);  
5156   s->defstate = SS_DEFINED;
5157   
5158   DPRINTF (("Set defined: %s", sRef_unparseFull (s)));
5159
5160   /* e.g., if x is allocated, *x = 3 defines x */
5161   
5162   if (s->kind == SK_PTR)
5163     {
5164       sRef p = s->info->ref;
5165       sRef arr;
5166
5167       if (p->defstate == SS_ALLOCATED
5168           || p->defstate == SS_SPECIAL) /* evans 2001-07-12: shouldn't need this */
5169         {
5170           sRef_setDefinedAux (p, loc, clear);
5171         }
5172
5173       /* 
5174       ** Defines a[0] also:
5175       */
5176
5177       arr = sRef_findDerivedArrayFetch (p, FALSE, 0, FALSE);
5178
5179       if (sRef_isReasonable (arr))
5180         {
5181           sRef_setDefinedAux (arr, loc, clear);
5182         }
5183     }
5184   else if (s->kind == SK_ARRAYFETCH) 
5185     {
5186       if (!s->info->arrayfetch->indknown
5187           || (s->info->arrayfetch->ind == 0))
5188         {
5189           sRef p = s->info->arrayfetch->arr;
5190           sRef ptr = sRef_constructPointer (p);
5191
5192           if (sRef_isReasonable (ptr))
5193             {
5194               if (ptr->defstate == SS_ALLOCATED 
5195                   || ptr->defstate == SS_UNDEFINED
5196                   || ptr->defstate == SS_SPECIAL) /* evans 2001-07-12: shouldn't need this */
5197                 {
5198                   sRef_setDefinedAux (ptr, loc, clear);
5199                 }
5200             }
5201           
5202           if (p->defstate == SS_RELDEF) 
5203             {
5204               ;
5205             }
5206           else if (p->defstate == SS_ALLOCATED || p->defstate == SS_PDEFINED
5207                    || p->defstate == SS_SPECIAL) /* evans 2001-07-12: shouldn't need this */
5208             {
5209               p->defstate = SS_DEFINED;
5210             }
5211           else
5212             {
5213             }
5214         }
5215     }
5216   else if (s->kind == SK_FIELD)
5217     {
5218       sRef parent = s->info->field->rec;
5219       
5220       if (sRef_isReasonable (parent))
5221         {
5222           if (ctype_isUnion (ctype_realType (parent->type)))
5223             {
5224               /*
5225               ** Should not clear derived from here.
5226               */
5227               
5228               sRef_setDefinedNoClear (parent, loc);
5229             }
5230           else
5231             {
5232               ; /* Nothing to do for structures. */
5233             }
5234         }
5235
5236           }
5237   else
5238     {
5239       ;
5240     }
5241
5242   if (clear)
5243     {
5244       sRef_clearDerived (s);
5245     } 
5246   else
5247     {
5248       /* evans 2001-07-12: need to define the derived references */
5249       sRefSet_elements (s->deriv, el)
5250         {
5251           llassert (sRef_isReasonable (el));
5252           el->defstate = SS_DEFINED;
5253         } end_sRefSet_elements ;
5254     }
5255   
5256   DPRINTF (("Set defined: %s", sRef_unparseFull (s)));
5257 }
5258
5259 static void sRef_setPartialDefined (sRef s, fileloc loc)
5260 {
5261   sRef_checkMutable (s);
5262
5263   if (!sRef_isPartial (s))
5264     {
5265       sRef_setDefined (s, loc);
5266     }
5267 }
5268
5269 void sRef_setPartialDefinedComplete (sRef s, fileloc loc)
5270 {
5271   sRef_innerAliasSetComplete (sRef_setPartialDefined, s, loc);
5272 }
5273
5274 void sRef_setDefinedComplete (sRef s, fileloc loc)
5275 {
5276   sRef_innerAliasSetComplete (sRef_setDefined, s, loc);
5277 }
5278
5279 void sRef_setDefinedCompleteDirect (sRef s, fileloc loc)
5280 {
5281   sRefSet aliases;
5282   
5283   aliases = usymtab_allAliases (s);
5284   DPRINTF (("Set defined complete: %s", sRef_unparseFull (s)));
5285   DPRINTF (("All aliases: %s", sRefSet_unparseFull (aliases)));
5286   
5287   sRef_setDefined (s, loc);
5288
5289   sRefSet_realElements (aliases, current)
5290     {
5291       if (sRef_isReasonable (current))
5292         {
5293           current = sRef_updateSref (current);
5294           sRef_setDefined (current, loc);
5295         }
5296     } end_sRefSet_realElements;
5297   
5298   sRefSet_free (aliases);
5299   sRef_innerAliasSetComplete (sRef_setDefined, s, loc);
5300 }
5301
5302 void sRef_setDefined (sRef s, fileloc loc)
5303 {
5304   sRef_checkMutable (s);
5305   sRef_setDefinedAux (s, loc, TRUE);
5306 }
5307
5308 static void sRef_setDefinedNoClear (sRef s, fileloc loc)
5309 {
5310   sRef_checkMutable (s);
5311   DPRINTF (("Defining: %s", sRef_unparseFull (s)));
5312   sRef_setDefinedAux (s, loc, FALSE);
5313   DPRINTF (("==> %s", sRef_unparseFull (s)));
5314 }
5315
5316 void sRef_setDefinedNCComplete (sRef s, fileloc loc)
5317 {
5318   sRef_checkMutable (s);
5319   DPRINTF (("Set Defined Complete: %s", sRef_unparseFull (s)));
5320   sRef_innerAliasSetComplete (sRef_setDefinedNoClear, s, loc);
5321   DPRINTF (("==> %s", sRef_unparseFull (s)));
5322 }
5323
5324 static bool sRef_isDeepUnionField (sRef s)
5325 {
5326   return (sRef_deepPred (sRef_isUnionField, s));
5327 }
5328
5329 bool sRef_isUnionField (sRef s)
5330 {
5331   if (sRef_isReasonable (s) && s->kind == SK_FIELD)
5332     {
5333       /*
5334        ** defining one field of a union defines the union
5335        */
5336       
5337       sRef base = s->info->field->rec;
5338
5339       if (sRef_isReasonable (base))
5340         {
5341           return (ctype_isUnion (ctype_realType (base->type)));
5342         }
5343     }
5344
5345   return FALSE;
5346 }
5347
5348 void sRef_setPdefined (sRef s, fileloc loc)
5349 {
5350   sRef_checkMutable (s);
5351   if (sRef_isReasonable (s) && !sRef_isPartial (s))
5352     {
5353       sRef base = sRef_getBaseSafe (s);
5354
5355       if (s->defstate == SS_ALLOCATED)
5356         {
5357           return;
5358         }
5359       
5360       s->definfo = stateInfo_updateLoc (s->definfo, SA_PDEFINED, loc);
5361       s->defstate = SS_PDEFINED;
5362       
5363       /* e.g., if x is allocated, *x = 3 defines x */
5364       
5365       while (sRef_isReasonable (base) && sRef_isKnown (base))
5366         {
5367           if (base->defstate == SS_DEFINED)
5368             { 
5369               sRef nb;
5370               
5371               DPRINTF (("set pdefined: %s", sRef_unparseFull (base)));
5372               base->defstate = SS_PDEFINED; 
5373               nb = sRef_getBaseSafe (base); 
5374               base = nb;
5375             }
5376           else 
5377             { 
5378               break; 
5379             }
5380         }      
5381     }
5382 }
5383
5384 static void sRef_setStateAux (sRef s, sstate ss, fileloc loc)
5385 {
5386   sRef_checkMutable (s);
5387
5388   DPRINTF (("Set state: %s => %s", sRef_unparseFull (s), sstate_unparse (ss)));
5389
5390   if (sRef_isReasonable (s))
5391     {
5392       /* if (s->defstate == SS_RELDEF) return; */
5393
5394       if (s->defstate != ss && fileloc_isDefined (loc))
5395         {
5396           s->definfo = stateInfo_updateLoc (s->definfo, 
5397                                             stateAction_fromSState (ss), loc);
5398         }
5399
5400       s->defstate = ss;
5401       sRef_clearDerived (s); 
5402
5403       if (ss == SS_ALLOCATED)
5404         {
5405           sRef base = sRef_getBaseSafe (s);
5406           
5407           while (sRef_isReasonable (base) && sRef_isKnown (base))
5408             {
5409               if (base->defstate == SS_DEFINED) 
5410                 { 
5411                   sRef nb;
5412
5413                   DPRINTF (("set pdefined: %s", sRef_unparseFull (s)));           
5414                   base->defstate = SS_PDEFINED; 
5415                   nb = sRef_getBaseSafe (base); 
5416                   base = nb;
5417                 }
5418               else 
5419                 { 
5420                   break; 
5421                 }
5422             }
5423         }
5424     }
5425 }
5426
5427 void sRef_setAllocatedComplete (sRef s, fileloc loc)
5428 {
5429   sRef_innerAliasSetComplete (sRef_setAllocated, s, loc);
5430 }
5431
5432 static void sRef_setAllocatedShallow (sRef s, fileloc loc)
5433 {
5434   sRef_checkMutable (s);
5435
5436   if (sRef_isReasonable (s))
5437     {
5438       if (s->defstate == SS_DEAD || s->defstate == SS_UNDEFINED)
5439         {
5440           s->defstate = SS_ALLOCATED;
5441           s->definfo = stateInfo_updateLoc (s->definfo, SA_ALLOCATED, loc);
5442         }
5443     }
5444 }
5445
5446 void sRef_setAllocatedShallowComplete (sRef s, fileloc loc)
5447 {
5448   sRef_innerAliasSetComplete (sRef_setAllocatedShallow, s, loc);
5449 }
5450
5451 void sRef_setAllocated (sRef s, fileloc loc)
5452 {
5453   sRef_checkMutable (s);
5454   sRef_setStateAux (s, SS_ALLOCATED, loc);
5455 }
5456
5457 void sRef_setPartial (sRef s, fileloc loc)
5458 {
5459   sRef_checkMutable (s);
5460   sRef_setStateAux (s, SS_PARTIAL, loc);
5461 }
5462
5463 void sRef_setShared (sRef s, fileloc loc)
5464 {
5465   sRef_checkMutable (s);
5466
5467   if (sRef_isReasonable (s))
5468     {
5469       if (s->aliaskind != AK_SHARED && fileloc_isDefined (loc))
5470         {
5471           s->aliasinfo = stateInfo_updateLoc (s->aliasinfo, SA_SHARED, loc);
5472         }
5473
5474       s->aliaskind = AK_SHARED;
5475       /* don't! sRef_clearDerived (s); */
5476     }
5477 }
5478
5479 void sRef_setLastReference (sRef s, /*@exposed@*/ sRef ref, fileloc loc)
5480 {
5481   sRef_checkMutable (s);
5482
5483   if (sRef_isReasonable (s))
5484     {
5485       s->aliaskind = sRef_getAliasKind (ref);
5486       s->aliasinfo = stateInfo_updateRefLoc (s->aliasinfo, ref, stateAction_fromAlkind (s->aliaskind), loc);
5487     }
5488 }
5489
5490 static
5491 void sRef_setNullStateAux (/*@notnull@*/ sRef s, nstate ns, fileloc loc)
5492 {
5493   sRef_checkMutable (s);
5494   s->nullstate = ns;
5495   sRef_resetAliasKind (s);
5496
5497   if (fileloc_isDefined (loc))
5498     {
5499       s->nullinfo = stateInfo_updateLoc (s->nullinfo, stateAction_fromNState (ns), loc);
5500     }
5501 }
5502
5503 void sRef_setNotNull (sRef s, fileloc loc)
5504 {
5505   if (sRef_isReasonable (s))
5506     {
5507       sRef_setNullStateAux (s, NS_NOTNULL, loc);
5508     }
5509 }
5510
5511 void sRef_setNullStateN (sRef s, nstate n)
5512 {
5513   if (sRef_isReasonable (s))
5514     {
5515       sRef_checkMutable (s);
5516       s->nullstate = n;
5517       sRef_resetAliasKind (s);
5518     }
5519 }
5520
5521 void sRef_setNullState (sRef s, nstate n, fileloc loc)
5522 {
5523   if (sRef_isReasonable (s))
5524     {
5525       sRef_setNullStateAux (s, n, loc);
5526     }
5527 }
5528
5529 void sRef_setNullTerminatedStateInnerComplete (sRef s, struct s_bbufinfo b, /*@unused@*/ fileloc loc) 
5530 {
5531   switch (b.bufstate) {
5532   case BB_NULLTERMINATED:
5533     sRef_setNullTerminatedState (s);
5534     sRef_setLen (s, b.len);
5535     break;
5536   case BB_POSSIBLYNULLTERMINATED:
5537     sRef_setPossiblyNullTerminatedState(s);
5538     break;
5539   case BB_NOTNULLTERMINATED:
5540     sRef_setNotNullTerminatedState (s);
5541     break;
5542   }
5543
5544   sRef_setSize (s, b.size);
5545   
5546   /* PL: TO BE DONE : Aliases are not modified right now, have to be similar to
5547    * setNullStateInnerComplete.
5548    */
5549 }
5550
5551 void sRef_setNullStateInnerComplete (sRef s, nstate n, fileloc loc)
5552 {
5553   DPRINTF (("Set null state: %s", nstate_unparse (n)));
5554   
5555   sRef_setNullState (s, n, loc);
5556   
5557   switch (n)
5558     {
5559     case NS_POSNULL:
5560       sRef_innerAliasSetComplete (sRef_setPosNull, s, loc);
5561       break;
5562     case NS_DEFNULL:
5563       sRef_innerAliasSetComplete (sRef_setDefNull, s, loc);
5564       break;
5565     case NS_UNKNOWN:
5566       sRef_innerAliasSetComplete (sRef_setNullUnknown, s, loc);
5567       break;
5568     case NS_NOTNULL:
5569       sRef_innerAliasSetComplete (sRef_setNotNull, s, loc);
5570       break;
5571     case NS_MNOTNULL:
5572       sRef_innerAliasSetComplete (sRef_setNotNull, s, loc);
5573       break;
5574     case NS_RELNULL:
5575       sRef_innerAliasSetComplete (sRef_setNullUnknown, s, loc);
5576       break;
5577     case NS_CONSTNULL:
5578       sRef_innerAliasSetComplete (sRef_setDefNull, s, loc);
5579       break;
5580     case NS_ABSNULL:
5581       sRef_innerAliasSetComplete (sRef_setNullUnknown, s, loc);
5582       break;
5583     case NS_ERROR:
5584       sRef_innerAliasSetComplete (sRef_setNullErrorLoc, s, loc);
5585       break;
5586     }
5587 }
5588
5589 void sRef_setPosNull (sRef s, fileloc loc)
5590 {
5591   if (sRef_isReasonable (s))
5592     {
5593       sRef_setNullStateAux (s, NS_POSNULL, loc);
5594     }
5595 }
5596   
5597 void sRef_setDefNull (sRef s, fileloc loc)
5598 {
5599   if (sRef_isReasonable (s))
5600     {
5601       sRef_setNullStateAux (s, NS_DEFNULL, loc);
5602     }
5603 }
5604
5605 void sRef_setNullUnknown (sRef s, fileloc loc)
5606 {
5607   if (sRef_isReasonable (s))
5608     {
5609       sRef_setNullStateAux (s, NS_UNKNOWN, loc);
5610     }
5611 }
5612
5613 void sRef_setNullError (sRef s)
5614 {
5615   if (sRef_isReasonable (s) && !sRef_isConst (s))
5616     {
5617       sRef_setNullStateAux (s, NS_UNKNOWN, fileloc_undefined);
5618     }
5619 }
5620
5621 void sRef_setNullErrorLoc (sRef s, fileloc loc)
5622 {
5623   if (sRef_isReasonable (s) && !sRef_isConst (s))
5624     {
5625       sRef_setNullStateAux (s, NS_UNKNOWN, loc);
5626     }
5627 }
5628
5629 void sRef_setOnly (sRef s, fileloc loc)
5630 {
5631   if (sRef_isReasonable (s) && s->aliaskind != AK_ONLY)
5632     {
5633       sRef_checkMutable (s);
5634       s->aliaskind = AK_ONLY;
5635       s->aliasinfo = stateInfo_updateLoc (s->aliasinfo, SA_ONLY, loc);
5636     }
5637 }
5638
5639 void sRef_setDependent (sRef s, fileloc loc)
5640 {
5641   if (sRef_isReasonable (s) && !sRef_isConst (s) && (s->aliaskind != AK_DEPENDENT))
5642     {
5643       sRef_checkMutable (s);
5644       DPRINTF (("Setting dependent: %s", sRef_unparseFull (s)));
5645       s->aliaskind = AK_DEPENDENT;
5646       s->aliasinfo = stateInfo_updateLoc (s->aliasinfo, SA_DEPENDENT, loc);
5647     }
5648 }
5649
5650 void sRef_setOwned (sRef s, fileloc loc)
5651 {
5652   if (sRef_isReasonable (s) && !sRef_isConst (s) && (s->aliaskind != AK_OWNED))
5653     {
5654       sRef_checkMutable (s);
5655       s->aliaskind = AK_OWNED;
5656       s->aliasinfo = stateInfo_updateLoc (s->aliasinfo, SA_OWNED, loc);
5657     }
5658 }
5659
5660 void sRef_setKept (sRef s, fileloc loc)
5661 {
5662   if (sRef_isReasonable (s) && !sRef_isConst (s) && (s->aliaskind != AK_KEPT))
5663     {
5664       sRef base = sRef_getBaseSafe (s);  
5665  
5666       while (sRef_isReasonable (base) && sRef_isKnown (base))
5667         {
5668           if (base->defstate == SS_DEFINED) 
5669             {
5670               sRef_checkMutable (base);
5671               base->defstate = SS_PDEFINED; 
5672               base = sRef_getBaseSafe (base); 
5673             }
5674           else 
5675             {
5676               break; 
5677             }
5678         }
5679
5680       sRef_checkMutable (s);
5681       s->aliaskind = AK_KEPT;
5682       s->aliasinfo = stateInfo_updateLoc (s->aliasinfo, SA_KEPT, loc);
5683     }
5684 }
5685
5686 static void sRef_setKeptAux (sRef s, fileloc loc)
5687 {
5688   if (!sRef_isShared (s))
5689     {
5690       sRef_setKept (s, loc);
5691     }
5692 }
5693
5694 static void sRef_setDependentAux (sRef s, fileloc loc)
5695 {
5696   if (!sRef_isShared (s))
5697     {
5698       sRef_setDependent (s, loc);
5699     }
5700 }
5701
5702 void sRef_setKeptComplete (sRef s, fileloc loc)
5703 {
5704   sRef_aliasSetComplete (sRef_setKeptAux, s, loc);
5705 }
5706
5707 void sRef_setDependentComplete (sRef s, fileloc loc)
5708 {
5709   sRef_aliasSetComplete (sRef_setDependentAux, s, loc);
5710 }
5711
5712 void sRef_setFresh (sRef s, fileloc loc)
5713 {
5714   if (sRef_isReasonable (s) && !sRef_isConst (s))
5715     {
5716       sRef_checkMutable (s);
5717       s->aliaskind = AK_FRESH;
5718       s->aliasinfo = stateInfo_updateLoc (s->aliasinfo, SA_CREATED, loc);
5719       DPRINTF (("SetFresh: %s", sRef_unparseFull (s)));
5720     }
5721 }
5722
5723 void sRef_kill (sRef s, fileloc loc)
5724 {
5725   DPRINTF (("Kill: %s", sRef_unparseFull (s)));
5726
5727   if (sRef_isReasonable (s) && !sRef_isShared (s) && !sRef_isConst (s))
5728     {
5729       sRef base = sRef_getBaseSafe (s);  
5730       sRef_checkMutable (s);
5731         
5732       while (sRef_isReasonable (base) && sRef_isKnown (base))
5733         {
5734           if (base->defstate == SS_DEFINED) 
5735             {
5736               sRef_checkMutable (base);
5737               base->defstate = SS_PDEFINED; 
5738               base = sRef_getBaseSafe (base); 
5739             }
5740           else 
5741             {
5742               break; 
5743             }
5744         }
5745       
5746       s->aliaskind = s->oaliaskind;
5747       s->defstate = SS_DEAD;
5748       s->definfo = stateInfo_updateLoc (s->definfo, SA_KILLED, loc);
5749       DPRINTF (("State info: %s", stateInfo_unparse (s->definfo)));
5750       sRef_clearDerived (s);
5751     }
5752 }
5753
5754 void sRef_maybeKill (sRef s, fileloc loc)
5755 {
5756   if (sRef_isReasonable (s))
5757     {
5758       sRef base = sRef_getBaseSafe (s);  
5759       sRef_checkMutable (s);
5760             
5761       while (sRef_isReasonable (base) && sRef_isKnown (base))
5762         {
5763           if (base->defstate == SS_DEFINED || base->defstate == SS_RELDEF)
5764             {
5765               sRef_checkMutable (base);
5766               base->defstate = SS_PDEFINED; 
5767               base = sRef_getBaseSafe (base); 
5768             }
5769           else 
5770             {
5771               break; 
5772             }
5773           
5774         }
5775       
5776       s->aliaskind = s->oaliaskind;
5777       s->defstate = SS_HOFFA; 
5778       s->definfo = stateInfo_updateLoc (s->definfo, SA_PKILLED, loc);
5779       DPRINTF (("State info: %s / %s", sRef_unparse (s), 
5780                 stateInfo_unparse (s->definfo)));
5781       sRef_clearDerived (s); 
5782     }
5783
5784   }
5785
5786 /*
5787 ** just for type checking...
5788 */
5789
5790 static void sRef_killAux (sRef s, fileloc loc)
5791 {
5792   if (sRef_isReasonable (s) && !sRef_isShared (s))
5793     {
5794       if (sRef_isUnknownArrayFetch (s))
5795         {
5796           sRef_maybeKill (s, loc);
5797         }
5798       else
5799         {
5800           sRef_kill (s, loc);
5801         }
5802     }
5803 }
5804
5805 /*
5806 ** kills s and all aliases to s
5807 */
5808
5809 void sRef_killComplete (sRef s, fileloc loc)
5810 {
5811   DPRINTF (("Kill complete: %s", sRef_unparseFull (s)));
5812   sRef_aliasSetComplete (sRef_killAux, s, loc);
5813 }
5814
5815 static bool sRef_equivalent (sRef s1, sRef s2)
5816 {
5817   return (sRef_compare (s1, s2) == 0);
5818 }
5819
5820 /*
5821 ** returns an sRef that will not be free'd on function exit.
5822 */
5823
5824 /*@only@*/ sRef sRef_saveCopy (sRef s)
5825 {
5826   sRef ret;
5827
5828   if (sRef_isReasonable (s))
5829     {
5830       bool old = inFunction;
5831
5832       /*
5833       ** Exit the function scope, so this sRef is not
5834       ** stored in the deallocation table.
5835       */
5836       
5837       inFunction = FALSE;
5838       DPRINTF (("Copying sref: %s", sRef_unparseFull(s)));
5839       ret = sRef_copy (s);
5840       DPRINTF (("Copying ===>: %s", sRef_unparseFull(ret)));
5841       inFunction = old;
5842     }
5843   else
5844     {
5845       ret = sRef_undefined;
5846     }
5847
5848   /*@-dependenttrans@*/ 
5849   return ret;
5850   /*@=dependenttrans@*/ 
5851 }
5852
5853 sRef sRef_copy (sRef s)
5854 {
5855   if (sRef_isKindSpecial (s) && !sRef_isGlobalMarker (s))
5856     {
5857       /*@-retalias@*/
5858       return s; /* don't copy specials (except for global markers) */
5859       /*@=retalias@*/
5860     }
5861
5862   if (sRef_isReasonable (s))
5863     {
5864       sRef t = sRef_alloc ();
5865
5866       DPRINTF (("Copying: [%p] %s", s, sRef_unparse (s)));
5867       DPRINTF (("Full: %s", sRef_unparseFull (s)));
5868
5869       t->kind = s->kind;
5870       t->safe = s->safe;
5871       t->modified = s->modified;
5872       t->immut = FALSE; /* Note mutability is not copied. */
5873       t->type = s->type;
5874       t->val = multiVal_copy (s->val);
5875
5876       t->info = sinfo_copy (s);
5877       t->defstate = s->defstate;
5878       t->nullstate = s->nullstate;
5879  
5880       /* start modifications */
5881       t->bufinfo.bufstate = s->bufinfo.bufstate;
5882       t->bufinfo.len = s->bufinfo.len;
5883       t->bufinfo.size = s->bufinfo.size;
5884       /* end modifications */
5885
5886       t->aliaskind = s->aliaskind;
5887       t->oaliaskind = s->oaliaskind;
5888
5889       t->expkind = s->expkind;
5890       t->oexpkind = s->oexpkind;
5891
5892       t->nullinfo = stateInfo_copy (s->nullinfo);
5893       t->aliasinfo = stateInfo_copy (s->aliasinfo);
5894       t->definfo = stateInfo_copy (s->definfo);
5895       t->expinfo = stateInfo_copy (s->expinfo);
5896
5897       t->deriv = sRefSet_newDeepCopy (s->deriv);
5898       t->state = valueTable_copy (s->state);
5899       
5900       DPRINTF (("Made copy: %s => %s", sRef_unparseFull (s), sRef_unparseFull (t)));
5901       return t;
5902     }
5903   else
5904     {
5905       return sRef_undefined;
5906     }
5907 }
5908
5909 /*@notfunction@*/
5910 # define PREDTEST(func,s) \
5911    do { if (sRef_isInvalid (s)) { return FALSE; } \
5912         else { if (sRef_isConj (s)) \
5913                   { return (func (sRef_getConjA (s)) \
5914                             || func (sRef_getConjB (s))); }}} while (FALSE);
5915
5916 bool sRef_isAddress (sRef s)
5917 {
5918   PREDTEST (sRef_isAddress, s);
5919   return (s->kind == SK_ADR);
5920 }
5921           
5922 /*
5923 ** pretty weak... maybe a flag should control this.
5924 */
5925
5926 bool sRef_isThroughArrayFetch (sRef s)
5927 {
5928   if (sRef_isReasonable (s))
5929     {
5930       sRef tref = s;
5931
5932       do 
5933         {
5934           sRef lt;
5935
5936           if (sRef_isArrayFetch (tref)) 
5937             {
5938               return TRUE;
5939             }
5940           
5941           lt = sRef_getBase (tref);
5942           tref = lt;
5943         } while (sRef_isReasonable (tref));
5944     } 
5945
5946   return FALSE;
5947 }
5948
5949 bool sRef_isArrayFetch (sRef s)
5950 {
5951   PREDTEST (sRef_isArrayFetch, s);
5952   return (s->kind == SK_ARRAYFETCH);
5953 }
5954
5955 bool sRef_isMacroParamRef (sRef s)
5956 {
5957   if (context_inMacro () && sRef_isCvar (s))
5958     {
5959       uentry ue = sRef_getUentry (s);
5960       cstring pname = makeParam (uentry_rawName (ue));
5961       uentry mac = usymtab_lookupSafe (pname);
5962
5963       cstring_free (pname);
5964       return (uentry_isValid (mac));
5965     }
5966
5967   return FALSE;
5968 }
5969       
5970 bool sRef_isCvar (sRef s) 
5971 {
5972   PREDTEST (sRef_isCvar, s);
5973   return (s->kind == SK_CVAR);
5974 }
5975
5976 bool sRef_isConst (sRef s) 
5977 {
5978   PREDTEST (sRef_isConst, s);
5979   return (s->kind == SK_CONST);
5980 }
5981
5982 bool sRef_isObject (sRef s) 
5983 {
5984   PREDTEST (sRef_isObject, s);
5985   return (s->kind == SK_OBJECT);
5986 }
5987
5988 bool sRef_isExternal (sRef s) 
5989 {
5990   PREDTEST (sRef_isExternal, s);
5991   return (s->kind == SK_EXTERNAL);
5992 }
5993
5994 static bool sRef_isDerived (sRef s) 
5995 {
5996   PREDTEST (sRef_isDerived, s);
5997   return (s->kind == SK_DERIVED);
5998 }
5999
6000 bool sRef_isField (sRef s)
6001 {
6002   PREDTEST (sRef_isField, s);
6003   return (s->kind == SK_FIELD);
6004 }
6005
6006 static bool sRef_isIndex (sRef s)
6007 {
6008   PREDTEST (sRef_isIndex, s);
6009   return (s->kind == SK_ARRAYFETCH);
6010 }
6011
6012 bool sRef_isAnyParam (sRef s)
6013 {
6014   PREDTEST (sRef_isAnyParam, s);
6015   return (s->kind == SK_PARAM);  
6016 }
6017
6018 bool sRef_isParam (sRef s)
6019 {
6020   PREDTEST (sRef_isParam, s);
6021   return (s->kind == SK_PARAM);
6022 }
6023
6024 bool sRef_isDirectParam (sRef s)
6025 {
6026   PREDTEST (sRef_isDirectParam, s);
6027
6028   return ((s->kind == SK_CVAR) &&
6029           (s->info->cvar->lexlevel == functionScope) &&
6030           (context_inFunction () && 
6031            (s->info->cvar->index <= usymId_fromInt (uentryList_size (context_getParams ())))));
6032 }
6033
6034 bool sRef_isPointer (sRef s)
6035 {
6036   PREDTEST (sRef_isPointer, s);
6037   return (s->kind == SK_PTR);
6038 }
6039
6040 /*
6041 ** returns true if storage referenced by s is visible
6042 */
6043
6044 bool sRef_isReference (sRef s)
6045 {
6046   PREDTEST (sRef_isReference, s);
6047
6048   return (sRef_isPointer (s) || sRef_isIndex (s) || sRef_isFileOrGlobalScope (s)
6049           || (sRef_isField (s) && (sRef_isReference (s->info->field->rec))));
6050 }
6051
6052 bool sRef_isIReference (sRef s)
6053 {
6054   return (sRef_isPointer (s) || sRef_isAddress (s) || sRef_isIndex (s)
6055           || sRef_isField (s) || sRef_isArrayFetch (s));
6056 }
6057
6058 bool sRef_isFileOrGlobalScope (sRef s)
6059 {
6060   return (sRef_isCvar (s) && (s->info->cvar->lexlevel <= fileScope));
6061 }
6062
6063 bool sRef_isRealGlobal (sRef s)
6064 {
6065   return (sRef_isCvar (s) && (s->info->cvar->lexlevel == globScope));
6066 }
6067
6068 bool sRef_isFileStatic (sRef s)
6069 {
6070   return (sRef_isCvar (s) && (s->info->cvar->lexlevel == fileScope));
6071 }
6072
6073 bool sRef_isAliasCheckedGlobal (sRef s)
6074 {
6075   if (sRef_isFileOrGlobalScope (s))
6076     {
6077       uentry ue = sRef_getUentry (s);
6078
6079       return context_checkAliasGlob (ue);
6080     }
6081   else
6082     {
6083       return FALSE;
6084     }
6085 }
6086
6087 void sRef_free (/*@only@*/ sRef s)
6088 {
6089   if (s != sRef_undefined && s->kind != SK_SPECIAL)
6090     {
6091       DPRINTF (("Free sref: [%p]", s));
6092
6093       sRef_checkValid (s);
6094       
6095       multiVal_free (s->val); /* evans 2002-07-12 */
6096
6097       stateInfo_free (s->expinfo);
6098       stateInfo_free (s->aliasinfo);
6099       stateInfo_free (s->definfo);
6100       stateInfo_free (s->nullinfo);
6101
6102       sRefSet_free (s->deriv);
6103       s->deriv = sRefSet_undefined;
6104
6105       valueTable_free (s->state); 
6106       sinfo_free (s);
6107       
6108       
6109       /* drl added to help locate use after release*/
6110       s->expinfo = stateInfo_undefined;
6111       s->aliasinfo = stateInfo_undefined;
6112       s->definfo = stateInfo_undefined;
6113       s->nullinfo = stateInfo_undefined;
6114
6115       sfree (s);
6116     }
6117 }
6118
6119 void sRef_setType (sRef s, ctype t)
6120 {
6121   if (sRef_isReasonable (s))
6122     {
6123       sRef_checkMutable (s); 
6124       s->type = t;
6125     }
6126 }
6127
6128 void sRef_setTypeFull (sRef s, ctype t)
6129 {
6130   if (sRef_isReasonable (s))
6131     {
6132       sRef_checkMutable (s);
6133       s->type = t;
6134
6135       sRefSet_allElements (s->deriv, current)
6136         {
6137           sRef_setTypeFull (current, ctype_unknown);
6138         } end_sRefSet_allElements ;
6139     }
6140 }
6141
6142 /*@exposed@*/ sRef
6143   sRef_buildField (/*@exposed@*/ sRef rec, /*@dependent@*/ cstring f)
6144 {
6145   return (sRef_buildNCField (rec, f)); 
6146 }
6147
6148 static /*@exposed@*/ sRef
6149 sRef_findDerivedField (/*@notnull@*/ sRef rec, cstring f)
6150 {
6151   sRefSet_allElements (sRef_derivedFields (rec), sr)
6152     {
6153       if (sRef_isReasonable (sr))
6154         {
6155           if (sRef_isReasonable (sr))
6156             {
6157               if (sr->info != NULL) 
6158                 {
6159                   if (sr->kind == SK_FIELD && cstring_equal (sr->info->field->field, f))
6160                     {
6161                       return sr;
6162                     }
6163                 }
6164             }
6165           else
6166             {
6167               llcontbug (message ("Invalid sRef as derived field of %s", sRef_unparse (rec)));
6168             }
6169         }
6170     } end_sRefSet_allElements;
6171
6172   return sRef_undefined;
6173 }
6174
6175 /*@dependent@*/ /*@observer@*/ sRefSet sRef_derivedFields (/*@temp@*/ sRef rec)
6176 {
6177   if (sRef_isReasonable (rec))
6178     {
6179       sRefSet ret;
6180       ret = rec->deriv;
6181       return (ret);
6182     }
6183   else
6184     {
6185       return (sRefSet_undefined);
6186     }
6187 }
6188
6189 static /*@exposed@*/ sRef
6190   sRef_findDerivedPointer (sRef s)
6191 {
6192   if (sRef_isReasonable (s))
6193     {
6194       sRefSet_realElements (s->deriv, sr)
6195         {
6196           if (sRef_isReasonable (sr) && sr->kind == SK_PTR)
6197             {
6198               return sr;
6199             }
6200         } end_sRefSet_realElements;
6201     }
6202
6203   return sRef_undefined;
6204 }
6205
6206 bool
6207 sRef_isUnknownArrayFetch (sRef s)
6208 {
6209   return (sRef_isReasonable (s) 
6210           && s->kind == SK_ARRAYFETCH
6211           && !s->info->arrayfetch->indknown);
6212 }
6213
6214 static /*@exposed@*/ sRef
6215 sRef_findDerivedArrayFetch (/*@notnull@*/ sRef s, bool isknown, int idx, bool dead)
6216 {
6217   
6218   if (isknown) 
6219     {
6220       sRefSet_realElements (s->deriv, sr)
6221         {
6222           if (sRef_isReasonable (sr)
6223               && sr->kind == SK_ARRAYFETCH
6224               && sr->info->arrayfetch->indknown
6225               && (sr->info->arrayfetch->ind == idx))
6226             {
6227               return sr;
6228             }
6229         } end_sRefSet_realElements;
6230     }
6231   else
6232     {
6233       sRefSet_realElements (s->deriv, sr)
6234         {
6235           if (sRef_isReasonable (sr)
6236               && sr->kind == SK_ARRAYFETCH
6237               && (!sr->info->arrayfetch->indknown
6238                   || (sr->info->arrayfetch->indknown && 
6239                       sr->info->arrayfetch->ind == 0)))
6240             {
6241               if (sRef_isDead (sr) || sRef_isKept (sr))
6242                 {
6243                   if (dead || context_getFlag (FLG_STRICTUSERELEASED))
6244                     {
6245                       return sr;
6246                     }
6247                 }
6248               else
6249                 {
6250                   return sr;
6251                 }
6252             }
6253         } end_sRefSet_realElements;
6254     }
6255
6256   return sRef_undefined;
6257 }
6258
6259 static /*@exposed@*/ sRef 
6260 sRef_buildNCField (/*@exposed@*/ sRef rec, /*@exposed@*/ cstring f)
6261 {
6262   sRef s;
6263
6264   DPRINTF (("Build nc field: %s / %s",
6265             sRef_unparseFull (rec), f));
6266
6267   if (sRef_isInvalid (rec))
6268     {
6269       return sRef_undefined;
6270     }
6271       
6272   /*
6273   ** check if the field already has been referenced 
6274   */
6275
6276   s = sRef_findDerivedField (rec, f);
6277   
6278   if (sRef_isReasonable (s))
6279     {
6280       return s;
6281     }
6282   else
6283     {
6284       ctype ct = ctype_realType (rec->type);
6285       
6286       DPRINTF (("Field of: %s", sRef_unparse (rec)));
6287       
6288       s = sRef_newRef ();      
6289       s->kind = SK_FIELD;
6290       s->info = (sinfo) dmalloc (sizeof (*s->info));
6291       s->info->field = (fldinfo) dmalloc (sizeof (*s->info->field));
6292       s->info->field->rec = rec;
6293       s->info->field->field = f; /* doesn't copy f */
6294       
6295       if (ctype_isKnown (ct) && ctype_isSU (ct))
6296         {
6297           uentry ue = uentryList_lookupField (ctype_getFields (ct), f);
6298         
6299           if (!uentry_isUndefined (ue))
6300             {
6301               DPRINTF (("lookup: %s for %s", uentry_unparseFull (ue),
6302                         ctype_unparse (ct)));
6303               
6304               s->type = uentry_getType (ue);
6305
6306               if (ctype_isMutable (s->type)
6307                   && rec->aliaskind != AK_STACK 
6308                   && !alkind_isStatic (rec->aliaskind))
6309                 {
6310                   s->aliaskind = rec->aliaskind;
6311                 }
6312               else
6313                 {
6314                   s->aliaskind = AK_UNKNOWN;
6315                 }
6316
6317               if (sRef_isStateDefined (rec) || sRef_isStateUnknown (rec) 
6318                   || sRef_isPdefined (rec))
6319                 {
6320                   sRef_setStateFromUentry (s, ue);
6321                 }
6322               else
6323                 {
6324                   sRef_setPartsFromUentry (s, ue);
6325                 }
6326               
6327               s->oaliaskind = s->aliaskind;
6328               s->oexpkind = s->expkind;
6329
6330               DPRINTF (("sref: %s", sRef_unparseFull (s)));
6331             }
6332           else
6333             {
6334               /*
6335                 Never report this as an error.  It can happen whenever there
6336                 is casting involved.
6337
6338               if (report)
6339                 {
6340                   llcontbug (message ("buildNCField --- no field %s: %q / %s",
6341                                       f, sRef_unparse (s), ctype_unparse (ct)));
6342                 }
6343                 */
6344
6345               return sRef_undefined;
6346             }
6347         }
6348       
6349       if (rec->defstate == SS_DEFINED 
6350           && (s->defstate == SS_UNDEFINED || s->defstate == SS_UNKNOWN))
6351         {
6352           s->defstate = SS_DEFINED;
6353         }
6354       else if (rec->defstate == SS_PARTIAL)
6355         {
6356           s->defstate = SS_PARTIAL;
6357         }
6358       else if (rec->defstate == SS_ALLOCATED) 
6359         {
6360           if (ctype_isStackAllocated (ct) && ctype_isStackAllocated (s->type))
6361             {
6362               s->defstate = SS_ALLOCATED;
6363             }
6364           else
6365             {
6366               s->defstate = SS_UNDEFINED;
6367             }
6368         }
6369       else if (s->defstate == SS_UNKNOWN)
6370         {
6371           s->defstate = rec->defstate;
6372         }
6373       else
6374         {
6375           ; /* no change */
6376         }
6377
6378       if (s->defstate == SS_UNDEFINED)
6379         {
6380           ctype rt = ctype_realType (s->type);
6381           
6382           if (ctype_isArray (rt) || ctype_isSU (rt))
6383             {
6384               s->defstate = SS_ALLOCATED;
6385             }
6386         }
6387
6388       sRef_addDeriv (rec, s);
6389       DPRINTF (("Add deriv: %s", sRef_unparseFull (rec)));
6390
6391       if (ctype_isInt (s->type) && cstring_equal (f, REFSNAME))
6392         {
6393           s->aliaskind = AK_REFS;
6394           s->oaliaskind = AK_REFS;
6395         }
6396
6397       DPRINTF (("Build field ==> %s", sRef_unparseFull (s)));
6398       return s;
6399     }
6400 }
6401
6402 bool
6403 sRef_isStackAllocated (sRef s)
6404 {
6405   return (sRef_isReasonable(s) 
6406           && s->defstate == SS_ALLOCATED && ctype_isStackAllocated (s->type));
6407 }
6408           
6409 static
6410 void sRef_setArrayFetchState (/*@notnull@*/ /*@exposed@*/ sRef s, 
6411                               /*@notnull@*/ /*@exposed@*/ sRef arr)
6412 {
6413   sRef_checkMutable (s);
6414
6415   if (ctype_isRealAP (arr->type))
6416     {
6417       s->type = ctype_baseArrayPtr (arr->type);
6418     }
6419
6420   /* a hack, methinks... makeArrayFetch (&a[0]) ==> a[] */
6421   /* evans - 2001-08-27: not sure where this was necessary - it
6422   ** causes an assertion in in aliasCheckPred to fail.
6423   */
6424
6425   if (sRef_isAddress (arr)) 
6426     {
6427       sRef t = arr->info->ref;
6428       
6429       if (sRef_isArrayFetch (t))
6430         {
6431           s->info->arrayfetch->arr = t->info->arrayfetch->arr;
6432         }
6433     }
6434   else if (ctype_isRealPointer (arr->type))
6435     {
6436       sRef sp = sRef_findDerivedPointer (arr);
6437       
6438       if (sRef_isReasonable (sp))
6439         {
6440           
6441           if (ctype_isMutable (s->type))
6442             {
6443               s->expkind = sRef_getExKind (sp);
6444               s->expinfo = stateInfo_copy (sp->expinfo);
6445               
6446               s->aliaskind = sp->aliaskind;
6447               s->aliasinfo = stateInfo_copy (sp->aliasinfo);
6448             }
6449
6450           s->defstate = sp->defstate;
6451
6452           if (s->defstate == SS_DEFINED) 
6453             {
6454               if (!context_getFlag (FLG_STRICTDESTROY))
6455                 {
6456                   s->defstate = SS_PARTIAL;
6457                 }
6458             }
6459
6460           DPRINTF (("Set null state: %s / %s", sRef_unparseFull (s), sRef_unparseFull (sp)));
6461           sRef_setNullStateN (s, sRef_getNullState (sp));
6462         }
6463       else
6464         {
6465           if (arr->defstate == SS_UNDEFINED)
6466             {
6467               s->defstate = SS_UNUSEABLE;
6468             }
6469           else if ((arr->defstate == SS_ALLOCATED) && !ctype_isSU (s->type))
6470             {
6471               s->defstate = SS_UNDEFINED;
6472             }
6473           else
6474             {
6475               if (!context_getFlag (FLG_STRICTDESTROY))
6476                 {
6477                   s->defstate = SS_PARTIAL;
6478                 }
6479               else
6480                 {
6481                   s->defstate = SS_DEFINED;
6482                 }
6483
6484               /*
6485               ** Very weak checking for array elements.
6486               ** Was:
6487               **     s->defstate = arr->defstate;
6488               */
6489             }
6490
6491           s->expkind = sRef_getExKind (arr);
6492           s->expinfo = stateInfo_copy (arr->expinfo);
6493           
6494           if (arr->aliaskind == AK_LOCAL || arr->aliaskind == AK_FRESH)
6495             {
6496               s->aliaskind = AK_LOCAL;
6497             }
6498           else
6499             {
6500               s->aliaskind = AK_UNKNOWN;
6501             }
6502           
6503           sRef_setTypeState (s);
6504         }
6505     }
6506   else
6507     {
6508       if (arr->defstate == SS_DEFINED)
6509         {
6510           /*
6511           ** Very weak checking for array elements.
6512           ** Was:
6513           **     s->defstate = arr->defstate;
6514           */
6515
6516           if (context_getFlag (FLG_STRICTDESTROY))
6517             {
6518               s->defstate = SS_DEFINED;
6519             }
6520           else
6521             {
6522               s->defstate = SS_PARTIAL;
6523             }
6524         }
6525       else if (arr->defstate == SS_ALLOCATED)
6526         {
6527           if (ctype_isRealArray (s->type))
6528             {
6529               s->defstate = SS_ALLOCATED;
6530             }
6531           else 
6532             {
6533               if (!s->info->arrayfetch->indknown)
6534                 {
6535                   /*
6536                   ** is index is unknown, elements is defined or 
6537                   ** allocated is any element is!
6538                   */
6539                   
6540                   s->defstate = SS_UNDEFINED;
6541                   
6542                   sRefSet_allElements (arr->deriv, sr)
6543                     {
6544                       if (sRef_isReasonable (sr))
6545                         {
6546                           if (sRef_isReasonable (sr))
6547                             {
6548                               if (sr->defstate == SS_ALLOCATED)
6549                                 {
6550                                   s->defstate = SS_ALLOCATED;
6551                                 }
6552                               else 
6553                                 {
6554                                   if (sr->defstate == SS_DEFINED)
6555                                     {
6556                                       if (context_getFlag (FLG_STRICTDESTROY))
6557                                         {
6558                                           s->defstate = SS_DEFINED;
6559                                         }
6560                                       else
6561                                         {
6562                                           s->defstate = SS_PARTIAL;
6563                                         }
6564                                       
6565                                       break;
6566                                     }
6567                                 }
6568                             }
6569                           else
6570                             {
6571                               llcontbug (message ("Invalid sRef as derived element of %s", sRef_unparse (arr)));
6572                             }
6573                         }
6574                     } end_sRefSet_allElements;
6575                 }
6576               else
6577                 {
6578                   s->defstate = SS_UNDEFINED;
6579                 }
6580             }
6581         }
6582       else
6583         {
6584           s->defstate = arr->defstate;
6585         }
6586       
6587       
6588       /*
6589       ** kludgey way to guess where aliaskind applies
6590       */
6591       
6592       if (ctype_isMutable (s->type) 
6593           && !ctype_isPointer (arr->type) 
6594           && !alkind_isStatic (arr->aliaskind)
6595           && !alkind_isStack (arr->aliaskind)) /* evs - 2000-06-20: don't pass stack allocation to members */
6596         {
6597           s->aliaskind = arr->aliaskind;
6598         }
6599       else
6600         {
6601           s->aliaskind = AK_UNKNOWN;
6602         }
6603     
6604       sRef_setTypeState (s);
6605     }
6606
6607   if (sRef_isObserver (arr)) 
6608     {
6609       s->expkind = XO_OBSERVER;
6610       s->expinfo = stateInfo_copy (arr->expinfo);
6611     }
6612 }  
6613
6614 /*@exposed@*/ sRef sRef_buildArrayFetch (/*@exposed@*/ sRef arr)
6615 {
6616   sRef s;
6617
6618   if (!sRef_isReasonable (arr)) {
6619     /*@-nullret@*/ return arr /*@=nullret@*/;
6620   }
6621
6622   if (ctype_isRealPointer (arr->type))
6623     {
6624       (void) sRef_buildPointer (arr); /* do this to define arr! */
6625     }
6626   
6627   s = sRef_findDerivedArrayFetch (arr, FALSE, 0, FALSE);
6628   
6629   if (sRef_isReasonable (s))
6630     {
6631       /* evans 2001-07-12: this is bogus, clean-up hack */
6632       if (s->info->arrayfetch->arr != arr)
6633         {
6634           sRef res;
6635           check (sRefSet_delete (arr->deriv, s));
6636           res = sRef_buildArrayFetch (arr);
6637           sRef_copyState (res, s);
6638           llassert (res->info->arrayfetch->arr == arr); 
6639           return res;
6640         }
6641
6642       s->expkind = sRef_getExKind (arr);
6643       s->expinfo = stateInfo_copy (arr->expinfo);
6644
6645       return s;
6646     }
6647   else
6648     {
6649       s = sRef_newRef ();
6650
6651       s->kind = SK_ARRAYFETCH;
6652       s->info = (sinfo) dmalloc (sizeof (*s->info));
6653       s->info->arrayfetch = (ainfo) dmalloc (sizeof (*s->info->arrayfetch));
6654       s->info->arrayfetch->indknown = FALSE;
6655       s->info->arrayfetch->ind = 0;
6656       s->info->arrayfetch->arr = arr;
6657
6658       sRef_setArrayFetchState (s, arr);
6659
6660       s->oaliaskind = s->aliaskind;
6661       s->oexpkind = s->expkind;
6662
6663       if (!context_inProtectVars ())
6664         {
6665           sRef_addDeriv (arr, s);
6666         }
6667       
6668       if (valueTable_isUndefined (s->state))
6669         {
6670           s->state = context_createValueTable 
6671             (s, stateInfo_makeLoc (g_currentloc, SA_CREATED));
6672         }
6673       
6674       return (s);
6675     }
6676 }
6677
6678 /*@exposed@*/ sRef
6679   sRef_buildArrayFetchKnown (/*@exposed@*/ sRef arr, int i)
6680 {
6681   sRef s;
6682
6683   if (!sRef_isReasonable (arr)) {
6684     /*@-nullret@*/ return arr /*@=nullret@*/;
6685   }
6686
6687   if (ctype_isRealPointer (arr->type))
6688     {
6689       (void) sRef_buildPointer (arr); /* do this to define arr! */
6690     }
6691
6692   s = sRef_findDerivedArrayFetch (arr, TRUE, i, FALSE);
6693
6694   if (sRef_isReasonable (s))
6695     {
6696       /* evans 2001-07-12: this is bogus, clean-up hack */
6697       if (s->info->arrayfetch->arr != arr)
6698         {
6699           sRef res;
6700
6701           check (sRefSet_delete (arr->deriv, s));
6702           res = sRef_buildArrayFetchKnown (arr, i);
6703
6704           llassert (res->info->arrayfetch->arr == arr);
6705           sRef_copyState (res, s);
6706           llassert (res->info->arrayfetch->arr == arr);
6707           return res;
6708         }
6709
6710       s->expkind = sRef_getExKind (arr);
6711       s->expinfo = stateInfo_copy (arr->expinfo);
6712
6713       llassert (s->info->arrayfetch->arr == arr);
6714       return s;
6715     }
6716   else
6717     {
6718       s = sRef_newRef ();
6719       
6720       s->kind = SK_ARRAYFETCH;
6721       s->info = (sinfo) dmalloc (sizeof (*s->info));
6722       s->info->arrayfetch = (ainfo) dmalloc (sizeof (*s->info->arrayfetch));
6723       s->info->arrayfetch->arr = arr;
6724       s->info->arrayfetch->indknown = TRUE;
6725       s->info->arrayfetch->ind = i;
6726
6727       sRef_setArrayFetchState (s, arr);
6728       /* evans 2001-08-27 no: can change this - llassert (s->info->arrayfetch->arr == arr); */
6729
6730       s->oaliaskind = s->aliaskind;
6731       s->oexpkind = s->expkind;
6732       sRef_addDeriv (arr, s);
6733
6734       llassert (valueTable_isUndefined (s->state));
6735       s->state = context_createValueTable (s, stateInfo_makeLoc (g_currentloc, SA_CREATED));
6736       return (s);
6737     }
6738 }
6739
6740 /*
6741 ** sets everything except for defstate
6742 */
6743
6744 static void
6745 sRef_setPartsFromUentry (sRef s, uentry ue)
6746 {    
6747   sRef uref = uentry_getSref (ue);
6748
6749   llassert (sRef_isReasonable (s));
6750
6751   s->aliaskind = alkind_derive (s->aliaskind, uentry_getAliasKind (ue));
6752   s->oaliaskind = s->aliaskind;
6753
6754   if (s->expkind == XO_UNKNOWN)
6755     {
6756       s->expkind = uentry_getExpKind (ue);
6757     }
6758   
6759   s->oexpkind = s->expkind;
6760   
6761   if (sRef_getNullState (s) == NS_UNKNOWN)
6762     {
6763       DPRINTF (("Set null state: %s / %s", sRef_unparseFull (s), uentry_unparseFull (ue)));
6764       sRef_setNullStateN (s, sRef_getNullState (uentry_getSref (ue)));
6765     }
6766   else
6767     {
6768       DPRINTF (("Skipping null null state!"));
6769     }
6770
6771   if (s->aliaskind == AK_IMPONLY && (sRef_isExposed (s) || sRef_isObserver (s)))
6772     {
6773       s->oaliaskind = s->aliaskind = AK_IMPDEPENDENT;
6774     } 
6775
6776   if (sRef_isReasonable (uref))
6777     {
6778       valueTable utable = uref->state;
6779       valueTable_free (s->state);
6780       s->state = valueTable_copy (utable);
6781     }
6782 }
6783
6784 static void
6785 sRef_setStateFromAbstractUentry (sRef s, uentry ue)
6786 {
6787   llassert (sRef_isReasonable (s));
6788   sRef_checkMutable (s);
6789
6790   sRef_setPartsFromUentry (s, ue);
6791
6792   s->aliaskind = alkind_derive (s->aliaskind, uentry_getAliasKind (ue));
6793   s->oaliaskind = s->aliaskind;
6794
6795   if (s->expkind == XO_UNKNOWN)
6796     {
6797       s->expkind = uentry_getExpKind (ue);
6798     }
6799
6800   s->oexpkind = s->expkind;
6801 }
6802
6803 void
6804 sRef_setStateFromUentry (sRef s, uentry ue)
6805 {
6806   sstate defstate;
6807
6808   sRef_checkMutable (s);
6809   llassert (sRef_isReasonable (s));
6810   
6811   sRef_setPartsFromUentry (s, ue);
6812
6813   defstate = uentry_getDefState (ue);
6814
6815   if (sstate_isKnown (defstate))
6816     {
6817       s->defstate = defstate;
6818     }
6819   else
6820     {
6821       ;
6822     }
6823 }
6824
6825 /*@exposed@*/ sRef
6826   sRef_buildPointer (/*@exposed@*/ sRef t)
6827 {
6828   DPRINTF (("build pointer: %s", sRef_unparse (t)));
6829
6830   if (sRef_isInvalid (t)) return sRef_undefined;
6831
6832   if (sRef_isAddress (t))
6833     {
6834       DPRINTF (("Return ref: %s", sRef_unparse (t->info->ref)));
6835       return (t->info->ref);
6836     }
6837   else
6838     {
6839       sRef s = sRef_findDerivedPointer (t);
6840
6841       DPRINTF (("find derived: %s", sRef_unparse (s)));
6842
6843       if (sRef_isReasonable (s))
6844         {
6845           s->expkind = sRef_getExKind (t);
6846           s->expinfo = stateInfo_copy (t->expinfo);       
6847
6848           s->oaliaskind = s->aliaskind;
6849           s->oexpkind = s->expkind;
6850
6851           return s;
6852         }
6853       else
6854         {
6855           s = sRef_constructPointerAux (t);
6856           
6857           DPRINTF (("construct: %s", sRef_unparse (s)));
6858
6859           if (sRef_isReasonable (s))
6860             {
6861               sRef_addDeriv (t, s);
6862
6863               s->oaliaskind = s->aliaskind;
6864               s->oexpkind = s->expkind;
6865             }
6866           
6867           return s;
6868         }
6869     }
6870 }
6871
6872 /*@exposed@*/ sRef
6873 sRef_constructPointer (/*@exposed@*/ sRef t)
6874    /*@modifies t@*/
6875 {
6876   return sRef_buildPointer (t);
6877 }
6878
6879 static /*@exposed@*/ sRef sRef_constructDerefAux (sRef t, bool isdead)
6880 {
6881   if (sRef_isReasonable (t))
6882     {
6883       sRef s;
6884       
6885       /*
6886       ** if there is a derived t[?], return that.  Otherwise, *t.
6887       */
6888       
6889       s = sRef_findDerivedArrayFetch (t, FALSE, 0, isdead);
6890       
6891       if (sRef_isReasonable (s))
6892         {
6893           DPRINTF (("Found array fetch: %s", sRef_unparseFull (s)));
6894           return s;
6895         }
6896       else
6897         {
6898           sRef ret = sRef_constructPointer (t);
6899
6900           DPRINTF (("Constructed pointer: %s", sRef_unparseFull (ret)));
6901
6902           return ret;
6903         }
6904     }
6905   else
6906     {
6907       return sRef_undefined;
6908     }
6909 }
6910
6911 sRef sRef_constructDeref (sRef t)
6912 {
6913   return sRef_constructDerefAux (t, FALSE);
6914 }
6915
6916 sRef sRef_constructDeadDeref (sRef t)
6917 {
6918   return sRef_constructDerefAux (t, TRUE);
6919 }
6920
6921 static sRef
6922 sRef_constructPointerAux (/*@notnull@*/ /*@exposed@*/ sRef t)
6923 {
6924   sRef s = sRef_newRef ();
6925   ctype rt = t->type;
6926   ctype st;
6927   
6928   llassert (valueTable_isUndefined (s->state));
6929
6930   s->kind = SK_PTR;
6931   s->info = (sinfo) dmalloc (sizeof (*s->info));
6932   s->info->ref = t; 
6933   
6934   if (ctype_isRealAP (rt))
6935     {
6936       s->type = ctype_baseArrayPtr (rt);
6937     }
6938   
6939   st = ctype_realType (s->type);  
6940
6941   if (t->defstate == SS_UNDEFINED)
6942     {
6943       s->defstate = SS_UNUSEABLE;
6944       s->definfo = stateInfo_copy (t->definfo);
6945     }
6946   else if ((t->defstate == SS_ALLOCATED) && !ctype_isSU (st))
6947     {
6948       s->defstate = SS_UNDEFINED;
6949       s->definfo = stateInfo_copy (t->definfo);
6950     }
6951   else
6952     {
6953       s->defstate = t->defstate;
6954       s->definfo = stateInfo_copy (t->definfo);
6955     }
6956   
6957   if (t->aliaskind == AK_LOCAL || t->aliaskind == AK_FRESH)
6958     {
6959       s->aliaskind = AK_LOCAL;
6960     }
6961   else
6962     {
6963       s->aliaskind = AK_UNKNOWN;
6964     }
6965
6966   s->expkind = sRef_getExKind (t);
6967   s->expinfo = stateInfo_copy (t->expinfo);
6968
6969   sRef_setTypeState (s);
6970
6971   s->oaliaskind = s->aliaskind;
6972   s->oexpkind = s->expkind;
6973
6974   if (valueTable_isUndefined (s->state))
6975     {
6976       s->state = context_createValueTable (s, stateInfo_makeLoc (g_currentloc, SA_CREATED));
6977     }
6978
6979   DPRINTF (("pointer: %s", sRef_unparseFull (s)));
6980   return s;
6981 }
6982
6983 bool sRef_hasDerived (sRef s)
6984 {
6985   return (sRef_isReasonable (s) && !sRefSet_isEmpty (s->deriv));
6986 }
6987
6988 void
6989 sRef_clearDerived (sRef s)
6990 {
6991   if (sRef_isReasonable (s))
6992     {
6993       DPRINTF (("Clear derived: [%p] %s", s, sRef_unparseDebug (s)));
6994       sRefSet_clear (s->deriv); 
6995     }
6996 }
6997
6998 void
6999 sRef_clearDerivedComplete (sRef s)
7000 {
7001   if (sRef_isReasonable (s))
7002     {
7003       sRef base = sRef_getBaseSafe (s);
7004       
7005       while (sRef_isReasonable (base))
7006         {
7007           DPRINTF (("Clear derived: [%p] %s", base, sRef_unparse (base)));
7008           sRefSet_clear (base->deriv); 
7009           base = sRef_getBaseSafe (base);
7010         }
7011
7012       DPRINTF (("Clear derived: [%p] %s", s, sRef_unparse (s)));
7013       sRefSet_clear (s->deriv); 
7014     }
7015 }
7016
7017 /*@exposed@*/ sRef sRef_makePointer (/*@exposed@*/ sRef s)
7018      /*@modifies s@*/
7019 {
7020   sRef res = sRef_buildPointer (s); 
7021
7022   DPRINTF (("Res: %s", sRef_unparseFull (res)));
7023   return res;
7024 }
7025
7026 /*
7027 ** &a[] => a (this is for out params)
7028 */
7029
7030 /*@exposed@*/ sRef
7031 sRef_makeAnyArrayFetch (/*@exposed@*/ sRef arr)
7032 {  
7033   if (sRef_isAddress (arr))
7034     {
7035       return (arr->info->ref);
7036     }
7037   else
7038     {
7039       return (sRef_buildArrayFetch (arr));
7040     }
7041 }
7042
7043 /*@exposed@*/ sRef
7044 sRef_makeArrayFetch (/*@exposed@*/ sRef arr)
7045 {
7046   return (sRef_buildArrayFetch (arr));
7047 }
7048
7049 /*@exposed@*/ sRef
7050 sRef_makeArrayFetchKnown (/*@exposed@*/ sRef arr, int i)
7051 {
7052   return (sRef_buildArrayFetchKnown (arr, i));
7053 }
7054
7055 /*@exposed@*/ sRef
7056 sRef_makeField (sRef rec, /*@dependent@*/ cstring f)
7057 {
7058   sRef ret;
7059   ret = sRef_buildField (rec, f);
7060   return ret;
7061 }
7062
7063 /*@exposed@*/ sRef
7064 sRef_makeNCField (/*@exposed@*/ sRef rec, /*@dependent@*/ cstring f)
7065 {
7066   return (sRef_buildNCField (rec, f));
7067 }
7068
7069 /*@only@*/ cstring
7070 sRef_unparseKindName (sRef s)
7071 {
7072   cstring result;
7073
7074   if (s == sRef_undefined) return cstring_makeLiteral ("<invalid>");
7075
7076   s = sRef_fixConj (s);
7077
7078   switch (s->kind)
7079     {
7080     case SK_CVAR: 
7081       if (sRef_isLocalVar (s)) 
7082         {
7083           result = cstring_makeLiteral ("Variable");
7084         }
7085       else
7086         {
7087           result = cstring_makeLiteral ("Undef global");
7088         }
7089       break;
7090     case SK_PARAM:
7091       result = cstring_makeLiteral ("Out parameter");
7092       break;
7093     case SK_ARRAYFETCH:
7094       if (sRef_isAnyParam (s->info->arrayfetch->arr)) 
7095         {
7096           result = cstring_makeLiteral ("Out parameter");
7097         }
7098       else if (sRef_isIndexKnown (s))
7099         {
7100           result = cstring_makeLiteral ("Array element");
7101         }
7102       else
7103         {
7104           result = cstring_makeLiteral ("Value");
7105         }
7106       break;
7107     case SK_PTR:
7108       if (sRef_isAnyParam (s->info->ref)) 
7109         {
7110           result = cstring_makeLiteral ("Out parameter");
7111         }
7112       else
7113         {
7114           result = cstring_makeLiteral ("Value");
7115         }
7116       break;
7117     case SK_ADR:
7118       result = cstring_makeLiteral ("Value");
7119       break;
7120     case SK_FIELD:
7121       result = cstring_makeLiteral ("Field");
7122       break;
7123     case SK_OBJECT:
7124       result = cstring_makeLiteral ("Object");
7125       break;
7126     case SK_UNCONSTRAINED:
7127       result = cstring_makeLiteral ("<anything>");
7128       break;
7129     case SK_RESULT:
7130     case SK_SPECIAL:
7131     case SK_UNKNOWN:
7132     case SK_EXTERNAL:
7133     case SK_DERIVED:
7134     case SK_CONST:
7135     case SK_TYPE:
7136       result = cstring_makeLiteral ("<unknown>");
7137       break;
7138     case SK_CONJ:
7139       result = cstring_makeLiteral ("<conj>");
7140       break;
7141     case SK_NEW:
7142       result = cstring_makeLiteral ("Storage");
7143       break;
7144     }
7145   
7146   return result;
7147 }
7148
7149 /*@only@*/ cstring
7150 sRef_unparseKindNamePlain (sRef s)
7151 {
7152   cstring result;
7153
7154   if (s == sRef_undefined) return cstring_makeLiteral ("<invalid>");
7155
7156   s = sRef_fixConj (s);
7157
7158   switch (s->kind)
7159     {
7160     case SK_CVAR: 
7161       if (sRef_isLocalVar (s)) 
7162         {
7163           result = cstring_makeLiteral ("Variable");
7164         }
7165       else 
7166         {
7167           result = cstring_makeLiteral ("Global");
7168         }
7169       break;
7170     case SK_PARAM:
7171       result = cstring_makeLiteral ("Parameter");
7172       break;
7173     case SK_ARRAYFETCH:
7174       if (sRef_isAnyParam (s->info->arrayfetch->arr)) 
7175         {
7176           result = cstring_makeLiteral ("Parameter");
7177         }
7178       else if (sRef_isIndexKnown (s))
7179         {
7180           result = cstring_makeLiteral ("Array element");
7181         }
7182       else 
7183         {
7184           result = cstring_makeLiteral ("Value");
7185         }
7186       break;
7187     case SK_PTR:
7188       if (sRef_isAnyParam (s->info->ref))
7189         {
7190           result = cstring_makeLiteral ("Parameter");
7191         }
7192       else
7193         {
7194           result = cstring_makeLiteral ("Value");
7195         }
7196       break;
7197     case SK_ADR:
7198       result = cstring_makeLiteral ("Value");
7199       break;
7200     case SK_FIELD:
7201       result = cstring_makeLiteral ("Field");
7202       break;
7203     case SK_OBJECT:
7204       result = cstring_makeLiteral ("Object");
7205       break;
7206     case SK_NEW:
7207       result = cstring_makeLiteral ("Storage");
7208       break;
7209     case SK_UNCONSTRAINED:
7210       result = cstring_makeLiteral ("<anything>");
7211       break;
7212     case SK_RESULT:
7213     case SK_TYPE:
7214     case SK_CONST:
7215     case SK_EXTERNAL:
7216     case SK_DERIVED:
7217     case SK_UNKNOWN:
7218     case SK_SPECIAL:
7219       result = cstring_makeLiteral ("<unknown>");
7220       break;
7221     case SK_CONJ:
7222       result = cstring_makeLiteral ("<conj>");
7223       break;
7224     }
7225   
7226   return result;
7227 }
7228
7229 /*
7230 ** s1 <- s2
7231 */
7232
7233 void
7234 sRef_copyState (sRef s1, sRef s2)
7235 {
7236   if (sRef_isReasonable (s1) && sRef_isReasonable (s2))
7237     {
7238       s1->defstate = s2->defstate;
7239       
7240       /* start modifications */
7241       s1->bufinfo.bufstate = s2->bufinfo.bufstate;
7242       s1->bufinfo.len = s2->bufinfo.len;
7243       s1->bufinfo.size = s2->bufinfo.size;
7244       /* end modifications */
7245
7246       s1->aliaskind = s2->aliaskind;
7247       s1->aliasinfo = stateInfo_update (s1->aliasinfo, s2->aliasinfo);
7248
7249       s1->expkind = s2->expkind;
7250       s1->expinfo = stateInfo_update (s1->expinfo, s2->expinfo);
7251
7252       s1->nullstate = s2->nullstate;
7253       s1->nullinfo = stateInfo_update (s1->nullinfo, s2->nullinfo);
7254
7255       valueTable_free (s1->state);  
7256       s1->state = valueTable_copy (s2->state);
7257       s1->safe = s2->safe;
7258     }
7259 }
7260
7261 sRef
7262 sRef_makeNew (ctype ct, sRef t, cstring name)
7263 {
7264   sRef s = sRef_newRef ();
7265
7266   s->kind = SK_NEW;
7267   s->type = ct;
7268
7269   llassert (sRef_isReasonable (t));
7270   s->defstate = t->defstate;
7271
7272   s->aliaskind = t->aliaskind;
7273   s->oaliaskind = s->aliaskind;
7274   s->nullstate = t->nullstate;
7275   
7276   s->expkind = t->expkind;
7277   s->oexpkind = s->expkind;
7278   
7279   s->info = (sinfo) dmalloc (sizeof (*s->info));
7280   s->info->fname = name;
7281
7282   /* start modifications */
7283   s->bufinfo.bufstate = t->bufinfo.bufstate;
7284   /* end modifications */
7285   
7286   llassert (valueTable_isUndefined (s->state));
7287   s->state = valueTable_copy (t->state);
7288
7289   DPRINTF (("==> Copying state: %s", valueTable_unparse (s->state)));
7290   DPRINTF (("==> new: %s", sRef_unparseFull (s)));
7291   return s;
7292 }
7293
7294 sRef
7295 sRef_makeType (ctype ct)
7296 {
7297   sRef s = sRef_newRef ();
7298
7299   sRef_checkMutable (s);
7300
7301   s->kind = SK_TYPE;
7302   s->type = ct;
7303
7304   s->defstate = SS_UNKNOWN; 
7305   s->aliaskind = AK_UNKNOWN;
7306   sRef_setNullStateN (s, NS_UNKNOWN);
7307
7308   /* start modification */
7309   s->bufinfo.bufstate = BB_NOTNULLTERMINATED;
7310   /* end modification */
7311
7312     
7313   if (ctype_isUA (ct))
7314     {
7315       typeId uid = ctype_typeId (ct);
7316       uentry ue = usymtab_getTypeEntrySafe (uid);
7317
7318       if (uentry_isValid (ue))
7319         {
7320           sRef_mergeStateQuiet (s, uentry_getSref (ue));
7321         }
7322     }
7323   
7324   s->oaliaskind = s->aliaskind;
7325   s->oexpkind = s->expkind;
7326   llassert (valueTable_isUndefined (s->state));
7327   s->state = context_createValueTable (s, stateInfo_makeLoc (g_currentloc, SA_CREATED));
7328
7329   DPRINTF (("Create: %s", sRef_unparseFull (s)));
7330   return s;
7331 }
7332
7333 sRef
7334 sRef_makeConst (ctype ct)
7335 {
7336   sRef s = sRef_newRef ();
7337   
7338   s->kind = SK_CONST;
7339   s->type = ct;
7340
7341   s->defstate = SS_UNKNOWN;
7342   s->aliaskind = AK_UNKNOWN;
7343   sRef_setNullStateN (s, NS_UNKNOWN);
7344
7345   /* start modification */
7346   s->bufinfo.bufstate = BB_NULLTERMINATED;
7347   /* end modification */
7348
7349   /* evans 2002-04-22: added isManifestBool to avoid errors for -boolfalse initializations */
7350   if (!ctype_isManifestBool (ct) && ctype_isUA (ct)) 
7351     {
7352       typeId uid = ctype_typeId (ct);
7353       uentry te = usymtab_getTypeEntrySafe (uid);
7354       
7355       if (uentry_isValid (te))
7356         {
7357           sRef_mergeStateQuiet (s, uentry_getSref (te));
7358         }
7359     }
7360   
7361   s->oaliaskind = s->aliaskind;
7362   s->oexpkind = s->expkind;
7363
7364   llassert (valueTable_isUndefined (s->state));
7365   s->state = context_createValueTable (s, stateInfo_makeLoc (g_currentloc, SA_CREATED));
7366
7367   return s;
7368 }
7369
7370 bool sRef_hasName (sRef s)
7371 {
7372   if (sRef_isInvalid (s))
7373     {
7374       return (FALSE);
7375     }
7376
7377   switch (s->kind)
7378     {
7379     case SK_CVAR:
7380       {
7381         uentry u = usymtab_getRefQuiet (s->info->cvar->lexlevel,
7382                                          s->info->cvar->index);
7383         return (uentry_hasName (u));
7384       }
7385     case SK_PARAM:
7386       {
7387         if (s->info->paramno >= 0)
7388           {
7389             uentry u = uentryList_getN (context_getParams (), 
7390                                         s->info->paramno);
7391             
7392             return (uentry_hasName (u));
7393           }
7394         else
7395           {
7396             llassert (s->info->paramno == PARAMUNKNOWN);
7397             return FALSE;
7398           }
7399       }
7400     default:
7401       return TRUE;
7402     }
7403 }
7404
7405 bool
7406 sRef_sameName (sRef s1, sRef s2)
7407 {
7408   if (sRef_isInvalid (s1))
7409     {
7410       return sRef_isInvalid (s2);
7411     }
7412
7413   if (sRef_isInvalid (s2))
7414     {
7415       return (FALSE);
7416     }
7417
7418   switch (s1->kind)
7419     {
7420     case SK_CVAR:
7421       if (s2->kind == SK_CVAR)
7422         {
7423           return (s1->info->cvar->lexlevel == s2->info->cvar->lexlevel
7424                   && s1->info->cvar->index == s2->info->cvar->index);
7425         }
7426       else if (s2->kind == SK_PARAM)
7427         {
7428           if (context_inFunctionLike ())
7429             {
7430               if (s2->info->paramno != PARAMUNKNOWN)
7431                 {
7432                   uentry u1 = usymtab_getRefQuiet (s1->info->cvar->lexlevel,
7433                                                    s1->info->cvar->index);
7434                   uentry u2 = uentryList_getN (context_getParams (), 
7435                                                s2->info->paramno);
7436                   
7437                   return (cstring_equalFree (uentry_getName (u1),
7438                                              uentry_getName (u2)));
7439                 }
7440               else
7441                 {
7442                   return s1->info->paramno == PARAMUNKNOWN;
7443                 }
7444             }
7445           else 
7446             {
7447               return FALSE;
7448             }
7449         }
7450       else
7451         {
7452           return FALSE;
7453         }
7454     case SK_PARAM:
7455       {
7456         if (s2->kind == SK_PARAM)
7457           {
7458             return (s1->info->paramno == s2->info->paramno);
7459           }
7460         else if (s2->kind == SK_CVAR)
7461           {
7462             if (context_inFunctionLike ())
7463               {
7464                 if (s1->info->paramno == PARAMUNKNOWN)
7465                   {
7466                     return FALSE;
7467                   }
7468                 else
7469                   {
7470                     uentry u1 = uentryList_getN (context_getParams (), 
7471                                                  s1->info->paramno);
7472                     uentry u2 = usymtab_getRefQuiet (s2->info->cvar->lexlevel,
7473                                                      s2->info->cvar->index);
7474                     
7475                     
7476                     return (cstring_equalFree (uentry_getName (u1),
7477                                                uentry_getName (u2)));
7478                   }
7479               }
7480             else 
7481               {
7482                 return FALSE;
7483               }
7484           }
7485         else
7486           {
7487             return FALSE;
7488           }
7489       }
7490
7491     case SK_UNCONSTRAINED:
7492       return FALSE;
7493
7494     case SK_ARRAYFETCH:
7495       if (s2->kind == SK_ARRAYFETCH)
7496         {
7497           if (bool_equal (s1->info->arrayfetch->indknown,
7498                           s2->info->arrayfetch->indknown))
7499             {
7500               if (!s1->info->arrayfetch->indknown 
7501                   || (s1->info->arrayfetch->ind == s2->info->arrayfetch->ind))
7502                 {
7503                   return sRef_sameName (s1->info->arrayfetch->arr,
7504                                         s2->info->arrayfetch->arr);
7505                 }
7506             }
7507         }
7508
7509       return FALSE;
7510     case SK_FIELD:
7511       if (s2->kind == SK_FIELD)
7512         {
7513           if (cstring_equal (s1->info->field->field,
7514                              s2->info->field->field))
7515             {
7516               return sRef_sameName (s1->info->field->rec,
7517                                     s2->info->field->rec);
7518             }
7519
7520         }
7521       return FALSE;
7522     case SK_PTR:
7523     case SK_ADR:
7524     case SK_DERIVED:
7525     case SK_EXTERNAL:
7526       if (s2->kind == s1->kind)
7527         {
7528           return sRef_sameName (s1->info->ref,
7529                                 s2->info->ref);
7530         }
7531
7532       return FALSE;
7533     case SK_OBJECT:
7534       return FALSE;
7535     case SK_CONJ:
7536       return sRef_sameName (sRef_getConjA (s1), s2);
7537     case SK_NEW:
7538       return FALSE;
7539     case SK_UNKNOWN:
7540       return (s2->kind == SK_UNKNOWN);
7541     case SK_TYPE:
7542     case SK_CONST:
7543       if (s2->kind == s1->kind)
7544         {
7545           return (ctype_equal (s1->type, s2->type));
7546         }
7547       
7548       return FALSE;
7549     case SK_SPECIAL:
7550       if (s2->kind == SK_SPECIAL)
7551         {
7552           return (s1->info->spec == s2->info->spec);
7553         }
7554       return FALSE;
7555     case SK_RESULT:
7556       return (s2->kind == SK_RESULT);
7557     default:
7558       return FALSE;
7559     }
7560   BADEXIT;
7561 }
7562                 
7563 sRef
7564 sRef_fixOuterRef (/*@returned@*/ sRef s)
7565 {
7566   sRef root = sRef_getRootBase (s);
7567
7568   if (sRef_isCvar (root))
7569     {
7570       uentry ue = usymtab_getRefQuiet (root->info->cvar->lexlevel, 
7571                                        root->info->cvar->index);
7572
7573       if (uentry_isValid (ue))
7574         {
7575           sRef uref = uentry_getSref (ue);
7576           sRef sr = sRef_fixBase (s, uref);
7577
7578           return (sr);
7579         }
7580       else
7581         {
7582           llcontbug (message ("sRef_fixOuterRef: undefined: %q", sRef_unparseDebug (s)));
7583           return (s);
7584         }
7585     }
7586
7587   return (s);
7588 }
7589
7590 void
7591 sRef_storeState (sRef s)
7592 {
7593   if (sRef_isInvalid (s)) return;
7594
7595   sRef_checkMutable (s);
7596   s->oaliaskind = s->aliaskind;
7597   s->oexpkind = s->expkind;
7598 }
7599   
7600 static void sRef_resetStateAux (sRef s, /*@unused@*/ fileloc loc)
7601 {
7602   sRef_resetState (s);
7603 }
7604
7605 void
7606 sRef_resetState (sRef s)
7607 {
7608   bool changed = FALSE;
7609   if (sRef_isInvalid (s)) return;
7610
7611   
7612   if (s->oaliaskind == AK_KILLREF && !sRef_isParam (s))
7613     {
7614       /*
7615       ** killref is used in a kludgey way, to save having to add
7616       ** another alias kind (see usymtab_handleParams)
7617       */
7618  
7619       if (s->expkind != s->oexpkind)
7620         {
7621           changed = TRUE;
7622           s->expkind = s->oexpkind;
7623         }
7624     }
7625   else
7626     {
7627       if (s->expkind != s->oexpkind)
7628         {
7629           changed = TRUE;
7630           s->expkind = s->oexpkind;       
7631         }
7632
7633       if (s->aliaskind != s->oaliaskind
7634           && s->aliaskind != AK_REFCOUNTED
7635           && s->aliaskind != AK_REFS)
7636         {
7637           changed = TRUE;
7638           s->aliaskind = s->oaliaskind;
7639         }
7640     }
7641
7642   if (changed)
7643     {
7644       sRef_clearDerived (s);
7645     }
7646   
7647   }
7648
7649 void
7650 sRef_resetStateComplete (sRef s)
7651 {
7652   sRef_innerAliasSetComplete (sRef_resetStateAux, s, fileloc_undefined);
7653 }
7654
7655 /*@exposed@*/ sRef
7656 sRef_fixBase (/*@returned@*/ sRef s, /*@returned@*/ sRef base)
7657 {
7658   sRef tmp = sRef_undefined;
7659   sRef ret;
7660
7661   if (sRef_isInvalid (s)) return s;
7662   if (sRef_isInvalid (base)) return base;
7663
7664   switch (s->kind)
7665     {
7666     case SK_RESULT:
7667     case SK_PARAM:
7668     case SK_CVAR:
7669       ret = base;
7670       break;
7671     case SK_ARRAYFETCH:
7672       tmp = sRef_fixBase (s->info->arrayfetch->arr, base);
7673
7674       if (s->info->arrayfetch->indknown)
7675         {
7676           ret = sRef_makeArrayFetchKnown (tmp, s->info->arrayfetch->ind);
7677         }
7678       else
7679         {
7680           ret = sRef_makeArrayFetch (tmp);
7681         }
7682       break;
7683     case SK_FIELD:
7684       tmp = sRef_fixBase (s->info->field->rec, base);
7685       ret = sRef_buildNCField (tmp, s->info->field->field);
7686       break;
7687     case SK_PTR:
7688       tmp = sRef_fixBase (s->info->ref, base);
7689       ret = sRef_makePointer (tmp);
7690       break;
7691     case SK_ADR:
7692       tmp = sRef_fixBase (s->info->ref, base);
7693       ret = sRef_makeAddress (tmp);
7694       break;
7695     case SK_CONJ:
7696       {
7697         sRef tmpb;
7698
7699         tmp = sRef_fixBase (s->info->conj->a, base);
7700         tmpb = sRef_fixBase (s->info->conj->b, base);
7701
7702         ret = sRef_makeConj (tmp, tmpb);
7703         break;
7704       }
7705       BADDEFAULT;
7706     }
7707
7708   return ret;
7709 }
7710
7711 static /*@exposed@*/ sRef 
7712 sRef_fixDirectBase (sRef s, sRef base)
7713 {
7714   sRef ret;
7715
7716   
7717   if (sRef_isInvalid (s))
7718     {
7719       return sRef_undefined;
7720     }
7721   
7722   switch (s->kind)
7723     {
7724     case SK_ARRAYFETCH:
7725       if (s->info->arrayfetch->indknown)
7726         {
7727           ret = sRef_makeArrayFetchKnown (base, s->info->arrayfetch->ind);
7728         }
7729       else
7730         {
7731           ret = sRef_makeArrayFetch (base);
7732         }
7733       break;
7734     case SK_FIELD:
7735       ret = sRef_buildNCField (base, s->info->field->field);
7736       break;
7737     case SK_PTR:
7738             ret = sRef_makePointer (base);
7739             break;
7740     case SK_ADR:
7741       ret = sRef_makeAddress (base);
7742       break;
7743     case SK_CONJ:
7744       {
7745         sRef tmpa, tmpb;
7746
7747         tmpa = sRef_fixDirectBase (s->info->conj->a, base);
7748         tmpb = sRef_fixDirectBase (s->info->conj->b, base);
7749
7750         ret = sRef_makeConj (tmpa, tmpb);
7751         break;
7752       }
7753       BADDEFAULT;
7754     }
7755
7756     sRef_copyState (ret, s);
7757     return ret;
7758 }
7759
7760 bool
7761 sRef_isAllocIndexRef (sRef s)
7762 {
7763   return (sRef_isArrayFetch (s) && !(s->info->arrayfetch->indknown) 
7764           && sRef_isAllocated (s->info->arrayfetch->arr));
7765 }
7766
7767 void
7768 sRef_showRefLost (sRef s)
7769 {
7770   if (sRef_hasAliasInfoLoc (s))
7771     {
7772       llgenindentmsg (cstring_makeLiteral ("Original reference lost"),
7773                       sRef_getAliasInfoLoc (s));
7774     }
7775 }
7776
7777 void
7778 sRef_showRefKilled (sRef s)
7779 {
7780   if (sRef_isValid (s)) 
7781     {
7782       DPRINTF (("Killed: %s", sRef_unparseFull (s)));
7783       if (context_getLocIndentSpaces () == 0) {
7784         stateInfo_display (s->definfo, message ("  Storage %q", sRef_unparseOpt (s)));
7785       } else {
7786         stateInfo_display (s->definfo, message ("Storage %q", sRef_unparseOpt (s)));
7787       }
7788     }
7789 }
7790
7791 void
7792 sRef_showStateInconsistent (sRef s)
7793 {
7794   if (sRef_hasStateInfoLoc (s))
7795     {
7796       llgenindentmsg
7797         (message ("Storage %qbecomes inconsistent (released on one branch)",
7798                   sRef_unparseOpt (s)), 
7799          sRef_getStateInfoLoc (s));
7800     }
7801 }
7802
7803 void
7804 sRef_showStateInfo (sRef s)
7805 {
7806   if (sRef_isValid (s)) {
7807     if (context_getLocIndentSpaces () == 0) {
7808       stateInfo_display (s->definfo, message ("   Storage %q", sRef_unparseOpt (s)));
7809     } else {
7810       stateInfo_display (s->definfo, message ("Storage %q", sRef_unparseOpt (s)));
7811     }
7812   }
7813 }
7814
7815 void
7816 sRef_showExpInfo (sRef s)
7817 {
7818   if (sRef_isValid (s)) {
7819     if (context_getLocIndentSpaces () == 0) {
7820       stateInfo_display (s->expinfo, message ("   Storage %q", sRef_unparseOpt (s)));
7821     } else {
7822       stateInfo_display (s->expinfo, message ("Storage %q", sRef_unparseOpt (s)));
7823     }
7824   }
7825 }
7826
7827 void
7828 sRef_showMetaStateInfo (sRef s, cstring key)
7829 {
7830   stateValue val;
7831   metaStateInfo minfo = context_lookupMetaStateInfo (key);
7832
7833   llassert (sRef_isReasonable (s));
7834   llassert (valueTable_isDefined (s->state));
7835   llassert (metaStateInfo_isDefined (minfo));
7836
7837   val = valueTable_lookup (s->state, key);
7838   
7839   if (stateValue_hasLoc (val))
7840     {
7841       llgenindentmsg 
7842         (message ("%qbecomes %q", sRef_unparseOpt (s), 
7843                   stateValue_unparseValue (val, minfo)),
7844          stateValue_getLoc (val));
7845     }
7846 }
7847
7848 void
7849 sRef_showNullInfo (sRef s)
7850 {
7851   DPRINTF (("Show null info: %s", sRef_unparseFull (s)));
7852
7853   if (sRef_hasNullInfoLoc (s) && sRef_isKnown (s))
7854     {
7855       DPRINTF (("has null info: %s",
7856                 fileloc_unparse (sRef_getNullInfoLoc (s))));
7857
7858       switch (sRef_getNullState (s))
7859         {
7860         case NS_CONSTNULL:
7861           {
7862             fileloc loc = sRef_getNullInfoLoc (s);
7863             
7864             if (fileloc_isDefined (loc) && !fileloc_isLib (loc))
7865               {
7866                 llgenindentmsg 
7867                   (message ("Storage %qbecomes null", sRef_unparseOpt (s)),
7868                    loc);
7869               }
7870             break;
7871           }
7872         case NS_DEFNULL:
7873           {
7874             fileloc loc = sRef_getNullInfoLoc (s);
7875             
7876             if (fileloc_isDefined (loc) && !fileloc_isLib (loc))
7877               {
7878                 llgenindentmsg (message ("Storage %qbecomes null", sRef_unparseOpt (s)),
7879                                 loc);
7880               }
7881             break;
7882           }
7883         case NS_ABSNULL:
7884         case NS_POSNULL:
7885           llgenindentmsg
7886             (message ("Storage %qmay become null", sRef_unparseOpt (s)),
7887              sRef_getNullInfoLoc (s));
7888           break;
7889         case NS_NOTNULL:
7890         case NS_MNOTNULL:
7891           llgenindentmsg
7892             (message ("Storage %qbecomes not null", sRef_unparseOpt (s)),
7893              sRef_getNullInfoLoc (s));
7894           break;
7895         case NS_UNKNOWN:
7896           llgenindentmsg
7897             (message ("Storage %qnull state becomes unknown",
7898                       sRef_unparseOpt (s)),
7899              sRef_getNullInfoLoc (s));
7900           break;
7901
7902         case NS_ERROR:
7903           BADBRANCHCONT;
7904           break;
7905
7906         default:
7907           llgenindentmsg
7908             (message ("<error case> Storage %q becomes %s",
7909                       sRef_unparse (s), 
7910                       nstate_unparse (sRef_getNullState (s))),
7911              sRef_getNullInfoLoc (s));
7912           
7913           break;
7914         }
7915     }
7916 }
7917
7918 void
7919 sRef_showAliasInfo (sRef s)
7920 {
7921   if (sRef_isValid (s)) 
7922     {
7923       if (sRef_isFresh (s))
7924         {
7925           if (context_getLocIndentSpaces () == 0) {
7926             stateInfo_display (s->aliasinfo, message ("   Fresh storage %q", sRef_unparseOpt (s)));
7927           } else {
7928             stateInfo_display (s->aliasinfo, message ("Fresh storage %q", sRef_unparseOpt (s)));
7929           }
7930         }
7931       else
7932         {
7933           if (context_getLocIndentSpaces () == 0) {
7934             stateInfo_display (s->aliasinfo, message ("   Storage %q", sRef_unparseOpt (s))); 
7935           } else {
7936             stateInfo_display (s->aliasinfo, message ("Storage %q", sRef_unparseOpt (s)));
7937           }
7938         }
7939     }
7940 }
7941
7942 void
7943 sRef_mergeNullState (sRef s, nstate n)
7944 {
7945   if (sRef_isReasonable (s))
7946     {
7947       nstate old;
7948       
7949       old = sRef_getNullState (s);
7950       
7951       if (n != old && n != NS_UNKNOWN)
7952         {                 
7953           sRef_setNullState (s, n, g_currentloc);
7954         }
7955     }
7956   else
7957     {
7958       llbuglit ("sRef_mergeNullState: invalid");
7959     }
7960 }
7961
7962 bool
7963 sRef_possiblyNull (sRef s)
7964 {
7965   if (sRef_isReasonable (s))
7966     {
7967       if (sRef_getNullState (s) == NS_ABSNULL)
7968         {
7969           ctype rct = ctype_realType (s->type);
7970           
7971           if (ctype_isAbstract (rct))
7972             {
7973               return FALSE;
7974             }
7975           else
7976             {
7977               if (ctype_isUser (rct))
7978                 {
7979                   uentry ue = usymtab_getTypeEntry (ctype_typeId (rct));
7980                   
7981                   return (nstate_possiblyNull
7982                           (sRef_getNullState (uentry_getSref (ue))));
7983                 }
7984               else
7985                 {
7986                   return FALSE;
7987                 }
7988             }
7989         }
7990       else
7991         {
7992           return nstate_possiblyNull (sRef_getNullState (s));
7993         }
7994     }
7995   
7996   return FALSE;
7997 }
7998
7999 cstring
8000 sRef_getScopeName (sRef s)
8001 {
8002   sRef base = sRef_getRootBase (s);
8003
8004   if (sRef_isRealGlobal (base))
8005     {
8006       return (cstring_makeLiteralTemp ("Global"));
8007     }
8008   else if (sRef_isFileStatic (base))
8009     {
8010       return (cstring_makeLiteralTemp ("Static"));
8011     }
8012   else
8013     {
8014       return (cstring_makeLiteralTemp ("Local"));
8015     }
8016 }
8017
8018 cstring
8019 sRef_unparseScope (sRef s)
8020 {
8021   sRef base = sRef_getRootBase (s);
8022
8023   if (sRef_isRealGlobal (base))
8024     {
8025       return (cstring_makeLiteralTemp ("global"));
8026     }
8027   else if (sRef_isFileStatic (base))
8028     {
8029       return (cstring_makeLiteralTemp ("file static"));
8030     }
8031   else
8032     {
8033       BADEXIT;
8034     }
8035 }
8036
8037 int
8038 sRef_getScope (sRef s)
8039 {
8040   llassert (sRef_isReasonable (s));
8041
8042   if (sRef_isCvar (s))
8043     {
8044       return s->info->cvar->lexlevel;
8045     }
8046   else if (sRef_isParam (s))
8047     {
8048       return paramsScope;
8049     }
8050   else
8051     {
8052       return fileScope;
8053     }
8054 }
8055
8056 bool
8057 sRef_isDead (sRef s)
8058 {
8059   return (sRef_isReasonable (s) && (s)->defstate == SS_DEAD);
8060 }
8061
8062 bool
8063 sRef_isDeadStorage (sRef s)
8064 {
8065   if (sRef_isReasonable (s))
8066     {
8067       if (s->defstate == SS_DEAD
8068           || s->defstate == SS_UNUSEABLE
8069           || s->defstate == SS_UNDEFINED
8070           || s->defstate == SS_UNKNOWN)
8071         {
8072           return TRUE;
8073         }
8074       else 
8075         {
8076           return (sRef_isDefinitelyNull (s));
8077         }
8078     }
8079   else
8080     {
8081       return FALSE;
8082     }
8083 }
8084
8085 bool
8086 sRef_isPossiblyDead (sRef s)
8087 {
8088   return (sRef_isReasonable (s) && s->defstate == SS_HOFFA);
8089 }
8090
8091 bool sRef_isStateLive (sRef s)
8092 {
8093   if (sRef_isReasonable (s))
8094     {
8095       sstate ds = s->defstate;
8096
8097       return (!(ds == SS_UNDEFINED 
8098                 || ds == SS_DEAD
8099                 || ds == SS_UNUSEABLE
8100                 || ds == SS_HOFFA));
8101     }
8102   else
8103     {
8104       return FALSE;
8105     }
8106 }
8107
8108
8109 bool sRef_isStateUndefined (sRef s)
8110 {
8111   return ((sRef_isReasonable(s)) && ((s)->defstate == SS_UNDEFINED));
8112 }
8113
8114 bool sRef_isJustAllocated (sRef s)
8115 {
8116   if (sRef_isAllocated (s))
8117     {
8118       sRefSet_allElements (s->deriv, el)
8119         {
8120           if (!(sRef_isStateUndefined (el) || sRef_isUnuseable (el)))
8121             {
8122               return FALSE;
8123             }
8124         } end_sRefSet_allElements ;
8125
8126       return TRUE;
8127     }
8128
8129   return FALSE;
8130 }
8131
8132 static bool
8133 sRef_isAllocatedStorage (sRef s)
8134 {
8135   if (sRef_isReasonable (s) && ynm_toBoolStrict (sRef_isValidLvalue (s)))
8136     {
8137       return (ctype_isVisiblySharable (sRef_getType (s)));
8138     }
8139   else
8140     {
8141       return FALSE;
8142     }
8143 }
8144
8145 bool
8146 sRef_isUnuseable (sRef s)
8147 {
8148   return ((sRef_isValid(s)) && ((s)->defstate == SS_UNUSEABLE));
8149 }
8150
8151 bool
8152 sRef_perhapsNull (sRef s)
8153 {
8154   if (sRef_isReasonable (s))
8155     {
8156       if (sRef_getNullState (s) == NS_ABSNULL)
8157         {
8158           ctype rct = ctype_realType (s->type);
8159
8160           if (ctype_isAbstract (rct))
8161             {
8162               return FALSE;
8163             }
8164           else
8165             {
8166               if (ctype_isUser (rct))
8167                 {
8168                   uentry ue = usymtab_getTypeEntry (ctype_typeId (rct));
8169
8170                   return (nstate_perhapsNull 
8171                           (sRef_getNullState (uentry_getSref (ue))));
8172                 }
8173               else
8174                 {
8175                   return FALSE;
8176                 }
8177             }
8178         }
8179       else
8180         {
8181           return nstate_perhapsNull (sRef_getNullState (s));
8182         }
8183     }
8184
8185   return FALSE;
8186 }
8187
8188 /*
8189 ** definitelyNull --- called when TRUE is good
8190 */
8191
8192 bool 
8193 sRef_definitelyNull (sRef s)
8194 {
8195   return (sRef_isReasonable (s)
8196           && (sRef_getNullState (s) == NS_DEFNULL || sRef_getNullState (s) == NS_CONSTNULL));
8197 }
8198
8199 /*
8200 ** based on sRef_similar
8201 */
8202
8203 void
8204 sRef_setDerivNullState (sRef set, sRef guide, nstate ns)
8205 {
8206   if (sRef_isReasonable (set))
8207     {
8208       sRef deriv = sRef_getDeriv (set, guide);
8209       
8210       if (sRef_isReasonable (deriv))
8211         {
8212           sRef_setNullStateN (deriv, ns);
8213         }
8214     }
8215 }
8216
8217 static /*@exposed@*/ sRef
8218 sRef_getDeriv (/*@returned@*/ /*@notnull@*/ sRef set, sRef guide)
8219 {
8220   llassert (sRef_isReasonable (set));
8221   llassert (sRef_isReasonable (guide));
8222
8223   switch (guide->kind)
8224     {
8225     case SK_CVAR:
8226       llassert (set->kind == SK_CVAR);      
8227       return set;
8228
8229     case SK_PARAM:
8230       llassert (set->kind == guide->kind);
8231       llassert (set->info->paramno == guide->info->paramno);
8232       return set;
8233
8234     case SK_ARRAYFETCH:
8235
8236       if (set->kind == SK_ARRAYFETCH
8237           && (sRef_similar (set->info->arrayfetch->arr,
8238                             guide->info->arrayfetch->arr)))
8239         {
8240           return set;
8241         }
8242       else
8243         {
8244           return (sRef_makeAnyArrayFetch 
8245                   (sRef_getDeriv (set, guide->info->arrayfetch->arr)));
8246         }
8247
8248     case SK_PTR:
8249       
8250       if (set->kind == SK_PTR && sRef_similar (set->info->ref, guide->info->ref))
8251         {
8252           return set;
8253         }
8254       else
8255         {
8256           return (sRef_makePointer (sRef_getDeriv (set, guide->info->ref)));
8257         }
8258       
8259     case SK_FIELD:
8260       
8261       if ((set->kind == SK_FIELD &&
8262            (sRef_similar (set->info->field->rec, guide->info->field->rec) &&
8263             cstring_equal (set->info->field->field, guide->info->field->field))))
8264         {
8265           return set;
8266         }
8267       else
8268         {
8269           return (sRef_makeField (sRef_getDeriv (set, guide->info->field->rec),
8270                                   guide->info->field->field));
8271         }
8272     case SK_ADR:
8273       
8274       if ((set->kind == SK_ADR) && sRef_similar (set->info->ref, guide->info->ref))
8275         {
8276           return set;
8277         }
8278       else
8279         {
8280           return (sRef_makeAddress (sRef_getDeriv (set, guide->info->ref)));
8281         }
8282
8283     case SK_CONJ:
8284       
8285             return sRef_undefined;
8286
8287     case SK_RESULT:
8288     case SK_SPECIAL:
8289     case SK_UNCONSTRAINED:
8290     case SK_TYPE:
8291     case SK_CONST:
8292     case SK_NEW:
8293     case SK_UNKNOWN:
8294     case SK_OBJECT:
8295     case SK_DERIVED:
8296     case SK_EXTERNAL:
8297       return sRef_undefined;
8298     }
8299
8300   BADEXIT;
8301 }
8302       
8303 /*
8304 ** sRef_aliasCheckPred
8305 **
8306 ** A confusing but spiffy function:
8307 **
8308 **    Calls predf (s, e, text, <alias>) on s and all of s's aliases
8309 **    (unless checkAliases (s) is FALSE).
8310 **
8311 **    For alias calls, calls as
8312 **          predf (alias, e, text, s)
8313 */
8314
8315 void
8316 sRef_aliasCheckPred (bool (predf) (sRef, exprNode, sRef, exprNode),
8317                      /*@null@*/ bool (checkAliases) (sRef),
8318                      sRef s, exprNode e, exprNode err)
8319 {
8320   bool error = (*predf)(s, e, sRef_undefined, err);
8321   
8322   
8323   if (checkAliases != NULL && !(checkAliases (s)))
8324     {
8325       /* don't check aliases */
8326     }
8327   else
8328     {
8329       sRefSet aliases = usymtab_allAliases (s);
8330       
8331       sRefSet_realElements (aliases, current)
8332         {
8333           if (sRef_isReasonable (current))
8334             {
8335               if (sRef_isReasonable (current))
8336                 {
8337                   if (!sRef_similar (current, s)
8338                       || (error && sRef_sameName (current, s)))
8339                     {
8340                       (void) (*predf)(current, e, s, err);
8341                     }
8342                 }
8343               else
8344                 {
8345                   llcontbug (message ("Invalid sRef as alias field of %s", sRef_unparse (s)));
8346                 }
8347             }
8348         } end_sRefSet_realElements;
8349
8350       sRefSet_free (aliases);
8351     }
8352 }
8353
8354 /*
8355 ** return TRUE iff predf (s) is true for s or any alias of s
8356 */
8357
8358 bool
8359 sRef_aliasCheckSimplePred (sRefTest predf, sRef s)
8360 {
8361     
8362   if ((*predf)(s))
8363     {
8364       return TRUE;
8365     }
8366   else
8367     {
8368       sRefSet aliases;
8369
8370       aliases = usymtab_allAliases (s);
8371       
8372       sRefSet_realElements (aliases, current)
8373         {
8374           if (sRef_isReasonable (current))
8375             {
8376               sRef cref = sRef_updateSref (current);
8377               
8378               /* Whoa! a very kludgey way to make sure the right sref is used
8379               ** where there is a conditional symbol table.  I am beginning
8380               ** to think that having a conditional symbol table wasn't such
8381               ** a great idea.  ;(
8382               */
8383               
8384               if ((*predf)(cref))
8385                 {
8386                   DPRINTF (("Checking alias: %s", sRef_unparseFull (cref)));
8387                   sRefSet_free (aliases);
8388                   return TRUE;
8389                 }
8390             }
8391         } end_sRefSet_realElements;
8392
8393       sRefSet_free (aliases);
8394     }
8395   return FALSE;
8396 }
8397
8398 bool
8399 sRef_aliasCompleteSimplePred (bool (predf) (sRef), sRef s)
8400 {
8401   sRefSet aliases;
8402   bool result = FALSE;
8403   
8404   
8405   aliases = usymtab_allAliases (s);
8406   
8407   if ((*predf)(s)) result = TRUE;
8408
8409   
8410   sRefSet_realElements (aliases, current)
8411     {
8412       if (sRef_isReasonable (current))
8413         {
8414           current = sRef_updateSref (current);
8415           if ((*predf)(current)) result = TRUE;
8416         }
8417     } end_sRefSet_realElements;
8418   
8419   sRefSet_free (aliases);
8420   return result;
8421 }
8422
8423 void
8424 sRef_aliasSetComplete (void (predf) (sRef, fileloc), sRef s, fileloc loc)
8425 {
8426   sRefSet aliases;
8427   
8428   aliases = usymtab_allAliases (s);
8429
8430   DPRINTF (("All aliases: %s", sRefSet_unparseFull (aliases)));
8431
8432   (*predf)(s, loc);
8433
8434   sRefSet_realElements (aliases, current)
8435     {
8436       if (sRef_isReasonable (current))
8437         {
8438           current = sRef_updateSref (current);
8439           ((*predf)(current, loc));
8440           DPRINTF (("Killed: %s", sRef_unparseFull (current)));
8441         }
8442     } end_sRefSet_realElements;
8443
8444   sRefSet_free (aliases);
8445 }
8446
8447 void
8448 sRef_aliasSetCompleteParam (void (predf) (sRef, int, fileloc), sRef s, 
8449                             int kind, fileloc loc)
8450 {
8451   sRefSet aliases;
8452   
8453   if (sRef_isDeep (s))
8454     {
8455       aliases = usymtab_allAliases (s);
8456     }
8457   else
8458     {
8459       aliases = usymtab_aliasedBy (s);
8460     }
8461
8462   (*predf)(s, kind, loc);
8463
8464   sRefSet_realElements (aliases, current)
8465     {
8466       if (sRef_isReasonable (current))
8467         {
8468           current = sRef_updateSref (current);
8469           ((*predf)(current, kind, loc));
8470         }
8471     } end_sRefSet_realElements;
8472
8473   sRefSet_free (aliases);
8474 }
8475
8476 /*
8477 ** Version of aliasSetCompleteParam for alkind parameters
8478 */
8479
8480 void
8481 sRef_aliasSetCompleteAlkParam (void (predf) (sRef, alkind, fileloc), sRef s, 
8482                                alkind kind, fileloc loc)
8483 {
8484   sRefSet aliases;
8485   
8486   if (sRef_isDeep (s))
8487     {
8488       aliases = usymtab_allAliases (s);
8489     }
8490   else
8491     {
8492       aliases = usymtab_aliasedBy (s);
8493     }
8494
8495   (*predf)(s, kind, loc);
8496
8497   sRefSet_realElements (aliases, current)
8498     {
8499       if (sRef_isReasonable (current))
8500         {
8501           current = sRef_updateSref (current);
8502           ((*predf)(current, kind, loc));
8503         }
8504     } end_sRefSet_realElements;
8505
8506   sRefSet_free (aliases);
8507 }
8508
8509 static void
8510 sRef_innerAliasSetComplete (void (predf) (sRef, fileloc), sRef s, fileloc loc)
8511 {
8512   sRef inner;
8513   sRefSet aliases;
8514   ctype ct;
8515
8516   if (!sRef_isReasonable (s)) return;
8517
8518   /*
8519   ** Type equivalence checking is necessary --- there might be casting.
8520   */
8521
8522   (*predf)(s, loc);
8523
8524   switch (s->kind)
8525     {
8526     case SK_UNCONSTRAINED:
8527     case SK_CVAR:
8528     case SK_PARAM:
8529       break;
8530     case SK_PTR:
8531       inner = s->info->ref;
8532       aliases = usymtab_allAliases (inner);
8533       ct = sRef_getType (inner);
8534       
8535       sRefSet_realElements (aliases, current)
8536         {
8537           if (sRef_isReasonable (current))
8538             {
8539               current = sRef_updateSref (current);
8540               
8541               if (ctype_equal (ct, sRef_getType (current)))
8542                 {
8543                   sRef ptr = sRef_makePointer (current);
8544                   ((*predf)(ptr, loc));
8545                 }
8546             }
8547         } end_sRefSet_realElements;
8548
8549       sRefSet_free (aliases);
8550       break;
8551     case SK_ARRAYFETCH:
8552       inner = s->info->arrayfetch->arr;
8553       aliases = usymtab_allAliases (inner);
8554       ct = sRef_getType (inner);
8555
8556       DPRINTF (("Array fetch: %s", sRefSet_unparse (aliases)));
8557
8558       sRefSet_realElements (aliases, current)
8559         {
8560           if (sRef_isReasonable (current))
8561             {
8562               current = sRef_updateSref (current);
8563               DPRINTF (("Current: %s", sRef_unparseFull (current)));
8564
8565               if (ctype_equal (ct, sRef_getType (current)))
8566                 {
8567                   if (s->info->arrayfetch->indknown)
8568                     {
8569                       sRef af = sRef_makeArrayFetchKnown (current, s->info->arrayfetch->ind);
8570                       DPRINTF (("Defining: %s", sRef_unparseFull (af)));
8571                       /* evans 2001-08-27 This isn't true:
8572                            llassert (af->info->arrayfetch->arr == current);
8573                          see comments in buildArrayFetchKnown
8574                       */
8575                       ((*predf)(af, loc));
8576                     }
8577                   else
8578                     {
8579                       sRef af = sRef_makeArrayFetch (current);
8580                       /* evans 2001-08-27 This isn't true:
8581                          llassert (af->info->arrayfetch->arr == current);
8582                          see comments in buildArrayFetch
8583                       */ 
8584                       DPRINTF (("Defining: %s", sRef_unparseFull (af)));
8585                       ((*predf)(af, loc));
8586                     }
8587                 }
8588               else
8589                 {
8590                   DPRINTF (("Type mismatch: %s / %s",
8591                             ctype_unparse (ct),
8592                             ctype_unparse (sRef_getType (current))));
8593                 }
8594             }
8595         } end_sRefSet_realElements;
8596
8597       sRefSet_free (aliases);
8598       break;
8599     case SK_FIELD:
8600       inner = s->info->field->rec;
8601       aliases = usymtab_allAliases (inner);
8602       ct = sRef_getType (inner);
8603       
8604       sRefSet_realElements (aliases, current)
8605         {
8606           if (sRef_isReasonable (current))
8607             {
8608               current = sRef_updateSref (current);
8609               
8610               if (ctype_equal (ct, sRef_getType (current)))
8611                 {
8612                   sRef f = sRef_makeField (current, s->info->field->field);
8613                   
8614                   ((*predf)(f, loc));
8615                 }
8616             }
8617         } end_sRefSet_realElements;
8618       
8619       sRefSet_free (aliases);
8620       break;
8621     case SK_CONJ:
8622       sRef_innerAliasSetComplete (predf, s->info->conj->a, loc);
8623       sRef_innerAliasSetComplete (predf, s->info->conj->b, loc);
8624       break;
8625     case SK_SPECIAL:
8626     case SK_ADR:
8627     case SK_TYPE:
8628     case SK_CONST:
8629     case SK_NEW:
8630     case SK_UNKNOWN:
8631     case SK_OBJECT:
8632     case SK_DERIVED:
8633     case SK_EXTERNAL:
8634     case SK_RESULT:
8635       break;
8636     }
8637 }
8638
8639 static void
8640 sRef_innerAliasSetCompleteParam (void (predf) (sRef, sRef), sRef s, sRef t)
8641 {
8642   sRef inner;
8643   sRefSet aliases;
8644   ctype ct;
8645
8646   if (!sRef_isReasonable (s)) return;
8647
8648   /*
8649   ** Type equivalence checking is necessary --- there might be casting.
8650   */
8651
8652   (*predf)(s, t);
8653
8654   switch (s->kind)
8655     {
8656     case SK_UNCONSTRAINED:
8657     case SK_CVAR:
8658     case SK_PARAM:
8659       break;
8660     case SK_PTR:
8661       inner = s->info->ref;
8662       aliases = usymtab_allAliases (inner);
8663       ct = sRef_getType (inner);
8664             
8665       sRefSet_realElements (aliases, current)
8666         {
8667           if (sRef_isReasonable (current))
8668             {
8669               current = sRef_updateSref (current);
8670               
8671               if (ctype_equal (ct, sRef_getType (current)))
8672                 {
8673                   sRef ptr = sRef_makePointer (current);
8674                   
8675                   ((*predf)(ptr, t));
8676                 }
8677             }
8678         } end_sRefSet_realElements;
8679
8680       sRefSet_free (aliases);
8681       break;
8682     case SK_ARRAYFETCH:
8683       inner = s->info->arrayfetch->arr;
8684       aliases = usymtab_allAliases (inner);
8685       ct = sRef_getType (inner);
8686
8687       sRefSet_realElements (aliases, current)
8688         {
8689           if (sRef_isReasonable (current))
8690             {
8691               current = sRef_updateSref (current);
8692               
8693               if (ctype_equal (ct, sRef_getType (current)))
8694                 {
8695                                   
8696                   if (s->info->arrayfetch->indknown)
8697                     {
8698                       sRef af = sRef_makeArrayFetchKnown (current, s->info->arrayfetch->ind);
8699                       
8700                       ((*predf)(af, t));
8701                     }
8702                   else
8703                     {
8704                       sRef af = sRef_makeArrayFetch (current);
8705                       
8706                       ((*predf)(af, t));
8707                     }
8708                 }
8709             }
8710         } end_sRefSet_realElements;
8711
8712       sRefSet_free (aliases);
8713       break;
8714     case SK_FIELD:
8715       inner = s->info->field->rec;
8716       aliases = usymtab_allAliases (inner);
8717       ct = sRef_getType (inner);
8718
8719       
8720       sRefSet_realElements (aliases, current)
8721         {
8722           if (sRef_isReasonable (current))
8723             {
8724               current = sRef_updateSref (current);
8725               
8726               if (ctype_equal (ct, sRef_getType (current)))
8727                 {
8728                   sRef f = sRef_makeField (current, s->info->field->field);
8729                   
8730                   ((*predf)(f, t));
8731                 }
8732             }
8733         } end_sRefSet_realElements;
8734       
8735       sRefSet_free (aliases);
8736       break;
8737     case SK_CONJ:
8738       sRef_innerAliasSetCompleteParam (predf, s->info->conj->a, t);
8739       sRef_innerAliasSetCompleteParam (predf, s->info->conj->b, t);
8740       break;
8741     case SK_SPECIAL:
8742     case SK_ADR:
8743     case SK_TYPE:
8744     case SK_CONST:
8745     case SK_NEW:
8746     case SK_UNKNOWN:
8747     case SK_OBJECT:
8748     case SK_DERIVED:
8749     case SK_EXTERNAL:
8750     case SK_RESULT:
8751       break;
8752     }
8753 }
8754
8755 static void sRef_combineExKinds (/*@notnull@*/ sRef res, /*@notnull@*/ sRef other)
8756 {
8757   exkind a1 = sRef_getExKind (res);
8758   exkind a2 = sRef_getExKind (other);
8759
8760   if (a1 == a2 || a2 == XO_UNKNOWN) 
8761     {
8762       ;
8763     }
8764   else if (a1 == XO_UNKNOWN) 
8765     { 
8766       res->expinfo = stateInfo_update (res->expinfo, other->expinfo);
8767       res->expkind = a2;
8768     }
8769   else
8770     {
8771       res->expkind = XO_OBSERVER;
8772     }
8773 }
8774
8775 /*
8776 ** Currently, this is a very ad hoc implementation, with lots of fixes to
8777 ** make real code work okay.  I need to come up with some more general
8778 ** rules or principles here.
8779 */
8780
8781 static void 
8782   sRef_combineAliasKindsError (/*@notnull@*/ sRef res, 
8783                                /*@notnull@*/ sRef other, 
8784                                clause cl, fileloc loc)
8785 {
8786   bool hasError = FALSE;
8787   alkind ares = sRef_getAliasKind (res);
8788   alkind aother = sRef_getAliasKind (other);
8789
8790   sRef_checkMutable (res);
8791
8792   if (alkind_isDependent (ares))
8793     {
8794       if (aother == AK_KEPT)
8795         {
8796           res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8797           res->aliaskind = AK_KEPT;      
8798         }
8799       else 
8800         {
8801           if (aother == AK_LOCAL || aother == AK_STATIC 
8802               || alkind_isTemp (aother))
8803             {
8804               DPRINTF (("Setting dependent: %s", sRef_unparseFull (res)));
8805               res->aliaskind = AK_DEPENDENT;
8806             }
8807         }
8808     }
8809   else if (alkind_isDependent (aother))
8810     {
8811       if (ares == AK_KEPT)
8812         {
8813           res->aliaskind = AK_KEPT;      
8814         }
8815       else 
8816         {
8817           if (ares == AK_LOCAL || ares == AK_STATIC || alkind_isTemp (ares))
8818             {
8819               DPRINTF (("Setting dependent: %s", sRef_unparseFull (res)));
8820               res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8821               res->aliaskind = AK_DEPENDENT;
8822             }
8823         }
8824     }
8825   else if ((ares == AK_LOCAL || ares == AK_UNIQUE
8826             || ares == AK_STATIC || alkind_isTemp (ares))
8827            && sRef_isFresh (other))
8828     {
8829       /*
8830       ** cases like: if (s == NULL) s = malloc...;
8831       **    don't generate errors
8832       */
8833       
8834       if (usymtab_isAltDefinitelyNullDeep (res))
8835         {
8836           res->aliaskind = ares;
8837         }
8838       else
8839         {
8840           hasError = TRUE; 
8841         }
8842     }
8843   else if ((aother == AK_LOCAL || aother == AK_UNIQUE
8844             || aother == AK_STATIC || alkind_isTemp (aother))
8845            && sRef_isFresh (res))
8846     {
8847       /*
8848       ** cases like: if (s == NULL) s = malloc...;
8849       **    don't generate errors
8850       */
8851       
8852       if (usymtab_isDefinitelyNullDeep (other))
8853         {
8854           res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8855           res->aliaskind = aother;
8856         }
8857       else
8858         {
8859           hasError = TRUE;
8860         }
8861     }
8862   else if (ares == AK_NEWREF && aother == AK_REFCOUNTED 
8863            && sRef_isConst (other))
8864     {
8865       res->aliaskind = AK_NEWREF;
8866     }
8867   else if (aother == AK_NEWREF && ares == AK_REFCOUNTED
8868            && sRef_isConst (res))
8869     {
8870       res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8871       res->aliaskind = AK_NEWREF;
8872     }
8873   else if (sRef_isLocalVar (res)
8874            && ((ares == AK_KEPT && aother == AK_LOCAL)
8875                || (aother == AK_KEPT && ares == AK_LOCAL)))
8876     {
8877       res->aliaskind = AK_KEPT;
8878     }
8879   else if ((ares == AK_OWNED && aother == AK_ONLY)
8880            || (aother == AK_OWNED && ares == AK_ONLY))
8881     {
8882       res->aliaskind = AK_OWNED;
8883
8884       if (aother == AK_OWNED)
8885         {
8886           res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8887         }
8888     }
8889   else
8890     {
8891       hasError = TRUE;
8892     }
8893
8894   if (hasError)
8895     {
8896       if (sRef_isThroughArrayFetch (res))
8897         {
8898           if (optgenerror2 
8899               (FLG_BRANCHSTATE, FLG_STRICTBRANCHSTATE,
8900                message
8901                ("Clauses exit with %q possibly referencing %s storage %s, "
8902                 "%s storage %s", 
8903                 sRef_unparse (res),
8904                 alkind_unparse (aother),
8905                 clause_nameTaken (cl),
8906                 alkind_unparse (ares),
8907                 clause_nameAlternate (cl)),
8908                loc))
8909             {
8910               sRef_showAliasInfo (res);
8911               sRef_showAliasInfo (other);
8912               res->aliaskind = AK_ERROR;
8913             }
8914           else
8915             {
8916               if (ares == AK_KEPT || aother == AK_KEPT)
8917                 {
8918                   sRef_maybeKill (res, loc);
8919                 }
8920             }
8921         }
8922       else 
8923         {
8924           if (optgenerror 
8925               (FLG_BRANCHSTATE,
8926                message ("Clauses exit with %q referencing %s storage %s, "
8927                         "%s storage %s", 
8928                         sRef_unparse (res),
8929                         alkind_unparse (aother),
8930                         clause_nameTaken (cl),
8931                         alkind_unparse (ares),
8932                         clause_nameAlternate (cl)),
8933                loc))
8934             {
8935               sRef_showAliasInfo (res);
8936               sRef_showAliasInfo (other);
8937               
8938               res->aliaskind = AK_ERROR;
8939             }
8940         }
8941       
8942       res->aliaskind = (sRef_isLocalVar (res) ? AK_LOCAL : AK_UNKNOWN);
8943     }
8944 }
8945
8946 static void 
8947   sRef_combineAliasKinds (/*@notnull@*/ sRef res, /*@notnull@*/ sRef other, 
8948                           clause cl, fileloc loc)
8949 {
8950   alkind ares = sRef_getAliasKind (res);
8951   alkind aother = sRef_getAliasKind (other);
8952
8953   sRef_checkMutable (res);
8954
8955   DPRINTF (("Combine alias kinds: \n\t%s / \n\t%s",
8956             sRef_unparseFull (res), sRef_unparseFull (other)));
8957   if (alkind_equal (ares, aother)
8958       || aother == AK_UNKNOWN
8959       || aother == AK_ERROR)
8960     {
8961       ; /* keep current state */
8962     }
8963   else if (sRef_isDead (res) || sRef_isDead (other))
8964     {
8965       /* dead error reported (or storage is dead) */
8966       res ->aliaskind = AK_ERROR; 
8967     }
8968   else if (ares == AK_UNKNOWN || ares == AK_ERROR
8969            || sRef_isStateUndefined (res)
8970            || sRef_isDefinitelyNull (res))
8971     { 
8972       res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8973       res->aliaskind = aother;  
8974     }
8975   else if (sRef_isStateUndefined (other)
8976            || sRef_isDefinitelyNull (other))
8977     {
8978       ;
8979     }
8980   else if (((ares == AK_UNIQUE || alkind_isTemp (ares))
8981             && aother == AK_LOCAL) 
8982            || ((aother == AK_UNIQUE || alkind_isTemp (aother))
8983                && ares == AK_LOCAL))
8984     {
8985       if (ares != AK_LOCAL)
8986         {
8987           res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8988         }
8989
8990       res->aliaskind = AK_LOCAL;
8991     }
8992   else if ((ares == AK_OWNED && aother == AK_FRESH) 
8993            || (aother == AK_OWNED && ares == AK_FRESH))
8994     {
8995       if (ares != AK_FRESH)
8996         {
8997           res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8998         }
8999       
9000       res->aliaskind = AK_FRESH;
9001     }
9002   else if ((ares == AK_KEEP && aother == AK_FRESH) ||
9003            (aother == AK_KEEP && ares == AK_FRESH))
9004     {
9005       if (ares != AK_KEEP)
9006         {
9007           res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
9008         }
9009       
9010       res->aliaskind = AK_KEEP;
9011     }
9012   else if ((ares == AK_LOCAL && aother == AK_STACK) ||
9013            (aother == AK_LOCAL && ares == AK_STACK))
9014     {
9015       if (ares != AK_STACK)
9016         {
9017           res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
9018         }
9019
9020       res->aliaskind = AK_STACK;
9021     }
9022   else if ((ares == AK_LOCAL
9023             && (aother == AK_OWNED && sRef_isLocalVar (other)))
9024            || (aother == AK_LOCAL 
9025                && (ares == AK_OWNED && sRef_isLocalVar (res))))
9026     {
9027       if (ares != AK_LOCAL)
9028         {
9029           res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
9030         }
9031
9032       res->aliaskind = AK_LOCAL;
9033     }
9034   else if ((ares == AK_FRESH && alkind_isOnly (aother))
9035            || (aother == AK_FRESH && alkind_isOnly (ares)))
9036     {
9037       res->aliaskind = AK_FRESH;
9038     }
9039   else if ((aother == AK_FRESH && sRef_definitelyNull (res))
9040            || (ares == AK_FRESH && sRef_definitelyNull (other)))
9041     {
9042       if (ares != AK_FRESH)
9043         {
9044           res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
9045           res->aliaskind = AK_FRESH;
9046         }
9047     }
9048   else if ((sRef_isFresh (res) && sRef_isConst (other))
9049            || (sRef_isFresh (other) && sRef_isConst (res)))
9050     {
9051       /*
9052       ** for NULL constantants
9053       ** this is bogus!
9054       */
9055
9056       if (!sRef_isFresh (res))
9057         {
9058           res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
9059         }
9060
9061       res->aliaskind = AK_FRESH;
9062     }
9063   else if ((alkind_isStatic (aother) && sRef_isConst (res))
9064            || (alkind_isStatic (ares) && sRef_isConst (other)))
9065     {
9066       if (!alkind_isStatic (ares))
9067         {
9068           res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
9069           res->aliaskind = AK_STATIC;
9070         }
9071     }
9072   else
9073     {
9074       sRef_combineAliasKindsError (res, other, cl, loc);
9075     }
9076 }
9077
9078 static void sRef_combineDefState (/*@notnull@*/ sRef res, 
9079                                   /*@notnull@*/ sRef other)
9080 {
9081   sstate s1 = res->defstate;
9082   sstate s2 = other->defstate;
9083   bool flip = FALSE;
9084
9085   sRef_checkMutable (res);
9086
9087   if (s1 == s2 || s2 == SS_UNKNOWN)
9088     {
9089       ;
9090     }
9091   else if (s1 == SS_UNKNOWN)
9092     {
9093       flip = TRUE;
9094     }
9095   else
9096     {
9097       switch (s1)
9098         {
9099         case SS_FIXED:   
9100           if (s2 == SS_DEFINED) 
9101             {
9102               break;
9103             }
9104           else
9105             {
9106               llcontbuglit ("ssfixed: not implemented");
9107               flip = TRUE;
9108             }
9109           break;
9110         case SS_DEFINED: 
9111           flip = TRUE;
9112           break;
9113         case SS_PDEFINED:
9114         case SS_ALLOCATED: 
9115           flip = (s2 != SS_DEFINED);
9116           break;
9117         case SS_HOFFA:
9118         case SS_RELDEF:
9119         case SS_UNUSEABLE: 
9120         case SS_UNDEFINED: 
9121         case SS_PARTIAL:
9122         case SS_UNDEFGLOB:
9123         case SS_KILLED:
9124         case SS_DEAD:      
9125         case SS_SPECIAL: 
9126           break;
9127         BADDEFAULT;
9128         }
9129     }
9130
9131   if (flip)
9132     {
9133       res->definfo = stateInfo_update (res->definfo, other->definfo);
9134       res->defstate = s2;
9135     }
9136 }
9137
9138 extern /*@notnull@*/ sRef sRef_getConjA (sRef s)
9139 {
9140   sRef ret;
9141   llassert (sRef_isConj (s));
9142
9143   ret = s->info->conj->a;
9144   llassert (ret != NULL);
9145   return ret;
9146 }
9147
9148 extern /*@notnull@*/ sRef sRef_getConjB (sRef s)
9149 {
9150   sRef ret;
9151   llassert (sRef_isConj (s));
9152
9153   ret = s->info->conj->b;
9154   llassert (ret != NULL);
9155   return ret;
9156 }
9157   
9158 extern /*@exposed@*/ sRef sRef_makeArrow (sRef s, /*@dependent@*/ cstring f)
9159 {
9160   sRef p;
9161   sRef ret;
9162   
9163   p = sRef_makePointer (s);
9164   ret = sRef_makeField (p, f);
9165   DPRINTF (("Arrow: %s => %s",
9166             sRef_unparseFull (s), sRef_unparseFull (ret)));
9167   return ret;
9168 }
9169
9170 extern /*@exposed@*/ sRef sRef_buildArrow (sRef s, cstring f)
9171 {
9172   sRef p;
9173   sRef ret;
9174
9175   p = sRef_buildPointer (s);
9176   ret = sRef_buildField (p, f);
9177   
9178   return ret;
9179 }
9180
9181 static /*@null@*/ sinfo sinfo_copy (/*@notnull@*/ sRef s)
9182 {
9183   sinfo ret;
9184
9185   switch (s->kind)
9186     {
9187     case SK_CVAR:
9188       ret = (sinfo) dmalloc (sizeof (*ret));
9189       ret->cvar = (cref) dmalloc (sizeof (*ret->cvar));
9190       ret->cvar->lexlevel = s->info->cvar->lexlevel; 
9191       ret->cvar->index = s->info->cvar->index; 
9192       break;
9193
9194     case SK_PARAM:
9195       ret = (sinfo) dmalloc (sizeof (*ret));
9196       ret->paramno = s->info->paramno; 
9197       llassert (ret->paramno >= -1);
9198       break;
9199
9200     case SK_ARRAYFETCH:
9201       ret = (sinfo) dmalloc (sizeof (*ret));
9202       ret->arrayfetch = (ainfo) dmalloc (sizeof (*ret->arrayfetch));
9203       ret->arrayfetch->indknown = s->info->arrayfetch->indknown;
9204       ret->arrayfetch->ind = s->info->arrayfetch->ind;
9205       ret->arrayfetch->arr = s->info->arrayfetch->arr; 
9206       break;
9207
9208     case SK_FIELD:
9209       ret = (sinfo) dmalloc (sizeof (*ret));
9210       ret->field = (fldinfo) dmalloc (sizeof (*ret->field));
9211       ret->field->rec = s->info->field->rec; 
9212       ret->field->field = s->info->field->field; 
9213       break;
9214
9215     case SK_OBJECT:
9216       ret = (sinfo) dmalloc (sizeof (*ret));
9217       ret->object = s->info->object;
9218       break;
9219
9220     case SK_PTR:
9221     case SK_ADR:
9222     case SK_DERIVED:
9223     case SK_EXTERNAL:
9224       ret = (sinfo) dmalloc (sizeof (*ret));
9225       ret->ref = s->info->ref; /* Ref_copy (s->info->ref); */
9226       break;
9227
9228     case SK_CONJ:
9229       ret = (sinfo) dmalloc (sizeof (*ret));
9230       ret->conj = (cjinfo) dmalloc (sizeof (*ret->conj));
9231       ret->conj->a = s->info->conj->a; /* sRef_copy (s->info->conj->a); */
9232       ret->conj->b = s->info->conj->b; /* sRef_copy (s->info->conj->b);*/
9233       break;
9234     case SK_SPECIAL:
9235       ret = (sinfo) dmalloc (sizeof (*ret));
9236       ret->spec = s->info->spec;
9237       break;
9238
9239     case SK_UNCONSTRAINED:
9240     case SK_NEW:
9241       ret = (sinfo) dmalloc (sizeof (*ret));
9242       ret->fname = s->info->fname;
9243       break;
9244
9245     case SK_RESULT:
9246     case SK_CONST:
9247     case SK_TYPE:
9248     case SK_UNKNOWN:
9249       llassertprint (s->info == NULL, ("s = %s", sRef_unparse (s)));
9250       ret = NULL;
9251       break;
9252     }
9253
9254   return ret;
9255 }
9256
9257 static /*@null@*/ sinfo sinfo_fullCopy (/*@notnull@*/ sRef s)
9258 {
9259   sinfo ret;
9260
9261   /*
9262   ** Since its a full copy, only storage is assigned
9263   ** to dependent fields.
9264   */
9265   /*@-onlytrans@*/
9266
9267   switch (s->kind)
9268     {
9269     case SK_CVAR:
9270       ret = (sinfo) dmalloc (sizeof (*ret));
9271       ret->cvar = (cref) dmalloc (sizeof (*ret->cvar));
9272       ret->cvar->lexlevel = s->info->cvar->lexlevel; 
9273       ret->cvar->index = s->info->cvar->index; 
9274       break;
9275
9276     case SK_PARAM:
9277       ret = (sinfo) dmalloc (sizeof (*ret));
9278       ret->paramno = s->info->paramno; 
9279       llassert (ret->paramno >= -1);
9280       break;
9281
9282     case SK_ARRAYFETCH:
9283       ret = (sinfo) dmalloc (sizeof (*ret));
9284       ret->arrayfetch = (ainfo) dmalloc (sizeof (*ret->arrayfetch));
9285       ret->arrayfetch->indknown = s->info->arrayfetch->indknown;
9286       ret->arrayfetch->ind = s->info->arrayfetch->ind;
9287       ret->arrayfetch->arr = sRef_saveCopy (s->info->arrayfetch->arr);
9288       break;
9289
9290     case SK_FIELD:
9291       ret = (sinfo) dmalloc (sizeof (*ret));
9292       ret->field = (fldinfo) dmalloc (sizeof (*ret->field));
9293       ret->field->rec = sRef_saveCopy (s->info->field->rec);
9294       ret->field->field = s->info->field->field; 
9295       break;
9296
9297     case SK_OBJECT:
9298       ret = (sinfo) dmalloc (sizeof (*ret));
9299       ret->object = s->info->object;
9300       break;
9301
9302     case SK_PTR:
9303     case SK_ADR:
9304     case SK_DERIVED:
9305     case SK_EXTERNAL:
9306       ret = (sinfo) dmalloc (sizeof (*ret));
9307       ret->ref = sRef_saveCopy (s->info->ref);   
9308       break;
9309
9310     case SK_CONJ:
9311       ret = (sinfo) dmalloc (sizeof (*ret));
9312       ret->conj = (cjinfo) dmalloc (sizeof (*ret->conj));
9313       ret->conj->a = sRef_saveCopy (s->info->conj->a);
9314       ret->conj->b = sRef_saveCopy (s->info->conj->b);
9315       break;
9316     case SK_SPECIAL:
9317       ret = (sinfo) dmalloc (sizeof (*ret));
9318       ret->spec = s->info->spec;
9319       break;
9320     case SK_NEW:
9321     case SK_UNCONSTRAINED:
9322       ret = (sinfo) dmalloc (sizeof (*ret));
9323       ret->fname = s->info->fname;
9324       break;
9325     case SK_CONST:
9326     case SK_TYPE:
9327     case SK_RESULT:
9328     case SK_UNKNOWN:
9329       llassert (s->info == NULL);
9330       ret = NULL;
9331       break;
9332     }
9333   /*@=onlytrans@*/ 
9334   return ret;
9335 }
9336
9337
9338 static void 
9339   sinfo_update (/*@notnull@*/ /*@exposed@*/ sRef res, 
9340                 /*@notnull@*/ /*@exposed@*/ sRef other)
9341 {
9342   llassert (res->kind == other->kind);
9343
9344   switch (res->kind)
9345     {
9346     case SK_CVAR:
9347       res->info->cvar->lexlevel = other->info->cvar->lexlevel; 
9348       res->info->cvar->index = other->info->cvar->index; 
9349       break;
9350
9351     case SK_PARAM:
9352       res->info->paramno = other->info->paramno; 
9353       llassert (res->info->paramno >= -1);
9354       break;
9355
9356     case SK_ARRAYFETCH:
9357       res->info->arrayfetch->indknown = other->info->arrayfetch->indknown;
9358       res->info->arrayfetch->ind = other->info->arrayfetch->ind;
9359       res->info->arrayfetch->arr = other->info->arrayfetch->arr;
9360       break;
9361
9362     case SK_FIELD:
9363       res->info->field->rec = other->info->field->rec;
9364       res->info->field->field = other->info->field->field; 
9365       break;
9366
9367     case SK_OBJECT:
9368       res->info->object = other->info->object;
9369       break;
9370
9371     case SK_PTR:
9372     case SK_ADR:
9373     case SK_DERIVED:
9374     case SK_EXTERNAL:
9375       res->info->ref = other->info->ref;         
9376       break;
9377
9378     case SK_CONJ:
9379       res->info->conj->a = other->info->conj->a;
9380       res->info->conj->b = other->info->conj->b;
9381       break;
9382
9383     case SK_SPECIAL:
9384       res->info->spec = other->info->spec;
9385       break;
9386
9387     case SK_NEW:
9388     case SK_UNCONSTRAINED:
9389       res->info->fname = other->info->fname;
9390       break;
9391
9392     case SK_CONST:
9393     case SK_TYPE:
9394     case SK_UNKNOWN:
9395     case SK_RESULT:
9396       llassert (res->info == NULL);
9397       break;
9398     }
9399 }
9400
9401 static void sinfo_free (/*@special@*/ /*@temp@*/ /*@notnull@*/ sRef s)
9402    /*@uses s->kind, s->info@*/
9403    /*@releases s->info@*/ 
9404 {
9405   switch (s->kind)
9406     {
9407     case SK_CVAR:
9408       DPRINTF (("Free sinfo: [%p]", s->info->cvar));
9409       sfree (s->info->cvar);
9410       break;
9411
9412     case SK_PARAM:
9413       break;
9414
9415     case SK_ARRAYFETCH:
9416       DPRINTF (("Free sinfo: [%p]", s->info->arrayfetch));
9417       sfree (s->info->arrayfetch);
9418       break;
9419
9420     case SK_FIELD:
9421       DPRINTF (("Free sinfo: [%p]", s->info->field));
9422       sfree (s->info->field); 
9423       break;
9424
9425     case SK_OBJECT:
9426       break;
9427
9428     case SK_PTR:
9429     case SK_ADR:
9430     case SK_DERIVED:
9431     case SK_EXTERNAL: /* is copy now! */
9432       break;
9433
9434     case SK_CONJ:
9435       DPRINTF (("Free sinfo: [%p]", s->info->conj));
9436       sfree (s->info->conj);
9437       break;
9438
9439     case SK_UNCONSTRAINED:
9440     case SK_SPECIAL:
9441     case SK_CONST:
9442     case SK_NEW:
9443     case SK_TYPE:
9444     case SK_UNKNOWN:
9445     case SK_RESULT:
9446       break;
9447     }
9448
9449   if (s->info != NULL) {
9450       DPRINTF (("Free sinfo: [%p]", s->info));
9451   }
9452
9453   sfree (s->info);
9454 }
9455
9456 bool sRef_isNSLocalVar (sRef s)  
9457 {
9458   if (sRef_isLocalVar (s))
9459     {
9460       uentry ue = sRef_getUentry (s);
9461
9462       return (!uentry_isStatic (ue));
9463     }
9464   else
9465     {
9466       return FALSE;
9467     }
9468 }
9469
9470 bool sRef_isLocalVar (sRef s)  
9471 {
9472   if (sRef_isValid(s))
9473     {
9474       return (s->kind == SK_CVAR 
9475               && (s->info->cvar->lexlevel > fileScope));
9476     }
9477   
9478   return FALSE;
9479 }
9480
9481 bool sRef_isRealLocalVar (sRef s)  
9482 {
9483   if (sRef_isValid(s))
9484     {
9485       if (s->kind == SK_CVAR)
9486         {
9487           if (s->info->cvar->lexlevel == functionScope)
9488             {
9489               uentry ue = sRef_getUentry (s);
9490
9491               if (uentry_isAnyParam (ue)
9492                   || uentry_isRefParam (ue))
9493                 {
9494                   return FALSE;
9495                 }
9496               else
9497                 {
9498                   return TRUE;
9499                 }
9500             }
9501           else
9502             {
9503               return (s->info->cvar->lexlevel > functionScope);
9504             }
9505         }
9506     }
9507   
9508   return FALSE;
9509 }
9510
9511 bool sRef_isLocalParamVar (sRef s)  
9512 {
9513   if (sRef_isValid(s))
9514     {
9515       return (s->kind == SK_PARAM
9516               || (s->kind == SK_CVAR 
9517                   && (s->info->cvar->lexlevel > fileScope)));
9518     }
9519   
9520   return FALSE;
9521 }
9522
9523 static speckind speckind_fromInt (int i)
9524 {
9525   /*@+enumint@*/ 
9526   llassert (i >= SR_NOTHING && i <= SR_SYSTEM); 
9527   /*@=enumint@*/
9528
9529   return ((speckind) i);
9530 }
9531
9532
9533 static void sRef_updateNullState (/*@notnull@*/ sRef res, /*@notnull@*/ sRef other)
9534      /*@modifies res@*/
9535 {
9536   res->nullstate = other->nullstate;
9537   res->nullinfo = stateInfo_update (res->nullinfo, other->nullinfo);
9538   sRef_resetAliasKind (res);
9539 }
9540
9541 void sRef_combineNullState (/*@notnull@*/ sRef res, /*@notnull@*/ sRef other)
9542 {
9543   nstate n1 = sRef_getNullState (res);
9544   nstate n2 = sRef_getNullState (other);
9545   bool flip = FALSE;
9546   nstate nn = n1;
9547
9548   if (n1 == n2 || n2 == NS_UNKNOWN)
9549     {
9550       ;
9551     }
9552   else
9553     {
9554       /* note: n2 is not unknown or defnull */
9555
9556       switch (n1)
9557         {
9558         case NS_ERROR:   nn = NS_ERROR; break;
9559         case NS_UNKNOWN: flip = TRUE; nn = n2; break; 
9560         case NS_POSNULL: break;
9561         case NS_DEFNULL: nn = NS_POSNULL; break;
9562         case NS_RELNULL: break;
9563         case NS_NOTNULL:  
9564           if (n2 == NS_MNOTNULL)
9565             {
9566               ;
9567             }
9568           else 
9569             { 
9570               flip = TRUE;
9571               nn = NS_POSNULL; 
9572             }
9573           break;
9574         case NS_MNOTNULL: 
9575           if (n2 == NS_NOTNULL) 
9576             {
9577               nn = NS_NOTNULL; 
9578             }
9579           else 
9580             {
9581               flip = TRUE;
9582               nn = NS_POSNULL; 
9583             }
9584           break;
9585         case NS_CONSTNULL:
9586         case NS_ABSNULL:
9587           flip = TRUE;
9588           nn = n2;
9589         }
9590     }
9591   
9592   if (flip)
9593     {
9594       res->nullinfo = stateInfo_update (res->nullinfo, other->nullinfo);      
9595     }
9596
9597   res->nullstate = nn;
9598   sRef_resetAliasKind (res);
9599 }
9600
9601 cstring sRef_nullMessage (sRef s)
9602 {
9603   llassert (sRef_isReasonable (s));
9604
9605   switch (sRef_getNullState (s))
9606     {
9607     case NS_DEFNULL:
9608     case NS_CONSTNULL:
9609       return (cstring_makeLiteralTemp ("null"));
9610     default:
9611       return (cstring_makeLiteralTemp ("possibly null"));
9612     }
9613   BADEXIT;
9614 }
9615
9616 /*@observer@*/ cstring sRef_ntMessage (sRef s)
9617 {
9618   llassert (sRef_isReasonable (s));
9619
9620   switch (s->nullstate)
9621     {
9622     case NS_DEFNULL:
9623     case NS_CONSTNULL:
9624       return (cstring_makeLiteralTemp ("not nullterminated"));
9625     default:
9626       return (cstring_makeLiteralTemp ("possibly non-nullterminated"));
9627     }
9628   BADEXIT;
9629 }
9630
9631
9632
9633 sRef sRef_fixResultType (/*@returned@*/ sRef s, ctype typ, uentry ue)
9634 {
9635   sRef tmp = sRef_undefined;
9636   sRef ret;
9637
9638   llassert (sRef_isReasonable (s));
9639
9640   switch (s->kind)
9641     {
9642     case SK_RESULT:
9643       s->type = typ;
9644       ret = s;
9645       break;
9646     case SK_ARRAYFETCH:
9647       {
9648         ctype ct;
9649         tmp = sRef_fixResultType (s->info->arrayfetch->arr, typ, ue);
9650
9651         ct = ctype_realType (sRef_getType (tmp));
9652
9653         
9654         if (ctype_isKnown (ct))
9655           {
9656             if (ctype_isAP (ct))
9657               {
9658                 ;
9659               }
9660             else
9661               {
9662                 voptgenerror 
9663                   (FLG_TYPE,
9664                    message
9665                    ("Special clause indexes non-array (%t): *%q",
9666                     ct, sRef_unparse (s->info->arrayfetch->arr)),
9667                    uentry_whereLast (ue));
9668               }
9669           }
9670
9671         tmp = sRef_fixResultType (s->info->arrayfetch->arr, typ, ue);
9672
9673         if (s->info->arrayfetch->indknown)
9674           {
9675             ret = sRef_makeArrayFetchKnown (tmp, s->info->arrayfetch->ind);
9676           }
9677         else
9678           {
9679             ret = sRef_makeArrayFetch (tmp);
9680           }
9681       }
9682       break;
9683     case SK_FIELD:
9684       {
9685         sRef rec = sRef_fixResultType (s->info->field->rec, typ, ue);
9686         ctype ct = ctype_realType (sRef_getType (rec));
9687
9688         if (ctype_isKnown (ct))
9689           {
9690             if (ctype_isSU (ct))
9691               {
9692                 if (uentry_isValid (uentryList_lookupField (ctype_getFields (ct), 
9693                                                             s->info->field->field)))
9694                   {
9695                     ;
9696                   }
9697                 else
9698                   {
9699                     voptgenerror 
9700                       (FLG_TYPE,
9701                        message
9702                        ("Special clause accesses non-existent field of result: %q.%s",
9703                         sRef_unparse (rec), s->info->field->field),
9704                        uentry_whereLast (ue));
9705                   }
9706               }
9707             else
9708               {
9709                 voptgenerror 
9710                   (FLG_TYPE,
9711                    message
9712                    ("Special clause accesses field of non-struct or union result (%t): %q.%s",
9713                     ct, sRef_unparse (rec), s->info->field->field),
9714                    uentry_whereLast (ue));
9715               }
9716           }
9717         
9718         ret = sRef_makeField (tmp, s->info->field->field);
9719         break;
9720       }
9721     case SK_PTR:
9722       {
9723         ctype ct;
9724         tmp = sRef_fixResultType (s->info->ref, typ, ue);
9725
9726         ct = ctype_realType (sRef_getType (tmp));
9727
9728         if (ctype_isKnown (ct))
9729           {
9730             if (ctype_isAP (ct))
9731               {
9732                 ;
9733               }
9734             else
9735               {
9736                 voptgenerror 
9737                   (FLG_TYPE,
9738                    message
9739                    ("Special clause dereferences non-pointer (%t): *%q",
9740                     ct, sRef_unparse (s->info->ref)),
9741                    uentry_whereLast (ue));
9742               }
9743           }
9744         
9745         ret = sRef_makePointer (tmp);
9746         break;
9747       }
9748     case SK_ADR:
9749       voptgenerror 
9750         (FLG_TYPE,
9751          message
9752          ("Special clause uses & operator (not allowed): &%q", sRef_unparse (s->info->ref)),
9753          uentry_whereLast (ue));
9754       ret = s;
9755       break;
9756     BADDEFAULT;
9757     }
9758
9759   return ret;
9760 }
9761
9762 bool sRef_isOnly (sRef s)
9763 {
9764   return (sRef_isValid(s) && alkind_isOnly (s->aliaskind));
9765 }
9766
9767 bool sRef_isDependent (sRef s) 
9768 {
9769   return (sRef_isValid(s) && alkind_isDependent (s->aliaskind));
9770 }
9771
9772 bool sRef_isOwned (sRef s)
9773 {
9774   return (sRef_isReasonable (s) && (s->aliaskind == AK_OWNED));
9775 }
9776
9777 bool sRef_isKeep (sRef s) 
9778 {
9779   return (sRef_isReasonable (s) && (s->aliaskind == AK_KEEP));
9780 }
9781
9782 bool sRef_isTemp (sRef s)
9783 {
9784   return (sRef_isReasonable (s) && alkind_isTemp (s->aliaskind));
9785 }
9786
9787 bool sRef_isLocalState (sRef s) 
9788 {
9789   return (sRef_isReasonable (s) && (s->aliaskind == AK_LOCAL));
9790 }
9791
9792 bool sRef_isUnique (sRef s)
9793 {
9794   return (sRef_isReasonable (s) && (s->aliaskind == AK_UNIQUE));
9795 }
9796
9797 bool sRef_isShared (sRef s) 
9798 {
9799   return (sRef_isReasonable (s) && (s->aliaskind == AK_SHARED));
9800 }
9801
9802 bool sRef_isExposed (sRef s) 
9803 {
9804   return (sRef_isReasonable (s) && (s->expkind == XO_EXPOSED));
9805 }
9806
9807 bool sRef_isObserver (sRef s) 
9808 {
9809   return (sRef_isReasonable (s) && (s->expkind == XO_OBSERVER));
9810 }
9811
9812 bool sRef_isFresh (sRef s) 
9813 {
9814   return (sRef_isReasonable (s) && (s->aliaskind == AK_FRESH));
9815 }
9816
9817 bool sRef_isDefinitelyNull (sRef s) 
9818 {
9819   return (sRef_isReasonable (s) && (sRef_getNullState (s) == NS_DEFNULL 
9820                                || sRef_getNullState (s) == NS_CONSTNULL));
9821 }
9822
9823 bool sRef_isAllocated (sRef s)
9824 {
9825   return (sRef_isReasonable (s) && (s->defstate == SS_ALLOCATED));
9826 }
9827
9828 bool sRef_isStack (sRef s)
9829 {
9830   return (sRef_isReasonable (s) && (s->aliaskind == AK_STACK));
9831 }
9832
9833 bool sRef_isNotNull (sRef s)
9834 {
9835   return (sRef_isValid(s) && (sRef_getNullState (s) == NS_MNOTNULL 
9836                               || sRef_getNullState (s) == NS_NOTNULL));
9837 }
9838
9839 alkind sRef_getAliasKind (sRef s)
9840 {
9841   if (sRef_isValid(s)) {
9842     llassert (alkind_isValid (s->aliaskind));
9843     return s->aliaskind;
9844   }
9845
9846   return AK_ERROR;
9847 }
9848
9849 nstate sRef_getNullState (sRef s)
9850 {
9851   if (sRef_isReasonable (s)) {
9852     llassert (nstate_isValid (s->nullstate));
9853     return s->nullstate;
9854   }
9855   
9856   return NS_UNKNOWN;
9857 }
9858
9859 void sRef_reflectAnnotation (sRef s, annotationInfo a, fileloc loc)
9860 {
9861   if (sRef_isReasonable (s))
9862     {
9863       if (!valueTable_isDefined (s->state))
9864         {
9865           s->state = valueTable_create (1);
9866           valueTable_insert
9867             (s->state, 
9868              cstring_copy (metaStateInfo_getName (annotationInfo_getState (a))),
9869              stateValue_create (annotationInfo_getValue (a), 
9870                                 stateInfo_makeLoc (loc, SA_DECLARED)));
9871         }
9872       else
9873         {
9874           DPRINTF (("reflect loc: %s", fileloc_unparse (loc)));
9875           valueTable_update 
9876             (s->state,
9877              metaStateInfo_getName (annotationInfo_getState (a)),
9878              stateValue_create (annotationInfo_getValue (a),
9879                                 stateInfo_makeLoc (loc, SA_DECLARED)));
9880           
9881           DPRINTF (("sref: %s", sRef_unparse (s)));
9882           DPRINTF (("sref: %s", sRef_unparseFull (s)));
9883         }
9884     }
9885 }
9886
9887 void sRef_setMetaStateValueComplete (sRef s, cstring key, int value, fileloc loc)
9888 {
9889   sRefSet aliases = usymtab_allAliases (s);
9890
9891   sRef_setMetaStateValue (s, key, value, loc);
9892
9893   sRefSet_realElements (aliases, current)
9894     {
9895       if (sRef_isReasonable (current))
9896         {
9897           current = sRef_updateSref (current);
9898           sRef_setMetaStateValue (current, key, value, loc);
9899         }
9900     } end_sRefSet_realElements ;
9901
9902   sRefSet_free (aliases);
9903 }
9904
9905 void sRef_setMetaStateValue (sRef s, cstring key, int value, fileloc loc)
9906 {
9907   sRef_checkMutable (s);
9908
9909   if (sRef_isReasonable (s))
9910     {
9911       if (!valueTable_isDefined (s->state))
9912         {
9913           DPRINTF (("inserting state: %s: %s %d", sRef_unparse (s), key, value));
9914           s->state = valueTable_create (1);
9915           valueTable_insert (s->state, cstring_copy (key),
9916                              stateValue_create (value, 
9917                                                 stateInfo_makeLoc (loc, SA_CHANGED)));
9918         }
9919       else
9920         {
9921           DPRINTF (("Updating state: %s: %s %d / %s", sRef_unparse (s), key, value,
9922                     fileloc_unparse (loc)));
9923           if (valueTable_contains (s->state, key))
9924             {
9925               valueTable_update 
9926                 (s->state, key, stateValue_create (value,
9927                                                    stateInfo_makeLoc (loc, SA_CHANGED)));
9928             }
9929           else
9930             {
9931               valueTable_insert 
9932                 (s->state, cstring_copy (key),
9933                  stateValue_create (value, stateInfo_makeLoc (loc, SA_CHANGED)));
9934             }
9935
9936           DPRINTF (("After: %s", sRef_unparseFull (s)));
9937         }
9938     }
9939 }
9940
9941 bool sRef_checkMetaStateValue (sRef s, cstring key, int value)
9942 {
9943   if (sRef_isReasonable (s))
9944     {
9945       if (valueTable_isDefined (s->state))
9946         {
9947           stateValue val;
9948           
9949           DPRINTF (("check state: %s: %s %d", sRef_unparse (s), key, value));
9950           
9951           val = valueTable_lookup (s->state, key);
9952           llassert (stateValue_isDefined (val));
9953           return (stateValue_isError (val)
9954                   || stateValue_getValue (val) == value);
9955         }
9956       else
9957         {
9958           return TRUE;
9959         }
9960     }
9961   else
9962     {
9963       return TRUE;
9964     }
9965 }
9966
9967 /*@observer@*/ stateValue sRef_getMetaStateValue (sRef s, cstring key)
9968 {
9969   if (sRef_isReasonable (s))
9970     {
9971       if (valueTable_isDefined (s->state))
9972         {
9973           stateValue val;
9974           
9975           val = valueTable_lookup (s->state, key);
9976           /* Okay if its not defined, just returns stateValue_undefined */
9977           return val;
9978         }
9979       else
9980         {
9981           return stateValue_undefined;
9982         }
9983     }
9984   else
9985     {
9986       return stateValue_undefined;
9987     }
9988 }
9989
9990 /*@observer@*/ valueTable sRef_getValueTable (sRef s) 
9991 {
9992   DPRINTF (("Get value table: %s", sRef_unparse (s)));
9993
9994   if (sRef_isReasonable (s)) 
9995     {
9996       llassert (sRef_isReasonable (s));
9997       DPRINTF (("Value table: %s", valueTable_unparse (s->state)));
9998       return s->state;
9999     }  
10000   else 
10001     {
10002       DPRINTF (("No value table!"));
10003       return valueTable_undefined;
10004     }
10005 }
10006
10007 bool sRef_makeStateSpecial (sRef s)
10008 {
10009   /*
10010   ** Default defined state can be made special.
10011   */
10012
10013   llassert (sRef_isReasonable (s));
10014
10015   if (s->defstate == SS_UNKNOWN || s->defstate == SS_DEFINED || s->defstate == SS_SPECIAL)
10016     {
10017       /* s->aliaskind = AK_IMPTEMP; */ /* evans 2001-07-23 shouldn't effect alias state */
10018       s->defstate = SS_SPECIAL;
10019       DPRINTF (("Made special: %s", sRef_unparseFull (s)));
10020       return TRUE;
10021     }
10022   else
10023     {
10024       /* s->aliaskind = AK_IMPTEMP; */
10025       s->defstate = SS_SPECIAL;
10026       return FALSE;
10027     }
10028 }
10029
10030 void sRef_markImmutable (sRef s)
10031 {
10032   if (sRef_isReasonable (s))
10033     {
10034       DPRINTF (("Mark immutable: %s", sRef_unparseFull (s)));
10035       s->immut = TRUE;
10036     }
10037 }
10038
10039 bool sRef_definitelyNullContext (sRef s)
10040 {
10041   return (sRef_definitelyNull (s)
10042           || usymtab_isDefinitelyNullDeep (s));
10043 }
10044
10045 bool sRef_definitelyNullAltContext (sRef s)
10046 {
10047   return (sRef_definitelyNull (s)
10048           || usymtab_isAltDefinitelyNullDeep (s));
10049 }
10050
10051
10052 /* start modifications */
10053 struct s_bbufinfo sRef_getNullTerminatedState (sRef p_s) {
10054    struct s_bbufinfo BUFSTATE_UNKNOWN;
10055    BUFSTATE_UNKNOWN.bufstate = BB_NOTNULLTERMINATED;
10056    BUFSTATE_UNKNOWN.size = 0;
10057    BUFSTATE_UNKNOWN.len = 0;
10058    
10059    if (sRef_isValid(p_s))
10060       return p_s->bufinfo;
10061    return BUFSTATE_UNKNOWN; 
10062 }
10063
10064 void sRef_setNullTerminatedState(sRef p_s) {
10065    if(sRef_isReasonable (p_s)) {
10066       p_s->bufinfo.bufstate = BB_NULLTERMINATED;
10067    } else {
10068       llfatalbug( message("sRef_setNT passed a invalid sRef\n"));
10069    }
10070 }
10071
10072
10073 void sRef_setPossiblyNullTerminatedState(sRef p_s) {
10074    if( sRef_isReasonable (p_s)) {
10075       p_s->bufinfo.bufstate = BB_POSSIBLYNULLTERMINATED;
10076    } else {
10077       llfatalbug( message("sRef_setPossNT passed a invalid sRef\n"));
10078    }
10079 }
10080
10081 void sRef_setNotNullTerminatedState(sRef p_s) {
10082    if( sRef_isReasonable (p_s)) {
10083       p_s->bufinfo.bufstate = BB_NOTNULLTERMINATED;
10084    } else {
10085       llfatalbug( message("sRef_unsetNT passed a invalid sRef\n"));
10086    }
10087 }
10088
10089 void sRef_setLen(sRef p_s, int len) {
10090    if (sRef_isReasonable (p_s) && sRef_isNullTerminated(p_s)) 
10091      {
10092        p_s->bufinfo.len = len;
10093      } 
10094    else 
10095      {
10096        llfatalbug( message("sRef_setLen passed an invalid sRef\n"));
10097      }
10098 }
10099     
10100
10101 void sRef_setSize(sRef p_s, int size) {
10102    if( sRef_isValid(p_s)) 
10103      {
10104        p_s->bufinfo.size = size;
10105      } 
10106    else
10107      {
10108        llfatalbug( message("sRef_setSize passed a invalid sRef\n"));
10109      }
10110 }
10111
10112 void sRef_resetLen(sRef p_s) {
10113   if (sRef_isReasonable (p_s)) 
10114     {
10115       p_s->bufinfo.len = 0;
10116     }
10117   else
10118     {
10119       llfatalbug (message ("sRef_setLen passed an invalid sRef\n"));
10120     }
10121 }
10122
10123 /*drl7x 11/28/2000 */
10124
10125 bool sRef_isFixedArray (sRef p_s) /*@*/ {
10126   ctype c;
10127   c = sRef_getType (p_s);
10128   return ( ctype_isFixedArray (c) );
10129 }
10130
10131 size_t sRef_getArraySize (sRef p_s) /*@*/ 
10132 {
10133   ctype c;
10134   llassert (sRef_isFixedArray(p_s) );
10135   DPRINTF (( message ("sRef_getArraySize getting array size for %s", sRef_unparse(p_s) )  ));
10136   
10137   c = sRef_getType (p_s);
10138   return (ctype_getArraySize (c));
10139 }
10140
10141 void sRef_setValue (sRef s, multiVal val)
10142 {
10143   if (!sRef_isReasonable (s))
10144     {
10145       llcontbuglit ("Unreasonable sRef");
10146       llcontbug (message ("sRef: %s", sRef_unparse (s)));
10147       return;
10148     }
10149
10150   multiVal_free (s->val);
10151   s->val = val;
10152 }
10153
10154 bool sRef_hasValue (sRef s)
10155 {
10156   return (sRef_isReasonable (s)
10157           && multiVal_isDefined (s->val));
10158 }
10159
10160 multiVal sRef_getValue (sRef s)
10161 {
10162   if (sRef_isReasonable (s))
10163     {
10164       return s->val;
10165     }
10166
10167   return multiVal_undefined;
10168 }
This page took 0.865699 seconds and 5 git commands to generate.