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