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