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