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