]> andersk Git - splint.git/blob - src/sRef.c
Fixed problem with NULL being changed.
[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       DPRINTF (("Set null state ==> %s", sRef_unparseFull (s)));
5520       sRef_resetAliasKind (s);
5521     }
5522 }
5523
5524 void sRef_setNullState (sRef s, nstate n, fileloc loc)
5525 {
5526   if (sRef_isReasonable (s))
5527     {
5528       sRef_setNullStateAux (s, n, loc);
5529     }
5530 }
5531
5532 void sRef_setNullTerminatedStateInnerComplete (sRef s, struct s_bbufinfo b, /*@unused@*/ fileloc loc) 
5533 {
5534   switch (b.bufstate) {
5535   case BB_NULLTERMINATED:
5536     sRef_setNullTerminatedState (s);
5537     sRef_setLen (s, b.len);
5538     break;
5539   case BB_POSSIBLYNULLTERMINATED:
5540     sRef_setPossiblyNullTerminatedState(s);
5541     break;
5542   case BB_NOTNULLTERMINATED:
5543     sRef_setNotNullTerminatedState (s);
5544     break;
5545   }
5546
5547   sRef_setSize (s, b.size);
5548   
5549   /* PL: TO BE DONE : Aliases are not modified right now, have to be similar to
5550    * setNullStateInnerComplete.
5551    */
5552 }
5553
5554 void sRef_setNullStateInnerComplete (sRef s, nstate n, fileloc loc)
5555 {
5556   DPRINTF (("Set null state: %s", nstate_unparse (n)));
5557   
5558   sRef_setNullState (s, n, loc);
5559   
5560   switch (n)
5561     {
5562     case NS_POSNULL:
5563       sRef_innerAliasSetComplete (sRef_setPosNull, s, loc);
5564       break;
5565     case NS_DEFNULL:
5566       sRef_innerAliasSetComplete (sRef_setDefNull, s, loc);
5567       break;
5568     case NS_UNKNOWN:
5569       sRef_innerAliasSetComplete (sRef_setNullUnknown, s, loc);
5570       break;
5571     case NS_NOTNULL:
5572       sRef_innerAliasSetComplete (sRef_setNotNull, s, loc);
5573       break;
5574     case NS_MNOTNULL:
5575       sRef_innerAliasSetComplete (sRef_setNotNull, s, loc);
5576       break;
5577     case NS_RELNULL:
5578       sRef_innerAliasSetComplete (sRef_setNullUnknown, s, loc);
5579       break;
5580     case NS_CONSTNULL:
5581       sRef_innerAliasSetComplete (sRef_setDefNull, s, loc);
5582       break;
5583     case NS_ABSNULL:
5584       sRef_innerAliasSetComplete (sRef_setNullUnknown, s, loc);
5585       break;
5586     case NS_ERROR:
5587       sRef_innerAliasSetComplete (sRef_setNullErrorLoc, s, loc);
5588       break;
5589     }
5590 }
5591
5592 void sRef_setPosNull (sRef s, fileloc loc)
5593 {
5594   if (sRef_isReasonable (s))
5595     {
5596       sRef_setNullStateAux (s, NS_POSNULL, loc);
5597     }
5598 }
5599   
5600 void sRef_setDefNull (sRef s, fileloc loc)
5601 {
5602   if (sRef_isReasonable (s))
5603     {
5604       sRef_setNullStateAux (s, NS_DEFNULL, loc);
5605     }
5606 }
5607
5608 void sRef_setNullUnknown (sRef s, fileloc loc)
5609 {
5610   if (sRef_isReasonable (s))
5611     {
5612       sRef_setNullStateAux (s, NS_UNKNOWN, loc);
5613     }
5614 }
5615
5616 void sRef_setNullError (sRef s)
5617 {
5618   if (sRef_isReasonable (s) && !sRef_isConst (s))
5619     {
5620       sRef_setNullStateAux (s, NS_UNKNOWN, fileloc_undefined);
5621     }
5622 }
5623
5624 void sRef_setNullErrorLoc (sRef s, fileloc loc)
5625 {
5626   if (sRef_isReasonable (s) && !sRef_isConst (s))
5627     {
5628       sRef_setNullStateAux (s, NS_UNKNOWN, loc);
5629     }
5630 }
5631
5632 void sRef_setOnly (sRef s, fileloc loc)
5633 {
5634   if (sRef_isReasonable (s) && s->aliaskind != AK_ONLY)
5635     {
5636       sRef_checkMutable (s);
5637       s->aliaskind = AK_ONLY;
5638       s->aliasinfo = stateInfo_updateLoc (s->aliasinfo, SA_ONLY, loc);
5639     }
5640 }
5641
5642 void sRef_setDependent (sRef s, fileloc loc)
5643 {
5644   if (sRef_isReasonable (s) && !sRef_isConst (s) && (s->aliaskind != AK_DEPENDENT))
5645     {
5646       sRef_checkMutable (s);
5647       DPRINTF (("Setting dependent: %s", sRef_unparseFull (s)));
5648       s->aliaskind = AK_DEPENDENT;
5649       s->aliasinfo = stateInfo_updateLoc (s->aliasinfo, SA_DEPENDENT, loc);
5650     }
5651 }
5652
5653 void sRef_setOwned (sRef s, fileloc loc)
5654 {
5655   if (sRef_isReasonable (s) && !sRef_isConst (s) && (s->aliaskind != AK_OWNED))
5656     {
5657       sRef_checkMutable (s);
5658       s->aliaskind = AK_OWNED;
5659       s->aliasinfo = stateInfo_updateLoc (s->aliasinfo, SA_OWNED, loc);
5660     }
5661 }
5662
5663 void sRef_setKept (sRef s, fileloc loc)
5664 {
5665   if (sRef_isReasonable (s) && !sRef_isConst (s) && (s->aliaskind != AK_KEPT))
5666     {
5667       sRef base = sRef_getBaseSafe (s);  
5668  
5669       while (sRef_isReasonable (base) && sRef_isKnown (base))
5670         {
5671           if (base->defstate == SS_DEFINED) 
5672             {
5673               sRef_checkMutable (base);
5674               base->defstate = SS_PDEFINED; 
5675               base = sRef_getBaseSafe (base); 
5676             }
5677           else 
5678             {
5679               break; 
5680             }
5681         }
5682
5683       sRef_checkMutable (s);
5684       s->aliaskind = AK_KEPT;
5685       s->aliasinfo = stateInfo_updateLoc (s->aliasinfo, SA_KEPT, loc);
5686     }
5687 }
5688
5689 static void sRef_setKeptAux (sRef s, fileloc loc)
5690 {
5691   if (!sRef_isShared (s))
5692     {
5693       sRef_setKept (s, loc);
5694     }
5695 }
5696
5697 static void sRef_setDependentAux (sRef s, fileloc loc)
5698 {
5699   if (!sRef_isShared (s))
5700     {
5701       sRef_setDependent (s, loc);
5702     }
5703 }
5704
5705 void sRef_setKeptComplete (sRef s, fileloc loc)
5706 {
5707   sRef_aliasSetComplete (sRef_setKeptAux, s, loc);
5708 }
5709
5710 void sRef_setDependentComplete (sRef s, fileloc loc)
5711 {
5712   sRef_aliasSetComplete (sRef_setDependentAux, s, loc);
5713 }
5714
5715 void sRef_setFresh (sRef s, fileloc loc)
5716 {
5717   if (sRef_isReasonable (s) && !sRef_isConst (s))
5718     {
5719       sRef_checkMutable (s);
5720       s->aliaskind = AK_FRESH;
5721       s->aliasinfo = stateInfo_updateLoc (s->aliasinfo, SA_CREATED, loc);
5722       DPRINTF (("SetFresh: %s", sRef_unparseFull (s)));
5723     }
5724 }
5725
5726 void sRef_kill (sRef s, fileloc loc)
5727 {
5728   DPRINTF (("Kill: %s", sRef_unparseFull (s)));
5729
5730   if (sRef_isReasonable (s) && !sRef_isShared (s) && !sRef_isConst (s))
5731     {
5732       sRef base = sRef_getBaseSafe (s);  
5733       sRef_checkMutable (s);
5734         
5735       while (sRef_isReasonable (base) && sRef_isKnown (base))
5736         {
5737           if (base->defstate == SS_DEFINED) 
5738             {
5739               sRef_checkMutable (base);
5740               base->defstate = SS_PDEFINED; 
5741               base = sRef_getBaseSafe (base); 
5742             }
5743           else 
5744             {
5745               break; 
5746             }
5747         }
5748       
5749       s->aliaskind = s->oaliaskind;
5750       s->defstate = SS_DEAD;
5751       s->definfo = stateInfo_updateLoc (s->definfo, SA_KILLED, loc);
5752       DPRINTF (("State info: %s", stateInfo_unparse (s->definfo)));
5753       sRef_clearDerived (s);
5754     }
5755 }
5756
5757 void sRef_maybeKill (sRef s, fileloc loc)
5758 {
5759   if (sRef_isReasonable (s))
5760     {
5761       sRef base = sRef_getBaseSafe (s);  
5762       sRef_checkMutable (s);
5763             
5764       while (sRef_isReasonable (base) && sRef_isKnown (base))
5765         {
5766           if (base->defstate == SS_DEFINED || base->defstate == SS_RELDEF)
5767             {
5768               sRef_checkMutable (base);
5769               base->defstate = SS_PDEFINED; 
5770               base = sRef_getBaseSafe (base); 
5771             }
5772           else 
5773             {
5774               break; 
5775             }
5776           
5777         }
5778       
5779       s->aliaskind = s->oaliaskind;
5780       s->defstate = SS_HOFFA; 
5781       s->definfo = stateInfo_updateLoc (s->definfo, SA_PKILLED, loc);
5782       DPRINTF (("State info: %s / %s", sRef_unparse (s), 
5783                 stateInfo_unparse (s->definfo)));
5784       sRef_clearDerived (s); 
5785     }
5786
5787   }
5788
5789 /*
5790 ** just for type checking...
5791 */
5792
5793 static void sRef_killAux (sRef s, fileloc loc)
5794 {
5795   if (sRef_isReasonable (s) && !sRef_isShared (s))
5796     {
5797       if (sRef_isUnknownArrayFetch (s))
5798         {
5799           sRef_maybeKill (s, loc);
5800         }
5801       else
5802         {
5803           sRef_kill (s, loc);
5804         }
5805     }
5806 }
5807
5808 /*
5809 ** kills s and all aliases to s
5810 */
5811
5812 void sRef_killComplete (sRef s, fileloc loc)
5813 {
5814   DPRINTF (("Kill complete: %s", sRef_unparseFull (s)));
5815   sRef_aliasSetComplete (sRef_killAux, s, loc);
5816 }
5817
5818 static bool sRef_equivalent (sRef s1, sRef s2)
5819 {
5820   return (sRef_compare (s1, s2) == 0);
5821 }
5822
5823 /*
5824 ** returns an sRef that will not be free'd on function exit.
5825 */
5826
5827 /*@only@*/ sRef sRef_saveCopy (sRef s)
5828 {
5829   sRef ret;
5830
5831   if (sRef_isReasonable (s))
5832     {
5833       bool old = inFunction;
5834
5835       /*
5836       ** Exit the function scope, so this sRef is not
5837       ** stored in the deallocation table.
5838       */
5839       
5840       inFunction = FALSE;
5841       DPRINTF (("Copying sref: %s", sRef_unparseFull(s)));
5842       ret = sRef_copy (s);
5843       DPRINTF (("Copying ===>: %s", sRef_unparseFull(ret)));
5844       inFunction = old;
5845     }
5846   else
5847     {
5848       ret = sRef_undefined;
5849     }
5850
5851   /*@-dependenttrans@*/ 
5852   return ret;
5853   /*@=dependenttrans@*/ 
5854 }
5855
5856 sRef sRef_copy (sRef s)
5857 {
5858   if (sRef_isKindSpecial (s) && !sRef_isGlobalMarker (s))
5859     {
5860       /*@-retalias@*/
5861       return s; /* don't copy specials (except for global markers) */
5862       /*@=retalias@*/
5863     }
5864
5865   if (sRef_isReasonable (s))
5866     {
5867       sRef t = sRef_alloc ();
5868
5869       DPRINTF (("Copying: [%p] %s", s, sRef_unparse (s)));
5870       DPRINTF (("Full: %s", sRef_unparseFull (s)));
5871
5872       t->kind = s->kind;
5873       t->safe = s->safe;
5874       t->modified = s->modified;
5875       t->immut = FALSE; /* Note mutability is not copied. */
5876       t->type = s->type;
5877       t->val = multiVal_copy (s->val);
5878
5879       t->info = sinfo_copy (s);
5880       t->defstate = s->defstate;
5881       t->nullstate = s->nullstate;
5882       DPRINTF (("Set null state==> %s", sRef_unparseFull (t)));
5883
5884  
5885       /* start modifications */
5886       t->bufinfo.bufstate = s->bufinfo.bufstate;
5887       t->bufinfo.len = s->bufinfo.len;
5888       t->bufinfo.size = s->bufinfo.size;
5889       /* end modifications */
5890
5891       t->aliaskind = s->aliaskind;
5892       t->oaliaskind = s->oaliaskind;
5893
5894       t->expkind = s->expkind;
5895       t->oexpkind = s->oexpkind;
5896
5897       t->nullinfo = stateInfo_copy (s->nullinfo);
5898       t->aliasinfo = stateInfo_copy (s->aliasinfo);
5899       t->definfo = stateInfo_copy (s->definfo);
5900       t->expinfo = stateInfo_copy (s->expinfo);
5901
5902       t->deriv = sRefSet_newDeepCopy (s->deriv);
5903       t->state = valueTable_copy (s->state);
5904       
5905       DPRINTF (("Made copy: %s => %s", sRef_unparseFull (s), sRef_unparseFull (t)));
5906       return t;
5907     }
5908   else
5909     {
5910       return sRef_undefined;
5911     }
5912 }
5913
5914 /*@notfunction@*/
5915 # define PREDTEST(func,s) \
5916    do { if (sRef_isInvalid (s)) { return FALSE; } \
5917         else { if (sRef_isConj (s)) \
5918                   { return (func (sRef_getConjA (s)) \
5919                             || func (sRef_getConjB (s))); }}} while (FALSE);
5920
5921 bool sRef_isAddress (sRef s)
5922 {
5923   PREDTEST (sRef_isAddress, s);
5924   return (s->kind == SK_ADR);
5925 }
5926           
5927 /*
5928 ** pretty weak... maybe a flag should control this.
5929 */
5930
5931 bool sRef_isThroughArrayFetch (sRef s)
5932 {
5933   if (sRef_isReasonable (s))
5934     {
5935       sRef tref = s;
5936
5937       do 
5938         {
5939           sRef lt;
5940
5941           if (sRef_isArrayFetch (tref)) 
5942             {
5943               return TRUE;
5944             }
5945           
5946           lt = sRef_getBase (tref);
5947           tref = lt;
5948         } while (sRef_isReasonable (tref));
5949     } 
5950
5951   return FALSE;
5952 }
5953
5954 bool sRef_isArrayFetch (sRef s)
5955 {
5956   PREDTEST (sRef_isArrayFetch, s);
5957   return (s->kind == SK_ARRAYFETCH);
5958 }
5959
5960 bool sRef_isMacroParamRef (sRef s)
5961 {
5962   if (context_inMacro () && sRef_isCvar (s))
5963     {
5964       uentry ue = sRef_getUentry (s);
5965       cstring pname = makeParam (uentry_rawName (ue));
5966       uentry mac = usymtab_lookupSafe (pname);
5967
5968       cstring_free (pname);
5969       return (uentry_isValid (mac));
5970     }
5971
5972   return FALSE;
5973 }
5974       
5975 bool sRef_isCvar (sRef s) 
5976 {
5977   PREDTEST (sRef_isCvar, s);
5978   return (s->kind == SK_CVAR);
5979 }
5980
5981 bool sRef_isConst (sRef s) 
5982 {
5983   PREDTEST (sRef_isConst, s);
5984   return (s->kind == SK_CONST);
5985 }
5986
5987 bool sRef_isObject (sRef s) 
5988 {
5989   PREDTEST (sRef_isObject, s);
5990   return (s->kind == SK_OBJECT);
5991 }
5992
5993 bool sRef_isExternal (sRef s) 
5994 {
5995   PREDTEST (sRef_isExternal, s);
5996   return (s->kind == SK_EXTERNAL);
5997 }
5998
5999 static bool sRef_isDerived (sRef s) 
6000 {
6001   PREDTEST (sRef_isDerived, s);
6002   return (s->kind == SK_DERIVED);
6003 }
6004
6005 bool sRef_isField (sRef s)
6006 {
6007   PREDTEST (sRef_isField, s);
6008   return (s->kind == SK_FIELD);
6009 }
6010
6011 static bool sRef_isIndex (sRef s)
6012 {
6013   PREDTEST (sRef_isIndex, s);
6014   return (s->kind == SK_ARRAYFETCH);
6015 }
6016
6017 bool sRef_isAnyParam (sRef s)
6018 {
6019   PREDTEST (sRef_isAnyParam, s);
6020   return (s->kind == SK_PARAM);  
6021 }
6022
6023 bool sRef_isParam (sRef s)
6024 {
6025   PREDTEST (sRef_isParam, s);
6026   return (s->kind == SK_PARAM);
6027 }
6028
6029 bool sRef_isDirectParam (sRef s)
6030 {
6031   PREDTEST (sRef_isDirectParam, s);
6032
6033   return ((s->kind == SK_CVAR) &&
6034           (s->info->cvar->lexlevel == functionScope) &&
6035           (context_inFunction () && 
6036            (s->info->cvar->index <= usymId_fromInt (uentryList_size (context_getParams ())))));
6037 }
6038
6039 bool sRef_isPointer (sRef s)
6040 {
6041   PREDTEST (sRef_isPointer, s);
6042   return (s->kind == SK_PTR);
6043 }
6044
6045 /*
6046 ** returns true if storage referenced by s is visible
6047 */
6048
6049 bool sRef_isReference (sRef s)
6050 {
6051   PREDTEST (sRef_isReference, s);
6052
6053   return (sRef_isPointer (s) || sRef_isIndex (s) || sRef_isFileOrGlobalScope (s)
6054           || (sRef_isField (s) && (sRef_isReference (s->info->field->rec))));
6055 }
6056
6057 bool sRef_isIReference (sRef s)
6058 {
6059   return (sRef_isPointer (s) || sRef_isAddress (s) || sRef_isIndex (s)
6060           || sRef_isField (s) || sRef_isArrayFetch (s));
6061 }
6062
6063 bool sRef_isFileOrGlobalScope (sRef s)
6064 {
6065   return (sRef_isCvar (s) && (s->info->cvar->lexlevel <= fileScope));
6066 }
6067
6068 bool sRef_isRealGlobal (sRef s)
6069 {
6070   return (sRef_isCvar (s) && (s->info->cvar->lexlevel == globScope));
6071 }
6072
6073 bool sRef_isFileStatic (sRef s)
6074 {
6075   return (sRef_isCvar (s) && (s->info->cvar->lexlevel == fileScope));
6076 }
6077
6078 bool sRef_isAliasCheckedGlobal (sRef s)
6079 {
6080   if (sRef_isFileOrGlobalScope (s))
6081     {
6082       uentry ue = sRef_getUentry (s);
6083
6084       return context_checkAliasGlob (ue);
6085     }
6086   else
6087     {
6088       return FALSE;
6089     }
6090 }
6091
6092 void sRef_free (/*@only@*/ sRef s)
6093 {
6094   if (s != sRef_undefined && s->kind != SK_SPECIAL)
6095     {
6096       DPRINTF (("Free sref: [%p]", s));
6097
6098       sRef_checkValid (s);
6099       
6100       multiVal_free (s->val); /* evans 2002-07-12 */
6101
6102       stateInfo_free (s->expinfo);
6103       stateInfo_free (s->aliasinfo);
6104       stateInfo_free (s->definfo);
6105       stateInfo_free (s->nullinfo);
6106
6107       sRefSet_free (s->deriv);
6108       s->deriv = sRefSet_undefined;
6109
6110       valueTable_free (s->state); 
6111       sinfo_free (s);
6112       
6113       
6114       /* drl added to help locate use after release*/
6115       s->expinfo = stateInfo_undefined;
6116       s->aliasinfo = stateInfo_undefined;
6117       s->definfo = stateInfo_undefined;
6118       s->nullinfo = stateInfo_undefined;
6119
6120       sfree (s);
6121     }
6122 }
6123
6124 void sRef_setType (sRef s, ctype t)
6125 {
6126   if (sRef_isReasonable (s))
6127     {
6128       sRef_checkMutable (s); 
6129       s->type = t;
6130     }
6131 }
6132
6133 void sRef_setTypeFull (sRef s, ctype t)
6134 {
6135   if (sRef_isReasonable (s))
6136     {
6137       sRef_checkMutable (s);
6138       s->type = t;
6139
6140       sRefSet_allElements (s->deriv, current)
6141         {
6142           sRef_setTypeFull (current, ctype_unknown);
6143         } end_sRefSet_allElements ;
6144     }
6145 }
6146
6147 /*@exposed@*/ sRef
6148   sRef_buildField (/*@exposed@*/ sRef rec, /*@dependent@*/ cstring f)
6149 {
6150   return (sRef_buildNCField (rec, f)); 
6151 }
6152
6153 static /*@exposed@*/ sRef
6154 sRef_findDerivedField (/*@notnull@*/ sRef rec, cstring f)
6155 {
6156   sRefSet_allElements (sRef_derivedFields (rec), sr)
6157     {
6158       if (sRef_isReasonable (sr))
6159         {
6160           if (sRef_isReasonable (sr))
6161             {
6162               if (sr->info != NULL) 
6163                 {
6164                   if (sr->kind == SK_FIELD && cstring_equal (sr->info->field->field, f))
6165                     {
6166                       return sr;
6167                     }
6168                 }
6169             }
6170           else
6171             {
6172               llcontbug (message ("Invalid sRef as derived field of %s", sRef_unparse (rec)));
6173             }
6174         }
6175     } end_sRefSet_allElements;
6176
6177   return sRef_undefined;
6178 }
6179
6180 /*@dependent@*/ /*@observer@*/ sRefSet sRef_derivedFields (/*@temp@*/ sRef rec)
6181 {
6182   if (sRef_isReasonable (rec))
6183     {
6184       sRefSet ret;
6185       ret = rec->deriv;
6186       return (ret);
6187     }
6188   else
6189     {
6190       return (sRefSet_undefined);
6191     }
6192 }
6193
6194 static /*@exposed@*/ sRef
6195   sRef_findDerivedPointer (sRef s)
6196 {
6197   if (sRef_isReasonable (s))
6198     {
6199       sRefSet_realElements (s->deriv, sr)
6200         {
6201           if (sRef_isReasonable (sr) && sr->kind == SK_PTR)
6202             {
6203               return sr;
6204             }
6205         } end_sRefSet_realElements;
6206     }
6207
6208   return sRef_undefined;
6209 }
6210
6211 bool
6212 sRef_isUnknownArrayFetch (sRef s)
6213 {
6214   return (sRef_isReasonable (s) 
6215           && s->kind == SK_ARRAYFETCH
6216           && !s->info->arrayfetch->indknown);
6217 }
6218
6219 static /*@exposed@*/ sRef
6220 sRef_findDerivedArrayFetch (/*@notnull@*/ sRef s, bool isknown, int idx, bool dead)
6221 {
6222   
6223   if (isknown) 
6224     {
6225       sRefSet_realElements (s->deriv, sr)
6226         {
6227           if (sRef_isReasonable (sr)
6228               && sr->kind == SK_ARRAYFETCH
6229               && sr->info->arrayfetch->indknown
6230               && (sr->info->arrayfetch->ind == idx))
6231             {
6232               return sr;
6233             }
6234         } end_sRefSet_realElements;
6235     }
6236   else
6237     {
6238       sRefSet_realElements (s->deriv, sr)
6239         {
6240           if (sRef_isReasonable (sr)
6241               && sr->kind == SK_ARRAYFETCH
6242               && (!sr->info->arrayfetch->indknown
6243                   || (sr->info->arrayfetch->indknown && 
6244                       sr->info->arrayfetch->ind == 0)))
6245             {
6246               if (sRef_isDead (sr) || sRef_isKept (sr))
6247                 {
6248                   if (dead || context_getFlag (FLG_STRICTUSERELEASED))
6249                     {
6250                       return sr;
6251                     }
6252                 }
6253               else
6254                 {
6255                   return sr;
6256                 }
6257             }
6258         } end_sRefSet_realElements;
6259     }
6260
6261   return sRef_undefined;
6262 }
6263
6264 static /*@exposed@*/ sRef 
6265 sRef_buildNCField (/*@exposed@*/ sRef rec, /*@exposed@*/ cstring f)
6266 {
6267   sRef s;
6268
6269   DPRINTF (("Build nc field: %s / %s",
6270             sRef_unparseFull (rec), f));
6271
6272   if (sRef_isInvalid (rec))
6273     {
6274       return sRef_undefined;
6275     }
6276       
6277   /*
6278   ** check if the field already has been referenced 
6279   */
6280
6281   s = sRef_findDerivedField (rec, f);
6282   
6283   if (sRef_isReasonable (s))
6284     {
6285       return s;
6286     }
6287   else
6288     {
6289       ctype ct = ctype_realType (rec->type);
6290       
6291       DPRINTF (("Field of: %s", sRef_unparse (rec)));
6292       
6293       s = sRef_newRef ();      
6294       s->kind = SK_FIELD;
6295       s->info = (sinfo) dmalloc (sizeof (*s->info));
6296       s->info->field = (fldinfo) dmalloc (sizeof (*s->info->field));
6297       s->info->field->rec = rec;
6298       s->info->field->field = f; /* doesn't copy f */
6299       
6300       if (ctype_isKnown (ct) && ctype_isSU (ct))
6301         {
6302           uentry ue = uentryList_lookupField (ctype_getFields (ct), f);
6303         
6304           if (!uentry_isUndefined (ue))
6305             {
6306               DPRINTF (("lookup: %s for %s", uentry_unparseFull (ue),
6307                         ctype_unparse (ct)));
6308               
6309               s->type = uentry_getType (ue);
6310
6311               if (ctype_isMutable (s->type)
6312                   && rec->aliaskind != AK_STACK 
6313                   && !alkind_isStatic (rec->aliaskind))
6314                 {
6315                   s->aliaskind = rec->aliaskind;
6316                 }
6317               else
6318                 {
6319                   s->aliaskind = AK_UNKNOWN;
6320                 }
6321
6322               if (sRef_isStateDefined (rec) || sRef_isStateUnknown (rec) 
6323                   || sRef_isPdefined (rec))
6324                 {
6325                   sRef_setStateFromUentry (s, ue);
6326                 }
6327               else
6328                 {
6329                   sRef_setPartsFromUentry (s, ue);
6330                 }
6331               
6332               s->oaliaskind = s->aliaskind;
6333               s->oexpkind = s->expkind;
6334
6335               DPRINTF (("sref: %s", sRef_unparseFull (s)));
6336             }
6337           else
6338             {
6339               /*
6340                 Never report this as an error.  It can happen whenever there
6341                 is casting involved.
6342
6343               if (report)
6344                 {
6345                   llcontbug (message ("buildNCField --- no field %s: %q / %s",
6346                                       f, sRef_unparse (s), ctype_unparse (ct)));
6347                 }
6348                 */
6349
6350               return sRef_undefined;
6351             }
6352         }
6353       
6354       if (rec->defstate == SS_DEFINED 
6355           && (s->defstate == SS_UNDEFINED || s->defstate == SS_UNKNOWN))
6356         {
6357           s->defstate = SS_DEFINED;
6358         }
6359       else if (rec->defstate == SS_PARTIAL)
6360         {
6361           s->defstate = SS_PARTIAL;
6362         }
6363       else if (rec->defstate == SS_ALLOCATED) 
6364         {
6365           if (ctype_isStackAllocated (ct) && ctype_isStackAllocated (s->type))
6366             {
6367               s->defstate = SS_ALLOCATED;
6368             }
6369           else
6370             {
6371               s->defstate = SS_UNDEFINED;
6372             }
6373         }
6374       else if (s->defstate == SS_UNKNOWN)
6375         {
6376           s->defstate = rec->defstate;
6377         }
6378       else
6379         {
6380           ; /* no change */
6381         }
6382
6383       if (s->defstate == SS_UNDEFINED)
6384         {
6385           ctype rt = ctype_realType (s->type);
6386           
6387           if (ctype_isArray (rt) || ctype_isSU (rt))
6388             {
6389               s->defstate = SS_ALLOCATED;
6390             }
6391         }
6392
6393       sRef_addDeriv (rec, s);
6394       DPRINTF (("Add deriv: %s", sRef_unparseFull (rec)));
6395
6396       if (ctype_isInt (s->type) && cstring_equal (f, REFSNAME))
6397         {
6398           s->aliaskind = AK_REFS;
6399           s->oaliaskind = AK_REFS;
6400         }
6401
6402       DPRINTF (("Build field ==> %s", sRef_unparseFull (s)));
6403       return s;
6404     }
6405 }
6406
6407 bool
6408 sRef_isStackAllocated (sRef s)
6409 {
6410   return (sRef_isReasonable(s) 
6411           && s->defstate == SS_ALLOCATED && ctype_isStackAllocated (s->type));
6412 }
6413           
6414 static
6415 void sRef_setArrayFetchState (/*@notnull@*/ /*@exposed@*/ sRef s, 
6416                               /*@notnull@*/ /*@exposed@*/ sRef arr)
6417 {
6418   sRef_checkMutable (s);
6419
6420   if (ctype_isRealAP (arr->type))
6421     {
6422       s->type = ctype_baseArrayPtr (arr->type);
6423     }
6424
6425   /* a hack, methinks... makeArrayFetch (&a[0]) ==> a[] */
6426   /* evans - 2001-08-27: not sure where this was necessary - it
6427   ** causes an assertion in in aliasCheckPred to fail.
6428   */
6429
6430   if (sRef_isAddress (arr)) 
6431     {
6432       sRef t = arr->info->ref;
6433       
6434       if (sRef_isArrayFetch (t))
6435         {
6436           s->info->arrayfetch->arr = t->info->arrayfetch->arr;
6437         }
6438     }
6439   else if (ctype_isRealPointer (arr->type))
6440     {
6441       sRef sp = sRef_findDerivedPointer (arr);
6442       
6443       if (sRef_isReasonable (sp))
6444         {
6445           
6446           if (ctype_isMutable (s->type))
6447             {
6448               s->expkind = sRef_getExKind (sp);
6449               s->expinfo = stateInfo_copy (sp->expinfo);
6450               
6451               s->aliaskind = sp->aliaskind;
6452               s->aliasinfo = stateInfo_copy (sp->aliasinfo);
6453             }
6454
6455           s->defstate = sp->defstate;
6456
6457           if (s->defstate == SS_DEFINED) 
6458             {
6459               if (!context_getFlag (FLG_STRICTDESTROY))
6460                 {
6461                   s->defstate = SS_PARTIAL;
6462                 }
6463             }
6464
6465           DPRINTF (("Set null state: %s / %s", sRef_unparseFull (s), sRef_unparseFull (sp)));
6466           sRef_setNullStateN (s, sRef_getNullState (sp));
6467         }
6468       else
6469         {
6470           if (arr->defstate == SS_UNDEFINED)
6471             {
6472               s->defstate = SS_UNUSEABLE;
6473             }
6474           else if ((arr->defstate == SS_ALLOCATED) && !ctype_isSU (s->type))
6475             {
6476               s->defstate = SS_UNDEFINED;
6477             }
6478           else
6479             {
6480               if (!context_getFlag (FLG_STRICTDESTROY))
6481                 {
6482                   s->defstate = SS_PARTIAL;
6483                 }
6484               else
6485                 {
6486                   s->defstate = SS_DEFINED;
6487                 }
6488
6489               /*
6490               ** Very weak checking for array elements.
6491               ** Was:
6492               **     s->defstate = arr->defstate;
6493               */
6494             }
6495
6496           s->expkind = sRef_getExKind (arr);
6497           s->expinfo = stateInfo_copy (arr->expinfo);
6498           
6499           if (arr->aliaskind == AK_LOCAL || arr->aliaskind == AK_FRESH)
6500             {
6501               s->aliaskind = AK_LOCAL;
6502             }
6503           else
6504             {
6505               s->aliaskind = AK_UNKNOWN;
6506             }
6507           
6508           sRef_setTypeState (s);
6509         }
6510     }
6511   else
6512     {
6513       if (arr->defstate == SS_DEFINED)
6514         {
6515           /*
6516           ** Very weak checking for array elements.
6517           ** Was:
6518           **     s->defstate = arr->defstate;
6519           */
6520
6521           if (context_getFlag (FLG_STRICTDESTROY))
6522             {
6523               s->defstate = SS_DEFINED;
6524             }
6525           else
6526             {
6527               s->defstate = SS_PARTIAL;
6528             }
6529         }
6530       else if (arr->defstate == SS_ALLOCATED)
6531         {
6532           if (ctype_isRealArray (s->type))
6533             {
6534               s->defstate = SS_ALLOCATED;
6535             }
6536           else 
6537             {
6538               if (!s->info->arrayfetch->indknown)
6539                 {
6540                   /*
6541                   ** is index is unknown, elements is defined or 
6542                   ** allocated is any element is!
6543                   */
6544                   
6545                   s->defstate = SS_UNDEFINED;
6546                   
6547                   sRefSet_allElements (arr->deriv, sr)
6548                     {
6549                       if (sRef_isReasonable (sr))
6550                         {
6551                           if (sRef_isReasonable (sr))
6552                             {
6553                               if (sr->defstate == SS_ALLOCATED)
6554                                 {
6555                                   s->defstate = SS_ALLOCATED;
6556                                 }
6557                               else 
6558                                 {
6559                                   if (sr->defstate == SS_DEFINED)
6560                                     {
6561                                       if (context_getFlag (FLG_STRICTDESTROY))
6562                                         {
6563                                           s->defstate = SS_DEFINED;
6564                                         }
6565                                       else
6566                                         {
6567                                           s->defstate = SS_PARTIAL;
6568                                         }
6569                                       
6570                                       break;
6571                                     }
6572                                 }
6573                             }
6574                           else
6575                             {
6576                               llcontbug (message ("Invalid sRef as derived element of %s", sRef_unparse (arr)));
6577                             }
6578                         }
6579                     } end_sRefSet_allElements;
6580                 }
6581               else
6582                 {
6583                   s->defstate = SS_UNDEFINED;
6584                 }
6585             }
6586         }
6587       else
6588         {
6589           s->defstate = arr->defstate;
6590         }
6591       
6592       
6593       /*
6594       ** kludgey way to guess where aliaskind applies
6595       */
6596       
6597       if (ctype_isMutable (s->type) 
6598           && !ctype_isPointer (arr->type) 
6599           && !alkind_isStatic (arr->aliaskind)
6600           && !alkind_isStack (arr->aliaskind)) /* evs - 2000-06-20: don't pass stack allocation to members */
6601         {
6602           s->aliaskind = arr->aliaskind;
6603         }
6604       else
6605         {
6606           s->aliaskind = AK_UNKNOWN;
6607         }
6608     
6609       sRef_setTypeState (s);
6610     }
6611
6612   if (sRef_isObserver (arr)) 
6613     {
6614       s->expkind = XO_OBSERVER;
6615       s->expinfo = stateInfo_copy (arr->expinfo);
6616     }
6617 }  
6618
6619 /*@exposed@*/ sRef sRef_buildArrayFetch (/*@exposed@*/ sRef arr)
6620 {
6621   sRef s;
6622
6623   if (!sRef_isReasonable (arr)) {
6624     /*@-nullret@*/ return arr /*@=nullret@*/;
6625   }
6626
6627   if (ctype_isRealPointer (arr->type))
6628     {
6629       (void) sRef_buildPointer (arr); /* do this to define arr! */
6630     }
6631   
6632   s = sRef_findDerivedArrayFetch (arr, FALSE, 0, FALSE);
6633   
6634   if (sRef_isReasonable (s))
6635     {
6636       /* evans 2001-07-12: this is bogus, clean-up hack */
6637       if (s->info->arrayfetch->arr != arr)
6638         {
6639           sRef res;
6640           check (sRefSet_delete (arr->deriv, s));
6641           res = sRef_buildArrayFetch (arr);
6642           sRef_copyState (res, s);
6643           llassert (res->info->arrayfetch->arr == arr); 
6644           return res;
6645         }
6646
6647       s->expkind = sRef_getExKind (arr);
6648       s->expinfo = stateInfo_copy (arr->expinfo);
6649
6650       return s;
6651     }
6652   else
6653     {
6654       s = sRef_newRef ();
6655
6656       s->kind = SK_ARRAYFETCH;
6657       s->info = (sinfo) dmalloc (sizeof (*s->info));
6658       s->info->arrayfetch = (ainfo) dmalloc (sizeof (*s->info->arrayfetch));
6659       s->info->arrayfetch->indknown = FALSE;
6660       s->info->arrayfetch->ind = 0;
6661       s->info->arrayfetch->arr = arr;
6662
6663       sRef_setArrayFetchState (s, arr);
6664
6665       s->oaliaskind = s->aliaskind;
6666       s->oexpkind = s->expkind;
6667
6668       if (!context_inProtectVars ())
6669         {
6670           sRef_addDeriv (arr, s);
6671         }
6672       
6673       if (valueTable_isUndefined (s->state))
6674         {
6675           s->state = context_createValueTable 
6676             (s, stateInfo_makeLoc (g_currentloc, SA_CREATED));
6677         }
6678       
6679       return (s);
6680     }
6681 }
6682
6683 /*@exposed@*/ sRef
6684   sRef_buildArrayFetchKnown (/*@exposed@*/ sRef arr, int i)
6685 {
6686   sRef s;
6687
6688   if (!sRef_isReasonable (arr)) {
6689     /*@-nullret@*/ return arr /*@=nullret@*/;
6690   }
6691
6692   if (ctype_isRealPointer (arr->type))
6693     {
6694       (void) sRef_buildPointer (arr); /* do this to define arr! */
6695     }
6696
6697   s = sRef_findDerivedArrayFetch (arr, TRUE, i, FALSE);
6698
6699   if (sRef_isReasonable (s))
6700     {
6701       /* evans 2001-07-12: this is bogus, clean-up hack */
6702       if (s->info->arrayfetch->arr != arr)
6703         {
6704           sRef res;
6705
6706           check (sRefSet_delete (arr->deriv, s));
6707           res = sRef_buildArrayFetchKnown (arr, i);
6708
6709           llassert (res->info->arrayfetch->arr == arr);
6710           sRef_copyState (res, s);
6711           llassert (res->info->arrayfetch->arr == arr);
6712           return res;
6713         }
6714
6715       s->expkind = sRef_getExKind (arr);
6716       s->expinfo = stateInfo_copy (arr->expinfo);
6717
6718       llassert (s->info->arrayfetch->arr == arr);
6719       return s;
6720     }
6721   else
6722     {
6723       s = sRef_newRef ();
6724       
6725       s->kind = SK_ARRAYFETCH;
6726       s->info = (sinfo) dmalloc (sizeof (*s->info));
6727       s->info->arrayfetch = (ainfo) dmalloc (sizeof (*s->info->arrayfetch));
6728       s->info->arrayfetch->arr = arr;
6729       s->info->arrayfetch->indknown = TRUE;
6730       s->info->arrayfetch->ind = i;
6731
6732       sRef_setArrayFetchState (s, arr);
6733       /* evans 2001-08-27 no: can change this - llassert (s->info->arrayfetch->arr == arr); */
6734
6735       s->oaliaskind = s->aliaskind;
6736       s->oexpkind = s->expkind;
6737       sRef_addDeriv (arr, s);
6738
6739       llassert (valueTable_isUndefined (s->state));
6740       s->state = context_createValueTable (s, stateInfo_makeLoc (g_currentloc, SA_CREATED));
6741       return (s);
6742     }
6743 }
6744
6745 /*
6746 ** sets everything except for defstate
6747 */
6748
6749 static void
6750 sRef_setPartsFromUentry (sRef s, uentry ue)
6751 {    
6752   sRef uref = uentry_getSref (ue);
6753
6754   llassert (sRef_isReasonable (s));
6755
6756   s->aliaskind = alkind_derive (s->aliaskind, uentry_getAliasKind (ue));
6757   s->oaliaskind = s->aliaskind;
6758
6759   if (s->expkind == XO_UNKNOWN)
6760     {
6761       s->expkind = uentry_getExpKind (ue);
6762     }
6763   
6764   s->oexpkind = s->expkind;
6765   
6766   if (sRef_getNullState (s) == NS_UNKNOWN)
6767     {
6768       DPRINTF (("Set null state: %s / %s", sRef_unparseFull (s), uentry_unparseFull (ue)));
6769       sRef_setNullStateN (s, sRef_getNullState (uentry_getSref (ue)));
6770     }
6771   else
6772     {
6773       DPRINTF (("Skipping null null state!"));
6774     }
6775
6776   if (s->aliaskind == AK_IMPONLY && (sRef_isExposed (s) || sRef_isObserver (s)))
6777     {
6778       s->oaliaskind = s->aliaskind = AK_IMPDEPENDENT;
6779     } 
6780
6781   if (sRef_isReasonable (uref))
6782     {
6783       valueTable utable = uref->state;
6784       valueTable_free (s->state);
6785       s->state = valueTable_copy (utable);
6786     }
6787 }
6788
6789 static void
6790 sRef_setStateFromAbstractUentry (sRef s, uentry ue)
6791 {
6792   llassert (sRef_isReasonable (s));
6793   sRef_checkMutable (s);
6794
6795   sRef_setPartsFromUentry (s, ue);
6796
6797   s->aliaskind = alkind_derive (s->aliaskind, uentry_getAliasKind (ue));
6798   s->oaliaskind = s->aliaskind;
6799
6800   if (s->expkind == XO_UNKNOWN)
6801     {
6802       s->expkind = uentry_getExpKind (ue);
6803     }
6804
6805   s->oexpkind = s->expkind;
6806 }
6807
6808 void
6809 sRef_setStateFromUentry (sRef s, uentry ue)
6810 {
6811   sstate defstate;
6812
6813   sRef_checkMutable (s);
6814   llassert (sRef_isReasonable (s));
6815   
6816   sRef_setPartsFromUentry (s, ue);
6817
6818   defstate = uentry_getDefState (ue);
6819
6820   if (sstate_isKnown (defstate))
6821     {
6822       s->defstate = defstate;
6823     }
6824   else
6825     {
6826       ;
6827     }
6828 }
6829
6830 /*@exposed@*/ sRef
6831   sRef_buildPointer (/*@exposed@*/ sRef t)
6832 {
6833   DPRINTF (("build pointer: %s", sRef_unparse (t)));
6834
6835   if (sRef_isInvalid (t)) return sRef_undefined;
6836
6837   if (sRef_isAddress (t))
6838     {
6839       DPRINTF (("Return ref: %s", sRef_unparse (t->info->ref)));
6840       return (t->info->ref);
6841     }
6842   else
6843     {
6844       sRef s = sRef_findDerivedPointer (t);
6845
6846       DPRINTF (("find derived: %s", sRef_unparse (s)));
6847
6848       if (sRef_isReasonable (s))
6849         {
6850           s->expkind = sRef_getExKind (t);
6851           s->expinfo = stateInfo_copy (t->expinfo);       
6852
6853           s->oaliaskind = s->aliaskind;
6854           s->oexpkind = s->expkind;
6855
6856           return s;
6857         }
6858       else
6859         {
6860           s = sRef_constructPointerAux (t);
6861           
6862           DPRINTF (("construct: %s", sRef_unparse (s)));
6863
6864           if (sRef_isReasonable (s))
6865             {
6866               sRef_addDeriv (t, s);
6867
6868               s->oaliaskind = s->aliaskind;
6869               s->oexpkind = s->expkind;
6870             }
6871           
6872           return s;
6873         }
6874     }
6875 }
6876
6877 /*@exposed@*/ sRef
6878 sRef_constructPointer (/*@exposed@*/ sRef t)
6879    /*@modifies t@*/
6880 {
6881   return sRef_buildPointer (t);
6882 }
6883
6884 static /*@exposed@*/ sRef sRef_constructDerefAux (sRef t, bool isdead)
6885 {
6886   if (sRef_isReasonable (t))
6887     {
6888       sRef s;
6889       
6890       /*
6891       ** if there is a derived t[?], return that.  Otherwise, *t.
6892       */
6893       
6894       s = sRef_findDerivedArrayFetch (t, FALSE, 0, isdead);
6895       
6896       if (sRef_isReasonable (s))
6897         {
6898           DPRINTF (("Found array fetch: %s", sRef_unparseFull (s)));
6899           return s;
6900         }
6901       else
6902         {
6903           sRef ret = sRef_constructPointer (t);
6904
6905           DPRINTF (("Constructed pointer: %s", sRef_unparseFull (ret)));
6906
6907           return ret;
6908         }
6909     }
6910   else
6911     {
6912       return sRef_undefined;
6913     }
6914 }
6915
6916 sRef sRef_constructDeref (sRef t)
6917 {
6918   return sRef_constructDerefAux (t, FALSE);
6919 }
6920
6921 sRef sRef_constructDeadDeref (sRef t)
6922 {
6923   return sRef_constructDerefAux (t, TRUE);
6924 }
6925
6926 static sRef
6927 sRef_constructPointerAux (/*@notnull@*/ /*@exposed@*/ sRef t)
6928 {
6929   sRef s = sRef_newRef ();
6930   ctype rt = t->type;
6931   ctype st;
6932   
6933   llassert (valueTable_isUndefined (s->state));
6934
6935   s->kind = SK_PTR;
6936   s->info = (sinfo) dmalloc (sizeof (*s->info));
6937   s->info->ref = t; 
6938   
6939   if (ctype_isRealAP (rt))
6940     {
6941       s->type = ctype_baseArrayPtr (rt);
6942     }
6943   
6944   st = ctype_realType (s->type);  
6945
6946   if (t->defstate == SS_UNDEFINED)
6947     {
6948       s->defstate = SS_UNUSEABLE;
6949       s->definfo = stateInfo_copy (t->definfo);
6950     }
6951   else if ((t->defstate == SS_ALLOCATED) && !ctype_isSU (st))
6952     {
6953       s->defstate = SS_UNDEFINED;
6954       s->definfo = stateInfo_copy (t->definfo);
6955     }
6956   else
6957     {
6958       s->defstate = t->defstate;
6959       s->definfo = stateInfo_copy (t->definfo);
6960     }
6961   
6962   if (t->aliaskind == AK_LOCAL || t->aliaskind == AK_FRESH)
6963     {
6964       s->aliaskind = AK_LOCAL;
6965     }
6966   else
6967     {
6968       s->aliaskind = AK_UNKNOWN;
6969     }
6970
6971   s->expkind = sRef_getExKind (t);
6972   s->expinfo = stateInfo_copy (t->expinfo);
6973
6974   sRef_setTypeState (s);
6975
6976   s->oaliaskind = s->aliaskind;
6977   s->oexpkind = s->expkind;
6978
6979   if (valueTable_isUndefined (s->state))
6980     {
6981       s->state = context_createValueTable (s, stateInfo_makeLoc (g_currentloc, SA_CREATED));
6982     }
6983
6984   DPRINTF (("pointer: %s", sRef_unparseFull (s)));
6985   return s;
6986 }
6987
6988 bool sRef_hasDerived (sRef s)
6989 {
6990   return (sRef_isReasonable (s) && !sRefSet_isEmpty (s->deriv));
6991 }
6992
6993 void
6994 sRef_clearDerived (sRef s)
6995 {
6996   if (sRef_isReasonable (s))
6997     {
6998       DPRINTF (("Clear derived: [%p] %s", s, sRef_unparseDebug (s)));
6999       sRefSet_clear (s->deriv); 
7000     }
7001 }
7002
7003 void
7004 sRef_clearDerivedComplete (sRef s)
7005 {
7006   if (sRef_isReasonable (s))
7007     {
7008       sRef base = sRef_getBaseSafe (s);
7009       
7010       while (sRef_isReasonable (base))
7011         {
7012           DPRINTF (("Clear derived: [%p] %s", base, sRef_unparse (base)));
7013           sRefSet_clear (base->deriv); 
7014           base = sRef_getBaseSafe (base);
7015         }
7016
7017       DPRINTF (("Clear derived: [%p] %s", s, sRef_unparse (s)));
7018       sRefSet_clear (s->deriv); 
7019     }
7020 }
7021
7022 /*@exposed@*/ sRef sRef_makePointer (/*@exposed@*/ sRef s)
7023      /*@modifies s@*/
7024 {
7025   sRef res = sRef_buildPointer (s); 
7026
7027   DPRINTF (("Res: %s", sRef_unparseFull (res)));
7028   return res;
7029 }
7030
7031 /*
7032 ** &a[] => a (this is for out params)
7033 */
7034
7035 /*@exposed@*/ sRef
7036 sRef_makeAnyArrayFetch (/*@exposed@*/ sRef arr)
7037 {  
7038   if (sRef_isAddress (arr))
7039     {
7040       return (arr->info->ref);
7041     }
7042   else
7043     {
7044       return (sRef_buildArrayFetch (arr));
7045     }
7046 }
7047
7048 /*@exposed@*/ sRef
7049 sRef_makeArrayFetch (/*@exposed@*/ sRef arr)
7050 {
7051   return (sRef_buildArrayFetch (arr));
7052 }
7053
7054 /*@exposed@*/ sRef
7055 sRef_makeArrayFetchKnown (/*@exposed@*/ sRef arr, int i)
7056 {
7057   return (sRef_buildArrayFetchKnown (arr, i));
7058 }
7059
7060 /*@exposed@*/ sRef
7061 sRef_makeField (sRef rec, /*@dependent@*/ cstring f)
7062 {
7063   sRef ret;
7064   ret = sRef_buildField (rec, f);
7065   return ret;
7066 }
7067
7068 /*@exposed@*/ sRef
7069 sRef_makeNCField (/*@exposed@*/ sRef rec, /*@dependent@*/ cstring f)
7070 {
7071   return (sRef_buildNCField (rec, f));
7072 }
7073
7074 /*@only@*/ cstring
7075 sRef_unparseKindName (sRef s)
7076 {
7077   cstring result;
7078
7079   if (s == sRef_undefined) return cstring_makeLiteral ("<invalid>");
7080
7081   s = sRef_fixConj (s);
7082
7083   switch (s->kind)
7084     {
7085     case SK_CVAR: 
7086       if (sRef_isLocalVar (s)) 
7087         {
7088           result = cstring_makeLiteral ("Variable");
7089         }
7090       else
7091         {
7092           result = cstring_makeLiteral ("Undef global");
7093         }
7094       break;
7095     case SK_PARAM:
7096       result = cstring_makeLiteral ("Out parameter");
7097       break;
7098     case SK_ARRAYFETCH:
7099       if (sRef_isAnyParam (s->info->arrayfetch->arr)) 
7100         {
7101           result = cstring_makeLiteral ("Out parameter");
7102         }
7103       else if (sRef_isIndexKnown (s))
7104         {
7105           result = cstring_makeLiteral ("Array element");
7106         }
7107       else
7108         {
7109           result = cstring_makeLiteral ("Value");
7110         }
7111       break;
7112     case SK_PTR:
7113       if (sRef_isAnyParam (s->info->ref)) 
7114         {
7115           result = cstring_makeLiteral ("Out parameter");
7116         }
7117       else
7118         {
7119           result = cstring_makeLiteral ("Value");
7120         }
7121       break;
7122     case SK_ADR:
7123       result = cstring_makeLiteral ("Value");
7124       break;
7125     case SK_FIELD:
7126       result = cstring_makeLiteral ("Field");
7127       break;
7128     case SK_OBJECT:
7129       result = cstring_makeLiteral ("Object");
7130       break;
7131     case SK_UNCONSTRAINED:
7132       result = cstring_makeLiteral ("<anything>");
7133       break;
7134     case SK_RESULT:
7135     case SK_SPECIAL:
7136     case SK_UNKNOWN:
7137     case SK_EXTERNAL:
7138     case SK_DERIVED:
7139     case SK_CONST:
7140     case SK_TYPE:
7141       result = cstring_makeLiteral ("<unknown>");
7142       break;
7143     case SK_CONJ:
7144       result = cstring_makeLiteral ("<conj>");
7145       break;
7146     case SK_NEW:
7147       result = cstring_makeLiteral ("Storage");
7148       break;
7149     }
7150   
7151   return result;
7152 }
7153
7154 /*@only@*/ cstring
7155 sRef_unparseKindNamePlain (sRef s)
7156 {
7157   cstring result;
7158
7159   if (s == sRef_undefined) return cstring_makeLiteral ("<invalid>");
7160
7161   s = sRef_fixConj (s);
7162
7163   switch (s->kind)
7164     {
7165     case SK_CVAR: 
7166       if (sRef_isLocalVar (s)) 
7167         {
7168           result = cstring_makeLiteral ("Variable");
7169         }
7170       else 
7171         {
7172           result = cstring_makeLiteral ("Global");
7173         }
7174       break;
7175     case SK_PARAM:
7176       result = cstring_makeLiteral ("Parameter");
7177       break;
7178     case SK_ARRAYFETCH:
7179       if (sRef_isAnyParam (s->info->arrayfetch->arr)) 
7180         {
7181           result = cstring_makeLiteral ("Parameter");
7182         }
7183       else if (sRef_isIndexKnown (s))
7184         {
7185           result = cstring_makeLiteral ("Array element");
7186         }
7187       else 
7188         {
7189           result = cstring_makeLiteral ("Value");
7190         }
7191       break;
7192     case SK_PTR:
7193       if (sRef_isAnyParam (s->info->ref))
7194         {
7195           result = cstring_makeLiteral ("Parameter");
7196         }
7197       else
7198         {
7199           result = cstring_makeLiteral ("Value");
7200         }
7201       break;
7202     case SK_ADR:
7203       result = cstring_makeLiteral ("Value");
7204       break;
7205     case SK_FIELD:
7206       result = cstring_makeLiteral ("Field");
7207       break;
7208     case SK_OBJECT:
7209       result = cstring_makeLiteral ("Object");
7210       break;
7211     case SK_NEW:
7212       result = cstring_makeLiteral ("Storage");
7213       break;
7214     case SK_UNCONSTRAINED:
7215       result = cstring_makeLiteral ("<anything>");
7216       break;
7217     case SK_RESULT:
7218     case SK_TYPE:
7219     case SK_CONST:
7220     case SK_EXTERNAL:
7221     case SK_DERIVED:
7222     case SK_UNKNOWN:
7223     case SK_SPECIAL:
7224       result = cstring_makeLiteral ("<unknown>");
7225       break;
7226     case SK_CONJ:
7227       result = cstring_makeLiteral ("<conj>");
7228       break;
7229     }
7230   
7231   return result;
7232 }
7233
7234 /*
7235 ** s1 <- s2
7236 */
7237
7238 void
7239 sRef_copyState (sRef s1, sRef s2)
7240 {
7241   if (sRef_isReasonable (s1) && sRef_isReasonable (s2))
7242     {
7243       s1->defstate = s2->defstate;
7244       
7245       /* start modifications */
7246       s1->bufinfo.bufstate = s2->bufinfo.bufstate;
7247       s1->bufinfo.len = s2->bufinfo.len;
7248       s1->bufinfo.size = s2->bufinfo.size;
7249       /* end modifications */
7250
7251       s1->aliaskind = s2->aliaskind;
7252       s1->aliasinfo = stateInfo_update (s1->aliasinfo, s2->aliasinfo);
7253
7254       s1->expkind = s2->expkind;
7255       s1->expinfo = stateInfo_update (s1->expinfo, s2->expinfo);
7256
7257       s1->nullstate = s2->nullstate;
7258       DPRINTF (("Set null state==> %s", sRef_unparseFull (s1)));
7259       s1->nullinfo = stateInfo_update (s1->nullinfo, s2->nullinfo);
7260
7261       valueTable_free (s1->state);  
7262       s1->state = valueTable_copy (s2->state);
7263       s1->safe = s2->safe;
7264     }
7265 }
7266
7267 sRef
7268 sRef_makeNew (ctype ct, sRef t, cstring name)
7269 {
7270   sRef s = sRef_newRef ();
7271
7272   s->kind = SK_NEW;
7273   s->type = ct;
7274
7275   llassert (sRef_isReasonable (t));
7276   s->defstate = t->defstate;
7277
7278   s->aliaskind = t->aliaskind;
7279   s->oaliaskind = s->aliaskind;
7280   s->nullstate = t->nullstate;
7281   
7282   s->expkind = t->expkind;
7283   s->oexpkind = s->expkind;
7284   
7285   s->info = (sinfo) dmalloc (sizeof (*s->info));
7286   s->info->fname = name;
7287
7288   /* start modifications */
7289   s->bufinfo.bufstate = t->bufinfo.bufstate;
7290   /* end modifications */
7291   
7292   llassert (valueTable_isUndefined (s->state));
7293   s->state = valueTable_copy (t->state);
7294
7295   DPRINTF (("==> Copying state: %s", valueTable_unparse (s->state)));
7296   DPRINTF (("==> new: %s", sRef_unparseFull (s)));
7297   return s;
7298 }
7299
7300 sRef
7301 sRef_makeType (ctype ct)
7302 {
7303   sRef s = sRef_newRef ();
7304
7305   sRef_checkMutable (s);
7306
7307   s->kind = SK_TYPE;
7308   s->type = ct;
7309
7310   s->defstate = SS_UNKNOWN; 
7311   s->aliaskind = AK_UNKNOWN;
7312   sRef_setNullStateN (s, NS_UNKNOWN);
7313
7314   /* start modification */
7315   s->bufinfo.bufstate = BB_NOTNULLTERMINATED;
7316   /* end modification */
7317
7318     
7319   if (ctype_isUA (ct))
7320     {
7321       typeId uid = ctype_typeId (ct);
7322       uentry ue = usymtab_getTypeEntrySafe (uid);
7323
7324       if (uentry_isValid (ue))
7325         {
7326           sRef_mergeStateQuiet (s, uentry_getSref (ue));
7327         }
7328     }
7329   
7330   s->oaliaskind = s->aliaskind;
7331   s->oexpkind = s->expkind;
7332   llassert (valueTable_isUndefined (s->state));
7333   s->state = context_createValueTable (s, stateInfo_makeLoc (g_currentloc, SA_CREATED));
7334
7335   DPRINTF (("Create: %s", sRef_unparseFull (s)));
7336   return s;
7337 }
7338
7339 sRef
7340 sRef_makeConst (ctype ct)
7341 {
7342   sRef s = sRef_newRef ();
7343   
7344   s->kind = SK_CONST;
7345   s->type = ct;
7346
7347   s->defstate = SS_UNKNOWN;
7348   s->aliaskind = AK_UNKNOWN;
7349   sRef_setNullStateN (s, NS_UNKNOWN);
7350
7351   /* start modification */
7352   s->bufinfo.bufstate = BB_NULLTERMINATED;
7353   /* end modification */
7354
7355   /* evans 2002-04-22: added isManifestBool to avoid errors for -boolfalse initializations */
7356   if (!ctype_isManifestBool (ct) && ctype_isUA (ct)) 
7357     {
7358       typeId uid = ctype_typeId (ct);
7359       uentry te = usymtab_getTypeEntrySafe (uid);
7360       
7361       if (uentry_isValid (te))
7362         {
7363           sRef_mergeStateQuiet (s, uentry_getSref (te));
7364         }
7365     }
7366   
7367   s->oaliaskind = s->aliaskind;
7368   s->oexpkind = s->expkind;
7369
7370   llassert (valueTable_isUndefined (s->state));
7371   s->state = context_createValueTable (s, stateInfo_makeLoc (g_currentloc, SA_CREATED));
7372
7373   return s;
7374 }
7375
7376 bool sRef_hasName (sRef s)
7377 {
7378   if (sRef_isInvalid (s))
7379     {
7380       return (FALSE);
7381     }
7382
7383   switch (s->kind)
7384     {
7385     case SK_CVAR:
7386       {
7387         uentry u = usymtab_getRefQuiet (s->info->cvar->lexlevel,
7388                                          s->info->cvar->index);
7389         return (uentry_hasName (u));
7390       }
7391     case SK_PARAM:
7392       {
7393         if (s->info->paramno >= 0)
7394           {
7395             uentry u = uentryList_getN (context_getParams (), 
7396                                         s->info->paramno);
7397             
7398             return (uentry_hasName (u));
7399           }
7400         else
7401           {
7402             llassert (s->info->paramno == PARAMUNKNOWN);
7403             return FALSE;
7404           }
7405       }
7406     default:
7407       return TRUE;
7408     }
7409 }
7410
7411 bool
7412 sRef_sameName (sRef s1, sRef s2)
7413 {
7414   if (sRef_isInvalid (s1))
7415     {
7416       return sRef_isInvalid (s2);
7417     }
7418
7419   if (sRef_isInvalid (s2))
7420     {
7421       return (FALSE);
7422     }
7423
7424   switch (s1->kind)
7425     {
7426     case SK_CVAR:
7427       if (s2->kind == SK_CVAR)
7428         {
7429           return (s1->info->cvar->lexlevel == s2->info->cvar->lexlevel
7430                   && s1->info->cvar->index == s2->info->cvar->index);
7431         }
7432       else if (s2->kind == SK_PARAM)
7433         {
7434           if (context_inFunctionLike ())
7435             {
7436               if (s2->info->paramno != PARAMUNKNOWN)
7437                 {
7438                   uentry u1 = usymtab_getRefQuiet (s1->info->cvar->lexlevel,
7439                                                    s1->info->cvar->index);
7440                   uentry u2 = uentryList_getN (context_getParams (), 
7441                                                s2->info->paramno);
7442                   
7443                   return (cstring_equalFree (uentry_getName (u1),
7444                                              uentry_getName (u2)));
7445                 }
7446               else
7447                 {
7448                   return s1->info->paramno == PARAMUNKNOWN;
7449                 }
7450             }
7451           else 
7452             {
7453               return FALSE;
7454             }
7455         }
7456       else
7457         {
7458           return FALSE;
7459         }
7460     case SK_PARAM:
7461       {
7462         if (s2->kind == SK_PARAM)
7463           {
7464             return (s1->info->paramno == s2->info->paramno);
7465           }
7466         else if (s2->kind == SK_CVAR)
7467           {
7468             if (context_inFunctionLike ())
7469               {
7470                 if (s1->info->paramno == PARAMUNKNOWN)
7471                   {
7472                     return FALSE;
7473                   }
7474                 else
7475                   {
7476                     uentry u1 = uentryList_getN (context_getParams (), 
7477                                                  s1->info->paramno);
7478                     uentry u2 = usymtab_getRefQuiet (s2->info->cvar->lexlevel,
7479                                                      s2->info->cvar->index);
7480                     
7481                     
7482                     return (cstring_equalFree (uentry_getName (u1),
7483                                                uentry_getName (u2)));
7484                   }
7485               }
7486             else 
7487               {
7488                 return FALSE;
7489               }
7490           }
7491         else
7492           {
7493             return FALSE;
7494           }
7495       }
7496
7497     case SK_UNCONSTRAINED:
7498       return FALSE;
7499
7500     case SK_ARRAYFETCH:
7501       if (s2->kind == SK_ARRAYFETCH)
7502         {
7503           if (bool_equal (s1->info->arrayfetch->indknown,
7504                           s2->info->arrayfetch->indknown))
7505             {
7506               if (!s1->info->arrayfetch->indknown 
7507                   || (s1->info->arrayfetch->ind == s2->info->arrayfetch->ind))
7508                 {
7509                   return sRef_sameName (s1->info->arrayfetch->arr,
7510                                         s2->info->arrayfetch->arr);
7511                 }
7512             }
7513         }
7514
7515       return FALSE;
7516     case SK_FIELD:
7517       if (s2->kind == SK_FIELD)
7518         {
7519           if (cstring_equal (s1->info->field->field,
7520                              s2->info->field->field))
7521             {
7522               return sRef_sameName (s1->info->field->rec,
7523                                     s2->info->field->rec);
7524             }
7525
7526         }
7527       return FALSE;
7528     case SK_PTR:
7529     case SK_ADR:
7530     case SK_DERIVED:
7531     case SK_EXTERNAL:
7532       if (s2->kind == s1->kind)
7533         {
7534           return sRef_sameName (s1->info->ref,
7535                                 s2->info->ref);
7536         }
7537
7538       return FALSE;
7539     case SK_OBJECT:
7540       return FALSE;
7541     case SK_CONJ:
7542       return sRef_sameName (sRef_getConjA (s1), s2);
7543     case SK_NEW:
7544       return FALSE;
7545     case SK_UNKNOWN:
7546       return (s2->kind == SK_UNKNOWN);
7547     case SK_TYPE:
7548     case SK_CONST:
7549       if (s2->kind == s1->kind)
7550         {
7551           return (ctype_equal (s1->type, s2->type));
7552         }
7553       
7554       return FALSE;
7555     case SK_SPECIAL:
7556       if (s2->kind == SK_SPECIAL)
7557         {
7558           return (s1->info->spec == s2->info->spec);
7559         }
7560       return FALSE;
7561     case SK_RESULT:
7562       return (s2->kind == SK_RESULT);
7563     default:
7564       return FALSE;
7565     }
7566   BADEXIT;
7567 }
7568                 
7569 sRef
7570 sRef_fixOuterRef (/*@returned@*/ sRef s)
7571 {
7572   sRef root = sRef_getRootBase (s);
7573
7574   if (sRef_isCvar (root))
7575     {
7576       uentry ue = usymtab_getRefQuiet (root->info->cvar->lexlevel, 
7577                                        root->info->cvar->index);
7578
7579       if (uentry_isValid (ue))
7580         {
7581           sRef uref = uentry_getSref (ue);
7582           sRef sr = sRef_fixBase (s, uref);
7583
7584           return (sr);
7585         }
7586       else
7587         {
7588           llcontbug (message ("sRef_fixOuterRef: undefined: %q", sRef_unparseDebug (s)));
7589           return (s);
7590         }
7591     }
7592
7593   return (s);
7594 }
7595
7596 void
7597 sRef_storeState (sRef s)
7598 {
7599   if (sRef_isInvalid (s)) return;
7600
7601   sRef_checkMutable (s);
7602   s->oaliaskind = s->aliaskind;
7603   s->oexpkind = s->expkind;
7604 }
7605   
7606 static void sRef_resetStateAux (sRef s, /*@unused@*/ fileloc loc)
7607 {
7608   sRef_resetState (s);
7609 }
7610
7611 void
7612 sRef_resetState (sRef s)
7613 {
7614   bool changed = FALSE;
7615   if (sRef_isInvalid (s)) return;
7616
7617   
7618   if (s->oaliaskind == AK_KILLREF && !sRef_isParam (s))
7619     {
7620       /*
7621       ** killref is used in a kludgey way, to save having to add
7622       ** another alias kind (see usymtab_handleParams)
7623       */
7624  
7625       if (s->expkind != s->oexpkind)
7626         {
7627           changed = TRUE;
7628           s->expkind = s->oexpkind;
7629         }
7630     }
7631   else
7632     {
7633       if (s->expkind != s->oexpkind)
7634         {
7635           changed = TRUE;
7636           s->expkind = s->oexpkind;       
7637         }
7638
7639       if (s->aliaskind != s->oaliaskind
7640           && s->aliaskind != AK_REFCOUNTED
7641           && s->aliaskind != AK_REFS)
7642         {
7643           changed = TRUE;
7644           s->aliaskind = s->oaliaskind;
7645         }
7646     }
7647
7648   if (changed)
7649     {
7650       sRef_clearDerived (s);
7651     }
7652   
7653   }
7654
7655 void
7656 sRef_resetStateComplete (sRef s)
7657 {
7658   sRef_innerAliasSetComplete (sRef_resetStateAux, s, fileloc_undefined);
7659 }
7660
7661 /*@exposed@*/ sRef
7662 sRef_fixBase (/*@returned@*/ sRef s, /*@returned@*/ sRef base)
7663 {
7664   sRef tmp = sRef_undefined;
7665   sRef ret;
7666
7667   if (sRef_isInvalid (s)) return s;
7668   if (sRef_isInvalid (base)) return base;
7669
7670   switch (s->kind)
7671     {
7672     case SK_RESULT:
7673     case SK_PARAM:
7674     case SK_CVAR:
7675       ret = base;
7676       break;
7677     case SK_ARRAYFETCH:
7678       tmp = sRef_fixBase (s->info->arrayfetch->arr, base);
7679
7680       if (s->info->arrayfetch->indknown)
7681         {
7682           ret = sRef_makeArrayFetchKnown (tmp, s->info->arrayfetch->ind);
7683         }
7684       else
7685         {
7686           ret = sRef_makeArrayFetch (tmp);
7687         }
7688       break;
7689     case SK_FIELD:
7690       tmp = sRef_fixBase (s->info->field->rec, base);
7691       ret = sRef_buildNCField (tmp, s->info->field->field);
7692       break;
7693     case SK_PTR:
7694       tmp = sRef_fixBase (s->info->ref, base);
7695       ret = sRef_makePointer (tmp);
7696       break;
7697     case SK_ADR:
7698       tmp = sRef_fixBase (s->info->ref, base);
7699       ret = sRef_makeAddress (tmp);
7700       break;
7701     case SK_CONJ:
7702       {
7703         sRef tmpb;
7704
7705         tmp = sRef_fixBase (s->info->conj->a, base);
7706         tmpb = sRef_fixBase (s->info->conj->b, base);
7707
7708         ret = sRef_makeConj (tmp, tmpb);
7709         break;
7710       }
7711       BADDEFAULT;
7712     }
7713
7714   return ret;
7715 }
7716
7717 static /*@exposed@*/ sRef 
7718 sRef_fixDirectBase (sRef s, sRef base)
7719 {
7720   sRef ret;
7721
7722   
7723   if (sRef_isInvalid (s))
7724     {
7725       return sRef_undefined;
7726     }
7727   
7728   switch (s->kind)
7729     {
7730     case SK_ARRAYFETCH:
7731       if (s->info->arrayfetch->indknown)
7732         {
7733           ret = sRef_makeArrayFetchKnown (base, s->info->arrayfetch->ind);
7734         }
7735       else
7736         {
7737           ret = sRef_makeArrayFetch (base);
7738         }
7739       break;
7740     case SK_FIELD:
7741       ret = sRef_buildNCField (base, s->info->field->field);
7742       break;
7743     case SK_PTR:
7744             ret = sRef_makePointer (base);
7745             break;
7746     case SK_ADR:
7747       ret = sRef_makeAddress (base);
7748       break;
7749     case SK_CONJ:
7750       {
7751         sRef tmpa, tmpb;
7752
7753         tmpa = sRef_fixDirectBase (s->info->conj->a, base);
7754         tmpb = sRef_fixDirectBase (s->info->conj->b, base);
7755
7756         ret = sRef_makeConj (tmpa, tmpb);
7757         break;
7758       }
7759       BADDEFAULT;
7760     }
7761
7762     sRef_copyState (ret, s);
7763     return ret;
7764 }
7765
7766 bool
7767 sRef_isAllocIndexRef (sRef s)
7768 {
7769   return (sRef_isArrayFetch (s) && !(s->info->arrayfetch->indknown) 
7770           && sRef_isAllocated (s->info->arrayfetch->arr));
7771 }
7772
7773 void
7774 sRef_showRefLost (sRef s)
7775 {
7776   if (sRef_hasAliasInfoLoc (s))
7777     {
7778       llgenindentmsg (cstring_makeLiteral ("Original reference lost"),
7779                       sRef_getAliasInfoLoc (s));
7780     }
7781 }
7782
7783 void
7784 sRef_showRefKilled (sRef s)
7785 {
7786   if (sRef_isValid (s)) 
7787     {
7788       DPRINTF (("Killed: %s", sRef_unparseFull (s)));
7789       if (context_getLocIndentSpaces () == 0) {
7790         stateInfo_display (s->definfo, message ("  Storage %q", sRef_unparseOpt (s)));
7791       } else {
7792         stateInfo_display (s->definfo, message ("Storage %q", sRef_unparseOpt (s)));
7793       }
7794     }
7795 }
7796
7797 void
7798 sRef_showStateInconsistent (sRef s)
7799 {
7800   if (sRef_hasStateInfoLoc (s))
7801     {
7802       llgenindentmsg
7803         (message ("Storage %qbecomes inconsistent (released on one branch)",
7804                   sRef_unparseOpt (s)), 
7805          sRef_getStateInfoLoc (s));
7806     }
7807 }
7808
7809 void
7810 sRef_showStateInfo (sRef s)
7811 {
7812   if (sRef_isValid (s)) {
7813     if (context_getLocIndentSpaces () == 0) {
7814       stateInfo_display (s->definfo, message ("   Storage %q", sRef_unparseOpt (s)));
7815     } else {
7816       stateInfo_display (s->definfo, message ("Storage %q", sRef_unparseOpt (s)));
7817     }
7818   }
7819 }
7820
7821 void
7822 sRef_showExpInfo (sRef s)
7823 {
7824   if (sRef_isValid (s)) {
7825     if (context_getLocIndentSpaces () == 0) {
7826       stateInfo_display (s->expinfo, message ("   Storage %q", sRef_unparseOpt (s)));
7827     } else {
7828       stateInfo_display (s->expinfo, message ("Storage %q", sRef_unparseOpt (s)));
7829     }
7830   }
7831 }
7832
7833 void
7834 sRef_showMetaStateInfo (sRef s, cstring key)
7835 {
7836   stateValue val;
7837   metaStateInfo minfo = context_lookupMetaStateInfo (key);
7838
7839   llassert (sRef_isReasonable (s));
7840   llassert (valueTable_isDefined (s->state));
7841   llassert (metaStateInfo_isDefined (minfo));
7842
7843   val = valueTable_lookup (s->state, key);
7844   
7845   if (stateValue_hasLoc (val))
7846     {
7847       llgenindentmsg 
7848         (message ("%qbecomes %q", sRef_unparseOpt (s), 
7849                   stateValue_unparseValue (val, minfo)),
7850          stateValue_getLoc (val));
7851     }
7852 }
7853
7854 void
7855 sRef_showNullInfo (sRef s)
7856 {
7857   DPRINTF (("Show null info: %s", sRef_unparseFull (s)));
7858
7859   if (sRef_hasNullInfoLoc (s) && sRef_isKnown (s))
7860     {
7861       DPRINTF (("has null info: %s",
7862                 fileloc_unparse (sRef_getNullInfoLoc (s))));
7863
7864       switch (sRef_getNullState (s))
7865         {
7866         case NS_CONSTNULL:
7867           {
7868             fileloc loc = sRef_getNullInfoLoc (s);
7869             
7870             if (fileloc_isDefined (loc) && !fileloc_isLib (loc))
7871               {
7872                 llgenindentmsg 
7873                   (message ("Storage %qbecomes null", sRef_unparseOpt (s)),
7874                    loc);
7875               }
7876             break;
7877           }
7878         case NS_DEFNULL:
7879           {
7880             fileloc loc = sRef_getNullInfoLoc (s);
7881             
7882             if (fileloc_isDefined (loc) && !fileloc_isLib (loc))
7883               {
7884                 llgenindentmsg (message ("Storage %qbecomes null", sRef_unparseOpt (s)),
7885                                 loc);
7886               }
7887             break;
7888           }
7889         case NS_ABSNULL:
7890         case NS_POSNULL:
7891           llgenindentmsg
7892             (message ("Storage %qmay become null", sRef_unparseOpt (s)),
7893              sRef_getNullInfoLoc (s));
7894           break;
7895         case NS_NOTNULL:
7896         case NS_MNOTNULL:
7897           llgenindentmsg
7898             (message ("Storage %qbecomes not null", sRef_unparseOpt (s)),
7899              sRef_getNullInfoLoc (s));
7900           break;
7901         case NS_UNKNOWN:
7902           llgenindentmsg
7903             (message ("Storage %qnull state becomes unknown",
7904                       sRef_unparseOpt (s)),
7905              sRef_getNullInfoLoc (s));
7906           break;
7907
7908         case NS_ERROR:
7909           BADBRANCHCONT;
7910           break;
7911
7912         default:
7913           llgenindentmsg
7914             (message ("<error case> Storage %q becomes %s",
7915                       sRef_unparse (s), 
7916                       nstate_unparse (sRef_getNullState (s))),
7917              sRef_getNullInfoLoc (s));
7918           
7919           break;
7920         }
7921     }
7922 }
7923
7924 void
7925 sRef_showAliasInfo (sRef s)
7926 {
7927   if (sRef_isValid (s)) 
7928     {
7929       if (sRef_isFresh (s))
7930         {
7931           if (context_getLocIndentSpaces () == 0) {
7932             stateInfo_display (s->aliasinfo, message ("   Fresh storage %q", sRef_unparseOpt (s)));
7933           } else {
7934             stateInfo_display (s->aliasinfo, message ("Fresh storage %q", sRef_unparseOpt (s)));
7935           }
7936         }
7937       else
7938         {
7939           if (context_getLocIndentSpaces () == 0) {
7940             stateInfo_display (s->aliasinfo, message ("   Storage %q", sRef_unparseOpt (s))); 
7941           } else {
7942             stateInfo_display (s->aliasinfo, message ("Storage %q", sRef_unparseOpt (s)));
7943           }
7944         }
7945     }
7946 }
7947
7948 void
7949 sRef_mergeNullState (sRef s, nstate n)
7950 {
7951   if (sRef_isReasonable (s))
7952     {
7953       nstate old;
7954       
7955       old = sRef_getNullState (s);
7956       
7957       if (n != old && n != NS_UNKNOWN)
7958         {                 
7959           sRef_setNullState (s, n, g_currentloc);
7960         }
7961     }
7962   else
7963     {
7964       llbuglit ("sRef_mergeNullState: invalid");
7965     }
7966 }
7967
7968 bool
7969 sRef_possiblyNull (sRef s)
7970 {
7971   if (sRef_isReasonable (s))
7972     {
7973       if (sRef_getNullState (s) == NS_ABSNULL)
7974         {
7975           ctype rct = ctype_realType (s->type);
7976           
7977           if (ctype_isAbstract (rct))
7978             {
7979               return FALSE;
7980             }
7981           else
7982             {
7983               if (ctype_isUser (rct))
7984                 {
7985                   uentry ue = usymtab_getTypeEntry (ctype_typeId (rct));
7986                   
7987                   return (nstate_possiblyNull
7988                           (sRef_getNullState (uentry_getSref (ue))));
7989                 }
7990               else
7991                 {
7992                   return FALSE;
7993                 }
7994             }
7995         }
7996       else
7997         {
7998           return nstate_possiblyNull (sRef_getNullState (s));
7999         }
8000     }
8001   
8002   return FALSE;
8003 }
8004
8005 cstring
8006 sRef_getScopeName (sRef s)
8007 {
8008   sRef base = sRef_getRootBase (s);
8009
8010   if (sRef_isRealGlobal (base))
8011     {
8012       return (cstring_makeLiteralTemp ("Global"));
8013     }
8014   else if (sRef_isFileStatic (base))
8015     {
8016       return (cstring_makeLiteralTemp ("Static"));
8017     }
8018   else
8019     {
8020       return (cstring_makeLiteralTemp ("Local"));
8021     }
8022 }
8023
8024 cstring
8025 sRef_unparseScope (sRef s)
8026 {
8027   sRef base = sRef_getRootBase (s);
8028
8029   if (sRef_isRealGlobal (base))
8030     {
8031       return (cstring_makeLiteralTemp ("global"));
8032     }
8033   else if (sRef_isFileStatic (base))
8034     {
8035       return (cstring_makeLiteralTemp ("file static"));
8036     }
8037   else
8038     {
8039       BADEXIT;
8040     }
8041 }
8042
8043 int
8044 sRef_getScope (sRef s)
8045 {
8046   llassert (sRef_isReasonable (s));
8047
8048   if (sRef_isCvar (s))
8049     {
8050       return s->info->cvar->lexlevel;
8051     }
8052   else if (sRef_isParam (s))
8053     {
8054       return paramsScope;
8055     }
8056   else
8057     {
8058       return fileScope;
8059     }
8060 }
8061
8062 bool
8063 sRef_isDead (sRef s)
8064 {
8065   return (sRef_isReasonable (s) && (s)->defstate == SS_DEAD);
8066 }
8067
8068 bool
8069 sRef_isDeadStorage (sRef s)
8070 {
8071   if (sRef_isReasonable (s))
8072     {
8073       if (s->defstate == SS_DEAD
8074           || s->defstate == SS_UNUSEABLE
8075           || s->defstate == SS_UNDEFINED
8076           || s->defstate == SS_UNKNOWN)
8077         {
8078           return TRUE;
8079         }
8080       else 
8081         {
8082           return (sRef_isDefinitelyNull (s));
8083         }
8084     }
8085   else
8086     {
8087       return FALSE;
8088     }
8089 }
8090
8091 bool
8092 sRef_isPossiblyDead (sRef s)
8093 {
8094   return (sRef_isReasonable (s) && s->defstate == SS_HOFFA);
8095 }
8096
8097 bool sRef_isStateLive (sRef s)
8098 {
8099   if (sRef_isReasonable (s))
8100     {
8101       sstate ds = s->defstate;
8102
8103       return (!(ds == SS_UNDEFINED 
8104                 || ds == SS_DEAD
8105                 || ds == SS_UNUSEABLE
8106                 || ds == SS_HOFFA));
8107     }
8108   else
8109     {
8110       return FALSE;
8111     }
8112 }
8113
8114
8115 bool sRef_isStateUndefined (sRef s)
8116 {
8117   return ((sRef_isReasonable(s)) && ((s)->defstate == SS_UNDEFINED));
8118 }
8119
8120 bool sRef_isJustAllocated (sRef s)
8121 {
8122   if (sRef_isAllocated (s))
8123     {
8124       sRefSet_allElements (s->deriv, el)
8125         {
8126           if (!(sRef_isStateUndefined (el) || sRef_isUnuseable (el)))
8127             {
8128               return FALSE;
8129             }
8130         } end_sRefSet_allElements ;
8131
8132       return TRUE;
8133     }
8134
8135   return FALSE;
8136 }
8137
8138 static bool
8139 sRef_isAllocatedStorage (sRef s)
8140 {
8141   if (sRef_isReasonable (s) && ynm_toBoolStrict (sRef_isValidLvalue (s)))
8142     {
8143       return (ctype_isVisiblySharable (sRef_getType (s)));
8144     }
8145   else
8146     {
8147       return FALSE;
8148     }
8149 }
8150
8151 bool
8152 sRef_isUnuseable (sRef s)
8153 {
8154   return ((sRef_isValid(s)) && ((s)->defstate == SS_UNUSEABLE));
8155 }
8156
8157 bool
8158 sRef_perhapsNull (sRef s)
8159 {
8160   if (sRef_isReasonable (s))
8161     {
8162       if (sRef_getNullState (s) == NS_ABSNULL)
8163         {
8164           ctype rct = ctype_realType (s->type);
8165
8166           if (ctype_isAbstract (rct))
8167             {
8168               return FALSE;
8169             }
8170           else
8171             {
8172               if (ctype_isUser (rct))
8173                 {
8174                   uentry ue = usymtab_getTypeEntry (ctype_typeId (rct));
8175
8176                   return (nstate_perhapsNull 
8177                           (sRef_getNullState (uentry_getSref (ue))));
8178                 }
8179               else
8180                 {
8181                   return FALSE;
8182                 }
8183             }
8184         }
8185       else
8186         {
8187           return nstate_perhapsNull (sRef_getNullState (s));
8188         }
8189     }
8190
8191   return FALSE;
8192 }
8193
8194 /*
8195 ** definitelyNull --- called when TRUE is good
8196 */
8197
8198 bool 
8199 sRef_definitelyNull (sRef s)
8200 {
8201   return (sRef_isReasonable (s)
8202           && (sRef_getNullState (s) == NS_DEFNULL || sRef_getNullState (s) == NS_CONSTNULL));
8203 }
8204
8205 /*
8206 ** based on sRef_similar
8207 */
8208
8209 void
8210 sRef_setDerivNullState (sRef set, sRef guide, nstate ns)
8211 {
8212   if (sRef_isReasonable (set))
8213     {
8214       sRef deriv = sRef_getDeriv (set, guide);
8215       
8216       if (sRef_isReasonable (deriv))
8217         {
8218           sRef_setNullStateN (deriv, ns);
8219         }
8220     }
8221 }
8222
8223 static /*@exposed@*/ sRef
8224 sRef_getDeriv (/*@returned@*/ /*@notnull@*/ sRef set, sRef guide)
8225 {
8226   llassert (sRef_isReasonable (set));
8227   llassert (sRef_isReasonable (guide));
8228
8229   switch (guide->kind)
8230     {
8231     case SK_CVAR:
8232       llassert (set->kind == SK_CVAR);      
8233       return set;
8234
8235     case SK_PARAM:
8236       llassert (set->kind == guide->kind);
8237       llassert (set->info->paramno == guide->info->paramno);
8238       return set;
8239
8240     case SK_ARRAYFETCH:
8241
8242       if (set->kind == SK_ARRAYFETCH
8243           && (sRef_similar (set->info->arrayfetch->arr,
8244                             guide->info->arrayfetch->arr)))
8245         {
8246           return set;
8247         }
8248       else
8249         {
8250           return (sRef_makeAnyArrayFetch 
8251                   (sRef_getDeriv (set, guide->info->arrayfetch->arr)));
8252         }
8253
8254     case SK_PTR:
8255       
8256       if (set->kind == SK_PTR && sRef_similar (set->info->ref, guide->info->ref))
8257         {
8258           return set;
8259         }
8260       else
8261         {
8262           return (sRef_makePointer (sRef_getDeriv (set, guide->info->ref)));
8263         }
8264       
8265     case SK_FIELD:
8266       
8267       if ((set->kind == SK_FIELD &&
8268            (sRef_similar (set->info->field->rec, guide->info->field->rec) &&
8269             cstring_equal (set->info->field->field, guide->info->field->field))))
8270         {
8271           return set;
8272         }
8273       else
8274         {
8275           return (sRef_makeField (sRef_getDeriv (set, guide->info->field->rec),
8276                                   guide->info->field->field));
8277         }
8278     case SK_ADR:
8279       
8280       if ((set->kind == SK_ADR) && sRef_similar (set->info->ref, guide->info->ref))
8281         {
8282           return set;
8283         }
8284       else
8285         {
8286           return (sRef_makeAddress (sRef_getDeriv (set, guide->info->ref)));
8287         }
8288
8289     case SK_CONJ:
8290       
8291             return sRef_undefined;
8292
8293     case SK_RESULT:
8294     case SK_SPECIAL:
8295     case SK_UNCONSTRAINED:
8296     case SK_TYPE:
8297     case SK_CONST:
8298     case SK_NEW:
8299     case SK_UNKNOWN:
8300     case SK_OBJECT:
8301     case SK_DERIVED:
8302     case SK_EXTERNAL:
8303       return sRef_undefined;
8304     }
8305
8306   BADEXIT;
8307 }
8308       
8309 /*
8310 ** sRef_aliasCheckPred
8311 **
8312 ** A confusing but spiffy function:
8313 **
8314 **    Calls predf (s, e, text, <alias>) on s and all of s's aliases
8315 **    (unless checkAliases (s) is FALSE).
8316 **
8317 **    For alias calls, calls as
8318 **          predf (alias, e, text, s)
8319 */
8320
8321 void
8322 sRef_aliasCheckPred (bool (predf) (sRef, exprNode, sRef, exprNode),
8323                      /*@null@*/ bool (checkAliases) (sRef),
8324                      sRef s, exprNode e, exprNode err)
8325 {
8326   bool error = (*predf)(s, e, sRef_undefined, err);
8327   
8328   
8329   if (checkAliases != NULL && !(checkAliases (s)))
8330     {
8331       /* don't check aliases */
8332     }
8333   else
8334     {
8335       sRefSet aliases = usymtab_allAliases (s);
8336       
8337       sRefSet_realElements (aliases, current)
8338         {
8339           if (sRef_isReasonable (current))
8340             {
8341               if (sRef_isReasonable (current))
8342                 {
8343                   if (!sRef_similar (current, s)
8344                       || (error && sRef_sameName (current, s)))
8345                     {
8346                       (void) (*predf)(current, e, s, err);
8347                     }
8348                 }
8349               else
8350                 {
8351                   llcontbug (message ("Invalid sRef as alias field of %s", sRef_unparse (s)));
8352                 }
8353             }
8354         } end_sRefSet_realElements;
8355
8356       sRefSet_free (aliases);
8357     }
8358 }
8359
8360 /*
8361 ** return TRUE iff predf (s) is true for s or any alias of s
8362 */
8363
8364 bool
8365 sRef_aliasCheckSimplePred (sRefTest predf, sRef s)
8366 {
8367     
8368   if ((*predf)(s))
8369     {
8370       return TRUE;
8371     }
8372   else
8373     {
8374       sRefSet aliases;
8375
8376       aliases = usymtab_allAliases (s);
8377       
8378       sRefSet_realElements (aliases, current)
8379         {
8380           if (sRef_isReasonable (current))
8381             {
8382               sRef cref = sRef_updateSref (current);
8383               
8384               /* Whoa! a very kludgey way to make sure the right sref is used
8385               ** where there is a conditional symbol table.  I am beginning
8386               ** to think that having a conditional symbol table wasn't such
8387               ** a great idea.  ;(
8388               */
8389               
8390               if ((*predf)(cref))
8391                 {
8392                   DPRINTF (("Checking alias: %s", sRef_unparseFull (cref)));
8393                   sRefSet_free (aliases);
8394                   return TRUE;
8395                 }
8396             }
8397         } end_sRefSet_realElements;
8398
8399       sRefSet_free (aliases);
8400     }
8401   return FALSE;
8402 }
8403
8404 bool
8405 sRef_aliasCompleteSimplePred (bool (predf) (sRef), sRef s)
8406 {
8407   sRefSet aliases;
8408   bool result = FALSE;
8409   
8410   
8411   aliases = usymtab_allAliases (s);
8412   
8413   if ((*predf)(s)) result = TRUE;
8414
8415   
8416   sRefSet_realElements (aliases, current)
8417     {
8418       if (sRef_isReasonable (current))
8419         {
8420           current = sRef_updateSref (current);
8421           if ((*predf)(current)) result = TRUE;
8422         }
8423     } end_sRefSet_realElements;
8424   
8425   sRefSet_free (aliases);
8426   return result;
8427 }
8428
8429 void
8430 sRef_aliasSetComplete (void (predf) (sRef, fileloc), sRef s, fileloc loc)
8431 {
8432   sRefSet aliases;
8433   
8434   aliases = usymtab_allAliases (s);
8435
8436   DPRINTF (("All aliases: %s --> %s", sRef_unparseFull (s), sRefSet_unparseFull (aliases)));
8437
8438   (*predf)(s, loc);
8439
8440   sRefSet_realElements (aliases, current)
8441     {
8442       if (sRef_isReasonable (current))
8443         {
8444           DPRINTF (("Update: %s", sRef_unparseFull (current)));
8445           current = sRef_updateSref (current);
8446           DPRINTF (("Updated ==> %s", sRef_unparseFull (current)));
8447           ((*predf)(current, loc));
8448           DPRINTF (("Killed: %s", sRef_unparseFull (current)));
8449         }
8450     } end_sRefSet_realElements;
8451
8452   sRefSet_free (aliases);
8453 }
8454
8455 void
8456 sRef_aliasSetCompleteParam (void (predf) (sRef, int, fileloc), sRef s, 
8457                             int kind, fileloc loc)
8458 {
8459   sRefSet aliases;
8460   
8461   if (sRef_isDeep (s))
8462     {
8463       aliases = usymtab_allAliases (s);
8464     }
8465   else
8466     {
8467       aliases = usymtab_aliasedBy (s);
8468     }
8469
8470   (*predf)(s, kind, loc);
8471
8472   sRefSet_realElements (aliases, current)
8473     {
8474       if (sRef_isReasonable (current))
8475         {
8476           current = sRef_updateSref (current);
8477           ((*predf)(current, kind, loc));
8478         }
8479     } end_sRefSet_realElements;
8480
8481   sRefSet_free (aliases);
8482 }
8483
8484 /*
8485 ** Version of aliasSetCompleteParam for alkind parameters
8486 */
8487
8488 void
8489 sRef_aliasSetCompleteAlkParam (void (predf) (sRef, alkind, fileloc), sRef s, 
8490                                alkind kind, fileloc loc)
8491 {
8492   sRefSet aliases;
8493   
8494   if (sRef_isDeep (s))
8495     {
8496       aliases = usymtab_allAliases (s);
8497     }
8498   else
8499     {
8500       aliases = usymtab_aliasedBy (s);
8501     }
8502
8503   (*predf)(s, kind, loc);
8504
8505   sRefSet_realElements (aliases, current)
8506     {
8507       if (sRef_isReasonable (current))
8508         {
8509           current = sRef_updateSref (current);
8510           ((*predf)(current, kind, loc));
8511         }
8512     } end_sRefSet_realElements;
8513
8514   sRefSet_free (aliases);
8515 }
8516
8517 static void
8518 sRef_innerAliasSetComplete (void (predf) (sRef, fileloc), sRef s, fileloc loc)
8519 {
8520   sRef inner;
8521   sRefSet aliases;
8522   ctype ct;
8523
8524   if (!sRef_isReasonable (s)) return;
8525
8526   /*
8527   ** Type equivalence checking is necessary --- there might be casting.
8528   */
8529
8530   (*predf)(s, loc);
8531
8532   switch (s->kind)
8533     {
8534     case SK_UNCONSTRAINED:
8535     case SK_CVAR:
8536     case SK_PARAM:
8537       break;
8538     case SK_PTR:
8539       inner = s->info->ref;
8540       aliases = usymtab_allAliases (inner);
8541       ct = sRef_getType (inner);
8542       
8543       sRefSet_realElements (aliases, current)
8544         {
8545           if (sRef_isReasonable (current))
8546             {
8547               current = sRef_updateSref (current);
8548               
8549               if (ctype_equal (ct, sRef_getType (current)))
8550                 {
8551                   sRef ptr = sRef_makePointer (current);
8552                   ((*predf)(ptr, loc));
8553                 }
8554             }
8555         } end_sRefSet_realElements;
8556
8557       sRefSet_free (aliases);
8558       break;
8559     case SK_ARRAYFETCH:
8560       inner = s->info->arrayfetch->arr;
8561       aliases = usymtab_allAliases (inner);
8562       ct = sRef_getType (inner);
8563
8564       DPRINTF (("Array fetch: %s", sRefSet_unparse (aliases)));
8565
8566       sRefSet_realElements (aliases, current)
8567         {
8568           if (sRef_isReasonable (current))
8569             {
8570               current = sRef_updateSref (current);
8571               DPRINTF (("Current: %s", sRef_unparseFull (current)));
8572
8573               if (ctype_equal (ct, sRef_getType (current)))
8574                 {
8575                   if (s->info->arrayfetch->indknown)
8576                     {
8577                       sRef af = sRef_makeArrayFetchKnown (current, s->info->arrayfetch->ind);
8578                       DPRINTF (("Defining: %s", sRef_unparseFull (af)));
8579                       /* evans 2001-08-27 This isn't true:
8580                            llassert (af->info->arrayfetch->arr == current);
8581                          see comments in buildArrayFetchKnown
8582                       */
8583                       ((*predf)(af, loc));
8584                     }
8585                   else
8586                     {
8587                       sRef af = sRef_makeArrayFetch (current);
8588                       /* evans 2001-08-27 This isn't true:
8589                          llassert (af->info->arrayfetch->arr == current);
8590                          see comments in buildArrayFetch
8591                       */ 
8592                       DPRINTF (("Defining: %s", sRef_unparseFull (af)));
8593                       ((*predf)(af, loc));
8594                     }
8595                 }
8596               else
8597                 {
8598                   DPRINTF (("Type mismatch: %s / %s",
8599                             ctype_unparse (ct),
8600                             ctype_unparse (sRef_getType (current))));
8601                 }
8602             }
8603         } end_sRefSet_realElements;
8604
8605       sRefSet_free (aliases);
8606       break;
8607     case SK_FIELD:
8608       inner = s->info->field->rec;
8609       aliases = usymtab_allAliases (inner);
8610       ct = sRef_getType (inner);
8611       
8612       sRefSet_realElements (aliases, current)
8613         {
8614           if (sRef_isReasonable (current))
8615             {
8616               current = sRef_updateSref (current);
8617               
8618               if (ctype_equal (ct, sRef_getType (current)))
8619                 {
8620                   sRef f = sRef_makeField (current, s->info->field->field);
8621                   
8622                   ((*predf)(f, loc));
8623                 }
8624             }
8625         } end_sRefSet_realElements;
8626       
8627       sRefSet_free (aliases);
8628       break;
8629     case SK_CONJ:
8630       sRef_innerAliasSetComplete (predf, s->info->conj->a, loc);
8631       sRef_innerAliasSetComplete (predf, s->info->conj->b, loc);
8632       break;
8633     case SK_SPECIAL:
8634     case SK_ADR:
8635     case SK_TYPE:
8636     case SK_CONST:
8637     case SK_NEW:
8638     case SK_UNKNOWN:
8639     case SK_OBJECT:
8640     case SK_DERIVED:
8641     case SK_EXTERNAL:
8642     case SK_RESULT:
8643       break;
8644     }
8645 }
8646
8647 static void
8648 sRef_innerAliasSetCompleteParam (void (predf) (sRef, sRef), sRef s, sRef t)
8649 {
8650   sRef inner;
8651   sRefSet aliases;
8652   ctype ct;
8653
8654   if (!sRef_isReasonable (s)) return;
8655
8656   /*
8657   ** Type equivalence checking is necessary --- there might be casting.
8658   */
8659
8660   (*predf)(s, t);
8661
8662   switch (s->kind)
8663     {
8664     case SK_UNCONSTRAINED:
8665     case SK_CVAR:
8666     case SK_PARAM:
8667       break;
8668     case SK_PTR:
8669       inner = s->info->ref;
8670       aliases = usymtab_allAliases (inner);
8671       ct = sRef_getType (inner);
8672             
8673       sRefSet_realElements (aliases, current)
8674         {
8675           if (sRef_isReasonable (current))
8676             {
8677               current = sRef_updateSref (current);
8678               
8679               if (ctype_equal (ct, sRef_getType (current)))
8680                 {
8681                   sRef ptr = sRef_makePointer (current);
8682                   
8683                   ((*predf)(ptr, t));
8684                 }
8685             }
8686         } end_sRefSet_realElements;
8687
8688       sRefSet_free (aliases);
8689       break;
8690     case SK_ARRAYFETCH:
8691       inner = s->info->arrayfetch->arr;
8692       aliases = usymtab_allAliases (inner);
8693       ct = sRef_getType (inner);
8694
8695       sRefSet_realElements (aliases, current)
8696         {
8697           if (sRef_isReasonable (current))
8698             {
8699               current = sRef_updateSref (current);
8700               
8701               if (ctype_equal (ct, sRef_getType (current)))
8702                 {
8703                                   
8704                   if (s->info->arrayfetch->indknown)
8705                     {
8706                       sRef af = sRef_makeArrayFetchKnown (current, s->info->arrayfetch->ind);
8707                       
8708                       ((*predf)(af, t));
8709                     }
8710                   else
8711                     {
8712                       sRef af = sRef_makeArrayFetch (current);
8713                       
8714                       ((*predf)(af, t));
8715                     }
8716                 }
8717             }
8718         } end_sRefSet_realElements;
8719
8720       sRefSet_free (aliases);
8721       break;
8722     case SK_FIELD:
8723       inner = s->info->field->rec;
8724       aliases = usymtab_allAliases (inner);
8725       ct = sRef_getType (inner);
8726
8727       
8728       sRefSet_realElements (aliases, current)
8729         {
8730           if (sRef_isReasonable (current))
8731             {
8732               current = sRef_updateSref (current);
8733               
8734               if (ctype_equal (ct, sRef_getType (current)))
8735                 {
8736                   sRef f = sRef_makeField (current, s->info->field->field);
8737                   
8738                   ((*predf)(f, t));
8739                 }
8740             }
8741         } end_sRefSet_realElements;
8742       
8743       sRefSet_free (aliases);
8744       break;
8745     case SK_CONJ:
8746       sRef_innerAliasSetCompleteParam (predf, s->info->conj->a, t);
8747       sRef_innerAliasSetCompleteParam (predf, s->info->conj->b, t);
8748       break;
8749     case SK_SPECIAL:
8750     case SK_ADR:
8751     case SK_TYPE:
8752     case SK_CONST:
8753     case SK_NEW:
8754     case SK_UNKNOWN:
8755     case SK_OBJECT:
8756     case SK_DERIVED:
8757     case SK_EXTERNAL:
8758     case SK_RESULT:
8759       break;
8760     }
8761 }
8762
8763 static void sRef_combineExKinds (/*@notnull@*/ sRef res, /*@notnull@*/ sRef other)
8764 {
8765   exkind a1 = sRef_getExKind (res);
8766   exkind a2 = sRef_getExKind (other);
8767
8768   if (a1 == a2 || a2 == XO_UNKNOWN) 
8769     {
8770       ;
8771     }
8772   else if (a1 == XO_UNKNOWN) 
8773     { 
8774       res->expinfo = stateInfo_update (res->expinfo, other->expinfo);
8775       res->expkind = a2;
8776     }
8777   else
8778     {
8779       res->expkind = XO_OBSERVER;
8780     }
8781 }
8782
8783 /*
8784 ** Currently, this is a very ad hoc implementation, with lots of fixes to
8785 ** make real code work okay.  I need to come up with some more general
8786 ** rules or principles here.
8787 */
8788
8789 static void 
8790   sRef_combineAliasKindsError (/*@notnull@*/ sRef res, 
8791                                /*@notnull@*/ sRef other, 
8792                                clause cl, fileloc loc)
8793 {
8794   bool hasError = FALSE;
8795   alkind ares = sRef_getAliasKind (res);
8796   alkind aother = sRef_getAliasKind (other);
8797
8798   sRef_checkMutable (res);
8799
8800   if (alkind_isDependent (ares))
8801     {
8802       if (aother == AK_KEPT)
8803         {
8804           res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8805           res->aliaskind = AK_KEPT;      
8806         }
8807       else 
8808         {
8809           if (aother == AK_LOCAL || aother == AK_STATIC 
8810               || alkind_isTemp (aother))
8811             {
8812               DPRINTF (("Setting dependent: %s", sRef_unparseFull (res)));
8813               res->aliaskind = AK_DEPENDENT;
8814             }
8815         }
8816     }
8817   else if (alkind_isDependent (aother))
8818     {
8819       if (ares == AK_KEPT)
8820         {
8821           res->aliaskind = AK_KEPT;      
8822         }
8823       else 
8824         {
8825           if (ares == AK_LOCAL || ares == AK_STATIC || alkind_isTemp (ares))
8826             {
8827               DPRINTF (("Setting dependent: %s", sRef_unparseFull (res)));
8828               res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8829               res->aliaskind = AK_DEPENDENT;
8830             }
8831         }
8832     }
8833   else if ((ares == AK_LOCAL || ares == AK_UNIQUE
8834             || ares == AK_STATIC || alkind_isTemp (ares))
8835            && sRef_isFresh (other))
8836     {
8837       /*
8838       ** cases like: if (s == NULL) s = malloc...;
8839       **    don't generate errors
8840       */
8841       
8842       if (usymtab_isAltDefinitelyNullDeep (res))
8843         {
8844           res->aliaskind = ares;
8845         }
8846       else
8847         {
8848           hasError = TRUE; 
8849         }
8850     }
8851   else if ((aother == AK_LOCAL || aother == AK_UNIQUE
8852             || aother == AK_STATIC || alkind_isTemp (aother))
8853            && sRef_isFresh (res))
8854     {
8855       /*
8856       ** cases like: if (s == NULL) s = malloc...;
8857       **    don't generate errors
8858       */
8859       
8860       if (usymtab_isDefinitelyNullDeep (other))
8861         {
8862           res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8863           res->aliaskind = aother;
8864         }
8865       else
8866         {
8867           hasError = TRUE;
8868         }
8869     }
8870   else if (ares == AK_NEWREF && aother == AK_REFCOUNTED 
8871            && sRef_isConst (other))
8872     {
8873       res->aliaskind = AK_NEWREF;
8874     }
8875   else if (aother == AK_NEWREF && ares == AK_REFCOUNTED
8876            && sRef_isConst (res))
8877     {
8878       res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8879       res->aliaskind = AK_NEWREF;
8880     }
8881   else if (sRef_isLocalVar (res)
8882            && ((ares == AK_KEPT && aother == AK_LOCAL)
8883                || (aother == AK_KEPT && ares == AK_LOCAL)))
8884     {
8885       res->aliaskind = AK_KEPT;
8886     }
8887   else if ((ares == AK_OWNED && aother == AK_ONLY)
8888            || (aother == AK_OWNED && ares == AK_ONLY))
8889     {
8890       res->aliaskind = AK_OWNED;
8891
8892       if (aother == AK_OWNED)
8893         {
8894           res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8895         }
8896     }
8897   else
8898     {
8899       hasError = TRUE;
8900     }
8901
8902   if (hasError)
8903     {
8904       if (sRef_isThroughArrayFetch (res))
8905         {
8906           if (optgenerror2 
8907               (FLG_BRANCHSTATE, FLG_STRICTBRANCHSTATE,
8908                message
8909                ("Clauses exit with %q possibly referencing %s storage %s, "
8910                 "%s storage %s", 
8911                 sRef_unparse (res),
8912                 alkind_unparse (aother),
8913                 clause_nameTaken (cl),
8914                 alkind_unparse (ares),
8915                 clause_nameAlternate (cl)),
8916                loc))
8917             {
8918               sRef_showAliasInfo (res);
8919               sRef_showAliasInfo (other);
8920               res->aliaskind = AK_ERROR;
8921             }
8922           else
8923             {
8924               if (ares == AK_KEPT || aother == AK_KEPT)
8925                 {
8926                   sRef_maybeKill (res, loc);
8927                 }
8928             }
8929         }
8930       else 
8931         {
8932           if (optgenerror 
8933               (FLG_BRANCHSTATE,
8934                message ("Clauses exit with %q referencing %s storage %s, "
8935                         "%s storage %s", 
8936                         sRef_unparse (res),
8937                         alkind_unparse (aother),
8938                         clause_nameTaken (cl),
8939                         alkind_unparse (ares),
8940                         clause_nameAlternate (cl)),
8941                loc))
8942             {
8943               sRef_showAliasInfo (res);
8944               sRef_showAliasInfo (other);
8945               
8946               res->aliaskind = AK_ERROR;
8947             }
8948         }
8949       
8950       res->aliaskind = (sRef_isLocalVar (res) ? AK_LOCAL : AK_UNKNOWN);
8951     }
8952 }
8953
8954 static void 
8955   sRef_combineAliasKinds (/*@notnull@*/ sRef res, /*@notnull@*/ sRef other, 
8956                           clause cl, fileloc loc)
8957 {
8958   alkind ares = sRef_getAliasKind (res);
8959   alkind aother = sRef_getAliasKind (other);
8960
8961   sRef_checkMutable (res);
8962
8963   DPRINTF (("Combine alias kinds: \n\t%s / \n\t%s",
8964             sRef_unparseFull (res), sRef_unparseFull (other)));
8965   if (alkind_equal (ares, aother)
8966       || aother == AK_UNKNOWN
8967       || aother == AK_ERROR)
8968     {
8969       ; /* keep current state */
8970     }
8971   else if (sRef_isDead (res) || sRef_isDead (other))
8972     {
8973       /* dead error reported (or storage is dead) */
8974       res ->aliaskind = AK_ERROR; 
8975     }
8976   else if (ares == AK_UNKNOWN || ares == AK_ERROR
8977            || sRef_isStateUndefined (res)
8978            || sRef_isDefinitelyNull (res))
8979     { 
8980       res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8981       res->aliaskind = aother;  
8982     }
8983   else if (sRef_isStateUndefined (other)
8984            || sRef_isDefinitelyNull (other))
8985     {
8986       ;
8987     }
8988   else if (((ares == AK_UNIQUE || alkind_isTemp (ares))
8989             && aother == AK_LOCAL) 
8990            || ((aother == AK_UNIQUE || alkind_isTemp (aother))
8991                && ares == AK_LOCAL))
8992     {
8993       if (ares != AK_LOCAL)
8994         {
8995           res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
8996         }
8997
8998       res->aliaskind = AK_LOCAL;
8999     }
9000   else if ((ares == AK_OWNED && aother == AK_FRESH) 
9001            || (aother == AK_OWNED && ares == AK_FRESH))
9002     {
9003       if (ares != AK_FRESH)
9004         {
9005           res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
9006         }
9007       
9008       res->aliaskind = AK_FRESH;
9009     }
9010   else if ((ares == AK_KEEP && aother == AK_FRESH) ||
9011            (aother == AK_KEEP && ares == AK_FRESH))
9012     {
9013       if (ares != AK_KEEP)
9014         {
9015           res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
9016         }
9017       
9018       res->aliaskind = AK_KEEP;
9019     }
9020   else if ((ares == AK_LOCAL && aother == AK_STACK) ||
9021            (aother == AK_LOCAL && ares == AK_STACK))
9022     {
9023       if (ares != AK_STACK)
9024         {
9025           res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
9026         }
9027
9028       res->aliaskind = AK_STACK;
9029     }
9030   else if ((ares == AK_LOCAL
9031             && (aother == AK_OWNED && sRef_isLocalVar (other)))
9032            || (aother == AK_LOCAL 
9033                && (ares == AK_OWNED && sRef_isLocalVar (res))))
9034     {
9035       if (ares != AK_LOCAL)
9036         {
9037           res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
9038         }
9039
9040       res->aliaskind = AK_LOCAL;
9041     }
9042   else if ((ares == AK_FRESH && alkind_isOnly (aother))
9043            || (aother == AK_FRESH && alkind_isOnly (ares)))
9044     {
9045       res->aliaskind = AK_FRESH;
9046     }
9047   else if ((aother == AK_FRESH && sRef_definitelyNull (res))
9048            || (ares == AK_FRESH && sRef_definitelyNull (other)))
9049     {
9050       if (ares != AK_FRESH)
9051         {
9052           res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
9053           res->aliaskind = AK_FRESH;
9054         }
9055     }
9056   else if ((sRef_isFresh (res) && sRef_isConst (other))
9057            || (sRef_isFresh (other) && sRef_isConst (res)))
9058     {
9059       /*
9060       ** for NULL constantants
9061       ** this is bogus!
9062       */
9063
9064       if (!sRef_isFresh (res))
9065         {
9066           res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
9067         }
9068
9069       res->aliaskind = AK_FRESH;
9070     }
9071   else if ((alkind_isStatic (aother) && sRef_isConst (res))
9072            || (alkind_isStatic (ares) && sRef_isConst (other)))
9073     {
9074       if (!alkind_isStatic (ares))
9075         {
9076           res->aliasinfo = stateInfo_update (res->aliasinfo, other->aliasinfo);
9077           res->aliaskind = AK_STATIC;
9078         }
9079     }
9080   else
9081     {
9082       sRef_combineAliasKindsError (res, other, cl, loc);
9083     }
9084 }
9085
9086 static void sRef_combineDefState (/*@notnull@*/ sRef res, 
9087                                   /*@notnull@*/ sRef other)
9088 {
9089   sstate s1 = res->defstate;
9090   sstate s2 = other->defstate;
9091   bool flip = FALSE;
9092
9093   sRef_checkMutable (res);
9094
9095   if (s1 == s2 || s2 == SS_UNKNOWN)
9096     {
9097       ;
9098     }
9099   else if (s1 == SS_UNKNOWN)
9100     {
9101       flip = TRUE;
9102     }
9103   else
9104     {
9105       switch (s1)
9106         {
9107         case SS_FIXED:   
9108           if (s2 == SS_DEFINED) 
9109             {
9110               break;
9111             }
9112           else
9113             {
9114               llcontbuglit ("ssfixed: not implemented");
9115               flip = TRUE;
9116             }
9117           break;
9118         case SS_DEFINED: 
9119           flip = TRUE;
9120           break;
9121         case SS_PDEFINED:
9122         case SS_ALLOCATED: 
9123           flip = (s2 != SS_DEFINED);
9124           break;
9125         case SS_HOFFA:
9126         case SS_RELDEF:
9127         case SS_UNUSEABLE: 
9128         case SS_UNDEFINED: 
9129         case SS_PARTIAL:
9130         case SS_UNDEFGLOB:
9131         case SS_KILLED:
9132         case SS_DEAD:      
9133         case SS_SPECIAL: 
9134           break;
9135         BADDEFAULT;
9136         }
9137     }
9138
9139   if (flip)
9140     {
9141       res->definfo = stateInfo_update (res->definfo, other->definfo);
9142       res->defstate = s2;
9143     }
9144 }
9145
9146 extern /*@notnull@*/ sRef sRef_getConjA (sRef s)
9147 {
9148   sRef ret;
9149   llassert (sRef_isConj (s));
9150
9151   ret = s->info->conj->a;
9152   llassert (ret != NULL);
9153   return ret;
9154 }
9155
9156 extern /*@notnull@*/ sRef sRef_getConjB (sRef s)
9157 {
9158   sRef ret;
9159   llassert (sRef_isConj (s));
9160
9161   ret = s->info->conj->b;
9162   llassert (ret != NULL);
9163   return ret;
9164 }
9165   
9166 extern /*@exposed@*/ sRef sRef_makeArrow (sRef s, /*@dependent@*/ cstring f)
9167 {
9168   sRef p;
9169   sRef ret;
9170   
9171   p = sRef_makePointer (s);
9172   ret = sRef_makeField (p, f);
9173   DPRINTF (("Arrow: %s => %s",
9174             sRef_unparseFull (s), sRef_unparseFull (ret)));
9175   return ret;
9176 }
9177
9178 extern /*@exposed@*/ sRef sRef_buildArrow (sRef s, cstring f)
9179 {
9180   sRef p;
9181   sRef ret;
9182
9183   p = sRef_buildPointer (s);
9184   ret = sRef_buildField (p, f);
9185   
9186   return ret;
9187 }
9188
9189 static /*@null@*/ sinfo sinfo_copy (/*@notnull@*/ sRef s)
9190 {
9191   sinfo ret;
9192
9193   switch (s->kind)
9194     {
9195     case SK_CVAR:
9196       ret = (sinfo) dmalloc (sizeof (*ret));
9197       ret->cvar = (cref) dmalloc (sizeof (*ret->cvar));
9198       ret->cvar->lexlevel = s->info->cvar->lexlevel; 
9199       ret->cvar->index = s->info->cvar->index; 
9200       break;
9201
9202     case SK_PARAM:
9203       ret = (sinfo) dmalloc (sizeof (*ret));
9204       ret->paramno = s->info->paramno; 
9205       llassert (ret->paramno >= -1);
9206       break;
9207
9208     case SK_ARRAYFETCH:
9209       ret = (sinfo) dmalloc (sizeof (*ret));
9210       ret->arrayfetch = (ainfo) dmalloc (sizeof (*ret->arrayfetch));
9211       ret->arrayfetch->indknown = s->info->arrayfetch->indknown;
9212       ret->arrayfetch->ind = s->info->arrayfetch->ind;
9213       ret->arrayfetch->arr = s->info->arrayfetch->arr; 
9214       break;
9215
9216     case SK_FIELD:
9217       ret = (sinfo) dmalloc (sizeof (*ret));
9218       ret->field = (fldinfo) dmalloc (sizeof (*ret->field));
9219       ret->field->rec = s->info->field->rec; 
9220       ret->field->field = s->info->field->field; 
9221       break;
9222
9223     case SK_OBJECT:
9224       ret = (sinfo) dmalloc (sizeof (*ret));
9225       ret->object = s->info->object;
9226       break;
9227
9228     case SK_PTR:
9229     case SK_ADR:
9230     case SK_DERIVED:
9231     case SK_EXTERNAL:
9232       ret = (sinfo) dmalloc (sizeof (*ret));
9233       ret->ref = s->info->ref; /* Ref_copy (s->info->ref); */
9234       break;
9235
9236     case SK_CONJ:
9237       ret = (sinfo) dmalloc (sizeof (*ret));
9238       ret->conj = (cjinfo) dmalloc (sizeof (*ret->conj));
9239       ret->conj->a = s->info->conj->a; /* sRef_copy (s->info->conj->a); */
9240       ret->conj->b = s->info->conj->b; /* sRef_copy (s->info->conj->b);*/
9241       break;
9242     case SK_SPECIAL:
9243       ret = (sinfo) dmalloc (sizeof (*ret));
9244       ret->spec = s->info->spec;
9245       break;
9246
9247     case SK_UNCONSTRAINED:
9248     case SK_NEW:
9249       ret = (sinfo) dmalloc (sizeof (*ret));
9250       ret->fname = s->info->fname;
9251       break;
9252
9253     case SK_RESULT:
9254     case SK_CONST:
9255     case SK_TYPE:
9256     case SK_UNKNOWN:
9257       llassertprint (s->info == NULL, ("s = %s", sRef_unparse (s)));
9258       ret = NULL;
9259       break;
9260     }
9261
9262   return ret;
9263 }
9264
9265 static /*@null@*/ sinfo sinfo_fullCopy (/*@notnull@*/ sRef s)
9266 {
9267   sinfo ret;
9268
9269   /*
9270   ** Since its a full copy, only storage is assigned
9271   ** to dependent fields.
9272   */
9273   /*@-onlytrans@*/
9274
9275   switch (s->kind)
9276     {
9277     case SK_CVAR:
9278       ret = (sinfo) dmalloc (sizeof (*ret));
9279       ret->cvar = (cref) dmalloc (sizeof (*ret->cvar));
9280       ret->cvar->lexlevel = s->info->cvar->lexlevel; 
9281       ret->cvar->index = s->info->cvar->index; 
9282       break;
9283
9284     case SK_PARAM:
9285       ret = (sinfo) dmalloc (sizeof (*ret));
9286       ret->paramno = s->info->paramno; 
9287       llassert (ret->paramno >= -1);
9288       break;
9289
9290     case SK_ARRAYFETCH:
9291       ret = (sinfo) dmalloc (sizeof (*ret));
9292       ret->arrayfetch = (ainfo) dmalloc (sizeof (*ret->arrayfetch));
9293       ret->arrayfetch->indknown = s->info->arrayfetch->indknown;
9294       ret->arrayfetch->ind = s->info->arrayfetch->ind;
9295       ret->arrayfetch->arr = sRef_saveCopy (s->info->arrayfetch->arr);
9296       break;
9297
9298     case SK_FIELD:
9299       ret = (sinfo) dmalloc (sizeof (*ret));
9300       ret->field = (fldinfo) dmalloc (sizeof (*ret->field));
9301       ret->field->rec = sRef_saveCopy (s->info->field->rec);
9302       ret->field->field = s->info->field->field; 
9303       break;
9304
9305     case SK_OBJECT:
9306       ret = (sinfo) dmalloc (sizeof (*ret));
9307       ret->object = s->info->object;
9308       break;
9309
9310     case SK_PTR:
9311     case SK_ADR:
9312     case SK_DERIVED:
9313     case SK_EXTERNAL:
9314       ret = (sinfo) dmalloc (sizeof (*ret));
9315       ret->ref = sRef_saveCopy (s->info->ref);   
9316       break;
9317
9318     case SK_CONJ:
9319       ret = (sinfo) dmalloc (sizeof (*ret));
9320       ret->conj = (cjinfo) dmalloc (sizeof (*ret->conj));
9321       ret->conj->a = sRef_saveCopy (s->info->conj->a);
9322       ret->conj->b = sRef_saveCopy (s->info->conj->b);
9323       break;
9324     case SK_SPECIAL:
9325       ret = (sinfo) dmalloc (sizeof (*ret));
9326       ret->spec = s->info->spec;
9327       break;
9328     case SK_NEW:
9329     case SK_UNCONSTRAINED:
9330       ret = (sinfo) dmalloc (sizeof (*ret));
9331       ret->fname = s->info->fname;
9332       break;
9333     case SK_CONST:
9334     case SK_TYPE:
9335     case SK_RESULT:
9336     case SK_UNKNOWN:
9337       llassert (s->info == NULL);
9338       ret = NULL;
9339       break;
9340     }
9341   /*@=onlytrans@*/ 
9342   return ret;
9343 }
9344
9345
9346 static void 
9347   sinfo_update (/*@notnull@*/ /*@exposed@*/ sRef res, 
9348                 /*@notnull@*/ /*@exposed@*/ sRef other)
9349 {
9350   llassert (res->kind == other->kind);
9351
9352   switch (res->kind)
9353     {
9354     case SK_CVAR:
9355       res->info->cvar->lexlevel = other->info->cvar->lexlevel; 
9356       res->info->cvar->index = other->info->cvar->index; 
9357       break;
9358
9359     case SK_PARAM:
9360       res->info->paramno = other->info->paramno; 
9361       llassert (res->info->paramno >= -1);
9362       break;
9363
9364     case SK_ARRAYFETCH:
9365       res->info->arrayfetch->indknown = other->info->arrayfetch->indknown;
9366       res->info->arrayfetch->ind = other->info->arrayfetch->ind;
9367       res->info->arrayfetch->arr = other->info->arrayfetch->arr;
9368       break;
9369
9370     case SK_FIELD:
9371       res->info->field->rec = other->info->field->rec;
9372       res->info->field->field = other->info->field->field; 
9373       break;
9374
9375     case SK_OBJECT:
9376       res->info->object = other->info->object;
9377       break;
9378
9379     case SK_PTR:
9380     case SK_ADR:
9381     case SK_DERIVED:
9382     case SK_EXTERNAL:
9383       res->info->ref = other->info->ref;         
9384       break;
9385
9386     case SK_CONJ:
9387       res->info->conj->a = other->info->conj->a;
9388       res->info->conj->b = other->info->conj->b;
9389       break;
9390
9391     case SK_SPECIAL:
9392       res->info->spec = other->info->spec;
9393       break;
9394
9395     case SK_NEW:
9396     case SK_UNCONSTRAINED:
9397       res->info->fname = other->info->fname;
9398       break;
9399
9400     case SK_CONST:
9401     case SK_TYPE:
9402     case SK_UNKNOWN:
9403     case SK_RESULT:
9404       llassert (res->info == NULL);
9405       break;
9406     }
9407 }
9408
9409 static void sinfo_free (/*@special@*/ /*@temp@*/ /*@notnull@*/ sRef s)
9410    /*@uses s->kind, s->info@*/
9411    /*@releases s->info@*/ 
9412 {
9413   switch (s->kind)
9414     {
9415     case SK_CVAR:
9416       DPRINTF (("Free sinfo: [%p]", s->info->cvar));
9417       sfree (s->info->cvar);
9418       break;
9419
9420     case SK_PARAM:
9421       break;
9422
9423     case SK_ARRAYFETCH:
9424       DPRINTF (("Free sinfo: [%p]", s->info->arrayfetch));
9425       sfree (s->info->arrayfetch);
9426       break;
9427
9428     case SK_FIELD:
9429       DPRINTF (("Free sinfo: [%p]", s->info->field));
9430       sfree (s->info->field); 
9431       break;
9432
9433     case SK_OBJECT:
9434       break;
9435
9436     case SK_PTR:
9437     case SK_ADR:
9438     case SK_DERIVED:
9439     case SK_EXTERNAL: /* is copy now! */
9440       break;
9441
9442     case SK_CONJ:
9443       DPRINTF (("Free sinfo: [%p]", s->info->conj));
9444       sfree (s->info->conj);
9445       break;
9446
9447     case SK_UNCONSTRAINED:
9448     case SK_SPECIAL:
9449     case SK_CONST:
9450     case SK_NEW:
9451     case SK_TYPE:
9452     case SK_UNKNOWN:
9453     case SK_RESULT:
9454       break;
9455     }
9456
9457   if (s->info != NULL) {
9458       DPRINTF (("Free sinfo: [%p]", s->info));
9459   }
9460
9461   sfree (s->info);
9462 }
9463
9464 bool sRef_isNSLocalVar (sRef s)  
9465 {
9466   if (sRef_isLocalVar (s))
9467     {
9468       uentry ue = sRef_getUentry (s);
9469
9470       return (!uentry_isStatic (ue));
9471     }
9472   else
9473     {
9474       return FALSE;
9475     }
9476 }
9477
9478 bool sRef_isLocalVar (sRef s)  
9479 {
9480   if (sRef_isValid(s))
9481     {
9482       return (s->kind == SK_CVAR 
9483               && (s->info->cvar->lexlevel > fileScope));
9484     }
9485   
9486   return FALSE;
9487 }
9488
9489 bool sRef_isRealLocalVar (sRef s)  
9490 {
9491   if (sRef_isValid(s))
9492     {
9493       if (s->kind == SK_CVAR)
9494         {
9495           if (s->info->cvar->lexlevel == functionScope)
9496             {
9497               uentry ue = sRef_getUentry (s);
9498
9499               if (uentry_isAnyParam (ue)
9500                   || uentry_isRefParam (ue))
9501                 {
9502                   return FALSE;
9503                 }
9504               else
9505                 {
9506                   return TRUE;
9507                 }
9508             }
9509           else
9510             {
9511               return (s->info->cvar->lexlevel > functionScope);
9512             }
9513         }
9514     }
9515   
9516   return FALSE;
9517 }
9518
9519 bool sRef_isLocalParamVar (sRef s)  
9520 {
9521   if (sRef_isValid(s))
9522     {
9523       return (s->kind == SK_PARAM
9524               || (s->kind == SK_CVAR 
9525                   && (s->info->cvar->lexlevel > fileScope)));
9526     }
9527   
9528   return FALSE;
9529 }
9530
9531 static speckind speckind_fromInt (int i)
9532 {
9533   /*@+enumint@*/ 
9534   llassert (i >= SR_NOTHING && i <= SR_SYSTEM); 
9535   /*@=enumint@*/
9536
9537   return ((speckind) i);
9538 }
9539
9540
9541 static void sRef_updateNullState (/*@notnull@*/ sRef res, /*@notnull@*/ sRef other)
9542      /*@modifies res@*/
9543 {
9544   res->nullstate = other->nullstate;
9545   DPRINTF (("update null state==> %s", sRef_unparseFull (res)));
9546   res->nullinfo = stateInfo_update (res->nullinfo, other->nullinfo);
9547   sRef_resetAliasKind (res);
9548 }
9549
9550 void sRef_combineNullState (/*@notnull@*/ sRef res, /*@notnull@*/ sRef other)
9551 {
9552   nstate n1 = sRef_getNullState (res);
9553   nstate n2 = sRef_getNullState (other);
9554   bool flip = FALSE;
9555   nstate nn = n1;
9556
9557   if (n1 == n2 || n2 == NS_UNKNOWN)
9558     {
9559       ;
9560     }
9561   else
9562     {
9563       /* note: n2 is not unknown or defnull */
9564
9565       switch (n1)
9566         {
9567         case NS_ERROR:   nn = NS_ERROR; break;
9568         case NS_UNKNOWN: flip = TRUE; nn = n2; break; 
9569         case NS_POSNULL: break;
9570         case NS_DEFNULL: nn = NS_POSNULL; break;
9571         case NS_RELNULL: break;
9572         case NS_NOTNULL:  
9573           if (n2 == NS_MNOTNULL)
9574             {
9575               ;
9576             }
9577           else 
9578             { 
9579               flip = TRUE;
9580               nn = NS_POSNULL; 
9581             }
9582           break;
9583         case NS_MNOTNULL: 
9584           if (n2 == NS_NOTNULL) 
9585             {
9586               nn = NS_NOTNULL; 
9587             }
9588           else 
9589             {
9590               flip = TRUE;
9591               nn = NS_POSNULL; 
9592             }
9593           break;
9594         case NS_CONSTNULL:
9595         case NS_ABSNULL:
9596           flip = TRUE;
9597           nn = n2;
9598         }
9599     }
9600   
9601   if (flip)
9602     {
9603       res->nullinfo = stateInfo_update (res->nullinfo, other->nullinfo);      
9604     }
9605
9606   res->nullstate = nn;
9607   DPRINTF (("update null state==> %s", sRef_unparseFull (res)));
9608   sRef_resetAliasKind (res);
9609 }
9610
9611 cstring sRef_nullMessage (sRef s)
9612 {
9613   llassert (sRef_isReasonable (s));
9614
9615   switch (sRef_getNullState (s))
9616     {
9617     case NS_DEFNULL:
9618     case NS_CONSTNULL:
9619       return (cstring_makeLiteralTemp ("null"));
9620     default:
9621       return (cstring_makeLiteralTemp ("possibly null"));
9622     }
9623   BADEXIT;
9624 }
9625
9626 /*@observer@*/ cstring sRef_ntMessage (sRef s)
9627 {
9628   llassert (sRef_isReasonable (s));
9629
9630   switch (s->nullstate)
9631     {
9632     case NS_DEFNULL:
9633     case NS_CONSTNULL:
9634       return (cstring_makeLiteralTemp ("not nullterminated"));
9635     default:
9636       return (cstring_makeLiteralTemp ("possibly non-nullterminated"));
9637     }
9638   BADEXIT;
9639 }
9640
9641
9642
9643 sRef sRef_fixResultType (/*@returned@*/ sRef s, ctype typ, uentry ue)
9644 {
9645   sRef tmp = sRef_undefined;
9646   sRef ret;
9647
9648   llassert (sRef_isReasonable (s));
9649
9650   switch (s->kind)
9651     {
9652     case SK_RESULT:
9653       s->type = typ;
9654       ret = s;
9655       break;
9656     case SK_ARRAYFETCH:
9657       {
9658         ctype ct;
9659         tmp = sRef_fixResultType (s->info->arrayfetch->arr, typ, ue);
9660
9661         ct = ctype_realType (sRef_getType (tmp));
9662
9663         
9664         if (ctype_isKnown (ct))
9665           {
9666             if (ctype_isAP (ct))
9667               {
9668                 ;
9669               }
9670             else
9671               {
9672                 voptgenerror 
9673                   (FLG_TYPE,
9674                    message
9675                    ("Special clause indexes non-array (%t): *%q",
9676                     ct, sRef_unparse (s->info->arrayfetch->arr)),
9677                    uentry_whereLast (ue));
9678               }
9679           }
9680
9681         tmp = sRef_fixResultType (s->info->arrayfetch->arr, typ, ue);
9682
9683         if (s->info->arrayfetch->indknown)
9684           {
9685             ret = sRef_makeArrayFetchKnown (tmp, s->info->arrayfetch->ind);
9686           }
9687         else
9688           {
9689             ret = sRef_makeArrayFetch (tmp);
9690           }
9691       }
9692       break;
9693     case SK_FIELD:
9694       {
9695         sRef rec = sRef_fixResultType (s->info->field->rec, typ, ue);
9696         ctype ct = ctype_realType (sRef_getType (rec));
9697
9698         if (ctype_isKnown (ct))
9699           {
9700             if (ctype_isSU (ct))
9701               {
9702                 if (uentry_isValid (uentryList_lookupField (ctype_getFields (ct), 
9703                                                             s->info->field->field)))
9704                   {
9705                     ;
9706                   }
9707                 else
9708                   {
9709                     voptgenerror 
9710                       (FLG_TYPE,
9711                        message
9712                        ("Special clause accesses non-existent field of result: %q.%s",
9713                         sRef_unparse (rec), s->info->field->field),
9714                        uentry_whereLast (ue));
9715                   }
9716               }
9717             else
9718               {
9719                 voptgenerror 
9720                   (FLG_TYPE,
9721                    message
9722                    ("Special clause accesses field of non-struct or union result (%t): %q.%s",
9723                     ct, sRef_unparse (rec), s->info->field->field),
9724                    uentry_whereLast (ue));
9725               }
9726           }
9727         
9728         ret = sRef_makeField (tmp, s->info->field->field);
9729         break;
9730       }
9731     case SK_PTR:
9732       {
9733         ctype ct;
9734         tmp = sRef_fixResultType (s->info->ref, typ, ue);
9735
9736         ct = ctype_realType (sRef_getType (tmp));
9737
9738         if (ctype_isKnown (ct))
9739           {
9740             if (ctype_isAP (ct))
9741               {
9742                 ;
9743               }
9744             else
9745               {
9746                 voptgenerror 
9747                   (FLG_TYPE,
9748                    message
9749                    ("Special clause dereferences non-pointer (%t): *%q",
9750                     ct, sRef_unparse (s->info->ref)),
9751                    uentry_whereLast (ue));
9752               }
9753           }
9754         
9755         ret = sRef_makePointer (tmp);
9756         break;
9757       }
9758     case SK_ADR:
9759       voptgenerror 
9760         (FLG_TYPE,
9761          message
9762          ("Special clause uses & operator (not allowed): &%q", sRef_unparse (s->info->ref)),
9763          uentry_whereLast (ue));
9764       ret = s;
9765       break;
9766     BADDEFAULT;
9767     }
9768
9769   return ret;
9770 }
9771
9772 bool sRef_isOnly (sRef s)
9773 {
9774   return (sRef_isValid(s) && alkind_isOnly (s->aliaskind));
9775 }
9776
9777 bool sRef_isDependent (sRef s) 
9778 {
9779   return (sRef_isValid(s) && alkind_isDependent (s->aliaskind));
9780 }
9781
9782 bool sRef_isOwned (sRef s)
9783 {
9784   return (sRef_isReasonable (s) && (s->aliaskind == AK_OWNED));
9785 }
9786
9787 bool sRef_isKeep (sRef s) 
9788 {
9789   return (sRef_isReasonable (s) && (s->aliaskind == AK_KEEP));
9790 }
9791
9792 bool sRef_isTemp (sRef s)
9793 {
9794   return (sRef_isReasonable (s) && alkind_isTemp (s->aliaskind));
9795 }
9796
9797 bool sRef_isLocalState (sRef s) 
9798 {
9799   return (sRef_isReasonable (s) && (s->aliaskind == AK_LOCAL));
9800 }
9801
9802 bool sRef_isUnique (sRef s)
9803 {
9804   return (sRef_isReasonable (s) && (s->aliaskind == AK_UNIQUE));
9805 }
9806
9807 bool sRef_isShared (sRef s) 
9808 {
9809   return (sRef_isReasonable (s) && (s->aliaskind == AK_SHARED));
9810 }
9811
9812 bool sRef_isExposed (sRef s) 
9813 {
9814   return (sRef_isReasonable (s) && (s->expkind == XO_EXPOSED));
9815 }
9816
9817 bool sRef_isObserver (sRef s) 
9818 {
9819   return (sRef_isReasonable (s) && (s->expkind == XO_OBSERVER));
9820 }
9821
9822 bool sRef_isFresh (sRef s) 
9823 {
9824   return (sRef_isReasonable (s) && (s->aliaskind == AK_FRESH));
9825 }
9826
9827 bool sRef_isDefinitelyNull (sRef s) 
9828 {
9829   return (sRef_isReasonable (s) && (sRef_getNullState (s) == NS_DEFNULL 
9830                                || sRef_getNullState (s) == NS_CONSTNULL));
9831 }
9832
9833 bool sRef_isAllocated (sRef s)
9834 {
9835   return (sRef_isReasonable (s) && (s->defstate == SS_ALLOCATED));
9836 }
9837
9838 bool sRef_isStack (sRef s)
9839 {
9840   return (sRef_isReasonable (s) && (s->aliaskind == AK_STACK));
9841 }
9842
9843 bool sRef_isNotNull (sRef s)
9844 {
9845   return (sRef_isValid(s) && (sRef_getNullState (s) == NS_MNOTNULL 
9846                               || sRef_getNullState (s) == NS_NOTNULL));
9847 }
9848
9849 alkind sRef_getAliasKind (sRef s)
9850 {
9851   if (sRef_isValid(s)) {
9852     llassert (alkind_isValid (s->aliaskind));
9853     return s->aliaskind;
9854   }
9855
9856   return AK_ERROR;
9857 }
9858
9859 nstate sRef_getNullState (sRef s)
9860 {
9861   if (sRef_isReasonable (s)) {
9862     llassert (nstate_isValid (s->nullstate));
9863     return s->nullstate;
9864   }
9865   
9866   return NS_UNKNOWN;
9867 }
9868
9869 void sRef_reflectAnnotation (sRef s, annotationInfo a, fileloc loc)
9870 {
9871   if (sRef_isReasonable (s))
9872     {
9873       if (!valueTable_isDefined (s->state))
9874         {
9875           s->state = valueTable_create (1);
9876           valueTable_insert
9877             (s->state, 
9878              cstring_copy (metaStateInfo_getName (annotationInfo_getState (a))),
9879              stateValue_create (annotationInfo_getValue (a), 
9880                                 stateInfo_makeLoc (loc, SA_DECLARED)));
9881         }
9882       else
9883         {
9884           DPRINTF (("reflect loc: %s", fileloc_unparse (loc)));
9885           valueTable_update 
9886             (s->state,
9887              metaStateInfo_getName (annotationInfo_getState (a)),
9888              stateValue_create (annotationInfo_getValue (a),
9889                                 stateInfo_makeLoc (loc, SA_DECLARED)));
9890           
9891           DPRINTF (("sref: %s", sRef_unparse (s)));
9892           DPRINTF (("sref: %s", sRef_unparseFull (s)));
9893         }
9894     }
9895 }
9896
9897 void sRef_setMetaStateValueComplete (sRef s, cstring key, int value, fileloc loc)
9898 {
9899   sRefSet aliases = usymtab_allAliases (s);
9900
9901   sRef_setMetaStateValue (s, key, value, loc);
9902
9903   sRefSet_realElements (aliases, current)
9904     {
9905       if (sRef_isReasonable (current))
9906         {
9907           current = sRef_updateSref (current);
9908           sRef_setMetaStateValue (current, key, value, loc);
9909         }
9910     } end_sRefSet_realElements ;
9911
9912   sRefSet_free (aliases);
9913 }
9914
9915 void sRef_setMetaStateValue (sRef s, cstring key, int value, fileloc loc)
9916 {
9917   sRef_checkMutable (s);
9918
9919   if (sRef_isReasonable (s))
9920     {
9921       if (!valueTable_isDefined (s->state))
9922         {
9923           DPRINTF (("inserting state: %s: %s %d", sRef_unparse (s), key, value));
9924           s->state = valueTable_create (1);
9925           valueTable_insert (s->state, cstring_copy (key),
9926                              stateValue_create (value, 
9927                                                 stateInfo_makeLoc (loc, SA_CHANGED)));
9928         }
9929       else
9930         {
9931           DPRINTF (("Updating state: %s: %s %d / %s", sRef_unparse (s), key, value,
9932                     fileloc_unparse (loc)));
9933           if (valueTable_contains (s->state, key))
9934             {
9935               valueTable_update 
9936                 (s->state, key, stateValue_create (value,
9937                                                    stateInfo_makeLoc (loc, SA_CHANGED)));
9938             }
9939           else
9940             {
9941               valueTable_insert 
9942                 (s->state, cstring_copy (key),
9943                  stateValue_create (value, stateInfo_makeLoc (loc, SA_CHANGED)));
9944             }
9945
9946           DPRINTF (("After: %s", sRef_unparseFull (s)));
9947         }
9948     }
9949 }
9950
9951 bool sRef_checkMetaStateValue (sRef s, cstring key, int value)
9952 {
9953   if (sRef_isReasonable (s))
9954     {
9955       if (valueTable_isDefined (s->state))
9956         {
9957           stateValue val;
9958           
9959           DPRINTF (("check state: %s: %s %d", sRef_unparse (s), key, value));
9960           
9961           val = valueTable_lookup (s->state, key);
9962           llassert (stateValue_isDefined (val));
9963           return (stateValue_isError (val)
9964                   || stateValue_getValue (val) == value);
9965         }
9966       else
9967         {
9968           return TRUE;
9969         }
9970     }
9971   else
9972     {
9973       return TRUE;
9974     }
9975 }
9976
9977 /*@observer@*/ stateValue sRef_getMetaStateValue (sRef s, cstring key)
9978 {
9979   if (sRef_isReasonable (s))
9980     {
9981       if (valueTable_isDefined (s->state))
9982         {
9983           stateValue val;
9984           
9985           val = valueTable_lookup (s->state, key);
9986           /* Okay if its not defined, just returns stateValue_undefined */
9987           return val;
9988         }
9989       else
9990         {
9991           return stateValue_undefined;
9992         }
9993     }
9994   else
9995     {
9996       return stateValue_undefined;
9997     }
9998 }
9999
10000 /*@observer@*/ valueTable sRef_getValueTable (sRef s) 
10001 {
10002   DPRINTF (("Get value table: %s", sRef_unparse (s)));
10003
10004   if (sRef_isReasonable (s)) 
10005     {
10006       llassert (sRef_isReasonable (s));
10007       DPRINTF (("Value table: %s", valueTable_unparse (s->state)));
10008       return s->state;
10009     }  
10010   else 
10011     {
10012       DPRINTF (("No value table!"));
10013       return valueTable_undefined;
10014     }
10015 }
10016
10017 bool sRef_makeStateSpecial (sRef s)
10018 {
10019   /*
10020   ** Default defined state can be made special.
10021   */
10022
10023   llassert (sRef_isReasonable (s));
10024
10025   if (s->defstate == SS_UNKNOWN || s->defstate == SS_DEFINED || s->defstate == SS_SPECIAL)
10026     {
10027       /* s->aliaskind = AK_IMPTEMP; */ /* evans 2001-07-23 shouldn't effect alias state */
10028       s->defstate = SS_SPECIAL;
10029       DPRINTF (("Made special: %s", sRef_unparseFull (s)));
10030       return TRUE;
10031     }
10032   else
10033     {
10034       /* s->aliaskind = AK_IMPTEMP; */
10035       s->defstate = SS_SPECIAL;
10036       return FALSE;
10037     }
10038 }
10039
10040 void sRef_markImmutable (sRef s)
10041 {
10042   if (sRef_isReasonable (s))
10043     {
10044       DPRINTF (("Mark immutable: %s", sRef_unparseFull (s)));
10045       s->immut = TRUE;
10046     }
10047 }
10048
10049 bool sRef_definitelyNullContext (sRef s)
10050 {
10051   return (sRef_definitelyNull (s)
10052           || usymtab_isDefinitelyNullDeep (s));
10053 }
10054
10055 bool sRef_definitelyNullAltContext (sRef s)
10056 {
10057   return (sRef_definitelyNull (s)
10058           || usymtab_isAltDefinitelyNullDeep (s));
10059 }
10060
10061
10062 /* start modifications */
10063 struct s_bbufinfo sRef_getNullTerminatedState (sRef p_s) {
10064    struct s_bbufinfo BUFSTATE_UNKNOWN;
10065    BUFSTATE_UNKNOWN.bufstate = BB_NOTNULLTERMINATED;
10066    BUFSTATE_UNKNOWN.size = 0;
10067    BUFSTATE_UNKNOWN.len = 0;
10068    
10069    if (sRef_isValid(p_s))
10070       return p_s->bufinfo;
10071    return BUFSTATE_UNKNOWN; 
10072 }
10073
10074 void sRef_setNullTerminatedState(sRef p_s) {
10075    if(sRef_isReasonable (p_s)) {
10076       p_s->bufinfo.bufstate = BB_NULLTERMINATED;
10077    } else {
10078       llfatalbug( message("sRef_setNT passed a invalid sRef\n"));
10079    }
10080 }
10081
10082
10083 void sRef_setPossiblyNullTerminatedState(sRef p_s) {
10084    if( sRef_isReasonable (p_s)) {
10085       p_s->bufinfo.bufstate = BB_POSSIBLYNULLTERMINATED;
10086    } else {
10087       llfatalbug( message("sRef_setPossNT passed a invalid sRef\n"));
10088    }
10089 }
10090
10091 void sRef_setNotNullTerminatedState(sRef p_s) {
10092    if( sRef_isReasonable (p_s)) {
10093       p_s->bufinfo.bufstate = BB_NOTNULLTERMINATED;
10094    } else {
10095       llfatalbug( message("sRef_unsetNT passed a invalid sRef\n"));
10096    }
10097 }
10098
10099 void sRef_setLen(sRef p_s, int len) {
10100    if (sRef_isReasonable (p_s) && sRef_isNullTerminated(p_s)) 
10101      {
10102        p_s->bufinfo.len = len;
10103      } 
10104    else 
10105      {
10106        llfatalbug( message("sRef_setLen passed an invalid sRef\n"));
10107      }
10108 }
10109     
10110
10111 void sRef_setSize(sRef p_s, int size) {
10112    if( sRef_isValid(p_s)) 
10113      {
10114        p_s->bufinfo.size = size;
10115      } 
10116    else
10117      {
10118        llfatalbug( message("sRef_setSize passed a invalid sRef\n"));
10119      }
10120 }
10121
10122 void sRef_resetLen(sRef p_s) {
10123   if (sRef_isReasonable (p_s)) 
10124     {
10125       p_s->bufinfo.len = 0;
10126     }
10127   else
10128     {
10129       llfatalbug (message ("sRef_setLen passed an invalid sRef\n"));
10130     }
10131 }
10132
10133 /*drl7x 11/28/2000 */
10134
10135 bool sRef_isFixedArray (sRef p_s) /*@*/ {
10136   ctype c;
10137   c = sRef_getType (p_s);
10138   return ( ctype_isFixedArray (c) );
10139 }
10140
10141 size_t sRef_getArraySize (sRef p_s) /*@*/ 
10142 {
10143   ctype c;
10144   llassert (sRef_isFixedArray(p_s) );
10145   DPRINTF (( message ("sRef_getArraySize getting array size for %s", sRef_unparse(p_s) )  ));
10146   
10147   c = sRef_getType (p_s);
10148   return (ctype_getArraySize (c));
10149 }
10150
10151 void sRef_setValue (sRef s, multiVal val)
10152 {
10153   if (!sRef_isReasonable (s))
10154     {
10155       llcontbuglit ("Unreasonable sRef");
10156       llcontbug (message ("sRef: %s", sRef_unparse (s)));
10157       return;
10158     }
10159
10160   multiVal_free (s->val);
10161   s->val = val;
10162 }
10163
10164 bool sRef_hasValue (sRef s)
10165 {
10166   return (sRef_isReasonable (s)
10167           && multiVal_isDefined (s->val));
10168 }
10169
10170 multiVal sRef_getValue (sRef s)
10171 {
10172   if (sRef_isReasonable (s))
10173     {
10174       return s->val;
10175     }
10176
10177   return multiVal_undefined;
10178 }
This page took 1.719724 seconds and 5 git commands to generate.