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